0ca6538e49723fc97d4dde2697ffce228c960e5c
[reactos.git] / reactos / apps / tests / oskittcp / tcptest.cpp
1 #include <list>
2 #include <string>
3 #include <sstream>
4 extern "C" {
5 typedef unsigned short u_short;
6 #include <stdio.h>
7 #include <oskittcp.h>
8 #include <windows.h>
9 #include <winsock2.h>
10 };
11
12 char hwaddr[6] = { 0x08, 0x00, 0x20, 0x0b, 0xb7, 0xbb };
13
14 #undef malloc
15 #undef free
16
17 unsigned long TCP_IPIdentification;
18
19 #define MAX_DG_SIZE 0x10000
20 #define TI_DbgPrint(x,y) printf y
21
22 std::list<std::string> output_packets;
23
24 typedef struct _CONNECTION_ENDPOINT {
25 OSK_UINT State;
26 } CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;
27
28 int TCPSocketState(void *ClientData,
29 void *WhichSocket,
30 void *WhichConnection,
31 OSK_UINT NewState ) {
32 PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)WhichConnection;
33 PLIST_ENTRY Entry;
34
35 TI_DbgPrint(MID_TRACE,("Called: NewState %x\n", NewState));
36
37 if( !Connection ) {
38 TI_DbgPrint(MID_TRACE,("Socket closing.\n"));
39 return 0;
40 }
41
42 if( (NewState & SEL_CONNECT) &&
43 !(Connection->State & SEL_CONNECT) ) {
44 } else if( (NewState & SEL_READ) || (NewState & SEL_FIN) ) {
45 }
46
47 return 0;
48 }
49
50 #define STRINGIFY(x) #x
51
52 char hdr[14] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x08, 0x00 };
55
56 int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
57 output_packets.push_back( std::string( hdr, 14 ) +
58 std::string( (char *)data, (int)len ) );
59 return 0;
60 }
61
62 struct ifaddr *TCPFindInterface( void *ClientData,
63 OSK_UINT AddrType,
64 OSK_UINT FindType,
65 struct sockaddr *ReqAddr ) {
66 static struct sockaddr_in ifa = { AF_INET }, nm = { AF_INET };
67 static struct ifaddr a = {
68 (struct sockaddr *)&ifa,
69 NULL,
70 (struct sockaddr *)&nm,
71 0,
72 0,
73 1,
74 1500
75 };
76 ifa.sin_addr.s_addr = inet_addr( "10.10.2.115" );
77 nm.sin_addr.s_addr = inet_addr( "255.255.255.0" );
78 return &a;
79 }
80
81 void *TCPMalloc( void *ClientData,
82 OSK_UINT Bytes, OSK_PCHAR File, OSK_UINT Line ) {
83 void *v = malloc( Bytes );
84 fprintf( stderr, "(%s:%d) malloc( %d ) => %x\n", File, Line, Bytes, v );
85 return v;
86 }
87
88 void TCPFree( void *ClientData,
89 void *data, OSK_PCHAR File, OSK_UINT Line ) {
90 fprintf( stderr, "(%s:%d) free( %x )\n", File, Line, data );
91 free( data );
92 }
93
94 int TCPSleep( void *ClientData, void *token, int priority, char *msg,
95 int tmio ) {
96 #if 0
97 PSLEEPING_THREAD SleepingThread;
98
99 TI_DbgPrint(MID_TRACE,
100 ("Called TSLEEP: tok = %x, pri = %d, wmesg = %s, tmio = %x\n",
101 token, priority, msg, tmio));
102
103 SleepingThread = ExAllocatePool( NonPagedPool, sizeof( *SleepingThread ) );
104 if( SleepingThread ) {
105 KeInitializeEvent( &SleepingThread->Event, NotificationEvent, FALSE );
106 SleepingThread->SleepToken = token;
107
108 ExAcquireFastMutex( &SleepingThreadsLock );
109 InsertTailList( &SleepingThreadsList, &SleepingThread->Entry );
110 ExReleaseFastMutex( &SleepingThreadsLock );
111
112 TI_DbgPrint(MID_TRACE,("Waiting on %x\n", token));
113 KeWaitForSingleObject( &SleepingThread->Event,
114 WrSuspended,
115 KernelMode,
116 TRUE,
117 NULL );
118
119 ExAcquireFastMutex( &SleepingThreadsLock );
120 RemoveEntryList( &SleepingThread->Entry );
121 ExReleaseFastMutex( &SleepingThreadsLock );
122
123 ExFreePool( SleepingThread );
124 }
125 TI_DbgPrint(MID_TRACE,("Waiting finished: %x\n", token));
126 #endif
127 return 0;
128 }
129
130 void TCPWakeup( void *ClientData, void *token ) {
131 #if 0
132 PLIST_ENTRY Entry;
133 PSLEEPING_THREAD SleepingThread;
134
135 ExAcquireFastMutex( &SleepingThreadsLock );
136 Entry = SleepingThreadsList.Flink;
137 while( Entry != &SleepingThreadsList ) {
138 SleepingThread = CONTAINING_RECORD(Entry, SLEEPING_THREAD, Entry);
139 TI_DbgPrint(MID_TRACE,("Sleeper @ %x\n", SleepingThread));
140 if( SleepingThread->SleepToken == token ) {
141 TI_DbgPrint(MID_TRACE,("Setting event to wake %x\n", token));
142 KeSetEvent( &SleepingThread->Event, IO_NETWORK_INCREMENT, FALSE );
143 }
144 Entry = Entry->Flink;
145 }
146 ExReleaseFastMutex( &SleepingThreadsLock );
147 #endif
148 }
149
150 OSKITTCP_EVENT_HANDLERS EventHandlers = {
151 NULL,
152 TCPSocketState,
153 TCPPacketSend,
154 TCPFindInterface,
155 TCPMalloc,
156 TCPFree,
157 TCPSleep,
158 TCPWakeup
159 };
160
161 void display_row( char *data, int off, int len ) {
162 int i;
163
164 printf( "%08x:", off );
165 for( i = off; i < len && i < off + 16; i++ ) {
166 printf( " %02x", data[i] & 0xff );
167 }
168
169 printf( " -- " );
170
171 for( i = off; i < len && i < off + 16; i++ ) {
172 printf( "%c", (data[i] >= ' ') ? data[i] : '.' );
173 }
174
175 printf( "\n" );
176 }
177
178 int main( int argc, char **argv ) {
179 int asock = INVALID_SOCKET, selret, dgrecv, fromsize, err, port = 5001;
180 char datagram[MAX_DG_SIZE];
181 void *conn = 0;
182 struct fd_set readf;
183 struct timeval tv;
184 struct sockaddr_in addr_from = { AF_INET }, addr_to = { AF_INET };
185 std::list<std::string>::iterator i;
186 WSADATA wsadata;
187
188 WSAStartup( 0x101, &wsadata );
189
190 if( argc > 1 ) port = atoi(argv[1]);
191
192 RegisterOskitTCPEventHandlers( &EventHandlers );
193 InitOskitTCP();
194
195 asock = socket( AF_INET, SOCK_DGRAM, 0 );
196
197 addr_from.sin_port = htons( port );
198
199 if( bind( asock, (struct sockaddr *)&addr_from, sizeof( addr_from ) ) ) {
200 printf( "Bind error\n" );
201 return 0;
202 }
203
204 addr_to.sin_port = htons( port & (~1) );
205 addr_to.sin_addr.s_addr = inet_addr("127.0.0.1");
206
207 while( true ) {
208 FD_ZERO( &readf );
209 FD_SET( asock, &readf );
210 tv.tv_sec = 0;
211 tv.tv_usec = 10000;
212 selret = select( asock + 1, &readf, NULL, NULL, &tv );
213
214 if( FD_ISSET( asock, &readf ) ) {
215 fromsize = sizeof( addr_from );
216 dgrecv = recvfrom( asock, datagram, sizeof(datagram), 0,
217 (struct sockaddr *)&addr_from, &fromsize );
218
219 if( datagram[0] == 'C' && datagram[1] == 'M' &&
220 datagram[2] == 'D' && datagram[3] == ' ' ) {
221 int theport, bytes, recvret, off, bytin;
222 struct sockaddr_in nam;
223 std::string faddr, word;
224 std::istringstream
225 cmdin( std::string( datagram + 4, dgrecv - 4 ) );
226
227 cmdin >> word;
228
229 if( word == "socket" ) {
230 cmdin >> faddr >> theport;
231
232 nam.sin_family = AF_INET;
233 nam.sin_addr.s_addr = inet_addr(faddr.c_str());
234 nam.sin_port = htons(theport);
235
236 if( (err = OskitTCPSocket( NULL, &conn, AF_INET,
237 SOCK_STREAM, 0 )) != 0 ) {
238 fprintf( stderr, "OskitTCPSocket: error %d\n", err );
239 }
240
241 if( (err = OskitTCPConnect( conn, NULL, &nam,
242 sizeof(nam) )) != 0 ) {
243 fprintf( stderr, "OskitTCPConnect: error %d\n", err );
244 } else {
245 printf( "Socket created\n" );
246 }
247 }
248
249 /* The rest of the commands apply only to an open socket */
250 if( !conn ) continue;
251
252 if( word == "recv" ) {
253 cmdin >> bytes;
254
255 if( (err = OskitTCPRecv( conn, (OSK_PCHAR)datagram,
256 sizeof(datagram),
257 (unsigned int *)&bytin, 0 )) != 0 ) {
258 fprintf( stderr, "OskitTCPRecv: error %d\n", err );
259 } else {
260 for( off = 0; off < bytin; off += 16 ) {
261 display_row( datagram, off, bytin );
262 }
263 printf( "\n" );
264 }
265 } else if ( word == "type" ) {
266 std::string therest = &cmdin.str()[word.size()];
267 char* p = &therest[0];
268 p += strspn ( p, " \t" );
269 char* src = p;
270 char* dst = p;
271 while ( *src )
272 {
273 char c = *src++;
274 if ( c == '\r' || c == '\n' ) break;
275 if ( c == '\\' )
276 {
277 c = *src++;
278 switch ( c )
279 {
280 case 'b': c = '\b'; break;
281 case 'n': c = '\n'; break;
282 case 'r': c = '\r'; break;
283 case 't': c = '\t'; break;
284 case 'v': c = '\v'; break;
285 }
286 }
287 *dst++ = c;
288 }
289 *dst = '\0';
290 if ( (err = OskitTCPSend ( conn, (OSK_PCHAR)p, strlen(p), (OSK_UINT*)&bytin, 0 ))
291 != 0 ) {
292 fprintf ( stderr, "OskitTCPConnect: error %d\n", err );
293 } else {
294 printf ( "wrote %d bytes\n", bytin );
295 }
296 } else if( word == "send" ) {
297 off = 0;
298 while( cmdin >> word ) {
299 datagram[off++] =
300 atoi( (std::string("0x") + word).c_str() );
301 }
302
303 if( (err = OskitTCPSend( conn, (OSK_PCHAR)datagram,
304 off, (OSK_UINT *)&bytin, 0 ))
305 != 0 ) {
306 fprintf( stderr, "OskitTCPConnect: error %d\n", err );
307 } else {
308 printf( "wrote %d bytes\n", bytin );
309 }
310 } else if( word == "close" ) {
311 OskitTCPClose( conn );
312 conn = NULL;
313 }
314 } else if( dgrecv > 14 ) {
315 addr_to = addr_from;
316
317 if( datagram[12] == 8 && datagram[13] == 6 ) {
318 /* Answer arp query */
319 char laddr[4];
320 /* Mark patch as to the previous sender */
321 memcpy( datagram + 32, datagram + 6, 6 );
322 memcpy( datagram, datagram + 6, 6 );
323 /* Mark packet as from us */
324 memcpy( datagram + 22, hwaddr, 6 );
325 memcpy( datagram + 6, hwaddr, 6 );
326 /* Swap inet addresses */
327 memcpy( laddr, datagram + 28, 4 );
328 memcpy( datagram + 28, datagram + 38, 4 );
329 memcpy( datagram + 38, laddr, 4 );
330 /* Set reply opcode */
331 datagram[21] = 2;
332
333 err = sendto( asock, datagram, dgrecv, 0,
334 (struct sockaddr *)&addr_to,
335 sizeof(addr_to) );
336
337 if( err != 0 )
338 printf( "sendto: %d\n", err );
339 } else {
340 memcpy( hdr, datagram + 6, 6 );
341 memcpy( hdr + 6, datagram, 6 );
342 memcpy( hdr + 12, datagram + 12, 2 );
343 OskitTCPReceiveDatagram
344 ( (unsigned char *)datagram + 14,
345 dgrecv - 14, 20 );
346 }
347 }
348 }
349
350 TimerOskitTCP();
351
352 for( i = output_packets.begin(); i != output_packets.end(); i++ ) {
353 err = sendto( asock, i->c_str(), i->size(), 0,
354 (struct sockaddr *)&addr_to, sizeof(addr_to) );
355
356 fprintf( stderr, "** SENDING PACKET %d bytes **\n", i->size() );
357
358 if( err != 0 )
359 printf( "sendto: %d\n", err );
360 }
361
362 output_packets.clear();
363 }
364 }
365