From eab8fe500a1eceded776ebfb8e281baa9c1fdf36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?= Date: Thu, 27 Jun 2019 10:37:33 +0200 Subject: [PATCH] single thread Based on https://github.com/sctplab/usrsctp/pull/38/commits/010fcbc6f193152607dc267c7e7e573c9bffc111 from @ccaughie --- programs/CMakeLists.txt | 1 + programs/Makefile.am | 8 +- programs/Makefile.nmake | 9 +- programs/st_client.c | 355 ++++++++++++++++++++++++++++++ usrsctplib/netinet/sctp_callout.c | 2 +- usrsctplib/netinet/sctp_callout.h | 1 + usrsctplib/netinet/sctp_output.c | 2 +- usrsctplib/netinet/sctp_pcb.c | 5 +- usrsctplib/netinet/sctp_pcb.h | 2 +- usrsctplib/netinet/sctp_usrreq.c | 7 +- usrsctplib/netinet/sctp_var.h | 2 +- usrsctplib/user_socket.c | 45 +++- usrsctplib/usrsctp.h | 15 ++ 13 files changed, 435 insertions(+), 19 deletions(-) create mode 100644 programs/st_client.c diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt index 8e372660f..230f698fd 100644 --- a/programs/CMakeLists.txt +++ b/programs/CMakeLists.txt @@ -101,6 +101,7 @@ list(APPEND check_programs http_client.c http_client_upcall.c rtcweb.c + st_client.c test_libmgmt.c test_timer.c tsctp.c diff --git a/programs/Makefile.am b/programs/Makefile.am index acb216872..794c32e19 100644 --- a/programs/Makefile.am +++ b/programs/Makefile.am @@ -52,7 +52,8 @@ EXTRA_DIST = \ ekr_peer.c \ test_libmgmt.c \ http_client.c \ - http_client_upcall.c + http_client_upcall.c \ + st_client.c noinst_PROGRAMS = \ test_libmgmt \ @@ -76,7 +77,8 @@ noinst_PROGRAMS = \ ekr_peer \ test_libmgmt \ http_client \ - http_client_upcall + http_client_upcall \ + st_client test_libmgmt_SOURCES = programs_helper.c test_libmgmt.c test_libmgmt_LDADD = ../usrsctplib/libusrsctp.la @@ -120,3 +122,5 @@ http_client_SOURCES = programs_helper.c http_client.c http_client_LDADD = ../usrsctplib/libusrsctp.la http_client_upcall_SOURCES = programs_helper.c http_client_upcall.c http_client_upcall_LDADD = ../usrsctplib/libusrsctp.la +st_client_SOURCES = programs_helper.c st_client.c +st_client_LDADD = ../usrsctplib/libusrsctp.la diff --git a/programs/Makefile.nmake b/programs/Makefile.nmake index d426b2442..24e9695ec 100644 --- a/programs/Makefile.nmake +++ b/programs/Makefile.nmake @@ -57,7 +57,8 @@ all: \ ekr_loop_upcall \ test_libmgmt \ http_client \ - http_client_upcall + http_client_upcall \ + st_client programs_helper.obj : programs_helper.c programs_helper.h cl $(CVARSDLL) $(CFLAGS) -c programs_helper.c @@ -138,6 +139,10 @@ http_client_upcall: $(CC) $(CFLAGS) $(CVARSDLL) -c http_client_upcall.c link -out:http_client_upcall.exe http_client_upcall.obj programs_helper.obj $(LINKFLAGS) +st_client: + $(CC) $(CFLAGS) $(CVARSDLL) -c st_client.c + link -out:st_client.exe st_client.obj programs_helper.obj $(LINKFLAGS) + clean: del /F client.exe del /F client.obj @@ -177,3 +182,5 @@ clean: del /F http_client.obj del /F http_client_upcall.exe del /F http_client_upcall.obj + del /F st_client.exe + del /F st_client.obj diff --git a/programs/st_client.c b/programs/st_client.c new file mode 100644 index 000000000..36eed741c --- /dev/null +++ b/programs/st_client.c @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2011-2013 Michael Tuexen + * Copyright (C) 2011-2015 Colin Caughie + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif +#include +#include +#include +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#else +#include +#include +#endif +#include +#include "programs_helper.h" + +#define MAX_PACKET_SIZE (1<<16) +#define BUFFER_SIZE 80 +#define DISCARD_PPID 39 + +#define TIMER_INTERVAL_MSECS 10 + +static int connecting = 0; +static int finish = 0; + +static unsigned get_tick_count() +{ +#ifdef _WIN32 + return GetTickCount(); +#else + static const clock_t clocks_per_msec = CLOCKS_PER_SEC / 1000; + return clock() / clocks_per_msec; +#endif +} + +static void +handle_packets(int sock, struct socket* s, void* sconn_addr) +{ + char *dump_buf; + ssize_t length; + char buf[MAX_PACKET_SIZE]; + + fd_set rfds; + struct timeval tv; + int retval; + + unsigned next_fire_time = get_tick_count(); + unsigned last_fire_time = next_fire_time; + + while (!finish) { + + unsigned now = get_tick_count(); + int wait_time; + + if ((int) (now - next_fire_time) > 0) { + usrsctp_fire_timer(now - last_fire_time); + last_fire_time = now; + next_fire_time = now + TIMER_INTERVAL_MSECS; + } + + wait_time = next_fire_time - now; + tv.tv_sec = wait_time / 1000; + tv.tv_usec = (wait_time % 1000) * 1000; + + retval = select(1, &rfds, NULL, NULL, &tv); + + length = recv(sock, buf, MAX_PACKET_SIZE, 0); + if (length > 0) { + if ((dump_buf = usrsctp_dumppacket(buf, (size_t)length, SCTP_DUMP_INBOUND)) != NULL) { + fprintf(stderr, "%s", dump_buf); + usrsctp_freedumpbuffer(dump_buf); + } + usrsctp_conninput(sconn_addr, buf, (size_t)length, 0); + } + } +} + +static void on_connect(struct socket* s) +{ + struct sctp_sndinfo sndinfo; + char buffer[BUFFER_SIZE]; + + memset(buffer, 'A', BUFFER_SIZE); + sndinfo.snd_sid = 1; + sndinfo.snd_flags = 0; + sndinfo.snd_ppid = htonl(DISCARD_PPID); + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + if (usrsctp_sendv(s, buffer, BUFFER_SIZE, NULL, 0, (void *)&sndinfo, + (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) { + perror("usrsctp_sendv"); + } +} + +static void on_socket_readable(struct socket* s) { + char buffer[BUFFER_SIZE]; + union sctp_sockstore addr; + socklen_t fromlen = sizeof(addr); + struct sctp_rcvinfo rcv_info; + socklen_t infolen = sizeof(rcv_info); + unsigned int infotype = 0; + int flags = 0; + ssize_t retval; + + /* Keep reading until there is no more data */ + for (;;) { + retval = usrsctp_recvv(s, buffer, sizeof(buffer), (struct sockaddr*) &addr, + &fromlen, &rcv_info, &infolen, &infotype, &flags); + + if (retval < 0) { + if (errno != EWOULDBLOCK) { + perror("usrsctp_recvv"); + finish = 1; + } + return; + } else if (retval == 0) { + printf("socket was disconnected\n"); + finish = 1; + return; + } + + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %d received.\n", (int)retval); + } else { + printf("Msg of length %d received via %p:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u.\n", + (int)retval, + addr.sconn.sconn_addr, + ntohs(addr.sconn.sconn_port), + rcv_info.rcv_sid, + rcv_info.rcv_ssn, + rcv_info.rcv_tsn, + ntohl(rcv_info.rcv_ppid), + rcv_info.rcv_context); + } + } +} + +static void handle_upcall(struct socket *s, void *arg, int flags) +{ + int events = usrsctp_get_events(s); + + if (connecting) { + if (events & SCTP_EVENT_ERROR) { + connecting = 0; + finish = 1; + } else if (events & SCTP_EVENT_WRITE) { + connecting = 0; + on_connect(s); + } + + return; + } + + if (events & SCTP_EVENT_READ) { + on_socket_readable(s); + } +} + +static int +conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df) +{ + char *dump_buf; +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + +#ifdef _WIN32 + fdp = (SOCKET *)addr; +#else + fdp = (int *)addr; +#endif + if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) { + fprintf(stderr, "%s", dump_buf); + usrsctp_freedumpbuffer(dump_buf); + } +#ifdef _WIN32 + if (send(*fdp, buf, length, 0) == SOCKET_ERROR) { + return (WSAGetLastError()); +#else + if (send(*fdp, buf, length, 0) < 0) { + return (errno); +#endif + } else { + return (0); + } +} + +/* Usage: st_client local_addr local_port remote_addr remote_port remote_sctp_port */ +int +main(int argc, char *argv[]) +{ + struct sockaddr_in sin; + struct sockaddr_conn sconn; +#ifdef _WIN32 + SOCKET fd; +#else + int fd; +#endif + struct socket *s; + int retval; +#ifdef _WIN32 + WSADATA wsaData; +#endif + + if (argc < 6) { + printf("Usage: st_client local_addr local_port remote_addr remote_port remote_sctp_port\n"); + exit(EXIT_FAILURE); + } + +#ifdef _WIN32 + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { + printf("WSAStartup failed\n"); + exit (EXIT_FAILURE); + } +#endif + usrsctp_init_nothreads(0, conn_output, debug_printf); + /* set up a connected UDP socket */ +#ifdef _WIN32 + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { + printf("socket() failed with error: %ld\n", WSAGetLastError()); + exit(1); + } +#else + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("socket"); + exit(1); + } +#endif + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif + sin.sin_port = htons(atoi(argv[2])); + if (!inet_pton(AF_INET, argv[1], &sin.sin_addr.s_addr)){ + printf("error: invalid address\n"); + exit(1); + } +#ifdef _WIN32 + if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("bind() failed with error: %ld\n", WSAGetLastError()); + exit(1); + } +#else + if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + exit(1); + } +#endif + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif + sin.sin_port = htons(atoi(argv[4])); + if (!inet_pton(AF_INET, argv[3], &sin.sin_addr.s_addr)){ + printf("error: invalid address\n"); + exit(1); + } +#ifdef _WIN32 + if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("connect() failed with error: %ld\n", WSAGetLastError()); + exit(1); + } +#else + if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { + perror("connect"); + exit(1); + } +#endif +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_ecn_enable(0); + usrsctp_register_address((void *)&fd); + + if ((s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL)) == NULL) { + perror("usrsctp_socket"); + exit(1); + } + + usrsctp_set_non_blocking(s, 1); + usrsctp_set_upcall(s, handle_upcall, NULL); + + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(0); + sconn.sconn_addr = NULL; + if (usrsctp_bind(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_bind"); + } + + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(atoi(argv[5])); + sconn.sconn_addr = &fd; + + retval = usrsctp_connect(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)); + + if (retval < 0 && errno != EWOULDBLOCK && errno != EINPROGRESS) { + perror("usrsctp_connect"); + exit(1); + } + + connecting = 1; + + handle_packets(fd, s, sconn.sconn_addr); + + return 0; +} diff --git a/usrsctplib/netinet/sctp_callout.c b/usrsctplib/netinet/sctp_callout.c index b12b4b23f..3ba527071 100755 --- a/usrsctplib/netinet/sctp_callout.c +++ b/usrsctplib/netinet/sctp_callout.c @@ -217,7 +217,7 @@ sctp_os_timer_stop(sctp_os_timer_t *c) return (1); } -static void +void sctp_handle_tick(int delta) { sctp_os_timer_t *c; diff --git a/usrsctplib/netinet/sctp_callout.h b/usrsctplib/netinet/sctp_callout.h index 814bd0698..3ac6c5bb4 100755 --- a/usrsctplib/netinet/sctp_callout.h +++ b/usrsctplib/netinet/sctp_callout.h @@ -103,6 +103,7 @@ typedef struct sctp_callout sctp_os_timer_t; void sctp_os_timer_init(sctp_os_timer_t *tmr); void sctp_os_timer_start(sctp_os_timer_t *, int, void (*)(void *), void *); int sctp_os_timer_stop(sctp_os_timer_t *); +void sctp_handle_tick(int delta); #define SCTP_OS_TIMER_INIT sctp_os_timer_init #define SCTP_OS_TIMER_START sctp_os_timer_start diff --git a/usrsctplib/netinet/sctp_output.c b/usrsctplib/netinet/sctp_output.c index 3f7c461c5..3ba64da9c 100755 --- a/usrsctplib/netinet/sctp_output.c +++ b/usrsctplib/netinet/sctp_output.c @@ -13901,7 +13901,7 @@ sctp_lower_sosend(struct socket *so, } } #if defined(__Userspace__) - if (inp->recv_callback) { + if (inp->recv_callback || SCTP_SO_IS_NBIO(so)) { non_blocking = 1; } #endif diff --git a/usrsctplib/netinet/sctp_pcb.c b/usrsctplib/netinet/sctp_pcb.c index f5c4e3a19..4ea0845cb 100755 --- a/usrsctplib/netinet/sctp_pcb.c +++ b/usrsctplib/netinet/sctp_pcb.c @@ -6635,7 +6635,7 @@ sctp_netisr_hdlr(struct mbuf *m, uintptr_t source) #endif void -sctp_pcb_init() +sctp_pcb_init(int start_threads) { /* * SCTP initialization for the PCB structures should be called by @@ -6851,7 +6851,8 @@ sctp_pcb_init() mbuf_initialize(NULL); atomic_init(); #if defined(INET) || defined(INET6) - recv_thread_init(); + if (start_threads) + recv_thread_init(); #endif #endif } diff --git a/usrsctplib/netinet/sctp_pcb.h b/usrsctplib/netinet/sctp_pcb.h index dad09e0e5..16b19c034 100755 --- a/usrsctplib/netinet/sctp_pcb.h +++ b/usrsctplib/netinet/sctp_pcb.h @@ -843,7 +843,7 @@ void sctp_remove_net(struct sctp_tcb *, struct sctp_nets *); int sctp_del_remote_addr(struct sctp_tcb *, struct sockaddr *); -void sctp_pcb_init(void); +void sctp_pcb_init(int); void sctp_pcb_finish(void); diff --git a/usrsctplib/netinet/sctp_usrreq.c b/usrsctplib/netinet/sctp_usrreq.c index 0912e3e9d..5ff7a2a8a 100755 --- a/usrsctplib/netinet/sctp_usrreq.c +++ b/usrsctplib/netinet/sctp_usrreq.c @@ -77,7 +77,7 @@ void #if defined(__Userspace__) sctp_init(uint16_t port, int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), - void (*debug_printf)(const char *format, ...)) + void (*debug_printf)(const char *format, ...), int start_threads) #elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)) sctp_init(struct protosw *pp SCTP_UNUSED, struct domain *dp SCTP_UNUSED) #else @@ -151,9 +151,10 @@ sctp_init(void) SCTP_BASE_VAR(debug_printf) = debug_printf; SCTP_BASE_VAR(crc32c_offloaded) = 0; #endif - sctp_pcb_init(); + sctp_pcb_init(start_threads); #if defined(__Userspace__) - sctp_start_timer(); + if (start_threads) + sctp_start_timer(); #endif #if defined(SCTP_PACKET_LOGGING) SCTP_BASE_VAR(packet_log_writers) = 0; diff --git a/usrsctplib/netinet/sctp_var.h b/usrsctplib/netinet/sctp_var.h index bc4afe95f..ead9e9cd6 100755 --- a/usrsctplib/netinet/sctp_var.h +++ b/usrsctplib/netinet/sctp_var.h @@ -454,7 +454,7 @@ void sctp_drain(void); #if defined(__Userspace__) void sctp_init(uint16_t, int (*)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), - void (*)(const char *, ...)); + void (*)(const char *, ...), int start_threads); #elif defined(__FreeBSD__) && __FreeBSD_version < 902000 void sctp_init __P((void)); #elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)) diff --git a/usrsctplib/user_socket.c b/usrsctplib/user_socket.c index 6ac0af7ea..3b6fafae8 100755 --- a/usrsctplib/user_socket.c +++ b/usrsctplib/user_socket.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #ifdef INET6 #include @@ -77,11 +78,7 @@ extern int sctp_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio extern int sctp_attach(struct socket *so, int proto, uint32_t vrf_id); extern int sctpconn_attach(struct socket *so, int proto, uint32_t vrf_id); -void -usrsctp_init(uint16_t port, - int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), - void (*debug_printf)(const char *format, ...)) -{ +static void init_sync() { #if defined(__Userspace_os_Windows) #if defined(INET) || defined(INET6) WSADATA wsaData; @@ -104,7 +101,25 @@ usrsctp_init(uint16_t port, pthread_mutexattr_destroy(&mutex_attr); pthread_cond_init(&accept_cond, NULL); #endif - sctp_init(port, conn_output, debug_printf); +} + +void +usrsctp_init(uint16_t port, + int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), + void (*debug_printf)(const char *format, ...)) +{ + init_sync(); + sctp_init(port, conn_output, debug_printf, 1); +} + + +void +usrsctp_init_nothreads(uint16_t port, + int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), + void (*debug_printf)(const char *format, ...)) +{ + init_sync(); + sctp_init(port, conn_output, debug_printf, 0); } @@ -1564,8 +1579,9 @@ sowakeup(struct socket *so, struct sockbuf *sb) #endif } SOCKBUF_UNLOCK(sb); - /*__Userspace__ what todo about so_upcall?*/ + if ((sb->sb_flags & SB_UPCALL) && so->so_upcall != NULL) + (*so->so_upcall)(so, so->so_upcallarg, M_NOWAIT); } #else /* kernel version for reference */ /* @@ -2406,6 +2422,16 @@ usrsctp_getsockopt(struct socket *so, int level, int option_name, *option_len = (socklen_t)sizeof(struct linger); return (0); } + case SO_ERROR: + if (*option_len < sizeof(int)) { + errno = EINVAL; + return (-1); + } else { + int *intval = (int *)option_value; + *intval = so->so_error; + *option_len = (socklen_t)sizeof(int); + return (0); + } default: errno = EINVAL; return (-1); @@ -3501,6 +3527,11 @@ usrsctp_conninput(void *addr, const void *buffer, size_t length, uint8_t ecn_bit return; } +void usrsctp_fire_timer(int delta) +{ + sctp_handle_tick(delta); +} + int usrsctp_get_events(struct socket *so) { diff --git a/usrsctplib/usrsctp.h b/usrsctplib/usrsctp.h index 0533c495e..6c8e9bf76 100644 --- a/usrsctplib/usrsctp.h +++ b/usrsctplib/usrsctp.h @@ -892,6 +892,11 @@ usrsctp_init(uint16_t, int (*)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), void (*)(const char *format, ...)); +void +usrsctp_init_nothreads(uint16_t, + int (*)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), + void (*)(const char *format, ...)); + struct socket * usrsctp_socket(int domain, int type, int protocol, int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data, @@ -1016,6 +1021,13 @@ usrsctp_set_non_blocking(struct socket *, int); int usrsctp_get_non_blocking(struct socket *); +int +usrsctp_get_events(struct socket *so); + +int +usrsctp_set_upcall(struct socket *so, + void (*upcall)(struct socket *, void *, int), void *arg); + void usrsctp_register_address(void *); @@ -1034,6 +1046,9 @@ int usrsctp_get_events(struct socket *so); +void +usrsctp_fire_timer(int delta); + #define SCTP_DUMP_OUTBOUND 1 #define SCTP_DUMP_INBOUND 0