Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1670 lines
54 KiB

  1. /*
  2. * TTCP
  3. *
  4. * Test TCP connection. Makes a connection on port 5001
  5. * and transfers fabricated buffers or data copied from stdin.
  6. *
  7. * Usable on 4.2, 4.3, and 4.1a systems by defining one of
  8. * BSD42 BSD43 (BSD41a)
  9. * Machines using System V with BSD sockets should define SYSV.
  10. *
  11. * Modified for operation under 4.2BSD, 18 Dec 84
  12. * T.C. Slattery, USNA
  13. * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
  14. * Modified in 1989 at Silicon Graphics, Inc.
  15. * catch SIGPIPE to be able to print stats when receiver has died
  16. * for tcp, don't look for sentinel during reads to allow small transfers
  17. * increased default buffer size to 8K, nbuf to 2K to transfer 16MB
  18. * moved default port to 5001, beyond IPPORT_USERRESERVED
  19. * make sinkmode default because it is more popular,
  20. * -s now means don't sink/source
  21. * count number of _read/_write system calls to see effects of
  22. * blocking from full socket buffers
  23. * for tcp, -D option turns off buffered writes (sets SO_NODELAY sockopt)
  24. * buffer alignment options, -A and -O
  25. * print stats in a format that's a bit easier to use with grep & awk
  26. * for SYSV, mimic BSD routines to use most of the existing timing code
  27. *
  28. * Distribution Status -
  29. * Public Domain. Distribution Unlimited.
  30. */
  31. #define BSD43
  32. /* #define BSD42 */
  33. /* #define BSD41a */
  34. #if defined(sgi) || defined(CRAY)
  35. #define SYSV
  36. #endif
  37. #include <nt.h>
  38. #include <ntrtl.h>
  39. #include <nturtl.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <io.h>
  43. #include <signal.h>
  44. #include <ctype.h>
  45. #include <sys/types.h>
  46. #include <winsock2.h>
  47. #include <ws2tcpip.h>
  48. #include <ws2ip6.h>
  49. #include <wspiapi.h>
  50. #include <mswsock.h>
  51. //
  52. // Localization library and MessageIds.
  53. //
  54. #include <nls.h>
  55. #include "localmsg.h"
  56. #if defined(SYSV)
  57. #include <sys/times.h>
  58. #include <sys/param.h>
  59. struct rusage {
  60. struct timeval ru_utime, ru_stime;
  61. };
  62. #define RUSAGE_SELF 0
  63. #else
  64. #endif
  65. u_short prot; // 0 (don't care), PF_INET, PF_INET6
  66. struct sockaddr_storage sinsrcStorage;
  67. struct sockaddr *sinsrc = (struct sockaddr *)&sinsrcStorage;
  68. struct sockaddr_storage sinmeStorage;
  69. struct sockaddr *sinme = (struct sockaddr *)&sinmeStorage;
  70. struct sockaddr_storage sinhimStorage;
  71. struct sockaddr *sinhim = (struct sockaddr *)&sinhimStorage;
  72. DWORD tmpbuf;
  73. struct addrinfo *aihim;
  74. SOCKET fd; /* fd of network socket */
  75. SOCKET fd2; /* fd of accepted connection */
  76. int buflen = 8 * 1024; /* length of buffer */
  77. char *buf; /* ptr to dynamic buffer */
  78. int nbuf = 2 * 1024; /* number of buffers to send in sinkmode */
  79. int bufoffset = 0; /* align buffer to this */
  80. int bufalign = 16*1024; /* modulo this */
  81. int udp = 0; /* 0 = tcp, !0 = udp */
  82. int udpcoverage = 0; /* UDP Lite checksum coverage */
  83. int options = 0; /* socket options */
  84. int one = 1; /* for 4.3 BSD style setsockopt() */
  85. short port = 5001; /* TCP port number */
  86. char *host; /* ptr to name of host */
  87. int trans; /* 0=receive, !0=transmit mode */
  88. int sinkmode = 1; /* 0=normal I/O, !0=sink/source mode */
  89. int verbose = 0; /* 0=print basic info, 1=print cpu rate, proc
  90. * resource usage. */
  91. int nodelay = 0; /* set TCP_NODELAY socket option */
  92. int b_flag = 0; /* use mread() */
  93. int write_delay = 0; /* milliseconds of delay before each write */
  94. int hops = -1; /* hop limit */
  95. int udp_connect = 0; /* connect UDP sockets */
  96. #define SOBUF_DEFAULT -1
  97. int sobuf = SOBUF_DEFAULT; /* SO_RCVBUF/SO_SNDBUF setting; 0 == default */
  98. int async = 0; /* async vs. synchronous io calls. value == */
  99. /* number of simultaneous async calls. */
  100. int connecttest = 0;
  101. char *filename = NULL;
  102. HANDLE filehandle;
  103. WSADATA WsaData;
  104. char stats[128];
  105. unsigned long nbytes; /* bytes on net */
  106. unsigned long numCalls; /* # of I/O system calls */
  107. int Nread( SOCKET fd, PBYTE buf, INT count );
  108. int mread( SOCKET fd, PBYTE bufp, INT n);
  109. int Nwrite( SOCKET fd, PBYTE buf, INT count );
  110. void err(unsigned int message);
  111. void pattern(char *cp, int cnt );
  112. void prep_timer();
  113. double read_timer(char *s, int l);
  114. //double cput, realt; /* user, real time (seconds) */
  115. DWORD realt;
  116. typedef struct _TTCP_ASYNC_INFO {
  117. PVOID Buffer;
  118. DWORD BytesWritten;
  119. OVERLAPPED Overlapped;
  120. } TTCP_ASYNC_INFO, *PTTCP_ASYNC_INFO;
  121. void
  122. sigpipe()
  123. {
  124. }
  125. int parse_addr(char *s, struct sockaddr *sa);
  126. char *format_addr(struct sockaddr *sa);
  127. void set_port(struct sockaddr *sa, u_short port);
  128. u_short get_port(struct sockaddr *sa);
  129. u_int addr_len(struct sockaddr *sa);
  130. void __cdecl
  131. main(argc,argv)
  132. int argc;
  133. char **argv;
  134. {
  135. char *Term;
  136. struct in_addr IPv4Group;
  137. struct in6_addr IPv6Group;
  138. int error;
  139. int i;
  140. BOOL ret;
  141. error = WSAStartup(MAKEWORD(2, 0), &WsaData );
  142. if ( error == SOCKET_ERROR ) {
  143. NlsPutMsg(STDOUT, TTCP_MESSAGE_0, WSAGetLastError());
  144. // printf("ttcp: WSAStartup failed %ld:", WSAGetLastError());
  145. }
  146. if (argc < 2) goto usage;
  147. for (i = 1; i < argc; i++) {
  148. if ((argv[i][0] != '-') &&
  149. (argv[i][0] != '/'))
  150. break;
  151. switch (argv[i][1]) {
  152. case 'B':
  153. b_flag = 1;
  154. break;
  155. case 't':
  156. trans = 1;
  157. break;
  158. case 'f':
  159. trans = 1;
  160. filename = &argv[i][2];
  161. break;
  162. case 'r':
  163. trans = 0;
  164. break;
  165. case 'd':
  166. options |= SO_DEBUG;
  167. break;
  168. case 'D':
  169. nodelay = 1;
  170. break;
  171. case 'n':
  172. nbuf = atoi(&argv[i][2]);
  173. break;
  174. case 'l':
  175. buflen = atoi(&argv[i][2]);
  176. break;
  177. case 'h':
  178. sobuf = atoi(&argv[i][2]);
  179. break;
  180. case 'H':
  181. hops = atoi(&argv[i][2]);
  182. break;
  183. case 's':
  184. sinkmode = 0; /* sink/source data */
  185. break;
  186. case 'p':
  187. port = (short) atoi(&argv[i][2]);
  188. break;
  189. case 'u':
  190. udp = 1;
  191. connecttest = 0;
  192. if (argv[i][2] == '\0')
  193. udpcoverage = 0;
  194. else
  195. udpcoverage = atoi(&argv[i][2]);
  196. break;
  197. case 'v':
  198. verbose = 1;
  199. break;
  200. case 'A':
  201. bufalign = atoi(&argv[i][2]);
  202. break;
  203. case 'O':
  204. bufoffset = atoi(&argv[i][2]);
  205. break;
  206. case 'c':
  207. udp_connect = 1;
  208. break;
  209. case 'a':
  210. if (argv[i][2] == '\0') {
  211. async = 3;
  212. } else {
  213. async = atoi(&argv[i][2]);
  214. }
  215. break;
  216. case 'C':
  217. connecttest = 1;
  218. udp = 0;
  219. break;
  220. case 'S':
  221. if (!parse_addr(&argv[i][2], sinsrc))
  222. err(TTCP_MESSAGE_31); // "bad source address"
  223. break;
  224. case 'w':
  225. if (argv[i][2] == '\0')
  226. goto usage;
  227. write_delay = atoi(&argv[i][2]);
  228. break;
  229. case 'P':
  230. if (argv[i][2] == '4')
  231. prot = PF_INET;
  232. else if (argv[i][2] == '6')
  233. prot = PF_INET6;
  234. else
  235. goto usage;
  236. break;
  237. case 'j':
  238. trans = 0;
  239. udp = 1;
  240. // Figure out if this is an IPv4 or IPv6 group.
  241. if (NT_SUCCESS(RtlIpv6StringToAddressA(&argv[i][2],
  242. &Term,
  243. &IPv6Group))) {
  244. // We should use IPv6.
  245. if (prot == 0)
  246. prot = PF_INET6;
  247. else if (prot != PF_INET6)
  248. goto usage;
  249. }
  250. else if (NT_SUCCESS(RtlIpv4StringToAddressA(&argv[i][2],
  251. TRUE,
  252. &Term,
  253. &IPv4Group))) {
  254. // We should use IPv4.
  255. if (prot == 0)
  256. prot = PF_INET;
  257. else if (prot != PF_INET)
  258. goto usage;
  259. }
  260. else
  261. goto usage;
  262. // Sanity-check the interface index, if present.
  263. if (*Term == '\0')
  264. ; // No interface index.
  265. else if (*Term == '/') {
  266. if (atoi(Term+1) == 0)
  267. goto usage;
  268. } else
  269. goto usage;
  270. break;
  271. default:
  272. goto usage;
  273. }
  274. }
  275. if (filename != NULL) {
  276. filehandle = CreateFile(
  277. filename,
  278. GENERIC_READ,
  279. FILE_SHARE_READ,
  280. NULL,
  281. OPEN_EXISTING,
  282. FILE_ATTRIBUTE_NORMAL,
  283. NULL
  284. );
  285. if ( filehandle == INVALID_HANDLE_VALUE ) {
  286. NlsPutMsg(STDOUT, TTCP_MESSAGE_1, filename, GetLastError());
  287. // printf("failed to open file %s: %ld\n", filename, GetLastError( ) );
  288. exit(1);
  289. }
  290. NlsPutMsg(STDOUT, TTCP_MESSAGE_2, filename );
  291. // printf("ttcp-t: opened file %s\n", filename );
  292. }
  293. if ((async != 0) && trans && (sobuf == SOBUF_DEFAULT)) {
  294. sobuf = 0;
  295. NlsPutMsg(STDOUT, TTCP_MESSAGE_3);
  296. // printf("ttcp-t: for async write, setting SO_SNDBUF to 0.\n");
  297. }
  298. if (udp && !trans && (sobuf == SOBUF_DEFAULT))
  299. sobuf = 65536;
  300. if (connecttest) {
  301. INT zero = 0;
  302. // ??? What is this?
  303. // disable socket sharing in the process
  304. setsockopt((SOCKET)NULL, SOL_SOCKET, 0x8002, (char *)&zero, 4);
  305. }
  306. if (trans) {
  307. /* xmitr */
  308. struct addrinfo hints;
  309. if (i + 1 != argc) goto usage;
  310. host = argv[i];
  311. memset(&hints, 0, sizeof hints);
  312. hints.ai_flags = AI_NUMERICHOST;
  313. hints.ai_family = prot;
  314. if (getaddrinfo(host, NULL, &hints, &aihim) != 0) {
  315. struct addrinfo *aitmp;
  316. hints.ai_flags = AI_CANONNAME;
  317. if (getaddrinfo(host, NULL, &hints, &aihim) != 0)
  318. err(TTCP_MESSAGE_32); // "getaddrinfo"
  319. for (aitmp = aihim; aitmp != NULL; aitmp = aitmp->ai_next)
  320. NlsPutMsg(STDOUT, TTCP_MESSAGE_4,
  321. aihim->ai_canonname,
  322. format_addr(aitmp->ai_addr));
  323. // printf("ttcp-t: %s -> %s\n",
  324. // aihim->ai_canonname,
  325. // format_addr(aitmp->ai_addr));
  326. }
  327. retry:
  328. if (aihim == NULL)
  329. err(TTCP_MESSAGE_54); // "connect"
  330. memcpy(sinhim, aihim->ai_addr, aihim->ai_addrlen);
  331. aihim = aihim->ai_next;
  332. memcpy(sinme, sinsrc, sizeof(struct sockaddr_storage));
  333. if (sinme->sa_family == 0) {
  334. // Use same family as destination.
  335. sinme->sa_family = sinhim->sa_family;
  336. } else {
  337. // Source and destination family should be the same.
  338. // Let connect() check for this.
  339. }
  340. set_port(sinhim, htons(port));
  341. set_port(sinme, 0); // free choice
  342. } else {
  343. /* rcvr */
  344. if (i != argc) goto usage;
  345. memcpy(sinme, sinsrc, sizeof(struct sockaddr_storage));
  346. if (sinme->sa_family == 0)
  347. sinme->sa_family = prot;
  348. set_port(sinme, htons(port));
  349. }
  350. //
  351. // Create the socket and prepare it for the test.
  352. //
  353. if (trans) {
  354. fd = socket(sinme->sa_family, udp?SOCK_DGRAM:SOCK_STREAM, 0);
  355. if (fd == SOCKET_ERROR)
  356. err(TTCP_MESSAGE_48); // "socket"
  357. if (bind(fd, sinme, addr_len(sinme)) < 0)
  358. err(TTCP_MESSAGE_33); // "bind"
  359. if (options) {
  360. #if defined(BSD42)
  361. if (setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
  362. #else // BSD43
  363. if (setsockopt(fd, SOL_SOCKET, options,
  364. (char *)&one, sizeof(one)) < 0)
  365. #endif
  366. err(TTCP_MESSAGE_50); // "setsockopt"
  367. }
  368. if (!udp && nodelay) {
  369. if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
  370. (char *)&one, sizeof(one)) < 0)
  371. err(TTCP_MESSAGE_34); // "setsockopt: nodelay"
  372. }
  373. if (udp && udpcoverage) {
  374. if (setsockopt(fd, IPPROTO_UDP, UDP_CHECKSUM_COVERAGE,
  375. (char *)&udpcoverage, sizeof(udpcoverage)) < 0)
  376. err(TTCP_MESSAGE_35); // "setsockopt: udp checksum coverage"
  377. }
  378. if (sobuf != SOBUF_DEFAULT) {
  379. if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
  380. (char *)&sobuf, sizeof(sobuf)) < 0)
  381. err(TTCP_MESSAGE_36); // "setsockopt: SO_SNDBUF"
  382. }
  383. if (hops != -1) {
  384. switch (sinme->sa_family) {
  385. case AF_INET:
  386. if (setsockopt(fd, IPPROTO_IP, IP_TTL,
  387. (char *)&hops, sizeof(hops)) < 0)
  388. err(TTCP_MESSAGE_37); // "setsockopt: IP_TTL"
  389. if (udp) {
  390. if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
  391. (char *)&hops, sizeof(hops)) < 0)
  392. err(TTCP_MESSAGE_38); // "setsockopt: IP_MULTICAST_TTL"
  393. }
  394. break;
  395. case AF_INET6:
  396. if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
  397. (char *)&hops, sizeof(hops)) < 0)
  398. err(TTCP_MESSAGE_39); // "setsockopt: IPV6_UNICAST_HOPS"
  399. if (udp) {
  400. if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
  401. (char *)&hops, sizeof(hops)) < 0)
  402. err(TTCP_MESSAGE_40); // "setsockopt: IPV6_MULTICAST_HOPS"
  403. }
  404. break;
  405. }
  406. }
  407. if (!udp || udp_connect) {
  408. if (connect(fd, sinhim, addr_len(sinhim)) < 0)
  409. goto retry;
  410. tmpbuf = sizeof(struct sockaddr_storage);
  411. if (getpeername(fd, (struct sockaddr *)sinhim, &tmpbuf) < 0)
  412. err(TTCP_MESSAGE_41); // "getpeername"
  413. }
  414. tmpbuf = sizeof(struct sockaddr_storage);
  415. if (getsockname(fd, (struct sockaddr *)sinme, &tmpbuf) < 0)
  416. err(TTCP_MESSAGE_42); // "getsockname"
  417. } else { // if not (trans)
  418. if (sinme->sa_family == 0) {
  419. SOCKET fd4, fd6;
  420. fd_set fdset;
  421. int numsockets;
  422. struct sockaddr_in sin;
  423. struct sockaddr_in6 sin6;
  424. //
  425. // We do not know apriori whether to use IPv4 or IPv6.
  426. // So we create two sockets and listen on both.
  427. // socket() will fail if the protocol is not installed,
  428. // and bind() will fail if the stack is stopped,
  429. // so we allow for those errors.
  430. //
  431. FD_ZERO(&fdset);
  432. numsockets = 0;
  433. fd4 = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0);
  434. if (fd4 != INVALID_SOCKET) {
  435. memset(&sin, 0, sizeof sin);
  436. sin.sin_family = AF_INET;
  437. sin.sin_port = get_port(sinme);
  438. if (bind(fd4, (struct sockaddr *)&sin, sizeof sin) == 0) {
  439. if (!udp) {
  440. if (hops != -1) {
  441. if (setsockopt(fd4, IPPROTO_IP, IP_TTL,
  442. (char *)&hops, sizeof(hops)) < 0)
  443. err(TTCP_MESSAGE_37); // "setsockopt: IP_TTL"
  444. }
  445. if (listen(fd4, 0) < 0)
  446. err(TTCP_MESSAGE_44); // "listen"
  447. }
  448. numsockets++;
  449. FD_SET(fd4, &fdset);
  450. }
  451. }
  452. fd6 = socket(AF_INET6, udp?SOCK_DGRAM:SOCK_STREAM, 0);
  453. if (fd6 != INVALID_SOCKET) {
  454. memset(&sin6, 0, sizeof sin6);
  455. sin6.sin6_family = AF_INET6;
  456. sin6.sin6_port = get_port(sinme);
  457. if (bind(fd6, (struct sockaddr *)&sin6, sizeof sin6) == 0) {
  458. if (!udp) {
  459. if (hops != -1) {
  460. if (setsockopt(fd6, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
  461. (char *)&hops, sizeof(hops)) < 0)
  462. err(TTCP_MESSAGE_39); // "setsockopt: IPV6_UNICAST_HOPS"
  463. }
  464. if (listen(fd6, 0) < 0)
  465. err(TTCP_MESSAGE_44); // "listen"
  466. }
  467. numsockets++;
  468. FD_SET(fd6, &fdset);
  469. }
  470. }
  471. if (numsockets == 0)
  472. err(TTCP_MESSAGE_48); // "socket"
  473. if (select(numsockets, &fdset, NULL, NULL, NULL) != 1)
  474. err(TTCP_MESSAGE_47); // "select"
  475. if ((fd4 != INVALID_SOCKET) && FD_ISSET(fd4, &fdset)) {
  476. fd = fd4;
  477. memcpy(sinme, &sin, sizeof sin);
  478. }
  479. else if ((fd6 != INVALID_SOCKET) && FD_ISSET(fd6, &fdset)) {
  480. fd = fd6;
  481. memcpy(sinme, &sin6, sizeof sin6);
  482. }
  483. else {
  484. NlsPutMsg(STDOUT, TTCP_MESSAGE_5);
  485. // printf("select() bug\n");
  486. exit(1);
  487. }
  488. } else { // if not (sinme->sa_family == 0)
  489. fd = socket(sinme->sa_family, udp?SOCK_DGRAM:SOCK_STREAM, 0);
  490. if (fd == SOCKET_ERROR)
  491. err(TTCP_MESSAGE_48); // "socket"
  492. if (bind(fd, sinme, addr_len(sinme)) < 0)
  493. err(TTCP_MESSAGE_33); // "bind"
  494. if (!udp) {
  495. if (hops != -1) {
  496. switch (sinme->sa_family) {
  497. case AF_INET:
  498. if (setsockopt(fd, IPPROTO_IP, IP_TTL,
  499. (char *)&hops, sizeof(hops)) < 0)
  500. err(TTCP_MESSAGE_43); // "setsockopt: IP_TTL"
  501. break;
  502. case AF_INET6:
  503. if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
  504. (char *)&hops, sizeof(hops)) < 0)
  505. err(TTCP_MESSAGE_39); // "setsockopt: IPV6_UNICAST_HOPS"
  506. break;
  507. }
  508. }
  509. if (listen(fd, 0) < 0) /* allow a queue of 0 */
  510. err(TTCP_MESSAGE_44); // "listen"
  511. }
  512. } // end if (sinme->sa_family == 0)
  513. if (options) {
  514. #if defined(BSD42)
  515. if (setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
  516. #else // BSD43
  517. if (setsockopt(fd, SOL_SOCKET, options,
  518. (char *)&one, sizeof(one)) < 0)
  519. #endif
  520. err(TTCP_MESSAGE_50); // "setsockopt"
  521. }
  522. if (sobuf != SOBUF_DEFAULT) {
  523. if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
  524. (char *)&sobuf, sizeof(sobuf)) < 0)
  525. err(TTCP_MESSAGE_51); // "setsockopt: SO_RCVBUF"
  526. }
  527. if (!udp) {
  528. tmpbuf = sizeof(struct sockaddr_storage);
  529. fd2 = accept(fd, (struct sockaddr *)sinhim, &tmpbuf);
  530. if (fd2 == SOCKET_ERROR)
  531. err(TTCP_MESSAGE_52); // "accept"
  532. tmpbuf = sizeof(struct sockaddr_storage);
  533. if (getsockname(fd2, (struct sockaddr *)sinme, &tmpbuf) < 0)
  534. err(TTCP_MESSAGE_42); // "getsockname"
  535. } else {
  536. tmpbuf = sizeof(struct sockaddr_storage);
  537. if (getsockname(fd, (struct sockaddr *)sinme, &tmpbuf) < 0)
  538. err(TTCP_MESSAGE_42); // "getsockname"
  539. // Join multicast groups.
  540. for (i = 1; i < argc; i++) {
  541. if ((argv[i][0] != '-') &&
  542. (argv[i][0] != '/'))
  543. break;
  544. if (argv[i][1] == 'j') {
  545. if (sinme->sa_family == AF_INET) {
  546. struct ip_mreq mreq;
  547. (void) RtlIpv4StringToAddressA(&argv[i][2],
  548. TRUE,
  549. &Term,
  550. &mreq.imr_multiaddr);
  551. if ((*Term == ':') || (*Term == '/')) {
  552. // In Whistler, this ioctl allows an
  553. // interface index in addition to an address.
  554. mreq.imr_interface.s_addr = htonl(atoi(Term+1));
  555. } else {
  556. mreq.imr_interface.s_addr = 0;
  557. }
  558. if (setsockopt(fd, IPPROTO_IP,
  559. IP_ADD_MEMBERSHIP,
  560. (char *)&mreq, sizeof mreq) < 0)
  561. err(TTCP_MESSAGE_SSO_IP_ADD_MEMBERSHIP);
  562. } else { // sinme->sa_family == AF_INET6
  563. struct ipv6_mreq mreq;
  564. (void) RtlIpv6StringToAddressA(&argv[i][2],
  565. &Term,
  566. &mreq.ipv6mr_multiaddr);
  567. if ((*Term == ':') || (*Term == '/')) {
  568. mreq.ipv6mr_interface = atoi(Term+1);
  569. } else {
  570. mreq.ipv6mr_interface = 0;
  571. }
  572. if (setsockopt(fd, IPPROTO_IPV6,
  573. IPV6_ADD_MEMBERSHIP,
  574. (char *)&mreq, sizeof mreq) < 0)
  575. err(TTCP_MESSAGE_SSO_IPV6_ADD_MEMBERSHIP);
  576. }
  577. }
  578. }
  579. }
  580. } // end if (trans)
  581. if (trans) {
  582. NlsPutMsg(STDOUT, TTCP_MESSAGE_6, format_addr(sinme));
  583. // printf("ttcp-t: local %s", format_addr(sinme));
  584. NlsPutMsg(STDOUT, TTCP_MESSAGE_7, format_addr(sinhim));
  585. // printf(" -> remote %s\n", format_addr(sinhim));
  586. } else {
  587. NlsPutMsg(STDOUT, TTCP_MESSAGE_8, format_addr(sinme));
  588. // printf("ttcp-r: local %s", format_addr(sinme));
  589. if (udp)
  590. NlsPutMsg(STDOUT, TTCP_MESSAGE_9);
  591. // printf("\n");
  592. else
  593. NlsPutMsg(STDOUT, TTCP_MESSAGE_10, format_addr(sinhim));
  594. // printf(" <- remote %s\n", format_addr(sinhim));
  595. }
  596. if (connecttest) {
  597. //
  598. // Instead of testing data transfer,
  599. // test connection setup/teardown.
  600. //
  601. if (trans) {
  602. //
  603. // Close the socket that we have from above.
  604. //
  605. closesocket(fd);
  606. prep_timer();
  607. for (i = 1; i < nbuf; i++) {
  608. fd = socket(sinme->sa_family, SOCK_STREAM, 0);
  609. if (fd == INVALID_SOCKET)
  610. err(TTCP_MESSAGE_48); // "socket"
  611. if (bind(fd, sinme, addr_len(sinme)) < 0)
  612. err(TTCP_MESSAGE_33); // "bind"
  613. if (connect(fd, sinhim, addr_len(sinhim)) < 0)
  614. err(TTCP_MESSAGE_54); // "connect"
  615. if (recv(fd, (char *)&tmpbuf, sizeof(tmpbuf), 0) < 0)
  616. err(TTCP_MESSAGE_55); // "recv"
  617. closesocket(fd);
  618. }
  619. } else { // if not (trans)
  620. //
  621. // Close the socket that we have from above.
  622. //
  623. closesocket(fd2);
  624. prep_timer();
  625. for (i = 1; i < nbuf; i++) {
  626. fd2 = accept(fd, NULL, NULL);
  627. if (fd2 == INVALID_SOCKET)
  628. err(TTCP_MESSAGE_52); // "accept"
  629. closesocket(fd2);
  630. }
  631. } // end if (trans)
  632. numCalls = i;
  633. (void)read_timer(stats,sizeof(stats));
  634. goto display;
  635. } // end if (connecttest)
  636. //
  637. // Send/receive data using the socket.
  638. //
  639. if (!udp && !trans) {
  640. fd = fd2;
  641. }
  642. if (udp && buflen < 5) {
  643. buflen = 5; /* send more than the sentinel size */
  644. }
  645. if ( (buf = (char *)malloc(buflen+bufalign)) == (char *)NULL)
  646. err(TTCP_MESSAGE_57); // "malloc"
  647. if (bufalign != 0)
  648. buf +=(bufalign - (PtrToUlong(buf) % bufalign) + bufoffset) % bufalign;
  649. if (trans) {
  650. if (udp) {
  651. NlsPutMsg(STDOUT, TTCP_MESSAGE_11,
  652. buflen, nbuf, bufalign, bufoffset, port, argv[i]);
  653. } else {
  654. NlsPutMsg(STDOUT, TTCP_MESSAGE_58,
  655. buflen, nbuf, bufalign, bufoffset, port, argv[i]);
  656. }
  657. // printf("ttcp"
  658. // "-t: buflen=%d, nbuf=%d, align=%d/+%d, port=%d %s -> %s\n",
  659. // buflen, nbuf, bufalign, bufoffset, port,
  660. // udp?"udp":"tcp",
  661. // argv[i]);
  662. } else {
  663. if (udp) {
  664. NlsPutMsg(STDOUT, TTCP_MESSAGE_12,
  665. buflen, nbuf, bufalign, bufoffset, port);
  666. } else {
  667. NlsPutMsg(STDOUT, TTCP_MESSAGE_59,
  668. buflen, nbuf, bufalign, bufoffset, port);
  669. }
  670. // printf("ttcp"
  671. // "-r: buflen=%d, nbuf=%d, align=%d/+%d, port=%d %s\n",
  672. // buflen, nbuf, bufalign, bufoffset, port,
  673. // udp?"udp":"tcp");
  674. }
  675. prep_timer();
  676. if (async != 0) {
  677. TTCP_ASYNC_INFO *info;
  678. HANDLE *events;
  679. info = malloc( sizeof(*info) * async );
  680. if ( info == NULL ) {
  681. NlsPutMsg(STDOUT, TTCP_MESSAGE_13);
  682. // printf("malloc failed.\n" );
  683. exit(1);
  684. }
  685. events = malloc( sizeof(HANDLE) * async );
  686. if ( events == NULL ) {
  687. NlsPutMsg(STDOUT, TTCP_MESSAGE_13);
  688. // printf("malloc failed.\n" );
  689. exit(1);
  690. }
  691. for ( i = 0; i < async; i++ ) {
  692. info[i].Buffer = malloc(buflen);
  693. if ( info[i].Buffer == NULL ) {
  694. NlsPutMsg(STDOUT, TTCP_MESSAGE_13);
  695. // printf("malloc failed.\n" );
  696. exit(1);
  697. }
  698. events[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
  699. if ( events[i] == NULL ) {
  700. NlsPutMsg(STDOUT, TTCP_MESSAGE_14, GetLastError());
  701. // printf("CreateEvent failed: %ld\n", GetLastError( ) );
  702. exit(1);
  703. }
  704. info[i].Overlapped.Internal = 0;
  705. info[i].Overlapped.InternalHigh = 0;
  706. info[i].Overlapped.Offset = 0;
  707. info[i].Overlapped.OffsetHigh = 0;
  708. info[i].Overlapped.hEvent = events[i];
  709. }
  710. if (trans) {
  711. for ( i = 0; i < async; i++ ) {
  712. ret = WriteFile(
  713. (HANDLE)fd,
  714. info[i].Buffer,
  715. buflen,
  716. &info[i].BytesWritten,
  717. &info[i].Overlapped
  718. );
  719. if ( !ret && GetLastError( ) != ERROR_IO_PENDING ) {
  720. NlsPutMsg(STDOUT, TTCP_MESSAGE_15, GetLastError());
  721. // printf("WriteFile failed: %ld\n", GetLastError( ) );
  722. break;
  723. }
  724. nbuf--;
  725. numCalls++;
  726. }
  727. while (nbuf > 0) {
  728. ret = WaitForMultipleObjects( async, events, FALSE, INFINITE );
  729. i = ret - WAIT_OBJECT_0;
  730. ret = GetOverlappedResult(
  731. (HANDLE)fd,
  732. &info[i].Overlapped,
  733. &info[i].BytesWritten,
  734. FALSE
  735. );
  736. if ( !ret ) {
  737. NlsPutMsg(STDOUT, TTCP_MESSAGE_16, GetLastError());
  738. // printf("pended WriteFile failed: %ld\n", GetLastError( ) );
  739. break;
  740. }
  741. nbytes += info[i].BytesWritten;
  742. ret = WriteFile(
  743. (HANDLE)fd,
  744. info[i].Buffer,
  745. buflen,
  746. &info[i].BytesWritten,
  747. &info[i].Overlapped
  748. );
  749. if ( !ret && GetLastError( ) != ERROR_IO_PENDING ) {
  750. NlsPutMsg(STDOUT, TTCP_MESSAGE_15, GetLastError());
  751. // printf("WriteFile failed: %ld\n", GetLastError( ) );
  752. break;
  753. }
  754. nbuf--;
  755. numCalls++;
  756. }
  757. for ( i = 0; i < async; i++ ) {
  758. ret = GetOverlappedResult(
  759. (HANDLE)fd,
  760. &info[i].Overlapped,
  761. &info[i].BytesWritten,
  762. TRUE
  763. );
  764. if ( !ret ) {
  765. NlsPutMsg(STDOUT, TTCP_MESSAGE_16, GetLastError());
  766. // printf("pended WriteFile failed: %ld\n", GetLastError());
  767. break;
  768. }
  769. nbytes += info[i].BytesWritten;
  770. }
  771. } else { // if not (trans)
  772. for ( i = 0; i < async; i++ ) {
  773. ret = ReadFile(
  774. (HANDLE)fd,
  775. info[i].Buffer,
  776. buflen,
  777. &info[i].BytesWritten,
  778. &info[i].Overlapped
  779. );
  780. if ( !ret && GetLastError( ) != ERROR_IO_PENDING ) {
  781. NlsPutMsg(STDOUT, TTCP_MESSAGE_17, GetLastError());
  782. // printf("ReadFile failed: %ld\n", GetLastError( ) );
  783. break;
  784. }
  785. nbuf--;
  786. numCalls++;
  787. }
  788. while (TRUE) {
  789. ret = WaitForMultipleObjects( async, events, FALSE, INFINITE );
  790. i = ret - WAIT_OBJECT_0;
  791. ret = GetOverlappedResult(
  792. (HANDLE)fd,
  793. &info[i].Overlapped,
  794. &info[i].BytesWritten,
  795. FALSE
  796. );
  797. if ( !ret ) {
  798. NlsPutMsg(STDOUT, TTCP_MESSAGE_18, GetLastError());
  799. // printf("pended ReadFile failed: %ld\n", GetLastError( ) );
  800. break;
  801. }
  802. nbytes += info[i].BytesWritten;
  803. if (info[i].BytesWritten == 0) {
  804. break;
  805. }
  806. ret = ReadFile(
  807. (HANDLE)fd,
  808. info[i].Buffer,
  809. buflen,
  810. &info[i].BytesWritten,
  811. &info[i].Overlapped
  812. );
  813. if ( !ret && GetLastError( ) != ERROR_IO_PENDING ) {
  814. NlsPutMsg(STDOUT, TTCP_MESSAGE_17, GetLastError());
  815. // printf("ReadFile failed: %ld\n", GetLastError( ) );
  816. break;
  817. }
  818. nbuf--;
  819. numCalls++;
  820. }
  821. for ( i = 0; i < async; i++ ) {
  822. ret = GetOverlappedResult(
  823. (HANDLE)fd,
  824. &info[i].Overlapped,
  825. &info[i].BytesWritten,
  826. TRUE
  827. );
  828. if ( !ret ) {
  829. NlsPutMsg(STDOUT, TTCP_MESSAGE_18, GetLastError( ) );
  830. // printf("pended ReadFile failed: %ld\n", GetLastError( ) );
  831. break;
  832. }
  833. nbytes += info[i].BytesWritten;
  834. }
  835. } // end if (trans)
  836. } // end if (async != 0)
  837. else if (filename != NULL ) {
  838. ret = TransmitFile( fd, filehandle,
  839. 0, // nNumberOfBytesToWrite
  840. 0, // nNumberOfBytesPerSend
  841. NULL, // lpOverlapped
  842. NULL, // lpTransmitBuffers
  843. 0 ); // dwFlags
  844. if ( !ret ) {
  845. NlsPutMsg(STDOUT, TTCP_MESSAGE_19, GetLastError());
  846. // printf("TransmitFile failed: %ld\n", GetLastError( ) );
  847. exit(1);
  848. }
  849. } else if (sinkmode) {
  850. register int cnt;
  851. if (trans) {
  852. pattern( buf, buflen );
  853. if(udp) (void)Nwrite( fd, buf, 4 ); /* rcvr start */
  854. while (nbuf-- && Nwrite(fd,buf,buflen) == buflen)
  855. nbytes += buflen;
  856. NlsPutMsg(STDOUT, TTCP_MESSAGE_20, nbuf);
  857. // printf("ttcp-t: done sending, nbuf = %d\n", nbuf );
  858. if(udp) {
  859. Sleep( 10 );
  860. (void)Nwrite( fd, buf, 4 ); /* rcvr end */
  861. }
  862. } else {
  863. if (udp) {
  864. while ((cnt=Nread(fd,buf,buflen)) > 0) {
  865. static int going = 0;
  866. if( cnt <= 4 ) {
  867. if( going ) {
  868. break; /* "EOF" */
  869. }
  870. going = 1;
  871. prep_timer();
  872. } else {
  873. nbytes += cnt;
  874. }
  875. }
  876. } else {
  877. while ((cnt=Nread(fd,buf,buflen)) > 0) {
  878. nbytes += cnt;
  879. }
  880. }
  881. }
  882. } else {
  883. register int cnt;
  884. if (trans) {
  885. while((cnt=_read(0,buf,buflen)) > 0 &&
  886. Nwrite(fd,buf,cnt) == cnt)
  887. nbytes += cnt;
  888. } else {
  889. while((cnt=Nread(fd,buf,buflen)) > 0 &&
  890. _write(1,buf,cnt) == cnt)
  891. nbytes += cnt;
  892. }
  893. }
  894. //if(errno) err(TTCP_MESSAGE_); // "IO"
  895. (void)read_timer(stats,sizeof(stats));
  896. if(udp&&trans) {
  897. (void)Nwrite( fd, buf, 4 ); /* rcvr end */
  898. (void)Nwrite( fd, buf, 4 ); /* rcvr end */
  899. (void)Nwrite( fd, buf, 4 ); /* rcvr end */
  900. (void)Nwrite( fd, buf, 4 ); /* rcvr end */
  901. }
  902. display:
  903. closesocket(fd);
  904. //if( cput <= 0.0 ) cput = 0.001;
  905. if ( numCalls == 0 ) {
  906. numCalls = 1;
  907. }
  908. if ( realt == 0 ) {
  909. realt = 1;
  910. }
  911. if (trans) {
  912. NlsPutMsg(STDOUT, TTCP_MESSAGE_21,
  913. nbytes, realt,
  914. (int)((1000.0*(nbytes/(double)realt))/1024.0));
  915. } else {
  916. NlsPutMsg(STDOUT, TTCP_MESSAGE_60,
  917. nbytes, realt,
  918. (int)((1000.0*(nbytes/(double)realt))/1024.0));
  919. }
  920. // printf("ttcp"
  921. // "%s: %ld bytes in %ld real milliseconds = %ld KB/sec\n",
  922. // trans?"-t":"-r",
  923. // nbytes, realt, (int)((1000.0*(nbytes/(double)realt))/1024.0) );
  924. #if 0
  925. printf("ttcp"
  926. "%s: %ld bytes in %.2f CPU seconds = %.2f KB/cpu sec\n",
  927. trans?"-t":"-r",
  928. nbytes, cput, ((double)nbytes)/cput/1024 );
  929. #endif
  930. if (trans) {
  931. NlsPutMsg(STDOUT, TTCP_MESSAGE_22,
  932. numCalls, realt/numCalls,
  933. (1000*numCalls)/realt, nbytes/numCalls);
  934. } else {
  935. NlsPutMsg(STDOUT, TTCP_MESSAGE_61,
  936. numCalls, realt/numCalls,
  937. (1000*numCalls)/realt, nbytes/numCalls);
  938. }
  939. // printf("ttcp"
  940. // "%s: %ld I/O calls, msec/call = %ld, calls/sec = %ld, "
  941. // "bytes/call = %ld\n",
  942. // trans?"-t":"-r",
  943. // numCalls,
  944. // realt/numCalls,
  945. // (1000*numCalls)/realt,
  946. // nbytes/numCalls);
  947. #if 0
  948. printf("ttcp%s: %s\n", trans?"-t":"-r", stats);
  949. #endif
  950. #if 0
  951. printf("ttcp%s: system CPU %ld%%, User %ld%%, Kernel %ld%%, "
  952. "User/Kernel ratio %ld%%\n",
  953. trans?"-t":"-r",
  954. ((systemUserTime+systemKernelTime)*100+50)/realt,
  955. (systemUserTime*100+50)/realt,
  956. (systemKernelTime*100+50)/realt,
  957. (systemUserTime+systemKernelTime == 0) ? 100 :
  958. (systemUserTime*100+50)/(systemUserTime+systemKernelTime));
  959. fprintf(stdout, "ttcp%s: process CPU %ld%%, User %ld%%, Kernel %ld%%, "
  960. "User/Kernel ratio %ld%%\n",
  961. trans?"-t":"-r",
  962. ((processUserTime+processKernelTime)*100+50)/realt,
  963. (processUserTime*100+50)/realt,
  964. (processKernelTime*100+50)/realt,
  965. (processUserTime+processKernelTime == 0) ? 100 :
  966. (processUserTime*100+50)/(processUserTime+processKernelTime));
  967. #endif
  968. if (verbose) {
  969. if (trans) {
  970. NlsPutMsg(STDOUT, TTCP_MESSAGE_23, buf);
  971. } else {
  972. NlsPutMsg(STDOUT, TTCP_MESSAGE_62, buf);
  973. }
  974. // printf("ttcp%s: buffer address %#p\n", trans?"-t":"-r", buf);
  975. }
  976. WSACleanup();
  977. exit(0);
  978. usage:
  979. NlsPutMsg(STDERR, TTCP_MESSAGE_24);
  980. // fprintf(stderr, "Usage: ttcp -t [-options] host [ < in ]\n");
  981. // fprintf(stderr," ttcp -r [-options > out]\n");
  982. // fprintf(stderr,"Common options:\n");
  983. // fprintf(stderr," -l## length of bufs read from or written to network (default 8192)\n");
  984. // fprintf(stderr," -u use UDP instead of TCP\n");
  985. // fprintf(stderr," -p## port number to send to or listen at (default 5001)\n");
  986. // fprintf(stderr," -P4 use IPv4\n");
  987. // fprintf(stderr," -P6 use IPv6\n");
  988. // fprintf(stderr," -s -t: don't source a pattern to network, get data from stdin\n");
  989. // fprintf(stderr," -r: don't sink (discard), print data on stdout\n");
  990. // fprintf(stderr," -A align the start of buffers to this modulus (default 16384)\n");
  991. // fprintf(stderr," -O start buffers at this offset from the modulus (default 0)\n");
  992. // fprintf(stderr," -v verbose: print more statistics\n");
  993. // fprintf(stderr," -d set SO_DEBUG socket option\n");
  994. // fprintf(stderr," -h set SO_SNDBUF or SO_RCVBUF\n");
  995. // fprintf(stderr," -a use asynchronous I/O calls\n");
  996. // fprintf(stderr," -S## specify source address\n");
  997. // fprintf(stderr," -H## specify TTL or hop limit\n");
  998. // fprintf(stderr,"Options specific to -t:\n");
  999. // fprintf(stderr," -n## number of source bufs written to network (default 2048)\n");
  1000. // fprintf(stderr," -D don't buffer TCP writes (sets TCP_NODELAY socket option)\n");
  1001. // fprintf(stderr," -w## milliseconds of delay before each write\n");
  1002. // fprintf(stderr," -f## specify a file name for TransmitFile\n");
  1003. // fprintf(stderr,"Options specific to -r:\n");
  1004. // fprintf(stderr," -B for -s, only output full blocks as specified by -l (for TAR)\n");
  1005. // fprintf(stderr," -j##[/##] specify multicast group and optional ifindex (UDP-only)\n");
  1006. WSACleanup();
  1007. exit(1);
  1008. }
  1009. void err(message)
  1010. unsigned int message;
  1011. {
  1012. if (trans) {
  1013. NlsPutMsg(STDOUT, TTCP_MESSAGE_25);
  1014. } else {
  1015. NlsPutMsg(STDOUT, TTCP_MESSAGE_63);
  1016. }
  1017. // fprintf(stdout, "ttcp%s: ", trans?"-t":"-r");
  1018. NlsPerror(message, WSAGetLastError());
  1019. // perror(message);
  1020. NlsPutMsg(STDERR, TTCP_MESSAGE_26, WSAGetLastError());
  1021. // fprintf(stderr, "errno=%d\n",WSAGetLastError());
  1022. WSACleanup();
  1023. exit(1);
  1024. }
  1025. void pattern( cp, cnt )
  1026. register char *cp;
  1027. register int cnt;
  1028. {
  1029. register char c;
  1030. c = 0;
  1031. while( cnt-- > 0 ) {
  1032. while( !isprint((c&0x7F)) ) c++;
  1033. *cp++ = (c++&0x7F);
  1034. }
  1035. }
  1036. static void prusage();
  1037. static void tvadd();
  1038. static void tvsub();
  1039. static void psecs();
  1040. #if defined(SYSV)
  1041. /*ARGSUSED*/
  1042. static
  1043. getrusage(ignored, ru)
  1044. int ignored;
  1045. register struct rusage *ru;
  1046. {
  1047. struct tms buf;
  1048. times(&buf);
  1049. /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
  1050. ru->ru_stime.tv_sec = buf.tms_stime / HZ;
  1051. ru->ru_stime.tv_usec = ((buf.tms_stime % HZ) * 1000000) / HZ;
  1052. ru->ru_utime.tv_sec = buf.tms_utime / HZ;
  1053. ru->ru_utime.tv_usec = ((buf.tms_utime % HZ) * 1000000) / HZ;
  1054. }
  1055. #if !defined(sgi)
  1056. /*ARGSUSED*/
  1057. static
  1058. gettimeofday(tp, zp)
  1059. struct timeval *tp;
  1060. struct timezone *zp;
  1061. {
  1062. tp->tv_sec = time(0);
  1063. tp->tv_usec = 0;
  1064. }
  1065. #endif
  1066. #endif // SYSV
  1067. __int64 time0;
  1068. __int64 time1;
  1069. __int64 freq;
  1070. /*
  1071. * P R E P _ T I M E R
  1072. */
  1073. void
  1074. prep_timer()
  1075. {
  1076. #if 0
  1077. gettimeofday(&time0, (struct timezone *)0);
  1078. getrusage(RUSAGE_SELF, &ru0);
  1079. #endif
  1080. (void) QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
  1081. (void) QueryPerformanceCounter((LARGE_INTEGER *)&time0);
  1082. }
  1083. /*
  1084. * R E A D _ T I M E R
  1085. *
  1086. */
  1087. double
  1088. read_timer(str,len)
  1089. char *str;
  1090. int len;
  1091. {
  1092. #if 0
  1093. char line[132];
  1094. getrusage(RUSAGE_SELF, &ru1);
  1095. gettimeofday(&timedol, (struct timezone *)0);
  1096. prusage(&ru0, &ru1, &timedol, &time0, line);
  1097. (void)strncpy( str, line, len );
  1098. /* Get real time */
  1099. tvsub( &td, &timedol, &time0 );
  1100. realt = td.tv_sec + ((double)td.tv_usec) / 1000000;
  1101. /* Get CPU time (user+sys) */
  1102. tvadd( &tend, &ru1.ru_utime, &ru1.ru_stime );
  1103. tvadd( &tstart, &ru0.ru_utime, &ru0.ru_stime );
  1104. tvsub( &td, &tend, &tstart );
  1105. cput = td.tv_sec + ((double)td.tv_usec) / 1000000;
  1106. if( cput < 0.00001 ) cput = 0.00001;
  1107. return( cput );
  1108. #endif
  1109. (void) QueryPerformanceCounter((LARGE_INTEGER *)&time1);
  1110. // realt is real elapsed time in milliseconds
  1111. realt = (DWORD) ((1000 * (time1 - time0)) / freq);
  1112. return 0;
  1113. }
  1114. #if 0
  1115. static void
  1116. prusage(r0, r1, e, b, outp)
  1117. register struct rusage *r0, *r1;
  1118. struct timeval *e, *b;
  1119. char *outp;
  1120. {
  1121. struct timeval tdiff;
  1122. register time_t t;
  1123. register char *cp;
  1124. register int i;
  1125. int ms;
  1126. t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
  1127. (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
  1128. (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
  1129. (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
  1130. ms = (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
  1131. #define END(x) {while(*x) x++;}
  1132. #if defined(SYSV)
  1133. cp = "%Uuser %Zsys %Ereal %P";
  1134. #else
  1135. cp = "%Uuser %Zsys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Xcsw";
  1136. #endif
  1137. for (; *cp; cp++) {
  1138. if (*cp != '%')
  1139. *outp++ = *cp;
  1140. else if (cp[1]) switch(*++cp) {
  1141. case 'U':
  1142. tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
  1143. sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000);
  1144. END(outp);
  1145. break;
  1146. case 'S':
  1147. tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
  1148. sprintf(outp,"%d.%01d", tdiff.tv_sec, tdiff.tv_usec/100000);
  1149. END(outp);
  1150. break;
  1151. case 'E':
  1152. psecs(ms / 100, outp);
  1153. END(outp);
  1154. break;
  1155. case 'P':
  1156. sprintf(outp,"%d%%", (int) (t*100 / ((ms ? ms : 1))));
  1157. END(outp);
  1158. break;
  1159. #if !defined(SYSV)
  1160. case 'W':
  1161. i = r1->ru_nswap - r0->ru_nswap;
  1162. sprintf(outp,"%d", i);
  1163. END(outp);
  1164. break;
  1165. case 'X':
  1166. sprintf(outp,"%d", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
  1167. END(outp);
  1168. break;
  1169. case 'D':
  1170. sprintf(outp,"%d", t == 0 ? 0 :
  1171. (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
  1172. END(outp);
  1173. break;
  1174. case 'K':
  1175. sprintf(outp,"%d", t == 0 ? 0 :
  1176. ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
  1177. (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
  1178. END(outp);
  1179. break;
  1180. case 'M':
  1181. sprintf(outp,"%d", r1->ru_maxrss/2);
  1182. END(outp);
  1183. break;
  1184. case 'F':
  1185. sprintf(outp,"%d", r1->ru_majflt-r0->ru_majflt);
  1186. END(outp);
  1187. break;
  1188. case 'R':
  1189. sprintf(outp,"%d", r1->ru_minflt-r0->ru_minflt);
  1190. END(outp);
  1191. break;
  1192. case 'I':
  1193. sprintf(outp,"%d", r1->ru_inblock-r0->ru_inblock);
  1194. END(outp);
  1195. break;
  1196. case 'O':
  1197. sprintf(outp,"%d", r1->ru_oublock-r0->ru_oublock);
  1198. END(outp);
  1199. break;
  1200. case 'C':
  1201. sprintf(outp,"%d+%d", r1->ru_nvcsw-r0->ru_nvcsw,
  1202. r1->ru_nivcsw-r0->ru_nivcsw );
  1203. END(outp);
  1204. break;
  1205. #endif !SYSV
  1206. }
  1207. }
  1208. *outp = '\0';
  1209. }
  1210. #endif
  1211. static void
  1212. tvadd(tsum, t0, t1)
  1213. struct timeval *tsum, *t0, *t1;
  1214. {
  1215. tsum->tv_sec = t0->tv_sec + t1->tv_sec;
  1216. tsum->tv_usec = t0->tv_usec + t1->tv_usec;
  1217. if (tsum->tv_usec > 1000000)
  1218. tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1219. }
  1220. static void
  1221. tvsub(tdiff, t1, t0)
  1222. struct timeval *tdiff, *t1, *t0;
  1223. {
  1224. tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1225. tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1226. if (tdiff->tv_usec < 0)
  1227. tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  1228. }
  1229. #if 0
  1230. static void
  1231. psecs(l,cp)
  1232. long l;
  1233. register char *cp;
  1234. {
  1235. register int i;
  1236. i = l / 3600;
  1237. if (i) {
  1238. sprintf(cp,"%d:", i);
  1239. END(cp);
  1240. i = l % 3600;
  1241. sprintf(cp,"%d%d", (i/60) / 10, (i/60) % 10);
  1242. END(cp);
  1243. } else {
  1244. i = l;
  1245. sprintf(cp,"%d", i / 60);
  1246. END(cp);
  1247. }
  1248. i %= 60;
  1249. *cp++ = ':';
  1250. sprintf(cp,"%d%d", i / 10, i % 10);
  1251. }
  1252. #endif
  1253. /*
  1254. * N R E A D
  1255. */
  1256. int
  1257. Nread( SOCKET fd, PBYTE buf, INT count )
  1258. {
  1259. static int didit = 0;
  1260. int len = sizeof(sinhimStorage);
  1261. register int cnt;
  1262. if( udp ) {
  1263. if (udp_connect) {
  1264. cnt = recv( fd, buf, count, 0 );
  1265. numCalls++;
  1266. } else {
  1267. cnt = recvfrom( fd, buf, count, 0, sinhim, &len );
  1268. if ((recvfrom > 0) && !didit) {
  1269. didit = 1;
  1270. NlsPutMsg(STDOUT, TTCP_MESSAGE_28, format_addr(sinhim));
  1271. // fprintf(stdout, "ttcp-r: recvfrom %s\n", format_addr(sinhim));
  1272. }
  1273. numCalls++;
  1274. }
  1275. } else {
  1276. if( b_flag )
  1277. cnt = mread( fd, buf, count ); /* fill buf */
  1278. else {
  1279. cnt = recv( fd, buf, count, 0 );
  1280. numCalls++;
  1281. }
  1282. }
  1283. if (cnt<0) {
  1284. NlsPutMsg(STDOUT, TTCP_MESSAGE_29, WSAGetLastError());
  1285. // printf("recv(from) failed: %ld\n", WSAGetLastError( ) );
  1286. }
  1287. return(cnt);
  1288. }
  1289. /*
  1290. * N W R I T E
  1291. */
  1292. int
  1293. Nwrite( SOCKET fd, PBYTE buf, INT count )
  1294. {
  1295. register int cnt = 0;
  1296. int bytesToSend = count;
  1297. if (write_delay)
  1298. Sleep(write_delay);
  1299. if( udp && !udp_connect) {
  1300. again:
  1301. cnt = sendto( fd, buf, count, 0, sinhim, addr_len(sinhim) );
  1302. numCalls++;
  1303. if( cnt<0 && WSAGetLastError( ) == WSAENOBUFS ) {
  1304. Sleep(18000);
  1305. goto again;
  1306. }
  1307. } else {
  1308. while( count > 0 )
  1309. {
  1310. cnt = send( fd, buf, count, 0 );
  1311. numCalls++;
  1312. //if (count != cnt) {
  1313. // printf("Tried %d, sent %d\n", count, cnt );
  1314. //} else {
  1315. // printf("send %d bytes as requested.\n", cnt );
  1316. //}
  1317. if( cnt == SOCKET_ERROR )
  1318. {
  1319. break;
  1320. }
  1321. count -= cnt;
  1322. buf += cnt;
  1323. }
  1324. }
  1325. if (cnt<0) {
  1326. NlsPutMsg(STDOUT, TTCP_MESSAGE_30, WSAGetLastError());
  1327. // printf("send(to) failed: %ld\n", WSAGetLastError( ) );
  1328. return -1;
  1329. }
  1330. return(bytesToSend);
  1331. }
  1332. /*
  1333. * M R E A D
  1334. *
  1335. * This function performs the function of a read(II) but will
  1336. * call read(II) multiple times in order to get the requested
  1337. * number of characters. This can be necessary because
  1338. * network connections don't deliver data with the same
  1339. * grouping as it is written with. Written by Robert S. Miles, BRL.
  1340. */
  1341. int
  1342. mread( SOCKET fd, PBYTE bufp, INT n)
  1343. {
  1344. register unsigned count = 0;
  1345. register int nread;
  1346. do {
  1347. nread = recv(fd, bufp, n-count, 0);
  1348. numCalls++;
  1349. if(nread < 0) {
  1350. return(-1);
  1351. }
  1352. if(nread == 0)
  1353. return((int)count);
  1354. count += (unsigned)nread;
  1355. bufp += nread;
  1356. } while(count < (UINT)n);
  1357. return((int)count);
  1358. }
  1359. int
  1360. parse_addr(char *s, struct sockaddr *sa)
  1361. {
  1362. struct addrinfo hints;
  1363. struct addrinfo *result;
  1364. memset(&hints, 0, sizeof hints);
  1365. hints.ai_family = prot;
  1366. if (getaddrinfo(s, NULL, &hints, &result) != 0)
  1367. return FALSE; // Failed to parse/resolve the address.
  1368. memcpy(sa, result->ai_addr, result->ai_addrlen);
  1369. freeaddrinfo(result);
  1370. return TRUE;
  1371. }
  1372. u_int
  1373. addr_len(struct sockaddr *sa)
  1374. {
  1375. u_int salen;
  1376. switch (sa->sa_family) {
  1377. case AF_INET:
  1378. salen = sizeof(struct sockaddr_in);
  1379. break;
  1380. case AF_INET6:
  1381. salen = sizeof(struct sockaddr_in6);
  1382. break;
  1383. default:
  1384. salen = 0;
  1385. break;
  1386. }
  1387. return salen;
  1388. }
  1389. char *
  1390. format_addr(struct sockaddr *sa)
  1391. {
  1392. static char buffer[NI_MAXHOST];
  1393. if (getnameinfo(sa, addr_len(sa),
  1394. buffer, sizeof buffer,
  1395. NULL, 0, NI_NUMERICHOST) != 0)
  1396. strcpy(buffer, "<invalid>");
  1397. return buffer;
  1398. }
  1399. void
  1400. set_port(struct sockaddr *sa, u_short port)
  1401. {
  1402. //
  1403. // The port field is in the same location
  1404. // for both sockaddr_in and sockaddr_in6.
  1405. //
  1406. ((struct sockaddr_in *)sa)->sin_port = port;
  1407. }
  1408. u_short
  1409. get_port(struct sockaddr *sa)
  1410. {
  1411. //
  1412. // The port field is in the same location
  1413. // for both sockaddr_in and sockaddr_in6.
  1414. //
  1415. return ((struct sockaddr_in *)sa)->sin_port;
  1416. }