Example #1
0
char *CL_SetConfigString (int index, dbuffer *msg)
{
	if (!Com_CheckConfigStringIndex(index))
		Com_Error(ERR_DROP, "invalid access to configstring array with index: %i", index);

	/* change the string in cl
	 * there may be overflows in i==CS_TILES - but thats ok
	 * see definition of configstrings and MAX_TILESTRINGS */
	if (index == CS_TILES || index == CS_POSITIONS)
		NET_ReadString(msg, cl.configstrings[index], MAX_TOKEN_CHARS * MAX_TILESTRINGS);
	else
		NET_ReadString(msg, cl.configstrings[index], sizeof(cl.configstrings[index]));

	return cl.configstrings[index];
}
static void NET_SV_ParseHolePunch(net_packet_t *packet)
{
    const char *addr_string;
    net_packet_t *sendpacket;
    net_addr_t *addr;

    addr_string = NET_ReadString(packet);
    if (addr_string == NULL)
    {
        NET_Log("server: error: hole punch request but no address provided");
        return;
    }

    addr = NET_ResolveAddress(server_context, addr_string);
    if (addr == NULL)
    {
        NET_Log("server: error: failed to resolve address: %s", addr_string);
        return;
    }

    sendpacket = NET_NewPacket(16);
    NET_WriteInt16(sendpacket, NET_PACKET_TYPE_NAT_HOLE_PUNCH);
    NET_SendPacket(addr, sendpacket);
    NET_FreePacket(sendpacket);
    NET_ReleaseAddress(addr);
    NET_Log("server: sent hole punch to %s", addr_string);
}
Example #3
0
/**
 * @brief Reads from a buffer according to format; version without syntactic sugar for variable arguments, to call it from other functions with variable arguments
 * @sa SV_ReadFormat
 * @param[in] buf The buffer we read the data from
 * @param[in] format The format string may not be nullptr
 * @param ap The variadic function argument list corresponding to the format string
 */
