From 986191fadf6a79bdaf99de240baef21d8675ab0b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 21 Jun 2011 19:56:26 +0200 Subject: 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. --- include/osmocom/abis/ipa.h | 15 +++++++ src/input/ipa.c | 73 +++++++++++++++++++++++++++++++ src/input/ipaccess.c | 104 +++++++++++++++++++-------------------------- 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 #include +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; -- cgit v1.2.3-55-g7522