client_upcall.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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: client_upcall remote_addr remote_port [local_port] [local_encaps_port] [remote_encaps_port]
  32. */
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <stdarg.h>
  37. #if !defined(_WIN32)
  38. #include <unistd.h>
  39. #include <sys/time.h>
  40. #endif /* !defined(_WIN32) */
  41. #include <sys/types.h>
  42. #if !defined(_WIN32)
  43. #include <sys/socket.h>
  44. #include <netinet/in.h>
  45. #include <arpa/inet.h>
  46. #else /* !defined(_WIN32) */
  47. #include <io.h>
  48. #endif
  49. #include <usrsctp.h>
  50. #include "programs_helper.h"
  51. #include <fcntl.h>
  52. #define BUFFERSIZE (1<<16)
  53. int done = 0, input_done = 0, connected = 0;
  54. #ifdef _WIN32
  55. typedef char* caddr_t;
  56. #endif
  57. int inputAvailable(void)
  58. {
  59. struct timeval tv;
  60. fd_set fds;
  61. tv.tv_sec = 0;
  62. tv.tv_usec = 0;
  63. FD_ZERO(&fds);
  64. #if defined(_WIN32) && !defined(__MINGW32__)
  65. FD_SET((SOCKET)_fileno(stdin), &fds);
  66. select(_fileno(stdin) + 1, &fds, NULL, NULL, &tv);
  67. #else
  68. FD_SET(STDIN_FILENO, &fds);
  69. select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
  70. #endif
  71. return (FD_ISSET(0, &fds));
  72. }
  73. static void
  74. handle_upcall(struct socket *sock, void *arg, int flgs)
  75. {
  76. int events = usrsctp_get_events(sock);
  77. if (events & SCTP_EVENT_WRITE && !done && !connected) {
  78. connected = 1;
  79. printf("socket connected\n");
  80. return;
  81. }
  82. while (events & SCTP_EVENT_READ && !done && connected) {
  83. struct sctp_recvv_rn rn;
  84. ssize_t n;
  85. struct sockaddr_in addr;
  86. char *buf = calloc(1, BUFFERSIZE);
  87. int flags = 0;
  88. socklen_t len = (socklen_t)sizeof(struct sockaddr_in);
  89. unsigned int infotype = 0;
  90. socklen_t infolen = sizeof(struct sctp_recvv_rn);
  91. memset(&rn, 0, sizeof(struct sctp_recvv_rn));
  92. n = usrsctp_recvv(sock, buf, BUFFERSIZE, (struct sockaddr *) &addr, &len, (void *)&rn,
  93. &infolen, &infotype, &flags);
  94. if (n > 0) {
  95. #ifdef _WIN32
  96. _write(_fileno(stdout), buf, (unsigned int)n);
  97. #else
  98. if (write(fileno(stdout), buf, n) < 0) {
  99. perror("write");
  100. }
  101. #endif
  102. } else if (n == 0) {
  103. done = 1;
  104. input_done = 1;
  105. free(buf);
  106. break;
  107. } else {
  108. perror("\nusrsctp_recvv");
  109. free (buf);
  110. break;
  111. }
  112. free(buf);
  113. events = usrsctp_get_events(sock);
  114. }
  115. return;
  116. }
  117. int
  118. main(int argc, char *argv[])
  119. {
  120. struct socket *sock;
  121. struct sockaddr *addr, *addrs;
  122. struct sockaddr_in addr4;
  123. struct sockaddr_in6 addr6;
  124. struct sctp_udpencaps encaps;
  125. struct sctpstat stat;
  126. char buffer[200];
  127. int i, n;
  128. if (argc > 4) {
  129. usrsctp_init(atoi(argv[4]), NULL, debug_printf_stack);
  130. } else {
  131. usrsctp_init(9899, NULL, debug_printf_stack);
  132. }
  133. #ifdef SCTP_DEBUG
  134. usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
  135. #endif
  136. usrsctp_sysctl_set_sctp_blackhole(2);
  137. usrsctp_sysctl_set_sctp_no_csum_on_loopback(0);
  138. if ((sock = usrsctp_socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL)) == NULL) {
  139. perror("usrsctp_socket");
  140. exit(1);
  141. }
  142. usrsctp_set_non_blocking(sock, 1);
  143. if (argc > 3) {
  144. memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
  145. #ifdef HAVE_SIN6_LEN
  146. addr6.sin6_len = sizeof(struct sockaddr_in6);
  147. #endif
  148. addr6.sin6_family = AF_INET6;
  149. addr6.sin6_port = htons(atoi(argv[3]));
  150. addr6.sin6_addr = in6addr_any;
  151. if (usrsctp_bind(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
  152. perror("bind");
  153. usrsctp_close(sock);
  154. exit(1);
  155. }
  156. }
  157. if (argc > 5) {
  158. memset(&encaps, 0, sizeof(struct sctp_udpencaps));
  159. encaps.sue_address.ss_family = AF_INET6;
  160. encaps.sue_port = htons(atoi(argv[5]));
  161. if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
  162. perror("setsockopt");
  163. usrsctp_close(sock);
  164. exit(1);
  165. }
  166. }
  167. memset((void *)&addr4, 0, sizeof(struct sockaddr_in));
  168. memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
  169. #ifdef HAVE_SIN_LEN
  170. addr4.sin_len = sizeof(struct sockaddr_in);
  171. #endif
  172. #ifdef HAVE_SIN6_LEN
  173. addr6.sin6_len = sizeof(struct sockaddr_in6);
  174. #endif
  175. addr4.sin_family = AF_INET;
  176. addr6.sin6_family = AF_INET6;
  177. addr4.sin_port = htons(atoi(argv[2]));
  178. addr6.sin6_port = htons(atoi(argv[2]));
  179. if (inet_pton(AF_INET6, argv[1], &addr6.sin6_addr) == 1) {
  180. if (usrsctp_connect(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
  181. perror("usrsctp_connect");
  182. }
  183. } else if (inet_pton(AF_INET, argv[1], &addr4.sin_addr) == 1) {
  184. if (usrsctp_connect(sock, (struct sockaddr *)&addr4, sizeof(struct sockaddr_in)) < 0) {
  185. perror("usrsctp_connect");
  186. }
  187. } else {
  188. printf("Illegal destination address.\n");
  189. }
  190. usrsctp_set_upcall(sock, handle_upcall, NULL);
  191. if ((n = usrsctp_getladdrs(sock, 0, &addrs)) < 0) {
  192. perror("usrsctp_getladdrs");
  193. } else {
  194. addr = addrs;
  195. printf("Local addresses: ");
  196. for (i = 0; i < n; i++) {
  197. if (i > 0) {
  198. printf("%s", ", ");
  199. }
  200. switch (addr->sa_family) {
  201. case AF_INET:
  202. {
  203. struct sockaddr_in *sin;
  204. char buf[INET_ADDRSTRLEN];
  205. const char *name;
  206. sin = (struct sockaddr_in *)addr;
  207. name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN);
  208. printf("%s", name);
  209. #ifndef HAVE_SA_LEN
  210. addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
  211. #endif
  212. break;
  213. }
  214. case AF_INET6:
  215. {
  216. struct sockaddr_in6 *sin6;
  217. char buf[INET6_ADDRSTRLEN];
  218. const char *name;
  219. sin6 = (struct sockaddr_in6 *)addr;
  220. name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
  221. printf("%s", name);
  222. #ifndef HAVE_SA_LEN
  223. addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
  224. #endif
  225. break;
  226. }
  227. default:
  228. break;
  229. }
  230. #ifdef HAVE_SA_LEN
  231. addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len);
  232. #endif
  233. }
  234. printf(".\n");
  235. usrsctp_freeladdrs(addrs);
  236. }
  237. if ((n = usrsctp_getpaddrs(sock, 0, &addrs)) < 0) {
  238. perror("usrsctp_getpaddrs");
  239. } else {
  240. addr = addrs;
  241. printf("Peer addresses: ");
  242. for (i = 0; i < n; i++) {
  243. if (i > 0) {
  244. printf("%s", ", ");
  245. }
  246. switch (addr->sa_family) {
  247. case AF_INET:
  248. {
  249. struct sockaddr_in *sin;
  250. char buf[INET_ADDRSTRLEN];
  251. const char *name;
  252. sin = (struct sockaddr_in *)addr;
  253. name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN);
  254. printf("%s", name);
  255. #ifndef HAVE_SA_LEN
  256. addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
  257. #endif
  258. break;
  259. }
  260. case AF_INET6:
  261. {
  262. struct sockaddr_in6 *sin6;
  263. char buf[INET6_ADDRSTRLEN];
  264. const char *name;
  265. sin6 = (struct sockaddr_in6 *)addr;
  266. name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
  267. printf("%s", name);
  268. #ifndef HAVE_SA_LEN
  269. addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
  270. #endif
  271. break;
  272. }
  273. default:
  274. break;
  275. }
  276. #ifdef HAVE_SA_LEN
  277. addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len);
  278. #endif
  279. }
  280. printf(".\n");
  281. usrsctp_freepaddrs(addrs);
  282. }
  283. while (!done && !input_done) {
  284. if (inputAvailable()) {
  285. if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
  286. usrsctp_sendv(sock, buffer, strlen(buffer), NULL, 0, NULL, 0, SCTP_SENDV_NOINFO, 0);
  287. } else {
  288. if (usrsctp_shutdown(sock, SHUT_WR) < 0) {
  289. perror("usrsctp_shutdown");
  290. }
  291. break;
  292. }
  293. }
  294. }
  295. #ifdef _WIN32
  296. Sleep(1000);
  297. #else
  298. sleep(1);
  299. #endif
  300. usrsctp_close(sock);
  301. usrsctp_get_stat(&stat);
  302. printf("Number of packets (sent/received): (%u/%u).\n",
  303. stat.sctps_outpackets, stat.sctps_inpackets);
  304. while (usrsctp_finish() != 0) {
  305. #ifdef _WIN32
  306. Sleep(1000);
  307. #else
  308. sleep(1);
  309. #endif
  310. }
  311. printf("Client finished\n");
  312. return(0);
  313. }