/*
 * Class:     net_tomp2p_sctp_core_Sctp
 * Method:    usrsctp_init
 * Signature: (I)Z
 */
JNIEXPORT jboolean JNICALL
Java_net_tomp2p_sctp_core_Sctp_usrsctp_1init
    (JNIEnv *env, jclass clazz, jint port)
{
    /*
     * First argument is udp_encapsulation_port which is not relevant to our
     * AF_CONN use of SCTP.
     */
    debugSctpPrintf("=====>: net_tomp2p_sctp_core_Sctp.c calling init\n");
    usrsctp_init((uint16_t) port, onSctpOutboundPacket, debugSctpPrintf);

    debugSctpPrintf("=====>: net_tomp2p_sctp_core_Sctp.c about to set SCTP_DEBUG_ALL\n");
#ifdef SCTP_DEBUG
    debugSctpPrintf("=====>: net_tomp2p_sctp_core_Sctp.c setting SCTP_DEBUG_ALL\n");
    //usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
    usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
#endif


    /* TODO(ldixon) Consider turning this on/off. */
    usrsctp_sysctl_set_sctp_ecn_enable(0);

    return JNI_TRUE;
}
Example #2
0
int
main(int argc, char *argv[])
{
	struct socket *sock;
	struct sockaddr_in addr;
	socklen_t addr_len;
	char line[LINE_LENGTH + 1];
	unsigned int unordered, policy, value, id, seconds;
	unsigned int i;
	struct channel *channel;
	const int on = 1;
	struct sctp_assoc_value av;
	struct sctp_event event;
	struct sctp_udpencaps encaps;
	struct sctp_initmsg initmsg;
	uint16_t event_types[] = {SCTP_ASSOC_CHANGE,
	                          SCTP_PEER_ADDR_CHANGE,
	                          SCTP_REMOTE_ERROR,
	                          SCTP_SHUTDOWN_EVENT,
	                          SCTP_ADAPTATION_INDICATION,
	                          SCTP_SEND_FAILED_EVENT,
	                          SCTP_STREAM_RESET_EVENT,
	                          SCTP_STREAM_CHANGE_EVENT};

	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 ((sock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &peer_connection)) == NULL) {
		perror("socket");
	}
	init_peer_connection(&peer_connection);
	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(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
			perror("setsockopt");
		}
	}
	if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(int)) < 0) {
		perror("setsockopt SCTP_RECVRCVINFO");
	}
	if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &on, sizeof(int)) < 0) {
		perror("setsockopt SCTP_EXPLICIT_EOR");
	}
	/* Allow resetting streams. */
	av.assoc_id = SCTP_ALL_ASSOC;
	av.assoc_value = SCTP_ENABLE_RESET_STREAM_REQ | SCTP_ENABLE_CHANGE_ASSOC_REQ;
	if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, &av, sizeof(struct sctp_assoc_value)) < 0) {
		perror("setsockopt SCTP_ENABLE_STREAM_RESET");
	}
	/* Enable the events of interest. */
	memset(&event, 0, sizeof(event));
	event.se_assoc_id = SCTP_ALL_ASSOC;
	event.se_on = 1;
	for (i = 0; i < sizeof(event_types)/sizeof(uint16_t); i++) {
		event.se_type = event_types[i];
		if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) {
			perror("setsockopt SCTP_EVENT");
		}
	}
	memset(&initmsg, 0, sizeof(struct sctp_initmsg));
	initmsg.sinit_num_ostreams = 5;
	initmsg.sinit_max_instreams = 65535;
	if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(struct sctp_initmsg)) < 0) {
		perror("setsockopt SCTP_INITMSG");
	}
	
	if (argc == 5) {
		/* operating as client */
		memset(&addr, 0, sizeof(struct sockaddr_in));
		addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
		addr.sin_len = sizeof(struct sockaddr_in);
#endif
		addr.sin_addr.s_addr = inet_addr(argv[3]);
		addr.sin_port = htons(atoi(argv[4]));
		if (usrsctp_connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
			perror("connect");
		}
		printf("Connected to %s:%d.\n",
		       inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
	} else if (argc == 4) {
		struct socket *conn_sock;

		/* operating as server */
		memset(&addr, 0, sizeof(struct sockaddr_in));
		addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
		addr.sin_len = sizeof(struct sockaddr_in);
#endif
		addr.sin_addr.s_addr = INADDR_ANY;
		addr.sin_port = htons(atoi(argv[3]));
		if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
			perror("bind");
		}
		if (usrsctp_listen(sock, 1) < 0) {
			perror("listen");
		}
		addr_len = (socklen_t)sizeof(struct sockaddr_in);
		memset(&addr, 0, sizeof(struct sockaddr_in));
		if ((conn_sock = usrsctp_accept(sock, (struct sockaddr *)&addr, &addr_len)) == NULL) {
			perror("accept");
		}
		usrsctp_close(sock);
		sock = conn_sock;
		printf("Connected to %s:%d.\n",
		       inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
	} else {
		printf("Usage: %s local_udp_port remote_udp_port local_port when operating as server\n"
		       "       %s local_udp_port remote_udp_port remote_addr remote_port when operating as client\n",
		       argv[0], argv[0]);
		return (0);
	}

	lock_peer_connection(&peer_connection);
	peer_connection.sock = sock;
	unlock_peer_connection(&peer_connection);

	for (;;) {
#ifdef _WIN32
		if (gets_s(line, LINE_LENGTH) == NULL) {
#else
		if (fgets(line, LINE_LENGTH, stdin) == NULL) {
#endif
			if (usrsctp_shutdown(sock, SHUT_WR) < 0) {
				perror("usrsctp_shutdown");
			}
			while (usrsctp_finish() != 0) {
#ifdef _WIN32
				Sleep(1000);
#else
				sleep(1);
#endif
			}
			break;
		}
		if (strncmp(line, "?", strlen("?")) == 0 ||
		    strncmp(line, "help", strlen("help")) == 0) {
			printf("Commands:\n"
			       "open unordered pr_policy pr_value - opens a channel\n"
			       "close channel - closes the channel\n"
			       "send channel:string - sends string using channel\n"
			       "status - prints the status\n"
			       "sleep n - sleep for n seconds\n"
			       "help - this message\n");
		} else if (strncmp(line, "status", strlen("status")) == 0) {
			lock_peer_connection(&peer_connection);
			print_status(&peer_connection);
			unlock_peer_connection(&peer_connection);
		} else if (strncmp(line, "quit", strlen("quit")) == 0) {
			if (usrsctp_shutdown(sock, SHUT_WR) < 0) {
				perror("usrsctp_shutdown");
			}
			while (usrsctp_finish() != 0) {
#ifdef _WIN32
				Sleep(1000);
#else
				sleep(1);
#endif
			}
			break;
		} else if (sscanf(line, "open %u %u %u", &unordered, &policy, &value) == 3) {
			lock_peer_connection(&peer_connection);
			channel = open_channel(&peer_connection, (uint8_t)unordered, (uint16_t)policy, (uint32_t)value);
			unlock_peer_connection(&peer_connection);
			if (channel == NULL) {
				printf("Creating channel failed.\n");
			} else {
				printf("Channel with id %u created.\n", channel->id);
			}
		} else if (sscanf(line, "close %u", &id) == 1) {
			if (id < NUMBER_OF_CHANNELS) {
				lock_peer_connection(&peer_connection);
				close_channel(&peer_connection, &peer_connection.channels[id]);
				unlock_peer_connection(&peer_connection);
			}
		} else if (sscanf(line, "send %u", &id) == 1) {
			if (id < NUMBER_OF_CHANNELS) {
				char *msg;

				msg = strstr(line, ":");
				if (msg) {
					msg++;
					lock_peer_connection(&peer_connection);
#ifdef _WIN32
					if (send_user_message(&peer_connection, &peer_connection.channels[id], msg, strlen(msg))) {
#else
					if (send_user_message(&peer_connection, &peer_connection.channels[id], msg, strlen(msg) - 1)) {
#endif
						printf("Message sent.\n");
					} else {
						printf("Message sending failed.\n");
					}
					unlock_peer_connection(&peer_connection);
				}
			}
		} else if (sscanf(line, "sleep %u", &seconds) == 1) {
#ifdef _WIN32
			Sleep(seconds * 1000);
#else
			sleep(seconds);
#endif
		} else {
			printf("Unknown command: %s", line);
		}
	}
	return (0);
}
int
main(int argc, char *argv[])
{
	struct socket *sock;
	struct sockaddr_in6 addr;
	struct sctp_udpencaps encaps;
	struct sctp_event event;
	uint16_t event_types[] = {SCTP_ASSOC_CHANGE,
	                          SCTP_PEER_ADDR_CHANGE,
	                          SCTP_REMOTE_ERROR,
	                          SCTP_SHUTDOWN_EVENT,
	                          SCTP_ADAPTATION_INDICATION,
	                          SCTP_PARTIAL_DELIVERY_EVENT};
	unsigned int i;
	struct sctp_assoc_value av;
	const int on = 1;
	ssize_t n;
	int flags;
	socklen_t from_len;
	char buffer[BUFFER_SIZE];
	char name[INET6_ADDRSTRLEN];
	socklen_t infolen;
	struct sctp_rcvinfo rcv_info;
	unsigned int infotype;

	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 ((sock = usrsctp_socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, use_cb?receive_cb:NULL, NULL, 0, NULL)) == NULL) {
		perror("usrsctp_socket");
	}
	if (usrsctp_setsockopt(sock, 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(sock, IPPROTO_SCTP, SCTP_CONTEXT, (const void*)&av, (socklen_t)sizeof(struct sctp_assoc_value)) < 0) {
		perror("usrsctp_setsockopt SCTP_CONTEXT");
	}
	if (usrsctp_setsockopt(sock, 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(sock, 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");
		}
	}
	memset(&event, 0, sizeof(event));
	event.se_assoc_id = SCTP_FUTURE_ASSOC;
	event.se_on = 1;
	for (i = 0; i < (unsigned int)(sizeof(event_types)/sizeof(uint16_t)); i++) {
		event.se_type = event_types[i];
		if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event)) < 0) {
			perror("usrsctp_setsockopt SCTP_EVENT");
		}
	}
	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(9);
	addr.sin6_addr = in6addr_any;
	if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0) {
		perror("usrsctp_bind");
	}
	if (usrsctp_listen(sock, 1) < 0) {
		perror("usrsctp_listen");
	}
	while (1) {
		if (use_cb) {
#ifdef _WIN32
			Sleep(1*1000);
#else
			sleep(1);
#endif
		} else {
			from_len = (socklen_t)sizeof(struct sockaddr_in6);
			flags = 0;
			infolen = (socklen_t)sizeof(struct sctp_rcvinfo);
			n = usrsctp_recvv(sock, (void*)buffer, BUFFER_SIZE, (struct sockaddr *) &addr, &from_len, (void *)&rcv_info,
			                  &infolen, &infotype, &flags);
			if (n > 0) {
				if (flags & MSG_NOTIFICATION) {
					printf("Notification of length %llu received.\n", (unsigned long long)n);
				} else {
					if (infotype == SCTP_RECVV_RCVINFO) {
						printf("Msg of length %llu received from %s:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u, complete %d.\n",
						        (unsigned long long)n,
						        inet_ntop(AF_INET6, &addr.sin6_addr, name, INET6_ADDRSTRLEN), ntohs(addr.sin6_port),
						        rcv_info.rcv_sid,
						        rcv_info.rcv_ssn,
						        rcv_info.rcv_tsn,
						        ntohl(rcv_info.rcv_ppid),
						        rcv_info.rcv_context,
						        (flags & MSG_EOR) ? 1 : 0);
					} else {
						printf("Msg of length %llu received from %s:%u, complete %d.\n",
						        (unsigned long long)n,
						        inet_ntop(AF_INET6, &addr.sin6_addr, name, INET6_ADDRSTRLEN), ntohs(addr.sin6_port),
						        (flags & MSG_EOR) ? 1 : 0);
					}
				}
			} else {
				break;
			}
		}
	}
	usrsctp_close(sock);
	while (usrsctp_finish() != 0) {
#ifdef _WIN32
		Sleep(1000);
#else
		sleep(1);
#endif
	}
	return (0);
}
Example #4
0
int main(int argc, char **argv)
{
#ifndef _WIN32
	int c;
#endif
	socklen_t addr_len;
	struct sockaddr_in local_addr;
	struct timeval start_time, now, diff_time;
	int client;
	uint16_t local_port, remote_port, port, local_udp_port, remote_udp_port;
	double seconds;
	double throughput;
	int nodelay = 0;
	struct sctp_assoc_value av;
	struct sctp_udpencaps encaps;
	struct sctp_sndinfo sndinfo;
#ifdef _WIN32
	HANDLE tid;
#else
	pthread_t tid;
#endif
	int fragpoint = 0;
	unsigned int runtime = 0;
	struct sctp_setadaptation ind = {0};
#ifdef _WIN32
	char *opt;
	int optind;
#endif
	unordered = 0;
	/*struct sctp_prinfo prinfo;
	struct sctp_sendv_spa spa;*/

	length = DEFAULT_LENGTH;
	number_of_messages = DEFAULT_NUMBER_OF_MESSAGES;
	port = DEFAULT_PORT;
	remote_udp_port = 0;
	local_udp_port = 9899;
	verbose = 0;
	very_verbose = 0;

	memset((void *) &remote_addr, 0, sizeof(struct sockaddr_in));
	memset((void *) &local_addr, 0, sizeof(struct sockaddr_in));

#ifndef _WIN32
	while ((c = getopt(argc, argv, "a:cp:l:E:f:n:T:uU:vVD")) != -1)
		switch(c) {
			case 'a':
				ind.ssb_adaptation_ind = atoi(optarg);
				break;
			case 'c':
				use_cb = 1;
				break;
			case 'l':
				length = atoi(optarg);
				break;
			case 'n':
				number_of_messages = atoi(optarg);
				break;
			case 'p':
				port = atoi(optarg);
				break;
			case 'E':
				local_udp_port = atoi(optarg);
				break;
			case 'f':
				fragpoint = atoi(optarg);
				break;
			case 'T':
				runtime = atoi(optarg);
				number_of_messages = 0;
				break;
			case 'u':
				unordered = 1;
				break;
			case 'U':
				remote_udp_port = atoi(optarg);
				break;
			case 'v':
				verbose = 1;
				break;
			case 'V':
				verbose = 1;
				very_verbose = 1;
				break;
			case 'D':
				nodelay = 1;
				break;
			default:
				fprintf(stderr, "%s", Usage);
				exit(1);
		}
#else
	for (optind = 1; optind < argc; optind++) {
		if (argv[optind][0] == '-') {
			switch (argv[optind][1]) {
				case 'a':
					if (++optind >= argc) {
						printf("%s", Usage);
						exit(1);
					}
					opt = argv[optind];
					ind.ssb_adaptation_ind = atoi(opt);
					break;
				case 'c':
					use_cb = 1;
					break;
				case 'l':
					if (++optind >= argc) {
						printf("%s", Usage);
						exit(1);
					}
					opt = argv[optind];
					length = atoi(opt);
					break;
				case 'p':
					if (++optind >= argc) {
						printf("%s", Usage);
						exit(1);
					}
					opt = argv[optind];
					port = atoi(opt);
					break;
				case 'n':
					if (++optind >= argc) {
						printf("%s", Usage);
						exit(1);
					}
					opt = argv[optind];
					number_of_messages = atoi(opt);
					break;
				case 'f':
					if (++optind >= argc) {
						printf("%s", Usage);
						exit(1);
					}
					opt = argv[optind];
					fragpoint = atoi(opt);
					break;
				case 'U':
					if (++optind >= argc) {
						printf("%s", Usage);
						exit(1);
					}
					opt = argv[optind];
					remote_udp_port = atoi(opt);
					break;
				case 'E':
					if (++optind >= argc) {
						printf("%s", Usage);
						exit(1);
					}
					opt = argv[optind];
					local_udp_port = atoi(opt);
					break;
				case 'T':
					if (++optind >= argc) {
						printf("%s", Usage);
						exit(1);
					}
					opt = argv[optind];
					runtime = atoi(opt);
					number_of_messages = 0;
					break;
				case 'u':
					unordered = 1;
					break;
				case 'v':
					verbose = 1;
					break;
				case 'V':
					verbose = 1;
					very_verbose = 1;
					break;
				case 'D':
					nodelay = 1;
					break;
				default:
					printf("%s", Usage);
					exit(1);
			}
		} else {
			break;
		}
	}
#endif
	if (optind == argc) {
		client = 0;
		local_port = port;
		remote_port = 0;
	} else {
		client = 1;
		local_port = 0;
		remote_port = port;
	}
	local_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
	local_addr.sin_len = sizeof(struct sockaddr_in);
#endif
	local_addr.sin_port = htons(local_port);
	local_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	usrsctp_init(local_udp_port, NULL, debug_printf);
#ifdef SCTP_DEBUG
	usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
#endif
	usrsctp_sysctl_set_sctp_blackhole(2);

	if (client) {
		if (use_cb) {
			if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, receive_cb, send_cb, length, NULL)) ){
				printf("user_socket() returned NULL\n");
				exit(1);
			}
		} else {
			if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL)) ){
				printf("user_socket() returned NULL\n");
				exit(1);
			}
		}
	} else {
		if (use_cb) {
			if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, NULL)) ){
				printf("user_socket() returned NULL\n");
				exit(1);
			}
		} else {
			if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL)) ){
				printf("user_socket() returned NULL\n");
				exit(1);
			}
		}
	}

	if (usrsctp_bind(psock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_in)) == -1) {
		printf("usrsctp_bind failed.\n");
		exit(1);
	}

	if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, (const void*)&ind, (socklen_t)sizeof(struct sctp_setadaptation)) < 0) {
		perror("setsockopt");
	}

	if (!client) {
		if (usrsctp_listen(psock, 1) < 0) {
			printf("usrsctp_listen failed.\n");
			exit(1);
		}

		while (1) {
			memset(&remote_addr, 0, sizeof(struct sockaddr_in));
			addr_len = sizeof(struct sockaddr_in);
			if (use_cb) {
				struct socket *conn_sock;

				if ((conn_sock = usrsctp_accept(psock, (struct sockaddr *) &remote_addr, &addr_len))== NULL) {
					printf("usrsctp_accept failed.  exiting...\n");
					continue;
				}
			} else {
				struct socket **conn_sock;

				conn_sock = (struct socket **)malloc(sizeof(struct socket *));
				if ((*conn_sock = usrsctp_accept(psock, (struct sockaddr *) &remote_addr, &addr_len))== NULL) {
					printf("usrsctp_accept failed.  exiting...\n");
					continue;
				}
#ifdef _WIN32
				tid = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&handle_connection, (void *)conn_sock, 0, NULL);
#else
				pthread_create(&tid, NULL, &handle_connection, (void *)conn_sock);
#endif
			}
			if (verbose)
				printf("Connection accepted from %s:%d\n", inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port));
		}
		usrsctp_close(psock);
	} else {
		memset(&encaps, 0, sizeof(struct sctp_udpencaps));
		encaps.sue_address.ss_family = AF_INET;
		encaps.sue_port = htons(remote_udp_port);
		if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
			perror("setsockopt");
		}

		remote_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
		remote_addr.sin_len = sizeof(struct sockaddr_in);
