]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockImpl.c
update file header
[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 /**
24 Get the length of the data that can be retrieved from the socket
25 receive buffer.
26
27 @param SockBuffer Pointer to the socket receive buffer.
28 @param IsUrg Pointer to a BOOLEAN variable. If TRUE the data is
29 OOB.
30 @param BufLen The maximum length of the data buffer to store the
31 received data in socket layer.
32
33 @return The length of the data can be retreived.
34
35 **/
36 UINT32
37 SockTcpDataToRcv (
38 IN SOCK_BUFFER *SockBuffer,
39 OUT BOOLEAN *IsOOB,
40 IN UINT32 BufLen
41 );
42
43 /**
44 Process the send token.
45
46 @param Sock Pointer to the socket.
47
48 **/
49 VOID
50 SockProcessSndToken (
51 IN SOCKET *Sock
52 );
53
54 /**
55
56
57 **/
58 VOID
59 SockFreeFoo (
60 IN EFI_EVENT Event
61 )
62 {
63 return ;
64 }
65
66
67 /**
68 Get the length of the data that can be retrieved from the socket
69 receive buffer.
70
71 @param SockBuffer Pointer to the socket receive buffer.
72 @param IsUrg Pointer to a BOOLEAN variable. If TRUE the data is
73 OOB.
74 @param BufLen The maximum length of the data buffer to store the
75 received data in socket layer.
76
77 @return The length of the data can be retreived.
78
79 **/
80 UINT32
81 SockTcpDataToRcv (
82 IN SOCK_BUFFER *SockBuffer,
83 OUT BOOLEAN *IsUrg,
84 IN UINT32 BufLen
85 )
86 {
87 NET_BUF *RcvBufEntry;
88 UINT32 DataLen;
89 TCP_RSV_DATA *TcpRsvData;
90 BOOLEAN Urg;
91
92 ASSERT ((SockBuffer != NULL) && (IsUrg != NULL) && (BufLen > 0));
93
94 RcvBufEntry = SockBufFirst (SockBuffer);
95 ASSERT (RcvBufEntry != NULL);
96
97 TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;
98
99 *IsUrg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);
100
101 if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) {
102
103 DataLen = MIN (TcpRsvData->UrgLen, BufLen);
104
105 if (DataLen < TcpRsvData->UrgLen) {
106 TcpRsvData->UrgLen = TcpRsvData->UrgLen - DataLen;
107 } else {
108 TcpRsvData->UrgLen = 0;
109 }
110
111 return DataLen;
112
113 }
114
115 DataLen = RcvBufEntry->TotalSize;
116
117 RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);
118
119 while ((BufLen > DataLen) && (RcvBufEntry != NULL)) {
120
121 TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;
122
123 Urg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);
124
125 if (*IsUrg != Urg) {
126 break;
127 }
128
129 if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) {
130
131 if (TcpRsvData->UrgLen + DataLen < BufLen) {
132 TcpRsvData->UrgLen = 0;
133 } else {
134 TcpRsvData->UrgLen = TcpRsvData->UrgLen - (BufLen - DataLen);
135 }
136
137 return MIN (TcpRsvData->UrgLen + DataLen, BufLen);
138
139 }
140
141 DataLen += RcvBufEntry->TotalSize;
142
143 RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);
144 }
145
146 DataLen = MIN (BufLen, DataLen);
147 return DataLen;
148 }
149
150
151 /**
152 Copy data from socket buffer to application provided receive buffer.
153
154 @param Sock Pointer to the socket.
155 @param TcpRxData Pointer to the application provided receive buffer.
156 @param RcvdBytes The maximum length of the data can be copied.
157 @param IsOOB If TURE the data is OOB, else the data is normal.
158
159 **/
160 VOID
161 SockSetTcpRxData (
162 IN SOCKET *Sock,
163 IN VOID *TcpRxData,
164 IN UINT32 RcvdBytes,
165 IN BOOLEAN IsOOB
166 )
167 {
168 UINT32 Index;
169 UINT32 CopyBytes;
170 UINT32 OffSet;
171 EFI_TCP4_RECEIVE_DATA *RxData;
172 EFI_TCP4_FRAGMENT_DATA *Fragment;
173
174 RxData = (EFI_TCP4_RECEIVE_DATA *) TcpRxData;
175
176 OffSet = 0;
177
178 ASSERT (RxData->DataLength >= RcvdBytes);
179
180 RxData->DataLength = RcvdBytes;
181 RxData->UrgentFlag = IsOOB;
182
183 for (Index = 0; (Index < RxData->FragmentCount) && (RcvdBytes > 0); Index++) {
184
185 Fragment = &RxData->FragmentTable[Index];
186 CopyBytes = MIN ((UINT32) (Fragment->FragmentLength), RcvdBytes);
187
188 NetbufQueCopy (
189 Sock->RcvBuffer.DataQueue,
190 OffSet,
191 CopyBytes,
192 Fragment->FragmentBuffer
193 );
194
195 Fragment->FragmentLength = CopyBytes;
196 RcvdBytes -= CopyBytes;
197 OffSet += CopyBytes;
198 }
199 }
200
201
202 /**
203 Get received data from the socket layer to the receive token.
204
205 @param Sock Pointer to the socket.
206 @param RcvToken Pointer to the application provided receive token.
207
208 @return The length of data received in this token.
209
210 **/
211 UINT32
212 SockProcessRcvToken (
213 IN SOCKET *Sock,
214 IN SOCK_IO_TOKEN *RcvToken
215 )
216 {
217 UINT32 TokenRcvdBytes;
218 EFI_TCP4_RECEIVE_DATA *RxData;
219 BOOLEAN IsUrg;
220
221 ASSERT (Sock != NULL);
222
223 ASSERT (SOCK_STREAM == Sock->Type);
224
225 RxData = RcvToken->Packet.RxData;
226
227 TokenRcvdBytes = SockTcpDataToRcv (
228 &Sock->RcvBuffer,
229 &IsUrg,
230 (UINT32) RxData->DataLength
231 );
232
233 //
234 // Copy data from RcvBuffer of socket to user
235 // provided RxData and set the fields in TCP RxData
236 //
237 SockSetTcpRxData (Sock, RxData, TokenRcvdBytes, IsUrg);
238
239 SOCK_TRIM_RCV_BUFF (Sock, TokenRcvdBytes);
240 SIGNAL_TOKEN (&(RcvToken->Token), EFI_SUCCESS);
241
242 return TokenRcvdBytes;
243 }
244
245
246 /**
247 Process the TCP send data, buffer the tcp txdata and append
248 the buffer to socket send buffer,then try to send it.
249
250 @param Sock Pointer to the socket.
251 @param TcpTxData Pointer to the tcp txdata.
252
253 @retval EFI_SUCCESS The operation is completed successfully.
254 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
255
256 **/
257 EFI_STATUS
258 SockProcessTcpSndData (
259 IN SOCKET *Sock,
260 IN VOID *TcpTxData
261 )
262 {
263 NET_BUF *SndData;
264 EFI_STATUS Status;
265 EFI_TCP4_TRANSMIT_DATA *TxData;
266
267 TxData = (EFI_TCP4_TRANSMIT_DATA *) TcpTxData;
268
269 //
270 // transform this TxData into a NET_BUFFER
271 // and insert it into Sock->SndBuffer
272 //
273 SndData = NetbufFromExt (
274 (NET_FRAGMENT *) TxData->FragmentTable,
275 (UINT32) TxData->FragmentCount,
276 0,
277 0,
278 SockFreeFoo,
279 NULL
280 );
281
282 if (NULL == SndData) {
283 DEBUG ((EFI_D_ERROR, "SockKProcessSndData: Failed to"
284 " call NetBufferFromExt\n"));
285
286 return EFI_OUT_OF_RESOURCES;
287 }
288
289 NetbufQueAppend (Sock->SndBuffer.DataQueue, SndData);
290
291 //
292 // notify the low layer protocol to handle this send token
293 //
294 if (TxData->Urgent) {
295 Status = Sock->ProtoHandler (Sock, SOCK_SNDURG, NULL);
296
297 if (EFI_ERROR (Status)) {
298 return Status;
299 }
300 }
301
302 if (TxData->Push) {
303 Status = Sock->ProtoHandler (Sock, SOCK_SNDPUSH, NULL);
304
305 if (EFI_ERROR (Status)) {
306 return Status;
307 }
308 }
309
310 //
311 // low layer protocol should really handle the sending
312 // process when catching SOCK_SND request
313 //
314 Status = Sock->ProtoHandler (Sock, SOCK_SND, NULL);
315
316 if (EFI_ERROR (Status)) {
317 return Status;
318 }
319
320 return EFI_SUCCESS;
321 }
322
323
324 /**
325 Flush the tokens in the specific token list.
326
327 @param Sock Pointer to the socket.
328 @param PendingTokenList Pointer to the token list to be flushed.
329
330 **/
331 VOID
332 SockFlushPendingToken (
333 IN SOCKET *Sock,
334 IN LIST_ENTRY *PendingTokenList
335 )
336 {
337 SOCK_TOKEN *SockToken;
338 SOCK_COMPLETION_TOKEN *Token;
339
340 ASSERT ((Sock != NULL) && (PendingTokenList != NULL));
341
342 while (!IsListEmpty (PendingTokenList)) {
343 SockToken = NET_LIST_HEAD (
344 PendingTokenList,
345 SOCK_TOKEN,
346 TokenList
347 );
348
349 Token = SockToken->Token;
350 SIGNAL_TOKEN (Token, Sock->SockError);
351
352 RemoveEntryList (&(SockToken->TokenList));
353 gBS->FreePool (SockToken);
354 }
355 }
356
357
358 /**
359 Wake up the connection token while the connection is successfully established,
360 then try to process any pending send token.
361
362 @param Sock Pointer to the socket.
363
364 **/
365 VOID
366 SockWakeConnToken (
367 IN SOCKET *Sock
368 )
369 {
370 ASSERT (Sock->ConnectionToken != NULL);
371
372 SIGNAL_TOKEN (Sock->ConnectionToken, EFI_SUCCESS);
373 Sock->ConnectionToken = NULL;
374
375 //
376 // check to see if some pending send token existed?
377 //
378 SockProcessSndToken (Sock);
379 return ;
380 }
381
382
383 /**
384 Wake up the listen token while the connection is established successfully.
385
386 @param Sock Pointer to the socket.
387
388 **/
389 VOID
390 SockWakeListenToken (
391 IN SOCKET *Sock
392 )
393 {
394 SOCKET *Parent;
395 SOCK_TOKEN *SockToken;
396 EFI_TCP4_LISTEN_TOKEN *ListenToken;
397
398 Parent = Sock->Parent;
399
400 ASSERT ((Parent != NULL) && SOCK_IS_LISTENING (Parent) && SOCK_IS_CONNECTED (Sock));
401
402 if (!IsListEmpty (&Parent->ListenTokenList)) {
403 SockToken = NET_LIST_HEAD (
404 &Parent->ListenTokenList,
405 SOCK_TOKEN,
406 TokenList
407 );
408
409 ListenToken = (EFI_TCP4_LISTEN_TOKEN *) SockToken->Token;
410 ListenToken->NewChildHandle = Sock->SockHandle;
411
412 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
413
414 RemoveEntryList (&SockToken->TokenList);
415 gBS->FreePool (SockToken);
416
417 RemoveEntryList (&Sock->ConnectionList);
418
419 Parent->ConnCnt--;
420 DEBUG ((EFI_D_WARN, "SockWakeListenToken: accept a socket, now conncnt is %d", Parent->ConnCnt));
421
422 Sock->Parent = NULL;
423 }
424 }
425
426
427 /**
428 Wake up the receive token while some data is received.
429
430 @param Sock Pointer to the socket.
431
432 **/
433 VOID
434 SockWakeRcvToken (
435 IN SOCKET *Sock
436 )
437 {
438 UINT32 RcvdBytes;
439 UINT32 TokenRcvdBytes;
440 SOCK_TOKEN *SockToken;
441 SOCK_IO_TOKEN *RcvToken;
442
443 ASSERT (Sock->RcvBuffer.DataQueue != NULL);
444
445 RcvdBytes = (Sock->RcvBuffer.DataQueue)->BufSize;
446
447 ASSERT (RcvdBytes > 0);
448
449 while (RcvdBytes > 0 && !IsListEmpty (&Sock->RcvTokenList)) {
450
451 SockToken = NET_LIST_HEAD (
452 &Sock->RcvTokenList,
453 SOCK_TOKEN,
454 TokenList
455 );
456
457 RcvToken = (SOCK_IO_TOKEN *) SockToken->Token;
458 TokenRcvdBytes = SockProcessRcvToken (Sock, RcvToken);
459
460 if (0 == TokenRcvdBytes) {
461 return ;
462 }
463
464 RemoveEntryList (&(SockToken->TokenList));
465 gBS->FreePool (SockToken);
466 RcvdBytes -= TokenRcvdBytes;
467 }
468 }
469
470
471 /**
472 Process the send token.
473
474 @param Sock Pointer to the socket.
475
476 **/
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 != NULL) && (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 !IsListEmpty (&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 RemoveEntryList (&(SockToken->TokenList));
510 InsertTailList (
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 RemoveEntryList (&SockToken->TokenList);
542 SIGNAL_TOKEN (SockToken->Token, Status);
543 gBS->FreePool (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 != NULL) && (SockInitData->ProtoHandler != NULL));
565 ASSERT (SockInitData->Type == SOCK_STREAM);
566 ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN));
567
568 Parent = SockInitData->Parent;
569
570 if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) {
571 DEBUG (
572 (EFI_D_ERROR,
573 "SockCreate: Socket parent has "
574 "reached its connection limit with %d ConnCnt and %d BackLog\n",
575 Parent->ConnCnt,
576 Parent->BackLog)
577 );
578
579 return NULL;
580 }
581
582 Sock = AllocateZeroPool (sizeof (SOCKET));
583 if (NULL == Sock) {
584
585 DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n"));
586 return NULL;
587 }
588
589 InitializeListHead (&Sock->Link);
590 InitializeListHead (&Sock->ConnectionList);
591 InitializeListHead (&Sock->ListenTokenList);
592 InitializeListHead (&Sock->RcvTokenList);
593 InitializeListHead (&Sock->SndTokenList);
594 InitializeListHead (&Sock->ProcessingSndTokenList);
595
596 EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK);
597
598 Sock->SndBuffer.DataQueue = NetbufQueAlloc ();
599 if (NULL == Sock->SndBuffer.DataQueue) {
600 DEBUG ((EFI_D_ERROR, "SockCreate: No resource to allocate"
601 " SndBuffer for new socket\n"));
602
603 goto OnError;
604 }
605
606 Sock->RcvBuffer.DataQueue = NetbufQueAlloc ();
607 if (NULL == Sock->RcvBuffer.DataQueue) {
608 DEBUG ((EFI_D_ERROR, "SockCreate: No resource to allocate "
609 "RcvBuffer for new socket\n"));
610
611 goto OnError;
612 }
613
614 Sock->Signature = SOCK_SIGNATURE;
615
616 Sock->Parent = Parent;
617 Sock->BackLog = SockInitData->BackLog;
618 Sock->ProtoHandler = SockInitData->ProtoHandler;
619 Sock->SndBuffer.HighWater = SockInitData->SndBufferSize;
620 Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize;
621 Sock->Type = SockInitData->Type;
622 Sock->DriverBinding = SockInitData->DriverBinding;
623 Sock->State = SockInitData->State;
624 Sock->CreateCallback = SockInitData->CreateCallback;
625 Sock->DestroyCallback = SockInitData->DestroyCallback;
626 Sock->Context = SockInitData->Context;
627
628 Sock->SockError = EFI_ABORTED;
629 Sock->SndBuffer.LowWater = SOCK_BUFF_LOW_WATER;
630 Sock->RcvBuffer.LowWater = SOCK_BUFF_LOW_WATER;
631
632 //
633 // Install protocol on Sock->SockHandle
634 //
635 CopyMem (
636 &(Sock->NetProtocol.TcpProtocol),
637 SockInitData->Protocol,
638 sizeof (EFI_TCP4_PROTOCOL)
639 );
640
641 //
642 // copy the protodata into socket
643 //
644 CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize);
645
646 Status = gBS->InstallMultipleProtocolInterfaces (
647 &Sock->SockHandle,
648 &gEfiTcp4ProtocolGuid,
649 &(Sock->NetProtocol.TcpProtocol),
650 NULL
651 );
652
653 if (EFI_ERROR (Status)) {
654 DEBUG ((EFI_D_ERROR, "SockCreate: Install TCP protocol in "
655 "socket failed with %r\n", Status));
656
657 goto OnError;
658 }
659
660 if (Parent != NULL) {
661 ASSERT (Parent->BackLog > 0);
662 ASSERT (SOCK_IS_LISTENING (Parent));
663
664 //
665 // need to add it into Parent->ConnectionList
666 // if the Parent->ConnCnt < Parent->BackLog
667 //
668 Parent->ConnCnt++;
669
670 DEBUG (
671 (EFI_D_WARN,
672 "SockCreate: Create a new socket and add to parent, now conncnt is %d\n",
673 Parent->ConnCnt)
674 );
675
676 InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList);
677 }
678
679 if (Sock->CreateCallback != NULL) {
680 Status = Sock->CreateCallback (Sock, Sock->Context);
681 if (EFI_ERROR (Status)) {
682 goto OnError;
683 }
684 }
685
686 return Sock;
687
688 OnError:
689
690 if (Sock->SockHandle != NULL) {
691 gBS->UninstallMultipleProtocolInterfaces (
692 Sock->SockHandle,
693 &gEfiTcp4ProtocolGuid,
694 &(Sock->NetProtocol.TcpProtocol),
695 NULL
696 );
697 }
698
699 if (NULL != Sock->SndBuffer.DataQueue) {
700 NetbufQueFree (Sock->SndBuffer.DataQueue);
701 }
702
703 if (NULL != Sock->RcvBuffer.DataQueue) {
704 NetbufQueFree (Sock->RcvBuffer.DataQueue);
705 }
706
707 gBS->FreePool (Sock);
708
709 return NULL;
710 }
711
712
713 /**
714 Destroy a socket.
715
716 @param Sock Pointer to the socket.
717
718 **/
719 VOID
720 SockDestroy (
721 IN SOCKET *Sock
722 )
723 {
724 VOID *SockProtocol;
725 EFI_GUID *ProtocolGuid;
726 EFI_STATUS Status;
727
728 ASSERT (SOCK_STREAM == Sock->Type);
729
730 if (Sock->DestroyCallback != NULL) {
731 Sock->DestroyCallback (Sock, Sock->Context);
732 }
733
734 //
735 // Flush the completion token buffered
736 // by sock and rcv, snd buffer
737 //
738 if (!SOCK_IS_UNCONFIGURED (Sock)) {
739
740 SockConnFlush (Sock);
741 SockSetState (Sock, SO_CLOSED);
742 Sock->ConfigureState = SO_UNCONFIGURED;
743
744 }
745 //
746 // Destory the RcvBuffer Queue and SendBuffer Queue
747 //
748 NetbufQueFree (Sock->RcvBuffer.DataQueue);
749 NetbufQueFree (Sock->SndBuffer.DataQueue);
750
751 //
752 // Remove it from parent connection list if needed
753 //
754 if (Sock->Parent != NULL) {
755
756 RemoveEntryList (&(Sock->ConnectionList));
757 (Sock->Parent->ConnCnt)--;
758
759 DEBUG (
760 (EFI_D_WARN,
761 "SockDestory: Delete a unaccepted socket from parent"
762 "now conncnt is %d\n",
763 Sock->Parent->ConnCnt)
764 );
765
766 Sock->Parent = NULL;
767 }
768
769 //
770 // Set the protocol guid and driver binding handle
771 // in the light of Sock->SockType
772 //
773 ProtocolGuid = &gEfiTcp4ProtocolGuid;
774
775 //
776 // Retrieve the protocol installed on this sock
777 //
778 Status = gBS->OpenProtocol (
779 Sock->SockHandle,
780 ProtocolGuid,
781 &SockProtocol,
782 Sock->DriverBinding,
783 Sock->SockHandle,
784 EFI_OPEN_PROTOCOL_GET_PROTOCOL
785 );
786
787 if (EFI_ERROR (Status)) {
788
789 DEBUG ((EFI_D_ERROR, "SockDestroy: Open protocol installed "
790 "on socket failed with %r\n", Status));
791
792 goto FreeSock;
793 }
794
795 //
796 // Uninstall the protocol installed on this sock
797 // in the light of Sock->SockType
798 //
799 gBS->UninstallMultipleProtocolInterfaces (
800 Sock->SockHandle,
801 ProtocolGuid,
802 SockProtocol,
803 NULL
804 );
805
806 FreeSock:
807 gBS->FreePool (Sock);
808 return ;
809 }
810
811
812 /**
813 Flush the socket.
814
815 @param Sock Pointer to the socket.
816
817 **/
818 VOID
819 SockConnFlush (
820 IN SOCKET *Sock
821 )
822 {
823 SOCKET *Child;
824
825 ASSERT (Sock != NULL);
826
827 //
828 // Clear the flag in this socket
829 //
830 Sock->Flag = 0;
831
832 //
833 // Flush the SndBuffer and RcvBuffer of Sock
834 //
835 NetbufQueFlush (Sock->SndBuffer.DataQueue);
836 NetbufQueFlush (Sock->RcvBuffer.DataQueue);
837
838 //
839 // Signal the pending token
840 //
841 if (Sock->ConnectionToken != NULL) {
842 SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError);
843 Sock->ConnectionToken = NULL;
844 }
845
846 if (Sock->CloseToken != NULL) {
847 SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError);
848 Sock->CloseToken = NULL;
849 }
850
851 SockFlushPendingToken (Sock, &(Sock->ListenTokenList));
852 SockFlushPendingToken (Sock, &(Sock->RcvTokenList));
853 SockFlushPendingToken (Sock, &(Sock->SndTokenList));
854 SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList));
855
856 //
857 // Destroy the pending connection, if it is a listening socket
858 //
859 if (SOCK_IS_LISTENING (Sock)) {
860 while (!IsListEmpty (&Sock->ConnectionList)) {
861 Child = NET_LIST_HEAD (
862 &Sock->ConnectionList,
863 SOCKET,
864 ConnectionList
865 );
866
867 SockDestroyChild (Child);
868 }
869
870 Sock->ConnCnt = 0;
871 }
872
873 return ;
874 }
875
876
877 /**
878 Set the state of the socket.
879
880 @param Sock Pointer to the socket.
881 @param State The new state to be set.
882
883 **/
884 VOID
885 SockSetState (
886 IN SOCKET *Sock,
887 IN SOCK_STATE State
888 )
889 {
890 Sock->State = State;
891 }
892
893
894 /**
895 Clone a new socket including its associated protocol control block.
896
897 @param Sock Pointer to the socket to be cloned.
898
899 @return Pointer to the newly cloned socket. If NULL, error condition occurred.
900
901 **/
902 SOCKET *
903 SockClone (
904 IN SOCKET *Sock
905 )
906 {
907 SOCKET *ClonedSock;
908 SOCK_INIT_DATA InitData;
909
910 InitData.BackLog = Sock->BackLog;
911 InitData.Parent = Sock;
912 InitData.State = Sock->State;
913 InitData.ProtoHandler = Sock->ProtoHandler;
914 InitData.Type = Sock->Type;
915 InitData.RcvBufferSize = Sock->RcvBuffer.HighWater;
916 InitData.SndBufferSize = Sock->SndBuffer.HighWater;
917 InitData.DriverBinding = Sock->DriverBinding;
918 InitData.Protocol = &(Sock->NetProtocol);
919 InitData.CreateCallback = Sock->CreateCallback;
920 InitData.DestroyCallback = Sock->DestroyCallback;
921 InitData.Context = Sock->Context;
922 InitData.ProtoData = Sock->ProtoReserved;
923 InitData.DataSize = sizeof (Sock->ProtoReserved);
924
925 ClonedSock = SockCreate (&InitData);
926
927 if (NULL == ClonedSock) {
928 DEBUG ((EFI_D_ERROR, "SockClone: no resource to create a cloned sock\n"));
929 return NULL;
930 }
931
932 SockSetState (ClonedSock, SO_CONNECTING);
933 ClonedSock->ConfigureState = Sock->ConfigureState;
934
935 return ClonedSock;
936 }
937
938
939 /**
940 Called by the low layer protocol to indicate the socket a connection is
941 established. This function just changes the socket's state to SO_CONNECTED
942 and signals the token used for connection establishment.
943
944 @param Sock Pointer to the socket associated with the
945 established connection.
946 **/
947 VOID
948 SockConnEstablished (
949 IN SOCKET *Sock
950 )
951 {
952
953 ASSERT (SO_CONNECTING == Sock->State);
954
955 SockSetState (Sock, SO_CONNECTED);
956
957 if (NULL == Sock->Parent) {
958 SockWakeConnToken (Sock);
959 } else {
960 SockWakeListenToken (Sock);
961 }
962
963 return ;
964 }
965
966
967 /**
968 Called by the low layer protocol to indicate the connection is closed; This
969 function flushes the socket, sets the state to SO_CLOSED and signals the close
970 token.
971
972 @param Sock Pointer to the socket associated with the closed
973 connection.
974 **/
975 VOID
976 SockConnClosed (
977 IN SOCKET *Sock
978 )
979 {
980 if (Sock->CloseToken != NULL) {
981 SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS);
982 Sock->CloseToken = NULL;
983 }
984
985 SockConnFlush (Sock);
986 SockSetState (Sock, SO_CLOSED);
987
988 if (Sock->Parent != NULL) {
989 SockDestroyChild (Sock);
990 }
991
992 }
993
994
995 /**
996 Called by low layer protocol to indicate that some data is sent or processed;
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 gBS->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) && SOCK_STREAM == 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 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 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 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
1192 will be no more data from the communication peer; This
1193 function set the socket's state to SO_NO_MORE_DATA and
1194 signal all queued IO tokens with the error status
1195 EFI_CONNECTION_FIN.
1196
1197 @param Sock Pointer to the socket.
1198
1199 **/
1200 VOID
1201 SockNoMoreData (
1202 IN 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 }