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