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