diff --git a/src/scXp.c b/src/scXp.c index 9617f8d..62cb3da 100644 --- a/src/scXp.c +++ b/src/scXp.c @@ -1,13 +1,17 @@ /* SCCP / SCTP+SUA interface */ #include +#include #include +#include #include #include - +#include +#include #include #include +#include #include "tcap_user.h" #include "tcap.h" @@ -18,14 +22,103 @@ int tcap_tco_n_unitdata_ind(struct tcap_transport_entity *se, struct msgb *msg); /* prototype of what we need to call in case of incoming NOTICE */ int tcap_tco_n_notice_ind(struct tcap_transport_entity *se); + +/***********************************************************************/ +/* Simple UDP transport (not according to any kind of official spec) */ +/***********************************************************************/ + +static int tcap_tp_udp_unitdata_req(struct tcap_transport_entity *se, struct msgb *msg) +{ + return write_queue_enqueue(&se->udp.write_queue, msg); +} + +/* called by the write queue / FD magic in case we need to write a message */ +static int udp_write_cb(struct bsc_fd *fd, struct msgb *msg) +{ + struct write_queue *wq = container_of(fd, struct write_queue, bfd); + struct tcap_transport_entity *tte = container_of(wq, struct tcap_transport_entity, udp.write_queue); + + return sendto(fd->fd, msg->data, msg->len, 0, (struct sockaddr *) &tte->remote_addr, sizeof(tte->remote_addr)); +} + +/* called by write queue / FD magic in case the socket has some data */ +static int udp_read_cb(struct bsc_fd *fd) +{ + struct write_queue *wq = container_of(fd, struct write_queue, bfd); + struct tcap_transport_entity *tte = container_of(wq, struct tcap_transport_entity, udp.write_queue); + struct msgb *msg = msgb_alloc_headroom(4096+128, 128, "incoming TCAP/UDP"); + socklen_t addr_len = sizeof(tte->remote_addr); + int rc; + + if (!msg) + return -ENOMEM; + + rc = recvfrom(fd->fd, msg->data, msgb_tailroom(msg), 0, + &tte->remote_addr, &addr_len); + if (rc < 0) + return rc; + + msgb_put(msg, rc); + + return tcap_tco_n_unitdata_ind(tte, msg); +} + +struct tcap_transport_entity *tcap_transp_udp_create(struct sockaddr_storage *local_addr) +{ + struct tcap_transport_entity *tte = talloc_zero(NULL, struct tcap_transport_entity); + struct write_queue *wq; + int rc; + + if (!tte) + return NULL; + + memcpy(&tte->local_addr, local_addr, sizeof(tte->local_addr)); + tte->type = SCXP_T_UDP; + + /* Initialize write queue */ + wq = &tte->udp.write_queue; + write_queue_init(wq, 100); + wq->read_cb = udp_read_cb; + wq->write_cb = udp_write_cb; + + wq->bfd.fd = socket(tte->local_addr.ss_family, SOCK_DGRAM, IPPROTO_UDP); + if (wq->bfd.fd < 0) + goto err_free; + + rc = bind(wq->bfd.fd, (struct sockaddr *) &tte->local_addr, sizeof(tte->local_addr)); + if (rc < 0) + goto err_close; + + wq->bfd.when |= BSC_FD_READ; + bsc_register_fd(&wq->bfd); + + return tte; + +err_close: + close(wq->bfd.fd); +err_free: + talloc_free(tte); + return NULL; +} + /* Called by TCAP stack if it wants to request transmission of UNITDATA */ int tcap_scXp_n_unitdata_req(struct tcap_transport_entity *se, struct msgb *msg) { + int rc = 0; + printf("N-UNITDATA.req(%s)\n", hexdump(msg->data, msg->len)); +#if 0 int i = open("ber.out", O_CREAT|O_WRONLY|O_TRUNC); write(i, msg->data, msg->len); close(i); - tcap_tco_n_unitdata_ind(se, msg); +#endif + switch (se->type) { + case SCXP_T_UDP: + rc = write_queue_enqueue(&se->udp.write_queue, msg); + break; + } + + return rc; } diff --git a/src/tcap_test.c b/src/tcap_test.c index 1dc818f..ed4d98b 100644 --- a/src/tcap_test.c +++ b/src/tcap_test.c @@ -3,6 +3,8 @@ #include #include +#include + //#include #include @@ -10,6 +12,7 @@ #include "tcap_user.h" static struct { + struct tcap_transport_entity *tte; unsigned int begin_rcvd:1; uint32_t dialg_id; } test_state; @@ -64,6 +67,7 @@ static int send_begin(uint32_t dialg_id, OBJECT_IDENTIFIER_t *app_ctx) memset(&tcdi, 0, sizeof(tcdi)); tcdi.dialg_id = dialg_id; tcdi.app_ctx_name = app_ctx; + tcdi.transp_ent = test_state.tte; return tcap_user_req_dialg(TCAP_PR_TC_BEGIN, &tcdi); } @@ -117,10 +121,30 @@ static int initialize(void) int main(int argc, char **argv) { + struct sockaddr_storage ss; + struct sockaddr_in *sin = (struct sockaddr_in *)&ss; + initialize(); + ss.ss_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + sin->sin_port = htons(4242); + + test_state.tte = tcap_transp_udp_create(&ss); + if (!test_state.tte) { + fprintf(stderr, "Cannot create UDP socket\n"); + exit(1); + } + /* make sure we sent messages to ourselves */ + inet_aton("127.0.0.1", &sin->sin_addr); + memcpy(&test_state.tte->remote_addr, &ss, sizeof(test_state.tte->remote_addr)); + send_invoke(0x1234, 0, gprs_loc_upd_param, sizeof(gprs_loc_upd_param)); send_invoke(0x1234, 1, NULL, 0); send_invoke(0x1234, -1, NULL, 0); send_begin(0x1234, &gprs_loc_upd_ctx_v3_oid); + + while (1) { + bsc_select_main(0); + } } diff --git a/src/tcap_user.h b/src/tcap_user.h index 3d6783f..2b8533c 100644 --- a/src/tcap_user.h +++ b/src/tcap_user.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -23,12 +24,12 @@ struct tcap_transport_entity { /* common parts */ struct sockaddr_storage local_addr; struct sockaddr_storage remote_addr; - struct bsc_fd socket_fd; /* type of underlying transport */ enum tcap_transport_entity_type type; union { struct { + struct write_queue write_queue; } udp; struct { } sccp_ipa; diff --git a/src/tcu.c b/src/tcu.c index aa70e4f..a3725ef 100644 --- a/src/tcu.c +++ b/src/tcu.c @@ -186,6 +186,8 @@ int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg_ind *tcdi) switch (prim) { case TCAP_PR_TC_BEGIN: td = tcap_dialg_alloc(tcdi->dialg_id); + if (!td) + return -EINVAL; break; default: return -EINVAL; @@ -194,6 +196,7 @@ int tcap_user_req_dialg(enum tcap_primitive prim, struct tcap_dialg_ind *tcdi) switch (prim) { case TCAP_PR_TC_BEGIN: + td->transp_ent = tcdi->transp_ent; rc = tcap_csl_tc_begin_req(td, tcdi->app_ctx_name, tcdi->user_info); break; case TCAP_PR_TC_CONTINUE: diff --git a/src/tsl_tco.c b/src/tsl_tco.c index 5367e45..f805b35 100644 --- a/src/tsl_tco.c +++ b/src/tsl_tco.c @@ -14,7 +14,7 @@ uint32_t tid_from_octetstr(struct OCTET_STRING *octstr) { if (octstr->size != sizeof(uint32_t)) - fprintf(stderr, "Transaction ID length != violates spec\n", octstr->size); + fprintf(stderr, "Transaction ID length %u != violates spec\n", octstr->size); return ntohl(*(uint32_t *)octstr->buf); } @@ -51,6 +51,7 @@ int tcap_tco_n_unitdata_ind(struct tcap_transport_entity *se, struct msgb *msg) tt->tid_local = tcap_trans_id_alloc(); /* FIXME: Is TID == no TID ? */ /* Send BEGIN.recv to TSM */ + dialg_by_trans(tt)->transp_ent = se; rc = tcap_tsm_begin_rcvd(tt, tcmsg, msg); break; case TCMessage_PR_continue: