From fb3e20b4b2a38cd09bf4ed7687dacd3ab6f15d44 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 21 Dec 2015 20:54:19 +0100 Subject: SCTP support for osmo_stream_{cli,srv} code Wih this change, osmo_stream_ client and server API can be used not only for TCP but also for SCTP. The latter is needed in SIGTRAN ad Iuh applications, for example. --- configure.ac | 7 ++++ include/osmocom/netif/stream.h | 5 +++ src/Makefile.am | 4 +- src/stream.c | 89 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 98 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 3d4c4f0..42f3f42 100644 --- a/configure.ac +++ b/configure.ac @@ -40,6 +40,13 @@ PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.0) dnl FIXME: We depend on libosmoabis by now until we can move LAPD code here PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.0.7) PKG_CHECK_MODULES(ORTP, ortp >= 0.15.0) +AC_CHECK_LIB([sctp], [sctp_send], [ + AC_DEFINE(HAVE_LIBSCTP, 1, [Define 1 to enable SCTP support]) + AC_SUBST(HAVE_LIBSCTP, [1]) + LIBS="-lsctp $LIBS" + ], [ + AC_MSG_ERROR([libsctp not found]) + ]) AC_CHECK_HEADERS(dahdi/user.h,,AC_MSG_WARN(DAHDI input driver will not be built)) diff --git a/include/osmocom/netif/stream.h b/include/osmocom/netif/stream.h index ed399bf..efbb917 100644 --- a/include/osmocom/netif/stream.h +++ b/include/osmocom/netif/stream.h @@ -1,6 +1,9 @@ #ifndef _OSMO_STREAM_H_ #define _OSMO_STREAM_H_ +#define msgb_sctp_ppid(msg) (msg)->cb[3] +#define msgb_sctp_stream(msg) (msg)->cb[4] + struct osmo_stream_srv_link; struct osmo_stream_srv_link *osmo_stream_srv_link_create(void *ctx); @@ -8,6 +11,7 @@ void osmo_stream_srv_link_destroy(struct osmo_stream_srv_link *link); void osmo_stream_srv_link_set_addr(struct osmo_stream_srv_link *link, const char *addr); void osmo_stream_srv_link_set_port(struct osmo_stream_srv_link *link, uint16_t port); +void osmo_stream_srv_link_set_proto(struct osmo_stream_srv_link *link, uint16_t proto); void osmo_stream_srv_link_set_accept_cb(struct osmo_stream_srv_link *link, int (*accept_cb)(struct osmo_stream_srv_link *link, int fd)); void osmo_stream_srv_link_set_data(struct osmo_stream_srv_link *link, void *data); void *osmo_stream_srv_link_get_data(struct osmo_stream_srv_link *link); @@ -33,6 +37,7 @@ struct osmo_stream_cli; void osmo_stream_cli_set_addr(struct osmo_stream_cli *cli, const char *addr); void osmo_stream_cli_set_port(struct osmo_stream_cli *cli, uint16_t port); +void osmo_stream_cli_set_proto(struct osmo_stream_cli *cli, uint16_t proto); void osmo_stream_cli_set_data(struct osmo_stream_cli *cli, void *data); void osmo_stream_cli_set_reconnect_timeout(struct osmo_stream_cli *cli, int timeout); void *osmo_stream_cli_get_data(struct osmo_stream_cli *cli); diff --git a/src/Makefile.am b/src/Makefile.am index 641dcc9..4bc481e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,14 +3,14 @@ LIBVERSION=3:0:0 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir) -AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) +AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) $(LIBSCTP_CFLAGS) AM_LDFLAGS = $(COVERAGE_LDFLAGS) SUBDIRS = channel lib_LTLIBRARIES = libosmonetif.la -libosmonetif_la_LIBADD = channel/abis/libosmonetif-abis.la $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) +libosmonetif_la_LIBADD = channel/abis/libosmonetif-abis.la $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBSCTP_LIBS) libosmonetif_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined libosmonetif_la_SOURCES = amr.c \ diff --git a/src/stream.c b/src/stream.c index 8c7fde7..21c99c7 100644 --- a/src/stream.c +++ b/src/stream.c @@ -20,6 +20,29 @@ #include +#include "config.h" + +#ifdef HAVE_LIBSCTP +#include +#endif + +static int sctp_sock_activate_events(int fd) +{ +#ifdef HAVE_LIBSCTP + struct sctp_event_subscribe event; + int rc; + + /* subscribe for all events */ + memset((uint8_t *)&event, 1, sizeof(event)); + rc = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, + &event, sizeof(event)); + + return rc; +#else + return -1; +#endif +} + /* * Client side. */ @@ -40,6 +63,7 @@ struct osmo_stream_cli { enum osmo_stream_cli_state state; const char *addr; uint16_t port; + uint16_t proto; int (*connect_cb)(struct osmo_stream_cli *srv); int (*read_cb)(struct osmo_stream_cli *srv); int (*write_cb)(struct osmo_stream_cli *srv); @@ -80,6 +104,9 @@ static void osmo_stream_cli_read(struct osmo_stream_cli *cli) static int osmo_stream_cli_write(struct osmo_stream_cli *cli) { +#ifdef HAVE_LIBSCTP + struct sctp_sndrcvinfo sinfo; +#endif struct msgb *msg; struct llist_head *lh; int ret; @@ -99,7 +126,20 @@ static int osmo_stream_cli_write(struct osmo_stream_cli *cli) return 0; } - ret = send(cli->ofd.fd, msg->data, msg->len, 0); + switch (cli->proto) { +#ifdef HAVE_LIBSCTP + case IPPROTO_SCTP: + sinfo.sinfo_ppid = htonl(msgb_sctp_ppid(msg)); + sinfo.sinfo_stream = htonl(msgb_sctp_stream(msg)); + ret = sctp_send(cli->ofd.fd, msg->data, msgb_length(msg), + &sinfo, MSG_NOSIGNAL); + break; +#endif + case IPPROTO_TCP: + default: + ret = send(cli->ofd.fd, msg->data, msg->len, 0); + break; + } if (ret < 0) { if (errno == EPIPE || errno == ENOTCONN) { osmo_stream_cli_reconnect(cli); @@ -126,6 +166,8 @@ static int osmo_stream_cli_fd_cb(struct osmo_fd *ofd, unsigned int what) ofd->when &= ~BSC_FD_WRITE; LOGP(DLINP, LOGL_DEBUG, "connection done.\n"); cli->state = STREAM_CLI_STATE_CONNECTED; + if (cli->proto == IPPROTO_SCTP) + sctp_sock_activate_events(ofd->fd); if (cli->connect_cb) cli->connect_cb(cli); break; @@ -155,6 +197,7 @@ struct osmo_stream_cli *osmo_stream_cli_create(void *ctx) if (!cli) return NULL; + cli->proto = IPPROTO_TCP; cli->ofd.fd = -1; cli->ofd.when |= BSC_FD_READ | BSC_FD_WRITE; cli->ofd.priv_nr = 0; /* XXX */ @@ -183,6 +226,13 @@ osmo_stream_cli_set_port(struct osmo_stream_cli *cli, uint16_t port) cli->flags |= OSMO_STREAM_CLI_F_RECONF; } +void +osmo_stream_cli_set_proto(struct osmo_stream_cli *cli, uint16_t proto) +{ + cli->proto = proto; + cli->flags |= OSMO_STREAM_CLI_F_RECONF; +} + void osmo_stream_cli_set_reconnect_timeout(struct osmo_stream_cli *cli, int timeout) { @@ -235,9 +285,9 @@ int osmo_stream_cli_open(struct osmo_stream_cli *cli) cli->flags &= ~OSMO_STREAM_CLI_F_RECONF; - ret = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, + ret = osmo_sock_init(AF_INET, SOCK_STREAM, cli->proto, cli->addr, cli->port, - OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_NONBLOCK); + OSMO_SOCK_F_CONNECT); if (ret < 0) { if (errno != EINPROGRESS) return ret; @@ -303,6 +353,7 @@ struct osmo_stream_srv_link { struct osmo_fd ofd; const char *addr; uint16_t port; + uint16_t proto; int (*accept_cb)(struct osmo_stream_srv_link *srv, int fd); void *data; int flags; @@ -324,6 +375,9 @@ static int osmo_stream_srv_fd_cb(struct osmo_fd *ofd, unsigned int what) LOGP(DLINP, LOGL_DEBUG, "accept()ed new link from %s to port %u\n", inet_ntoa(sa.sin_addr), link->port); + if (link->proto == IPPROTO_SCTP) + sctp_sock_activate_events(ret); + if (link->accept_cb) link->accept_cb(link, ret); @@ -338,6 +392,7 @@ struct osmo_stream_srv_link *osmo_stream_srv_link_create(void *ctx) if (!link) return NULL; + link->proto = IPPROTO_TCP; link->ofd.fd = -1; link->ofd.when |= BSC_FD_READ | BSC_FD_WRITE; link->ofd.cb = osmo_stream_srv_fd_cb; @@ -360,6 +415,14 @@ void osmo_stream_srv_link_set_port(struct osmo_stream_srv_link *link, link->flags |= OSMO_STREAM_SRV_F_RECONF; } +void +osmo_stream_srv_link_set_proto(struct osmo_stream_srv_link *link, + uint16_t proto) +{ + link->proto = proto; + link->flags |= OSMO_STREAM_SRV_F_RECONF; +} + void osmo_stream_srv_link_set_data(struct osmo_stream_srv_link *link, void *data) @@ -400,7 +463,7 @@ int osmo_stream_srv_link_open(struct osmo_stream_srv_link *link) link->flags &= ~OSMO_STREAM_SRV_F_RECONF; - ret = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, + ret = osmo_sock_init(AF_INET, SOCK_STREAM, link->proto, link->addr, link->port, OSMO_SOCK_F_BIND); if (ret < 0) return ret; @@ -440,6 +503,9 @@ static void osmo_stream_srv_read(struct osmo_stream_srv *conn) static void osmo_stream_srv_write(struct osmo_stream_srv *conn) { +#ifdef HAVE_LIBSCTP + struct sctp_sndrcvinfo sinfo; +#endif struct msgb *msg; struct llist_head *lh; int ret; @@ -454,7 +520,20 @@ static void osmo_stream_srv_write(struct osmo_stream_srv *conn) llist_del(lh); msg = llist_entry(lh, struct msgb, list); - ret = send(conn->ofd.fd, msg->data, msg->len, 0); + switch (conn->srv->proto) { +#ifdef HAVE_LIBSCTP + case IPPROTO_SCTP: + sinfo.sinfo_ppid = htonl(msgb_sctp_ppid(msg)); + sinfo.sinfo_stream = htonl(msgb_sctp_stream(msg)); + ret = sctp_send(conn->ofd.fd, msg->data, msgb_length(msg), + &sinfo, MSG_NOSIGNAL); + break; +#endif + case IPPROTO_TCP: + default: + ret = send(conn->ofd.fd, msg->data, msg->len, 0); + break; + } if (ret < 0) { LOGP(DLINP, LOGL_ERROR, "error to send\n"); } -- cgit v1.2.3