ekr_loop.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. /*
  2. * Copyright (C) 2011-2013 Michael Tuexen
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the project nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. /*
  31. * Usage: ekr_loop [client_port] [server_port] [crc32c offloading <0/1>]
  32. */
  33. #ifdef _WIN32
  34. #define _CRT_SECURE_NO_WARNINGS
  35. #endif
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <stdarg.h>
  40. #include <sys/types.h>
  41. #ifndef _WIN32
  42. #include <sys/socket.h>
  43. #include <netinet/in.h>
  44. #include <arpa/inet.h>
  45. #include <errno.h>
  46. #include <pthread.h>
  47. #include <unistd.h>
  48. #else
  49. #include <winsock2.h>
  50. #include <ws2tcpip.h>
  51. #endif
  52. #include <usrsctp.h>
  53. #include "programs_helper.h"
  54. #define MAX_PACKET_SIZE (1<<16)
  55. #define LINE_LENGTH (1<<20)
  56. #define DISCARD_PPID 39
  57. #define NUMBER_OF_STEPS 10
  58. static uint8_t crc32c_offloading = 0;
  59. #ifdef _WIN32
  60. static DWORD WINAPI
  61. #else
  62. static void *
  63. #endif
  64. handle_packets(void *arg)
  65. {
  66. #ifdef _WIN32
  67. SOCKET *fdp;
  68. #else
  69. int *fdp;
  70. #endif
  71. char *dump_buf;
  72. struct sctp_common_header *hdr;
  73. ssize_t length;
  74. char buf[MAX_PACKET_SIZE];
  75. uint32_t received_crc32c, computed_crc32c;
  76. #ifdef _WIN32
  77. fdp = (SOCKET *)arg;
  78. #else
  79. fdp = (int *)arg;
  80. #endif
  81. for (;;) {
  82. #if defined(__NetBSD__)
  83. pthread_testcancel();
  84. #endif
  85. length = recv(*fdp, buf, MAX_PACKET_SIZE, 0);
  86. if (length > 0) {
  87. if ((dump_buf = usrsctp_dumppacket(buf, (size_t)length, SCTP_DUMP_INBOUND)) != NULL) {
  88. /* debug_printf_clean("%s", dump_buf); */
  89. usrsctp_freedumpbuffer(dump_buf);
  90. }
  91. if (crc32c_offloading) {
  92. if ((size_t)length >= sizeof(struct sctp_common_header)) {
  93. hdr = (struct sctp_common_header *)buf;
  94. received_crc32c = hdr->crc32c;
  95. hdr->crc32c = htonl(0);
  96. computed_crc32c = usrsctp_crc32c(buf, (size_t)length);
  97. hdr->crc32c = received_crc32c;
  98. if (received_crc32c == computed_crc32c) {
  99. usrsctp_conninput(fdp, buf, (size_t)length, 0);
  100. } else {
  101. debug_printf("Wrong CRC32c: expected %08x received %08x\n",
  102. ntohl(computed_crc32c), ntohl(received_crc32c));
  103. }
  104. } else {
  105. debug_printf("Packet too short: length %zd", length);
  106. }
  107. } else {
  108. usrsctp_conninput(fdp, buf, (size_t)length, 0);
  109. }
  110. }
  111. }
  112. #ifdef _WIN32
  113. return 0;
  114. #else
  115. return (NULL);
  116. #endif
  117. }
  118. static int
  119. conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df)
  120. {
  121. char *dump_buf;
  122. struct sctp_common_header *hdr;
  123. #ifdef _WIN32
  124. SOCKET *fdp;
  125. #else
  126. int *fdp;
  127. #endif
  128. #ifdef _WIN32
  129. fdp = (SOCKET *)addr;
  130. #else
  131. fdp = (int *)addr;
  132. #endif
  133. if (crc32c_offloading && length >= sizeof(struct sctp_common_header)) {
  134. hdr = (struct sctp_common_header *)buf;
  135. hdr->crc32c = usrsctp_crc32c(buf, (size_t)length);
  136. }
  137. if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) {
  138. /* debug_printf_clean("%s", dump_buf); */
  139. usrsctp_freedumpbuffer(dump_buf);
  140. }
  141. #ifdef _WIN32
  142. if (send(*fdp, buf, (int)length, 0) == SOCKET_ERROR) {
  143. return (WSAGetLastError());
  144. #else
  145. if (send(*fdp, buf, length, 0) < 0) {
  146. return (errno);
  147. #endif
  148. } else {
  149. return (0);
  150. }
  151. }
  152. static int
  153. receive_cb(struct socket *sock, union sctp_sockstore addr, void *data,
  154. size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info)
  155. {
  156. debug_printf("MSG RCV: %p received on sock = %p.\n", data, (void *)sock);
  157. if (data) {
  158. if ((flags & MSG_NOTIFICATION) == 0) {
  159. debug_printf("MSG RCV: length %d, addr %p:%u, stream %u, SSN %u, TSN %u, PPID %u, context %u, %s%s.\n",
  160. (int)datalen,
  161. addr.sconn.sconn_addr,
  162. ntohs(addr.sconn.sconn_port),
  163. rcv.rcv_sid,
  164. rcv.rcv_ssn,
  165. rcv.rcv_tsn,
  166. ntohl(rcv.rcv_ppid),
  167. rcv.rcv_context,
  168. (rcv.rcv_flags & SCTP_UNORDERED) ? "unordered" : "ordered",
  169. (flags & MSG_EOR) ? ", EOR" : "");
  170. }
  171. free(data);
  172. } else {
  173. usrsctp_deregister_address(ulp_info);
  174. usrsctp_close(sock);
  175. }
  176. return (1);
  177. }
  178. static void
  179. print_addresses(struct socket *sock)
  180. {
  181. int i, n;
  182. struct sockaddr *addrs, *addr;
  183. #if !defined(HAVE_SA_LEN)
  184. int sa_len;
  185. #endif
  186. debug_printf("Addresses: ");
  187. n = usrsctp_getladdrs(sock, 0, &addrs);
  188. addr = addrs;
  189. for (i = 0; i < n; i++) {
  190. switch (addr->sa_family) {
  191. case AF_INET:
  192. {
  193. struct sockaddr_in *sin;
  194. char buf[INET_ADDRSTRLEN];
  195. const char *name;
  196. sin = (struct sockaddr_in *)addr;
  197. name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN);
  198. debug_printf_clean("%s:%d", name, ntohs(sin->sin_port));
  199. #if !defined(HAVE_SA_LEN)
  200. sa_len = (int)sizeof(struct sockaddr_in);
  201. #endif
  202. break;
  203. }
  204. case AF_INET6:
  205. {
  206. struct sockaddr_in6 *sin6;
  207. char buf[INET6_ADDRSTRLEN];
  208. const char *name;
  209. sin6 = (struct sockaddr_in6 *)addr;
  210. name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
  211. debug_printf_clean("%s:%d", name, ntohs(sin6->sin6_port));
  212. #if !defined(HAVE_SA_LEN)
  213. sa_len = (int)sizeof(struct sockaddr_in6);
  214. #endif
  215. break;
  216. }
  217. case AF_CONN:
  218. {
  219. struct sockaddr_conn *sconn;
  220. sconn = (struct sockaddr_conn *)addr;
  221. debug_printf_clean("%p:%d", sconn->sconn_addr, ntohs(sconn->sconn_port));
  222. #if !defined(HAVE_SA_LEN)
  223. sa_len = (int)sizeof(struct sockaddr_conn);
  224. #endif
  225. break;
  226. }
  227. default:
  228. debug_printf_clean("Unknown family: %d", addr->sa_family);
  229. #if !defined(HAVE_SA_LEN)
  230. sa_len = (int)sizeof(struct sockaddr);
  231. #endif
  232. break;
  233. }
  234. #if !defined(HAVE_SA_LEN)
  235. addr = (struct sockaddr *)((char *)addr + sa_len);
  236. #else
  237. addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len);
  238. #endif
  239. if (i != n - 1) {
  240. debug_printf_clean(",");
  241. }
  242. }
  243. if (n > 0) {
  244. usrsctp_freeladdrs(addrs);
  245. }
  246. debug_printf_clean("<->");
  247. n = usrsctp_getpaddrs(sock, 0, &addrs);
  248. addr = addrs;
  249. for (i = 0; i < n; i++) {
  250. switch (addr->sa_family) {
  251. case AF_INET:
  252. {
  253. struct sockaddr_in *sin;
  254. char buf[INET_ADDRSTRLEN];
  255. const char *name;
  256. sin = (struct sockaddr_in *)addr;
  257. name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN);
  258. debug_printf_clean("%s:%d", name, ntohs(sin->sin_port));
  259. #if !defined(HAVE_SA_LEN)
  260. sa_len = (int)sizeof(struct sockaddr_in);
  261. #endif
  262. break;
  263. }
  264. case AF_INET6:
  265. {
  266. struct sockaddr_in6 *sin6;
  267. char buf[INET6_ADDRSTRLEN];
  268. const char *name;
  269. sin6 = (struct sockaddr_in6 *)addr;
  270. name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
  271. debug_printf_clean("%s:%d", name, ntohs(sin6->sin6_port));
  272. #if !defined(HAVE_SA_LEN)
  273. sa_len = (int)sizeof(struct sockaddr_in6);
  274. #endif
  275. break;
  276. }
  277. case AF_CONN:
  278. {
  279. struct sockaddr_conn *sconn;
  280. sconn = (struct sockaddr_conn *)addr;
  281. debug_printf_clean("%p:%d", sconn->sconn_addr, ntohs(sconn->sconn_port));
  282. #if !defined(HAVE_SA_LEN)
  283. sa_len = (int)sizeof(struct sockaddr_conn);
  284. #endif
  285. break;
  286. }
  287. default:
  288. debug_printf_clean("Unknown family: %d", addr->sa_family);
  289. #if !defined(HAVE_SA_LEN)
  290. sa_len = (int)sizeof(struct sockaddr);
  291. #endif
  292. break;
  293. }
  294. #if !defined(HAVE_SA_LEN)
  295. addr = (struct sockaddr *)((char *)addr + sa_len);
  296. #else
  297. addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len);
  298. #endif
  299. if (i != n - 1) {
  300. debug_printf_clean(",");
  301. }
  302. }
  303. if (n > 0) {
  304. usrsctp_freepaddrs(addrs);
  305. }
  306. debug_printf_clean("\n");
  307. }
  308. int
  309. main(int argc, char *argv[])
  310. {
  311. struct sockaddr_in sin_s, sin_c;
  312. struct sockaddr_conn sconn;
  313. struct sctp_paddrparams paddrparams;
  314. #ifdef _WIN32
  315. SOCKET fd_c, fd_s;
  316. #else
  317. int fd_c, fd_s, rc;
  318. #endif
  319. struct socket *s_c, *s_s, *s_l;
  320. #ifdef _WIN32
  321. HANDLE tid_c, tid_s;
  322. #else
  323. pthread_t tid_c, tid_s;
  324. #endif
  325. int i, j, cur_buf_size, snd_buf_size, rcv_buf_size, sendv_retries_left;
  326. socklen_t opt_len;
  327. struct sctp_sndinfo sndinfo;
  328. char *line;
  329. #ifdef _WIN32
  330. WSADATA wsaData;
  331. #endif
  332. uint16_t client_port = 9900;
  333. uint16_t server_port = 9901;
  334. if (argc > 1) {
  335. client_port = atoi(argv[1]);
  336. }
  337. if (argc > 2) {
  338. server_port = atoi(argv[2]);
  339. }
  340. if (argc > 3) {
  341. crc32c_offloading = atoi(argv[3]);
  342. }
  343. debug_printf("Starting program\n");
  344. debug_printf("Config:\n\tClient Port:\t%d\n\tServer Port:\t%d\n\tCRC32C Calc:\t%s\n", client_port, server_port, crc32c_offloading ? "offloaded" : "NOT offloaded");
  345. #ifdef _WIN32
  346. if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
  347. debug_printf("WSAStartup failed\n");
  348. exit (EXIT_FAILURE);
  349. }
  350. #endif
  351. usrsctp_init(0, conn_output, debug_printf_stack);
  352. #ifdef SCTP_DEBUG
  353. usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
  354. #endif
  355. if (crc32c_offloading) {
  356. usrsctp_enable_crc32c_offload();
  357. }
  358. /* set up a connected UDP socket */
  359. #ifdef _WIN32
  360. if ((fd_c = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
  361. debug_printf("socket() failed with error: %d\n", WSAGetLastError());
  362. exit(EXIT_FAILURE);
  363. }
  364. if ((fd_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
  365. debug_printf("socket() failed with error: %d\n", WSAGetLastError());
  366. exit(EXIT_FAILURE);
  367. }
  368. #else
  369. if ((fd_c = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  370. perror("socket");
  371. exit(EXIT_FAILURE);
  372. }
  373. if ((fd_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  374. perror("socket");
  375. exit(EXIT_FAILURE);
  376. }
  377. #endif
  378. memset(&sin_c, 0, sizeof(struct sockaddr_in));
  379. sin_c.sin_family = AF_INET;
  380. #ifdef HAVE_SIN_LEN
  381. sin_c.sin_len = sizeof(struct sockaddr_in);
  382. #endif
  383. sin_c.sin_port = htons(client_port);
  384. sin_c.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  385. memset(&sin_s, 0, sizeof(struct sockaddr_in));
  386. sin_s.sin_family = AF_INET;
  387. #ifdef HAVE_SIN_LEN
  388. sin_s.sin_len = sizeof(struct sockaddr_in);
  389. #endif
  390. sin_s.sin_port = htons(server_port);
  391. sin_s.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  392. #ifdef _WIN32
  393. if (bind(fd_c, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
  394. debug_printf("bind() failed with error: %d\n", WSAGetLastError());
  395. exit(EXIT_FAILURE);
  396. }
  397. if (bind(fd_s, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
  398. debug_printf("bind() failed with error: %d\n", WSAGetLastError());
  399. exit(EXIT_FAILURE);
  400. }
  401. #else
  402. if (bind(fd_c, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) < 0) {
  403. perror("bind");
  404. exit(EXIT_FAILURE);
  405. }
  406. if (bind(fd_s, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) < 0) {
  407. perror("bind");
  408. exit(EXIT_FAILURE);
  409. }
  410. #endif
  411. #ifdef _WIN32
  412. if (connect(fd_c, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
  413. debug_printf("connect() failed with error: %d\n", WSAGetLastError());
  414. exit(EXIT_FAILURE);
  415. }
  416. if (connect(fd_s, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
  417. debug_printf("connect() failed with error: %d\n", WSAGetLastError());
  418. exit(EXIT_FAILURE);
  419. }
  420. #else
  421. if (connect(fd_c, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) < 0) {
  422. perror("connect");
  423. exit(EXIT_FAILURE);
  424. }
  425. if (connect(fd_s, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) < 0) {
  426. perror("connect");
  427. exit(EXIT_FAILURE);
  428. }
  429. #endif
  430. #ifdef _WIN32
  431. if ((tid_c = CreateThread(NULL, 0, &handle_packets, (void *)&fd_c, 0, NULL)) == NULL) {
  432. debug_printf("CreateThread() failed with error: %d\n", GetLastError());
  433. exit(EXIT_FAILURE);
  434. }
  435. if ((tid_s = CreateThread(NULL, 0, &handle_packets, (void *)&fd_s, 0, NULL)) == NULL) {
  436. debug_printf("CreateThread() failed with error: %d\n", GetLastError());
  437. exit(EXIT_FAILURE);
  438. }
  439. #else
  440. if ((rc = pthread_create(&tid_c, NULL, &handle_packets, (void *)&fd_c)) != 0) {
  441. debug_printf_clean("pthread_create tid_c: %s\n", strerror(rc));
  442. exit(EXIT_FAILURE);
  443. }
  444. if ((rc = pthread_create(&tid_s, NULL, &handle_packets, (void *)&fd_s)) != 0) {
  445. debug_printf_clean("pthread_create tid_s: %s\n", strerror(rc));
  446. exit(EXIT_FAILURE);
  447. };
  448. #endif
  449. usrsctp_sysctl_set_sctp_ecn_enable(0);
  450. usrsctp_register_address((void *)&fd_c);
  451. usrsctp_register_address((void *)&fd_s);
  452. if ((s_c = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd_c)) == NULL) {
  453. perror("usrsctp_socket");
  454. exit(EXIT_FAILURE);
  455. }
  456. opt_len = (socklen_t)sizeof(int);
  457. cur_buf_size = 0;
  458. if (usrsctp_getsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &cur_buf_size, &opt_len) < 0) {
  459. perror("usrsctp_getsockopt");
  460. exit(EXIT_FAILURE);
  461. }
  462. debug_printf("Change send socket buffer size from %d ", cur_buf_size);
  463. snd_buf_size = 1<<22; /* 4 MB */
  464. if (usrsctp_setsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &snd_buf_size, sizeof(int)) < 0) {
  465. perror("usrsctp_setsockopt");
  466. exit(EXIT_FAILURE);
  467. }
  468. opt_len = (socklen_t)sizeof(int);
  469. cur_buf_size = 0;
  470. if (usrsctp_getsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &cur_buf_size, &opt_len) < 0) {
  471. perror("usrsctp_getsockopt");
  472. exit(EXIT_FAILURE);
  473. }
  474. debug_printf_clean("to %d.\n", cur_buf_size);
  475. memset(&paddrparams, 0, sizeof(struct sctp_paddrparams));
  476. paddrparams.spp_address.ss_family = AF_CONN;
  477. #ifdef HAVE_SCONN_LEN
  478. paddrparams.spp_address.ss_len = sizeof(struct sockaddr_conn);
  479. #endif
  480. paddrparams.spp_flags = SPP_PMTUD_DISABLE;
  481. paddrparams.spp_pathmtu = 9000;
  482. if (usrsctp_setsockopt(s_c, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &paddrparams, sizeof(struct sctp_paddrparams)) < 0) {
  483. perror("usrsctp_setsockopt");
  484. exit(EXIT_FAILURE);
  485. }
  486. if ((s_l = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd_s)) == NULL) {
  487. perror("usrsctp_socket");
  488. exit(EXIT_FAILURE);
  489. }
  490. opt_len = (socklen_t)sizeof(int);
  491. cur_buf_size = 0;
  492. if (usrsctp_getsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &cur_buf_size, &opt_len) < 0) {
  493. perror("usrsctp_getsockopt");
  494. exit(EXIT_FAILURE);
  495. }
  496. debug_printf("Change receive socket buffer size from %d ", cur_buf_size);
  497. rcv_buf_size = 1<<16; /* 64 KB */
  498. if (usrsctp_setsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &rcv_buf_size, sizeof(int)) < 0) {
  499. perror("usrsctp_setsockopt");
  500. exit(EXIT_FAILURE);
  501. }
  502. opt_len = (socklen_t)sizeof(int);
  503. cur_buf_size = 0;
  504. if (usrsctp_getsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &cur_buf_size, &opt_len) < 0) {
  505. perror("usrsctp_getsockopt");
  506. exit(EXIT_FAILURE);
  507. }
  508. debug_printf_clean("to %d.\n", cur_buf_size);
  509. /* Bind the client side. */
  510. memset(&sconn, 0, sizeof(struct sockaddr_conn));
  511. sconn.sconn_family = AF_CONN;
  512. #ifdef HAVE_SCONN_LEN
  513. sconn.sconn_len = sizeof(struct sockaddr_conn);
  514. #endif
  515. sconn.sconn_port = htons(5001);
  516. sconn.sconn_addr = &fd_c;
  517. if (usrsctp_bind(s_c, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
  518. perror("usrsctp_bind");
  519. exit(EXIT_FAILURE);
  520. }
  521. /* Bind the server side. */
  522. memset(&sconn, 0, sizeof(struct sockaddr_conn));
  523. sconn.sconn_family = AF_CONN;
  524. #ifdef HAVE_SCONN_LEN
  525. sconn.sconn_len = sizeof(struct sockaddr_conn);
  526. #endif
  527. sconn.sconn_port = htons(5001);
  528. sconn.sconn_addr = &fd_s;
  529. if (usrsctp_bind(s_l, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
  530. perror("usrsctp_bind");
  531. exit(EXIT_FAILURE);
  532. }
  533. /* Make server side passive... */
  534. if (usrsctp_listen(s_l, 1) < 0) {
  535. perror("usrsctp_listen");
  536. exit(EXIT_FAILURE);
  537. }
  538. /* Initiate the handshake */
  539. memset(&sconn, 0, sizeof(struct sockaddr_conn));
  540. sconn.sconn_family = AF_CONN;
  541. #ifdef HAVE_SCONN_LEN
  542. sconn.sconn_len = sizeof(struct sockaddr_conn);
  543. #endif
  544. sconn.sconn_port = htons(5001);
  545. sconn.sconn_addr = &fd_c;
  546. if (usrsctp_connect(s_c, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
  547. perror("usrsctp_connect");
  548. exit(EXIT_FAILURE);
  549. }
  550. if ((s_s = usrsctp_accept(s_l, NULL, NULL)) == NULL) {
  551. perror("usrsctp_accept");
  552. exit(EXIT_FAILURE);
  553. }
  554. usrsctp_close(s_l);
  555. print_addresses(s_s);
  556. if ((line = malloc(LINE_LENGTH)) == NULL) {
  557. exit(EXIT_FAILURE);
  558. }
  559. memset(line, 'A', LINE_LENGTH);
  560. sndinfo.snd_sid = 1;
  561. sndinfo.snd_ppid = htonl(DISCARD_PPID);
  562. sndinfo.snd_context = 0;
  563. sndinfo.snd_assoc_id = 0;
  564. for (i = 0; i < NUMBER_OF_STEPS; i++) {
  565. if (i % 2) {
  566. sndinfo.snd_flags = SCTP_UNORDERED;
  567. } else {
  568. sndinfo.snd_flags = 0;
  569. }
  570. for (j = 0; j < 2; j++) {
  571. /* Send a 1 MB message */
  572. sendv_retries_left = 120;
  573. debug_printf("usrscp_sendv - step %d - call %d flags %x\n", i, j + 1, sndinfo.snd_flags);
  574. while (usrsctp_sendv(s_c, line, LINE_LENGTH, NULL, 0, (void *)&sndinfo,
  575. (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) {
  576. debug_printf("usrsctp_sendv - errno: %d - %s\n", errno, strerror(errno));
  577. if (errno != EWOULDBLOCK || !sendv_retries_left) {
  578. exit(EXIT_FAILURE);
  579. }
  580. sendv_retries_left--;
  581. #ifdef _WIN32
  582. Sleep(1000);
  583. #else
  584. sleep(1);
  585. #endif
  586. }
  587. }
  588. debug_printf("Sending done, sleeping\n");
  589. #ifdef _WIN32
  590. Sleep(1000);
  591. #else
  592. sleep(1);
  593. #endif
  594. }
  595. free(line);
  596. usrsctp_shutdown(s_c, SHUT_WR);
  597. while (usrsctp_finish() != 0) {
  598. debug_printf("Waiting for usrsctp_finish()\n");
  599. #ifdef _WIN32
  600. Sleep(1000);
  601. #else
  602. sleep(1);
  603. #endif
  604. }
  605. #ifdef _WIN32
  606. TerminateThread(tid_c, 0);
  607. WaitForSingleObject(tid_c, INFINITE);
  608. TerminateThread(tid_s, 0);
  609. WaitForSingleObject(tid_s, INFINITE);
  610. if (closesocket(fd_c) == SOCKET_ERROR) {
  611. debug_printf("closesocket() failed with error: %d\n", WSAGetLastError());
  612. exit(EXIT_FAILURE);
  613. }
  614. if (closesocket(fd_s) == SOCKET_ERROR) {
  615. debug_printf("closesocket() failed with error: %d\n", WSAGetLastError());
  616. exit(EXIT_FAILURE);
  617. }
  618. WSACleanup();
  619. #else
  620. pthread_cancel(tid_c);
  621. pthread_join(tid_c, NULL);
  622. pthread_cancel(tid_s);
  623. pthread_join(tid_s, NULL);
  624. if (close(fd_c) < 0) {
  625. perror("close");
  626. exit(EXIT_FAILURE);
  627. }
  628. if (close(fd_s) < 0) {
  629. perror("close");
  630. exit(EXIT_FAILURE);
  631. }
  632. #endif
  633. return (0);
  634. }