Home

Awesome

NkPACKET: Generic Erlang transport layer

NkPACKET is a generic transport layer for Erlang.

It can be used to develop high perfomance, low latency network servers, clients and proxies.

Features:

In order to write a server or client using NkPACKET, you must define a protocol, an Erlang module implementing some of the callback functions defined in nkpacket_protocol.erl. All callbacks are optional. In your protocol callback module, you can specify available transports, default ports and callback functions for your protocol.

Listeners and connections can belong to a group, and can then be managed together. When sending packets, if a previous connection exists belonging to the same group, it will be used instead of starting a new one.

Registering the protocol

If you want to use a scheme associated with your protocol (like in my_scheme://0.0.0.0:5315;transport=wss) you must register your protocol with NkPACKET calling nkpacket:register_protocol/2,3. Different goups can have different protocol implementations for the same scheme:

nkpacket:register_protocol(my_scheme, my_protocol)

In this example, the module my_protocol.erl must exist.

Writing a server

After defining your callback protocol module, you can start your server calling nkpacket:start_listener/2. You must provide a nkpacket:user_connection() network specification, for example:

nkpacket:start_listener("my_scheme://0.0.0.0:5315;transport=wss", 
						#{tcp_listeners=>100, idle_timeout=>5000})

or

nkpacket:start_listener({my_protocol, wss, {0,0,0,0}, 5315}, 
						#{group=>my_group, tcp_listeners=>100, idle_timeout=>5000})

or even

nkpacket:start_listener(my_domain, "my_scheme://0.0.0.0:5315;transport=wss;tcp_listeners=100;idle_timeout=5000")

There are many available options, like setting connection timeouts, start STUN servers fot UDP, TLS parameters, maximum number of connections, etc. (See nkpacket:listener_opts()). The following options are allowed in urls: idle_timeout, connect_timeout, sctp_out_streams, sctp_in_streams, no_dns_cache, tcp_listeners, host, path, ws_proto, tls_certfile, tls_keyfile, tls_cacertfile, tls_password, tls_verify, tls_depth.

NkPACKET will then start the indicated transport. When a new connection arrives, a new connection process will be started, and the conn_init/0 callback function in your protocol callback function will be called. Incoming data will be parsed and sent to your protocol module.

You can use the option user to pass specific metadata to the callback init function. If you use the url format, you can use header values, and they will generate an erlang list(). The following are equivalent:

nkpacket:start_listener(my_domain, "my_scheme://0.0.0.0:5315;transport=wss", 
						#{user=>[{<<"key1">>, <<"value1">>}, <<"key2">>]})

and

nkpacket:start_listener(my_domain, "my_scheme://0.0.0.0:5315;transport=wss?key1=value1&key2", 
						#{})

You can send packets over the started connection calling nkpacket:send/2,3. Packets will be encoded calling the corresponding function in the callback module.

After a configurable timeout, if no packets are sent or received, the connection is dropped. Incoming UDP packets will also (by default) generate a new connection, associated to that remote ip and port. New packets to/from the same ip and port will be sent/received through the same connection process. You can disable this behaviour.

Writing a client

After defining the callback protocol module (if it is not already defined) you can send any packet to a remote server calling nkpacket:send/2,3, for example:

nkpacket:send("my_scheme://my_host:5315;transport=wss", my_msg)

(to use urls like in this example you need to register your protocol previously).

After resolving my_host using the local DNS engine (using NAPTR and SRV if available), your message will be encoded (using the corresponding callback function on your protocol callback module), and, if a connection is already started for the same group, transport, ip and port, the packet will be sent through it. If none is available, or no group was specified, a new one will be automatically started.

NkPACKET offers a sofisticated mechanism to specify destinations, with multiple fallback routes, forcing new or old connections, trying tcp after udp failure, etc. (See nkpacket:send_opts()). You can also force a new connection to start without sending any packet yet, calling nkpacket:connect/2.

Writing a web server

NkPACKET includes two pseudo_transports: http and https.

NkPACKET registers on start the included protocol nkpacket_protocol_http, associating it with the schema http (only for pseudo-transport http) and the schema https (for pseudo-transport https). You can then start a server listening on this protocol and transport.

NkPACKET allows several different domains to share the same web server. You must use the options host and/or path to filter and select the right domain to send the request to (see nkpacket:listener_opts()). You must also use cowboy_dispatch to process the request as an standard Cowboy request.

For more specific behaviours, use cowboy_opts instead of cowbow_dispatch, including any supported Cowboy middlewares and environment.

You can of course register your own protocol using tranports http and https (using schemas http and https or not), implementing the callback function http_init/3 (see nkpacket_protocol_http for an example).

Application configurarion

There are several aspects of NkPACKET that can be configured globally, using standard Erlang application environment:

OptionTypeDefaultComment
max_connectionsinteger()1024Maximum globally number of connections.
dns_cache_ttlinteger()30000Time to cache DNS queries. 0 to disable cache (msecs).
udp_timeoutinteger()30000(msecs)
tcp_timeoutinteger()180000(msecs)
sctp_timeoutinteger()180000(msecs)
ws_timeoutinteger()180000(msecs)
http_timeoutinteger()180000(msecs)
connect_timeoutinteger()30000(msecs)
sctp_out_streamsinteger()10Default SCTP out streams
sctp_in_streamsinteger()10Default SCTP in streams
tcp_listenersinteger()10Default number of TCP listeners
main_ipinet:ip4_address()autoMain IPv4 of the host
main_ip6inet:ip6_address()autoMain IPv6 of the host
ext_ipinet:ip4_address()autoPublic Ipv4 of the host
tls_certfilestring()-Custom certificate file
tls_keyfilestring()-Custom key file
tls_cacertfilestring()-Custom CA certificate file
tls_passwordstring()-Password fort the certificate
tls_verifyboolean()falseIf we must check certificate
tls_depthinteger()0TLS check depth

main_ip, main_ip6, if auto, are guessed from the main network cards. ext_ip, if auto, is obtained using STUN. None of them are used by nkpacket itself, but are available for client projects.

NkPACKET uses lager for log management.

NkPACKET needs Erlang >= 17 and it is tested on Linux and OSX.

Contributing

Please contribute with code, bug fixes, documentation fixes, testing or any other form. Use GitHub Issues and Pull Requests, forking this repository. Please make sure all tests pass and Dialyzer is happy after your patch.