182f20ab756a3458a3a54709bac428d2eaa4540e
[reactos.git] / reactos / drivers / lib / 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(MID_TRACE,("Flags: %c%c%c%c\n",
20 NewState & SEL_CONNECT ? 'C' : 'c',
21 NewState & SEL_READ ? 'R' : 'r',
22 NewState & SEL_FIN ? 'F' : 'f',
23 NewState & SEL_ACCEPT ? 'A' : 'a'));
24
25 TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
26 NewState, Connection,
27 Connection ? Connection->State ^ NewState :
28 NewState));
29
30 if( !Connection ) {
31 TI_DbgPrint(DEBUG_TCP,("Socket closing.\n"));
32 Connection = FileFindConnectionByContext( WhichSocket );
33 if( !Connection )
34 return 0;
35 else
36 TI_DbgPrint(DEBUG_TCP,("Found socket %x\n", Connection));
37 }
38
39 TI_DbgPrint(MID_TRACE,("Connection signalled: %d\n",
40 Connection->Signalled));
41
42 Connection->SignalState |= NewState;
43 if( !Connection->Signalled ) {
44 Connection->Signalled = TRUE;
45 InsertTailList( &SignalledConnections, &Connection->SignalList );
46 }
47
48 return 0;
49 }
50
51 void TCPPacketSendComplete( PVOID Context,
52 PNDIS_PACKET NdisPacket,
53 NDIS_STATUS NdisStatus ) {
54 TI_DbgPrint(DEBUG_TCP,("called %x\n", NdisPacket));
55 FreeNdisPacket(NdisPacket);
56 TI_DbgPrint(DEBUG_TCP,("done\n"));
57 }
58
59 #define STRINGIFY(x) #x
60
61 int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
62 NDIS_STATUS NdisStatus;
63 PNEIGHBOR_CACHE_ENTRY NCE;
64 IP_PACKET Packet = { 0 };
65 IP_ADDRESS RemoteAddress, LocalAddress;
66 PIPv4_HEADER Header;
67
68 if( *data == 0x45 ) { /* IPv4 */
69 Header = (PIPv4_HEADER)data;
70 LocalAddress.Type = IP_ADDRESS_V4;
71 LocalAddress.Address.IPv4Address = Header->SrcAddr;
72 RemoteAddress.Type = IP_ADDRESS_V4;
73 RemoteAddress.Address.IPv4Address = Header->DstAddr;
74 } else {
75 TI_DbgPrint(MIN_TRACE,("Outgoing packet is not IPv4\n"));
76 OskitDumpBuffer( data, len );
77 return OSK_EINVAL;
78 }
79
80 RemoteAddress.Type = LocalAddress.Type = IP_ADDRESS_V4;
81
82 if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
83 TI_DbgPrint(MIN_TRACE,("No route to %s\n", A2S(&RemoteAddress)));
84 return OSK_EADDRNOTAVAIL;
85 }
86
87 NdisStatus = AllocatePacketWithBuffer( &Packet.NdisPacket, NULL,
88 MaxLLHeaderSize + len );
89
90 if (NdisStatus != NDIS_STATUS_SUCCESS) {
91 TI_DbgPrint(DEBUG_TCP, ("Error from NDIS: %08x\n", NdisStatus));
92 return OSK_ENOBUFS;
93 }
94
95 GetDataPtr( Packet.NdisPacket, MaxLLHeaderSize,
96 (PCHAR *)&Packet.Header, &Packet.ContigSize );
97
98 RtlCopyMemory( Packet.Header, data, len );
99
100 Packet.HeaderSize = sizeof(IPv4_HEADER);
101 Packet.TotalSize = len;
102 Packet.SrcAddr = LocalAddress;
103 Packet.DstAddr = RemoteAddress;
104
105 IPSendDatagram( &Packet, NCE, TCPPacketSendComplete, NULL );
106
107 if( !NT_SUCCESS(NdisStatus) ) return OSK_EINVAL;
108 else return 0;
109 }
110
111 void *TCPMalloc( void *ClientData,
112 OSK_UINT Bytes, OSK_PCHAR File, OSK_UINT Line ) {
113 void *v = PoolAllocateBuffer( Bytes );
114 if( v ) TrackWithTag( FOURCC('f','b','s','d'), v, (PCHAR)File, Line );
115 return v;
116 }
117
118 void TCPFree( void *ClientData,
119 void *data, OSK_PCHAR File, OSK_UINT Line ) {
120 UntrackFL( (PCHAR)File, Line, data );
121 PoolFreeBuffer( data );
122 }
123
124 int TCPSleep( void *ClientData, void *token, int priority, char *msg,
125 int tmio ) {
126 PSLEEPING_THREAD SleepingThread;
127
128 TI_DbgPrint(DEBUG_TCP,
129 ("Called TSLEEP: tok = %x, pri = %d, wmesg = %s, tmio = %x\n",
130 token, priority, msg, tmio));
131
132 SleepingThread = PoolAllocateBuffer( sizeof( *SleepingThread ) );
133 if( SleepingThread ) {
134 KeInitializeEvent( &SleepingThread->Event, NotificationEvent, FALSE );
135 SleepingThread->SleepToken = token;
136
137 TcpipAcquireFastMutex( &SleepingThreadsLock );
138 InsertTailList( &SleepingThreadsList, &SleepingThread->Entry );
139 TcpipReleaseFastMutex( &SleepingThreadsLock );
140
141 TI_DbgPrint(DEBUG_TCP,("Waiting on %x\n", token));
142 KeWaitForSingleObject( &SleepingThread->Event,
143 WrSuspended,
144 KernelMode,
145 TRUE,
146 NULL );
147
148 TcpipAcquireFastMutex( &SleepingThreadsLock );
149 RemoveEntryList( &SleepingThread->Entry );
150 TcpipReleaseFastMutex( &SleepingThreadsLock );
151
152 PoolFreeBuffer( SleepingThread );
153 }
154 TI_DbgPrint(DEBUG_TCP,("Waiting finished: %x\n", token));
155 return 0;
156 }
157
158 void TCPWakeup( void *ClientData, void *token ) {
159 PLIST_ENTRY Entry;
160 PSLEEPING_THREAD SleepingThread;
161
162 TcpipAcquireFastMutex( &SleepingThreadsLock );
163 Entry = SleepingThreadsList.Flink;
164 while( Entry != &SleepingThreadsList ) {
165 SleepingThread = CONTAINING_RECORD(Entry, SLEEPING_THREAD, Entry);
166 TI_DbgPrint(DEBUG_TCP,("Sleeper @ %x\n", SleepingThread));
167 if( SleepingThread->SleepToken == token ) {
168 TI_DbgPrint(DEBUG_TCP,("Setting event to wake %x\n", token));
169 KeSetEvent( &SleepingThread->Event, IO_NETWORK_INCREMENT, FALSE );
170 }
171 Entry = Entry->Flink;
172 }
173 TcpipReleaseFastMutex( &SleepingThreadsLock );
174 }