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
24 ( &FCB
->TdiDeviceName
,
25 &FCB
->Connection
.Handle
,
26 &FCB
->Connection
.Object
);
28 if( NT_SUCCESS(Status
) ) {
29 Status
= TdiAssociateAddressFile
30 ( FCB
->AddressFile
.Handle
,
31 FCB
->Connection
.Object
);
34 if( !NT_SUCCESS(Status
) ) {
35 TdiCloseDevice( &FCB
->Connection
.Handle
,
36 FCB
->Connection
.Object
);
37 RtlZeroMemory( &FCB
->Connection
, sizeof(FCB
->Connection
) );
43 NTSTATUS
MakeSocketIntoConnection( PAFD_FCB FCB
) {
46 /* Allocate the receive area and start receiving */
48 ExAllocatePool( NonPagedPool
, FCB
->Recv
.Size
);
50 ExAllocatePool( NonPagedPool
, FCB
->Send
.Size
);
52 FCB
->State
= SOCKET_STATE_CONNECTED
;
54 if( FCB
->Recv
.Window
) {
55 Status
= TdiReceive( &FCB
->ReceiveIrp
.InFlightRequest
,
56 FCB
->Connection
.Object
,
60 &FCB
->ReceiveIrp
.Iosb
,
68 NTSTATUS DDKAPI 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 LostSocket( Irp
, FALSE
);
84 AFD_DbgPrint(MID_TRACE
,("Irp->IoStatus.Status = %x\n",
85 Irp
->IoStatus
.Status
));
87 if( NT_SUCCESS(Irp
->IoStatus
.Status
) ) {
88 FCB
->PollState
|= AFD_EVENT_CONNECT
| AFD_EVENT_SEND
;
89 FCB
->State
= SOCKET_STATE_CONNECTED
;
90 AFD_DbgPrint(MID_TRACE
,("Going to connected state %d\n", FCB
->State
));
91 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
93 FCB
->PollState
|= AFD_EVENT_CONNECT_FAIL
| AFD_EVENT_RECEIVE
;
94 AFD_DbgPrint(MID_TRACE
,("Going to bound state\n"));
95 FCB
->State
= SOCKET_STATE_BOUND
;
96 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
99 /* Succeed pending irps on the FUNCTION_CONNECT list */
100 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_CONNECT
] ) ) {
101 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_CONNECT
]);
102 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
103 AFD_DbgPrint(MID_TRACE
,("Completing connect %x\n", NextIrp
));
104 NextIrp
->IoStatus
.Status
= Status
;
105 NextIrp
->IoStatus
.Information
= 0;
106 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
109 if( NT_SUCCESS(Status
) ) {
110 Status
= MakeSocketIntoConnection( FCB
);
112 if( FCB
->Send
.Window
&&
113 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
114 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
115 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
,
116 Tail
.Overlay
.ListEntry
);
117 AFD_DbgPrint(MID_TRACE
,("Launching send request %x\n", NextIrp
));
118 Status
= AfdConnectedSocketWriteData
121 IoGetCurrentIrpStackLocation( NextIrp
),
125 if( Status
== STATUS_PENDING
)
126 Status
= STATUS_SUCCESS
;
129 SocketStateUnlock( FCB
);
131 AFD_DbgPrint(MID_TRACE
,("Returning %x\n", Status
));
136 /* Return the socket object for ths request only if it is a connected or
139 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
140 PIO_STACK_LOCATION IrpSp
) {
141 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
142 PTDI_CONNECTION_INFORMATION TargetAddress
;
143 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
144 PAFD_FCB FCB
= FileObject
->FsContext
;
145 PAFD_CONNECT_INFO ConnectReq
;
146 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
148 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
149 if( !(ConnectReq
= LockRequest( Irp
, IrpSp
)) )
150 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
,
153 AFD_DbgPrint(MID_TRACE
,("Connect request:\n"));
156 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
158 switch( FCB
->State
) {
159 case SOCKET_STATE_CONNECTED
:
160 Status
= STATUS_SUCCESS
;
163 case SOCKET_STATE_CONNECTING
:
164 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
166 case SOCKET_STATE_CREATED
: {
168 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
170 if( FCB
->LocalAddress
) {
171 RtlZeroMemory( FCB
->LocalAddress
,
172 TaLengthOfTransportAddress
173 ( &ConnectReq
->RemoteAddress
) );
175 FCB
->LocalAddress
->TAAddressCount
= 1;
176 FCB
->LocalAddress
->Address
[0].AddressType
=
177 ConnectReq
->RemoteAddress
.Address
[0].AddressType
;
178 FCB
->LocalAddress
->Address
[0].AddressLength
=
179 ConnectReq
->RemoteAddress
.Address
[0].AddressLength
;
181 Status
= WarmSocketForBind( FCB
);
183 if( NT_SUCCESS(Status
) )
184 FCB
->State
= SOCKET_STATE_BOUND
;
186 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
,
189 return UnlockAndMaybeComplete
190 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
, TRUE
);
191 } /* Drop through to SOCKET_STATE_BOUND */
193 case SOCKET_STATE_BOUND
:
195 TaCopyTransportAddress( &ConnectReq
->RemoteAddress
);
197 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
199 Status
= STATUS_SUCCESS
;
203 Status
= WarmSocketForConnection( FCB
);
205 if( !NT_SUCCESS(Status
) )
208 FCB
->State
= SOCKET_STATE_CONNECTING
;
210 TdiBuildConnectionInfo
212 &ConnectReq
->RemoteAddress
);
214 if( TargetAddress
) {
215 Status
= TdiConnect( &FCB
->ConnectIrp
.InFlightRequest
,
216 FCB
->Connection
.Object
,
218 &FCB
->ConnectIrp
.Iosb
,
219 StreamSocketConnectComplete
,
222 ExFreePool( TargetAddress
);
224 AFD_DbgPrint(MID_TRACE
,("Queueing IRP %x\n", Irp
));
226 if( Status
== STATUS_PENDING
)
227 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_CONNECT
);
228 } else Status
= STATUS_NO_MEMORY
;
232 AFD_DbgPrint(MID_TRACE
,("Inappropriate socket state %d for connect\n",
237 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0, NULL
, TRUE
);