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( PDEVICE_OBJECT DeviceObject
,
85 NTSTATUS Status
= STATUS_SUCCESS
;
86 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
87 PAFD_TDI_OBJECT_QELT Qelt
;
88 PLIST_ENTRY NextIrpEntry
;
91 if( !SocketAcquireStateLock( FCB
) )
92 return STATUS_FILE_CLOSED
;
94 ASSERT(FCB
->ListenIrp
.InFlightRequest
== Irp
);
95 FCB
->ListenIrp
.InFlightRequest
= NULL
;
97 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
98 /* Cleanup our IRP queue because the FCB is being destroyed */
99 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) ) {
100 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_PREACCEPT
]);
101 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
102 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
103 NextIrp
->IoStatus
.Information
= 0;
104 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
105 (void)IoSetCancelRoutine(NextIrp
, NULL
);
106 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
109 /* Free ConnectionReturnInfo and ConnectionCallInfo */
110 if (FCB
->ListenIrp
.ConnectionReturnInfo
)
112 ExFreePool(FCB
->ListenIrp
.ConnectionReturnInfo
);
113 FCB
->ListenIrp
.ConnectionReturnInfo
= NULL
;
116 if (FCB
->ListenIrp
.ConnectionCallInfo
)
118 ExFreePool(FCB
->ListenIrp
.ConnectionCallInfo
);
119 FCB
->ListenIrp
.ConnectionCallInfo
= NULL
;
122 SocketStateUnlock( FCB
);
123 return STATUS_FILE_CLOSED
;
126 AFD_DbgPrint(MID_TRACE
,("Completing listen request.\n"));
127 AFD_DbgPrint(MID_TRACE
,("IoStatus was %x\n", Irp
->IoStatus
.Status
));
129 if (Irp
->IoStatus
.Status
!= STATUS_SUCCESS
)
131 SocketStateUnlock(FCB
);
132 return Irp
->IoStatus
.Status
;
135 Qelt
= ExAllocatePool( NonPagedPool
, sizeof(*Qelt
) );
137 Status
= STATUS_NO_MEMORY
;
140 FCB
->LocalAddress
->Address
[0].AddressType
;
142 Qelt
->Object
= FCB
->Connection
;
143 Qelt
->Seq
= FCB
->ConnSeq
++;
144 AFD_DbgPrint(MID_TRACE
,("Address Type: %d (RA %x)\n",
147 ConnectionReturnInfo
->RemoteAddress
));
149 Status
= TdiBuildNullConnectionInfo( &Qelt
->ConnInfo
, AddressType
);
150 if( NT_SUCCESS(Status
) ) {
151 TaCopyTransportAddressInPlace
152 ( Qelt
->ConnInfo
->RemoteAddress
,
153 FCB
->ListenIrp
.ConnectionReturnInfo
->RemoteAddress
);
154 InsertTailList( &FCB
->PendingConnections
, &Qelt
->ListEntry
);
158 /* Satisfy a pre-accept request if one is available */
159 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) &&
160 !IsListEmpty( &FCB
->PendingConnections
) ) {
161 PLIST_ENTRY PendingIrp
=
162 RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] );
163 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
165 ( CONTAINING_RECORD( PendingIrp
, IRP
,
166 Tail
.Overlay
.ListEntry
),
167 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
,
171 /* Launch new accept socket */
172 Status
= WarmSocketForConnection( FCB
);
174 if (NT_SUCCESS(Status
))
176 Status
= TdiBuildNullConnectionInfoInPlace(FCB
->ListenIrp
.ConnectionCallInfo
,
177 FCB
->LocalAddress
->Address
[0].AddressType
);
178 ASSERT(Status
== STATUS_SUCCESS
);
180 Status
= TdiBuildNullConnectionInfoInPlace(FCB
->ListenIrp
.ConnectionReturnInfo
,
181 FCB
->LocalAddress
->Address
[0].AddressType
);
182 ASSERT(Status
== STATUS_SUCCESS
);
184 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
185 FCB
->Connection
.Object
,
186 &FCB
->ListenIrp
.ConnectionCallInfo
,
187 &FCB
->ListenIrp
.ConnectionReturnInfo
,
188 &FCB
->ListenIrp
.Iosb
,
192 if (Status
== STATUS_PENDING
)
193 Status
= STATUS_SUCCESS
;
196 /* Trigger a select return if appropriate */
197 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
198 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
199 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
200 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
202 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
204 SocketStateUnlock( FCB
);
209 NTSTATUS
AfdListenSocket( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
210 PIO_STACK_LOCATION IrpSp
) {
211 NTSTATUS Status
= STATUS_SUCCESS
;
212 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
213 PAFD_FCB FCB
= FileObject
->FsContext
;
214 PAFD_LISTEN_DATA ListenReq
;
216 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
218 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
220 if( !(ListenReq
= LockRequest( Irp
, IrpSp
)) )
221 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
224 if( FCB
->State
!= SOCKET_STATE_BOUND
) {
225 Status
= STATUS_INVALID_PARAMETER
;
226 AFD_DbgPrint(MIN_TRACE
,("Could not listen an unbound socket\n"));
227 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
230 FCB
->DelayedAccept
= ListenReq
->UseDelayedAcceptance
;
232 AFD_DbgPrint(MID_TRACE
,("ADDRESSFILE: %x\n", FCB
->AddressFile
.Handle
));
234 Status
= WarmSocketForConnection( FCB
);
236 AFD_DbgPrint(MID_TRACE
,("Status from warmsocket %x\n", Status
));
238 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
240 Status
= TdiBuildNullConnectionInfo
241 ( &FCB
->ListenIrp
.ConnectionCallInfo
,
242 FCB
->LocalAddress
->Address
[0].AddressType
);
244 if (!NT_SUCCESS(Status
)) return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
246 Status
= TdiBuildNullConnectionInfo
247 ( &FCB
->ListenIrp
.ConnectionReturnInfo
,
248 FCB
->LocalAddress
->Address
[0].AddressType
);
250 if (!NT_SUCCESS(Status
))
252 ExFreePool(FCB
->ListenIrp
.ConnectionCallInfo
);
253 FCB
->ListenIrp
.ConnectionCallInfo
= NULL
;
254 return UnlockAndMaybeComplete(FCB
, Status
, Irp
, 0);
257 FCB
->State
= SOCKET_STATE_LISTENING
;
259 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
260 FCB
->Connection
.Object
,
261 &FCB
->ListenIrp
.ConnectionCallInfo
,
262 &FCB
->ListenIrp
.ConnectionReturnInfo
,
263 &FCB
->ListenIrp
.Iosb
,
267 if( Status
== STATUS_PENDING
)
268 Status
= STATUS_SUCCESS
;
270 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
271 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
274 NTSTATUS
AfdWaitForListen( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
275 PIO_STACK_LOCATION IrpSp
) {
276 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
277 PAFD_FCB FCB
= FileObject
->FsContext
;
280 AFD_DbgPrint(MID_TRACE
,("Called\n"));
282 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
284 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
285 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
287 /* We have a pending connection ... complete this irp right away */
288 Status
= SatisfyPreAccept
291 ( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
) );
293 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
295 if ( !IsListEmpty( &FCB
->PendingConnections
) )
297 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
298 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
299 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
301 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
303 SocketStateUnlock( FCB
);
305 } else if (FCB
->NonBlocking
) {
306 AFD_DbgPrint(MIN_TRACE
,("No connection ready on a non-blocking socket\n"));
308 return UnlockAndMaybeComplete(FCB
, STATUS_CANT_WAIT
, Irp
, 0);
310 AFD_DbgPrint(MID_TRACE
,("Holding\n"));
312 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_PREACCEPT
);
316 NTSTATUS
AfdAccept( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
317 PIO_STACK_LOCATION IrpSp
) {
318 NTSTATUS Status
= STATUS_SUCCESS
;
319 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
320 PAFD_DEVICE_EXTENSION DeviceExt
=
321 (PAFD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
322 PAFD_FCB FCB
= FileObject
->FsContext
;
323 PAFD_ACCEPT_DATA AcceptData
= Irp
->AssociatedIrp
.SystemBuffer
;
324 PLIST_ENTRY PendingConn
;
326 AFD_DbgPrint(MID_TRACE
,("Called\n"));
328 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
330 for( PendingConn
= FCB
->PendingConnections
.Flink
;
331 PendingConn
!= &FCB
->PendingConnections
;
332 PendingConn
= PendingConn
->Flink
) {
333 PAFD_TDI_OBJECT_QELT PendingConnObj
=
334 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
);
336 AFD_DbgPrint(MID_TRACE
,("Comparing Seq %d to Q %d\n",
337 AcceptData
->SequenceNumber
,
338 PendingConnObj
->Seq
));
340 if( PendingConnObj
->Seq
== AcceptData
->SequenceNumber
) {
341 PFILE_OBJECT NewFileObject
= NULL
;
343 RemoveEntryList( PendingConn
);
345 Status
= ObReferenceObjectByHandle
346 ( AcceptData
->ListenHandle
,
350 (PVOID
*)&NewFileObject
,
353 if( !NT_SUCCESS(Status
) ) return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
355 ASSERT(NewFileObject
!= FileObject
);
356 ASSERT(NewFileObject
->FsContext
!= FCB
);
358 /* We have a pending connection ... complete this irp right away */
359 Status
= SatisfyAccept( DeviceExt
, Irp
, NewFileObject
, PendingConnObj
);
361 ObDereferenceObject( NewFileObject
);
363 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
365 ExFreePool( PendingConnObj
);
367 FCB
->EventSelectDisabled
&= ~AFD_EVENT_ACCEPT
;
369 if( !IsListEmpty( &FCB
->PendingConnections
) )
371 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
372 FCB
->PollStatus
[FD_ACCEPT_BIT
] = STATUS_SUCCESS
;
373 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
375 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
377 SocketStateUnlock( FCB
);
382 AFD_DbgPrint(MIN_TRACE
,("No connection waiting\n"));
384 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0 );