#endif
		remote_addr.sin_addr.s_addr = inet_addr(argv[optind]);
		remote_addr.sin_port = htons(remote_port);

		/* TODO fragpoint stuff */
		if (nodelay == 1) {
			optval = 1;
		} else {
			optval = 0;
		}
		usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_NODELAY, &optval, sizeof(int));

		if (fragpoint) {
			av.assoc_id = 0;
			av.assoc_value = fragpoint;
			if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_MAXSEG, &av, sizeof(struct sctp_assoc_value)) < 0)
				perror("setsockopt: SCTP_MAXSEG");
		}

		if (usrsctp_connect(psock, (struct sockaddr *) &remote_addr, sizeof(struct sockaddr_in)) == -1 ) {
			printf("usrsctpconnect failed.  exiting...\n");
			exit(1);
		}

		buffer = malloc(length);
		memset(buffer, 'b', length);
		gettimeofday(&start_time, NULL);
		if (verbose) {
			printf("Start sending %ld messages...\n", (long)number_of_messages);
			fflush(stdout);
		}

		done = 0;

		if (runtime > 0) {
#ifndef _WIN32
			signal(SIGALRM, stop_sender);
			alarm(runtime);
#else
			printf("You cannot set the runtime in Windows yet\n");
			exit(-1);
#endif
		}

		messages = 0;

		sndinfo.snd_sid = 0;
		sndinfo.snd_flags = 0;
		sndinfo.snd_ppid = 0;
		sndinfo.snd_context = 0;
		sndinfo.snd_assoc_id = 0;

	/*prinfo.pr_policy = SCTP_PR_SCTP_RTX;
		prinfo.pr_value = 2;
		spa.sendv_sndinfo = sndinfo;
		spa.sendv_prinfo = prinfo;
		spa.sendv_flags = SCTP_SEND_SNDINFO_VALID | SCTP_SEND_PRINFO_VALID;*/

		if (use_cb) {
			if (very_verbose)
				printf("Sending message number %lu.\n", messages);

				if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1,
				                  (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO,
				                  unordered?SCTP_UNORDERED:0) < 0) {
				perror("usrctp_sendv returned < 0");
				exit(1);
			}
			messages++;
			while (!done && (messages < (number_of_messages - 1))) {
#ifdef _WIN32
				Sleep(1000);
#else
				sleep(1);
#endif
			}
		} else {
			while (!done && ((number_of_messages == 0) || (messages < (number_of_messages - 1)))) {
				if (very_verbose)
					printf("Sending message number %lu.\n", messages + 1);

				if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1,
				                  (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO,
				                  unordered?SCTP_UNORDERED:0) < 0) {
					perror("usrsctp_sendv returned < 0");
					exit(1);
				}
				messages++;
			}
			if (very_verbose)
				printf("Sending message number %lu.\n", messages + 1);

			if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1,
			                  (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO,
			                  unordered?SCTP_UNORDERED:0) < 0) {
				perror("final usrsctp_sendv returned\n");
				exit(1);
			}
			messages++;
		}
		free (buffer);
		if (verbose)
			printf("done.\n");

		usrsctp_close(psock);
		gettimeofday(&now, NULL);
		timersub(&now, &start_time, &diff_time);
		seconds = diff_time.tv_sec + (double)diff_time.tv_usec/1000000;
		printf("%s of %ld messages of length %u took %f seconds.\n",
		       "Sending", messages, length, seconds);
		throughput = (double)messages * (double)length / seconds;
		printf("Throughput was %f Byte/sec.\n", throughput);
	}

	while (usrsctp_finish() != 0) {
#ifdef _WIN32
		Sleep(1000);
#else
		sleep(1);
#endif
	}
	return 0;
}
Example #5
0
int main(int argc, char **argv)
{
#ifndef _WIN32
    int c;
#endif
    socklen_t addr_len;
    struct sockaddr_in local_addr;
    struct timeval start_time, now, diff_time;
    int client;
    uint16_t local_port, remote_port, port, local_udp_port, remote_udp_port;
    int rcvbufsize=0, sndbufsize=0, myrcvbufsize, mysndbufsize;
    socklen_t intlen;
    double seconds;
    double throughput;
    int nodelay = 0;
    struct sctp_assoc_value av;
    struct sctp_udpencaps encaps;
    struct sctp_sndinfo sndinfo;
#ifdef _WIN32
    unsigned long srcAddr;
    HANDLE tid;
#else
    in_addr_t srcAddr;
    pthread_t tid;
#endif
    int fragpoint = 0;
    struct sctp_setadaptation ind = {0};
#ifdef _WIN32
    char *opt;
    int optind;
#endif
    unordered = 0;

    length = DEFAULT_LENGTH;
    number_of_messages = DEFAULT_NUMBER_OF_MESSAGES;
    port = DEFAULT_PORT;
    remote_udp_port = 0;
    local_udp_port = 9899;
    verbose = 0;
    very_verbose = 0;
    srcAddr = htonl(INADDR_ANY);

    memset((void *) &remote_addr, 0, sizeof(struct sockaddr_in));
    memset((void *) &local_addr, 0, sizeof(struct sockaddr_in));

#ifndef _WIN32
    while ((c = getopt(argc, argv, "a:cp:l:E:f:L:n:R:S:T:uU:vVD")) != -1)
        switch(c) {
        case 'a':
            ind.ssb_adaptation_ind = atoi(optarg);
            break;
        case 'c':
            use_cb = 1;
            break;
        case 'l':
            length = atoi(optarg);
            break;
        case 'n':
            number_of_messages = atoi(optarg);
            break;
        case 'p':
            port = atoi(optarg);
            break;
        case 'E':
            local_udp_port = atoi(optarg);
            break;
        case 'f':
            fragpoint = atoi(optarg);
            break;
        case 'L':
            inet_pton(AF_INET, optarg, &srcAddr);
            break;
        case 'R':
            rcvbufsize = atoi(optarg);
            break;
        case 'S':
            sndbufsize = atoi(optarg);
            break;
        case 'T':
            runtime = atoi(optarg);
            number_of_messages = 0;
            break;
        case 'u':
            unordered = 1;
            break;
        case 'U':
            remote_udp_port = atoi(optarg);
            break;
        case 'v':
            verbose = 1;
            break;
        case 'V':
            verbose = 1;
            very_verbose = 1;
            break;
        case 'D':
            nodelay = 1;
            break;
        default:
            fprintf(stderr, "%s", Usage);
            exit(1);
        }
#else
    for (optind = 1; optind < argc; optind++) {
        if (argv[optind][0] == '-') {
            switch (argv[optind][1]) {
            case 'a':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                ind.ssb_adaptation_ind = atoi(opt);
                break;
            case 'c':
                use_cb = 1;
                break;
            case 'l':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                length = atoi(opt);
                break;
            case 'p':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                port = atoi(opt);
                break;
            case 'n':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                number_of_messages = atoi(opt);
                break;
            case 'f':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                fragpoint = atoi(opt);
                break;
            case 'L':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                inet_pton(AF_INET, opt, &srcAddr);
                break;
            case 'U':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                remote_udp_port = atoi(opt);
                break;
            case 'E':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                local_udp_port = atoi(opt);
                break;
            case 'R':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                rcvbufsize = atoi(opt);
                break;
            case 'S':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                sndbufsize = atoi(opt);
                break;
            case 'T':
                if (++optind >= argc) {
                    printf("%s", Usage);
                    exit(1);
                }
                opt = argv[optind];
                runtime = atoi(opt);
                number_of_messages = 0;
                break;
            case 'u':
                unordered = 1;
                break;
            case 'v':
                verbose = 1;
                break;
            case 'V':
                verbose = 1;
                very_verbose = 1;
                break;
            case 'D':
                nodelay = 1;
                break;
            default:
                printf("%s", Usage);
                exit(1);
            }
        } else {
            break;
        }
    }
#endif
    if (optind == argc) {
        client = 0;
        local_port = port;
        remote_port = 0;
    } else {
        client = 1;
        local_port = 0;
        remote_port = port;
    }
    local_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
    local_addr.sin_len = sizeof(struct sockaddr_in);
#endif
    local_addr.sin_port = htons(local_port);
    local_addr.sin_addr.s_addr = srcAddr;

    usrsctp_init(local_udp_port, NULL, debug_printf);
#ifdef SCTP_DEBUG
    usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
#endif
    usrsctp_sysctl_set_sctp_blackhole(2);
    usrsctp_sysctl_set_sctp_enable_sack_immediately(1);

    if (client) {
        if (use_cb) {
            if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, client_receive_cb, send_cb, length, NULL))) {
                perror("user_socket");
                exit(1);
            }
        } else {
            if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL))) {
                perror("user_socket");
                exit(1);
            }
        }
    } else {
        if (use_cb) {
            if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, server_receive_cb, NULL, 0, NULL))) {
                perror("user_socket");
                exit(1);
            }
        } else {
            if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL))) {
                perror("user_socket");
                exit(1);
            }
        }
    }

    if (usrsctp_bind(psock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_in)) == -1) {
        perror("usrsctp_bind");
        exit(1);
    }

    if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, (const void*)&ind, (socklen_t)sizeof(struct sctp_setadaptation)) < 0) {
        perror("setsockopt");
    }

    if (!client) {
        if (rcvbufsize) {
            if (usrsctp_setsockopt(psock, SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(int)) < 0) {
                perror("setsockopt: rcvbuf");
            }
        }
        if (verbose) {
            intlen = sizeof(int);
            if (usrsctp_getsockopt(psock, SOL_SOCKET, SO_RCVBUF, &myrcvbufsize, (socklen_t *)&intlen) < 0) {
                perror("getsockopt: rcvbuf");
            } else {
                fprintf(stdout,"Receive buffer size: %d.\n", myrcvbufsize);
            }
        }

        if (usrsctp_listen(psock, 1) < 0) {
            perror("usrsctp_listen");
            exit(1);
        }

        while (1) {
            memset(&remote_addr, 0, sizeof(struct sockaddr_in));
            addr_len = sizeof(struct sockaddr_in);
            if (use_cb) {
                struct socket *conn_sock;

                if ((conn_sock = usrsctp_accept(psock, (struct sockaddr *) &remote_addr, &addr_len))== NULL) {
                    perror("usrsctp_accept");
                    continue;
                }
            } else {
                struct socket **conn_sock;

                conn_sock = (struct socket **)malloc(sizeof(struct socket *));
                if ((*conn_sock = usrsctp_accept(psock, (struct sockaddr *) &remote_addr, &addr_len))== NULL) {
                    perror("usrsctp_accept");
                    continue;
                }
#ifdef _WIN32
                tid = CreateThread(NULL, 0, &handle_connection, (void *)conn_sock, 0, NULL);
#else
                pthread_create(&tid, NULL, &handle_connection, (void *)conn_sock);
#endif
            }
            if (verbose) {
                // const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
                //inet_ntoa(remote_addr.sin_addr)
                char addrbuf[INET_ADDRSTRLEN];
                printf("Connection accepted from %s:%d\n", inet_ntop(AF_INET, &(remote_addr.sin_addr), addrbuf, INET_ADDRSTRLEN), ntohs(remote_addr.sin_port));
            }
        }
        usrsctp_close(psock);
    } else {
        memset(&encaps, 0, sizeof(struct sctp_udpencaps));
        encaps.sue_address.ss_family = AF_INET;
        encaps.sue_port = htons(remote_udp_port);
        if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
            perror("setsockopt");
        }

        remote_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
        remote_addr.sin_len = sizeof(struct sockaddr_in);
