]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Sockets/DataSource/DataSource.c
- For writing sin_port, htons() must be used.
[mirror_edk2.git] / AppPkg / Applications / Sockets / DataSource / DataSource.c
CommitLineData
4684b66f 1/** @file\r
2 Data source for network testing.\r
3\r
9f7f5161 4 Copyright (c) 2011-2012, Intel Corporation\r
4684b66f 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
b8a86b22 389 ntohs ( pRemoteAddress4->sin_port ));\r
f6e5cdd5 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
b8a86b22 409 ntohs ( pRemoteAddress6->sin6_port ));\r
f6e5cdd5 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
b8a86b22 444 ntohs ( pRemoteAddress4->sin_port ));\r
f6e5cdd5 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
b8a86b22 464 ntohs ( pRemoteAddress6->sin6_port ));\r
f6e5cdd5 465 }\r
b8a86b22 466Print ( L"ConnectStatus: %d, Status: %r\r\n", ConnectStatus, Status );\r
4684b66f 467 }\r
468 else {\r
469 //\r
470 // Close the socket and try again\r
471 //\r
472 if ( EAGAIN != errno ) {\r
473 Status = EFI_NOT_STARTED;\r
474 break;\r
475 }\r
476 }\r
477 } while ( -1 == ConnectStatus );\r
478\r
479 //\r
480 // Return the operation status\r
481 //\r
b8a86b22 482Print ( L"SocketConnect returning Status: %r\r\n", Status );\r
4684b66f 483 return Status;\r
484}\r
485\r
486\r
487/**\r
488 Create the socket\r
489\r
f6e5cdd5 490 @param [in] Family Network family, AF_INET or AF_INET6\r
491\r
4684b66f 492 @retval EFI_SUCCESS The application is running normally\r
493 @retval Other The user stopped the application\r
494**/\r
495EFI_STATUS\r
496SocketNew (\r
f6e5cdd5 497 sa_family_t Family\r
4684b66f 498 )\r
499{\r
500 EFI_STATUS Status;\r
501\r
502 //\r
503 // Loop creating the socket\r
504 //\r
505 DEBUG (( DEBUG_INFO,\r
506 "Creating the socket\r\n" ));\r
507 do {\r
508 //\r
509 // Check for user stop request\r
510 //\r
511 Status = ControlCCheck ( );\r
512 if ( EFI_ERROR ( Status )) {\r
513 break;\r
514 }\r
515\r
516 //\r
517 // Attempt to create the socket\r
518 //\r
f6e5cdd5 519 Socket = socket ( Family,\r
4684b66f 520 SOCK_STREAM,\r
521 IPPROTO_TCP );\r
522 if ( -1 != Socket ) {\r
523 DEBUG (( DEBUG_INFO,\r
524 "0x%08x: Socket created\r\n",\r
525 Socket ));\r
526 break;\r
527 }\r
528 } while ( -1 == Socket );\r
529\r
530 //\r
531 // Return the operation status\r
532 //\r
533 return Status;\r
534}\r
535\r
536\r
537/**\r
538 Send data over the socket\r
539\r
540 @retval EFI_SUCCESS The application is running normally\r
541 @retval Other The user stopped the application\r
542**/\r
543EFI_STATUS\r
544SocketSend (\r
545 )\r
546{\r
547 size_t BytesSent;\r
548 EFI_STATUS Status;\r
549 EFI_TPL TplPrevious;\r
550\r
551 //\r
552 // Restart the timer\r
553 //\r
f6e5cdd5 554 TimerStart ( 1 * 1000 );\r
4684b66f 555\r
556 //\r
557 // Loop until the connection breaks or the user stops\r
558 //\r
559 do {\r
560 //\r
561 // Check for user stop request\r
562 //\r
563 Status = ControlCCheck ( );\r
564 if ( EFI_ERROR ( Status )) {\r
565 break;\r
566 }\r
567\r
568 //\r
569 // Send some bytes\r
570 //\r
571 BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));\r
572 if ( -1 == BytesSent ) {\r
573 DEBUG (( DEBUG_INFO,\r
574 "ERROR: send failed, errno: %d\r\n",\r
575 errno ));\r
b8a86b22 576Print ( L"ERROR: send failed, errno: %d\r\n", errno );\r
4684b66f 577\r
578 //\r
579 // Try again\r
580 //\r
581 Status = EFI_SUCCESS;\r
582\r
583//\r
584// Exit now\r
585//\r
586Status = EFI_NOT_STARTED;\r
587 break;\r
588 }\r
589\r
590 //\r
591 // Synchronize with the TimerCallback routine\r
592 //\r
593 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
594\r
595 //\r
596 // Account for the data sent\r
597 //\r
598 TotalBytesSent += BytesSent;\r
599\r
600 //\r
601 // Release the TimerCallback routine synchronization\r
602 //\r
603 gBS->RestoreTPL ( TplPrevious );\r
604 } while ( !EFI_ERROR ( Status ));\r
605\r
606 //\r
607 // Return the operation status\r
608 //\r
609 return Status;\r
610}\r
611\r
612\r
613/**\r
614 Open the network connection and send the data.\r
615\r
616 @retval EFI_SUCCESS Continue looping\r
617 @retval other Stopped by user's Control-C input\r
618\r
619**/\r
620EFI_STATUS\r
621SocketOpen (\r
622 )\r
623{\r
624 EFI_STATUS Status;\r
625\r
626 //\r
627 // Use do/while and break instead of goto\r
628 //\r
59bc0593 629 do {\r
4684b66f 630 //\r
631 // Wait for the network layer to initialize\r
632 //\r
f6e5cdd5 633 Status = SocketNew ( RemoteHostAddress.sin6_family );\r
4684b66f 634 if ( EFI_ERROR ( Status )) {\r
635 break;\r
636 }\r
637\r
638 //\r
639 // Wait for the remote network application to start\r
640 //\r
641 Status = SocketConnect ( );\r
b8a86b22 642Print ( L"Status: %r\r\n", Status );\r
4684b66f 643 if ( EFI_NOT_STARTED == Status ) {\r
644 Status = SocketClose ( );\r
645 continue;\r
646 }\r
647 else if ( EFI_SUCCESS != Status ) {\r
648 //\r
649 // Control-C\r
650 //\r
651 break;\r
652 }\r
653\r
654 //\r
655 // Send data until the connection breaks\r
656 //\r
657 Status = SocketSend ( );\r
658 if ( EFI_ERROR ( Status )) {\r
659 break;\r
660 }\r
661 } while ( FALSE );\r
662\r
663 //\r
664 // Return the operation status\r
665 //\r
b8a86b22 666Print ( L"Returning Status: %r\r\n", Status );\r
4684b66f 667 return Status;\r
668}\r
669\r
670\r
671/**\r
672 Close the TCP connection\r
673\r
674 @retval EFI_SUCCESS The application is running normally\r
675 @retval Other The user stopped the application\r
676**/\r
677EFI_STATUS\r
678Tcp4Close (\r
679 )\r
680{\r
681 UINTN Index;\r
682 UINT8 * pIpAddress;\r
683 EFI_STATUS Status;\r
684\r
685 //\r
686 // Close the port\r
687 //\r
688 if ( bTcp4Connected ) {\r
689 Tcp4CloseToken.AbortOnClose = TRUE;\r
690 Status = pTcp4Protocol->Close ( pTcp4Protocol,\r
691 &Tcp4CloseToken );\r
692 if ( EFI_ERROR ( Status )) {\r
693 DEBUG (( DEBUG_ERROR,\r
694 "ERROR - Failed to start the TCP port close, Status: %r\r\n",\r
695 Status ));\r
696 }\r
697 else {\r
698 Status = gBS->WaitForEvent ( 1,\r
699 &Tcp4CloseToken.CompletionToken.Event,\r
700 &Index );\r
701 if ( EFI_ERROR ( Status )) {\r
702 DEBUG (( DEBUG_ERROR,\r
703 "ERROR - Failed to wait for close event, Status: %r\r\n",\r
704 Status ));\r
705 }\r
706 else {\r
707 Status = Tcp4CloseToken.CompletionToken.Status;\r
708 if ( EFI_ERROR ( Status )) {\r
709 DEBUG (( DEBUG_ERROR,\r
710 "ERROR - Failed to close the TCP port, Status: %r\r\n",\r
711 Status ));\r
712 }\r
713 else {\r
714 DEBUG (( DEBUG_INFO,\r
715 "0x%08x: TCP port closed\r\n",\r
716 pTcp4Protocol ));\r
717 bTcp4Connected = FALSE;\r
718\r
719 //\r
720 // Display the port closed message\r
721 //\r
f6e5cdd5 722 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 723 Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",\r
724 pIpAddress[0],\r
725 pIpAddress[1],\r
726 pIpAddress[2],\r
727 pIpAddress[3],\r
b8a86b22 728 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 729 }\r
730 }\r
731 }\r
732 }\r
733\r
734 //\r
735 // Release the events\r
736 //\r
737 if ( NULL != Tcp4TxToken.CompletionToken.Event ) {\r
738 Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );\r
739 if ( !EFI_ERROR ( Status )) {\r
740 DEBUG (( DEBUG_INFO,\r
741 "0x%08x: TX event closed\r\n",\r
742 Tcp4TxToken.CompletionToken.Event ));\r
743 Tcp4TxToken.CompletionToken.Event = NULL;\r
744 }\r
745 else {\r
746 DEBUG (( DEBUG_ERROR,\r
747 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",\r
748 Status ));\r
749 }\r
750 }\r
751\r
752 if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {\r
753 Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );\r
754 if ( !EFI_ERROR ( Status )) {\r
755 DEBUG (( DEBUG_INFO,\r
756 "0x%08x: Listen event closed\r\n",\r
757 Tcp4ListenToken.CompletionToken.Event ));\r
758 Tcp4ListenToken.CompletionToken.Event = NULL;\r
759 }\r
760 else {\r
761 DEBUG (( DEBUG_ERROR,\r
762 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",\r
763 Status ));\r
764 }\r
765 }\r
766\r
767 if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {\r
768 Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );\r
769 if ( !EFI_ERROR ( Status )) {\r
770 DEBUG (( DEBUG_INFO,\r
771 "0x%08x: Connect event closed\r\n",\r
772 Tcp4ConnectToken.CompletionToken.Event ));\r
773 Tcp4ConnectToken.CompletionToken.Event = NULL;\r
774 }\r
775 else {\r
776 DEBUG (( DEBUG_ERROR,\r
777 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",\r
778 Status ));\r
779 }\r
780 }\r
781\r
782 if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {\r
783 Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );\r
784 if ( !EFI_ERROR ( Status )) {\r
785 DEBUG (( DEBUG_INFO,\r
786 "0x%08x: Close event closed\r\n",\r
787 Tcp4CloseToken.CompletionToken.Event ));\r
788 Tcp4CloseToken.CompletionToken.Event = NULL;\r
789 }\r
790 else {\r
791 DEBUG (( DEBUG_ERROR,\r
792 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",\r
793 Status ));\r
794 }\r
795 }\r
796\r
797 //\r
798 // Close the TCP protocol\r
799 //\r
800 if ( NULL != pTcp4Protocol ) {\r
801 Status = gBS->CloseProtocol ( Tcp4Handle,\r
802 &gEfiTcp4ProtocolGuid,\r
803 gImageHandle,\r
804 NULL );\r
805 if ( EFI_ERROR ( Status )) {\r
806 DEBUG (( DEBUG_ERROR,\r
807 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",\r
808 Status ));\r
809 }\r
810 else {\r
811 DEBUG (( DEBUG_INFO,\r
812 "0x%08x: TCP4 protocol closed\r\n",\r
813 pTcp4Protocol ));\r
814 pTcp4Protocol = NULL;\r
815 }\r
816 }\r
817\r
818 //\r
819 // Done with the TCP service\r
820 //\r
821 if ( NULL != Tcp4Handle ) {\r
822 Status = pTcp4Service->DestroyChild ( pTcp4Service,\r
823 Tcp4Handle );\r
824 if ( EFI_ERROR ( Status )) {\r
825 DEBUG (( DEBUG_ERROR,\r
826 "ERROR - Failed to release TCP service handle, Status: %r\r\n",\r
827 Status ));\r
828 }\r
829 else {\r
830 DEBUG (( DEBUG_INFO,\r
831 "Ox%08x: TCP service closed\r\n",\r
832 Tcp4Handle ));\r
833 Tcp4Handle = NULL;\r
834 }\r
835 }\r
836\r
837 //\r
838 // Close the service protocol\r
839 //\r
840 if ( NULL != pTcp4Service ) {\r
841 Status = gBS->CloseProtocol ( Tcp4Controller,\r
842 &gEfiTcp4ServiceBindingProtocolGuid,\r
843 gImageHandle,\r
844 NULL );\r
845 if ( !EFI_ERROR ( Status )) {\r
846 DEBUG (( DEBUG_INFO,\r
847 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
848 Tcp4Controller ));\r
849 pTcp4Service = NULL;\r
850 }\r
851 else {\r
852 DEBUG (( DEBUG_ERROR,\r
853 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",\r
854 Status ));\r
855 }\r
856 }\r
857 Tcp4Controller = NULL;\r
858 bTcp4Connecting = TRUE;\r
859\r
860 //\r
861 // Mark the connection as closed\r
862 //\r
863 Status = EFI_SUCCESS;\r
864\r
865 //\r
866 // Return the operation status\r
867 //\r
868 return Status;\r
869}\r
870\r
871\r
872/**\r
873 Locate TCP protocol\r
874\r
875 @retval EFI_SUCCESS Protocol found\r
876 @retval other Protocl not found\r
877**/\r
878EFI_STATUS\r
879Tcp4Locate (\r
880 )\r
881{\r
882 UINTN HandleCount;\r
883 EFI_HANDLE * pHandles;\r
884 UINT8 * pIpAddress;\r
885 EFI_STATUS Status;\r
886\r
887 //\r
888 // Use do/while and break instead of goto\r
889 //\r
890 do {\r
891 //\r
892 // Attempt to locate the next TCP adapter in the system\r
893 //\r
894 Status = gBS->LocateHandleBuffer ( ByProtocol,\r
895 &gEfiTcp4ServiceBindingProtocolGuid,\r
896 NULL,\r
897 &HandleCount,\r
898 &pHandles );\r
899 if ( EFI_ERROR ( Status )) {\r
900 DEBUG (( DEBUG_WARN,\r
901 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",\r
902 Status ));\r
903 break;\r
904 }\r
905\r
906 //\r
907 // Wrap the index if necessary\r
908 //\r
909 if ( HandleCount <= Tcp4Index ) {\r
910 Tcp4Index = 0;\r
7dc13291 911\r
4684b66f 912 //\r
913 // Wait for the next timer tick\r
914 //\r
915 do {\r
916 } while ( !bTick );\r
917 bTick = FALSE;\r
918 }\r
919\r
920 //\r
921 // Display the connecting message\r
922 //\r
923 if ( bTcp4Connecting ) {\r
f6e5cdd5 924 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 925 Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",\r
926 pIpAddress[0],\r
927 pIpAddress[1],\r
928 pIpAddress[2],\r
929 pIpAddress[3],\r
b8a86b22 930 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 931 bTcp4Connecting = FALSE;\r
932 }\r
7dc13291 933\r
4684b66f 934 //\r
935 // Open the network controller's service protocol\r
936 //\r
59bc0593 937 Tcp4Controller = pHandles[ Tcp4Index++ ];\r
4684b66f 938 Status = gBS->OpenProtocol (\r
939 Tcp4Controller,\r
940 &gEfiTcp4ServiceBindingProtocolGuid,\r
941 (VOID **) &pTcp4Service,\r
942 gImageHandle,\r
943 NULL,\r
944 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
945 if ( EFI_ERROR ( Status )) {\r
946 DEBUG (( DEBUG_ERROR,\r
947 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",\r
948 Tcp4Controller ));\r
949 Tcp4Controller = NULL;\r
950 break;\r
951 }\r
952 DEBUG (( DEBUG_INFO,\r
953 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
954 Tcp4Controller ));\r
955\r
956 //\r
957 // Connect to the TCP service\r
958 //\r
959 Status = pTcp4Service->CreateChild ( pTcp4Service,\r
960 &Tcp4Handle );\r
961 if ( EFI_ERROR ( Status )) {\r
962 DEBUG (( DEBUG_ERROR,\r
963 "ERROR - Failed to open TCP service, Status: %r\r\n",\r
964 Status ));\r
965 Tcp4Handle = NULL;\r
966 break;\r
967 }\r
968 DEBUG (( DEBUG_INFO,\r
969 "Ox%08x: TCP service opened\r\n",\r
970 Tcp4Handle ));\r
971\r
972 //\r
973 // Locate the TCP protcol\r
974 //\r
975 Status = gBS->OpenProtocol ( Tcp4Handle,\r
976 &gEfiTcp4ProtocolGuid,\r
977 (VOID **)&pTcp4Protocol,\r
978 gImageHandle,\r
979 NULL,\r
980 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
981 if ( EFI_ERROR ( Status )) {\r
982 DEBUG (( DEBUG_ERROR,\r
983 "ERROR - Failed to open the TCP protocol, Status: %r\r\n",\r
984 Status ));\r
985 pTcp4Protocol = NULL;\r
986 break;\r
987 }\r
988 DEBUG (( DEBUG_INFO,\r
989 "0x%08x: TCP4 protocol opened\r\n",\r
990 pTcp4Protocol ));\r
991 }while ( FALSE );\r
992\r
993 //\r
994 // Release the handle buffer\r
995 //\r
996 gBS->FreePool ( pHandles );\r
997\r
998 //\r
999 // Return the operation status\r
1000 //\r
1001 return Status;\r
1002}\r
1003\r
1004\r
1005/**\r
1006 Send data over the TCP4 connection\r
1007\r
1008 @retval EFI_SUCCESS The application is running normally\r
1009 @retval Other The user stopped the application\r
1010**/\r
1011EFI_STATUS\r
1012Tcp4Send (\r
1013 )\r
1014{\r
1015 UINTN Index;\r
1016 EFI_TCP4_TRANSMIT_DATA Packet;\r
1017 EFI_STATUS Status;\r
1018 EFI_TPL TplPrevious;\r
1019\r
1020 //\r
1021 // Restart the timer\r
1022 //\r
f6e5cdd5 1023 TimerStart ( 1 * 1000 );\r
4684b66f 1024\r
1025 //\r
1026 // Initialize the packet\r
1027 //\r
1028 Packet.DataLength = sizeof ( Buffer );\r
1029 Packet.FragmentCount = 1;\r
1030 Packet.Push = FALSE;\r
1031 Packet.Urgent = FALSE;\r
1032 Packet.FragmentTable[0].FragmentBuffer = &Buffer[0];\r
1033 Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer );\r
1034 Tcp4TxToken.Packet.TxData = &Packet;\r
1035\r
1036 //\r
1037 // Loop until the connection breaks or the user stops\r
1038 //\r
1039 do {\r
1040 //\r
1041 // Check for user stop request\r
1042 //\r
1043 Status = ControlCCheck ( );\r
1044 if ( EFI_ERROR ( Status )) {\r
1045 break;\r
1046 }\r
1047\r
1048 //\r
1049 // Send some bytes\r
1050 //\r
1051 Status = pTcp4Protocol->Transmit ( pTcp4Protocol,\r
1052 &Tcp4TxToken );\r
1053 if ( EFI_ERROR ( Status )) {\r
1054 DEBUG (( DEBUG_ERROR,\r
1055 "ERROR - Failed to start the transmit, Status: %r\r\n",\r
1056 Status ));\r
1057\r
1058 //\r
1059 // Try again\r
1060 //\r
1061 Status = EFI_SUCCESS;\r
1062 break;\r
1063 }\r
1064\r
1065 //\r
1066 // Wait for the transmit to complete\r
1067 //\r
1068 Status = gBS->WaitForEvent ( 1,\r
1069 &Tcp4TxToken.CompletionToken.Event,\r
1070 &Index );\r
1071 if ( EFI_ERROR ( Status )) {\r
1072 DEBUG (( DEBUG_ERROR,\r
1073 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",\r
1074 Status ));\r
1075\r
1076 //\r
1077 // Try again\r
1078 //\r
1079 Status = EFI_SUCCESS;\r
1080 break;\r
1081 }\r
1082\r
1083 //\r
1084 // Get the transmit status\r
1085 //\r
1086 Status = Tcp4TxToken.CompletionToken.Status;\r
1087 if ( EFI_ERROR ( Status )) {\r
1088 DEBUG (( DEBUG_WARN,\r
1089 "WARNING - Failed the transmission, Status: %r\r\n",\r
1090 Status ));\r
1091\r
1092 //\r
1093 // Try again\r
1094 //\r
1095 Status = EFI_SUCCESS;\r
1096\r
1097//\r
1098// Exit now\r
1099//\r
1100Status = EFI_NOT_STARTED;\r
1101 break;\r
1102 }\r
1103\r
1104 //\r
1105 // Synchronize with the TimerCallback routine\r
1106 //\r
1107 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
1108\r
1109 //\r
1110 // Account for the data sent\r
1111 //\r
1112 TotalBytesSent += Packet.DataLength;\r
1113\r
1114 //\r
1115 // Release the TimerCallback routine synchronization\r
1116 //\r
1117 gBS->RestoreTPL ( TplPrevious );\r
1118 } while ( !EFI_ERROR ( Status ));\r
1119\r
1120 //\r
1121 // Return the operation status\r
1122 //\r
1123 return Status;\r
1124}\r
1125\r
1126\r
1127/**\r
1128 Open the network connection and send the data.\r
1129\r
1130 @retval EFI_SUCCESS Continue looping\r
1131 @retval other Stopped by user's Control-C input\r
1132\r
1133**/\r
1134EFI_STATUS\r
1135Tcp4Open (\r
1136 )\r
1137{\r
1138 UINTN Index;\r
1139 UINT8 * pIpAddress;\r
1140 EFI_STATUS Status;\r
1141\r
1142 //\r
1143 // Use do/while and break instead of goto\r
1144 //\r
1145 do {\r
1146 //\r
1147 // Locate the TCP protocol\r
1148 //\r
1149 Status = Tcp4Locate ( );\r
1150 if ( EFI_ERROR ( Status )) {\r
1151 break;\r
1152 }\r
1153\r
1154 //\r
1155 // Create the necessary events\r
1156 //\r
1157 Status = gBS->CreateEvent ( 0,\r
1158 TPL_CALLBACK,\r
1159 NULL,\r
1160 NULL,\r
1161 &Tcp4CloseToken.CompletionToken.Event );\r
1162 if ( EFI_ERROR ( Status )) {\r
1163 DEBUG (( DEBUG_ERROR,\r
1164 "ERROR - Failed to create the close event, Status: %r\r\n",\r
1165 Status ));\r
1166 Tcp4CloseToken.CompletionToken.Event = NULL;\r
1167 break;\r
1168 }\r
1169 DEBUG (( DEBUG_INFO,\r
1170 "0x%08x: Close event open\r\n",\r
1171 Tcp4CloseToken.CompletionToken.Event ));\r
1172\r
1173 Status = gBS->CreateEvent ( 0,\r
1174 TPL_CALLBACK,\r
1175 NULL,\r
1176 NULL,\r
1177 &Tcp4ConnectToken.CompletionToken.Event );\r
1178 if ( EFI_ERROR ( Status )) {\r
1179 DEBUG (( DEBUG_ERROR,\r
1180 "ERROR - Failed to create the connect event, Status: %r\r\n",\r
1181 Status ));\r
1182 Tcp4ConnectToken.CompletionToken.Event = NULL;\r
1183 break;\r
1184 }\r
1185 DEBUG (( DEBUG_INFO,\r
1186 "0x%08x: Connect event open\r\n",\r
1187 Tcp4ConnectToken.CompletionToken.Event ));\r
1188\r
1189 Status = gBS->CreateEvent ( 0,\r
1190 TPL_CALLBACK,\r
1191 NULL,\r
1192 NULL,\r
1193 &Tcp4ListenToken.CompletionToken.Event );\r
1194 if ( EFI_ERROR ( Status )) {\r
1195 DEBUG (( DEBUG_ERROR,\r
1196 "ERROR - Failed to create the listen event, Status: %r\r\n",\r
1197 Status ));\r
1198 Tcp4ListenToken.CompletionToken.Event = NULL;\r
1199 break;\r
1200 }\r
1201 DEBUG (( DEBUG_INFO,\r
1202 "0x%08x: Listen event open\r\n",\r
1203 Tcp4ListenToken.CompletionToken.Event ));\r
1204\r
1205 Status = gBS->CreateEvent ( 0,\r
1206 TPL_CALLBACK,\r
1207 NULL,\r
1208 NULL,\r
1209 &Tcp4TxToken.CompletionToken.Event );\r
1210 if ( EFI_ERROR ( Status )) {\r
1211 DEBUG (( DEBUG_ERROR,\r
1212 "ERROR - Failed to create the TX event, Status: %r\r\n",\r
1213 Status ));\r
1214 Tcp4TxToken.CompletionToken.Event = NULL;\r
1215 break;\r
1216 }\r
1217 DEBUG (( DEBUG_INFO,\r
1218 "0x%08x: TX event open\r\n",\r
1219 Tcp4TxToken.CompletionToken.Event ));\r
1220\r
1221 //\r
1222 // Configure the local TCP port\r
1223 //\r
1224 Tcp4ConfigData.TimeToLive = 255;\r
1225 Tcp4ConfigData.TypeOfService = 0;\r
1226 Tcp4ConfigData.ControlOption = NULL;\r
1227 Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE;\r
1228 Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0;\r
1229 Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 0;\r
1230 Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;\r
1231 Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;\r
1232 Tcp4ConfigData.AccessPoint.StationPort = 0;\r
f6e5cdd5 1233 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8) ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
1234 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 8 );\r
1235 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 16 );\r
1236 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 24 );\r
b8a86b22 1237 Tcp4ConfigData.AccessPoint.RemotePort = ntohs (((struct sockaddr_in *)&RemoteHostAddress)->sin_port);\r
4684b66f 1238 Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;\r
1239 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;\r
1240 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;\r
1241 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0;\r
1242 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0;\r
1243 Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
1244 &Tcp4ConfigData );\r
1245 if ( EFI_ERROR ( Status )) {\r
7dc13291 1246 DEBUG (( DEBUG_ERROR,\r
4684b66f 1247 "ERROR - Failed to configure TCP port, Status: %r\r\n",\r
1248 Status ));\r
1249 break;\r
1250 }\r
1251 DEBUG (( DEBUG_INFO,\r
1252 "0x%08x: TCP4 port configured\r\n",\r
1253 pTcp4Protocol ));\r
1254\r
1255 //\r
1256 // Connect to the remote TCP port\r
1257 //\r
1258 Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
1259 &Tcp4ConnectToken );\r
1260 if ( EFI_ERROR ( Status )) {\r
1261 DEBUG (( DEBUG_ERROR,\r
1262 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",\r
1263 Status ));\r
1264 break;\r
1265 }\r
1266 Status = gBS->WaitForEvent ( 1,\r
1267 &Tcp4ConnectToken.CompletionToken.Event,\r
1268 &Index );\r
1269 if ( EFI_ERROR ( Status )) {\r
1270 DEBUG (( DEBUG_ERROR,\r
1271 "ERROR - Failed to wait for the connection, Status: %r\r\n",\r
1272 Status ));\r
1273 break;\r
1274 }\r
1275 Status = Tcp4ConnectToken.CompletionToken.Status;\r
1276 if ( EFI_ERROR ( Status )) {\r
1277 DEBUG (( DEBUG_WARN,\r
1278 "WARNING - Failed to connect to the remote system, Status: %r\r\n",\r
1279 Status ));\r
1280 break;\r
1281 }\r
1282 DEBUG (( DEBUG_INFO,\r
1283 "0x%08x: TCP4 port connected\r\n",\r
1284 pTcp4Protocol ));\r
1285 bTcp4Connected = TRUE;\r
1286\r
1287 //\r
1288 // Display the connection\r
1289 //\r
f6e5cdd5 1290 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
4684b66f 1291 Print ( L"Connected to %d.%d.%d.%d:%d\r\n",\r
1292 pIpAddress[0],\r
1293 pIpAddress[1],\r
1294 pIpAddress[2],\r
1295 pIpAddress[3],\r
b8a86b22 1296 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
4684b66f 1297 } while ( 0 );\r
1298\r
1299 if ( EFI_ERROR ( Status )) {\r
1300 //\r
1301 // Try again\r
1302 //\r
1303 Status = EFI_SUCCESS;\r
1304 }\r
1305 else {\r
1306 //\r
1307 // Semd data until the connection breaks\r
1308 //\r
1309 Status = Tcp4Send ( );\r
1310 }\r
1311\r
1312 //\r
1313 // Return the operation status\r
1314 //\r
1315 return Status;\r
1316}\r
1317\r
1318\r
1319/**\r
1320 Handle the timer callback\r
1321\r
1322 @param [in] Event Event that caused this callback\r
1323 @param [in] pContext Context for this routine\r
1324**/\r
1325VOID\r
53c31c51 1326EFIAPI\r
4684b66f 1327TimerCallback (\r
1328 IN EFI_EVENT Event,\r
1329 IN VOID * pContext\r
1330 )\r
1331{\r
f6e5cdd5 1332 UINT32 Average;\r
1333 UINT64 BitsPerSecond;\r
1334 UINT32 Index;\r
1335 UINT64 TotalBytes;\r
4684b66f 1336\r
1337 //\r
1338 // Notify the other code of the timer tick\r
1339 //\r
1340 bTick = TRUE;\r
1341\r
1342 //\r
1343 // Update the average bytes per second\r
1344 //\r
f6e5cdd5 1345 if ( 0 != TotalBytesSent ) {\r
1346 BytesSent[ In ] = TotalBytesSent;\r
1347 TotalBytesSent = 0;\r
1348 In += 1;\r
1349 if ( DATA_SAMPLES <= In ) {\r
1350 In = 0;\r
1351 }\r
4684b66f 1352\r
1353 //\r
1354 // Separate the samples\r
1355 //\r
f6e5cdd5 1356 if ( DATA_SAMPLES == Samples ) {\r
4684b66f 1357 Print ( L"---------- Stable average ----------\r\n" );\r
1358 }\r
1359 Samples += 1;\r
1360\r
f6e5cdd5 1361 //\r
1362 // Compute the data rate\r
1363 //\r
1364 TotalBytes = 0;\r
1365 for ( Index = 0; DATA_SAMPLES > Index; Index++ ) {\r
1366 TotalBytes += BytesSent[ Index ];\r
1367 }\r
1368 Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );\r
1369 BitsPerSecond = Average * 8;\r
1370\r
4684b66f 1371 //\r
1372 // Display the data rate\r
1373 //\r
f6e5cdd5 1374 if (( RANGE_SWITCH >> 10 ) > Average ) {\r
1375 Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",\r
1376 Average,\r
1377 BitsPerSecond );\r
4684b66f 1378 }\r
1379 else {\r
f6e5cdd5 1380 BitsPerSecond /= 1000;\r
1381 if ( RANGE_SWITCH > Average ) {\r
1382 Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",\r
1383 Average >> 10,\r
1384 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1385 BitsPerSecond );\r
4684b66f 1386 }\r
1387 else {\r
f6e5cdd5 1388 BitsPerSecond /= 1000;\r
4684b66f 1389 Average >>= 10;\r
f6e5cdd5 1390 if ( RANGE_SWITCH > Average ) {\r
1391 Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",\r
1392 Average >> 10,\r
1393 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1394 BitsPerSecond );\r
4684b66f 1395 }\r
1396 else {\r
f6e5cdd5 1397 BitsPerSecond /= 1000;\r
4684b66f 1398 Average >>= 10;\r
f6e5cdd5 1399 if ( RANGE_SWITCH > Average ) {\r
1400 Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",\r
1401 Average >> 10,\r
1402 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1403 BitsPerSecond );\r
4684b66f 1404 }\r
1405 else {\r
f6e5cdd5 1406 BitsPerSecond /= 1000;\r
4684b66f 1407 Average >>= 10;\r
f6e5cdd5 1408 if ( RANGE_SWITCH > Average ) {\r
1409 Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",\r
1410 Average >> 10,\r
1411 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1412 BitsPerSecond );\r
4684b66f 1413 }\r
1414 else {\r
f6e5cdd5 1415 BitsPerSecond /= 1000;\r
4684b66f 1416 Average >>= 10;\r
f6e5cdd5 1417 Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",\r
1418 Average >> 10,\r
1419 (( Average & 0x3ff ) * 1000 ) >> 10,\r
1420 BitsPerSecond );\r
4684b66f 1421 }\r
1422 }\r
1423 }\r
1424 }\r
1425 }\r
1426 }\r
1427}\r
1428\r
1429\r
1430/**\r
1431 Create the timer\r
1432\r
1433 @retval EFI_SUCCESS The timer was successfully created\r
1434 @retval Other Timer initialization failed\r
1435**/\r
1436EFI_STATUS\r
1437TimerCreate (\r
1438 )\r
1439{\r
1440 EFI_STATUS Status;\r
1441\r
1442 //\r
1443 // Create the timer\r
1444 //\r
1445 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1446 TPL_DATASOURCE,\r
1447 TimerCallback,\r
1448 NULL,\r
1449 &pTimer );\r
1450 if ( EFI_ERROR ( Status )) {\r
1451 DEBUG (( DEBUG_ERROR,\r
1452 "ERROR - Failed to allocate the timer event, Status: %r\r\n",\r
1453 Status ));\r
1454 }\r
1455 else {\r
1456 DEBUG (( DEBUG_INFO,\r
1457 "0x%08x: Timer created\r\n",\r
1458 pTimer ));\r
1459 }\r
1460\r
1461 //\r
1462 // Return the operation status\r
1463 //\r
1464 return Status;\r
1465}\r
1466\r
1467\r
1468/**\r
1469 Stop the timer\r
1470\r
1471 @retval EFI_SUCCESS The timer was stopped successfully\r
1472 @retval Other The timer failed to stop\r
1473**/\r
1474EFI_STATUS\r
1475TimerStop (\r
1476 )\r
1477{\r
1478 EFI_STATUS Status;\r
1479\r
1480 //\r
1481 // Assume success\r
1482 //\r
1483 Status = EFI_SUCCESS;\r
1484\r
1485 //\r
1486 // Determine if the timer is running\r
1487 //\r
1488 if ( bTimerRunning ) {\r
1489 //\r
1490 // Stop the timer\r
1491 //\r
1492 Status = gBS->SetTimer ( pTimer,\r
1493 TimerCancel,\r
1494 0 );\r
1495 if ( EFI_ERROR ( Status )) {\r
1496 DEBUG (( DEBUG_ERROR,\r
1497 "ERROR - Failed to stop the timer, Status: %r\r\n",\r
1498 Status ));\r
1499 }\r
1500 else {\r
1501 //\r
1502 // Timer timer is now stopped\r
1503 //\r
1504 bTimerRunning = FALSE;\r
1505 DEBUG (( DEBUG_INFO,\r
1506 "0x%08x: Timer stopped\r\n",\r
1507 pTimer ));\r
1508 }\r
1509 }\r
1510\r
1511 //\r
1512 // Return the operation status\r
1513 //\r
1514 return Status;\r
1515}\r
1516\r
1517\r
1518/**\r
1519 Start the timer\r
1520\r
1521 @param [in] Milliseconds The number of milliseconds between timer callbacks\r
1522\r
1523 @retval EFI_SUCCESS The timer was successfully created\r
1524 @retval Other Timer initialization failed\r
1525**/\r
1526EFI_STATUS\r
1527TimerStart (\r
1528 UINTN Milliseconds\r
1529 )\r
1530{\r
1531 EFI_STATUS Status;\r
1532 UINT64 TimeDelay;\r
1533\r
1534 //\r
1535 // Stop the timer if necessary\r
1536 //\r
1537 Status = EFI_SUCCESS;\r
1538 if ( bTimerRunning ) {\r
1539 Status = TimerStop ( );\r
1540 }\r
1541 if ( !EFI_ERROR ( Status )) {\r
1542 //\r
1543 // Compute the new delay\r
1544 //\r
1545 TimeDelay = Milliseconds;\r
1546 TimeDelay *= 1000 * 10;\r
1547\r
1548 //\r
1549 // Start the timer\r
1550 //\r
1551 Status = gBS->SetTimer ( pTimer,\r
1552 TimerPeriodic,\r
1553 TimeDelay );\r
1554 if ( EFI_ERROR ( Status )) {\r
1555 DEBUG (( DEBUG_ERROR,\r
1556 "ERROR - Failed to start the timer, Status: %r\r\n",\r
1557 Status ));\r
1558 }\r
1559 else {\r
1560 //\r
1561 // The timer is now running\r
1562 //\r
1563 bTimerRunning = TRUE;\r
1564 DEBUG (( DEBUG_INFO,\r
1565 "0x%08x: Timer running\r\n",\r
1566 pTimer ));\r
1567 }\r
1568 }\r
1569\r
1570 //\r
1571 // Return the operation status\r
1572 //\r
1573 return Status;\r
1574}\r
1575\r
1576\r
1577/**\r
1578 Destroy the timer\r
1579\r
1580 @retval EFI_SUCCESS The timer was destroyed successfully\r
1581 @retval Other Failed to destroy the timer\r
1582**/\r
1583EFI_STATUS\r
1584TimerDestroy (\r
1585 )\r
1586{\r
1587 EFI_STATUS Status;\r
1588\r
1589 //\r
1590 // Assume success\r
1591 //\r
1592 Status = EFI_SUCCESS;\r
1593\r
1594 //\r
1595 // Determine if the timer is running\r
1596 //\r
1597 if ( bTimerRunning ) {\r
1598 //\r
1599 // Stop the timer\r
1600 //\r
1601 Status = TimerStop ( );\r
1602 }\r
1603 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {\r
1604 //\r
1605 // Done with this timer\r
1606 //\r
1607 Status = gBS->CloseEvent ( pTimer );\r
1608 if ( EFI_ERROR ( Status )) {\r
1609 DEBUG (( DEBUG_ERROR,\r
1610 "ERROR - Failed to free the timer event, Status: %r\r\n",\r
1611 Status ));\r
1612 }\r
1613 else {\r
1614 DEBUG (( DEBUG_INFO,\r
1615 "0x%08x: Timer Destroyed\r\n",\r
1616 pTimer ));\r
1617 pTimer = NULL;\r
1618 }\r
1619 }\r
1620\r
1621 //\r
1622 // Return the operation status\r
1623 //\r
1624 return Status;\r
1625}\r
1626\r
1627\r
1628/**\r
1629 Send data to the DataSink program to test a network's bandwidth.\r
1630\r
1631 @param [in] Argc The number of arguments\r
1632 @param [in] Argv The argument value array\r
1633\r
1634 @retval 0 The application exited normally.\r
1635 @retval Other An error occurred.\r
1636**/\r
1637int\r
1638main (\r
1639 IN int Argc,\r
1640 IN char **Argv\r
1641 )\r
1642{\r
1643 EFI_STATUS (* pClose) ();\r
1644 EFI_STATUS (* pOpen) ();\r
1645 EFI_STATUS Status;\r
1646\r
1647 DEBUG (( DEBUG_INFO,\r
1648 "DataSource starting\r\n" ));\r
1649\r
1650 //\r
1651 // Validate the command line\r
1652 //\r
59bc0593 1653 if ( 2 > Argc ) {\r
1654 Print ( L"%s <remote IP address> [Use TCP]\r\n", Argv[0] );\r
4684b66f 1655 return -1;\r
1656 }\r
1657\r
59bc0593 1658 //\r
1659 // Determine if TCP should be used\r
1660 //\r
1661 bTcp4 = (BOOLEAN)( 2 < Argc );\r
4684b66f 1662\r
1663 //\r
1664 // Determine the support routines\r
1665 //\r
1666 if ( bTcp4 ) {\r
1667 pOpen = Tcp4Open;\r
1668 pClose = Tcp4Close;\r
1669 bTcp4Connecting = TRUE;\r
1670 }\r
1671 else {\r
1672 pOpen = SocketOpen;\r
1673 pClose = SocketClose;\r
1674 }\r
1675\r
1676 //\r
1677 // Use for/break instead of goto\r
1678 //\r
59bc0593 1679 for ( ; ; ) {\r
4684b66f 1680 //\r
1681 // No bytes sent so far\r
1682 //\r
1683 TotalBytesSent = 0;\r
4684b66f 1684 Samples = 0;\r
f6e5cdd5 1685 memset ( &BytesSent, 0, sizeof ( BytesSent ));\r
4684b66f 1686\r
4684b66f 1687 //\r
1688 // Get the IP address\r
1689 //\r
59bc0593 1690 pRemoteHost = Argv[1];\r
4684b66f 1691 Status = IpAddress ( );\r
1692 if ( EFI_ERROR ( Status )) {\r
1693 break;\r
1694 }\r
1695\r
1696 //\r
1697 // Create the timer\r
1698 //\r
1699 bTick = TRUE;\r
1700 Status = TimerCreate ( );\r
1701 if ( EFI_ERROR ( Status )) {\r
1702 break;\r
1703 }\r
1704\r
1705 //\r
1706 // Loop forever abusing the specified system\r
1707 //\r
1708 do {\r
1709 //\r
1710 // Start a timer to perform connection polling and display updates\r
1711 //\r
1712 Status = TimerStart ( 2 * 1000 );\r
1713 if ( EFI_ERROR ( Status )) {\r
1714 break;\r
1715 }\r
1716\r
1717 //\r
1718 // Open the network connection and send the data\r
1719 //\r
1720 Status = pOpen ( );\r
1721 if ( EFI_ERROR ( Status )) {\r
1722 break;\r
1723 }\r
1724\r
1725 //\r
1726 // Done with the network connection\r
1727 //\r
1728 Status = pClose ( );\r
1729 } while ( !EFI_ERROR ( Status ));\r
1730\r
1731 //\r
1732 // Close the network connection if necessary\r
1733 //\r
1734 pClose ( );\r
1735\r
1736 //\r
1737 // All done\r
1738 //\r
1739 break;\r
1740 }\r
1741\r
1742 //\r
1743 // Stop the timer if necessary\r
1744 //\r
1745 TimerStop ( );\r
1746 TimerDestroy ( );\r
1747\r
1748 //\r
1749 // Return the operation status\r
1750 //\r
1751 DEBUG (( DEBUG_INFO,\r
1752 "DataSource exiting, Status: %r\r\n",\r
1753 Status ));\r
1754 return Status;\r
1755}\r