1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
19 #define PORT_INC_DO +100
24 #define PORT_INC_3264 +200
29 #define BASE_PORT 9867 PORT_INC_DO PORT_INC_3264
31 int PR_CALLBACK
Writev(int argc
, char **argv
)
36 PRFileDesc
*clientSock
, *debug
= NULL
;
40 PRBool passed
= PR_TRUE
;
41 PRIntervalTime timein
, elapsed
, timeout
;
42 PRIntervalTime tmo_min
= 0x7fffffff, tmo_max
= 0, tmo_elapsed
= 0;
43 PRInt32 tmo_counted
= 0, iov_index
, loop
, bytes
, number_fragments
;
44 PRInt32 message_length
= 100, fragment_length
= 100, messages
= 100;
52 * -h dns name of host serving the connection (default = self)
53 * -m number of messages to send (default = 100)
54 * -s size of each message (default = 100)
55 * -f size of each message fragment (default = 100)
59 PLOptState
*opt
= PL_CreateOptState(argc
, argv
, "dh:m:s:f:");
62 rv
= PR_InitializeNetAddr(PR_IpAddrLoopback
, BASE_PORT
, &serverAddr
);
63 PR_ASSERT(PR_SUCCESS
== rv
);
65 while (PL_OPT_EOL
!= (os
= PL_GetNextOpt(opt
)))
67 if (PL_OPT_BAD
== os
) {
72 case 'h': /* the remote host */
77 (void)PR_GetHostByName(opt
->value
, buffer
, sizeof(buffer
), &host
);
78 es
= PR_EnumerateHostEnt(es
, &host
, BASE_PORT
, &serverAddr
);
82 case 'd': /* debug mode */
83 debug
= PR_GetSpecialFD(PR_StandardError
);
85 case 'm': /* number of messages to send */
86 messages
= atoi(opt
->value
);
88 case 's': /* total size of each message */
89 message_length
= atoi(opt
->value
);
91 case 'f': /* size of each message fragment */
92 fragment_length
= atoi(opt
->value
);
98 PL_DestroyOptState(opt
);
100 buffer
= (char*)malloc(message_length
);
102 number_fragments
= (message_length
+ fragment_length
- 1) / fragment_length
+ 1;
103 while (IOV_MAX
< number_fragments
)
105 fragment_length
= message_length
/ (IOV_MAX
- 2);
106 number_fragments
= (message_length
+ fragment_length
- 1) /
108 if (NULL
!= debug
) PR_fprintf(debug
,
109 "Too many fragments - reset fragment length to %ld\n", fragment_length
);
111 iov
= (PRIOVec
*)malloc(number_fragments
* sizeof(PRIOVec
));
113 iov
[0].iov_base
= (char*)&descriptor
;
114 iov
[0].iov_len
= sizeof(descriptor
);
115 for (iov_index
= 1; iov_index
< number_fragments
; ++iov_index
)
117 iov
[iov_index
].iov_base
= buffer
+ (iov_index
- 1) * fragment_length
;
118 iov
[iov_index
].iov_len
= fragment_length
;
121 for (bytes
= 0; bytes
< message_length
; ++bytes
) {
122 buffer
[bytes
] = (char)bytes
;
125 timeout
= PR_SecondsToInterval(1);
127 for (loop
= 0; loop
< messages
; ++loop
)
130 PR_fprintf(debug
, "[%d]socket ... ", loop
);
132 clientSock
= PR_NewTCPSocket();
135 timein
= PR_IntervalNow();
137 PR_fprintf(debug
, "connecting ... ");
139 rv
= PR_Connect(clientSock
, &serverAddr
, timeout
);
140 if (PR_SUCCESS
== rv
)
142 descriptor
.checksum
= 0;
143 descriptor
.length
= (loop
< (messages
- 1)) ? message_length
: 0;
144 if (0 == descriptor
.length
) {
145 number_fragments
= 1;
148 for (iov_index
= 0; iov_index
< descriptor
.length
; ++iov_index
)
150 PRUint32 overflow
= descriptor
.checksum
& 0x80000000;
151 descriptor
.checksum
= (descriptor
.checksum
<< 1);
152 if (0x00000000 != overflow
) {
153 descriptor
.checksum
+= 1;
155 descriptor
.checksum
+= buffer
[iov_index
];
157 if (NULL
!= debug
) PR_fprintf(
158 debug
, "sending %d bytes ... ", descriptor
.length
);
160 /* then, at the last moment ... */
161 descriptor
.length
= PR_ntohl(descriptor
.length
);
162 descriptor
.checksum
= PR_ntohl(descriptor
.checksum
);
164 bytes
= PR_Writev(clientSock
, iov
, number_fragments
, timeout
);
166 PR_fprintf(debug
, "closing ... ");
168 rv
= PR_Shutdown(clientSock
, PR_SHUTDOWN_BOTH
);
169 rv
= PR_Close(clientSock
);
170 if (NULL
!= debug
) PR_fprintf(
171 debug
, "%s\n", ((PR_SUCCESS
== rv
) ? "good" : "bad"));
172 elapsed
= PR_IntervalNow() - timein
;
173 if (elapsed
< tmo_min
) {
176 else if (elapsed
> tmo_max
) {
179 tmo_elapsed
+= elapsed
;
184 if (NULL
!= debug
) PR_fprintf(
185 debug
, "failed - retrying (%d, %d)\n",
186 PR_GetError(), PR_GetOSError());
187 PR_Close(clientSock
);
190 else if (NULL
!= debug
)
192 PR_fprintf(debug
, "unable to create client socket\n");
197 if (0 == tmo_counted
) {
198 PR_fprintf(debug
, "No connection made\n");
201 debug
, "\nTimings: %d [%d] %d (microseconds)\n",
202 PR_IntervalToMicroseconds(tmo_min
),
203 PR_IntervalToMicroseconds(tmo_elapsed
/ tmo_counted
),
204 PR_IntervalToMicroseconds(tmo_max
));
212 PR_GetSpecialFD(PR_StandardError
),
213 "%s\n", (passed
) ? "PASSED" : "FAILED");
214 return (passed
) ? 0 : 1;
217 int main(int argc
, char **argv
)
219 return (PR_VersionCheck(PR_VERSION
)) ?
220 PR_Initialize(Writev
, argc
, argv
, 4) : -1;