c714dd3dae9c197dfa12a1dc559ea4c7f720616c
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Dispatcher.c
1 /** @file\r
2 \r
3 Copyright (c) 2005 - 2006, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 Module Name:\r
13 \r
14   Tcp4Dispatcher.c\r
15 \r
16 Abstract:\r
17 \r
18 \r
19 **/\r
20 \r
21 #include "Tcp4Main.h"\r
22 \r
23 #define TCP_COMP_VAL(Min, Max, Default, Val) \\r
24   ((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))\r
25 \r
26 STATIC\r
27 EFI_STATUS\r
28 Tcp4Route (\r
29   IN TCP_CB           *Tcb,\r
30   IN TCP4_ROUTE_INFO  *RouteInfo\r
31   )\r
32 /*++\r
33 \r
34 Routine Description:\r
35 \r
36   Add or remove a route entry in the IP route table associated\r
37   with this TCP instance.\r
38 \r
39 Arguments:\r
40 \r
41   Tcb       - Pointer to the TCP_CB of this TCP instance.\r
42   RouteInfo - Pointer to the route info to be processed.\r
43 \r
44 Returns:\r
45 \r
46   EFI_SUCCESS          - The operation completed successfully.\r
47   EFI_NOT_STARTED      - The driver instance has not been started.\r
48   EFI_NO_MAPPING       - When using the default address, configuration(DHCP,\r
49                          BOOTP, RARP, etc.) is not finished yet.\r
50   EFI_OUT_OF_RESOURCES - Could not add the entry to the routing table.\r
51   EFI_NOT_FOUND        - This route is not in the routing table\r
52                          (when RouteInfo->DeleteRoute is TRUE).\r
53   EFI_ACCESS_DENIED    - The route is already defined in the routing table\r
54                          (when RouteInfo->DeleteRoute is FALSE).\r
55 \r
56 --*/\r
57 {\r
58   EFI_IP4_PROTOCOL  *Ip;\r
59 \r
60   Ip = Tcb->IpInfo->Ip;\r
61 \r
62   ASSERT (Ip);\r
63 \r
64   return Ip->Routes (\r
65               Ip,\r
66               RouteInfo->DeleteRoute,\r
67               RouteInfo->SubnetAddress,\r
68               RouteInfo->SubnetMask,\r
69               RouteInfo->GatewayAddress\r
70               );\r
71 \r
72 }\r
73 \r
74 \r
75 /**\r
76   Get the operational settings of this TCP instance.\r
77 \r
78   @param  Tcb                    Pointer to the TCP_CB of this TCP instance.\r
79   @param  Mode                   Pointer to the buffer to store the operational\r
80                                  settings.\r
81 \r
82   @retval EFI_SUCCESS            The mode data is read.\r
83   @retval EFI_NOT_STARTED        No configuration data is available because this\r
84                                  instance hasn't been started.\r
85 \r
86 **/\r
87 STATIC\r
88 EFI_STATUS\r
89 Tcp4GetMode (\r
90   IN TCP_CB         *Tcb,\r
91   IN TCP4_MODE_DATA *Mode\r
92   )\r
93 {\r
94   SOCKET                *Sock;\r
95   EFI_TCP4_CONFIG_DATA  *ConfigData;\r
96   EFI_TCP4_ACCESS_POINT *AccessPoint;\r
97   EFI_TCP4_OPTION       *Option;\r
98   EFI_IP4_PROTOCOL      *Ip;\r
99 \r
100   Sock = Tcb->Sk;\r
101 \r
102   if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {\r
103     return EFI_NOT_STARTED;\r
104   }\r
105 \r
106   if (Mode->Tcp4State) {\r
107     *(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE) Tcb->State;\r
108   }\r
109 \r
110   if (Mode->Tcp4ConfigData) {\r
111 \r
112     ConfigData                      = Mode->Tcp4ConfigData;\r
113     AccessPoint                     = &(ConfigData->AccessPoint);\r
114     Option                          = ConfigData->ControlOption;\r
115 \r
116     ConfigData->TypeOfService       = Tcb->TOS;\r
117     ConfigData->TimeToLive          = Tcb->TTL;\r
118 \r
119     AccessPoint->UseDefaultAddress  = Tcb->UseDefaultAddr;\r
120 \r
121     NetCopyMem (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip, sizeof (EFI_IPv4_ADDRESS));\r
122     AccessPoint->SubnetMask         = Tcb->SubnetMask;\r
123     AccessPoint->StationPort        = NTOHS (Tcb->LocalEnd.Port);\r
124 \r
125     NetCopyMem (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip, sizeof (EFI_IPv4_ADDRESS));\r
126     AccessPoint->RemotePort         = NTOHS (Tcb->RemoteEnd.Port);\r
127     AccessPoint->ActiveFlag         = (BOOLEAN) (Tcb->State != TCP_LISTEN);\r
128 \r
129     if (Option != NULL) {\r
130       Option->ReceiveBufferSize       = GET_RCV_BUFFSIZE (Tcb->Sk);\r
131       Option->SendBufferSize          = GET_SND_BUFFSIZE (Tcb->Sk);\r
132       Option->MaxSynBackLog           = GET_BACKLOG (Tcb->Sk);\r
133 \r
134       Option->ConnectionTimeout       = Tcb->ConnectTimeout / TCP_TICK_HZ;\r
135       Option->DataRetries             = Tcb->MaxRexmit;\r
136       Option->FinTimeout              = Tcb->FinWait2Timeout / TCP_TICK_HZ;\r
137       Option->TimeWaitTimeout         = Tcb->TimeWaitTimeout / TCP_TICK_HZ;\r
138       Option->KeepAliveProbes         = Tcb->MaxKeepAlive;\r
139       Option->KeepAliveTime           = Tcb->KeepAliveIdle / TCP_TICK_HZ;\r
140       Option->KeepAliveInterval       = Tcb->KeepAlivePeriod / TCP_TICK_HZ;\r
141 \r
142       Option->EnableNagle         = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));\r
143       Option->EnableTimeStamp     = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));\r
144       Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS))\r
145 ;\r
146 \r
147       Option->EnableSelectiveAck      = FALSE;\r
148       Option->EnablePathMtuDiscovery  = FALSE;\r
149     }\r
150   }\r
151 \r
152   Ip = Tcb->IpInfo->Ip;\r
153   ASSERT (Ip);\r
154 \r
155   return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);\r
156 }\r
157 \r
158 \r
159 /**\r
160   If AP->StationPort isn't zero, check whether the access point\r
161   is registered, else generate a random station port for this\r
162   access point.\r
163 \r
164   @param  AP                     Pointer to the access point.\r
165 \r
166   @retval EFI_SUCCESS            The check is passed or the port is assigned.\r
167   @retval EFI_INVALID_PARAMETER  The non-zero station port is already used.\r
168   @retval EFI_OUT_OF_RESOURCES   No port can be allocated.\r
169 \r
170 **/\r
171 STATIC\r
172 EFI_STATUS\r
173 Tcp4Bind (\r
174   IN EFI_TCP4_ACCESS_POINT *AP\r
175   )\r
176 {\r
177   BOOLEAN Cycle;\r
178 \r
179   if (0 != AP->StationPort) {\r
180     //\r
181     // check if a same endpoint is bound\r
182     //\r
183     if (TcpFindTcbByPeer (&AP->StationAddress, AP->StationPort)) {\r
184 \r
185       return EFI_INVALID_PARAMETER;\r
186     }\r
187   } else {\r
188     //\r
189     // generate a random port\r
190     //\r
191     Cycle = FALSE;\r
192 \r
193     if (TCP4_PORT_USER_RESERVED == mTcp4RandomPort) {\r
194       mTcp4RandomPort = TCP4_PORT_KNOWN;\r
195     }\r
196 \r
197     mTcp4RandomPort++;\r
198 \r
199     while (TcpFindTcbByPeer (&AP->StationAddress, mTcp4RandomPort)) {\r
200 \r
201       mTcp4RandomPort++;\r
202 \r
203       if (mTcp4RandomPort <= TCP4_PORT_KNOWN) {\r
204 \r
205         if (Cycle) {\r
206           TCP4_DEBUG_ERROR (("Tcp4Bind: no port can be allocated "\r
207             "for this pcb\n"));\r
208 \r
209           return EFI_OUT_OF_RESOURCES;\r
210         }\r
211 \r
212         mTcp4RandomPort = TCP4_PORT_KNOWN + 1;\r
213 \r
214         Cycle = TRUE;\r
215       }\r
216 \r
217     }\r
218 \r
219     AP->StationPort = mTcp4RandomPort;\r
220   }\r
221 \r
222   return EFI_SUCCESS;\r
223 }\r
224 \r
225 \r
226 /**\r
227   Flush the Tcb add its associated protocols..\r
228 \r
229   @param  Tcb                    Pointer to the TCP_CB to be flushed.\r
230 \r
231   @retval EFI_SUCCESS            The operation is completed successfully.\r
232 \r
233 **/\r
234 STATIC\r
235 VOID\r
236 Tcp4FlushPcb (\r
237   IN TCP_CB *Tcb\r
238   )\r
239 {\r
240   SOCKET           *Sock;\r
241   TCP4_PROTO_DATA  *TcpProto;\r
242 \r
243   IpIoConfigIp (Tcb->IpInfo, NULL);\r
244 \r
245   Sock     = Tcb->Sk;\r
246   TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
247 \r
248   if (SOCK_IS_CONFIGURED (Sock)) {\r
249     NetListRemoveEntry (&Tcb->List);\r
250 \r
251     TcpSetVariableData (TcpProto->TcpService);\r
252   }\r
253 \r
254   NetbufFreeList (&Tcb->SndQue);\r
255   NetbufFreeList (&Tcb->RcvQue);\r
256 }\r
257 \r
258 STATIC\r
259 EFI_STATUS\r
260 Tcp4AttachPcb (\r
261   IN SOCKET  *Sk\r
262   )\r
263 {\r
264   TCP_CB            *Tcb;\r
265   TCP4_PROTO_DATA   *ProtoData;\r
266   IP_IO             *IpIo;\r
267 \r
268   Tcb = NetAllocateZeroPool (sizeof (TCP_CB));\r
269 \r
270   if (Tcb == NULL) {\r
271 \r
272     TCP4_DEBUG_ERROR (("Tcp4ConfigurePcb: failed to allocate a TCB\n"));\r
273 \r
274     return EFI_OUT_OF_RESOURCES;\r
275   }\r
276 \r
277   ProtoData  = (TCP4_PROTO_DATA *) Sk->ProtoReserved;\r
278   IpIo       = ProtoData->TcpService->IpIo;\r
279 \r
280   //\r
281   // Create an IpInfo for this Tcb.\r
282   //\r
283   Tcb->IpInfo = IpIoAddIp (IpIo);\r
284   if (Tcb->IpInfo == NULL) {\r
285 \r
286     NetFreePool (Tcb);\r
287     return EFI_OUT_OF_RESOURCES;\r
288   }\r
289 \r
290   NetListInit (&Tcb->List);\r
291   NetListInit (&Tcb->SndQue);\r
292   NetListInit (&Tcb->RcvQue);\r
293 \r
294   Tcb->State        = TCP_CLOSED;\r
295   Tcb->Sk           = Sk;\r
296   ProtoData->TcpPcb = Tcb;\r
297 \r
298   return EFI_SUCCESS;\r
299 }\r
300 \r
301 STATIC\r
302 VOID\r
303 Tcp4DetachPcb (\r
304   IN SOCKET  *Sk\r
305   )\r
306 {\r
307   TCP4_PROTO_DATA  *ProtoData;\r
308   TCP_CB           *Tcb;\r
309 \r
310   ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;\r
311   Tcb       = ProtoData->TcpPcb;\r
312 \r
313   ASSERT (Tcb != NULL);\r
314 \r
315   Tcp4FlushPcb (Tcb);\r
316 \r
317   IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);\r
318 \r
319   NetFreePool (Tcb);\r
320 \r
321   ProtoData->TcpPcb = NULL;\r
322 }\r
323 \r
324 \r
325 /**\r
326   Configure the Tcb using CfgData.\r
327 \r
328   @param  Sk                     Pointer to the socket of this TCP instance.\r
329   @param  SkTcb                  Pointer to the TCP_CB of this TCP instance.\r
330   @param  CfgData                Pointer to the TCP configuration data.\r
331 \r
332   @retval EFI_SUCCESS            The operation is completed successfully.\r
333   @retval EFI_INVALID_PARAMETER  A same access point has been configured in\r
334                                  another TCP instance.\r
335   @retval EFI_OUT_OF_RESOURCES   Failed due to resource limit.\r
336 \r
337 **/\r
338 STATIC\r
339 EFI_STATUS\r
340 Tcp4ConfigurePcb (\r
341   IN SOCKET               *Sk,\r
342   IN EFI_TCP4_CONFIG_DATA *CfgData\r
343   )\r
344 {\r
345   EFI_IP4_CONFIG_DATA IpCfgData;\r
346   EFI_STATUS          Status;\r
347   EFI_TCP4_OPTION     *Option;\r
348   TCP4_PROTO_DATA     *TcpProto;\r
349   TCP_CB              *Tcb;\r
350 \r
351   ASSERT (CfgData && Sk && Sk->SockHandle);\r
352 \r
353   TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;\r
354   Tcb      = TcpProto->TcpPcb;\r
355 \r
356   ASSERT (Tcb != NULL);\r
357 \r
358   //\r
359   // Add Ip for send pkt to the peer\r
360   //\r
361   CopyMem (&IpCfgData, &mIpIoDefaultIpConfigData, sizeof (IpCfgData));\r
362   IpCfgData.DefaultProtocol   = EFI_IP_PROTO_TCP;\r
363   IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;\r
364   IpCfgData.StationAddress    = CfgData->AccessPoint.StationAddress;\r
365   IpCfgData.SubnetMask        = CfgData->AccessPoint.SubnetMask;\r
366   IpCfgData.ReceiveTimeout    = (UINT32) (-1);\r
367 \r
368   //\r
369   // Configure the IP instance this Tcb consumes.\r
370   //\r
371   Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);\r
372   if (EFI_ERROR (Status)) {\r
373     goto OnExit;\r
374   }\r
375 \r
376   //\r
377   // Get the default address info if the instance is configured to use default address.\r
378   //\r
379   if (CfgData->AccessPoint.UseDefaultAddress) {\r
380     CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;\r
381     CfgData->AccessPoint.SubnetMask     = IpCfgData.SubnetMask;\r
382   }\r
383 \r
384   //\r
385   // check if we can bind this endpoint in CfgData\r
386   //\r
387   Status = Tcp4Bind (&(CfgData->AccessPoint));\r
388 \r
389   if (EFI_ERROR (Status)) {\r
390     TCP4_DEBUG_ERROR (("Tcp4ConfigurePcb: Bind endpoint failed "\r
391       "with %r\n", Status));\r
392 \r
393     goto OnExit;\r
394   }\r
395 \r
396   //\r
397   // Initalize the operating information in this Tcb\r
398   //\r
399   ASSERT (Tcb->State == TCP_CLOSED &&\r
400     NetListIsEmpty (&Tcb->SndQue) &&\r
401     NetListIsEmpty (&Tcb->RcvQue));\r
402 \r
403   TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);\r
404   Tcb->State            = TCP_CLOSED;\r
405 \r
406   Tcb->SndMss           = 536;\r
407   Tcb->RcvMss           = TcpGetRcvMss (Sk);\r
408 \r
409   Tcb->SRtt             = 0;\r
410   Tcb->Rto              = 3 * TCP_TICK_HZ;\r
411 \r
412   Tcb->CWnd             = Tcb->SndMss;\r
413   Tcb->Ssthresh         = 0xffffffff;\r
414 \r
415   Tcb->CongestState     = TCP_CONGEST_OPEN;\r
416 \r
417   Tcb->KeepAliveIdle    = TCP_KEEPALIVE_IDLE_MIN;\r
418   Tcb->KeepAlivePeriod  = TCP_KEEPALIVE_PERIOD;\r
419   Tcb->MaxKeepAlive     = TCP_MAX_KEEPALIVE;\r
420   Tcb->MaxRexmit        = TCP_MAX_LOSS;\r
421   Tcb->FinWait2Timeout  = TCP_FIN_WAIT2_TIME;\r
422   Tcb->TimeWaitTimeout  = TCP_TIME_WAIT_TIME;\r
423   Tcb->ConnectTimeout   = TCP_CONNECT_TIME;\r
424 \r
425   //\r
426   // initialize Tcb in the light of CfgData\r
427   //\r
428   Tcb->TTL            = CfgData->TimeToLive;\r
429   Tcb->TOS            = CfgData->TypeOfService;\r
430 \r
431   NetCopyMem (&Tcb->LocalEnd.Ip, &CfgData->AccessPoint.StationAddress, sizeof (IP4_ADDR));\r
432   Tcb->LocalEnd.Port  = HTONS (CfgData->AccessPoint.StationPort);\r
433   Tcb->SubnetMask     = CfgData->AccessPoint.SubnetMask;\r
434 \r
435   NetCopyMem (&Tcb->RemoteEnd.Ip, &CfgData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));\r
436   Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);\r
437 \r
438   Option              = CfgData->ControlOption;\r
439 \r
440   if (Option != NULL) {\r
441     SET_RCV_BUFFSIZE (\r
442       Sk,\r
443       (UINT32) (TCP_COMP_VAL (\r
444                   TCP_RCV_BUF_SIZE_MIN,\r
445                   TCP_RCV_BUF_SIZE,\r
446                   TCP_RCV_BUF_SIZE,\r
447                   Option->ReceiveBufferSize\r
448                   )\r
449                )\r
450       );\r
451     SET_SND_BUFFSIZE (\r
452       Sk,\r
453       (UINT32) (TCP_COMP_VAL (\r
454                   TCP_SND_BUF_SIZE_MIN,\r
455                   TCP_SND_BUF_SIZE,\r
456                   TCP_SND_BUF_SIZE,\r
457                   Option->SendBufferSize\r
458                   )\r
459                )\r
460       );\r
461 \r
462     SET_BACKLOG (\r
463       Sk,\r
464       (UINT32) (TCP_COMP_VAL (\r
465                   TCP_BACKLOG_MIN,\r
466                   TCP_BACKLOG,\r
467                   TCP_BACKLOG,\r
468                   Option->MaxSynBackLog\r
469                   )\r
470                )\r
471       );\r
472 \r
473     Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (\r
474                                 TCP_MAX_LOSS_MIN,\r
475                                 TCP_MAX_LOSS,\r
476                                 TCP_MAX_LOSS,\r
477                                 Option->DataRetries\r
478                                 );\r
479     Tcb->FinWait2Timeout = TCP_COMP_VAL (\r
480                               TCP_FIN_WAIT2_TIME,\r
481                               TCP_FIN_WAIT2_TIME_MAX,\r
482                               TCP_FIN_WAIT2_TIME,\r
483                               (UINT32) (Option->FinTimeout * TCP_TICK_HZ)\r
484                               );\r
485 \r
486     if (Option->TimeWaitTimeout != 0) {\r
487       Tcb->TimeWaitTimeout = TCP_COMP_VAL (\r
488                                TCP_TIME_WAIT_TIME,\r
489                                TCP_TIME_WAIT_TIME_MAX,\r
490                                TCP_TIME_WAIT_TIME,\r
491                                (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ)\r
492                                );\r
493     } else {\r
494       Tcb->TimeWaitTimeout = 0;\r
495     }\r
496 \r
497     if (Option->KeepAliveProbes != 0) {\r
498       TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);\r
499 \r
500       Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (\r
501                                     TCP_MAX_KEEPALIVE_MIN,\r
502                                     TCP_MAX_KEEPALIVE,\r
503                                     TCP_MAX_KEEPALIVE,\r
504                                     Option->KeepAliveProbes\r
505                                     );\r
506       Tcb->KeepAliveIdle = TCP_COMP_VAL (\r
507                              TCP_KEEPALIVE_IDLE_MIN,\r
508                              TCP_KEEPALIVE_IDLE_MAX,\r
509                              TCP_KEEPALIVE_IDLE_MIN,\r
510                              (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)\r
511                              );\r
512       Tcb->KeepAlivePeriod = TCP_COMP_VAL (\r
513                                TCP_KEEPALIVE_PERIOD_MIN,\r
514                                TCP_KEEPALIVE_PERIOD,\r
515                                TCP_KEEPALIVE_PERIOD,\r
516                                (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)\r
517                                );\r
518     }\r
519 \r
520     Tcb->ConnectTimeout = TCP_COMP_VAL (\r
521                             TCP_CONNECT_TIME_MIN,\r
522                             TCP_CONNECT_TIME,\r
523                             TCP_CONNECT_TIME,\r
524                             (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)\r
525                             );\r
526 \r
527     if (Option->EnableNagle == FALSE) {\r
528       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);\r
529     }\r
530 \r
531     if (Option->EnableTimeStamp == FALSE) {\r
532       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);\r
533     }\r
534 \r
535     if (Option->EnableWindowScaling == FALSE) {\r
536       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);\r
537     }\r
538   }\r
539 \r
540   //\r
541   // update state of Tcb and socket\r
542   //\r
543   if (CfgData->AccessPoint.ActiveFlag == FALSE) {\r
544 \r
545     TcpSetState (Tcb, TCP_LISTEN);\r
546     SockSetState (Sk, SO_LISTENING);\r
547 \r
548     Sk->ConfigureState = SO_CONFIGURED_PASSIVE;\r
549   } else {\r
550 \r
551     Sk->ConfigureState = SO_CONFIGURED_ACTIVE;\r
552   }\r
553 \r
554   TcpInsertTcb (Tcb);\r
555 \r
556 OnExit:\r
557 \r
558   return Status;\r
559 }\r
560 \r
561 \r
562 /**\r
563   The procotol handler provided to the socket layer, used to\r
564   dispatch the socket level requests by calling the corresponding\r
565   TCP layer functions.\r
566 \r
567   @param  Sock                   Pointer to the socket of this TCP instance.\r
568   @param  Request                The code of this operation request.\r
569   @param  Data                   Pointer to the operation specific data passed in\r
570                                  together with the operation request.\r
571 \r
572   @retval EFI_SUCCESS            The socket request is completed successfully.\r
573   @retval other                  The error status returned by the corresponding TCP\r
574                                  layer function.\r
575 \r
576 **/\r
577 EFI_STATUS\r
578 Tcp4Dispatcher (\r
579   IN SOCKET                  *Sock,\r
580   IN SOCK_REQUEST            Request,\r
581   IN VOID                    *Data    OPTIONAL\r
582   )\r
583 {\r
584   TCP_CB            *Tcb;\r
585   TCP4_PROTO_DATA   *ProtoData;\r
586   EFI_IP4_PROTOCOL  *Ip;\r
587 \r
588   ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
589   Tcb       = ProtoData->TcpPcb;\r
590 \r
591   switch (Request) {\r
592   case SOCK_POLL:\r
593     Ip = ProtoData->TcpService->IpIo->Ip;\r
594     Ip->Poll (Ip);\r
595     break;\r
596 \r
597   case SOCK_CONSUMED:\r
598     //\r
599     // After user received data from socket buffer, socket will\r
600     // notify TCP using this message to give it a chance to send out\r
601     // window update information\r
602     //\r
603     ASSERT (Tcb);\r
604     TcpOnAppConsume (Tcb);\r
605     break;\r
606 \r
607   case SOCK_SND:\r
608 \r
609     ASSERT (Tcb);\r
610     TcpOnAppSend (Tcb);\r
611     break;\r
612 \r
613   case SOCK_CLOSE:\r
614 \r
615     TcpOnAppClose (Tcb);\r
616 \r
617     break;\r
618 \r
619   case SOCK_ABORT:\r
620 \r
621     TcpOnAppAbort (Tcb);\r
622 \r
623     break;\r
624 \r
625   case SOCK_SNDPUSH:\r
626     Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);\r
627     TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);\r
628 \r
629     break;\r
630 \r
631   case SOCK_SNDURG:\r
632     Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;\r
633     TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);\r
634 \r
635     break;\r
636 \r
637   case SOCK_CONNECT:\r
638 \r
639     TcpOnAppConnect (Tcb);\r
640 \r
641     break;\r
642 \r
643   case SOCK_ATTACH:\r
644 \r
645     return Tcp4AttachPcb (Sock);\r
646 \r
647     break;\r
648 \r
649   case SOCK_FLUSH:\r
650 \r
651     Tcp4FlushPcb (Tcb);\r
652 \r
653     break;\r
654 \r
655   case SOCK_DETACH:\r
656 \r
657     Tcp4DetachPcb (Sock);\r
658 \r
659     break;\r
660 \r
661   case SOCK_CONFIGURE:\r
662 \r
663     return Tcp4ConfigurePcb (\r
664             Sock,\r
665             (EFI_TCP4_CONFIG_DATA *) Data\r
666             );\r
667 \r
668     break;\r
669 \r
670   case SOCK_MODE:\r
671 \r
672     ASSERT (Data && Tcb);\r
673 \r
674     return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);\r
675 \r
676     break;\r
677 \r
678   case SOCK_ROUTE:\r
679 \r
680     ASSERT (Data && Tcb);\r
681 \r
682     return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);\r
683 \r
684   default:\r
685     return EFI_UNSUPPORTED;\r
686   }\r
687 \r
688   return EFI_SUCCESS;\r
689 \r
690 }\r