#endif
        if (!inet_pton(AF_INET, argv[optind], &remote_addr.sin_addr.s_addr)) {
            printf("error: invalid destination address\n");
            exit(1);
        }
        remote_addr.sin_port = htons(remote_port);

        /* TODO fragpoint stuff */
        if (nodelay == 1) {
            optval = 1;
        } else {
            optval = 0;
        }
        usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_NODELAY, &optval, sizeof(int));

        if (fragpoint) {
            av.assoc_id = 0;
            av.assoc_value = fragpoint;
            if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_MAXSEG, &av, sizeof(struct sctp_assoc_value)) < 0) {
                perror("setsockopt: SCTP_MAXSEG");
            }
        }

        if (sndbufsize) {
            if (usrsctp_setsockopt(psock, SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(int)) < 0) {
                perror("setsockopt: sndbuf");
            }
        }
        if (verbose) {
            intlen = sizeof(int);
            if (usrsctp_getsockopt(psock, SOL_SOCKET, SO_SNDBUF, &mysndbufsize, (socklen_t *)&intlen) < 0) {
                perror("setsockopt: SO_SNDBUF");
            } else {
                fprintf(stdout,"Send buffer size: %d.\n", mysndbufsize);
            }
        }

        buffer = malloc(length);
        memset(buffer, 'b', length);

        if (usrsctp_connect(psock, (struct sockaddr *) &remote_addr, sizeof(struct sockaddr_in)) == -1 ) {
            perror("usrsctp_connect");
            exit(1);
        }

        gettimeofday(&start_time, NULL);

        done = 0;

        if (runtime > 0) {
#ifndef _WIN32
            signal(SIGALRM, stop_sender);
            alarm(runtime);
#else
            printf("You cannot set the runtime in Windows yet\n");
            exit(-1);
#endif
        }

        if (use_cb) {
            while (!done && (messages < (number_of_messages - 1))) {
#ifdef _WIN32
                Sleep(1000);
#else
                sleep(1);
#endif
            }
        } else {
            sndinfo.snd_sid = 0;
            sndinfo.snd_flags = 0;
            if (unordered != 0) {
                sndinfo.snd_flags |= SCTP_UNORDERED;
            }
            sndinfo.snd_ppid = 0;
            sndinfo.snd_context = 0;
            sndinfo.snd_assoc_id = 0;
            if (verbose) {
                printf("Start sending ");
                if (number_of_messages > 0) {
                    printf("%ld messages ", (long)number_of_messages);
                }
                if (runtime > 0) {
                    printf("for %u seconds ...", runtime);
                }
                printf("\n");
                fflush(stdout);
            }
            while (!done && ((number_of_messages == 0) || (messages < (number_of_messages - 1)))) {
                if (very_verbose) {
                    printf("Sending message number %lu.\n", messages + 1);
                }

                if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1,
                                  (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO,
                                  0) < 0) {
                    perror("usrsctp_sendv");
                    exit(1);
                }
                messages++;
            }
            if (very_verbose) {
                printf("Sending message number %lu.\n", messages + 1);
            }

            sndinfo.snd_flags |= SCTP_EOF;
            if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1,
                              (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO,
                              0) < 0) {
                perror("usrsctp_sendv");
                exit(1);
            }
            messages++;
        }
        free (buffer);

        if (verbose) {
            printf("Closing socket.\n");
        }

        usrsctp_close(psock);
        gettimeofday(&now, NULL);
        timersub(&now, &start_time, &diff_time);
        seconds = diff_time.tv_sec + (double)diff_time.tv_usec/1000000;
        printf("%s of %ld messages of length %u took %f seconds.\n",
               "Sending", messages, length, seconds);
        throughput = (double)messages * (double)length / seconds;
        printf("Throughput was %f Byte/sec.\n", throughput);
    }

    while (usrsctp_finish() != 0) {
#ifdef _WIN32
        Sleep(1000);
#else
        sleep(1);
#endif
    }
    return 0;
}
Example #6
0
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;
#ifdef _WIN32
	HANDLE tid;
