Add Socket Library applications.
[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 {
247 Status = EFI_NOT_STARTED;
248 }
249 }
250
251 //
252 // Return the operation status
253 //
254 return Status;
255 }
256
257
258 /**
259 Poll the socket for more work
260
261 @retval EFI_SUCCESS The application is running normally
262 @retval EFI_NOT_STARTED Listen socket error
263 @retval Other The user stopped the application
264 **/
265 EFI_STATUS
266 SocketPoll (
267 )
268 {
269 BOOLEAN bRemoveSocket;
270 BOOLEAN bListenError;
271 size_t BytesReceived;
272 int CloseStatus;
273 nfds_t Entry;
274 INTN EntryPrevious;
275 int FdCount;
276 nfds_t Index;
277 socklen_t LengthInBytes;
278 struct sockaddr_in RemoteAddress;
279 int Socket;
280 EFI_STATUS Status;
281 EFI_TPL TplPrevious;
282
283 //
284 // Check for control-C
285 //
286 bListenError = FALSE;
287 Status = ControlCCheck ( );
288 if ( !EFI_ERROR ( Status )) {
289 //
290 // Poll the sockets
291 //
292 FdCount = poll ( &PollFd[0],
293 MaxPort,
294 0 );
295 if ( -1 == FdCount ) {
296 //
297 // Poll error
298 //
299 DEBUG (( DEBUG_ERROR,
300 "ERROR - Poll error, errno: %d\r\n",
301 errno ));
302 Status = EFI_DEVICE_ERROR;
303 }
304 else {
305 //
306 // Process the poll output
307 //
308 Index = 0;
309 while ( FdCount ) {
310 bRemoveSocket = FALSE;
311
312 //
313 // Account for this descriptor
314 //
315 if ( 0 != PollFd [ Index ].revents ) {
316 FdCount -= 1;
317 }
318
319 //
320 // Check for a broken connection
321 //
322 if ( 0 != ( PollFd [ Index ].revents & POLLHUP )) {
323 bRemoveSocket = TRUE;
324 if ( ListenSocket == PollFd [ Index ].fd ) {
325 bListenError = TRUE;
326 DEBUG (( DEBUG_ERROR,
327 "ERROR - Network closed on listen socket, errno: %d\r\n",
328 errno ));
329 }
330 else {
331 DEBUG (( DEBUG_ERROR,
332 "ERROR - Network closed on socket %d.%d.%d.%d:%d, errno: %d\r\n",
333 Port [ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
334 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
335 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
336 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
337 htons ( Port [ Index ].RemoteAddress.sin_port ),
338 errno ));
339
340 //
341 // Close the socket
342 //
343 CloseStatus = close ( PollFd [ Index ].fd );
344 if ( 0 == CloseStatus ) {
345 bRemoveSocket = TRUE;
346 DEBUG (( DEBUG_INFO,
347 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
348 PollFd [ Index ].fd,
349 Port [ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
350 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
351 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
352 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
353 htons ( Port [ Index ].RemoteAddress.sin_port )));
354 }
355 else {
356 DEBUG (( DEBUG_ERROR,
357 "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
358 PollFd [ Index ].fd,
359 Port [ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
360 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
361 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
362 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
363 htons ( Port [ Index ].RemoteAddress.sin_port ),
364 errno ));
365 }
366 }
367 }
368
369 //
370 // Check for a connection or read data
371 //
372 if ( 0 != ( PollFd [ Index ].revents & POLLRDNORM )) {
373 //
374 // Check for a connection
375 //
376 if ( ListenSocket == PollFd [ Index ].fd ) {
377 //
378 // Another client connection was received
379 //
380 LengthInBytes = sizeof ( RemoteAddress );
381 Socket = accept ( ListenSocket,
382 (struct sockaddr *) &RemoteAddress,
383 &LengthInBytes );
384 if ( -1 == Socket ) {
385 //
386 // Listen socket error
387 //
388 bListenError = TRUE;
389 bRemoveSocket = TRUE;
390 DEBUG (( DEBUG_ERROR,
391 "ERROR - Listen socket failure, errno: %d\r\n",
392 errno ));
393 }
394 else {
395 //
396 // Determine if there is room for this connection
397 //
398 if (( MAX_CONNECTIONS <= MaxPort )
399 || ((( MAX_CONNECTIONS - 1 ) == MaxPort ) && ( -1 == ListenSocket ))) {
400 //
401 // Display the connection
402 //
403 Print ( L"Rejecting connection to remote system %d.%d.%d.%d:%d\r\n",
404 RemoteAddress.sin_addr.s_addr & 0xff,
405 ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
406 ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
407 ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
408 htons ( RemoteAddress.sin_port ));
409
410 //
411 // No room for this connection
412 // Close the connection
413 //
414 CloseStatus = close ( Socket );
415 if ( 0 == CloseStatus ) {
416 bRemoveSocket = TRUE;
417 DEBUG (( DEBUG_INFO,
418 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
419 PollFd [ Index ].fd,
420 RemoteAddress.sin_addr.s_addr & 0xff,
421 ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
422 ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
423 ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
424 htons ( RemoteAddress.sin_port )));
425 }
426 else {
427 DEBUG (( DEBUG_ERROR,
428 "ERROR - Failed to close socket 0x%08x, errno: %d\r\n",
429 PollFd [ Index ].fd,
430 errno ));
431 }
432
433 //
434 // Keep the application running
435 // No issue with the listen socket
436 //
437 Status = EFI_SUCCESS;
438 }
439 else
440 {
441 //
442 // Display the connection
443 //
444 Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",
445 RemoteAddress.sin_addr.s_addr & 0xff,
446 ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
447 ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
448 ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
449 htons ( RemoteAddress.sin_port ));
450
451 //
452 // Allocate the client connection
453 //
454 Index = MaxPort++;
455 Port [ Index ].BytesAverage = 0;
456 Port [ Index ].BytesPrevious = 0;
457 Port [ Index ].BytesTotal = 0;
458 Port [ Index ].Samples = 0;
459 Port [ Index ].RemoteAddress.sin_len = RemoteAddress.sin_len;
460 Port [ Index ].RemoteAddress.sin_family = RemoteAddress.sin_family;
461 Port [ Index ].RemoteAddress.sin_port = RemoteAddress.sin_port;
462 Port [ Index ].RemoteAddress.sin_addr = RemoteAddress.sin_addr;
463 PollFd [ Index ].fd = Socket;
464 PollFd [ Index ].events = POLLRDNORM | POLLHUP;
465 PollFd [ Index ].revents = 0;
466 }
467 }
468 }
469 else {
470 //
471 // Data received
472 //
473 BytesReceived = read ( PollFd [ Index ].fd,
474 &Buffer,
475 sizeof ( Buffer ));
476 if ( 0 < BytesReceived ) {
477 //
478 // Display the amount of data received
479 //
480 DEBUG (( DEBUG_INFO,
481 "0x%08x: Socket received 0x%08x bytes from %d.%d.%d.%d:%d\r\n",
482 PollFd [ Index ].fd,
483 BytesReceived,
484 Port [ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
485 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
486 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
487 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
488 htons ( Port [ Index ].RemoteAddress.sin_port )));
489
490 //
491 // Synchronize with the TimerCallback routine
492 //
493 TplPrevious = gBS->RaiseTPL ( TPL_DATASINK );
494
495 //
496 // Account for the data received
497 //
498 Port [ Index ].BytesTotal += BytesReceived;
499
500 //
501 // Release the synchronization with the TimerCallback routine
502 //
503 gBS->RestoreTPL ( TplPrevious );
504 }
505 else if ( -1 == BytesReceived ) {
506 //
507 // Close the socket
508 //
509 DEBUG (( DEBUG_INFO,
510 "ERROR - Receive failure for %d.%d.%d.%d:%d, errno: %d\r\n",
511 Port [ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
512 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
513 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
514 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
515 htons ( Port [ Index ].RemoteAddress.sin_port ),
516 errno ));
517 CloseStatus = close ( PollFd [ Index ].fd );
518 if ( 0 == CloseStatus ) {
519 bRemoveSocket = TRUE;
520 DEBUG (( DEBUG_INFO,
521 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
522 PollFd [ Index ].fd,
523 Port [ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
524 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
525 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
526 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
527 htons ( Port [ Index ].RemoteAddress.sin_port )));
528 }
529 else {
530 DEBUG (( DEBUG_ERROR,
531 "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
532 PollFd [ Index ].fd,
533 Port [ Index ].RemoteAddress.sin_addr.s_addr & 0xff,
534 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
535 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
536 ( Port [ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
537 htons ( Port [ Index ].RemoteAddress.sin_port ),
538 errno ));
539 }
540 }
541
542 //
543 // Keep the application running
544 // No issue with the listen socket
545 //
546 Status = EFI_SUCCESS;
547 }
548 }
549
550 //
551 // Remove the socket if necessary
552 //
553 if ( bRemoveSocket ) {
554 DEBUG (( DEBUG_INFO,
555 "0x%08x: Socket removed from polling\r\n",
556 PollFd [ Index ].fd ));
557 MaxPort -= 1;
558 for ( Entry = Index + 1; MaxPort >= Entry; Entry++ ) {
559 EntryPrevious = Entry;
560 Port [ EntryPrevious ].BytesAverage = Port [ Entry ].BytesAverage;
561 Port [ EntryPrevious ].BytesPrevious = Port [ Entry ].BytesPrevious;
562 Port [ EntryPrevious ].BytesTotal = Port [ Entry ].BytesTotal;
563 Port [ EntryPrevious ].RemoteAddress.sin_len = Port [ Entry ].RemoteAddress.sin_len;
564 Port [ EntryPrevious ].RemoteAddress.sin_family = Port [ Entry ].RemoteAddress.sin_family;
565 Port [ EntryPrevious ].RemoteAddress.sin_port = Port [ Entry ].RemoteAddress.sin_port;
566 Port [ EntryPrevious ].RemoteAddress.sin_addr.s_addr = Port [ Entry ].RemoteAddress.sin_addr.s_addr;
567 Port [ EntryPrevious ].Samples = Port [ Entry ].Samples;
568 PollFd [ EntryPrevious ].events = PollFd [ Entry ].events;
569 PollFd [ EntryPrevious ].fd = PollFd [ Entry ].fd;
570 PollFd [ EntryPrevious ].revents = PollFd [ Entry ].revents;
571 }
572 PollFd [ MaxPort ].fd = -1;
573 Index -= 1;
574 }
575
576 //
577 // Account for this socket
578 //
579 Index += 1;
580 }
581 }
582 }
583
584 //
585 // Return the listen failure if necessary
586 //
587 if (( !EFI_ERROR ( Status )) && bListenError ) {
588 Status = EFI_NOT_STARTED;
589 }
590
591 //
592 // Return the poll status
593 //
594 return Status;
595 }
596
597
598 /**
599 Handle the timer callback
600
601 @param [in] Event Event that caused this callback
602 @param [in] pContext Context for this routine
603 **/
604 VOID
605 TimerCallback (
606 IN EFI_EVENT Event,
607 IN VOID * pContext
608 )
609 {
610 UINT64 Average;
611 UINT64 BytesReceived;
612 UINT32 Delta;
613 UINT64 DeltaBytes;
614 nfds_t Index;
615
616 //
617 // Notify the other code of the timer tick
618 //
619 bTick = TRUE;
620
621 //
622 // Walk the list of ports
623 //
624 for ( Index = 0; MaxPort > Index; Index++ ) {
625 //
626 // Determine if any data was received
627 //
628 BytesReceived = Port [ Index ].BytesTotal;
629 if (( ListenSocket != PollFd [ Index ].fd )
630 && ( 0 != BytesReceived )) {
631 //
632 // Update the average bytes per second
633 //
634 DeltaBytes = Port [ Index ].BytesAverage >> AVERAGE_SHIFT_COUNT;
635 Port [ Index ].BytesAverage -= DeltaBytes;
636 DeltaBytes = BytesReceived - Port [ Index ].BytesPrevious;
637 Port [ Index ].BytesPrevious = BytesReceived;
638 Port [ Index ].BytesAverage += DeltaBytes;
639
640 //
641 // Separate the samples
642 //
643 if (( 2 << AVERAGE_SHIFT_COUNT ) == Port [ Index ].Samples ) {
644 Print ( L"---------- Stable average ----------\r\n" );
645 }
646 Port [ Index ].Samples += 1;
647
648 //
649 // Display the data rate
650 //
651 Delta = (UINT32)( DeltaBytes >> DATA_RATE_UPDATE_SHIFT );
652 Average = Port [ Index ].BytesAverage >> ( AVERAGE_SHIFT_COUNT + DATA_RATE_UPDATE_SHIFT );
653 if ( Average < RANGE_SWITCH ) {
654 Print ( L"%d Bytes/sec, Ave: %d Bytes/Sec\r\n",
655 Delta,
656 (UINT32) Average );
657 }
658 else {
659 Average >>= 10;
660 if ( Average < RANGE_SWITCH ) {
661 Print ( L"%d Bytes/sec, Ave: %d KiBytes/Sec\r\n",
662 Delta,
663 (UINT32) Average );
664 }
665 else {
666 Average >>= 10;
667 if ( Average < RANGE_SWITCH ) {
668 Print ( L"%d Bytes/sec, Ave: %d MiBytes/Sec\r\n",
669 Delta,
670 (UINT32) Average );
671 }
672 else {
673 Average >>= 10;
674 if ( Average < RANGE_SWITCH ) {
675 Print ( L"%d Bytes/sec, Ave: %d GiBytes/Sec\r\n",
676 Delta,
677 (UINT32) Average );
678 }
679 else {
680 Average >>= 10;
681 if ( Average < RANGE_SWITCH ) {
682 Print ( L"%d Bytes/sec, Ave: %d TiBytes/Sec\r\n",
683 Delta,
684 Average );
685 }
686 else {
687 Average >>= 10;
688 Print ( L"%d Bytes/sec, Ave: %d PiBytes/Sec\r\n",
689 Delta,
690 (UINT32) Average );
691 }
692 }
693 }
694 }
695 }
696 }
697 }
698 }
699
700
701 /**
702 Create the timer
703
704 @retval EFI_SUCCESS The timer was successfully created
705 @retval Other Timer initialization failed
706 **/
707 EFI_STATUS
708 TimerCreate (
709 )
710 {
711 EFI_STATUS Status;
712
713 //
714 // Create the timer
715 //
716 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,
717 TPL_DATASINK,
718 TimerCallback,
719 NULL,
720 &pTimer );
721 if ( EFI_ERROR ( Status )) {
722 DEBUG (( DEBUG_ERROR,
723 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
724 Status ));
725 }
726 else {
727 DEBUG (( DEBUG_INFO,
728 "0x%08x: Timer created\r\n",
729 pTimer ));
730 }
731
732 //
733 // Return the operation status
734 //
735 return Status;
736 }
737
738
739 /**
740 Stop the timer
741
742 @retval EFI_SUCCESS The timer was stopped successfully
743 @retval Other The timer failed to stop
744 **/
745 EFI_STATUS
746 TimerStop (
747 )
748 {
749 EFI_STATUS Status;
750
751 //
752 // Assume success
753 //
754 Status = EFI_SUCCESS;
755
756 //
757 // Determine if the timer is running
758 //
759 if ( bTimerRunning ) {
760 //
761 // Stop the timer
762 //
763 Status = gBS->SetTimer ( pTimer,
764 TimerCancel,
765 0 );
766 if ( EFI_ERROR ( Status )) {
767 DEBUG (( DEBUG_ERROR,
768 "ERROR - Failed to stop the timer, Status: %r\r\n",
769 Status ));
770 }
771 else {
772 //
773 // Timer timer is now stopped
774 //
775 bTimerRunning = FALSE;
776 DEBUG (( DEBUG_INFO,
777 "0x%08x: Timer stopped\r\n",
778 pTimer ));
779 }
780 }
781
782 //
783 // Return the operation status
784 //
785 return Status;
786 }
787
788
789 /**
790 Start the timer
791
792 @param [in] Milliseconds The number of milliseconds between timer callbacks
793
794 @retval EFI_SUCCESS The timer was successfully created
795 @retval Other Timer initialization failed
796 **/
797 EFI_STATUS
798 TimerStart (
799 UINTN Milliseconds
800 )
801 {
802 EFI_STATUS Status;
803 UINT64 TimeDelay;
804
805 //
806 // Stop the timer if necessary
807 //
808 Status = EFI_SUCCESS;
809 if ( bTimerRunning ) {
810 Status = TimerStop ( );
811 }
812 if ( !EFI_ERROR ( Status )) {
813 //
814 // Compute the new delay
815 //
816 TimeDelay = Milliseconds;
817 TimeDelay *= 1000 * 10;
818
819 //
820 // Start the timer
821 //
822 Status = gBS->SetTimer ( pTimer,
823 TimerPeriodic,
824 TimeDelay );
825 if ( EFI_ERROR ( Status )) {
826 DEBUG (( DEBUG_ERROR,
827 "ERROR - Failed to start the timer, Status: %r\r\n",
828 Status ));
829 }
830 else {
831 //
832 // The timer is now running
833 //
834 bTimerRunning = TRUE;
835 DEBUG (( DEBUG_INFO,
836 "0x%08x: Timer running\r\n",
837 pTimer ));
838 }
839 }
840
841 //
842 // Return the operation status
843 //
844 return Status;
845 }
846
847
848 /**
849 Destroy the timer
850
851 @retval EFI_SUCCESS The timer was destroyed successfully
852 @retval Other Failed to destroy the timer
853 **/
854 EFI_STATUS
855 TimerDestroy (
856 )
857 {
858 EFI_STATUS Status;
859
860 //
861 // Assume success
862 //
863 Status = EFI_SUCCESS;
864
865 //
866 // Determine if the timer is running
867 //
868 if ( bTimerRunning ) {
869 //
870 // Stop the timer
871 //
872 Status = TimerStop ( );
873 }
874 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {
875 //
876 // Done with this timer
877 //
878 Status = gBS->CloseEvent ( pTimer );
879 if ( EFI_ERROR ( Status )) {
880 DEBUG (( DEBUG_ERROR,
881 "ERROR - Failed to free the timer event, Status: %r\r\n",
882 Status ));
883 }
884 else {
885 DEBUG (( DEBUG_INFO,
886 "0x%08x: Timer Destroyed\r\n",
887 pTimer ));
888 pTimer = NULL;
889 }
890 }
891
892 //
893 // Return the operation status
894 //
895 return Status;
896 }
897
898
899 /**
900 Receive data from the DataSource program to test a network's bandwidth.
901
902 @param [in] Argc The number of arguments
903 @param [in] Argv The argument value array
904
905 @retval 0 The application exited normally.
906 @retval Other An error occurred.
907 **/
908 int
909 main (
910 IN int Argc,
911 IN char **Argv
912 )
913 {
914 EFI_STATUS Status;
915
916 DEBUG (( DEBUG_INFO,
917 "DataSink starting\r\n" ));
918
919 //
920 // Use for/break instead of goto
921 //
922 for ( ; ; )
923 {
924 //
925 // Create the timer
926 //
927 bTick = TRUE;
928 Status = TimerCreate ( );
929 if ( EFI_ERROR ( Status )) {
930 break;
931 }
932
933 //
934 // Start a timer to perform network polling and display updates
935 //
936 Status = TimerStart ( 1 * 1000 );
937 if ( EFI_ERROR ( Status )) {
938 break;
939 }
940
941 //
942 // Loop forever waiting for abuse
943 //
944 do {
945 ListenSocket = -1;
946 do {
947 //
948 // Complete any client operations
949 //
950 Status = SocketPoll ( );
951 if ( EFI_ERROR ( Status )) {
952 //
953 // Control-C
954 //
955 break;
956 }
957
958 //
959 // Wait for a while
960 //
961 } while ( !bTick );
962 if ( EFI_ERROR ( Status )) {
963 //
964 // Control-C
965 //
966 break;
967 }
968
969 //
970 // Wait for the network layer to initialize
971 //
972 Status = SocketNew ( );
973 if ( EFI_ERROR ( Status )) {
974 continue;
975 }
976
977 //
978 // Wait for the remote network application to start
979 //
980 Status = SocketAccept ( );
981 if ( EFI_NOT_STARTED == Status ) {
982 Status = SocketClose ( );
983 continue;
984 }
985 else if ( EFI_SUCCESS != Status ) {
986 //
987 // Control-C
988 //
989 break;
990 }
991
992 //
993 // Send data until the connection breaks
994 //
995 do {
996 Status = SocketPoll ( );
997 } while ( !EFI_ERROR ( Status ));
998
999 //
1000 // Done with the socket
1001 //
1002 Status = SocketClose ( );
1003 } while ( !EFI_ERROR ( Status ));
1004
1005 //
1006 // Close the socket if necessary
1007 //
1008 SocketClose ( );
1009
1010 //
1011 // All done
1012 //
1013 break;
1014 }
1015
1016 //
1017 // Stop the timer if necessary
1018 //
1019 TimerStop ( );
1020 TimerDestroy ( );
1021
1022 //
1023 // Return the operation status
1024 //
1025 DEBUG (( DEBUG_INFO,
1026 "DataSink exiting, Status: %r\r\n",
1027 Status ));
1028 return Status;
1029 }