- Fix more leaks
[reactos.git] / drivers / network / afd / afd / connect.c
1 /* $Id$
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)
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 NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) {
16 NTSTATUS Status;
17
18 if( !FCB->TdiDeviceName.Length || !FCB->TdiDeviceName.Buffer ) {
19 AFD_DbgPrint(MID_TRACE,("Null Device\n"));
20 return STATUS_NO_SUCH_DEVICE;
21 }
22
23 Status = TdiOpenConnectionEndpointFile(&FCB->TdiDeviceName,
24 &FCB->Connection.Handle,
25 &FCB->Connection.Object );
26
27 if( NT_SUCCESS(Status) ) {
28 Status = TdiAssociateAddressFile( FCB->AddressFile.Handle,
29 FCB->Connection.Object );
30 }
31
32 return Status;
33 }
34
35 NTSTATUS MakeSocketIntoConnection( PAFD_FCB FCB ) {
36 NTSTATUS Status = STATUS_NO_MEMORY;
37
38 /* Allocate the receive area and start receiving */
39 FCB->Recv.Window =
40 ExAllocatePool( NonPagedPool, FCB->Recv.Size );
41 FCB->Send.Window =
42 ExAllocatePool( NonPagedPool, FCB->Send.Size );
43
44 FCB->State = SOCKET_STATE_CONNECTED;
45
46 if( FCB->Recv.Window ) {
47 Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
48 FCB->Connection.Object,
49 TDI_RECEIVE_NORMAL,
50 FCB->Recv.Window,
51 FCB->Recv.Size,
52 &FCB->ReceiveIrp.Iosb,
53 ReceiveComplete,
54 FCB );
55 }
56
57 return Status;
58 }
59
60 static NTSTATUS NTAPI StreamSocketConnectComplete
61 ( PDEVICE_OBJECT DeviceObject,
62 PIRP Irp,
63 PVOID Context ) {
64 NTSTATUS Status = Irp->IoStatus.Status;
65 PAFD_FCB FCB = (PAFD_FCB)Context;
66 PLIST_ENTRY NextIrpEntry;
67 PIRP NextIrp;
68
69 AFD_DbgPrint(MID_TRACE,("Called: FCB %x, FO %x\n",
70 Context, FCB->FileObject));
71
72 /* I was wrong about this before as we can have pending writes to a not
73 * yet connected socket */
74 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
75
76 AFD_DbgPrint(MID_TRACE,("Irp->IoStatus.Status = %x\n",
77 Irp->IoStatus.Status));
78
79 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
80 FCB->PollState |= AFD_EVENT_CONNECT | AFD_EVENT_SEND;
81 FCB->State = SOCKET_STATE_CONNECTED;
82 AFD_DbgPrint(MID_TRACE,("Going to connected state %d\n", FCB->State));
83 PollReeval( FCB->DeviceExt, FCB->FileObject );
84 } else {
85 FCB->PollState |= AFD_EVENT_CONNECT_FAIL | AFD_EVENT_RECEIVE;
86 AFD_DbgPrint(MID_TRACE,("Going to bound state\n"));
87 FCB->State = SOCKET_STATE_BOUND;
88 PollReeval( FCB->DeviceExt, FCB->FileObject );
89 }
90
91 /* Succeed pending irps on the FUNCTION_CONNECT list */
92 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_CONNECT] ) ) {
93 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_CONNECT]);
94 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
95 AFD_DbgPrint(MID_TRACE,("Completing connect %x\n", NextIrp));
96 NextIrp->IoStatus.Status = Status;
97 NextIrp->IoStatus.Information = 0;
98 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
99 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
100 }
101
102 if( NT_SUCCESS(Status) ) {
103 Status = MakeSocketIntoConnection( FCB );
104
105 if( FCB->Send.Window &&
106 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
107 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
108 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP,
109 Tail.Overlay.ListEntry);
110 AFD_DbgPrint(MID_TRACE,("Launching send request %x\n", NextIrp));
111 Status = AfdConnectedSocketWriteData
112 ( DeviceObject,
113 NextIrp,
114 IoGetCurrentIrpStackLocation( NextIrp ),
115 FALSE );
116 }
117
118 if( Status == STATUS_PENDING )
119 Status = STATUS_SUCCESS;
120 }
121
122 SocketStateUnlock( FCB );
123
124 AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
125
126 return Status;
127 }
128
129 /* Return the socket object for ths request only if it is a connected or
130 stream type. */
131 NTSTATUS STDCALL
132 AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
133 PIO_STACK_LOCATION IrpSp) {
134 NTSTATUS Status = STATUS_INVALID_PARAMETER;
135 PTDI_CONNECTION_INFORMATION TargetAddress;
136 PFILE_OBJECT FileObject = IrpSp->FileObject;
137 PAFD_FCB FCB = FileObject->FsContext;
138 PAFD_CONNECT_INFO ConnectReq;
139 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
140
141 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
142 if( !(ConnectReq = LockRequest( Irp, IrpSp )) )
143 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp,
144 0, NULL );
145
146 AFD_DbgPrint(MID_TRACE,("Connect request:\n"));
147 #if 0
148 OskitDumpBuffer
149 ( (PCHAR)ConnectReq,
150 IrpSp->Parameters.DeviceIoControl.InputBufferLength );
151 #endif
152
153 switch( FCB->State ) {
154 case SOCKET_STATE_CONNECTED:
155 Status = STATUS_SUCCESS;
156 break;
157
158 case SOCKET_STATE_CONNECTING:
159 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT );
160
161 case SOCKET_STATE_CREATED: {
162 FCB->LocalAddress =
163 TaCopyTransportAddress( &ConnectReq->RemoteAddress );
164
165 if( FCB->LocalAddress ) {
166 RtlZeroMemory( FCB->LocalAddress,
167 TaLengthOfTransportAddress
168 ( &ConnectReq->RemoteAddress ) );
169
170 FCB->LocalAddress->TAAddressCount = 1;
171 FCB->LocalAddress->Address[0].AddressType =
172 ConnectReq->RemoteAddress.Address[0].AddressType;
173 FCB->LocalAddress->Address[0].AddressLength =
174 ConnectReq->RemoteAddress.Address[0].AddressLength;
175
176 Status = WarmSocketForBind( FCB );
177
178 if( NT_SUCCESS(Status) )
179 FCB->State = SOCKET_STATE_BOUND;
180 else
181 return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL );
182 } else
183 return UnlockAndMaybeComplete
184 ( FCB, STATUS_NO_MEMORY, Irp, 0, NULL );
185 } /* Drop through to SOCKET_STATE_BOUND */
186
187 case SOCKET_STATE_BOUND:
188 FCB->RemoteAddress =
189 TaCopyTransportAddress( &ConnectReq->RemoteAddress );
190
191 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
192 {
193 Status = STATUS_SUCCESS;
194 break;
195 }
196
197 Status = WarmSocketForConnection( FCB );
198
199 if( !NT_SUCCESS(Status) )
200 break;
201
202 FCB->State = SOCKET_STATE_CONNECTING;
203
204 TdiBuildConnectionInfo
205 ( &TargetAddress,
206 &ConnectReq->RemoteAddress );
207
208 if( TargetAddress ) {
209 Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest,
210 FCB->Connection.Object,
211 TargetAddress,
212 &FCB->ConnectIrp.Iosb,
213 StreamSocketConnectComplete,
214 FCB );
215
216 ExFreePool( TargetAddress );
217
218 AFD_DbgPrint(MID_TRACE,("Queueing IRP %x\n", Irp));
219
220 if( Status == STATUS_PENDING )
221 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT );
222 } else Status = STATUS_NO_MEMORY;
223 break;
224
225 default:
226 AFD_DbgPrint(MID_TRACE,("Inappropriate socket state %d for connect\n",
227 FCB->State));
228 break;
229 }
230
231 return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL );
232 }