ReactOS 0.4.15-dev-8100-g1887773
tcp.c File Reference
#include <debug.h>
#include <lwip/tcpip.h>
#include "lwip_glue.h"
Include dependency graph for tcp.c:

Go to the source code of this file.

Functions

NTSTATUS TCPTranslateError (const err_t err)
 
void LibTCPDumpPcb (PVOID SocketContext)
 
static void LibTCPEmptyQueue (PCONNECTION_ENDPOINT Connection)
 
void LibTCPEnqueuePacket (PCONNECTION_ENDPOINT Connection, struct pbuf *p)
 
PQUEUE_ENTRY LibTCPDequeuePacket (PCONNECTION_ENDPOINT Connection)
 
NTSTATUS LibTCPGetDataFromConnectionQueue (PCONNECTION_ENDPOINT Connection, PUCHAR RecvBuffer, UINT RecvLen, UINT *Received)
 
static BOOLEAN WaitForEventSafely (PRKEVENT Event)
 
static err_t InternalSendEventHandler (void *arg, PTCP_PCB pcb, const u16_t space)
 
static err_t InternalRecvEventHandler (void *arg, PTCP_PCB pcb, struct pbuf *p, const err_t err)
 
static err_t InternalAcceptEventHandler (void *arg, PTCP_PCB newpcb, const err_t err)
 
static err_t InternalConnectEventHandler (void *arg, PTCP_PCB pcb, const err_t err)
 
static void InternalErrorEventHandler (void *arg, const err_t err)
 
static void LibTCPSocketCallback (void *arg)
 
struct tcp_pcb * LibTCPSocket (void *arg)
 
static void LibTCPFreeSocketCallback (void *arg)
 
void LibTCPFreeSocket (PTCP_PCB pcb)
 
static void LibTCPBindCallback (void *arg)
 
err_t LibTCPBind (PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port)
 
static void LibTCPListenCallback (void *arg)
 
PTCP_PCB LibTCPListen (PCONNECTION_ENDPOINT Connection, const u8_t backlog)
 
static void LibTCPSendCallback (void *arg)
 
err_t LibTCPSend (PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, u32_t *sent, const int safe)
 
static void LibTCPConnectCallback (void *arg)
 
err_t LibTCPConnect (PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port)
 
static void LibTCPShutdownCallback (void *arg)
 
err_t LibTCPShutdown (PCONNECTION_ENDPOINT Connection, const int shut_rx, const int shut_tx)
 
static void LibTCPCloseCallback (void *arg)
 
err_t LibTCPClose (PCONNECTION_ENDPOINT Connection, const int safe, const int callback)
 
void LibTCPAccept (PTCP_PCB pcb, struct tcp_pcb *listen_pcb, void *arg)
 
err_t LibTCPGetHostName (PTCP_PCB pcb, struct ip_addr *const ipaddr, u16_t *const port)
 
err_t LibTCPGetPeerName (PTCP_PCB pcb, struct ip_addr *const ipaddr, u16_t *const port)
 
void LibTCPSetNoDelay (PTCP_PCB pcb, BOOLEAN Set)
 
void LibTCPGetSocketStatus (PTCP_PCB pcb, PULONG State)
 

Variables

static const char *const tcp_state_str []
 
KEVENT TerminationEvent
 
NPAGED_LOOKASIDE_LIST MessageLookasideList
 
NPAGED_LOOKASIDE_LIST QueueEntryLookasideList
 

Function Documentation

◆ InternalAcceptEventHandler()

static err_t InternalAcceptEventHandler ( void arg,
PTCP_PCB  newpcb,
const err_t  err 
)
static

Definition at line 267 of file tcp.c.

268{
269 /* Make sure the socket didn't get closed */
270 if (!arg)
271 return ERR_CLSD;
272
273 TCPAcceptEventHandler(arg, newpcb);
274
275 /* Set in LibTCPAccept (called from TCPAcceptEventHandler) */
276 if (newpcb->callback_arg)
277 return ERR_OK;
278 else
279 return ERR_CLSD;
280}
#define ERR_OK
Definition: err.h:52
#define ERR_CLSD
Definition: err.h:67
void TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
Definition: event.c:231

Referenced by LibTCPListenCallback().

◆ InternalConnectEventHandler()

static err_t InternalConnectEventHandler ( void arg,
PTCP_PCB  pcb,
const err_t  err 
)
static

Definition at line 284 of file tcp.c.

285{
286 /* Make sure the socket didn't get closed */
287 if (!arg)
288 return ERR_OK;
289
291
292 return ERR_OK;
293}
void TCPConnectEventHandler(void *arg, const err_t err)
Definition: event.c:420
#define err(...)

Referenced by LibTCPConnectCallback().

◆ InternalErrorEventHandler()

static void InternalErrorEventHandler ( void arg,
const err_t  err 
)
static

Definition at line 297 of file tcp.c.

