diff options
Diffstat (limited to 'src/channel/abis/ipa_stream_server.c')
-rw-r--r-- | src/channel/abis/ipa_stream_server.c | 421 |
1 files changed, 0 insertions, 421 deletions
diff --git a/src/channel/abis/ipa_stream_server.c b/src/channel/abis/ipa_stream_server.c deleted file mode 100644 index 1cd889c..0000000 --- a/src/channel/abis/ipa_stream_server.c +++ /dev/null @@ -1,421 +0,0 @@ -/* (C) 2012 by Pablo Neira Ayuso <pablo@gnumonks.org> - * All Rights Reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <sys/socket.h> -#include <errno.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/select.h> -#include <osmocom/core/msgb.h> -#include <osmocom/core/logging.h> - -#include <osmocom/gsm/tlv.h> - -#include <osmocom/netif/channel.h> -#include <osmocom/netif/stream.h> -#include <osmocom/netif/ipa.h> -#include <osmocom/netif/ipa_unit.h> - -#define CHAN_SIGN_OML 0 -#define CHAN_SIGN_RSL 1 - -/* default IPA srv ports. */ -#define IPA_TCP_PORT_OML 3002 -#define IPA_TCP_PORT_RSL 3003 - -static void *abis_ipa_srv_tall; - -static int oml_accept_cb(struct osmo_stream_srv_link *srv, int fd); -static int rsl_accept_cb(struct osmo_stream_srv_link *srv, int fd); - -struct chan_abis_ipa_srv { - struct osmo_chan *chan; - struct osmo_stream_srv_link *oml; - struct osmo_stream_srv_link *rsl; - - struct llist_head bts_list; - - void (*signal_msg)(struct msgb *msg, int type); -}; - -struct chan_abis_ipa_srv_conn { - struct chan_abis_ipa_srv *master; - - struct osmo_stream_srv *oml; - struct osmo_stream_srv *rsl; -}; - -static int chan_abis_ipa_srv_create(struct osmo_chan *chan) -{ - struct chan_abis_ipa_srv *c = (struct chan_abis_ipa_srv *)chan->data; - - c->oml = osmo_stream_srv_link_create(abis_ipa_srv_tall); - if (c->oml == NULL) - goto err_oml; - - /* default address and port for OML. */ - osmo_stream_srv_link_set_addr(c->oml, "0.0.0.0"); - osmo_stream_srv_link_set_port(c->oml, IPA_TCP_PORT_OML); - osmo_stream_srv_link_set_accept_cb(c->oml, oml_accept_cb); - osmo_stream_srv_link_set_data(c->oml, c); - - c->rsl = osmo_stream_srv_link_create(abis_ipa_srv_tall); - if (c->rsl == NULL) - goto err_rsl; - - /* default address and port for RSL. */ - osmo_stream_srv_link_set_addr(c->rsl, "0.0.0.0"); - osmo_stream_srv_link_set_port(c->rsl, IPA_TCP_PORT_RSL); - osmo_stream_srv_link_set_accept_cb(c->rsl, rsl_accept_cb); - osmo_stream_srv_link_set_data(c->rsl, c); - - INIT_LLIST_HEAD(&c->bts_list); - - return 0; -err_rsl: - osmo_stream_srv_link_destroy(c->oml); -err_oml: - return -1; -} - -static void chan_abis_ipa_srv_destroy(struct osmo_chan *chan) -{ - struct chan_abis_ipa_srv *c = (struct chan_abis_ipa_srv *)chan->data; - - osmo_stream_srv_link_destroy(c->rsl); - osmo_stream_srv_link_destroy(c->oml); -} - -static int chan_abis_ipa_srv_open(struct osmo_chan *chan) -{ - struct chan_abis_ipa_srv *c = (struct chan_abis_ipa_srv *)chan->data; - struct osmo_fd *ofd; - int ret, on = 1; - - if (osmo_stream_srv_link_open(c->oml) < 0) - goto err; - - ofd = osmo_stream_srv_link_get_ofd(c->oml); - ret = setsockopt(ofd->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); - if (ret < 0) - goto err_oml; - - if (osmo_stream_srv_link_open(c->rsl) < 0) - goto err_oml; - - ofd = osmo_stream_srv_link_get_ofd(c->rsl); - ret = setsockopt(ofd->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); - if (ret < 0) - goto err_rsl; - - return 0; - -err_rsl: - osmo_stream_srv_link_close(c->rsl); -err_oml: - osmo_stream_srv_link_close(c->oml); -err: - return -1; -} - -static void chan_abis_ipa_srv_close(struct osmo_chan *chan) -{ - struct chan_abis_ipa_srv *c = (struct chan_abis_ipa_srv *)chan->data; - - osmo_stream_srv_link_close(c->oml); - osmo_stream_srv_link_close(c->rsl); -} - -static int chan_abis_ipa_srv_enqueue(struct osmo_chan *c, struct msgb *msg) -{ - osmo_stream_srv_send(msg->dst, msg); - return 0; -} - -void osmo_abis_ipa_srv_set_oml_addr(struct osmo_chan *c, const char *addr) -{ - struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data; - - osmo_stream_srv_link_set_addr(s->oml, addr); -} - -void osmo_abis_ipa_srv_set_oml_port(struct osmo_chan *c, uint16_t port) -{ - struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data; - - osmo_stream_srv_link_set_port(s->oml, port); -} - -void osmo_abis_ipa_srv_set_rsl_addr(struct osmo_chan *c, const char *addr) -{ - struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data; - - osmo_stream_srv_link_set_addr(s->rsl, addr); -} - -void osmo_abis_ipa_srv_set_rsl_port(struct osmo_chan *c, uint16_t port) -{ - struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data; - - osmo_stream_srv_link_set_port(s->rsl, port); -} - -void osmo_abis_ipa_srv_set_cb_signalmsg(struct osmo_chan *c, - void (*signal_msg)(struct msgb *msg, int type)) -{ - struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data; - - s->signal_msg = signal_msg; -} - -int -osmo_abis_ipa_unit_add(struct osmo_chan *c, uint16_t site_id, uint16_t bts_id) -{ - struct osmo_ipa_unit *unit; - struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data; - struct chan_abis_ipa_srv_conn *inst; - - unit = osmo_ipa_unit_alloc(sizeof(struct chan_abis_ipa_srv_conn)); - if (unit == NULL) - return -1; - - osmo_ipa_unit_set_site_id(unit, site_id); - osmo_ipa_unit_set_bts_id(unit, bts_id); - osmo_ipa_unit_add(&s->bts_list, unit); - - inst = osmo_ipa_unit_get_data(unit); - inst->master = s; - - return 0; -} - -static int oml_read_cb(struct osmo_stream_srv *conn); - -static int oml_accept_cb(struct osmo_stream_srv_link *srv, int fd) -{ - struct osmo_stream_srv *conn; - struct osmo_fd *ofd; - - conn = osmo_stream_srv_create(abis_ipa_srv_tall, - srv, fd, oml_read_cb, NULL, NULL); - if (conn == NULL) { - LOGP(DLINP, LOGL_ERROR, "error while creating connection\n"); - return -1; - } - - ofd = osmo_stream_srv_get_ofd(conn); - - /* XXX: better use chan_abis_ipa_srv_enqueue. */ - ipaccess_send_id_req(ofd->fd); - - return 0; -} - -static int rsl_read_cb(struct osmo_stream_srv *conn); - -static int rsl_accept_cb(struct osmo_stream_srv_link *srv, int fd) -{ - struct osmo_stream_srv *conn; - struct osmo_fd *ofd; - - conn = osmo_stream_srv_create(abis_ipa_srv_tall, srv, fd, - rsl_read_cb, NULL, NULL); - if (conn == NULL) { - LOGP(DLINP, LOGL_ERROR, "error while creating connection\n"); - return -1; - } - - ofd = osmo_stream_srv_get_ofd(conn); - - /* XXX: better use chan_abis_ipa_srv_enqueue. */ - ipaccess_send_id_req(ofd->fd); - - return 0; -} - -static void abis_ipa_put(struct osmo_ipa_unit *unit) -{ - struct chan_abis_ipa_srv_conn *inst = osmo_ipa_unit_get_data(unit); - - osmo_stream_srv_destroy(inst->oml); - osmo_stream_srv_destroy(inst->rsl); - inst->oml = NULL; - inst->rsl = NULL; -} - -static int -abis_ipa_srv_rcvmsg(struct osmo_stream_srv *conn, struct msgb *msg, int type) -{ - uint8_t msg_type = *(msg->l2h); - struct osmo_fd *ofd = osmo_stream_srv_get_ofd(conn); - struct osmo_stream_srv_link *link = osmo_stream_srv_get_master(conn); - struct chan_abis_ipa_srv *s = osmo_stream_srv_link_get_data(link); - struct chan_abis_ipa_srv_conn *inst; - int ret; - - /* Handle IPA PING, PONG and ID_ACK messages */ - if (osmo_ipa_rcvmsg_base(msg, ofd, 1)) /* XXX: 1 indicates server */ - return 0; - - if (msg_type == IPAC_MSGT_ID_RESP) { - struct osmo_ipa_unit *unit; - struct ipaccess_unit unit_data; - - if (osmo_ipa_parse_msg_id_resp(msg, &unit_data) < 0) { - LOGP(DLINP, LOGL_ERROR, "bad ID RESP message\n"); - return -EIO; - } - - unit = osmo_ipa_unit_find(&s->bts_list, unit_data.site_id, - unit_data.bts_id); - - if (unit == NULL) { - LOGP(DLINP, LOGL_ERROR, "Unable to find BTS " - "configuration for %u/%u/%u, disconnecting\n", - unit_data.site_id, unit_data.bts_id, - unit_data.trx_id); - return 0; - } - DEBUGP(DLINP, "Identified BTS %u/%u/%u\n", - unit_data.site_id, unit_data.bts_id, - unit_data.trx_id); - - inst = osmo_ipa_unit_get_data(unit); - - if (type == CHAN_SIGN_OML) { - if (inst->oml) { - /* link already exists, kill it. */ - osmo_stream_srv_destroy(inst->oml); - return 0; - } - inst->oml = conn; - } else if (type == CHAN_SIGN_RSL) { - if (!inst->oml) { - /* no OML link? Restart from scratch. */ - abis_ipa_put(unit); - return 0; - } - if (inst->rsl) { - /* RSL link already exists, kill it. */ - osmo_stream_srv_destroy(inst->rsl); - return 0; - } - inst->rsl = conn; - } - osmo_stream_srv_set_data(conn, unit); - ret = 0; - } else { - LOGP(DLINP, LOGL_ERROR, "Unknown IPA message type\n"); - ret = -EINVAL; - } - return ret; -} - -static int read_cb(struct osmo_stream_srv *conn, int type) -{ - int ret; - struct msgb *msg; - struct osmo_ipa_unit *unit = osmo_stream_srv_get_data(conn); - struct chan_abis_ipa_srv_conn *inst; - struct ipa_head *hh; - - LOGP(DLINP, LOGL_DEBUG, "received message from stream\n"); - - msg = osmo_ipa_msg_alloc(0); - if (msg == NULL) { - LOGP(DLINP, LOGL_ERROR, "cannot allocate message\n"); - return 0; - } - ret = osmo_stream_srv_recv(conn, msg); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "cannot receive message\n"); - msgb_free(msg); - if (unit != NULL) - abis_ipa_put(unit); - else - osmo_stream_srv_destroy(conn); - - return 0; - } else if (ret == 0) { - /* link has vanished, dead socket. */ - LOGP(DLINP, LOGL_ERROR, "closed connection\n"); - msgb_free(msg); - if (unit != NULL) - abis_ipa_put(unit); - else - osmo_stream_srv_destroy(conn); - - return 0; - } - ret = osmo_ipa_process_msg(msg); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "invalid IPA message\n"); - msgb_free(msg); - } - - hh = (struct ipa_head *) msg->data; - if (hh->proto == IPAC_PROTO_IPACCESS) { - abis_ipa_srv_rcvmsg(conn, msg, type); - msgb_free(msg); - return -EIO; - } - - if (unit == NULL) { - LOGP(DLINP, LOGL_ERROR, "no IPA unit associated to this " - "connection\n"); - return -EIO; - } - inst = osmo_ipa_unit_get_data(unit); - - if (hh->proto != IPAC_PROTO_OML && hh->proto != IPAC_PROTO_RSL) { - LOGP(DLINP, LOGL_ERROR, "wrong protocol\n"); - return -EIO; - } - msg->dst = conn; - - inst->master->signal_msg(msg, type); - - return 0; -} - -static int oml_read_cb(struct osmo_stream_srv *conn) -{ - return read_cb(conn, CHAN_SIGN_OML); -} - -static int rsl_read_cb(struct osmo_stream_srv *conn) -{ - return read_cb(conn, CHAN_SIGN_RSL); -} - -struct osmo_chan_type chan_abis_ipa_srv = { - .type = OSMO_CHAN_ABIS_IPA_SRV, - .subtype = OSMO_SUBCHAN_STREAM, - .name = "A-bis IPA server", - .datasiz = sizeof(struct chan_abis_ipa_srv), - .create = chan_abis_ipa_srv_create, - .destroy = chan_abis_ipa_srv_destroy, - .open = chan_abis_ipa_srv_open, - .close = chan_abis_ipa_srv_close, - .enqueue = chan_abis_ipa_srv_enqueue, -}; |