Login | Register

Development

Transport Interface Design


This document contains the design of the new Transport Interface that will be deployed in OpenSIPS 2.1.


Description

The current transport protocols (UDP, TCP, TLS, etc.) are embedded directly in the OpenSIPS core. This makes the management of these protocols in script more difficult and also complicates the addition of new ones (such as WebSockets).

In order to simplify this, we designed a new Transport Interface that aims to provide a new transport layer in OpenSIPS's core. This interface will separate the network level transport protocols (such as TCP and UDP) from higher level, SIP aware, protocols (such as TLS, WebSocket, SCTP). This clear separation will facilitate the addition of higher level protocols while efficiently reusing the lower network level protocols implementations.

Design

The architecture of the new Transport Interface is presented in the picture below.

The picture consists of three layers, from top down:

  1. OpenSIPS Core and Modules - here stand the already existing OpenSIPS modules and core functions, that send and receive SIP messages over the network. This layer will not suffer too many changes, only align to the new interface.
  2. Transport layer - here are the specific transport modules (such as UDP, SCTP, TCP, TLS, WebSocket) that handle the sending and receiving over the network. Some of these protocols will be implemented as separate modules that will be automatically loaded when used in the script, and some of them will be developed directly in OpenSIPS's core (i.e. UDP and TCP).
  3. Network layer - this layer takes care of the listeners and connections management, and provides an interface for the TCP reactor.

The last two points above will represent a separation of the current TCP/UDP implementations and will suffer major changes.

In order to interact between the three layers, the Transport Interface will provide three different APIs: Application(app), Transport(trans) and Network(net).

Application API (app)

// looks for the transport protocol that knows how to handle the proto and calls the corresponding add_listener() function
int add_listener(char* host, int proto, int port);

// used to tune connection attributes
int dst_fcntl(int id, union sockaddr_union* to, int attr, void *value);

// called by the transport protocol when a whole message was received
int recv_msg(char* buf, unsigned int len, struct receive_info* rcv_info);

// used to send a buffer over the network
int send_msg(struct socket_info *send_socket, int proto, \
             union sockaddr_union* to, int id, char* buf, int len);

Transport API (trans)

Each type of transport has to implement this structure

struct trans_proto {
    // the id of the protocol
    int proto;

    // the name of the protocol: UDP, SCTP. Used for detecting the outgoing/incoming socket
    char *name;

    // the default port for the protocol
    int default_port;

    // function called when the module is loaded
    int (*proto_init)(void);

    // function called to destroy the data initialized at startup
    void (*proto_destroy)(void);

    // adds a new listener read by the parser. The port might be missing, and the default_port is used further
    int (*add_listener)(char* host, int port);

    // binds the listener and returns a file descriptor (used by the WebSocket library)
    int (*bind)(char *host, int port);

    // connects to a different peer
    int (*connect)(union sockaddr_union* to);

    // initializes a new connection
    int (*conn_init)(struct connection *conn, void *ctx);

    // reads the data received on the connection
    int (*recv)(struct connection *conn, void *ctx);

    // used to send a buffer over the network
    int (*send)(struct connection *conn, char* buf, int len);
}

Network API (net)

// binds the interface and adds the socket to the listening sockets
int add_listener(char* host, int proto, int port);

// used to return a listener
struct socket_info* find_listener(union sockaddr_union* to, int proto);

struct net_proto {
    // initializes the structures
    int (*init_tcp)(void);

    // initializes the listeners
    int (*init_listeners)(void);

    // destroys the TCP data
    void (*destroy_udp)(void);

    // returns the connection identified by either the id or the destination to
    struct connection* (*conn_get)(int id, union sockaddr_union* to);

    // used to tune connection attributes
    int (*conn_fcntl)(struct connection *conn, int attr, void *value);
}

TCP network proto

// initializes the TCP structures
int init_tcp(void);

// initializes the TCP listeners
int init_tcp_listeners(void);

// destroys the TCP data
void destroy_tcp(void);

// returns the connection identified by either the id or the destination to
struct connection* conn_get(int id, union sockaddr_union* to);

// used to tune connection attributes
int conn_fcntl(struct connection *conn, int attr, void *value);

UDP network proto

// initializes the UDP structures
int init_udp(void);

// initializes the UDP listeners
int init_udp_listeners(void);

// destroys the UDP data
void destroy_udp(void);

Flow Charts

The following diagrams represent the execution flows for the TCP network protocol.

Receive Message

The following scenario represents the state machine executed when a message is received.

Send Message

The next diagram represents the state machine executed when a message is sent by the OpenSIPS core or modules.


Page last modified on February 02, 2015, at 03:21 PM