Annotation of quake1/net_dgrm.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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