VirtualBox

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

Last change on this file since 77662 was 77662, checked in by vboxsync, 6 years ago

EFI: First step in UDK2018 merge. Does not build yet.

  • Property svn:eol-style set to native
File size: 28.8 KB
Line 
1/** @file
2 Implementation of the Socket.
3
4 Copyright (c) 2009 - 2017, 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**/
26NET_BUF *
27SockBufFirst (
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**/
52NET_BUF *
53SockBufNext (
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**/
79VOID
80EFIAPI
81SockFreeFoo (
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**/
101UINT32
102SockTcpDataToRcv (
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**/
191VOID
192SockSetTcpRxData (
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**/
241VOID
242SockProcessSndToken (
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
302OnError:
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**/
318UINT32
319SockProcessRcvToken (
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**/
363EFI_STATUS
364SockProcessTcpSndData (
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**/
438VOID
439SockFlushPendingToken (
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**/
471VOID
472SockWakeConnToken (
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**/
493VOID
494SockWakeListenToken (
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_NET,
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**/
540VOID
541SockWakeRcvToken (
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**/
588EFI_STATUS
589SockCancelToken (
590 IN SOCK_COMPLETION_TOKEN *Token,
591 IN OUT LIST_ENTRY *SpecifiedTokenList
592 )
593{
594 EFI_STATUS Status;
595 LIST_ENTRY *Entry;
596 SOCK_TOKEN *SockToken;
597
598 Status = EFI_SUCCESS;
599 Entry = NULL;
600 SockToken = NULL;
601
602 if (IsListEmpty (SpecifiedTokenList) && Token != NULL) {
603 return EFI_NOT_FOUND;
604 }
605
606 //
607 // Iterate through the SpecifiedTokenList.
608 //
609 Entry = SpecifiedTokenList->ForwardLink;
610 while (Entry != SpecifiedTokenList) {
611 SockToken = NET_LIST_USER_STRUCT (Entry, SOCK_TOKEN, TokenList);
612
613 if (Token == NULL) {
614 SIGNAL_TOKEN (SockToken->Token, EFI_ABORTED);
615 RemoveEntryList (&SockToken->TokenList);
616 FreePool (SockToken);
617
618 Entry = SpecifiedTokenList->ForwardLink;
619 Status = EFI_SUCCESS;
620 } else {
621 if (Token == (VOID *) SockToken->Token) {
622 SIGNAL_TOKEN (Token, EFI_ABORTED);
623 RemoveEntryList (&(SockToken->TokenList));
624 FreePool (SockToken);
625
626 return EFI_SUCCESS;
627 }
628
629 Status = EFI_NOT_FOUND;
630
631 Entry = Entry->ForwardLink;
632 }
633 }
634
635 ASSERT (IsListEmpty (SpecifiedTokenList) || Token != NULL);
636
637 return Status;
638}
639
640/**
641 Create a socket with initial data SockInitData.
642
643 @param[in] SockInitData Pointer to the initial data of the socket.
644
645 @return Pointer to the newly created socket, return NULL when an exception occurs.
646
647**/
648SOCKET *
649SockCreate (
650 IN SOCK_INIT_DATA *SockInitData
651 )
652{
653 SOCKET *Sock;
654 SOCKET *Parent;
655 EFI_STATUS Status;
656 EFI_GUID *TcpProtocolGuid;
657 UINTN ProtocolLength;
658
659 ASSERT ((SockInitData != NULL) && (SockInitData->ProtoHandler != NULL));
660 ASSERT (SockInitData->Type == SockStream);
661 ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN));
662
663 if (SockInitData->IpVersion == IP_VERSION_4) {
664 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
665 ProtocolLength = sizeof (EFI_TCP4_PROTOCOL);
666 } else {
667 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
668 ProtocolLength = sizeof (EFI_TCP6_PROTOCOL);
669 }
670
671
672 Parent = SockInitData->Parent;
673
674 if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) {
675 DEBUG (
676 (EFI_D_ERROR,
677 "SockCreate: Socket parent has reached its connection limit with %d ConnCnt and %d BackLog\n",
678 Parent->ConnCnt,
679 Parent->BackLog)
680 );
681
682 return NULL;
683 }
684
685 Sock = AllocateZeroPool (sizeof (SOCKET));
686 if (NULL == Sock) {
687
688 DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n"));
689 return NULL;
690 }
691
692 InitializeListHead (&Sock->Link);
693 InitializeListHead (&Sock->ConnectionList);
694 InitializeListHead (&Sock->ListenTokenList);
695 InitializeListHead (&Sock->RcvTokenList);
696 InitializeListHead (&Sock->SndTokenList);
697 InitializeListHead (&Sock->ProcessingSndTokenList);
698
699 EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK);
700
701 Sock->SndBuffer.DataQueue = NetbufQueAlloc ();
702 if (NULL == Sock->SndBuffer.DataQueue) {
703 DEBUG (
704 (EFI_D_ERROR,
705 "SockCreate: No resource to allocate SndBuffer for new socket\n")
706 );
707
708 goto OnError;
709 }
710
711 Sock->RcvBuffer.DataQueue = NetbufQueAlloc ();
712 if (NULL == Sock->RcvBuffer.DataQueue) {
713 DEBUG (
714 (EFI_D_ERROR,
715 "SockCreate: No resource to allocate RcvBuffer for new socket\n")
716 );
717
718 goto OnError;
719 }
720
721 Sock->Signature = SOCK_SIGNATURE;
722
723 Sock->Parent = Parent;
724 Sock->BackLog = SockInitData->BackLog;
725 Sock->ProtoHandler = SockInitData->ProtoHandler;
726 Sock->SndBuffer.HighWater = SockInitData->SndBufferSize;
727 Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize;
728 Sock->Type = SockInitData->Type;
729 Sock->DriverBinding = SockInitData->DriverBinding;
730 Sock->State = SockInitData->State;
731 Sock->CreateCallback = SockInitData->CreateCallback;
732 Sock->DestroyCallback = SockInitData->DestroyCallback;
733 Sock->Context = SockInitData->Context;
734
735 Sock->SockError = EFI_ABORTED;
736 Sock->SndBuffer.LowWater = SOCK_BUFF_LOW_WATER;
737 Sock->RcvBuffer.LowWater = SOCK_BUFF_LOW_WATER;
738
739 Sock->IpVersion = SockInitData->IpVersion;
740
741 //
742 // Install protocol on Sock->SockHandle
743 //
744 CopyMem (&Sock->NetProtocol, SockInitData->Protocol, ProtocolLength);
745
746 //
747 // copy the protodata into socket
748 //
749 CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize);
750
751 Status = gBS->InstallMultipleProtocolInterfaces (
752 &Sock->SockHandle,
753 TcpProtocolGuid,
754 &Sock->NetProtocol,
755 NULL
756 );
757
758 if (EFI_ERROR (Status)) {
759 DEBUG (
760 (EFI_D_ERROR,
761 "SockCreate: Install TCP protocol in socket failed with %r\n",
762 Status)
763 );
764
765 goto OnError;
766 }
767
768 if (Parent != NULL) {
769 ASSERT (Parent->BackLog > 0);
770 ASSERT (SOCK_IS_LISTENING (Parent));
771
772 //
773 // need to add it into Parent->ConnectionList
774 // if the Parent->ConnCnt < Parent->BackLog
775 //
776 Parent->ConnCnt++;
777
778 DEBUG (
779 (EFI_D_NET,
780 "SockCreate: Create a new socket and add to parent, now conncnt is %d\n",
781 Parent->ConnCnt)
782 );
783
784 InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList);
785 }
786
787 if (Sock->CreateCallback != NULL) {
788 Status = Sock->CreateCallback (Sock, Sock->Context);
789 if (EFI_ERROR (Status)) {
790 goto OnError;
791 }
792 }
793
794 return Sock;
795
796OnError:
797
798 if (Sock->SockHandle != NULL) {
799 gBS->UninstallMultipleProtocolInterfaces (
800 Sock->SockHandle,
801 TcpProtocolGuid,
802 &Sock->NetProtocol,
803 NULL
804 );
805 }
806
807 if (NULL != Sock->SndBuffer.DataQueue) {
808 NetbufQueFree (Sock->SndBuffer.DataQueue);
809 }
810
811 if (NULL != Sock->RcvBuffer.DataQueue) {
812 NetbufQueFree (Sock->RcvBuffer.DataQueue);
813 }
814
815 FreePool (Sock);
816
817 return NULL;
818}
819
820/**
821 Destroy a socket.
822
823 @param[in, out] Sock Pointer to the socket.
824
825**/
826VOID
827SockDestroy (
828 IN OUT SOCKET *Sock
829 )
830{
831 ASSERT (SockStream == Sock->Type);
832
833 //
834 // Flush the completion token buffered
835 // by sock and rcv, snd buffer
836 //
837 if (!SOCK_IS_UNCONFIGURED (Sock)) {
838
839 SockConnFlush (Sock);
840 SockSetState (Sock, SO_CLOSED);
841 Sock->ConfigureState = SO_UNCONFIGURED;
842
843 }
844 //
845 // Destroy the RcvBuffer Queue and SendBuffer Queue
846 //
847 NetbufQueFree (Sock->RcvBuffer.DataQueue);
848 NetbufQueFree (Sock->SndBuffer.DataQueue);
849
850 //
851 // Remove it from parent connection list if needed
852 //
853 if (Sock->Parent != NULL) {
854
855 RemoveEntryList (&(Sock->ConnectionList));
856 (Sock->Parent->ConnCnt)--;
857
858 DEBUG (
859 (EFI_D_WARN,
860 "SockDestroy: Delete a unaccepted socket from parent now conncnt is %d\n",
861 Sock->Parent->ConnCnt)
862 );
863
864 Sock->Parent = NULL;
865 }
866
867 FreePool (Sock);
868}
869
870/**
871 Flush the sndBuffer and rcvBuffer of socket.
872
873 @param[in, out] Sock Pointer to the socket.
874
875**/
876VOID
877SockConnFlush (
878 IN OUT SOCKET *Sock
879 )
880{
881 SOCKET *Child;
882
883 ASSERT (Sock != NULL);
884
885 //
886 // Clear the flag in this socket
887 //
888 Sock->Flag = 0;
889
890 //
891 // Flush the SndBuffer and RcvBuffer of Sock
892 //
893 NetbufQueFlush (Sock->SndBuffer.DataQueue);
894 NetbufQueFlush (Sock->RcvBuffer.DataQueue);
895
896 //
897 // Signal the pending token
898 //
899 if (Sock->ConnectionToken != NULL) {
900 SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError);
901 Sock->ConnectionToken = NULL;
902 }
903
904 if (Sock->CloseToken != NULL) {
905 SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError);
906 Sock->CloseToken = NULL;
907 }
908
909 SockFlushPendingToken (Sock, &(Sock->ListenTokenList));
910 SockFlushPendingToken (Sock, &(Sock->RcvTokenList));
911 SockFlushPendingToken (Sock, &(Sock->SndTokenList));
912 SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList));
913
914 //
915 // Destroy the pending connection, if it is a listening socket
916 //
917 if (SOCK_IS_LISTENING (Sock)) {
918 while (!IsListEmpty (&Sock->ConnectionList)) {
919 Child = NET_LIST_HEAD (
920 &Sock->ConnectionList,
921 SOCKET,
922 ConnectionList
923 );
924
925 SockDestroyChild (Child);
926 }
927
928 Sock->ConnCnt = 0;
929 }
930
931}
932
933/**
934 Set the state of the socket.
935
936 @param[in, out] Sock Pointer to the socket.
937 @param[in] State The new socket state to be set.
938
939**/
940VOID
941SockSetState (
942 IN OUT SOCKET *Sock,
943 IN UINT8 State
944 )
945{
946 Sock->State = State;
947}
948
949/**
950 Clone a new socket, including its associated protocol control block.
951
952 @param[in] Sock Pointer to the socket to be cloned.
953
954 @return Pointer to the newly cloned socket. If NULL, an error condition occurred.
955
956**/
957SOCKET *
958SockClone (
959 IN SOCKET *Sock
960 )
961{
962 SOCKET *ClonedSock;
963 SOCK_INIT_DATA InitData;
964
965 InitData.BackLog = Sock->BackLog;
966 InitData.Parent = Sock;
967 InitData.State = Sock->State;
968 InitData.ProtoHandler = Sock->ProtoHandler;
969 InitData.Type = Sock->Type;
970 InitData.RcvBufferSize = Sock->RcvBuffer.HighWater;
971 InitData.SndBufferSize = Sock->SndBuffer.HighWater;
972 InitData.DriverBinding = Sock->DriverBinding;
973 InitData.IpVersion = Sock->IpVersion;
974 InitData.Protocol = &(Sock->NetProtocol);
975 InitData.CreateCallback = Sock->CreateCallback;
976 InitData.DestroyCallback = Sock->DestroyCallback;
977 InitData.Context = Sock->Context;
978 InitData.ProtoData = Sock->ProtoReserved;
979 InitData.DataSize = sizeof (Sock->ProtoReserved);
980
981 ClonedSock = SockCreate (&InitData);
982
983 if (NULL == ClonedSock) {
984 DEBUG ((EFI_D_ERROR, "SockClone: no resource to create a cloned sock\n"));
985 return NULL;
986 }
987
988 SockSetState (ClonedSock, SO_CONNECTING);
989 ClonedSock->ConfigureState = Sock->ConfigureState;
990
991 return ClonedSock;
992}
993
994/**
995 Called by the low layer protocol to indicate the socket a connection is
996 established.
997
998 This function just changes the socket's state to SO_CONNECTED
999 and signals the token used for connection establishment.
1000
1001 @param[in, out] Sock Pointer to the socket associated with the
1002 established connection.
1003
1004**/
1005VOID
1006SockConnEstablished (
1007 IN OUT SOCKET *Sock
1008 )
1009{
1010
1011 ASSERT (SO_CONNECTING == Sock->State);
1012
1013 SockSetState (Sock, SO_CONNECTED);
1014
1015 if (NULL == Sock->Parent) {
1016 SockWakeConnToken (Sock);
1017 } else {
1018 SockWakeListenToken (Sock);
1019 }
1020
1021}
1022
1023/**
1024 Called by the low layer protocol to indicate the connection is closed.
1025
1026 This function flushes the socket, sets the state to SO_CLOSED, and signals
1027 the close token.
1028
1029 @param[in, out] Sock Pointer to the socket associated with the closed
1030 connection.
1031
1032**/
1033VOID
1034SockConnClosed (
1035 IN OUT SOCKET *Sock
1036 )
1037{
1038 if (Sock->CloseToken != NULL) {
1039 SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS);
1040 Sock->CloseToken = NULL;
1041 }
1042
1043 SockConnFlush (Sock);
1044 SockSetState (Sock, SO_CLOSED);
1045
1046 if (Sock->Parent != NULL) {
1047 SockDestroyChild (Sock);
1048 }
1049
1050}
1051
1052/**
1053 Called by low layer protocol to indicate that some data was sent or processed.
1054
1055 This function trims the sent data in the socket send buffer, and signals the data
1056 token if proper.
1057
1058 @param[in, out] Sock Pointer to the socket.
1059 @param[in] Count The length of the data processed or sent, in bytes.
1060
1061**/
1062VOID
1063SockDataSent (
1064 IN OUT SOCKET *Sock,
1065 IN UINT32 Count
1066 )
1067{
1068 SOCK_TOKEN *SockToken;
1069 SOCK_COMPLETION_TOKEN *SndToken;
1070
1071 ASSERT (!IsListEmpty (&Sock->ProcessingSndTokenList));
1072 ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize);
1073
1074 NetbufQueTrim (Sock->SndBuffer.DataQueue, Count);
1075
1076 //
1077 // To check if we can signal some snd token in this socket
1078 //
1079 while (Count > 0) {
1080 SockToken = NET_LIST_HEAD (
1081 &(Sock->ProcessingSndTokenList),
1082 SOCK_TOKEN,
1083 TokenList
1084 );
1085
1086 SndToken = SockToken->Token;
1087
1088 if (SockToken->RemainDataLen <= Count) {
1089
1090 RemoveEntryList (&(SockToken->TokenList));
1091 SIGNAL_TOKEN (SndToken, EFI_SUCCESS);
1092 Count -= SockToken->RemainDataLen;
1093 FreePool (SockToken);
1094 } else {
1095
1096 SockToken->RemainDataLen -= Count;
1097 Count = 0;
1098 }
1099 }
1100
1101 //
1102 // to judge if we can process some send token in
1103 // Sock->SndTokenList, if so process those send token
1104 //
1105 SockProcessSndToken (Sock);
1106}
1107
1108/**
1109 Called by the low layer protocol to copy some data in the socket send
1110 buffer starting from the specific offset to a buffer provided by
1111 the caller.
1112
1113 @param[in] Sock Pointer to the socket.
1114 @param[in] Offset The start point of the data to be copied.
1115 @param[in] Len The length of the data to be copied.
1116 @param[out] Dest Pointer to the destination to copy the data.
1117
1118 @return The data size copied.
1119
1120**/
1121UINT32
1122SockGetDataToSend (
1123 IN SOCKET *Sock,
1124 IN UINT32 Offset,
1125 IN UINT32 Len,
1126 OUT UINT8 *Dest
1127 )
1128{
1129 ASSERT ((Sock != NULL) && SockStream == Sock->Type);
1130
1131 return NetbufQueCopy (
1132 Sock->SndBuffer.DataQueue,
1133 Offset,
1134 Len,
1135 Dest
1136 );
1137}
1138
1139/**
1140 Called by the low layer protocol to deliver received data to socket layer.
1141
1142 This function will append the data to the socket receive buffer, set the
1143 urgent data length, and then check if any receive token can be signaled.
1144
1145 @param[in, out] Sock Pointer to the socket.
1146 @param[in, out] NetBuffer Pointer to the buffer that contains the received data.
1147 @param[in] UrgLen The length of the urgent data in the received data.
1148
1149**/
1150VOID
1151SockDataRcvd (
1152 IN OUT SOCKET *Sock,
1153 IN OUT NET_BUF *NetBuffer,
1154 IN UINT32 UrgLen
1155 )
1156{
1157 ASSERT ((Sock != NULL) && (Sock->RcvBuffer.DataQueue != NULL) &&
1158 UrgLen <= NetBuffer->TotalSize);
1159
1160 NET_GET_REF (NetBuffer);
1161
1162 ((TCP_RSV_DATA *) (NetBuffer->ProtoData))->UrgLen = UrgLen;
1163
1164 NetbufQueAppend (Sock->RcvBuffer.DataQueue, NetBuffer);
1165
1166 SockWakeRcvToken (Sock);
1167}
1168
1169/**
1170 Get the length of the free space of the specific socket buffer.
1171
1172 @param[in] Sock Pointer to the socket.
1173 @param[in] Which Flag to indicate which socket buffer to check:
1174 either send buffer or receive buffer.
1175
1176 @return The length of the free space, in bytes.
1177
1178**/
1179UINT32
1180SockGetFreeSpace (
1181 IN SOCKET *Sock,
1182 IN UINT32 Which
1183 )
1184{
1185 UINT32 BufferCC;
1186 SOCK_BUFFER *SockBuffer;
1187
1188 ASSERT (Sock != NULL && ((SOCK_SND_BUF == Which) || (SOCK_RCV_BUF == Which)));
1189
1190 if (SOCK_SND_BUF == Which) {
1191 SockBuffer = &(Sock->SndBuffer);
1192 } else {
1193 SockBuffer = &(Sock->RcvBuffer);
1194 }
1195
1196 BufferCC = (SockBuffer->DataQueue)->BufSize;
1197
1198 if (BufferCC >= SockBuffer->HighWater) {
1199
1200 return 0;
1201 }
1202
1203 return SockBuffer->HighWater - BufferCC;
1204}
1205
1206/**
1207 Called by the low layer protocol to indicate that there will be no more data
1208 from the communication peer.
1209
1210 This function sets the socket's state to SO_NO_MORE_DATA and signals all queued
1211 IO tokens with the error status EFI_CONNECTION_FIN.
1212
1213 @param[in, out] Sock Pointer to the socket.
1214
1215**/
1216VOID
1217SockNoMoreData (
1218 IN OUT SOCKET *Sock
1219 )
1220{
1221 EFI_STATUS Err;
1222
1223 SOCK_NO_MORE_DATA (Sock);
1224
1225 if (!IsListEmpty (&Sock->RcvTokenList)) {
1226
1227 ASSERT (0 == GET_RCV_DATASIZE (Sock));
1228
1229 Err = Sock->SockError;
1230
1231 SOCK_ERROR (Sock, EFI_CONNECTION_FIN);
1232
1233 SockFlushPendingToken (Sock, &Sock->RcvTokenList);
1234
1235 SOCK_ERROR (Sock, Err);
1236
1237 }
1238}
1239
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