2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/connect.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
11 #include "tdi_proto.h"
15 NTSTATUS
WarmSocketForConnection( PAFD_FCB FCB
) {
18 if( !FCB
->TdiDeviceName
.Length
|| !FCB
->TdiDeviceName
.Buffer
) {
19 AFD_DbgPrint(MID_TRACE
,("Null Device\n"));
20 return STATUS_NO_SUCH_DEVICE
;
23 Status
= TdiOpenConnectionEndpointFile(&FCB
->TdiDeviceName
,
24 &FCB
->Connection
.Handle
,
25 &FCB
->Connection
.Object
);
27 if( NT_SUCCESS(Status
) ) {
28 Status
= TdiAssociateAddressFile( FCB
->AddressFile
.Handle
,
29 FCB
->Connection
.Object
);
35 NTSTATUS
MakeSocketIntoConnection( PAFD_FCB FCB
) {
38 /* Allocate the receive area and start receiving */
40 ExAllocatePool( NonPagedPool
, FCB
->Recv
.Size
);
42 if( !FCB
->Recv
.Window
) return STATUS_NO_MEMORY
;
45 ExAllocatePool( NonPagedPool
, FCB
->Send
.Size
);
47 if( !FCB
->Send
.Window
) {
48 ExFreePool( FCB
->Recv
.Window
);
49 FCB
->Recv
.Window
= NULL
;
50 return STATUS_NO_MEMORY
;
53 FCB
->State
= SOCKET_STATE_CONNECTED
;
55 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
56 FCB
->Connection
.Object
,
60 &FCB
->ReceiveIrp
.Iosb
,
64 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
66 FCB
->PollState
|= AFD_EVENT_CONNECT
| AFD_EVENT_SEND
;
67 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
72 static NTSTATUS NTAPI StreamSocketConnectComplete
73 ( PDEVICE_OBJECT DeviceObject
,
76 NTSTATUS Status
= Irp
->IoStatus
.Status
;
77 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
78 PLIST_ENTRY NextIrpEntry
;
81 AFD_DbgPrint(MID_TRACE
,("Called: FCB %x, FO %x\n",
82 Context
, FCB
->FileObject
));
84 /* I was wrong about this before as we can have pending writes to a not
85 * yet connected socket */
86 if( !SocketAcquireStateLock( FCB
) )
87 return STATUS_FILE_CLOSED
;
89 AFD_DbgPrint(MID_TRACE
,("Irp->IoStatus.Status = %x\n",
90 Irp
->IoStatus
.Status
));
92 FCB
->ConnectIrp
.InFlightRequest
= NULL
;
94 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
95 /* Cleanup our IRP queue because the FCB is being destroyed */
96 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
97 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
98 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
99 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
100 NextIrp
->IoStatus
.Information
= 0;
101 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
102 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
104 SocketStateUnlock( FCB
);
105 return STATUS_FILE_CLOSED
;
108 if( !NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
109 FCB
->PollState
|= AFD_EVENT_CONNECT_FAIL
;
110 AFD_DbgPrint(MID_TRACE
,("Going to bound state\n"));
111 FCB
->State
= SOCKET_STATE_BOUND
;
112 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
115 /* Succeed pending irps on the FUNCTION_CONNECT list */
116 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
117 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
118 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
119 AFD_DbgPrint(MID_TRACE
,("Completing connect %x\n", NextIrp
));
120 NextIrp
->IoStatus
.Status
= Status
;
121 NextIrp
->IoStatus
.Information
= 0;
122 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
123 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
126 if( NT_SUCCESS(Status
) ) {
127 Status
= MakeSocketIntoConnection( FCB
);
129 if( !NT_SUCCESS(Status
) ) {
130 SocketStateUnlock( FCB
);
134 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
135 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
136 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
,
137 Tail
.Overlay
.ListEntry
);
138 AFD_DbgPrint(MID_TRACE
,("Launching send request %x\n", NextIrp
));
139 Status
= AfdConnectedSocketWriteData
142 IoGetCurrentIrpStackLocation( NextIrp
),
146 if( Status
== STATUS_PENDING
)
147 Status
= STATUS_SUCCESS
;
150 SocketStateUnlock( FCB
);
152 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
157 /* Return the socket object for ths request only if it is a connected or
160 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
161 PIO_STACK_LOCATION IrpSp
) {
162 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
163 PTDI_CONNECTION_INFORMATION TargetAddress
;
164 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
165 PAFD_FCB FCB
= FileObject
->FsContext
;
166 PAFD_CONNECT_INFO ConnectReq
;
167 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
169 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
170 if( !(ConnectReq
= LockRequest( Irp
, IrpSp
)) )
171 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
174 AFD_DbgPrint(MID_TRACE
,("Connect request:\n"));
178 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
181 switch( FCB
->State
) {
182 case SOCKET_STATE_CONNECTED
:
183 Status
= STATUS_SUCCESS
;
186 case SOCKET_STATE_CONNECTING
:
187 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
189 case SOCKET_STATE_CREATED
:
190 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
192 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
194 if( FCB
->LocalAddress
) {
195 Status
= WarmSocketForBind( FCB
);
197 if( NT_SUCCESS(Status
) )
198 FCB
->State
= SOCKET_STATE_BOUND
;
200 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
202 return UnlockAndMaybeComplete
203 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
205 /* Drop through to SOCKET_STATE_BOUND */
207 case SOCKET_STATE_BOUND
:
208 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
210 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
212 if( !FCB
->RemoteAddress
) {
213 Status
= STATUS_NO_MEMORY
;
217 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
219 Status
= STATUS_SUCCESS
;
223 Status
= WarmSocketForConnection( FCB
);
225 if( !NT_SUCCESS(Status
) )
228 FCB
->State
= SOCKET_STATE_CONNECTING
;
230 TdiBuildConnectionInfo
232 &ConnectReq
->RemoteAddress
);
234 if( TargetAddress
) {
235 Status
= TdiConnect( &FCB
->ConnectIrp
.InFlightRequest
,
236 FCB
->Connection
.Object
,
238 &FCB
->ConnectIrp
.Iosb
,
239 StreamSocketConnectComplete
,
242 ExFreePool( TargetAddress
);
244 AFD_DbgPrint(MID_TRACE
,("Queueing IRP %x\n", Irp
));
246 if( Status
== STATUS_PENDING
)
247 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
248 } else Status
= STATUS_NO_MEMORY
;
252 AFD_DbgPrint(MID_TRACE
,("Inappropriate socket state %d for connect\n",
257 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );