- Get afd to build.
[reactos.git] / reactos / drivers / net / 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
24 ( &FCB->TdiDeviceName,
25 &FCB->Connection.Handle,
26 &FCB->Connection.Object );
27
28 if( NT_SUCCESS(Status) ) {
29 Status = TdiAssociateAddressFile
30 ( FCB->AddressFile.Handle,
31 FCB->Connection.Object );
32 }
33
34 if( !NT_SUCCESS(Status) ) {
35 TdiCloseDevice( &FCB->Connection.Handle,
36 FCB->Connection.Object );
37 RtlZeroMemory( &FCB->Connection, sizeof(FCB->Connection) );
38 }
39
40 return Status;
41 }
42
43 NTSTATUS MakeSocketIntoConnection( PAFD_FCB FCB ) {
44 NTSTATUS Status = STATUS_NO_MEMORY;
45
46 /* Allocate the receive area and start receiving */
47 FCB->Recv.Window =
48 ExAllocatePool( NonPagedPool, FCB->Recv.Size );
49 FCB->Send.Window =
50 ExAllocatePool( NonPagedPool, FCB->Send.Size );
51
52 FCB->State = SOCKET_STATE_CONNECTED;
53
54 if( FCB->Recv.Window ) {
55 Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
56 FCB->Connection.Object,
57 TDI_RECEIVE_NORMAL,
58 FCB->Recv.Window,
59 FCB->Recv.Size,
60 &FCB->ReceiveIrp.Iosb,
61 ReceiveComplete,
62 FCB );
63 }
64
65 return Status;
66 }
67
68 static NTSTATUS NTAPI StreamSocketConnectComplete
69 ( PDEVICE_OBJECT DeviceObject,
70 PIRP Irp,
71 PVOID Context ) {
72 NTSTATUS Status = Irp->IoStatus.Status;
73 PAFD_FCB FCB = (PAFD_FCB)Context;
74 PLIST_ENTRY NextIrpEntry;
75 PIRP NextIrp;
76
77 AFD_DbgPrint(MID_TRACE,("Called: FCB %x, FO %x\n",
78 Context, FCB->FileObject));
79
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 );
83
84 AFD_DbgPrint(MID_TRACE,("Irp->IoStatus.Status = %x\n",
85 Irp->IoStatus.Status));
86
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 );
92 } else {
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 );
97 }
98
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 );
107 }
108
109 if( NT_SUCCESS(Status) ) {
110 Status = MakeSocketIntoConnection( FCB );
111
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
119 ( DeviceObject,
120 NextIrp,
121 IoGetCurrentIrpStackLocation( NextIrp ),
122 FALSE );
123 }
124
125 if( Status == STATUS_PENDING )
126 Status = STATUS_SUCCESS;
127 }
128
129 SocketStateUnlock( FCB );
130
131 AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
132
133 return Status;
134 }
135
136 /* Return the socket object for ths request only if it is a connected or
137 stream type. */
138 NTSTATUS STDCALL
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));
147
148 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
149 if( !(ConnectReq = LockRequest( Irp, IrpSp )) )
150 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp,
151 0, NULL, TRUE );
152
153 AFD_DbgPrint(MID_TRACE,("Connect request:\n"));
154 #if 0
155 OskitDumpBuffer
156 ( (PCHAR)ConnectReq,
157 IrpSp->Parameters.DeviceIoControl.InputBufferLength );
158 #endif
159
160 switch( FCB->State ) {
161 case SOCKET_STATE_CONNECTED:
162 Status = STATUS_SUCCESS;
163 break;
164
165 case SOCKET_STATE_CONNECTING:
166 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT );
167
168 case SOCKET_STATE_CREATED: {
169 FCB->LocalAddress =
170 TaCopyTransportAddress( &ConnectReq->RemoteAddress );
171
172 if( FCB->LocalAddress ) {
173 RtlZeroMemory( FCB->LocalAddress,
174 TaLengthOfTransportAddress
175 ( &ConnectReq->RemoteAddress ) );
176
177 FCB->LocalAddress->TAAddressCount = 1;
178 FCB->LocalAddress->Address[0].AddressType =
179 ConnectReq->RemoteAddress.Address[0].AddressType;
180 FCB->LocalAddress->Address[0].AddressLength =
181 ConnectReq->RemoteAddress.Address[0].AddressLength;
182
183 Status = WarmSocketForBind( FCB );
184
185 if( NT_SUCCESS(Status) )
186 FCB->State = SOCKET_STATE_BOUND;
187 else
188 return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL,
189 TRUE );
190 } else
191 return UnlockAndMaybeComplete
192 ( FCB, STATUS_NO_MEMORY, Irp, 0, NULL, TRUE );
193 } /* Drop through to SOCKET_STATE_BOUND */
194
195 case SOCKET_STATE_BOUND:
196 FCB->RemoteAddress =
197 TaCopyTransportAddress( &ConnectReq->RemoteAddress );
198
199 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
200 {
201 Status = STATUS_SUCCESS;
202 break;
203 }
204
205 Status = WarmSocketForConnection( FCB );
206
207 if( !NT_SUCCESS(Status) )
208 break;
209
210 FCB->State = SOCKET_STATE_CONNECTING;
211
212 TdiBuildConnectionInfo
213 ( &TargetAddress,
214 &ConnectReq->RemoteAddress );
215
216 if( TargetAddress ) {
217 Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest,
218 FCB->Connection.Object,
219 TargetAddress,
220 &FCB->ConnectIrp.Iosb,
221 StreamSocketConnectComplete,
222 FCB );
223
224 ExFreePool( TargetAddress );
225
226 AFD_DbgPrint(MID_TRACE,("Queueing IRP %x\n", Irp));
227
228 if( Status == STATUS_PENDING )
229 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT );
230 } else Status = STATUS_NO_MEMORY;
231 break;
232
233 default:
234 AFD_DbgPrint(MID_TRACE,("Inappropriate socket state %d for connect\n",
235 FCB->State));
236 break;
237 }
238
239 return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
240 }