summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso2011-06-07 14:07:48 +0200
committerPablo Neira Ayuso2011-06-07 17:28:53 +0200
commit5a4b7c54c699889b3255e578ef75c0989622b541 (patch)
tree17aa3d1999806375e0ce7e627cca406dcaec9940 /src
parente1input: log_set_context(...) should be called from the application (diff)
downloadlibosmo-abis-5a4b7c54c699889b3255e578ef75c0989622b541.tar.gz
libosmo-abis-5a4b7c54c699889b3255e578ef75c0989622b541.tar.xz
libosmo-abis-5a4b7c54c699889b3255e578ef75c0989622b541.zip
e1input: rework generic (virtual and real) E1 line operations
struct e1inp_line_ops { int (*sign_link_up)(struct msgb *msg, struct e1inp_line *line); int (*sign_link)(struct msgb *msg, struct e1inp_sign_link *link); int (*error)(struct msgb *msg, int error); }; The description of the operations is the following: * sign_link_up is invoked if the signalling link becomes up. In A-bis over IP, we have to wait until the other peer identifies itself as a BTS/BSC device, then this function is invoked. This function is not used by ISDN drivers, the signalling link can be set up just after the line is created. * sign_link is called if we receive OML/RSL message. This function is used both by ISDN and A-bis over IP drivers. * error is called if we receive a malformed message. It is used both by ISDN and A-bis over IP drivers.
Diffstat (limited to 'src')
-rw-r--r--src/e1_input.c16
-rw-r--r--src/input/dahdi.c8
-rw-r--r--src/input/hsl.c56
-rw-r--r--src/input/ipaccess.c79
-rw-r--r--src/input/misdn.c5
5 files changed, 143 insertions, 21 deletions
diff --git a/src/e1_input.c b/src/e1_input.c
index 1c3d3b0..7904f61 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -305,8 +305,7 @@ struct e1inp_line *e1inp_line_get(uint8_t e1_nr)
struct e1inp_line *
e1inp_line_create(uint8_t e1_nr, const char *driver_name,
- int (*rx)(struct msgb *msgb, struct e1inp_ts *ts),
- int (*rx_err)(int error))
+ const struct e1inp_line_ops *ops)
{
struct e1inp_driver *driver;
struct e1inp_line *line;
@@ -331,8 +330,7 @@ e1inp_line_create(uint8_t e1_nr, const char *driver_name,
return NULL;
line->driver = driver;
- line->rx = rx;
- line->rx_err = rx_err;
+ memcpy(&line->ops, ops, sizeof(struct e1inp_line_ops));
line->num = e1_nr;
for (i = 0; i < NUM_E1_TS; i++) {
@@ -467,10 +465,12 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
"tei %d, sapi %d\n", tei, sapi);
return -EINVAL;
}
- if (!ts->line->rx)
- printf("XXX Error, horror\n");
-
- ts->line->rx(msg, ts);
+ if (!ts->line->ops.sign_link) {
+ LOGP(DINP, LOGL_ERROR, "Fix your application, "
+ "no action set for signalling messages.\n");
+ return -ENOENT;
+ }
+ ts->line->ops.sign_link(msg, link);
break;
case E1INP_TS_TYPE_TRAU:
ret = subch_demux_in(&ts->trau.demux, msg->l2h, msgb_l2len(msg));
diff --git a/src/input/dahdi.c b/src/input/dahdi.c
index ba8ce02..8e5e635 100644
--- a/src/input/dahdi.c
+++ b/src/input/dahdi.c
@@ -121,8 +121,11 @@ static int handle_ts1_read(struct osmo_fd *bfd)
DEBUGP(DMI, "<= len = %d, sapi(%d) tei(%d)", ret, sapi, tei);
idata = lapd_receive(e1i_ts->driver.dahdi.lapd, msg->data, msg->len, &ilen, &prim);
- if (!idata && prim == 0)
+ if (!idata && prim == 0) {
+ if (line->ops.error)
+ line->ops.error(NULL, -EBADMSG);
return -EIO;
+ }
msgb_pull(msg, 2);
@@ -149,7 +152,8 @@ static int handle_ts1_read(struct osmo_fd *bfd)
ret = e1inp_rx_ts(e1i_ts, msg, tei, sapi);
break;
default:
- printf("ERROR: unknown prim\n");
+ if (line->ops.error)
+ line->ops.error(NULL, -EBADMSG);
break;
}
diff --git a/src/input/hsl.c b/src/input/hsl.c
index b7c7897..97475cf 100644
--- a/src/input/hsl.c
+++ b/src/input/hsl.c
@@ -77,13 +77,15 @@ static int handle_ts1_read(struct osmo_fd *bfd)
struct e1inp_line *line = bfd->data;
unsigned int ts_nr = bfd->priv_nr;
struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct e1inp_sign_link *link;
+ struct ipaccess_head *hh;
struct msgb *msg;
int ret = 0, error;
msg = ipaccess_read_msg(bfd, &error);
if (!msg) {
- if (e1i_ts->line->rx_err)
- e1i_ts->line->rx_err(error);
+ if (e1i_ts->line->ops.error)
+ e1i_ts->line->ops.error(NULL, error);
if (error == 0) {
osmo_fd_unregister(bfd);
close(bfd->fd);
@@ -93,9 +95,53 @@ static int handle_ts1_read(struct osmo_fd *bfd)
}
DEBUGP(DMI, "RX %u: %s\n", ts_nr, osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
- /* XXX better use e1inp_rx_ts. */
- if (e1i_ts->line->rx)
- e1i_ts->line->rx(msg, e1i_ts);
+ hh = (struct ipaccess_head *) msg->data;
+ if (hh->proto == HSL_PROTO_DEBUG) {
+ LOGP(DINP, LOGL_NOTICE, "HSL debug: %s\n", msg->data + sizeof(*hh));
+ msgb_free(msg);
+ return ret;
+ }
+
+ /* HSL proprietary RSL extension */
+ if (hh->proto == 0 && (msg->l2h[0] == 0x81 || msg->l2h[0] == 0x80)) {
+ if (!line->ops.sign_link_up) {
+ LOGP(DINP, LOGL_ERROR, "Fix your application, no "
+ "action set if the signalling link "
+ "becomes ready.\n");
+ return -EINVAL;
+ }
+ ret = line->ops.sign_link_up(msg, line);
+ if (ret < 0) {
+ /* FIXME: close connection */
+ if (line->ops.error)
+ line->ops.error(msg, -EBADMSG);
+ return ret;
+ } else if (ret == 1)
+ return 0;
+ /* else: continue... */
+ }
+
+#ifdef HSL_SR_1_0
+ /* HSL for whatever reason chose to use 0x81 instead of 0x80 for FOM */
+ if (hh->proto == 255 && msg->l2h[0] == (ABIS_OM_MDISC_FOM | 0x01))
+ msg->l2h[0] = ABIS_OM_MDISC_FOM;
+#endif
+ link = e1inp_lookup_sign_link(e1i_ts, hh->proto, 0);
+ if (!link) {
+ LOGP(DINP, LOGL_ERROR, "no matching signalling link for "
+ "hh->proto=0x%02x\n", hh->proto);
+ msgb_free(msg);
+ return -EIO;
+ }
+ msg->dst = link;
+
+ /* XXX: better use e1inp_ts_rx? */
+ if (!e1i_ts->line->ops.sign_link) {
+ LOGP(DINP, LOGL_ERROR, "Fix your application, "
+ "no action set for signalling messages.\n");
+ return -ENOENT;
+ }
+ e1i_ts->line->ops.sign_link(msg, link);
return ret;
}
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index ef773ba..92819ac 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -170,18 +170,65 @@ struct msgb *ipaccess_read_msg(struct osmo_fd *bfd, int *error)
return msg;
}
+/* base handling of the ip.access protocol */
+int ipaccess_rcvmsg_base(struct msgb *msg,
+ struct osmo_fd *bfd)
+{
+ uint8_t msg_type = *(msg->l2h);
+ int ret = 0;
+
+ switch (msg_type) {
+ case IPAC_MSGT_PING:
+ ret = ipaccess_send_pong(bfd->fd);
+ break;
+ case IPAC_MSGT_PONG:
+ DEBUGP(DMI, "PONG!\n");
+ break;
+ case IPAC_MSGT_ID_ACK:
+ DEBUGP(DMI, "ID_ACK? -> ACK!\n");
+ ret = ipaccess_send_id_ack(bfd->fd);
+ break;
+ }
+ return 0;
+}
+
+static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
+ struct osmo_fd *bfd)
+{
+ uint8_t msg_type = *(msg->l2h);
+
+ /* handle base messages */
+ ipaccess_rcvmsg_base(msg, bfd);
+
+ switch (msg_type) {
+ case IPAC_MSGT_ID_RESP:
+ DEBUGP(DMI, "ID_RESP\n");
+ if (!line->ops.sign_link_up) {
+ LOGP(DINP, LOGL_ERROR, "Fix your application, "
+ "no action set if the signalling link "
+ "becomes ready\n");
+ return -EINVAL;
+ }
+ line->ops.sign_link_up(msg, line);
+ break;
+ }
+ return 0;
+}
+
static int handle_ts1_read(struct osmo_fd *bfd)
{
struct e1inp_line *line = bfd->data;
unsigned int ts_nr = bfd->priv_nr;
struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+ struct e1inp_sign_link *link;
+ struct ipaccess_head *hh;
struct msgb *msg;
int ret = 0, error;
msg = ipaccess_read_msg(bfd, &error);
if (!msg) {
- if (e1i_ts->line->rx_err)
- e1i_ts->line->rx_err(error);
+ if (e1i_ts->line->ops.error)
+ e1i_ts->line->ops.error(NULL, error);
if (error == 0) {
osmo_fd_unregister(bfd);
close(bfd->fd);
@@ -191,10 +238,32 @@ static int handle_ts1_read(struct osmo_fd *bfd)
}
DEBUGP(DMI, "RX %u: %s\n", ts_nr, osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
- /* XXX better use e1inp_ts_rx. */
+ hh = (struct ipaccess_head *) msg->data;
+ if (hh->proto == IPAC_PROTO_IPACCESS) {
+ ipaccess_rcvmsg(line, msg, bfd);
+ msgb_free(msg);
+ return ret;
+ }
+ /* BIG FAT WARNING: bfd might no longer exist here, since ipaccess_rcvmsg()
+ * might have free'd it !!! */
+
+ link = e1inp_lookup_sign_link(e1i_ts, hh->proto, 0);
+ if (!link) {
+ LOGP(DINP, LOGL_ERROR, "no matching signalling link for "
+ "hh->proto=0x%02x\n", hh->proto);
+ msgb_free(msg);
+ return -EIO;
+ }
+ msg->dst = link;
+
+ /* XXX better use e1inp_ts_rx? */
+ if (!e1i_ts->line->ops.sign_link) {
+ LOGP(DINP, LOGL_ERROR, "Fix your application, "
+ "no action set for signalling messages.\n");
+ return -ENOENT;
+ }
+ e1i_ts->line->ops.sign_link(msg, link);
- if (e1i_ts->line->rx)
- e1i_ts->line->rx(msg, e1i_ts);
return ret;
}
diff --git a/src/input/misdn.c b/src/input/misdn.c
index c97169a..afa9032 100644
--- a/src/input/misdn.c
+++ b/src/input/misdn.c
@@ -115,7 +115,8 @@ static int handle_ts1_read(struct osmo_fd *bfd)
}
if (alen != sizeof(l2addr)) {
- fprintf(stderr, "%s error len\n", __func__);
+ if (line->ops.error)
+ line->ops.error(NULL, -EBADMSG);
return -EINVAL;
}
@@ -178,6 +179,8 @@ static int handle_ts1_read(struct osmo_fd *bfd)
l2addr.channel, l2addr.sapi, l2addr.tei);
break;
default:
+ if (line->ops.error)
+ line->ops.error(NULL, -EBADMSG);
break;
}
return ret;