summaryrefslogtreecommitdiff
path: root/src/lib/ecore_con/ecore_con-eoify-analisys.md
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/ecore_con/ecore_con-eoify-analisys.md')
-rw-r--r--src/lib/ecore_con/ecore_con-eoify-analisys.md486
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).