Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upcall API and some examples (2 clients and 4 servers) #189

Merged
merged 8 commits into from
Aug 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@ This is a userland SCTP stack supporting FreeBSD, Linux, Mac OS X and Windows.

See [manual](Manual.md) for more information.

The status of continuous integration testing is available from [grid](http://212.201.121.110:18010/grid) and [waterfall](http://212.201.121.110:18010/waterfall).
If you are only interested in a single branch, just append `?branch=BRANCHNAME` to the URL, for example [waterfall](http://212.201.121.110:18010/waterfall?branch=master).
6 changes: 6 additions & 0 deletions programs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ set(check_programs
test_libmgmt.c
test_timer.c
tsctp.c
http_client_upcall.c
client_upcall.c
discard_server_upcall.c
echo_server_upcall.c
chargen_server_upcall.c
daytime_server_upcall.c
)

foreach (source_file ${check_programs})
Expand Down
239 changes: 239 additions & 0 deletions programs/chargen_server_upcall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
/*
* Copyright (C) 2012-2013 Michael Tuexen
*
* 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.
*/

/*
* Usage: daytime_server [local_encaps_port] [remote_encaps_port]
*/

#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#ifndef _WIN32
#include <unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include <usrsctp.h>

#define BUFFERSIZE 10240
#define PORT 19

char buffer[95];
int done = 0;
int send_done = 0;

static void
initBuffer() {
int i, j;
for (i = 32, j = 0; i < 126; i++, j++) {
buffer[j] = i;
}
}

unsigned int signCounter = 0;
static void
handle_upcall(struct socket *sock, void *data, int flgs);

static void
handle_accept(struct socket *sock, void *data, int flags)
{
struct socket *conn_sock;

if (((conn_sock = usrsctp_accept(sock, NULL, NULL)) == NULL)
&& (errno != EINPROGRESS)) {
perror("usrsctp_accept");
return;
}
done = 0;
printf("connection accepted from socket %p\n", (void *)conn_sock);
usrsctp_set_upcall(conn_sock, handle_upcall, NULL);
}

static void
handle_upcall(struct socket *sock, void *data, int flgs)
{
int events = usrsctp_get_events(sock);

if (events & SCTP_EVENT_READ && !send_done) {
char *buf;
struct sctp_recvv_rn rn;
ssize_t n;
struct sockaddr_storage addr;
buf = malloc(BUFFERSIZE);
int flags = 0;
socklen_t len = (socklen_t)sizeof(struct sockaddr_storage);
unsigned int infotype = 0;
socklen_t infolen = sizeof(struct sctp_recvv_rn);
memset(&rn, 0, sizeof(struct sctp_recvv_rn));

n = usrsctp_recvv(sock, buf, BUFFERSIZE, (struct sockaddr *) &addr, &len, (void *)&rn,
&infolen, &infotype, &flags);
if (n < 0) {
perror("usrsctp_recvv");
done = 1;
usrsctp_close(sock);
printf("client socket %p closed\n", (void *)sock);
sock = NULL;
return;
}
if (n == 0) {
done = 1;
usrsctp_close(sock);
printf("client socket %p closed\n", (void *)sock);
sock = NULL;
return;
}
if (n > 0) {
if (flags & MSG_NOTIFICATION) {
printf("Notification of length %d received.\n", (int)n);
} else {
printf("data of size %zd received\n", n);
}
}
free(buf);
}

if ((events & SCTP_EVENT_WRITE) && !done) {
struct sctp_sndinfo snd_info;
snd_info.snd_sid = 0;
snd_info.snd_flags = 0;
snd_info.snd_ppid = 0;
snd_info.snd_context = 0;
snd_info.snd_assoc_id = 0;
if (usrsctp_sendv(sock, buffer, strlen(buffer), NULL, 0, &snd_info, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) {
if (errno != EAGAIN) {
send_done = 1;
usrsctp_close(sock);
printf("client socket %p closed\n", (void *)sock);
return;
}
}
}

return;
}

void
debug_printf(const char *format, ...)
{
va_list ap;

va_start(ap, format);
vprintf(format, ap);
va_end(ap);
}

int
main(int argc, char *argv[])
{
struct socket *listening_socket;
struct sockaddr_in6 addr;
struct sctp_udpencaps encaps;
struct sctp_assoc_value av;
const int on = 1;

if (argc > 1) {
usrsctp_init(atoi(argv[1]), NULL, debug_printf);
} else {
usrsctp_init(9899, NULL, debug_printf);
}
#ifdef SCTP_DEBUG
usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
#endif
usrsctp_sysctl_set_sctp_blackhole(2);

if ((listening_socket = usrsctp_socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL)) == NULL) {
perror("usrsctp_socket");
}
usrsctp_set_non_blocking(listening_socket, 1);
if (usrsctp_setsockopt(listening_socket, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, (const void*)&on, (socklen_t)sizeof(int)) < 0) {
perror("usrsctp_setsockopt SCTP_I_WANT_MAPPED_V4_ADDR");
}
memset(&av, 0, sizeof(struct sctp_assoc_value));
av.assoc_id = SCTP_ALL_ASSOC;
av.assoc_value = 47;

if (usrsctp_setsockopt(listening_socket, IPPROTO_SCTP, SCTP_CONTEXT, (const void*)&av, (socklen_t)sizeof(struct sctp_assoc_value)) < 0) {
perror("usrsctp_setsockopt SCTP_CONTEXT");
}
if (usrsctp_setsockopt(listening_socket, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(int)) < 0) {
perror("usrsctp_setsockopt SCTP_RECVRCVINFO");
}
if (argc > 2) {
memset(&encaps, 0, sizeof(struct sctp_udpencaps));
encaps.sue_address.ss_family = AF_INET6;
encaps.sue_port = htons(atoi(argv[2]));
if (usrsctp_setsockopt(listening_socket, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
perror("usrsctp_setsockopt SCTP_REMOTE_UDP_ENCAPS_PORT");
}
}

initBuffer();

memset((void *)&addr, 0, sizeof(struct sockaddr_in6));
#ifdef HAVE_SIN6_LEN
addr.sin6_len = sizeof(struct sockaddr_in6);
#endif
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(PORT);
addr.sin6_addr = in6addr_any;
if (usrsctp_bind(listening_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0) {
perror("usrsctp_bind");
}
if (usrsctp_listen(listening_socket, 1) < 0) {
perror("usrsctp_listen");
}
usrsctp_set_upcall(listening_socket, handle_accept, NULL);

while (1) {
#ifdef _WIN32
Sleep(1*1000);
#else
sleep(1);
#endif
}
usrsctp_close(listening_socket);
while (usrsctp_finish() != 0) {
#ifdef _WIN32
Sleep(1000);
#else
sleep(1);
#endif
}
return (0);
}
Loading