f3d5a145597de2061f14a6dd63a5e0f279630784
[reactos.git] / lib / drivers / 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 int TCPSocketState(void *ClientData,
14 void *WhichSocket,
15 void *WhichConnection,
16 OSK_UINT NewState ) {
17 PCONNECTION_ENDPOINT Connection = WhichConnection;
18
19 TI_DbgPrint(DEBUG_TCP,("Connection: %x Flags: %c%c%c%c%c\n",
20 Connection,
21 NewState & SEL_CONNECT ? 'C' : 'c',
22 NewState & SEL_READ ? 'R' : 'r',
23 NewState & SEL_FIN ? 'F' : 'f',
24 NewState & SEL_ACCEPT ? 'A' : 'a',
25 NewState & SEL_WRITE ? 'W' : 'w'));
26
27 if (!Connection)
28 {
29 return 0;
30 }
31
32 if (ClientInfo.Unlocked)
33 KeAcquireSpinLockAtDpcLevel(&Connection->Lock);
34
35 TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
36 NewState, Connection,
37 Connection->SignalState ^ NewState,
38 NewState));
39
40 Connection->SignalState |= NewState;
41
42 HandleSignalledConnection(Connection);
43
44 if (ClientInfo.Unlocked)
45 KeReleaseSpinLockFromDpcLevel(&Connection->Lock);
46
47 return 0;
48 }
49
50 void TCPPacketSendComplete( PVOID Context,
51 PNDIS_PACKET NdisPacket,
52 NDIS_STATUS NdisStatus ) {
53 TI_DbgPrint(DEBUG_TCP,("called %x\n", NdisPacket));
54 FreeNdisPacket(NdisPacket);
55 TI_DbgPrint(DEBUG_TCP,("done\n"));
56 }
57
58 #define STRINGIFY(x) #x
59
60 int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
61 NDIS_STATUS NdisStatus;
62 PNEIGHBOR_CACHE_ENTRY NCE;
63 IP_PACKET Packet = { 0 };
64 IP_ADDRESS RemoteAddress, LocalAddress;
65 PIPv4_HEADER Header;
66
67 if( *data == 0x45 ) { /* IPv4 */
68 Header = (PIPv4_HEADER)data;
69 LocalAddress.Type = IP_ADDRESS_V4;
70 LocalAddress.Address.IPv4Address = Header->SrcAddr;
71 RemoteAddress.Type = IP_ADDRESS_V4;
72 RemoteAddress.Address.IPv4Address = Header->DstAddr;
73 } else {
74 TI_DbgPrint(MIN_TRACE,("Outgoing packet is not IPv4\n"));
75 OskitDumpBuffer( data, len );
76 return OSK_EINVAL;
77 }
78
79 if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
80 TI_DbgPrint(MIN_TRACE,("No route to %s\n", A2S(&RemoteAddress)));
81 return OSK_EADDRNOTAVAIL;
82 }
83
84 NdisStatus = AllocatePacketWithBuffer( &Packet.NdisPacket, NULL, len );
85
86 if (NdisStatus != NDIS_STATUS_SUCCESS) {
87 TI_DbgPrint(DEBUG_TCP, ("Error from NDIS: %08x\n", NdisStatus));
88 return OSK_ENOBUFS;
89 }
90
91 GetDataPtr( Packet.NdisPacket, 0,
92 (PCHAR *)&Packet.Header, &Packet.ContigSize );
93
94 RtlCopyMemory( Packet.Header, data, len );
95
96 Packet.HeaderSize = sizeof(IPv4_HEADER);
97 Packet.TotalSize = len;
98 Packet.SrcAddr = LocalAddress;
99 Packet.DstAddr = RemoteAddress;
100
101 if (!NT_SUCCESS(IPSendDatagram( &Packet, NCE, TCPPacketSendComplete, NULL )))
102 {
103 FreeNdisPacket(Packet.NdisPacket);
104 return OSK_EINVAL;
105 }
106
107 return 0;
108 }
109
110 /* Memory management routines
111 *
112 * By far the most requests for memory are either for 128 or 2048 byte blocks,
113 * so we want to satisfy those from lookaside lists. Unfortunately, the
114 * TCPFree() function doesn't pass the size of the block to be freed, so we
115 * need to keep track of it ourselves. We do it by prepending each block with
116 * 4 bytes, indicating if this is a 'L'arge (2048), 'S'mall (128) or 'O'ther
117 * block.
118 */
119
120 /* Set to some non-zero value to get a profile of memory allocation sizes */
121 #define MEM_PROFILE 0
122
123 #define SMALL_SIZE 128
124 #define LARGE_SIZE 2048
125
126 #define SIGNATURE_LARGE 'LLLL'
127 #define SIGNATURE_SMALL 'SSSS'
128 #define SIGNATURE_OTHER 'OOOO'
129 static NPAGED_LOOKASIDE_LIST LargeLookasideList;
130 static NPAGED_LOOKASIDE_LIST SmallLookasideList;
131
132 NTSTATUS
133 TCPMemStartup( void )
134 {
135 ExInitializeNPagedLookasideList( &LargeLookasideList,
136 NULL,
137 NULL,
138 0,
139 LARGE_SIZE + sizeof( ULONG ),
140 OSK_LARGE_TAG,
141 0 );
142 ExInitializeNPagedLookasideList( &SmallLookasideList,
143 NULL,
144 NULL,
145 0,
146 SMALL_SIZE + sizeof( ULONG ),
147 OSK_SMALL_TAG,
148 0 );
149
150 return STATUS_SUCCESS;
151 }
152
153 void *TCPMalloc( void *ClientData,
154 OSK_UINT Bytes, OSK_PCHAR File, OSK_UINT Line ) {
155 void *v;
156 ULONG Signature;
157
158 #if 0 != MEM_PROFILE
159 static OSK_UINT *Sizes = NULL, *Counts = NULL, ArrayAllocated = 0;
160 static OSK_UINT ArrayUsed = 0, AllocationCount = 0;
161 OSK_UINT i, NewSize, *NewArray;
162 int Found;
163
164 Found = 0;
165 for ( i = 0; i < ArrayUsed && ! Found; i++ ) {
166 Found = ( Sizes[i] == Bytes );
167 if ( Found ) {
168 Counts[i]++;
169 }
170 }
171 if ( ! Found ) {
172 if ( ArrayAllocated <= ArrayUsed ) {
173 NewSize = ( 0 == ArrayAllocated ? 16 : 2 * ArrayAllocated );
174 NewArray = exAllocatePool( NonPagedPool, 2 * NewSize * sizeof( OSK_UINT ) );
175 if ( NULL != NewArray ) {
176 if ( 0 != ArrayAllocated ) {
177 memcpy( NewArray, Sizes,
178 ArrayAllocated * sizeof( OSK_UINT ) );
179 exFreePool( Sizes );
180 memcpy( NewArray + NewSize, Counts,
181 ArrayAllocated * sizeof( OSK_UINT ) );
182 exFreePool( Counts );
183 }
184 Sizes = NewArray;
185 Counts = NewArray + NewSize;
186 ArrayAllocated = NewSize;
187 } else if ( 0 != ArrayAllocated ) {
188 exFreePool( Sizes );
189 exFreePool( Counts );
190 ArrayAllocated = 0;
191 }
192 }
193 if ( ArrayUsed < ArrayAllocated ) {
194 Sizes[ArrayUsed] = Bytes;
195 Counts[ArrayUsed] = 1;
196 ArrayUsed++;
197 }
198 }
199
200 if ( 0 == (++AllocationCount % MEM_PROFILE) ) {
201 TI_DbgPrint(DEBUG_TCP, ("Memory allocation size profile:\n"));
202 for ( i = 0; i < ArrayUsed; i++ ) {
203 TI_DbgPrint(DEBUG_TCP,
204 ("Size %4u Count %5u\n", Sizes[i], Counts[i]));
205 }
206 TI_DbgPrint(DEBUG_TCP, ("End of memory allocation size profile\n"));
207 }
208 #endif /* MEM_PROFILE */
209
210 if ( SMALL_SIZE == Bytes ) {
211 v = ExAllocateFromNPagedLookasideList( &SmallLookasideList );
212 Signature = SIGNATURE_SMALL;
213 } else if ( LARGE_SIZE == Bytes ) {
214 v = ExAllocateFromNPagedLookasideList( &LargeLookasideList );
215 Signature = SIGNATURE_LARGE;
216 } else {
217 v = ExAllocatePoolWithTag( NonPagedPool, Bytes + sizeof(ULONG),
218 OSK_OTHER_TAG );
219 Signature = SIGNATURE_OTHER;
220 }
221 if( v ) {
222 *((ULONG *) v) = Signature;
223 v = (void *)((char *) v + sizeof(ULONG));
224 }
225
226 return v;
227 }
228
229 void TCPFree( void *ClientData,
230 void *data, OSK_PCHAR File, OSK_UINT Line ) {
231 ULONG Signature;
232
233 data = (void *)((char *) data - sizeof(ULONG));
234 Signature = *((ULONG *) data);
235 if ( SIGNATURE_SMALL == Signature ) {
236 ExFreeToNPagedLookasideList( &SmallLookasideList, data );
237 } else if ( SIGNATURE_LARGE == Signature ) {
238 ExFreeToNPagedLookasideList( &LargeLookasideList, data );
239 } else if ( SIGNATURE_OTHER == Signature ) {
240 ExFreePoolWithTag( data, OSK_OTHER_TAG );
241 } else {
242 ASSERT( FALSE );
243 }
244 }
245
246 void
247 TCPMemShutdown( void )
248 {
249 ExDeleteNPagedLookasideList( &SmallLookasideList );
250 ExDeleteNPagedLookasideList( &LargeLookasideList );
251 }