recv function is tested for Userland SCTP library

This commit is contained in:
Sukchan Lee 2017-10-19 12:50:39 +09:00
parent 1df4fc9a41
commit cca9f6d521
3 changed files with 163 additions and 110 deletions

View File

@ -219,6 +219,8 @@ AC_CHECK_HEADERS(netinet/ip.h net/route.h,,,[[
#endif
]])
AC_CHECK_HEADERS(netinet/ip_icmp.h, [], [], [#include <netinet/ip.h>])
##########################################
#### Checks for typedefs, structures, ####
#### and compiler characteristics. ####
@ -230,6 +232,41 @@ AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.__tm_gmtoff],,,[
#include <sys/types.h>
#include <time.h>])
AC_CHECK_MEMBER(struct sockaddr.sa_len,
AC_DEFINE(HAVE_SA_LEN, 1, [Define this if your stack has sa_len in sockaddr struct.]),,
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <sys/socket.h>])
AC_CHECK_MEMBER(struct sockaddr_in.sin_len,
AC_DEFINE(HAVE_SIN_LEN, 1, [Define this if your IPv4 has sin_len in sockaddr_in struct.]),,
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <netinet/in.h>])
AC_CHECK_MEMBER(struct sockaddr_in6.sin6_len,
AC_DEFINE(HAVE_SIN6_LEN, 1, [Define this if your IPv6 has sin6_len in sockaddr_in6 struct.]),,
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <netinet/in.h>])
AC_CHECK_MEMBER(struct sockaddr_conn.sconn_len,
AC_DEFINE(HAVE_SCONN_LEN, 1, [Define this if your userland stack has sconn_len in sockaddr_conn struct.]),,
[#include "usrsctplib/usrsctp.h"])
AC_MSG_CHECKING(for socklen_t)
AC_TRY_COMPILE([#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <sys/socket.h>],
[socklen_t x; x = 1; return ((int)x);],
[AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(int)
AC_DEFINE(socklen_t, int, [Define a type for socklen_t.])])
AC_CHECK_FILE(/dev/random,
AC_DEFINE([HAVE_DEV_RANDOM], [1],
[Define to 1 if you have the /dev/random file.]))
@ -304,6 +341,9 @@ AC_CHECK_FUNCS(\
sched_yield \
)
AC_CHECK_FUNCS(socket, , AC_CHECK_LIB(socket, socket))
AC_CHECK_FUNCS(inet_addr, , AC_CHECK_LIB(nsl, inet_addr))
AC_CHECK_LIB([pthread], [pthread_mutex_init], [LIBS="${LIBS} -lpthread"])
AC_CHECK_LIB([dl], [dlopen], [LIBS="${LIBS} -ldl"])
AC_CHECK_LIB([sctp], [sctp_sendmsg], [have_sctp_lib=yes], [have_sctp_lib=no])
@ -314,8 +354,6 @@ else
if test "$have_usrsctp_lib" == "yes"; then
LIBS="${LIBS} -lusrsctp"
AC_DEFINE([USE_USRSCTP], [1], [Define to 1 if you have the usrsctp library.])
else
AC_MSG_ERROR([You must install the SCTP libraries and development headers to enable SCTP support.])
fi
fi
AM_CONDITIONAL([USRSCTP], [test x$have_usrsctp_lib = xyes])

View File

@ -8,18 +8,17 @@
#include "s1ap_path.h"
#if HAVE_USRSCTP_H
#undef SCTP_DEBUG
#ifndef INET
#define INET 1
#endif
#ifndef INET6
#define INET6 1
#endif
#include <usrsctp.h>
#endif
#define LOCAL_UDP_PORT 8277
#define LOCAL_UDP_PORT 9899
static int s1ap_usrsctp_thread_should_stop = 0;
static thread_id s1ap_usrsctp_thread;
struct socket *s1ap_usrsctp_connect(c_uint32_t addr);
static void *THREAD_FUNC s1ap_usrsctp_accept_cb(thread_id id, void *data);
static int s1ap_usrsctp_recv_cb(struct socket *sock,
union sctp_sockstore addr, void *data, size_t datalen,
struct sctp_rcvinfo rcv, int flags, void *ulp_info);
@ -32,7 +31,17 @@ status_t s1ap_open(void)
struct socket *psock = NULL;
struct sockaddr_in local_addr;
struct sctp_setadaptation ind = {0};
const int on = 1;
struct sctp_event event;
c_uint16_t event_types[] = {
SCTP_ASSOC_CHANGE,
SCTP_PEER_ADDR_CHANGE,
SCTP_REMOTE_ERROR,
SCTP_SHUTDOWN_EVENT,
SCTP_ADAPTATION_INDICATION,
SCTP_PARTIAL_DELIVERY_EVENT
};
int i;
usrsctp_init(LOCAL_UDP_PORT, NULL, debug_printf);
#ifdef SCTP_DEBUG
@ -51,14 +60,32 @@ status_t s1ap_open(void)
mme_self()->s1ap_sock = (net_sock_t *)psock;
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_RECVRCVINFO,
&on, sizeof(int)) < 0)
{
d_error("usrsctp_setsockopt SCTP_RECVRCVINFO");
return CORE_ERROR;
}
memset(&event, 0, sizeof(event));
event.se_assoc_id = SCTP_FUTURE_ASSOC;
event.se_on = 1;
for (i = 0; i < (int)(sizeof(event_types)/sizeof(c_uint16_t)); i++)
{
event.se_type = event_types[i];
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_EVENT,
&event, sizeof(struct sctp_event)) < 0)
{
d_error("usrsctp_setsockopt SCTP_EVENT");
return CORE_ERROR;
}
}
memset((void *)&local_addr, 0, sizeof(struct sockaddr_in));
local_addr.sin_family = AF_INET;
local_addr.sin_len = sizeof(struct sockaddr_in);
local_addr.sin_port = htons(mme_self()->s1ap_port);
#if 1 /* FIXME : At this time, I'll just test using loopback */
mme_self()->s1ap_addr = inet_addr("127.0.0.1");
#endif
local_addr.sin_addr.s_addr = mme_self()->s1ap_addr;
local_addr.sin_addr.s_addr = 0;
if (usrsctp_bind(psock, (struct sockaddr *)&local_addr,
sizeof(struct sockaddr_in)) == -1)
@ -68,27 +95,12 @@ status_t s1ap_open(void)
return CORE_ERROR;
}
if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER,
(const void*)&ind, (socklen_t)sizeof(struct sctp_setadaptation)) < 0)
{
perror("setsockopt");
}
if (usrsctp_listen(psock, 1) < 0)
{
d_error("usrsctp_listen failed");
return CORE_ERROR;
}
#if 0
if (thread_create(&s1ap_usrsctp_thread,
NULL, s1ap_usrsctp_accept_cb, NULL) != CORE_OK)
{
d_error("accept thread creation failed");
return CORE_ERROR;
}
#endif
d_trace(1, "s1_enb_listen() %s:%d\n",
INET_NTOP(&mme_self()->s1ap_addr, buf), mme_self()->s1ap_port);
@ -97,19 +109,12 @@ status_t s1ap_open(void)
status_t s1ap_close()
{
struct socket *dummy;
d_assert(mme_self(), return CORE_ERROR, "Null param");
d_assert(mme_self()->s1ap_sock != NULL, return CORE_ERROR,
"S1-ENB path already opened");
s1ap_usrsctp_thread_should_stop = 1;
dummy = s1ap_usrsctp_connect(mme_self()->s1ap_addr);
thread_delete(s1ap_usrsctp_thread);
usrsctp_close(dummy);
usrsctp_close((struct socket *)mme_self()->s1ap_sock);
core_sleep(time_from_msec(100));
d_assert(usrsctp_finish() == 0, , "failed to execute 'usrsctp_finish()'");
while(usrsctp_finish() != 0) core_sleep(time_from_msec(50));
return CORE_OK;
}
@ -159,78 +164,11 @@ status_t s1ap_sendto(net_sock_t *s, pkbuf_t *pkbuf,
return CORE_OK;
}
struct socket *s1ap_usrsctp_connect(c_uint32_t addr)
{
struct sockaddr_in remote_addr;
struct socket *psock = NULL;
if (!(psock = usrsctp_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP,
NULL, NULL, 0, NULL)))
{
d_error("usrsctp_socket error");
return NULL;
}
memset((void *)&remote_addr, 0, sizeof(struct sockaddr_in));
remote_addr.sin_family = AF_INET;
remote_addr.sin_len = sizeof(struct sockaddr_in);
remote_addr.sin_port = htons(mme_self()->s1ap_port);
remote_addr.sin_addr.s_addr = addr;
if (usrsctp_connect(psock, (struct sockaddr *)&remote_addr,
sizeof(struct sockaddr_in)) == -1)
{
d_error("usrsctp_connect error");
return NULL;
}
return psock;
}
static void *THREAD_FUNC s1ap_usrsctp_accept_cb(thread_id id, void *data)
{
char buf[INET_ADDRSTRLEN];
struct socket *psock = (struct socket *)mme_self()->s1ap_sock;
struct sockaddr_in remote_addr;
struct socket *conn_sock;
socklen_t addr_len;
event_t e;
c_uint32_t addr;
c_uint16_t port;
while (!s1ap_usrsctp_thread_should_stop)
{
memset(&remote_addr, 0, sizeof(struct sockaddr_in));
addr_len = sizeof(struct sockaddr_in);
if ((conn_sock = usrsctp_accept(psock,
(struct sockaddr *)&remote_addr, &addr_len)) == NULL)
{
d_error("usrsctp_accept failed");
continue;
}
d_trace(1, "eNB-S1 accepted[%s] in s1_path module\n",
INET_NTOP(&addr, buf));
addr = remote_addr.sin_addr.s_addr;
port = ntohs(remote_addr.sin_port);
event_set(&e, MME_EVT_S1AP_LO_ACCEPT);
event_set_param1(&e, (c_uintptr_t)conn_sock);
event_set_param2(&e, (c_uintptr_t)addr);
event_set_param3(&e, (c_uintptr_t)port);
mme_event_send(&e);
}
return NULL;
}
static int s1ap_usrsctp_recv_cb(struct socket *sock,
union sctp_sockstore addr, void *data, size_t datalen,
struct sctp_rcvinfo rcv, int flags, void *ulp_info)
{
#if 0
event_t e;
pkbuf_t *pkbuf;
@ -259,6 +197,56 @@ static int s1ap_usrsctp_recv_cb(struct socket *sock,
free(data);
return 1;
#else
char namebuf[INET6_ADDRSTRLEN];
const char *name;
uint16_t port;
if (data) {
if (flags & MSG_NOTIFICATION) {
printf("Notification of length %d received.\n", (int)datalen);
} else {
switch (addr.sa.sa_family) {
#ifdef INET
case AF_INET:
name = inet_ntop(AF_INET, &addr.sin.sin_addr, namebuf, INET_ADDRSTRLEN);
port = ntohs(addr.sin.sin_port);
break;
#endif
#ifdef INET6
case AF_INET6:
name = inet_ntop(AF_INET6, &addr.sin6.sin6_addr, namebuf, INET6_ADDRSTRLEN),
port = ntohs(addr.sin6.sin6_port);
break;
#endif
case AF_CONN:
#ifdef _WIN32
_snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr);
#else
snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr);
#endif
name = namebuf;
port = ntohs(addr.sconn.sconn_port);
break;
default:
name = NULL;
port = 0;
break;
}
printf("Msg of length %d received from %s:%u on stream %u with SSN %u and TSN %u, PPID %u, context %u.\n",
(int)datalen,
name,
port,
rcv.rcv_sid,
rcv.rcv_ssn,
rcv.rcv_tsn,
ntohl(rcv.rcv_ppid),
rcv.rcv_context);
}
free(data);
}
return (1);
#endif
}
static void debug_printf(const char *format, ...)