298{
299 PCONNECTION_ENDPOINT Connection = arg;
300
301 /* Make sure the socket didn't get closed */
302 if (!arg || Connection->SocketContext == NULL) return;
303
304 /* The PCB is dead now */
305 Connection->SocketContext = NULL;
306
307 /* Give them one shot to receive the remaining data */
308 Connection->ReceiveShutdown = TRUE;
310 TCPRecvEventHandler(Connection);
311
312 /* Terminate the connection */
313 TCPFinEventHandler(Connection, err);
314}
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
NTSTATUS TCPTranslateError(const err_t err)
Definition: tcp.c:267
void TCPRecvEventHandler(void *arg)
Definition: event.c:380
void TCPFinEventHandler(void *arg, const err_t err)
Definition: event.c:182
NTSTATUS ReceiveShutdownStatus
Definition: titypes.h:266
BOOLEAN ReceiveShutdown
Definition: titypes.h:265
void * arg
Definition: msvc.h:10

Referenced by LibTCPAccept(), and LibTCPSocketCallback().

◆ InternalRecvEventHandler()

static err_t InternalRecvEventHandler ( void arg,
PTCP_PCB  pcb,
struct pbuf p,
const err_t  err 
)
static

Definition at line 213 of file tcp.c.

214{
215 PCONNECTION_ENDPOINT Connection = arg;
216
217 /* Make sure the socket didn't get closed */
218 if (!arg)
219 {
220 if (p)
221 pbuf_free(p);
222
223 return ERR_OK;
224 }
225
226 if (p)
227 {
228 LibTCPEnqueuePacket(Connection, p);
229
230 tcp_recved(pcb, p->tot_len);
231
233 }
234 else if (err == ERR_OK)
235 {
236 /* Complete pending reads with 0 bytes to indicate a graceful closure,
237 * but note that send is still possible in this state so we don't close the
238 * whole socket here (by calling tcp_close()) as that would violate TCP specs
239 */
240 Connection->ReceiveShutdown = TRUE;
242
243 /* If we already did a send shutdown, we're in TIME_WAIT so we can't use this PCB anymore */
244 if (Connection->SendShutdown)
245 {
246 Connection->SocketContext = NULL;
247 tcp_arg(pcb, NULL);
248 }
249
250 /* Indicate the graceful close event */
252
253 /* If the PCB is gone, clean up the connection */
254 if (Connection->SendShutdown)
255 {
256 TCPFinEventHandler(Connection, ERR_CLSD);
257 }
258 }
259
260 return ERR_OK;
261}
void LibTCPEnqueuePacket(PCONNECTION_ENDPOINT Connection, struct pbuf *p)
Definition: tcp.c:73
GLfloat GLfloat p
Definition: glext.h:8902
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
#define STATUS_SUCCESS
Definition: shellext.h:65
BOOLEAN SendShutdown
Definition: titypes.h:264

Referenced by LibTCPAccept(), and LibTCPConnectCallback().

◆ InternalSendEventHandler()

static err_t InternalSendEventHandler ( void arg,
PTCP_PCB  pcb,
const u16_t  space 
)
static

Definition at line 201 of file tcp.c.

202{
203 /* Make sure the socket didn't get closed */
204 if (!arg) return ERR_OK;
205
207
208 return ERR_OK;
209}
void TCPSendEventHandler(void *arg, const u16_t space)
Definition: event.c:294

Referenced by LibTCPAccept(), and LibTCPConnectCallback().

◆ LibTCPAccept()

void LibTCPAccept ( PTCP_PCB  pcb,
struct tcp_pcb *  listen_pcb,
void arg 
)

Definition at line 830 of file tcp.c.

831{
832 ASSERT(arg);
833
834 tcp_arg(pcb, NULL);
836 tcp_sent(pcb, InternalSendEventHandler);
837 tcp_err(pcb, InternalErrorEventHandler);
838 tcp_arg(pcb, arg);
839
840 tcp_accepted(listen_pcb);
841}
STREAM tcp_recv(STREAM s, uint32 length)
Definition: tcp.c:344
static err_t InternalRecvEventHandler(void *arg, PTCP_PCB pcb, struct pbuf *p, const err_t err)
Definition: tcp.c:213
static err_t InternalSendEventHandler(void *arg, PTCP_PCB pcb, const u16_t space)
Definition: tcp.c:201
static void InternalErrorEventHandler(void *arg, const err_t err)
Definition: tcp.c:297
#define ASSERT(a)
Definition: mode.c:44

Referenced by TCPAcceptEventHandler().

◆ LibTCPBind()

err_t LibTCPBind ( PCONNECTION_ENDPOINT  Connection,
struct ip_addr *const  ipaddr,
const u16_t  port 
)

Definition at line 415 of file tcp.c.

416{
417 struct lwip_callback_msg *msg;
418 err_t ret;
419
420 msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
421 if (msg)
422 {
424 msg->Input.Bind.Connection = Connection;
425 msg->Input.Bind.IpAddress = ipaddr;
426 msg->Input.Bind.Port = port;
427
429
430 if (WaitForEventSafely(&msg->Event))
431 ret = msg->Output.Bind.Error;
432 else
433 ret = ERR_CLSD;
434
435 ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
436
437 return ret;
438 }
439
440 return ERR_MEM;
441}
#define msg(x)
Definition: auth_time.c:54
#define FALSE
Definition: types.h:117
USHORT port
Definition: uri.c:228
static void LibTCPBindCallback(void *arg)
Definition: tcp.c:390
NPAGED_LOOKASIDE_LIST MessageLookasideList
Definition: sys_arch.c:10
static BOOLEAN WaitForEventSafely(PRKEVENT Event)
Definition: tcp.c:176
#define ERR_MEM
Definition: err.h:53
s8_t err_t
Definition: err.h:47
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
@ NotificationEvent
PCONNECTION_ENDPOINT Connection
Definition: lwip_glue.h:38
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
Definition: tcpip.c:214
int ret