void NET_vReadFormat (dbuffer* buf, const char* format, va_list ap)
{
    while (*format) {
        const char typeID = *format++;

        switch (typeID) {
        case 'c':
            *va_arg(ap, int*) = NET_ReadChar(buf);
            break;
        case 'b':
            *va_arg(ap, int*) = NET_ReadByte(buf);
            break;
        case 's':
            *va_arg(ap, int*) = NET_ReadShort(buf);
            break;
        case 'l':
            *va_arg(ap, int*) = NET_ReadLong(buf);
            break;
        case 'p':
            NET_ReadPos(buf, *va_arg(ap, vec3_t*));
            break;
        case 'g':
            NET_ReadGPos(buf, *va_arg(ap, pos3_t*));
            break;
        case 'd':
            NET_ReadDir(buf, *va_arg(ap, vec3_t*));
            break;
        case 'a':
            *va_arg(ap, float*) = NET_ReadAngle(buf);
            break;
        case '!':
            format++;
            break;
        case '&': {
            char* str = va_arg(ap, char*);
            const size_t length = va_arg(ap, size_t);
            NET_ReadString(buf, str, length);
            break;
        }
        case '*':
        {
            const int n = NET_ReadShort(buf);

            *va_arg(ap, int*) = n;
            byte* p = va_arg(ap, byte*);

            for (int i = 0; i < n; i++)
                *p++ = NET_ReadByte(buf);
        }
        break;
        default:
            Com_Error(ERR_DROP, "ReadFormat: Unknown type!");
        }
    }
    /* Too many arguments for the given format; too few cause crash above */
#ifdef PARANOID
    if (!ap)
        Com_Error(ERR_DROP, "ReadFormat: Too many arguments!");
#endif
}
Example #4
0
char *NET_EndSecureDemo(sha1_digest_t demo_hash)
{
    net_packet_t *request, *response;
    net_addr_t *master_addr;
    char *signature;

    master_addr = NET_Query_ResolveMaster(query_context);

    // Construct end request and send to master server.

    request = NET_NewPacket(10);
    NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_END);
    NET_WriteSHA1Sum(request, demo_hash);
    NET_WriteString(request, securedemo_start_message);
    NET_SendPacket(master_addr, request);
    NET_FreePacket(request);

    // Block for response. The response packet simply contains a string
    // with the ASCII signature.

    response = BlockForPacket(master_addr,
                              NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE,
                              SIGNATURE_TIMEOUT_SECS * 1000);

    if (response == NULL)
    {
        return NULL;
    }

    signature = NET_ReadString(response);

    NET_FreePacket(response);

    return signature;
}
Example #5
0
void NET_SkipFormat (dbuffer* buf, const char* format)
{
    while (*format) {
        const char typeID = *format++;

        switch (typeID) {
        case 'c':
            NET_ReadChar(buf);
            break;
        case 'b':
            NET_ReadByte(buf);
            break;
        case 's':
            NET_ReadShort(buf);
            break;
        case 'l':
            NET_ReadLong(buf);
            break;
        case 'p': {
            vec3_t v;
            NET_ReadPos(buf, v);
            break;
        }
        case 'g': {
            pos3_t p;
            NET_ReadGPos(buf, p);
            break;
        }
        case 'd': {
            vec3_t v;
            NET_ReadDir(buf, v);
            break;
        }
        case 'a':
            NET_ReadAngle(buf);
            break;
        case '!':
            format++;
            break;
        case '&':
            NET_ReadString(buf, nullptr, 0);
            break;
        case '*': {
            const int n = NET_ReadShort(buf);
            for (int i = 0; i < n; i++)
                NET_ReadByte(buf);
            break;
        }
        default:
            Com_Error(ERR_DROP, "ReadFormat: Unknown type!");
        }
    }
}
Example #6
0
boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data)
{
    int i;
    char *s;

    if (!NET_ReadInt8(packet, (unsigned int *) &data->num_players)
     || !NET_ReadInt8(packet, (unsigned int *) &data->num_drones)
     || !NET_ReadInt8(packet, (unsigned int *) &data->ready_players)
     || !NET_ReadInt8(packet, (unsigned int *) &data->max_players)
     || !NET_ReadInt8(packet, (unsigned int *) &data->is_controller)
     || !NET_ReadSInt8(packet, &data->consoleplayer))
    {
        return false;
    }

    for (i = 0; i < data->num_players && i < NET_MAXPLAYERS; ++i)
    {
        s = NET_ReadString(packet);

        if (s == NULL || strlen(s) >= MAXPLAYERNAME)
        {
            return false;
        }

        strcpy(data->player_names[i], s);

        s = NET_ReadString(packet);

        if (s == NULL || strlen(s) >= MAXPLAYERNAME)
        {
            return false;
        }

        strcpy(data->player_addrs[i], s);
    }

    return NET_ReadSHA1Sum(packet, data->wad_sha1sum)
        && NET_ReadSHA1Sum(packet, data->deh_sha1sum)
        && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom);
}
static void NET_CL_ParseConsoleMessage(net_packet_t *packet)
{
    char *msg;

    msg = NET_ReadString(packet);

    if (msg == NULL)
    {
        return;
    }

    printf("Message from server: ");

    NET_SafePuts(msg);
}
Example #8
0
boolean NET_ReadQueryData(net_packet_t *packet, net_querydata_t *query)
{
    boolean result;

    query->version = NET_ReadString(packet);

    result = query->version != NULL
          && NET_ReadInt8(packet, (unsigned int *) &query->server_state)
          && NET_ReadInt8(packet, (unsigned int *) &query->num_players)
          && NET_ReadInt8(packet, (unsigned int *) &query->max_players)
          && NET_ReadInt8(packet, (unsigned int *) &query->gamemode)
          && NET_ReadInt8(packet, (unsigned int *) &query->gamemission);
    
    if (result)
    {
        query->description = NET_ReadString(packet);

        return query->description != NULL;
    }   
    else
    {
        return false;
    } 
}
Example #9
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 #10
0
boolean NET_StartSecureDemo(prng_seed_t seed)
{
    net_packet_t *request, *response;
    net_addr_t *master_addr;
    char *signature;
    boolean result;

    NET_Query_Init();
    master_addr = NET_Query_ResolveMaster(query_context);

    // Send request packet to master server.

    request = NET_NewPacket(10);
    NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_START);
    NET_SendPacket(master_addr, request);
    NET_FreePacket(request);

    // Block for response and read contents.
    // The signed start message will be saved for later.

    response = BlockForPacket(master_addr,
                              NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE,
                              SIGNATURE_TIMEOUT_SECS * 1000);

    result = false;

    if (response != NULL)
    {
        if (NET_ReadPRNGSeed(response, seed))
        {
            signature = NET_ReadString(response);

            if (signature != NULL)
            {
                securedemo_start_message = strdup(signature);
                result = true;
            }
        }

        NET_FreePacket(response);
    }

    return result;
}
Example #11
0
static void NET_Conn_ParseReject(net_connection_t *conn, net_packet_t *packet)
{
    char *msg;

    msg = NET_ReadString(packet);

    if (msg == NULL)
    {
        return;
    }
    
    if (conn->state == NET_CONN_STATE_CONNECTING)
    {
        // rejected by server

        conn->state = NET_CONN_STATE_DISCONNECTED;
        conn->disconnect_reason = NET_DISCONNECT_REMOTE;

        printf("Rejected by server: ");
        NET_SafePuts(msg);
    }
}
Example #12
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;
    }
}
static void NET_CL_ParseWaitingData(net_packet_t *packet)
{
    unsigned int num_players;
    unsigned int num_drones;
    unsigned int is_controller;
    signed int player_number;
    char *player_names[MAXPLAYERS];
    char *player_addr[MAXPLAYERS];
    md5_digest_t wad_md5sum, deh_md5sum;
    unsigned int server_is_freedoom;
    size_t i;

    if (!NET_ReadInt8(packet, &num_players)
     || !NET_ReadInt8(packet, &num_drones)
     || !NET_ReadInt8(packet, &is_controller)
     || !NET_ReadSInt8(packet, &player_number))
    {
        // invalid packet

        return;
    }

    if (num_players > MAXPLAYERS)
    {
        // insane data

        return;
    }

    if ((player_number >= 0 && drone)
     || (player_number < 0 && !drone)
     || (player_number >= (signed int) num_players))
    {
        // Invalid player number

        return;
    }
 
    // Read the player names

    for (i=0; i<num_players; ++i)
    {
        player_names[i] = NET_ReadString(packet);
        player_addr[i] = NET_ReadString(packet);

        if (player_names[i] == NULL || player_addr[i] == NULL)
        {
            return;
        }
    }

    if (!NET_ReadMD5Sum(packet, wad_md5sum)
     || !NET_ReadMD5Sum(packet, deh_md5sum)
     || !NET_ReadInt8(packet, &server_is_freedoom))
    {
        return;
    }

    net_clients_in_game = num_players;
    net_drones_in_game = num_drones;
    net_client_controller = is_controller != 0;
    net_player_number = player_number;

    for (i=0; i<num_players; ++i)
    {
        strncpy(net_player_names[i], player_names[i], MAXPLAYERNAME);
        net_player_names[i][MAXPLAYERNAME-1] = '\0';
        strncpy(net_player_addresses[i], player_addr[i], MAXPLAYERNAME);
        net_player_addresses[i][MAXPLAYERNAME-1] = '\0';
    }

    memcpy(net_server_wad_md5sum, wad_md5sum, sizeof(md5_digest_t));
    memcpy(net_server_deh_md5sum, deh_md5sum, sizeof(md5_digest_t));
    net_server_is_freedoom = server_is_freedoom;

    net_client_received_wait_data = true;
}
Example #14
0
/**
 * @brief The current net_message is parsed for the given client
 */
