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