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
,
194 &FCB
->ListenIrp
.Iosb
,
198 if (Status
== STATUS_PENDING
)
199 Status
= STATUS_SUCCESS
;
202 /* Trigger a select return if appropriate */
203 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
204 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
205 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
206 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
208 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
210 SocketStateUnlock( FCB
);
215 NTSTATUS
AfdListenSocket( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
216 PIO_STACK_LOCATION IrpSp
) {
217 NTSTATUS Status
= STATUS_SUCCESS
;
218 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
219 PAFD_FCB FCB
= FileObject
->FsContext
;
220 PAFD_LISTEN_DATA ListenReq
;
222 UNREFERENCED_PARAMETER(DeviceObject
);
224 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
226 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
228 if( !(ListenReq
= LockRequest( Irp
, IrpSp
, FALSE
, NULL
)) )
229 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
232 if( FCB
->State
!= SOCKET_STATE_BOUND
) {
233 Status
= STATUS_INVALID_PARAMETER
;
234 AFD_DbgPrint(MIN_TRACE
,("Could not listen an unbound socket\n"));
235 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
238 FCB
->DelayedAccept
= ListenReq
->UseDelayedAcceptance
;
240 AFD_DbgPrint(MID_TRACE
,("ADDRESSFILE: %p\n", FCB
->AddressFile
.Handle
));
242 Status
= WarmSocketForConnection( FCB
);
244 AFD_DbgPrint(MID_TRACE
,("Status from warmsocket %x\n", Status
));
246 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
248 Status
= TdiBuildNullConnectionInfo
249 ( &FCB
->ListenIrp
.ConnectionCallInfo
,
250 FCB
->LocalAddress
->Address
[0].AddressType
);
252 if (!NT_SUCCESS(Status
)) return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
254 Status
= TdiBuildNullConnectionInfo
255 ( &FCB
->ListenIrp
.ConnectionReturnInfo
,
256 FCB
->LocalAddress
->Address
[0].AddressType
);
258 if (!NT_SUCCESS(Status
))
260 ExFreePool(FCB
->ListenIrp
.ConnectionCallInfo
);
261 FCB
->ListenIrp
.ConnectionCallInfo
= NULL
;
262 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
265 FCB
->State
= SOCKET_STATE_LISTENING
;
267 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
268 FCB
->Connection
.Object
,
269 &FCB
->ListenIrp
.ConnectionCallInfo
,
270 &FCB
->ListenIrp
.ConnectionReturnInfo
,
271 &FCB
->ListenIrp
.Iosb
,
275 if( Status
== STATUS_PENDING
)
276 Status
= STATUS_SUCCESS
;
278 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
279 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
282 NTSTATUS
AfdWaitForListen( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
283 PIO_STACK_LOCATION IrpSp
) {
284 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
285 PAFD_FCB FCB
= FileObject
->FsContext
;
288 UNREFERENCED_PARAMETER(DeviceObject
);
290 AFD_DbgPrint(MID_TRACE
,("Called\n"));
292 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
294 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
295 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
297 /* We have a pending connection ... complete this irp right away */
298 Status
= SatisfyPreAccept
301 ( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
) );
303 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
305 if ( !IsListEmpty( &FCB
->PendingConnections
) )
307 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
308 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
309 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
311 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
313 SocketStateUnlock( FCB
);
315 } else if (FCB
->NonBlocking
) {
316 AFD_DbgPrint(MIN_TRACE
,("No connection ready on a non-blocking socket\n"));
318 return UnlockAndMaybeComplete(FCB
, STATUS_CANT_WAIT
, Irp
, 0);
320 AFD_DbgPrint(MID_TRACE
,("Holding\n"));
322 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_PREACCEPT
);
326 NTSTATUS
AfdAccept( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
327 PIO_STACK_LOCATION IrpSp
) {
328 NTSTATUS Status
= STATUS_SUCCESS
;
329 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
330 PAFD_DEVICE_EXTENSION DeviceExt
=
331 (PAFD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
332 PAFD_FCB FCB
= FileObject
->FsContext
;
333 PAFD_ACCEPT_DATA AcceptData
= Irp
->AssociatedIrp
.SystemBuffer
;
334 PLIST_ENTRY PendingConn
;
336 AFD_DbgPrint(MID_TRACE
,("Called\n"));
338 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
340 FCB
->EventSelectDisabled
&= ~AFD_EVENT_ACCEPT
;
342 for( PendingConn
= FCB
->PendingConnections
.Flink
;
343 PendingConn
!= &FCB
->PendingConnections
;
344 PendingConn
= PendingConn
->Flink
) {
345 PAFD_TDI_OBJECT_QELT PendingConnObj
=
346 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
);
348 AFD_DbgPrint(MID_TRACE
,("Comparing Seq %u to Q %u\n",
349 AcceptData
->SequenceNumber
,
350 PendingConnObj
->Seq
));
352 if( PendingConnObj
->Seq
== AcceptData
->SequenceNumber
) {
353 PFILE_OBJECT NewFileObject
= NULL
;
355 RemoveEntryList( PendingConn
);
357 Status
= ObReferenceObjectByHandle
358 ( AcceptData
->ListenHandle
,
362 (PVOID
*)&NewFileObject
,
365 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
367 ASSERT(NewFileObject
!= FileObject
);
368 ASSERT(NewFileObject
->FsContext
!= FCB
);
370 /* We have a pending connection ... complete this irp right away */
371 Status
= SatisfyAccept( DeviceExt
, Irp
, NewFileObject
, PendingConnObj
);
373 ObDereferenceObject( NewFileObject
);
375 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
377 ExFreePool( PendingConnObj
);
379 if( !IsListEmpty( &FCB
->PendingConnections
) )
381 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
382 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
383 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
385 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
387 SocketStateUnlock( FCB
);
392 AFD_DbgPrint(MIN_TRACE
,("No connection waiting\n"));
394 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0 );