void SV_ExecuteClientMessage (client_t * cl, int cmd, struct dbuffer *msg)
{
	if (cmd == -1)
		return;

	switch (cmd) {
	default:
		Com_Printf("SV_ExecuteClientMessage: unknown command char '%d'\n", cmd);
		SV_DropClient(cl, "Unknown command\n");
		return;

	case clc_nop:
		break;

	case clc_ack:
		cl->lastmessage = svs.realtime;
		break;

	case clc_userinfo:
		NET_ReadString(msg, cl->userinfo, sizeof(cl->userinfo));
		Com_DPrintf(DEBUG_SERVER, "userinfo from client: %s\n", cl->userinfo);
		SV_UserinfoChanged(cl);
		break;

	case clc_stringcmd:
	{
		char str[1024];
		NET_ReadString(msg, str, sizeof(str));

		Com_DPrintf(DEBUG_SERVER, "stringcmd from client: %s\n", str);
		SV_ExecuteUserCommand(cl, str);

		if (cl->state == cs_free)
			return;			/* disconnect command */
		break;
	}

	case clc_action:
		/* client actions are handled by the game module */
		sv->messageBuffer = msg;
		TH_MutexLock(svs.serverMutex);
		svs.ge->ClientAction(cl->player);
		TH_MutexUnlock(svs.serverMutex);
		sv->messageBuffer = NULL;
		break;

	case clc_endround:
		/* player wants to end round */
		sv->messageBuffer = msg;
		TH_MutexLock(svs.serverMutex);
		svs.ge->ClientEndRound(cl->player);
		TH_MutexUnlock(svs.serverMutex);
		sv->messageBuffer = NULL;
		break;

	case clc_teaminfo:
		/* player sends team info */
		/* actors spawn accordingly */
		sv->messageBuffer = msg;
		TH_MutexLock(svs.serverMutex);
		svs.ge->ClientTeamInfo(cl->player);
		TH_MutexUnlock(svs.serverMutex);
		sv->messageBuffer = NULL;
		SV_SetClientState(cl, cs_spawned);
		break;

	case clc_initactorstates:
		/* player sends team info */
		/* actors spawn accordingly */
		sv->messageBuffer = msg;
		TH_MutexLock(svs.serverMutex);
		svs.ge->ClientInitActorStates(cl->player);
		TH_MutexUnlock(svs.serverMutex);
		sv->messageBuffer = NULL;
		break;
	}
}
static void NET_SV_ParseSYN(net_packet_t *packet, net_client_t *client,
                            net_addr_t *addr)
{
    unsigned int magic;
    net_connect_data_t data;
    net_packet_t *reply;
    net_protocol_t protocol;
    char *player_name;
    char *client_version;
    int num_players;
    int i;

    NET_Log("server: processing SYN packet");

    // Read the magic number and check it is the expected one.
    if (!NET_ReadInt32(packet, &magic))
    {
        NET_Log("server: error: no magic number for SYN");
        return;
    }

    switch (magic)
    {
        case NET_MAGIC_NUMBER:
            break;

        case NET_OLD_MAGIC_NUMBER:
            NET_Log("server: error: client using old magic number: %d", magic);
            NET_SV_SendReject(addr,
                "You are using an old client version that is not supported by "
                "this server. This server is running " PACKAGE_STRING ".");
            return;

        default:
            NET_Log("server: error: wrong magic number: %d", magic);
            return;
    }

    // Read the client version string. We actually now only use this when
    // sending a reject message, as we only reject if we can't negotiate a
    // common protocol (below).
    client_version = NET_ReadString(packet);
    if (client_version == NULL)
    {
        NET_Log("server: error: no version from client");
        return;
    }

    // Read the client's list of accepted protocols. Net play between forks
    // of Chocolate Doom is accepted provided that they can negotiate a
    // common accepted protocol.
    protocol = NET_ReadProtocolList(packet);
    if (protocol == NET_PROTOCOL_UNKNOWN)
    {
        char reject_msg[256];

        M_snprintf(reject_msg, sizeof(reject_msg),
            "Version mismatch: server version is: " PACKAGE_STRING "; "
            "client is: %s. No common compatible protocol could be "
            "negotiated.", client_version);
        NET_SV_SendReject(addr, reject_msg);
        NET_Log("server: error: no common protocol");
        return;
    }

    // Read connect data, and check that the game mode/mission are valid
    // and the max_players value is in a sensible range.
    if (!NET_ReadConnectData(packet, &data))
    {
        NET_Log("server: error: failed to read connect data");
        return;
    }

    if (!D_ValidGameMode(data.gamemission, data.gamemode)
     || data.max_players > NET_MAXPLAYERS)
    {
        NET_Log("server: error: invalid connect data, max_players=%d, "
                "gamemission=%d, gamemode=%d",
                data.max_players, data.gamemission, data.gamemode);
        return;
    }

    // Read the player's name
    player_name = NET_ReadString(packet);
    if (player_name == NULL)
    {
        NET_Log("server: error: failed to read player name");
        return;
    }

    // At this point we have received a valid SYN.

    // Not accepting new connections?
    if (server_state != SERVER_WAITING_LAUNCH)
    {
        NET_Log("server: error: not in waiting launch state, server_state=%d",
                server_state);
        NET_SV_SendReject(addr,
                          "Server is not currently accepting connections");
        return;
    }

    // Before accepting a new client, check that there is a slot free.
    NET_SV_AssignPlayers();
    num_players = NET_SV_NumPlayers();

    if ((!data.drone && num_players >= NET_SV_MaxPlayers())
     || NET_SV_NumClients() >= MAXNETNODES)
    {
        NET_Log("server: no more players, num_players=%d, max=%d",
                num_players, NET_SV_MaxPlayers());
        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 && !data.drone)
    {
        sv_gamemode = data.gamemode;
        sv_gamemission = data.gamemission;
        NET_Log("server: new game, mode=%d, mission=%d",
                sv_gamemode, sv_gamemission);
    }

    // Check the connecting client is playing the same game as all
    // the other clients
    if (data.gamemode != sv_gamemode || data.gamemission != sv_gamemission)
    {
        char msg[128];
        NET_Log("server: wrong mode/mission, %d != %d || %d != %d",
                data.gamemode, sv_gamemode, data.gamemission, sv_gamemission);
        M_snprintf(msg, sizeof(msg),
                   "Game mismatch: server is %s (%s), client is %s (%s)",
                   D_GameMissionString(sv_gamemission),
                   D_GameModeString(sv_gamemode),
                   D_GameMissionString(data.gamemission),
                   D_GameModeString(data.gamemode));

        NET_SV_SendReject(addr, msg);
        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;
        }
    }

    // Client already connected?
    if (client->active)
    {
        NET_Log("server: client is already initialized (duplicate SYN?)");
        return;
    }

    // Activate, initialize connection
    NET_SV_InitNewClient(client, addr, protocol);

    // Save the SHA1 checksums and other details.
    memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t));
    memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t));
    client->is_freedoom = data.is_freedoom;
    client->max_players = data.max_players;
    client->name = M_StringDuplicate(player_name);
    client->recording_lowres = data.lowres_turn;
    client->drone = data.drone;
    client->player_class = data.player_class;

    // Send a reply back to the client, indicating a successful connection
    // and specifying the protocol that will be used for communications.
    reply = NET_Conn_NewReliable(&client->connection, NET_PACKET_TYPE_SYN);
    NET_WriteString(reply, PACKAGE_STRING);
    NET_WriteProtocol(reply, protocol);
}
Example #16
0
static int SV_ReadString (char *str, size_t length)
{
	return NET_ReadString(sv->messageBuffer, str, length);
}
Example #17
0
/**
 * @brief Responses to broadcasts, etc
 * @sa CL_ReadPackets
 * @sa CL_Frame
 * @sa SVC_DirectConnect
 * @param[in,out] msg The client stream message buffer to read from
 */