Referenced by TCPConnect(), and TCPListen().

◆ LibTCPBindCallback()

static void LibTCPBindCallback ( void arg)
static

Definition at line 390 of file tcp.c.

391{
392 struct lwip_callback_msg *msg = arg;
393 PTCP_PCB pcb = msg->Input.Bind.Connection->SocketContext;
394
395 ASSERT(msg);
396
397 if (!msg->Input.Bind.Connection->SocketContext)
398 {
399 msg->Output.Bind.Error = ERR_CLSD;
400 goto done;
401 }
402
403 /* We're guaranteed that the local address is valid to bind at this point */
404 pcb->so_options |= SOF_REUSEADDR;
405
406 msg->Output.Bind.Error = tcp_bind(pcb,
407 msg->Input.Bind.IpAddress,
408 ntohs(msg->Input.Bind.Port));
409
410done:
412}
#define SOF_REUSEADDR
Definition: ip.h:99
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
struct tcp_pcb * PTCP_PCB
Definition: lwip_glue.h:15
#define ntohs(x)
Definition: module.h:210
struct tcp_pcb * pcb
Definition: lwip_glue.h:35
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Referenced by LibTCPBind().

◆ LibTCPClose()

err_t LibTCPClose ( PCONNECTION_ENDPOINT  Connection,
const int  safe,
const int  callback 
)

Definition at line 798 of file tcp.c.

799{
800 err_t ret;
801 struct lwip_callback_msg *msg;
802
803 msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
804 if (msg)
805 {
807
808 msg->Input.Close.Connection = Connection;
809 msg->Input.Close.Callback = callback;
810
811 if (safe)
813 else
815
816 if (WaitForEventSafely(&msg->Event))
817 ret = msg->Output.Close.Error;
818 else
819 ret = ERR_CLSD;
820
821 ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
822
823 return ret;
824 }
825
826 return ERR_MEM;
827}
static void LibTCPCloseCallback(void *arg)
Definition: tcp.c:748
static IPrintDialogCallback callback
Definition: printdlg.c:326

Referenced by TCPAcceptEventHandler(), and TCPClose().

◆ LibTCPCloseCallback()

static void LibTCPCloseCallback ( void arg)
static

Definition at line 748 of file tcp.c.

749{
750 struct lwip_callback_msg *msg = arg;
751 PTCP_PCB pcb = msg->Input.Close.Connection->SocketContext;
752
753 /* Empty the queue even if we're already "closed" */
754 LibTCPEmptyQueue(msg->Input.Close.Connection);
755
756 /* Check if we've already been closed */
757 if (msg->Input.Close.Connection->Closing)
758 {
759 msg->Output.Close.Error = ERR_OK;
760 goto done;
761 }
762
763 /* Enter "closing" mode if we're doing a normal close */
764 if (msg->Input.Close.Callback)
765 msg->Input.Close.Connection->Closing = TRUE;
766
767 /* Check if the PCB was already "closed" but the client doesn't know it yet */
768 if (!msg->Input.Close.Connection->SocketContext)
769 {
770 msg->Output.Close.Error = ERR_OK;
771 goto done;
772 }
773
774 /* Clear the PCB pointer and stop callbacks */
775 msg->Input.Close.Connection->SocketContext = NULL;
776 tcp_arg(pcb, NULL);
777
778 /* This may generate additional callbacks but we don't care,
779 * because they're too inconsistent to rely on */
780 msg->Output.Close.Error = tcp_close(pcb);
781
782 if (msg->Output.Close.Error)
783 {
784 /* Restore the PCB pointer */
785 msg->Input.Close.Connection->SocketContext = pcb;
786 msg->Input.Close.Connection->Closing = FALSE;
787 }
788 else if (msg->Input.Close.Callback)
789 {
790 TCPFinEventHandler(msg->Input.Close.Connection, ERR_CLSD);
791 }
792
793done:
795}
static void LibTCPEmptyQueue(PCONNECTION_ENDPOINT Connection)
Definition: tcp.c:52
void tcp_close(struct sock *sk, long timeout)

Referenced by LibTCPClose().

◆ LibTCPConnect()

err_t LibTCPConnect ( PCONNECTION_ENDPOINT  Connection,
struct ip_addr *const  ipaddr,
const u16_t  port 
)

Definition at line 622 of file tcp.c.

623{
624 struct lwip_callback_msg *msg;
625 err_t ret;
626
627 msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
628 if (msg)
629 {
631 msg->Input.Connect.Connection = Connection;
632 msg->Input.Connect.IpAddress = ipaddr;
633 msg->Input.Connect.Port = port;
634
636
637 if (WaitForEventSafely(&msg->Event))
638 {
639 ret = msg->Output.Connect.Error;
640 }
641 else
642 ret = ERR_CLSD;
643
644 ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
645
646 return ret;
647 }
648
649 return ERR_MEM;
650}
static void LibTCPConnectCallback(void *arg)
Definition: tcp.c:595

Referenced by TCPConnect().

◆ LibTCPConnectCallback()

static void LibTCPConnectCallback ( void arg)
static

Definition at line 595 of file tcp.c.

