Leaked source code of windows server 2003
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.

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