static void CL_ConnectionlessPacket (dbuffer* msg)
{
	char s[512];
	NET_ReadStringLine(msg, s, sizeof(s));

	Cmd_TokenizeString(s, false);

	const char* c = Cmd_Argv(0);
	Com_DPrintf(DEBUG_CLIENT, "server OOB: %s (%s)\n", c, Cmd_Args());

	/* server connection */
	if (Q_streq(c, CL_CMD_CLIENT_CONNECT)) {
		int i;
		for (i = 1; i < Cmd_Argc(); i++) {
			if (char const* const p = Q_strstart(Cmd_Argv(i), "dlserver=")) {
				Com_sprintf(cls.downloadReferer, sizeof(cls.downloadReferer), "ufo://%s", cls.servername);
				CL_SetHTTPServer(p);
				if (cls.downloadServer[0])
					Com_Printf("HTTP downloading enabled, URL: %s\n", cls.downloadServer);
			}
		}
		if (cls.state == ca_connected) {
			Com_Printf("Dup connect received. Ignored.\n");
			return;
		}
		dbuffer buf(5);
		NET_WriteByte(&buf, clc_stringcmd);
		NET_WriteString(&buf, NET_STATE_NEW "\n");
		NET_WriteMsg(cls.netStream, buf);
		GAME_InitMissionBriefing(_("Loading"));
		return;
	}

	/* remote command from gui front end */
	if (Q_streq(c, CL_CMD_COMMAND)) {
		if (!NET_StreamIsLoopback(cls.netStream)) {
			Com_Printf("Command packet from remote host. Ignored.\n");
			return;
		} else {
			char str[512];
			NET_ReadString(msg, str, sizeof(str));
			Cbuf_AddText("%s\n", str);
		}
		return;
	}

	/* ping from server */
	if (Q_streq(c, CL_CMD_PING)) {
		NET_OOB_Printf(cls.netStream, SV_CMD_ACK);
		return;
	}

	/* echo request from server */
	if (Q_streq(c, CL_CMD_ECHO)) {
		NET_OOB_Printf(cls.netStream, "%s", Cmd_Argv(1));
		return;
	}

	/* print */
	if (Q_streq(c, SV_CMD_PRINT)) {
		NET_ReadString(msg, popupText, sizeof(popupText));
		/* special reject messages needs proper handling */
		if (strstr(popupText, REJ_PASSWORD_REQUIRED_OR_INCORRECT)) {
			UI_PushWindow("serverpassword");
			if (Q_strvalid(Cvar_GetString("password"))) {
				Cvar_Set("password", "");
				CL_Drop();
				UI_Popup(_("Connection failure"), _("The password you specified was wrong."));
			} else {
				CL_Drop();
				UI_Popup(_("Connection failure"), _("This server requires a password."));
			}
		} else if (strstr(popupText, REJ_SERVER_FULL)) {
			CL_Drop();
			UI_Popup(_("Connection failure"), _("This server is full."));
		} else if (strstr(popupText, REJ_BANNED)) {
			CL_Drop();
			UI_Popup(_("Connection failure"), _("You are banned on this server."));
		} else if (strstr(popupText, REJ_GAME_ALREADY_STARTED)) {
			CL_Drop();
			UI_Popup(_("Connection failure"), _("The game has already started."));
		} else if (strstr(popupText, REJ_SERVER_VERSION_MISMATCH)) {
			CL_Drop();
			UI_Popup(_("Connection failure"), _("The server is running a different version of the game."));
		} else if (strstr(popupText, BAD_RCON_PASSWORD)) {
			Cvar_Set("rcon_password", "");
			UI_Popup(_("Bad rcon password"), _("The rcon password you specified was wrong."));
		} else if (strstr(popupText, REJ_CONNECTION_REFUSED)) {
			CL_Drop();
			UI_Popup(_("Connection failure"), _("The server refused the connection."));
		} else if (Q_strvalid(popupText)) {
			UI_Popup(_("Notice"), _(popupText));
		}
		return;
	}

	if (!GAME_HandleServerCommand(c, msg))
		Com_Printf("Unknown command received \"%s\"\n", c);
}