]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TcpDxe/SockInterface.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / TcpDxe / SockInterface.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Interface function of the Socket.\r
3\r
f75a7f56 4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
a3bcde70 5\r
ecf98fbc 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a3bcde70
HT
7\r
8**/\r
9\r
10#include "SockImpl.h"\r
11\r
12/**\r
13 Check whether the Event is in the List.\r
14\r
15 @param[in] List Pointer to the token list to be searched.\r
16 @param[in] Event The event to be checked.\r
17\r
18 @retval TRUE The specific Event exists in the List.\r
19 @retval FALSE The specific Event is not in the List.\r
20\r
21**/\r
22BOOLEAN\r
23SockTokenExistedInList (\r
d1050b9d
MK
24 IN LIST_ENTRY *List,\r
25 IN EFI_EVENT Event\r
a3bcde70
HT
26 )\r
27{\r
d1050b9d
MK
28 LIST_ENTRY *ListEntry;\r
29 SOCK_TOKEN *SockToken;\r
a3bcde70
HT
30\r
31 NET_LIST_FOR_EACH (ListEntry, List) {\r
32 SockToken = NET_LIST_USER_STRUCT (\r
33 ListEntry,\r
34 SOCK_TOKEN,\r
35 TokenList\r
36 );\r
37\r
38 if (Event == SockToken->Token->Event) {\r
39 return TRUE;\r
40 }\r
41 }\r
42\r
43 return FALSE;\r
44}\r
45\r
46/**\r
47 Call SockTokenExistedInList() to check whether the Event is\r
48 in the related socket's lists.\r
49\r
50 @param[in] Sock Pointer to the instance's socket.\r
51 @param[in] Event The event to be checked.\r
52\r
53 @retval TRUE The Event exists in related socket's lists.\r
54 @retval FALSE The Event is not in related socket's lists.\r
55\r
56**/\r
57BOOLEAN\r
58SockTokenExisted (\r
d1050b9d
MK
59 IN SOCKET *Sock,\r
60 IN EFI_EVENT Event\r
a3bcde70
HT
61 )\r
62{\r
a3bcde70
HT
63 if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||\r
64 SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||\r
65 SockTokenExistedInList (&Sock->RcvTokenList, Event) ||\r
66 SockTokenExistedInList (&Sock->ListenTokenList, Event)\r
d1050b9d
MK
67 )\r
68 {\r
a3bcde70
HT
69 return TRUE;\r
70 }\r
71\r
72 if ((Sock->ConnectionToken != NULL) && (Sock->ConnectionToken->Event == Event)) {\r
a3bcde70
HT
73 return TRUE;\r
74 }\r
75\r
76 if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {\r
77 return TRUE;\r
78 }\r
79\r
80 return FALSE;\r
81}\r
82\r
83/**\r
84 Buffer a token into the specific list of the socket Sock.\r
85\r
86 @param[in] Sock Pointer to the instance's socket.\r
87 @param[in] List Pointer to the list to store the token.\r
88 @param[in] Token Pointer to the token to be buffered.\r
89 @param[in] DataLen The data length of the buffer contained in Token.\r
90\r
91 @return Pointer to the token that wraps Token. If NULL, an error condition occurred.\r
92\r
93**/\r
94SOCK_TOKEN *\r
95SockBufferToken (\r
d1050b9d
MK
96 IN SOCKET *Sock,\r
97 IN LIST_ENTRY *List,\r
98 IN VOID *Token,\r
99 IN UINT32 DataLen\r
a3bcde70
HT
100 )\r
101{\r
102 SOCK_TOKEN *SockToken;\r
103\r
104 SockToken = AllocateZeroPool (sizeof (SOCK_TOKEN));\r
105 if (NULL == SockToken) {\r
a3bcde70 106 DEBUG (\r
c49ca4a2 107 (DEBUG_ERROR,\r
d1050b9d 108 "SockBufferIOToken: No Memory to allocate SockToken\n")\r
a3bcde70
HT
109 );\r
110\r
111 return NULL;\r
112 }\r
113\r
d1050b9d
MK
114 SockToken->Sock = Sock;\r
115 SockToken->Token = (SOCK_COMPLETION_TOKEN *)Token;\r
116 SockToken->RemainDataLen = DataLen;\r
a3bcde70
HT
117 InsertTailList (List, &SockToken->TokenList);\r
118\r
119 return SockToken;\r
120}\r
121\r
122/**\r
75dce340 123 Destroy the socket Sock and its associated protocol control block.\r
a3bcde70
HT
124\r
125 @param[in, out] Sock The socket to be destroyed.\r
126\r
127 @retval EFI_SUCCESS The socket Sock was destroyed successfully.\r
128 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
129\r
130**/\r
131EFI_STATUS\r
132SockDestroyChild (\r
d1050b9d 133 IN OUT SOCKET *Sock\r
a3bcde70
HT
134 )\r
135{\r
d1050b9d
MK
136 EFI_STATUS Status;\r
137 TCP_PROTO_DATA *ProtoData;\r
138 TCP_CB *Tcb;\r
139 EFI_GUID *IpProtocolGuid;\r
140 EFI_GUID *TcpProtocolGuid;\r
141 VOID *SockProtocol;\r
a3bcde70
HT
142\r
143 ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));\r
144\r
216f7970 145 if (Sock->InDestroy) {\r
a3bcde70
HT
146 return EFI_SUCCESS;\r
147 }\r
148\r
216f7970 149 Sock->InDestroy = TRUE;\r
a3bcde70 150\r
d555699b 151 if (Sock->IpVersion == IP_VERSION_4) {\r
d1050b9d 152 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
d555699b
ZL
153 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;\r
154 } else {\r
d1050b9d 155 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
d555699b
ZL
156 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;\r
157 }\r
d1050b9d
MK
158\r
159 ProtoData = (TCP_PROTO_DATA *)Sock->ProtoReserved;\r
d555699b
ZL
160 Tcb = ProtoData->TcpPcb;\r
161\r
162 ASSERT (Tcb != NULL);\r
163\r
d555699b
ZL
164 //\r
165 // Close the IP protocol.\r
166 //\r
167 gBS->CloseProtocol (\r
168 Tcb->IpInfo->ChildHandle,\r
169 IpProtocolGuid,\r
170 ProtoData->TcpService->IpIo->Image,\r
171 Sock->SockHandle\r
172 );\r
173\r
174 if (Sock->DestroyCallback != NULL) {\r
175 Sock->DestroyCallback (Sock, Sock->Context);\r
176 }\r
177\r
178 //\r
179 // Retrieve the protocol installed on this sock\r
180 //\r
181 Status = gBS->OpenProtocol (\r
182 Sock->SockHandle,\r
183 TcpProtocolGuid,\r
184 &SockProtocol,\r
185 Sock->DriverBinding,\r
186 Sock->SockHandle,\r
187 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
188 );\r
189\r
190 if (EFI_ERROR (Status)) {\r
d555699b 191 DEBUG (\r
c49ca4a2 192 (DEBUG_ERROR,\r
d1050b9d
MK
193 "SockDestroyChild: Open protocol installed on socket failed with %r\n",\r
194 Status)\r
d555699b
ZL
195 );\r
196 }\r
197\r
198 //\r
199 // Uninstall the protocol installed on this sock\r
200 //\r
201 gBS->UninstallMultipleProtocolInterfaces (\r
d1050b9d
MK
202 Sock->SockHandle,\r
203 TcpProtocolGuid,\r
204 SockProtocol,\r
205 NULL\r
206 );\r
597cf8a1 207\r
d1050b9d 208 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
597cf8a1 209 if (EFI_ERROR (Status)) {\r
597cf8a1 210 DEBUG (\r
c49ca4a2 211 (DEBUG_ERROR,\r
d1050b9d
MK
212 "SockDestroyChild: Get the lock to access socket failed with %r\n",\r
213 Status)\r
597cf8a1
ZL
214 );\r
215\r
216 return EFI_ACCESS_DENIED;\r
217 }\r
218\r
a3bcde70
HT
219 //\r
220 // force protocol layer to detach the PCB\r
221 //\r
222 Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);\r
223\r
224 if (EFI_ERROR (Status)) {\r
a3bcde70 225 DEBUG (\r
c49ca4a2 226 (DEBUG_ERROR,\r
d1050b9d
MK
227 "SockDestroyChild: Protocol detach socket failed with %r\n",\r
228 Status)\r
a3bcde70
HT
229 );\r
230\r
216f7970 231 Sock->InDestroy = FALSE;\r
a3bcde70 232 } else if (SOCK_IS_CONFIGURED (Sock)) {\r
a3bcde70
HT
233 SockConnFlush (Sock);\r
234 SockSetState (Sock, SO_CLOSED);\r
235\r
236 Sock->ConfigureState = SO_UNCONFIGURED;\r
237 }\r
238\r
239 EfiReleaseLock (&(Sock->Lock));\r
240\r
241 if (EFI_ERROR (Status)) {\r
242 return Status;\r
243 }\r
244\r
245 SockDestroy (Sock);\r
246 return EFI_SUCCESS;\r
247}\r
248\r
249/**\r
250 Create a socket and its associated protocol control block\r
4cefb5e9 251 with the initial data SockInitData and protocol specific\r
a3bcde70
HT
252 data ProtoData.\r
253\r
4cefb5e9 254 @param[in] SockInitData Initial data to setting the socket.\r
a3bcde70 255\r
4cefb5e9 256 @return Pointer to the newly created socket. If NULL, an error condition occurred.\r
a3bcde70
HT
257\r
258**/\r
259SOCKET *\r
260SockCreateChild (\r
d1050b9d 261 IN SOCK_INIT_DATA *SockInitData\r
a3bcde70
HT
262 )\r
263{\r
264 SOCKET *Sock;\r
265 EFI_STATUS Status;\r
d555699b
ZL
266 VOID *SockProtocol;\r
267 EFI_GUID *TcpProtocolGuid;\r
a3bcde70
HT
268\r
269 //\r
270 // create a new socket\r
271 //\r
272 Sock = SockCreate (SockInitData);\r
273 if (NULL == Sock) {\r
a3bcde70 274 DEBUG (\r
c49ca4a2 275 (DEBUG_ERROR,\r
d1050b9d 276 "SockCreateChild: No resource to create a new socket\n")\r
a3bcde70
HT
277 );\r
278\r
279 return NULL;\r
280 }\r
281\r
282 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
283 if (EFI_ERROR (Status)) {\r
a3bcde70 284 DEBUG (\r
c49ca4a2 285 (DEBUG_ERROR,\r
d1050b9d
MK
286 "SockCreateChild: Get the lock to access socket failed with %r\n",\r
287 Status)\r
a3bcde70 288 );\r
d555699b 289 goto ERROR;\r
a3bcde70 290 }\r
d1050b9d 291\r
a3bcde70
HT
292 //\r
293 // inform the protocol layer to attach the socket\r
294 // with a new protocol control block\r
295 //\r
296 Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);\r
80ae1cc7 297 EfiReleaseLock (&(Sock->Lock));\r
a3bcde70 298 if (EFI_ERROR (Status)) {\r
a3bcde70 299 DEBUG (\r
c49ca4a2 300 (DEBUG_ERROR,\r
d1050b9d
MK
301 "SockCreateChild: Protocol failed to attach a socket with %r\n",\r
302 Status)\r
a3bcde70 303 );\r
d555699b 304 goto ERROR;\r
a3bcde70
HT
305 }\r
306\r
a3bcde70 307 return Sock;\r
d555699b
ZL
308\r
309ERROR:\r
310\r
311 if (Sock->DestroyCallback != NULL) {\r
312 Sock->DestroyCallback (Sock, Sock->Context);\r
313 }\r
314\r
315 if (Sock->IpVersion == IP_VERSION_4) {\r
316 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;\r
317 } else {\r
318 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;\r
319 }\r
320\r
321 gBS->OpenProtocol (\r
322 Sock->SockHandle,\r
323 TcpProtocolGuid,\r
324 &SockProtocol,\r
325 Sock->DriverBinding,\r
326 Sock->SockHandle,\r
327 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
328 );\r
329 //\r
330 // Uninstall the protocol installed on this sock\r
331 //\r
332 gBS->UninstallMultipleProtocolInterfaces (\r
d1050b9d
MK
333 Sock->SockHandle,\r
334 TcpProtocolGuid,\r
335 SockProtocol,\r
336 NULL\r
337 );\r
338 SockDestroy (Sock);\r
339 return NULL;\r
a3bcde70
HT
340}\r
341\r
342/**\r
343 Configure the specific socket Sock using configuration data ConfigData.\r
344\r
345 @param[in] Sock Pointer to the socket to be configured.\r
346 @param[in] ConfigData Pointer to the configuration data.\r
347\r
348 @retval EFI_SUCCESS The socket configured successfully.\r
349 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
350 socket is already configured.\r
351\r
352**/\r
353EFI_STATUS\r
354SockConfigure (\r
d1050b9d
MK
355 IN SOCKET *Sock,\r
356 IN VOID *ConfigData\r
a3bcde70
HT
357 )\r
358{\r
359 EFI_STATUS Status;\r
360\r
361 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
362 if (EFI_ERROR (Status)) {\r
a3bcde70 363 DEBUG (\r
c49ca4a2 364 (DEBUG_ERROR,\r
d1050b9d
MK
365 "SockConfigure: Get the access for socket failed with %r",\r
366 Status)\r
a3bcde70
HT
367 );\r
368\r
369 return EFI_ACCESS_DENIED;\r
370 }\r
371\r
372 if (SOCK_IS_CONFIGURED (Sock)) {\r
373 Status = EFI_ACCESS_DENIED;\r
374 goto OnExit;\r
375 }\r
376\r
377 ASSERT (Sock->State == SO_CLOSED);\r
378\r
379 Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);\r
380\r
381OnExit:\r
382 EfiReleaseLock (&(Sock->Lock));\r
383\r
384 return Status;\r
385}\r
386\r
387/**\r
388 Initiate a connection establishment process.\r
389\r
4cefb5e9 390 @param[in] Sock Pointer to the socket to initiate the\r
a3bcde70
HT
391 connection.\r
392 @param[in] Token Pointer to the token used for the connection\r
393 operation.\r
394\r
395 @retval EFI_SUCCESS The connection initialized successfully.\r
396 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
397 socket is closed, or the socket is not configured to\r
398 be an active one, or the token is already in one of\r
399 this socket's lists.\r
400 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
401 finished.\r
402 @retval EFI_NOT_STARTED The socket is not configured.\r
403\r
404**/\r
405EFI_STATUS\r
406SockConnect (\r
d1050b9d
MK
407 IN SOCKET *Sock,\r
408 IN VOID *Token\r
a3bcde70
HT
409 )\r
410{\r
411 EFI_STATUS Status;\r
412 EFI_EVENT Event;\r
413\r
414 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
415 if (EFI_ERROR (Status)) {\r
a3bcde70 416 DEBUG (\r
c49ca4a2 417 (DEBUG_ERROR,\r
d1050b9d
MK
418 "SockConnect: Get the access for socket failed with %r",\r
419 Status)\r
a3bcde70
HT
420 );\r
421\r
422 return EFI_ACCESS_DENIED;\r
423 }\r
424\r
425 if (SOCK_IS_NO_MAPPING (Sock)) {\r
426 Status = EFI_NO_MAPPING;\r
427 goto OnExit;\r
428 }\r
429\r
430 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
a3bcde70
HT
431 Status = EFI_NOT_STARTED;\r
432 goto OnExit;\r
433 }\r
434\r
435 if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {\r
a3bcde70
HT
436 Status = EFI_ACCESS_DENIED;\r
437 goto OnExit;\r
438 }\r
439\r
d1050b9d 440 Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;\r
a3bcde70
HT
441\r
442 if (SockTokenExisted (Sock, Event)) {\r
a3bcde70
HT
443 Status = EFI_ACCESS_DENIED;\r
444 goto OnExit;\r
445 }\r
446\r
d1050b9d 447 Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *)Token;\r
a3bcde70
HT
448 SockSetState (Sock, SO_CONNECTING);\r
449 Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);\r
450\r
451OnExit:\r
452 EfiReleaseLock (&(Sock->Lock));\r
453 return Status;\r
454}\r
455\r
456/**\r
457 Issue a listen token to get an existed connected network instance\r
458 or wait for a connection if there is none.\r
459\r
460 @param[in] Sock Pointer to the socket to accept connections.\r
461 @param[in] Token The token to accept a connection.\r
462\r
4cefb5e9 463 @retval EFI_SUCCESS Either a connection is accepted or the Token is\r
a3bcde70
HT
464 buffered for further acception.\r
465 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
466 socket is closed, or the socket is not configured to\r
467 be a passive one, or the token is already in one of\r
468 this socket's lists.\r
469 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
470 finished.\r
471 @retval EFI_NOT_STARTED The socket is not configured.\r
472 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limits.\r
473\r
474**/\r
475EFI_STATUS\r
476SockAccept (\r
d1050b9d
MK
477 IN SOCKET *Sock,\r
478 IN VOID *Token\r
a3bcde70
HT
479 )\r
480{\r
d1050b9d
MK
481 EFI_TCP4_LISTEN_TOKEN *ListenToken;\r
482 LIST_ENTRY *ListEntry;\r
483 EFI_STATUS Status;\r
484 SOCKET *Socket;\r
485 EFI_EVENT Event;\r
a3bcde70
HT
486\r
487 ASSERT (SockStream == Sock->Type);\r
488\r
489 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
490 if (EFI_ERROR (Status)) {\r
a3bcde70 491 DEBUG (\r
c49ca4a2 492 (DEBUG_ERROR,\r
d1050b9d
MK
493 "SockAccept: Get the access for socket failed with %r",\r
494 Status)\r
a3bcde70
HT
495 );\r
496\r
497 return EFI_ACCESS_DENIED;\r
498 }\r
499\r
500 if (SOCK_IS_NO_MAPPING (Sock)) {\r
501 Status = EFI_NO_MAPPING;\r
502 goto Exit;\r
503 }\r
504\r
505 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
a3bcde70
HT
506 Status = EFI_NOT_STARTED;\r
507 goto Exit;\r
508 }\r
509\r
510 if (!SOCK_IS_LISTENING (Sock)) {\r
a3bcde70
HT
511 Status = EFI_ACCESS_DENIED;\r
512 goto Exit;\r
513 }\r
514\r
d1050b9d 515 Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;\r
a3bcde70
HT
516\r
517 if (SockTokenExisted (Sock, Event)) {\r
a3bcde70
HT
518 Status = EFI_ACCESS_DENIED;\r
519 goto Exit;\r
520 }\r
521\r
d1050b9d 522 ListenToken = (EFI_TCP4_LISTEN_TOKEN *)Token;\r
a3bcde70
HT
523\r
524 //\r
525 // Check if a connection has already in this Sock->ConnectionList\r
526 //\r
527 NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {\r
a3bcde70
HT
528 Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);\r
529\r
530 if (SOCK_IS_CONNECTED (Socket)) {\r
531 ListenToken->NewChildHandle = Socket->SockHandle;\r
532 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);\r
533\r
534 RemoveEntryList (ListEntry);\r
535\r
536 ASSERT (Socket->Parent != NULL);\r
537\r
538 Socket->Parent->ConnCnt--;\r
539\r
540 DEBUG (\r
c49ca4a2 541 (DEBUG_NET,\r
d1050b9d
MK
542 "SockAccept: Accept a socket, now conncount is %d",\r
543 Socket->Parent->ConnCnt)\r
a3bcde70
HT
544 );\r
545 Socket->Parent = NULL;\r
546\r
547 goto Exit;\r
548 }\r
549 }\r
550\r
551 //\r
552 // Buffer this token for latter incoming connection request\r
553 //\r
554 if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {\r
a3bcde70
HT
555 Status = EFI_OUT_OF_RESOURCES;\r
556 }\r
557\r
558Exit:\r
559 EfiReleaseLock (&(Sock->Lock));\r
560\r
561 return Status;\r
562}\r
563\r
564/**\r
565 Issue a token with data to the socket to send out.\r
566\r
567 @param[in] Sock Pointer to the socket to process the token with\r
568 data.\r
569 @param[in] Token The token with data that needs to send out.\r
570\r
571 @retval EFI_SUCCESS The token processed successfully.\r
572 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
573 socket is closed, or the socket is not in a\r
574 synchronized state , or the token is already in one\r
575 of this socket's lists.\r
576 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
577 finished.\r
578 @retval EFI_NOT_STARTED The socket is not configured.\r
579 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limits.\r
580\r
581**/\r
582EFI_STATUS\r
583SockSend (\r
d1050b9d
MK
584 IN SOCKET *Sock,\r
585 IN VOID *Token\r
a3bcde70
HT
586 )\r
587{\r
588 SOCK_IO_TOKEN *SndToken;\r
589 EFI_EVENT Event;\r
590 UINT32 FreeSpace;\r
591 EFI_TCP4_TRANSMIT_DATA *TxData;\r
592 EFI_STATUS Status;\r
593 SOCK_TOKEN *SockToken;\r
594 UINT32 DataLen;\r
595\r
596 ASSERT (SockStream == Sock->Type);\r
597\r
598 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
599 if (EFI_ERROR (Status)) {\r
a3bcde70 600 DEBUG (\r
c49ca4a2 601 (DEBUG_ERROR,\r
d1050b9d
MK
602 "SockSend: Get the access for socket failed with %r",\r
603 Status)\r
a3bcde70
HT
604 );\r
605\r
606 return EFI_ACCESS_DENIED;\r
607 }\r
608\r
609 if (SOCK_IS_NO_MAPPING (Sock)) {\r
610 Status = EFI_NO_MAPPING;\r
611 goto Exit;\r
612 }\r
613\r
d1050b9d
MK
614 SndToken = (SOCK_IO_TOKEN *)Token;\r
615 TxData = (EFI_TCP4_TRANSMIT_DATA *)SndToken->Packet.TxData;\r
a3bcde70
HT
616\r
617 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
618 Status = EFI_NOT_STARTED;\r
619 goto Exit;\r
620 }\r
621\r
622 if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {\r
a3bcde70
HT
623 Status = EFI_ACCESS_DENIED;\r
624 goto Exit;\r
625 }\r
626\r
627 //\r
628 // check if a token is already in the token buffer\r
629 //\r
630 Event = SndToken->Token.Event;\r
631\r
632 if (SockTokenExisted (Sock, Event)) {\r
633 Status = EFI_ACCESS_DENIED;\r
634 goto Exit;\r
635 }\r
636\r
637 DataLen = TxData->DataLength;\r
638\r
639 //\r
640 // process this sending token now or buffer it only?\r
641 //\r
642 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);\r
643\r
644 if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {\r
a3bcde70
HT
645 SockToken = SockBufferToken (\r
646 Sock,\r
647 &Sock->SndTokenList,\r
648 SndToken,\r
649 DataLen\r
650 );\r
651\r
652 if (NULL == SockToken) {\r
653 Status = EFI_OUT_OF_RESOURCES;\r
654 }\r
655 } else {\r
a3bcde70
HT
656 SockToken = SockBufferToken (\r
657 Sock,\r
658 &Sock->ProcessingSndTokenList,\r
659 SndToken,\r
660 DataLen\r
661 );\r
662\r
663 if (NULL == SockToken) {\r
664 DEBUG (\r
c49ca4a2 665 (DEBUG_ERROR,\r
d1050b9d
MK
666 "SockSend: Failed to buffer IO token into socket processing SndToken List\n",\r
667 Status)\r
a3bcde70
HT
668 );\r
669\r
670 Status = EFI_OUT_OF_RESOURCES;\r
671 goto Exit;\r
672 }\r
673\r
674 Status = SockProcessTcpSndData (Sock, TxData);\r
675\r
676 if (EFI_ERROR (Status)) {\r
677 DEBUG (\r
c49ca4a2 678 (DEBUG_ERROR,\r
d1050b9d
MK
679 "SockSend: Failed to process Snd Data\n",\r
680 Status)\r
a3bcde70
HT
681 );\r
682\r
683 RemoveEntryList (&(SockToken->TokenList));\r
684 FreePool (SockToken);\r
685 }\r
686 }\r
687\r
688Exit:\r
689 EfiReleaseLock (&(Sock->Lock));\r
690 return Status;\r
691}\r
692\r
693/**\r
694 Issue a token to get data from the socket.\r
695\r
696 @param[in] Sock Pointer to the socket to get data from.\r
697 @param[in] Token The token to store the received data from the\r
698 socket.\r
699\r
700 @retval EFI_SUCCESS The token processed successfully.\r
701 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
702 socket is closed, or the socket is not in a\r
703 synchronized state , or the token is already in one\r
704 of this socket's lists.\r
705 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
706 finished.\r
707 @retval EFI_NOT_STARTED The socket is not configured.\r
708 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.\r
709 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
710\r
711**/\r
712EFI_STATUS\r
713SockRcv (\r
d1050b9d
MK
714 IN SOCKET *Sock,\r
715 IN VOID *Token\r
a3bcde70
HT
716 )\r
717{\r
d1050b9d
MK
718 SOCK_IO_TOKEN *RcvToken;\r
719 UINT32 RcvdBytes;\r
720 EFI_STATUS Status;\r
721 EFI_EVENT Event;\r
a3bcde70
HT
722\r
723 ASSERT (SockStream == Sock->Type);\r
724\r
725 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
726 if (EFI_ERROR (Status)) {\r
a3bcde70 727 DEBUG (\r
c49ca4a2 728 (DEBUG_ERROR,\r
d1050b9d
MK
729 "SockRcv: Get the access for socket failed with %r",\r
730 Status)\r
a3bcde70
HT
731 );\r
732\r
733 return EFI_ACCESS_DENIED;\r
734 }\r
735\r
736 if (SOCK_IS_NO_MAPPING (Sock)) {\r
a3bcde70
HT
737 Status = EFI_NO_MAPPING;\r
738 goto Exit;\r
739 }\r
740\r
741 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
a3bcde70
HT
742 Status = EFI_NOT_STARTED;\r
743 goto Exit;\r
744 }\r
745\r
746 if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {\r
a3bcde70
HT
747 Status = EFI_ACCESS_DENIED;\r
748 goto Exit;\r
749 }\r
750\r
d1050b9d 751 RcvToken = (SOCK_IO_TOKEN *)Token;\r
a3bcde70
HT
752\r
753 //\r
754 // check if a token is already in the token buffer of this socket\r
755 //\r
756 Event = RcvToken->Token.Event;\r
757 if (SockTokenExisted (Sock, Event)) {\r
758 Status = EFI_ACCESS_DENIED;\r
759 goto Exit;\r
760 }\r
761\r
d1050b9d 762 RcvToken = (SOCK_IO_TOKEN *)Token;\r
a3bcde70
HT
763 RcvdBytes = GET_RCV_DATASIZE (Sock);\r
764\r
765 //\r
766 // check whether an error has happened before\r
767 //\r
768 if (EFI_ABORTED != Sock->SockError) {\r
a3bcde70
HT
769 SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);\r
770 Sock->SockError = EFI_ABORTED;\r
771 goto Exit;\r
772 }\r
773\r
774 //\r
775 // check whether can not receive and there is no any\r
776 // data buffered in Sock->RcvBuffer\r
777 //\r
778 if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {\r
a3bcde70
HT
779 Status = EFI_CONNECTION_FIN;\r
780 goto Exit;\r
781 }\r
782\r
783 if (RcvdBytes != 0) {\r
72a4f34e 784 SockProcessRcvToken (Sock, RcvToken);\r
a3bcde70
HT
785\r
786 Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);\r
787 } else {\r
a3bcde70
HT
788 if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {\r
789 Status = EFI_OUT_OF_RESOURCES;\r
790 }\r
791 }\r
792\r
793Exit:\r
794 EfiReleaseLock (&(Sock->Lock));\r
795 return Status;\r
796}\r
797\r
798/**\r
799 Reset the socket and its associated protocol control block.\r
800\r
801 @param[in, out] Sock Pointer to the socket to be flushed.\r
802\r
803 @retval EFI_SUCCESS The socket is flushed successfully.\r
804 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
805\r
806**/\r
807EFI_STATUS\r
808SockFlush (\r
d1050b9d 809 IN OUT SOCKET *Sock\r
a3bcde70
HT
810 )\r
811{\r
812 EFI_STATUS Status;\r
813\r
814 ASSERT (SockStream == Sock->Type);\r
815\r
816 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
817 if (EFI_ERROR (Status)) {\r
a3bcde70 818 DEBUG (\r
c49ca4a2 819 (DEBUG_ERROR,\r
d1050b9d
MK
820 "SockFlush: Get the access for socket failed with %r",\r
821 Status)\r
a3bcde70
HT
822 );\r
823\r
824 return EFI_ACCESS_DENIED;\r
825 }\r
826\r
827 if (!SOCK_IS_CONFIGURED (Sock)) {\r
a3bcde70
HT
828 Status = EFI_ACCESS_DENIED;\r
829 goto Exit;\r
830 }\r
831\r
832 Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);\r
833 if (EFI_ERROR (Status)) {\r
a3bcde70 834 DEBUG (\r
c49ca4a2 835 (DEBUG_ERROR,\r
d1050b9d
MK
836 "SockFlush: Protocol failed handling SOCK_FLUSH with %r",\r
837 Status)\r
a3bcde70
HT
838 );\r
839\r
840 goto Exit;\r
841 }\r
842\r
843 SOCK_ERROR (Sock, EFI_ABORTED);\r
844 SockConnFlush (Sock);\r
845 SockSetState (Sock, SO_CLOSED);\r
846\r
847 Sock->ConfigureState = SO_UNCONFIGURED;\r
848\r
849Exit:\r
850 EfiReleaseLock (&(Sock->Lock));\r
851 return Status;\r
852}\r
853\r
854/**\r
855 Close or abort the socket associated connection.\r
856\r
857 @param[in, out] Sock Pointer to the socket of the connection to close\r
858 or abort.\r
859 @param[in] Token The token for a close operation.\r
860 @param[in] OnAbort TRUE for aborting the connection; FALSE to close it.\r
861\r
862 @retval EFI_SUCCESS The close or abort operation initialized\r
863 successfully.\r
864 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
865 socket is closed, or the socket is not in a\r
866 synchronized state , or the token is already in one\r
867 of this socket's lists.\r
868 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
869 finished.\r
870 @retval EFI_NOT_STARTED The socket is not configured.\r
871\r
872**/\r
873EFI_STATUS\r
874SockClose (\r
d1050b9d
MK
875 IN OUT SOCKET *Sock,\r
876 IN VOID *Token,\r
877 IN BOOLEAN OnAbort\r
a3bcde70
HT
878 )\r
879{\r
880 EFI_STATUS Status;\r
881 EFI_EVENT Event;\r
882\r
883 ASSERT (SockStream == Sock->Type);\r
884\r
885 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
886 if (EFI_ERROR (Status)) {\r
887 DEBUG (\r
c49ca4a2 888 (DEBUG_ERROR,\r
d1050b9d
MK
889 "SockClose: Get the access for socket failed with %r",\r
890 Status)\r
a3bcde70
HT
891 );\r
892\r
893 return EFI_ACCESS_DENIED;\r
894 }\r
895\r
896 if (SOCK_IS_NO_MAPPING (Sock)) {\r
897 Status = EFI_NO_MAPPING;\r
898 goto Exit;\r
899 }\r
900\r
901 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
902 Status = EFI_NOT_STARTED;\r
903 goto Exit;\r
904 }\r
905\r
906 if (SOCK_IS_DISCONNECTING (Sock)) {\r
907 Status = EFI_ACCESS_DENIED;\r
908 goto Exit;\r
909 }\r
910\r
d1050b9d 911 Event = ((SOCK_COMPLETION_TOKEN *)Token)->Event;\r
a3bcde70
HT
912\r
913 if (SockTokenExisted (Sock, Event)) {\r
914 Status = EFI_ACCESS_DENIED;\r
915 goto Exit;\r
916 }\r
917\r
918 Sock->CloseToken = Token;\r
919 SockSetState (Sock, SO_DISCONNECTING);\r
920\r
921 if (OnAbort) {\r
922 Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);\r
923 } else {\r
924 Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);\r
925 }\r
926\r
927Exit:\r
928 EfiReleaseLock (&(Sock->Lock));\r
929 return Status;\r
930}\r
931\r
5ffe214a
JW
932/**\r
933 Abort the socket associated connection, listen, transmission or receive request.\r
934\r
935 @param[in, out] Sock Pointer to the socket to abort.\r
936 @param[in] Token Pointer to a token that has been issued by\r
937 Connect(), Accept(), Transmit() or Receive(). If\r
938 NULL, all pending tokens issued by the four\r
939 functions listed above will be aborted.\r
940\r
941 @retval EFI_UNSUPPORTED The operation is not supported in the current\r
942 implementation.\r
943**/\r
944EFI_STATUS\r
945SockCancel (\r
946 IN OUT SOCKET *Sock,\r
947 IN VOID *Token\r
f75a7f56 948 )\r
5ffe214a 949{\r
d1050b9d 950 EFI_STATUS Status;\r
5ffe214a 951\r
d1050b9d 952 Status = EFI_SUCCESS;\r
5ffe214a
JW
953\r
954 ASSERT (SockStream == Sock->Type);\r
955\r
956 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
957 if (EFI_ERROR (Status)) {\r
958 DEBUG (\r
c49ca4a2 959 (DEBUG_ERROR,\r
d1050b9d
MK
960 "SockCancel: Get the access for socket failed with %r",\r
961 Status)\r
5ffe214a
JW
962 );\r
963\r
964 return EFI_ACCESS_DENIED;\r
965 }\r
966\r
967 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
968 Status = EFI_NOT_STARTED;\r
969 goto Exit;\r
970 }\r
f75a7f56 971\r
5ffe214a
JW
972 //\r
973 // 1. Check ConnectionToken.\r
974 //\r
d1050b9d 975 if ((Token == NULL) || ((SOCK_COMPLETION_TOKEN *)Token == Sock->ConnectionToken)) {\r
5ffe214a
JW
976 if (Sock->ConnectionToken != NULL) {\r
977 SIGNAL_TOKEN (Sock->ConnectionToken, EFI_ABORTED);\r
978 Sock->ConnectionToken = NULL;\r
979 }\r
980\r
981 if (Token != NULL) {\r
982 Status = EFI_SUCCESS;\r
983 goto Exit;\r
984 }\r
985 }\r
986\r
987 //\r
988 // 2. Check ListenTokenList.\r
989 //\r
990 Status = SockCancelToken (Token, &Sock->ListenTokenList);\r
d1050b9d 991 if ((Token != NULL) && !EFI_ERROR (Status)) {\r
5ffe214a
JW
992 goto Exit;\r
993 }\r
994\r
995 //\r
996 // 3. Check RcvTokenList.\r
997 //\r
998 Status = SockCancelToken (Token, &Sock->RcvTokenList);\r
d1050b9d 999 if ((Token != NULL) && !EFI_ERROR (Status)) {\r
5ffe214a
JW
1000 goto Exit;\r
1001 }\r
f75a7f56 1002\r
5ffe214a
JW
1003 //\r
1004 // 4. Check SndTokenList.\r
1005 //\r
1006 Status = SockCancelToken (Token, &Sock->SndTokenList);\r
d1050b9d 1007 if ((Token != NULL) && !EFI_ERROR (Status)) {\r
5ffe214a
JW
1008 goto Exit;\r
1009 }\r
1010\r
1011 //\r
1012 // 5. Check ProcessingSndTokenList.\r
1013 //\r
1014 Status = SockCancelToken (Token, &Sock->ProcessingSndTokenList);\r
f75a7f56 1015\r
5ffe214a
JW
1016Exit:\r
1017 EfiReleaseLock (&(Sock->Lock));\r
1018 return Status;\r
1019}\r
1020\r
a3bcde70
HT
1021/**\r
1022 Get the mode data of the low layer protocol.\r
1023\r
1024 @param[in] Sock Pointer to the socket to get mode data from.\r
1025 @param[in, out] Mode Pointer to the data to store the low layer mode\r
1026 information.\r
1027\r
1028 @retval EFI_SUCCESS The mode data was obtained successfully.\r
1029 @retval EFI_NOT_STARTED The socket is not configured.\r
1030\r
1031**/\r
1032EFI_STATUS\r
1033SockGetMode (\r
d1050b9d
MK
1034 IN SOCKET *Sock,\r
1035 IN OUT VOID *Mode\r
a3bcde70
HT
1036 )\r
1037{\r
1038 return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);\r
1039}\r
1040\r
a3bcde70
HT
1041/**\r
1042 Add or remove route information in IP route table associated\r
1043 with this socket.\r
1044\r
1045 @param[in] Sock Pointer to the socket associated with the IP route\r
1046 table to operate on.\r
1047 @param[in] RouteInfo Pointer to the route information to be processed.\r
1048\r
1049 @retval EFI_SUCCESS The route table updated successfully.\r
1050 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
1051 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
1052 finished.\r
1053 @retval EFI_NOT_STARTED The socket is not configured.\r
1054\r
1055**/\r
1056EFI_STATUS\r
1057SockRoute (\r
d1050b9d
MK
1058 IN SOCKET *Sock,\r
1059 IN VOID *RouteInfo\r
a3bcde70
HT
1060 )\r
1061{\r
1062 EFI_STATUS Status;\r
1063\r
1064 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
1065 if (EFI_ERROR (Status)) {\r
1066 DEBUG (\r
c49ca4a2 1067 (DEBUG_ERROR,\r
d1050b9d
MK
1068 "SockRoute: Get the access for socket failed with %r",\r
1069 Status)\r
a3bcde70
HT
1070 );\r
1071\r
1072 return EFI_ACCESS_DENIED;\r
1073 }\r
1074\r
1075 if (SOCK_IS_NO_MAPPING (Sock)) {\r
1076 Status = EFI_NO_MAPPING;\r
1077 goto Exit;\r
1078 }\r
1079\r
1080 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
1081 Status = EFI_NOT_STARTED;\r
1082 goto Exit;\r
1083 }\r
1084\r
1085 Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);\r
1086\r
1087Exit:\r
1088 EfiReleaseLock (&(Sock->Lock));\r
1089 return Status;\r
1090}\r