Removed remaining kernel imports from ip lib.
[reactos.git] / reactos / drivers / lib / ip / transport / tcp / event.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: transport/tcp/event.c
5 * PURPOSE: Transmission Control Protocol -- Events from oskittcp
6 * PROGRAMMERS: Art Yerkes
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10
11 #include "precomp.h"
12
13 extern ULONG TCP_IPIdentification;
14 extern LIST_ENTRY SleepingThreadsList;
15 extern FAST_MUTEX SleepingThreadsLock;
16
17 int TCPSocketState(void *ClientData,
18 void *WhichSocket,
19 void *WhichConnection,
20 OSK_UINT NewState ) {
21 PCONNECTION_ENDPOINT Connection = WhichConnection;
22 PTCP_COMPLETION_ROUTINE Complete;
23 PTDI_BUCKET Bucket;
24 PLIST_ENTRY Entry;
25
26 TI_DbgPrint(MID_TRACE,("Called: NewState %x (Conn %x)\n",
27 NewState, Connection));
28
29 if( !Connection ) {
30 TI_DbgPrint(MID_TRACE,("Socket closing.\n"));
31 return 0;
32 }
33
34 if( (NewState & SEL_CONNECT) &&
35 !(Connection->State & SEL_CONNECT) ) {
36 while( !IsListEmpty( &Connection->ConnectRequest ) ) {
37 Connection->State |= SEL_CONNECT;
38 Entry = RemoveHeadList( &Connection->ConnectRequest );
39 Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
40 Complete = Bucket->Request.RequestNotifyObject;
41 TI_DbgPrint(MID_TRACE,
42 ("Completing Connect Request %x\n", Bucket->Request));
43 Complete( Bucket->Request.RequestContext, STATUS_SUCCESS, 0 );
44 /* Frees the bucket allocated in TCPConnect */
45 PoolFreeBuffer( Bucket );
46 }
47 } else if( (NewState & SEL_READ) || (NewState & SEL_FIN) ) {
48 TI_DbgPrint(MID_TRACE,("Readable (or closed): irp list %s\n",
49 IsListEmpty(&Connection->ReceiveRequest) ?
50 "empty" : "nonempty"));
51
52 while( !IsListEmpty( &Connection->ReceiveRequest ) ) {
53 PIRP Irp;
54 OSK_UINT RecvLen = 0, Received = 0;
55 OSK_PCHAR RecvBuffer = 0;
56 PMDL Mdl;
57 NTSTATUS Status;
58
59 Entry = RemoveHeadList( &Connection->ReceiveRequest );
60 Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
61 Complete = Bucket->Request.RequestNotifyObject;
62
63 TI_DbgPrint(MID_TRACE,
64 ("Readable, Completing read request %x\n",
65 Bucket->Request));
66
67 Irp = Bucket->Request.RequestContext;
68 Mdl = Irp->MdlAddress;
69
70 TI_DbgPrint(MID_TRACE,
71 ("Getting the user buffer from %x\n", Mdl));
72
73 NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
74
75 TI_DbgPrint(MID_TRACE,
76 ("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
77
78 if( NewState & SEL_FIN && !RecvLen ) {
79 Status = STATUS_END_OF_FILE;
80 Received = 0;
81 } else {
82 TI_DbgPrint(MID_TRACE, ("Connection: %x\n", Connection));
83 TI_DbgPrint
84 (MID_TRACE,
85 ("Connection->SocketContext: %x\n",
86 Connection->SocketContext));
87 TI_DbgPrint(MID_TRACE, ("RecvBuffer: %x\n", RecvBuffer));
88
89 Status = TCPTranslateError
90 ( OskitTCPRecv( Connection->SocketContext,
91 RecvBuffer,
92 RecvLen,
93 &Received,
94 0 ) );
95 }
96
97 TI_DbgPrint(MID_TRACE,("TCP Bytes: %d\n", Received));
98
99 if( Status == STATUS_SUCCESS && Received != 0 ) {
100 TI_DbgPrint(MID_TRACE,("Received %d bytes with status %x\n",
101 Received, Status));
102
103 TI_DbgPrint(MID_TRACE,
104 ("Completing Receive Request: %x\n",
105 Bucket->Request));
106
107 Complete( Bucket->Request.RequestContext,
108 STATUS_SUCCESS, Received );
109 } else if( Status == STATUS_PENDING ||
110 (Status == STATUS_SUCCESS && Received == 0) ) {
111 InsertHeadList( &Connection->ReceiveRequest,
112 &Bucket->Entry );
113 break;
114 } else {
115 TI_DbgPrint(MID_TRACE,
116 ("Completing Receive request: %x %x\n",
117 Bucket->Request, Status));
118 Complete( Bucket->Request.RequestContext, Status, 0 );
119 }
120 }
121 }
122
123 return 0;
124 }
125
126 void TCPPacketSendComplete( PVOID Context,
127 PNDIS_PACKET NdisPacket,
128 NDIS_STATUS NdisStatus ) {
129 TI_DbgPrint(MID_TRACE,("called %x\n", NdisPacket));
130 FreeNdisPacket(NdisPacket);
131 TI_DbgPrint(MID_TRACE,("done\n"));
132 }
133
134 #define STRINGIFY(x) #x
135
136 int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
137 NTSTATUS Status;
138 NDIS_STATUS NdisStatus;
139 ROUTE_CACHE_NODE *RCN;
140 IP_PACKET Packet = { 0 };
141 IP_ADDRESS RemoteAddress, LocalAddress;
142 PIPv4_HEADER Header;
143
144 TI_DbgPrint(MID_TRACE,("TCP OUTPUT (%x:%d):\n", data, len));
145 OskitDumpBuffer( data, len );
146
147 if( *data == 0x45 ) { /* IPv4 */
148 Header = (PIPv4_HEADER)data;
149 LocalAddress.Type = IP_ADDRESS_V4;
150 LocalAddress.Address.IPv4Address = Header->SrcAddr;
151 RemoteAddress.Type = IP_ADDRESS_V4;
152 RemoteAddress.Address.IPv4Address = Header->DstAddr;
153 } else {
154 DbgPrint("Don't currently handle IPv6\n");
155 KeBugCheck(4);
156 }
157
158 RemoteAddress.Type = LocalAddress.Type = IP_ADDRESS_V4;
159
160 DbgPrint("OSKIT SENDING PACKET *** %x -> %x\n",
161 LocalAddress.Address.IPv4Address,
162 RemoteAddress.Address.IPv4Address);
163
164 Status = RouteGetRouteToDestination( &RemoteAddress, NULL, &RCN );
165
166 if( !NT_SUCCESS(Status) || !RCN ) return OSK_EADDRNOTAVAIL;
167
168 NdisStatus = AllocatePacketWithBuffer( &Packet.NdisPacket, NULL,
169 MaxLLHeaderSize + len );
170
171 if (NdisStatus != NDIS_STATUS_SUCCESS) {
172 TI_DbgPrint(MAX_TRACE, ("Error from NDIS: %08x\n", NdisStatus));
173 return STATUS_NO_MEMORY;
174 }
175
176 GetDataPtr( Packet.NdisPacket, MaxLLHeaderSize,
177 (PCHAR *)&Packet.Header, &Packet.ContigSize );
178
179 RtlCopyMemory( Packet.Header, data, len );
180
181 Packet.HeaderSize = sizeof(IPv4_HEADER);
182 Packet.TotalSize = len;
183 Packet.SrcAddr = LocalAddress;
184 Packet.DstAddr = RemoteAddress;
185
186 IPSendDatagram( &Packet, RCN, TCPPacketSendComplete, NULL );
187
188 if( !NT_SUCCESS(NdisStatus) ) return OSK_EINVAL;
189 else return 0;
190 }
191
192 void *TCPMalloc( void *ClientData,
193 OSK_UINT Bytes, OSK_PCHAR File, OSK_UINT Line ) {
194 void *v = PoolAllocateBuffer( Bytes );
195 if( v ) TrackWithTag( FOURCC('f','b','s','d'), v, File, Line );
196 return v;
197 }
198
199 void TCPFree( void *ClientData,
200 void *data, OSK_PCHAR File, OSK_UINT Line ) {
201 UntrackFL( File, Line, data );
202 PoolFreeBuffer( data );
203 }
204
205 int TCPSleep( void *ClientData, void *token, int priority, char *msg,
206 int tmio ) {
207 PSLEEPING_THREAD SleepingThread;
208
209 TI_DbgPrint(MID_TRACE,
210 ("Called TSLEEP: tok = %x, pri = %d, wmesg = %s, tmio = %x\n",
211 token, priority, msg, tmio));
212
213 SleepingThread = PoolAllocateBuffer( sizeof( *SleepingThread ) );
214 if( SleepingThread ) {
215 KeInitializeEvent( &SleepingThread->Event, NotificationEvent, FALSE );
216 SleepingThread->SleepToken = token;
217
218 TcpipAcquireFastMutex( &SleepingThreadsLock );
219 InsertTailList( &SleepingThreadsList, &SleepingThread->Entry );
220 TcpipReleaseFastMutex( &SleepingThreadsLock );
221
222 TI_DbgPrint(MID_TRACE,("Waiting on %x\n", token));
223 KeWaitForSingleObject( &SleepingThread->Event,
224 WrSuspended,
225 KernelMode,
226 TRUE,
227 NULL );
228
229 TcpipAcquireFastMutex( &SleepingThreadsLock );
230 RemoveEntryList( &SleepingThread->Entry );
231 TcpipReleaseFastMutex( &SleepingThreadsLock );
232
233 PoolFreeBuffer( SleepingThread );
234 }
235 TI_DbgPrint(MID_TRACE,("Waiting finished: %x\n", token));
236 return 0;
237 }
238
239 void TCPWakeup( void *ClientData, void *token ) {
240 PLIST_ENTRY Entry;
241 PSLEEPING_THREAD SleepingThread;
242
243 TcpipAcquireFastMutex( &SleepingThreadsLock );
244 Entry = SleepingThreadsList.Flink;
245 while( Entry != &SleepingThreadsList ) {
246 SleepingThread = CONTAINING_RECORD(Entry, SLEEPING_THREAD, Entry);
247 TI_DbgPrint(MID_TRACE,("Sleeper @ %x\n", SleepingThread));
248 if( SleepingThread->SleepToken == token ) {
249 TI_DbgPrint(MID_TRACE,("Setting event to wake %x\n", token));
250 KeSetEvent( &SleepingThread->Event, IO_NETWORK_INCREMENT, FALSE );
251 }
252 Entry = Entry->Flink;
253 }
254 TcpipReleaseFastMutex( &SleepingThreadsLock );
255 }