596{
597 struct lwip_callback_msg *msg = arg;
598 err_t Error;
599
600 ASSERT(arg);
601
602 if (!msg->Input.Connect.Connection->SocketContext)
603 {
604 msg->Output.Connect.Error = ERR_CLSD;
605 goto done;
606 }
607
608 tcp_recv((PTCP_PCB)msg->Input.Connect.Connection->SocketContext, InternalRecvEventHandler);
609 tcp_sent((PTCP_PCB)msg->Input.Connect.Connection->SocketContext, InternalSendEventHandler);
610
611 Error = tcp_connect((PTCP_PCB)msg->Input.Connect.Connection->SocketContext,
612 msg->Input.Connect.IpAddress, ntohs(msg->Input.Connect.Port),
614
615 msg->Output.Connect.Error = Error == ERR_OK ? ERR_INPROGRESS : Error;
616
617done:
619}
RD_BOOL tcp_connect(char *server)
Definition: tcp.c:717
BOOL Error
Definition: chkdsk.c:66
static err_t InternalConnectEventHandler(void *arg, PTCP_PCB pcb, const err_t err)
Definition: tcp.c:284
#define ERR_INPROGRESS
Definition: err.h:57

Referenced by LibTCPConnect().

◆ LibTCPDequeuePacket()

PQUEUE_ENTRY LibTCPDequeuePacket ( PCONNECTION_ENDPOINT  Connection)

Definition at line 86 of file tcp.c.

87{
89 PQUEUE_ENTRY qp = NULL;
90
91 if (IsListEmpty(&Connection->PacketQueue)) return NULL;
92
93 Entry = RemoveHeadList(&Connection->PacketQueue);
94
95 qp = CONTAINING_RECORD(Entry, QUEUE_ENTRY, ListEntry);
96
97 return qp;
98}
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
base of all file and directory entries
Definition: entries.h:83
LIST_ENTRY PacketQueue
Definition: titypes.h:256
Definition: typedefs.h:120
Definition: lwip_glue.h:18
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by LibTCPGetDataFromConnectionQueue().

◆ LibTCPDumpPcb()

void LibTCPDumpPcb ( PVOID  SocketContext)

Definition at line 36 of file tcp.c.

37{
38 struct tcp_pcb *pcb = (struct tcp_pcb*)SocketContext;
39 unsigned int addr = ntohl(pcb->remote_ip.addr);
40
41 DbgPrint("\tState: %s\n", tcp_state_str[pcb->state]);
42 DbgPrint("\tRemote: (%d.%d.%d.%d, %d)\n",
43 (addr >> 24) & 0xFF,
44 (addr >> 16) & 0xFF,
45 (addr >> 8) & 0xFF,
46 addr & 0xFF,
47 pcb->remote_port);
48}
static const char *const tcp_state_str[]
Definition: tcp.c:6
GLenum const GLvoid * addr
Definition: glext.h:9621
#define DbgPrint
Definition: hal.h:12
#define ntohl(x)
Definition: module.h:205
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID SocketContext
Definition: wsk.h:187

Referenced by LogActiveObjects().

◆ LibTCPEmptyQueue()

static void LibTCPEmptyQueue ( PCONNECTION_ENDPOINT  Connection)
static

Definition at line 52 of file tcp.c.

53{
55 PQUEUE_ENTRY qp = NULL;
56
57 ReferenceObject(Connection);
58
59 while (!IsListEmpty(&Connection->PacketQueue))
60 {
61 Entry = RemoveHeadList(&Connection->PacketQueue);
62 qp = CONTAINING_RECORD(Entry, QUEUE_ENTRY, ListEntry);
63
64 /* We're in the tcpip thread here so this is safe */
65 pbuf_free(qp->p);
66
67 ExFreeToNPagedLookasideList(&QueueEntryLookasideList, qp);
68 }
69
70 DereferenceObject(Connection);
71}
NPAGED_LOOKASIDE_LIST QueueEntryLookasideList
Definition: sys_arch.c:11
struct pbuf * p
Definition: lwip_glue.h:19
#define ReferenceObject(Object)
Definition: titypes.h:14
#define DereferenceObject(Object)
Definition: titypes.h:24

Referenced by LibTCPCloseCallback().

◆ LibTCPEnqueuePacket()

void LibTCPEnqueuePacket ( PCONNECTION_ENDPOINT  Connection,
struct pbuf p 
)

Definition at line 73 of file tcp.c.

74{
75 PQUEUE_ENTRY qp;
76
77 qp = (PQUEUE_ENTRY)ExAllocateFromNPagedLookasideList(&QueueEntryLookasideList);
78 qp->p = p;
79 qp->Offset = 0;
80
81 LockObject(Connection);
82 InsertTailList(&Connection->PacketQueue, &qp->ListEntry);
83 UnlockObject(Connection);
84}
#define InsertTailList(ListHead, Entry)
struct _QUEUE_ENTRY * PQUEUE_ENTRY
LIST_ENTRY ListEntry
Definition: lwip_glue.h:21
ULONG Offset
Definition: lwip_glue.h:20
#define UnlockObject(Object)
Definition: titypes.h:44
#define LockObject(Object)
Definition: titypes.h:34

Referenced by InternalRecvEventHandler().

◆ LibTCPFreeSocket()

void LibTCPFreeSocket ( PTCP_PCB  pcb)

Definition at line 375 of file tcp.c.

376{
377 struct lwip_callback_msg msg;
378
380 msg.Input.FreeSocket.pcb = pcb;
381
383
384 WaitForEventSafely(&msg.Event);
385}
static void LibTCPFreeSocketCallback(void *arg)
Definition: tcp.c:363

◆ LibTCPFreeSocketCallback()

static void LibTCPFreeSocketCallback ( void arg)
static

Definition at line 363 of file tcp.c.

364{
365 struct lwip_callback_msg *msg = arg;
366
367 ASSERT(msg);
368
369 /* Calling tcp_close will free it */
370 tcp_close(msg->Input.FreeSocket.pcb);
371
373}

Referenced by LibTCPFreeSocket().

◆ LibTCPGetDataFromConnectionQueue()

NTSTATUS LibTCPGetDataFromConnectionQueue ( PCONNECTION_ENDPOINT  Connection,
PUCHAR  RecvBuffer,
UINT  RecvLen,
UINT Received 
)

Definition at line 100 of file tcp.c.

101{
102 PQUEUE_ENTRY qp;
103 struct pbuf* p;
106
107 (*Received) = 0;
108
109 LockObject(Connection);
110
111 if (!IsListEmpty(&Connection->PacketQueue))
112 {
113 while ((qp = LibTCPDequeuePacket(Connection)) != NULL)
114 {
115 p = qp->p;
116
117 /* Calculate the payload length first */
118 PayloadLength = p->tot_len;
119 PayloadLength -= qp->Offset;
120 Offset = qp->Offset;
121
122 /* Check if we're reading the whole buffer */
123 ReadLength = MIN(PayloadLength, RecvLen);
124 ASSERT(ReadLength != 0);
126 {
127 /* Save this one for later */
128 qp->Offset += ReadLength;
129 InsertHeadList(&Connection->PacketQueue, &qp->ListEntry);
130 qp = NULL;
131 }
132
133 Copied = pbuf_copy_partial(p, RecvBuffer, ReadLength, Offset);
134 ASSERT(Copied == ReadLength);
135
136 /* Update trackers */
137 RecvLen -= ReadLength;
138 RecvBuffer += ReadLength;
139 (*Received) += ReadLength;
140
141 if (qp != NULL)
142 {
143 /* Use this special pbuf free callback function because we're outside tcpip thread */
145
146 ExFreeToNPagedLookasideList(&QueueEntryLookasideList, qp);
147 }
148 else
149 {
150 /* If we get here, it means we've filled the buffer */
151 ASSERT(RecvLen == 0);
152 }
153
154 ASSERT((*Received) != 0);
156
157 if (!RecvLen)
158 break;
159 }
160 }
161 else
162 {
163 if (Connection->ReceiveShutdown)
164 Status = Connection->ReceiveShutdownStatus;
165 else
167 }
168
169 UnlockObject(Connection);
170
171 return Status;
172}
ULONG ReadLength
UINT Received
Definition: arping.c:40
LONG NTSTATUS
Definition: precomp.h:26
#define MIN(x, y)
Definition: rdesktop.h:171
PQUEUE_ENTRY LibTCPDequeuePacket(PCONNECTION_ENDPOINT Connection)
Definition: tcp.c:86
#define InsertHeadList(ListHead, Entry)
Status
Definition: gdiplustypes.h:25
unsigned int UINT
Definition: ndis.h:50
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define STATUS_PENDING
Definition: ntstatus.h:82
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:918
Definition: pbuf.h:79
err_t pbuf_free_callback(struct pbuf *p)
Definition: tcpip.c:496
_In_ PVOID _In_ ULONG _In_ PVOID _In_ ULONG PayloadLength
Definition: iotypes.h:471

Referenced by TCPReceiveData(), and TCPRecvEventHandler().

◆ LibTCPGetHostName()

err_t LibTCPGetHostName ( PTCP_PCB  pcb,
struct ip_addr *const  ipaddr,
u16_t *const  port 
)

Definition at line 844 of file tcp.c.

845{
846 if (!pcb)
847 return ERR_CLSD;
848
849 *ipaddr = pcb->local_ip;
850 *port = pcb->local_port;
851
852 return ERR_OK;
853}

Referenced by TCPGetSockAddress().

◆ LibTCPGetPeerName()

err_t LibTCPGetPeerName ( PTCP_PCB  pcb,
struct ip_addr *const  ipaddr,
u16_t *const  port 
)

Definition at line 856 of file tcp.c.

857{
858 if (!pcb)
859 return ERR_CLSD;
860
861 *ipaddr = pcb->remote_ip;
862 *port = pcb->remote_port;
863
864 return ERR_OK;
865}

Referenced by TCPCheckPeerForAccept(), and TCPGetSockAddress().

◆ LibTCPGetSocketStatus()

void LibTCPGetSocketStatus ( PTCP_PCB  pcb,
PULONG  State 
)

Definition at line 879 of file tcp.c.

882{
883 /* Translate state from enum tcp_state -> MIB_TCP_STATE */
884 *State = pcb->state + 1;
885}

Referenced by TCPGetSocketStatus().

◆ LibTCPListen()

PTCP_PCB LibTCPListen ( PCONNECTION_ENDPOINT  Connection,
const u8_t  backlog 
)

Definition at line 469 of file tcp.c.

470{
471 struct lwip_callback_msg *msg;
473
474 msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
475 if (msg)
476 {
478 msg->Input.Listen.Connection = Connection;
479 msg->Input.Listen.Backlog = backlog;
480
482
483 if (WaitForEventSafely(&msg->Event))
484 ret = msg->Output.Listen.NewPcb;
485 else
486 ret = NULL;
487
488 ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
489
490 return ret;
491 }
492
493 return NULL;
494}
static void LibTCPListenCallback(void *arg)
Definition: tcp.c:445

Referenced by TCPListen().

◆ LibTCPListenCallback()

static void LibTCPListenCallback ( void arg)
static

Definition at line 445 of file tcp.c.

446{
447 struct lwip_callback_msg *msg = arg;
448
449 ASSERT(msg);
450
451 if (!msg->Input.Listen.Connection->SocketContext)
452 {
453 msg->Output.Listen.NewPcb = NULL;
454 goto done;
455 }
456
457 msg->Output.Listen.NewPcb = tcp_listen_with_backlog((PTCP_PCB)msg->Input.Listen.Connection->SocketContext, msg->Input.Listen.Backlog);
458
459 if (msg->Output.Listen.NewPcb)
460 {
461 tcp_accept(msg->Output.Listen.NewPcb, InternalAcceptEventHandler);
462 }
463
464done:
466}
static err_t InternalAcceptEventHandler(void *arg, PTCP_PCB newpcb, const err_t err)
Definition: tcp.c:267
struct sock * tcp_accept(struct sock *sk, int flags, int *err)

Referenced by LibTCPListen().

◆ LibTCPSend()

err_t LibTCPSend ( PCONNECTION_ENDPOINT  Connection,
void *const  dataptr,
const u16_t  len,
u32_t sent,
const int  safe 
)

Definition at line 557 of file tcp.c.

558{
559 err_t ret;
560 struct lwip_callback_msg *msg;
561
562 msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
563 if (msg)
564 {
566 msg->Input.Send.Connection = Connection;
567 msg->Input.Send.Data = dataptr;
568 msg->Input.Send.DataLength = len;
569
570 if (safe)
572 else
574
575 if (WaitForEventSafely(&msg->Event))
576 ret = msg->Output.Send.Error;
577 else
578 ret = ERR_CLSD;
579
580 if (ret == ERR_OK)
581 *sent = msg->Output.Send.Information;
582 else
583 *sent = 0;
584
585 ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
586
587 return ret;
588 }
589
590 return ERR_MEM;
591}
@ sent
Definition: SystemMenu.c:27
static void LibTCPSendCallback(void *arg)
Definition: tcp.c:498
GLenum GLsizei len
Definition: glext.h:6722
int const JOCTET * dataptr
Definition: jpeglib.h:1031

Referenced by TCPSendData(), and TCPSendEventHandler().

◆ LibTCPSendCallback()

static void LibTCPSendCallback ( void arg)
static

Definition at line 498 of file tcp.c.

499{
500 struct lwip_callback_msg *msg = arg;
501 PTCP_PCB pcb = msg->Input.Send.Connection->SocketContext;
502 ULONG SendLength;
503 UCHAR SendFlags;
504
505 ASSERT(msg);
506
507 if (!msg->Input.Send.Connection->SocketContext)
508 {
509 msg->Output.Send.Error = ERR_CLSD;
510 goto done;
511 }
512
513 if (msg->Input.Send.Connection->SendShutdown)
514 {
515 msg->Output.Send.Error = ERR_CLSD;
516 goto done;
517 }
518
519 SendFlags = TCP_WRITE_FLAG_COPY;
520 SendLength = msg->Input.Send.DataLength;
521 if (tcp_sndbuf(pcb) == 0)
522 {
523 /* No buffer space so return pending */
524 msg->Output.Send.Error = ERR_INPROGRESS;
525 goto done;
526 }
527 else if (tcp_sndbuf(pcb) < SendLength)
528 {
529 /* We've got some room so let's send what we can */
530 SendLength = tcp_sndbuf(pcb);
531
532 /* Don't set the push flag */
533 SendFlags |= TCP_WRITE_FLAG_MORE;
534 }
535
536 msg->Output.Send.Error = tcp_write(pcb,
537 msg->Input.Send.Data,
538 SendLength,
539 SendFlags);
540 if (msg->Output.Send.Error == ERR_OK)
541 {
542 /* Queued successfully so try to send it */
543 tcp_output((PTCP_PCB)msg->Input.Send.Connection->SocketContext);
544 msg->Output.Send.Information = SendLength;
545 }
546 else if (msg->Output.Send.Error == ERR_MEM)
547 {
548 /* The queue is too long */
549 msg->Output.Send.Error = ERR_INPROGRESS;
550 }
551
552done:
554}
uint32_t ULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by LibTCPSend().

◆ LibTCPSetNoDelay()

void LibTCPSetNoDelay ( PTCP_PCB  pcb,
BOOLEAN  Set 
)

Definition at line 868 of file tcp.c.

871{
872 if (Set)
873 pcb->flags |= TF_NODELAY;
874 else
875 pcb->flags &= ~TF_NODELAY;
876}
static BOOL Set
Definition: pageheap.c:10

Referenced by TCPSetNoDelay().

◆ LibTCPShutdown()

err_t LibTCPShutdown ( PCONNECTION_ENDPOINT  Connection,
const int  shut_rx,
const int  shut_tx 
)

Definition at line 717 of file tcp.c.

718{
719 struct lwip_callback_msg *msg;
720 err_t ret;
721
722 msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
723 if (msg)
724 {
726
727 msg->Input.Shutdown.Connection = Connection;
728 msg->Input.Shutdown.shut_rx = shut_rx;
729 msg->Input.Shutdown.shut_tx = shut_tx;
730
732
733 if (WaitForEventSafely(&msg->Event))
734 ret = msg->Output.Shutdown.Error;
735 else
736 ret = ERR_CLSD;
737
738 ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
739
740 return ret;
741 }
742
743 return ERR_MEM;
744}
static void LibTCPShutdownCallback(void *arg)
Definition: tcp.c:654

Referenced by DisconnectWorker(), and TCPDisconnect().

◆ LibTCPShutdownCallback()

static void LibTCPShutdownCallback ( void arg)
static

Definition at line 654 of file tcp.c.

655{
656 struct lwip_callback_msg *msg = arg;
657 PTCP_PCB pcb = msg->Input.Shutdown.Connection->SocketContext;
658
659 if (!msg->Input.Shutdown.Connection->SocketContext)
660 {
661 msg->Output.Shutdown.Error = ERR_CLSD;
662 goto done;
663 }
664
665 /* LwIP makes the (questionable) assumption that SHUTDOWN_RDWR is equivalent to tcp_close().
666 * This assumption holds even if the shutdown calls are done separately (even through multiple
667 * WinSock shutdown() calls). This assumption means that lwIP has the right to deallocate our
668 * PCB without telling us if we shutdown TX and RX. To avoid these problems, we'll clear the
669 * socket context if we have called shutdown for TX and RX.
670 */
671 if (msg->Input.Shutdown.shut_rx != msg->Input.Shutdown.shut_tx) {
672 if (msg->Input.Shutdown.shut_rx) {
673 msg->Output.Shutdown.Error = tcp_shutdown(pcb, TRUE, FALSE);
674 }
675 if (msg->Input.Shutdown.shut_tx) {
676 msg->Output.Shutdown.Error = tcp_shutdown(pcb, FALSE, TRUE);
677 }
678 }
679 else if (msg->Input.Shutdown.shut_rx) {
680 /* We received both RX and TX requests, which seems to mean closing connection from TDI.
681 * So call tcp_close, otherwise we risk to be put in TCP_WAIT_* states, which makes further
682 * attempts to close the socket to fail in this state.
683 */
684 msg->Output.Shutdown.Error = tcp_close(pcb);
685 }
686 else {
687 /* This case shouldn't happen */
688 DbgPrint("Requested socket shutdown(0, 0) !\n");
689 }
690
691 if (!msg->Output.Shutdown.Error)
692 {
693 if (msg->Input.Shutdown.shut_rx)
694 {
695 msg->Input.Shutdown.Connection->ReceiveShutdown = TRUE;
696 msg->Input.Shutdown.Connection->ReceiveShutdownStatus = STATUS_FILE_CLOSED;
697 }
698
699 if (msg->Input.Shutdown.shut_tx)
700 msg->Input.Shutdown.Connection->SendShutdown = TRUE;
701
702 if (msg->Input.Shutdown.Connection->ReceiveShutdown &&
703 msg->Input.Shutdown.Connection->SendShutdown)
704 {
705 /* The PCB is not ours anymore */
706 msg->Input.Shutdown.Connection->SocketContext = NULL;
707 tcp_arg(pcb, NULL);
708 TCPFinEventHandler(msg->Input.Shutdown.Connection, ERR_CLSD);
709 }
710 }
711
712done:
714}
#define STATUS_FILE_CLOSED
Definition: ntstatus.h:532
void tcp_shutdown(struct sock *sk, int how)

Referenced by LibTCPShutdown().

◆ LibTCPSocket()

struct tcp_pcb * LibTCPSocket ( void arg)

Definition at line 336 of file tcp.c.

337{
338 struct lwip_callback_msg *msg = ExAllocateFromNPagedLookasideList(&MessageLookasideList);
339 struct tcp_pcb *ret;
340
341 if (msg)
342 {
344 msg->Input.Socket.Arg = arg;
345
347
348 if (WaitForEventSafely(&msg->Event))
349 ret = msg->Output.Socket.NewPcb;
350 else
351 ret = NULL;
352
353 ExFreeToNPagedLookasideList(&MessageLookasideList, msg);
354
355 return ret;
356 }
357
358 return NULL;
359}
static void LibTCPSocketCallback(void *arg)
Definition: tcp.c:318

Referenced by TCPSocket().

◆ LibTCPSocketCallback()

static void LibTCPSocketCallback ( void arg)
static

Definition at line 318 of file tcp.c.

319{
320 struct lwip_callback_msg *msg = arg;
321
322 ASSERT(msg);
323
324 msg->Output.Socket.NewPcb = tcp_new();
325
326 if (msg->Output.Socket.NewPcb)
327 {
328 tcp_arg(msg->Output.Socket.NewPcb, msg->Input.Socket.Arg);
329 tcp_err(msg->Output.Socket.NewPcb, InternalErrorEventHandler);
330 }
331
333}

Referenced by LibTCPSocket().

◆ TCPTranslateError()

NTSTATUS TCPTranslateError ( const err_t  err)

Definition at line 267 of file tcp.c.

268{
270
271 switch (err)
272 {
273 case ERR_OK: Status = STATUS_SUCCESS; return Status; //0
274 case ERR_MEM: Status = STATUS_INSUFFICIENT_RESOURCES; break; //-1
275 case ERR_BUF: Status = STATUS_BUFFER_TOO_SMALL; break; //-2
276 case ERR_TIMEOUT: Status = STATUS_TIMEOUT; break; // -3
277 case ERR_RTE: Status = STATUS_NETWORK_UNREACHABLE; break; //-4
278 case ERR_INPROGRESS: Status = STATUS_PENDING; return Status; //-5
279 case ERR_VAL: Status = STATUS_INVALID_PARAMETER; break; //-6
280 case ERR_WOULDBLOCK: Status = STATUS_CANT_WAIT; break; //-7
281 case ERR_USE: Status = STATUS_ADDRESS_ALREADY_EXISTS; break; //-8
282 case ERR_ISCONN: Status = STATUS_UNSUCCESSFUL; break; //-9 (FIXME)
283 case ERR_ABRT: Status = STATUS_LOCAL_DISCONNECT; break; //-10
284 case ERR_RST: Status = STATUS_REMOTE_DISCONNECT; break; //-11
285 case ERR_CLSD: Status = STATUS_FILE_CLOSED; break; //-12
286 case ERR_CONN: Status = STATUS_INVALID_CONNECTION; break; //-13
287 case ERR_ARG: Status = STATUS_INVALID_PARAMETER; break; //-14
288 case ERR_IF: Status = STATUS_UNEXPECTED_NETWORK_ERROR; break; //-15
289 default:
290 DbgPrint("Invalid error value: %d\n", err);
291 ASSERT(FALSE);
293 break;
294 }
295
296 TI_DbgPrint(DEBUG_TCP,("TCP operation failed: 0x%x (%d)\n", Status, err));
297
298 return Status;
299}
#define DEBUG_TCP
Definition: debug.h:28
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
#define ERR_ABRT
Definition: err.h:65
#define ERR_RST
Definition: err.h:66
#define ERR_ISCONN
Definition: err.h:61
#define ERR_USE
Definition: err.h:60
#define ERR_ARG
Definition: err.h:70
#define ERR_CONN
Definition: err.h:68
#define ERR_RTE
Definition: err.h:56
#define ERR_WOULDBLOCK
Definition: err.h:59
#define ERR_VAL
Definition: err.h:58
#define ERR_BUF
Definition: err.h:54
#define ERR_TIMEOUT
Definition: err.h:55
#define ERR_IF
Definition: err.h:72
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_NETWORK_UNREACHABLE
Definition: ntstatus.h:704
#define STATUS_CANT_WAIT
Definition: ntstatus.h:452
#define STATUS_ADDRESS_ALREADY_EXISTS
Definition: ntstatus.h:654
#define STATUS_REMOTE_DISCONNECT
Definition: ntstatus.h:552
#define STATUS_INVALID_CONNECTION
Definition: ntstatus.h:556
#define STATUS_UNEXPECTED_NETWORK_ERROR
Definition: ntstatus.h:432
#define STATUS_LOCAL_DISCONNECT
Definition: ntstatus.h:551
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by DisconnectWorker(), InternalErrorEventHandler(), TCPConnect(), TCPDisconnect(), TCPGetSockAddress(), and TCPSendData().

◆ WaitForEventSafely()

static BOOLEAN WaitForEventSafely ( PRKEVENT  Event)
static

Definition at line 176 of file tcp.c.

177{
178 PVOID WaitObjects[] = {Event, &TerminationEvent};
179
181 WaitObjects,
182 WaitAny,
183 Executive,
185 FALSE,
186 NULL,
188 {
189 /* Signalled by the caller's event */
190 return TRUE;
191 }
192 else /* if KeWaitForMultipleObjects() == STATUS_WAIT_1 */
193 {
194 /* Signalled by our termination event */
195 return FALSE;
196 }
197}
KEVENT TerminationEvent
Definition: sys_arch.c:9
#define KernelMode
Definition: asm.h:34
@ WaitAny
NTSTATUS NTAPI KeWaitForMultipleObjects(IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PKWAIT_BLOCK WaitBlockArray OPTIONAL)
Definition: wait.c:586
#define STATUS_WAIT_0
Definition: ntstatus.h:237
@ Executive
Definition: ketypes.h:415

Referenced by LibTCPBind(), LibTCPClose(), LibTCPConnect(), LibTCPFreeSocket(), LibTCPListen(), LibTCPSend(), LibTCPShutdown(), and LibTCPSocket().

Variable Documentation

◆ MessageLookasideList

◆ QueueEntryLookasideList

NPAGED_LOOKASIDE_LIST QueueEntryLookasideList
extern

◆ tcp_state_str

const char* const tcp_state_str[]
static
Initial value:
= {
"CLOSED",
"LISTEN",
"SYN_SENT",
"SYN_RCVD",
"ESTABLISHED",
"FIN_WAIT_1",
"FIN_WAIT_2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"
}

Definition at line 6 of file tcp.c.

Referenced by LibTCPDumpPcb().

◆ TerminationEvent

KEVENT TerminationEvent
extern