libosmo-tcap/src/scXp.c

125 lines
3.3 KiB
C

/* 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"
/* prototype of what we need to call in case of incoming UNITDATA */
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);
#endif
switch (se->type) {
case SCXP_T_UDP:
rc = write_queue_enqueue(&se->udp.write_queue, msg);
break;
}
return rc;
}