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