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