From af8cd05c9921f9187aea01b0f729f7820c84b43c Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Sat, 25 Dec 2004 21:30:20 +0000 Subject: [PATCH] Added a (currently unworking) accept implementation. Needs work, but doesn't break anything. Committed a patch by GvG: - SignalSocket: Removed collected parameter, changed Information to actual number of bytes returned. svn path=/trunk/; revision=12333 --- reactos/drivers/lib/ip/makefile | 4 +- reactos/drivers/lib/ip/transport/tcp/accept.c | 157 ++++++++++++++ reactos/drivers/lib/ip/transport/tcp/event.c | 8 + reactos/drivers/lib/ip/transport/tcp/tcp.c | 116 ++++------ .../drivers/lib/oskittcp/include/oskittcp.h | 6 + .../drivers/lib/oskittcp/oskittcp/interface.c | 120 ++++++++++- reactos/drivers/lib/oskittcp/oskittcp/sleep.c | 7 +- .../drivers/lib/oskittcp/oskittcp/uipc_mbuf.c | 2 +- .../lib/oskittcp/oskittcp/uipc_socket.c | 4 +- reactos/drivers/net/afd/afd/connect.c | 45 ++-- reactos/drivers/net/afd/afd/listen.c | 203 +++++++++++++++++- reactos/drivers/net/afd/afd/lock.c | 5 +- reactos/drivers/net/afd/afd/main.c | 14 +- reactos/drivers/net/afd/afd/select.c | 21 +- reactos/drivers/net/afd/afd/tdi.c | 3 +- reactos/drivers/net/afd/include/afd.h | 29 ++- reactos/drivers/net/tcpip/datalink/lan.c | 7 +- reactos/drivers/net/tcpip/include/tcp.h | 21 +- reactos/drivers/net/tcpip/include/titypes.h | 31 +-- reactos/drivers/net/tcpip/makefile | 3 +- reactos/drivers/net/tcpip/tcpip/dispatch.c | 54 ++++- reactos/drivers/net/tcpip/tcpip/fileobjs.c | 3 + reactos/drivers/net/tcpip/tcpip/main.c | 5 +- 23 files changed, 691 insertions(+), 177 deletions(-) create mode 100644 reactos/drivers/lib/ip/transport/tcp/accept.c diff --git a/reactos/drivers/lib/ip/makefile b/reactos/drivers/lib/ip/makefile index 8ec4780308a..249ab0b3f96 100644 --- a/reactos/drivers/lib/ip/makefile +++ b/reactos/drivers/lib/ip/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.9 2004/11/30 00:10:40 arty Exp $ +# $Id: makefile,v 1.10 2004/12/25 21:30:18 arty Exp $ PATH_TO_TOP = ../../.. @@ -11,7 +11,6 @@ TARGET_PCH = $(PATH_TO_TOP)/drivers/lib/ip/include/precomp.h # -DMEMTRACK TARGET_CFLAGS = \ -D__USE_W32API \ - -DMEMTRACK \ -D__NTDRIVER__ \ -D_SEH_NO_NATIVE_NLG \ -Wall -Werror \ @@ -40,6 +39,7 @@ TARGET_OBJECTS = \ network/routines.o \ network/transmit.o \ transport/rawip/rawip.o \ + transport/tcp/accept.o \ transport/tcp/event.o \ transport/tcp/if.o \ transport/tcp/tcp.o \ diff --git a/reactos/drivers/lib/ip/transport/tcp/accept.c b/reactos/drivers/lib/ip/transport/tcp/accept.c new file mode 100644 index 00000000000..1b79bed5aa3 --- /dev/null +++ b/reactos/drivers/lib/ip/transport/tcp/accept.c @@ -0,0 +1,157 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: transport/tcp/tcp.c + * PURPOSE: Transmission Control Protocol Listen/Accept code + * PROGRAMMERS: Art Yerkes (arty@users.sf.net) + * REVISIONS: + * arty 12/21/2004 Created + */ + +#include "precomp.h" + +NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener, + PCONNECTION_ENDPOINT Connection, + PTDI_REQUEST_KERNEL Request ) { + NTSTATUS Status; + SOCKADDR_IN OutAddr; + OSK_UINT OutAddrLen; + PTA_ADDRESS RequestAddressReturn; + SOCKADDR_IN AddressConnecting; + PTDI_CONNECTION_INFORMATION WhoIsConnecting; + + /* Unpack TDI info -- We need the return connection information + * struct to return the address so it can be filtered if needed + * by WSAAccept -- The returned address will be passed on to + * userland after we complete this irp */ + WhoIsConnecting = (PTDI_CONNECTION_INFORMATION) + Request->ReturnConnectionInformation; + + Status = TCPTranslateError + ( OskitTCPAccept( Listener->SocketContext, + &Connection->SocketContext, + &OutAddr, + sizeof(OutAddr), + &OutAddrLen, + Request->RequestFlags & TDI_QUERY_ACCEPT ? 0 : 1 ) ); + + TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status)); + + if( NT_SUCCESS(Status) && Status != STATUS_PENDING ) { + TI_DbgPrint(DEBUG_TCP,("Copying address to %x (Who %x)\n", + RequestAddressReturn, WhoIsConnecting)); + + RequestAddressReturn = (PTA_ADDRESS)WhoIsConnecting->RemoteAddress; + RequestAddressReturn->AddressLength = OutAddrLen; + RequestAddressReturn->AddressType = + AddressConnecting.sin_family; + TI_DbgPrint(DEBUG_TCP,("Copying address proper: from %x to %x,%x\n", + ((PCHAR)&AddressConnecting) + + sizeof(AddressConnecting.sin_family), + RequestAddressReturn->Address, + RequestAddressReturn->AddressLength)); + RtlCopyMemory( RequestAddressReturn->Address, + ((PCHAR)&AddressConnecting) + + sizeof(AddressConnecting.sin_family), + RequestAddressReturn->AddressLength ); + TI_DbgPrint(DEBUG_TCP,("Done copying\n")); + } + + TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status)); + + return Status; +} + +/* This listen is on a socket we keep as internal. That socket has the same + * lifetime as the address file */ +NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) { + NTSTATUS Status = STATUS_SUCCESS; + SOCKADDR_IN AddressToBind; + + TI_DbgPrint(DEBUG_TCP,("TCPListen started\n")); + + TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n", + Connection->SocketContext)); + + ASSERT(Connection); + ASSERT_KM_POINTER(Connection->SocketContext); + ASSERT_KM_POINTER(Connection->AddressFile); + + TcpipRecursiveMutexEnter( &TCPLock, TRUE ); + + AddressToBind.sin_family = AF_INET; + memcpy( &AddressToBind.sin_addr, + &Connection->AddressFile->Address.Address.IPv4Address, + sizeof(AddressToBind.sin_addr) ); + AddressToBind.sin_port = Connection->AddressFile->Port; + + TI_DbgPrint(DEBUG_TCP,("AddressToBind - %x:%x\n", AddressToBind.sin_addr, AddressToBind.sin_port)); + + OskitTCPBind( Connection->SocketContext, + Connection, + &AddressToBind, + sizeof(AddressToBind) ); + + Status = TCPTranslateError( OskitTCPListen( Connection->SocketContext, + Backlog ) ); + + TcpipRecursiveMutexLeave( &TCPLock ); + + TI_DbgPrint(DEBUG_TCP,("TCPListen finished %x\n", Status)); + + return Status; +} + +VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener, + PCONNECTION_ENDPOINT Connection ) { + PLIST_ENTRY ListEntry; + PTDI_BUCKET Bucket; + + TcpipRecursiveMutexEnter( &TCPLock, TRUE ); + + for( ListEntry = Listener->ListenRequest.Flink; + ListEntry != &Listener->ListenRequest; + ListEntry = ListEntry->Flink ) { + Bucket = CONTAINING_RECORD(ListEntry, TDI_BUCKET, Entry); + + if( Bucket->Request.Handle.ConnectionContext == Connection ) { +#ifdef MEMTRACK + UntrackFL( __FILE__, __LINE__, Bucket->Request.RequestContext ); +#endif + RemoveEntryList( ListEntry ); + ExFreePool( Bucket ); + } + } + + TcpipRecursiveMutexLeave( &TCPLock ); +} + +NTSTATUS TCPAccept +( PTDI_REQUEST Request, + PCONNECTION_ENDPOINT Listener, + PCONNECTION_ENDPOINT Connection, + PTCP_COMPLETION_ROUTINE Complete, + PVOID Context ) { + NTSTATUS Status; + PTDI_BUCKET Bucket; + + TI_DbgPrint(DEBUG_TCP,("TCPAccept started\n")); + + TcpipRecursiveMutexEnter( &TCPLock, TRUE ); + + Status = TCPServiceListeningSocket( Listener, Connection, + (PTDI_REQUEST_KERNEL)Request ); + + if( Status == STATUS_PENDING ) { + Bucket = ExAllocatePool( NonPagedPool, sizeof(*Bucket) ); + Bucket->AssociatedEndpoint = Connection; + Bucket->Request.RequestNotifyObject = Complete; + Bucket->Request.RequestContext = Context; + InsertHeadList( &Listener->ListenRequest, &Bucket->Entry ); + } + + TcpipRecursiveMutexLeave( &TCPLock ); + + TI_DbgPrint(DEBUG_TCP,("TCPAccept finished %x\n", Status)); + return Status; +} diff --git a/reactos/drivers/lib/ip/transport/tcp/event.c b/reactos/drivers/lib/ip/transport/tcp/event.c index fe2d8e02597..401d4444b9c 100644 --- a/reactos/drivers/lib/ip/transport/tcp/event.c +++ b/reactos/drivers/lib/ip/transport/tcp/event.c @@ -18,6 +18,12 @@ int TCPSocketState(void *ClientData, OSK_UINT NewState ) { PCONNECTION_ENDPOINT Connection = WhichConnection; + TI_DbgPrint(MID_TRACE,("Flags: %c%c%c%c\n", + NewState & SEL_CONNECT ? 'C' : 'c', + NewState & SEL_READ ? 'R' : 'r', + NewState & SEL_FIN ? 'F' : 'f', + NewState & SEL_ACCEPT ? 'A' : 'a')); + TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n", NewState, Connection, Connection ? Connection->State ^ NewState : @@ -33,6 +39,8 @@ int TCPSocketState(void *ClientData, TI_DbgPrint(DEBUG_TCP,("Found socket %x\n", Connection)); } + TI_DbgPrint(MID_TRACE,("Connection signalled: %d\n", + Connection->Signalled)); if( !Connection->Signalled ) { Connection->Signalled = TRUE; Connection->SignalState = NewState; diff --git a/reactos/drivers/lib/ip/transport/tcp/tcp.c b/reactos/drivers/lib/ip/transport/tcp/tcp.c index 7a58e6334db..c46b8ce7fa5 100644 --- a/reactos/drivers/lib/ip/transport/tcp/tcp.c +++ b/reactos/drivers/lib/ip/transport/tcp/tcp.c @@ -4,8 +4,10 @@ * FILE: transport/tcp/tcp.c * PURPOSE: Transmission Control Protocol * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * Art Yerkes (arty@users.sf.net) * REVISIONS: - * CSH 01/08-2000 Created + * CSH 01/08-2000 Created + * arty 12/21/2004 Added accept */ #include "precomp.h" @@ -25,11 +27,11 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection, PTCP_COMPLETION_ROUTINE Complete; PTDI_BUCKET Bucket; PLIST_ENTRY Entry; - BOOLEAN CompletedOne = FALSE; + PIRP Irp; + PMDL Mdl; /* Things that can happen when we try the initial connection */ if( ((NewState & SEL_CONNECT) || (NewState & SEL_FIN)) && - !(Connection->State & (SEL_CONNECT | SEL_FIN)) ) { while( !IsListEmpty( &Connection->ConnectRequest ) ) { Connection->State |= NewState & (SEL_CONNECT | SEL_FIN); @@ -45,27 +47,56 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection, } } + if( (NewState & SEL_ACCEPT) ) { + /* Handle readable on a listening socket -- + * TODO: Implement filtering + */ + + TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: %s)\n", + Connection, + IsListEmpty(&Connection->ListenRequest) ? + "empty" : "nonempty")); + + while( !IsListEmpty( &Connection->ListenRequest ) ) { + PIO_STACK_LOCATION IrpSp; + + Entry = RemoveHeadList( &Connection->ListenRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); + Complete = Bucket->Request.RequestNotifyObject; + + Irp = Bucket->Request.RequestContext; + IrpSp = IoGetCurrentIrpStackLocation( Irp ); + + TI_DbgPrint(DEBUG_TCP,("Getting the socket\n")); + Status = TCPServiceListeningSocket + ( Connection->AddressFile->Listener, + Bucket->AssociatedEndpoint, + (PTDI_REQUEST_KERNEL)&IrpSp->Parameters ); + + TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n")); + + if( Status == STATUS_PENDING ) { + InsertHeadList( &Connection->ListenRequest, &Bucket->Entry ); + break; + } else + Complete( Bucket->Request.RequestContext, Status, 0 ); + } + } + /* Things that happen after we're connected */ if( (NewState & SEL_READ) ) { TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n", IsListEmpty(&Connection->ReceiveRequest) ? "empty" : "nonempty")); - + while( !IsListEmpty( &Connection->ReceiveRequest ) ) { - PIRP Irp; OSK_UINT RecvLen = 0, Received = 0; OSK_PCHAR RecvBuffer = 0; - PMDL Mdl; - NTSTATUS Status; Entry = RemoveHeadList( &Connection->ReceiveRequest ); Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); Complete = Bucket->Request.RequestNotifyObject; - TI_DbgPrint(DEBUG_TCP, - ("Readable, Completing read request %x\n", - Bucket->Request)); - Irp = Bucket->Request.RequestContext; Mdl = Irp->MdlAddress; @@ -97,23 +128,17 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection, TI_DbgPrint(DEBUG_TCP,("Received %d bytes with status %x\n", Received, Status)); - TI_DbgPrint(DEBUG_TCP, - ("Completing Receive Request: %x\n", - Bucket->Request)); - Complete( Bucket->Request.RequestContext, STATUS_SUCCESS, Received ); - CompletedOne = TRUE; } else if( Status == STATUS_PENDING ) { - InsertHeadList( &Connection->ReceiveRequest, - &Bucket->Entry ); + InsertHeadList + ( &Connection->ReceiveRequest, &Bucket->Entry ); break; } else { TI_DbgPrint(DEBUG_TCP, ("Completing Receive request: %x %x\n", Bucket->Request, Status)); Complete( Bucket->Request.RequestContext, Status, 0 ); - CompletedOne = TRUE; } } } @@ -491,59 +516,6 @@ NTSTATUS TCPClose return Status; } -NTSTATUS TCPListen -( PCONNECTION_ENDPOINT Connection, - UINT Backlog, - PTCP_COMPLETION_ROUTINE Complete, - PVOID Context) { - NTSTATUS Status; - SOCKADDR_IN AddressToBind; - - TI_DbgPrint(DEBUG_TCP,("TCPListen started\n")); - - TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n", - Connection->SocketContext)); - - ASSERT(Connection); - ASSERT_KM_POINTER(Connection->SocketContext); - ASSERT_KM_POINTER(Connection->AddressFile); - - TcpipRecursiveMutexEnter( &TCPLock, TRUE ); - - AddressToBind.sin_family = AF_INET; - memcpy( &AddressToBind.sin_addr, - &Connection->AddressFile->Address.Address.IPv4Address, - sizeof(AddressToBind.sin_addr) ); - AddressToBind.sin_port = Connection->AddressFile->Port; - - TI_DbgPrint(DEBUG_TCP,("AddressToBind - %x:%x\n", AddressToBind.sin_addr, AddressToBind.sin_port)); - - OskitTCPBind( Connection->SocketContext, - Connection, - &AddressToBind, - sizeof(AddressToBind) ); - - Status = TCPTranslateError( OskitTCPListen( Connection->SocketContext, - Backlog ) ); - - TcpipRecursiveMutexLeave( &TCPLock ); - - TI_DbgPrint(DEBUG_TCP,("TCPListen finished %x\n", Status)); - - return Status; -} - -NTSTATUS TCPAccept -( PTDI_REQUEST Request, - VOID **NewSocketContext ) { - NTSTATUS Status; - - TI_DbgPrint(DEBUG_TCP,("TCPAccept started\n")); - Status = STATUS_UNSUCCESSFUL; - TI_DbgPrint(DEBUG_TCP,("TCPAccept finished %x\n", Status)); - return Status; -} - NTSTATUS TCPReceiveData ( PCONNECTION_ENDPOINT Connection, PNDIS_BUFFER Buffer, diff --git a/reactos/drivers/lib/oskittcp/include/oskittcp.h b/reactos/drivers/lib/oskittcp/include/oskittcp.h index bf7f5192b86..c8df57c37cf 100644 --- a/reactos/drivers/lib/oskittcp/include/oskittcp.h +++ b/reactos/drivers/lib/oskittcp/include/oskittcp.h @@ -133,6 +133,12 @@ extern int OskitTCPClose( void *socket ); extern int OskitTCPBind( void *socket, void *connection, void *nam, OSK_UINT namelen ); +extern int OskitTCPAccept( void *socket, void **new_socket, + void *addr_out, + OSK_UINT addr_len, + OSK_UINT *out_addr_len, + OSK_UINT finish_accept ); + extern int OskitTCPListen( void *socket, int backlog ); extern int OskitTCPRecv( void *connection, diff --git a/reactos/drivers/lib/oskittcp/oskittcp/interface.c b/reactos/drivers/lib/oskittcp/oskittcp/interface.c index 6dd4fb99a99..bb60fd5255a 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/interface.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/interface.c @@ -22,8 +22,8 @@ struct linker_set domain_set; OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 }; -//OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA; -OSK_UINT OskitDebugTraceLevel = 0; +OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA; +//OSK_UINT OskitDebugTraceLevel = 0; /* SPL */ unsigned cpl; @@ -119,6 +119,7 @@ int OskitTCPSocket( void *context, if( !error ) { so->so_connection = context; so->so_state = SS_NBIO; + so->so_error = 0; *aso = so; } return error; @@ -138,6 +139,8 @@ int OskitTCPRecv( void *connection, *OutLen = 0; + printf("so->so_state %x\n", ((struct socket *)connection)->so_state); + if( Flags & OSK_MSG_OOB ) tcp_flags |= MSG_OOB; if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT; if( Flags & OSK_MSG_PEEK ) tcp_flags |= MSG_PEEK; @@ -281,16 +284,117 @@ int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len, } int OskitTCPAccept( void *socket, + void **new_socket, void *AddrOut, OSK_UINT AddrLen, - OSK_UINT *OutAddrLen ) { - struct mbuf nam; - int error; + OSK_UINT *OutAddrLen, + OSK_UINT FinishAccepting ) { + struct socket *head = (void *)socket; + struct sockaddr *name = (struct sockaddr *)AddrOut; + struct socket **newso = (struct socket **)new_socket; + struct socket *so = socket; + struct sockaddr_in sa; + struct mbuf mnam; + int namelen = 0, error = 0, s; - nam.m_data = AddrOut; - nam.m_len = AddrLen; + OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Doing accept (Finish %d)\n", + FinishAccepting)); + + *OutAddrLen = AddrLen; - return soaccept( socket, &nam ); + if (name) + /* that's a copyin actually */ + namelen = *OutAddrLen; + + s = splnet(); + + OskitDumpBuffer( so, sizeof(*so) ); + +#if 0 + if ((head->so_options & SO_ACCEPTCONN) == 0) { + splx(s); + OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: head->so_options = %x, wanted bit %x\n", + head->so_options, SO_ACCEPTCONN)); + error = EINVAL; + goto out; + } +#endif + + OS_DbgPrint(OSK_MID_TRACE,("head->so_q = %x, head->so_state = %x\n", + head->so_q, head->so_state)); + + if ((head->so_state & SS_NBIO) && head->so_q == NULL) { + splx(s); + error = EWOULDBLOCK; + goto out; + } + + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + while (head->so_q == NULL && head->so_error == 0) { + if (head->so_state & SS_CANTRCVMORE) { + head->so_error = ECONNABORTED; + break; + } + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH, + "accept", 0); + if (error) { + splx(s); + goto out; + } + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + } + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + +#if 0 + if (head->so_error) { + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + error = head->so_error; + head->so_error = 0; + splx(s); + goto out; + } + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); +#endif + + /* + * At this point we know that there is at least one connection + * ready to be accepted. Remove it from the queue. + */ + so = head->so_q; + + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + if( FinishAccepting ) { + head->so_q = so->so_q; + head->so_qlen--; + + *newso = so; + + /*so->so_state &= ~SS_COMP;*/ + so->so_q = NULL; + + mnam.m_data = &sa; + mnam.m_len = sizeof(sa); + + (void) soaccept(so, &mnam); + + so->so_state = SS_NBIO | SS_ISCONNECTED; + + OskitDumpBuffer( so, sizeof(*so) ); + + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + if (name) { + /* check sa_len before it is destroyed */ + memcpy( AddrOut, &sa, AddrLen < sizeof(sa) ? AddrLen : sizeof(sa) ); + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + *OutAddrLen = namelen; /* copyout actually */ + } + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); + splx(s); + } +out: + OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Returning %d\n", error)); + return (error); } /* The story so far diff --git a/reactos/drivers/lib/oskittcp/oskittcp/sleep.c b/reactos/drivers/lib/oskittcp/oskittcp/sleep.c index 7a34a44a591..ec164404e80 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/sleep.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/sleep.c @@ -20,12 +20,17 @@ void wakeup( struct socket *so, void *token ) { OSK_UINT flags = 0; OS_DbgPrint - (OSK_MID_TRACE,("XXX Bytes to receive: %d\n", so->so_rcv.sb_cc)); + (OSK_MID_TRACE,("XXX Bytes to receive: %d state %x\n", + so->so_rcv.sb_cc, so->so_state)); if( so->so_state & SS_ISCONNECTED ) { OS_DbgPrint(OSK_MID_TRACE,("Socket connected!\n")); flags |= SEL_CONNECT; } + if( so->so_q ) { + OS_DbgPrint(OSK_MID_TRACE,("Socket accepting q\n")); + flags |= SEL_ACCEPT; + } if( so->so_rcv.sb_cc > 0 ) { OS_DbgPrint(OSK_MID_TRACE,("Socket readable\n")); flags |= SEL_READ; diff --git a/reactos/drivers/lib/oskittcp/oskittcp/uipc_mbuf.c b/reactos/drivers/lib/oskittcp/oskittcp/uipc_mbuf.c index 7b48b7e4f77..fa031f8ce7f 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/uipc_mbuf.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/uipc_mbuf.c @@ -330,7 +330,7 @@ m_copym(m, off0, len, wait) copyhdr = 1; while (off > 0) { if (m == 0) - panic("m_copym"); + panic("m_copym: %d", off); if (off < m->m_len) break; off -= m->m_len; diff --git a/reactos/drivers/lib/oskittcp/oskittcp/uipc_socket.c b/reactos/drivers/lib/oskittcp/oskittcp/uipc_socket.c index 0891134d64c..2c9408e0c96 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/uipc_socket.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/uipc_socket.c @@ -608,6 +608,8 @@ restart: } if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && (so->so_proto->pr_flags & PR_CONNREQUIRED)) { + printf("so: %x\n", so); + __asm__("int3"); error = ENOTCONN; goto release; } @@ -774,7 +776,7 @@ dontblock: * Keep sockbuf locked against other readers. */ while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 && - !sosendallatonce(so) && !nextrecord) { + !sosendallatonce(so) && !nextrecord) { if (so->so_error || so->so_state & SS_CANTRCVMORE) break; error = sbwait(&so->so_rcv); diff --git a/reactos/drivers/net/afd/afd/connect.c b/reactos/drivers/net/afd/afd/connect.c index 6885ecef6e9..5e9d4bb3e1d 100644 --- a/reactos/drivers/net/afd/afd/connect.c +++ b/reactos/drivers/net/afd/afd/connect.c @@ -1,4 +1,4 @@ -/* $Id: connect.c,v 1.9 2004/12/13 21:20:37 arty Exp $ +/* $Id: connect.c,v 1.10 2004/12/25 21:30:17 arty Exp $ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/net/afd/afd/connect.c @@ -40,12 +40,36 @@ NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) { return Status; } +NTSTATUS MakeSocketIntoConnection( PAFD_FCB FCB ) { + NTSTATUS Status; + + /* Allocate the receive area and start receiving */ + FCB->Recv.Window = + ExAllocatePool( NonPagedPool, FCB->Recv.Size ); + FCB->Send.Window = + ExAllocatePool( NonPagedPool, FCB->Send.Size ); + + FCB->State = SOCKET_STATE_CONNECTED; + + if( FCB->Recv.Window ) { + Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest, + FCB->Connection.Object, + TDI_RECEIVE_NORMAL, + FCB->Recv.Window, + FCB->Recv.Size, + &FCB->ReceiveIrp.Iosb, + ReceiveComplete, + FCB ); + } + + return Status; +} + NTSTATUS DDKAPI StreamSocketConnectComplete ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { NTSTATUS Status = Irp->IoStatus.Status; - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PAFD_FCB FCB = (PAFD_FCB)Context; PLIST_ENTRY NextIrpEntry; PIRP NextIrp; @@ -83,22 +107,7 @@ NTSTATUS DDKAPI StreamSocketConnectComplete } if( NT_SUCCESS(Status) ) { - /* Allocate the receive area and start receiving */ - FCB->Recv.Window = - ExAllocatePool( NonPagedPool, FCB->Recv.Size ); - FCB->Send.Window = - ExAllocatePool( NonPagedPool, FCB->Send.Size ); - - if( FCB->Recv.Window ) { - Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest, - IrpSp->FileObject, - TDI_RECEIVE_NORMAL, - FCB->Recv.Window, - FCB->Recv.Size, - &FCB->ReceiveIrp.Iosb, - ReceiveComplete, - FCB ); - } + Status = MakeSocketIntoConnection( FCB ); if( FCB->Send.Window && !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { diff --git a/reactos/drivers/net/afd/afd/listen.c b/reactos/drivers/net/afd/afd/listen.c index bb2cfcc9180..249346319ba 100644 --- a/reactos/drivers/net/afd/afd/listen.c +++ b/reactos/drivers/net/afd/afd/listen.c @@ -1,4 +1,4 @@ -/* $Id: listen.c,v 1.4 2004/09/05 04:26:29 arty Exp $ +/* $Id: listen.c,v 1.5 2004/12/25 21:30:17 arty Exp $ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/net/afd/afd/listen.c @@ -12,12 +12,54 @@ #include "tdiconn.h" #include "debug.h" +VOID SatisfyAccept( PIRP Irp, PFILE_OBJECT NewFileObject, + PAFD_TDI_OBJECT_QELT Qelt ) { + PAFD_FCB FCB = NewFileObject->FsContext; + + if( !SocketAcquireStateLock( FCB ) ) return; + + /* Transfer the connection to the new socket, launch the opening read */ + AFD_DbgPrint(MID_TRACE,("Completing a real accept (FCB %x)\n", FCB)); + + FCB->State = SOCKET_STATE_CONNECTED; + FCB->Connection = Qelt->Object; +#if 0 + FCB->RemoteAddress = + TaCopyTransportAddress( Qelt->ConnInfo->RemoteAddress ); +#endif + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); + + MakeSocketIntoConnection( FCB ); + + SocketStateUnlock( FCB ); +} + +VOID SatisfyPreAccept( PIRP Irp, PAFD_TDI_OBJECT_QELT Qelt ) { + PAFD_RECEIVED_ACCEPT_DATA ListenReceive = + (PAFD_RECEIVED_ACCEPT_DATA)Irp->AssociatedIrp.SystemBuffer; + + ListenReceive->SequenceNumber = Qelt->Seq; + AFD_DbgPrint(MID_TRACE,("Giving SEQ %d to userland\n", Qelt->Seq)); +#if 0 + TaCopyTransportAddressInPlace( &ListenReceive->Address, + Qelt->ConnInfo->RemoteAddress ); +#endif + + Irp->IoStatus.Information = sizeof(*ListenReceive); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); +} + NTSTATUS DDKAPI ListenComplete ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PAFD_FCB FCB = (PAFD_FCB)Context; + PAFD_TDI_OBJECT_QELT Qelt; if( !SocketAcquireStateLock( FCB ) ) return Status; @@ -31,7 +73,39 @@ NTSTATUS DDKAPI ListenComplete AFD_DbgPrint(MID_TRACE,("Completing listen request.\n")); AFD_DbgPrint(MID_TRACE,("IoStatus was %x\n", FCB->ListenIrp.Iosb.Status)); - AFD_DbgPrint(MID_TRACE,("Doing nothing as yet.\n")); + + Qelt = ExAllocatePool( NonPagedPool, sizeof(*Qelt) ); + if( !Qelt ) { + TdiCloseDevice( FCB->Connection.Handle, + FCB->Connection.Object ); + } else { + Qelt->Object = FCB->Connection; + Qelt->Seq = FCB->ConnSeq++; + InsertTailList( &FCB->PendingConnections, &Qelt->ListEntry ); + } + + /* Satisfy a pre-accept request if one is available */ + if( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_PREACCEPT] ) && + !IsListEmpty( &FCB->PendingConnections ) ) { + PLIST_ENTRY PendingIrp = + RemoveHeadList( &FCB->PendingIrpList[FUNCTION_PREACCEPT] ); + PLIST_ENTRY PendingConn = FCB->PendingConnections.Flink; + SatisfyPreAccept + ( CONTAINING_RECORD( PendingIrp, IRP, + Tail.Overlay.ListEntry ), + CONTAINING_RECORD( PendingConn, AFD_TDI_OBJECT_QELT, + ListEntry ) ); + } + + FCB->NeedsNewListen = TRUE; + + /* Trigger a select return if appropriate */ + if( !IsListEmpty( &FCB->PendingConnections ) ) { + FCB->PollState |= AFD_EVENT_ACCEPT; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } else { + FCB->PollState &= ~AFD_EVENT_ACCEPT; + } SocketStateUnlock( FCB ); @@ -61,17 +135,140 @@ NTSTATUS AfdListenSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB->DelayedAccept = ListenReq->UseDelayedAcceptance; + AFD_DbgPrint(MID_TRACE,("ADDRESSFILE: %x\n", FCB->AddressFile.Handle)); + Status = WarmSocketForConnection( FCB ); FCB->State = SOCKET_STATE_LISTENING; + AFD_DbgPrint(MID_TRACE,("Status from warmsocket %x\n", Status)); + + TdiBuildNullConnectionInfo + ( &FCB->ListenIrp.ConnectionCallInfo, + FCB->LocalAddress->Address[0].AddressType ); + TdiBuildNullConnectionInfo + ( &FCB->ListenIrp.ConnectionReturnInfo, + FCB->LocalAddress->Address[0].AddressType ); + Status = TdiListen( &FCB->ListenIrp.InFlightRequest, FCB->Connection.Object, - &FCB->ListenIrp.ConnectionInfo, + &FCB->ListenIrp.ConnectionCallInfo, + &FCB->ListenIrp.ConnectionReturnInfo, &FCB->ListenIrp.Iosb, ListenComplete, FCB ); + if( NT_SUCCESS(Status) || Status == STATUS_PENDING ) + Status = STATUS_SUCCESS; + AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE ); } + +NTSTATUS AfdWaitForListen( PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp ) { + NTSTATUS Status = STATUS_SUCCESS; + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + + AFD_DbgPrint(MID_TRACE,("Called\n")); + + if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE ); + + if( !IsListEmpty( &FCB->PendingConnections ) ) { + PLIST_ENTRY PendingConn = FCB->PendingConnections.Flink; + + /* We have a pending connection ... complete this irp right away */ + SatisfyPreAccept + ( Irp, + CONTAINING_RECORD + ( PendingConn, AFD_TDI_OBJECT_QELT, ListEntry ) ); + + AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n")); + + SocketStateUnlock( FCB ); + return Status; + } else { + AFD_DbgPrint(MID_TRACE,("Holding\n")); + + return LeaveIrpUntilLater( FCB, Irp, FUNCTION_PREACCEPT ); + } +} + +NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp ) { + NTSTATUS Status = STATUS_SUCCESS; + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PAFD_ACCEPT_DATA AcceptData = Irp->AssociatedIrp.SystemBuffer; + PLIST_ENTRY PendingConn; + + AFD_DbgPrint(MID_TRACE,("Called\n")); + + if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE ); + + if( FCB->NeedsNewListen ) { + AFD_DbgPrint(MID_TRACE,("ADDRESSFILE: %x\n", FCB->AddressFile.Handle)); + + /* Launch new accept socket */ + Status = WarmSocketForConnection( FCB ); + + if( Status == STATUS_SUCCESS ) { + TdiBuildNullConnectionInfo + ( &FCB->ListenIrp.ConnectionReturnInfo, + FCB->LocalAddress->Address[0].AddressType ); + + Status = TdiListen( &FCB->ListenIrp.InFlightRequest, + FCB->Connection.Object, + &FCB->ListenIrp.ConnectionCallInfo, + &FCB->ListenIrp.ConnectionReturnInfo, + &FCB->ListenIrp.Iosb, + ListenComplete, + FCB ); + } + FCB->NeedsNewListen = FALSE; + } + + for( PendingConn = FCB->PendingConnections.Flink; + PendingConn != &FCB->PendingConnections; + PendingConn = PendingConn->Flink ) { + PAFD_TDI_OBJECT_QELT PendingConnObj = + CONTAINING_RECORD( PendingConn, AFD_TDI_OBJECT_QELT, ListEntry ); + + AFD_DbgPrint(MID_TRACE,("Comparing Seq %d to Q %d\n", + AcceptData->SequenceNumber, + PendingConnObj->Seq)); + + if( PendingConnObj->Seq == AcceptData->SequenceNumber ) { + PFILE_OBJECT NewFileObject; + + RemoveEntryList( PendingConn ); + + Status = ObReferenceObjectByHandle + ( (HANDLE)AcceptData->ListenHandle, + FILE_ALL_ACCESS, + NULL, + KernelMode, + (PVOID *)&NewFileObject, + NULL ); + + /* We have a pending connection ... complete this irp right away */ + SatisfyAccept( Irp, NewFileObject, PendingConnObj ); + + ObDereferenceObject( NewFileObject ); + + AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n")); + + ExFreePool( PendingConnObj ); + + if( IsListEmpty( &FCB->PendingConnections ) ) + FCB->PollState &= ~AFD_EVENT_ACCEPT; + + SocketStateUnlock( FCB ); + return Status; + } + } + + SocketStateUnlock( FCB ); + return STATUS_UNSUCCESSFUL; +} diff --git a/reactos/drivers/net/afd/afd/lock.c b/reactos/drivers/net/afd/afd/lock.c index 64256488367..a47c90fee99 100644 --- a/reactos/drivers/net/afd/afd/lock.c +++ b/reactos/drivers/net/afd/afd/lock.c @@ -1,4 +1,4 @@ -/* $Id: lock.c,v 1.7 2004/11/17 05:17:22 arty Exp $ +/* $Id: lock.c,v 1.8 2004/12/25 21:30:17 arty Exp $ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/net/afd/afd/lock.c @@ -142,7 +142,8 @@ VOID UnlockHandles( PAFD_HANDLE HandleArray, UINT HandleCount ) { UINT i; for( i = 0; i < HandleCount; i++ ) { - ObDereferenceObject( (PVOID)HandleArray[i].Handle ); + if( HandleArray[i].Handle ) + ObDereferenceObject( (PVOID)HandleArray[i].Handle ); } ExFreePool( HandleArray ); diff --git a/reactos/drivers/net/afd/afd/main.c b/reactos/drivers/net/afd/afd/main.c index 6cb2ffff2c9..d62247ab200 100644 --- a/reactos/drivers/net/afd/afd/main.c +++ b/reactos/drivers/net/afd/afd/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.16 2004/12/11 14:59:31 navaraf Exp $ +/* $Id: main.c,v 1.17 2004/12/25 21:30:17 arty Exp $ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/net/afd/afd/main.c @@ -104,7 +104,8 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, } InitializeListHead( &FCB->DatagramList ); - + InitializeListHead( &FCB->PendingConnections ); + AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB)); if( ConnectInfo ) { @@ -252,7 +253,8 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( DisReq->DisconnectType & AFD_DISCONNECT_SEND ) Flags |= TDI_DISCONNECT_RELEASE; - if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ) + if( DisReq->DisconnectType & AFD_DISCONNECT_RECV || + DisReq->DisconnectType & AFD_DISCONNECT_ABORT ) Flags |= TDI_DISCONNECT_ABORT; Status = TdiDisconnect( FCB->Connection.Object, @@ -349,12 +351,10 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) return AfdSetContext( DeviceObject, Irp, IrpSp ); case IOCTL_AFD_WAIT_FOR_LISTEN: - AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_WAIT_FOR_LISTEN\n")); - break; + return AfdWaitForListen( DeviceObject, Irp, IrpSp ); case IOCTL_AFD_ACCEPT: - AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_ACCEPT\n")); - break; + return AfdAccept( DeviceObject, Irp, IrpSp ); case IOCTL_AFD_DISCONNECT: return AfdDisconnect( DeviceObject, Irp, IrpSp ); diff --git a/reactos/drivers/net/afd/afd/select.c b/reactos/drivers/net/afd/afd/select.c index f6671a7a06f..a0f05060348 100644 --- a/reactos/drivers/net/afd/afd/select.c +++ b/reactos/drivers/net/afd/afd/select.c @@ -1,4 +1,4 @@ -/* $Id: select.c,v 1.8 2004/11/25 23:36:36 arty Exp $ +/* $Id: select.c,v 1.9 2004/12/25 21:30:17 arty Exp $ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/net/afd/afd/select.c @@ -42,12 +42,12 @@ VOID RemoveSelect( PAFD_ACTIVE_POLL Poll ) { } VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq, - NTSTATUS Status, UINT Collected ) { + NTSTATUS Status ) { PIRP Irp = Poll->Irp; - AFD_DbgPrint(MID_TRACE,("Called (Status %x Events %d)\n", - Status, Collected)); + AFD_DbgPrint(MID_TRACE,("Called (Status %x)\n", Status)); Poll->Irp->IoStatus.Status = Status; - Poll->Irp->IoStatus.Information = Collected; + Poll->Irp->IoStatus.Information = + FIELD_OFFSET(AFD_POLL_INFO, Handles) + sizeof(AFD_HANDLE) * PollReq->HandleCount; CopyBackStatus( PollReq->Handles, PollReq->HandleCount ); UnlockHandles( AFD_HANDLES(PollReq), PollReq->HandleCount ); @@ -77,7 +77,7 @@ VOID SelectTimeout( PKDPC Dpc, ZeroEvents( PollReq->Handles, PollReq->HandleCount ); KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); - SignalSocket( Poll, PollReq, STATUS_TIMEOUT, 0 ); + SignalSocket( Poll, PollReq, STATUS_TIMEOUT ); KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); AFD_DbgPrint(MID_TRACE,("Timeout\n")); @@ -100,7 +100,7 @@ VOID KillExclusiveSelects( PAFD_DEVICE_EXTENSION DeviceExt ) { Irp = Poll->Irp; PollReq = Irp->AssociatedIrp.SystemBuffer; ZeroEvents( PollReq->Handles, PollReq->HandleCount ); - SignalSocket( Poll, PollReq, STATUS_CANCELLED, 0 ); + SignalSocket( Poll, PollReq, STATUS_CANCELLED ); } } @@ -135,7 +135,7 @@ AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !AFD_HANDLES(PollReq) ) { Irp->IoStatus.Status = STATUS_NO_MEMORY; - Irp->IoStatus.Information = -1; + Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); return Irp->IoStatus.Status; } @@ -186,8 +186,7 @@ AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, if( Signalled ) { Status = STATUS_SUCCESS; Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = Signalled; - SignalSocket( Poll, PollReq, Status, Signalled ); + SignalSocket( Poll, PollReq, Status ); } else { Status = STATUS_PENDING; IoMarkIrpPending( Irp ); @@ -344,7 +343,7 @@ VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) { if( UpdatePollWithFCB( Poll, FileObject ) ) { ThePollEnt = ThePollEnt->Flink; AFD_DbgPrint(MID_TRACE,("Signalling socket\n")); - SignalSocket( Poll, PollReq, STATUS_SUCCESS, 1 ); + SignalSocket( Poll, PollReq, STATUS_SUCCESS ); } else ThePollEnt = ThePollEnt->Flink; } diff --git a/reactos/drivers/net/afd/afd/tdi.c b/reactos/drivers/net/afd/afd/tdi.c index 38ce2eb1127..5435dd31a55 100644 --- a/reactos/drivers/net/afd/afd/tdi.c +++ b/reactos/drivers/net/afd/afd/tdi.c @@ -369,6 +369,7 @@ NTSTATUS TdiListen ( PIRP *Irp, PFILE_OBJECT ConnectionObject, PTDI_CONNECTION_INFORMATION *RequestConnectionInfo, + PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo, PIO_STATUS_BLOCK Iosb, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext) @@ -412,7 +413,7 @@ NTSTATUS TdiListen CompletionContext, /* Completion routine context */ 0, /* Flags */ *RequestConnectionInfo, /* Request connection information */ - NULL /* ReturnConnectionInfo */); /* Return connection information */ + *ReturnConnectionInfo); /* Return connection information */ Status = TdiCall(*Irp, DeviceObject, NULL /* Don't wait for completion */, Iosb); diff --git a/reactos/drivers/net/afd/include/afd.h b/reactos/drivers/net/afd/include/afd.h index 52a9cfde38f..19f9c55044c 100644 --- a/reactos/drivers/net/afd/include/afd.h +++ b/reactos/drivers/net/afd/include/afd.h @@ -1,4 +1,4 @@ -/* $Id: afd.h,v 1.28 2004/12/13 21:20:38 arty Exp $ +/* $Id: afd.h,v 1.29 2004/12/25 21:30:18 arty Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -51,8 +51,10 @@ #define FUNCTION_CONNECT 0 #define FUNCTION_RECV 1 #define FUNCTION_SEND 2 -#define FUNCTION_CLOSE 3 -#define MAX_FUNCTIONS 4 +#define FUNCTION_PREACCEPT 3 +#define FUNCTION_ACCEPT 4 +#define FUNCTION_CLOSE 5 +#define MAX_FUNCTIONS 6 #define IN_FLIGHT_REQUESTS 3 @@ -102,10 +104,18 @@ typedef struct _AFD_TDI_OBJECT { HANDLE Handle; } AFD_TDI_OBJECT, *PAFD_TDI_OBJECT; +typedef struct _AFD_TDI_OBJECT_QELT { + LIST_ENTRY ListEntry; + UINT Seq; + PTDI_CONNECTION_INFORMATION ConnInfo; + AFD_TDI_OBJECT Object; +} AFD_TDI_OBJECT_QELT, *PAFD_TDI_OBJECT_QELT; + typedef struct _AFD_IN_FLIGHT_REQUEST { PIRP InFlightRequest; IO_STATUS_BLOCK Iosb; - PTDI_CONNECTION_INFORMATION ConnectionInfo; + PTDI_CONNECTION_INFORMATION ConnectionCallInfo; + PTDI_CONNECTION_INFORMATION ConnectionReturnInfo; } AFD_IN_FLIGHT_REQUEST, *PAFD_IN_FLIGHT_REQUEST; typedef struct _AFD_DATA_WINDOW { @@ -129,7 +139,8 @@ typedef struct _AFD_FCB { KSPIN_LOCK SpinLock; PFILE_OBJECT FileObject; PAFD_DEVICE_EXTENSION DeviceExt; - BOOLEAN DelayedAccept; + BOOLEAN DelayedAccept, NeedsNewListen; + UINT ConnSeq; PTRANSPORT_ADDRESS LocalAddress, RemoteAddress; PTDI_CONNECTION_INFORMATION AddressFrom; AFD_TDI_OBJECT AddressFile, Connection; @@ -146,6 +157,7 @@ typedef struct _AFD_FCB { UINT ContextSize; LIST_ENTRY PendingIrpList[MAX_FUNCTIONS]; LIST_ENTRY DatagramList; + LIST_ENTRY PendingConnections; } AFD_FCB, *PAFD_FCB; /* bind.c */ @@ -157,6 +169,7 @@ AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* connect.c */ +NTSTATUS MakeSocketIntoConnection( PAFD_FCB FCB ); NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ); NTSTATUS STDCALL AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, @@ -182,10 +195,15 @@ AfdGetSockName( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ); /* listen.c */ +NTSTATUS AfdWaitForListen( PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp ); NTSTATUS AfdListenSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); +NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp ); + /* lock.c */ PAFD_WSABUF LockBuffers( PAFD_WSABUF Buf, UINT Count, @@ -261,6 +279,7 @@ NTSTATUS TdiListen ( PIRP *Irp, PFILE_OBJECT ConnectionObject, PTDI_CONNECTION_INFORMATION *RequestConnectionInfo, + PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo, PIO_STATUS_BLOCK Iosb, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext); diff --git a/reactos/drivers/net/tcpip/datalink/lan.c b/reactos/drivers/net/tcpip/datalink/lan.c index 0ea67c18f56..731706ed0c9 100644 --- a/reactos/drivers/net/tcpip/datalink/lan.c +++ b/reactos/drivers/net/tcpip/datalink/lan.c @@ -92,8 +92,8 @@ BOOLEAN LanShouldComplete( PLAN_ADAPTER Adapter, PNDIS_PACKET NdisPacket ) { } KeReleaseSpinLock( &LanSendCompleteLock, OldIrql ); - TI_DbgPrint(MID_TRACE,("NDIS completed the same send packet twice " - "(Adapter %x Packet %x)!!\n", Adapter, NdisPacket)); + DbgPrint("NDIS completed the same send packet twice " + "(Adapter %x Packet %x)!!\n", Adapter, NdisPacket); #ifdef BREAK_ON_DOUBLE_COMPLETE KeBugCheck(0); #endif @@ -356,7 +356,8 @@ VOID LanSubmitReceiveWork( if( !LanReceiveWorkerBusy ) { LanReceiveWorkerBusy = TRUE; ExQueueWorkItem( &LanWorkItem, CriticalWorkQueue ); - DbgPrint("Work item inserted %x %x\n", &LanWorkItem, WQItem); + TI_DbgPrint(DEBUG_DATALINK, + ("Work item inserted %x %x\n", &LanWorkItem, WQItem)); } else { DbgPrint("LAN WORKER BUSY %x %x\n", &LanWorkItem, WQItem); } diff --git a/reactos/drivers/net/tcpip/include/tcp.h b/reactos/drivers/net/tcpip/include/tcp.h index 23641d3cae4..08a0e4cdba1 100644 --- a/reactos/drivers/net/tcpip/include/tcp.h +++ b/reactos/drivers/net/tcpip/include/tcp.h @@ -87,6 +87,21 @@ extern LIST_ENTRY SleepingThreadsList; extern FAST_MUTEX SleepingThreadsLock; extern RECURSIVE_MUTEX TCPLock; +/* accept.c */ +NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener, + PCONNECTION_ENDPOINT Connection, + PTDI_REQUEST_KERNEL Request ); +NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ); +VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener, + PCONNECTION_ENDPOINT Connection ); +NTSTATUS TCPAccept +( PTDI_REQUEST Request, + PCONNECTION_ENDPOINT Listener, + PCONNECTION_ENDPOINT Connection, + PTCP_COMPLETION_ROUTINE Complete, + PVOID Context ); + +/* tcp.c */ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ); VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection ); @@ -121,12 +136,6 @@ NTSTATUS TCPDisconnect( PTCP_COMPLETION_ROUTINE Complete, PVOID Context); -NTSTATUS TCPListen( - PCONNECTION_ENDPOINT Connection, - UINT Backlog, - PTCP_COMPLETION_ROUTINE Complete, - PVOID Context); - NTSTATUS TCPReceiveData( PCONNECTION_ENDPOINT Connection, PNDIS_BUFFER Buffer, diff --git a/reactos/drivers/net/tcpip/include/titypes.h b/reactos/drivers/net/tcpip/include/titypes.h index 6308bc54913..997a01450f9 100644 --- a/reactos/drivers/net/tcpip/include/titypes.h +++ b/reactos/drivers/net/tcpip/include/titypes.h @@ -144,28 +144,6 @@ typedef struct _DATAGRAM_SEND_REQUEST { ULONG Flags; /* Protocol specific flags */ } DATAGRAM_SEND_REQUEST, *PDATAGRAM_SEND_REQUEST; -#if 0 -#define InitializeDatagramSendRequest( \ - _SendRequest, \ - _RemoteAddress, \ - _RemotePort, \ - _Buffer, \ - _BufferSize, \ - _Complete, \ - _Context, \ - _Build, \ - _Flags) { \ - (_SendRequest)->RemoteAddress = (_RemoteAddress); \ - (_SendRequest)->RemotePort = (_RemotePort); \ - (_SendRequest)->Buffer = (_Buffer); \ - (_SendRequest)->BufferSize = (_BufferSize); \ - (_SendRequest)->Complete = (_Complete); \ - (_SendRequest)->Context = (_Context); \ - (_SendRequest)->Build = (_Build); \ - (_SendRequest)->Flags = (_Flags); \ - } -#endif /* These things bug me... They hide the member names. */ - /* Transport address file context structure. The FileObject->FsContext2 field holds a pointer to this structure */ typedef struct _ADDRESS_FILE { @@ -175,6 +153,7 @@ typedef struct _ADDRESS_FILE { OBJECT_FREE_ROUTINE Free; /* Routine to use to free resources for the object */ USHORT Flags; /* Flags for address file (see below) */ IP_ADDRESS Address; /* Address of this address file */ + USHORT Family; /* Address family */ USHORT Protocol; /* Protocol number */ USHORT Port; /* Network port (network byte order) */ WORK_QUEUE_ITEM WorkItem; /* Work queue item handle */ @@ -184,8 +163,9 @@ typedef struct _ADDRESS_FILE { LIST_ENTRY ReceiveQueue; /* List of outstanding receive requests */ LIST_ENTRY TransmitQueue; /* List of outstanding transmit requests */ struct _CONNECTION_ENDPOINT *Connection; - /* Associated connection or NULL if no - associated connection exist */ + /* Associated connection or NULL if no associated connection exist */ + struct _CONNECTION_ENDPOINT *Listener; + /* Associated listener (see transport/tcp/accept.c) */ IP_ADDRESS AddrCache; /* One entry address cache (destination address of last packet transmitted) */ @@ -302,6 +282,7 @@ typedef struct _TCP_SEGMENT { typedef struct _TDI_BUCKET { LIST_ENTRY Entry; + struct _CONNECTION_ENDPOINT *AssociatedEndpoint; TDI_REQUEST Request; } TDI_BUCKET, *PTDI_BUCKET; @@ -316,7 +297,7 @@ typedef struct _CONNECTION_ENDPOINT { PVOID SocketContext; /* Context for lower layer */ UINT State; /* Socket state W.R.T. oskit */ - + /* Requests */ LIST_ENTRY ConnectRequest; /* Queued connect rqueusts */ LIST_ENTRY ListenRequest; /* Queued listen requests */ diff --git a/reactos/drivers/net/tcpip/makefile b/reactos/drivers/net/tcpip/makefile index f341bbd4a79..4eff95e1f47 100644 --- a/reactos/drivers/net/tcpip/makefile +++ b/reactos/drivers/net/tcpip/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.33 2004/12/03 23:37:40 blight Exp $ +# $Id: makefile,v 1.34 2004/12/25 21:30:19 arty Exp $ PATH_TO_TOP = ../../.. @@ -14,7 +14,6 @@ TARGET_PCH = include/precomp.h TARGET_CFLAGS = \ -D__USE_W32API \ -D_SEH_NO_NATIVE_NLG \ - -DMEMTRACK \ -DNDIS40 \ -Wall -Werror \ -I./include \ diff --git a/reactos/drivers/net/tcpip/tcpip/dispatch.c b/reactos/drivers/net/tcpip/tcpip/dispatch.c index ab241d406e4..c4450d66b17 100644 --- a/reactos/drivers/net/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/net/tcpip/tcpip/dispatch.c @@ -1,4 +1,3 @@ - /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS TCP/IP protocol driver @@ -272,8 +271,8 @@ NTSTATUS DispTdiAssociateAddress( (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X).\n", - Parameters->AddressHandle)); + TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X): %x.\n", + Parameters->AddressHandle, Status)); return STATUS_INVALID_PARAMETER; } @@ -465,7 +464,7 @@ NTSTATUS DispTdiListen( PTDI_REQUEST_KERNEL Parameters; PTRANSPORT_CONTEXT TranContext; PIO_STACK_LOCATION IrpSp; - NTSTATUS Status; + NTSTATUS Status = STATUS_SUCCESS; TI_DbgPrint(DEBUG_IRP, ("Called.\n")); @@ -489,9 +488,50 @@ NTSTATUS DispTdiListen( Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters; - Status = TCPListen( Connection, 1024 /* BACKLOG */, - DispDataRequestComplete, - Irp ); + TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile: %x\n", + Connection->AddressFile )); + if( Connection->AddressFile ) { + TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile->Listener: %x\n", + Connection->AddressFile->Listener)); + } + + /* Listening will require us to create a listening socket and store it in + * the address file. It will be signalled, and attempt to complete an irp + * when a new connection arrives. */ + /* The important thing to note here is that the irp we'll complete belongs + * to the socket to be accepted onto, not the listener */ + if( !Connection->AddressFile->Listener ) { + Connection->AddressFile->Listener = + TCPAllocateConnectionEndpoint( NULL ); + + if( !Connection->AddressFile->Listener ) + Status = STATUS_NO_MEMORY; + + if( NT_SUCCESS(Status) ) { + Connection->AddressFile->Listener->AddressFile = + Connection->AddressFile; + + Status = TCPSocket( Connection->AddressFile->Listener, + Connection->AddressFile->Family, + SOCK_STREAM, + Connection->AddressFile->Protocol ); + } + + if( NT_SUCCESS(Status) ) + Status = TCPListen( Connection->AddressFile->Listener, 1024 ); + /* BACKLOG */ + } + + if( NT_SUCCESS(Status) ) { + Status = TCPAccept + ( (PTDI_REQUEST)Parameters, + Connection->AddressFile->Listener, + Connection, + DispDataRequestComplete, + Irp ); + } + + TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status)); return Status; } diff --git a/reactos/drivers/net/tcpip/tcpip/fileobjs.c b/reactos/drivers/net/tcpip/tcpip/fileobjs.c index b2547ab1270..f219bf3631b 100644 --- a/reactos/drivers/net/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/net/tcpip/tcpip/fileobjs.c @@ -249,6 +249,7 @@ NTSTATUS FileOpenAddress( /* Locate address entry. If specified address is 0, a random address is chosen */ /* FIXME: IPv4 only */ + AddrFile->Family = Address->Address[0].AddressType; IPv4Address = Address->Address[0].Address[0].in_addr; if (IPv4Address == 0) Matched = IPGetDefaultAddress(&AddrFile->Address); @@ -351,6 +352,8 @@ NTSTATUS FileCloseAddress( switch (AddrFile->Protocol) { case IPPROTO_TCP: TCPFreePort( AddrFile->Port ); + if( AddrFile->Listener ) + TCPClose( AddrFile->Listener ); break; case IPPROTO_UDP: diff --git a/reactos/drivers/net/tcpip/tcpip/main.c b/reactos/drivers/net/tcpip/tcpip/main.c index 155a1b96775..ddbceccb7d8 100644 --- a/reactos/drivers/net/tcpip/tcpip/main.c +++ b/reactos/drivers/net/tcpip/tcpip/main.c @@ -9,10 +9,10 @@ */ #include "precomp.h" -#define NDEBUG +//#define NDEBUG #ifndef NDEBUG -DWORD DebugTraceLevel = DEBUG_ULTRA; +DWORD DebugTraceLevel = MAX_TRACE | DEBUG_TCP; #else DWORD DebugTraceLevel = 0; #endif /* NDEBUG */ @@ -480,6 +480,7 @@ TiDispatchInternal( case TDI_LISTEN: Status = DispTdiListen(Irp); + Complete = FALSE; break; case TDI_CONNECT: