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 VOID STDCALL
KeRaiseIrql(KIRQL NewIrql
, PKIRQL OldIrql
);
14 VOID STDCALL
KeLowerIrql(KIRQL NewIrql
);
16 extern ULONG TCP_IPIdentification
;
17 extern LIST_ENTRY SleepingThreadsList
;
18 extern FAST_MUTEX SleepingThreadsLock
;
20 int TCPSocketState(void *ClientData
,
22 void *WhichConnection
,
24 PCONNECTION_ENDPOINT Connection
= WhichConnection
;
25 PTCP_COMPLETION_ROUTINE Complete
;
29 TI_DbgPrint(MID_TRACE
,("Called: NewState %x (Conn %x)\n",
30 NewState
, Connection
));
33 TI_DbgPrint(MID_TRACE
,("Socket closing.\n"));
37 if( (NewState
& SEL_CONNECT
) &&
38 !(Connection
->State
& SEL_CONNECT
) ) {
39 while( !IsListEmpty( &Connection
->ConnectRequest
) ) {
40 Connection
->State
|= SEL_CONNECT
;
41 Entry
= RemoveHeadList( &Connection
->ConnectRequest
);
42 Bucket
= CONTAINING_RECORD( Entry
, TDI_BUCKET
, Entry
);
43 Complete
= Bucket
->Request
.RequestNotifyObject
;
44 TI_DbgPrint(MID_TRACE
,
45 ("Completing Connect Request %x\n", Bucket
->Request
));
46 Complete( Bucket
->Request
.RequestContext
, STATUS_SUCCESS
, 0 );
47 /* Frees the bucket allocated in TCPConnect */
50 } else if( (NewState
& SEL_READ
) || (NewState
& SEL_FIN
) ) {
51 TI_DbgPrint(MID_TRACE
,("Readable (or closed): irp list %s\n",
52 IsListEmpty(&Connection
->ReceiveRequest
) ?
53 "empty" : "nonempty"));
55 while( !IsListEmpty( &Connection
->ReceiveRequest
) ) {
57 OSK_UINT RecvLen
= 0, Received
= 0;
58 OSK_PCHAR RecvBuffer
= 0;
62 Entry
= RemoveHeadList( &Connection
->ReceiveRequest
);
63 Bucket
= CONTAINING_RECORD( Entry
, TDI_BUCKET
, Entry
);
64 Complete
= Bucket
->Request
.RequestNotifyObject
;
66 TI_DbgPrint(MID_TRACE
,
67 ("Readable, Completing read request %x\n",
70 Irp
= Bucket
->Request
.RequestContext
;
71 Mdl
= Irp
->MdlAddress
;
73 TI_DbgPrint(MID_TRACE
,
74 ("Getting the user buffer from %x\n", Mdl
));
76 NdisQueryBuffer( Mdl
, &RecvBuffer
, &RecvLen
);
78 TI_DbgPrint(MID_TRACE
,
79 ("Reading %d bytes to %x\n", RecvLen
, RecvBuffer
));
81 if( NewState
& SEL_FIN
&& !RecvLen
) {
82 Status
= STATUS_END_OF_FILE
;
85 Status
= TCPTranslateError
86 ( OskitTCPRecv( Connection
->SocketContext
,
92 TI_DbgPrint(MID_TRACE
,("TCP Bytes: %d\n", Received
));
94 if( Status
== STATUS_SUCCESS
&& Received
!= 0 ) {
95 TI_DbgPrint(MID_TRACE
,("Received %d bytes with status %x\n",
98 TI_DbgPrint(MID_TRACE
,
99 ("Completing Receive Request: %x\n",
102 Complete( Bucket
->Request
.RequestContext
,
103 STATUS_SUCCESS
, Received
);
104 } else if( Status
== STATUS_PENDING
||
105 (Status
== STATUS_SUCCESS
&& Received
== 0) ) {
106 InsertHeadList( &Connection
->ReceiveRequest
,
110 TI_DbgPrint(MID_TRACE
,
111 ("Completing Receive request: %x %x\n",
112 Bucket
->Request
, Status
));
113 Complete( Bucket
->Request
.RequestContext
, Status
, 0 );
121 void TCPPacketSendComplete( PVOID Context
,
122 PNDIS_PACKET NdisPacket
,
123 NDIS_STATUS NdisStatus
) {
124 TI_DbgPrint(MID_TRACE
,("called\n"));
127 #define STRINGIFY(x) #x
129 int TCPPacketSend(void *ClientData
, OSK_PCHAR data
, OSK_UINT len
) {
132 NDIS_STATUS NdisStatus
;
133 ROUTE_CACHE_NODE
*RCN
;
134 IP_PACKET Packet
= { 0 };
135 IP_ADDRESS RemoteAddress
, LocalAddress
;
138 TI_DbgPrint(MID_TRACE
,("TCP OUTPUT (%x:%d):\n", data
, len
));
139 OskitDumpBuffer( data
, len
);
141 if( *data
== 0x45 ) { /* IPv4 */
142 Header
= (PIPv4_HEADER
)data
;
143 LocalAddress
.Type
= IP_ADDRESS_V4
;
144 LocalAddress
.Address
.IPv4Address
= Header
->SrcAddr
;
145 RemoteAddress
.Type
= IP_ADDRESS_V4
;
146 RemoteAddress
.Address
.IPv4Address
= Header
->DstAddr
;
148 DbgPrint("Don't currently handle IPv6\n");
152 RemoteAddress
.Type
= LocalAddress
.Type
= IP_ADDRESS_V4
;
154 DbgPrint("OSKIT SENDING PACKET *** %x -> %x\n",
155 LocalAddress
.Address
.IPv4Address
,
156 RemoteAddress
.Address
.IPv4Address
);
158 ASSERT( (LocalAddress
.Address
.IPv4Address
& 0xc0000000) != 0xc0000000 );
161 Status
= RouteGetRouteToDestination( &RemoteAddress
,
165 if( !NT_SUCCESS(Status
) || !RCN
) return OSK_EADDRNOTAVAIL
;
167 KeRaiseIrql( DISPATCH_LEVEL
, &OldIrql
);
170 AllocatePacketWithBuffer( &Packet
.NdisPacket
, data
, len
);
172 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
173 TI_DbgPrint(MAX_TRACE
, ("Error from NDIS: %08x\n", NdisStatus
));
177 AdjustPacket( Packet
.NdisPacket
, 0, MaxLLHeaderSize
);
178 GetDataPtr( Packet
.NdisPacket
, 0, (PCHAR
*)&Packet
.Header
, &Packet
.ContigSize
);
179 TI_DbgPrint(MAX_TRACE
,("PC(Packet.NdisPacket) is %s (%x)\n", STRINGIFY(PC(Packet
.NdisPacket
)), PC(Packet
.NdisPacket
)));
180 PC(Packet
.NdisPacket
)->Complete
= TCPPacketSendComplete
;
181 OskitDumpBuffer((PCHAR
)(PC(Packet
.NdisPacket
)),sizeof(*(PC(Packet
.NdisPacket
))));
183 Packet
.HeaderSize
= sizeof(IPv4_HEADER
);
184 Packet
.TotalSize
= len
;
185 Packet
.SrcAddr
= LocalAddress
;
186 Packet
.DstAddr
= RemoteAddress
;
188 IPSendFragment( Packet
.NdisPacket
, RCN
->NCE
);
191 KeLowerIrql( OldIrql
);
193 if( !NT_SUCCESS(NdisStatus
) ) return OSK_EINVAL
;
197 void *TCPMalloc( void *ClientData
,
198 OSK_UINT Bytes
, OSK_PCHAR File
, OSK_UINT Line
) {
199 void *v
= ExAllocatePool( NonPagedPool
, Bytes
);
200 if( v
) TrackWithTag( FOURCC('f','b','s','d'), v
, File
, Line
);
204 void TCPFree( void *ClientData
,
205 void *data
, OSK_PCHAR File
, OSK_UINT Line
) {
206 UntrackFL( File
, Line
, data
);
210 int TCPSleep( void *ClientData
, void *token
, int priority
, char *msg
,
212 PSLEEPING_THREAD SleepingThread
;
214 TI_DbgPrint(MID_TRACE
,
215 ("Called TSLEEP: tok = %x, pri = %d, wmesg = %s, tmio = %x\n",
216 token
, priority
, msg
, tmio
));
218 SleepingThread
= ExAllocatePool( NonPagedPool
, sizeof( *SleepingThread
) );
219 if( SleepingThread
) {
220 KeInitializeEvent( &SleepingThread
->Event
, NotificationEvent
, FALSE
);
221 SleepingThread
->SleepToken
= token
;
223 ExAcquireFastMutex( &SleepingThreadsLock
);
224 InsertTailList( &SleepingThreadsList
, &SleepingThread
->Entry
);
225 ExReleaseFastMutex( &SleepingThreadsLock
);
227 TI_DbgPrint(MID_TRACE
,("Waiting on %x\n", token
));
228 KeWaitForSingleObject( &SleepingThread
->Event
,
234 ExAcquireFastMutex( &SleepingThreadsLock
);
235 RemoveEntryList( &SleepingThread
->Entry
);
236 ExReleaseFastMutex( &SleepingThreadsLock
);
238 ExFreePool( SleepingThread
);
240 TI_DbgPrint(MID_TRACE
,("Waiting finished: %x\n", token
));
244 void TCPWakeup( void *ClientData
, void *token
) {
246 PSLEEPING_THREAD SleepingThread
;
248 ExAcquireFastMutex( &SleepingThreadsLock
);
249 Entry
= SleepingThreadsList
.Flink
;
250 while( Entry
!= &SleepingThreadsList
) {
251 SleepingThread
= CONTAINING_RECORD(Entry
, SLEEPING_THREAD
, Entry
);
252 TI_DbgPrint(MID_TRACE
,("Sleeper @ %x\n", SleepingThread
));
253 if( SleepingThread
->SleepToken
== token
) {
254 TI_DbgPrint(MID_TRACE
,("Setting event to wake %x\n", token
));
255 KeSetEvent( &SleepingThread
->Event
, IO_NETWORK_INCREMENT
, FALSE
);
257 Entry
= Entry
->Flink
;
259 ExReleaseFastMutex( &SleepingThreadsLock
);