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