migrate substitution keywords to SVN
[reactos.git] / reactos / drivers / net / afd / afd / listen.c
1 /* $Id$
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)
7 * UPDATE HISTORY:
8 * 20040708 Created
9 */
10 #include "afd.h"
11 #include "tdi_proto.h"
12 #include "tdiconn.h"
13 #include "debug.h"
14
15 VOID SatisfyAccept( PIRP Irp, PFILE_OBJECT NewFileObject,
16 PAFD_TDI_OBJECT_QELT Qelt ) {
17 PAFD_FCB FCB = NewFileObject->FsContext;
18
19 if( !SocketAcquireStateLock( FCB ) ) return;
20
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));
23
24 FCB->State = SOCKET_STATE_CONNECTED;
25 FCB->Connection = Qelt->Object;
26 #if 0
27 FCB->RemoteAddress =
28 TaCopyTransportAddress( Qelt->ConnInfo->RemoteAddress );
29 #endif
30
31 Irp->IoStatus.Information = 0;
32 Irp->IoStatus.Status = STATUS_SUCCESS;
33 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
34
35 MakeSocketIntoConnection( FCB );
36
37 SocketStateUnlock( FCB );
38 }
39
40 VOID SatisfyPreAccept( PIRP Irp, PAFD_TDI_OBJECT_QELT Qelt ) {
41 PAFD_RECEIVED_ACCEPT_DATA ListenReceive =
42 (PAFD_RECEIVED_ACCEPT_DATA)Irp->AssociatedIrp.SystemBuffer;
43
44 ListenReceive->SequenceNumber = Qelt->Seq;
45 AFD_DbgPrint(MID_TRACE,("Giving SEQ %d to userland\n", Qelt->Seq));
46 #if 0
47 TaCopyTransportAddressInPlace( &ListenReceive->Address,
48 Qelt->ConnInfo->RemoteAddress );
49 #endif
50
51 Irp->IoStatus.Information = sizeof(*ListenReceive);
52 Irp->IoStatus.Status = STATUS_SUCCESS;
53 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
54 }
55
56 NTSTATUS DDKAPI ListenComplete
57 ( PDEVICE_OBJECT DeviceObject,
58 PIRP Irp,
59 PVOID Context ) {
60 NTSTATUS Status = STATUS_UNSUCCESSFUL;
61 PAFD_FCB FCB = (PAFD_FCB)Context;
62 PAFD_TDI_OBJECT_QELT Qelt;
63
64 if( !SocketAcquireStateLock( FCB ) ) return Status;
65
66 FCB->ListenIrp.InFlightRequest = NULL;
67
68 if( FCB->State == SOCKET_STATE_CLOSED ) {
69 SocketStateUnlock( FCB );
70 DestroySocket( FCB );
71 return STATUS_SUCCESS;
72 }
73
74 AFD_DbgPrint(MID_TRACE,("Completing listen request.\n"));
75 AFD_DbgPrint(MID_TRACE,("IoStatus was %x\n", FCB->ListenIrp.Iosb.Status));
76
77 Qelt = ExAllocatePool( NonPagedPool, sizeof(*Qelt) );
78 if( !Qelt ) {
79 TdiCloseDevice( FCB->Connection.Handle,
80 FCB->Connection.Object );
81 } else {
82 Qelt->Object = FCB->Connection;
83 Qelt->Seq = FCB->ConnSeq++;
84 InsertTailList( &FCB->PendingConnections, &Qelt->ListEntry );
85 }
86
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;
93 SatisfyPreAccept
94 ( CONTAINING_RECORD( PendingIrp, IRP,
95 Tail.Overlay.ListEntry ),
96 CONTAINING_RECORD( PendingConn, AFD_TDI_OBJECT_QELT,
97 ListEntry ) );
98 }
99
100 FCB->NeedsNewListen = TRUE;
101
102 /* Trigger a select return if appropriate */
103 if( !IsListEmpty( &FCB->PendingConnections ) ) {
104 FCB->PollState |= AFD_EVENT_ACCEPT;
105 PollReeval( FCB->DeviceExt, FCB->FileObject );
106 } else {
107 FCB->PollState &= ~AFD_EVENT_ACCEPT;
108 }
109
110 SocketStateUnlock( FCB );
111
112 return STATUS_SUCCESS;
113 }
114
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;
121
122 AFD_DbgPrint(MID_TRACE,("Called\n"));
123
124 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE );
125
126 if( !(ListenReq = LockRequest( Irp, IrpSp )) )
127 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp,
128 0, NULL, FALSE );
129
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 );
134 }
135
136 FCB->DelayedAccept = ListenReq->UseDelayedAcceptance;
137
138 AFD_DbgPrint(MID_TRACE,("ADDRESSFILE: %x\n", FCB->AddressFile.Handle));
139
140 Status = WarmSocketForConnection( FCB );
141
142 FCB->State = SOCKET_STATE_LISTENING;
143
144 AFD_DbgPrint(MID_TRACE,("Status from warmsocket %x\n", Status));
145
146 TdiBuildNullConnectionInfo
147 ( &FCB->ListenIrp.ConnectionCallInfo,
148 FCB->LocalAddress->Address[0].AddressType );
149 TdiBuildNullConnectionInfo
150 ( &FCB->ListenIrp.ConnectionReturnInfo,
151 FCB->LocalAddress->Address[0].AddressType );
152
153 Status = TdiListen( &FCB->ListenIrp.InFlightRequest,
154 FCB->Connection.Object,
155 &FCB->ListenIrp.ConnectionCallInfo,
156 &FCB->ListenIrp.ConnectionReturnInfo,
157 &FCB->ListenIrp.Iosb,
158 ListenComplete,
159 FCB );
160
161 if( NT_SUCCESS(Status) || Status == STATUS_PENDING )
162 Status = STATUS_SUCCESS;
163
164 AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
165 return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
166 }
167
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;
173
174 AFD_DbgPrint(MID_TRACE,("Called\n"));
175
176 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE );
177
178 if( !IsListEmpty( &FCB->PendingConnections ) ) {
179 PLIST_ENTRY PendingConn = FCB->PendingConnections.Flink;
180
181 /* We have a pending connection ... complete this irp right away */
182 SatisfyPreAccept
183 ( Irp,
184 CONTAINING_RECORD
185 ( PendingConn, AFD_TDI_OBJECT_QELT, ListEntry ) );
186
187 AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n"));
188
189 SocketStateUnlock( FCB );
190 return Status;
191 } else {
192 AFD_DbgPrint(MID_TRACE,("Holding\n"));
193
194 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_PREACCEPT );
195 }
196 }
197
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;
205
206 AFD_DbgPrint(MID_TRACE,("Called\n"));
207
208 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE );
209
210 if( FCB->NeedsNewListen ) {
211 AFD_DbgPrint(MID_TRACE,("ADDRESSFILE: %x\n", FCB->AddressFile.Handle));
212
213 /* Launch new accept socket */
214 Status = WarmSocketForConnection( FCB );
215
216 if( Status == STATUS_SUCCESS ) {
217 TdiBuildNullConnectionInfo
218 ( &FCB->ListenIrp.ConnectionReturnInfo,
219 FCB->LocalAddress->Address[0].AddressType );
220
221 Status = TdiListen( &FCB->ListenIrp.InFlightRequest,
222 FCB->Connection.Object,
223 &FCB->ListenIrp.ConnectionCallInfo,
224 &FCB->ListenIrp.ConnectionReturnInfo,
225 &FCB->ListenIrp.Iosb,
226 ListenComplete,
227 FCB );
228 }
229 FCB->NeedsNewListen = FALSE;
230 }
231
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 );
237
238 AFD_DbgPrint(MID_TRACE,("Comparing Seq %d to Q %d\n",
239 AcceptData->SequenceNumber,
240 PendingConnObj->Seq));
241
242 if( PendingConnObj->Seq == AcceptData->SequenceNumber ) {
243 PFILE_OBJECT NewFileObject;
244
245 RemoveEntryList( PendingConn );
246
247 Status = ObReferenceObjectByHandle
248 ( (HANDLE)AcceptData->ListenHandle,
249 FILE_ALL_ACCESS,
250 NULL,
251 KernelMode,
252 (PVOID *)&NewFileObject,
253 NULL );
254
255 /* We have a pending connection ... complete this irp right away */
256 SatisfyAccept( Irp, NewFileObject, PendingConnObj );
257
258 ObDereferenceObject( NewFileObject );
259
260 AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n"));
261
262 ExFreePool( PendingConnObj );
263
264 if( IsListEmpty( &FCB->PendingConnections ) )
265 FCB->PollState &= ~AFD_EVENT_ACCEPT;
266
267 SocketStateUnlock( FCB );
268 return Status;
269 }
270 }
271
272 SocketStateUnlock( FCB );
273 return STATUS_UNSUCCESSFUL;
274 }