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)
12 static NTSTATUS
SatisfyAccept( PAFD_DEVICE_EXTENSION DeviceExt
,
14 PFILE_OBJECT NewFileObject
,
15 PAFD_TDI_OBJECT_QELT Qelt
) {
16 PAFD_FCB FCB
= NewFileObject
->FsContext
;
19 UNREFERENCED_PARAMETER(DeviceExt
);
21 if( !SocketAcquireStateLock( FCB
) )
22 return LostSocket( Irp
);
24 /* Transfer the connection to the new socket, launch the opening read */
25 AFD_DbgPrint(MID_TRACE
,("Completing a real accept (FCB %p)\n", FCB
));
27 FCB
->Connection
= Qelt
->Object
;
29 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
31 TaCopyTransportAddress( Qelt
->ConnInfo
->RemoteAddress
);
33 if( !FCB
->RemoteAddress
)
34 Status
= STATUS_NO_MEMORY
;
36 Status
= MakeSocketIntoConnection( FCB
);
38 if (NT_SUCCESS(Status
))
39 Status
= TdiBuildConnectionInfo(&FCB
->ConnectCallInfo
, FCB
->RemoteAddress
);
41 if (NT_SUCCESS(Status
))
42 Status
= TdiBuildConnectionInfo(&FCB
->ConnectReturnInfo
, FCB
->RemoteAddress
);
44 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
47 static NTSTATUS
SatisfyPreAccept( PIRP Irp
, PAFD_TDI_OBJECT_QELT Qelt
) {
48 PAFD_RECEIVED_ACCEPT_DATA ListenReceive
=
49 (PAFD_RECEIVED_ACCEPT_DATA
)Irp
->AssociatedIrp
.SystemBuffer
;
50 PTA_IP_ADDRESS IPAddr
;
52 ListenReceive
->SequenceNumber
= Qelt
->Seq
;
54 AFD_DbgPrint(MID_TRACE
,("Giving SEQ %u to userland\n", Qelt
->Seq
));
55 AFD_DbgPrint(MID_TRACE
,("Socket Address (K) %p (U) %p\n",
56 &ListenReceive
->Address
,
57 Qelt
->ConnInfo
->RemoteAddress
));
59 TaCopyTransportAddressInPlace( &ListenReceive
->Address
,
60 Qelt
->ConnInfo
->RemoteAddress
);
62 IPAddr
= (PTA_IP_ADDRESS
)&ListenReceive
->Address
;
64 AFD_DbgPrint(MID_TRACE
,("IPAddr->TAAddressCount %d\n",
65 IPAddr
->TAAddressCount
));
66 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].AddressType %u\n",
67 IPAddr
->Address
[0].AddressType
));
68 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].AddressLength %u\n",
69 IPAddr
->Address
[0].AddressLength
));
70 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].Address[0].sin_port %x\n",
71 IPAddr
->Address
[0].Address
[0].sin_port
));
72 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].Address[0].sin_addr %x\n",
73 IPAddr
->Address
[0].Address
[0].in_addr
));
75 if( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
77 Irp
->IoStatus
.Information
= ((PCHAR
)&IPAddr
[1]) - ((PCHAR
)ListenReceive
);
78 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
79 (void)IoSetCancelRoutine(Irp
, NULL
);
80 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
81 return STATUS_SUCCESS
;
84 static IO_COMPLETION_ROUTINE ListenComplete
;
85 static NTSTATUS NTAPI
ListenComplete( PDEVICE_OBJECT DeviceObject
,
88 NTSTATUS Status
= STATUS_SUCCESS
;
89 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
90 PAFD_TDI_OBJECT_QELT Qelt
;
91 PLIST_ENTRY NextIrpEntry
;
94 UNREFERENCED_PARAMETER(DeviceObject
);
96 if( !SocketAcquireStateLock( FCB
) )
97 return STATUS_FILE_CLOSED
;
99 ASSERT(FCB
->ListenIrp
.InFlightRequest
== Irp
);
100 FCB
->ListenIrp
.InFlightRequest
= NULL
;
102 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
103 /* Cleanup our IRP queue because the FCB is being destroyed */
104 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) ) {
105 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_PREACCEPT
]);
106 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
107 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
108 NextIrp
->IoStatus
.Information
= 0;
109 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
110 (void)IoSetCancelRoutine(NextIrp
, NULL
);
111 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
114 /* Free ConnectionReturnInfo and ConnectionCallInfo */
115 if (FCB
->ListenIrp
.ConnectionReturnInfo
)
117 ExFreePool(FCB
->ListenIrp
.ConnectionReturnInfo
);
118 FCB
->ListenIrp
.ConnectionReturnInfo
= NULL
;
121 if (FCB
->ListenIrp
.ConnectionCallInfo
)
123 ExFreePool(FCB
->ListenIrp
.ConnectionCallInfo
);
124 FCB
->ListenIrp
.ConnectionCallInfo
= NULL
;
127 SocketStateUnlock( FCB
);
128 return STATUS_FILE_CLOSED
;
131 AFD_DbgPrint(MID_TRACE
,("Completing listen request.\n"));
132 AFD_DbgPrint(MID_TRACE
,("IoStatus was %x\n", Irp
->IoStatus
.Status
));
134 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
136 SocketStateUnlock(FCB
);
137 return Irp
->IoStatus
.Status
;
140 Qelt
= ExAllocatePool( NonPagedPool
, sizeof(*Qelt
) );
142 Status
= STATUS_NO_MEMORY
;
145 FCB
->LocalAddress
->Address
[0].AddressType
;
147 Qelt
->Object
= FCB
->Connection
;
148 Qelt
->Seq
= FCB
->ConnSeq
++;
149 AFD_DbgPrint(MID_TRACE
,("Address Type: %u (RA %p)\n",
152 ConnectionReturnInfo
->RemoteAddress
));
154 Status
= TdiBuildNullConnectionInfo( &Qelt
->ConnInfo
, AddressType
);
155 if( NT_SUCCESS(Status
) ) {
156 TaCopyTransportAddressInPlace
157 ( Qelt
->ConnInfo
->RemoteAddress
,
158 FCB
->ListenIrp
.ConnectionReturnInfo
->RemoteAddress
);
159 InsertTailList( &FCB
->PendingConnections
, &Qelt
->ListEntry
);
163 /* Satisfy a pre-accept request if one is available */
164 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) &&
165 !IsListEmpty( &FCB
->PendingConnections
) ) {
166 PLIST_ENTRY PendingIrp
=
167 RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] );
168 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
170 ( CONTAINING_RECORD( PendingIrp
, IRP
,
171 Tail
.Overlay
.ListEntry
),
172 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
,
176 /* Launch new accept socket */
177 Status
= WarmSocketForConnection( FCB
);
179 if (NT_SUCCESS(Status
))
181 Status
= TdiBuildNullConnectionInfoInPlace(FCB
->ListenIrp
.ConnectionCallInfo
,
182 FCB
->LocalAddress
->Address
[0].AddressType
);
183 ASSERT(Status
== STATUS_SUCCESS
);
185 Status
= TdiBuildNullConnectionInfoInPlace(FCB
->ListenIrp
.ConnectionReturnInfo
,
186 FCB
->LocalAddress
->Address
[0].AddressType
);
187 ASSERT(Status
== STATUS_SUCCESS
);
189 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
190 FCB
->Connection
.Object
,
191 &FCB
->ListenIrp
.ConnectionCallInfo
,
192 &FCB
->ListenIrp
.ConnectionReturnInfo
,
193 &FCB
->ListenIrp
.Iosb
,
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
,
270 &FCB
->ListenIrp
.Iosb
,
274 if( Status
== STATUS_PENDING
)
275 Status
= STATUS_SUCCESS
;
277 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
278 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
281 NTSTATUS
AfdWaitForListen( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
282 PIO_STACK_LOCATION IrpSp
) {
283 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
284 PAFD_FCB FCB
= FileObject
->FsContext
;
287 UNREFERENCED_PARAMETER(DeviceObject
);
289 AFD_DbgPrint(MID_TRACE
,("Called\n"));
291 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
293 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
294 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
296 /* We have a pending connection ... complete this irp right away */
297 Status
= SatisfyPreAccept
300 ( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
) );
302 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
304 if ( !IsListEmpty( &FCB
->PendingConnections
) )
306 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
307 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
308 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
310 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
312 SocketStateUnlock( FCB
);
314 } else if (FCB
->NonBlocking
) {
315 AFD_DbgPrint(MIN_TRACE
,("No connection ready on a non-blocking socket\n"));
317 return UnlockAndMaybeComplete(FCB
, STATUS_CANT_WAIT
, Irp
, 0);
319 AFD_DbgPrint(MID_TRACE
,("Holding\n"));
321 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_PREACCEPT
);
325 NTSTATUS
AfdAccept( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
326 PIO_STACK_LOCATION IrpSp
) {
327 NTSTATUS Status
= STATUS_SUCCESS
;
328 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
329 PAFD_DEVICE_EXTENSION DeviceExt
=
330 (PAFD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
331 PAFD_FCB FCB
= FileObject
->FsContext
;
332 PAFD_ACCEPT_DATA AcceptData
= Irp
->AssociatedIrp
.SystemBuffer
;
333 PLIST_ENTRY PendingConn
;
335 AFD_DbgPrint(MID_TRACE
,("Called\n"));
337 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
339 FCB
->EventSelectDisabled
&= ~AFD_EVENT_ACCEPT
;
341 for( PendingConn
= FCB
->PendingConnections
.Flink
;
342 PendingConn
!= &FCB
->PendingConnections
;
343 PendingConn
= PendingConn
->Flink
) {
344 PAFD_TDI_OBJECT_QELT PendingConnObj
=
345 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
);
347 AFD_DbgPrint(MID_TRACE
,("Comparing Seq %u to Q %u\n",
348 AcceptData
->SequenceNumber
,
349 PendingConnObj
->Seq
));
351 if( PendingConnObj
->Seq
== AcceptData
->SequenceNumber
) {
352 PFILE_OBJECT NewFileObject
= NULL
;
354 RemoveEntryList( PendingConn
);
356 Status
= ObReferenceObjectByHandle
357 ( AcceptData
->ListenHandle
,
361 (PVOID
*)&NewFileObject
,
364 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
366 ASSERT(NewFileObject
!= FileObject
);
367 ASSERT(NewFileObject
->FsContext
!= FCB
);
369 /* We have a pending connection ... complete this irp right away */
370 Status
= SatisfyAccept( DeviceExt
, Irp
, NewFileObject
, PendingConnObj
);
372 ObDereferenceObject( NewFileObject
);
374 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
376 ExFreePool( PendingConnObj
);
378 if( !IsListEmpty( &FCB
->PendingConnections
) )
380 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
381 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
382 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
384 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
386 SocketStateUnlock( FCB
);
391 AFD_DbgPrint(MIN_TRACE
,("No connection waiting\n"));
393 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0 );