125 lines
3.3 KiB
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;
|
|
}
|
|
|
|
|