implement simplistic UDP transport for TCAP
Normally, TCAP is not spoken directly on top of UDP, however this makes it really easy to test...
This commit is contained in:
parent
aa3011d53e
commit
1e2f04410b
97
src/scXp.c
97
src/scXp.c
|
@ -1,13 +1,17 @@
|
|||
/* SCCP / SCTP+SUA interface */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <osmocore/logging.h>
|
||||
#include <osmocore/msgb.h>
|
||||
#include <osmocore/talloc.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
//#include <asn1/OBJECT_IDENTIFIER.h>
|
||||
|
||||
#include <osmocore/utils.h>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <sys/socket.h>
|
||||
|
||||
#include <osmocore/select.h>
|
||||
#include <osmocore/write_queue.h>
|
||||
|
||||
#include <asn1c/OBJECT_IDENTIFIER.h>
|
||||
#include <osmocom/tcap/Parameter.h>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue