From a4d1bae08316a999625fe7dc10dea60b95ac6436 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Thu, 16 Nov 2017 10:46:25 +0000 Subject: [PATCH] SCTP library is initially added --- lib/core/include/core_sctp.h | 29 +++ lib/core/include/core_sock.h | 10 +- lib/core/src/Makefile.am | 4 + lib/core/src/unix/sctp.c | 344 ++++++++++++++++++++++++++ lib/core/src/unix/sock.c | 111 ++++----- lib/core/test/testsctp.c | 454 ++++++++++++++--------------------- lib/core/test/testsock.c | 58 ++--- 7 files changed, 649 insertions(+), 361 deletions(-) create mode 100644 lib/core/include/core_sctp.h create mode 100644 lib/core/src/unix/sctp.c diff --git a/lib/core/include/core_sctp.h b/lib/core/include/core_sctp.h new file mode 100644 index 000000000..141e53d98 --- /dev/null +++ b/lib/core/include/core_sctp.h @@ -0,0 +1,29 @@ +#ifndef __CORE_SCTP_H__ +#define __CORE_SCTP_H__ + +#include "core_sock.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +CORE_DECLARE(status_t) sctp_open(sock_id *new, + int family, int type, + const char *local_host, c_uint16_t local_port, + const char *remote_host, c_uint16_t remote_port, + int flags); + +CORE_DECLARE(int) sctp_write(sock_id id, const void *msg, size_t len, + struct sockaddr *to, socklen_t tolen, + c_uint32_t ppid, c_uint16_t stream_no); + +#define CORE_SCTP_REMOTE_CLOSED -2 +CORE_DECLARE(int) sctp_read(sock_id id, void *msg, size_t len, + struct sockaddr *from, socklen_t *fromlen, + c_uint32_t *ppid, c_uint16_t *stream_no); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/lib/core/include/core_sock.h b/lib/core/include/core_sock.h index 3d5777d4f..6fd0116df 100644 --- a/lib/core/include/core_sock.h +++ b/lib/core/include/core_sock.h @@ -52,7 +52,7 @@ extern "C" { #define SOCK_O_INCOMPLETE_READ (1 << 11) /**< Set on non-blocking sockets * (timeout != 0) on which the * previous read() did not fill a buffer - * completely. the next sock_recv() + * completely. the next sock_read() * will first call select()/poll() rather than * going straight into read(). (Can also * be set by an application to force a @@ -86,8 +86,6 @@ CORE_DECLARE(status_t) sock_create( sock_id *id, int family, int type, int protocol, int flags); CORE_DECLARE(status_t) sock_delete(sock_id id); -CORE_DECLARE(status_t) sock_setsockopt(sock_id id, c_int32_t opt, c_int32_t on); - CORE_DECLARE(status_t) sock_bind(sock_id id, const char *host, c_uint16_t port); CORE_DECLARE(status_t) sock_connect(sock_id id, @@ -96,13 +94,15 @@ CORE_DECLARE(status_t) sock_connect(sock_id id, CORE_DECLARE(status_t) sock_listen(sock_id id); CORE_DECLARE(status_t) sock_accept(sock_id *new, sock_id id); -CORE_DECLARE(ssize_t) sock_send(sock_id id, +CORE_DECLARE(ssize_t) sock_write(sock_id id, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); -CORE_DECLARE(ssize_t) sock_recv(sock_id id, +CORE_DECLARE(ssize_t) sock_read(sock_id id, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); +CORE_DECLARE(status_t) sock_setsockopt(sock_id id, c_int32_t opt, c_int32_t on); + CORE_DECLARE(status_t) sock_register(sock_id id, sock_handler handler, void *data); CORE_DECLARE(status_t) sock_unregister(sock_id id); diff --git a/lib/core/src/Makefile.am b/lib/core/src/Makefile.am index dc64488c4..483003962 100644 --- a/lib/core/src/Makefile.am +++ b/lib/core/src/Makefile.am @@ -33,6 +33,10 @@ libcore_la_SOURCES = \ unix/sock.c unix/udp.c unix/tcp.c \ $(NULL) +if !USRSCTP +libcore_la_SOURCES += ../include_core_sctp.h unix/sctp.c +endif + AM_LDFLAGS = \ -version-info @LIBVERSION@ \ $(NULL) diff --git a/lib/core/src/unix/sctp.c b/lib/core/src/unix/sctp.c new file mode 100644 index 000000000..cc8c225f5 --- /dev/null +++ b/lib/core/src/unix/sctp.c @@ -0,0 +1,344 @@ +#define TRACE_MODULE _sctp + +#include "core_debug.h" +#include "core_arch_sock.h" +#include "core_sctp.h" + +#if HAVE_NETINET_SCTP_H +#include +#endif + +static status_t subscribe_to_events(sock_id id); +static status_t set_paddrparams(sock_id id, c_uint32_t spp_hbinterval); +static status_t set_rtoinfo(sock_id id, + c_uint32_t srto_initial, c_uint32_t srto_min, c_uint32_t srto_max); +static status_t set_initmsg(sock_id id, + c_uint32_t sinit_max_attempts, c_uint32_t sinit_max_init_timeo); + +status_t sctp_open(sock_id *new, + int family, + int type, + const char *local_host, c_uint16_t local_port, + const char *remote_host, c_uint16_t remote_port, + int flags) +{ + status_t rv; + sock_id id; + + rv = sock_create(new, family, type, IPPROTO_SCTP, flags); + d_assert(new, return CORE_ERROR,); + id = *new; + + if (flags & SOCK_F_BIND) + { + rv = sock_bind(id, local_host, local_port); + d_assert(rv == CORE_OK, return CORE_ERROR,); + } + + if (flags & SOCK_F_CONNECT) + { + rv = sock_connect(id, remote_host, remote_port); + d_assert(rv == CORE_OK, return CORE_ERROR,); + } + + rv = subscribe_to_events(id); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + /* heartbit interval : 5 secs */ + rv = set_paddrparams(id, 5000); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + /* + * RTO info + * + * initial : 3 secs + * min : 1 sec + * max : 5 secs + */ + rv = set_rtoinfo(id, 3000, 1000, 5000); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + /* + * INITMSG + * + * max attemtps : 4 + * max initial timeout : 8 secs + */ + rv = set_initmsg(id, 4, 8000); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + if (flags & SOCK_F_BIND) + { + rv = sock_listen(id); + d_assert(rv == CORE_OK, return CORE_ERROR,); + } + + return CORE_OK; +} + +int sctp_write(sock_id id, const void *msg, size_t len, + struct sockaddr *to, socklen_t tolen, + c_uint32_t ppid, c_uint16_t stream_no) +{ + sock_t *sock = (sock_t *)id; + int size; + + d_assert(id, return -1, ); + + size = sctp_sendmsg(sock->fd, msg, len, to, tolen, + htonl(ppid), + 0, /* flags */ + stream_no, + 0, /* timetolive */ + 0); /* context */ + if (size < 0) + { + d_error("sctp_write(len:%ld) failed(%d:%s)", + len, errno, strerror(errno)); + } + + return size; +} + +int sctp_read(sock_id id, void *msg, size_t len, + struct sockaddr *from, socklen_t *fromlen, + c_uint32_t *ppid, c_uint16_t *stream_no) +{ + sock_t *sock = (sock_t *)id; + int size; + + int flags = 0; + struct sctp_sndrcvinfo sinfo; + + d_assert(id, return -1,); + + do + { + size = sctp_recvmsg(sock->fd, msg, len, + from, fromlen, &sinfo, &flags); + if (size < 0) + { + d_error("sctp_read(len:%ld) failed(%d:%s)", + len, errno, strerror(errno)); + + return size; + } + + if (!(flags & MSG_NOTIFICATION)) + break; + + if (flags & MSG_EOR) + { + union sctp_notification *not = (union sctp_notification *)msg; + + switch( not->sn_header.sn_type ) + { + case SCTP_ASSOC_CHANGE : + d_trace(3, "SCTP_ASSOC_CHANGE" + "(type:0x%x, flags:0x%x, state:0x%x)\n", + not->sn_assoc_change.sac_type, + not->sn_assoc_change.sac_flags, + not->sn_assoc_change.sac_state); + + if (not->sn_assoc_change.sac_state == + SCTP_SHUTDOWN_COMP || + not->sn_assoc_change.sac_state == + SCTP_COMM_LOST) + { + return CORE_SCTP_REMOTE_CLOSED; + } + + if (not->sn_assoc_change.sac_state == SCTP_COMM_UP) + d_trace(3, "SCTP_COMM_UP\n"); + + break; + case SCTP_SEND_FAILED : + d_error("SCTP_SEND_FAILED" + "(type:0x%x, flags:0x%x, error:0x%x)\n", + not->sn_send_failed.ssf_type, + not->sn_send_failed.ssf_flags, + not->sn_send_failed.ssf_error); + break; + case SCTP_SHUTDOWN_EVENT : + d_trace(3, "SCTP_SHUTDOWN_EVENT\n"); + return CORE_SCTP_REMOTE_CLOSED; + default : + d_error("Discarding event with unknown " + "flags = 0x%x, type 0x%x", + flags, not->sn_header.sn_type); + break; + } + } + else + { + d_error("Not engough buffer. Need more recv : 0x%x", flags); + return CORE_ERROR; + } + } while(1); + + if (ppid) + { + *ppid = ntohl(sinfo.sinfo_ppid); + } + + if (stream_no) + { + *stream_no = sinfo.sinfo_stream; + } + + return size; +} + +static status_t subscribe_to_events(sock_id id) +{ + sock_t *sock = (sock_t *)id; + struct sctp_event_subscribe event; + + d_assert(id, return CORE_ERROR,); + + memset(&event, 0, sizeof(event)); + event.sctp_data_io_event = 1; + event.sctp_association_event = 1; + event.sctp_send_failure_event = 1; + event.sctp_shutdown_event = 1; + + if (setsockopt(sock->fd, IPPROTO_SCTP, SCTP_EVENTS, + &event, sizeof( event)) != 0 ) + { + d_error("Unable to subscribe to SCTP events: (%d:%s)", + errno, strerror( errno )); + return CORE_ERROR; + } + + return CORE_OK; +} + +static status_t set_paddrparams(sock_id id, c_uint32_t spp_hbinterval) +{ + sock_t *sock = (sock_t *)id; + struct sctp_paddrparams heartbeat; + socklen_t socklen; + + d_assert(id, return CORE_ERROR,); + + memset(&heartbeat, 0, sizeof(heartbeat)); + socklen = sizeof(heartbeat); + if (getsockopt(sock->fd, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, + &heartbeat, &socklen) != 0 ) + { + d_error("getsockopt for SCTP_PEER_ADDR failed(%d:%s)", + errno, strerror(errno)); + return CORE_ERROR; + } + + d_trace(3,"Old spp _flags = 0x%x hbinter = %d pathmax = %d\n", + heartbeat.spp_flags, + heartbeat.spp_hbinterval, + heartbeat.spp_pathmaxrxt); + + heartbeat.spp_hbinterval = spp_hbinterval; + + if (setsockopt(sock->fd, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, + &heartbeat, sizeof( heartbeat)) != 0 ) + { + d_error("setsockopt for SCTP_PEER_ADDR_PARAMS failed(%d:%s)", + errno, strerror(errno)); + return CORE_ERROR; + } + + d_trace(3,"New spp _flags = 0x%x hbinter = %d pathmax = %d\n", + heartbeat.spp_flags, + heartbeat.spp_hbinterval, + heartbeat.spp_pathmaxrxt); + + return CORE_OK; +} + +static status_t set_rtoinfo(sock_id id, + c_uint32_t srto_initial, c_uint32_t srto_min, c_uint32_t srto_max) +{ + sock_t *sock = (sock_t *)id; + struct sctp_rtoinfo rtoinfo; + socklen_t socklen; + + d_assert(id, return CORE_ERROR,); + + memset(&rtoinfo, 0, sizeof(rtoinfo)); + socklen = sizeof(rtoinfo); + if (getsockopt(sock->fd, IPPROTO_SCTP, SCTP_RTOINFO, + &rtoinfo, &socklen) != 0 ) + { + d_error("getsockopt for SCTP_RTOINFO failed(%d:%s)", + errno, strerror( errno )); + return CORE_ERROR; + } + + d_trace(3,"Old RTO (initial:%d max:%d min:%d)\n", + rtoinfo.srto_initial, + rtoinfo.srto_max, + rtoinfo.srto_min); + + rtoinfo.srto_initial = srto_initial; + rtoinfo.srto_min = srto_min; + rtoinfo.srto_max = srto_max; + + if (setsockopt(sock->fd, IPPROTO_SCTP, SCTP_RTOINFO, + &rtoinfo, sizeof(rtoinfo)) != 0 ) + { + d_error("setsockopt for SCTP_RTOINFO failed(%d:%s)", + errno, strerror( errno )); + return CORE_ERROR; + } + d_trace(3,"New RTO (initial:%d max:%d min:%d)\n", + rtoinfo.srto_initial, + rtoinfo.srto_max, + rtoinfo.srto_min); + + return CORE_OK; +} + +static status_t set_initmsg(sock_id id, + c_uint32_t sinit_max_attempts, c_uint32_t sinit_max_init_timeo) +{ + sock_t *sock = (sock_t *)id; + struct sctp_initmsg initmsg; + socklen_t socklen; + + d_assert(id, return CORE_ERROR,); + + + memset(&initmsg, 0, sizeof(initmsg)); + socklen = sizeof(initmsg); + if (getsockopt(sock->fd, IPPROTO_SCTP, SCTP_INITMSG, + &initmsg, &socklen) != 0 ) + { + d_error("getsockopt for SCTP_INITMSG failed(%d:%s)", + errno, strerror( errno )); + return CORE_ERROR; + } + + d_trace(3,"Old INITMSG (numout:%d maxin:%d maxattempt:%d maxinit_to:%d)\n", + initmsg.sinit_num_ostreams, + initmsg.sinit_max_instreams, + initmsg.sinit_max_attempts, + initmsg.sinit_max_init_timeo); + + initmsg.sinit_max_attempts = sinit_max_attempts; + initmsg.sinit_max_init_timeo = sinit_max_init_timeo; + + if (setsockopt(sock->fd, IPPROTO_SCTP, SCTP_INITMSG, + &initmsg, sizeof(initmsg)) != 0 ) + { + d_error("setsockopt for SCTP_INITMSG failed(%d:%s)", + errno, strerror( errno )); + return CORE_ERROR; + } + + d_trace(3,"New INITMSG (numout:%d maxin:%d maxattempt:%d maxinit_to:%d)\n", + initmsg.sinit_num_ostreams, + initmsg.sinit_max_instreams, + initmsg.sinit_max_attempts, + initmsg.sinit_max_init_timeo); + + return CORE_OK; +} diff --git a/lib/core/src/unix/sock.c b/lib/core/src/unix/sock.c index bf8d1ffd5..10b8486ca 100644 --- a/lib/core/src/unix/sock.c +++ b/lib/core/src/unix/sock.c @@ -96,56 +96,6 @@ status_t sock_delete(sock_id id) return CORE_OK; } -status_t sock_setsockopt(sock_id id, c_int32_t opt, c_int32_t on) -{ - sock_t *sock = (sock_t *)id; - int one; - status_t rv; - - - d_assert(sock, return CORE_ERROR,); - if (on) - one = 1; - else - one = 0; - - switch(opt) - { - case SOCK_O_REUSEADDR: - if (on != sock_is_option_set(sock, SOCK_O_REUSEADDR)) - { - if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, - (void *)&one, sizeof(int)) == -1) - { - return errno; - } - sock_set_option(sock, SOCK_O_REUSEADDR, on); - } - break; - case SOCK_O_NONBLOCK: - if (sock_is_option_set(sock, SOCK_O_NONBLOCK) != on) - { - if (on) - { - if ((rv = sononblock(sock->fd)) != CORE_OK) - return rv; - } - else - { - if ((rv = soblock(sock->fd)) != CORE_OK) - return rv; - } - sock_set_option(sock, SOCK_O_NONBLOCK, on); - } - break; - default: - d_error("Not implemented(%d)", opt); - return CORE_EINVAL; - } - - return CORE_OK; -} - status_t sock_bind(sock_id id, const char *host, c_uint16_t port) { sock_t *sock = (sock_t *)id; @@ -281,7 +231,7 @@ status_t sock_accept(sock_id *new, sock_id id) return CORE_OK; } -ssize_t sock_send(sock_id id, const void *buf, size_t len, int flags, +ssize_t sock_write(sock_id id, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { sock_t *sock = (sock_t *)id; @@ -302,13 +252,14 @@ ssize_t sock_send(sock_id id, const void *buf, size_t len, int flags, if (size < 0) { - d_error("send(len:%ld) failed(%d:%s)", len, errno, strerror(errno)); + d_error("sock_write(len:%ld) failed(%d:%s)", + len, errno, strerror(errno)); } return size; } -ssize_t sock_recv(sock_id id, void *buf, size_t len, int flags, +ssize_t sock_read(sock_id id, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { sock_t *sock = (sock_t *)id; @@ -318,7 +269,6 @@ ssize_t sock_recv(sock_id id, void *buf, size_t len, int flags, if (sock->type == SOCK_DGRAM && !(sock->flags & SOCK_F_CONNECT)) { - *addrlen = sizeof(struct sockaddr); size = recvfrom(sock->fd, buf, len, flags, src_addr, addrlen); } else @@ -328,12 +278,63 @@ ssize_t sock_recv(sock_id id, void *buf, size_t len, int flags, if (size < 0) { - d_error("recv(len:%ld) failed(%d:%s)", len, errno, strerror(errno)); + d_error("sock_read(len:%ld) failed(%d:%s)", + len, errno, strerror(errno)); } return size; } +status_t sock_setsockopt(sock_id id, c_int32_t opt, c_int32_t on) +{ + sock_t *sock = (sock_t *)id; + int one; + status_t rv; + + + d_assert(sock, return CORE_ERROR,); + if (on) + one = 1; + else + one = 0; + + switch(opt) + { + case SOCK_O_REUSEADDR: + if (on != sock_is_option_set(sock, SOCK_O_REUSEADDR)) + { + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, + (void *)&one, sizeof(int)) == -1) + { + return errno; + } + sock_set_option(sock, SOCK_O_REUSEADDR, on); + } + break; + case SOCK_O_NONBLOCK: + if (sock_is_option_set(sock, SOCK_O_NONBLOCK) != on) + { + if (on) + { + if ((rv = sononblock(sock->fd)) != CORE_OK) + return rv; + } + else + { + if ((rv = soblock(sock->fd)) != CORE_OK) + return rv; + } + sock_set_option(sock, SOCK_O_NONBLOCK, on); + } + break; + default: + d_error("Not implemented(%d)", opt); + return CORE_EINVAL; + } + + return CORE_OK; +} + status_t sock_register(sock_id id, sock_handler handler, void *data) { sock_t *sock = (sock_t *)id; diff --git a/lib/core/test/testsctp.c b/lib/core/test/testsctp.c index eb359b8c1..bd318f497 100644 --- a/lib/core/test/testsctp.c +++ b/lib/core/test/testsctp.c @@ -1,325 +1,233 @@ -#define TRACE_MODULE _testsctp #include "core_debug.h" -#include "core_net.h" +#include "core_thread.h" +#include "core_sctp.h" + #include "testutil.h" -#define TEST_SERVER_PORT 5121 -#define TEST_BUFFER_SIZE 1024 +#define DATASTR "This is a test" +#define STRLEN 8092 +#define PORT 7777 +#define PPID 12345 -#define TEST_MAX_NUM 4 - -static char buffer[TEST_BUFFER_SIZE]; -static int sctp_stream_server_started = 0; -static int sctp_seq_server_started = 0; - -pthread_t streamserver_tid, seqserver_tid; -net_sock_t *streamserver_sock,*seqserver_sock; - -static void *sctp_stream_session_main(void *param) +static void sctp_test1(abts_case *tc, void *data) { - int rc; + sock_id sctp; + status_t rv; - net_sock_t *net_sock = (net_sock_t *)param; - while (1) - { - rc = net_read(net_sock, buffer, TEST_BUFFER_SIZE, 1); - if (rc > 0) - { - if (!strncmp(buffer, "QUIT",4)) - { - break; - } - else - { - /* Send received data */ - rc = net_send(net_sock, buffer, rc); - } - } - else if (rc == 0) - { - /* Timeout */ - } - else - { - if (rc != -2 && net_sock->sndrcv_errno != EAGAIN) - break; - } - } + rv = sctp_open(&sctp, AF_UNSPEC, SOCK_SEQPACKET, + 0, PORT, NULL, 0, SOCK_F_BIND); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); - net_close(net_sock); + rv = sctp_open(&sctp, AF_UNSPEC, SOCK_STREAM, + "127.0.0.1", PORT, NULL, 0, SOCK_F_BIND); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + rv = sctp_open(&sctp, AF_UNSPEC, SOCK_SEQPACKET, + "::1", PORT, NULL, 0, SOCK_F_BIND); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); +} + +static thread_id test2_thread; +static void *THREAD_FUNC test2_main(thread_id id, void *data) +{ + abts_case *tc = data; + status_t rv; + sock_id sctp; + char str[STRLEN]; + ssize_t size; + c_uint32_t ppid; + + rv = sctp_open(&sctp, AF_UNSPEC, SOCK_SEQPACKET, + NULL, 0, "::1", PORT, SOCK_F_CONNECT); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + size = sctp_read(sctp, str, STRLEN, NULL, NULL, &ppid, NULL); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + ABTS_INT_EQUAL(tc, PPID, ppid); + + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + thread_exit(id, size); return NULL; } -static void start_stream_sctp_session(net_sock_t *net_sock) +static void sctp_test2(abts_case *tc, void *data) { - pthread_t tid; + sock_id sctp, sctp2; + status_t rv; + ssize_t size; - pthread_create(&tid, NULL, sctp_stream_session_main, (void *)net_sock); - pthread_detach(tid); - return; + rv = sctp_open(&sctp, AF_INET6, SOCK_STREAM, + NULL, PORT, NULL, 0, SOCK_F_BIND); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = thread_create(&test2_thread, NULL, test2_main, tc); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = sock_accept(&sctp2, sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + size = sctp_write(sctp2, DATASTR, strlen(DATASTR), + NULL, 0, PPID, 0); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + + thread_join(&rv, test2_thread); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + + rv = sock_delete(sctp2); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); } -static void *sctp_stream_server_main(void *param) +static thread_id test3_thread; +static void *THREAD_FUNC test3_main(thread_id id, void *data) { + abts_case *tc = data; + status_t rv; + sock_id sctp; + struct sockaddr_in dst_addr; + socklen_t addrlen; + char str[STRLEN]; + ssize_t size; int rc; - net_sock_t *new_sock; - rc = net_listen(&streamserver_sock, - SOCK_STREAM, IPPROTO_SCTP, TEST_SERVER_PORT); - if (rc != 0) - { - d_error("net_sctp_listen Error(rc = %d)\n",rc); - return NULL; - } + rv = sctp_open(&sctp, AF_INET, SOCK_SEQPACKET, NULL, 0, NULL, 0, 0); + ABTS_INT_EQUAL(tc, CORE_OK, rv); - sctp_stream_server_started = 1; + memset(&dst_addr, 0, sizeof(dst_addr)); + dst_addr.sin_port = htons(PORT); + dst_addr.sin_family = AF_INET; + rc = inet_pton(AF_INET, "127.0.0.1", &(dst_addr.sin_addr)); + ABTS_INT_EQUAL(tc, 1, rc); - while (1) - { - rc = net_accept(&new_sock, streamserver_sock, 1); - if (rc >0) - { - /* New connection arrived. Start session */ - start_stream_sctp_session(new_sock); - } - else if (rc == 0) - { - /* Timeout */ - } - else - { - /* Error occured */ - break; - } - } + size = sctp_write(sctp, DATASTR, strlen(DATASTR), + (struct sockaddr *)&dst_addr, sizeof(struct sockaddr), PPID, 0); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + thread_exit(id, size); return NULL; } -static void start_stream_sctp_server() +static void sctp_test3(abts_case *tc, void *data) { - pthread_create(&streamserver_tid, NULL, sctp_stream_server_main, NULL); - while (sctp_stream_server_started == 0) - { - sleep(1); - } - sleep(1); - return; + sock_id sctp; + status_t rv; + ssize_t size; + struct sockaddr_in src_addr; + socklen_t addrlen; + char str[STRLEN]; + char buf[INET6_ADDRSTRLEN]; + c_uint32_t ppid; + + rv = sctp_open(&sctp, AF_INET, SOCK_SEQPACKET, + NULL, PORT, NULL, 0, SOCK_F_BIND); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = thread_create(&test3_thread, NULL, test3_main, tc); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + addrlen = sizeof(src_addr); + size = sctp_read(sctp, str, STRLEN, + (struct sockaddr *)&src_addr, &addrlen, &ppid, NULL); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + ABTS_INT_EQUAL(tc, sizeof(src_addr), addrlen); + ABTS_INT_EQUAL(tc, PPID, ppid); + ABTS_STR_EQUAL(tc, "127.0.0.1", SOCK_NTOP(&src_addr, buf)); + + thread_join(&rv, test3_thread); + ABTS_INT_EQUAL(tc, strlen(DATASTR), rv); + + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); } -static void stop_stream_sctp_server() +static thread_id test4_thread; +static void *THREAD_FUNC test4_main(thread_id id, void *data) { - net_close(streamserver_sock); - pthread_join(streamserver_tid, NULL); -} + abts_case *tc = data; + status_t rv; + sock_id sctp; + char str[STRLEN]; + ssize_t size; + c_uint32_t ppid; -static void *sctp_seq_server_main(void *param) -{ - int rc; + rv = sctp_open(&sctp, AF_UNSPEC, SOCK_STREAM, + NULL, 0, "::1", PORT, SOCK_F_CONNECT); + ABTS_INT_EQUAL(tc, CORE_OK, rv); - rc = net_listen(&seqserver_sock, - SOCK_SEQPACKET, IPPROTO_SCTP, TEST_SERVER_PORT); - if (rc != 0) - { - d_error("net_sctp Error(rc = %d)\n",rc); - return NULL; - } + size = sctp_write(sctp, DATASTR, strlen(DATASTR), NULL, 0, PPID, 0); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); - sctp_seq_server_started = 1; + size = sctp_read(sctp, str, STRLEN, NULL, NULL, &ppid, NULL); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + ABTS_INT_EQUAL(tc, PPID, ppid); - while (1) - { - d_trace(1,"Wait for data....\n"); - rc = net_read(seqserver_sock, buffer, TEST_BUFFER_SIZE, 2); - if (rc >0) - { - d_trace(1,"RECV %d bytes\n", rc); - if (!strncmp(buffer, "QUIT",4)) - { - break; - } - else - { - /* Send received data */ - rc = net_send(seqserver_sock, buffer, rc); - d_trace(1,"SEND %d bytes\n", rc); - if (rc == -1) - { - printf("error = %d\n", seqserver_sock->sndrcv_errno); - } - } - } - else if (rc == 0) - { - /* Timeout */ - } - else - { - /* Error occured */ - if (rc != -2 && seqserver_sock->sndrcv_errno != EAGAIN) - break; - } - } + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + thread_exit(id, size); return NULL; } -static void start_seq_sctp_server() +static void sctp_test4(abts_case *tc, void *data) { - pthread_create(&seqserver_tid, NULL, sctp_seq_server_main, NULL); - while (sctp_seq_server_started == 0) - { - sleep(1); - } - return; -} + sock_id sctp; + status_t rv; + ssize_t size; + struct sockaddr_in6 src_addr; + socklen_t addrlen; + char str[STRLEN]; + c_uint32_t ppid; + char buf[INET6_ADDRSTRLEN]; -static void stop_seq_sctp_server() -{ - net_close(seqserver_sock); - pthread_join(seqserver_tid, NULL); -} + rv = sctp_open(&sctp, AF_INET6, SOCK_SEQPACKET, + NULL, PORT, NULL, 0, SOCK_F_BIND); + ABTS_INT_EQUAL(tc, CORE_OK, rv); -static void test_sctp1(abts_case *tc, void *data) -{ - int rc = 0; - net_sock_t *net_sock[TEST_MAX_NUM]; - char inputbuf[TEST_MAX_NUM][25]; - char outputbuf[TEST_MAX_NUM][25]; - int i; + rv = thread_create(&test4_thread, NULL, test4_main, tc); + ABTS_INT_EQUAL(tc, CORE_OK, rv); - /* Start SCTP Server */ - start_stream_sctp_server(); + addrlen = sizeof(src_addr); + size = sctp_read(sctp, str, STRLEN, (struct sockaddr *)&src_addr, &addrlen, &ppid, NULL); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + ABTS_INT_EQUAL(tc, sizeof(src_addr), addrlen); + ABTS_STR_EQUAL(tc, "::1", SOCK_NTOP(&src_addr, buf)); + ABTS_INT_EQUAL(tc, PPID, ppid); - /* Connect to invalid port */ - d_log_set_level(D_MSG_TO_STDOUT, D_LOG_LEVEL_FATAL); - for (i =0 ; isndrcv_errno == EAGAIN) - continue; - rc += n; - if (n == 0 || n == 6) - break; - } - ABTS_INT_EQUAL(tc, 6, rc); - ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1); - ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]); - } - - for (i = 0 ; i< TEST_MAX_NUM; i++) - { - rc = net_close(net_sock[i]); - ABTS_INT_EQUAL(tc, 0, rc); - } - - stop_stream_sctp_server(); -} - -static void test_sctp2(abts_case *tc, void *data) -{ - int rc = 0; - net_sock_t *net_sock[TEST_MAX_NUM]; - char inputbuf[TEST_MAX_NUM][25]; - char outputbuf[TEST_MAX_NUM][25]; - int i; - - /* Connect to invalid port. - * In SCTP cases, net_open should be success always - */ - for (i =0 ; isndrcv_errno == EAGAIN) - continue; - rc += n; - if (n == 0 || n == 6) - break; - } - ABTS_INT_EQUAL(tc, 6, rc); - ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1); - ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]); - } - - for (i = 0 ; i< TEST_MAX_NUM; i++) - { - rc = net_close(net_sock[i]); - ABTS_INT_EQUAL(tc, 0, rc); - } - - stop_seq_sctp_server(); + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); } abts_suite *testsctp(abts_suite *suite) { suite = ADD_SUITE(suite); - abts_run_test(suite, test_sctp1, NULL); - abts_run_test(suite, test_sctp2, NULL); + abts_run_test(suite, sctp_test1, NULL); + abts_run_test(suite, sctp_test2, NULL); + abts_run_test(suite, sctp_test3, NULL); + abts_run_test(suite, sctp_test4, NULL); return suite; } diff --git a/lib/core/test/testsock.c b/lib/core/test/testsock.c index 239e9a16d..58654fc80 100644 --- a/lib/core/test/testsock.c +++ b/lib/core/test/testsock.c @@ -8,28 +8,27 @@ #define DATASTR "This is a test" #define STRLEN 8092 -#define SRV_PORT 7777 -#define CLI_PORT 7778 +#define PORT 7777 static void sock_test1(abts_case *tc, void *data) { sock_id udp; status_t rv; - rv = udp_open(&udp, AF_UNSPEC, 0, SRV_PORT, NULL, 0, SOCK_F_BIND); + rv = udp_open(&udp, AF_UNSPEC, 0, PORT, NULL, 0, SOCK_F_BIND); ABTS_INT_EQUAL(tc, CORE_OK, rv); rv = sock_delete(udp); ABTS_INT_EQUAL(tc, CORE_OK, rv); rv = udp_open(&udp, AF_UNSPEC, - "127.0.0.1", SRV_PORT, NULL, 0, SOCK_F_BIND); + "127.0.0.1", PORT, NULL, 0, SOCK_F_BIND); ABTS_INT_EQUAL(tc, CORE_OK, rv); rv = sock_delete(udp); ABTS_INT_EQUAL(tc, CORE_OK, rv); - rv = udp_open(&udp, AF_UNSPEC, "::1", SRV_PORT, NULL, 0, SOCK_F_BIND); + rv = udp_open(&udp, AF_UNSPEC, "::1", PORT, NULL, 0, SOCK_F_BIND); ABTS_INT_EQUAL(tc, CORE_OK, rv); rv = sock_delete(udp); @@ -45,10 +44,10 @@ static void *THREAD_FUNC test2_main(thread_id id, void *data) char str[STRLEN]; ssize_t size; - rv = tcp_open(&tcp, AF_UNSPEC, NULL, 0, "::1", SRV_PORT, SOCK_F_CONNECT); + rv = tcp_open(&tcp, AF_UNSPEC, NULL, 0, "::1", PORT, SOCK_F_CONNECT); ABTS_INT_EQUAL(tc, CORE_OK, rv); - size = sock_recv(tcp, str, STRLEN, 0, NULL, NULL); + size = sock_read(tcp, str, STRLEN, 0, NULL, NULL); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); rv = sock_delete(tcp); @@ -64,7 +63,7 @@ static void sock_test2(abts_case *tc, void *data) status_t rv; ssize_t size; - rv = tcp_open(&tcp, AF_INET6, NULL, SRV_PORT, NULL, 0, SOCK_F_BIND); + rv = tcp_open(&tcp, AF_INET6, NULL, PORT, NULL, 0, SOCK_F_BIND); ABTS_INT_EQUAL(tc, CORE_OK, rv); rv = thread_create(&test2_thread, NULL, test2_main, tc); @@ -73,7 +72,7 @@ static void sock_test2(abts_case *tc, void *data) rv = sock_accept(&tcp2, tcp); ABTS_INT_EQUAL(tc, CORE_OK, rv); - size = sock_send(tcp2, DATASTR, strlen(DATASTR), 0, NULL, 0); + size = sock_write(tcp2, DATASTR, strlen(DATASTR), 0, NULL, 0); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); thread_join(&rv, test2_thread); @@ -102,12 +101,12 @@ static void *THREAD_FUNC test3_main(thread_id id, void *data) ABTS_INT_EQUAL(tc, CORE_OK, rv); memset(&dst_addr, 0, sizeof(dst_addr)); - dst_addr.sin_port = htons(SRV_PORT); + dst_addr.sin_port = htons(PORT); dst_addr.sin_family = AF_INET; rc = inet_pton(AF_INET, "127.0.0.1", &(dst_addr.sin_addr)); ABTS_INT_EQUAL(tc, 1, rc); - size = sock_send(udp, DATASTR, strlen(DATASTR), 0, + size = sock_write(udp, DATASTR, strlen(DATASTR), 0, (struct sockaddr *)&dst_addr, sizeof(struct sockaddr)); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); @@ -123,21 +122,23 @@ static void sock_test3(abts_case *tc, void *data) sock_id udp; status_t rv; ssize_t size; - struct sockaddr src_addr; + struct sockaddr_in src_addr; socklen_t addrlen; char str[STRLEN]; char buf[INET6_ADDRSTRLEN]; - rv = udp_open(&udp, AF_INET, NULL, SRV_PORT, NULL, 0, SOCK_F_BIND); + rv = udp_open(&udp, AF_INET, NULL, PORT, NULL, 0, SOCK_F_BIND); ABTS_INT_EQUAL(tc, CORE_OK, rv); rv = thread_create(&test3_thread, NULL, test3_main, tc); ABTS_INT_EQUAL(tc, CORE_OK, rv); - size = sock_recv(udp, str, STRLEN, 0, &src_addr, &addrlen); + addrlen = sizeof(src_addr); + size = sock_read(udp, str, STRLEN, 0, + (struct sockaddr *)&src_addr, &addrlen); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); - ABTS_INT_EQUAL(tc, addrlen, sizeof(src_addr)); - ABTS_STR_EQUAL(tc, SOCK_NTOP(&src_addr, buf), "127.0.0.1"); + ABTS_INT_EQUAL(tc, sizeof(src_addr), addrlen); + ABTS_STR_EQUAL(tc, "127.0.0.1", SOCK_NTOP(&src_addr, buf)); thread_join(&rv, test3_thread); ABTS_INT_EQUAL(tc, strlen(DATASTR), rv); @@ -156,13 +157,13 @@ static void *THREAD_FUNC test4_main(thread_id id, void *data) ssize_t size; rv = udp_open(&udp, AF_UNSPEC, - NULL, 0, "127.0.0.1", SRV_PORT, SOCK_F_CONNECT); + NULL, 0, "127.0.0.1", PORT, SOCK_F_CONNECT); ABTS_INT_EQUAL(tc, CORE_OK, rv); - size = sock_send(udp, DATASTR, strlen(DATASTR), 0, NULL, 0); + size = sock_write(udp, DATASTR, strlen(DATASTR), 0, NULL, 0); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); - size = sock_recv(udp, str, STRLEN, 0, NULL, NULL); + size = sock_read(udp, str, STRLEN, 0, NULL, NULL); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); rv = sock_delete(udp); @@ -177,20 +178,26 @@ static void sock_test4(abts_case *tc, void *data) sock_id udp; status_t rv; ssize_t size; - struct sockaddr src_addr; + struct sockaddr_in src_addr; socklen_t addrlen; char str[STRLEN]; + char buf[INET6_ADDRSTRLEN]; - rv = udp_open(&udp, AF_INET, NULL, SRV_PORT, NULL, 0, SOCK_F_BIND); + rv = udp_open(&udp, AF_INET, NULL, PORT, NULL, 0, SOCK_F_BIND); ABTS_INT_EQUAL(tc, CORE_OK, rv); rv = thread_create(&test4_thread, NULL, test4_main, tc); ABTS_INT_EQUAL(tc, CORE_OK, rv); - size = sock_recv(udp, str, STRLEN, 0, &src_addr, &addrlen); + addrlen = sizeof(src_addr); + size = sock_read(udp, str, STRLEN, 0, + (struct sockaddr *)&src_addr, &addrlen); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + ABTS_INT_EQUAL(tc, sizeof(src_addr), addrlen); + ABTS_STR_EQUAL(tc, "127.0.0.1", SOCK_NTOP(&src_addr, buf)); - size = sock_send(udp, DATASTR, strlen(DATASTR), 0, &src_addr, addrlen); + size = sock_write(udp, DATASTR, strlen(DATASTR), 0, + (struct sockaddr *)&src_addr, addrlen); ABTS_INT_EQUAL(tc, strlen(DATASTR), size); thread_join(&rv, test4_thread); @@ -204,11 +211,6 @@ abts_suite *testsock(abts_suite *suite) { suite = ADD_SUITE(suite) -#if 0 - extern int _sock; - d_trace_level(&_sock, 1); -#endif - abts_run_test(suite, sock_test1, NULL); abts_run_test(suite, sock_test2, NULL); abts_run_test(suite, sock_test3, NULL);