ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rostcp.c
Go to the documentation of this file.
00001 #include "lwip/sys.h"
00002 #include "lwip/tcpip.h"
00003 
00004 #include "rosip.h"
00005 
00006 #include <debug.h>
00007 
00008 static const char * const tcp_state_str[] = {
00009   "CLOSED",
00010   "LISTEN",
00011   "SYN_SENT",
00012   "SYN_RCVD",
00013   "ESTABLISHED",
00014   "FIN_WAIT_1",
00015   "FIN_WAIT_2",
00016   "CLOSE_WAIT",
00017   "CLOSING",
00018   "LAST_ACK",
00019   "TIME_WAIT"
00020 };
00021 
00022 /* The way that lwIP does multi-threading is really not ideal for our purposes but
00023  * we best go along with it unless we want another unstable TCP library. lwIP uses
00024  * a thread called the "tcpip thread" which is the only one allowed to call raw API
00025  * functions. Since this is the case, for each of our LibTCP* functions, we queue a request
00026  * for a callback to "tcpip thread" which calls our LibTCP*Callback functions. Yes, this is
00027  * a lot of unnecessary thread swapping and it could definitely be faster, but I don't want
00028  * to going messing around in lwIP because I have no desire to create another mess like oskittcp */
00029 
00030 extern KEVENT TerminationEvent;
00031 extern NPAGED_LOOKASIDE_LIST MessageLookasideList;
00032 extern NPAGED_LOOKASIDE_LIST QueueEntryLookasideList;
00033 
00034 static
00035 void
00036 LibTCPEmptyQueue(PCONNECTION_ENDPOINT Connection)
00037 {
00038     PLIST_ENTRY Entry;
00039     PQUEUE_ENTRY qp = NULL;
00040 
00041     ReferenceObject(Connection);
00042 
00043     while (!IsListEmpty(&Connection->PacketQueue))
00044     {
00045         Entry = RemoveHeadList(&Connection->PacketQueue);
00046         qp = CONTAINING_RECORD(Entry, QUEUE_ENTRY, ListEntry);
00047 
00048         /* We're in the tcpip thread here so this is safe */
00049         pbuf_free(qp->p);
00050 
00051         ExFreeToNPagedLookasideList(&QueueEntryLookasideList, qp);
00052     }
00053 
00054     DereferenceObject(Connection);
00055 }
00056 
00057 void LibTCPEnqueuePacket(PCONNECTION_ENDPOINT Connection, struct pbuf *p)
00058 {
00059     PQUEUE_ENTRY qp;
00060 
00061     qp = (PQUEUE_ENTRY)ExAllocateFromNPagedLookasideList(&QueueEntryLookasideList);
00062     qp->p = p;
00063 
00064     ExInterlockedInsertTailList(&Connection->PacketQueue, &qp->ListEntry, &Connection->Lock);
00065 }
00066 
00067 PQUEUE_ENTRY LibTCPDequeuePacket(PCONNECTION_ENDPOINT Connection)
00068 {
00069     PLIST_ENTRY Entry;
00070     PQUEUE_ENTRY qp = NULL;
00071 
00072     if (IsListEmpty(&Connection->PacketQueue)) return NULL;
00073 
00074     Entry = RemoveHeadList(&Connection->PacketQueue);
00075 
00076     qp = CONTAINING_RECORD(Entry, QUEUE_ENTRY, ListEntry);
00077 
00078     return qp;
00079 }
00080 
00081 NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHAR RecvBuffer, UINT RecvLen, UINT *Received)
00082 {
00083     PQUEUE_ENTRY qp;
00084     struct pbuf* p;
00085     NTSTATUS Status = STATUS_PENDING;
00086     UINT ReadLength, ExistingDataLength;
00087     KIRQL OldIrql;
00088 
00089     (*Received) = 0;
00090 
00091     LockObject(Connection, &OldIrql);
00092 
00093     if (!IsListEmpty(&Connection->PacketQueue))
00094     {
00095         while ((qp = LibTCPDequeuePacket(Connection)) != NULL)
00096         {
00097             p = qp->p;
00098             ExistingDataLength = (*Received);
00099 
00100             Status = STATUS_SUCCESS;
00101 
00102             ReadLength = MIN(p->tot_len, RecvLen);
00103             if (ReadLength != p->tot_len)
00104             {
00105                 if (ExistingDataLength)
00106                 {
00107                     /* The packet was too big but we used some data already so give it another shot later */
00108                     InsertHeadList(&Connection->PacketQueue, &qp->ListEntry);
00109                     break;
00110                 }
00111                 else
00112                 {
00113                     /* The packet is just too big to fit fully in our buffer, even when empty so
00114                      * return an informative status but still copy all the data we can fit.
00115                      */
00116                     Status = STATUS_BUFFER_OVERFLOW;
00117                 }
00118             }
00119 
00120             UnlockObject(Connection, OldIrql);
00121 
00122             /* Return to a lower IRQL because the receive buffer may be pageable memory */
00123             for (; (*Received) < ReadLength + ExistingDataLength; (*Received) += p->len, p = p->next)
00124             {
00125                 RtlCopyMemory(RecvBuffer + (*Received), p->payload, p->len);
00126             }
00127 
00128             LockObject(Connection, &OldIrql);
00129 
00130             RecvLen -= ReadLength;
00131 
00132             /* Use this special pbuf free callback function because we're outside tcpip thread */
00133             pbuf_free_callback(qp->p);
00134 
00135             ExFreeToNPagedLookasideList(&QueueEntryLookasideList, qp);
00136 
00137             if (!RecvLen)
00138                 break;
00139 
00140             if (Status != STATUS_SUCCESS)
00141                 break;
00142         }
00143     }
00144     else
00145     {
00146         if (Connection->ReceiveShutdown)
00147             Status = STATUS_SUCCESS;
00148         else
00149             Status = STATUS_PENDING;
00150     }
00151 
00152     UnlockObject(Connection, OldIrql);
00153 
00154     return Status;
00155 }
00156 
00157 static
00158 BOOLEAN
00159 WaitForEventSafely(PRKEVENT Event)
00160 {
00161     PVOID WaitObjects[] = {Event, &TerminationEvent};
00162 
00163     if (KeWaitForMultipleObjects(2,
00164                                  WaitObjects,
00165                                  WaitAny,
00166                                  Executive,
00167                                  KernelMode,
00168                                  FALSE,
00169                                  NULL,
00170                                  NULL) == STATUS_WAIT_0)
00171     {
00172         /* Signalled by the caller's event */
00173         return TRUE;
00174     }
00175     else /* if KeWaitForMultipleObjects() == STATUS_WAIT_1 */
00176     {
00177         /* Signalled by our termination event */
00178         return FALSE;
00179     }
00180 }
00181 
00182 static
00183 err_t
00184 InternalSendEventHandler(void *arg, PTCP_PCB pcb, const u16_t space)
00185 {
00186     /* Make sure the socket didn't get closed */
00187     if (!arg) return ERR_OK;
00188 
00189     TCPSendEventHandler(arg, space);
00190 
00191     return ERR_OK;
00192 }
00193 
00194 static
00195 err_t
00196 InternalRecvEventHandler(void *arg, PTCP_PCB pcb, struct pbuf *p, const err_t err)
00197 {
00198     PCONNECTION_ENDPOINT Connection = arg;
00199 
00200     /* Make sure the socket didn't get closed */
00201     if (!arg)
00202     {
00203         if (p)
00204             pbuf_free(p);
00205 
00206         return ERR_OK;
00207     }
00208 
00209     if (p)
00210     {
00211         LibTCPEnqueuePacket(Connection, p);
00212 
00213         tcp_recved(pcb, p->tot_len);
00214 
00215         TCPRecvEventHandler(arg);
00216     }
00217     else if (err == ERR_OK)
00218     {
00219         /* Complete pending reads with 0 bytes to indicate a graceful closure,
00220          * but note that send is still possible in this state so we don't close the
00221          * whole socket here (by calling tcp_close()) as that would violate TCP specs
00222          */
00223         Connection->ReceiveShutdown = TRUE;
00224         TCPFinEventHandler(arg, ERR_OK);
00225     }
00226 
00227     return ERR_OK;
00228 }
00229 
00230 static
00231 err_t
00232 InternalAcceptEventHandler(void *arg, PTCP_PCB newpcb, const err_t err)
00233 {
00234     /* Make sure the socket didn't get closed */
00235     if (!arg)
00236         return ERR_ABRT;
00237 
00238     TCPAcceptEventHandler(arg, newpcb);
00239 
00240     /* Set in LibTCPAccept (called from TCPAcceptEventHandler) */
00241     if (newpcb->callback_arg)
00242         return ERR_OK;
00243     else
00244         return ERR_ABRT;
00245 }
00246 
00247 static
00248 err_t
00249 InternalConnectEventHandler(void *arg, PTCP_PCB pcb, const err_t err)
00250 {
00251     /* Make sure the socket didn't get closed */
00252     if (!arg)
00253         return ERR_OK;
00254 
00255     TCPConnectEventHandler(arg, err);
00256 
00257     return ERR_OK;
00258 }
00259 
00260 static
00261 void
00262 InternalErrorEventHandler(void *arg, const err_t err)
00263 {
00264     /* Make sure the socket didn't get closed */
00265     if (!arg) return;
00266 
00267     TCPFinEventHandler(arg, err);
00268 }
00269 
00270 static
00271 void
00272 LibTCPSocketCallback(void *arg)
00273 {
00274     struct lwip_callback_msg *msg = arg;
00275 
00276     ASSERT(msg);
00277 
00278     msg->Output.Socket.NewPcb = tcp_new();
00279 
00280     if (msg->Output.Socket.NewPcb)
00281     {
00282         tcp_arg(msg->Output.Socket.NewPcb, msg->Input.Socket.Arg);
00283         tcp_err(msg->Output.Socket.NewPcb, InternalErrorEventHandler);
00284     }
00285 
00286     KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
00287 }
00288 
00289 struct tcp_pcb *
00290 LibTCPSocket(void *arg)
00291 {
00292     struct lwip_callback_msg *msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
00293     struct tcp_pcb *ret;
00294 
00295     if (msg)
00296     {
00297         KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
00298         msg->Input.Socket.Arg = arg;
00299 
00300         tcpip_callback_with_block(LibTCPSocketCallback, msg, 1);
00301 
00302         if (WaitForEventSafely(&msg->Event))
00303             ret = msg->Output.Socket.NewPcb;
00304         else
00305             ret = NULL;
00306 
00307         ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
00308 
00309         return ret;
00310     }
00311 
00312     return NULL;
00313 }
00314 
00315 static
00316 void
00317 LibTCPBindCallback(void *arg)
00318 {
00319     struct lwip_callback_msg *msg = arg;
00320 
00321     ASSERT(msg);
00322 
00323     if (!msg->Input.Bind.Connection->SocketContext)
00324     {
00325         msg->Output.Bind.Error = ERR_CLSD;
00326         goto done;
00327     }
00328 
00329     msg->Output.Bind.Error = tcp_bind((PTCP_PCB)msg->Input.Bind.Connection->SocketContext,
00330                                       msg->Input.Bind.IpAddress,
00331                                       ntohs(msg->Input.Bind.Port));
00332 
00333 done:
00334     KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
00335 }
00336 
00337 err_t
00338 LibTCPBind(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port)
00339 {
00340     struct lwip_callback_msg *msg;
00341     err_t ret;
00342 
00343     msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
00344     if (msg)
00345     {
00346         KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
00347         msg->Input.Bind.Connection = Connection;
00348         msg->Input.Bind.IpAddress = ipaddr;
00349         msg->Input.Bind.Port = port;
00350 
00351         tcpip_callback_with_block(LibTCPBindCallback, msg, 1);
00352 
00353         if (WaitForEventSafely(&msg->Event))
00354             ret = msg->Output.Bind.Error;
00355         else
00356             ret = ERR_CLSD;
00357 
00358         ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
00359 
00360         return ret;
00361     }
00362 
00363     return ERR_MEM;
00364 }
00365 
00366 static
00367 void
00368 LibTCPListenCallback(void *arg)
00369 {
00370     struct lwip_callback_msg *msg = arg;
00371 
00372     ASSERT(msg);
00373 
00374     if (!msg->Input.Listen.Connection->SocketContext)
00375     {
00376         msg->Output.Listen.NewPcb = NULL;
00377         goto done;
00378     }
00379 
00380     msg->Output.Listen.NewPcb = tcp_listen_with_backlog((PTCP_PCB)msg->Input.Listen.Connection->SocketContext, msg->Input.Listen.Backlog);
00381 
00382     if (msg->Output.Listen.NewPcb)
00383     {
00384         tcp_accept(msg->Output.Listen.NewPcb, InternalAcceptEventHandler);
00385     }
00386 
00387 done:
00388     KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
00389 }
00390 
00391 PTCP_PCB
00392 LibTCPListen(PCONNECTION_ENDPOINT Connection, const u8_t backlog)
00393 {
00394     struct lwip_callback_msg *msg;
00395     PTCP_PCB ret;
00396 
00397     msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
00398     if (msg)
00399     {
00400         KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
00401         msg->Input.Listen.Connection = Connection;
00402         msg->Input.Listen.Backlog = backlog;
00403 
00404         tcpip_callback_with_block(LibTCPListenCallback, msg, 1);
00405 
00406         if (WaitForEventSafely(&msg->Event))
00407             ret = msg->Output.Listen.NewPcb;
00408         else
00409             ret = NULL;
00410 
00411         ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
00412 
00413         return ret;
00414     }
00415 
00416     return NULL;
00417 }
00418 
00419 static
00420 void
00421 LibTCPSendCallback(void *arg)
00422 {
00423     struct lwip_callback_msg *msg = arg;
00424 
00425     ASSERT(msg);
00426 
00427     if (!msg->Input.Send.Connection->SocketContext)
00428     {
00429         msg->Output.Send.Error = ERR_CLSD;
00430         goto done;
00431     }
00432 
00433     if (msg->Input.Send.Connection->SendShutdown)
00434     {
00435         msg->Output.Send.Error = ERR_CLSD;
00436         goto done;
00437     }
00438 
00439     msg->Output.Send.Error = tcp_write((PTCP_PCB)msg->Input.Send.Connection->SocketContext,
00440                                        msg->Input.Send.Data,
00441                                        msg->Input.Send.DataLength,
00442                                        TCP_WRITE_FLAG_COPY);
00443     if (msg->Output.Send.Error == ERR_MEM)
00444     {
00445         /* No buffer space so return pending */
00446         msg->Output.Send.Error = ERR_INPROGRESS;
00447     }
00448     else if (msg->Output.Send.Error == ERR_OK)
00449     {
00450         /* Queued successfully so try to send it */
00451         tcp_output((PTCP_PCB)msg->Input.Send.Connection->SocketContext);
00452     }
00453 
00454 done:
00455     KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
00456 }
00457 
00458 err_t
00459 LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, const int safe)
00460 {
00461     err_t ret;
00462     struct lwip_callback_msg *msg;
00463 
00464     msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
00465     if (msg)
00466     {
00467         KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
00468         msg->Input.Send.Connection = Connection;
00469         msg->Input.Send.Data = dataptr;
00470         msg->Input.Send.DataLength = len;
00471 
00472         if (safe)
00473             LibTCPSendCallback(msg);
00474         else
00475             tcpip_callback_with_block(LibTCPSendCallback, msg, 1);
00476 
00477         if (WaitForEventSafely(&msg->Event))
00478             ret = msg->Output.Send.Error;
00479         else
00480             ret = ERR_CLSD;
00481 
00482         ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
00483 
00484         return ret;
00485     }
00486 
00487     return ERR_MEM;
00488 }
00489 
00490 static
00491 void
00492 LibTCPConnectCallback(void *arg)
00493 {
00494     struct lwip_callback_msg *msg = arg;
00495     err_t Error;
00496 
00497     ASSERT(arg);
00498 
00499     if (!msg->Input.Connect.Connection->SocketContext)
00500     {
00501         msg->Output.Connect.Error = ERR_CLSD;
00502         goto done;
00503     }
00504 
00505     tcp_recv((PTCP_PCB)msg->Input.Connect.Connection->SocketContext, InternalRecvEventHandler);
00506     tcp_sent((PTCP_PCB)msg->Input.Connect.Connection->SocketContext, InternalSendEventHandler);
00507 
00508     Error = tcp_connect((PTCP_PCB)msg->Input.Connect.Connection->SocketContext,
00509                         msg->Input.Connect.IpAddress, ntohs(msg->Input.Connect.Port),
00510                         InternalConnectEventHandler);
00511 
00512     msg->Output.Connect.Error = Error == ERR_OK ? ERR_INPROGRESS : Error;
00513 
00514 done:
00515     KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
00516 }
00517 
00518 err_t
00519 LibTCPConnect(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port)
00520 {
00521     struct lwip_callback_msg *msg;
00522     err_t ret;
00523 
00524     msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
00525     if (msg)
00526     {
00527         KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
00528         msg->Input.Connect.Connection = Connection;
00529         msg->Input.Connect.IpAddress = ipaddr;
00530         msg->Input.Connect.Port = port;
00531 
00532         tcpip_callback_with_block(LibTCPConnectCallback, msg, 1);
00533 
00534         if (WaitForEventSafely(&msg->Event))
00535         {
00536             ret = msg->Output.Connect.Error;
00537         }
00538         else
00539             ret = ERR_CLSD;
00540 
00541         ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
00542 
00543         return ret;
00544     }
00545 
00546     return ERR_MEM;
00547 }
00548 
00549 static
00550 void
00551 LibTCPShutdownCallback(void *arg)
00552 {
00553     struct lwip_callback_msg *msg = arg;
00554     PTCP_PCB pcb = msg->Input.Shutdown.Connection->SocketContext;
00555 
00556     if (!msg->Input.Shutdown.Connection->SocketContext)
00557     {
00558         msg->Output.Shutdown.Error = ERR_CLSD;
00559         goto done;
00560     }
00561 
00562     if (pcb->state == CLOSE_WAIT)
00563     {
00564         /* This case actually results in a socket closure later (lwIP bug?) */
00565         msg->Input.Shutdown.Connection->SocketContext = NULL;
00566     }
00567 
00568     msg->Output.Shutdown.Error = tcp_shutdown(pcb, msg->Input.Shutdown.shut_rx, msg->Input.Shutdown.shut_tx);
00569     if (msg->Output.Shutdown.Error)
00570     {
00571         msg->Input.Shutdown.Connection->SocketContext = pcb;
00572     }
00573     else
00574     {
00575         if (msg->Input.Shutdown.shut_rx)
00576             msg->Input.Shutdown.Connection->ReceiveShutdown = TRUE;
00577 
00578         if (msg->Input.Shutdown.shut_tx)
00579             msg->Input.Shutdown.Connection->SendShutdown = TRUE;
00580     }
00581 
00582 done:
00583     KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
00584 }
00585 
00586 err_t
00587 LibTCPShutdown(PCONNECTION_ENDPOINT Connection, const int shut_rx, const int shut_tx)
00588 {
00589     struct lwip_callback_msg *msg;
00590     err_t ret;
00591 
00592     msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
00593     if (msg)
00594     {
00595         KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
00596 
00597         msg->Input.Shutdown.Connection = Connection;
00598         msg->Input.Shutdown.shut_rx = shut_rx;
00599         msg->Input.Shutdown.shut_tx = shut_tx;
00600 
00601         tcpip_callback_with_block(LibTCPShutdownCallback, msg, 1);
00602 
00603         if (WaitForEventSafely(&msg->Event))
00604             ret = msg->Output.Shutdown.Error;
00605         else
00606             ret = ERR_CLSD;
00607 
00608         ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
00609 
00610         return ret;
00611     }
00612 
00613     return ERR_MEM;
00614 }
00615 
00616 static
00617 void
00618 LibTCPCloseCallback(void *arg)
00619 {
00620     struct lwip_callback_msg *msg = arg;
00621     PTCP_PCB pcb = msg->Input.Close.Connection->SocketContext;
00622 
00623     /* Empty the queue even if we're already "closed" */
00624     LibTCPEmptyQueue(msg->Input.Close.Connection);
00625 
00626     if (!msg->Input.Close.Connection->SocketContext)
00627     {
00628         msg->Output.Close.Error = ERR_OK;
00629         goto done;
00630     }
00631 
00632     /* Clear the PCB pointer */
00633     msg->Input.Close.Connection->SocketContext = NULL;
00634 
00635     switch (pcb->state)
00636     {
00637         case CLOSED:
00638         case LISTEN:
00639         case SYN_SENT:
00640            msg->Output.Close.Error = tcp_close(pcb);
00641 
00642            if (!msg->Output.Close.Error && msg->Input.Close.Callback)
00643                TCPFinEventHandler(msg->Input.Close.Connection, ERR_OK);
00644            break;
00645 
00646         default:
00647            if (msg->Input.Close.Connection->SendShutdown &&
00648                msg->Input.Close.Connection->ReceiveShutdown)
00649            {
00650                /* Abort the connection */
00651                tcp_abort(pcb);
00652 
00653                /* Aborts always succeed */
00654                msg->Output.Close.Error = ERR_OK;
00655            }
00656            else
00657            {
00658                /* Start the graceful close process (or send RST for pending data) */
00659                msg->Output.Close.Error = tcp_close(pcb);
00660            }
00661            break;
00662     }
00663 
00664     if (msg->Output.Close.Error)
00665     {
00666         /* Restore the PCB pointer */
00667         msg->Input.Close.Connection->SocketContext = pcb;
00668     }
00669 
00670 done:
00671     KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
00672 }
00673 
00674 err_t
00675 LibTCPClose(PCONNECTION_ENDPOINT Connection, const int safe, const int callback)
00676 {
00677     err_t ret;
00678     struct lwip_callback_msg *msg;
00679 
00680     msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
00681     if (msg)
00682     {
00683         KeInitializeEvent(&msg->Event, NotificationEvent, FALSE);
00684 
00685         msg->Input.Close.Connection = Connection;
00686         msg->Input.Close.Callback = callback;
00687 
00688         if (safe)
00689             LibTCPCloseCallback(msg);
00690         else
00691             tcpip_callback_with_block(LibTCPCloseCallback, msg, 1);
00692 
00693         if (WaitForEventSafely(&msg->Event))
00694             ret = msg->Output.Close.Error;
00695         else
00696             ret = ERR_CLSD;
00697 
00698         ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
00699 
00700         return ret;
00701     }
00702 
00703     return ERR_MEM;
00704 }
00705 
00706 void
00707 LibTCPAccept(PTCP_PCB pcb, struct tcp_pcb *listen_pcb, void *arg)
00708 {
00709     ASSERT(arg);
00710 
00711     tcp_arg(pcb, NULL);
00712     tcp_recv(pcb, InternalRecvEventHandler);
00713     tcp_sent(pcb, InternalSendEventHandler);
00714     tcp_err(pcb, InternalErrorEventHandler);
00715     tcp_arg(pcb, arg);
00716 
00717     tcp_accepted(listen_pcb);
00718 }
00719 
00720 err_t
00721 LibTCPGetHostName(PTCP_PCB pcb, struct ip_addr *const ipaddr, u16_t *const port)
00722 {
00723     if (!pcb)
00724         return ERR_CLSD;
00725 
00726     *ipaddr = pcb->local_ip;
00727     *port = pcb->local_port;
00728 
00729     return ERR_OK;
00730 }
00731 
00732 err_t
00733 LibTCPGetPeerName(PTCP_PCB pcb, struct ip_addr * const ipaddr, u16_t * const port)
00734 {
00735     if (!pcb)
00736         return ERR_CLSD;
00737 
00738     *ipaddr = pcb->remote_ip;
00739     *port = pcb->remote_port;
00740 
00741     return ERR_OK;
00742 }

Generated on Sat May 26 2012 04:35:02 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.