#else
	pthread_t tid;
#endif
	struct sctp_sndinfo sndinfo;
	char buffer[BUFFER_SIZE];
#ifdef _WIN32
	WSADATA wsaData;
#endif

	if (argc < 4) {
		printf("error: this program requires 4 arguments!\n");
		exit(EXIT_FAILURE);
	}

#ifdef _WIN32
	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
		printf("WSAStartup failed\n");
		exit (EXIT_FAILURE);
	}
#endif
	usrsctp_init(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: %d\n", WSAGetLastError());
	}
#else
	if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
		perror("socket");
	}
#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: %d\n", WSAGetLastError());
	}
#else
	if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) {
		perror("bind");
	}
#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: %d\n", WSAGetLastError());
	}
#else
	if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) {
		perror("connect");
	}
#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);
#ifdef _WIN32
	tid = CreateThread(NULL, 0, &handle_packets, (void *)&fd, 0, NULL);
#else
	pthread_create(&tid, NULL, &handle_packets, (void *)&fd);
#endif
	if ((s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd)) == NULL) {
		perror("usrsctp_socket");
	}

	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(5001);
	sconn.sconn_addr = &fd;
	if (usrsctp_connect(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
		perror("usrsctp_connect");
	}
	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");
	}

	usrsctp_shutdown(s, SHUT_WR);
	while (usrsctp_finish() != 0) {
#ifdef _WIN32
		Sleep(1000);
#else
		sleep(1);
#endif
	}
