1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Netscape Portable Runtime (NSPR).
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
47 #define printf PR_LogPrint
55 #define BASE_PORT 9867
57 int PR_CALLBACK
Writev(int argc
, char **argv
)
62 PRFileDesc
*clientSock
, *debug
= NULL
;
66 PRBool passed
= PR_TRUE
;
67 PRIntervalTime timein
, elapsed
, timeout
;
68 PRIntervalTime tmo_min
= 0x7fffffff, tmo_max
= 0, tmo_elapsed
= 0;
69 PRInt32 tmo_counted
= 0, iov_index
, loop
, bytes
, number_fragments
;
70 PRInt32 message_length
= 100, fragment_length
= 100, messages
= 100;
71 struct Descriptor
{ PRInt32 length
; PRUint32 checksum
; } descriptor
;
75 * -h dns name of host serving the connection (default = self)
76 * -m number of messages to send (default = 100)
77 * -s size of each message (default = 100)
78 * -f size of each message fragment (default = 100)
82 PLOptState
*opt
= PL_CreateOptState(argc
, argv
, "dh:m:s:f:");
85 rv
= PR_InitializeNetAddr(PR_IpAddrLoopback
, BASE_PORT
, &serverAddr
);
86 PR_ASSERT(PR_SUCCESS
== rv
);
88 while (PL_OPT_EOL
!= (os
= PL_GetNextOpt(opt
)))
90 if (PL_OPT_BAD
== os
) continue;
93 case 'h': /* the remote host */
98 (void)PR_GetHostByName(opt
->value
, buffer
, sizeof(buffer
), &host
);
99 es
= PR_EnumerateHostEnt(es
, &host
, BASE_PORT
, &serverAddr
);
103 case 'd': /* debug mode */
104 debug
= PR_GetSpecialFD(PR_StandardError
);
106 case 'm': /* number of messages to send */
107 messages
= atoi(opt
->value
);
109 case 's': /* total size of each message */
110 message_length
= atoi(opt
->value
);
112 case 'f': /* size of each message fragment */
113 fragment_length
= atoi(opt
->value
);
119 PL_DestroyOptState(opt
);
121 buffer
= (char*)malloc(message_length
);
123 number_fragments
= (message_length
+ fragment_length
- 1) / fragment_length
+ 1;
124 while (IOV_MAX
< number_fragments
)
126 fragment_length
= message_length
/ (IOV_MAX
- 2);
127 number_fragments
= (message_length
+ fragment_length
- 1) /
129 if (NULL
!= debug
) PR_fprintf(debug
,
130 "Too many fragments - reset fragment length to %ld\n", fragment_length
);
132 iov
= (PRIOVec
*)malloc(number_fragments
* sizeof(PRIOVec
));
134 iov
[0].iov_base
= (char*)&descriptor
;
135 iov
[0].iov_len
= sizeof(descriptor
);
136 for (iov_index
= 1; iov_index
< number_fragments
; ++iov_index
)
138 iov
[iov_index
].iov_base
= buffer
+ (iov_index
- 1) * fragment_length
;
139 iov
[iov_index
].iov_len
= fragment_length
;
142 for (bytes
= 0; bytes
< message_length
; ++bytes
)
143 buffer
[bytes
] = (char)bytes
;
145 timeout
= PR_SecondsToInterval(1);
147 for (loop
= 0; loop
< messages
; ++loop
)
150 PR_fprintf(debug
, "[%d]socket ... ", loop
);
151 clientSock
= PR_NewTCPSocket();
154 timein
= PR_IntervalNow();
156 PR_fprintf(debug
, "connecting ... ");
157 rv
= PR_Connect(clientSock
, &serverAddr
, timeout
);
158 if (PR_SUCCESS
== rv
)
160 descriptor
.checksum
= 0;
161 descriptor
.length
= (loop
< (messages
- 1)) ? message_length
: 0;
162 if (0 == descriptor
.length
) number_fragments
= 1;
164 for (iov_index
= 0; iov_index
< descriptor
.length
; ++iov_index
)
166 PRUint32 overflow
= descriptor
.checksum
& 0x80000000;
167 descriptor
.checksum
= (descriptor
.checksum
<< 1);
168 if (0x00000000 != overflow
) descriptor
.checksum
+= 1;
169 descriptor
.checksum
+= buffer
[iov_index
];
171 if (NULL
!= debug
) PR_fprintf(
172 debug
, "sending %d bytes ... ", descriptor
.length
);
174 /* then, at the last moment ... */
175 descriptor
.length
= PR_ntohl(descriptor
.length
);
176 descriptor
.checksum
= PR_ntohl(descriptor
.checksum
);
178 bytes
= PR_Writev(clientSock
, iov
, number_fragments
, timeout
);
180 PR_fprintf(debug
, "closing ... ");
181 rv
= PR_Shutdown(clientSock
, PR_SHUTDOWN_BOTH
);
182 rv
= PR_Close(clientSock
);
183 if (NULL
!= debug
) PR_fprintf(
184 debug
, "%s\n", ((PR_SUCCESS
== rv
) ? "good" : "bad"));
185 elapsed
= PR_IntervalNow() - timein
;
186 if (elapsed
< tmo_min
) tmo_min
= elapsed
;
187 else if (elapsed
> tmo_max
) tmo_max
= elapsed
;
188 tmo_elapsed
+= elapsed
;
193 if (NULL
!= debug
) PR_fprintf(
194 debug
, "failed - retrying (%d, %d)\n",
195 PR_GetError(), PR_GetOSError());
196 PR_Close(clientSock
);
199 else if (NULL
!= debug
)
201 PR_fprintf(debug
, "unable to create client socket\n");
206 if (0 == tmo_counted
) {
207 PR_fprintf(debug
, "No connection made\n");
210 debug
, "\nTimings: %d [%d] %d (microseconds)\n",
211 PR_IntervalToMicroseconds(tmo_min
),
212 PR_IntervalToMicroseconds(tmo_elapsed
/ tmo_counted
),
213 PR_IntervalToMicroseconds(tmo_max
));
221 PR_GetSpecialFD(PR_StandardError
),
222 "%s\n", (passed
) ? "PASSED" : "FAILED");
223 return (passed
) ? 0 : 1;
226 int main(int argc
, char **argv
)
228 return (PR_VersionCheck(PR_VERSION
)) ?
229 PR_Initialize(Writev
, argc
, argv
, 4) : -1;