Annotation of quake1/net_dgrm.c, revision 1.1

1.1     ! root        1: // net_dgrm.c
        !             2: 
        !             3: // This is enables a simple IP banning mechanism
        !             4: #define BAN_TEST
        !             5: 
        !             6: #ifdef BAN_TEST
        !             7: #if defined(_WIN32)
        !             8: #include <windows.h>
        !             9: #elif defined (NeXT)
        !            10: #include <sys/socket.h>
        !            11: #include <arpa/inet.h>
        !            12: #else
        !            13: #define AF_INET                2       /* internet */
        !            14: struct in_addr
        !            15: {
        !            16:        union
        !            17:        {
        !            18:                struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
        !            19:                struct { unsigned short s_w1,s_w2; } S_un_w;
        !            20:                unsigned long S_addr;
        !            21:        } S_un;
        !            22: };
        !            23: #define        s_addr  S_un.S_addr     /* can be used for most tcp & ip code */
        !            24: struct sockaddr_in
        !            25: {
        !            26:     short                      sin_family;
        !            27:     unsigned short     sin_port;
        !            28:        struct in_addr  sin_addr;
        !            29:     char                       sin_zero[8];
        !            30: };
        !            31: char *inet_ntoa(struct in_addr in);
        !            32: unsigned long inet_addr(const char *cp);
        !            33: #endif
        !            34: #endif // BAN_TEST
        !            35: 
        !            36: #include "quakedef.h"
        !            37: #include "net_dgrm.h"
        !            38: 
        !            39: // these two macros are to make the code more readable
        !            40: #define sfunc  net_landrivers[sock->landriver]
        !            41: #define dfunc  net_landrivers[net_landriverlevel]
        !            42: 
        !            43: static int net_landriverlevel;
        !            44: 
        !            45: /* statistic counters */
        !            46: int    packetsSent = 0;
        !            47: int    packetsReSent = 0;
        !            48: int packetsReceived = 0;
        !            49: int receivedDuplicateCount = 0;
        !            50: int shortPacketCount = 0;
        !            51: int droppedDatagrams;
        !            52: 
        !            53: static int myDriverLevel;
        !            54: 
        !            55: struct
        !            56: {
        !            57:        unsigned int    length;
        !            58:        unsigned int    sequence;
        !            59:        byte                    data[MAX_DATAGRAM];
        !            60: } packetBuffer;
        !            61: 
        !            62: extern int m_return_state;
        !            63: extern int m_state;
        !            64: extern qboolean m_return_onerror;
        !            65: extern char m_return_reason[32];
        !            66: 
        !            67: 
        !            68: #ifdef DEBUG
        !            69: char *StrAddr (struct qsockaddr *addr)
        !            70: {
        !            71:        static char buf[34];
        !            72:        byte *p = (byte *)addr;
        !            73:        int n;
        !            74: 
        !            75:        for (n = 0; n < 16; n++)
        !            76:                sprintf (buf + n * 2, "%02x", *p++);
        !            77:        return buf;
        !            78: }
        !            79: #endif
        !            80: 
        !            81: 
        !            82: #ifdef BAN_TEST
        !            83: unsigned long banAddr = 0x00000000;
        !            84: unsigned long banMask = 0xffffffff;
        !            85: 
        !            86: void NET_Ban_f (void)
        !            87: {
        !            88:        char    addrStr [32];
        !            89:        char    maskStr [32];
        !            90:        void    (*print) (char *fmt, ...);
        !            91: 
        !            92:        if (cmd_source == src_command)
        !            93:        {
        !            94:                if (!sv.active)
        !            95:                {
        !            96:                        Cmd_ForwardToServer ();
        !            97:                        return;
        !            98:                }
        !            99:                print = Con_Printf;
        !           100:        }
        !           101:        else
        !           102:        {
        !           103:                if (pr_global_struct->deathmatch && !host_client->privileged)
        !           104:                        return;
        !           105:                print = SV_ClientPrintf;
        !           106:        }
        !           107: 
        !           108:        switch (Cmd_Argc ())
        !           109:        {
        !           110:                case 1:
        !           111:                        if (((struct in_addr *)&banAddr)->s_addr)
        !           112:                        {
        !           113:                                Q_strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr));
        !           114:                                Q_strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask));
        !           115:                                print("Banning %s [%s]\n", addrStr, maskStr);
        !           116:                        }
        !           117:                        else
        !           118:                                print("Banning not active\n");
        !           119:                        break;
        !           120: 
        !           121:                case 2:
        !           122:                        if (Q_strcasecmp(Cmd_Argv(1), "off") == 0)
        !           123:                                banAddr = 0x00000000;
        !           124:                        else
        !           125:                                banAddr = inet_addr(Cmd_Argv(1));
        !           126:                        banMask = 0xffffffff;
        !           127:                        break;
        !           128: 
        !           129:                case 3:
        !           130:                        banAddr = inet_addr(Cmd_Argv(1));
        !           131:                        banMask = inet_addr(Cmd_Argv(2));
        !           132:                        break;
        !           133: 
        !           134:                default:
        !           135:                        print("BAN ip_address [mask]\n");
        !           136:                        break;
        !           137:        }
        !           138: }
        !           139: #endif
        !           140: 
        !           141: 
        !           142: int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data)
        !           143: {
        !           144:        unsigned int    packetLen;
        !           145:        unsigned int    dataLen;
        !           146:        unsigned int    eom;
        !           147: 
        !           148: #ifdef DEBUG
        !           149:        if (data->cursize == 0)
        !           150:                Sys_Error("Datagram_SendMessage: zero length message\n");
        !           151: 
        !           152:        if (data->cursize > NET_MAXMESSAGE)
        !           153:                Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize);
        !           154: 
        !           155:        if (sock->canSend == false)
        !           156:                Sys_Error("SendMessage: called with canSend == false\n");
        !           157: #endif
        !           158: 
        !           159:        Q_memcpy(sock->sendMessage, data->data, data->cursize);
        !           160:        sock->sendMessageLength = data->cursize;
        !           161: 
        !           162:        if (data->cursize <= MAX_DATAGRAM)
        !           163:        {
        !           164:                dataLen = data->cursize;
        !           165:                eom = NETFLAG_EOM;
        !           166:        }
        !           167:        else
        !           168:        {
        !           169:                dataLen = MAX_DATAGRAM;
        !           170:                eom = 0;
        !           171:        }
        !           172:        packetLen = NET_HEADERSIZE + dataLen;
        !           173: 
        !           174:        packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
        !           175:        packetBuffer.sequence = BigLong(sock->sendSequence++);
        !           176:        Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
        !           177: 
        !           178:        sock->canSend = false;
        !           179: 
        !           180:        if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
        !           181:                return -1;
        !           182: 
        !           183:        sock->lastSendTime = net_time;
        !           184:        packetsSent++;
        !           185:        return 1;
        !           186: }
        !           187: 
        !           188: 
        !           189: int SendMessageNext (qsocket_t *sock)
        !           190: {
        !           191:        unsigned int    packetLen;
        !           192:        unsigned int    dataLen;
        !           193:        unsigned int    eom;
        !           194: 
        !           195:        if (sock->sendMessageLength <= MAX_DATAGRAM)
        !           196:        {
        !           197:                dataLen = sock->sendMessageLength;
        !           198:                eom = NETFLAG_EOM;
        !           199:        }
        !           200:        else
        !           201:        {
        !           202:                dataLen = MAX_DATAGRAM;
        !           203:                eom = 0;
        !           204:        }
        !           205:        packetLen = NET_HEADERSIZE + dataLen;
        !           206: 
        !           207:        packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
        !           208:        packetBuffer.sequence = BigLong(sock->sendSequence++);
        !           209:        Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
        !           210: 
        !           211:        sock->sendNext = false;
        !           212: 
        !           213:        if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
        !           214:                return -1;
        !           215: 
        !           216:        sock->lastSendTime = net_time;
        !           217:        packetsSent++;
        !           218:        return 1;
        !           219: }
        !           220: 
        !           221: 
        !           222: int ReSendMessage (qsocket_t *sock)
        !           223: {
        !           224:        unsigned int    packetLen;
        !           225:        unsigned int    dataLen;
        !           226:        unsigned int    eom;
        !           227: 
        !           228:        if (sock->sendMessageLength <= MAX_DATAGRAM)
        !           229:        {
        !           230:                dataLen = sock->sendMessageLength;
        !           231:                eom = NETFLAG_EOM;
        !           232:        }
        !           233:        else
        !           234:        {
        !           235:                dataLen = MAX_DATAGRAM;
        !           236:                eom = 0;
        !           237:        }
        !           238:        packetLen = NET_HEADERSIZE + dataLen;
        !           239: 
        !           240:        packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
        !           241:        packetBuffer.sequence = BigLong(sock->sendSequence - 1);
        !           242:        Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
        !           243: 
        !           244:        sock->sendNext = false;
        !           245: 
        !           246:        if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
        !           247:                return -1;
        !           248: 
        !           249:        sock->lastSendTime = net_time;
        !           250:        packetsReSent++;
        !           251:        return 1;
        !           252: }
        !           253: 
        !           254: 
        !           255: qboolean Datagram_CanSendMessage (qsocket_t *sock)
        !           256: {
        !           257:        if (sock->sendNext)
        !           258:                SendMessageNext (sock);
        !           259: 
        !           260:        return sock->canSend;
        !           261: }
        !           262: 
        !           263: 
        !           264: qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
        !           265: {
        !           266:        return true;
        !           267: }
        !           268: 
        !           269: 
        !           270: int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
        !           271: {
        !           272:        int     packetLen;
        !           273: 
        !           274: #ifdef DEBUG
        !           275:        if (data->cursize == 0)
        !           276:                Sys_Error("Datagram_SendUnreliableMessage: zero length message\n");
        !           277: 
        !           278:        if (data->cursize > MAX_DATAGRAM)
        !           279:                Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize);
        !           280: #endif
        !           281: 
        !           282:        packetLen = NET_HEADERSIZE + data->cursize;
        !           283: 
        !           284:        packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE);
        !           285:        packetBuffer.sequence = BigLong(sock->unreliableSendSequence++);
        !           286:        Q_memcpy (packetBuffer.data, data->data, data->cursize);
        !           287: 
        !           288:        if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
        !           289:                return -1;
        !           290: 
        !           291:        packetsSent++;
        !           292:        return 1;
        !           293: }
        !           294: 
        !           295: 
        !           296: int    Datagram_GetMessage (qsocket_t *sock)
        !           297: {
        !           298:        unsigned int    length;
        !           299:        unsigned int    flags;
        !           300:        int                             ret = 0;
        !           301:        struct qsockaddr readaddr;
        !           302:        unsigned int    sequence;
        !           303:        unsigned int    count;
        !           304: 
        !           305:        if (!sock->canSend)
        !           306:                if ((net_time - sock->lastSendTime) > 1.0)
        !           307:                        ReSendMessage (sock);
        !           308: 
        !           309:        while(1)
        !           310:        {       
        !           311:                length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr);
        !           312: 
        !           313: //     if ((rand() & 255) > 220)
        !           314: //             continue;
        !           315: 
        !           316:                if (length == 0)
        !           317:                        break;
        !           318: 
        !           319:                if (length == -1)
        !           320:                {
        !           321:                        Con_Printf("Read error\n");
        !           322:                        return -1;
        !           323:                }
        !           324: 
        !           325:                if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0)
        !           326:                {
        !           327: #ifdef DEBUG
        !           328:                        Con_DPrintf("Forged packet received\n");
        !           329:                        Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
        !           330:                        Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
        !           331: #endif
        !           332:                        continue;
        !           333:                }
        !           334: 
        !           335:                if (length < NET_HEADERSIZE)
        !           336:                {
        !           337:                        shortPacketCount++;
        !           338:                        continue;
        !           339:                }
        !           340: 
        !           341:                length = BigLong(packetBuffer.length);
        !           342:                flags = length & (~NETFLAG_LENGTH_MASK);
        !           343:                length &= NETFLAG_LENGTH_MASK;
        !           344: 
        !           345:                if (flags & NETFLAG_CTL)
        !           346:                        continue;
        !           347: 
        !           348:                sequence = BigLong(packetBuffer.sequence);
        !           349:                packetsReceived++;
        !           350: 
        !           351:                if (flags & NETFLAG_UNRELIABLE)
        !           352:                {
        !           353:                        if (sequence < sock->unreliableReceiveSequence)
        !           354:                        {
        !           355:                                Con_DPrintf("Got a stale datagram\n");
        !           356:                                ret = 0;
        !           357:                                break;
        !           358:                        }
        !           359:                        if (sequence != sock->unreliableReceiveSequence)
        !           360:                        {
        !           361:                                count = sequence - sock->unreliableReceiveSequence;
        !           362:                                droppedDatagrams += count;
        !           363:                                Con_DPrintf("Dropped %u datagram(s)\n", count);
        !           364:                        }
        !           365:                        sock->unreliableReceiveSequence = sequence + 1;
        !           366: 
        !           367:                        length -= NET_HEADERSIZE;
        !           368: 
        !           369:                        SZ_Clear (&net_message);
        !           370:                        SZ_Write (&net_message, packetBuffer.data, length);
        !           371: 
        !           372:                        ret = 2;
        !           373:                        break;
        !           374:                }
        !           375: 
        !           376:                if (flags & NETFLAG_ACK)
        !           377:                {
        !           378:                        if (sequence != (sock->sendSequence - 1))
        !           379:                        {
        !           380:                                Con_DPrintf("Stale ACK received\n");
        !           381:                                continue;
        !           382:                        }
        !           383:                        if (sequence == sock->ackSequence)
        !           384:                        {
        !           385:                                sock->ackSequence++;
        !           386:                                if (sock->ackSequence != sock->sendSequence)
        !           387:                                        Con_DPrintf("ack sequencing error\n");
        !           388:                        }
        !           389:                        else
        !           390:                        {
        !           391:                                Con_DPrintf("Duplicate ACK received\n");
        !           392:                                continue;
        !           393:                        }
        !           394:                        sock->sendMessageLength -= MAX_DATAGRAM;
        !           395:                        if (sock->sendMessageLength > 0)
        !           396:                        {
        !           397:                                Q_memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength);
        !           398:                                sock->sendNext = true;
        !           399:                        }
        !           400:                        else
        !           401:                        {
        !           402:                                sock->sendMessageLength = 0;
        !           403:                                sock->canSend = true;
        !           404:                        }
        !           405:                        continue;
        !           406:                }
        !           407: 
        !           408:                if (flags & NETFLAG_DATA)
        !           409:                {
        !           410:                        packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
        !           411:                        packetBuffer.sequence = BigLong(sequence);
        !           412:                        sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr);
        !           413: 
        !           414:                        if (sequence != sock->receiveSequence)
        !           415:                        {
        !           416:                                receivedDuplicateCount++;
        !           417:                                continue;
        !           418:                        }
        !           419:                        sock->receiveSequence++;
        !           420: 
        !           421:                        length -= NET_HEADERSIZE;
        !           422: 
        !           423:                        if (flags & NETFLAG_EOM)
        !           424:                        {
        !           425:                                SZ_Clear(&net_message);
        !           426:                                SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength);
        !           427:                                SZ_Write(&net_message, packetBuffer.data, length);
        !           428:                                sock->receiveMessageLength = 0;
        !           429: 
        !           430:                                ret = 1;
        !           431:                                break;
        !           432:                        }
        !           433: 
        !           434:                        Q_memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
        !           435:                        sock->receiveMessageLength += length;
        !           436:                        continue;
        !           437:                }
        !           438:        }
        !           439: 
        !           440:        if (sock->sendNext)
        !           441:                SendMessageNext (sock);
        !           442: 
        !           443:        return ret;
        !           444: }
        !           445: 
        !           446: 
        !           447: void PrintStats(qsocket_t *s)
        !           448: {
        !           449:        Con_Printf("canSend = %4u   \n", s->canSend);
        !           450:        Con_Printf("sendSeq = %4u   ", s->sendSequence);
        !           451:        Con_Printf("recvSeq = %4u   \n", s->receiveSequence);
        !           452:        Con_Printf("\n");
        !           453: }
        !           454: 
        !           455: void NET_Stats_f (void)
        !           456: {
        !           457:        qsocket_t       *s;
        !           458: 
        !           459:        if (Cmd_Argc () == 1)
        !           460:        {
        !           461:                Con_Printf("unreliable messages sent   = %i\n", unreliableMessagesSent);
        !           462:                Con_Printf("unreliable messages recv   = %i\n", unreliableMessagesReceived);
        !           463:                Con_Printf("reliable messages sent     = %i\n", messagesSent);
        !           464:                Con_Printf("reliable messages received = %i\n", messagesReceived);
        !           465:                Con_Printf("packetsSent                = %i\n", packetsSent);
        !           466:                Con_Printf("packetsReSent              = %i\n", packetsReSent);
        !           467:                Con_Printf("packetsReceived            = %i\n", packetsReceived);
        !           468:                Con_Printf("receivedDuplicateCount     = %i\n", receivedDuplicateCount);
        !           469:                Con_Printf("shortPacketCount           = %i\n", shortPacketCount);
        !           470:                Con_Printf("droppedDatagrams           = %i\n", droppedDatagrams);
        !           471:        }
        !           472:        else if (Q_strcmp(Cmd_Argv(1), "*") == 0)
        !           473:        {
        !           474:                for (s = net_activeSockets; s; s = s->next)
        !           475:                        PrintStats(s);
        !           476:                for (s = net_freeSockets; s; s = s->next)
        !           477:                        PrintStats(s);
        !           478:        }
        !           479:        else
        !           480:        {
        !           481:                for (s = net_activeSockets; s; s = s->next)
        !           482:                        if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
        !           483:                                break;
        !           484:                if (s == NULL)
        !           485:                        for (s = net_freeSockets; s; s = s->next)
        !           486:                                if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
        !           487:                                        break;
        !           488:                if (s == NULL)
        !           489:                        return;
        !           490:                PrintStats(s);
        !           491:        }
        !           492: }
        !           493: 
        !           494: 
        !           495: static qboolean testInProgress = false;
        !           496: static int             testPollCount;
        !           497: static int             testDriver;
        !           498: static int             testSocket;
        !           499: 
        !           500: static void Test_Poll(void);
        !           501: PollProcedure  testPollProcedure = {NULL, 0.0, Test_Poll};
        !           502: 
        !           503: static void Test_Poll(void)
        !           504: {
        !           505:        struct qsockaddr clientaddr;
        !           506:        int             control;
        !           507:        int             len;
        !           508:        char    name[32];
        !           509:        char    address[64];
        !           510:        int             colors;
        !           511:        int             frags;
        !           512:        int             connectTime;
        !           513:        byte    playerNumber;
        !           514: 
        !           515:        net_landriverlevel = testDriver;
        !           516: 
        !           517:        while (1)
        !           518:        {
        !           519:                len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
        !           520:                if (len < sizeof(int))
        !           521:                        break;
        !           522: 
        !           523:                net_message.cursize = len;
        !           524: 
        !           525:                MSG_BeginReading ();
        !           526:                control = BigLong(*((int *)net_message.data));
        !           527:                MSG_ReadLong();
        !           528:                if (control == -1)
        !           529:                        break;
        !           530:                if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
        !           531:                        break;
        !           532:                if ((control & NETFLAG_LENGTH_MASK) != len)
        !           533:                        break;
        !           534: 
        !           535:                if (MSG_ReadByte() != CCREP_PLAYER_INFO)
        !           536:                        Sys_Error("Unexpected repsonse to Player Info request\n");
        !           537: 
        !           538:                playerNumber = MSG_ReadByte();
        !           539:                Q_strcpy(name, MSG_ReadString());
        !           540:                colors = MSG_ReadLong();
        !           541:                frags = MSG_ReadLong();
        !           542:                connectTime = MSG_ReadLong();
        !           543:                Q_strcpy(address, MSG_ReadString());
        !           544: 
        !           545:                Con_Printf("%s\n  frags:%3i  colors:%u %u  time:%u\n  %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
        !           546:        }
        !           547: 
        !           548:        testPollCount--;
        !           549:        if (testPollCount)
        !           550:        {
        !           551:                SchedulePollProcedure(&testPollProcedure, 0.1);
        !           552:        }
        !           553:        else
        !           554:        {
        !           555:                dfunc.CloseSocket(testSocket);
        !           556:                testInProgress = false;
        !           557:        }
        !           558: }
        !           559: 
        !           560: static void Test_f (void)
        !           561: {
        !           562:        char    *host;
        !           563:        int             n;
        !           564:        int             max = MAX_SCOREBOARD;
        !           565:        struct qsockaddr sendaddr;
        !           566: 
        !           567:        if (testInProgress)
        !           568:                return;
        !           569: 
        !           570:        host = Cmd_Argv (1);
        !           571: 
        !           572:        if (host && hostCacheCount)
        !           573:        {
        !           574:                for (n = 0; n < hostCacheCount; n++)
        !           575:                        if (Q_strcasecmp (host, hostcache[n].name) == 0)
        !           576:                        {
        !           577:                                if (hostcache[n].driver != myDriverLevel)
        !           578:                                        continue;
        !           579:                                net_landriverlevel = hostcache[n].ldriver;
        !           580:                                max = hostcache[n].maxusers;
        !           581:                                Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
        !           582:                                break;
        !           583:                        }
        !           584:                if (n < hostCacheCount)
        !           585:                        goto JustDoIt;
        !           586:        }
        !           587: 
        !           588:        for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
        !           589:        {
        !           590:                if (!net_landrivers[net_landriverlevel].initialized)
        !           591:                        continue;
        !           592: 
        !           593:                // see if we can resolve the host name
        !           594:                if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
        !           595:                        break;
        !           596:        }
        !           597:        if (net_landriverlevel == net_numlandrivers)
        !           598:                return;
        !           599: 
        !           600: JustDoIt:
        !           601:        testSocket = dfunc.OpenSocket(0);
        !           602:        if (testSocket == -1)
        !           603:                return;
        !           604: 
        !           605:        testInProgress = true;
        !           606:        testPollCount = 20;
        !           607:        testDriver = net_landriverlevel;
        !           608: 
        !           609:        for (n = 0; n < max; n++)
        !           610:        {
        !           611:                SZ_Clear(&net_message);
        !           612:                // save space for the header, filled in later
        !           613:                MSG_WriteLong(&net_message, 0);
        !           614:                MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
        !           615:                MSG_WriteByte(&net_message, n);
        !           616:                *((int *)net_message.data) = BigLong(NETFLAG_CTL |      (net_message.cursize & NETFLAG_LENGTH_MASK));
        !           617:                dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
        !           618:        }
        !           619:        SZ_Clear(&net_message);
        !           620:        SchedulePollProcedure(&testPollProcedure, 0.1);
        !           621: }
        !           622: 
        !           623: 
        !           624: static qboolean test2InProgress = false;
        !           625: static int             test2Driver;
        !           626: static int             test2Socket;
        !           627: 
        !           628: static void Test2_Poll(void);
        !           629: PollProcedure  test2PollProcedure = {NULL, 0.0, Test2_Poll};
        !           630: 
        !           631: static void Test2_Poll(void)
        !           632: {
        !           633:        struct qsockaddr clientaddr;
        !           634:        int             control;
        !           635:        int             len;
        !           636:        char    name[32];
        !           637:        char    value[32];
        !           638: 
        !           639:        net_landriverlevel = test2Driver;
        !           640:        name[0] = 0;
        !           641: 
        !           642:        len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
        !           643:        if (len < sizeof(int))
        !           644:                goto Reschedule;
        !           645: 
        !           646:        net_message.cursize = len;
        !           647: 
        !           648:        MSG_BeginReading ();
        !           649:        control = BigLong(*((int *)net_message.data));
        !           650:        MSG_ReadLong();
        !           651:        if (control == -1)
        !           652:                goto Error;
        !           653:        if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
        !           654:                goto Error;
        !           655:        if ((control & NETFLAG_LENGTH_MASK) != len)
        !           656:                goto Error;
        !           657: 
        !           658:        if (MSG_ReadByte() != CCREP_RULE_INFO)
        !           659:                goto Error;
        !           660: 
        !           661:        Q_strcpy(name, MSG_ReadString());
        !           662:        if (name[0] == 0)
        !           663:                goto Done;
        !           664:        Q_strcpy(value, MSG_ReadString());
        !           665: 
        !           666:        Con_Printf("%-16.16s  %-16.16s\n", name, value);
        !           667: 
        !           668:        SZ_Clear(&net_message);
        !           669:        // save space for the header, filled in later
        !           670:        MSG_WriteLong(&net_message, 0);
        !           671:        MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
        !           672:        MSG_WriteString(&net_message, name);
        !           673:        *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !           674:        dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
        !           675:        SZ_Clear(&net_message);
        !           676: 
        !           677: Reschedule:
        !           678:        SchedulePollProcedure(&test2PollProcedure, 0.05);
        !           679:        return;
        !           680: 
        !           681: Error:
        !           682:        Con_Printf("Unexpected repsonse to Rule Info request\n");
        !           683: Done:
        !           684:        dfunc.CloseSocket(test2Socket);
        !           685:        test2InProgress = false;
        !           686:        return;
        !           687: }
        !           688: 
        !           689: static void Test2_f (void)
        !           690: {
        !           691:        char    *host;
        !           692:        int             n;
        !           693:        struct qsockaddr sendaddr;
        !           694: 
        !           695:        if (test2InProgress)
        !           696:                return;
        !           697: 
        !           698:        host = Cmd_Argv (1);
        !           699: 
        !           700:        if (host && hostCacheCount)
        !           701:        {
        !           702:                for (n = 0; n < hostCacheCount; n++)
        !           703:                        if (Q_strcasecmp (host, hostcache[n].name) == 0)
        !           704:                        {
        !           705:                                if (hostcache[n].driver != myDriverLevel)
        !           706:                                        continue;
        !           707:                                net_landriverlevel = hostcache[n].ldriver;
        !           708:                                Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
        !           709:                                break;
        !           710:                        }
        !           711:                if (n < hostCacheCount)
        !           712:                        goto JustDoIt;
        !           713:        }
        !           714: 
        !           715:        for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
        !           716:        {
        !           717:                if (!net_landrivers[net_landriverlevel].initialized)
        !           718:                        continue;
        !           719: 
        !           720:                // see if we can resolve the host name
        !           721:                if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
        !           722:                        break;
        !           723:        }
        !           724:        if (net_landriverlevel == net_numlandrivers)
        !           725:                return;
        !           726: 
        !           727: JustDoIt:
        !           728:        test2Socket = dfunc.OpenSocket(0);
        !           729:        if (test2Socket == -1)
        !           730:                return;
        !           731: 
        !           732:        test2InProgress = true;
        !           733:        test2Driver = net_landriverlevel;
        !           734: 
        !           735:        SZ_Clear(&net_message);
        !           736:        // save space for the header, filled in later
        !           737:        MSG_WriteLong(&net_message, 0);
        !           738:        MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
        !           739:        MSG_WriteString(&net_message, "");
        !           740:        *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !           741:        dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
        !           742:        SZ_Clear(&net_message);
        !           743:        SchedulePollProcedure(&test2PollProcedure, 0.05);
        !           744: }
        !           745: 
        !           746: 
        !           747: int Datagram_Init (void)
        !           748: {
        !           749:        int i;
        !           750:        int csock;
        !           751: 
        !           752:        myDriverLevel = net_driverlevel;
        !           753:        Cmd_AddCommand ("net_stats", NET_Stats_f);
        !           754: 
        !           755:        if (COM_CheckParm("-nolan"))
        !           756:                return -1;
        !           757: 
        !           758:        for (i = 0; i < net_numlandrivers; i++)
        !           759:                {
        !           760:                csock = net_landrivers[i].Init ();
        !           761:                if (csock == -1)
        !           762:                        continue;
        !           763:                net_landrivers[i].initialized = true;
        !           764:                net_landrivers[i].controlSock = csock;
        !           765:                }
        !           766: 
        !           767: #ifdef BAN_TEST
        !           768:        Cmd_AddCommand ("ban", NET_Ban_f);
        !           769: #endif
        !           770:        Cmd_AddCommand ("test", Test_f);
        !           771:        Cmd_AddCommand ("test2", Test2_f);
        !           772: 
        !           773:        return 0;
        !           774: }
        !           775: 
        !           776: 
        !           777: void Datagram_Shutdown (void)
        !           778: {
        !           779:        int i;
        !           780: 
        !           781: //
        !           782: // shutdown the lan drivers
        !           783: //
        !           784:        for (i = 0; i < net_numlandrivers; i++)
        !           785:        {
        !           786:                if (net_landrivers[i].initialized)
        !           787:                {
        !           788:                        net_landrivers[i].Shutdown ();
        !           789:                        net_landrivers[i].initialized = false;
        !           790:                }
        !           791:        }
        !           792: }
        !           793: 
        !           794: 
        !           795: void Datagram_Close (qsocket_t *sock)
        !           796: {
        !           797:        sfunc.CloseSocket(sock->socket);
        !           798: }
        !           799: 
        !           800: 
        !           801: void Datagram_Listen (qboolean state)
        !           802: {
        !           803:        int i;
        !           804: 
        !           805:        for (i = 0; i < net_numlandrivers; i++)
        !           806:                if (net_landrivers[i].initialized)
        !           807:                        net_landrivers[i].Listen (state);
        !           808: }
        !           809: 
        !           810: 
        !           811: static qsocket_t *_Datagram_CheckNewConnections (void)
        !           812: {
        !           813:        struct qsockaddr clientaddr;
        !           814:        struct qsockaddr newaddr;
        !           815:        int                     newsock;
        !           816:        int                     acceptsock;
        !           817:        qsocket_t       *sock;
        !           818:        qsocket_t       *s;
        !           819:        int                     len;
        !           820:        int                     command;
        !           821:        int                     control;
        !           822:        int                     ret;
        !           823: 
        !           824:        acceptsock = dfunc.CheckNewConnections();
        !           825:        if (acceptsock == -1)
        !           826:                return NULL;
        !           827: 
        !           828:        SZ_Clear(&net_message);
        !           829: 
        !           830:        len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
        !           831:        if (len < sizeof(int))
        !           832:                return NULL;
        !           833:        net_message.cursize = len;
        !           834: 
        !           835:        MSG_BeginReading ();
        !           836:        control = BigLong(*((int *)net_message.data));
        !           837:        MSG_ReadLong();
        !           838:        if (control == -1)
        !           839:                return NULL;
        !           840:        if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
        !           841:                return NULL;
        !           842:        if ((control & NETFLAG_LENGTH_MASK) != len)
        !           843:                return NULL;
        !           844: 
        !           845:        command = MSG_ReadByte();
        !           846:        if (command == CCREQ_SERVER_INFO)
        !           847:        {
        !           848:                if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
        !           849:                        return NULL;
        !           850: 
        !           851:                SZ_Clear(&net_message);
        !           852:                // save space for the header, filled in later
        !           853:                MSG_WriteLong(&net_message, 0);
        !           854:                MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
        !           855:                dfunc.GetSocketAddr(acceptsock, &newaddr);
        !           856:                MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
        !           857:                MSG_WriteString(&net_message, hostname.string);
        !           858:                MSG_WriteString(&net_message, sv.name);
        !           859:                MSG_WriteByte(&net_message, net_activeconnections);
        !           860:                MSG_WriteByte(&net_message, svs.maxclients);
        !           861:                MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
        !           862:                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !           863:                dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        !           864:                SZ_Clear(&net_message);
        !           865:                return NULL;
        !           866:        }
        !           867: 
        !           868:        if (command == CCREQ_PLAYER_INFO)
        !           869:        {
        !           870:                int                     playerNumber;
        !           871:                int                     activeNumber;
        !           872:                int                     clientNumber;
        !           873:                client_t        *client;
        !           874:                
        !           875:                playerNumber = MSG_ReadByte();
        !           876:                activeNumber = -1;
        !           877:                for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
        !           878:                {
        !           879:                        if (client->active)
        !           880:                        {
        !           881:                                activeNumber++;
        !           882:                                if (activeNumber == playerNumber)
        !           883:                                        break;
        !           884:                        }
        !           885:                }
        !           886:                if (clientNumber == svs.maxclients)
        !           887:                        return NULL;
        !           888: 
        !           889:                SZ_Clear(&net_message);
        !           890:                // save space for the header, filled in later
        !           891:                MSG_WriteLong(&net_message, 0);
        !           892:                MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
        !           893:                MSG_WriteByte(&net_message, playerNumber);
        !           894:                MSG_WriteString(&net_message, client->name);
        !           895:                MSG_WriteLong(&net_message, client->colors);
        !           896:                MSG_WriteLong(&net_message, (int)client->edict->v.frags);
        !           897:                MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
        !           898:                MSG_WriteString(&net_message, client->netconnection->address);
        !           899:                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !           900:                dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        !           901:                SZ_Clear(&net_message);
        !           902: 
        !           903:                return NULL;
        !           904:        }
        !           905: 
        !           906:        if (command == CCREQ_RULE_INFO)
        !           907:        {
        !           908:                char    *prevCvarName;
        !           909:                cvar_t  *var;
        !           910: 
        !           911:                // find the search start location
        !           912:                prevCvarName = MSG_ReadString();
        !           913:                if (*prevCvarName)
        !           914:                {
        !           915:                        var = Cvar_FindVar (prevCvarName);
        !           916:                        if (!var)
        !           917:                                return NULL;
        !           918:                        var = var->next;
        !           919:                }
        !           920:                else
        !           921:                        var = cvar_vars;
        !           922: 
        !           923:                // search for the next server cvar
        !           924:                while (var)
        !           925:                {
        !           926:                        if (var->server)
        !           927:                                break;
        !           928:                        var = var->next;
        !           929:                }
        !           930: 
        !           931:                // send the response
        !           932: 
        !           933:                SZ_Clear(&net_message);
        !           934:                // save space for the header, filled in later
        !           935:                MSG_WriteLong(&net_message, 0);
        !           936:                MSG_WriteByte(&net_message, CCREP_RULE_INFO);
        !           937:                if (var)
        !           938:                {
        !           939:                        MSG_WriteString(&net_message, var->name);
        !           940:                        MSG_WriteString(&net_message, var->string);
        !           941:                }
        !           942:                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !           943:                dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        !           944:                SZ_Clear(&net_message);
        !           945: 
        !           946:                return NULL;
        !           947:        }
        !           948: 
        !           949:        if (command != CCREQ_CONNECT)
        !           950:                return NULL;
        !           951: 
        !           952:        if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
        !           953:                return NULL;
        !           954: 
        !           955:        if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
        !           956:        {
        !           957:                SZ_Clear(&net_message);
        !           958:                // save space for the header, filled in later
        !           959:                MSG_WriteLong(&net_message, 0);
        !           960:                MSG_WriteByte(&net_message, CCREP_REJECT);
        !           961:                MSG_WriteString(&net_message, "Incompatible version.\n");
        !           962:                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !           963:                dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        !           964:                SZ_Clear(&net_message);
        !           965:                return NULL;
        !           966:        }
        !           967: 
        !           968: #ifdef BAN_TEST
        !           969:        // check for a ban
        !           970:        if (clientaddr.sa_family == AF_INET)
        !           971:        {
        !           972:                unsigned long testAddr;
        !           973:                testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
        !           974:                if ((testAddr & banMask) == banAddr)
        !           975:                {
        !           976:                        SZ_Clear(&net_message);
        !           977:                        // save space for the header, filled in later
        !           978:                        MSG_WriteLong(&net_message, 0);
        !           979:                        MSG_WriteByte(&net_message, CCREP_REJECT);
        !           980:                        MSG_WriteString(&net_message, "You have been banned.\n");
        !           981:                        *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !           982:                        dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        !           983:                        SZ_Clear(&net_message);
        !           984:                        return NULL;
        !           985:                }
        !           986:        }
        !           987: #endif
        !           988: 
        !           989:        // see if this guy is already connected
        !           990:        for (s = net_activeSockets; s; s = s->next)
        !           991:        {
        !           992:                if (s->driver != net_driverlevel)
        !           993:                        continue;
        !           994:                ret = dfunc.AddrCompare(&clientaddr, &s->addr);
        !           995:                if (ret >= 0)
        !           996:                {
        !           997:                        // is this a duplicate connection reqeust?
        !           998:                        if (ret == 0 && net_time - s->connecttime < 2.0)
        !           999:                        {
        !          1000:                                // yes, so send a duplicate reply
        !          1001:                                SZ_Clear(&net_message);
        !          1002:                                // save space for the header, filled in later
        !          1003:                                MSG_WriteLong(&net_message, 0);
        !          1004:                                MSG_WriteByte(&net_message, CCREP_ACCEPT);
        !          1005:                                dfunc.GetSocketAddr(s->socket, &newaddr);
        !          1006:                                MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
        !          1007:                                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !          1008:                                dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        !          1009:                                SZ_Clear(&net_message);
        !          1010:                                return NULL;
        !          1011:                        }
        !          1012:                        // it's somebody coming back in from a crash/disconnect
        !          1013:                        // so close the old qsocket and let their retry get them back in
        !          1014:                        NET_Close(s);
        !          1015:                        return NULL;
        !          1016:                }
        !          1017:        }
        !          1018: 
        !          1019:        // allocate a QSocket
        !          1020:        sock = NET_NewQSocket ();
        !          1021:        if (sock == NULL)
        !          1022:        {
        !          1023:                // no room; try to let him know
        !          1024:                SZ_Clear(&net_message);
        !          1025:                // save space for the header, filled in later
        !          1026:                MSG_WriteLong(&net_message, 0);
        !          1027:                MSG_WriteByte(&net_message, CCREP_REJECT);
        !          1028:                MSG_WriteString(&net_message, "Server is full.\n");
        !          1029:                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !          1030:                dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        !          1031:                SZ_Clear(&net_message);
        !          1032:                return NULL;
        !          1033:        }
        !          1034: 
        !          1035:        // allocate a network socket
        !          1036:        newsock = dfunc.OpenSocket(0);
        !          1037:        if (newsock == -1)
        !          1038:        {
        !          1039:                NET_FreeQSocket(sock);
        !          1040:                return NULL;
        !          1041:        }
        !          1042: 
        !          1043:        // connect to the client
        !          1044:        if (dfunc.Connect (newsock, &clientaddr) == -1)
        !          1045:        {
        !          1046:                dfunc.CloseSocket(newsock);
        !          1047:                NET_FreeQSocket(sock);
        !          1048:                return NULL;
        !          1049:        }
        !          1050: 
        !          1051:        // everything is allocated, just fill in the details    
        !          1052:        sock->socket = newsock;
        !          1053:        sock->landriver = net_landriverlevel;
        !          1054:        sock->addr = clientaddr;
        !          1055:        Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr));
        !          1056: 
        !          1057:        // send him back the info about the server connection he has been allocated
        !          1058:        SZ_Clear(&net_message);
        !          1059:        // save space for the header, filled in later
        !          1060:        MSG_WriteLong(&net_message, 0);
        !          1061:        MSG_WriteByte(&net_message, CCREP_ACCEPT);
        !          1062:        dfunc.GetSocketAddr(newsock, &newaddr);
        !          1063:        MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
        !          1064: //     MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
        !          1065:        *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !          1066:        dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        !          1067:        SZ_Clear(&net_message);
        !          1068: 
        !          1069:        return sock;
        !          1070: }
        !          1071: 
        !          1072: qsocket_t *Datagram_CheckNewConnections (void)
        !          1073: {
        !          1074:        qsocket_t *ret = NULL;
        !          1075: 
        !          1076:        for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
        !          1077:                if (net_landrivers[net_landriverlevel].initialized)
        !          1078:                        if ((ret = _Datagram_CheckNewConnections ()) != NULL)
        !          1079:                                break;
        !          1080:        return ret;
        !          1081: }
        !          1082: 
        !          1083: 
        !          1084: static void _Datagram_SearchForHosts (qboolean xmit)
        !          1085: {
        !          1086:        int             ret;
        !          1087:        int             n;
        !          1088:        int             i;
        !          1089:        struct qsockaddr readaddr;
        !          1090:        struct qsockaddr myaddr;
        !          1091:        int             control;
        !          1092: 
        !          1093:        dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
        !          1094:        if (xmit)
        !          1095:        {
        !          1096:                SZ_Clear(&net_message);
        !          1097:                // save space for the header, filled in later
        !          1098:                MSG_WriteLong(&net_message, 0);
        !          1099:                MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
        !          1100:                MSG_WriteString(&net_message, "QUAKE");
        !          1101:                MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
        !          1102:                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !          1103:                dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
        !          1104:                SZ_Clear(&net_message);
        !          1105:        }
        !          1106: 
        !          1107:        while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
        !          1108:        {
        !          1109:                if (ret < sizeof(int))
        !          1110:                        continue;
        !          1111:                net_message.cursize = ret;
        !          1112: 
        !          1113:                // don't answer our own query
        !          1114:                if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
        !          1115:                        continue;
        !          1116: 
        !          1117:                // is the cache full?
        !          1118:                if (hostCacheCount == HOSTCACHESIZE)
        !          1119:                        continue;
        !          1120: 
        !          1121:                MSG_BeginReading ();
        !          1122:                control = BigLong(*((int *)net_message.data));
        !          1123:                MSG_ReadLong();
        !          1124:                if (control == -1)
        !          1125:                        continue;
        !          1126:                if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
        !          1127:                        continue;
        !          1128:                if ((control & NETFLAG_LENGTH_MASK) != ret)
        !          1129:                        continue;
        !          1130: 
        !          1131:                if (MSG_ReadByte() != CCREP_SERVER_INFO)
        !          1132:                        continue;
        !          1133: 
        !          1134:                dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
        !          1135:                // search the cache for this server
        !          1136:                for (n = 0; n < hostCacheCount; n++)
        !          1137:                        if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
        !          1138:                                break;
        !          1139: 
        !          1140:                // is it already there?
        !          1141:                if (n < hostCacheCount)
        !          1142:                        continue;
        !          1143: 
        !          1144:                // add it
        !          1145:                hostCacheCount++;
        !          1146:                Q_strcpy(hostcache[n].name, MSG_ReadString());
        !          1147:                Q_strcpy(hostcache[n].map, MSG_ReadString());
        !          1148:                hostcache[n].users = MSG_ReadByte();
        !          1149:                hostcache[n].maxusers = MSG_ReadByte();
        !          1150:                if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
        !          1151:                {
        !          1152:                        Q_strcpy(hostcache[n].cname, hostcache[n].name);
        !          1153:                        hostcache[n].cname[14] = 0;
        !          1154:                        Q_strcpy(hostcache[n].name, "*");
        !          1155:                        Q_strcat(hostcache[n].name, hostcache[n].cname);
        !          1156:                }
        !          1157:                Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
        !          1158:                hostcache[n].driver = net_driverlevel;
        !          1159:                hostcache[n].ldriver = net_landriverlevel;
        !          1160:                Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
        !          1161: 
        !          1162:                // check for a name conflict
        !          1163:                for (i = 0; i < hostCacheCount; i++)
        !          1164:                {
        !          1165:                        if (i == n)
        !          1166:                                continue;
        !          1167:                        if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
        !          1168:                        {
        !          1169:                                i = Q_strlen(hostcache[n].name);
        !          1170:                                if (i < 15 && hostcache[n].name[i-1] > '8')
        !          1171:                                {
        !          1172:                                        hostcache[n].name[i] = '0';
        !          1173:                                        hostcache[n].name[i+1] = 0;
        !          1174:                                }
        !          1175:                                else
        !          1176:                                        hostcache[n].name[i-1]++;
        !          1177:                                i = -1;
        !          1178:                        }
        !          1179:                }
        !          1180:        }
        !          1181: }
        !          1182: 
        !          1183: void Datagram_SearchForHosts (qboolean xmit)
        !          1184: {
        !          1185:        for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
        !          1186:        {
        !          1187:                if (hostCacheCount == HOSTCACHESIZE)
        !          1188:                        break;
        !          1189:                if (net_landrivers[net_landriverlevel].initialized)
        !          1190:                        _Datagram_SearchForHosts (xmit);
        !          1191:        }
        !          1192: }
        !          1193: 
        !          1194: 
        !          1195: static qsocket_t *_Datagram_Connect (char *host)
        !          1196: {
        !          1197:        struct qsockaddr sendaddr;
        !          1198:        struct qsockaddr readaddr;
        !          1199:        qsocket_t       *sock;
        !          1200:        int                     newsock;
        !          1201:        int                     ret;
        !          1202:        int                     reps;
        !          1203:        double          start_time;
        !          1204:        int                     control;
        !          1205:        char            *reason;
        !          1206: 
        !          1207:        // see if we can resolve the host name
        !          1208:        if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
        !          1209:                return NULL;
        !          1210: 
        !          1211:        newsock = dfunc.OpenSocket (0);
        !          1212:        if (newsock == -1)
        !          1213:                return NULL;
        !          1214: 
        !          1215:        sock = NET_NewQSocket ();
        !          1216:        if (sock == NULL)
        !          1217:                goto ErrorReturn2;
        !          1218:        sock->socket = newsock;
        !          1219:        sock->landriver = net_landriverlevel;
        !          1220: 
        !          1221:        // connect to the host
        !          1222:        if (dfunc.Connect (newsock, &sendaddr) == -1)
        !          1223:                goto ErrorReturn;
        !          1224: 
        !          1225:        // send the connection request
        !          1226:        Con_Printf("trying...\n"); SCR_UpdateScreen ();
        !          1227:        start_time = net_time;
        !          1228: 
        !          1229:        for (reps = 0; reps < 3; reps++)
        !          1230:        {
        !          1231:                SZ_Clear(&net_message);
        !          1232:                // save space for the header, filled in later
        !          1233:                MSG_WriteLong(&net_message, 0);
        !          1234:                MSG_WriteByte(&net_message, CCREQ_CONNECT);
        !          1235:                MSG_WriteString(&net_message, "QUAKE");
        !          1236:                MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
        !          1237:                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        !          1238:                dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
        !          1239:                SZ_Clear(&net_message);
        !          1240:                do
        !          1241:                {
        !          1242:                        ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
        !          1243:                        // if we got something, validate it
        !          1244:                        if (ret > 0)
        !          1245:                        {
        !          1246:                                // is it from the right place?
        !          1247:                                if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
        !          1248:                                {
        !          1249: #ifdef DEBUG
        !          1250:                                        Con_Printf("wrong reply address\n");
        !          1251:                                        Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
        !          1252:                                        Con_Printf("Received: %s\n", StrAddr (&readaddr));
        !          1253:                                        SCR_UpdateScreen ();
        !          1254: #endif
        !          1255:                                        ret = 0;
        !          1256:                                        continue;
        !          1257:                                }
        !          1258: 
        !          1259:                                if (ret < sizeof(int))
        !          1260:                                {
        !          1261:                                        ret = 0;
        !          1262:                                        continue;
        !          1263:                                }
        !          1264: 
        !          1265:                                net_message.cursize = ret;
        !          1266:                                MSG_BeginReading ();
        !          1267: 
        !          1268:                                control = BigLong(*((int *)net_message.data));
        !          1269:                                MSG_ReadLong();
        !          1270:                                if (control == -1)
        !          1271:                                {
        !          1272:                                        ret = 0;
        !          1273:                                        continue;
        !          1274:                                }
        !          1275:                                if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
        !          1276:                                {
        !          1277:                                        ret = 0;
        !          1278:                                        continue;
        !          1279:                                }
        !          1280:                                if ((control & NETFLAG_LENGTH_MASK) != ret)
        !          1281:                                {
        !          1282:                                        ret = 0;
        !          1283:                                        continue;
        !          1284:                                }
        !          1285:                        }
        !          1286:                }
        !          1287:                while (ret == 0 && (SetNetTime() - start_time) < 2.5);
        !          1288:                if (ret)
        !          1289:                        break;
        !          1290:                Con_Printf("still trying...\n"); SCR_UpdateScreen ();
        !          1291:                start_time = SetNetTime();
        !          1292:        }
        !          1293: 
        !          1294:        if (ret == 0)
        !          1295:        {
        !          1296:                reason = "No Response";
        !          1297:                Con_Printf("%s\n", reason);
        !          1298:                Q_strcpy(m_return_reason, reason);
        !          1299:                goto ErrorReturn;
        !          1300:        }
        !          1301: 
        !          1302:        if (ret == -1)
        !          1303:        {
        !          1304:                reason = "Network Error";
        !          1305:                Con_Printf("%s\n", reason);
        !          1306:                Q_strcpy(m_return_reason, reason);
        !          1307:                goto ErrorReturn;
        !          1308:        }
        !          1309: 
        !          1310:        ret = MSG_ReadByte();
        !          1311:        if (ret == CCREP_REJECT)
        !          1312:        {
        !          1313:                reason = MSG_ReadString();
        !          1314:                Con_Printf(reason);
        !          1315:                Q_strncpy(m_return_reason, reason, 31);
        !          1316:                goto ErrorReturn;
        !          1317:        }
        !          1318: 
        !          1319:        if (ret == CCREP_ACCEPT)
        !          1320:        {
        !          1321:                Q_memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
        !          1322:                dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
        !          1323:        }
        !          1324:        else
        !          1325:        {
        !          1326:                reason = "Bad Response";
        !          1327:                Con_Printf("%s\n", reason);
        !          1328:                Q_strcpy(m_return_reason, reason);
        !          1329:                goto ErrorReturn;
        !          1330:        }
        !          1331: 
        !          1332:        dfunc.GetNameFromAddr (&sendaddr, sock->address);
        !          1333: 
        !          1334:        Con_Printf ("Connection accepted\n");
        !          1335:        sock->lastMessageTime = SetNetTime();
        !          1336: 
        !          1337:        // switch the connection to the specified address
        !          1338:        if (dfunc.Connect (newsock, &sock->addr) == -1)
        !          1339:        {
        !          1340:                reason = "Connect to Game failed";
        !          1341:                Con_Printf("%s\n", reason);
        !          1342:                Q_strcpy(m_return_reason, reason);
        !          1343:                goto ErrorReturn;
        !          1344:        }
        !          1345: 
        !          1346:        m_return_onerror = false;
        !          1347:        return sock;
        !          1348: 
        !          1349: ErrorReturn:
        !          1350:        NET_FreeQSocket(sock);
        !          1351: ErrorReturn2:
        !          1352:        dfunc.CloseSocket(newsock);
        !          1353:        if (m_return_onerror)
        !          1354:        {
        !          1355:                key_dest = key_menu;
        !          1356:                m_state = m_return_state;
        !          1357:                m_return_onerror = false;
        !          1358:        }
        !          1359:        return NULL;
        !          1360: }
        !          1361: 
        !          1362: qsocket_t *Datagram_Connect (char *host)
        !          1363: {
        !          1364:        qsocket_t *ret = NULL;
        !          1365: 
        !          1366:        for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
        !          1367:                if (net_landrivers[net_landriverlevel].initialized)
        !          1368:                        if ((ret = _Datagram_Connect (host)) != NULL)
        !          1369:                                break;
        !          1370:        return ret;
        !          1371: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.