-
Notifications
You must be signed in to change notification settings - Fork 32
API Proposal TCP
- Irakli Gozalishvili (@gozala / gozala@mozilla.com)
- Dietrich Ayala (dietrich / dietrich@mozilla.com)
Over tha past few years new p2p protocols (IPFS, Dat, SSB) have emerged that are becoming increasingly more popular. Unfortunately rather then enriching web ecosystem and growing Firefox user base they are forced to being developed & grow user base outside, usually via Electron based applications like Beaker Browser, Patchwork SSB client and alike. They also have correpsponding web-extensions (IPFS Companion, DatFox, PatchFox) but they are only able to redirect calls to either gateway & compromise on providing decentralization / p2p-ness (whic is the whole point) or redirect to a separately installed local server application and compromise on UX which naturally forces ecosystem to grow in separate Electron app space.
In order to deliver p2p network implementers need to be able to establish direct connections between nodes. Mentioned protocols use TCP server / client sockets (usually in combination with other transport options) to achieve direct connections. This proposal draws inspiration from prior art:
- W3C TCP/UDP API.
- TCP Server / TCP Client Socket APIs for Chrome Apps.
- Firefox OS TCP Socket API
This section details a proposed webextensions API for connecting to a TCP sockets and for accepting connections on the local TCP server socket. It is broken into a few high-level sections:
As with most existing webextension APIs, this API will expose new top-level permission that could be included into permissions or optional_permissions.
Web extension may request permission to connect to any address / port via following permission "tcp-connect:*:*"
or request connect to a specific address on any port "tcp-connect:127.0.0.1:*"
or access to a specific address / port "tcp-connect:127.0.0.1:8080"
.
Outlined TCPSocket.connect
function will not appear in an extension’s browser
namespace unless above permission is included in the extension manifest.
Web extension may request permission to listen for incoming on a specific port via following permission tcp-listen:3030
or request to listen to incoming connections on arbirtary port via tcp-listen:*
permission.
Outlined TCPSocket.listen
function will not appear in an extension’s browser
namespace unless above permission is included in the extension manifest.
In this way, a user who installs an extension that uses this API can be offered a prompt describing message describing corresponding permission.
In case of optional_permission
request can also be requested at runtime via existing permissions API.
Putting these pieces together, the TCPSocket.connect()
method will only succeed for connections thar are permitted to the running extension. Similarly, calls to the TCPSocket.listen()
will only succeed for for the ports that running extension has being granted access to. Calls to any of these methods on address
/ port
to which permission han not being granted to will fail with a “permission denied” error.
Name | type | description |
---|---|---|
address |
number | Network address to connect to |
port |
number | Port to connect to |
useSecureTransport |
boolean | Connection to use TLS |
Method will establish TCP connection to the requested address / port as long as the running extension is granted permission to do so. If permission isn't granted, returned promise will fail with "permission denied" error.
Name | Returns |
---|---|
connect(TCPConnectionOptions) |
Promise<TCPClientSocket> |
Represents a client TCP socket and can be used for sending / receiving message from the server socket.
Name | type | description |
---|---|---|
address |
number | Network address of the socket |
port |
number | Port of the socket |
ssl |
boolean | True if TLS is used |
readyState |
"connecting","open","closing" "closed" | status of the socket |
opened | Promise<void> |
Promise that is resolved once connection is established |
closed | Promise<void> |
Promise that is resolved once connection is closed |
write(ArrayBuffer, byteOffset?: number, byteLength?: number) |
Promise<void> |
Writes data to a socket |
read() |
Promise<ArrayBuffer> |
Returns promise that is resolved with next data chunk |
suspend() |
void | Pause reading incoming data |
resume() |
void | Resume reading incoming data |
close() |
Promise<void> |
Close the socket and resolve return promise that resolves once closed. Will wait for all queued data to drain |
closeImmediately() |
void | Close the socket without waiting queued data to be drained |
Name | type | description |
---|---|---|
port |
?number | Port to listen on. If omitted or is -1 will be selected automatically |
backLog |
number | Queue size of pending connections. May be silently limited. If omitted or -1 default value is used |
Creates server socket and puts it in the listening state. It will asynchronously listen for and accept client connections. Lack of permission causes returned promise to fail with "permission denied" error.
Name | Returns |
---|---|
connect(?TCPServerOptions) |
Promise<TCPServerSocket> |
Represents a TCP server socket that can be used to handle client connections.
Name | type | description |
---|---|---|
localPort |
number | The port of this server socket |
close() |
void | Close the server socket |
connections |
AsyncIterator | Async iterator of connecting client connections. |