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