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