]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Sockets/DataSink/DataSink.c
8223ead118079e3b652eb7d7f32c7d4ea122a4c2
[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 MAX_CONNECTIONS ( 1 + 16 ) ///< Maximum number of client connections
32 #define RANGE_SWITCH 2048 ///< Switch display ranges
33 #define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates
34 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average
35
36 #define TPL_DATASINK TPL_CALLBACK ///< Synchronization TPL
37
38 #define PACKET_SIZE 1448 ///< Size of data packets
39 #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes
40
41 typedef struct _DT_PORT {
42 UINT64 BytesAverage;
43 UINT64 BytesPrevious;
44 UINT64 BytesTotal;
45 struct sockaddr_in RemoteAddress;
46 UINT64 Samples;
47 } DT_PORT;
48
49 volatile BOOLEAN bTick;
50 BOOLEAN bTimerRunning;
51 struct sockaddr_in LocalAddress;
52 EFI_EVENT pTimer;
53 int ListenSocket;
54 UINT8 Buffer[ DATA_BUFFER_SIZE ];
55 struct pollfd PollFd[ MAX_CONNECTIONS ];
56 DT_PORT Port[ MAX_CONNECTIONS ];
57 nfds_t MaxPort;
58
59
60 //
61 // Forward routine declarations
62 //
63 EFI_STATUS TimerStart ( UINTN Milliseconds );
64
65
66 /**
67 Check for control C entered at console
68
69 @retval EFI_SUCCESS Control C not entered
70 @retval EFI_ABORTED Control C entered
71 **/
72 EFI_STATUS
73 ControlCCheck (
74 )
75 {
76 EFI_STATUS Status;
77
78 //
79 // Assume no user intervention
80 //
81 Status = EFI_SUCCESS;
82
83 //
84 // Display user stop request
85 //
86 if ( EFI_ERROR ( Status )) {
87 DEBUG (( DEBUG_INFO,
88 "User stop request!\r\n" ));
89 }
90
91 //
92 // Return the check status
93 //
94 return Status;
95 }
96
97
98 /**
99 Accept a socket connection
100
101 @retval EFI_SUCCESS The application is running normally
102 @retval EFI_NOT_STARTED Error with the listen socket
103 @retval Other The user stopped the application
104 **/
105 EFI_STATUS
106 SocketAccept (
107 )
108 {
109 INT32 SocketStatus;
110 EFI_STATUS Status;
111 INTN Index;
112
113 //
114 // Assume failure
115 //
116 Status = EFI_DEVICE_ERROR;
117
118 //
119 // Bind to the local address
120 //
121 SocketStatus = bind ( ListenSocket,
122 (struct sockaddr *) &LocalAddress,
123 LocalAddress.sin_len );
124 if ( 0 == SocketStatus ) {
125 //
126 // Start listening on the local socket
127 //
128 SocketStatus = listen ( ListenSocket, 5 );
129 if ( 0 == SocketStatus ) {
130 //
131 // Local socket in the listen state
132 //
133 Status = EFI_SUCCESS;
134
135 //
136 // Allocate a port
137 //
138 Index = MaxPort++;
139 PollFd[ Index ].fd = ListenSocket;
140 PollFd[ Index ].events = POLLRDNORM | POLLHUP;
141 PollFd[ Index ].revents = 0;
142 Port[ Index ].BytesAverage = 0;
143 Port[ Index ].BytesPrevious = 0;
144 Port[ Index ].BytesTotal = 0;
145 Port[ Index ].Samples = 0;
146 Port[ Index ].RemoteAddress.sin_len = 0;
147 Port[ Index ].RemoteAddress.sin_family = 0;
148 Port[ Index ].RemoteAddress.sin_port = 0;
149 Port[ Index ].RemoteAddress.sin_addr.s_addr= 0;
150 }
151 }
152
153 //
154 // Return the operation status
155 //
156 return Status;
157 }
158
159
160 /**
161 Close the socket
162
163 @retval EFI_SUCCESS The application is running normally
164 @retval Other The user stopped the application
165 **/
166 EFI_STATUS
167 SocketClose (
168 )
169 {
170 INT32 CloseStatus;
171 EFI_STATUS Status;
172
173 //
174 // Determine if the socket is open
175 //
176 Status = EFI_DEVICE_ERROR;
177 if ( -1 != ListenSocket ) {
178 //
179 // Attempt to close the socket
180 //
181 CloseStatus = close ( ListenSocket );
182 if ( 0 == CloseStatus ) {
183 DEBUG (( DEBUG_INFO,
184 "0x%08x: Socket closed\r\n",
185 ListenSocket ));
186 ListenSocket = -1;
187 Status = EFI_SUCCESS;
188 }
189 else {
190 DEBUG (( DEBUG_ERROR,
191 "ERROR: Failed to close socket, errno: %d\r\n",
192 errno ));
193 }
194 }
195
196 //
197 // Return the operation status
198 //
199 return Status;
200 }
201
202
203 /**
204 Create the socket
205
206 @retval EFI_SUCCESS The application is running normally
207 @retval Other The user stopped the application
208 **/
209 EFI_STATUS
210 SocketNew (
211 )
212 {
213 EFI_STATUS Status;
214
215 //
216 // Get the port number
217 //
218 ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));
219 LocalAddress.sin_len = sizeof ( LocalAddress );
220 LocalAddress.sin_family = AF_INET;
221 LocalAddress.sin_port = htons ( PcdGet16 ( DataSource_Port ));
222
223 //
224 // Loop creating the socket
225 //
226 DEBUG (( DEBUG_INFO,
227 "Creating the socket\r\n" ));
228
229 //
230 // Check for user stop request
231 //
232 Status = ControlCCheck ( );
233 if ( !EFI_ERROR ( Status )) {
234 //
235 // Attempt to create the socket
236 //
237 ListenSocket = socket ( AF_INET,
238 SOCK_STREAM,
239 IPPROTO_TCP );
240 if ( -1 != ListenSocket ) {
241 DEBUG (( DEBUG_INFO,
242 "0x%08x: Socket created\r\n",
243 ListenSocket ));
244 }
245 else {
246 Status = EFI_NOT_STARTED;
247 }
248 }
249
250 //
251 // Return the operation status
252 //
253 return Status;
254 }
255
256
257 /**
258 Poll the socket for more work
259
260 @retval EFI_SUCCESS The application is running normally
261 @retval EFI_NOT_STARTED Listen socket error
262 @retval Other The user stopped the application
263 **/
264 EFI_STATUS
265 SocketPoll (
266 )
267 {
268 BOOLEAN bRemoveSocket;
269 BOOLEAN bListenError;
270 size_t BytesReceived;
271 int CloseStatus;
272 nfds_t Entry;
273 INTN EntryPrevious;
274 int FdCount;
275 nfds_t Index;
276 socklen_t LengthInBytes;
277 struct sockaddr_in RemoteAddress;
278 int Socket;
279 EFI_STATUS Status;
280 EFI_TPL TplPrevious;
281
282 //
283 // Check for control-C
284 //
285 bListenError = FALSE;
286 Status = ControlCCheck ( );
287 if ( !EFI_ERROR ( Status )) {
288 //
289 // Poll the sockets
290 //
291 FdCount = poll ( &PollFd[0],
292 MaxPort,
293 0 );
294 if ( -1 == FdCount ) {
295 //
296 // Poll error
297 //
298 DEBUG (( DEBUG_ERROR,
299 "ERROR - Poll error, errno: %d\r\n",
300 errno ));
301 Status = EFI_DEVICE_ERROR;
302 }
303 else {
304 //
305 // Process the poll output
306 //
307 Index = 0;
308 while ( FdCount ) {
309 bRemoveSocket = FALSE;
310
311 //
312 // Account for this descriptor
313 //
314 if ( 0 != PollFd[ Index ].revents ) {
315 FdCount -= 1;
316 }
317
318 //
319 // Check for a broken connection
320 //
321 if ( 0 != ( PollFd[ Index ].revents & POLLHUP )) {
322 bRemoveSocket = TRUE;
323 if ( ListenSocket == PollFd[ Index ].fd ) {
324 bListenError = TRUE;
325 DEBUG (( DEBUG_ERROR,
326 "ERROR - Network closed on listen socket, errno: %d\r\n",
327 errno ));
328 }
329 else {
330 DEBUG (( DEBUG_ERROR,
331 "ERROR - Network closed on socket %d.%d.%d.%d:%d, errno: %d\r\n",
332 Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
333 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
334 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
335 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
336 htons ( Port[ Index ].RemoteAddress.sin_port ),
337 errno ));
338
339 //
340 // Close the socket
341 //
342 CloseStatus = close ( PollFd[ Index ].fd );
343 if ( 0 == CloseStatus ) {
344 bRemoveSocket = TRUE;
345 DEBUG (( DEBUG_INFO,
346 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
347 PollFd[ Index ].fd,
348 Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
349 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
350 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
351 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
352 htons ( Port[ Index ].RemoteAddress.sin_port )));
353 }
354 else {
355 DEBUG (( DEBUG_ERROR,
356 "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
357 PollFd[ Index ].fd,
358 Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
359 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
360 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
361 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
362 htons ( Port[ Index ].RemoteAddress.sin_port ),
363 errno ));
364 }
365 }
366 }
367
368 //
369 // Check for a connection or read data
370 //
371 if ( 0 != ( PollFd[ Index ].revents & POLLRDNORM )) {
372 //
373 // Check for a connection
374 //
375 if ( ListenSocket == PollFd[ Index ].fd ) {
376 //
377 // Another client connection was received
378 //
379 LengthInBytes = sizeof ( RemoteAddress );
380 Socket = accept ( ListenSocket,
381 (struct sockaddr *) &RemoteAddress,
382 &LengthInBytes );
383 if ( -1 == Socket ) {
384 //
385 // Listen socket error
386 //
387 bListenError = TRUE;
388 bRemoveSocket = TRUE;
389 DEBUG (( DEBUG_ERROR,
390 "ERROR - Listen socket failure, errno: %d\r\n",
391 errno ));
392 }
393 else {
394 //
395 // Determine if there is room for this connection
396 //
397 if (( MAX_CONNECTIONS <= MaxPort )
398 || ((( MAX_CONNECTIONS - 1 ) == MaxPort ) && ( -1 == ListenSocket ))) {
399 //
400 // Display the connection
401 //
402 Print ( L"Rejecting connection to remote system %d.%d.%d.%d:%d\r\n",
403 RemoteAddress.sin_addr.s_addr & 0xff,
404 ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
405 ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
406 ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
407 htons ( RemoteAddress.sin_port ));
408
409 //
410 // No room for this connection
411 // Close the connection
412 //
413 CloseStatus = close ( Socket );
414 if ( 0 == CloseStatus ) {
415 bRemoveSocket = TRUE;
416 DEBUG (( DEBUG_INFO,
417 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
418 PollFd[ Index ].fd,
419 RemoteAddress.sin_addr.s_addr & 0xff,
420 ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
421 ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
422 ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
423 htons ( RemoteAddress.sin_port )));
424 }
425 else {
426 DEBUG (( DEBUG_ERROR,
427 "ERROR - Failed to close socket 0x%08x, errno: %d\r\n",
428 PollFd[ Index ].fd,
429 errno ));
430 }
431
432 //
433 // Keep the application running
434 // No issue with the listen socket
435 //
436 Status = EFI_SUCCESS;
437 }
438 else {
439 //
440 // Display the connection
441 //
442 Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",
443 RemoteAddress.sin_addr.s_addr & 0xff,
444 ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
445 ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
446 ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
447 htons ( RemoteAddress.sin_port ));
448
449 //
450 // Allocate the client connection
451 //
452 Index = MaxPort++;
453 Port[ Index ].BytesAverage = 0;
454 Port[ Index ].BytesPrevious = 0;
455 Port[ Index ].BytesTotal = 0;
456 Port[ Index ].Samples = 0;
457 Port[ Index ].RemoteAddress.sin_len = RemoteAddress.sin_len;
458 Port[ Index ].RemoteAddress.sin_family = RemoteAddress.sin_family;
459 Port[ Index ].RemoteAddress.sin_port = RemoteAddress.sin_port;
460 Port[ Index ].RemoteAddress.sin_addr = RemoteAddress.sin_addr;
461 PollFd[ Index ].fd = Socket;
462 PollFd[ Index ].events = POLLRDNORM | POLLHUP;
463 PollFd[ Index ].revents = 0;
464 }
465 }
466 }
467 else {
468 //
469 // Data received
470 //
471 BytesReceived = read ( PollFd[ Index ].fd,
472 &Buffer,
473 sizeof ( Buffer ));
474 if ( 0 < BytesReceived ) {
475 //
476 // Display the amount of data received
477 //
478 DEBUG (( DEBUG_INFO,
479 "0x%08x: Socket received 0x%08x bytes from %d.%d.%d.%d:%d\r\n",
480 PollFd[ Index ].fd,
481 BytesReceived,
482 Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
483 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
484 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
485 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
486 htons ( Port[ Index ].RemoteAddress.sin_port )));
487
488 //
489 // Synchronize with the TimerCallback routine
490 //
491 TplPrevious = gBS->RaiseTPL ( TPL_DATASINK );
492
493 //
494 // Account for the data received
495 //
496 Port[ Index ].BytesTotal += BytesReceived;
497
498 //
499 // Release the synchronization with the TimerCallback routine
500 //
501 gBS->RestoreTPL ( TplPrevious );
502 }
503 else if ( -1 == BytesReceived ) {
504 //
505 // Close the socket
506 //
507 DEBUG (( DEBUG_INFO,
508 "ERROR - Receive failure for %d.%d.%d.%d:%d, errno: %d\r\n",
509 Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
510 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
511 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
512 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
513 htons ( Port[ Index ].RemoteAddress.sin_port ),
514 errno ));
515 CloseStatus = close ( PollFd[ Index ].fd );
516 if ( 0 == CloseStatus ) {
517 bRemoveSocket = TRUE;
518 DEBUG (( DEBUG_INFO,
519 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
520 PollFd[ Index ].fd,
521 Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
522 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
523 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
524 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
525 htons ( Port[ Index ].RemoteAddress.sin_port )));
526 }
527 else {
528 DEBUG (( DEBUG_ERROR,
529 "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
530 PollFd[ Index ].fd,
531 Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
532 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
533 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
534 ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
535 htons ( Port[ Index ].RemoteAddress.sin_port ),
536 errno ));
537 }
538 }
539
540 //
541 // Keep the application running
542 // No issue with the listen socket
543 //
544 Status = EFI_SUCCESS;
545 }
546 }
547
548 //
549 // Remove the socket if necessary
550 //
551 if ( bRemoveSocket ) {
552 DEBUG (( DEBUG_INFO,
553 "0x%08x: Socket removed from polling\r\n",
554 PollFd[ Index ].fd ));
555 MaxPort -= 1;
556 for ( Entry = Index + 1; MaxPort >= Entry; Entry++ ) {
557 EntryPrevious = Entry;
558 Port[ EntryPrevious ].BytesAverage = Port[ Entry ].BytesAverage;
559 Port[ EntryPrevious ].BytesPrevious = Port[ Entry ].BytesPrevious;
560 Port[ EntryPrevious ].BytesTotal = Port[ Entry ].BytesTotal;
561 Port[ EntryPrevious ].RemoteAddress.sin_len = Port[ Entry ].RemoteAddress.sin_len;
562 Port[ EntryPrevious ].RemoteAddress.sin_family = Port[ Entry ].RemoteAddress.sin_family;
563 Port[ EntryPrevious ].RemoteAddress.sin_port = Port[ Entry ].RemoteAddress.sin_port;
564 Port[ EntryPrevious ].RemoteAddress.sin_addr.s_addr = Port[ Entry ].RemoteAddress.sin_addr.s_addr;
565 Port[ EntryPrevious ].Samples = Port[ Entry ].Samples;
566 PollFd[ EntryPrevious ].events = PollFd[ Entry ].events;
567 PollFd[ EntryPrevious ].fd = PollFd[ Entry ].fd;
568 PollFd[ EntryPrevious ].revents = PollFd[ Entry ].revents;
569 }
570 PollFd[ MaxPort ].fd = -1;
571 Index -= 1;
572 }
573
574 //
575 // Account for this socket
576 //
577 Index += 1;
578 }
579 }
580 }
581
582 //
583 // Return the listen failure if necessary
584 //
585 if (( !EFI_ERROR ( Status )) && bListenError ) {
586 Status = EFI_NOT_STARTED;
587 }
588
589 //
590 // Return the poll status
591 //
592 return Status;
593 }
594
595
596 /**
597 Handle the timer callback
598
599 @param [in] Event Event that caused this callback
600 @param [in] pContext Context for this routine
601 **/
602 VOID
603 TimerCallback (
604 IN EFI_EVENT Event,
605 IN VOID * pContext
606 )
607 {
608 UINT64 Average;
609 UINT64 BytesReceived;
610 UINT32 Delta;
611 UINT64 DeltaBytes;
612 nfds_t Index;
613
614 //
615 // Notify the other code of the timer tick
616 //
617 bTick = TRUE;
618
619 //
620 // Walk the list of ports
621 //
622 for ( Index = 0; MaxPort > Index; Index++ ) {
623 //
624 // Determine if any data was received
625 //
626 BytesReceived = Port[ Index ].BytesTotal;
627 if (( ListenSocket != PollFd[ Index ].fd )
628 && ( 0 != BytesReceived )) {
629 //
630 // Update the average bytes per second
631 //
632 DeltaBytes = Port[ Index ].BytesAverage >> AVERAGE_SHIFT_COUNT;
633 Port[ Index ].BytesAverage -= DeltaBytes;
634 DeltaBytes = BytesReceived - Port[ Index ].BytesPrevious;
635 Port[ Index ].BytesPrevious = BytesReceived;
636 Port[ Index ].BytesAverage += DeltaBytes;
637
638 //
639 // Separate the samples
640 //
641 if (( 2 << AVERAGE_SHIFT_COUNT ) == Port[ Index ].Samples ) {
642 Print ( L"---------- Stable average ----------\r\n" );
643 }
644 Port[ Index ].Samples += 1;
645
646 //
647 // Display the data rate
648 //
649 Delta = (UINT32)( DeltaBytes >> DATA_RATE_UPDATE_SHIFT );
650 Average = Port[ Index ].BytesAverage >> ( AVERAGE_SHIFT_COUNT + DATA_RATE_UPDATE_SHIFT );
651 if ( Average < RANGE_SWITCH ) {
652 Print ( L"%d Bytes/sec, Ave: %d Bytes/Sec\r\n",
653 Delta,
654 (UINT32) Average );
655 }
656 else {
657 Average >>= 10;
658 if ( Average < RANGE_SWITCH ) {
659 Print ( L"%d Bytes/sec, Ave: %d KiBytes/Sec\r\n",
660 Delta,
661 (UINT32) Average );
662 }
663 else {
664 Average >>= 10;
665 if ( Average < RANGE_SWITCH ) {
666 Print ( L"%d Bytes/sec, Ave: %d MiBytes/Sec\r\n",
667 Delta,
668 (UINT32) Average );
669 }
670 else {
671 Average >>= 10;
672 if ( Average < RANGE_SWITCH ) {
673 Print ( L"%d Bytes/sec, Ave: %d GiBytes/Sec\r\n",
674 Delta,
675 (UINT32) Average );
676 }
677 else {
678 Average >>= 10;
679 if ( Average < RANGE_SWITCH ) {
680 Print ( L"%d Bytes/sec, Ave: %d TiBytes/Sec\r\n",
681 Delta,
682 Average );
683 }
684 else {
685 Average >>= 10;
686 Print ( L"%d Bytes/sec, Ave: %d PiBytes/Sec\r\n",
687 Delta,
688 (UINT32) Average );
689 }
690 }
691 }
692 }
693 }
694 }
695 }
696 }
697
698
699 /**
700 Create the timer
701
702 @retval EFI_SUCCESS The timer was successfully created
703 @retval Other Timer initialization failed
704 **/
705 EFI_STATUS
706 TimerCreate (
707 )
708 {
709 EFI_STATUS Status;
710
711 //
712 // Create the timer
713 //
714 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,
715 TPL_DATASINK,
716 TimerCallback,
717 NULL,
718 &pTimer );
719 if ( EFI_ERROR ( Status )) {
720 DEBUG (( DEBUG_ERROR,
721 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
722 Status ));
723 }
724 else {
725 DEBUG (( DEBUG_INFO,
726 "0x%08x: Timer created\r\n",
727 pTimer ));
728 }
729
730 //
731 // Return the operation status
732 //
733 return Status;
734 }
735
736
737 /**
738 Stop the timer
739
740 @retval EFI_SUCCESS The timer was stopped successfully
741 @retval Other The timer failed to stop
742 **/
743 EFI_STATUS
744 TimerStop (
745 )
746 {
747 EFI_STATUS Status;
748
749 //
750 // Assume success
751 //
752 Status = EFI_SUCCESS;
753
754 //
755 // Determine if the timer is running
756 //
757 if ( bTimerRunning ) {
758 //
759 // Stop the timer
760 //
761 Status = gBS->SetTimer ( pTimer,
762 TimerCancel,
763 0 );
764 if ( EFI_ERROR ( Status )) {
765 DEBUG (( DEBUG_ERROR,
766 "ERROR - Failed to stop the timer, Status: %r\r\n",
767 Status ));
768 }
769 else {
770 //
771 // Timer timer is now stopped
772 //
773 bTimerRunning = FALSE;
774 DEBUG (( DEBUG_INFO,
775 "0x%08x: Timer stopped\r\n",
776 pTimer ));
777 }
778 }
779
780 //
781 // Return the operation status
782 //
783 return Status;
784 }
785
786
787 /**
788 Start the timer
789
790 @param [in] Milliseconds The number of milliseconds between timer callbacks
791
792 @retval EFI_SUCCESS The timer was successfully created
793 @retval Other Timer initialization failed
794 **/
795 EFI_STATUS
796 TimerStart (
797 UINTN Milliseconds
798 )
799 {
800 EFI_STATUS Status;
801 UINT64 TimeDelay;
802
803 //
804 // Stop the timer if necessary
805 //
806 Status = EFI_SUCCESS;
807 if ( bTimerRunning ) {
808 Status = TimerStop ( );
809 }
810 if ( !EFI_ERROR ( Status )) {
811 //
812 // Compute the new delay
813 //
814 TimeDelay = Milliseconds;
815 TimeDelay *= 1000 * 10;
816
817 //
818 // Start the timer
819 //
820 Status = gBS->SetTimer ( pTimer,
821 TimerPeriodic,
822 TimeDelay );
823 if ( EFI_ERROR ( Status )) {
824 DEBUG (( DEBUG_ERROR,
825 "ERROR - Failed to start the timer, Status: %r\r\n",
826 Status ));
827 }
828 else {
829 //
830 // The timer is now running
831 //
832 bTimerRunning = TRUE;
833 DEBUG (( DEBUG_INFO,
834 "0x%08x: Timer running\r\n",
835 pTimer ));
836 }
837 }
838
839 //
840 // Return the operation status
841 //
842 return Status;
843 }
844
845
846 /**
847 Destroy the timer
848
849 @retval EFI_SUCCESS The timer was destroyed successfully
850 @retval Other Failed to destroy the timer
851 **/
852 EFI_STATUS
853 TimerDestroy (
854 )
855 {
856 EFI_STATUS Status;
857
858 //
859 // Assume success
860 //
861 Status = EFI_SUCCESS;
862
863 //
864 // Determine if the timer is running
865 //
866 if ( bTimerRunning ) {
867 //
868 // Stop the timer
869 //
870 Status = TimerStop ( );
871 }
872 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {
873 //
874 // Done with this timer
875 //
876 Status = gBS->CloseEvent ( pTimer );
877 if ( EFI_ERROR ( Status )) {
878 DEBUG (( DEBUG_ERROR,
879 "ERROR - Failed to free the timer event, Status: %r\r\n",
880 Status ));
881 }
882 else {
883 DEBUG (( DEBUG_INFO,
884 "0x%08x: Timer Destroyed\r\n",
885 pTimer ));
886 pTimer = NULL;
887 }
888 }
889
890 //
891 // Return the operation status
892 //
893 return Status;
894 }
895
896
897 /**
898 Receive data from the DataSource program to test a network's bandwidth.
899
900 @param [in] Argc The number of arguments
901 @param [in] Argv The argument value array
902
903 @retval 0 The application exited normally.
904 @retval Other An error occurred.
905 **/
906 int
907 main (
908 IN int Argc,
909 IN char **Argv
910 )
911 {
912 EFI_STATUS Status;
913
914 DEBUG (( DEBUG_INFO,
915 "DataSink starting\r\n" ));
916
917 //
918 // Use for/break instead of goto
919 //
920 for ( ; ; ) {
921 //
922 // Create the timer
923 //
924 bTick = TRUE;
925 Status = TimerCreate ( );
926 if ( EFI_ERROR ( Status )) {
927 break;
928 }
929
930 //
931 // Start a timer to perform network polling and display updates
932 //
933 Status = TimerStart ( 1 * 1000 );
934 if ( EFI_ERROR ( Status )) {
935 break;
936 }
937
938 //
939 // Loop forever waiting for abuse
940 //
941 do {
942 ListenSocket = -1;
943 do {
944 //
945 // Complete any client operations
946 //
947 Status = SocketPoll ( );
948 if ( EFI_ERROR ( Status )) {
949 //
950 // Control-C
951 //
952 break;
953 }
954
955 //
956 // Wait for a while
957 //
958 } while ( !bTick );
959 if ( EFI_ERROR ( Status )) {
960 //
961 // Control-C
962 //
963 break;
964 }
965
966 //
967 // Wait for the network layer to initialize
968 //
969 Status = SocketNew ( );
970 if ( EFI_ERROR ( Status )) {
971 continue;
972 }
973
974 //
975 // Wait for the remote network application to start
976 //
977 Status = SocketAccept ( );
978 if ( EFI_NOT_STARTED == Status ) {
979 Status = SocketClose ( );
980 continue;
981 }
982 else if ( EFI_SUCCESS != Status ) {
983 //
984 // Control-C
985 //
986 break;
987 }
988
989 //
990 // Send data until the connection breaks
991 //
992 do {
993 Status = SocketPoll ( );
994 } while ( !EFI_ERROR ( Status ));
995
996 //
997 // Done with the socket
998 //
999 Status = SocketClose ( );
1000 } while ( !EFI_ERROR ( Status ));
1001
1002 //
1003 // Close the socket if necessary
1004 //
1005 SocketClose ( );
1006
1007 //
1008 // All done
1009 //
1010 break;
1011 }
1012
1013 //
1014 // Stop the timer if necessary
1015 //
1016 TimerStop ( );
1017 TimerDestroy ( );
1018
1019 //
1020 // Return the operation status
1021 //
1022 DEBUG (( DEBUG_INFO,
1023 "DataSink exiting, Status: %r\r\n",
1024 Status ));
1025 return Status;
1026 }