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