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 if( !SocketAcquireStateLock( FCB
) )
20 return LostSocket( Irp
);
22 /* Transfer the connection to the new socket, launch the opening read */
23 AFD_DbgPrint(MID_TRACE
,("Completing a real accept (FCB %x)\n", FCB
));
25 FCB
->Connection
= Qelt
->Object
;
27 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
29 TaCopyTransportAddress( Qelt
->ConnInfo
->RemoteAddress
);
31 if( !FCB
->RemoteAddress
)
32 Status
= STATUS_NO_MEMORY
;
34 Status
= MakeSocketIntoConnection( FCB
);
36 if (NT_SUCCESS(Status
))
37 Status
= TdiBuildConnectionInfo(&FCB
->ConnectCallInfo
, FCB
->RemoteAddress
);
39 if (NT_SUCCESS(Status
))
40 Status
= TdiBuildConnectionInfo(&FCB
->ConnectReturnInfo
, FCB
->RemoteAddress
);
42 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
45 static NTSTATUS
SatisfyPreAccept( PIRP Irp
, PAFD_TDI_OBJECT_QELT Qelt
) {
46 PAFD_RECEIVED_ACCEPT_DATA ListenReceive
=
47 (PAFD_RECEIVED_ACCEPT_DATA
)Irp
->AssociatedIrp
.SystemBuffer
;
48 PTA_IP_ADDRESS IPAddr
;
50 ListenReceive
->SequenceNumber
= Qelt
->Seq
;
52 AFD_DbgPrint(MID_TRACE
,("Giving SEQ %d to userland\n", Qelt
->Seq
));
53 AFD_DbgPrint(MID_TRACE
,("Socket Address (K) %x (U) %x\n",
54 &ListenReceive
->Address
,
55 Qelt
->ConnInfo
->RemoteAddress
));
57 TaCopyTransportAddressInPlace( &ListenReceive
->Address
,
58 Qelt
->ConnInfo
->RemoteAddress
);
60 IPAddr
= (PTA_IP_ADDRESS
)&ListenReceive
->Address
;
62 AFD_DbgPrint(MID_TRACE
,("IPAddr->TAAddressCount %d\n",
63 IPAddr
->TAAddressCount
));
64 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].AddressType %d\n",
65 IPAddr
->Address
[0].AddressType
));
66 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].AddressLength %d\n",
67 IPAddr
->Address
[0].AddressLength
));
68 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].Address[0].sin_port %x\n",
69 IPAddr
->Address
[0].Address
[0].sin_port
));
70 AFD_DbgPrint(MID_TRACE
,("IPAddr->Address[0].Address[0].sin_addr %x\n",
71 IPAddr
->Address
[0].Address
[0].in_addr
));
73 if( Irp
->MdlAddress
) UnlockRequest( Irp
, IoGetCurrentIrpStackLocation( Irp
) );
75 Irp
->IoStatus
.Information
= ((PCHAR
)&IPAddr
[1]) - ((PCHAR
)ListenReceive
);
76 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
77 (void)IoSetCancelRoutine(Irp
, NULL
);
78 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
79 return STATUS_SUCCESS
;
82 static NTSTATUS NTAPI ListenComplete
83 ( PDEVICE_OBJECT DeviceObject
,
86 NTSTATUS Status
= STATUS_SUCCESS
;
87 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
88 PAFD_TDI_OBJECT_QELT Qelt
;
89 PLIST_ENTRY NextIrpEntry
;
92 if( !SocketAcquireStateLock( FCB
) )
93 return STATUS_FILE_CLOSED
;
95 ASSERT(FCB
->ListenIrp
.InFlightRequest
== Irp
);
96 FCB
->ListenIrp
.InFlightRequest
= NULL
;
98 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
99 /* Cleanup our IRP queue because the FCB is being destroyed */
100 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) ) {
101 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_PREACCEPT
]);
102 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
103 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
104 NextIrp
->IoStatus
.Information
= 0;
105 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
106 (void)IoSetCancelRoutine(NextIrp
, NULL
);
107 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
110 /* Free ConnectionReturnInfo and ConnectionCallInfo */
111 if (FCB
->ListenIrp
.ConnectionReturnInfo
)
113 ExFreePool(FCB
->ListenIrp
.ConnectionReturnInfo
);
114 FCB
->ListenIrp
.ConnectionReturnInfo
= NULL
;
117 if (FCB
->ListenIrp
.ConnectionCallInfo
)
119 ExFreePool(FCB
->ListenIrp
.ConnectionCallInfo
);
120 FCB
->ListenIrp
.ConnectionCallInfo
= NULL
;
123 SocketStateUnlock( FCB
);
124 return STATUS_FILE_CLOSED
;
127 AFD_DbgPrint(MID_TRACE
,("Completing listen request.\n"));
128 AFD_DbgPrint(MID_TRACE
,("IoStatus was %x\n", Irp
->IoStatus
.Status
));
130 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
132 SocketStateUnlock(FCB
);
133 return Irp
->IoStatus
.Status
;
136 Qelt
= ExAllocatePool( NonPagedPool
, sizeof(*Qelt
) );
138 Status
= STATUS_NO_MEMORY
;
141 FCB
->LocalAddress
->Address
[0].AddressType
;
143 Qelt
->Object
= FCB
->Connection
;
144 Qelt
->Seq
= FCB
->ConnSeq
++;
145 AFD_DbgPrint(MID_TRACE
,("Address Type: %d (RA %x)\n",
148 ConnectionReturnInfo
->RemoteAddress
));
150 Status
= TdiBuildNullConnectionInfo( &Qelt
->ConnInfo
, AddressType
);
151 if( NT_SUCCESS(Status
) ) {
152 TaCopyTransportAddressInPlace
153 ( Qelt
->ConnInfo
->RemoteAddress
,
154 FCB
->ListenIrp
.ConnectionReturnInfo
->RemoteAddress
);
155 InsertTailList( &FCB
->PendingConnections
, &Qelt
->ListEntry
);
159 /* Satisfy a pre-accept request if one is available */
160 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) &&
161 !IsListEmpty( &FCB
->PendingConnections
) ) {
162 PLIST_ENTRY PendingIrp
=
163 RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] );
164 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
166 ( CONTAINING_RECORD( PendingIrp
, IRP
,
167 Tail
.Overlay
.ListEntry
),
168 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
,
172 /* Launch new accept socket */
173 Status
= WarmSocketForConnection( FCB
);
175 if (NT_SUCCESS(Status
))
177 Status
= TdiBuildNullConnectionInfoInPlace(FCB
->ListenIrp
.ConnectionCallInfo
,
178 FCB
->LocalAddress
->Address
[0].AddressType
);
179 ASSERT(Status
== STATUS_SUCCESS
);
181 Status
= TdiBuildNullConnectionInfoInPlace(FCB
->ListenIrp
.ConnectionReturnInfo
,
182 FCB
->LocalAddress
->Address
[0].AddressType
);
183 ASSERT(Status
== STATUS_SUCCESS
);
185 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
186 FCB
->Connection
.Object
,
187 &FCB
->ListenIrp
.ConnectionCallInfo
,
188 &FCB
->ListenIrp
.ConnectionReturnInfo
,
189 &FCB
->ListenIrp
.Iosb
,
193 if (Status
== STATUS_PENDING
)
194 Status
= STATUS_SUCCESS
;
197 /* Trigger a select return if appropriate */
198 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
199 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
200 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
201 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
203 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
205 SocketStateUnlock( FCB
);
210 NTSTATUS
AfdListenSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
211 PIO_STACK_LOCATION IrpSp
) {
212 NTSTATUS Status
= STATUS_SUCCESS
;
213 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
214 PAFD_FCB FCB
= FileObject
->FsContext
;
215 PAFD_LISTEN_DATA ListenReq
;
217 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
219 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
221 if( !(ListenReq
= LockRequest( Irp
, IrpSp
)) )
222 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
225 if( FCB
->State
!= SOCKET_STATE_BOUND
) {
226 Status
= STATUS_INVALID_PARAMETER
;
227 AFD_DbgPrint(MIN_TRACE
,("Could not listen an unbound socket\n"));
228 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
231 FCB
->DelayedAccept
= ListenReq
->UseDelayedAcceptance
;
233 AFD_DbgPrint(MID_TRACE
,("ADDRESSFILE: %x\n", FCB
->AddressFile
.Handle
));
235 Status
= WarmSocketForConnection( FCB
);
237 AFD_DbgPrint(MID_TRACE
,("Status from warmsocket %x\n", Status
));
239 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
241 Status
= TdiBuildNullConnectionInfo
242 ( &FCB
->ListenIrp
.ConnectionCallInfo
,
243 FCB
->LocalAddress
->Address
[0].AddressType
);
245 if (!NT_SUCCESS(Status
)) return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
247 Status
= TdiBuildNullConnectionInfo
248 ( &FCB
->ListenIrp
.ConnectionReturnInfo
,
249 FCB
->LocalAddress
->Address
[0].AddressType
);
251 if (!NT_SUCCESS(Status
))
253 ExFreePool(FCB
->ListenIrp
.ConnectionCallInfo
);
254 FCB
->ListenIrp
.ConnectionCallInfo
= NULL
;
255 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
258 FCB
->State
= SOCKET_STATE_LISTENING
;
260 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
261 FCB
->Connection
.Object
,
262 &FCB
->ListenIrp
.ConnectionCallInfo
,
263 &FCB
->ListenIrp
.ConnectionReturnInfo
,
264 &FCB
->ListenIrp
.Iosb
,
268 if( Status
== STATUS_PENDING
)
269 Status
= STATUS_SUCCESS
;
271 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
272 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
275 NTSTATUS
AfdWaitForListen( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
276 PIO_STACK_LOCATION IrpSp
) {
277 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
278 PAFD_FCB FCB
= FileObject
->FsContext
;
281 AFD_DbgPrint(MID_TRACE
,("Called\n"));
283 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
285 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
286 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
288 /* We have a pending connection ... complete this irp right away */
289 Status
= SatisfyPreAccept
292 ( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
) );
294 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
296 if ( !IsListEmpty( &FCB
->PendingConnections
) )
298 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
299 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
300 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
302 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
304 SocketStateUnlock( FCB
);
306 } else if (FCB
->NonBlocking
) {
307 AFD_DbgPrint(MIN_TRACE
,("No connection ready on a non-blocking socket\n"));
309 return UnlockAndMaybeComplete(FCB
, STATUS_CANT_WAIT
, Irp
, 0);
311 AFD_DbgPrint(MID_TRACE
,("Holding\n"));
313 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_PREACCEPT
);
317 NTSTATUS
AfdAccept( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
318 PIO_STACK_LOCATION IrpSp
) {
319 NTSTATUS Status
= STATUS_SUCCESS
;
320 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
321 PAFD_DEVICE_EXTENSION DeviceExt
=
322 (PAFD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
323 PAFD_FCB FCB
= FileObject
->FsContext
;
324 PAFD_ACCEPT_DATA AcceptData
= Irp
->AssociatedIrp
.SystemBuffer
;
325 PLIST_ENTRY PendingConn
;
327 AFD_DbgPrint(MID_TRACE
,("Called\n"));
329 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
331 for( PendingConn
= FCB
->PendingConnections
.Flink
;
332 PendingConn
!= &FCB
->PendingConnections
;
333 PendingConn
= PendingConn
->Flink
) {
334 PAFD_TDI_OBJECT_QELT PendingConnObj
=
335 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
);
337 AFD_DbgPrint(MID_TRACE
,("Comparing Seq %d to Q %d\n",
338 AcceptData
->SequenceNumber
,
339 PendingConnObj
->Seq
));
341 if( PendingConnObj
->Seq
== AcceptData
->SequenceNumber
) {
342 PFILE_OBJECT NewFileObject
= NULL
;
344 RemoveEntryList( PendingConn
);
346 Status
= ObReferenceObjectByHandle
347 ( AcceptData
->ListenHandle
,
351 (PVOID
*)&NewFileObject
,
354 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
356 ASSERT(NewFileObject
!= FileObject
);
357 ASSERT(NewFileObject
->FsContext
!= FCB
);
359 /* We have a pending connection ... complete this irp right away */
360 Status
= SatisfyAccept( DeviceExt
, Irp
, NewFileObject
, PendingConnObj
);
362 ObDereferenceObject( NewFileObject
);
364 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
366 ExFreePool( PendingConnObj
);
368 FCB
->EventSelectDisabled
&= ~AFD_EVENT_ACCEPT
;
370 if( !IsListEmpty( &FCB
->PendingConnections
) )
372 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
373 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
374 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
376 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
378 SocketStateUnlock( FCB
);
383 AFD_DbgPrint(MIN_TRACE
,("No connection waiting\n"));
385 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0 );