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); }
struct sctp_transport * create_sctp_transport(struct rtcdc_peer_connection *peer) { if (peer == NULL || peer->transport == NULL) return NULL; struct sctp_transport *sctp = (struct sctp_transport *)calloc(1, sizeof *sctp); if (sctp == NULL) return NULL; peer->transport->sctp = sctp; sctp->local_port = random_integer(10000, 60000); if (g_sctp_ref == 0) { usrsctp_init(0, sctp_data_ready_cb, NULL); usrsctp_sysctl_set_sctp_ecn_enable(1); } g_sctp_ref++; usrsctp_register_address(sctp); struct socket *s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, sctp_data_received_cb, NULL, 0, peer); if (s == NULL) goto trans_err; sctp->sock = s; BIO *bio = BIO_new(BIO_s_mem()); if (bio == NULL) goto trans_err; BIO_set_mem_eof_return(bio, -1); sctp->incoming_bio = bio; bio = BIO_new(BIO_s_mem()); if (bio == NULL) goto trans_err; BIO_set_mem_eof_return(bio, -1); sctp->outgoing_bio = bio; #ifdef DEBUG_SCTP int sd; struct sockaddr_in stub_addr; memset(&stub_addr, 0, sizeof stub_addr); inet_pton(AF_INET, "127.0.0.1", &stub_addr.sin_addr); stub_addr.sin_family = AF_INET; sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); stub_addr.sin_port = htons(60001); bind(sd, (const struct sockaddr *)&stub_addr, sizeof stub_addr); stub_addr.sin_port = htons(60002); connect(sd, (const struct sockaddr *)&stub_addr, sizeof stub_addr); sctp->incoming_stub = sd; sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); stub_addr.sin_port = htons(60002); bind(sd, (const struct sockaddr *)&stub_addr, sizeof stub_addr); stub_addr.sin_port = htons(60001); connect(sd, (const struct sockaddr *)&stub_addr, sizeof stub_addr); sctp->outgoing_stub = sd; #endif struct linger lopt; lopt.l_onoff = 1; lopt.l_linger = 0; usrsctp_setsockopt(s, SOL_SOCKET, SO_LINGER, &lopt, sizeof lopt); struct sctp_paddrparams peer_param; memset(&peer_param, 0, sizeof peer_param); peer_param.spp_flags = SPP_PMTUD_DISABLE; peer_param.spp_pathmtu = 1200; usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &peer_param, sizeof peer_param); struct sctp_assoc_value av; av.assoc_id = SCTP_ALL_ASSOC; av.assoc_value = 1; usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, &av, sizeof av); uint32_t nodelay = 1; usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof nodelay); struct sctp_initmsg init_msg; memset(&init_msg, 0, sizeof init_msg); init_msg.sinit_num_ostreams = RTCDC_MAX_OUT_STREAM; init_msg.sinit_max_instreams = RTCDC_MAX_IN_STREAM; usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_INITMSG, &init_msg, sizeof init_msg); struct sockaddr_conn sconn; memset(&sconn, 0, sizeof sconn); sconn.sconn_family = AF_CONN; sconn.sconn_port = htons(sctp->local_port); sconn.sconn_addr = (void *)sctp; #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) sconn.sconn_len = sizeof *sctp; #endif usrsctp_bind(s, (struct sockaddr *)&sconn, sizeof sconn); sctp->deferred_messages = g_async_queue_new(); // modified by uniray7 sctp->peer = peer; //==================== if (0) { trans_err: peer->transport->sctp = NULL; usrsctp_finish(); free(sctp); sctp = NULL; } return sctp; }
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; }
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; }
/* * Class: net_tomp2p_sctp_core_Sctp * Method: usrsctp_socket * Signature: (I)J */ JNIEXPORT jlong JNICALL Java_net_tomp2p_sctp_core_Sctp_usrsctp_1socket (JNIEnv *env, jclass clazz, jint localPort) { SctpSocket *sctpSocket; struct socket *so; struct linger linger_opt; struct sctp_assoc_value stream_rst; uint32_t nodelay = 1; size_t i, eventTypeCount; struct sctp_event ev; sctpSocket = malloc(sizeof(SctpSocket)); if (sctpSocket == NULL) { perror("Out of memory!"); return 0; } // Register this class as an address for usrsctp. This is used by SCTP to // direct the packets received (by the created socket) to this class. usrsctp_register_address(sctpSocket); so = usrsctp_socket( AF_CONN, SOCK_STREAM, IPPROTO_SCTP, onSctpInboundPacket, /* send_cb */ NULL, /* sb_threshold */ 0, sctpSocket); if (so == NULL) { perror("usrsctp_socket"); free(sctpSocket); return 0; } // Make the socket non-blocking. Connect, close, shutdown etc will not block // the thread waiting for the socket operation to complete. if (usrsctp_set_non_blocking(so, 1) < 0) { perror("Failed to set SCTP to non blocking."); free(sctpSocket); return 0; } // This ensures that the usrsctp close call deletes the association. This // prevents usrsctp from calling onSctpOutboundPacket with references to // this class as the address. linger_opt.l_onoff = 1; linger_opt.l_linger = 0; if (usrsctp_setsockopt(so, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt))) { perror("Failed to set SO_LINGER."); free(sctpSocket); return 0; } // Enable stream ID resets. stream_rst.assoc_id = SCTP_ALL_ASSOC; stream_rst.assoc_value = 1; if (usrsctp_setsockopt(so, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, &stream_rst, sizeof(stream_rst))) { perror("Failed to set SCTP_ENABLE_STREAM_RESET."); free(sctpSocket); return 0; } // Nagle. if (usrsctp_setsockopt(so, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay))) { perror("Failed to set SCTP_NODELAY."); free(sctpSocket); return 0; } // Subscribe to SCTP events. eventTypeCount = sizeof(SCTP_EVENT_TYPES) / sizeof(int); memset(&ev, 0, sizeof(ev)); ev.se_assoc_id = SCTP_ALL_ASSOC; ev.se_on = 1; for (i = 0; i < eventTypeCount; i++) { ev.se_type = SCTP_EVENT_TYPES[i]; if (usrsctp_setsockopt(so, IPPROTO_SCTP, SCTP_EVENT, &ev, sizeof(ev)) < 0) { printf("Failed to set SCTP_EVENT type: %i\n", ev.se_type); free(sctpSocket); return 0; } } sctpSocket->so = so; sctpSocket->localPort = (int) localPort; return (jlong) (intptr_t) sctpSocket; }
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); }
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); }
janus_sctp_association *janus_sctp_association_create(void *dtls, uint64_t handle_id, uint16_t udp_port) { if(dtls == NULL || udp_port == 0) return NULL; /* usrsctp provides UDP encapsulation of SCTP, but we need these messages to * be encapsulated in DTLS and actually sent/received by libnice, and not by * usrsctp itself... as such, we make use of the AF_CONN approach */ janus_sctp_association *sctp = (janus_sctp_association *)calloc(1, sizeof(janus_sctp_association)); if(sctp == NULL) { JANUS_LOG(LOG_FATAL, "Memory error!\n"); return NULL; } sctp->dtls = dtls; sctp->handle_id = handle_id; sctp->ready = FALSE; /* We wait for the association setup, for this */ sctp->local_port = 5000; /* FIXME We always use this one */ sctp->remote_port = udp_port; sctp->sock = NULL; struct socket *sock = NULL; unsigned int i = 0; struct sockaddr_conn sconn; /* Now go on with SCTP */ janus_sctp_channel *channel = NULL; for(i = 0; i < NUMBER_OF_CHANNELS; i++) { channel = &(sctp->channels[i]); channel->id = i; channel->state = DATA_CHANNEL_CLOSED; channel->pr_policy = SCTP_PR_SCTP_NONE; channel->pr_value = 0; channel->stream = 0; channel->unordered = 0; channel->flags = 0; } for(i = 0; i < NUMBER_OF_STREAMS; i++) { sctp->stream_channel[i] = NULL; sctp->stream_buffer[i] = 0; } sctp->stream_buffer_counter = 0; sctp->sock = NULL; janus_mutex_init(&sctp->mutex); usrsctp_register_address((void *)sctp); usrsctp_sysctl_set_sctp_ecn_enable(0); if((sock = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, janus_sctp_incoming_data, NULL, 0, (void *)sctp)) == NULL) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error creating usrsctp socket...\n", handle_id); free(sctp); sctp = NULL; return NULL; } /* Set SO_LINGER */ struct linger linger_opt; linger_opt.l_onoff = 1; linger_opt.l_linger = 0; if(usrsctp_setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt))) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] setsockopt error: SO_LINGER\n", handle_id); free(sctp); sctp = NULL; return NULL; } /* Allow resetting streams */ struct sctp_assoc_value av; av.assoc_id = SCTP_ALL_ASSOC; av.assoc_value = 1; if(usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, &av, sizeof(struct sctp_assoc_value)) < 0) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] setsockopt error: SCTP_ENABLE_STREAM_RESET\n", handle_id); free(sctp); sctp = NULL; return NULL; } /* Disable Nagle */ uint32_t nodelay = 1; if(usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay))) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] setsockopt error: SCTP_NODELAY\n", handle_id); free(sctp); sctp = NULL; return NULL; } /* Enable the events of interest */ struct sctp_event event; 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) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] setsockopt error: SCTP_EVENT\n", handle_id); free(sctp); sctp = NULL; return NULL; } } /* Configure our INIT message */ struct sctp_initmsg initmsg; memset(&initmsg, 0, sizeof(struct sctp_initmsg)); initmsg.sinit_num_ostreams = 16; /* What Firefox says in the INIT (Chrome says 1023) */ initmsg.sinit_max_instreams = 2048; /* What both Chrome and Firefox say in the INIT */ if(usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(struct sctp_initmsg)) < 0) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] setsockopt error: SCTP_INITMSG\n", handle_id); free(sctp); sctp = NULL; return NULL; } /* Bind our side of the communication, using AF_CONN as we're doing the actual delivery ourselves */ memset(&sconn, 0, sizeof(struct sockaddr_conn)); sconn.sconn_family = AF_CONN; sconn.sconn_port = htons(sctp->local_port); sconn.sconn_addr = (void *)sctp; if(usrsctp_bind(sock, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error binding client on port %"SCNu16"\n", handle_id, sctp->local_port); free(sctp); sctp = NULL; return NULL; } #ifdef DEBUG_SCTP char debug_file[1024]; g_snprintf(debug_file, 1024, "%s/sctp-debug-%"SCNu64".txt", debug_folder, handle_id); sctp->debug_dump = fopen(debug_file, "wt"); #endif /* We're done for now, the setup is done elsewhere */ janus_mutex_lock(&sctp->mutex); sctp->sock = sock; sctp->in_messages = g_queue_new(); sctp->out_messages = g_queue_new(); GError *error = NULL; sctp->thread = g_thread_try_new("JanusSCTP", &janus_sctp_thread, sctp, &error); if(error != NULL) { /* Something went wrong... */ JANUS_LOG(LOG_ERR, "[%"SCNu64"] Got error %d (%s) trying to launch the SCTP thread...\n", handle_id, error->code, error->message ? error->message : "??"); g_queue_free(sctp->in_messages); sctp->in_messages = NULL; g_queue_free(sctp->out_messages); sctp->out_messages = NULL; g_free(sctp); sctp = NULL; return NULL; } janus_mutex_unlock(&sctp->mutex); return sctp; }