]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TcpDxe/SockImpl.c
NetworkPkg: Support TCP Cancel function
[mirror_edk2.git] / NetworkPkg / TcpDxe / SockImpl.c
1 /** @file
2 Implementation of the Socket.
3
4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "SockImpl.h"
17
18 /**
19 Get the first buffer block in the specific socket buffer.
20
21 @param[in] Sockbuf Pointer to the socket buffer.
22
23 @return Pointer to the first buffer in the queue. NULL if the queue is empty.
24
25 **/
26 NET_BUF *
27 SockBufFirst (
28 IN SOCK_BUFFER *Sockbuf
29 )
30 {
31 LIST_ENTRY *NetbufList;
32
33 NetbufList = &(Sockbuf->DataQueue->BufList);
34
35 if (IsListEmpty (NetbufList)) {
36 return NULL;
37 }
38
39 return NET_LIST_HEAD (NetbufList, NET_BUF, List);
40 }
41
42 /**
43 Get the next buffer block in the specific socket buffer.
44
45 @param[in] Sockbuf Pointer to the socket buffer.
46 @param[in] SockEntry Pointer to the buffer block prior to the required one.
47
48 @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is
49 the tail or head entry.
50
51 **/
52 NET_BUF *
53 SockBufNext (
54 IN SOCK_BUFFER *Sockbuf,
55 IN NET_BUF *SockEntry
56 )
57 {
58 LIST_ENTRY *NetbufList;
59
60 NetbufList = &(Sockbuf->DataQueue->BufList);
61
62 if ((SockEntry->List.ForwardLink == NetbufList) ||
63 (SockEntry->List.BackLink == &SockEntry->List) ||
64 (SockEntry->List.ForwardLink == &SockEntry->List)
65 ) {
66
67 return NULL;
68 }
69
70 return NET_LIST_USER_STRUCT (SockEntry->List.ForwardLink, NET_BUF, List);
71 }
72
73 /**
74 User provided callback function for NetbufFromExt.
75
76 @param[in] Event The Event this notify function registered to, ignored.
77
78 **/
79 VOID
80 EFIAPI
81 SockFreeFoo (
82 IN EFI_EVENT Event
83 )
84 {
85 return;
86 }
87
88 /**
89 Get the length of the data that can be retrieved from the socket
90 receive buffer.
91
92 @param[in] SockBuffer Pointer to the socket receive buffer.
93 @param[out] IsUrg Pointer to a BOOLEAN variable.
94 If TRUE the data is OOB.
95 @param[in] BufLen The maximum length of the data buffer to
96 store the received data in the socket layer.
97
98 @return The length of the data can be retreived.
99
100 **/
101 UINT32
102 SockTcpDataToRcv (
103 IN SOCK_BUFFER *SockBuffer,
104 OUT BOOLEAN *IsUrg,
105 IN UINT32 BufLen
106 )
107 {
108 NET_BUF *RcvBufEntry;
109 UINT32 DataLen;
110 TCP_RSV_DATA *TcpRsvData;
111 BOOLEAN Urg;
112
113 ASSERT ((SockBuffer != NULL) && (IsUrg != NULL) && (BufLen > 0));
114
115 //
116 // Get the first socket receive buffer
117 //
118 RcvBufEntry = SockBufFirst (SockBuffer);
119 ASSERT (RcvBufEntry != NULL);
120
121 TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;
122
123 //
124 // Check whether the receive data is out of bound. If yes, calculate the maximum
125 // allowed length of the urgent data and output it.
126 //
127 *IsUrg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);
128
129 if (*IsUrg && (TcpRsvData->UrgLen < RcvBufEntry->TotalSize)) {
130
131 DataLen = MIN (TcpRsvData->UrgLen, BufLen);
132
133 if (DataLen < TcpRsvData->UrgLen) {
134 TcpRsvData->UrgLen = TcpRsvData->UrgLen - DataLen;
135 } else {
136 TcpRsvData->UrgLen = 0;
137 }
138
139 return DataLen;
140
141 }
142
143 //
144 // Process the next socket receive buffer to get the maximum allowed length
145 // of the received data.
146 //
147 DataLen = RcvBufEntry->TotalSize;
148
149 RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);
150
151 while ((BufLen > DataLen) && (RcvBufEntry != NULL)) {
152
153 TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;
154
155 Urg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);
156
157 if (*IsUrg != Urg) {
158 break;
159 }
160
161 if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) {
162
163 if (TcpRsvData->UrgLen + DataLen < BufLen) {
164 TcpRsvData->UrgLen = 0;
165 } else {
166 TcpRsvData->UrgLen = TcpRsvData->UrgLen - (BufLen - DataLen);
167 }
168
169 return MIN (TcpRsvData->UrgLen + DataLen, BufLen);
170
171 }
172
173 DataLen += RcvBufEntry->TotalSize;
174
175 RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);
176 }
177
178 DataLen = MIN (BufLen, DataLen);
179 return DataLen;
180 }
181
182 /**
183 Copy data from socket buffer to an application provided receive buffer.
184
185 @param[in] Sock Pointer to the socket.
186 @param[in] TcpRxData Pointer to the application provided receive buffer.
187 @param[in] RcvdBytes The maximum length of the data can be copied.
188 @param[in] IsUrg If TRUE the data is Out of Bound, FALSE the data is normal.
189
190 **/
191 VOID
192 SockSetTcpRxData (
193 IN SOCKET *Sock,
194 IN VOID *TcpRxData,
195 IN UINT32 RcvdBytes,
196 IN BOOLEAN IsUrg
197 )
198 {
199 UINT32 Index;
200 UINT32 CopyBytes;
201 UINT32 OffSet;
202 EFI_TCP4_RECEIVE_DATA *RxData;
203 EFI_TCP4_FRAGMENT_DATA *Fragment;
204
205 RxData = (EFI_TCP4_RECEIVE_DATA *) TcpRxData;
206
207 OffSet = 0;
208
209 ASSERT (RxData->DataLength >= RcvdBytes);
210
211 RxData->DataLength = RcvdBytes;
212 RxData->UrgentFlag = IsUrg;
213
214 //
215 // Copy the CopyBytes data from socket receive buffer to RxData.
216 //
217 for (Index = 0; (Index < RxData->FragmentCount) && (RcvdBytes > 0); Index++) {
218
219 Fragment = &RxData->FragmentTable[Index];
220 CopyBytes = MIN ((UINT32) (Fragment->FragmentLength), RcvdBytes);
221
222 NetbufQueCopy (
223 Sock->RcvBuffer.DataQueue,
224 OffSet,
225 CopyBytes,
226 Fragment->FragmentBuffer
227 );
228
229 Fragment->FragmentLength = CopyBytes;
230 RcvdBytes -= CopyBytes;
231 OffSet += CopyBytes;
232 }
233 }
234
235 /**
236 Process the send token.
237
238 @param[in, out] Sock Pointer to the socket.
239
240 **/
241 VOID
242 SockProcessSndToken (
243 IN OUT SOCKET *Sock
244 )
245 {
246 UINT32 FreeSpace;
247 SOCK_TOKEN *SockToken;
248 UINT32 DataLen;
249 SOCK_IO_TOKEN *SndToken;
250 EFI_TCP4_TRANSMIT_DATA *TxData;
251 EFI_STATUS Status;
252
253 ASSERT ((Sock != NULL) && (SockStream == Sock->Type));
254
255 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
256
257 //
258 // to determine if process a send token using
259 // socket layer flow control policy
260 //
261 while ((FreeSpace >= Sock->SndBuffer.LowWater) && !IsListEmpty (&Sock->SndTokenList)) {
262
263 SockToken = NET_LIST_HEAD (
264 &(Sock->SndTokenList),
265 SOCK_TOKEN,
266 TokenList
267 );
268
269 //
270 // process this token
271 //
272 RemoveEntryList (&(SockToken->TokenList));
273 InsertTailList (
274 &(Sock->ProcessingSndTokenList),
275 &(SockToken->TokenList)
276 );
277
278 //
279 // Proceess it in the light of SockType
280 //
281 SndToken = (SOCK_IO_TOKEN *) SockToken->Token;
282 TxData = SndToken->Packet.TxData;
283
284 DataLen = TxData->DataLength;
285 Status = SockProcessTcpSndData (Sock, TxData);
286
287 if (EFI_ERROR (Status)) {
288 goto OnError;
289 }
290
291 if (DataLen >= FreeSpace) {
292 FreeSpace = 0;
293
294 } else {
295 FreeSpace -= DataLen;
296
297 }
298 }
299
300 return;
301
302 OnError:
303
304 RemoveEntryList (&SockToken->TokenList);
305 SIGNAL_TOKEN (SockToken->Token, Status);
306 FreePool (SockToken);
307 }
308
309 /**
310 Get received data from the socket layer to the receive token.
311
312 @param[in, out] Sock Pointer to the socket.
313 @param[in, out] RcvToken Pointer to the application provided receive token.
314
315 @return The length of data received in this token.
316
317 **/
318 UINT32
319 SockProcessRcvToken (
320 IN OUT SOCKET *Sock,
321 IN OUT SOCK_IO_TOKEN *RcvToken
322 )
323 {
324 UINT32 TokenRcvdBytes;
325 EFI_TCP4_RECEIVE_DATA *RxData;
326 BOOLEAN IsUrg;
327
328 ASSERT (Sock != NULL);
329
330 ASSERT (SockStream == Sock->Type);
331
332 RxData = RcvToken->Packet.RxData;
333
334 TokenRcvdBytes = SockTcpDataToRcv (
335 &Sock->RcvBuffer,
336 &IsUrg,
337 RxData->DataLength
338 );
339
340 //
341 // Copy data from RcvBuffer of socket to user
342 // provided RxData and set the fields in TCP RxData
343 //
344 SockSetTcpRxData (Sock, RxData, TokenRcvdBytes, IsUrg);
345
346 NetbufQueTrim (Sock->RcvBuffer.DataQueue, TokenRcvdBytes);
347 SIGNAL_TOKEN (&(RcvToken->Token), EFI_SUCCESS);
348
349 return TokenRcvdBytes;
350 }
351
352 /**
353 Process the TCP send data, buffer the tcp txdata, and append
354 the buffer to socket send buffer, then try to send it.
355
356 @param[in] Sock Pointer to the socket.
357 @param[in] TcpTxData Pointer to the application provided send buffer.
358
359 @retval EFI_SUCCESS The operation completed successfully.
360 @retval EFI_OUT_OF_RESOURCES Failed due to resource limits.
361
362 **/
363 EFI_STATUS
364 SockProcessTcpSndData (
365 IN SOCKET *Sock,
366 IN VOID *TcpTxData
367 )
368 {
369 NET_BUF *SndData;
370 EFI_STATUS Status;
371 EFI_TCP4_TRANSMIT_DATA *TxData;
372
373 TxData = (EFI_TCP4_TRANSMIT_DATA *) TcpTxData;
374
375 //
376 // transform this TxData into a NET_BUFFER
377 // and insert it into Sock->SndBuffer
378 //
379 SndData = NetbufFromExt (
380 (NET_FRAGMENT *) TxData->FragmentTable,
381 TxData->FragmentCount,
382 0,
383 0,
384 SockFreeFoo,
385 NULL
386 );
387
388 if (NULL == SndData) {
389 DEBUG (
390 (EFI_D_ERROR,
391 "SockKProcessSndData: Failed to call NetBufferFromExt\n")
392 );
393
394 return EFI_OUT_OF_RESOURCES;
395 }
396
397 NetbufQueAppend (Sock->SndBuffer.DataQueue, SndData);
398
399 //
400 // notify the low layer protocol to handle this send token
401 //
402 if (TxData->Urgent) {
403 Status = Sock->ProtoHandler (Sock, SOCK_SNDURG, NULL);
404
405 if (EFI_ERROR (Status)) {
406 return Status;
407 }
408 }
409
410 if (TxData->Push) {
411 Status = Sock->ProtoHandler (Sock, SOCK_SNDPUSH, NULL);
412
413 if (EFI_ERROR (Status)) {
414 return Status;
415 }
416 }
417
418 //
419 // low layer protocol should really handle the sending
420 // process when catching SOCK_SND request
421 //
422 Status = Sock->ProtoHandler (Sock, SOCK_SND, NULL);
423
424 if (EFI_ERROR (Status)) {
425 return Status;
426 }
427
428 return EFI_SUCCESS;
429 }
430
431 /**
432 Flush the tokens in the specific token list.
433
434 @param[in] Sock Pointer to the socket.
435 @param[in, out] PendingTokenList Pointer to the token list to be flushed.
436
437 **/
438 VOID
439 SockFlushPendingToken (
440 IN SOCKET *Sock,
441 IN OUT LIST_ENTRY *PendingTokenList
442 )
443 {
444 SOCK_TOKEN *SockToken;
445 SOCK_COMPLETION_TOKEN *Token;
446
447 ASSERT ((Sock != NULL) && (PendingTokenList != NULL));
448
449 while (!IsListEmpty (PendingTokenList)) {
450 SockToken = NET_LIST_HEAD (
451 PendingTokenList,
452 SOCK_TOKEN,
453 TokenList
454 );
455
456 Token = SockToken->Token;
457 SIGNAL_TOKEN (Token, Sock->SockError);
458
459 RemoveEntryList (&(SockToken->TokenList));
460 FreePool (SockToken);
461 }
462 }
463
464 /**
465 Wake up the connection token while the connection is successfully established,
466 then try to process any pending send token.
467
468 @param[in, out] Sock Pointer to the socket.
469
470 **/
471 VOID
472 SockWakeConnToken (
473 IN OUT SOCKET *Sock
474 )
475 {
476 ASSERT (Sock->ConnectionToken != NULL);
477
478 SIGNAL_TOKEN (Sock->ConnectionToken, EFI_SUCCESS);
479 Sock->ConnectionToken = NULL;
480
481 //
482 // check to see if some pending send token existed?
483 //
484 SockProcessSndToken (Sock);
485 }
486
487 /**
488 Wake up the listen token while the connection is established successfully.
489
490 @param[in, out] Sock Pointer to the socket.
491
492 **/
493 VOID
494 SockWakeListenToken (
495 IN OUT SOCKET *Sock
496 )
497 {
498 SOCKET *Parent;
499 SOCK_TOKEN *SockToken;
500 EFI_TCP4_LISTEN_TOKEN *ListenToken;
501
502 Parent = Sock->Parent;
503
504 ASSERT ((Parent != NULL) && SOCK_IS_LISTENING (Parent) && SOCK_IS_CONNECTED (Sock));
505
506 if (!IsListEmpty (&Parent->ListenTokenList)) {
507 SockToken = NET_LIST_HEAD (
508 &Parent->ListenTokenList,
509 SOCK_TOKEN,
510 TokenList
511 );
512
513 ListenToken = (EFI_TCP4_LISTEN_TOKEN *) SockToken->Token;
514 ListenToken->NewChildHandle = Sock->SockHandle;
515
516 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
517
518 RemoveEntryList (&SockToken->TokenList);
519 FreePool (SockToken);
520
521 RemoveEntryList (&Sock->ConnectionList);
522
523 Parent->ConnCnt--;
524 DEBUG (
525 (EFI_D_INFO,
526 "SockWakeListenToken: accept a socket, now conncnt is %d",
527 Parent->ConnCnt)
528 );
529
530 Sock->Parent = NULL;
531 }
532 }
533
534 /**
535 Wake up the receive token while some data is received.
536
537 @param[in, out] Sock Pointer to the socket.
538
539 **/
540 VOID
541 SockWakeRcvToken (
542 IN OUT SOCKET *Sock
543 )
544 {
545 UINT32 RcvdBytes;
546 UINT32 TokenRcvdBytes;
547 SOCK_TOKEN *SockToken;
548 SOCK_IO_TOKEN *RcvToken;
549
550 ASSERT (Sock->RcvBuffer.DataQueue != NULL);
551
552 RcvdBytes = (Sock->RcvBuffer.DataQueue)->BufSize;
553
554 ASSERT (RcvdBytes > 0);
555
556 while (RcvdBytes > 0 && !IsListEmpty (&Sock->RcvTokenList)) {
557
558 SockToken = NET_LIST_HEAD (
559 &Sock->RcvTokenList,
560 SOCK_TOKEN,
561 TokenList
562 );
563
564 RcvToken = (SOCK_IO_TOKEN *) SockToken->Token;
565 TokenRcvdBytes = SockProcessRcvToken (Sock, RcvToken);
566
567 if (0 == TokenRcvdBytes) {
568 return ;
569 }
570
571 RemoveEntryList (&(SockToken->TokenList));
572 FreePool (SockToken);
573 RcvdBytes -= TokenRcvdBytes;
574 }
575 }
576
577 /**
578 Cancel the tokens in the specific token list.
579
580 @param[in] Token Pointer to the Token. If NULL, all tokens
581 in SpecifiedTokenList will be canceled.
582 @param[in, out] SpecifiedTokenList Pointer to the token list to be checked.
583
584 @retval EFI_SUCCESS Cancel the tokens in the specific token listsuccessfully.
585 @retval EFI_NOT_FOUND The Token is not found in SpecifiedTokenList.
586
587 **/
588 EFI_STATUS
589 SockCancelToken (
590 IN SOCK_COMPLETION_TOKEN *Token,
591 IN OUT LIST_ENTRY *SpecifiedTokenList
592 )
593 {
594 EFI_STATUS Status;
595 LIST_ENTRY *Entry;
596 LIST_ENTRY *Next;
597 SOCK_TOKEN *SockToken;
598
599 Status = EFI_SUCCESS;
600 Entry = NULL;
601 Next = NULL;
602 SockToken = NULL;
603
604 if (IsListEmpty (SpecifiedTokenList) && Token != NULL) {
605 return EFI_NOT_FOUND;
606 }
607
608 //
609 // Iterate through the SpecifiedTokenList.
610 //
611 Entry = SpecifiedTokenList->ForwardLink;
612 while (Entry != SpecifiedTokenList) {
613 SockToken = NET_LIST_USER_STRUCT (Entry, SOCK_TOKEN, TokenList);
614
615 if (Token == NULL) {
616 SIGNAL_TOKEN (SockToken->Token, EFI_ABORTED);
617 RemoveEntryList (&SockToken->TokenList);
618 FreePool (SockToken);
619
620 Entry = SpecifiedTokenList->ForwardLink;
621 Status = EFI_SUCCESS;
622 } else {
623 if (Token == (VOID *) SockToken->Token) {
624 SIGNAL_TOKEN (Token, EFI_ABORTED);
625 RemoveEntryList (&(SockToken->TokenList));
626 FreePool (SockToken);
627
628 return EFI_SUCCESS;
629 }
630
631 Status = EFI_NOT_FOUND;
632
633 Entry = Entry->ForwardLink;
634 }
635 }
636
637 ASSERT (IsListEmpty (SpecifiedTokenList) || Token != NULL);
638
639 return Status;
640 }
641
642 /**
643 Create a socket with initial data SockInitData.
644
645 @param[in] SockInitData Pointer to the initial data of the socket.
646
647 @return Pointer to the newly created socket, return NULL when an exception occurs.
648
649 **/
650 SOCKET *
651 SockCreate (
652 IN SOCK_INIT_DATA *SockInitData
653 )
654 {
655 SOCKET *Sock;
656 SOCKET *Parent;
657 EFI_STATUS Status;
658 EFI_GUID *TcpProtocolGuid;
659 UINTN ProtocolLength;
660
661 ASSERT ((SockInitData != NULL) && (SockInitData->ProtoHandler != NULL));
662 ASSERT (SockInitData->Type == SockStream);
663 ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN));
664
665 if (SockInitData->IpVersion == IP_VERSION_4) {
666 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
667 ProtocolLength = sizeof (EFI_TCP4_PROTOCOL);
668 } else {
669 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
670 ProtocolLength = sizeof (EFI_TCP6_PROTOCOL);
671 }
672
673
674 Parent = SockInitData->Parent;
675
676 if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) {
677 DEBUG (
678 (EFI_D_ERROR,
679 "SockCreate: Socket parent has reached its connection limit with %d ConnCnt and %d BackLog\n",
680 Parent->ConnCnt,
681 Parent->BackLog)
682 );
683
684 return NULL;
685 }
686
687 Sock = AllocateZeroPool (sizeof (SOCKET));
688 if (NULL == Sock) {
689
690 DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n"));
691 return NULL;
692 }
693
694 InitializeListHead (&Sock->Link);
695 InitializeListHead (&Sock->ConnectionList);
696 InitializeListHead (&Sock->ListenTokenList);
697 InitializeListHead (&Sock->RcvTokenList);
698 InitializeListHead (&Sock->SndTokenList);
699 InitializeListHead (&Sock->ProcessingSndTokenList);
700
701 EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK);
702
703 Sock->SndBuffer.DataQueue = NetbufQueAlloc ();
704 if (NULL == Sock->SndBuffer.DataQueue) {
705 DEBUG (
706 (EFI_D_ERROR,
707 "SockCreate: No resource to allocate SndBuffer for new socket\n")
708 );
709
710 goto OnError;
711 }
712
713 Sock->RcvBuffer.DataQueue = NetbufQueAlloc ();
714 if (NULL == Sock->RcvBuffer.DataQueue) {
715 DEBUG (
716 (EFI_D_ERROR,
717 "SockCreate: No resource to allocate RcvBuffer for new socket\n")
718 );
719
720 goto OnError;
721 }
722
723 Sock->Signature = SOCK_SIGNATURE;
724
725 Sock->Parent = Parent;
726 Sock->BackLog = SockInitData->BackLog;
727 Sock->ProtoHandler = SockInitData->ProtoHandler;
728 Sock->SndBuffer.HighWater = SockInitData->SndBufferSize;
729 Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize;
730 Sock->Type = SockInitData->Type;
731 Sock->DriverBinding = SockInitData->DriverBinding;
732 Sock->State = SockInitData->State;
733 Sock->CreateCallback = SockInitData->CreateCallback;
734 Sock->DestroyCallback = SockInitData->DestroyCallback;
735 Sock->Context = SockInitData->Context;
736
737 Sock->SockError = EFI_ABORTED;
738 Sock->SndBuffer.LowWater = SOCK_BUFF_LOW_WATER;
739 Sock->RcvBuffer.LowWater = SOCK_BUFF_LOW_WATER;
740
741 Sock->IpVersion = SockInitData->IpVersion;
742
743 //
744 // Install protocol on Sock->SockHandle
745 //
746 CopyMem (&Sock->NetProtocol, SockInitData->Protocol, ProtocolLength);
747
748 //
749 // copy the protodata into socket
750 //
751 CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize);
752
753 Status = gBS->InstallMultipleProtocolInterfaces (
754 &Sock->SockHandle,
755 TcpProtocolGuid,
756 &Sock->NetProtocol,
757 NULL
758 );
759
760 if (EFI_ERROR (Status)) {
761 DEBUG (
762 (EFI_D_ERROR,
763 "SockCreate: Install TCP protocol in socket failed with %r\n",
764 Status)
765 );
766
767 goto OnError;
768 }
769
770 if (Parent != NULL) {
771 ASSERT (Parent->BackLog > 0);
772 ASSERT (SOCK_IS_LISTENING (Parent));
773
774 //
775 // need to add it into Parent->ConnectionList
776 // if the Parent->ConnCnt < Parent->BackLog
777 //
778 Parent->ConnCnt++;
779
780 DEBUG (
781 (EFI_D_INFO,
782 "SockCreate: Create a new socket and add to parent, now conncnt is %d\n",
783 Parent->ConnCnt)
784 );
785
786 InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList);
787 }
788
789 if (Sock->CreateCallback != NULL) {
790 Status = Sock->CreateCallback (Sock, Sock->Context);
791 if (EFI_ERROR (Status)) {
792 goto OnError;
793 }
794 }
795
796 return Sock;
797
798 OnError:
799
800 if (Sock->SockHandle != NULL) {
801 gBS->UninstallMultipleProtocolInterfaces (
802 Sock->SockHandle,
803 TcpProtocolGuid,
804 &Sock->NetProtocol,
805 NULL
806 );
807 }
808
809 if (NULL != Sock->SndBuffer.DataQueue) {
810 NetbufQueFree (Sock->SndBuffer.DataQueue);
811 }
812
813 if (NULL != Sock->RcvBuffer.DataQueue) {
814 NetbufQueFree (Sock->RcvBuffer.DataQueue);
815 }
816
817 FreePool (Sock);
818
819 return NULL;
820 }
821
822 /**
823 Destroy a socket.
824
825 @param[in, out] Sock Pointer to the socket.
826
827 **/
828 VOID
829 SockDestroy (
830 IN OUT SOCKET *Sock
831 )
832 {
833 VOID *SockProtocol;
834 EFI_GUID *TcpProtocolGuid;
835 EFI_STATUS Status;
836
837 ASSERT (SockStream == Sock->Type);
838
839 if (Sock->DestroyCallback != NULL) {
840 Sock->DestroyCallback (Sock, Sock->Context);
841 }
842
843 //
844 // Flush the completion token buffered
845 // by sock and rcv, snd buffer
846 //
847 if (!SOCK_IS_UNCONFIGURED (Sock)) {
848
849 SockConnFlush (Sock);
850 SockSetState (Sock, SO_CLOSED);
851 Sock->ConfigureState = SO_UNCONFIGURED;
852
853 }
854 //
855 // Destroy the RcvBuffer Queue and SendBuffer Queue
856 //
857 NetbufQueFree (Sock->RcvBuffer.DataQueue);
858 NetbufQueFree (Sock->SndBuffer.DataQueue);
859
860 //
861 // Remove it from parent connection list if needed
862 //
863 if (Sock->Parent != NULL) {
864
865 RemoveEntryList (&(Sock->ConnectionList));
866 (Sock->Parent->ConnCnt)--;
867
868 DEBUG (
869 (EFI_D_WARN,
870 "SockDestroy: Delete a unaccepted socket from parent now conncnt is %d\n",
871 Sock->Parent->ConnCnt)
872 );
873
874 Sock->Parent = NULL;
875 }
876
877 //
878 // Set the protocol guid and driver binding handle
879 // in the light of Sock->SockType
880 //
881 if (Sock->IpVersion == IP_VERSION_4) {
882 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
883 } else {
884 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
885 }
886
887 //
888 // Retrieve the protocol installed on this sock
889 //
890 Status = gBS->OpenProtocol (
891 Sock->SockHandle,
892 TcpProtocolGuid,
893 &SockProtocol,
894 Sock->DriverBinding,
895 Sock->SockHandle,
896 EFI_OPEN_PROTOCOL_GET_PROTOCOL
897 );
898
899 if (EFI_ERROR (Status)) {
900
901 DEBUG (
902 (EFI_D_ERROR,
903 "SockDestroy: Open protocol installed on socket failed with %r\n",
904 Status)
905 );
906
907 goto FreeSock;
908 }
909
910 //
911 // Uninstall the protocol installed on this sock
912 // in the light of Sock->SockType
913 //
914 gBS->UninstallMultipleProtocolInterfaces (
915 Sock->SockHandle,
916 TcpProtocolGuid,
917 SockProtocol,
918 NULL
919 );
920
921 FreeSock:
922
923 FreePool (Sock);
924 }
925
926 /**
927 Flush the sndBuffer and rcvBuffer of socket.
928
929 @param[in, out] Sock Pointer to the socket.
930
931 **/
932 VOID
933 SockConnFlush (
934 IN OUT SOCKET *Sock
935 )
936 {
937 SOCKET *Child;
938
939 ASSERT (Sock != NULL);
940
941 //
942 // Clear the flag in this socket
943 //
944 Sock->Flag = 0;
945
946 //
947 // Flush the SndBuffer and RcvBuffer of Sock
948 //
949 NetbufQueFlush (Sock->SndBuffer.DataQueue);
950 NetbufQueFlush (Sock->RcvBuffer.DataQueue);
951
952 //
953 // Signal the pending token
954 //
955 if (Sock->ConnectionToken != NULL) {
956 SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError);
957 Sock->ConnectionToken = NULL;
958 }
959
960 if (Sock->CloseToken != NULL) {
961 SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError);
962 Sock->CloseToken = NULL;
963 }
964
965 SockFlushPendingToken (Sock, &(Sock->ListenTokenList));
966 SockFlushPendingToken (Sock, &(Sock->RcvTokenList));
967 SockFlushPendingToken (Sock, &(Sock->SndTokenList));
968 SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList));
969
970 //
971 // Destroy the pending connection, if it is a listening socket
972 //
973 if (SOCK_IS_LISTENING (Sock)) {
974 while (!IsListEmpty (&Sock->ConnectionList)) {
975 Child = NET_LIST_HEAD (
976 &Sock->ConnectionList,
977 SOCKET,
978 ConnectionList
979 );
980
981 SockDestroyChild (Child);
982 }
983
984 Sock->ConnCnt = 0;
985 }
986
987 }
988
989 /**
990 Set the state of the socket.
991
992 @param[in, out] Sock Pointer to the socket.
993 @param[in] State The new socket state to be set.
994
995 **/
996 VOID
997 SockSetState (
998 IN OUT SOCKET *Sock,
999 IN UINT8 State
1000 )
1001 {
1002 Sock->State = State;
1003 }
1004
1005 /**
1006 Clone a new socket, including its associated protocol control block.
1007
1008 @param[in] Sock Pointer to the socket to be cloned.
1009
1010 @return Pointer to the newly cloned socket. If NULL, an error condition occurred.
1011
1012 **/
1013 SOCKET *
1014 SockClone (
1015 IN SOCKET *Sock
1016 )
1017 {
1018 SOCKET *ClonedSock;
1019 SOCK_INIT_DATA InitData;
1020
1021 InitData.BackLog = Sock->BackLog;
1022 InitData.Parent = Sock;
1023 InitData.State = Sock->State;
1024 InitData.ProtoHandler = Sock->ProtoHandler;
1025 InitData.Type = Sock->Type;
1026 InitData.RcvBufferSize = Sock->RcvBuffer.HighWater;
1027 InitData.SndBufferSize = Sock->SndBuffer.HighWater;
1028 InitData.DriverBinding = Sock->DriverBinding;
1029 InitData.IpVersion = Sock->IpVersion;
1030 InitData.Protocol = &(Sock->NetProtocol);
1031 InitData.CreateCallback = Sock->CreateCallback;
1032 InitData.DestroyCallback = Sock->DestroyCallback;
1033 InitData.Context = Sock->Context;
1034 InitData.ProtoData = Sock->ProtoReserved;
1035 InitData.DataSize = sizeof (Sock->ProtoReserved);
1036
1037 ClonedSock = SockCreate (&InitData);
1038
1039 if (NULL == ClonedSock) {
1040 DEBUG ((EFI_D_ERROR, "SockClone: no resource to create a cloned sock\n"));
1041 return NULL;
1042 }
1043
1044 SockSetState (ClonedSock, SO_CONNECTING);
1045 ClonedSock->ConfigureState = Sock->ConfigureState;
1046
1047 return ClonedSock;
1048 }
1049
1050 /**
1051 Called by the low layer protocol to indicate the socket a connection is
1052 established.
1053
1054 This function just changes the socket's state to SO_CONNECTED
1055 and signals the token used for connection establishment.
1056
1057 @param[in, out] Sock Pointer to the socket associated with the
1058 established connection.
1059
1060 **/
1061 VOID
1062 SockConnEstablished (
1063 IN OUT SOCKET *Sock
1064 )
1065 {
1066
1067 ASSERT (SO_CONNECTING == Sock->State);
1068
1069 SockSetState (Sock, SO_CONNECTED);
1070
1071 if (NULL == Sock->Parent) {
1072 SockWakeConnToken (Sock);
1073 } else {
1074 SockWakeListenToken (Sock);
1075 }
1076
1077 }
1078
1079 /**
1080 Called by the low layer protocol to indicate the connection is closed.
1081
1082 This function flushes the socket, sets the state to SO_CLOSED, and signals
1083 the close token.
1084
1085 @param[in, out] Sock Pointer to the socket associated with the closed
1086 connection.
1087
1088 **/
1089 VOID
1090 SockConnClosed (
1091 IN OUT SOCKET *Sock
1092 )
1093 {
1094 if (Sock->CloseToken != NULL) {
1095 SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS);
1096 Sock->CloseToken = NULL;
1097 }
1098
1099 SockConnFlush (Sock);
1100 SockSetState (Sock, SO_CLOSED);
1101
1102 if (Sock->Parent != NULL) {
1103 SockDestroyChild (Sock);
1104 }
1105
1106 }
1107
1108 /**
1109 Called by low layer protocol to indicate that some data was sent or processed.
1110
1111 This function trims the sent data in the socket send buffer, and signals the data
1112 token if proper.
1113
1114 @param[in, out] Sock Pointer to the socket.
1115 @param[in] Count The length of the data processed or sent, in bytes.
1116
1117 **/
1118 VOID
1119 SockDataSent (
1120 IN OUT SOCKET *Sock,
1121 IN UINT32 Count
1122 )
1123 {
1124 SOCK_TOKEN *SockToken;
1125 SOCK_COMPLETION_TOKEN *SndToken;
1126
1127 ASSERT (!IsListEmpty (&Sock->ProcessingSndTokenList));
1128 ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize);
1129
1130 NetbufQueTrim (Sock->SndBuffer.DataQueue, Count);
1131
1132 //
1133 // To check if we can signal some snd token in this socket
1134 //
1135 while (Count > 0) {
1136 SockToken = NET_LIST_HEAD (
1137 &(Sock->ProcessingSndTokenList),
1138 SOCK_TOKEN,
1139 TokenList
1140 );
1141
1142 SndToken = SockToken->Token;
1143
1144 if (SockToken->RemainDataLen <= Count) {
1145
1146 RemoveEntryList (&(SockToken->TokenList));
1147 SIGNAL_TOKEN (SndToken, EFI_SUCCESS);
1148 Count -= SockToken->RemainDataLen;
1149 FreePool (SockToken);
1150 } else {
1151
1152 SockToken->RemainDataLen -= Count;
1153 Count = 0;
1154 }
1155 }
1156
1157 //
1158 // to judge if we can process some send token in
1159 // Sock->SndTokenList, if so process those send token
1160 //
1161 SockProcessSndToken (Sock);
1162 }
1163
1164 /**
1165 Called by the low layer protocol to copy some data in the socket send
1166 buffer starting from the specific offset to a buffer provided by
1167 the caller.
1168
1169 @param[in] Sock Pointer to the socket.
1170 @param[in] Offset The start point of the data to be copied.
1171 @param[in] Len The length of the data to be copied.
1172 @param[out] Dest Pointer to the destination to copy the data.
1173
1174 @return The data size copied.
1175
1176 **/
1177 UINT32
1178 SockGetDataToSend (
1179 IN SOCKET *Sock,
1180 IN UINT32 Offset,
1181 IN UINT32 Len,
1182 OUT UINT8 *Dest
1183 )
1184 {
1185 ASSERT ((Sock != NULL) && SockStream == Sock->Type);
1186
1187 return NetbufQueCopy (
1188 Sock->SndBuffer.DataQueue,
1189 Offset,
1190 Len,
1191 Dest
1192 );
1193 }
1194
1195 /**
1196 Called by the low layer protocol to deliver received data to socket layer.
1197
1198 This function will append the data to the socket receive buffer, set the
1199 urgent data length, and then check if any receive token can be signaled.
1200
1201 @param[in, out] Sock Pointer to the socket.
1202 @param[in, out] NetBuffer Pointer to the buffer that contains the received data.
1203 @param[in] UrgLen The length of the urgent data in the received data.
1204
1205 **/
1206 VOID
1207 SockDataRcvd (
1208 IN OUT SOCKET *Sock,
1209 IN OUT NET_BUF *NetBuffer,
1210 IN UINT32 UrgLen
1211 )
1212 {
1213 ASSERT ((Sock != NULL) && (Sock->RcvBuffer.DataQueue != NULL) &&
1214 UrgLen <= NetBuffer->TotalSize);
1215
1216 NET_GET_REF (NetBuffer);
1217
1218 ((TCP_RSV_DATA *) (NetBuffer->ProtoData))->UrgLen = UrgLen;
1219
1220 NetbufQueAppend (Sock->RcvBuffer.DataQueue, NetBuffer);
1221
1222 SockWakeRcvToken (Sock);
1223 }
1224
1225 /**
1226 Get the length of the free space of the specific socket buffer.
1227
1228 @param[in] Sock Pointer to the socket.
1229 @param[in] Which Flag to indicate which socket buffer to check:
1230 either send buffer or receive buffer.
1231
1232 @return The length of the free space, in bytes.
1233
1234 **/
1235 UINT32
1236 SockGetFreeSpace (
1237 IN SOCKET *Sock,
1238 IN UINT32 Which
1239 )
1240 {
1241 UINT32 BufferCC;
1242 SOCK_BUFFER *SockBuffer;
1243
1244 ASSERT (Sock != NULL && ((SOCK_SND_BUF == Which) || (SOCK_RCV_BUF == Which)));
1245
1246 if (SOCK_SND_BUF == Which) {
1247 SockBuffer = &(Sock->SndBuffer);
1248 } else {
1249 SockBuffer = &(Sock->RcvBuffer);
1250 }
1251
1252 BufferCC = (SockBuffer->DataQueue)->BufSize;
1253
1254 if (BufferCC >= SockBuffer->HighWater) {
1255
1256 return 0;
1257 }
1258
1259 return SockBuffer->HighWater - BufferCC;
1260 }
1261
1262 /**
1263 Called by the low layer protocol to indicate that there will be no more data
1264 from the communication peer.
1265
1266 This function sets the socket's state to SO_NO_MORE_DATA and signals all queued
1267 IO tokens with the error status EFI_CONNECTION_FIN.
1268
1269 @param[in, out] Sock Pointer to the socket.
1270
1271 **/
1272 VOID
1273 SockNoMoreData (
1274 IN OUT SOCKET *Sock
1275 )
1276 {
1277 EFI_STATUS Err;
1278
1279 SOCK_NO_MORE_DATA (Sock);
1280
1281 if (!IsListEmpty (&Sock->RcvTokenList)) {
1282
1283 ASSERT (0 == GET_RCV_DATASIZE (Sock));
1284
1285 Err = Sock->SockError;
1286
1287 SOCK_ERROR (Sock, EFI_CONNECTION_FIN);
1288
1289 SockFlushPendingToken (Sock, &Sock->RcvTokenList);
1290
1291 SOCK_ERROR (Sock, Err);
1292
1293 }
1294 }
1295