SCTP library is initially added

This commit is contained in:
Sukchan Lee 2017-11-16 10:46:25 +00:00
parent 7c505f917a
commit a4d1bae083
7 changed files with 649 additions and 361 deletions

View File

@ -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

View File

@ -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);

View File

@ -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)

344
lib/core/src/unix/sctp.c Normal file
View File

@ -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 <netinet/sctp.h>
#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;
}

View File

@ -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;

View File

@ -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 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0,TEST_SERVER_PORT + 1,
SOCK_STREAM, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, -1, rc);
ABTS_PTR_NULL(tc, net_sock[i]);
}
d_log_set_level(D_MSG_TO_STDOUT, D_LOG_LEVEL_FULL);
size = sctp_write(sctp, DATASTR, strlen(DATASTR),
(struct sockaddr *)&src_addr, addrlen, PPID, 0);
ABTS_INT_EQUAL(tc, strlen(DATASTR), size);
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT,
SOCK_STREAM, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
thread_join(&rv, test4_thread);
ABTS_INT_EQUAL(tc, strlen(DATASTR), rv);
for (i=0; i< TEST_MAX_NUM; i++)
{
sprintf(inputbuf[i],"asdf%d",i);
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
rc = net_send(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1);
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
rc = 0;
while (1)
{
int n;
n = net_read(net_sock[i], outputbuf[i], sizeof(outputbuf[1]), 1);
if (n < 0 && net_sock[i]->sndrcv_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 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT + 1,
SOCK_SEQPACKET, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
for (i = 0 ; i< TEST_MAX_NUM; i++)
{
rc = net_close(net_sock[i]);
ABTS_INT_EQUAL(tc, 0, rc);
}
/* Start SCTP Server */
start_seq_sctp_server();
for (i =0 ; i<TEST_MAX_NUM; i++)
{
net_sock[i] = NULL;
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT,
SOCK_SEQPACKET, IPPROTO_SCTP);
ABTS_INT_EQUAL(tc, 0, rc);
ABTS_PTR_NOTNULL(tc, net_sock[i]);
}
for (i=0; i< TEST_MAX_NUM; i++)
{
sprintf(inputbuf[i],"asdf%d",i);
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
rc = net_sendto(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1,
inet_addr("127.0.0.1"), TEST_SERVER_PORT);
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
rc = 0;
while (1)
{
int n;
n = net_read(net_sock[i], outputbuf[i], sizeof(outputbuf[i]), 1);
if (n < 0 && net_sock[i]->sndrcv_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;
}

View File

@ -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);