2 #include "lwip/tcpip.h"
8 static const char * const tcp_state_str
[] = {
22 /* The way that lwIP does multi-threading is really not ideal for our purposes but
23 * we best go along with it unless we want another unstable TCP library. lwIP uses
24 * a thread called the "tcpip thread" which is the only one allowed to call raw API
25 * functions. Since this is the case, for each of our LibTCP* functions, we queue a request
26 * for a callback to "tcpip thread" which calls our LibTCP*Callback functions. Yes, this is
27 * a lot of unnecessary thread swapping and it could definitely be faster, but I don't want
28 * to going messing around in lwIP because I have no desire to create another mess like oskittcp */
30 extern KEVENT TerminationEvent
;
34 WaitForEventSafely(PRKEVENT Event
)
36 PVOID WaitObjects
[] = {Event
, &TerminationEvent
};
38 if (KeWaitForMultipleObjects(2,
45 NULL
) == STATUS_WAIT_0
)
47 /* Signalled by the caller's event */
50 else /* if KeWaitForMultipleObjects() == STATUS_WAIT_1 */
52 /* Signalled by our termination event */
59 InternalSendEventHandler(void *arg
, struct tcp_pcb
*pcb
, u16_t space
)
61 DbgPrint("[lwIP, InternalSendEventHandler] SendEvent (0x%x, 0x%x, %d)\n",
62 arg
, pcb
, (unsigned int)space
);
64 /* Make sure the socket didn't get closed */
65 if (!arg
) return ERR_OK
;
67 TCPSendEventHandler(arg
, space
);
74 InternalRecvEventHandler(void *arg
, struct tcp_pcb
*pcb
, struct pbuf
*p
, err_t err
)
78 DbgPrint("[lwIP, InternalRecvEventHandler] RecvEvent (0x%x, 0x%x, 0x%x, %d)\n",
79 arg
, pcb
, p
, (unsigned int)err
);
81 /* Make sure the socket didn't get closed */
90 TCPFinEventHandler(arg
, ERR_OK
);
94 DbgPrint("[lwIP, InternalRecvEventHandler] RECV - p:0x%x p->payload:0x%x p->len:%d p->tot_len:%d\n",
95 p
, p
->payload
, p
->len
, p
->tot_len
);
99 len
= TCPRecvEventHandler(arg
, p
);
102 tcp_recved(pcb
, len
);
110 /* We want lwIP to store the pbuf on its queue for later */
125 InternalAcceptEventHandler(void *arg
, struct tcp_pcb
*newpcb
, err_t err
)
127 DbgPrint("[lwIP, InternalAcceptEventHandler] AcceptEvent (0x%x, 0x%x, %d)\n",
128 arg
, newpcb
, (unsigned int)err
);
130 /* Make sure the socket didn't get closed */
134 DbgPrint("[lwIP, InternalAcceptEventHandler] newpcb->state = %s\n",
135 tcp_state_str
[newpcb
->state
]);
137 TCPAcceptEventHandler(arg
, newpcb
);
139 /* Set in LibTCPAccept (called from TCPAcceptEventHandler) */
140 if (newpcb
->callback_arg
)
148 InternalConnectEventHandler(void *arg
, struct tcp_pcb
*pcb
, err_t err
)
150 DbgPrint("[lwIP, InternalConnectEventHandler] ConnectEvent(0x%x, 0x%x, %d)\n",
151 arg
, pcb
, (unsigned int)err
);
153 /* Make sure the socket didn't get closed */
157 TCPConnectEventHandler(arg
, err
);
159 tcp_recv(pcb
, InternalRecvEventHandler
);
166 InternalErrorEventHandler(void *arg
, err_t err
)
168 DbgPrint("[lwIP, InternalErrorEventHandler] ErrorEvent(0x%x, %d)\n",
169 arg
, (unsigned int)err
);
171 /* Make sure the socket didn't get closed */
174 TCPFinEventHandler(arg
, err
);
177 struct socket_callback_msg
179 /* Synchronization */
191 LibTCPSocketCallback(void *arg
)
193 struct socket_callback_msg
*msg
= arg
;
197 msg
->NewPcb
= tcp_new();
201 tcp_arg((struct tcp_pcb
*)msg
->NewPcb
, msg
->Arg
);
202 tcp_err((struct tcp_pcb
*)msg
->NewPcb
, InternalErrorEventHandler
);
205 KeSetEvent(&msg
->Event
, IO_NO_INCREMENT
, FALSE
);
209 LibTCPSocket(void *arg
)
211 struct socket_callback_msg
*msg
= ExAllocatePool(NonPagedPool
, sizeof(struct socket_callback_msg
));
216 KeInitializeEvent(&msg
->Event
, NotificationEvent
, FALSE
);
219 tcpip_callback_with_block(LibTCPSocketCallback
, msg
, 1);
221 if (WaitForEventSafely(&msg
->Event
))
226 DbgPrint("[lwIP, LibTCPSocket] (0x%x) = 0x%x\n", arg
, ret
);
230 return (struct tcp_pcb
*)ret
;
236 struct bind_callback_msg
238 /* Synchronization */
243 struct ip_addr
*IpAddress
;
252 LibTCPBindCallback(void *arg
)
254 struct bind_callback_msg
*msg
= arg
;
258 msg
->Error
= tcp_bind(msg
->Pcb
, msg
->IpAddress
, ntohs(msg
->Port
));
260 KeSetEvent(&msg
->Event
, IO_NO_INCREMENT
, FALSE
);
264 LibTCPBind(struct tcp_pcb
*pcb
, struct ip_addr
*ipaddr
, u16_t port
)
266 struct bind_callback_msg
*msg
;
272 DbgPrint("[lwIP, LibTCPBind] Called\n");
274 msg
= ExAllocatePool(NonPagedPool
, sizeof(struct bind_callback_msg
));
277 KeInitializeEvent(&msg
->Event
, NotificationEvent
, FALSE
);
279 msg
->IpAddress
= ipaddr
;
282 tcpip_callback_with_block(LibTCPBindCallback
, msg
, 1);
284 if (WaitForEventSafely(&msg
->Event
))
289 DbgPrint("[lwIP, LibTCPBind] pcb = 0x%x\n", pcb
);
291 DbgPrint("[lwIP, LibTCPBind] Done\n");
301 struct listen_callback_msg
303 /* Synchronization */
311 struct tcp_pcb
*NewPcb
;
316 LibTCPListenCallback(void *arg
)
318 struct listen_callback_msg
*msg
= arg
;
323 DbgPrint("[lwIP, LibTCPListenCallback] Called\n");
325 p
= msg
->Pcb
->callback_arg
;
326 msg
->NewPcb
= tcp_listen_with_backlog(msg
->Pcb
, msg
->Backlog
);
330 tcp_arg(msg
->NewPcb
, p
);
331 tcp_accept(msg
->NewPcb
, InternalAcceptEventHandler
);
332 tcp_err(msg
->NewPcb
, InternalErrorEventHandler
);
335 DbgPrint("[lwIP, LibTCPListenCallback] Done\n");
337 KeSetEvent(&msg
->Event
, IO_NO_INCREMENT
, FALSE
);
341 LibTCPListen(struct tcp_pcb
*pcb
, u8_t backlog
)
343 struct listen_callback_msg
*msg
;
346 DbgPrint("[lwIP, LibTCPListen] Called\n");
351 msg
= ExAllocatePool(NonPagedPool
, sizeof(struct listen_callback_msg
));
354 KeInitializeEvent(&msg
->Event
, NotificationEvent
, FALSE
);
356 msg
->Backlog
= backlog
;
358 tcpip_callback_with_block(LibTCPListenCallback
, msg
, 1);
360 if (WaitForEventSafely(&msg
->Event
))
365 DbgPrint("[lwIP, LibTCPListen] pcb = 0x%x \n", pcb
);
367 DbgPrint("[lwIP, LibTCPListen] Done\n");
377 struct send_callback_msg
379 /* Synchronization */
393 LibTCPSendCallback(void *arg
)
395 struct send_callback_msg
*msg
= arg
;
399 if (tcp_sndbuf(msg
->Pcb
) < msg
->DataLength
)
401 msg
->Error
= ERR_INPROGRESS
;
405 tcp_sent(msg
->Pcb
, InternalSendEventHandler
);
407 msg
->Error
= tcp_write(msg
->Pcb
, msg
->Data
, msg
->DataLength
, TCP_WRITE_FLAG_COPY
);
409 tcp_output(msg
->Pcb
);
412 KeSetEvent(&msg
->Event
, IO_NO_INCREMENT
, FALSE
);
416 LibTCPSend(struct tcp_pcb
*pcb
, void *dataptr
, u16_t len
)
418 struct send_callback_msg
*msg
;
424 msg
= ExAllocatePool(NonPagedPool
, sizeof(struct send_callback_msg
));
427 KeInitializeEvent(&msg
->Event
, NotificationEvent
, FALSE
);
430 msg
->DataLength
= len
;
432 tcpip_callback_with_block(LibTCPSendCallback
, msg
, 1);
434 if (WaitForEventSafely(&msg
->Event
))
439 DbgPrint("LibTCPSend(0x%x)\n", pcb
);
449 struct connect_callback_msg
451 /* Synchronization */
456 struct ip_addr
*IpAddress
;
465 LibTCPConnectCallback(void *arg
)
467 struct connect_callback_msg
*msg
= arg
;
469 DbgPrint("[lwIP, LibTCPConnectCallback] Called\n");
473 msg
->Error
= tcp_connect(msg
->Pcb
, msg
->IpAddress
, ntohs(msg
->Port
), InternalConnectEventHandler
);
474 if (msg
->Error
== ERR_OK
)
475 msg
->Error
= ERR_INPROGRESS
;
477 KeSetEvent(&msg
->Event
, IO_NO_INCREMENT
, FALSE
);
479 DbgPrint("[lwIP, LibTCPConnectCallback] Done\n");
483 LibTCPConnect(struct tcp_pcb
*pcb
, struct ip_addr
*ipaddr
, u16_t port
)
485 struct connect_callback_msg
*msg
;
488 DbgPrint("[lwIP, LibTCPConnect] Called\n");
493 msg
= ExAllocatePool(NonPagedPool
, sizeof(struct connect_callback_msg
));
496 KeInitializeEvent(&msg
->Event
, NotificationEvent
, FALSE
);
498 msg
->IpAddress
= ipaddr
;
501 tcpip_callback_with_block(LibTCPConnectCallback
, msg
, 1);
503 if (WaitForEventSafely(&msg
->Event
))
510 DbgPrint("[lwIP, LibTCPConnect] pcb = 0x%x\n", pcb
);
512 DbgPrint("[lwIP, LibTCPConnect] Done\n");
520 struct close_callback_msg
522 /* Synchronization */
534 LibTCPCloseCallback(void *arg
)
536 struct close_callback_msg
*msg
= arg
;
538 msg
->Error
= tcp_close(msg
->Pcb
);
540 KeSetEvent(&msg
->Event
, IO_NO_INCREMENT
, FALSE
);
544 LibTCPClose(struct tcp_pcb
*pcb
)
546 struct close_callback_msg
*msg
;
549 DbgPrint("[lwIP, LibTCPClose] Called\n");
553 DbgPrint("[lwIP, LibTCPClose] Done... NO pcb\n");
557 DbgPrint("[lwIP, LibTCPClose] Removing pcb callbacks\n");
563 tcp_accept(pcb
, NULL
);
565 DbgPrint("[lwIP, LibTCPClose] Attempting to allocate memory for msg\n");
567 msg
= ExAllocatePool(NonPagedPool
, sizeof(struct close_callback_msg
));
570 DbgPrint("[lwIP, LibTCPClose] Initializing msg->Event\n");
571 KeInitializeEvent(&msg
->Event
, NotificationEvent
, FALSE
);
573 DbgPrint("[lwIP, LibTCPClose] Initializing msg->pcb = 0x%x\n", pcb
);
576 DbgPrint("[lwIP, LibTCPClose] Attempting to call LibTCPCloseCallback\n");
578 tcpip_callback_with_block(LibTCPCloseCallback
, msg
, 1);
580 if (WaitForEventSafely(&msg
->Event
))
587 DbgPrint("[lwIP, LibTCPClose] pcb = 0x%x\n", pcb
);
589 DbgPrint("[lwIP, LibTCPClose] Done\n");
594 DbgPrint("[lwIP, LibTCPClose] Failed to allocate memory\n");
600 LibTCPAccept(struct tcp_pcb
*pcb
, struct tcp_pcb
*listen_pcb
, void *arg
)
602 DbgPrint("[lwIP, LibTCPAccept] Called. (pcb, arg) = (0x%x, 0x%x)\n", pcb
, arg
);
607 tcp_recv(pcb
, InternalRecvEventHandler
);
608 tcp_sent(pcb
, InternalSendEventHandler
);
611 tcp_accepted(listen_pcb
);
613 DbgPrint("[lwIP, LibTCPAccept] Done\n");
617 LibTCPGetHostName(struct tcp_pcb
*pcb
, struct ip_addr
*ipaddr
, u16_t
*port
)
619 DbgPrint("[lwIP, LibTCPGetHostName] Called. pcb = (0x%x)\n", pcb
);
624 *ipaddr
= pcb
->local_ip
;
625 *port
= pcb
->local_port
;
627 DbgPrint("[lwIP, LibTCPGetHostName] Got host port: %d\n", *port
);
629 DbgPrint("[lwIP, LibTCPGetHostName] Done\n");
635 LibTCPGetPeerName(struct tcp_pcb
*pcb
, struct ip_addr
*ipaddr
, u16_t
*port
)
637 DbgPrint("[lwIP, LibTCPGetPeerName] pcb = (0x%x)\n", pcb
);
642 *ipaddr
= pcb
->remote_ip
;
643 *port
= pcb
->remote_port
;
645 DbgPrint("[lwIP, LibTCPGetPeerName] Got remote port: %d\n", *port
);