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