source: Daodan/MSVC/Mariusnet.c@ 588

Last change on this file since 588 was 588, checked in by gumby, 14 years ago
File size: 17.1 KB
Line 
1
2#include <winsock2.h>
3#include "bool.h"
4#include "Flatline_Net.h"
5#include "Flatline_Win32.h"
6#include "Mariusnet_Defs.h"
7#include "Daodan_Console.h"
8#include <stdio.h>
9#include <inaddr.h>
10#pragma comment(lib, "wininet.lib")
11
12
13typedef struct hostent hostent ;
14typedef struct in_addr in_addr;
15
16char MariusLogin[32]={0};
17unsigned char MariusPassword[16]={0};
18
19m_room RoomList[64] = {0};
20bool RoomListGotten = 0;
21
22bool MariusNet_LoggedIn = 0;
23
24bool MsNet_Running = 0;
25int Marius_Socket = -1;
26int Room_Socket = -1;
27sockaddr_in RoomAddr = {0};
28int PlayerID = 0;
29/*
30
31RGBA green = {0, 0xFF, 0, 0};
32RGBA red = {0, 0, 0xFF, 0};
33
34RGBA grey = {0x80,0x80,0x80,0x80};
35*/
36extern RGBA red;
37//extern RGBA blue;
38RGBA blue = {0xFF, 0, 0, 0};
39RGBA cyan = {0xFF, 0xFF, 0, 0};
40RGBA white = {0xFF, 0xFF, 0xFF, 0};
41extern RGBA green;
42extern RGBA grey;
43int MariusNet_OutgoingPacketWrapper(int socket, const sockaddr* address, marius_packet* data, short datalen)
44{
45 data->header.PacketSize = htonl(datalen);
46 //NetUDPSocket_Send( socket, address, (char*)data, sizeof(marius_header) );
47 //datalen -= sizeof(marius_header);
48 //(char*)data += sizeof(marius_header);
49 return NetUDPSocket_Send( socket, address, (char*)data, datalen);
50}
51
52int PacketCached = 0;
53int MariusNet_IncomingPacketWrapper(int socket, char buffer[], int bufferlength, int flags)
54{
55 int inSize = 0;
56 unsigned fullSize = -1;
57 static char cacheBuffer[1440] = {0};
58 bool NeedMoreData = 0;
59 if(PacketCached)
60 {
61 unsigned int PacketSize = ntohl(((marius_packet*)cacheBuffer)->header.PacketSize);
62 /*
63 if(ntohs(((marius_packet*)cacheBuffer)->header.PacketSignature) != 0xDEAD)
64 {
65 PacketCached = PacketSize = 0;
66 NeedMoreData = 1;
67 }
68 */
69
70
71
72 if(PacketCached >= PacketSize)
73 {
74 memcpy( buffer, cacheBuffer, PacketSize );
75 PacketCached -= PacketSize;
76 }
77 else
78 {
79 memcpy( buffer, cacheBuffer, PacketCached );
80 inSize += PacketCached;
81 NeedMoreData = 1;
82 PacketCached = 0;
83 }
84 if(PacketCached < 0)
85 {
86 DDrConsole_PrintF("Warning, took too much from cache");
87 PacketCached = 0;
88 }
89 else if (PacketCached > 0)// && ntohs((short*)(cacheBuffer + PacketSize)) == 0xDEAD)
90 {
91 memcpy( cacheBuffer, cacheBuffer + PacketSize, PacketCached );
92 }
93 else
94 {
95 memset(cacheBuffer, 0, 1440);
96 }
97
98 if(!NeedMoreData) return PacketSize;
99
100 }
101 do
102 {
103 int tempSize = recv(socket, buffer + inSize, bufferlength, flags);
104 if(tempSize == SOCKET_ERROR)
105 {
106 NetCatchError();
107 return SOCKET_ERROR;
108 }
109
110 if(fullSize == -1)
111 {
112 if(ntohs(((marius_packet*)buffer)->header.PacketSignature) != 0xDEAD)
113 {
114 DDrConsole_PrintF("Bad header signature...closing Mariusnet connection");
115 return SOCKET_ERROR;
116 }
117 fullSize = ntohl(((marius_packet*)buffer)->header.PacketSize);
118 }
119 inSize += tempSize;
120
121 }
122 while(inSize < fullSize);
123
124 //double packet madness
125 if(inSize > fullSize
126 && ntohs(*(short*)(buffer + fullSize)) == 0xDEAD
127 && ntohl(((marius_packet*)(buffer + fullSize))->header.PacketSize) > 0
128 && inSize - fullSize > sizeof(marius_header)
129 )
130 {
131 memcpy(cacheBuffer, buffer + fullSize, inSize - fullSize);
132
133 PacketCached = inSize - fullSize;
134 }
135 else PacketCached = 0;
136 return inSize;
137}
138
139
140sockaddr_in Marius_Server;
141
142
143bool MariusNet_Initialize()
144{
145 hostent* host_info = 0;
146 //host_info = gethostbyname("myth.mariusnet.com");
147
148 host_info = gethostbyname("metaserver.lhowon.org");
149 if(!host_info)
150 {
151 DDrConsole_PrintF("Error, could not resolve myth.mariusnet.com");
152 return 1;
153 }
154 Marius_Server.sin_port = htons(6321);
155 Marius_Server.sin_family = AF_INET;
156 Marius_Server.sin_addr.S_un.S_addr = *(ULONG*)host_info->h_addr_list[0];
157 return 0;
158}
159
160void Initialize_MPacket( marius_packet* packet, short ID )
161{
162 memset( packet, 0, sizeof(marius_packet) );
163 packet->header.PacketSignature = htons(0xDEAD);
164 packet->header.PacketId = htons(ID);
165
166}
167
168void Initialize_LoginPacket( marius_packet* packet)
169{
170 int NameSize = 0;
171 int TeamSize = 0;
172 char (*test)[] = packet;
173 Initialize_MPacket(packet, pt_PlayerLogin);
174
175 packet->login.UpdateAppearance = 1;
176 packet->login.Platform = htons(1);
177 strncpy(packet->login.LoginId, MariusLogin, 32);
178 packet->login.EncryptionType = htons(1);
179 strcpy(packet->login.AppName, "MARATHON" ); //ONI ;)
180 strncpy(packet->login.BuildDate, __DATE__, 32 );
181 strncpy(packet->login.BuildTime, __TIME__, 32 );
182
183
184 packet->login.PlayerInfo.clientVersion = htons(5000);
185 NameSize = sprintf(packet->login.PlayerInfo.Name, MariusLogin);
186 //TeamSize = sprintf(packet->login.PlayerInfo.Name + NameSize, "TCTF") + 1;
187
188 packet->login.PlayerInfoSize = htons(40 + NameSize + TeamSize);
189}
190
191char EncryptionTypes[][32] =
192{
193 "Plaintext",
194 "Braindead Simple",
195};
196
197enum {
198 SyntaxError,
199 GamesNotAllowed,
200 InvalidVersion,
201 BadUserOrPassword,
202 UserNotLoggedIn,
203 BadMetaserverVersion,
204 UserAlreadyLoggedIn,
205 UnknownGameType,
206 LoginSuccessful,
207 LogoutSuccessful,
208 PlayerNotInRoom,
209 GameAlreadyExists,
210 AccountAlreadyLoggedIn,
211 RoomFull,
212 AccountLocked,
213 NotSupported
214};
215
216static const char* sRoomNames[] = {
217 "Crows Bridge",
218 "Otter Ferry",
219 "White Falls",
220 "Silvermines",
221 "Shoal",
222 "Madrigal",
223 "Tyr",
224 "Ash",
225 "Scales",
226 "Covenant",
227 "Muirthemne",
228 "Seven Gates",
229 "Bagrada",
230 "The Barrier",
231 "Forest Heart",
232 "The Ermine",
233 "The Dire Marsh",
234 "The Highlands",
235 "The Drowned Kingdom",
236 "The Great Devoid",
237 "Shiver",
238 "The Caterthuns",
239 "Soulblighter",
240 "Balor",
241 "Sons of Myrgard",
242 "Heart of the Stone",
243 "Arrival",
244 "Ingue Ferroque",
245 "Vimy Ridge",
246 "Stilwell Road"
247};
248void MSNet_LoginError_Output( int code )
249{
250 switch(code)
251 {
252 case(BadUserOrPassword):
253 DDrConsole_PrintF( "Login denied: bad username or password." );
254 break;
255 case(UserAlreadyLoggedIn):
256 DDrConsole_PrintF( "Login denied: that user is already logged in.");
257 break;
258 case(AccountAlreadyLoggedIn):
259 DDrConsole_PrintF( "Login denied: that account is already logged in.");
260 break;
261 case(RoomFull):
262 DDrConsole_PrintF( "Login denied: room is full!?");
263 break;
264 case(AccountLocked):
265 DDrConsole_PrintF( "Login denied: your account is locked.");
266 break;
267 default:
268 DDrConsole_PrintF("There was a problem connecting to the server"
269 "that tracks Internet games. Please try again later.");
270 break;
271 }
272
273}
274
275void MSNet_HandleChat( m_message* msg )
276{
277 //BGRA *cough*
278 /*RGBA chatcolor;
279 chatcolor.R = (msg->PrimaryColor.Red);
280 chatcolor.G = (msg->PrimaryColor.Green);
281 chatcolor.B = (msg->PrimaryColor.Blue);
282 chatcolor.A = 0;*/
283 char Message[1024];
284 int NameLen = sprintf_s( Message, 1024, "%s", msg->Message ) + 1;
285 sprintf_s( Message, 1024 - NameLen, "%s: %s", Message, msg->Message + NameLen );
286 //DDrConsole_PrintColored( msg->Message, 0, chatcolor,white );
287 DDrConsole_Print(Message);
288}
289
290void MSNet_SendChat( char* msg )
291{
292 marius_packet mPacket = {0};
293 int len;
294 if(!MsNet_Running || !MariusNet_LoggedIn) return;
295
296 Initialize_MPacket(&mPacket, pt_ChatMessage);
297
298
299 mPacket.message.SecondaryColor.Red = mPacket.message.SecondaryColor.Flags = -1;
300
301
302
303 //mPacket.message.Message = 'Gumby';
304 len = sprintf(mPacket.message.Message, "O %s", msg );
305 mPacket.message.Message[1] = 0;
306 mPacket.message.SenderId = htonl(PlayerID);
307 //mPacket.message.TargetId = -1;
308 MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket,
309 sizeof(marius_header) + sizeof(m_message) - (255 - len) );
310
311
312}
313
314int MSNet_Cleanup()
315{
316 if( Marius_Socket != -1) closesocket(Marius_Socket);
317 Marius_Socket = -1;
318 if( Room_Socket != -1) closesocket(Room_Socket);
319 Room_Socket = -1;
320 memset(RoomList, 0, sizeof(m_room) * 64 );
321 DDrConsole_PrintF("The metaserver connection will now close." );
322 MsNet_Running = 0;
323 MariusNet_LoggedIn = 0;
324 return 1;
325}
326
327void MSNet_HandleGameList( m_gameinfo* PacketGames, int PacketSize )
328{
329 m_gameinfo TempGameList[64] = {0};
330 int i ;
331 for( i = 0; PacketSize > 0; i++ )
332 {
333 int ThisSize = sizeof(m_gameinfo) + ntohs(PacketGames->len) - sizeof(m_gamedescription);
334
335 memcpy(TempGameList + i,PacketGames, sizeof(m_gameinfo) - 128);
336
337 sprintf_s( TempGameList[i].g.Buffer, 128, "%s", PacketGames->g.Buffer);
338 PacketSize -= ThisSize;
339 PacketGames = (m_gameinfo*)((char*)PacketGames + ThisSize);
340
341 }
342 //Do stuff with the games.
343}
344
345int MSNet_Room_Join( short Room, char* Key)
346{
347 marius_packet mPacket = {0};
348
349 char incomingData[1400] = {0};
350 marius_packet* incomingPacket = (marius_packet*)incomingData;
351 int sent_bytes = 0;
352
353 sockaddr_in SockAddr;
354 RoomAddr.sin_port = RoomList[Room].Port;
355 RoomAddr.sin_family = AF_INET;
356 RoomAddr.sin_addr.S_un.S_addr = RoomList[Room].IPAddress;
357
358 Room_Socket = NetTCPSocket_Create(RoomList[Room].Port, &SockAddr);
359
360 DDrConsole_PrintF("Joining room %hi", Room);
361
362 if(Room_Socket == -1)
363 {
364 DDrConsole_PrintF("Failed to initialize room socket!");
365 return MSNet_Cleanup();
366 }
367
368 if(connect( Room_Socket, (sockaddr *)&RoomAddr, sizeof(sockaddr_in)))
369 {
370 NetCatchError();
371 MariusNet_LoggedIn = 0;
372 return MSNet_Cleanup();
373 }
374
375 Initialize_MPacket(&mPacket, pt_ChatRoomLogin);
376 memcpy(mPacket.chatroom_join.RoomKey, Key, 32);
377 strcpy(mPacket.chatroom_join.Name, MariusLogin);
378 sent_bytes = MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket,
379 sizeof(marius_header) + 33 + strlen(MariusLogin));
380
381
382
383 Initialize_MPacket(&mPacket, pt_RoomPlayerInfo);
384 mPacket.player_info.clientVersion = htons(5000);
385 sprintf(mPacket.player_info.Name, MariusLogin);
386 sent_bytes = MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket,
387 sizeof(marius_header) + 40 + strlen(MariusLogin));
388
389 if(MariusNet_IncomingPacketWrapper(Room_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
390 {
391 return MSNet_Cleanup();
392 }
393
394 if(ntohs(incomingPacket->header.PacketId)== pt_LoginInfo)
395 {
396 //DDrConsole_PrintF("Login failed: %s", incomingPacket->login_denied.DenialMessage );
397 MSNet_LoginError_Output(ntohl(incomingPacket->login_denied.code));
398 return MSNet_Cleanup();
399 }
400
401 MariusNet_LoggedIn = 1;
402
403 /*
404 Initialize_MPacket(&mPacket, 104);
405 mPacket.newgame.g.maxplayers = -1;
406 mPacket.newgame.g.clientversion = htonl(0xc136e436);
407 mPacket.newgame.g.maxteams = -1;
408 //sprintf(mPacket.newgame.g.Buffer, "Oni!");
409 memcpy(mPacket.newgame.g.Buffer, "Blam!\0This is Oni, bitch.\0", 50);
410 sent_bytes = MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, (char*)&mPacket,
411 sizeof(marius_header) + sizeof(m_announcegame) + 50);
412 */
413 while(1)
414 {
415 if(MariusNet_IncomingPacketWrapper(Room_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
416 {
417 return 0;
418 }
419 switch(ntohs(incomingPacket->header.PacketId))
420 {
421 case pt_RoomList:
422 case pt_PlayerInfo:
423 case pt_PlayerList:
424 //Do nothing for now
425 break;
426 case pt_GameList:
427 MSNet_HandleGameList( incomingPacket->gamelist.Games,
428 ntohl(incomingPacket->header.PacketSize) - sizeof(marius_header));
429 break;
430 case pt_BlueBarMsg:
431 DDrConsole_PrintColored(incomingPacket->motd.Message, 0, cyan, grey );
432 break;
433 case pt_ChatMessage:
434 MSNet_HandleChat(&incomingPacket->message);
435 break;
436 case pt_KeepAlive:
437 MariusNet_OutgoingPacketWrapper(Room_Socket, (sockaddr*)&RoomAddr, incomingData,
438 sizeof(marius_header));
439 break;
440 default:
441 DDrConsole_PrintF("Got packet of type %hi", ntohs(incomingPacket->header.PacketId));
442 break;
443 }
444 }
445
446 return 0;
447}
448
449DWORD WINAPI MSNet_Handler(void* unused)
450{
451 int Port = 4156;
452
453
454 char RoomToken[33] = {0};
455 int i = 0;
456
457
458
459 sockaddr_in Marius_Addr = {0};
460 if(MsNet_Running)
461 {
462 DDrConsole_PrintF("The metaserver handler is already running!");
463 }
464 MsNet_Running = 1;
465
466 if(MariusNet_LoggedIn)
467 {
468 DDrConsole_PrintF("You're already logged in!");
469 return MSNet_Cleanup();
470 }
471
472 NetPlatform_Initalize();
473
474
475 if(MariusNet_Initialize())
476 {
477 return MSNet_Cleanup();
478 }
479
480 //Horribly set up.
481 while( (Marius_Socket == -1 || Marius_Socket == 0 )&& Port < 6641)
482 {
483
484 //Marius_Socket = NetTCPSocket_Create(Port, &Marius_Addr);
485 //NetUDPSocket_Close( Marius_Socket );
486 Marius_Socket = NetTCPSocket_Create(Port, &Marius_Addr);
487 //Port++;
488 }
489
490 if(Marius_Socket != -1)
491 {
492 unsigned char incomingData[1400] = {0};
493 short incomingLength = 0;
494 marius_packet* incomingPacket = &incomingData;
495 //Initialize
496 marius_packet mPacket;
497 int sent_bytes;
498 Initialize_LoginPacket(&mPacket);
499
500 DDrConsole_PrintF("Logging into Mariusnet <%s>...", inet_ntoa(Marius_Server.sin_addr));
501 if(connect( Marius_Socket, &Marius_Server, sizeof(sockaddr_in)))
502 {
503 NetCatchError();
504 return MSNet_Cleanup();
505 }
506 DDrConsole_PrintF("Sending Player Info...");
507 sent_bytes = MariusNet_OutgoingPacketWrapper(Marius_Socket, (sockaddr*)&Marius_Server, (char*)&mPacket,
508 sizeof(marius_header) + sizeof(m_player_login) - (sizeof(m_player_info) - ntohs(mPacket.login.PlayerInfoSize) ) );
509 /*
510 if(!NetUDPSocket_Recieve(Marius_Socket, (sockaddr*)&Marius_Addr,incomingData, &incomingLength))
511 {
512 DDrConsole_PrintF("Data: %s Length %i", incomingData, incomingLength);
513 return 0;
514 }
515 */
516 if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
517 {
518 return MSNet_Cleanup();
519 }
520
521 if(ntohs(incomingPacket->header.PacketId)== pt_EncryptionKey)
522 {
523 //recv( Marius_Socket, incomingData, 1440, 0);
524 DDrConsole_PrintF("Encryption Type %s", EncryptionTypes[ntohs(incomingPacket->salt.EncryptionType)] );
525
526 Initialize_MPacket(&mPacket, pt_Password);
527 if(incomingPacket->salt.EncryptionType)
528 {
529
530 unsigned char* Hash = mPacket.password.passHash;
531 unsigned char* Salt = incomingPacket->salt.salt;
532 unsigned char Pass[16] = {0};
533
534 memset(Pass, 0x23, 16);
535 strcpy(Pass, MariusPassword );
536
537 for( i = 0; i < 16; i++ ) Hash[i] = Pass[i]^Salt[i];
538 for( i = 1; i < 16; i++ ) Hash[i] = Hash[i]^Hash[i-1];
539 for( i = 1; i < 16; i++ )
540 {
541 short value = ~( Hash[i]*Hash[i-1] );
542 Hash[i] = (unsigned char) value;
543
544 }
545 }
546 else
547 {
548 strncpy(mPacket.password.passHash, MariusPassword, 16);
549 }
550
551 DDrConsole_PrintF("Sending Password...");
552 sent_bytes = MariusNet_OutgoingPacketWrapper(Marius_Socket, (sockaddr*)&Marius_Server, (char*)&mPacket, sizeof(marius_header) + sizeof(m_password) );
553
554 if(!NetUDPSocket_Recieve(Marius_Socket, (sockaddr*)&Marius_Addr,incomingData, &incomingLength))
555 {
556 return MSNet_Cleanup();
557 }
558 DDrConsole_PrintF("Password ACK!");
559 if(ntohs(incomingPacket->header.PacketId)== pt_PasswordAck)
560 {
561
562 Initialize_MPacket(&mPacket, pt_Localization);
563 mPacket.localization.one = htonl(1);
564 mPacket.localization.two = htonl(2);
565 mPacket.localization.three = htonl(3);
566 mPacket.localization.zero = 0;
567 sent_bytes = MariusNet_OutgoingPacketWrapper(Marius_Socket, (sockaddr*)&Marius_Server, (char*)&mPacket, sizeof(marius_header) + sizeof(m_localization) );
568
569 if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
570 {
571 return MSNet_Cleanup();
572 }
573 }
574 }
575
576 if(ntohs(incomingPacket->header.PacketId)== pt_UserLoggedIn)
577 {
578 PlayerID = ntohl(incomingPacket->login_success.userID);
579 //Not sure if this is a string or byte array, so I allocated 33 bytes,
580 //so it always zero terminates.
581 memcpy(RoomToken, incomingPacket->login_success.Token, 32);
582 DDrConsole_PrintF("Logged into Mariusnet!");
583 }
584 else if(ntohs(incomingPacket->header.PacketId)== pt_LoginInfo)
585 {
586 //DDrConsole_PrintF("Login failed: %s", incomingPacket->login_denied.DenialMessage );
587 MSNet_LoginError_Output(ntohl(incomingPacket->login_denied.code));
588 return MSNet_Cleanup();
589 }
590 else
591 {
592 return MSNet_Cleanup();
593 }
594
595
596 do
597 {
598 if(MariusNet_IncomingPacketWrapper(Marius_Socket, incomingData, 1400, 0) == SOCKET_ERROR)
599 {
600 return MSNet_Cleanup();
601 }
602 if(ntohs(incomingPacket->header.PacketId)== pt_RoomList)
603 {
604 DDrConsole_PrintF("Got room list!");
605 RoomListGotten = 1;
606 memcpy(RoomList, incomingPacket->roomlist.Rooms,
607 ntohl(incomingPacket->header.PacketSize) - sizeof(marius_header));
608 }
609 else if(ntohs(incomingPacket->header.PacketId)== pt_PlayerInfo)
610 {
611 //What do we do with this?!
612 DDrConsole_PrintF("Got player info!");
613 }
614 else
615 {
616 DDrConsole_PrintF("Invalid packet type %hi", ntohs(incomingPacket->header.PacketId));
617 return MSNet_Cleanup();
618 }
619 }
620 while(PacketCached || !RoomListGotten);
621
622 for(i = 0; i < 64, RoomList[i].IPAddress != 0 ; i++)
623 {
624 int IP = ntohl(RoomList[i].IPAddress);
625 DDrConsole_PrintF("Room %i %s IP %s Port %hi Players %hi",
626 i,
627 sRoomNames[ntohs(RoomList[i].RoomIndex)],
628 inet_ntoa(*(in_addr*)&IP),
629 ntohs(RoomList[i].Port),
630 ntohs(RoomList[i].PlayerCount)
631 );
632 }
633
634 closesocket(Marius_Socket);
635
636 MSNet_Room_Join( 1, RoomToken );
637
638
639 }
640 return 0;
641}
642
643bool MSNet_Login(char* username, char* password)
644{
645 sprintf_s(MariusLogin, 32, "%s", username);
646 sprintf_s(MariusPassword, 16, "%s", password);
647 CreateThread(NULL, 0, MSNet_Handler, NULL, 0, 0);
648
649 return 0;
650}
651
Note: See TracBrowser for help on using the repository browser.