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 return STATUS_NO_MEMORY
;
52 FCB
->State
= SOCKET_STATE_CONNECTED
;
54 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
55 FCB
->Connection
.Object
,
59 &FCB
->ReceiveIrp
.Iosb
,
63 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
68 static NTSTATUS NTAPI StreamSocketConnectComplete
69 ( PDEVICE_OBJECT DeviceObject
,
72 NTSTATUS Status
= Irp
->IoStatus
.Status
;
73 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
74 PLIST_ENTRY NextIrpEntry
;
77 AFD_DbgPrint(MID_TRACE
,("Called: FCB %x, FO %x\n",
78 Context
, FCB
->FileObject
));
80 /* I was wrong about this before as we can have pending writes to a not
81 * yet connected socket */
82 if( !SocketAcquireStateLock( FCB
) ) return STATUS_FILE_CLOSED
;
84 AFD_DbgPrint(MID_TRACE
,("Irp->IoStatus.Status = %x\n",
85 Irp
->IoStatus
.Status
));
87 FCB
->ConnectIrp
.InFlightRequest
= NULL
;
90 SocketStateUnlock( FCB
);
91 return STATUS_CANCELLED
;
94 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
95 FCB
->PollState
|= AFD_EVENT_CONNECT
| AFD_EVENT_SEND
;
96 AFD_DbgPrint(MID_TRACE
,("Going to connected state %d\n", FCB
->State
));
97 FCB
->State
= SOCKET_STATE_CONNECTED
;
99 FCB
->PollState
|= AFD_EVENT_CONNECT_FAIL
| AFD_EVENT_RECEIVE
;
100 AFD_DbgPrint(MID_TRACE
,("Going to bound state\n"));
101 FCB
->State
= SOCKET_STATE_BOUND
;
104 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
106 /* Succeed pending irps on the FUNCTION_CONNECT list */
107 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
108 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
109 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
110 AFD_DbgPrint(MID_TRACE
,("Completing connect %x\n", NextIrp
));
111 NextIrp
->IoStatus
.Status
= Status
;
112 NextIrp
->IoStatus
.Information
= 0;
113 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
114 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
117 if( NT_SUCCESS(Status
) ) {
118 Status
= MakeSocketIntoConnection( FCB
);
120 if( !NT_SUCCESS(Status
) ) {
121 SocketStateUnlock( FCB
);
125 if( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
126 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
127 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
,
128 Tail
.Overlay
.ListEntry
);
129 AFD_DbgPrint(MID_TRACE
,("Launching send request %x\n", NextIrp
));
130 Status
= AfdConnectedSocketWriteData
133 IoGetCurrentIrpStackLocation( NextIrp
),
137 if( Status
== STATUS_PENDING
)
138 Status
= STATUS_SUCCESS
;
141 SocketStateUnlock( FCB
);
143 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
148 /* Return the socket object for ths request only if it is a connected or
151 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
152 PIO_STACK_LOCATION IrpSp
) {
153 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
154 PTDI_CONNECTION_INFORMATION TargetAddress
;
155 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
156 PAFD_FCB FCB
= FileObject
->FsContext
;
157 PAFD_CONNECT_INFO ConnectReq
;
158 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
160 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
161 if( !(ConnectReq
= LockRequest( Irp
, IrpSp
)) )
162 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
165 AFD_DbgPrint(MID_TRACE
,("Connect request:\n"));
169 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
172 switch( FCB
->State
) {
173 case SOCKET_STATE_CONNECTED
:
174 Status
= STATUS_SUCCESS
;
177 case SOCKET_STATE_CONNECTING
:
178 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
180 case SOCKET_STATE_CREATED
:
181 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
183 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
185 if( FCB
->LocalAddress
) {
186 RtlZeroMemory( FCB
->LocalAddress
,
187 TaLengthOfTransportAddress
188 ( &ConnectReq
->RemoteAddress
) );
190 FCB
->LocalAddress
->TAAddressCount
= 1;
191 FCB
->LocalAddress
->Address
[0].AddressType
=
192 ConnectReq
->RemoteAddress
.Address
[0].AddressType
;
193 FCB
->LocalAddress
->Address
[0].AddressLength
=
194 ConnectReq
->RemoteAddress
.Address
[0].AddressLength
;
196 Status
= WarmSocketForBind( FCB
);
198 if( NT_SUCCESS(Status
) )
199 FCB
->State
= SOCKET_STATE_BOUND
;
201 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
);
203 return UnlockAndMaybeComplete
204 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
);
206 /* Drop through to SOCKET_STATE_BOUND */
208 case SOCKET_STATE_BOUND
:
209 if( FCB
->RemoteAddress
) ExFreePool( FCB
->RemoteAddress
);
211 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
213 if( !FCB
->RemoteAddress
) {
214 Status
= STATUS_NO_MEMORY
;
218 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
220 Status
= STATUS_SUCCESS
;
224 Status
= WarmSocketForConnection( FCB
);
226 if( !NT_SUCCESS(Status
) )
229 FCB
->State
= SOCKET_STATE_CONNECTING
;
231 TdiBuildConnectionInfo
233 &ConnectReq
->RemoteAddress
);
235 if( TargetAddress
) {
236 Status
= TdiConnect( &FCB
->ConnectIrp
.InFlightRequest
,
237 FCB
->Connection
.Object
,
239 &FCB
->ConnectIrp
.Iosb
,
240 StreamSocketConnectComplete
,
243 ExFreePool( TargetAddress
);
245 AFD_DbgPrint(MID_TRACE
,("Queueing IRP %x\n", Irp
));
247 if( Status
== STATUS_PENDING
)
248 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
249 } else Status
= STATUS_NO_MEMORY
;
253 AFD_DbgPrint(MID_TRACE
,("Inappropriate socket state %d for connect\n",
258 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
);