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
;
17 int TCPSocketState(void *ClientData
,
19 void *WhichConnection
,
21 PCONNECTION_ENDPOINT Connection
= WhichConnection
;
22 PTCP_COMPLETION_ROUTINE Complete
;
26 TI_DbgPrint(MID_TRACE
,("Called: NewState %x (Conn %x)\n",
27 NewState
, Connection
));
30 TI_DbgPrint(MID_TRACE
,("Socket closing.\n"));
34 if( (NewState
& SEL_CONNECT
) &&
35 !(Connection
->State
& SEL_CONNECT
) ) {
36 while( !IsListEmpty( &Connection
->ConnectRequest
) ) {
37 Connection
->State
|= SEL_CONNECT
;
38 Entry
= RemoveHeadList( &Connection
->ConnectRequest
);
39 Bucket
= CONTAINING_RECORD( Entry
, TDI_BUCKET
, Entry
);
40 Complete
= Bucket
->Request
.RequestNotifyObject
;
41 TI_DbgPrint(MID_TRACE
,
42 ("Completing Connect Request %x\n", Bucket
->Request
));
43 Complete( Bucket
->Request
.RequestContext
, STATUS_SUCCESS
, 0 );
44 /* Frees the bucket allocated in TCPConnect */
45 PoolFreeBuffer( Bucket
);
47 } else if( (NewState
& SEL_READ
) || (NewState
& SEL_FIN
) ) {
48 TI_DbgPrint(MID_TRACE
,("Readable (or closed): irp list %s\n",
49 IsListEmpty(&Connection
->ReceiveRequest
) ?
50 "empty" : "nonempty"));
52 while( !IsListEmpty( &Connection
->ReceiveRequest
) ) {
54 OSK_UINT RecvLen
= 0, Received
= 0;
55 OSK_PCHAR RecvBuffer
= 0;
59 Entry
= RemoveHeadList( &Connection
->ReceiveRequest
);
60 Bucket
= CONTAINING_RECORD( Entry
, TDI_BUCKET
, Entry
);
61 Complete
= Bucket
->Request
.RequestNotifyObject
;
63 TI_DbgPrint(MID_TRACE
,
64 ("Readable, Completing read request %x\n",
67 Irp
= Bucket
->Request
.RequestContext
;
68 Mdl
= Irp
->MdlAddress
;
70 TI_DbgPrint(MID_TRACE
,
71 ("Getting the user buffer from %x\n", Mdl
));
73 NdisQueryBuffer( Mdl
, &RecvBuffer
, &RecvLen
);
75 TI_DbgPrint(MID_TRACE
,
76 ("Reading %d bytes to %x\n", RecvLen
, RecvBuffer
));
78 if( NewState
& SEL_FIN
&& !RecvLen
) {
79 Status
= STATUS_END_OF_FILE
;
82 TI_DbgPrint(MID_TRACE
, ("Connection: %x\n", Connection
));
85 ("Connection->SocketContext: %x\n",
86 Connection
->SocketContext
));
87 TI_DbgPrint(MID_TRACE
, ("RecvBuffer: %x\n", RecvBuffer
));
89 Status
= TCPTranslateError
90 ( OskitTCPRecv( Connection
->SocketContext
,
97 TI_DbgPrint(MID_TRACE
,("TCP Bytes: %d\n", Received
));
99 if( Status
== STATUS_SUCCESS
&& Received
!= 0 ) {
100 TI_DbgPrint(MID_TRACE
,("Received %d bytes with status %x\n",
103 TI_DbgPrint(MID_TRACE
,
104 ("Completing Receive Request: %x\n",
107 Complete( Bucket
->Request
.RequestContext
,
108 STATUS_SUCCESS
, Received
);
109 } else if( Status
== STATUS_PENDING
||
110 (Status
== STATUS_SUCCESS
&& Received
== 0) ) {
111 InsertHeadList( &Connection
->ReceiveRequest
,
115 TI_DbgPrint(MID_TRACE
,
116 ("Completing Receive request: %x %x\n",
117 Bucket
->Request
, Status
));
118 Complete( Bucket
->Request
.RequestContext
, Status
, 0 );
126 void TCPPacketSendComplete( PVOID Context
,
127 PNDIS_PACKET NdisPacket
,
128 NDIS_STATUS NdisStatus
) {
129 TI_DbgPrint(MID_TRACE
,("called %x\n", NdisPacket
));
130 FreeNdisPacket(NdisPacket
);
131 TI_DbgPrint(MID_TRACE
,("done\n"));
134 #define STRINGIFY(x) #x
136 int TCPPacketSend(void *ClientData
, OSK_PCHAR data
, OSK_UINT len
) {
138 NDIS_STATUS NdisStatus
;
139 ROUTE_CACHE_NODE
*RCN
;
140 IP_PACKET Packet
= { 0 };
141 IP_ADDRESS RemoteAddress
, LocalAddress
;
144 TI_DbgPrint(MID_TRACE
,("TCP OUTPUT (%x:%d):\n", data
, len
));
145 OskitDumpBuffer( data
, len
);
147 if( *data
== 0x45 ) { /* IPv4 */
148 Header
= (PIPv4_HEADER
)data
;
149 LocalAddress
.Type
= IP_ADDRESS_V4
;
150 LocalAddress
.Address
.IPv4Address
= Header
->SrcAddr
;
151 RemoteAddress
.Type
= IP_ADDRESS_V4
;
152 RemoteAddress
.Address
.IPv4Address
= Header
->DstAddr
;
154 DbgPrint("Don't currently handle IPv6\n");
158 RemoteAddress
.Type
= LocalAddress
.Type
= IP_ADDRESS_V4
;
160 DbgPrint("OSKIT SENDING PACKET *** %x -> %x\n",
161 LocalAddress
.Address
.IPv4Address
,
162 RemoteAddress
.Address
.IPv4Address
);
164 Status
= RouteGetRouteToDestination( &RemoteAddress
, NULL
, &RCN
);
166 if( !NT_SUCCESS(Status
) || !RCN
) return OSK_EADDRNOTAVAIL
;
168 NdisStatus
= AllocatePacketWithBuffer( &Packet
.NdisPacket
, NULL
,
169 MaxLLHeaderSize
+ len
);
171 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
172 TI_DbgPrint(MAX_TRACE
, ("Error from NDIS: %08x\n", NdisStatus
));
173 return STATUS_NO_MEMORY
;
176 GetDataPtr( Packet
.NdisPacket
, MaxLLHeaderSize
,
177 (PCHAR
*)&Packet
.Header
, &Packet
.ContigSize
);
179 RtlCopyMemory( Packet
.Header
, data
, len
);
181 Packet
.HeaderSize
= sizeof(IPv4_HEADER
);
182 Packet
.TotalSize
= len
;
183 Packet
.SrcAddr
= LocalAddress
;
184 Packet
.DstAddr
= RemoteAddress
;
186 IPSendDatagram( &Packet
, RCN
, TCPPacketSendComplete
, NULL
);
188 if( !NT_SUCCESS(NdisStatus
) ) return OSK_EINVAL
;
192 void *TCPMalloc( void *ClientData
,
193 OSK_UINT Bytes
, OSK_PCHAR File
, OSK_UINT Line
) {
194 void *v
= PoolAllocateBuffer( Bytes
);
195 if( v
) TrackWithTag( FOURCC('f','b','s','d'), v
, File
, Line
);
199 void TCPFree( void *ClientData
,
200 void *data
, OSK_PCHAR File
, OSK_UINT Line
) {
201 UntrackFL( File
, Line
, data
);
202 PoolFreeBuffer( data
);
205 int TCPSleep( void *ClientData
, void *token
, int priority
, char *msg
,
207 PSLEEPING_THREAD SleepingThread
;
209 TI_DbgPrint(MID_TRACE
,
210 ("Called TSLEEP: tok = %x, pri = %d, wmesg = %s, tmio = %x\n",
211 token
, priority
, msg
, tmio
));
213 SleepingThread
= PoolAllocateBuffer( sizeof( *SleepingThread
) );
214 if( SleepingThread
) {
215 KeInitializeEvent( &SleepingThread
->Event
, NotificationEvent
, FALSE
);
216 SleepingThread
->SleepToken
= token
;
218 TcpipAcquireFastMutex( &SleepingThreadsLock
);
219 InsertTailList( &SleepingThreadsList
, &SleepingThread
->Entry
);
220 TcpipReleaseFastMutex( &SleepingThreadsLock
);
222 TI_DbgPrint(MID_TRACE
,("Waiting on %x\n", token
));
223 KeWaitForSingleObject( &SleepingThread
->Event
,
229 TcpipAcquireFastMutex( &SleepingThreadsLock
);
230 RemoveEntryList( &SleepingThread
->Entry
);
231 TcpipReleaseFastMutex( &SleepingThreadsLock
);
233 PoolFreeBuffer( SleepingThread
);
235 TI_DbgPrint(MID_TRACE
,("Waiting finished: %x\n", token
));
239 void TCPWakeup( void *ClientData
, void *token
) {
241 PSLEEPING_THREAD SleepingThread
;
243 TcpipAcquireFastMutex( &SleepingThreadsLock
);
244 Entry
= SleepingThreadsList
.Flink
;
245 while( Entry
!= &SleepingThreadsList
) {
246 SleepingThread
= CONTAINING_RECORD(Entry
, SLEEPING_THREAD
, Entry
);
247 TI_DbgPrint(MID_TRACE
,("Sleeper @ %x\n", SleepingThread
));
248 if( SleepingThread
->SleepToken
== token
) {
249 TI_DbgPrint(MID_TRACE
,("Setting event to wake %x\n", token
));
250 KeSetEvent( &SleepingThread
->Event
, IO_NETWORK_INCREMENT
, FALSE
);
252 Entry
= Entry
->Flink
;
254 TcpipReleaseFastMutex( &SleepingThreadsLock
);