summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso2011-06-21 19:56:26 +0200
committerPablo Neira Ayuso2011-06-21 19:56:26 +0200
commit986191fadf6a79bdaf99de240baef21d8675ab0b (patch)
treebfa8992d125c2c88c3db01fde0c65f99427a66ab
parentipa: rename `struct ipa_link' by `struct ipa_client_link' (diff)
downloadlibosmo-abis-986191fadf6a79bdaf99de240baef21d8675ab0b.tar.gz
libosmo-abis-986191fadf6a79bdaf99de240baef21d8675ab0b.tar.xz
libosmo-abis-986191fadf6a79bdaf99de240baef21d8675ab0b.zip
ipa: add ipa_server_link abstraction
This patch adds the ipa_server_link which allows to create IPA servers. I have also changed the ipaccess driver to use it. Still missing the port of HSL driver.
-rw-r--r--include/osmocom/abis/ipa.h15
-rw-r--r--src/input/ipa.c73
-rw-r--r--src/input/ipaccess.c104
3 files changed, 131 insertions, 61 deletions
diff --git a/include/osmocom/abis/ipa.h b/include/osmocom/abis/ipa.h
index bba7e8f..1a9e5d4 100644
--- a/include/osmocom/abis/ipa.h
+++ b/include/osmocom/abis/ipa.h
@@ -5,6 +5,21 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
+struct ipa_server_link {
+ struct e1inp_line *line;
+ struct osmo_fd ofd;
+ struct llist_head tx_queue;
+ const char *addr;
+ uint16_t port;
+ int (*accept_cb)(struct ipa_server_link *link, int fd);
+};
+
+struct ipa_server_link *ipa_server_link_create(void *ctx, struct e1inp_line *line, const char *addr, uint16_t port, int (*accept_cb)(struct ipa_server_link *link, int fd));
+void ipa_server_link_destroy(struct ipa_server_link *link);
+
+int ipa_server_link_open(struct ipa_server_link *link);
+void ipa_server_link_close(struct ipa_server_link *link);
+
enum ipa_client_link_state {
IPA_CLIENT_LINK_STATE_NONE = 0,
IPA_CLIENT_LINK_STATE_CONNECTING = 1,
diff --git a/src/input/ipa.c b/src/input/ipa.c
index 7c84559..d99e310 100644
--- a/src/input/ipa.c
+++ b/src/input/ipa.c
@@ -239,3 +239,76 @@ static void ipa_link_timer_cb(void *data)
break;
}
}
+
+int ipa_server_fd_cb(struct osmo_fd *ofd, unsigned int what)
+{
+ int ret;
+ struct sockaddr_in sa;
+ socklen_t sa_len = sizeof(sa);
+ struct ipa_server_link *link = ofd->data;
+
+ ret = accept(ofd->fd, (struct sockaddr *)&sa, &sa_len);
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "failed to accept from origin "
+ "peer, reason=`%s'\n", strerror(errno));
+ return ret;
+ }
+ LOGP(DINP, LOGL_NOTICE, "accept()ed new link from %s to port %u\n",
+ inet_ntoa(sa.sin_addr), link->port);
+
+ if (link->accept_cb)
+ link->accept_cb(link, ret);
+
+ return 0;
+}
+
+struct ipa_server_link *
+ipa_server_link_create(void *ctx, struct e1inp_line *line,
+ const char *addr, uint16_t port,
+ int (*accept_cb)(struct ipa_server_link *link, int fd))
+{
+ struct ipa_server_link *ipa_link;
+
+ ipa_link = talloc_zero(ctx, struct ipa_server_link);
+ if (!ipa_link)
+ return NULL;
+
+ ipa_link->ofd.when |= BSC_FD_READ | BSC_FD_WRITE;
+ ipa_link->ofd.cb = ipa_server_fd_cb;
+ ipa_link->ofd.data = ipa_link;
+ ipa_link->addr = talloc_strdup(ipa_link, addr);
+ ipa_link->port = port;
+ ipa_link->accept_cb = accept_cb;
+ ipa_link->line = line;
+
+ return ipa_link;
+
+}
+
+void ipa_server_link_destroy(struct ipa_server_link *link)
+{
+ talloc_free(link);
+}
+
+int ipa_server_link_open(struct ipa_server_link *link)
+{
+ int ret;
+
+ ret = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP,
+ link->addr, link->port, OSMO_SOCK_F_BIND);
+ if (ret < 0)
+ return ret;
+
+ link->ofd.fd = ret;
+ if (osmo_fd_register(&link->ofd) < 0) {
+ close(ret);
+ return -EIO;
+ }
+ return 0;
+}
+
+void ipa_server_link_close(struct ipa_server_link *link)
+{
+ osmo_fd_unregister(&link->ofd);
+ close(link->ofd.fd);
+}
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index 60e7109..3c0f59b 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -181,6 +181,7 @@ static int handle_ts1_read(struct osmo_fd *bfd)
osmo_fd_unregister(bfd);
close(bfd->fd);
bfd->fd = -1;
+ talloc_free(bfd);
}
return error;
}
@@ -338,27 +339,18 @@ struct e1inp_driver ipaccess_driver = {
};
/* callback of the OML listening filedescriptor */
-static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
+static int ipaccess_bsc_oml_cb(struct ipa_server_link *link, int fd)
{
int ret;
int idx = 0;
int i;
- struct e1inp_line *line = listen_bfd->data;
+ struct e1inp_line *line = link->line;
struct e1inp_ts *e1i_ts;
struct osmo_fd *bfd;
- struct sockaddr_in sa;
- socklen_t sa_len = sizeof(sa);
- if (!(what & BSC_FD_READ))
- return 0;
-
- ret = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len);
- if (ret < 0) {
- perror("accept");
- return ret;
- }
- LOGP(DINP, LOGL_NOTICE, "accept()ed new OML link from %s\n",
- inet_ntoa(sa.sin_addr));
+ bfd = talloc_zero(tall_ipa_ctx, struct osmo_fd);
+ if (!bfd)
+ return -ENOMEM;
/* create virrtual E1 timeslots for signalling */
e1inp_ts_config_sign(&line->ts[1-1], line);
@@ -369,8 +361,7 @@ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
e1i_ts = &line->ts[idx];
- bfd = &e1i_ts->driver.ipaccess.fd;
- bfd->fd = ret;
+ bfd->fd = fd;
bfd->data = line;
bfd->priv_nr = PRIV_OML;
bfd->cb = ipaccess_fd_cb;
@@ -379,6 +370,7 @@ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
if (ret < 0) {
LOGP(DINP, LOGL_ERROR, "could not register FD\n");
close(bfd->fd);
+ talloc_free(bfd);
return ret;
}
@@ -388,30 +380,16 @@ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
return ret;
}
-static int rsl_listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
+static int ipaccess_bsc_rsl_cb(struct ipa_server_link *link, int fd)
{
- struct sockaddr_in sa;
- socklen_t sa_len = sizeof(sa);
struct osmo_fd *bfd;
int ret;
- if (!(what & BSC_FD_READ))
- return 0;
-
bfd = talloc_zero(tall_ipa_ctx, struct osmo_fd);
if (!bfd)
return -ENOMEM;
- /* Some BTS has connected to us, but we don't know yet which line
- * (as created by the OML link) to associate it with. Thus, we
- * allocate a temporary bfd until we have received ID from BTS */
-
- bfd->fd = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len);
- if (bfd->fd < 0) {
- perror("accept");
- return bfd->fd;
- }
- LOGP(DINP, LOGL_NOTICE, "accept()ed new RSL link from %s\n", inet_ntoa(sa.sin_addr));
+ bfd->fd = fd;
bfd->priv_nr = PRIV_RSL;
bfd->cb = ipaccess_fd_cb;
bfd->when = BSC_FD_READ;
@@ -484,40 +462,44 @@ static int ipaccess_line_update(struct e1inp_line *line,
int ret = -ENOENT;
switch(role) {
- case E1INP_LINE_R_BSC:
- LOGP(DINP, LOGL_NOTICE, "enabling ipaccess BSC mode\n");
+ case E1INP_LINE_R_BSC: {
+ struct ipa_server_link *oml_link, *rsl_link;
- /* Listen for OML connections */
- ret = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP,
- addr, IPA_TCP_PORT_OML, OSMO_SOCK_F_BIND);
- if (ret < 0)
- return ret;
-
- e1h->listen_fd.fd = ret;
- e1h->listen_fd.when |= BSC_FD_READ;
- e1h->listen_fd.cb = listen_fd_cb;
- e1h->listen_fd.data = line;
+ LOGP(DINP, LOGL_NOTICE, "enabling ipaccess BSC mode\n");
- if (osmo_fd_register(&e1h->listen_fd) < 0) {
- close(ret);
- return ret;
+ oml_link = ipa_server_link_create(tall_ipa_ctx, line,
+ "0.0.0.0", IPA_TCP_PORT_OML,
+ ipaccess_bsc_oml_cb);
+ if (oml_link == NULL) {
+ LOGP(DINP, LOGL_ERROR, "cannot create OML "
+ "BSC link: %s\n", strerror(errno));
+ return -ENOMEM;
}
- /* Listen for RSL connections */
- ret = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP,
- addr, IPA_TCP_PORT_RSL, OSMO_SOCK_F_BIND);
- if (ret < 0)
- return ret;
-
- e1h->rsl_listen_fd.fd = ret;
- e1h->rsl_listen_fd.when |= BSC_FD_READ;
- e1h->rsl_listen_fd.cb = rsl_listen_fd_cb;
- e1h->rsl_listen_fd.data = NULL;
-
- if (osmo_fd_register(&e1h->rsl_listen_fd) < 0) {
- close(ret);
- return ret;
+ if (ipa_server_link_open(oml_link) < 0) {
+ LOGP(DINP, LOGL_ERROR, "cannot open OML BSC link: %s\n",
+ strerror(errno));
+ ipa_server_link_close(oml_link);
+ ipa_server_link_destroy(oml_link);
+ return -EIO;
}
+ rsl_link = ipa_server_link_create(tall_ipa_ctx, line,
+ "0.0.0.0", IPA_TCP_PORT_RSL,
+ ipaccess_bsc_rsl_cb);
+ if (rsl_link == NULL) {
+ LOGP(DINP, LOGL_ERROR, "cannot create RSL "
+ "BSC link: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+ if (ipa_server_link_open(rsl_link) < 0) {
+ LOGP(DINP, LOGL_ERROR, "cannot open RSL BSC link: %s\n",
+ strerror(errno));
+ ipa_server_link_close(rsl_link);
+ ipa_server_link_destroy(rsl_link);
+ return -EIO;
+ }
+ ret = 0;
break;
+ }
case E1INP_LINE_R_BTS: {
struct ipa_client_link *link, *rsl_link;