diff --git a/lib/core/include/core_network.h b/lib/core/include/core_network.h index beeb2ac36..8d01917a4 100644 --- a/lib/core/include/core_network.h +++ b/lib/core/include/core_network.h @@ -119,6 +119,8 @@ CORE_DECLARE(status_t) sctp_server(sock_id *new, int family, int type, const char *hostname, c_uint16_t port); CORE_DECLARE(status_t) sctp_client(sock_id *new, int family, int type, const char *hostname, c_uint16_t port); +CORE_DECLARE(status_t) sctp_connect(sock_id id, + const char *hostname, c_uint16_t port, c_sockaddr_t *result); CORE_DECLARE(int) core_sctp_sendmsg(sock_id id, const void *msg, size_t len, c_sockaddr_t *to, c_uint32_t ppid, c_uint16_t stream_no); #define CORE_SCTP_REMOTE_CLOSED -2 diff --git a/lib/core/src/unix/sctp.c b/lib/core/src/unix/sctp.c index 552ff8440..61e0c4ba6 100644 --- a/lib/core/src/unix/sctp.c +++ b/lib/core/src/unix/sctp.c @@ -144,6 +144,48 @@ status_t sctp_client(sock_id *new, return CORE_OK; } +status_t sctp_connect(sock_id id, const char *hostname, c_uint16_t port, + c_sockaddr_t *result) +{ + status_t rv; + c_sockaddr_t *sa; + sock_t *sock = (sock_t *)id; + char buf[CORE_ADDRSTRLEN]; + + d_assert(id, return CORE_ERROR,); + + rv = core_getaddrinfo(&sa, sock->family, hostname, port, 0); + d_assert(rv == CORE_OK && sa, return CORE_ERROR,); + + while(sa) + { + if (connect(sock->fd, &sa->sa, sa->sa_len) == 0) + { + d_trace(1, "sctp connect %s:%d\n", CORE_NTOP(sa, buf), port); + if (result) + { + memcpy(&result->sa, &sa->sa, sa->sa_len); + result->sa_len = sa->sa_len; + } + break; + } + + sa = sa->next; + } + + if (sa == NULL) + { + d_error("sctp connect(%d:%s:%d) failed(%d:%s)", + sock->family, hostname, port, errno, strerror(errno)); + return CORE_ERROR; + } + + rv = core_freeaddrinfo(sa); + d_assert(rv == CORE_OK, return CORE_ERROR,); + + return CORE_OK; +} + int core_sctp_sendmsg(sock_id id, const void *msg, size_t len, c_sockaddr_t *to, c_uint32_t ppid, c_uint16_t stream_no) { diff --git a/lib/core/test/testsctp.c b/lib/core/test/testsctp.c index ff9a634a5..0612d9bc2 100644 --- a/lib/core/test/testsctp.c +++ b/lib/core/test/testsctp.c @@ -206,6 +206,75 @@ static void sctp_test4(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, CORE_OK, rv); } +static thread_id test5_thread; +static void *THREAD_FUNC test5_main(thread_id id, void *data) +{ + abts_case *tc = data; + status_t rv; + sock_id sctp; + char str[STRLEN]; + c_sockaddr_t sa; + c_uint32_t ppid; + ssize_t size; + char buf[CORE_ADDRSTRLEN]; + + rv = sctp_server(&sctp, AF_INET6, SOCK_SEQPACKET, NULL, PORT2); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = sctp_connect(sctp, "::1", PORT, &sa); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + ABTS_INT_EQUAL(tc, sizeof(struct sockaddr_in6), sa.sa_len); + ABTS_STR_EQUAL(tc, "::1", CORE_NTOP(&sa, buf)); + + size = core_sctp_sendmsg(sctp, DATASTR, strlen(DATASTR), &sa, PPID, 0); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + + size = core_sctp_recvmsg(sctp, str, STRLEN, &sa, &ppid, NULL); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + ABTS_INT_EQUAL(tc, sizeof(struct sockaddr_in6), sa.sa_len); + ABTS_STR_EQUAL(tc, "::1", CORE_NTOP(&sa, buf)); + 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 sctp_test5(abts_case *tc, void *data) +{ + sock_id sctp; + status_t rv; + ssize_t size; + c_sockaddr_t sa; + socklen_t addrlen; + char str[STRLEN]; + c_uint32_t ppid; + char buf[CORE_ADDRSTRLEN]; + + rv = sctp_server(&sctp, AF_INET6, SOCK_SEQPACKET, NULL, PORT); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + rv = thread_create(&test5_thread, NULL, test5_main, tc); + ABTS_INT_EQUAL(tc, CORE_OK, rv); + + size = core_sctp_recvmsg(sctp, str, STRLEN, &sa, &ppid, NULL); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + ABTS_INT_EQUAL(tc, sizeof(struct sockaddr_in6), sa.sa_len); + ABTS_STR_EQUAL(tc, "::1", CORE_NTOP(&sa, buf)); + ABTS_INT_EQUAL(tc, PPID, ppid); + + size = core_sctp_sendmsg(sctp, DATASTR, strlen(DATASTR), &sa, ppid, 0); + ABTS_INT_EQUAL(tc, strlen(DATASTR), size); + + thread_join(&rv, test5_thread); + ABTS_INT_EQUAL(tc, strlen(DATASTR), rv); + + rv = sock_delete(sctp); + ABTS_INT_EQUAL(tc, CORE_OK, rv); +} + abts_suite *testsctp(abts_suite *suite) { suite = ADD_SUITE(suite); @@ -214,6 +283,7 @@ abts_suite *testsctp(abts_suite *suite) abts_run_test(suite, sctp_test2, NULL); abts_run_test(suite, sctp_test3, NULL); abts_run_test(suite, sctp_test4, NULL); + abts_run_test(suite, sctp_test5, NULL); return suite; }