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