2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: transport/tcp/accept.c
5 * PURPOSE: Transmission Control Protocol Listen/Accept code
6 * PROGRAMMERS: Art Yerkes (arty@users.sf.net)
8 * arty 12/21/2004 Created
13 /* Listener->Lock MUST be acquired */
14 NTSTATUS
TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener
,
15 PCONNECTION_ENDPOINT Connection
,
16 PTDI_REQUEST_KERNEL Request
) {
20 PTA_IP_ADDRESS RequestAddressReturn
;
21 PTDI_CONNECTION_INFORMATION WhoIsConnecting
;
23 /* Unpack TDI info -- We need the return connection information
24 * struct to return the address so it can be filtered if needed
25 * by WSAAccept -- The returned address will be passed on to
26 * userland after we complete this irp */
27 WhoIsConnecting
= (PTDI_CONNECTION_INFORMATION
)
28 Request
->ReturnConnectionInformation
;
30 Status
= TCPTranslateError
31 ( OskitTCPAccept( Listener
->SocketContext
,
32 &Connection
->SocketContext
,
37 Request
->RequestFlags
& TDI_QUERY_ACCEPT
? 0 : 1 ) );
39 TI_DbgPrint(DEBUG_TCP
,("Status %x\n", Status
));
41 if( NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
) {
42 RequestAddressReturn
= WhoIsConnecting
->RemoteAddress
;
44 TI_DbgPrint(DEBUG_TCP
,("Copying address to %x (Who %x)\n",
45 RequestAddressReturn
, WhoIsConnecting
));
47 RequestAddressReturn
->TAAddressCount
= 1;
48 RequestAddressReturn
->Address
[0].AddressLength
= TDI_ADDRESS_LENGTH_IP
;
49 RequestAddressReturn
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
50 RequestAddressReturn
->Address
[0].Address
[0].sin_port
= OutAddr
.sin_port
;
51 RequestAddressReturn
->Address
[0].Address
[0].in_addr
= OutAddr
.sin_addr
.s_addr
;
52 RtlZeroMemory(RequestAddressReturn
->Address
[0].Address
[0].sin_zero
, 8);
54 TI_DbgPrint(DEBUG_TCP
,("Done copying\n"));
57 TI_DbgPrint(DEBUG_TCP
,("Status %x\n", Status
));
62 /* This listen is on a socket we keep as internal. That socket has the same
63 * lifetime as the address file */
64 NTSTATUS
TCPListen( PCONNECTION_ENDPOINT Connection
, UINT Backlog
) {
65 NTSTATUS Status
= STATUS_SUCCESS
;
66 SOCKADDR_IN AddressToBind
;
68 TA_IP_ADDRESS LocalAddress
;
72 LockObject(Connection
, &OldIrql
);
74 ASSERT_KM_POINTER(Connection
->AddressFile
);
76 TI_DbgPrint(DEBUG_TCP
,("TCPListen started\n"));
78 TI_DbgPrint(DEBUG_TCP
,("Connection->SocketContext %x\n",
79 Connection
->SocketContext
));
81 if (Connection
->AddressFile
->Port
)
83 AddressToBind
.sin_family
= AF_INET
;
84 memcpy( &AddressToBind
.sin_addr
,
85 &Connection
->AddressFile
->Address
.Address
.IPv4Address
,
86 sizeof(AddressToBind
.sin_addr
) );
87 AddressToBind
.sin_port
= Connection
->AddressFile
->Port
;
88 TI_DbgPrint(DEBUG_TCP
,("AddressToBind - %x:%x\n", AddressToBind
.sin_addr
, AddressToBind
.sin_port
));
90 /* Perform an explicit bind */
91 Status
= TCPTranslateError(OskitTCPBind(Connection
->SocketContext
,
93 sizeof(AddressToBind
)));
97 /* An implicit bind will be performed */
98 Status
= STATUS_SUCCESS
;
101 if (NT_SUCCESS(Status
))
102 Status
= TCPTranslateError( OskitTCPListen( Connection
->SocketContext
, Backlog
) );
104 if (NT_SUCCESS(Status
))
106 /* Check if we had an unspecified port */
107 if (!Connection
->AddressFile
->Port
)
109 /* We did, so we need to copy back the port */
110 if (NT_SUCCESS(TCPGetSockAddress(Connection
, (PTRANSPORT_ADDRESS
)&LocalAddress
, FALSE
)))
112 /* Allocate the port in the port bitmap */
113 Connection
->AddressFile
->Port
= TCPAllocatePort(LocalAddress
.Address
[0].Address
[0].sin_port
);
115 /* This should never fail */
116 ASSERT(Connection
->AddressFile
->Port
!= 0xFFFF);
121 UnlockObject(Connection
, OldIrql
);
123 TI_DbgPrint(DEBUG_TCP
,("TCPListen finished %x\n", Status
));
128 BOOLEAN
TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener
,
129 PCONNECTION_ENDPOINT Connection
) {
130 PLIST_ENTRY ListEntry
;
133 BOOLEAN Found
= FALSE
;
135 LockObject(Listener
, &OldIrql
);
137 ListEntry
= Listener
->ListenRequest
.Flink
;
138 while ( ListEntry
!= &Listener
->ListenRequest
) {
139 Bucket
= CONTAINING_RECORD(ListEntry
, TDI_BUCKET
, Entry
);
141 if( Bucket
->AssociatedEndpoint
== Connection
) {
142 DereferenceObject(Bucket
->AssociatedEndpoint
);
143 RemoveEntryList( &Bucket
->Entry
);
144 ExFreePoolWithTag( Bucket
, TDI_BUCKET_TAG
);
149 ListEntry
= ListEntry
->Flink
;
152 UnlockObject(Listener
, OldIrql
);
157 NTSTATUS
TCPAccept ( PTDI_REQUEST Request
,
158 PCONNECTION_ENDPOINT Listener
,
159 PCONNECTION_ENDPOINT Connection
,
160 PTCP_COMPLETION_ROUTINE Complete
,
167 TI_DbgPrint(DEBUG_TCP
,("TCPAccept started\n"));
169 LockObject(Listener
, &OldIrql
);
171 Status
= TCPServiceListeningSocket( Listener
, Connection
,
172 (PTDI_REQUEST_KERNEL
)Request
);
174 if( Status
== STATUS_PENDING
) {
175 Bucket
= ExAllocatePoolWithTag( NonPagedPool
, sizeof(*Bucket
),
179 ReferenceObject(Connection
);
180 Bucket
->AssociatedEndpoint
= Connection
;
181 Bucket
->Request
.RequestNotifyObject
= Complete
;
182 Bucket
->Request
.RequestContext
= Context
;
183 InsertTailList( &Listener
->ListenRequest
, &Bucket
->Entry
);
185 Status
= STATUS_NO_MEMORY
;
188 UnlockObject(Listener
, OldIrql
);
190 TI_DbgPrint(DEBUG_TCP
,("TCPAccept finished %x\n", Status
));