github.com/ergo-services/ergo@v1.999.224/node/types.go (about)

     1  package node
     2  
     3  import (
     4  	"context"
     5  	"crypto/cipher"
     6  	"crypto/tls"
     7  	"net"
     8  	"time"
     9  
    10  	"github.com/ergo-services/ergo/etf"
    11  	"github.com/ergo-services/ergo/gen"
    12  	"github.com/ergo-services/ergo/lib"
    13  )
    14  
    15  const (
    16  	// node options
    17  	defaultListenBegin     uint16        = 15000
    18  	defaultListenEnd       uint16        = 65000
    19  	defaultKeepAlivePeriod time.Duration = 15
    20  	defaultProxyPathLimit  int           = 32
    21  
    22  	DefaultProcessMailboxSize   int = 100
    23  	DefaultProcessDirectboxSize int = 10
    24  
    25  	EnvKeyVersion     gen.EnvKey = "ergo:Version"
    26  	EnvKeyNode        gen.EnvKey = "ergo:Node"
    27  	EnvKeyRemoteSpawn gen.EnvKey = "ergo:RemoteSpawn"
    28  
    29  	DefaultProtoRecvQueueLength   int = 100
    30  	DefaultProtoSendQueueLength   int = 100
    31  	DefaultProtoFragmentationUnit int = 65000
    32  
    33  	DefaultCompressionLevel     int = -1
    34  	DefaultCompressionThreshold int = 1024
    35  
    36  	DefaultProxyMaxHop int = 8
    37  
    38  	EventNetwork gen.Event = "network"
    39  )
    40  
    41  type Node interface {
    42  	gen.Core
    43  	// Name returns node name
    44  	Name() string
    45  	// IsAlive returns true if node is still alive
    46  	IsAlive() bool
    47  	// Uptime returns node uptime in seconds
    48  	Uptime() int64
    49  	// Version return node version
    50  	Version() Version
    51  	// ListEnv returns a map of configured Node environment variables.
    52  	ListEnv() map[gen.EnvKey]interface{}
    53  	// SetEnv set node environment variable with given name. Use nil value to remove variable with given name. Ignores names with "ergo:" as a prefix.
    54  	SetEnv(name gen.EnvKey, value interface{})
    55  	// Env returns value associated with given environment name.
    56  	Env(name gen.EnvKey) interface{}
    57  
    58  	// Spawn spawns a new process
    59  	Spawn(name string, opts gen.ProcessOptions, object gen.ProcessBehavior, args ...etf.Term) (gen.Process, error)
    60  
    61  	// RegisterName
    62  	RegisterName(name string, pid etf.Pid) error
    63  	// UnregisterName
    64  	UnregisterName(name string) error
    65  
    66  	LoadedApplications() []gen.ApplicationInfo
    67  	WhichApplications() []gen.ApplicationInfo
    68  	ApplicationInfo(name string) (gen.ApplicationInfo, error)
    69  	ApplicationLoad(app gen.ApplicationBehavior, args ...etf.Term) (string, error)
    70  	ApplicationUnload(appName string) error
    71  	ApplicationStart(appName string, args ...etf.Term) (gen.Process, error)
    72  	ApplicationStartPermanent(appName string, args ...etf.Term) (gen.Process, error)
    73  	ApplicationStartTransient(appName string, args ...etf.Term) (gen.Process, error)
    74  	ApplicationStop(appName string) error
    75  
    76  	ProvideRemoteSpawn(name string, object gen.ProcessBehavior) error
    77  	RevokeRemoteSpawn(name string) error
    78  
    79  	// AddStaticRoute adds static route for the given name
    80  	AddStaticRoute(node string, host string, port uint16, options RouteOptions) error
    81  	// AddStaticRoutePort adds static route for the given node name which makes node skip resolving port process
    82  	AddStaticRoutePort(node string, port uint16, options RouteOptions) error
    83  	// AddStaticRouteOptions adds static route options for the given node name which does regular port resolving but applies static options
    84  	AddStaticRouteOptions(node string, options RouteOptions) error
    85  	// Remove static route removes static route with given name
    86  	RemoveStaticRoute(name string) bool
    87  	// StaticRoutes returns list of routes added using AddStaticRoute
    88  	StaticRoutes() []Route
    89  	// StaticRoute returns Route for the given name. Returns false if it doesn't exist.
    90  	StaticRoute(name string) (Route, bool)
    91  
    92  	AddProxyRoute(proxy ProxyRoute) error
    93  	RemoveProxyRoute(name string) bool
    94  	// ProxyRoutes returns list of proxy routes added using AddProxyRoute
    95  	ProxyRoutes() []ProxyRoute
    96  	// ProxyRoute returns proxy route added using AddProxyRoute
    97  	ProxyRoute(name string) (ProxyRoute, bool)
    98  
    99  	// Resolve
   100  	Resolve(node string) (Route, error)
   101  	// ResolveProxy resolves proxy route. Checks for the proxy route added using AddProxyRoute.
   102  	// If it wasn't found makes request to the registrar.
   103  	ResolveProxy(node string) (ProxyRoute, error)
   104  
   105  	// Returns Registrar interface
   106  	Registrar() Registrar
   107  
   108  	// Connect sets up a connection to node
   109  	Connect(node string) error
   110  	// Disconnect close connection to the node
   111  	Disconnect(node string) error
   112  	// Nodes returns the list of connected nodes
   113  	Nodes() []string
   114  	// NodesIndirect returns the list of nodes connected via proxies
   115  	NodesIndirect() []string
   116  	// NetworkStats returns network statistics of the connection with the node. Returns error
   117  	// ErrUnknown if connection with given node is not established.
   118  	NetworkStats(name string) (NetworkStats, error)
   119  
   120  	Links(process etf.Pid) []etf.Pid
   121  	Monitors(process etf.Pid) []etf.Pid
   122  	MonitorsByName(process etf.Pid) []gen.ProcessID
   123  	MonitoredBy(process etf.Pid) []etf.Pid
   124  
   125  	Stats() NodeStats
   126  
   127  	Stop()
   128  	Wait()
   129  	WaitWithTimeout(d time.Duration) error
   130  }
   131  
   132  // Version
   133  type Version struct {
   134  	Release string
   135  	Prefix  string
   136  	OTP     int
   137  }
   138  
   139  // CoreRouter routes messages from/to remote node
   140  type CoreRouter interface {
   141  
   142  	//
   143  	// implemented by core
   144  	//
   145  
   146  	// RouteSend routes message by Pid
   147  	RouteSend(from etf.Pid, to etf.Pid, message etf.Term) error
   148  	// RouteSendReg routes message by registered process name (gen.ProcessID)
   149  	RouteSendReg(from etf.Pid, to gen.ProcessID, message etf.Term) error
   150  	// RouteSendAlias routes message by process alias
   151  	RouteSendAlias(from etf.Pid, to etf.Alias, message etf.Term) error
   152  
   153  	RouteSpawnRequest(node string, behaviorName string, request gen.RemoteSpawnRequest, args ...etf.Term) error
   154  	RouteSpawnReply(to etf.Pid, ref etf.Ref, result etf.Term) error
   155  
   156  	//
   157  	// implemented by monitor
   158  	//
   159  
   160  	// RouteLink makes linking of the given two processes
   161  	RouteLink(pidA etf.Pid, pidB etf.Pid) error
   162  	// RouteUnlink makes unlinking of the given two processes
   163  	RouteUnlink(pidA etf.Pid, pidB etf.Pid) error
   164  	// RouteExit routes MessageExit to the linked process
   165  	RouteExit(to etf.Pid, terminated etf.Pid, reason string) error
   166  	// RouteMonitorReg makes monitor to the given registered process name (gen.ProcessID)
   167  	RouteMonitorReg(by etf.Pid, process gen.ProcessID, ref etf.Ref) error
   168  	// RouteMonitor makes monitor to the given Pid
   169  	RouteMonitor(by etf.Pid, process etf.Pid, ref etf.Ref) error
   170  	RouteDemonitor(by etf.Pid, ref etf.Ref) error
   171  	RouteMonitorExitReg(terminated gen.ProcessID, reason string, ref etf.Ref) error
   172  	RouteMonitorExit(terminated etf.Pid, reason string, ref etf.Ref) error
   173  	// RouteNodeDown
   174  	RouteNodeDown(name string, disconnect *ProxyDisconnect)
   175  
   176  	//
   177  	// implemented by network
   178  	//
   179  
   180  	// RouteProxyConnectRequest
   181  	RouteProxyConnectRequest(from ConnectionInterface, request ProxyConnectRequest) error
   182  	// RouteProxyConnectReply
   183  	RouteProxyConnectReply(from ConnectionInterface, reply ProxyConnectReply) error
   184  	// RouteProxyConnectCancel
   185  	RouteProxyConnectCancel(from ConnectionInterface, cancel ProxyConnectCancel) error
   186  	// RouteProxyDisconnect
   187  	RouteProxyDisconnect(from ConnectionInterface, disconnect ProxyDisconnect) error
   188  	// RouteProxy returns ErrProxySessionEndpoint if this node is the endpoint of the
   189  	// proxy session. In this case, the packet must be handled on this node with
   190  	// provided ProxySession parameters.
   191  	RouteProxy(from ConnectionInterface, sessionID string, packet *lib.Buffer) error
   192  }
   193  
   194  // Options defines bootstrapping options for the node
   195  type Options struct {
   196  	// Applications application list that must be started
   197  	Applications []gen.ApplicationBehavior
   198  
   199  	// Env node environment
   200  	Env map[gen.EnvKey]interface{}
   201  
   202  	// Creation. Default value: uint32(time.Now().Unix())
   203  	Creation uint32
   204  
   205  	// Listeners node can have multiple listening interface at once. If this list is empty
   206  	// the default listener will be using. Only the first listener will be registered on
   207  	// the Registrar
   208  	Listeners []Listener
   209  
   210  	// Flags defines option flags of this node for the outgoing connection
   211  	Flags Flags
   212  
   213  	// TLS settings
   214  	TLS *tls.Config
   215  
   216  	// StaticRoutesOnly disables resolving service (default is EPMD client) and
   217  	// makes resolving localy only for nodes added using gen.AddStaticRoute
   218  	StaticRoutesOnly bool
   219  
   220  	// Registrar defines a registrar service (default is EPMD service, client and server)
   221  	Registrar Registrar
   222  
   223  	// Compression defines default compression options for the spawning processes.
   224  	Compression Compression
   225  
   226  	// Handshake defines a handshake handler. By default is using
   227  	// DIST handshake created with dist.CreateHandshake(...)
   228  	Handshake HandshakeInterface
   229  
   230  	// Proto defines a proto handler. By default is using
   231  	// DIST proto created with dist.CreateProto(...)
   232  	Proto ProtoInterface
   233  
   234  	// Cloud enable Ergo Cloud support
   235  	Cloud Cloud
   236  
   237  	// Proxy options
   238  	Proxy Proxy
   239  
   240  	// System options for the system application
   241  	System System
   242  }
   243  
   244  type Listener struct {
   245  	// Cookie cookie for the incoming connection to this listener. Leave it empty in
   246  	// case of using the node's cookie.
   247  	Cookie string
   248  	// Hostname defines an interface for the listener. Default: takes from the node name.
   249  	Hostname string
   250  	// Listen defines a listening port number for accepting incoming connections.
   251  	Listen uint16
   252  	// ListenBegin and ListenEnd define a range of the port numbers where
   253  	// the node looking for available free port number for the listening.
   254  	// Default values 15000 and 65000 accordingly
   255  	ListenBegin uint16
   256  	ListenEnd   uint16
   257  	// Handshake if its nil the default TLS (Options.TLS) will be using
   258  	TLS *tls.Config
   259  	// Handshake if its nil the default Handshake (Options.Handshake) will be using
   260  	Handshake HandshakeInterface
   261  	// Proto if its nil the default Proto (Options.Proto) will be using
   262  	Proto ProtoInterface
   263  	// Flags defines option flags of this node for the incoming connection
   264  	// on this port. If its disabled the default Flags (Options.Flags) will be using
   265  	Flags Flags
   266  }
   267  
   268  type Cloud struct {
   269  	Enable  bool
   270  	Cluster string
   271  	Cookie  string
   272  	Flags   CloudFlags
   273  	Timeout time.Duration
   274  }
   275  
   276  type Proxy struct {
   277  	// Transit allows to use this node as a proxy
   278  	Transit bool
   279  	// Accept incoming proxy connections
   280  	Accept bool
   281  	// Cookie sets cookie for incoming connections
   282  	Cookie string
   283  	// Flags sets options for incoming connections
   284  	Flags ProxyFlags
   285  	// Routes sets options for outgoing connections
   286  	Routes map[string]ProxyRoute
   287  }
   288  
   289  type System struct {
   290  	DisableAnonMetrics bool
   291  }
   292  
   293  type Compression struct {
   294  	// Enable enables compression for all outgoing messages having size
   295  	// greater than the defined threshold.
   296  	Enable bool
   297  	// Level defines compression level. Value must be in range 1..9 or -1 for the default level
   298  	Level int
   299  	// Threshold defines the minimal message size for the compression.
   300  	// Messages less of this threshold will not be compressed.
   301  	Threshold int
   302  }
   303  
   304  // Connection
   305  type Connection struct {
   306  	ConnectionInterface
   307  }
   308  
   309  // ConnectionInterface
   310  type ConnectionInterface interface {
   311  	Send(from gen.Process, to etf.Pid, message etf.Term) error
   312  	SendReg(from gen.Process, to gen.ProcessID, message etf.Term) error
   313  	SendAlias(from gen.Process, to etf.Alias, message etf.Term) error
   314  
   315  	Link(local etf.Pid, remote etf.Pid) error
   316  	Unlink(local etf.Pid, remote etf.Pid) error
   317  	LinkExit(to etf.Pid, terminated etf.Pid, reason string) error
   318  
   319  	Monitor(local etf.Pid, remote etf.Pid, ref etf.Ref) error
   320  	Demonitor(local etf.Pid, remote etf.Pid, ref etf.Ref) error
   321  	MonitorExit(to etf.Pid, terminated etf.Pid, reason string, ref etf.Ref) error
   322  
   323  	MonitorReg(local etf.Pid, remote gen.ProcessID, ref etf.Ref) error
   324  	DemonitorReg(local etf.Pid, remote gen.ProcessID, ref etf.Ref) error
   325  	MonitorExitReg(to etf.Pid, terminated gen.ProcessID, reason string, ref etf.Ref) error
   326  
   327  	SpawnRequest(nodeName string, behaviorName string, request gen.RemoteSpawnRequest, args ...etf.Term) error
   328  	SpawnReply(to etf.Pid, ref etf.Ref, spawned etf.Pid) error
   329  	SpawnReplyError(to etf.Pid, ref etf.Ref, err error) error
   330  
   331  	ProxyConnectRequest(connect ProxyConnectRequest) error
   332  	ProxyConnectReply(reply ProxyConnectReply) error
   333  	ProxyConnectCancel(cancel ProxyConnectCancel) error
   334  	ProxyDisconnect(disconnect ProxyDisconnect) error
   335  	ProxyRegisterSession(session ProxySession) error
   336  	ProxyUnregisterSession(id string) error
   337  	ProxyPacket(packet *lib.Buffer) error
   338  
   339  	Creation() uint32
   340  	Stats() NetworkStats
   341  }
   342  
   343  // Handshake template struct for the custom Handshake implementation
   344  type Handshake struct {
   345  	HandshakeInterface
   346  }
   347  
   348  // Handshake defines handshake interface
   349  type HandshakeInterface interface {
   350  	// Mandatory:
   351  
   352  	// Init initialize handshake.
   353  	Init(nodename string, creation uint32, flags Flags) error
   354  
   355  	// Optional:
   356  
   357  	// Start initiates handshake process. Argument tls means the connection is wrapped by TLS
   358  	// Returns the name of connected peer, Flags and Creation wrapped into HandshakeDetails struct
   359  	Start(remote net.Addr, conn lib.NetReadWriter, tls bool, cookie string) (HandshakeDetails, error)
   360  	// Accept accepts handshake process initiated by another side of this connection.
   361  	// Returns the name of connected peer, Flags and Creation wrapped into HandshakeDetails struct
   362  	Accept(remote net.Addr, conn lib.NetReadWriter, tls bool, cookie string) (HandshakeDetails, error)
   363  	// Version handshake version. Must be implemented if this handshake is going to be used
   364  	// for the accepting connections (this method is used in registration on the Resolver)
   365  	Version() HandshakeVersion
   366  }
   367  
   368  // HandshakeDetails
   369  type HandshakeDetails struct {
   370  	// Name node name
   371  	Name string
   372  	// Flags node flags
   373  	Flags Flags
   374  	// Creation
   375  	Creation uint32
   376  	// Version
   377  	Version int
   378  	// NumHandlers defines the number of readers/writers per connection. Default value is provided by ProtoOptions
   379  	NumHandlers int
   380  	// AtomMapping
   381  	AtomMapping *etf.AtomMapping
   382  	// ProxyTransit allows to restrict proxy connection requests for this connection
   383  	ProxyTransit ProxyTransit
   384  	// Buffer keeps data received along with the handshake
   385  	Buffer *lib.Buffer
   386  	// Custom allows passing the custom data to the ProtoInterface.Start
   387  	Custom HandshakeCustomDetails
   388  }
   389  
   390  type HandshakeCustomDetails interface{}
   391  
   392  type HandshakeVersion int
   393  
   394  // Proto template struct for the custom Proto implementation
   395  type Proto struct {
   396  	ProtoInterface
   397  }
   398  
   399  // Proto defines proto interface for the custom Proto implementation
   400  type ProtoInterface interface {
   401  	// Init initialize connection handler
   402  	Init(ctx context.Context, conn lib.NetReadWriter, nodename string, details HandshakeDetails) (ConnectionInterface, error)
   403  	// Serve connection
   404  	Serve(connection ConnectionInterface, router CoreRouter)
   405  	// Terminate invoked once Serve callback is finished
   406  	Terminate(connection ConnectionInterface)
   407  }
   408  
   409  // ProtoOptions
   410  type ProtoOptions struct {
   411  	// NumHandlers defines the number of readers/writers per connection. Default is the number of CPU
   412  	NumHandlers int
   413  	// MaxMessageSize limit the message size. Default 0 (no limit)
   414  	MaxMessageSize int
   415  	// SendQueueLength defines queue size of handler for the outgoing messages. Default 100.
   416  	SendQueueLength int
   417  	// RecvQueueLength defines queue size of handler for the incoming messages. Default 100.
   418  	RecvQueueLength int
   419  	// FragmentationUnit defines unit size for the fragmentation feature. Default 65000
   420  	FragmentationUnit int
   421  	// Custom brings a custom set of options to the ProtoInterface.Serve handler
   422  	Custom CustomProtoOptions
   423  }
   424  
   425  // CustomProtoOptions a custom set of proto options
   426  type CustomProtoOptions interface{}
   427  
   428  // Flags
   429  type Flags struct {
   430  	// Enable enable flags customization
   431  	Enable bool
   432  	// EnableHeaderAtomCache enables header atom cache feature
   433  	EnableHeaderAtomCache bool
   434  	// EnableBigCreation
   435  	EnableBigCreation bool
   436  	// EnableBigPidRef accepts a larger amount of data in pids and references
   437  	EnableBigPidRef bool
   438  	// EnableFragmentation enables fragmentation feature for the sending data
   439  	EnableFragmentation bool
   440  	// EnableAlias accepts process aliases
   441  	EnableAlias bool
   442  	// EnableRemoteSpawn accepts remote spawn request
   443  	EnableRemoteSpawn bool
   444  	// Compression compression support
   445  	EnableCompression bool
   446  	// Proxy enables support for incoming proxy connection
   447  	EnableProxy bool
   448  }
   449  
   450  // Registrar defines registrar interface
   451  type Registrar interface {
   452  	Register(ctx context.Context, nodename string, options RegisterOptions) error
   453  	RegisterProxy(nodename string, maxhop int, flags ProxyFlags) error
   454  	UnregisterProxy(peername string) error
   455  	Resolve(peername string) (Route, error)
   456  	ResolveProxy(peername string) (ProxyRoute, error)
   457  	Config() (RegistrarConfig, error)
   458  	ConfigItem(name string) (etf.Term, error)
   459  	SetConfigUpdateCallback(func(name string, value etf.Term) error) error
   460  }
   461  
   462  type RegistrarConfig struct {
   463  	Version int
   464  	Config  etf.Term
   465  }
   466  
   467  // RegisterOptions defines resolving options
   468  type RegisterOptions struct {
   469  	Port              uint16
   470  	Creation          uint32
   471  	NodeVersion       Version
   472  	HandshakeVersion  HandshakeVersion
   473  	EnableTLS         bool
   474  	EnableProxy       bool
   475  	EnableCompression bool
   476  	Proxy             string
   477  }
   478  
   479  // Route
   480  type Route struct {
   481  	Node    string
   482  	Host    string
   483  	Port    uint16
   484  	Options RouteOptions
   485  }
   486  
   487  // RouteOptions
   488  type RouteOptions struct {
   489  	Cookie    string
   490  	TLS       *tls.Config
   491  	IsErgo    bool
   492  	Handshake HandshakeInterface
   493  	Proto     ProtoInterface
   494  }
   495  
   496  // ProxyRoute
   497  type ProxyRoute struct {
   498  	// Name can be either nodename (example@domain) or domain (@domain)
   499  	Name   string
   500  	Proxy  string
   501  	Cookie string
   502  	Flags  ProxyFlags
   503  	MaxHop int // DefaultProxyMaxHop == 8
   504  }
   505  
   506  // CloudFlags
   507  type CloudFlags struct {
   508  	Enable              bool
   509  	EnableIntrospection bool
   510  	EnableMetrics       bool
   511  	EnableRemoteSpawn   bool
   512  }
   513  
   514  // ProxyFlags
   515  type ProxyFlags struct {
   516  	Enable            bool
   517  	EnableLink        bool
   518  	EnableMonitor     bool
   519  	EnableRemoteSpawn bool
   520  	EnableEncryption  bool
   521  }
   522  
   523  // ProxyTransit
   524  type ProxyTransit struct {
   525  	AllowTo []string
   526  }
   527  
   528  // ProxyConnectRequest
   529  type ProxyConnectRequest struct {
   530  	ID        etf.Ref
   531  	To        string // To node
   532  	Digest    []byte // md5(md5(md5(md5(Node)+Cookie)+To)+PublicKey)
   533  	PublicKey []byte
   534  	Flags     ProxyFlags
   535  	Creation  uint32
   536  	Hop       int
   537  	Path      []string
   538  }
   539  
   540  // ProxyConnectReply
   541  type ProxyConnectReply struct {
   542  	ID        etf.Ref
   543  	To        string
   544  	Digest    []byte // md5(md5(md5(md5(Node)+Cookie)+To)+symmetric key)
   545  	Cipher    []byte // encrypted symmetric key using PublicKey from the ProxyConnectRequest
   546  	Flags     ProxyFlags
   547  	Creation  uint32
   548  	SessionID string // proxy session ID
   549  	Path      []string
   550  }
   551  
   552  // ProxyConnectCancel
   553  type ProxyConnectCancel struct {
   554  	ID     etf.Ref
   555  	From   string
   556  	Reason string
   557  	Path   []string
   558  }
   559  
   560  // ProxyDisconnect
   561  type ProxyDisconnect struct {
   562  	Node      string
   563  	Proxy     string
   564  	SessionID string
   565  	Reason    string
   566  }
   567  
   568  // Proxy session
   569  type ProxySession struct {
   570  	ID        string
   571  	NodeFlags ProxyFlags
   572  	PeerFlags ProxyFlags
   573  	Creation  uint32
   574  	PeerName  string
   575  	Block     cipher.Block // made from symmetric key
   576  }
   577  
   578  type NetworkStats struct {
   579  	NodeName        string
   580  	BytesIn         uint64
   581  	BytesOut        uint64
   582  	TransitBytesIn  uint64
   583  	TransitBytesOut uint64
   584  	MessagesIn      uint64
   585  	MessagesOut     uint64
   586  }
   587  
   588  type NodeStats struct {
   589  	TotalProcesses    uint64
   590  	TotalReferences   uint64
   591  	RunningProcesses  uint64
   592  	RegisteredNames   uint64
   593  	RegisteredAliases uint64
   594  
   595  	MonitorsByPid  uint64
   596  	MonitorsByName uint64
   597  	MonitorsNodes  uint64
   598  	Links          uint64
   599  
   600  	LoadedApplications  uint64
   601  	RunningApplications uint64
   602  
   603  	NetworkConnections uint64
   604  	ProxyConnections   uint64
   605  	TransitConnections uint64
   606  }
   607  
   608  type MessageEventNetwork struct {
   609  	PeerName string
   610  	Online   bool
   611  	Proxy    bool
   612  }