View File

@ -10,6 +10,12 @@
#include "s1ap_path.h"
#if USE_USRSCTP == 1
#ifndef INET
#define INET 1
#endif
#ifndef INET6
#define INET6 1
#endif
#if HAVE_USRSCTP_H
#include <usrsctp.h>
#endif
@ -20,25 +26,46 @@ net_sock_t *tests1ap_enb_connect(void)
char buf[INET_ADDRSTRLEN];
status_t rv;
mme_context_t *mme = mme_self();
net_sock_t *sock = NULL;
#if USE_USRSCTP == 1
struct sockaddr_in remote_addr;
struct socket *psock = NULL;
#else
net_sock_t *sock = NULL;
#endif
if (!mme) return NULL;
#if USE_USRSCTP == 1
struct socket *s1ap_usrsctp_connect(c_uint32_t addr);
sock = (net_sock_t *)s1ap_usrsctp_connect(mme_self()->s1ap_addr);
mme_self()->s1ap_addr = inet_addr("127.0.0.1");
if (!(psock = usrsctp_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP,
NULL, NULL, 0, NULL)))
{
d_error("usrsctp_socket error");
return NULL;
}
memset((void *)&remote_addr, 0, sizeof(struct sockaddr_in));
remote_addr.sin_family = AF_INET;
remote_addr.sin_len = sizeof(struct sockaddr_in);
remote_addr.sin_port = htons(mme_self()->s1ap_port);
remote_addr.sin_addr.s_addr = mme_self()->s1ap_addr;
if (usrsctp_connect(psock, (struct sockaddr *)&remote_addr,
sizeof(struct sockaddr_in)) == -1)
{
d_error("usrsctp_connect error");
return NULL;
}
return (net_sock_t *)psock;
#else
rv = net_open_ext(&sock, mme->s1ap_addr,
INET_NTOP(&mme->s1ap_addr, buf), 0, mme->s1ap_port,
SOCK_SEQPACKET, IPPROTO_SCTP, SCTP_S1AP_PPID, 0);
if (rv != CORE_OK) return NULL;
#endif
return sock;
#endif
}
status_t tests1ap_enb_close(net_sock_t *sock)