source: Daodan/MSVC/Mariusnet.c @ 588

Last change on this file since 588 was 588, checked in by gumby, 12 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.