aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac7
-rw-r--r--include/osmocom/netif/stream.h5
-rw-r--r--src/Makefile.am4
-rw-r--r--src/stream.c89
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 <osmocom/netif/stream.h>
+#include "config.h"
+
+#ifdef HAVE_LIBSCTP
+#include <netinet/sctp.h>
+#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 */
@@ -184,6 +227,13 @@ 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)
+{
+ cli->proto = proto;
+ cli->flags |= OSMO_STREAM_CLI_F_RECONF;
+}
+
+void
osmo_stream_cli_set_reconnect_timeout(struct osmo_stream_cli *cli, int timeout)
{
cli->reconnect_timeout = 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;
@@ -361,6 +416,14 @@ void osmo_stream_srv_link_set_port(struct osmo_stream_srv_link *link,
}
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");
}