VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/TcpDxe/SockImpl.c@ 80721

Last change on this file since 80721 was 80721, checked in by vboxsync, 5 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette