]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Sockets/DataSource/DataSource.c
AppPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / AppPkg / Applications / Sockets / DataSource / DataSource.c
CommitLineData
4684b66f 1/** @file\r
2 Data source for network testing.\r
3\r
bcb96695
MK
4 Copyright (c) 2011-2012, Intel Corporation. All rights reserved.\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
4684b66f 6\r
7**/\r
8\r
9#include <errno.h>\r
10#include <Uefi.h>\r
11\r
12#include <Library/BaseMemoryLib.h>\r
13#include <Library/DebugLib.h>\r
14#include <Library/PcdLib.h>\r
15#include <Library/UefiBootServicesTableLib.h>\r
16#include <Library/UefiLib.h>\r
17\r
18#include <netinet/in.h>\r
19\r
20#include <Protocol/ServiceBinding.h>\r
21#include <Protocol/Tcp4.h>\r
22\r
23#include <sys/EfiSysCall.h>\r
24#include <sys/poll.h>\r
25#include <sys/socket.h>\r
26\r
f6e5cdd5 27#include <stdio.h>\r
d3a595ce 28#include <string.h>\r
4684b66f 29\r
f6e5cdd5 30\r
31#define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples\r
32#define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges\r
33#define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates\r
4684b66f 34#define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average\r
f6e5cdd5 35#define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples\r
4684b66f 36\r
37#define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL\r
38\r
39#define PACKET_SIZE 1448 ///< Size of data packets\r
40#define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes\r
41\r
42\r
43//\r
44// Socket Data\r
45//\r
46int Socket = -1;\r
47\r
48//\r
49// TCP V4 Data\r
50//\r
51BOOLEAN bTcp4; ///< TRUE if TCP4 is being used\r
52BOOLEAN bTcp4Connected; ///< TRUE if connected to remote system\r
53BOOLEAN bTcp4Connecting; ///< TRUE while connection in progress\r
54UINTN Tcp4Index; ///< Index into handle array\r
55EFI_HANDLE Tcp4Controller; ///< Network controller handle\r
56EFI_HANDLE Tcp4Handle; ///< TCP4 port handle\r
57EFI_TCP4_PROTOCOL * pTcp4Protocol; ///< TCP4 protocol pointer\r
58EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service; ///< TCP4 Service binding\r
59EFI_TCP4_CONFIG_DATA Tcp4ConfigData;///< TCP4 configuration data\r
60EFI_TCP4_OPTION Tcp4Option; ///< TCP4 port options\r
61EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;///< Close control\r
62EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken; ///< Connection control\r
63EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken; ///< Listen control\r
64EFI_TCP4_IO_TOKEN Tcp4TxToken; ///< Normal data token\r
65\r
66//\r
67// Timer Data\r
68//\r
69volatile BOOLEAN bTick;\r
70BOOLEAN bTimerRunning;\r
71EFI_EVENT pTimer;\r
72\r
73//\r
74// Remote IP Address Data\r
75//\r
f6e5cdd5 76struct sockaddr_in6 RemoteHostAddress;\r
4684b66f 77CHAR8 * pRemoteHost;\r
78\r
79//\r
80// Traffic Data\r
81//\r
82UINT64 TotalBytesSent;\r
f6e5cdd5 83UINT32 In;\r
84UINT32 Samples;\r
85UINT64 BytesSent[ DATA_SAMPLES ];\r
59bc0593 86UINT8 Buffer[ DATA_BUFFER_SIZE ];\r
4684b66f 87\r
88\r
89//\r
90// Forward routine declarations\r
91//\r
92EFI_STATUS TimerStart ( UINTN Milliseconds );\r
93\r
94\r
95/**\r
96 Check for control C entered at console\r
97\r
98 @retval EFI_SUCCESS Control C not entered\r
99 @retval EFI_ABORTED Control C entered\r
100**/\r
101EFI_STATUS\r
102ControlCCheck (\r
103 )\r
104{\r
105 EFI_STATUS Status;\r
106\r
107 //\r
108 // Assume no user intervention\r
109 //\r
110 Status = EFI_SUCCESS;\r
111\r
112 //\r
113 // Display user stop request\r
114 //\r
115 if ( EFI_ERROR ( Status )) {\r
116 DEBUG (( DEBUG_INFO,\r
117 "User stop request!\r\n" ));\r
118 }\r
119\r
120 //\r
121 // Return the check status\r
122 //\r
123 return Status;\r
124}\r
125\r
126\r
127/**\r
128 Get a digit\r
129\r
130 @param [in] pDigit The address of the next digit\r
131 @param [out] pValue The address to receive the value\r
132\r
7dc13291 133 @return Returns the address of the separator\r
4684b66f 134\r
135**/\r
136CHAR8 *\r
137GetDigit (\r
138 CHAR8 * pDigit,\r
139 UINT32 * pValue\r
140 )\r
141{\r
142 UINT32 Value;\r
143\r
144 //\r
145 // Walk the digits\r
146 //\r
147 Value = 0;\r
59bc0593 148 while (( '0' <= *pDigit ) && ( '9' >= *pDigit )) {\r
4684b66f 149 //\r
150 // Make room for the new least significant digit\r
151 //\r
152 Value *= 10;\r
153\r
154 //\r
155 // Convert the digit from ASCII to binary\r
156 //\r
157 Value += *pDigit - '0';\r
158\r
159 //\r
160 // Set the next digit\r
161 //\r
162 pDigit += 1;\r
163 }\r
164\r
165 //\r
166 // Return the value\r
167 //\r
168 *pValue = Value;\r
169\r
170 //\r
171 // Return the next separator\r
172 //\r
173 return pDigit;\r
174}\r
175\r
176\r
177/**\r
178 Get the IP address\r
179\r
180 @retval EFI_SUCCESS The IP address is valid\r
181 @retval Other Failure to convert the IP address\r
182**/\r
183EFI_STATUS\r
184IpAddress (\r
185 )\r
186{\r
f6e5cdd5 187 struct sockaddr_in * pRemoteAddress4;\r
188 struct sockaddr_in6 * pRemoteAddress6;\r
189 UINT32 RemoteAddress;\r
4684b66f 190 EFI_STATUS Status;\r
191 UINT32 Value1;\r
192 UINT32 Value2;\r
193 UINT32 Value3;\r
194 UINT32 Value4;\r
f6e5cdd5 195 UINT32 Value5;\r
196 UINT32 Value6;\r
197 UINT32 Value7;\r
198 UINT32 Value8;\r
4684b66f 199\r
200 //\r
201 // Assume failure\r
202 //\r
203 Status = EFI_INVALID_PARAMETER;\r
204\r
f6e5cdd5 205 //\r
206 // Get the port number\r
207 //\r
208 ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));\r
209 RemoteHostAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));\r
210 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;\r
211 pRemoteAddress6 = &RemoteHostAddress;\r
212 \r
4684b66f 213 //\r
214 // Convert the IP address from a string to a numeric value\r
215 //\r
f6e5cdd5 216 if (( 4 == sscanf ( pRemoteHost,\r
217 "%d.%d.%d.%d",\r
218 &Value1,\r
219 &Value2,\r
220 &Value3,\r
221 &Value4 ))\r
222 && ( 255 >= Value1 )\r
223 && ( 255 >= Value2 )\r
224 && ( 255 >= Value3 )\r
225 && ( 255 >= Value4 )) {\r
226 //\r
227 // Build the IPv4 address\r
228 //\r
229 pRemoteAddress4->sin_len = sizeof ( *pRemoteAddress4 );\r
230 pRemoteAddress4->sin_family = AF_INET;\r
231 RemoteAddress = Value1\r
232 | ( Value2 << 8 )\r
233 | ( Value3 << 16 )\r
234 | ( Value4 << 24 );\r
235 pRemoteAddress4->sin_addr.s_addr = RemoteAddress;\r
236 Status = EFI_SUCCESS;\r
237\r
238 //\r
239 // Display the IP address\r
240 //\r
241 DEBUG (( DEBUG_INFO,\r
242 "%d.%d.%d.%d: Remote host IP address\r\n",\r
243 Value1,\r
244 Value2,\r
245 Value3,\r
246 Value4 ));\r
4684b66f 247 }\r
f6e5cdd5 248 else if (( 8 == sscanf ( pRemoteHost,\r
249 "%x:%x:%x:%x:%x:%x:%x:%x",\r
250 &Value1,\r
251 &Value2,\r
252 &Value3,\r
253 &Value4,\r
254 &Value5,\r
255 &Value6,\r
256 &Value7,\r
257 &Value8 ))\r
258 && ( 0xffff >= Value1 )\r
259 && ( 0xffff >= Value2 )\r
260 && ( 0xffff >= Value3 )\r
261 && ( 0xffff >= Value4 )\r
262 && ( 0xffff >= Value5 )\r
263 && ( 0xffff >= Value6 )\r
264 && ( 0xffff >= Value7 )\r
265 && ( 0xffff >= Value8 )) {\r
266 //\r
267 // Build the IPv6 address\r
268 //\r
269 pRemoteAddress6->sin6_len = sizeof ( *pRemoteAddress6 );\r
270 pRemoteAddress6->sin6_family = AF_INET6;\r
271 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ] = (UINT8)( Value1 >> 8 );\r
272 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ] = (UINT8)Value1;\r
273 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ] = (UINT8)( Value2 >> 8 );\r
274 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ] = (UINT8)Value2;\r
275 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ] = (UINT8)( Value3 >> 8 );\r
276 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ] = (UINT8)Value3;\r
277 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ] = (UINT8)( Value4 >> 8 );\r
278 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ] = (UINT8)Value4;\r
279 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ] = (UINT8)( Value5 >> 8 );\r
280 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ] = (UINT8)Value5;\r
281 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ] = (UINT8)( Value6 >> 8 );\r
282 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ] = (UINT8)Value6;\r
283 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ] = (UINT8)( Value7 >> 8 );\r
284 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ] = (UINT8)Value7;\r
285 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ] = (UINT8)( Value8 >> 8 );\r
286 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ] = (UINT8)Value8;\r
287 Status = EFI_SUCCESS;\r
288\r
289 //\r
290 // Display the IP address\r
291 //\r
292 DEBUG (( DEBUG_INFO,\r
293 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",\r
294 Value1,\r
295 Value2,\r
296 Value3,\r
297 Value4,\r
298 Value5,\r
299 Value6,\r
300 Value7,\r
301 Value8 ));\r
302 }\r
303 else {\r
304 Print ( L"ERROR - Invalid IP address!\r\n" );\r
4684b66f 305 }\r
306\r
307 //\r
308 // Return the operation status\r
309 //\r
310 return Status;\r
311}\r
312\r
313\r
314/**\r
315 Close the socket\r
316\r
317 @retval EFI_SUCCESS The application is running normally\r
318 @retval Other The user stopped the application\r
319**/\r
320EFI_STATUS\r
321SocketClose (\r
322 )\r
323{\r
324 int CloseStatus;\r
325 EFI_STATUS Status;\r
326\r
327 //\r
328 // Determine if the socket is open\r
329 //\r
330 Status = EFI_DEVICE_ERROR;\r
331 if ( -1 != Socket ) {\r
332 //\r
333 // Attempt to close the socket\r
334 //\r
335 CloseStatus = close ( Socket );\r
336 if ( 0 == CloseStatus ) {\r
337 DEBUG (( DEBUG_INFO,\r
338 "0x%08x: Socket closed\r\n",\r
339 Socket ));\r
340 Socket = -1;\r
341 Status = EFI_SUCCESS;\r
342 }\r
343 else {\r
344 DEBUG (( DEBUG_ERROR,\r
345 "ERROR: Failed to close socket, errno: %d\r\n",\r
346 errno ));\r
347 }\r
348 }\r
349\r
350 //\r
351 // Return the operation status\r
352 //\r
353 return Status;\r
354}\r
355\r
356\r
357/**\r
358 Connect the socket\r
359\r
360 @retval EFI_SUCCESS The application is running normally\r
361 @retval Other The user stopped the application\r
362**/\r
363EFI_STATUS\r
364SocketConnect (\r
365 )\r
366{\r
367 int ConnectStatus;\r
f6e5cdd5 368 struct sockaddr_in * pRemoteAddress4;\r
369 struct sockaddr_in6 * pRemoteAddress6;\r
4684b66f 370 EFI_STATUS Status;\r
371\r
372 //\r
373 // Display the connecting message\r
374 //\r
f6e5cdd5 375 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;\r
376 pRemoteAddress6 = &RemoteHostAddress;\r
377 if ( AF_INET == pRemoteAddress6->sin6_family ) {\r
378 Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",\r
379 pRemoteAddress4->sin_addr.s_addr & 0xff,\r
380 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
381 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
382 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
b8a86b22 383 ntohs ( pRemoteAddress4->sin_port ));\r
f6e5cdd5 384 }\r
385 else {\r
386 Print ( L"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
387 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
388 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
389 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
390 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
391 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
392 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
393 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
394 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
395 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
396 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
397 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
398 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
399 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
400 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
401 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
402 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
b8a86b22 403 ntohs ( pRemoteAddress6->sin6_port ));\r
f6e5cdd5 404 }\r
4684b66f 405\r
406 //\r
407 // Connect to the remote system\r
408 //\r
409 Status = EFI_SUCCESS;\r
410 do {\r
411 //\r
412 // Check for user stop request\r
413 //\r
59bc0593 414 while ( !bTick ) {\r
4684b66f 415 Status = ControlCCheck ( );\r
416 if ( EFI_ERROR ( Status )) {\r
417 break;\r
418 }\r
419 }\r
420 bTick = FALSE;\r
421 if ( EFI_ERROR ( Status )) {\r
422 break;\r
423 }\r
424\r
425 //\r
426 // Connect to the remote system\r
427 //\r
428 ConnectStatus = connect ( Socket,\r
f6e5cdd5 429 (struct sockaddr *)pRemoteAddress6,\r
430 pRemoteAddress6->sin6_len );\r
4684b66f 431 if ( -1 != ConnectStatus ) {\r
f6e5cdd5 432 if ( AF_INET == pRemoteAddress6->sin6_family ) {\r
433 Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",\r
434 pRemoteAddress4->sin_addr.s_addr & 0xff,\r
435 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
436 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
437 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
b8a86b22 438 ntohs ( pRemoteAddress4->sin_port ));\r
f6e5cdd5 439 }\r
440 else {\r
441 Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
442 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
443 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
444 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
445 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
446 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
447 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
448 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
449 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
450 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
451 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
452 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
453 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
454 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
455 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
456 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
457 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
b8a86b22 458 ntohs ( pRemoteAddress6->sin6_port ));\r
f6e5cdd5 459 }\r
b8a86b22 460Print ( L"ConnectStatus: %d, Status: %r\r\n", ConnectStatus, Status );\r
4684b66f 461 }\r
462 else {\r
463 //\r
464 // Close the socket and try again\r
465 //\r
466 if ( EAGAIN != errno ) {\r
467 Status = EFI_NOT_STARTED;\r
468 break;\r
469 }\r
470 }\r
471 } while ( -1 == ConnectStatus );\r
472\r
473 //\r
474 // Return the operation status\r
475 //\r
b8a86b22 476Print ( L"SocketConnect returning Status: %r\r\n", Status );\r
4684b66f 477 return Status;\r
478}\r
479\r
480\r
481/**\r
482 Create the socket\r
483\r
f6e5cdd5 484 @param [in] Family Network family, AF_INET or AF_INET6\r
485\r
4684b66f 486 @retval EFI_SUCCESS The application is running normally\r
487 @retval Other The user stopped the application\r
488**/\r
489EFI_STATUS\r
490SocketNew (\r
f6e5cdd5 491 sa_family_t Family\r
4684b66f 492 )\r
493{\r
494 EFI_STATUS Status;\r
495\r
496 //\r
497 // Loop creating the socket\r
498 //\r
499 DEBUG (( DEBUG_INFO,\r
500 "Creating the socket\r\n" ));\r
501 do {\r
502 //\r
503 // Check for user stop request\r
504 //\r
505 Status = ControlCCheck ( );\r
506 if ( EFI_ERROR ( Status )) {\r
507 break;\r
508 }\r
509\r
510 //\r
511 // Attempt to create the socket\r
512 //\r
f6e5cdd5 513 Socket = socket ( Family,\r
4684b66f 514 SOCK_STREAM,\r
515 IPPROTO_TCP );\r
516 if ( -1 != Socket ) {\r
517 DEBUG (( DEBUG_INFO,\r
518 "0x%08x: Socket created\r\n",\r
519 Socket ));\r
520 break;\r
521 }\r
522 } while ( -1 == Socket );\r
523\r
524 //\r
525 // Return the operation status\r
526 //\r
527 return Status;\r
528}\r
529\r
530\r
531/**\r
532 Send data over the socket\r
533\r
534 @retval EFI_SUCCESS The application is running normally\r
535 @retval Other The user stopped the application\r
536**/\r
537EFI_STATUS\r
538SocketSend (\r
539 )\r
540{\r
541 size_t BytesSent;\r
542 EFI_STATUS Status;\r
543 EFI_TPL TplPrevious;\r
544\r
545 //\r
546 // Restart the timer\r
547 //\r
f6e5cdd5 548 TimerStart ( 1 * 1000 );\r
4684b66f 549\r
550 //\r
551 // Loop until the connection breaks or the user stops\r
552 //\r
553 do {\r
554 //\r
555 // Check for user stop request\r
556 //\r
557 Status = ControlCCheck ( );\r
558 if ( EFI_ERROR ( Status )) {\r
559 break;\r
560 }\r
561\r
562 //\r
563 // Send some bytes\r
564 //\r
565 BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));\r
566 if ( -1 == BytesSent ) {\r
567 DEBUG (( DEBUG_INFO,\r
568 "ERROR: send failed, errno: %d\r\n",\r
569 errno ));\r
b8a86b22 570Print ( L"ERROR: send failed, errno: %d\r\n", errno );\r
4684b66f 571\r
572 //\r
573 // Try again\r
574 //\r
575 Status = EFI_SUCCESS;\r
576\r
577//\r
578// Exit now\r
579//\r
580Status = EFI_NOT_STARTED;\r
581 break;\r
582 }\r
583\r
584 //\r
585 // Synchronize with the TimerCallback routine\r
586 //\r
587 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
588\r
589 //\r
590 // Account for the data sent\r
591 //\r
592 TotalBytesSent += BytesSent;\r
593\r
594 //\r
595 // Release the TimerCallback routine synchronization\r
596 //\r
597 gBS->RestoreTPL ( TplPrevious );\r
598 } while ( !EFI_ERROR ( Status ));\r
599\r
600 //\r
601 // Return the operation status\r
602 //\r
603 return Status;\r
604}\r
605\r
606\r
607/**\r
608 Open the network connection and send the data.\r
609\r
610 @retval EFI_SUCCESS Continue looping\r
611 @retval other Stopped by user's Control-C input\r
612\r
613**/\r
614EFI_STATUS\r
615SocketOpen (\r
616 )\r
617{\r
618 EFI_STATUS Status;\r
619\r
620 //\r
621 // Use do/while and break instead of goto\r
622 //\r
59bc0593 623 do {\r
4684b66f 624 //\r
625 // Wait for the network layer to initialize\r
626 //\r
f6e5cdd5 627 Status = SocketNew ( RemoteHostAddress.sin6_family );\r
4684b66f 628 if ( EFI_ERROR ( Status )) {\r
629 break;\r
630 }\r
631\r
632 //\r
633 // Wait for the remote network application to start\r
634 //\r
635 Status = SocketConnect ( );\r
b8a86b22 636Print ( L"Status: %r\r\n", Status );\r
4684b66f 637 if ( EFI_NOT_STARTED == Status ) {\r
638 Status = SocketClose ( );\r
639 continue;\r
640 }\r
641 else if ( EFI_SUCCESS != Status ) {\r
642 //\r
643 // Control-C\r
644 //\r
645 break;\r
646 }\r
647\r
648 //\r
649 // Send data until the connection breaks\r
650 //\r
651 Status = SocketSend ( );\r
652 if ( EFI_ERROR ( Status )) {\r
653 break;\r
654 }\r
655 } while ( FALSE );\r
656\r
657 //\r
658 // Return the operation status\r
659 //\r
b8a86b22 660Print ( L"Returning Status: %r\r\n", Status );\r
4684b66f 661 return Status;\r
662}\r
663\r
664\r
665/**\r
666 Close the TCP connection\r
667\r
668 @retval EFI_SUCCESS The application is running normally\r
669 @retval Other The user stopped the application\r
670**/\r
671EFI_STATUS\r
672Tcp4Close (\r
673 )\r
674{\r
675 UINTN Index;\r
676 UINT8 * pIpAddress;\r
677 EFI_STATUS Status;\r
678\r
679 //\r
680 // Close the port\r
681 //\r
682 if ( bTcp4Connected ) {\r
683 Tcp4CloseToken.AbortOnClose = TRUE;\r
684 Status = pTcp4Protocol->Close ( pTcp4Protocol,\r
685 &Tcp4CloseToken );\r
686 if ( EFI_ERROR ( Status )) {\r
687 DEBUG (( DEBUG_ERROR,\r
688 "ERROR - Failed to start the TCP port close, Status: %r\r\n",\r
689 Status ));\r
690 }\r
691 else {\r
692 Status = gBS->WaitForEvent ( 1,\r
693 &Tcp4CloseToken.CompletionToken.Event,\r
694 &Index );\r
695 if ( EFI_ERROR ( Status )) {\r
696 DEBUG (( DEBUG_ERROR,\r
697 "ERROR - Failed to wait for close event, Status: %r\r\n",\r
698 Status ));\r
699 }\r
700 else {\r
701 Status = Tcp4CloseToken.CompletionToken.Status;\r
702 if ( EFI_ERROR ( Status )) {\r
703 DEBUG (( DEBUG_ERROR,\r
704 "ERROR - Failed to close the TCP port, Status: %r\r\n",\r
705 Status ));\r
706 }\r
707 else {\r
708 DEBUG (( DEBUG_INFO,\r
709 "0x%08x: TCP port closed\r\n",\r
710 pTcp4Protocol ));\r
711 bTcp4Connected = FALSE;\r
712\r
713 //\r
714 // Display the port closed message\r
715 //\r
f6e5cdd5 716 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 717 Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",\r
718 pIpAddress[0],\r
719 pIpAddress[1],\r
720 pIpAddress[2],\r
721 pIpAddress[3],\r
b8a86b22 722 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 723 }\r
724 }\r
725 }\r
726 }\r
727\r
728 //\r
729 // Release the events\r
730 //\r
731 if ( NULL != Tcp4TxToken.CompletionToken.Event ) {\r
732 Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );\r
733 if ( !EFI_ERROR ( Status )) {\r
734 DEBUG (( DEBUG_INFO,\r
735 "0x%08x: TX event closed\r\n",\r
736 Tcp4TxToken.CompletionToken.Event ));\r
737 Tcp4TxToken.CompletionToken.Event = NULL;\r
738 }\r
739 else {\r
740 DEBUG (( DEBUG_ERROR,\r
741 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",\r
742 Status ));\r
743 }\r
744 }\r
745\r
746 if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {\r
747 Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );\r
748 if ( !EFI_ERROR ( Status )) {\r
749 DEBUG (( DEBUG_INFO,\r
750 "0x%08x: Listen event closed\r\n",\r
751 Tcp4ListenToken.CompletionToken.Event ));\r
752 Tcp4ListenToken.CompletionToken.Event = NULL;\r
753 }\r
754 else {\r
755 DEBUG (( DEBUG_ERROR,\r
756 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",\r
757 Status ));\r
758 }\r
759 }\r
760\r
761 if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {\r
762 Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );\r
763 if ( !EFI_ERROR ( Status )) {\r
764 DEBUG (( DEBUG_INFO,\r
765 "0x%08x: Connect event closed\r\n",\r
766 Tcp4ConnectToken.CompletionToken.Event ));\r
767 Tcp4ConnectToken.CompletionToken.Event = NULL;\r
768 }\r
769 else {\r
770 DEBUG (( DEBUG_ERROR,\r
771 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",\r
772 Status ));\r
773 }\r
774 }\r
775\r
776 if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {\r
777 Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );\r
778 if ( !EFI_ERROR ( Status )) {\r
779 DEBUG (( DEBUG_INFO,\r
780 "0x%08x: Close event closed\r\n",\r
781 Tcp4CloseToken.CompletionToken.Event ));\r
782 Tcp4CloseToken.CompletionToken.Event = NULL;\r
783 }\r
784 else {\r
785 DEBUG (( DEBUG_ERROR,\r
786 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",\r
787 Status ));\r
788 }\r
789 }\r
790\r
791 //\r
792 // Close the TCP protocol\r
793 //\r
794 if ( NULL != pTcp4Protocol ) {\r
795 Status = gBS->CloseProtocol ( Tcp4Handle,\r
796 &gEfiTcp4ProtocolGuid,\r
797 gImageHandle,\r
798 NULL );\r
799 if ( EFI_ERROR ( Status )) {\r
800 DEBUG (( DEBUG_ERROR,\r
801 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",\r
802 Status ));\r
803 }\r
804 else {\r
805 DEBUG (( DEBUG_INFO,\r
806 "0x%08x: TCP4 protocol closed\r\n",\r
807 pTcp4Protocol ));\r
808 pTcp4Protocol = NULL;\r
809 }\r
810 }\r
811\r
812 //\r
813 // Done with the TCP service\r
814 //\r
815 if ( NULL != Tcp4Handle ) {\r
816 Status = pTcp4Service->DestroyChild ( pTcp4Service,\r
817 Tcp4Handle );\r
818 if ( EFI_ERROR ( Status )) {\r
819 DEBUG (( DEBUG_ERROR,\r
820 "ERROR - Failed to release TCP service handle, Status: %r\r\n",\r
821 Status ));\r
822 }\r
823 else {\r
824 DEBUG (( DEBUG_INFO,\r
825 "Ox%08x: TCP service closed\r\n",\r
826 Tcp4Handle ));\r
827 Tcp4Handle = NULL;\r
828 }\r
829 }\r
830\r
831 //\r
832 // Close the service protocol\r
833 //\r
834 if ( NULL != pTcp4Service ) {\r
835 Status = gBS->CloseProtocol ( Tcp4Controller,\r
836 &gEfiTcp4ServiceBindingProtocolGuid,\r
837 gImageHandle,\r
838 NULL );\r
839 if ( !EFI_ERROR ( Status )) {\r
840 DEBUG (( DEBUG_INFO,\r
841 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
842 Tcp4Controller ));\r
843 pTcp4Service = NULL;\r
844 }\r
845 else {\r
846 DEBUG (( DEBUG_ERROR,\r
847 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",\r
848 Status ));\r
849 }\r
850 }\r
851 Tcp4Controller = NULL;\r
852 bTcp4Connecting = TRUE;\r
853\r
854 //\r
855 // Mark the connection as closed\r
856 //\r
857 Status = EFI_SUCCESS;\r
858\r
859 //\r
860 // Return the operation status\r
861 //\r
862 return Status;\r
863}\r
864\r
865\r
866/**\r
867 Locate TCP protocol\r
868\r
869 @retval EFI_SUCCESS Protocol found\r
870 @retval other Protocl not found\r
871**/\r
872EFI_STATUS\r
873Tcp4Locate (\r
874 )\r
875{\r
876 UINTN HandleCount;\r
877 EFI_HANDLE * pHandles;\r
878 UINT8 * pIpAddress;\r
879 EFI_STATUS Status;\r
880\r
881 //\r
882 // Use do/while and break instead of goto\r
883 //\r
884 do {\r
885 //\r
886 // Attempt to locate the next TCP adapter in the system\r
887 //\r
888 Status = gBS->LocateHandleBuffer ( ByProtocol,\r
889 &gEfiTcp4ServiceBindingProtocolGuid,\r
890 NULL,\r
891 &HandleCount,\r
892 &pHandles );\r
893 if ( EFI_ERROR ( Status )) {\r
894 DEBUG (( DEBUG_WARN,\r
895 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",\r
896 Status ));\r
897 break;\r
898 }\r
899\r
900 //\r
901 // Wrap the index if necessary\r
902 //\r
903 if ( HandleCount <= Tcp4Index ) {\r
904 Tcp4Index = 0;\r
7dc13291 905\r
4684b66f 906 //\r
907 // Wait for the next timer tick\r
908 //\r
909 do {\r
910 } while ( !bTick );\r
911 bTick = FALSE;\r
912 }\r
913\r
914 //\r
915 // Display the connecting message\r
916 //\r
917 if ( bTcp4Connecting ) {\r
f6e5cdd5 918 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 919 Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",\r
920 pIpAddress[0],\r
921 pIpAddress[1],\r
922 pIpAddress[2],\r
923 pIpAddress[3],\r
b8a86b22 924 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 925 bTcp4Connecting = FALSE;\r
926 }\r
7dc13291 927\r
4684b66f 928 //\r
929 // Open the network controller's service protocol\r
930 //\r
59bc0593 931 Tcp4Controller = pHandles[ Tcp4Index++ ];\r
4684b66f 932 Status = gBS->OpenProtocol (\r
933 Tcp4Controller,\r
934 &gEfiTcp4ServiceBindingProtocolGuid,\r
935 (VOID **) &pTcp4Service,\r
936 gImageHandle,\r
937 NULL,\r
938 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
939 if ( EFI_ERROR ( Status )) {\r
940 DEBUG (( DEBUG_ERROR,\r
941 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",\r
942 Tcp4Controller ));\r
943 Tcp4Controller = NULL;\r
944 break;\r
945 }\r
946 DEBUG (( DEBUG_INFO,\r
947 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
948 Tcp4Controller ));\r
949\r
950 //\r
951 // Connect to the TCP service\r
952 //\r
953 Status = pTcp4Service->CreateChild ( pTcp4Service,\r
954 &Tcp4Handle );\r
955 if ( EFI_ERROR ( Status )) {\r
956 DEBUG (( DEBUG_ERROR,\r
957 "ERROR - Failed to open TCP service, Status: %r\r\n",\r
958 Status ));\r
959 Tcp4Handle = NULL;\r
960 break;\r
961 }\r
962 DEBUG (( DEBUG_INFO,\r
963 "Ox%08x: TCP service opened\r\n",\r
964 Tcp4Handle ));\r
965\r
966 //\r
967 // Locate the TCP protcol\r
968 //\r
969 Status = gBS->OpenProtocol ( Tcp4Handle,\r
970 &gEfiTcp4ProtocolGuid,\r
971 (VOID **)&pTcp4Protocol,\r
972 gImageHandle,\r
973 NULL,\r
974 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
975 if ( EFI_ERROR ( Status )) {\r
976 DEBUG (( DEBUG_ERROR,\r
977 "ERROR - Failed to open the TCP protocol, Status: %r\r\n",\r
978 Status ));\r
979 pTcp4Protocol = NULL;\r
980 break;\r
981 }\r
982 DEBUG (( DEBUG_INFO,\r
983 "0x%08x: TCP4 protocol opened\r\n",\r
984 pTcp4Protocol ));\r
985 }while ( FALSE );\r
986\r
987 //\r
988 // Release the handle buffer\r
989 //\r
990 gBS->FreePool ( pHandles );\r
991\r
992 //\r
993 // Return the operation status\r
994 //\r
995 return Status;\r
996}\r
997\r
998\r
999/**\r
1000 Send data over the TCP4 connection\r
1001\r
1002 @retval EFI_SUCCESS The application is running normally\r
1003 @retval Other The user stopped the application\r
1004**/\r
1005EFI_STATUS\r
1006Tcp4Send (\r
1007 )\r
1008{\r
1009 UINTN Index;\r
1010 EFI_TCP4_TRANSMIT_DATA Packet;\r
1011 EFI_STATUS Status;\r
1012 EFI_TPL TplPrevious;\r
1013\r
1014 //\r
1015 // Restart the timer\r
1016 //\r
f6e5cdd5 1017 TimerStart ( 1 * 1000 );\r
4684b66f 1018\r
1019 //\r
1020 // Initialize the packet\r
1021 //\r
1022 Packet.DataLength = sizeof ( Buffer );\r
1023 Packet.FragmentCount = 1;\r
1024 Packet.Push = FALSE;\r
1025 Packet.Urgent = FALSE;\r
1026 Packet.FragmentTable[0].FragmentBuffer = &Buffer[0];\r
1027 Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer );\r
1028 Tcp4TxToken.Packet.TxData = &Packet;\r
1029\r
1030 //\r
1031 // Loop until the connection breaks or the user stops\r
1032 //\r
1033 do {\r
1034 //\r
1035 // Check for user stop request\r
1036 //\r
1037 Status = ControlCCheck ( );\r
1038 if ( EFI_ERROR ( Status )) {\r
1039 break;\r
1040 }\r
1041\r
1042 //\r
1043 // Send some bytes\r
1044 //\r
1045 Status = pTcp4Protocol->Transmit ( pTcp4Protocol,\r
1046 &Tcp4TxToken );\r
1047 if ( EFI_ERROR ( Status )) {\r
1048 DEBUG (( DEBUG_ERROR,\r
1049 "ERROR - Failed to start the transmit, Status: %r\r\n",\r
1050 Status ));\r
1051\r
1052 //\r
1053 // Try again\r
1054 //\r
1055 Status = EFI_SUCCESS;\r
1056 break;\r
1057 }\r
1058\r
1059 //\r
1060 // Wait for the transmit to complete\r
1061 //\r
1062 Status = gBS->WaitForEvent ( 1,\r
1063 &Tcp4TxToken.CompletionToken.Event,\r
1064 &Index );\r
1065 if ( EFI_ERROR ( Status )) {\r
1066 DEBUG (( DEBUG_ERROR,\r
1067 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",\r
1068 Status ));\r
1069\r
1070 //\r
1071 // Try again\r
1072 //\r
1073 Status = EFI_SUCCESS;\r
1074 break;\r
1075 }\r
1076\r
1077 //\r
1078 // Get the transmit status\r
1079 //\r
1080 Status = Tcp4TxToken.CompletionToken.Status;\r
1081 if ( EFI_ERROR ( Status )) {\r
1082 DEBUG (( DEBUG_WARN,\r
1083 "WARNING - Failed the transmission, Status: %r\r\n",\r
1084 Status ));\r
1085\r
1086 //\r
1087 // Try again\r
1088 //\r
1089 Status = EFI_SUCCESS;\r
1090\r
1091//\r
1092// Exit now\r
1093//\r
1094Status = EFI_NOT_STARTED;\r
1095 break;\r
1096 }\r
1097\r
1098 //\r
1099 // Synchronize with the TimerCallback routine\r
1100 //\r
1101 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
1102\r
1103 //\r
1104 // Account for the data sent\r
1105 //\r
1106 TotalBytesSent += Packet.DataLength;\r
1107\r
1108 //\r
1109 // Release the TimerCallback routine synchronization\r
1110 //\r
1111 gBS->RestoreTPL ( TplPrevious );\r
1112 } while ( !EFI_ERROR ( Status ));\r
1113\r
1114 //\r
1115 // Return the operation status\r
1116 //\r
1117 return Status;\r
1118}\r
1119\r
1120\r
1121/**\r
1122 Open the network connection and send the data.\r
1123\r
1124 @retval EFI_SUCCESS Continue looping\r
1125 @retval other Stopped by user's Control-C input\r
1126\r
1127**/\r
1128EFI_STATUS\r
1129Tcp4Open (\r
1130 )\r
1131{\r
1132 UINTN Index;\r
1133 UINT8 * pIpAddress;\r
1134 EFI_STATUS Status;\r
1135\r
1136 //\r
1137 // Use do/while and break instead of goto\r
1138 //\r
1139 do {\r
1140 //\r
1141 // Locate the TCP protocol\r
1142 //\r
1143 Status = Tcp4Locate ( );\r
1144 if ( EFI_ERROR ( Status )) {\r
1145 break;\r
1146 }\r
1147\r
1148 //\r
1149 // Create the necessary events\r
1150 //\r
1151 Status = gBS->CreateEvent ( 0,\r
1152 TPL_CALLBACK,\r
1153 NULL,\r
1154 NULL,\r
1155 &Tcp4CloseToken.CompletionToken.Event );\r
1156 if ( EFI_ERROR ( Status )) {\r
1157 DEBUG (( DEBUG_ERROR,\r
1158 "ERROR - Failed to create the close event, Status: %r\r\n",\r
1159 Status ));\r
1160 Tcp4CloseToken.CompletionToken.Event = NULL;\r
1161 break;\r
1162 }\r
1163 DEBUG (( DEBUG_INFO,\r
1164 "0x%08x: Close event open\r\n",\r
1165 Tcp4CloseToken.CompletionToken.Event ));\r
1166\r
1167 Status = gBS->CreateEvent ( 0,\r
1168 TPL_CALLBACK,\r
1169 NULL,\r
1170 NULL,\r
1171 &Tcp4ConnectToken.CompletionToken.Event );\r
1172 if ( EFI_ERROR ( Status )) {\r
1173 DEBUG (( DEBUG_ERROR,\r
1174 "ERROR - Failed to create the connect event, Status: %r\r\n",\r
1175 Status ));\r
1176 Tcp4ConnectToken.CompletionToken.Event = NULL;\r
1177 break;\r
1178 }\r
1179 DEBUG (( DEBUG_INFO,\r
1180 "0x%08x: Connect event open\r\n",\r
1181 Tcp4ConnectToken.CompletionToken.Event ));\r
1182\r
1183 Status = gBS->CreateEvent ( 0,\r
1184 TPL_CALLBACK,\r
1185 NULL,\r
1186 NULL,\r
1187 &Tcp4ListenToken.CompletionToken.Event );\r
1188 if ( EFI_ERROR ( Status )) {\r
1189 DEBUG (( DEBUG_ERROR,\r
1190 "ERROR - Failed to create the listen event, Status: %r\r\n",\r
1191 Status ));\r
1192 Tcp4ListenToken.CompletionToken.Event = NULL;\r
1193 break;\r
1194 }\r
1195 DEBUG (( DEBUG_INFO,\r
1196 "0x%08x: Listen event open\r\n",\r
1197 Tcp4ListenToken.CompletionToken.Event ));\r
1198\r
1199 Status = gBS->CreateEvent ( 0,\r
1200 TPL_CALLBACK,\r
1201 NULL,\r
1202 NULL,\r
1203 &Tcp4TxToken.CompletionToken.Event );\r
1204 if ( EFI_ERROR ( Status )) {\r
1205 DEBUG (( DEBUG_ERROR,\r
1206 "ERROR - Failed to create the TX event, Status: %r\r\n",\r
1207 Status ));\r
1208 Tcp4TxToken.CompletionToken.Event = NULL;\r
1209 break;\r
1210 }\r
1211 DEBUG (( DEBUG_INFO,\r
1212 "0x%08x: TX event open\r\n",\r
1213 Tcp4TxToken.CompletionToken.Event ));\r
1214\r
1215 //\r
1216 // Configure the local TCP port\r
1217 //\r
1218 Tcp4ConfigData.TimeToLive = 255;\r
1219 Tcp4ConfigData.TypeOfService = 0;\r
1220 Tcp4ConfigData.ControlOption = NULL;\r
1221 Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE;\r
1222 Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0;\r
1223 Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 0;\r
1224 Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;\r
1225 Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;\r
1226 Tcp4ConfigData.AccessPoint.StationPort = 0;\r
f6e5cdd5 1227 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8) ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
1228 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 8 );\r
1229 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 16 );\r
1230 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 24 );\r
b8a86b22 1231 Tcp4ConfigData.AccessPoint.RemotePort = ntohs (((struct sockaddr_in *)&RemoteHostAddress)->sin_port);\r
4684b66f 1232 Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;\r
1233 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;\r
1234 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;\r
1235 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0;\r
1236 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0;\r
1237 Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
1238 &Tcp4ConfigData );\r
1239 if ( EFI_ERROR ( Status )) {\r
7dc13291 1240 DEBUG (( DEBUG_ERROR,\r
4684b66f 1241 "ERROR - Failed to configure TCP port, Status: %r\r\n",\r
1242 Status ));\r
1243 break;\r
1244 }\r
1245 DEBUG (( DEBUG_INFO,\r
1246 "0x%08x: TCP4 port configured\r\n",\r
1247 pTcp4Protocol ));\r
1248\r
1249 //\r
1250 // Connect to the remote TCP port\r
1251 //\r
1252 Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
1253 &Tcp4ConnectToken );\r
1254 if ( EFI_ERROR ( Status )) {\r
1255 DEBUG (( DEBUG_ERROR,\r
1256 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",\r
1257 Status ));\r
1258 break;\r
1259 }\r
1260 Status = gBS->WaitForEvent ( 1,\r
1261 &Tcp4ConnectToken.CompletionToken.Event,\r
1262 &Index );\r
1263 if ( EFI_ERROR ( Status )) {\r
1264 DEBUG (( DEBUG_ERROR,\r
1265 "ERROR - Failed to wait for the connection, Status: %r\r\n",\r
1266 Status ));\r
1267 break;\r
1268 }\r
1269 Status = Tcp4ConnectToken.CompletionToken.Status;\r
1270 if ( EFI_ERROR ( Status )) {\r
1271 DEBUG (( DEBUG_WARN,\r
1272 "WARNING - Failed to connect to the remote system, Status: %r\r\n",\r
1273 Status ));\r
1274 break;\r
1275 }\r
1276 DEBUG (( DEBUG_INFO,\r
1277 "0x%08x: TCP4 port connected\r\n",\r
1278 pTcp4Protocol ));\r
1279 bTcp4Connected = TRUE;\r
1280\r
1281 //\r
1282 // Display the connection\r
1283 //\r
f6e5cdd5 1284 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 1285 Print ( L"Connected to %d.%d.%d.%d:%d\r\n",\r
1286 pIpAddress[0],\r
1287 pIpAddress[1],\r
1288 pIpAddress[2],\r
1289 pIpAddress[3],\r
b8a86b22 1290 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 1291 } while ( 0 );\r
1292\r
1293 if ( EFI_ERROR ( Status )) {\r
1294 //\r
1295 // Try again\r
1296 //\r
1297 Status = EFI_SUCCESS;\r
1298 }\r
1299 else {\r
1300 //\r
1301 // Semd data until the connection breaks\r
1302 //\r
1303 Status = Tcp4Send ( );\r
1304 }\r
1305\r
1306 //\r
1307 // Return the operation status\r
1308 //\r
1309 return Status;\r
1310}\r
1311\r
1312\r
1313/**\r
1314 Handle the timer callback\r
1315\r
1316 @param [in] Event Event that caused this callback\r
1317 @param [in] pContext Context for this routine\r
1318**/\r
1319VOID\r
53c31c51 1320EFIAPI\r
4684b66f 1321TimerCallback (\r
1322 IN EFI_EVENT Event,\r
1323 IN VOID * pContext\r
1324 )\r
1325{\r
f6e5cdd5 1326 UINT32 Average;\r
1327 UINT64 BitsPerSecond;\r
1328 UINT32 Index;\r
1329 UINT64 TotalBytes;\r
4684b66f 1330\r
1331 //\r
1332 // Notify the other code of the timer tick\r
1333 //\r
1334 bTick = TRUE;\r
1335\r
1336 //\r
1337 // Update the average bytes per second\r
1338 //\r
f6e5cdd5 1339 if ( 0 != TotalBytesSent ) {\r
1340 BytesSent[ In ] = TotalBytesSent;\r
1341 TotalBytesSent = 0;\r
1342 In += 1;\r
1343 if ( DATA_SAMPLES <= In ) {\r
1344 In = 0;\r
1345 }\r
4684b66f 1346\r
1347 //\r
1348 // Separate the samples\r
1349 //\r
f6e5cdd5 1350 if ( DATA_SAMPLES == Samples ) {\r
4684b66f 1351 Print ( L"---------- Stable average ----------\r\n" );\r
1352 }\r
1353 Samples += 1;\r
1354\r
f6e5cdd5 1355 //\r
1356 // Compute the data rate\r
1357 //\r
1358 TotalBytes = 0;\r
1359 for ( Index = 0; DATA_SAMPLES > Index; Index++ ) {\r
1360 TotalBytes += BytesSent[ Index ];\r
1361 }\r
1362 Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );\r
1363 BitsPerSecond = Average * 8;\r
1364\r
4684b66f 1365 //\r
1366 // Display the data rate\r
1367 //\r
f6e5cdd5 1368 if (( RANGE_SWITCH >> 10 ) > Average ) {\r
1369 Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",\r
1370 Average,\r
1371 BitsPerSecond );\r
4684b66f 1372 }\r
1373 else {\r
f6e5cdd5 1374 BitsPerSecond /= 1000;\r
1375 if ( RANGE_SWITCH > Average ) {\r
1376 Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",\r
1377 Average >> 10,\r
1378 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1379 BitsPerSecond );\r
4684b66f 1380 }\r
1381 else {\r
f6e5cdd5 1382 BitsPerSecond /= 1000;\r
4684b66f 1383 Average >>= 10;\r
f6e5cdd5 1384 if ( RANGE_SWITCH > Average ) {\r
1385 Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",\r
1386 Average >> 10,\r
1387 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1388 BitsPerSecond );\r
4684b66f 1389 }\r
1390 else {\r
f6e5cdd5 1391 BitsPerSecond /= 1000;\r
4684b66f 1392 Average >>= 10;\r
f6e5cdd5 1393 if ( RANGE_SWITCH > Average ) {\r
1394 Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",\r
1395 Average >> 10,\r
1396 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1397 BitsPerSecond );\r
4684b66f 1398 }\r
1399 else {\r
f6e5cdd5 1400 BitsPerSecond /= 1000;\r
4684b66f 1401 Average >>= 10;\r
f6e5cdd5 1402 if ( RANGE_SWITCH > Average ) {\r
1403 Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",\r
1404 Average >> 10,\r
1405 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1406 BitsPerSecond );\r
4684b66f 1407 }\r
1408 else {\r
f6e5cdd5 1409 BitsPerSecond /= 1000;\r
4684b66f 1410 Average >>= 10;\r
f6e5cdd5 1411 Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",\r
1412 Average >> 10,\r
1413 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1414 BitsPerSecond );\r
4684b66f 1415 }\r
1416 }\r
1417 }\r
1418 }\r
1419 }\r
1420 }\r
1421}\r
1422\r
1423\r
1424/**\r
1425 Create the timer\r
1426\r
1427 @retval EFI_SUCCESS The timer was successfully created\r
1428 @retval Other Timer initialization failed\r
1429**/\r
1430EFI_STATUS\r
1431TimerCreate (\r
1432 )\r
1433{\r
1434 EFI_STATUS Status;\r
1435\r
1436 //\r
1437 // Create the timer\r
1438 //\r
1439 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1440 TPL_DATASOURCE,\r
1441 TimerCallback,\r
1442 NULL,\r
1443 &pTimer );\r
1444 if ( EFI_ERROR ( Status )) {\r
1445 DEBUG (( DEBUG_ERROR,\r
1446 "ERROR - Failed to allocate the timer event, Status: %r\r\n",\r
1447 Status ));\r
1448 }\r
1449 else {\r
1450 DEBUG (( DEBUG_INFO,\r
1451 "0x%08x: Timer created\r\n",\r
1452 pTimer ));\r
1453 }\r
1454\r
1455 //\r
1456 // Return the operation status\r
1457 //\r
1458 return Status;\r
1459}\r
1460\r
1461\r
1462/**\r
1463 Stop the timer\r
1464\r
1465 @retval EFI_SUCCESS The timer was stopped successfully\r
1466 @retval Other The timer failed to stop\r
1467**/\r
1468EFI_STATUS\r
1469TimerStop (\r
1470 )\r
1471{\r
1472 EFI_STATUS Status;\r
1473\r
1474 //\r
1475 // Assume success\r
1476 //\r
1477 Status = EFI_SUCCESS;\r
1478\r
1479 //\r
1480 // Determine if the timer is running\r
1481 //\r
1482 if ( bTimerRunning ) {\r
1483 //\r
1484 // Stop the timer\r
1485 //\r
1486 Status = gBS->SetTimer ( pTimer,\r
1487 TimerCancel,\r
1488 0 );\r
1489 if ( EFI_ERROR ( Status )) {\r
1490 DEBUG (( DEBUG_ERROR,\r
1491 "ERROR - Failed to stop the timer, Status: %r\r\n",\r
1492 Status ));\r
1493 }\r
1494 else {\r
1495 //\r
1496 // Timer timer is now stopped\r
1497 //\r
1498 bTimerRunning = FALSE;\r
1499 DEBUG (( DEBUG_INFO,\r
1500 "0x%08x: Timer stopped\r\n",\r
1501 pTimer ));\r
1502 }\r
1503 }\r
1504\r
1505 //\r
1506 // Return the operation status\r
1507 //\r
1508 return Status;\r
1509}\r
1510\r
1511\r
1512/**\r
1513 Start the timer\r
1514\r
1515 @param [in] Milliseconds The number of milliseconds between timer callbacks\r
1516\r
1517 @retval EFI_SUCCESS The timer was successfully created\r
1518 @retval Other Timer initialization failed\r
1519**/\r
1520EFI_STATUS\r
1521TimerStart (\r
1522 UINTN Milliseconds\r
1523 )\r
1524{\r
1525 EFI_STATUS Status;\r
1526 UINT64 TimeDelay;\r
1527\r
1528 //\r
1529 // Stop the timer if necessary\r
1530 //\r
1531 Status = EFI_SUCCESS;\r
1532 if ( bTimerRunning ) {\r
1533 Status = TimerStop ( );\r
1534 }\r
1535 if ( !EFI_ERROR ( Status )) {\r
1536 //\r
1537 // Compute the new delay\r
1538 //\r
1539 TimeDelay = Milliseconds;\r
1540 TimeDelay *= 1000 * 10;\r
1541\r
1542 //\r
1543 // Start the timer\r
1544 //\r
1545 Status = gBS->SetTimer ( pTimer,\r
1546 TimerPeriodic,\r
1547 TimeDelay );\r
1548 if ( EFI_ERROR ( Status )) {\r
1549 DEBUG (( DEBUG_ERROR,\r
1550 "ERROR - Failed to start the timer, Status: %r\r\n",\r
1551 Status ));\r
1552 }\r
1553 else {\r
1554 //\r
1555 // The timer is now running\r
1556 //\r
1557 bTimerRunning = TRUE;\r
1558 DEBUG (( DEBUG_INFO,\r
1559 "0x%08x: Timer running\r\n",\r
1560 pTimer ));\r
1561 }\r
1562 }\r
1563\r
1564 //\r
1565 // Return the operation status\r
1566 //\r
1567 return Status;\r
1568}\r
1569\r
1570\r
1571/**\r
1572 Destroy the timer\r
1573\r
1574 @retval EFI_SUCCESS The timer was destroyed successfully\r
1575 @retval Other Failed to destroy the timer\r
1576**/\r
1577EFI_STATUS\r
1578TimerDestroy (\r
1579 )\r
1580{\r
1581 EFI_STATUS Status;\r
1582\r
1583 //\r
1584 // Assume success\r
1585 //\r
1586 Status = EFI_SUCCESS;\r
1587\r
1588 //\r
1589 // Determine if the timer is running\r
1590 //\r
1591 if ( bTimerRunning ) {\r
1592 //\r
1593 // Stop the timer\r
1594 //\r
1595 Status = TimerStop ( );\r
1596 }\r
1597 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {\r
1598 //\r
1599 // Done with this timer\r
1600 //\r
1601 Status = gBS->CloseEvent ( pTimer );\r
1602 if ( EFI_ERROR ( Status )) {\r
1603 DEBUG (( DEBUG_ERROR,\r
1604 "ERROR - Failed to free the timer event, Status: %r\r\n",\r
1605 Status ));\r
1606 }\r
1607 else {\r
1608 DEBUG (( DEBUG_INFO,\r
1609 "0x%08x: Timer Destroyed\r\n",\r
1610 pTimer ));\r
1611 pTimer = NULL;\r
1612 }\r
1613 }\r
1614\r
1615 //\r
1616 // Return the operation status\r
1617 //\r
1618 return Status;\r
1619}\r
1620\r
1621\r
1622/**\r
1623 Send data to the DataSink program to test a network's bandwidth.\r
1624\r
1625 @param [in] Argc The number of arguments\r
1626 @param [in] Argv The argument value array\r
1627\r
1628 @retval 0 The application exited normally.\r
1629 @retval Other An error occurred.\r
1630**/\r
1631int\r
1632main (\r
1633 IN int Argc,\r
1634 IN char **Argv\r
1635 )\r
1636{\r
1637 EFI_STATUS (* pClose) ();\r
1638 EFI_STATUS (* pOpen) ();\r
1639 EFI_STATUS Status;\r
1640\r
1641 DEBUG (( DEBUG_INFO,\r
1642 "DataSource starting\r\n" ));\r
1643\r
1644 //\r
1645 // Validate the command line\r
1646 //\r
59bc0593 1647 if ( 2 > Argc ) {\r
1648 Print ( L"%s <remote IP address> [Use TCP]\r\n", Argv[0] );\r
4684b66f 1649 return -1;\r
1650 }\r
1651\r
59bc0593 1652 //\r
1653 // Determine if TCP should be used\r
1654 //\r
1655 bTcp4 = (BOOLEAN)( 2 < Argc );\r
4684b66f 1656\r
1657 //\r
1658 // Determine the support routines\r
1659 //\r
1660 if ( bTcp4 ) {\r
1661 pOpen = Tcp4Open;\r
1662 pClose = Tcp4Close;\r
1663 bTcp4Connecting = TRUE;\r
1664 }\r
1665 else {\r
1666 pOpen = SocketOpen;\r
1667 pClose = SocketClose;\r
1668 }\r
1669\r
1670 //\r
1671 // Use for/break instead of goto\r
1672 //\r
59bc0593 1673 for ( ; ; ) {\r
4684b66f 1674 //\r
1675 // No bytes sent so far\r
1676 //\r
1677 TotalBytesSent = 0;\r
4684b66f 1678 Samples = 0;\r
f6e5cdd5 1679 memset ( &BytesSent, 0, sizeof ( BytesSent ));\r
4684b66f 1680\r
4684b66f 1681 //\r
1682 // Get the IP address\r
1683 //\r
59bc0593 1684 pRemoteHost = Argv[1];\r
4684b66f 1685 Status = IpAddress ( );\r
1686 if ( EFI_ERROR ( Status )) {\r
1687 break;\r
1688 }\r
1689\r
1690 //\r
1691 // Create the timer\r
1692 //\r
1693 bTick = TRUE;\r
1694 Status = TimerCreate ( );\r
1695 if ( EFI_ERROR ( Status )) {\r
1696 break;\r
1697 }\r
1698\r
1699 //\r
1700 // Loop forever abusing the specified system\r
1701 //\r
1702 do {\r
1703 //\r
1704 // Start a timer to perform connection polling and display updates\r
1705 //\r
1706 Status = TimerStart ( 2 * 1000 );\r
1707 if ( EFI_ERROR ( Status )) {\r
1708 break;\r
1709 }\r
1710\r
1711 //\r
1712 // Open the network connection and send the data\r
1713 //\r
1714 Status = pOpen ( );\r
1715 if ( EFI_ERROR ( Status )) {\r
1716 break;\r
1717 }\r
1718\r
1719 //\r
1720 // Done with the network connection\r
1721 //\r
1722 Status = pClose ( );\r
1723 } while ( !EFI_ERROR ( Status ));\r
1724\r
1725 //\r
1726 // Close the network connection if necessary\r
1727 //\r
1728 pClose ( );\r
1729\r
1730 //\r
1731 // All done\r
1732 //\r
1733 break;\r
1734 }\r
1735\r
1736 //\r
1737 // Stop the timer if necessary\r
1738 //\r
1739 TimerStop ( );\r
1740 TimerDestroy ( );\r
1741\r
1742 //\r
1743 // Return the operation status\r
1744 //\r
1745 DEBUG (( DEBUG_INFO,\r
1746 "DataSource exiting, Status: %r\r\n",\r
1747 Status ));\r
1748 return Status;\r
1749}\r