]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockImpl.c
46c6ba492cbd7d3598dfde983a7a3d70d9dd372c
[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 SOCK_DEBUG_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 NET_LIST_ENTRY *PendingTokenList
320 )
321 {
322 SOCK_TOKEN *SockToken;
323 SOCK_COMPLETION_TOKEN *Token;
324
325 ASSERT (Sock && PendingTokenList);
326
327 while (!NetListIsEmpty (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 NetListRemoveEntry (&(SockToken->TokenList));
338 NetFreePool (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 (!NetListIsEmpty (&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 NetListRemoveEntry (&SockToken->TokenList);
408 NetFreePool (SockToken);
409
410 NetListRemoveEntry (&Sock->ConnectionList);
411
412 Parent->ConnCnt--;
413 SOCK_DEBUG_WARN (("SockWakeListenToken: accept a socket,"
414 "now conncnt is %d", Parent->ConnCnt));
415
416 Sock->Parent = NULL;
417 }
418 }
419
420
421 /**
422 Wake up the receive token while some data is received.
423
424 @param Sock Pointer to the socket.
425
426 @return None.
427
428 **/
429 STATIC
430 VOID
431 SockWakeRcvToken (
432 IN SOCKET *Sock
433 )
434 {
435 UINT32 RcvdBytes;
436 UINT32 TokenRcvdBytes;
437 SOCK_TOKEN *SockToken;
438 SOCK_IO_TOKEN *RcvToken;
439
440 ASSERT (Sock->RcvBuffer.DataQueue);
441
442 RcvdBytes = (Sock->RcvBuffer.DataQueue)->BufSize;
443
444 ASSERT (RcvdBytes > 0);
445
446 while (RcvdBytes > 0 && !NetListIsEmpty (&Sock->RcvTokenList)) {
447
448 SockToken = NET_LIST_HEAD (
449 &Sock->RcvTokenList,
450 SOCK_TOKEN,
451 TokenList
452 );
453
454 RcvToken = (SOCK_IO_TOKEN *) SockToken->Token;
455 TokenRcvdBytes = SockProcessRcvToken (Sock, RcvToken);
456
457 if (0 == TokenRcvdBytes) {
458 return ;
459 }
460
461 NetListRemoveEntry (&(SockToken->TokenList));
462 NetFreePool (SockToken);
463 RcvdBytes -= TokenRcvdBytes;
464 }
465 }
466
467
468 /**
469 Process the send token.
470
471 @param Sock Pointer to the socket.
472
473 @return None.
474
475 **/
476 STATIC
477 VOID
478 SockProcessSndToken (
479 IN SOCKET *Sock
480 )
481 {
482 UINT32 FreeSpace;
483 SOCK_TOKEN *SockToken;
484 UINT32 DataLen;
485 SOCK_IO_TOKEN *SndToken;
486 EFI_TCP4_TRANSMIT_DATA *TxData;
487 EFI_STATUS Status;
488
489 ASSERT (Sock && (SOCK_STREAM == Sock->Type));
490
491 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
492
493 //
494 // to determine if process a send token using
495 // socket layer flow control policy
496 //
497 while ((FreeSpace >= Sock->SndBuffer.LowWater) &&
498 !NetListIsEmpty (&Sock->SndTokenList)) {
499
500 SockToken = NET_LIST_HEAD (
501 &(Sock->SndTokenList),
502 SOCK_TOKEN,
503 TokenList
504 );
505
506 //
507 // process this token
508 //
509 NetListRemoveEntry (&(SockToken->TokenList));
510 NetListInsertTail (
511 &(Sock->ProcessingSndTokenList),
512 &(SockToken->TokenList)
513 );
514
515 //
516 // Proceess it in the light of SockType
517 //
518 SndToken = (SOCK_IO_TOKEN *) SockToken->Token;
519 TxData = SndToken->Packet.TxData;
520
521 DataLen = (UINT32) TxData->DataLength;
522 Status = SockProcessTcpSndData (Sock, TxData);
523
524 if (EFI_ERROR (Status)) {
525 goto OnError;
526 }
527
528 if (DataLen >= FreeSpace) {
529 FreeSpace = 0;
530
531 } else {
532 FreeSpace -= DataLen;
533
534 }
535 }
536
537 return ;
538
539 OnError:
540
541 NetListRemoveEntry (&SockToken->TokenList);
542 SIGNAL_TOKEN (SockToken->Token, Status);
543 NetFreePool (SockToken);
544 }
545
546
547 /**
548 Create a socket with initial data SockInitData.
549
550 @param SockInitData Pointer to the initial data of the socket.
551
552 @return Pointer to the newly created socket.
553
554 **/
555 SOCKET *
556 SockCreate (
557 IN SOCK_INIT_DATA *SockInitData
558 )
559 {
560 SOCKET *Sock;
561 SOCKET *Parent;
562 EFI_STATUS Status;
563
564 ASSERT (SockInitData && SockInitData->ProtoHandler);
565 ASSERT (SockInitData->Type == SOCK_STREAM);
566 ASSERT (SockInitData->ProtoData && (SockInitData->DataSize <= PROTO_RESERVED_LEN));
567
568 Parent = SockInitData->Parent;
569
570 if (Parent && (Parent->ConnCnt == Parent->BackLog)) {
571 SOCK_DEBUG_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 = NetAllocateZeroPool (sizeof (SOCKET));
582 if (NULL == Sock) {
583
584 SOCK_DEBUG_ERROR (("SockCreate: No resource to create a new socket\n"));
585 return NULL;
586 }
587
588 NetListInit (&Sock->Link);
589 NetListInit (&Sock->ConnectionList);
590 NetListInit (&Sock->ListenTokenList);
591 NetListInit (&Sock->RcvTokenList);
592 NetListInit (&Sock->SndTokenList);
593 NetListInit (&Sock->ProcessingSndTokenList);
594
595 NET_LOCK_INIT (&(Sock->Lock));
596
597 Sock->SndBuffer.DataQueue = NetbufQueAlloc ();
598 if (NULL == Sock->SndBuffer.DataQueue) {
599 SOCK_DEBUG_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 SOCK_DEBUG_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 NetCopyMem (
635 &(Sock->NetProtocol.TcpProtocol),
636 SockInitData->Protocol,
637 sizeof (EFI_TCP4_PROTOCOL)
638 );
639
640 //
641 // copy the protodata into socket
642 //
643 NetCopyMem (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 SOCK_DEBUG_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 SOCK_DEBUG_WARN (("SockCreate: Create a new socket and"
670 "add to parent, now conncnt is %d\n", Parent->ConnCnt));
671
672 NetListInsertTail (&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 NetFreePool (Sock);
704
705 return NULL;
706 }
707
708
709 /**
710 Destroy a socket.
711
712 @param Sock Pointer to the socket.
713
714 @return None.
715
716 **/
717 VOID
718 SockDestroy (
719 IN SOCKET *Sock
720 )
721 {
722 VOID *SockProtocol;
723 EFI_GUID *ProtocolGuid;
724 EFI_STATUS Status;
725
726 ASSERT (SOCK_STREAM == Sock->Type);
727
728 if (Sock->DestroyCallback != NULL) {
729 Sock->DestroyCallback (Sock, Sock->Context);
730 }
731
732 //
733 // Flush the completion token buffered
734 // by sock and rcv, snd buffer
735 //
736 if (!SOCK_IS_UNCONFIGURED (Sock)) {
737
738 SockConnFlush (Sock);
739 SockSetState (Sock, SO_CLOSED);
740 Sock->ConfigureState = SO_UNCONFIGURED;
741
742 }
743 //
744 // Destory the RcvBuffer Queue and SendBuffer Queue
745 //
746 NetbufQueFree (Sock->RcvBuffer.DataQueue);
747 NetbufQueFree (Sock->SndBuffer.DataQueue);
748
749 //
750 // Remove it from parent connection list if needed
751 //
752 if (Sock->Parent) {
753
754 NetListRemoveEntry (&(Sock->ConnectionList));
755 (Sock->Parent->ConnCnt)--;
756
757 SOCK_DEBUG_WARN (("SockDestory: Delete a unaccepted socket from parent"
758 "now conncnt is %d\n", Sock->Parent->ConnCnt));
759
760 Sock->Parent = NULL;
761 }
762
763 //
764 // Set the protocol guid and driver binding handle
765 // in the light of Sock->SockType
766 //
767 ProtocolGuid = &gEfiTcp4ProtocolGuid;
768
769 //
770 // Retrieve the protocol installed on this sock
771 //
772 Status = gBS->OpenProtocol (
773 Sock->SockHandle,
774 ProtocolGuid,
775 &SockProtocol,
776 Sock->DriverBinding,
777 Sock->SockHandle,
778 EFI_OPEN_PROTOCOL_GET_PROTOCOL
779 );
780
781 if (EFI_ERROR (Status)) {
782
783 SOCK_DEBUG_ERROR (("SockDestroy: Open protocol installed "
784 "on socket failed with %r\n", Status));
785
786 goto FreeSock;
787 }
788
789 //
790 // Uninstall the protocol installed on this sock
791 // in the light of Sock->SockType
792 //
793 gBS->UninstallMultipleProtocolInterfaces (
794 Sock->SockHandle,
795 ProtocolGuid,
796 SockProtocol,
797 NULL
798 );
799
800 FreeSock:
801 NetFreePool (Sock);
802 return ;
803 }
804
805
806 /**
807 Flush the socket.
808
809 @param Sock Pointer to the socket.
810
811 @return None.
812
813 **/
814 VOID
815 SockConnFlush (
816 IN SOCKET *Sock
817 )
818 {
819 SOCKET *Child;
820
821 ASSERT (Sock);
822
823 //
824 // Clear the flag in this socket
825 //
826 Sock->Flag = 0;
827
828 //
829 // Flush the SndBuffer and RcvBuffer of Sock
830 //
831 NetbufQueFlush (Sock->SndBuffer.DataQueue);
832 NetbufQueFlush (Sock->RcvBuffer.DataQueue);
833
834 //
835 // Signal the pending token
836 //
837 if (Sock->ConnectionToken != NULL) {
838 SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError);
839 Sock->ConnectionToken = NULL;
840 }
841
842 if (Sock->CloseToken != NULL) {
843 SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError);
844 Sock->CloseToken = NULL;
845 }
846
847 SockFlushPendingToken (Sock, &(Sock->ListenTokenList));
848 SockFlushPendingToken (Sock, &(Sock->RcvTokenList));
849 SockFlushPendingToken (Sock, &(Sock->SndTokenList));
850 SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList));
851
852 //
853 // Destroy the pending connection, if it is a listening socket
854 //
855 if (SOCK_IS_LISTENING (Sock)) {
856 while (!NetListIsEmpty (&Sock->ConnectionList)) {
857 Child = NET_LIST_HEAD (
858 &Sock->ConnectionList,
859 SOCKET,
860 ConnectionList
861 );
862
863 SockDestroyChild (Child);
864 }
865
866 Sock->ConnCnt = 0;
867 }
868
869 return ;
870 }
871
872
873 /**
874 Set the state of the socket.
875
876 @param Sock Pointer to the socket.
877 @param State The new state to be set.
878
879 @return None.
880
881 **/
882 VOID
883 SockSetState (
884 IN SOCKET *Sock,
885 IN SOCK_STATE State
886 )
887 {
888 Sock->State = State;
889 }
890
891
892 /**
893 Clone a new socket including its associated protocol control block.
894
895 @param Sock Pointer to the socket to be cloned.
896
897 @retval * Pointer to the newly cloned socket. If NULL, error
898 condition occurred.
899
900 **/
901 SOCKET *
902 SockClone (
903 IN SOCKET *Sock
904 )
905 {
906 SOCKET *ClonedSock;
907 SOCK_INIT_DATA InitData;
908
909 InitData.BackLog = Sock->BackLog;
910 InitData.Parent = Sock;
911 InitData.State = Sock->State;
912 InitData.ProtoHandler = Sock->ProtoHandler;
913 InitData.Type = Sock->Type;
914 InitData.RcvBufferSize = Sock->RcvBuffer.HighWater;
915 InitData.SndBufferSize = Sock->SndBuffer.HighWater;
916 InitData.DriverBinding = Sock->DriverBinding;
917 InitData.Protocol = &(Sock->NetProtocol);
918 InitData.CreateCallback = Sock->CreateCallback;
919 InitData.DestroyCallback = Sock->DestroyCallback;
920 InitData.Context = Sock->Context;
921 InitData.ProtoData = Sock->ProtoReserved;
922 InitData.DataSize = sizeof (Sock->ProtoReserved);
923
924 ClonedSock = SockCreate (&InitData);
925
926 if (NULL == ClonedSock) {
927 SOCK_DEBUG_ERROR (("SockClone: no resource to create a cloned sock\n"));
928 return NULL;
929 }
930
931 SockSetState (ClonedSock, SO_CONNECTING);
932 ClonedSock->ConfigureState = Sock->ConfigureState;
933
934 return ClonedSock;
935 }
936
937
938 /**
939 Called by the low layer protocol to indicate the socket
940 a connection is established. This function just changes
941 the socket's state to SO_CONNECTED and signals the token
942 used for connection establishment.
943
944 @param Sock Pointer to the socket associated with the
945 established connection.
946
947 @return None.
948
949 **/
950 VOID
951 SockConnEstablished (
952 IN SOCKET *Sock
953 )
954 {
955
956 ASSERT (SO_CONNECTING == Sock->State);
957
958 SockSetState (Sock, SO_CONNECTED);
959
960 if (NULL == Sock->Parent) {
961 SockWakeConnToken (Sock);
962 } else {
963 SockWakeListenToken (Sock);
964 }
965
966 return ;
967 }
968
969
970 /**
971 Called by the low layer protocol to indicate the connection
972 is closed. This function flushes the socket, sets the state
973 to SO_CLOSED and signals the close token.
974
975 @param Sock Pointer to the socket associated with the closed
976 connection.
977
978 @return None.
979
980 **/
981 VOID
982 SockConnClosed (
983 IN SOCKET *Sock
984 )
985 {
986 if (Sock->CloseToken) {
987 SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS);
988 Sock->CloseToken = NULL;
989 }
990
991 SockConnFlush (Sock);
992 SockSetState (Sock, SO_CLOSED);
993
994 if (Sock->Parent != NULL) {
995 SockDestroyChild (Sock);
996 }
997
998 }
999
1000
1001 /**
1002 Called by low layer protocol to indicate that some
1003 data is sent or processed. This function trims the
1004 sent data in the socket send buffer, signals the
1005 data token if proper
1006
1007 @param Sock Pointer to the socket.
1008 @param Count The length of the data processed or sent, in bytes.
1009
1010 @return None.
1011
1012 **/
1013 VOID
1014 SockDataSent (
1015 IN SOCKET *Sock,
1016 IN UINT32 Count
1017 )
1018 {
1019 SOCK_TOKEN *SockToken;
1020 SOCK_COMPLETION_TOKEN *SndToken;
1021
1022 ASSERT (!NetListIsEmpty (&Sock->ProcessingSndTokenList));
1023 ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize);
1024
1025 NetbufQueTrim (Sock->SndBuffer.DataQueue, Count);
1026
1027 //
1028 // To check if we can signal some snd token in this socket
1029 //
1030 while (Count > 0) {
1031 SockToken = NET_LIST_HEAD (
1032 &(Sock->ProcessingSndTokenList),
1033 SOCK_TOKEN,
1034 TokenList
1035 );
1036
1037 SndToken = SockToken->Token;
1038
1039 if (SockToken->RemainDataLen <= Count) {
1040
1041 NetListRemoveEntry (&(SockToken->TokenList));
1042 SIGNAL_TOKEN (SndToken, EFI_SUCCESS);
1043 Count -= SockToken->RemainDataLen;
1044 NetFreePool (SockToken);
1045 } else {
1046
1047 SockToken->RemainDataLen -= Count;
1048 Count = 0;
1049 }
1050 }
1051
1052 //
1053 // to judge if we can process some send token in
1054 // Sock->SndTokenList, if so process those send token
1055 //
1056 SockProcessSndToken (Sock);
1057 return ;
1058 }
1059
1060
1061 /**
1062 Called by the low layer protocol to copy some data in socket send
1063 buffer starting from the specific offset to a buffer provided by
1064 the caller.
1065
1066 @param Sock Pointer to the socket.
1067 @param Offset The start point of the data to be copied.
1068 @param Len The length of the data to be copied.
1069 @param Dest Pointer to the destination to copy the data.
1070
1071 @return The data size copied.
1072
1073 **/
1074 UINT32
1075 SockGetDataToSend (
1076 IN SOCKET *Sock,
1077 IN UINT32 Offset,
1078 IN UINT32 Len,
1079 IN UINT8 *Dest
1080 )
1081 {
1082 ASSERT (Sock && SOCK_STREAM == Sock->Type);
1083
1084 return NetbufQueCopy (
1085 Sock->SndBuffer.DataQueue,
1086 Offset,
1087 Len,
1088 Dest
1089 );
1090 }
1091
1092
1093 /**
1094 Called by the low layer protocol to deliver received data
1095 to socket layer. This function will append the data to the
1096 socket receive buffer, set ther urgent data length and then
1097 check if any receive token can be signaled.
1098
1099 @param Sock Pointer to the socket.
1100 @param NetBuffer Pointer to the buffer that contains the received
1101 data.
1102 @param UrgLen The length of the urgent data in the received data.
1103
1104 @return None.
1105
1106 **/
1107 VOID
1108 SockDataRcvd (
1109 IN SOCKET *Sock,
1110 IN NET_BUF *NetBuffer,
1111 IN UINT32 UrgLen
1112 )
1113 {
1114 ASSERT (Sock && Sock->RcvBuffer.DataQueue &&
1115 UrgLen <= NetBuffer->TotalSize);
1116
1117 NET_GET_REF (NetBuffer);
1118
1119 ((TCP_RSV_DATA *) (NetBuffer->ProtoData))->UrgLen = UrgLen;
1120
1121 NetbufQueAppend (Sock->RcvBuffer.DataQueue, NetBuffer);
1122
1123 SockWakeRcvToken (Sock);
1124 return ;
1125 }
1126
1127
1128 /**
1129 Get the length of the free space of the specific socket buffer.
1130
1131 @param Sock Pointer to the socket.
1132 @param Which Flag to indicate which socket buffer to check,
1133 either send buffer or receive buffer.
1134
1135 @return The length of the free space, in bytes.
1136
1137 **/
1138 UINT32
1139 SockGetFreeSpace (
1140 IN SOCKET *Sock,
1141 IN UINT32 Which
1142 )
1143 {
1144 UINT32 BufferCC;
1145 SOCK_BUFFER *SockBuffer;
1146
1147 ASSERT (Sock && ((SOCK_SND_BUF == Which) || (SOCK_RCV_BUF == Which)));
1148
1149 if (SOCK_SND_BUF == Which) {
1150 SockBuffer = &(Sock->SndBuffer);
1151 } else {
1152 SockBuffer = &(Sock->RcvBuffer);
1153 }
1154
1155 BufferCC = (SockBuffer->DataQueue)->BufSize;
1156
1157 if (BufferCC >= SockBuffer->HighWater) {
1158
1159 return 0;
1160 }
1161
1162 return SockBuffer->HighWater - BufferCC;
1163 }
1164
1165
1166 /**
1167 Signal the receive token with the specific error or
1168 set socket error code after error is received.
1169
1170 @param Sock Pointer to the socket.
1171 @param Error The error code received.
1172
1173 @return None.
1174
1175 **/
1176 VOID
1177 SockRcvdErr (
1178 IN SOCKET *Sock,
1179 IN EFI_STATUS Error
1180 )
1181 {
1182 SOCK_TOKEN *SockToken;
1183
1184 if (!NetListIsEmpty (&Sock->RcvTokenList)) {
1185
1186 SockToken = NET_LIST_HEAD (
1187 &Sock->RcvTokenList,
1188 SOCK_TOKEN,
1189 TokenList
1190 );
1191
1192 NetListRemoveEntry (&SockToken->TokenList);
1193
1194 SIGNAL_TOKEN (SockToken->Token, Error);
1195
1196 NetFreePool (SockToken);
1197 } else {
1198
1199 SOCK_ERROR (Sock, Error);
1200 }
1201 }
1202
1203
1204 /**
1205 Called by the low layer protocol to indicate that there
1206 will be no more data from the communication peer. This
1207 function set the socket's state to SO_NO_MORE_DATA and
1208 signal all queued IO tokens with the error status
1209 EFI_CONNECTION_FIN.
1210
1211 @param Sock Pointer to the socket.
1212
1213 @return None.
1214
1215 **/
1216 VOID
1217 SockNoMoreData (
1218 IN SOCKET *Sock
1219 )
1220 {
1221 EFI_STATUS Err;
1222
1223 SOCK_NO_MORE_DATA (Sock);
1224
1225 if (!NetListIsEmpty (&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 }
1240
1241
1242 /**
1243 Get the first buffer block in the specific socket buffer.
1244
1245 @param Sockbuf Pointer to the socket buffer.
1246
1247 @return Pointer to the first buffer in the queue. NULL if the queue is empty.
1248
1249 **/
1250 NET_BUF *
1251 SockBufFirst (
1252 IN SOCK_BUFFER *Sockbuf
1253 )
1254 {
1255 NET_LIST_ENTRY *NetbufList;
1256
1257 NetbufList = &(Sockbuf->DataQueue->BufList);
1258
1259 if (NetListIsEmpty (NetbufList)) {
1260 return NULL;
1261 }
1262
1263 return NET_LIST_HEAD (NetbufList, NET_BUF, List);
1264 }
1265
1266
1267 /**
1268 Get the next buffer block in the specific socket buffer.
1269
1270 @param Sockbuf Pointer to the socket buffer.
1271 @param SockEntry Pointer to the buffer block prior to the required
1272 one.
1273
1274 @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is the tail or head entry.
1275
1276 **/
1277 NET_BUF *
1278 SockBufNext (
1279 IN SOCK_BUFFER *Sockbuf,
1280 IN NET_BUF *SockEntry
1281 )
1282 {
1283 NET_LIST_ENTRY *NetbufList;
1284
1285 NetbufList = &(Sockbuf->DataQueue->BufList);
1286
1287 if ((SockEntry->List.ForwardLink == NetbufList) ||
1288 (SockEntry->List.BackLink == &SockEntry->List) ||
1289 (SockEntry->List.ForwardLink == &SockEntry->List)
1290 ) {
1291
1292 return NULL;
1293 }
1294
1295 return NET_LIST_USER_STRUCT (SockEntry->List.ForwardLink, NET_BUF, List);
1296 }