Example #1
0
void NET_Query_MasterResponse(net_packet_t *packet)
{
    unsigned int packet_type;
    unsigned int result;

    if (!NET_ReadInt16(packet, &packet_type)
     || !NET_ReadInt16(packet, &result))
    {
        return;
    }

    if (packet_type == NET_MASTER_PACKET_TYPE_ADD_RESPONSE)
    {
        if (result != 0)
        {
            // Only show the message once.

            if (!registered_with_master)
            {
                printf("Registered with master server at %s\n",
                       MASTER_SERVER_ADDRESS);
                registered_with_master = true;
            }
        }
        else
        {
            // Always show rejections.

            printf("Failed to register with master server at %s\n",
                   MASTER_SERVER_ADDRESS);
        }

        got_master_response = true;
    }
}
Example #2
0
static net_packet_t *BlockForPacket(net_addr_t *addr, unsigned int packet_type,
                                    unsigned int timeout_ms)
{
    net_packet_t *packet;
    net_addr_t *packet_src;
    unsigned int read_packet_type;
    unsigned int start_time;

    start_time = I_GetTimeMS();

    while (I_GetTimeMS() < start_time + timeout_ms)
    {
        if (!NET_RecvPacket(query_context, &packet_src, &packet))
        {
            I_Sleep(20);
            continue;
        }

        if (packet_src == addr
         && NET_ReadInt16(packet, &read_packet_type)
         && packet_type == read_packet_type)
        {
            return packet;
        }

        NET_FreePacket(packet);
    }

    // Timeout - no response.

    return NULL;
}
static void NET_SV_MasterPacket(net_packet_t *packet)
{
    unsigned int packet_type;

    // Read the packet type

    if (!NET_ReadInt16(packet, &packet_type))
    {
        NET_Log("server: error: no packet type in master server message");
        return;
    }

    NET_Log("server: packet from master server; type %d", packet_type);
    NET_LogPacket(packet);

    switch (packet_type)
    {
        case NET_MASTER_PACKET_TYPE_ADD_RESPONSE:
            NET_Query_AddResponse(packet);
            break;

        case NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH:
            NET_SV_ParseHolePunch(packet);
            break;
    }
}
Example #4
0
static void NET_CL_ParsePacket(net_packet_t *packet)
{
    unsigned int packet_type;

    if (!NET_ReadInt16(packet, &packet_type))
    {
        return;
    }

    if (NET_Conn_Packet(&client_connection, packet, &packet_type))
    {
        // Packet eaten by the common connection code
    }
    else
    {
        switch (packet_type)
        {
            case NET_PACKET_TYPE_WAITING_DATA:
                NET_CL_ParseWaitingData(packet);
                break;

            case NET_PACKET_TYPE_LAUNCH:
                NET_CL_ParseLaunch(packet);
                break;

            case NET_PACKET_TYPE_GAMESTART:
                NET_CL_ParseGameStart(packet);
                break;

            case NET_PACKET_TYPE_GAMEDATA:
                NET_CL_ParseGameData(packet);
                break;

            case NET_PACKET_TYPE_GAMEDATA_RESEND:
                NET_CL_ParseResendRequest(packet);
                break;

            case NET_PACKET_TYPE_CONSOLE_MESSAGE:
                NET_CL_ParseConsoleMessage(packet);
                break;

            default:
                break;
        }
    }
}
Example #5
0
static void NET_Query_ParseMasterResponse(net_addr_t *master_addr,
                                          net_packet_t *packet)
{
    unsigned int packet_type;
    query_target_t *target;
    char *addr_str;
    net_addr_t *addr;

    // Read the header.  We are only interested in query responses.

    if (!NET_ReadInt16(packet, &packet_type)
     || packet_type != NET_MASTER_PACKET_TYPE_QUERY_RESPONSE)
    {
        return;
    }

    // Read a list of strings containing the addresses of servers
    // that the master knows about.

    for (;;)
    {
        addr_str = NET_ReadString(packet);

        if (addr_str == NULL)
        {
            break;
        }

        // Resolve address and add to targets list if it is not already
        // there.

        addr = NET_ResolveAddress(query_context, addr_str);

        if (addr != NULL)
        {
            GetTargetForAddr(addr, true);
        }
    }

    // Mark the master as having responded.

    target = GetTargetForAddr(master_addr, true);
    target->state = QUERY_TARGET_RESPONDED;
}
Example #6
0
static void NET_Query_ParseResponse(net_addr_t *addr, net_packet_t *packet,
                                    net_query_callback_t callback,
                                    void *user_data)
{
    unsigned int packet_type;
    net_querydata_t querydata;
    query_target_t *target;

    // Read the header

    if (!NET_ReadInt16(packet, &packet_type)
     || packet_type != NET_PACKET_TYPE_QUERY_RESPONSE)
    {
        return;
    }

    // Read query data

    if (!NET_ReadQueryData(packet, &querydata))
    {
        return;
    }

    // Find the target that responded.

    target = GetTargetForAddr(addr, false);

    // If the target is not found, it may be because we are doing
    // a LAN broadcast search, in which case we need to create a
    // target for the new responder.

    if (target == NULL)
    {
        query_target_t *broadcast_target;

        broadcast_target = GetTargetForAddr(NULL, false);

        // Not in broadcast mode, unexpected response that came out
        // of nowhere. Ignore.

        if (broadcast_target == NULL
         || broadcast_target->state != QUERY_TARGET_QUERIED)
        {
            return;
        }

        // Create new target.

        target = GetTargetForAddr(addr, true);
        target->state = QUERY_TARGET_QUERIED;
        target->query_time = broadcast_target->query_time;
    }

    if (target->state != QUERY_TARGET_RESPONDED)
    {
        target->state = QUERY_TARGET_RESPONDED;
        memcpy(&target->data, &querydata, sizeof(net_querydata_t));

        // Calculate RTT.

        target->ping_time = I_GetTimeMS() - target->query_time;

        // Invoke callback to signal that we have a new address.

        callback(addr, &target->data, target->ping_time, user_data);
    }
}
Example #7
0
static void NET_SV_ParseSYN(net_packet_t *packet, 
                            net_client_t *client,
                            net_addr_t *addr)
{
    unsigned int magic;
    unsigned int cl_gamemode, cl_gamemission;
    unsigned int cl_recording_lowres;
    unsigned int cl_drone;
    unsigned int is_freedoom;
    md5_digest_t deh_md5sum, wad_md5sum;
    char *player_name;
    char *client_version;
    int i;

    // read the magic number

    if (!NET_ReadInt32(packet, &magic))
    {
        return;
    }

    if (magic != NET_MAGIC_NUMBER)
    {
        // invalid magic number

        return;
    }

    // Check the client version is the same as the server

    client_version = NET_ReadString(packet);

    if (client_version == NULL)
    {
        return;
    }

    if (strcmp(client_version, PACKAGE_STRING) != 0)
    {
        //!
        // @category net
        //
        // When running a netgame server, ignore version mismatches between
        // the server and the client. Using this option may cause game
        // desyncs to occur, or differences in protocol may mean the netgame
        // will simply not function at all.
        //

        if (M_CheckParm("-ignoreversion") == 0) 
        {
            NET_SV_SendReject(addr,
                              "Version mismatch: server version is: "
                              PACKAGE_STRING);
            return;
        }
    }

    // read the game mode and mission

    if (!NET_ReadInt16(packet, &cl_gamemode) 
     || !NET_ReadInt16(packet, &cl_gamemission)
     || !NET_ReadInt8(packet, &cl_recording_lowres)
     || !NET_ReadInt8(packet, &cl_drone)
     || !NET_ReadMD5Sum(packet, wad_md5sum)
     || !NET_ReadMD5Sum(packet, deh_md5sum)
     || !NET_ReadInt8(packet, &is_freedoom))
    {
        return;
    }

    if (!NET_ValidGameMode(cl_gamemode, cl_gamemission))
    {
        return;
    }

    // read the player's name

    player_name = NET_ReadString(packet);

    if (player_name == NULL)
    {
        return;
    }
    
    // received a valid SYN

    // not accepting new connections?
    
    if (server_state != SERVER_WAITING_START)
    {
        NET_SV_SendReject(addr, "Server is not currently accepting connections");
        return;
    }
    
    // allocate a client slot if there isn't one already

    if (client == NULL)
    {
        // find a slot, or return if none found

        for (i=0; i<MAXNETNODES; ++i)
        {
            if (!clients[i].active)
            {
                client = &clients[i];
                break;
            }
        }

        if (client == NULL)
        {
            return;
        }
    }
    else
    {
        // If this is a recently-disconnected client, deactivate
        // to allow immediate reconnection

        if (client->connection.state == NET_CONN_STATE_DISCONNECTED)
        {
            client->active = false;
        }
    }

    // New client?

    if (!client->active)
    {
        int num_players;

        // Before accepting a new client, check that there is a slot
        // free

        NET_SV_AssignPlayers();
        num_players = NET_SV_NumPlayers();

        if ((!cl_drone && num_players >= MAXPLAYERS)
         || NET_SV_NumClients() >= MAXNETNODES)
        {
            NET_SV_SendReject(addr, "Server is full!");
            return;
        }

        // TODO: Add server option to allow rejecting clients which
        // set lowres_turn.  This is potentially desirable as the 
        // presence of such clients affects turning resolution.

        // Adopt the game mode and mission of the first connecting client

        if (num_players == 0 && !cl_drone)
        {
            sv_gamemode = cl_gamemode;
            sv_gamemission = cl_gamemission;
        }

        // Save the MD5 checksums

        memcpy(client->wad_md5sum, wad_md5sum, sizeof(md5_digest_t));
        memcpy(client->deh_md5sum, deh_md5sum, sizeof(md5_digest_t));
        client->is_freedoom = is_freedoom;

        // Check the connecting client is playing the same game as all
        // the other clients

        if (cl_gamemode != sv_gamemode || cl_gamemission != sv_gamemission)
        {
            NET_SV_SendReject(addr, "You are playing the wrong game!");
            return;
        }
        
        // Activate, initialize connection

        NET_SV_InitNewClient(client, addr, player_name);

        client->recording_lowres = cl_recording_lowres;
        client->drone = cl_drone;
    }

    if (client->connection.state == NET_CONN_STATE_WAITING_ACK)
    {
        // force an acknowledgement
        client->connection.last_send_time = -1;
    }
}
Example #8
0
static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr)
{
    net_client_t *client;
    unsigned int packet_type;

    // Response from master server?

    if (addr != NULL && addr == master_server)
    {
        NET_Query_MasterResponse(packet);
        return;
    }

    // Find which client this packet came from

    client = NET_SV_FindClient(addr);

    // Read the packet type

    if (!NET_ReadInt16(packet, &packet_type))
    {
        // no packet type

        return;
    }

    if (packet_type == NET_PACKET_TYPE_SYN)
    {
        NET_SV_ParseSYN(packet, client, addr);
    }
    else if (packet_type == NET_PACKET_TYPE_QUERY)
    {
        NET_SV_SendQueryResponse(addr);
    }
    else if (client == NULL)
    {
        // Must come from a valid client; ignore otherwise
    }
    else if (NET_Conn_Packet(&client->connection, packet, &packet_type))
    {
        // Packet was eaten by the common connection code
    }
    else
    { 
        //printf("SV: %s: %i\n", NET_AddrToString(addr), packet_type);

        switch (packet_type)
        {
            case NET_PACKET_TYPE_GAMESTART:
                NET_SV_ParseGameStart(packet, client);
                break;
            case NET_PACKET_TYPE_GAMEDATA:
                NET_SV_ParseGameData(packet, client);
                break;
            case NET_PACKET_TYPE_GAMEDATA_ACK:
                NET_SV_ParseGameDataACK(packet, client);
                break;
            case NET_PACKET_TYPE_GAMEDATA_RESEND:
                NET_SV_ParseResendRequest(packet, client);
                break;
            default:
                // unknown packet type

                break;
        }
    }

    // If this address is not in the list of clients, be sure to
    // free it back.

    if (NET_SV_FindClient(addr) == NULL)
    {
        NET_FreeAddress(addr);
    }
}
static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr)
{
    net_client_t *client;
    unsigned int packet_type;

    // Response from master server?

    if (addr != NULL && addr == master_server)
    {
        NET_SV_MasterPacket(packet);
        return;
    }

    // Find which client this packet came from

    client = NET_SV_FindClient(addr);

    // Read the packet type

    if (!NET_ReadInt16(packet, &packet_type))
    {
        // no packet type

        return;
    }

    NET_Log("server: packet from %s; type %d", NET_AddrToString(addr),
            packet_type & ~NET_RELIABLE_PACKET);
    NET_LogPacket(packet);

    if (packet_type == NET_PACKET_TYPE_SYN)
    {
        NET_SV_ParseSYN(packet, client, addr);
    }
    else if (packet_type == NET_PACKET_TYPE_QUERY)
    {
        NET_SV_SendQueryResponse(addr);
    }
    else if (client == NULL)
    {
        // Must come from a valid client; ignore otherwise
    }
    else if (NET_Conn_Packet(&client->connection, packet, &packet_type))
    {
        // Packet was eaten by the common connection code
    }
    else
    {
        //printf("SV: %s: %i\n", NET_AddrToString(addr), packet_type);

        switch (packet_type)
        {
            case NET_PACKET_TYPE_GAMESTART:
                NET_SV_ParseGameStart(packet, client);
                break;
            case NET_PACKET_TYPE_LAUNCH:
                NET_SV_ParseLaunch(packet, client);
                break;
            case NET_PACKET_TYPE_GAMEDATA:
                NET_SV_ParseGameData(packet, client);
                break;
            case NET_PACKET_TYPE_GAMEDATA_ACK:
                NET_SV_ParseGameDataACK(packet, client);
                break;
            case NET_PACKET_TYPE_GAMEDATA_RESEND:
                NET_SV_ParseResendRequest(packet, client);
                break;
            default:
                // unknown packet type

                break;
        }
    }
}