diff options
Diffstat (limited to 'src/lib/ecore_con/ecore_con-eoify-analisys.md')
-rw-r--r-- | src/lib/ecore_con/ecore_con-eoify-analisys.md | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/src/lib/ecore_con/ecore_con-eoify-analisys.md b/src/lib/ecore_con/ecore_con-eoify-analisys.md new file mode 100644 index 0000000000..27909646dd --- /dev/null +++ b/src/lib/ecore_con/ecore_con-eoify-analisys.md @@ -0,0 +1,486 @@ +# Ecore_Con + +This module is used via `Ecore_Con_Server`, for both server and +connect-to-server roles, which can be confusing at first sight. + +There is an `Ecore_Con_Client` handle, but users do not create them +manually, rather receive them via an `Ecore_Event` +`ECORE_CON_EVENT_CLIENT_ADD`. This handle is to be used by server-side +to identify connected clients and send them data. + +The **connect-to-server** role (usually called "connection", "socket" or +"client") is done via an `Ecore_Con_Server` created with +`ecore_con_server_connect()`. + +The server role is done via an `Ecore_Con_Server` created with +`ecore_con_server_add()`. + +Current `ecore_con` usage (except `ecore_con_url`, within EFL): +https://gist.github.com/barbieri/ed77c1e829a6e684dd736a771d6732d1 + +## Ecore_Con_Server (as server role) + +Methods (omitted `ecore_con_server_` prefix): + + - `add(type, name, port, data): Ecore_Con_Server` *[[constructor]]* + - `ssl_cert_add(string): bool` *[[Add a PEM certificate file]]* + - `ssl_privkey_add(string): bool` *[[Add a PEM private key file]]* + - `ssl_crl_add(string): bool` *[[add PEM CRL file]]* + - `ssl_cafile_add(string): bool` *[[add PEM CA file]]* + +Properties: + + - `data: void_ptr` *[[user data]]* + - `connected: bool` *[[if connected or not]]* + - `port: int` *[[the port serving the requests]]* + - `uptime: double` *[[time in seconds since it was started]]* + - `client_limit: int` *[[number of concurrent clients to allow]]* + - `reject_excess_clients: bool` *[[if true, automatically disconnects extra clients]]* + +Events (omitted `ECORE_CON_EVENT_` prefix): + + - `CLIENT_ADD: Ecore_Con_Client` + - `CLIENT_DEL: Ecore_Con_Client` + +# Ecore_Con_Client (used only by the server role) + +Methods: + + - `send(buffer): int` *[[server writes data to client]]* + - `flush(): void` *[[block until all pending data is written]]* + - `del(): void` *[[server close connection to client and free client handle]]* + - `upgrade(type): bool` *[[upgrade to SSL using STARTTLS]]* + +Properties: + + - `fd: int` *[[get the internal filedescriptor]]* + - `data [RW]: void_ptr` *[[user data associated with a client]]* + - `ip: string` *[[IP address of this client]]* + - `port: int` *[[port of connected client]]* + - `uptime: double` *[[time in seconds since it was connected]]* + - `connected: bool` *[[if connected]]* + - `timeout [RW]: double` *[[duration of idleness to keep the client alive]]* + +Events (omitted `ECORE_CON_EVENT_CLIENT_` prefix and `Ecore_Con_Client` handle): + + - `DATA: buffer` *[[reports incoming data]]* + - `WRITE: int` *[[reports data sent]]* + - `UPGRADE: void` *[[reports completed handshake]]* + - `ERROR: string` *[[reports error]]* + + +# Ecore_Con_Server (as connect-to-server role) + +Methods: + + - `connect(type, name, port, data):` *[[constructor]]* + - `del():` *[[destructor]]* + - `send(buffer): int` *[[write data to server]]* + - `flush(): void` *[[block until all pending data is written]]* + - `upgrade(type): bool` *[[upgrade to SSL using STARTTLS]]* + +Methods (Did I get all of these right?): + + - `ssl_cert_add(string): bool` *[[Add a PEM certificate file]]* + - `ssl_privkey_add(string): bool` *[[Add a PEM private key file]]* + - `ssl_crl_add(string): bool` *[[add PEM CRL file]]* + - `ssl_cafile_add(string): bool` *[[add PEM CA file]]* + - `ssl_server_upgrade(type): void` *[[start TLS]]* + - `ssl_server_verify(): void` *[[enable (once) the verification of loaded certificates]]* + - `ssl_server_verify_basic(): void` *[[enable hostname-based verification]]* + - `ssl_server_verify_name_set(string): void` *[[change the name to use for the server]]* + - `ssl_server_verify_name_get(): string` *[[get the name to use for the server]]* + +Properties (omitted ecore_con_server_ prefix): + + - `fd: int` *[[get the internal filedescriptor]]* + - `ip: string` *[[IP address of the connected server]]* + - `data: void_ptr` *[[user data]]* + - `uptime: double` *[[time in seconds since it was connected]]* + - `connected: bool` *[[if connected or not]]* + - `timeout [RW]: double` *[[duration of idleness to keep the server alive]]* + +Events (omitted `ECORE_CON_EVENT_SERVER_` prefix and `Ecore_Con_Server` handle): + + - `ADD:` *[[server was connected]]* + - `DEL:` *[[server is disconnected]]* + - `DATA: buffer` *[[server sent some data and it's ready to be read]]* + - `WRITE: int` *[[reports data sent]]* + - `ERROR: string` *[[reports error]]* + - `UPGRADE: void` *[[reports completed handshake]]* + +# Node.js + +Node.js is based on a single thread and main loop with asynchronous +events. + +## net.Server + +This is analogous to `Ecore_Con_Server` as returned by the +`ecore_con_server_add()`. It will listen for connections and each new +accepted is a `net.Socket ` (see below), which is the equivalent of +`Ecore_Con_Client` as passed in `ECORE_CON_EVENT_CLIENT_ADD` event. + +A server is created with `net.createServer([options], [cb])` + +Doc: https://nodejs.org/api/net.html#net_class_net_server + +Methods: + + - `address(): object` *[[bound address with port, family and address]]* + - `close(): void` *[[stop the server servicing new conns, keeps existing]]* + - `getConnections(cb(err, count)):` *[[query count of existing conns]]* + - `listen(options, [cb]):` *[[start listening to conns]]* + +Properties: + + - `listening: bool` *[[whenever server is listening]]* + - `maxConnections: int` *[[maximum concurrent conns to accept]]* + +Events: + + - `close: void` *[[emitted when closed and the last connection is gone]]* + - `connection: client net.Socket` *[[new connection/client]]* + - `error: Error` *[[when an error occurs]]* + - `listening: void` *[[server.listen() was called]]* + +## net.Socket + +This is analogous to either `Ecore_Con_Client` as passed in +`ECORE_CON_EVENT_CLIENT_ADD` or `Ecore_Con_Server` as returned by +`ecore_con_server_connect()`. `Ecore_Con_Client` represents a client +connected to a server, while the `Ecore_Con_Server` represents a +connection to the server. Node.JS, as most APIs out there, simply +handle this as an ongoing connection which offers common properties +such as local and remote addresses, read and write methods and so on. + +A connection is passed to `net.Server::connection` event or created +with net.connect() or net.createConnection(). + +Doc: https://nodejs.org/api/net.html#net_class_net_socket + +Methods: + + - `constructor([{fd, readable, writeable}], [allowHalfOpen])` + - `write(data, encoding): bool` *[[sends data, True means all data was sent]]* + - `address(): object` *[[bound address with port, family and address]]* + - `connect(options, listener):` *[[connect to a server]]* + - `destroy([error]):` *[[ensures no more i/o]]* + - `end([data] [,encoding]):` *[[do write(data, encoding), then send FIN]]* + - `pause():` *[[pauses data reading, does not emit 'data' event]]* + - `resume():` *[[resumes data reading, allows emit 'data' event]]* + - `setEncoding(string):` *[[sets an encoding to convert raw bytes to string]]* + - `setKeepAlive(bool, initialDelay):` *[[change keep alive behavior]]* + - `setNoDelay(bool):` *[[send data immediately on each write()]]* + - `setTimeout(int):` *[[set socket timeout milliseconds, 0 disables]]* + +Properties: + + - `bufferSize: int` *[[write buffer to keep]]* + - `bytesRead: int` *[[received bytes]]* + - `bytesWritten: int` *[[sent bytes]]* + - `connecting: bool` *[[if connect() is still on going]]* + - `destroyed: bool` *[[conn was destroyed]]* + - `localAddress: string` *[[local IP or path]]* + - `localPort: int` *[[local port number]]* + - `remoteAddress: string` *[[remote IP or path]]* + - `remoteFamily: string` [remote family, IPv4 or IPv6]]* + - `remotePort: int` *[[remote port number]]* + +Events: + + - `close: had_error bool` *[[emitted once the socket is fully closed]]* + - `connect: void` *[[emitted once the connection is fully stablished]]* + - `data: buffer` *[[data is received]]* + - `drain: void` *[[emitted when write buffer becomes empty]]* + - `end: void` *[[emitted when the other end sends a FIN packet]]* + - `error: Error` *[[when an error occurs, followed by 'close' event.]]* + - `lookup: err, address, family, host` *[[after name is resolved, before connecting]]* + - `timeout: void` *[[after inactivity timeout]]* + + +# Qt + +Qt is based on single thread and main loop with asynchronous events. + +## QTcpServer + +This is analogous to `Ecore_Con_Server` as returned by +`ecore_con_server_add()`. It will listen for connecting and each new +accepted is a `QTcpSocket` (derivate of `QAbstractSocket`, see below, +which is the equivalent of `Ecore_Con_Client` as passed in +`ECORE_CON_EVENT_CLIENT_ADD` event. + +A server is created with `QTcpServer` object. Clients (`QTcpSocket`) +are child objects of `QTcpServer` and are deleted if the server is +destroyed. + +Doc: http://doc.qt.io/qt-5/qtcpserver.html + +Methods: + + - `close(): void` *[[stop listening for connections]]* + - `listen(address, port): bool` + - `nextPendingConnection(): QTcpSocket` *[[returns the next ready client as QTcpSocket]]* + - `pauseAccepting(): void` + - `resumeAccepting(): void` + - `waitForNewConnection(time)` *[[blocks main thread]]* + +Properties: + + - `isListening(): bool` + - `errorString(): string` *[[string of serverError()]]* + - `serverError(): SocketError` + - `serverAddress(): QHostAddress` + - `serverPort(): int` + - `maxPendingConnections(): int` + - `setMaxPendingConnections(int): void` + - `hasPendingConnections(): bool` *[[if can call nextPendingConnection()]]* + - `proxy(): QNetworkProxy` + - `setProxy(QNetworkProxy): void` + +Events: + + - `acceptError: SocketError` *[[if accept triggers an error]]* + - `newConnection: void` *[[need to call nextPendingConnection()]]* + +## QAbstractSocket + +This is analogous to either `Ecore_Con_Client` as passed in +`ECORE_CON_EVENT_CLIENT_ADD` or `Ecore_Con_Server` as returned by +`ecore_con_server_connect()`. `Ecore_Con_Client` represents a client +connected to a server, while the `Ecore_Con_Server` represents a +connection to the server. Qt, as most APIs out there, simply handle +this as an ongoing connection which offers common properties such as +local and remote addresses, read and write methods and so on. + +A connection is returned by `QTcpServer::nextPendingConnection()` or +created with `QTcpSocket()`, `QSslSocket()`, `QUdpSocket()`, +`QLocalSocket()`... + +Connections are implemented by specific classes such as `QTcpSocket`, +`QSslSocket`, `QUdpSocket` and `QLocalSocket`. + +Doc: http://doc.qt.io/qt-5/qabstractsocket.html + +Methods: + + - `connectToHost(address, port, mode):` *[[connect to server]]* + - `disconnectFromHost()` *[[schedule for close once all data is sent]]* + - `abort(): void` *[[ensures no more i/o]]* + - `flush(): bool` *[[flushes as much data to socket without block]]* + - `close(): bool` *[[emits 'aboutToClose', set mode=NotOpen, closes the socket]]* + - `waitForBytesWritten(time): bool` *[[block caller thread for write()]]* + - `waitForReadyRead(time): bool` *[[block caller thread for read()]]* + - `waitForDisconnect(time): bool`*[[block caller thread for disconnect]]* + - `waitForConnect(time): bool` *[[block caller thread for connect]]* + - `read(char *, int64 max): int64` + - `readAll(): buffer` + - `readLine(): buffer` + - `write(char *, int64 max): int64` + - `getChar(char *): bool` + - `putChar(char): bool` + - `peek(char *, int64 max): int64` + - `reset()` + +Properties: + + - `localAddress(): QHostAddress` + - `localPort(): int` + - `peerAddress(): QHostAddress` + - `peerPort(): int` + - `readBufferSize() int64` + - `setReadBufferSize(int64)` + - `setSocketOption(option, QVariant value)` + - `socketOption(option): QVariant` + - `setProxy(QNetworkProxy)` + - `proxy()` + - `socketType(): SocketType` + - `state(): SocketState` + - `error(): SocketError` + - `isOpen(): bool` + - `isReadable(): bool` + - `isWritable(): bool` + - `isSequential(): bool` *[[ie: TCP, streams]]* + - `isTextModeEnabled(): bool` + - `setTextModeEnabled(bool):` + - `canReadLine(): bool` *[[if there is a full line to be read]]* + - `atEnd(): bool` *[[to be used in loop constructs with read()]]* + - `bytesAvailable(): int64` *[[number of bytes waiting to be read]]* + - `bytesToWrite(): int64` *[[bytes queued for write]]* + - `pos(): int64` + - `canReadLine(): bool` + +Events: + + - `connected: void` + - `disconnected: void` + - `error: SocketError` + - `hostFound: void` *[[after name is resolved, before connecting]]* + - `proxyAuthenticationRequired: proxy, authenticator` + - `stateChanged: SocketState` + - `aboutToClose: void` *[[once close() is called]]* + - `bytesWritten: int64` + - `readChannelFinished` + - `readyRead` + +# Go (language) + +Go is based on *synchronous* and *blocking* primitives, using multiple +co-routines (goroutines) to implement concurrent tasks. + +## net.Listener + +This is the server role and is analogous to `Ecore_Con_Server` as +returned by `ecore_con_server_add()`. + +Listeners are implemented implemented by specific classes such as +`TCPListener`, `UDPListener` and `UnixListener`. + +Doc: https://golang.org/pkg/net/#Listener + +Methods: + + - `Listen(network, address): Listener, error` *[[creates a listener]]* + - `Accept(): Conn, error` *[[waits for and returns a new connection]]* + - `Close(): error` *[[closes the listener]]* + +Properties: + + - `Addr(): Addr` *[[returns the listener local address]]* + + +## net.Dialer + +This is the **client-to-server** role and is analogous to +`Ecore_Con_Server` as returned by `ecore_con_server_connect()`. + +Doc: https://golang.org/pkg/net/#Dialer + +Methods: + + - `Dial(network, address): Conn, error` *[[connect to the remote server]]* + - `Cancel(): chan` *[[close connection if chan is closed]]* + +Properties: + + - `Timeout: time` *[[maximum time to wait before conn times out]]* + - `Deadline: time` *[[absolute point in time to fail]]* + - `LocalAddr: Addr` *[[local address, if nil, assign automatic]]* + - `DualStack: bool` *[[ipv4 and ipv6]]* + - `FallbackDelay: time` *[[if DualStack, time to change to fallback conn]]* + - `KeepAlive: time` *[[duration of idleness to keep the connection alive]]* + +## net.Addr + +Doc: https://golang.org/pkg/net/#Addr + +Properties: + + - `Network(): string` *[[network name]]* + - `String(): string` *[[string representation of the address]]* + + +## net.TCPAddr / net.UDPAddr + +Doc: https://golang.org/pkg/net/#TCPAddr + +Properties: + + - `IP:` (4/16 byte address) + - `Port: int` + - `Zone: string` *[[IPv6 zone]]* + +## net.Conn + +This is analogous to either `Ecore_Con_Client` as passed in +`ECORE_CON_EVENT_CLIENT_ADD` or `Ecore_Con_Server` as returned by +`ecore_con_server_connect()`. `Ecore_Con_Client` represents a client +connected to a server, while the `Ecore_Con_Server` represents a +connection to the server. Go, as most APIs out there, simply handle +this as an ongoing connection which offers common properties such as +local and remote addresses, read and write methods and so on. + +A connection is returned by `net.Listener::Accept()` or created with +`net.Dialer`, such as `net.Dial(network, address)`. + +Unlike EFL, go primitives are all *synchronous* and people use +goroutines to start a co-routine (pseudo thread) to do the processing. + +Connections are implemented by specific classes such as `IPConn`, +`TCPConn`, `UDPConn` and `UnixConn`. + +Doc: https://golang.org/pkg/net/#Conn + +Methods: + + - `Read(buffer): int, error` *[[read to buffer, returns read amount]]* + - `Write(buffer): int, error` *[[write buffer, returns written ammount]]* + - `Close(): error` *[[closes the connection]]* + +Properties: + + - `LocalAddr(): Addr` *[[returns the local address]]* + - `RemoteAddr(): Addr` *[[returns the remote address]]* + - `SetDeadline(time): error` *[[set I/O deadlines]]* + - `SetReadDeadline(time): error` *[[set Input deadline]]* + - `SetWriteDeadline(time): error` *[[set Output deadline]]* + + +## net.IPConn (net.Conn) + +Base class for `TCPConn` and `UDPConn`. + +Doc: https://golang.org/pkg/net/#IPConn + +Extra methods: + + - `ReadFrom(buffer): int, Addr, error` *[[PacketConn variant of Read()]]* + - `ReadFromIP(buffer): int, IPAddr, error` *[[PacketConn variant of Read()]]* + - `ReadMsgIP(buffer, out_of_band_buffer): ...` *[[PacketConn variant]]* + - `WriteTo(buffer, Addr): int, error` *[[PacketConn variant]]* + - `WriteToIP(buffer, IPAddr): int, error` *[[PacketConn variant]]* + - `WriteMsgIP(buffer, out_of_band_buffer, IPAddr): `*[[PacketConn variant]]* + - `SetReadBuffer(int):` *[[bytes to use to receive data]]* + - `SetWriteBuffer(int):` *[[bytes to use to send data]]* + + +## Soletta + +Soletta (https://github.com/solettaproject/soletta) is based on single +thread and main loop with asynchronous events. + +It doesn't expose middleground classes to do socket, just the very +basic POSIX-like API and high level via each module (MQTT, +HTTP...). Nonetheless it focus on small and efficient APIs, thus +instead of multiple setters and getters, most parameters are specified +to the constructor as a structure with optional members (can be zero). + +The API to be listed here is not even a network one, but rather a +streaming API used by its UART module. It's focused on efficiency and +to save on memory it uses blobs (memory + size with parent and +references) to avoid copies in the streaming API. + +Doc: http://solettaproject.github.io/docs/c-api/group__UART.html + +Methods: + + - `open(config): handle` *[[constructor]]* + - `feed(blob): int` *[[]]* + +Events: + + - `data: binbuf, &int` *[[reports data is available in binbuf, user reports how much was consumed]]* + - `feed_done: blob, error` *[[notifies a blob was fully sent or failed]]* + +As one can see, by feeding immutable blobs, the API does not keep an +internal binbuf of pending memory, instead it will keep an array of +pending blobs and the offset of the first pending blob (for partial +sends). This maps well to iovec APIs in Linux. + +To avoid going over-memory on continuous send, `-ENOSPC` is returned +if it goes over pre-defined buffer size in config. + +The constructor specifies maximum read bytes (to be allocated using a +binbuf, 0 is unlimited) and write size (to be allowed in pending blobs +list). |