#ifdef _WIN32
	TerminateThread(tid, 0);
	WaitForSingleObject(tid, INFINITE);
	if (closesocket(fd) == SOCKET_ERROR) {
		printf("closesocket() failed with error: %d\n", WSAGetLastError());
	}
	WSACleanup();
#else
	pthread_cancel(tid);
	pthread_join(tid, NULL);
	if (close(fd) < 0) {
		perror("close");
	}
#endif
	return (0);
}
Example #7
0
int
main(void)
{
	struct sockaddr_in sin_s, sin_c;
	struct sockaddr_conn sconn;
#ifdef _WIN32
	SOCKET fd_c, fd_s;
#else
	int fd_c, fd_s;
#endif
	struct socket *s_c, *s_s, *s_l;
#ifdef _WIN32
	HANDLE tid_c, tid_s;
#else
	pthread_t tid_c, tid_s;
#endif
	int cur_buf_size, snd_buf_size, rcv_buf_size;
	socklen_t opt_len;
	struct sctp_sndinfo sndinfo;
	char *line;
#ifdef _WIN32
	WSADATA wsaData;
#endif

#ifdef _WIN32
	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
		printf("WSAStartup failed\n");
		exit (EXIT_FAILURE);
	}
#endif
	usrsctp_init(0, conn_output, debug_printf);
	/* set up a connected UDP socket */
