From da06516b26b459664ca4b5ea9e450dd76ac1d91f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 23 Jun 2012 21:58:41 +0200 Subject: initial skeleton for accepting UMA/GAN connections --- openbsc/src/osmo-ganc/conn.c | 145 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 openbsc/src/osmo-ganc/conn.c (limited to 'openbsc/src/osmo-ganc/conn.c') diff --git a/openbsc/src/osmo-ganc/conn.c b/openbsc/src/osmo-ganc/conn.c new file mode 100644 index 000000000..1c252757f --- /dev/null +++ b/openbsc/src/osmo-ganc/conn.c @@ -0,0 +1,145 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "conn.h" + + +static int slave_read_cb(struct osmo_fd *ofd) +{ + struct osmo_conn *conn = ofd->data; + + return conn->link->slave_read_cb(conn); +} + +static int slave_write_cb(struct osmo_fd *ofd, struct msgb *msg) +{ + int rc; + + rc = send(ofd->fd, msg->data, msg->len, 0); + if (rc < 0) { + LOGP(DLINP, LOGL_ERROR, "error %d on send()\n", rc); + } + + return rc; +} + +static int server_fd_cb(struct osmo_fd *ofd, unsigned int what) +{ + int rc; + struct sockaddr_in sa; + socklen_t sa_len = sizeof(sa); + struct osmo_link *link = ofd->data; + struct osmo_conn *conn; + + rc = accept(ofd->fd, (struct sockaddr *)&sa, &sa_len); + if (rc < 0) + return rc; + + conn = talloc_zero(link, struct osmo_conn); + if (!conn) { + close(rc); + return -ENOMEM; + } + + conn->link = link; + osmo_wqueue_init(&conn->queue, link->slave_max_qlen); + conn->queue.read_cb = slave_read_cb; + conn->queue.write_cb = slave_write_cb; + + conn->queue.bfd.when = BSC_FD_READ | BSC_FD_WRITE; + conn->queue.bfd.data = conn; + + conn->remote.host = talloc_strdup(conn, inet_ntoa(sa.sin_addr)); + conn->remote.port = ntohs(sa.sin_port); + + llist_add_tail(&conn->list, &link->conns); + + LOGP(DLINP, LOGL_NOTICE, "accept()ed new UNC link from %s:%u to port %u\n", + conn->remote.host, conn->remote.port, link->port); + + if (link->accept_cb) + link->accept_cb(conn); + + return 0; +} + +struct osmo_link *osmo_link_create(void *ctx, const char *addr, uint16_t port, + int (*read_cb)(struct osmo_conn *), + int slave_max_qlen) +{ + struct osmo_link *link; + + link = talloc_zero(ctx, struct osmo_link); + if (!link) + return NULL; + + link->ofd.when = BSC_FD_READ | BSC_FD_WRITE; + link->ofd.cb = server_fd_cb; + link->ofd.data = link; + link->addr = talloc_strdup(link, addr); + link->port = port; + link->slave_read_cb = read_cb; + link->slave_max_qlen = slave_max_qlen; + INIT_LLIST_HEAD(&link->conns); + + return link; +} + + +int osmo_link_listen(struct osmo_link *link, + void (*accept_cb)(struct osmo_conn *)) +{ + int rc; + + rc = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, + link->addr, link->port, OSMO_SOCK_F_BIND); + + link->ofd.fd = rc; + + if (osmo_fd_register(&link->ofd) < 0) { + close(rc); + return -EIO; + } + link->accept_cb = accept_cb; + + return 0; +} + +int osmo_conn_enqueue(struct osmo_conn *conn, struct msgb *msg) +{ + return osmo_wqueue_enqueue(&conn->queue, msg); +} + +void osmo_conn_close(struct osmo_conn *conn) +{ + close(conn->queue.bfd.fd); + osmo_wqueue_clear(&conn->queue); + llist_del(&conn->list); + + talloc_free(conn); +} + +int osmo_link_close(struct osmo_link *link) +{ + struct osmo_conn *conn, *conn2; + + osmo_fd_unregister(&link->ofd); + close(link->ofd.fd); + + llist_for_each_entry_safe(conn, conn2, &link->conns, list) + osmo_conn_close(conn); + + return 0; +} -- cgit v1.2.3