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
8 * CSH 01/08-2000 Created
13 int TCPSocketState(void *ClientData
,
15 void *WhichConnection
,
17 PCONNECTION_ENDPOINT Connection
= WhichConnection
;
21 ASSERT_LOCKED(&TCPLock
);
23 TI_DbgPrint(MID_TRACE
,("Flags: %c%c%c%c\n",
24 NewState
& SEL_CONNECT
? 'C' : 'c',
25 NewState
& SEL_READ
? 'R' : 'r',
26 NewState
& SEL_FIN
? 'F' : 'f',
27 NewState
& SEL_ACCEPT
? 'A' : 'a'));
29 TI_DbgPrint(DEBUG_TCP
,("Called: NewState %x (Conn %x) (Change %x)\n",
31 Connection
? Connection
->SignalState
^ NewState
:
35 TI_DbgPrint(DEBUG_TCP
,("Socket closing.\n"));
36 Connection
= FileFindConnectionByContext( WhichSocket
);
40 TI_DbgPrint(DEBUG_TCP
,("Found socket %x\n", Connection
));
43 OldState
= Connection
->SignalState
;
45 Connection
->SignalState
|= NewState
;
47 TcpipRecursiveMutexLeave(&TCPLock
);
49 /* We must not be locked when handling signalled connections
50 * because a completion could trigger another IOCTL which
51 * would cause a deadlock
53 NewState
= HandleSignalledConnection(Connection
);
55 TcpipRecursiveMutexEnter(&TCPLock
);
57 KeAcquireSpinLock(&SignalledConnectionsLock
, &OldIrql
);
58 if ((NewState
== 0 || NewState
== SEL_FIN
) &&
59 (OldState
!= 0 && OldState
!= SEL_FIN
))
61 RemoveEntryList(&Connection
->SignalList
);
63 else if (NewState
!= 0 && NewState
!= SEL_FIN
)
65 InsertTailList(&SignalledConnectionsList
, &Connection
->SignalList
);
67 KeReleaseSpinLock(&SignalledConnectionsLock
, OldIrql
);
72 void TCPPacketSendComplete( PVOID Context
,
73 PNDIS_PACKET NdisPacket
,
74 NDIS_STATUS NdisStatus
) {
75 TI_DbgPrint(DEBUG_TCP
,("called %x\n", NdisPacket
));
76 FreeNdisPacket(NdisPacket
);
77 TI_DbgPrint(DEBUG_TCP
,("done\n"));
80 #define STRINGIFY(x) #x
82 int TCPPacketSend(void *ClientData
, OSK_PCHAR data
, OSK_UINT len
) {
83 NDIS_STATUS NdisStatus
;
84 PNEIGHBOR_CACHE_ENTRY NCE
;
85 IP_PACKET Packet
= { 0 };
86 IP_ADDRESS RemoteAddress
, LocalAddress
;
89 ASSERT_LOCKED(&TCPLock
);
91 if( *data
== 0x45 ) { /* IPv4 */
92 Header
= (PIPv4_HEADER
)data
;
93 LocalAddress
.Type
= IP_ADDRESS_V4
;
94 LocalAddress
.Address
.IPv4Address
= Header
->SrcAddr
;
95 RemoteAddress
.Type
= IP_ADDRESS_V4
;
96 RemoteAddress
.Address
.IPv4Address
= Header
->DstAddr
;
98 TI_DbgPrint(MIN_TRACE
,("Outgoing packet is not IPv4\n"));
99 OskitDumpBuffer( data
, len
);
103 if(!(NCE
= RouteGetRouteToDestination( &RemoteAddress
))) {
104 TI_DbgPrint(MIN_TRACE
,("No route to %s\n", A2S(&RemoteAddress
)));
105 return OSK_EADDRNOTAVAIL
;
108 NdisStatus
= AllocatePacketWithBuffer( &Packet
.NdisPacket
, NULL
, len
);
110 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
111 TI_DbgPrint(DEBUG_TCP
, ("Error from NDIS: %08x\n", NdisStatus
));
115 GetDataPtr( Packet
.NdisPacket
, 0,
116 (PCHAR
*)&Packet
.Header
, &Packet
.ContigSize
);
118 RtlCopyMemory( Packet
.Header
, data
, len
);
120 Packet
.HeaderSize
= sizeof(IPv4_HEADER
);
121 Packet
.TotalSize
= len
;
122 Packet
.SrcAddr
= LocalAddress
;
123 Packet
.DstAddr
= RemoteAddress
;
125 if (!NT_SUCCESS(IPSendDatagram( &Packet
, NCE
, TCPPacketSendComplete
, NULL
)))
127 FreeNdisPacket(Packet
.NdisPacket
);
134 /* Memory management routines
136 * By far the most requests for memory are either for 128 or 2048 byte blocks,
137 * so we want to satisfy those from lookaside lists. Unfortunately, the
138 * TCPFree() function doesn't pass the size of the block to be freed, so we
139 * need to keep track of it ourselves. We do it by prepending each block with
140 * 4 bytes, indicating if this is a 'L'arge (2048), 'S'mall (128) or 'O'ther
144 /* Set to some non-zero value to get a profile of memory allocation sizes */
145 #define MEM_PROFILE 0
147 #define SMALL_SIZE 128
148 #define LARGE_SIZE 2048
150 #define SIGNATURE_LARGE 'LLLL'
151 #define SIGNATURE_SMALL 'SSSS'
152 #define SIGNATURE_OTHER 'OOOO'
153 #define TCP_TAG ' PCT'
155 static NPAGED_LOOKASIDE_LIST LargeLookasideList
;
156 static NPAGED_LOOKASIDE_LIST SmallLookasideList
;
159 TCPMemStartup( void )
161 ExInitializeNPagedLookasideList( &LargeLookasideList
,
165 LARGE_SIZE
+ sizeof( ULONG
),
168 ExInitializeNPagedLookasideList( &SmallLookasideList
,
172 SMALL_SIZE
+ sizeof( ULONG
),
176 return STATUS_SUCCESS
;
179 void *TCPMalloc( void *ClientData
,
180 OSK_UINT Bytes
, OSK_PCHAR File
, OSK_UINT Line
) {
184 ASSERT_LOCKED(&TCPLock
);
187 static OSK_UINT
*Sizes
= NULL
, *Counts
= NULL
, ArrayAllocated
= 0;
188 static OSK_UINT ArrayUsed
= 0, AllocationCount
= 0;
189 OSK_UINT i
, NewSize
, *NewArray
;
193 for ( i
= 0; i
< ArrayUsed
&& ! Found
; i
++ ) {
194 Found
= ( Sizes
[i
] == Bytes
);
200 if ( ArrayAllocated
<= ArrayUsed
) {
201 NewSize
= ( 0 == ArrayAllocated
? 16 : 2 * ArrayAllocated
);
202 NewArray
= exAllocatePool( NonPagedPool
, 2 * NewSize
* sizeof( OSK_UINT
) );
203 if ( NULL
!= NewArray
) {
204 if ( 0 != ArrayAllocated
) {
205 memcpy( NewArray
, Sizes
,
206 ArrayAllocated
* sizeof( OSK_UINT
) );
208 memcpy( NewArray
+ NewSize
, Counts
,
209 ArrayAllocated
* sizeof( OSK_UINT
) );
210 exFreePool( Counts
);
213 Counts
= NewArray
+ NewSize
;
214 ArrayAllocated
= NewSize
;
215 } else if ( 0 != ArrayAllocated
) {
217 exFreePool( Counts
);
221 if ( ArrayUsed
< ArrayAllocated
) {
222 Sizes
[ArrayUsed
] = Bytes
;
223 Counts
[ArrayUsed
] = 1;
228 if ( 0 == (++AllocationCount
% MEM_PROFILE
) ) {
229 TI_DbgPrint(DEBUG_TCP
, ("Memory allocation size profile:\n"));
230 for ( i
= 0; i
< ArrayUsed
; i
++ ) {
231 TI_DbgPrint(DEBUG_TCP
,
232 ("Size %4u Count %5u\n", Sizes
[i
], Counts
[i
]));
234 TI_DbgPrint(DEBUG_TCP
, ("End of memory allocation size profile\n"));
236 #endif /* MEM_PROFILE */
238 if ( SMALL_SIZE
== Bytes
) {
239 v
= ExAllocateFromNPagedLookasideList( &SmallLookasideList
);
240 Signature
= SIGNATURE_SMALL
;
241 } else if ( LARGE_SIZE
== Bytes
) {
242 v
= ExAllocateFromNPagedLookasideList( &LargeLookasideList
);
243 Signature
= SIGNATURE_LARGE
;
245 v
= ExAllocatePool( NonPagedPool
, Bytes
+ sizeof(ULONG
) );
246 Signature
= SIGNATURE_OTHER
;
249 *((ULONG
*) v
) = Signature
;
250 v
= (void *)((char *) v
+ sizeof(ULONG
));
251 TrackWithTag( FOURCC('f','b','s','d'), v
, (PCHAR
)File
, Line
);
257 void TCPFree( void *ClientData
,
258 void *data
, OSK_PCHAR File
, OSK_UINT Line
) {
261 ASSERT_LOCKED(&TCPLock
);
263 UntrackFL( (PCHAR
)File
, Line
, data
, FOURCC('f','b','s','d') );
264 data
= (void *)((char *) data
- sizeof(ULONG
));
265 Signature
= *((ULONG
*) data
);
266 if ( SIGNATURE_SMALL
== Signature
) {
267 ExFreeToNPagedLookasideList( &SmallLookasideList
, data
);
268 } else if ( SIGNATURE_LARGE
== Signature
) {
269 ExFreeToNPagedLookasideList( &LargeLookasideList
, data
);
270 } else if ( SIGNATURE_OTHER
== Signature
) {
278 TCPMemShutdown( void )
280 ExDeleteNPagedLookasideList( &SmallLookasideList
);
281 ExDeleteNPagedLookasideList( &LargeLookasideList
);