]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - AppPkg/Applications/Sockets/DataSource/DataSource.c
Merged socket development branch:
[mirror_edk2.git] / AppPkg / Applications / Sockets / DataSource / DataSource.c
... / ...
CommitLineData
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
33#include <stdio.h>\r
34\r
35\r
36#define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples\r
37#define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges\r
38#define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates\r
39#define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average\r
40#define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples\r
41\r
42#define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL\r
43\r
44#define PACKET_SIZE 1448 ///< Size of data packets\r
45#define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes\r
46\r
47\r
48//\r
49// Socket Data\r
50//\r
51int Socket = -1;\r
52\r
53//\r
54// TCP V4 Data\r
55//\r
56BOOLEAN bTcp4; ///< TRUE if TCP4 is being used\r
57BOOLEAN bTcp4Connected; ///< TRUE if connected to remote system\r
58BOOLEAN bTcp4Connecting; ///< TRUE while connection in progress\r
59UINTN Tcp4Index; ///< Index into handle array\r
60EFI_HANDLE Tcp4Controller; ///< Network controller handle\r
61EFI_HANDLE Tcp4Handle; ///< TCP4 port handle\r
62EFI_TCP4_PROTOCOL * pTcp4Protocol; ///< TCP4 protocol pointer\r
63EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service; ///< TCP4 Service binding\r
64EFI_TCP4_CONFIG_DATA Tcp4ConfigData;///< TCP4 configuration data\r
65EFI_TCP4_OPTION Tcp4Option; ///< TCP4 port options\r
66EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;///< Close control\r
67EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken; ///< Connection control\r
68EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken; ///< Listen control\r
69EFI_TCP4_IO_TOKEN Tcp4TxToken; ///< Normal data token\r
70\r
71//\r
72// Timer Data\r
73//\r
74volatile BOOLEAN bTick;\r
75BOOLEAN bTimerRunning;\r
76EFI_EVENT pTimer;\r
77\r
78//\r
79// Remote IP Address Data\r
80//\r
81struct sockaddr_in6 RemoteHostAddress;\r
82CHAR8 * pRemoteHost;\r
83\r
84//\r
85// Traffic Data\r
86//\r
87UINT64 TotalBytesSent;\r
88UINT32 In;\r
89UINT32 Samples;\r
90UINT64 BytesSent[ DATA_SAMPLES ];\r
91UINT8 Buffer[ DATA_BUFFER_SIZE ];\r
92\r
93\r
94//\r
95// Forward routine declarations\r
96//\r
97EFI_STATUS TimerStart ( UINTN Milliseconds );\r
98\r
99\r
100/**\r
101 Check for control C entered at console\r
102\r
103 @retval EFI_SUCCESS Control C not entered\r
104 @retval EFI_ABORTED Control C entered\r
105**/\r
106EFI_STATUS\r
107ControlCCheck (\r
108 )\r
109{\r
110 EFI_STATUS Status;\r
111\r
112 //\r
113 // Assume no user intervention\r
114 //\r
115 Status = EFI_SUCCESS;\r
116\r
117 //\r
118 // Display user stop request\r
119 //\r
120 if ( EFI_ERROR ( Status )) {\r
121 DEBUG (( DEBUG_INFO,\r
122 "User stop request!\r\n" ));\r
123 }\r
124\r
125 //\r
126 // Return the check status\r
127 //\r
128 return Status;\r
129}\r
130\r
131\r
132/**\r
133 Get a digit\r
134\r
135 @param [in] pDigit The address of the next digit\r
136 @param [out] pValue The address to receive the value\r
137\r
138 @return Returns the address of the separator\r
139\r
140**/\r
141CHAR8 *\r
142GetDigit (\r
143 CHAR8 * pDigit,\r
144 UINT32 * pValue\r
145 )\r
146{\r
147 UINT32 Value;\r
148\r
149 //\r
150 // Walk the digits\r
151 //\r
152 Value = 0;\r
153 while (( '0' <= *pDigit ) && ( '9' >= *pDigit )) {\r
154 //\r
155 // Make room for the new least significant digit\r
156 //\r
157 Value *= 10;\r
158\r
159 //\r
160 // Convert the digit from ASCII to binary\r
161 //\r
162 Value += *pDigit - '0';\r
163\r
164 //\r
165 // Set the next digit\r
166 //\r
167 pDigit += 1;\r
168 }\r
169\r
170 //\r
171 // Return the value\r
172 //\r
173 *pValue = Value;\r
174\r
175 //\r
176 // Return the next separator\r
177 //\r
178 return pDigit;\r
179}\r
180\r
181\r
182/**\r
183 Get the IP address\r
184\r
185 @retval EFI_SUCCESS The IP address is valid\r
186 @retval Other Failure to convert the IP address\r
187**/\r
188EFI_STATUS\r
189IpAddress (\r
190 )\r
191{\r
192 struct sockaddr_in * pRemoteAddress4;\r
193 struct sockaddr_in6 * pRemoteAddress6;\r
194 UINT32 RemoteAddress;\r
195 EFI_STATUS Status;\r
196 UINT32 Value1;\r
197 UINT32 Value2;\r
198 UINT32 Value3;\r
199 UINT32 Value4;\r
200 UINT32 Value5;\r
201 UINT32 Value6;\r
202 UINT32 Value7;\r
203 UINT32 Value8;\r
204\r
205 //\r
206 // Assume failure\r
207 //\r
208 Status = EFI_INVALID_PARAMETER;\r
209\r
210 //\r
211 // Get the port number\r
212 //\r
213 ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));\r
214 RemoteHostAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));\r
215 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;\r
216 pRemoteAddress6 = &RemoteHostAddress;\r
217 \r
218 //\r
219 // Convert the IP address from a string to a numeric value\r
220 //\r
221 if (( 4 == sscanf ( pRemoteHost,\r
222 "%d.%d.%d.%d",\r
223 &Value1,\r
224 &Value2,\r
225 &Value3,\r
226 &Value4 ))\r
227 && ( 255 >= Value1 )\r
228 && ( 255 >= Value2 )\r
229 && ( 255 >= Value3 )\r
230 && ( 255 >= Value4 )) {\r
231 //\r
232 // Build the IPv4 address\r
233 //\r
234 pRemoteAddress4->sin_len = sizeof ( *pRemoteAddress4 );\r
235 pRemoteAddress4->sin_family = AF_INET;\r
236 RemoteAddress = Value1\r
237 | ( Value2 << 8 )\r
238 | ( Value3 << 16 )\r
239 | ( Value4 << 24 );\r
240 pRemoteAddress4->sin_addr.s_addr = RemoteAddress;\r
241 Status = EFI_SUCCESS;\r
242\r
243 //\r
244 // Display the IP address\r
245 //\r
246 DEBUG (( DEBUG_INFO,\r
247 "%d.%d.%d.%d: Remote host IP address\r\n",\r
248 Value1,\r
249 Value2,\r
250 Value3,\r
251 Value4 ));\r
252 }\r
253 else if (( 8 == sscanf ( pRemoteHost,\r
254 "%x:%x:%x:%x:%x:%x:%x:%x",\r
255 &Value1,\r
256 &Value2,\r
257 &Value3,\r
258 &Value4,\r
259 &Value5,\r
260 &Value6,\r
261 &Value7,\r
262 &Value8 ))\r
263 && ( 0xffff >= Value1 )\r
264 && ( 0xffff >= Value2 )\r
265 && ( 0xffff >= Value3 )\r
266 && ( 0xffff >= Value4 )\r
267 && ( 0xffff >= Value5 )\r
268 && ( 0xffff >= Value6 )\r
269 && ( 0xffff >= Value7 )\r
270 && ( 0xffff >= Value8 )) {\r
271 //\r
272 // Build the IPv6 address\r
273 //\r
274 pRemoteAddress6->sin6_len = sizeof ( *pRemoteAddress6 );\r
275 pRemoteAddress6->sin6_family = AF_INET6;\r
276 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ] = (UINT8)( Value1 >> 8 );\r
277 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ] = (UINT8)Value1;\r
278 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ] = (UINT8)( Value2 >> 8 );\r
279 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ] = (UINT8)Value2;\r
280 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ] = (UINT8)( Value3 >> 8 );\r
281 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ] = (UINT8)Value3;\r
282 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ] = (UINT8)( Value4 >> 8 );\r
283 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ] = (UINT8)Value4;\r
284 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ] = (UINT8)( Value5 >> 8 );\r
285 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ] = (UINT8)Value5;\r
286 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ] = (UINT8)( Value6 >> 8 );\r
287 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ] = (UINT8)Value6;\r
288 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ] = (UINT8)( Value7 >> 8 );\r
289 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ] = (UINT8)Value7;\r
290 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ] = (UINT8)( Value8 >> 8 );\r
291 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ] = (UINT8)Value8;\r
292 Status = EFI_SUCCESS;\r
293\r
294 //\r
295 // Display the IP address\r
296 //\r
297 DEBUG (( DEBUG_INFO,\r
298 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",\r
299 Value1,\r
300 Value2,\r
301 Value3,\r
302 Value4,\r
303 Value5,\r
304 Value6,\r
305 Value7,\r
306 Value8 ));\r
307 }\r
308 else {\r
309 Print ( L"ERROR - Invalid IP address!\r\n" );\r
310 }\r
311\r
312 //\r
313 // Return the operation status\r
314 //\r
315 return Status;\r
316}\r
317\r
318\r
319/**\r
320 Close the socket\r
321\r
322 @retval EFI_SUCCESS The application is running normally\r
323 @retval Other The user stopped the application\r
324**/\r
325EFI_STATUS\r
326SocketClose (\r
327 )\r
328{\r
329 int CloseStatus;\r
330 EFI_STATUS Status;\r
331\r
332 //\r
333 // Determine if the socket is open\r
334 //\r
335 Status = EFI_DEVICE_ERROR;\r
336 if ( -1 != Socket ) {\r
337 //\r
338 // Attempt to close the socket\r
339 //\r
340 CloseStatus = close ( Socket );\r
341 if ( 0 == CloseStatus ) {\r
342 DEBUG (( DEBUG_INFO,\r
343 "0x%08x: Socket closed\r\n",\r
344 Socket ));\r
345 Socket = -1;\r
346 Status = EFI_SUCCESS;\r
347 }\r
348 else {\r
349 DEBUG (( DEBUG_ERROR,\r
350 "ERROR: Failed to close socket, errno: %d\r\n",\r
351 errno ));\r
352 }\r
353 }\r
354\r
355 //\r
356 // Return the operation status\r
357 //\r
358 return Status;\r
359}\r
360\r
361\r
362/**\r
363 Connect the socket\r
364\r
365 @retval EFI_SUCCESS The application is running normally\r
366 @retval Other The user stopped the application\r
367**/\r
368EFI_STATUS\r
369SocketConnect (\r
370 )\r
371{\r
372 int ConnectStatus;\r
373 struct sockaddr_in * pRemoteAddress4;\r
374 struct sockaddr_in6 * pRemoteAddress6;\r
375 EFI_STATUS Status;\r
376\r
377 //\r
378 // Display the connecting message\r
379 //\r
380 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;\r
381 pRemoteAddress6 = &RemoteHostAddress;\r
382 if ( AF_INET == pRemoteAddress6->sin6_family ) {\r
383 Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",\r
384 pRemoteAddress4->sin_addr.s_addr & 0xff,\r
385 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
386 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
387 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
388 htons ( pRemoteAddress4->sin_port ));\r
389 }\r
390 else {\r
391 Print ( L"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
392 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
393 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
394 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
395 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
396 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
397 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
398 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
399 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
400 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
401 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
402 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
403 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
404 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
405 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
406 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
407 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
408 htons ( pRemoteAddress6->sin6_port ));\r
409 }\r
410\r
411 //\r
412 // Connect to the remote system\r
413 //\r
414 Status = EFI_SUCCESS;\r
415 do {\r
416 //\r
417 // Check for user stop request\r
418 //\r
419 while ( !bTick ) {\r
420 Status = ControlCCheck ( );\r
421 if ( EFI_ERROR ( Status )) {\r
422 break;\r
423 }\r
424 }\r
425 bTick = FALSE;\r
426 if ( EFI_ERROR ( Status )) {\r
427 break;\r
428 }\r
429\r
430 //\r
431 // Connect to the remote system\r
432 //\r
433 ConnectStatus = connect ( Socket,\r
434 (struct sockaddr *)pRemoteAddress6,\r
435 pRemoteAddress6->sin6_len );\r
436 if ( -1 != ConnectStatus ) {\r
437 if ( AF_INET == pRemoteAddress6->sin6_family ) {\r
438 Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",\r
439 pRemoteAddress4->sin_addr.s_addr & 0xff,\r
440 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
441 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
442 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
443 htons ( pRemoteAddress4->sin_port ));\r
444 }\r
445 else {\r
446 Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
447 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
448 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
449 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
450 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
451 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
452 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
453 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
454 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
455 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
456 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
457 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
458 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
459 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
460 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
461 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
462 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
463 htons ( pRemoteAddress6->sin6_port ));\r
464 }\r
465 }\r
466 else {\r
467 //\r
468 // Close the socket and try again\r
469 //\r
470 if ( EAGAIN != errno ) {\r
471 Status = EFI_NOT_STARTED;\r
472 break;\r
473 }\r
474 }\r
475 } while ( -1 == ConnectStatus );\r
476\r
477 //\r
478 // Return the operation status\r
479 //\r
480 return Status;\r
481}\r
482\r
483\r
484/**\r
485 Create the socket\r
486\r
487 @param [in] Family Network family, AF_INET or AF_INET6\r
488\r
489 @retval EFI_SUCCESS The application is running normally\r
490 @retval Other The user stopped the application\r
491**/\r
492EFI_STATUS\r
493SocketNew (\r
494 sa_family_t Family\r
495 )\r
496{\r
497 EFI_STATUS Status;\r
498\r
499 //\r
500 // Loop creating the socket\r
501 //\r
502 DEBUG (( DEBUG_INFO,\r
503 "Creating the socket\r\n" ));\r
504 do {\r
505 //\r
506 // Check for user stop request\r
507 //\r
508 Status = ControlCCheck ( );\r
509 if ( EFI_ERROR ( Status )) {\r
510 break;\r
511 }\r
512\r
513 //\r
514 // Attempt to create the socket\r
515 //\r
516 Socket = socket ( Family,\r
517 SOCK_STREAM,\r
518 IPPROTO_TCP );\r
519 if ( -1 != Socket ) {\r
520 DEBUG (( DEBUG_INFO,\r
521 "0x%08x: Socket created\r\n",\r
522 Socket ));\r
523 break;\r
524 }\r
525 } while ( -1 == Socket );\r
526\r
527 //\r
528 // Return the operation status\r
529 //\r
530 return Status;\r
531}\r
532\r
533\r
534/**\r
535 Send data over the socket\r
536\r
537 @retval EFI_SUCCESS The application is running normally\r
538 @retval Other The user stopped the application\r
539**/\r
540EFI_STATUS\r
541SocketSend (\r
542 )\r
543{\r
544 size_t BytesSent;\r
545 EFI_STATUS Status;\r
546 EFI_TPL TplPrevious;\r
547\r
548 //\r
549 // Restart the timer\r
550 //\r
551 TimerStart ( 1 * 1000 );\r
552\r
553 //\r
554 // Loop until the connection breaks or the user stops\r
555 //\r
556 do {\r
557 //\r
558 // Check for user stop request\r
559 //\r
560 Status = ControlCCheck ( );\r
561 if ( EFI_ERROR ( Status )) {\r
562 break;\r
563 }\r
564\r
565 //\r
566 // Send some bytes\r
567 //\r
568 BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));\r
569 if ( -1 == BytesSent ) {\r
570 DEBUG (( DEBUG_INFO,\r
571 "ERROR: send failed, errno: %d\r\n",\r
572 errno ));\r
573\r
574 //\r
575 // Try again\r
576 //\r
577 Status = EFI_SUCCESS;\r
578\r
579//\r
580// Exit now\r
581//\r
582Status = EFI_NOT_STARTED;\r
583 break;\r
584 }\r
585\r
586 //\r
587 // Synchronize with the TimerCallback routine\r
588 //\r
589 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
590\r
591 //\r
592 // Account for the data sent\r
593 //\r
594 TotalBytesSent += BytesSent;\r
595\r
596 //\r
597 // Release the TimerCallback routine synchronization\r
598 //\r
599 gBS->RestoreTPL ( TplPrevious );\r
600 } while ( !EFI_ERROR ( Status ));\r
601\r
602 //\r
603 // Return the operation status\r
604 //\r
605 return Status;\r
606}\r
607\r
608\r
609/**\r
610 Open the network connection and send the data.\r
611\r
612 @retval EFI_SUCCESS Continue looping\r
613 @retval other Stopped by user's Control-C input\r
614\r
615**/\r
616EFI_STATUS\r
617SocketOpen (\r
618 )\r
619{\r
620 EFI_STATUS Status;\r
621\r
622 //\r
623 // Use do/while and break instead of goto\r
624 //\r
625 do {\r
626 //\r
627 // Wait for the network layer to initialize\r
628 //\r
629 Status = SocketNew ( RemoteHostAddress.sin6_family );\r
630 if ( EFI_ERROR ( Status )) {\r
631 break;\r
632 }\r
633\r
634 //\r
635 // Wait for the remote network application to start\r
636 //\r
637 Status = SocketConnect ( );\r
638 if ( EFI_NOT_STARTED == Status ) {\r
639 Status = SocketClose ( );\r
640 continue;\r
641 }\r
642 else if ( EFI_SUCCESS != Status ) {\r
643 //\r
644 // Control-C\r
645 //\r
646 break;\r
647 }\r
648\r
649 //\r
650 // Send data until the connection breaks\r
651 //\r
652 Status = SocketSend ( );\r
653 if ( EFI_ERROR ( Status )) {\r
654 break;\r
655 }\r
656 } while ( FALSE );\r
657\r
658 //\r
659 // Return the operation status\r
660 //\r
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
716 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
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
722 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
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
905\r
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
918 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
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
924 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
925 bTcp4Connecting = FALSE;\r
926 }\r
927\r
928 //\r
929 // Open the network controller's service protocol\r
930 //\r
931 Tcp4Controller = pHandles[ Tcp4Index++ ];\r
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
1017 TimerStart ( 1 * 1000 );\r
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
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
1231 Tcp4ConfigData.AccessPoint.RemotePort = ((struct sockaddr_in *)&RemoteHostAddress)->sin_port;\r
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
1240 DEBUG (( DEBUG_ERROR,\r
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
1284 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
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
1290 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
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
1320TimerCallback (\r
1321 IN EFI_EVENT Event,\r
1322 IN VOID * pContext\r
1323 )\r
1324{\r
1325 UINT32 Average;\r
1326 UINT64 BitsPerSecond;\r
1327 UINT32 Index;\r
1328 UINT64 TotalBytes;\r
1329\r
1330 //\r
1331 // Notify the other code of the timer tick\r
1332 //\r
1333 bTick = TRUE;\r
1334\r
1335 //\r
1336 // Update the average bytes per second\r
1337 //\r
1338 if ( 0 != TotalBytesSent ) {\r
1339 BytesSent[ In ] = TotalBytesSent;\r
1340 TotalBytesSent = 0;\r
1341 In += 1;\r
1342 if ( DATA_SAMPLES <= In ) {\r
1343 In = 0;\r
1344 }\r
1345\r
1346 //\r
1347 // Separate the samples\r
1348 //\r
1349 if ( DATA_SAMPLES == Samples ) {\r
1350 Print ( L"---------- Stable average ----------\r\n" );\r
1351 }\r
1352 Samples += 1;\r
1353\r
1354 //\r
1355 // Compute the data rate\r
1356 //\r
1357 TotalBytes = 0;\r
1358 for ( Index = 0; DATA_SAMPLES > Index; Index++ ) {\r
1359 TotalBytes += BytesSent[ Index ];\r
1360 }\r
1361 Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );\r
1362 BitsPerSecond = Average * 8;\r
1363\r
1364 //\r
1365 // Display the data rate\r
1366 //\r
1367 if (( RANGE_SWITCH >> 10 ) > Average ) {\r
1368 Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",\r
1369 Average,\r
1370 BitsPerSecond );\r
1371 }\r
1372 else {\r
1373 BitsPerSecond /= 1000;\r
1374 if ( RANGE_SWITCH > Average ) {\r
1375 Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",\r
1376 Average >> 10,\r
1377 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1378 BitsPerSecond );\r
1379 }\r
1380 else {\r
1381 BitsPerSecond /= 1000;\r
1382 Average >>= 10;\r
1383 if ( RANGE_SWITCH > Average ) {\r
1384 Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",\r
1385 Average >> 10,\r
1386 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1387 BitsPerSecond );\r
1388 }\r
1389 else {\r
1390 BitsPerSecond /= 1000;\r
1391 Average >>= 10;\r
1392 if ( RANGE_SWITCH > Average ) {\r
1393 Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",\r
1394 Average >> 10,\r
1395 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1396 BitsPerSecond );\r
1397 }\r
1398 else {\r
1399 BitsPerSecond /= 1000;\r
1400 Average >>= 10;\r
1401 if ( RANGE_SWITCH > Average ) {\r
1402 Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",\r
1403 Average >> 10,\r
1404 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1405 BitsPerSecond );\r
1406 }\r
1407 else {\r
1408 BitsPerSecond /= 1000;\r
1409 Average >>= 10;\r
1410 Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",\r
1411 Average >> 10,\r
1412 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1413 BitsPerSecond );\r
1414 }\r
1415 }\r
1416 }\r
1417 }\r
1418 }\r
1419 }\r
1420}\r
1421\r
1422\r
1423/**\r
1424 Create the timer\r
1425\r
1426 @retval EFI_SUCCESS The timer was successfully created\r
1427 @retval Other Timer initialization failed\r
1428**/\r
1429EFI_STATUS\r
1430TimerCreate (\r
1431 )\r
1432{\r
1433 EFI_STATUS Status;\r
1434\r
1435 //\r
1436 // Create the timer\r
1437 //\r
1438 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1439 TPL_DATASOURCE,\r
1440 TimerCallback,\r
1441 NULL,\r
1442 &pTimer );\r
1443 if ( EFI_ERROR ( Status )) {\r
1444 DEBUG (( DEBUG_ERROR,\r
1445 "ERROR - Failed to allocate the timer event, Status: %r\r\n",\r
1446 Status ));\r
1447 }\r
1448 else {\r
1449 DEBUG (( DEBUG_INFO,\r
1450 "0x%08x: Timer created\r\n",\r
1451 pTimer ));\r
1452 }\r
1453\r
1454 //\r
1455 // Return the operation status\r
1456 //\r
1457 return Status;\r
1458}\r
1459\r
1460\r
1461/**\r
1462 Stop the timer\r
1463\r
1464 @retval EFI_SUCCESS The timer was stopped successfully\r
1465 @retval Other The timer failed to stop\r
1466**/\r
1467EFI_STATUS\r
1468TimerStop (\r
1469 )\r
1470{\r
1471 EFI_STATUS Status;\r
1472\r
1473 //\r
1474 // Assume success\r
1475 //\r
1476 Status = EFI_SUCCESS;\r
1477\r
1478 //\r
1479 // Determine if the timer is running\r
1480 //\r
1481 if ( bTimerRunning ) {\r
1482 //\r
1483 // Stop the timer\r
1484 //\r
1485 Status = gBS->SetTimer ( pTimer,\r
1486 TimerCancel,\r
1487 0 );\r
1488 if ( EFI_ERROR ( Status )) {\r
1489 DEBUG (( DEBUG_ERROR,\r
1490 "ERROR - Failed to stop the timer, Status: %r\r\n",\r
1491 Status ));\r
1492 }\r
1493 else {\r
1494 //\r
1495 // Timer timer is now stopped\r
1496 //\r
1497 bTimerRunning = FALSE;\r
1498 DEBUG (( DEBUG_INFO,\r
1499 "0x%08x: Timer stopped\r\n",\r
1500 pTimer ));\r
1501 }\r
1502 }\r
1503\r
1504 //\r
1505 // Return the operation status\r
1506 //\r
1507 return Status;\r
1508}\r
1509\r
1510\r
1511/**\r
1512 Start the timer\r
1513\r
1514 @param [in] Milliseconds The number of milliseconds between timer callbacks\r
1515\r
1516 @retval EFI_SUCCESS The timer was successfully created\r
1517 @retval Other Timer initialization failed\r
1518**/\r
1519EFI_STATUS\r
1520TimerStart (\r
1521 UINTN Milliseconds\r
1522 )\r
1523{\r
1524 EFI_STATUS Status;\r
1525 UINT64 TimeDelay;\r
1526\r
1527 //\r
1528 // Stop the timer if necessary\r
1529 //\r
1530 Status = EFI_SUCCESS;\r
1531 if ( bTimerRunning ) {\r
1532 Status = TimerStop ( );\r
1533 }\r
1534 if ( !EFI_ERROR ( Status )) {\r
1535 //\r
1536 // Compute the new delay\r
1537 //\r
1538 TimeDelay = Milliseconds;\r
1539 TimeDelay *= 1000 * 10;\r
1540\r
1541 //\r
1542 // Start the timer\r
1543 //\r
1544 Status = gBS->SetTimer ( pTimer,\r
1545 TimerPeriodic,\r
1546 TimeDelay );\r
1547 if ( EFI_ERROR ( Status )) {\r
1548 DEBUG (( DEBUG_ERROR,\r
1549 "ERROR - Failed to start the timer, Status: %r\r\n",\r
1550 Status ));\r
1551 }\r
1552 else {\r
1553 //\r
1554 // The timer is now running\r
1555 //\r
1556 bTimerRunning = TRUE;\r
1557 DEBUG (( DEBUG_INFO,\r
1558 "0x%08x: Timer running\r\n",\r
1559 pTimer ));\r
1560 }\r
1561 }\r
1562\r
1563 //\r
1564 // Return the operation status\r
1565 //\r
1566 return Status;\r
1567}\r
1568\r
1569\r
1570/**\r
1571 Destroy the timer\r
1572\r
1573 @retval EFI_SUCCESS The timer was destroyed successfully\r
1574 @retval Other Failed to destroy the timer\r
1575**/\r
1576EFI_STATUS\r
1577TimerDestroy (\r
1578 )\r
1579{\r
1580 EFI_STATUS Status;\r
1581\r
1582 //\r
1583 // Assume success\r
1584 //\r
1585 Status = EFI_SUCCESS;\r
1586\r
1587 //\r
1588 // Determine if the timer is running\r
1589 //\r
1590 if ( bTimerRunning ) {\r
1591 //\r
1592 // Stop the timer\r
1593 //\r
1594 Status = TimerStop ( );\r
1595 }\r
1596 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {\r
1597 //\r
1598 // Done with this timer\r
1599 //\r
1600 Status = gBS->CloseEvent ( pTimer );\r
1601 if ( EFI_ERROR ( Status )) {\r
1602 DEBUG (( DEBUG_ERROR,\r
1603 "ERROR - Failed to free the timer event, Status: %r\r\n",\r
1604 Status ));\r
1605 }\r
1606 else {\r
1607 DEBUG (( DEBUG_INFO,\r
1608 "0x%08x: Timer Destroyed\r\n",\r
1609 pTimer ));\r
1610 pTimer = NULL;\r
1611 }\r
1612 }\r
1613\r
1614 //\r
1615 // Return the operation status\r
1616 //\r
1617 return Status;\r
1618}\r
1619\r
1620\r
1621/**\r
1622 Send data to the DataSink program to test a network's bandwidth.\r
1623\r
1624 @param [in] Argc The number of arguments\r
1625 @param [in] Argv The argument value array\r
1626\r
1627 @retval 0 The application exited normally.\r
1628 @retval Other An error occurred.\r
1629**/\r
1630int\r
1631main (\r
1632 IN int Argc,\r
1633 IN char **Argv\r
1634 )\r
1635{\r
1636 EFI_STATUS (* pClose) ();\r
1637 EFI_STATUS (* pOpen) ();\r
1638 EFI_STATUS Status;\r
1639\r
1640 DEBUG (( DEBUG_INFO,\r
1641 "DataSource starting\r\n" ));\r
1642\r
1643 //\r
1644 // Validate the command line\r
1645 //\r
1646 if ( 2 > Argc ) {\r
1647 Print ( L"%s <remote IP address> [Use TCP]\r\n", Argv[0] );\r
1648 return -1;\r
1649 }\r
1650\r
1651 //\r
1652 // Determine if TCP should be used\r
1653 //\r
1654 bTcp4 = (BOOLEAN)( 2 < Argc );\r
1655\r
1656 //\r
1657 // Determine the support routines\r
1658 //\r
1659 if ( bTcp4 ) {\r
1660 pOpen = Tcp4Open;\r
1661 pClose = Tcp4Close;\r
1662 bTcp4Connecting = TRUE;\r
1663 }\r
1664 else {\r
1665 pOpen = SocketOpen;\r
1666 pClose = SocketClose;\r
1667 }\r
1668\r
1669 //\r
1670 // Use for/break instead of goto\r
1671 //\r
1672 for ( ; ; ) {\r
1673 //\r
1674 // No bytes sent so far\r
1675 //\r
1676 TotalBytesSent = 0;\r
1677 Samples = 0;\r
1678 memset ( &BytesSent, 0, sizeof ( BytesSent ));\r
1679\r
1680 //\r
1681 // Get the IP address\r
1682 //\r
1683 pRemoteHost = Argv[1];\r
1684 Status = IpAddress ( );\r
1685 if ( EFI_ERROR ( Status )) {\r
1686 break;\r
1687 }\r
1688\r
1689 //\r
1690 // Create the timer\r
1691 //\r
1692 bTick = TRUE;\r
1693 Status = TimerCreate ( );\r
1694 if ( EFI_ERROR ( Status )) {\r
1695 break;\r
1696 }\r
1697\r
1698 //\r
1699 // Loop forever abusing the specified system\r
1700 //\r
1701 do {\r
1702 //\r
1703 // Start a timer to perform connection polling and display updates\r
1704 //\r
1705 Status = TimerStart ( 2 * 1000 );\r
1706 if ( EFI_ERROR ( Status )) {\r
1707 break;\r
1708 }\r
1709\r
1710 //\r
1711 // Open the network connection and send the data\r
1712 //\r
1713 Status = pOpen ( );\r
1714 if ( EFI_ERROR ( Status )) {\r
1715 break;\r
1716 }\r
1717\r
1718 //\r
1719 // Done with the network connection\r
1720 //\r
1721 Status = pClose ( );\r
1722 } while ( !EFI_ERROR ( Status ));\r
1723\r
1724 //\r
1725 // Close the network connection if necessary\r
1726 //\r
1727 pClose ( );\r
1728\r
1729 //\r
1730 // All done\r
1731 //\r
1732 break;\r
1733 }\r
1734\r
1735 //\r
1736 // Stop the timer if necessary\r
1737 //\r
1738 TimerStop ( );\r
1739 TimerDestroy ( );\r
1740\r
1741 //\r
1742 // Return the operation status\r
1743 //\r
1744 DEBUG (( DEBUG_INFO,\r
1745 "DataSource exiting, Status: %r\r\n",\r
1746 Status ));\r
1747 return Status;\r
1748}\r