#ifdef _WIN32
	if ((fd_c = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
		printf("socket() failed with error: %d\n", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
	if ((fd_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
		printf("socket() failed with error: %d\n", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
#else
	if ((fd_c = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
		perror("socket");
		exit(EXIT_FAILURE);
	}
	if ((fd_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
		perror("socket");
		exit(EXIT_FAILURE);
	}
#endif
	memset(&sin_c, 0, sizeof(struct sockaddr_in));
	sin_c.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
	sin_c.sin_len = sizeof(struct sockaddr_in);
#endif
	sin_c.sin_port = htons(9900);
	sin_c.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	memset(&sin_s, 0, sizeof(struct sockaddr_in));
	sin_s.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
	sin_s.sin_len = sizeof(struct sockaddr_in);
#endif
	sin_s.sin_port = htons(9901);
	sin_s.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
#ifdef _WIN32
	if (bind(fd_c, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
		printf("bind() failed with error: %d\n", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
	if (bind(fd_s, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
		printf("bind() failed with error: %d\n", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
#else
	if (bind(fd_c, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) < 0) {
		perror("bind");
		exit(EXIT_FAILURE);
	}
	if (bind(fd_s, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) < 0) {
		perror("bind");
		exit(EXIT_FAILURE);
	}
#endif
#ifdef _WIN32
	if (connect(fd_c, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
		printf("connect() failed with error: %d\n", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
	if (connect(fd_s, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
		printf("connect() failed with error: %d\n", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
#else
	if (connect(fd_c, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) < 0) {
		perror("connect");
		exit(EXIT_FAILURE);
	}
	if (connect(fd_s, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) < 0) {
		perror("connect");
		exit(EXIT_FAILURE);
	}
#endif
#ifdef _WIN32
	tid_c = CreateThread(NULL, 0, &handle_packets, (void *)&fd_c, 0, NULL);
	tid_s = CreateThread(NULL, 0, &handle_packets, (void *)&fd_s, 0, NULL);
#else
	if (pthread_create(&tid_c, NULL, &handle_packets, (void *)&fd_c)) {
		perror("pthread_create tid_c");
		exit(EXIT_FAILURE);
	}

	if (pthread_create(&tid_s, NULL, &handle_packets, (void *)&fd_s)) {
		perror("pthread_create tid_s");
		exit(EXIT_FAILURE);
	};
#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_c);
	usrsctp_register_address((void *)&fd_s);
	if ((s_c = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd_c)) == NULL) {
		perror("usrsctp_socket");
		exit(EXIT_FAILURE);
	}
	opt_len = (socklen_t)sizeof(int);
	cur_buf_size = 0;
	if (usrsctp_getsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &cur_buf_size, &opt_len) < 0) {
		perror("usrsctp_getsockopt");
		exit(EXIT_FAILURE);
	}
	printf("Change send socket buffer size from %d ", cur_buf_size);
	snd_buf_size = 1<<22; /* 4 MB */
	if (usrsctp_setsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &snd_buf_size, sizeof(int)) < 0) {
		perror("usrsctp_setsockopt");
		exit(EXIT_FAILURE);
	}
	opt_len = (socklen_t)sizeof(int);
	cur_buf_size = 0;
	if (usrsctp_getsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &cur_buf_size, &opt_len) < 0) {
		perror("usrsctp_getsockopt");
		exit(EXIT_FAILURE);
	}
	printf("to %d.\n", cur_buf_size);
	if ((s_l = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd_s)) == NULL) {
		perror("usrsctp_socket");
		exit(EXIT_FAILURE);
	}
	opt_len = (socklen_t)sizeof(int);
	cur_buf_size = 0;
	if (usrsctp_getsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &cur_buf_size, &opt_len) < 0) {
		perror("usrsctp_getsockopt");
		exit(EXIT_FAILURE);
	}
	printf("Change receive socket buffer size from %d ", cur_buf_size);
	rcv_buf_size = 1<<16; /* 64 KB */
	if (usrsctp_setsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &rcv_buf_size, sizeof(int)) < 0) {
		perror("usrsctp_setsockopt");
		exit(EXIT_FAILURE);
	}
	opt_len = (socklen_t)sizeof(int);
	cur_buf_size = 0;
	if (usrsctp_getsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &cur_buf_size, &opt_len) < 0) {
		perror("usrsctp_getsockopt");
		exit(EXIT_FAILURE);
	}
	printf("to %d.\n", cur_buf_size);
	/* Bind the client side. */
	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(5001);
	sconn.sconn_addr = &fd_c;
	if (usrsctp_bind(s_c, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
		perror("usrsctp_bind");
		exit(EXIT_FAILURE);
	}
	/* Bind the server side. */
	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(5001);
	sconn.sconn_addr = &fd_s;
	if (usrsctp_bind(s_l, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
		perror("usrsctp_bind");
		exit(EXIT_FAILURE);
	}
	/* Make server side passive... */
	if (usrsctp_listen(s_l, 1) < 0) {
		perror("usrsctp_listen");
		exit(EXIT_FAILURE);
	}
	/* Initiate the handshake */
	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(5001);
	sconn.sconn_addr = &fd_c;
	if (usrsctp_connect(s_c, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
		perror("usrsctp_connect");
		exit(EXIT_FAILURE);
	}
	if ((s_s = usrsctp_accept(s_l, NULL, NULL)) == NULL) {
		perror("usrsctp_accept");
		exit(EXIT_FAILURE);
	}
	usrsctp_close(s_l);
	if ((line = malloc(LINE_LENGTH)) == NULL) {
		exit(EXIT_FAILURE);
	}
	memset(line, 'A', LINE_LENGTH);
	sndinfo.snd_sid = 1;
	sndinfo.snd_flags = 0;
	sndinfo.snd_ppid = htonl(DISCARD_PPID);
	sndinfo.snd_context = 0;
	sndinfo.snd_assoc_id = 0;
	/* Send a 1 MB ordered message */
	if (usrsctp_sendv(s_c, line, LINE_LENGTH, NULL, 0, (void *)&sndinfo,
	                 (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) {
		perror("usrsctp_sendv");
		exit(EXIT_FAILURE);
	}
	/* Send a 1 MB ordered message */
	if (usrsctp_sendv(s_c, line, LINE_LENGTH, NULL, 0, (void *)&sndinfo,
	                 (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) {
		perror("usrsctp_sendv");
		exit(EXIT_FAILURE);
	}
	free(line);
	usrsctp_shutdown(s_c, SHUT_WR);

	while (usrsctp_finish() != 0) {
#ifdef _WIN32
		Sleep(1000);
#else
		sleep(1);
#endif
	}
#ifdef _WIN32
	TerminateThread(tid_c, 0);
	WaitForSingleObject(tid_c, INFINITE);
	TerminateThread(tid_s, 0);
	WaitForSingleObject(tid_s, INFINITE);
	if (closesocket(fd_c) == SOCKET_ERROR) {
		printf("closesocket() failed with error: %d\n", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
	if (closesocket(fd_s) == SOCKET_ERROR) {
		printf("closesocket() failed with error: %d\n", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
	WSACleanup();
#else
	pthread_cancel(tid_c);
	pthread_join(tid_c, NULL);
	pthread_cancel(tid_s);
	pthread_join(tid_s, NULL);
	if (close(fd_c) < 0) {
		perror("close");
		exit(EXIT_FAILURE);
	}
	if (close(fd_s) < 0) {
		perror("close");
		exit(EXIT_FAILURE);
	}
#endif
	return (0);
}
int
main(int argc, char *argv[])
{
	struct sockaddr_in sin;
	struct sockaddr_conn sconn;
	struct sctp_event event;
	uint16_t event_types[] = {SCTP_ASSOC_CHANGE,
	                          SCTP_PEER_ADDR_CHANGE,
	                          SCTP_SEND_FAILED_EVENT};
	unsigned int i;
#ifdef _WIN32
	SOCKET fd;
#else
	int fd;
#endif
	struct socket *s;
#ifdef _WIN32
	HANDLE tid;
#else
	pthread_t tid;
#endif
	struct sctp_sndinfo sndinfo;
	char line[LINE_LENGTH];

	usrsctp_init(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());
	}
#else
	if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
		perror("socket");
	}
#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]));
	sin.sin_addr.s_addr = inet_addr(argv[1]);
#ifdef _WIN32
	if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
		printf("bind() failed with error: %ld\n", WSAGetLastError());
	}
#else
	if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) {
		perror("bind");
	}
#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]));
	sin.sin_addr.s_addr = inet_addr(argv[3]);
#ifdef _WIN32
	if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
		printf("connect() failed with error: %ld\n", WSAGetLastError());
	}
#else
	if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) {
		perror("connect");
	}
#endif
#ifdef _WIN32
	tid = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&handle_packets, (void *)&fd, 0, NULL);
#else
	pthread_create(&tid, NULL, &handle_packets, (void *)&fd);
#endif
#ifdef SCTP_DEBUG
	usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
#endif
	usrsctp_register_address((void *)&fd);
	usrsctp_sysctl_set_sctp_ecn_enable(0);
	if ((s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd)) == NULL) {
		perror("usrsctp_socket");
	}
	/* Enable the events of interest. */
	if (usrsctp_set_non_blocking(s, 1) < 0) {
		perror("usrsctp_set_non_blocking");
	}
	memset(&event, 0, sizeof(event));
	event.se_assoc_id = SCTP_ALL_ASSOC;
	event.se_on = 1;
	for (i = 0; i < sizeof(event_types)/sizeof(uint16_t); i++) {
		event.se_type = event_types[i];
		if (usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) {
			perror("setsockopt SCTP_EVENT");
		}
	}
	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;
	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[6]));
	sconn.sconn_addr = &fd;
	if (usrsctp_connect(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
		perror("usrsctp_connect");
	}
	for (;;) {
#ifdef _WIN32
		if (gets_s(line, LINE_LENGTH) == NULL) {
#else
		if (fgets(line, LINE_LENGTH, stdin) == NULL) {
#endif
			if (usrsctp_shutdown(s, SHUT_WR) < 0) {
				perror("usrsctp_shutdown");
			}
			while (usrsctp_finish() != 0) {
#ifdef _WIN32
				Sleep(1000);
#else
				sleep(1);
#endif
			}
			break;
		}
		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, line, strlen(line), NULL, 0, (void *)&sndinfo,
	                          (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) {
			perror("usrsctp_sendv");
		}
	}
	return (0);
}