]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Sockets/DataSource/DataSource.c
* StdLib.dsc was changed to always build the sockets code.
[mirror_edk2.git] / AppPkg / Applications / Sockets / DataSource / DataSource.c
CommitLineData
4684b66f 1/** @file\r
2 Data source for network testing.\r
3\r
4 Copyright (c) 2011, Intel Corporation\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <errno.h>\r
16#include <Uefi.h>\r
17\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/PcdLib.h>\r
21#include <Library/UefiBootServicesTableLib.h>\r
22#include <Library/UefiLib.h>\r
23\r
24#include <netinet/in.h>\r
25\r
26#include <Protocol/ServiceBinding.h>\r
27#include <Protocol/Tcp4.h>\r
28\r
29#include <sys/EfiSysCall.h>\r
30#include <sys/poll.h>\r
31#include <sys/socket.h>\r
32\r
f6e5cdd5 33#include <stdio.h>\r
d3a595ce 34#include <string.h>\r
4684b66f 35\r
f6e5cdd5 36\r
37#define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples\r
38#define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges\r
39#define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates\r
4684b66f 40#define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average\r
f6e5cdd5 41#define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples\r
4684b66f 42\r
43#define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL\r
44\r
45#define PACKET_SIZE 1448 ///< Size of data packets\r
46#define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes\r
47\r
48\r
49//\r
50// Socket Data\r
51//\r
52int Socket = -1;\r
53\r
54//\r
55// TCP V4 Data\r
56//\r
57BOOLEAN bTcp4; ///< TRUE if TCP4 is being used\r
58BOOLEAN bTcp4Connected; ///< TRUE if connected to remote system\r
59BOOLEAN bTcp4Connecting; ///< TRUE while connection in progress\r
60UINTN Tcp4Index; ///< Index into handle array\r
61EFI_HANDLE Tcp4Controller; ///< Network controller handle\r
62EFI_HANDLE Tcp4Handle; ///< TCP4 port handle\r
63EFI_TCP4_PROTOCOL * pTcp4Protocol; ///< TCP4 protocol pointer\r
64EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service; ///< TCP4 Service binding\r
65EFI_TCP4_CONFIG_DATA Tcp4ConfigData;///< TCP4 configuration data\r
66EFI_TCP4_OPTION Tcp4Option; ///< TCP4 port options\r
67EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;///< Close control\r
68EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken; ///< Connection control\r
69EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken; ///< Listen control\r
70EFI_TCP4_IO_TOKEN Tcp4TxToken; ///< Normal data token\r
71\r
72//\r
73// Timer Data\r
74//\r
75volatile BOOLEAN bTick;\r
76BOOLEAN bTimerRunning;\r
77EFI_EVENT pTimer;\r
78\r
79//\r
80// Remote IP Address Data\r
81//\r
f6e5cdd5 82struct sockaddr_in6 RemoteHostAddress;\r
4684b66f 83CHAR8 * pRemoteHost;\r
84\r
85//\r
86// Traffic Data\r
87//\r
88UINT64 TotalBytesSent;\r
f6e5cdd5 89UINT32 In;\r
90UINT32 Samples;\r
91UINT64 BytesSent[ DATA_SAMPLES ];\r
59bc0593 92UINT8 Buffer[ DATA_BUFFER_SIZE ];\r
4684b66f 93\r
94\r
95//\r
96// Forward routine declarations\r
97//\r
98EFI_STATUS TimerStart ( UINTN Milliseconds );\r
99\r
100\r
101/**\r
102 Check for control C entered at console\r
103\r
104 @retval EFI_SUCCESS Control C not entered\r
105 @retval EFI_ABORTED Control C entered\r
106**/\r
107EFI_STATUS\r
108ControlCCheck (\r
109 )\r
110{\r
111 EFI_STATUS Status;\r
112\r
113 //\r
114 // Assume no user intervention\r
115 //\r
116 Status = EFI_SUCCESS;\r
117\r
118 //\r
119 // Display user stop request\r
120 //\r
121 if ( EFI_ERROR ( Status )) {\r
122 DEBUG (( DEBUG_INFO,\r
123 "User stop request!\r\n" ));\r
124 }\r
125\r
126 //\r
127 // Return the check status\r
128 //\r
129 return Status;\r
130}\r
131\r
132\r
133/**\r
134 Get a digit\r
135\r
136 @param [in] pDigit The address of the next digit\r
137 @param [out] pValue The address to receive the value\r
138\r
7dc13291 139 @return Returns the address of the separator\r
4684b66f 140\r
141**/\r
142CHAR8 *\r
143GetDigit (\r
144 CHAR8 * pDigit,\r
145 UINT32 * pValue\r
146 )\r
147{\r
148 UINT32 Value;\r
149\r
150 //\r
151 // Walk the digits\r
152 //\r
153 Value = 0;\r
59bc0593 154 while (( '0' <= *pDigit ) && ( '9' >= *pDigit )) {\r
4684b66f 155 //\r
156 // Make room for the new least significant digit\r
157 //\r
158 Value *= 10;\r
159\r
160 //\r
161 // Convert the digit from ASCII to binary\r
162 //\r
163 Value += *pDigit - '0';\r
164\r
165 //\r
166 // Set the next digit\r
167 //\r
168 pDigit += 1;\r
169 }\r
170\r
171 //\r
172 // Return the value\r
173 //\r
174 *pValue = Value;\r
175\r
176 //\r
177 // Return the next separator\r
178 //\r
179 return pDigit;\r
180}\r
181\r
182\r
183/**\r
184 Get the IP address\r
185\r
186 @retval EFI_SUCCESS The IP address is valid\r
187 @retval Other Failure to convert the IP address\r
188**/\r
189EFI_STATUS\r
190IpAddress (\r
191 )\r
192{\r
f6e5cdd5 193 struct sockaddr_in * pRemoteAddress4;\r
194 struct sockaddr_in6 * pRemoteAddress6;\r
195 UINT32 RemoteAddress;\r
4684b66f 196 EFI_STATUS Status;\r
197 UINT32 Value1;\r
198 UINT32 Value2;\r
199 UINT32 Value3;\r
200 UINT32 Value4;\r
f6e5cdd5 201 UINT32 Value5;\r
202 UINT32 Value6;\r
203 UINT32 Value7;\r
204 UINT32 Value8;\r
4684b66f 205\r
206 //\r
207 // Assume failure\r
208 //\r
209 Status = EFI_INVALID_PARAMETER;\r
210\r
f6e5cdd5 211 //\r
212 // Get the port number\r
213 //\r
214 ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));\r
215 RemoteHostAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));\r
216 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;\r
217 pRemoteAddress6 = &RemoteHostAddress;\r
218 \r
4684b66f 219 //\r
220 // Convert the IP address from a string to a numeric value\r
221 //\r
f6e5cdd5 222 if (( 4 == sscanf ( pRemoteHost,\r
223 "%d.%d.%d.%d",\r
224 &Value1,\r
225 &Value2,\r
226 &Value3,\r
227 &Value4 ))\r
228 && ( 255 >= Value1 )\r
229 && ( 255 >= Value2 )\r
230 && ( 255 >= Value3 )\r
231 && ( 255 >= Value4 )) {\r
232 //\r
233 // Build the IPv4 address\r
234 //\r
235 pRemoteAddress4->sin_len = sizeof ( *pRemoteAddress4 );\r
236 pRemoteAddress4->sin_family = AF_INET;\r
237 RemoteAddress = Value1\r
238 | ( Value2 << 8 )\r
239 | ( Value3 << 16 )\r
240 | ( Value4 << 24 );\r
241 pRemoteAddress4->sin_addr.s_addr = RemoteAddress;\r
242 Status = EFI_SUCCESS;\r
243\r
244 //\r
245 // Display the IP address\r
246 //\r
247 DEBUG (( DEBUG_INFO,\r
248 "%d.%d.%d.%d: Remote host IP address\r\n",\r
249 Value1,\r
250 Value2,\r
251 Value3,\r
252 Value4 ));\r
4684b66f 253 }\r
f6e5cdd5 254 else if (( 8 == sscanf ( pRemoteHost,\r
255 "%x:%x:%x:%x:%x:%x:%x:%x",\r
256 &Value1,\r
257 &Value2,\r
258 &Value3,\r
259 &Value4,\r
260 &Value5,\r
261 &Value6,\r
262 &Value7,\r
263 &Value8 ))\r
264 && ( 0xffff >= Value1 )\r
265 && ( 0xffff >= Value2 )\r
266 && ( 0xffff >= Value3 )\r
267 && ( 0xffff >= Value4 )\r
268 && ( 0xffff >= Value5 )\r
269 && ( 0xffff >= Value6 )\r
270 && ( 0xffff >= Value7 )\r
271 && ( 0xffff >= Value8 )) {\r
272 //\r
273 // Build the IPv6 address\r
274 //\r
275 pRemoteAddress6->sin6_len = sizeof ( *pRemoteAddress6 );\r
276 pRemoteAddress6->sin6_family = AF_INET6;\r
277 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ] = (UINT8)( Value1 >> 8 );\r
278 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ] = (UINT8)Value1;\r
279 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ] = (UINT8)( Value2 >> 8 );\r
280 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ] = (UINT8)Value2;\r
281 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ] = (UINT8)( Value3 >> 8 );\r
282 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ] = (UINT8)Value3;\r
283 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ] = (UINT8)( Value4 >> 8 );\r
284 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ] = (UINT8)Value4;\r
285 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ] = (UINT8)( Value5 >> 8 );\r
286 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ] = (UINT8)Value5;\r
287 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ] = (UINT8)( Value6 >> 8 );\r
288 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ] = (UINT8)Value6;\r
289 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ] = (UINT8)( Value7 >> 8 );\r
290 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ] = (UINT8)Value7;\r
291 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ] = (UINT8)( Value8 >> 8 );\r
292 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ] = (UINT8)Value8;\r
293 Status = EFI_SUCCESS;\r
294\r
295 //\r
296 // Display the IP address\r
297 //\r
298 DEBUG (( DEBUG_INFO,\r
299 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",\r
300 Value1,\r
301 Value2,\r
302 Value3,\r
303 Value4,\r
304 Value5,\r
305 Value6,\r
306 Value7,\r
307 Value8 ));\r
308 }\r
309 else {\r
310 Print ( L"ERROR - Invalid IP address!\r\n" );\r
4684b66f 311 }\r
312\r
313 //\r
314 // Return the operation status\r
315 //\r
316 return Status;\r
317}\r
318\r
319\r
320/**\r
321 Close the socket\r
322\r
323 @retval EFI_SUCCESS The application is running normally\r
324 @retval Other The user stopped the application\r
325**/\r
326EFI_STATUS\r
327SocketClose (\r
328 )\r
329{\r
330 int CloseStatus;\r
331 EFI_STATUS Status;\r
332\r
333 //\r
334 // Determine if the socket is open\r
335 //\r
336 Status = EFI_DEVICE_ERROR;\r
337 if ( -1 != Socket ) {\r
338 //\r
339 // Attempt to close the socket\r
340 //\r
341 CloseStatus = close ( Socket );\r
342 if ( 0 == CloseStatus ) {\r
343 DEBUG (( DEBUG_INFO,\r
344 "0x%08x: Socket closed\r\n",\r
345 Socket ));\r
346 Socket = -1;\r
347 Status = EFI_SUCCESS;\r
348 }\r
349 else {\r
350 DEBUG (( DEBUG_ERROR,\r
351 "ERROR: Failed to close socket, errno: %d\r\n",\r
352 errno ));\r
353 }\r
354 }\r
355\r
356 //\r
357 // Return the operation status\r
358 //\r
359 return Status;\r
360}\r
361\r
362\r
363/**\r
364 Connect the socket\r
365\r
366 @retval EFI_SUCCESS The application is running normally\r
367 @retval Other The user stopped the application\r
368**/\r
369EFI_STATUS\r
370SocketConnect (\r
371 )\r
372{\r
373 int ConnectStatus;\r
f6e5cdd5 374 struct sockaddr_in * pRemoteAddress4;\r
375 struct sockaddr_in6 * pRemoteAddress6;\r
4684b66f 376 EFI_STATUS Status;\r
377\r
378 //\r
379 // Display the connecting message\r
380 //\r
f6e5cdd5 381 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;\r
382 pRemoteAddress6 = &RemoteHostAddress;\r
383 if ( AF_INET == pRemoteAddress6->sin6_family ) {\r
384 Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",\r
385 pRemoteAddress4->sin_addr.s_addr & 0xff,\r
386 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
387 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
388 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
389 htons ( pRemoteAddress4->sin_port ));\r
390 }\r
391 else {\r
392 Print ( L"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
393 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
394 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
395 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
396 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
397 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
398 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
399 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
400 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
401 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
402 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
403 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
404 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
405 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
406 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
407 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
408 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
409 htons ( pRemoteAddress6->sin6_port ));\r
410 }\r
4684b66f 411\r
412 //\r
413 // Connect to the remote system\r
414 //\r
415 Status = EFI_SUCCESS;\r
416 do {\r
417 //\r
418 // Check for user stop request\r
419 //\r
59bc0593 420 while ( !bTick ) {\r
4684b66f 421 Status = ControlCCheck ( );\r
422 if ( EFI_ERROR ( Status )) {\r
423 break;\r
424 }\r
425 }\r
426 bTick = FALSE;\r
427 if ( EFI_ERROR ( Status )) {\r
428 break;\r
429 }\r
430\r
431 //\r
432 // Connect to the remote system\r
433 //\r
434 ConnectStatus = connect ( Socket,\r
f6e5cdd5 435 (struct sockaddr *)pRemoteAddress6,\r
436 pRemoteAddress6->sin6_len );\r
4684b66f 437 if ( -1 != ConnectStatus ) {\r
f6e5cdd5 438 if ( AF_INET == pRemoteAddress6->sin6_family ) {\r
439 Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",\r
440 pRemoteAddress4->sin_addr.s_addr & 0xff,\r
441 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
442 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
443 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
444 htons ( pRemoteAddress4->sin_port ));\r
445 }\r
446 else {\r
447 Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
448 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
449 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
450 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
451 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
452 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
453 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
454 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
455 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
456 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
457 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
458 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
459 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
460 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
461 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
462 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
463 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
464 htons ( pRemoteAddress6->sin6_port ));\r
465 }\r
4684b66f 466 }\r
467 else {\r
468 //\r
469 // Close the socket and try again\r
470 //\r
471 if ( EAGAIN != errno ) {\r
472 Status = EFI_NOT_STARTED;\r
473 break;\r
474 }\r
475 }\r
476 } while ( -1 == ConnectStatus );\r
477\r
478 //\r
479 // Return the operation status\r
480 //\r
481 return Status;\r
482}\r
483\r
484\r
485/**\r
486 Create the socket\r
487\r
f6e5cdd5 488 @param [in] Family Network family, AF_INET or AF_INET6\r
489\r
4684b66f 490 @retval EFI_SUCCESS The application is running normally\r
491 @retval Other The user stopped the application\r
492**/\r
493EFI_STATUS\r
494SocketNew (\r
f6e5cdd5 495 sa_family_t Family\r
4684b66f 496 )\r
497{\r
498 EFI_STATUS Status;\r
499\r
500 //\r
501 // Loop creating the socket\r
502 //\r
503 DEBUG (( DEBUG_INFO,\r
504 "Creating the socket\r\n" ));\r
505 do {\r
506 //\r
507 // Check for user stop request\r
508 //\r
509 Status = ControlCCheck ( );\r
510 if ( EFI_ERROR ( Status )) {\r
511 break;\r
512 }\r
513\r
514 //\r
515 // Attempt to create the socket\r
516 //\r
f6e5cdd5 517 Socket = socket ( Family,\r
4684b66f 518 SOCK_STREAM,\r
519 IPPROTO_TCP );\r
520 if ( -1 != Socket ) {\r
521 DEBUG (( DEBUG_INFO,\r
522 "0x%08x: Socket created\r\n",\r
523 Socket ));\r
524 break;\r
525 }\r
526 } while ( -1 == Socket );\r
527\r
528 //\r
529 // Return the operation status\r
530 //\r
531 return Status;\r
532}\r
533\r
534\r
535/**\r
536 Send data over the socket\r
537\r
538 @retval EFI_SUCCESS The application is running normally\r
539 @retval Other The user stopped the application\r
540**/\r
541EFI_STATUS\r
542SocketSend (\r
543 )\r
544{\r
545 size_t BytesSent;\r
546 EFI_STATUS Status;\r
547 EFI_TPL TplPrevious;\r
548\r
549 //\r
550 // Restart the timer\r
551 //\r
f6e5cdd5 552 TimerStart ( 1 * 1000 );\r
4684b66f 553\r
554 //\r
555 // Loop until the connection breaks or the user stops\r
556 //\r
557 do {\r
558 //\r
559 // Check for user stop request\r
560 //\r
561 Status = ControlCCheck ( );\r
562 if ( EFI_ERROR ( Status )) {\r
563 break;\r
564 }\r
565\r
566 //\r
567 // Send some bytes\r
568 //\r
569 BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));\r
570 if ( -1 == BytesSent ) {\r
571 DEBUG (( DEBUG_INFO,\r
572 "ERROR: send failed, errno: %d\r\n",\r
573 errno ));\r
574\r
575 //\r
576 // Try again\r
577 //\r
578 Status = EFI_SUCCESS;\r
579\r
580//\r
581// Exit now\r
582//\r
583Status = EFI_NOT_STARTED;\r
584 break;\r
585 }\r
586\r
587 //\r
588 // Synchronize with the TimerCallback routine\r
589 //\r
590 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
591\r
592 //\r
593 // Account for the data sent\r
594 //\r
595 TotalBytesSent += BytesSent;\r
596\r
597 //\r
598 // Release the TimerCallback routine synchronization\r
599 //\r
600 gBS->RestoreTPL ( TplPrevious );\r
601 } while ( !EFI_ERROR ( Status ));\r
602\r
603 //\r
604 // Return the operation status\r
605 //\r
606 return Status;\r
607}\r
608\r
609\r
610/**\r
611 Open the network connection and send the data.\r
612\r
613 @retval EFI_SUCCESS Continue looping\r
614 @retval other Stopped by user's Control-C input\r
615\r
616**/\r
617EFI_STATUS\r
618SocketOpen (\r
619 )\r
620{\r
621 EFI_STATUS Status;\r
622\r
623 //\r
624 // Use do/while and break instead of goto\r
625 //\r
59bc0593 626 do {\r
4684b66f 627 //\r
628 // Wait for the network layer to initialize\r
629 //\r
f6e5cdd5 630 Status = SocketNew ( RemoteHostAddress.sin6_family );\r
4684b66f 631 if ( EFI_ERROR ( Status )) {\r
632 break;\r
633 }\r
634\r
635 //\r
636 // Wait for the remote network application to start\r
637 //\r
638 Status = SocketConnect ( );\r
639 if ( EFI_NOT_STARTED == Status ) {\r
640 Status = SocketClose ( );\r
641 continue;\r
642 }\r
643 else if ( EFI_SUCCESS != Status ) {\r
644 //\r
645 // Control-C\r
646 //\r
647 break;\r
648 }\r
649\r
650 //\r
651 // Send data until the connection breaks\r
652 //\r
653 Status = SocketSend ( );\r
654 if ( EFI_ERROR ( Status )) {\r
655 break;\r
656 }\r
657 } while ( FALSE );\r
658\r
659 //\r
660 // Return the operation status\r
661 //\r
662 return Status;\r
663}\r
664\r
665\r
666/**\r
667 Close the TCP connection\r
668\r
669 @retval EFI_SUCCESS The application is running normally\r
670 @retval Other The user stopped the application\r
671**/\r
672EFI_STATUS\r
673Tcp4Close (\r
674 )\r
675{\r
676 UINTN Index;\r
677 UINT8 * pIpAddress;\r
678 EFI_STATUS Status;\r
679\r
680 //\r
681 // Close the port\r
682 //\r
683 if ( bTcp4Connected ) {\r
684 Tcp4CloseToken.AbortOnClose = TRUE;\r
685 Status = pTcp4Protocol->Close ( pTcp4Protocol,\r
686 &Tcp4CloseToken );\r
687 if ( EFI_ERROR ( Status )) {\r
688 DEBUG (( DEBUG_ERROR,\r
689 "ERROR - Failed to start the TCP port close, Status: %r\r\n",\r
690 Status ));\r
691 }\r
692 else {\r
693 Status = gBS->WaitForEvent ( 1,\r
694 &Tcp4CloseToken.CompletionToken.Event,\r
695 &Index );\r
696 if ( EFI_ERROR ( Status )) {\r
697 DEBUG (( DEBUG_ERROR,\r
698 "ERROR - Failed to wait for close event, Status: %r\r\n",\r
699 Status ));\r
700 }\r
701 else {\r
702 Status = Tcp4CloseToken.CompletionToken.Status;\r
703 if ( EFI_ERROR ( Status )) {\r
704 DEBUG (( DEBUG_ERROR,\r
705 "ERROR - Failed to close the TCP port, Status: %r\r\n",\r
706 Status ));\r
707 }\r
708 else {\r
709 DEBUG (( DEBUG_INFO,\r
710 "0x%08x: TCP port closed\r\n",\r
711 pTcp4Protocol ));\r
712 bTcp4Connected = FALSE;\r
713\r
714 //\r
715 // Display the port closed message\r
716 //\r
f6e5cdd5 717 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 718 Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",\r
719 pIpAddress[0],\r
720 pIpAddress[1],\r
721 pIpAddress[2],\r
722 pIpAddress[3],\r
f6e5cdd5 723 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 724 }\r
725 }\r
726 }\r
727 }\r
728\r
729 //\r
730 // Release the events\r
731 //\r
732 if ( NULL != Tcp4TxToken.CompletionToken.Event ) {\r
733 Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );\r
734 if ( !EFI_ERROR ( Status )) {\r
735 DEBUG (( DEBUG_INFO,\r
736 "0x%08x: TX event closed\r\n",\r
737 Tcp4TxToken.CompletionToken.Event ));\r
738 Tcp4TxToken.CompletionToken.Event = NULL;\r
739 }\r
740 else {\r
741 DEBUG (( DEBUG_ERROR,\r
742 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",\r
743 Status ));\r
744 }\r
745 }\r
746\r
747 if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {\r
748 Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );\r
749 if ( !EFI_ERROR ( Status )) {\r
750 DEBUG (( DEBUG_INFO,\r
751 "0x%08x: Listen event closed\r\n",\r
752 Tcp4ListenToken.CompletionToken.Event ));\r
753 Tcp4ListenToken.CompletionToken.Event = NULL;\r
754 }\r
755 else {\r
756 DEBUG (( DEBUG_ERROR,\r
757 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",\r
758 Status ));\r
759 }\r
760 }\r
761\r
762 if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {\r
763 Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );\r
764 if ( !EFI_ERROR ( Status )) {\r
765 DEBUG (( DEBUG_INFO,\r
766 "0x%08x: Connect event closed\r\n",\r
767 Tcp4ConnectToken.CompletionToken.Event ));\r
768 Tcp4ConnectToken.CompletionToken.Event = NULL;\r
769 }\r
770 else {\r
771 DEBUG (( DEBUG_ERROR,\r
772 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",\r
773 Status ));\r
774 }\r
775 }\r
776\r
777 if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {\r
778 Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );\r
779 if ( !EFI_ERROR ( Status )) {\r
780 DEBUG (( DEBUG_INFO,\r
781 "0x%08x: Close event closed\r\n",\r
782 Tcp4CloseToken.CompletionToken.Event ));\r
783 Tcp4CloseToken.CompletionToken.Event = NULL;\r
784 }\r
785 else {\r
786 DEBUG (( DEBUG_ERROR,\r
787 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",\r
788 Status ));\r
789 }\r
790 }\r
791\r
792 //\r
793 // Close the TCP protocol\r
794 //\r
795 if ( NULL != pTcp4Protocol ) {\r
796 Status = gBS->CloseProtocol ( Tcp4Handle,\r
797 &gEfiTcp4ProtocolGuid,\r
798 gImageHandle,\r
799 NULL );\r
800 if ( EFI_ERROR ( Status )) {\r
801 DEBUG (( DEBUG_ERROR,\r
802 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",\r
803 Status ));\r
804 }\r
805 else {\r
806 DEBUG (( DEBUG_INFO,\r
807 "0x%08x: TCP4 protocol closed\r\n",\r
808 pTcp4Protocol ));\r
809 pTcp4Protocol = NULL;\r
810 }\r
811 }\r
812\r
813 //\r
814 // Done with the TCP service\r
815 //\r
816 if ( NULL != Tcp4Handle ) {\r
817 Status = pTcp4Service->DestroyChild ( pTcp4Service,\r
818 Tcp4Handle );\r
819 if ( EFI_ERROR ( Status )) {\r
820 DEBUG (( DEBUG_ERROR,\r
821 "ERROR - Failed to release TCP service handle, Status: %r\r\n",\r
822 Status ));\r
823 }\r
824 else {\r
825 DEBUG (( DEBUG_INFO,\r
826 "Ox%08x: TCP service closed\r\n",\r
827 Tcp4Handle ));\r
828 Tcp4Handle = NULL;\r
829 }\r
830 }\r
831\r
832 //\r
833 // Close the service protocol\r
834 //\r
835 if ( NULL != pTcp4Service ) {\r
836 Status = gBS->CloseProtocol ( Tcp4Controller,\r
837 &gEfiTcp4ServiceBindingProtocolGuid,\r
838 gImageHandle,\r
839 NULL );\r
840 if ( !EFI_ERROR ( Status )) {\r
841 DEBUG (( DEBUG_INFO,\r
842 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
843 Tcp4Controller ));\r
844 pTcp4Service = NULL;\r
845 }\r
846 else {\r
847 DEBUG (( DEBUG_ERROR,\r
848 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",\r
849 Status ));\r
850 }\r
851 }\r
852 Tcp4Controller = NULL;\r
853 bTcp4Connecting = TRUE;\r
854\r
855 //\r
856 // Mark the connection as closed\r
857 //\r
858 Status = EFI_SUCCESS;\r
859\r
860 //\r
861 // Return the operation status\r
862 //\r
863 return Status;\r
864}\r
865\r
866\r
867/**\r
868 Locate TCP protocol\r
869\r
870 @retval EFI_SUCCESS Protocol found\r
871 @retval other Protocl not found\r
872**/\r
873EFI_STATUS\r
874Tcp4Locate (\r
875 )\r
876{\r
877 UINTN HandleCount;\r
878 EFI_HANDLE * pHandles;\r
879 UINT8 * pIpAddress;\r
880 EFI_STATUS Status;\r
881\r
882 //\r
883 // Use do/while and break instead of goto\r
884 //\r
885 do {\r
886 //\r
887 // Attempt to locate the next TCP adapter in the system\r
888 //\r
889 Status = gBS->LocateHandleBuffer ( ByProtocol,\r
890 &gEfiTcp4ServiceBindingProtocolGuid,\r
891 NULL,\r
892 &HandleCount,\r
893 &pHandles );\r
894 if ( EFI_ERROR ( Status )) {\r
895 DEBUG (( DEBUG_WARN,\r
896 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",\r
897 Status ));\r
898 break;\r
899 }\r
900\r
901 //\r
902 // Wrap the index if necessary\r
903 //\r
904 if ( HandleCount <= Tcp4Index ) {\r
905 Tcp4Index = 0;\r
7dc13291 906\r
4684b66f 907 //\r
908 // Wait for the next timer tick\r
909 //\r
910 do {\r
911 } while ( !bTick );\r
912 bTick = FALSE;\r
913 }\r
914\r
915 //\r
916 // Display the connecting message\r
917 //\r
918 if ( bTcp4Connecting ) {\r
f6e5cdd5 919 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 920 Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",\r
921 pIpAddress[0],\r
922 pIpAddress[1],\r
923 pIpAddress[2],\r
924 pIpAddress[3],\r
f6e5cdd5 925 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 926 bTcp4Connecting = FALSE;\r
927 }\r
7dc13291 928\r
4684b66f 929 //\r
930 // Open the network controller's service protocol\r
931 //\r
59bc0593 932 Tcp4Controller = pHandles[ Tcp4Index++ ];\r
4684b66f 933 Status = gBS->OpenProtocol (\r
934 Tcp4Controller,\r
935 &gEfiTcp4ServiceBindingProtocolGuid,\r
936 (VOID **) &pTcp4Service,\r
937 gImageHandle,\r
938 NULL,\r
939 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
940 if ( EFI_ERROR ( Status )) {\r
941 DEBUG (( DEBUG_ERROR,\r
942 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",\r
943 Tcp4Controller ));\r
944 Tcp4Controller = NULL;\r
945 break;\r
946 }\r
947 DEBUG (( DEBUG_INFO,\r
948 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
949 Tcp4Controller ));\r
950\r
951 //\r
952 // Connect to the TCP service\r
953 //\r
954 Status = pTcp4Service->CreateChild ( pTcp4Service,\r
955 &Tcp4Handle );\r
956 if ( EFI_ERROR ( Status )) {\r
957 DEBUG (( DEBUG_ERROR,\r
958 "ERROR - Failed to open TCP service, Status: %r\r\n",\r
959 Status ));\r
960 Tcp4Handle = NULL;\r
961 break;\r
962 }\r
963 DEBUG (( DEBUG_INFO,\r
964 "Ox%08x: TCP service opened\r\n",\r
965 Tcp4Handle ));\r
966\r
967 //\r
968 // Locate the TCP protcol\r
969 //\r
970 Status = gBS->OpenProtocol ( Tcp4Handle,\r
971 &gEfiTcp4ProtocolGuid,\r
972 (VOID **)&pTcp4Protocol,\r
973 gImageHandle,\r
974 NULL,\r
975 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
976 if ( EFI_ERROR ( Status )) {\r
977 DEBUG (( DEBUG_ERROR,\r
978 "ERROR - Failed to open the TCP protocol, Status: %r\r\n",\r
979 Status ));\r
980 pTcp4Protocol = NULL;\r
981 break;\r
982 }\r
983 DEBUG (( DEBUG_INFO,\r
984 "0x%08x: TCP4 protocol opened\r\n",\r
985 pTcp4Protocol ));\r
986 }while ( FALSE );\r
987\r
988 //\r
989 // Release the handle buffer\r
990 //\r
991 gBS->FreePool ( pHandles );\r
992\r
993 //\r
994 // Return the operation status\r
995 //\r
996 return Status;\r
997}\r
998\r
999\r
1000/**\r
1001 Send data over the TCP4 connection\r
1002\r
1003 @retval EFI_SUCCESS The application is running normally\r
1004 @retval Other The user stopped the application\r
1005**/\r
1006EFI_STATUS\r
1007Tcp4Send (\r
1008 )\r
1009{\r
1010 UINTN Index;\r
1011 EFI_TCP4_TRANSMIT_DATA Packet;\r
1012 EFI_STATUS Status;\r
1013 EFI_TPL TplPrevious;\r
1014\r
1015 //\r
1016 // Restart the timer\r
1017 //\r
f6e5cdd5 1018 TimerStart ( 1 * 1000 );\r
4684b66f 1019\r
1020 //\r
1021 // Initialize the packet\r
1022 //\r
1023 Packet.DataLength = sizeof ( Buffer );\r
1024 Packet.FragmentCount = 1;\r
1025 Packet.Push = FALSE;\r
1026 Packet.Urgent = FALSE;\r
1027 Packet.FragmentTable[0].FragmentBuffer = &Buffer[0];\r
1028 Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer );\r
1029 Tcp4TxToken.Packet.TxData = &Packet;\r
1030\r
1031 //\r
1032 // Loop until the connection breaks or the user stops\r
1033 //\r
1034 do {\r
1035 //\r
1036 // Check for user stop request\r
1037 //\r
1038 Status = ControlCCheck ( );\r
1039 if ( EFI_ERROR ( Status )) {\r
1040 break;\r
1041 }\r
1042\r
1043 //\r
1044 // Send some bytes\r
1045 //\r
1046 Status = pTcp4Protocol->Transmit ( pTcp4Protocol,\r
1047 &Tcp4TxToken );\r
1048 if ( EFI_ERROR ( Status )) {\r
1049 DEBUG (( DEBUG_ERROR,\r
1050 "ERROR - Failed to start the transmit, Status: %r\r\n",\r
1051 Status ));\r
1052\r
1053 //\r
1054 // Try again\r
1055 //\r
1056 Status = EFI_SUCCESS;\r
1057 break;\r
1058 }\r
1059\r
1060 //\r
1061 // Wait for the transmit to complete\r
1062 //\r
1063 Status = gBS->WaitForEvent ( 1,\r
1064 &Tcp4TxToken.CompletionToken.Event,\r
1065 &Index );\r
1066 if ( EFI_ERROR ( Status )) {\r
1067 DEBUG (( DEBUG_ERROR,\r
1068 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",\r
1069 Status ));\r
1070\r
1071 //\r
1072 // Try again\r
1073 //\r
1074 Status = EFI_SUCCESS;\r
1075 break;\r
1076 }\r
1077\r
1078 //\r
1079 // Get the transmit status\r
1080 //\r
1081 Status = Tcp4TxToken.CompletionToken.Status;\r
1082 if ( EFI_ERROR ( Status )) {\r
1083 DEBUG (( DEBUG_WARN,\r
1084 "WARNING - Failed the transmission, Status: %r\r\n",\r
1085 Status ));\r
1086\r
1087 //\r
1088 // Try again\r
1089 //\r
1090 Status = EFI_SUCCESS;\r
1091\r
1092//\r
1093// Exit now\r
1094//\r
1095Status = EFI_NOT_STARTED;\r
1096 break;\r
1097 }\r
1098\r
1099 //\r
1100 // Synchronize with the TimerCallback routine\r
1101 //\r
1102 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
1103\r
1104 //\r
1105 // Account for the data sent\r
1106 //\r
1107 TotalBytesSent += Packet.DataLength;\r
1108\r
1109 //\r
1110 // Release the TimerCallback routine synchronization\r
1111 //\r
1112 gBS->RestoreTPL ( TplPrevious );\r
1113 } while ( !EFI_ERROR ( Status ));\r
1114\r
1115 //\r
1116 // Return the operation status\r
1117 //\r
1118 return Status;\r
1119}\r
1120\r
1121\r
1122/**\r
1123 Open the network connection and send the data.\r
1124\r
1125 @retval EFI_SUCCESS Continue looping\r
1126 @retval other Stopped by user's Control-C input\r
1127\r
1128**/\r
1129EFI_STATUS\r
1130Tcp4Open (\r
1131 )\r
1132{\r
1133 UINTN Index;\r
1134 UINT8 * pIpAddress;\r
1135 EFI_STATUS Status;\r
1136\r
1137 //\r
1138 // Use do/while and break instead of goto\r
1139 //\r
1140 do {\r
1141 //\r
1142 // Locate the TCP protocol\r
1143 //\r
1144 Status = Tcp4Locate ( );\r
1145 if ( EFI_ERROR ( Status )) {\r
1146 break;\r
1147 }\r
1148\r
1149 //\r
1150 // Create the necessary events\r
1151 //\r
1152 Status = gBS->CreateEvent ( 0,\r
1153 TPL_CALLBACK,\r
1154 NULL,\r
1155 NULL,\r
1156 &Tcp4CloseToken.CompletionToken.Event );\r
1157 if ( EFI_ERROR ( Status )) {\r
1158 DEBUG (( DEBUG_ERROR,\r
1159 "ERROR - Failed to create the close event, Status: %r\r\n",\r
1160 Status ));\r
1161 Tcp4CloseToken.CompletionToken.Event = NULL;\r
1162 break;\r
1163 }\r
1164 DEBUG (( DEBUG_INFO,\r
1165 "0x%08x: Close event open\r\n",\r
1166 Tcp4CloseToken.CompletionToken.Event ));\r
1167\r
1168 Status = gBS->CreateEvent ( 0,\r
1169 TPL_CALLBACK,\r
1170 NULL,\r
1171 NULL,\r
1172 &Tcp4ConnectToken.CompletionToken.Event );\r
1173 if ( EFI_ERROR ( Status )) {\r
1174 DEBUG (( DEBUG_ERROR,\r
1175 "ERROR - Failed to create the connect event, Status: %r\r\n",\r
1176 Status ));\r
1177 Tcp4ConnectToken.CompletionToken.Event = NULL;\r
1178 break;\r
1179 }\r
1180 DEBUG (( DEBUG_INFO,\r
1181 "0x%08x: Connect event open\r\n",\r
1182 Tcp4ConnectToken.CompletionToken.Event ));\r
1183\r
1184 Status = gBS->CreateEvent ( 0,\r
1185 TPL_CALLBACK,\r
1186 NULL,\r
1187 NULL,\r
1188 &Tcp4ListenToken.CompletionToken.Event );\r
1189 if ( EFI_ERROR ( Status )) {\r
1190 DEBUG (( DEBUG_ERROR,\r
1191 "ERROR - Failed to create the listen event, Status: %r\r\n",\r
1192 Status ));\r
1193 Tcp4ListenToken.CompletionToken.Event = NULL;\r
1194 break;\r
1195 }\r
1196 DEBUG (( DEBUG_INFO,\r
1197 "0x%08x: Listen event open\r\n",\r
1198 Tcp4ListenToken.CompletionToken.Event ));\r
1199\r
1200 Status = gBS->CreateEvent ( 0,\r
1201 TPL_CALLBACK,\r
1202 NULL,\r
1203 NULL,\r
1204 &Tcp4TxToken.CompletionToken.Event );\r
1205 if ( EFI_ERROR ( Status )) {\r
1206 DEBUG (( DEBUG_ERROR,\r
1207 "ERROR - Failed to create the TX event, Status: %r\r\n",\r
1208 Status ));\r
1209 Tcp4TxToken.CompletionToken.Event = NULL;\r
1210 break;\r
1211 }\r
1212 DEBUG (( DEBUG_INFO,\r
1213 "0x%08x: TX event open\r\n",\r
1214 Tcp4TxToken.CompletionToken.Event ));\r
1215\r
1216 //\r
1217 // Configure the local TCP port\r
1218 //\r
1219 Tcp4ConfigData.TimeToLive = 255;\r
1220 Tcp4ConfigData.TypeOfService = 0;\r
1221 Tcp4ConfigData.ControlOption = NULL;\r
1222 Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE;\r
1223 Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0;\r
1224 Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 0;\r
1225 Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;\r
1226 Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;\r
1227 Tcp4ConfigData.AccessPoint.StationPort = 0;\r
f6e5cdd5 1228 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8) ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
1229 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 8 );\r
1230 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 16 );\r
1231 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 24 );\r
1232 Tcp4ConfigData.AccessPoint.RemotePort = ((struct sockaddr_in *)&RemoteHostAddress)->sin_port;\r
4684b66f 1233 Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;\r
1234 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;\r
1235 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;\r
1236 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0;\r
1237 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0;\r
1238 Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
1239 &Tcp4ConfigData );\r
1240 if ( EFI_ERROR ( Status )) {\r
7dc13291 1241 DEBUG (( DEBUG_ERROR,\r
4684b66f 1242 "ERROR - Failed to configure TCP port, Status: %r\r\n",\r
1243 Status ));\r
1244 break;\r
1245 }\r
1246 DEBUG (( DEBUG_INFO,\r
1247 "0x%08x: TCP4 port configured\r\n",\r
1248 pTcp4Protocol ));\r
1249\r
1250 //\r
1251 // Connect to the remote TCP port\r
1252 //\r
1253 Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
1254 &Tcp4ConnectToken );\r
1255 if ( EFI_ERROR ( Status )) {\r
1256 DEBUG (( DEBUG_ERROR,\r
1257 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",\r
1258 Status ));\r
1259 break;\r
1260 }\r
1261 Status = gBS->WaitForEvent ( 1,\r
1262 &Tcp4ConnectToken.CompletionToken.Event,\r
1263 &Index );\r
1264 if ( EFI_ERROR ( Status )) {\r
1265 DEBUG (( DEBUG_ERROR,\r
1266 "ERROR - Failed to wait for the connection, Status: %r\r\n",\r
1267 Status ));\r
1268 break;\r
1269 }\r
1270 Status = Tcp4ConnectToken.CompletionToken.Status;\r
1271 if ( EFI_ERROR ( Status )) {\r
1272 DEBUG (( DEBUG_WARN,\r
1273 "WARNING - Failed to connect to the remote system, Status: %r\r\n",\r
1274 Status ));\r
1275 break;\r
1276 }\r
1277 DEBUG (( DEBUG_INFO,\r
1278 "0x%08x: TCP4 port connected\r\n",\r
1279 pTcp4Protocol ));\r
1280 bTcp4Connected = TRUE;\r
1281\r
1282 //\r
1283 // Display the connection\r
1284 //\r
f6e5cdd5 1285 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 1286 Print ( L"Connected to %d.%d.%d.%d:%d\r\n",\r
1287 pIpAddress[0],\r
1288 pIpAddress[1],\r
1289 pIpAddress[2],\r
1290 pIpAddress[3],\r
f6e5cdd5 1291 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 1292 } while ( 0 );\r
1293\r
1294 if ( EFI_ERROR ( Status )) {\r
1295 //\r
1296 // Try again\r
1297 //\r
1298 Status = EFI_SUCCESS;\r
1299 }\r
1300 else {\r
1301 //\r
1302 // Semd data until the connection breaks\r
1303 //\r
1304 Status = Tcp4Send ( );\r
1305 }\r
1306\r
1307 //\r
1308 // Return the operation status\r
1309 //\r
1310 return Status;\r
1311}\r
1312\r
1313\r
1314/**\r
1315 Handle the timer callback\r
1316\r
1317 @param [in] Event Event that caused this callback\r
1318 @param [in] pContext Context for this routine\r
1319**/\r
1320VOID\r
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