Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrostcp.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
1.7.6.1
|