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 extern ULONG TCP_IPIdentification
;
14 extern LIST_ENTRY SleepingThreadsList
;
15 extern FAST_MUTEX SleepingThreadsLock
;
16 extern RECURSIVE_MUTEX TCPLock
;
18 int TCPSocketState(void *ClientData
,
20 void *WhichConnection
,
22 NTSTATUS Status
= STATUS_SUCCESS
;
23 PCONNECTION_ENDPOINT Connection
= WhichConnection
;
24 PTCP_COMPLETION_ROUTINE Complete
;
28 TI_DbgPrint(MID_TRACE
,("Called: NewState %x (Conn %x) (Change %x)\n",
30 Connection
? Connection
->State
^ NewState
:
33 TcpipRecursiveMutexEnter( &TCPLock
, TRUE
);
36 TI_DbgPrint(MID_TRACE
,("Socket closing.\n"));
37 Connection
= FileFindConnectionByContext( WhichSocket
);
39 TcpipRecursiveMutexLeave( &TCPLock
);
42 TI_DbgPrint(MID_TRACE
,("Found socket %x\n", Connection
));
45 if( ((NewState
& SEL_CONNECT
) || (NewState
& SEL_FIN
)) &&
46 !(Connection
->State
& (SEL_CONNECT
| SEL_FIN
)) ) {
47 while( !IsListEmpty( &Connection
->ConnectRequest
) ) {
48 Connection
->State
|= NewState
& (SEL_CONNECT
| SEL_FIN
);
49 Entry
= RemoveHeadList( &Connection
->ConnectRequest
);
50 Bucket
= CONTAINING_RECORD( Entry
, TDI_BUCKET
, Entry
);
51 Complete
= Bucket
->Request
.RequestNotifyObject
;
52 TI_DbgPrint(MID_TRACE
,
53 ("Completing Connect Request %x\n", Bucket
->Request
));
54 if( NewState
& SEL_FIN
) Status
= STATUS_CONNECTION_REFUSED
;
55 TcpipRecursiveMutexLeave( &TCPLock
);
56 Complete( Bucket
->Request
.RequestContext
, Status
, 0 );
57 TcpipRecursiveMutexEnter( &TCPLock
, TRUE
);
58 /* Frees the bucket allocated in TCPConnect */
59 PoolFreeBuffer( Bucket
);
62 if( (NewState
& SEL_READ
) || (NewState
& SEL_FIN
) ) {
63 TI_DbgPrint(MID_TRACE
,("Readable (or closed): irp list %s\n",
64 IsListEmpty(&Connection
->ReceiveRequest
) ?
65 "empty" : "nonempty"));
67 while( !IsListEmpty( &Connection
->ReceiveRequest
) ) {
69 OSK_UINT RecvLen
= 0, Received
= 0;
70 OSK_PCHAR RecvBuffer
= 0;
74 Entry
= RemoveHeadList( &Connection
->ReceiveRequest
);
75 Bucket
= CONTAINING_RECORD( Entry
, TDI_BUCKET
, Entry
);
76 Complete
= Bucket
->Request
.RequestNotifyObject
;
78 TI_DbgPrint(MID_TRACE
,
79 ("Readable, Completing read request %x\n",
82 Irp
= Bucket
->Request
.RequestContext
;
83 Mdl
= Irp
->MdlAddress
;
85 TI_DbgPrint(MID_TRACE
,
86 ("Getting the user buffer from %x\n", Mdl
));
88 NdisQueryBuffer( Mdl
, &RecvBuffer
, &RecvLen
);
90 TI_DbgPrint(MID_TRACE
,
91 ("Reading %d bytes to %x\n", RecvLen
, RecvBuffer
));
93 if( (NewState
& SEL_FIN
) && !RecvLen
) {
94 TI_DbgPrint(MID_TRACE
, ("EOF From socket\n"));
95 Status
= STATUS_END_OF_FILE
;
98 TI_DbgPrint(MID_TRACE
, ("Connection: %x\n", Connection
));
101 ("Connection->SocketContext: %x\n",
102 Connection
->SocketContext
));
103 TI_DbgPrint(MID_TRACE
, ("RecvBuffer: %x\n", RecvBuffer
));
105 Status
= TCPTranslateError
106 ( OskitTCPRecv( Connection
->SocketContext
,
113 TI_DbgPrint(MID_TRACE
,("TCP Bytes: %d\n", Received
));
115 if( Status
== STATUS_SUCCESS
&& Received
!= 0 ) {
116 TI_DbgPrint(MID_TRACE
,("Received %d bytes with status %x\n",
119 TI_DbgPrint(MID_TRACE
,
120 ("Completing Receive Request: %x\n",
123 TcpipRecursiveMutexLeave( &TCPLock
);
124 Complete( Bucket
->Request
.RequestContext
,
125 STATUS_SUCCESS
, Received
);
126 TcpipRecursiveMutexEnter( &TCPLock
, TRUE
);
127 } else if( Status
== STATUS_PENDING
||
128 (Status
== STATUS_SUCCESS
&& Received
== 0) ) {
129 InsertHeadList( &Connection
->ReceiveRequest
,
133 TI_DbgPrint(MID_TRACE
,
134 ("Completing Receive request: %x %x\n",
135 Bucket
->Request
, Status
));
136 TcpipRecursiveMutexLeave( &TCPLock
);
137 Complete( Bucket
->Request
.RequestContext
, Status
, 0 );
138 TcpipRecursiveMutexEnter( &TCPLock
, TRUE
);
143 TcpipRecursiveMutexLeave( &TCPLock
);
148 void TCPPacketSendComplete( PVOID Context
,
149 PNDIS_PACKET NdisPacket
,
150 NDIS_STATUS NdisStatus
) {
151 TI_DbgPrint(MID_TRACE
,("called %x\n", NdisPacket
));
152 FreeNdisPacket(NdisPacket
);
153 TI_DbgPrint(MID_TRACE
,("done\n"));
156 #define STRINGIFY(x) #x
158 int TCPPacketSend(void *ClientData
, OSK_PCHAR data
, OSK_UINT len
) {
159 NDIS_STATUS NdisStatus
;
160 PNEIGHBOR_CACHE_ENTRY NCE
;
161 IP_PACKET Packet
= { 0 };
162 IP_ADDRESS RemoteAddress
, LocalAddress
;
165 if( *data
== 0x45 ) { /* IPv4 */
166 Header
= (PIPv4_HEADER
)data
;
167 LocalAddress
.Type
= IP_ADDRESS_V4
;
168 LocalAddress
.Address
.IPv4Address
= Header
->SrcAddr
;
169 RemoteAddress
.Type
= IP_ADDRESS_V4
;
170 RemoteAddress
.Address
.IPv4Address
= Header
->DstAddr
;
172 DbgPrint("Don't currently handle IPv6\n");
176 RemoteAddress
.Type
= LocalAddress
.Type
= IP_ADDRESS_V4
;
178 DbgPrint("OSKIT SENDING PACKET *** %x -> %x\n",
179 LocalAddress
.Address
.IPv4Address
,
180 RemoteAddress
.Address
.IPv4Address
);
182 if(!(NCE
= RouteGetRouteToDestination( &RemoteAddress
)))
183 return OSK_EADDRNOTAVAIL
;
185 NdisStatus
= AllocatePacketWithBuffer( &Packet
.NdisPacket
, NULL
,
186 MaxLLHeaderSize
+ len
);
188 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
189 TI_DbgPrint(MAX_TRACE
, ("Error from NDIS: %08x\n", NdisStatus
));
190 return STATUS_NO_MEMORY
;
193 GetDataPtr( Packet
.NdisPacket
, MaxLLHeaderSize
,
194 (PCHAR
*)&Packet
.Header
, &Packet
.ContigSize
);
196 RtlCopyMemory( Packet
.Header
, data
, len
);
198 Packet
.HeaderSize
= sizeof(IPv4_HEADER
);
199 Packet
.TotalSize
= len
;
200 Packet
.SrcAddr
= LocalAddress
;
201 Packet
.DstAddr
= RemoteAddress
;
203 IPSendDatagram( &Packet
, NCE
, TCPPacketSendComplete
, NULL
);
205 if( !NT_SUCCESS(NdisStatus
) ) return OSK_EINVAL
;
209 void *TCPMalloc( void *ClientData
,
210 OSK_UINT Bytes
, OSK_PCHAR File
, OSK_UINT Line
) {
211 void *v
= PoolAllocateBuffer( Bytes
);
212 if( v
) TrackWithTag( FOURCC('f','b','s','d'), v
, File
, Line
);
216 void TCPFree( void *ClientData
,
217 void *data
, OSK_PCHAR File
, OSK_UINT Line
) {
218 UntrackFL( File
, Line
, data
);
219 PoolFreeBuffer( data
);
222 int TCPSleep( void *ClientData
, void *token
, int priority
, char *msg
,
224 PSLEEPING_THREAD SleepingThread
;
226 TI_DbgPrint(MID_TRACE
,
227 ("Called TSLEEP: tok = %x, pri = %d, wmesg = %s, tmio = %x\n",
228 token
, priority
, msg
, tmio
));
230 SleepingThread
= PoolAllocateBuffer( sizeof( *SleepingThread
) );
231 if( SleepingThread
) {
232 KeInitializeEvent( &SleepingThread
->Event
, NotificationEvent
, FALSE
);
233 SleepingThread
->SleepToken
= token
;
235 TcpipAcquireFastMutex( &SleepingThreadsLock
);
236 InsertTailList( &SleepingThreadsList
, &SleepingThread
->Entry
);
237 TcpipReleaseFastMutex( &SleepingThreadsLock
);
239 TI_DbgPrint(MID_TRACE
,("Waiting on %x\n", token
));
240 KeWaitForSingleObject( &SleepingThread
->Event
,
246 TcpipAcquireFastMutex( &SleepingThreadsLock
);
247 RemoveEntryList( &SleepingThread
->Entry
);
248 TcpipReleaseFastMutex( &SleepingThreadsLock
);
250 PoolFreeBuffer( SleepingThread
);
252 TI_DbgPrint(MID_TRACE
,("Waiting finished: %x\n", token
));
256 void TCPWakeup( void *ClientData
, void *token
) {
258 PSLEEPING_THREAD SleepingThread
;
260 TcpipAcquireFastMutex( &SleepingThreadsLock
);
261 Entry
= SleepingThreadsList
.Flink
;
262 while( Entry
!= &SleepingThreadsList
) {
263 SleepingThread
= CONTAINING_RECORD(Entry
, SLEEPING_THREAD
, Entry
);
264 TI_DbgPrint(MID_TRACE
,("Sleeper @ %x\n", SleepingThread
));
265 if( SleepingThread
->SleepToken
== token
) {
266 TI_DbgPrint(MID_TRACE
,("Setting event to wake %x\n", token
));
267 KeSetEvent( &SleepingThread
->Event
, IO_NETWORK_INCREMENT
, FALSE
);
269 Entry
= Entry
->Flink
;
271 TcpipReleaseFastMutex( &SleepingThreadsLock
);