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