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)
11 #include "tdi_proto.h"
15 VOID
SatisfyAccept( PIRP Irp
, PFILE_OBJECT NewFileObject
,
16 PAFD_TDI_OBJECT_QELT Qelt
) {
17 PAFD_FCB FCB
= NewFileObject
->FsContext
;
19 if( !SocketAcquireStateLock( FCB
) ) return;
21 /* Transfer the connection to the new socket, launch the opening read */
22 AFD_DbgPrint(MID_TRACE
,("Completing a real accept (FCB %x)\n", FCB
));
24 FCB
->State
= SOCKET_STATE_CONNECTED
;
25 FCB
->Connection
= Qelt
->Object
;
28 TaCopyTransportAddress( Qelt
->ConnInfo
->RemoteAddress
);
31 Irp
->IoStatus
.Information
= 0;
32 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
33 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
35 MakeSocketIntoConnection( FCB
);
37 SocketStateUnlock( FCB
);
40 VOID
SatisfyPreAccept( PIRP Irp
, PAFD_TDI_OBJECT_QELT Qelt
) {
41 PAFD_RECEIVED_ACCEPT_DATA ListenReceive
=
42 (PAFD_RECEIVED_ACCEPT_DATA
)Irp
->AssociatedIrp
.SystemBuffer
;
44 ListenReceive
->SequenceNumber
= Qelt
->Seq
;
45 AFD_DbgPrint(MID_TRACE
,("Giving SEQ %d to userland\n", Qelt
->Seq
));
47 TaCopyTransportAddressInPlace( &ListenReceive
->Address
,
48 Qelt
->ConnInfo
->RemoteAddress
);
51 Irp
->IoStatus
.Information
= sizeof(*ListenReceive
);
52 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
53 IoCompleteRequest( Irp
, IO_NETWORK_INCREMENT
);
56 NTSTATUS DDKAPI ListenComplete
57 ( PDEVICE_OBJECT DeviceObject
,
60 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
61 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
62 PAFD_TDI_OBJECT_QELT Qelt
;
64 if( !SocketAcquireStateLock( FCB
) ) return Status
;
66 FCB
->ListenIrp
.InFlightRequest
= NULL
;
68 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
69 SocketStateUnlock( FCB
);
71 return STATUS_SUCCESS
;
74 AFD_DbgPrint(MID_TRACE
,("Completing listen request.\n"));
75 AFD_DbgPrint(MID_TRACE
,("IoStatus was %x\n", FCB
->ListenIrp
.Iosb
.Status
));
77 Qelt
= ExAllocatePool( NonPagedPool
, sizeof(*Qelt
) );
79 TdiCloseDevice( FCB
->Connection
.Handle
,
80 FCB
->Connection
.Object
);
82 Qelt
->Object
= FCB
->Connection
;
83 Qelt
->Seq
= FCB
->ConnSeq
++;
84 InsertTailList( &FCB
->PendingConnections
, &Qelt
->ListEntry
);
87 /* Satisfy a pre-accept request if one is available */
88 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] ) &&
89 !IsListEmpty( &FCB
->PendingConnections
) ) {
90 PLIST_ENTRY PendingIrp
=
91 RemoveHeadList( &FCB
->PendingIrpList
[FUNCTION_PREACCEPT
] );
92 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
94 ( CONTAINING_RECORD( PendingIrp
, IRP
,
95 Tail
.Overlay
.ListEntry
),
96 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
,
100 FCB
->NeedsNewListen
= TRUE
;
102 /* Trigger a select return if appropriate */
103 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
104 FCB
->PollState
|= AFD_EVENT_ACCEPT
;
105 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
107 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
110 SocketStateUnlock( FCB
);
112 return STATUS_SUCCESS
;
115 NTSTATUS
AfdListenSocket(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
116 PIO_STACK_LOCATION IrpSp
) {
117 NTSTATUS Status
= STATUS_SUCCESS
;
118 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
119 PAFD_FCB FCB
= FileObject
->FsContext
;
120 PAFD_LISTEN_DATA ListenReq
;
122 AFD_DbgPrint(MID_TRACE
,("Called\n"));
124 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, TRUE
);
126 if( !(ListenReq
= LockRequest( Irp
, IrpSp
)) )
127 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
130 if( FCB
->State
!= SOCKET_STATE_BOUND
) {
131 Status
= STATUS_UNSUCCESSFUL
;
132 AFD_DbgPrint(MID_TRACE
,("Could not listen an unbound socket\n"));
133 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
, TRUE
);
136 FCB
->DelayedAccept
= ListenReq
->UseDelayedAcceptance
;
138 AFD_DbgPrint(MID_TRACE
,("ADDRESSFILE: %x\n", FCB
->AddressFile
.Handle
));
140 Status
= WarmSocketForConnection( FCB
);
142 FCB
->State
= SOCKET_STATE_LISTENING
;
144 AFD_DbgPrint(MID_TRACE
,("Status from warmsocket %x\n", Status
));
146 TdiBuildNullConnectionInfo
147 ( &FCB
->ListenIrp
.ConnectionCallInfo
,
148 FCB
->LocalAddress
->Address
[0].AddressType
);
149 TdiBuildNullConnectionInfo
150 ( &FCB
->ListenIrp
.ConnectionReturnInfo
,
151 FCB
->LocalAddress
->Address
[0].AddressType
);
153 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
154 FCB
->Connection
.Object
,
155 &FCB
->ListenIrp
.ConnectionCallInfo
,
156 &FCB
->ListenIrp
.ConnectionReturnInfo
,
157 &FCB
->ListenIrp
.Iosb
,
161 if( NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
162 Status
= STATUS_SUCCESS
;
164 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
165 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
, TRUE
);
168 NTSTATUS
AfdWaitForListen( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
169 PIO_STACK_LOCATION IrpSp
) {
170 NTSTATUS Status
= STATUS_SUCCESS
;
171 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
172 PAFD_FCB FCB
= FileObject
->FsContext
;
174 AFD_DbgPrint(MID_TRACE
,("Called\n"));
176 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, TRUE
);
178 if( !IsListEmpty( &FCB
->PendingConnections
) ) {
179 PLIST_ENTRY PendingConn
= FCB
->PendingConnections
.Flink
;
181 /* We have a pending connection ... complete this irp right away */
185 ( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
) );
187 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
189 SocketStateUnlock( FCB
);
192 AFD_DbgPrint(MID_TRACE
,("Holding\n"));
194 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_PREACCEPT
);
198 NTSTATUS
AfdAccept( PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
199 PIO_STACK_LOCATION IrpSp
) {
200 NTSTATUS Status
= STATUS_SUCCESS
;
201 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
202 PAFD_FCB FCB
= FileObject
->FsContext
;
203 PAFD_ACCEPT_DATA AcceptData
= Irp
->AssociatedIrp
.SystemBuffer
;
204 PLIST_ENTRY PendingConn
;
206 AFD_DbgPrint(MID_TRACE
,("Called\n"));
208 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, TRUE
);
210 if( FCB
->NeedsNewListen
) {
211 AFD_DbgPrint(MID_TRACE
,("ADDRESSFILE: %x\n", FCB
->AddressFile
.Handle
));
213 /* Launch new accept socket */
214 Status
= WarmSocketForConnection( FCB
);
216 if( Status
== STATUS_SUCCESS
) {
217 TdiBuildNullConnectionInfo
218 ( &FCB
->ListenIrp
.ConnectionReturnInfo
,
219 FCB
->LocalAddress
->Address
[0].AddressType
);
221 Status
= TdiListen( &FCB
->ListenIrp
.InFlightRequest
,
222 FCB
->Connection
.Object
,
223 &FCB
->ListenIrp
.ConnectionCallInfo
,
224 &FCB
->ListenIrp
.ConnectionReturnInfo
,
225 &FCB
->ListenIrp
.Iosb
,
229 FCB
->NeedsNewListen
= FALSE
;
232 for( PendingConn
= FCB
->PendingConnections
.Flink
;
233 PendingConn
!= &FCB
->PendingConnections
;
234 PendingConn
= PendingConn
->Flink
) {
235 PAFD_TDI_OBJECT_QELT PendingConnObj
=
236 CONTAINING_RECORD( PendingConn
, AFD_TDI_OBJECT_QELT
, ListEntry
);
238 AFD_DbgPrint(MID_TRACE
,("Comparing Seq %d to Q %d\n",
239 AcceptData
->SequenceNumber
,
240 PendingConnObj
->Seq
));
242 if( PendingConnObj
->Seq
== AcceptData
->SequenceNumber
) {
243 PFILE_OBJECT NewFileObject
;
245 RemoveEntryList( PendingConn
);
247 Status
= ObReferenceObjectByHandle
248 ( (HANDLE
)AcceptData
->ListenHandle
,
252 (PVOID
*)&NewFileObject
,
255 /* We have a pending connection ... complete this irp right away */
256 SatisfyAccept( Irp
, NewFileObject
, PendingConnObj
);
258 ObDereferenceObject( NewFileObject
);
260 AFD_DbgPrint(MID_TRACE
,("Completed a wait for accept\n"));
262 ExFreePool( PendingConnObj
);
264 if( IsListEmpty( &FCB
->PendingConnections
) )
265 FCB
->PollState
&= ~AFD_EVENT_ACCEPT
;
267 SocketStateUnlock( FCB
);
272 SocketStateUnlock( FCB
);
273 return STATUS_UNSUCCESSFUL
;