2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/listen.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
13 static NTSTATUS
SatisfyAccept( PAFD_DEVICE_EXTENSION DeviceExt
,
15 PFILE_OBJECT NewFileObject
,
16 PAFD_TDI_OBJECT_QELT Qelt
) {
17 PAFD_FCB FCB
= NewFileObject
->FsContext
;
20 UNREFERENCED_PARAMETER(DeviceExt
);
22 if( !SocketAcquireStateLock( FCB
) )
23 return LostSocket( Irp
);
25 /* Transfer the connection to the new socket, launch the opening read */
26 AFD_DbgPrint(MID_TRACE
,("Completing a real accept (FCB %p)\n", FCB
));
28 FCB
->Connection
= Qelt
->Object
;
30 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
32 TaCopyTransportAddress( Qelt
->ConnInfo
->RemoteAddress
);
34 if( !FCB
->RemoteAddress
)
35 Status
= STATUS_NO_MEMORY
;
37 Status
= MakeSocketIntoConnection( FCB
);
39 if (NT_SUCCESS(Status
))
40 Status
= TdiBuildConnectionInfo(&FCB
->ConnectCallInfo
, FCB
->RemoteAddress
);
42 if (NT_SUCCESS(Status
))
43 Status
= TdiBuildConnectionInfo(&FCB
->ConnectReturnInfo
, FCB
->RemoteAddress
);
45 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
48 static NTSTATUS
SatisfyPreAccept( PIRP Irp
, PAFD_TDI_OBJECT_QELT Qelt
) {
49 PAFD_RECEIVED_ACCEPT_DATA ListenReceive
=
50 (PAFD_RECEIVED_ACCEPT_DATA
)Irp
->AssociatedIrp
.SystemBuffer
;
51 PTA_IP_ADDRESS IPAddr
;
53 ListenReceive
->SequenceNumber
= Qelt
->Seq
;
55 AFD_DbgPrint(MID_TRACE
,("Giving SEQ %u to userland\n", Qelt
->Seq
));
56 AFD_DbgPrint(MID_TRACE
,("Socket Address (K) %p (U) %p\n",
57 &ListenReceive
->Address
,
58 Qelt
->ConnInfo
->RemoteAddress
));
60 TaCopyTransportAddressInPlace( &ListenReceive
->Address
,
61 Qelt
->ConnInfo
->RemoteAddress
);
63 IPAddr
= (PTA_IP_ADDRESS
)&ListenReceive
->Address
;
65 AFD_DbgPrint(MID_TRACE
,("IPAddr->TAAddressCount %d\n",
66 IPAddr
->TAAddressCount
));
67 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].AddressType %u\n",
68 IPAddr
->Address
[0].AddressType
));
69 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].AddressLength %u\n",
70 IPAddr
->Address
[0].AddressLength
));
71 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].Address[0].sin_port %x\n",
72 IPAddr
->Address
[0].Address
[0].sin_port
));
73 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].Address[0].sin_addr %x\n",
74 IPAddr
->Address
[0].Address
[0].in_addr
));
76 if( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
78 Irp
->IoStatus
.Information
= ((PCHAR
)&IPAddr
[1]) - ((PCHAR
)ListenReceive
);
79 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
80 (void)IoSetCancelRoutine(Irp
, NULL
);
81 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
82 return STATUS_SUCCESS
;
85 static IO_COMPLETION_ROUTINE ListenComplete
;
86 static NTSTATUS NTAPI
ListenComplete( PDEVICE_OBJECT DeviceObject
,
89 NTSTATUS Status
= STATUS_SUCCESS
;
90 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
91 PAFD_TDI_OBJECT_QELT Qelt
;
92 PLIST_ENTRY NextIrpEntry
;
95 UNREFERENCED_PARAMETER(DeviceObject
);
97 if( !SocketAcquireStateLock( FCB
) )
98 return STATUS_FILE_CLOSED
;
100 ASSERT(FCB
->ListenIrp
.InFlightRequest
== Irp
);
101 FCB
->ListenIrp
.InFlightRequest
= NULL
;
103 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
104 /* Cleanup our IRP queue because the FCB is being destroyed */
105 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) ) {
106 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_PREACCEPT
]);
107 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
108 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
109 NextIrp
->IoStatus
.Information
= 0;
110 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
111 (void)IoSetCancelRoutine(NextIrp
, NULL
);
112 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
115 /* Free ConnectionReturnInfo and ConnectionCallInfo */
116 if (FCB
->ListenIrp
.ConnectionReturnInfo
)
118 ExFreePool(FCB
->ListenIrp
.ConnectionReturnInfo
);
119 FCB
->ListenIrp
.ConnectionReturnInfo
= NULL
;
122 if (FCB
->ListenIrp
.ConnectionCallInfo
)
124 ExFreePool(FCB
->ListenIrp
.ConnectionCallInfo
);
125 FCB
->ListenIrp
.ConnectionCallInfo
= NULL
;
128 SocketStateUnlock( FCB
);
129 return STATUS_FILE_CLOSED
;
132 AFD_DbgPrint(MID_TRACE
,("Completing listen request.\n"));
133 AFD_DbgPrint(MID_TRACE
,("IoStatus was %x\n", Irp
->IoStatus
.Status
));
135 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
137 SocketStateUnlock(FCB
);
138 return Irp
->IoStatus
.Status
;
141 Qelt
= ExAllocatePool( NonPagedPool
, sizeof(*Qelt
) );
143 Status
= STATUS_NO_MEMORY
;
146 FCB
->LocalAddress
->Address
[0].AddressType
;
148 Qelt
->Object
= FCB
->Connection
;
149 Qelt
->Seq
= FCB
->ConnSeq
++;
150 AFD_DbgPrint(MID_TRACE
,("Address Type: %u (RA %p)\n",
153 ConnectionReturnInfo
->RemoteAddress
));
155 Status
= TdiBuildNullConnectionInfo( &Qelt
->ConnInfo
, AddressType
);
156 if( NT_SUCCESS(Status
) ) {
157 TaCopyTransportAddressInPlace
158 ( Qelt
->ConnInfo
->RemoteAddress
,
159 FCB
->ListenIrp
.ConnectionReturnInfo
->RemoteAddress
);
160 InsertTailList( &FCB
->PendingConnections
, &Qelt
->ListEntry
);
164 /* Satisfy a pre-accept request if one is available */
165 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) &&
166 !IsListEmpty( &FCB
->PendingConnections
) ) {
167 PLIST_ENTRY PendingIrp
=
168 RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] );
169 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
171 ( CONTAINING_RECORD( PendingIrp
, IRP
,
172 Tail
.Overlay
.ListEntry
),
173 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
,
177 /* Launch new accept socket */
178 Status
= WarmSocketForConnection( FCB
);
180 if (NT_SUCCESS(Status
))
182 Status
= TdiBuildNullConnectionInfoInPlace(FCB
->ListenIrp
.ConnectionCallInfo
,
183 FCB
->LocalAddress
->Address
[0].AddressType
);
184 ASSERT(Status
== STATUS_SUCCESS
);
186 Status
= TdiBuildNullConnectionInfoInPlace(FCB
->ListenIrp
.ConnectionReturnInfo
,
187 FCB
->LocalAddress
->Address
[0].AddressType
);
188 ASSERT(Status
== STATUS_SUCCESS
);
190 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
191 FCB
->Connection
.Object
,
192 &FCB
->ListenIrp
.ConnectionCallInfo
,
193 &FCB
->ListenIrp
.ConnectionReturnInfo
,
197 if (Status
== STATUS_PENDING
)
198 Status
= STATUS_SUCCESS
;
201 /* Trigger a select return if appropriate */
202 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
203 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
204 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
205 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
207 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
209 SocketStateUnlock( FCB
);
214 NTSTATUS
AfdListenSocket( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
215 PIO_STACK_LOCATION IrpSp
) {
216 NTSTATUS Status
= STATUS_SUCCESS
;
217 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
218 PAFD_FCB FCB
= FileObject
->FsContext
;
219 PAFD_LISTEN_DATA ListenReq
;
221 UNREFERENCED_PARAMETER(DeviceObject
);
223 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
225 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
227 if( !(ListenReq
= LockRequest( Irp
, IrpSp
, FALSE
, NULL
)) )
228 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
231 if( FCB
->State
!= SOCKET_STATE_BOUND
) {
232 Status
= STATUS_INVALID_PARAMETER
;
233 AFD_DbgPrint(MIN_TRACE
,("Could not listen an unbound socket\n"));
234 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
237 FCB
->DelayedAccept
= ListenReq
->UseDelayedAcceptance
;
239 AFD_DbgPrint(MID_TRACE
,("ADDRESSFILE: %p\n", FCB
->AddressFile
.Handle
));
241 Status
= WarmSocketForConnection( FCB
);
243 AFD_DbgPrint(MID_TRACE
,("Status from warmsocket %x\n", Status
));
245 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
247 Status
= TdiBuildNullConnectionInfo
248 ( &FCB
->ListenIrp
.ConnectionCallInfo
,
249 FCB
->LocalAddress
->Address
[0].AddressType
);
251 if (!NT_SUCCESS(Status
)) return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
253 Status
= TdiBuildNullConnectionInfo
254 ( &FCB
->ListenIrp
.ConnectionReturnInfo
,
255 FCB
->LocalAddress
->Address
[0].AddressType
);
257 if (!NT_SUCCESS(Status
))
259 ExFreePool(FCB
->ListenIrp
.ConnectionCallInfo
);
260 FCB
->ListenIrp
.ConnectionCallInfo
= NULL
;
261 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
264 FCB
->State
= SOCKET_STATE_LISTENING
;
266 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
267 FCB
->Connection
.Object
,
268 &FCB
->ListenIrp
.ConnectionCallInfo
,
269 &FCB
->ListenIrp
.ConnectionReturnInfo
,
273 if( Status
== STATUS_PENDING
)
274 Status
= STATUS_SUCCESS
;
276 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
277 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
280 NTSTATUS
AfdWaitForListen( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
281 PIO_STACK_LOCATION IrpSp
) {
282 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
283 PAFD_FCB FCB
= FileObject
->FsContext
;
286 UNREFERENCED_PARAMETER(DeviceObject
);
288 AFD_DbgPrint(MID_TRACE
,("Called\n"));
290 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
292 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
293 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
295 /* We have a pending connection ... complete this irp right away */
296 Status
= SatisfyPreAccept
299 ( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
) );
301 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
303 if ( !IsListEmpty( &FCB
->PendingConnections
) )
305 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
306 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
307 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
309 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
311 SocketStateUnlock( FCB
);
313 } else if (FCB
->NonBlocking
) {
314 AFD_DbgPrint(MIN_TRACE
,("No connection ready on a non-blocking socket\n"));
316 return UnlockAndMaybeComplete(FCB
, STATUS_CANT_WAIT
, Irp
, 0);
318 AFD_DbgPrint(MID_TRACE
,("Holding\n"));
320 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_PREACCEPT
);
324 NTSTATUS
AfdAccept( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
325 PIO_STACK_LOCATION IrpSp
) {
326 NTSTATUS Status
= STATUS_SUCCESS
;
327 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
328 PAFD_DEVICE_EXTENSION DeviceExt
=
329 (PAFD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
330 PAFD_FCB FCB
= FileObject
->FsContext
;
331 PAFD_ACCEPT_DATA AcceptData
= Irp
->AssociatedIrp
.SystemBuffer
;
332 PLIST_ENTRY PendingConn
;
334 AFD_DbgPrint(MID_TRACE
,("Called\n"));
336 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
338 FCB
->EventSelectDisabled
&= ~AFD_EVENT_ACCEPT
;
340 for( PendingConn
= FCB
->PendingConnections
.Flink
;
341 PendingConn
!= &FCB
->PendingConnections
;
342 PendingConn
= PendingConn
->Flink
) {
343 PAFD_TDI_OBJECT_QELT PendingConnObj
=
344 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
);
346 AFD_DbgPrint(MID_TRACE
,("Comparing Seq %u to Q %u\n",
347 AcceptData
->SequenceNumber
,
348 PendingConnObj
->Seq
));
350 if( PendingConnObj
->Seq
== AcceptData
->SequenceNumber
) {
351 PFILE_OBJECT NewFileObject
= NULL
;
353 RemoveEntryList( PendingConn
);
355 Status
= ObReferenceObjectByHandle
356 ( AcceptData
->ListenHandle
,
360 (PVOID
*)&NewFileObject
,
363 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
365 ASSERT(NewFileObject
!= FileObject
);
366 ASSERT(NewFileObject
->FsContext
!= FCB
);
368 /* We have a pending connection ... complete this irp right away */
369 Status
= SatisfyAccept( DeviceExt
, Irp
, NewFileObject
, PendingConnObj
);
371 ObDereferenceObject( NewFileObject
);
373 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
375 ExFreePool( PendingConnObj
);
377 if( !IsListEmpty( &FCB
->PendingConnections
) )
379 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
380 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
381 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
383 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
385 SocketStateUnlock( FCB
);
390 AFD_DbgPrint(MIN_TRACE
,("No connection waiting\n"));
392 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0 );