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