void GetServerPing(server_data *serv)
{
    int p;
    char buf[32];
    snprintf (buf, sizeof (buf), "%d.%d.%d.%d",
        serv->address.ip[0],
        serv->address.ip[1],
        serv->address.ip[2],
        serv->address.ip[3]);

    p = useNewPing
			// new ping = UPD QW Packet
			? PingHost(buf, serv->address.port, (int)max(1, min(sb_pings.value, 10)), sb_pingtimeout.value)
			// old ping = ICMP PING Packet
			: oldPingHost(buf, (int)max(1, min(sb_pings.value, 10)));
    
	if (p)
        SetPing(serv, p-1);
    else
        SetPing(serv, p-1);
}
Beispiel #2
0
void CLocalPlayer::PingReturn ( RakNet::BitStream * pBitStream )
{
	// Read the player ping
	unsigned short usPing;
	pBitStream->ReadCompressed ( usPing );

	// Set the last ping time
	m_ulLastPingTime = SharedUtility::GetTime ();

	// Set our ping
	SetPing ( usPing );

	// Mark as no connection problem
	pCore->SetConnectionProblem ( false );
}
DWORD WINAPI GetServerInfosProc(void * lpParameter)
{
    infohost *hosts;   // 0 if not sent yet, -1 if data read
    double interval, lastsenttime;

    socket_t newsocket;
    struct sockaddr_storage dest;
    int ret, i;
    fd_set fd;
    struct timeval timeout;

    if (abort_ping)
        return 0;

    // so we have a socket
    newsocket = UDP_OpenSocket(PORT_ANY);

    hosts = (infohost *) Q_malloc (serversn * sizeof(infohost));
    for (i=0; i < serversn; i++)
    {
        hosts[i].phase = 0;
        hosts[i].lastsenttime = -1000;
        Reset_Server(servers[i]);

        // do not update dead servers
		if (servers[i]->ping < 0) {
            hosts[i].phase = -1;//(int)sb_inforetries.value;
		}
		// do not update too distant servers
		else if (sb_hidehighping.integer && servers[i]->ping > sb_pinglimit.integer) {
			hosts[i].phase = -1;
		}
    }

    interval = (1000.0 / sb_infospersec.value) / 1000;
    lastsenttime = Sys_DoubleTime() - interval;
    timeout.tv_sec = 0;
    timeout.tv_usec = (long)(interval * 1000.0 * 1000.0 / 2);

    ping_pos = 0;

    while (1  &&  !abort_ping)
    {
        int index = -1;
        double time = Sys_DoubleTime();

        // if it is time to send next request
        if (time > lastsenttime + interval)
        {
            int finished = 0;
            int to_ask = 0;
            int phase = (int)(sb_inforetries.value);

            // find next server to ask
            for (i=0; i < serversn; i++)
            {
                if (hosts[i].phase < phase  &&  hosts[i].phase >= 0  &&
                    time > hosts[i].lastsenttime + (sb_infotimeout.value / 1000))
                {
                    index = i;
                    phase = hosts[i].phase;
                }

                if (hosts[i].phase >= (int)sb_inforetries.value)
                    finished++;
                else
                    if (hosts[i].phase >= 0)
                        to_ask++;
            }
            //ping_pos = finished / (double)serversn;
            ping_pos = (finished+to_ask <= 0) ? 0 :
            finished / (double)(finished+to_ask);
        }

        // check if we should finish
        if (index < 0)
            if (time > lastsenttime + 1.2 * (sb_infotimeout.value / 1000))
                break;

        // send status request
        if (index >= 0)
        {
            hosts[index].phase ++;
            hosts[index].lastsenttime = time;
            lastsenttime = time;

            NetadrToSockadr (&(servers[index]->address), &dest);

            ret = sendto (newsocket, senddata, sizeof(senddata), 0,
                          (struct sockaddr *)&dest, sizeof(*(struct sockaddr *)&dest));
            if(ret < 0)
            {
                Com_DPrintf("sendto() gave errno = %d : %s\n", errno, strerror(errno));
            }
            if (ret == -1)
                ;//return;

            // requests_sent++;
            // ping_pos = requests_total <= 0 ? 0 : requests_sent / (double)requests_total;
        }

        // check if answer arrived and decode it
        //fd.fd_count = 1;
        //fd.fd_array[0] = newsocket;
        FD_ZERO(&fd);
        FD_SET(newsocket, &fd);

        ret = select(newsocket+1, &fd, NULL, NULL, &timeout);
        if (ret < 1)
        {
            Com_DPrintf("select() gave errno = %d : %s\n", errno, strerror(errno));
        }

        if (FD_ISSET(newsocket, &fd))
        {
            struct sockaddr_storage hostaddr;
            netadr_t from;
            int i;
            char answer[5000];
            answer[0] = 0;

            i = sizeof(hostaddr);
            ret = recvfrom (newsocket, answer, 5000, 0, (struct sockaddr *)&hostaddr, (socklen_t *)&i);
            answer[max(0, min(ret, 4999))] = 0;

            if (ret > 0)
            {
                SockadrToNetadr (&hostaddr, &from);

                for (i=0; i < serversn; i++)
                    if (from.ip[0] == servers[i]->address.ip[0] &&
                        from.ip[1] == servers[i]->address.ip[1] &&
                        from.ip[2] == servers[i]->address.ip[2] &&
                        from.ip[3] == servers[i]->address.ip[3] &&
                        from.port == servers[i]->address.port)
                    {
                        hosts[i].phase = (int)sb_inforetries.value;
                        Parse_Serverinfo(servers[i], answer);
                        break;
                    }
            }
        }
    }

    // reset pings to 999 if server didn't answer
    for (i=0; i < serversn; i++)
        if (servers[i]->keysn <= 0)
            SetPing(servers[i], -1);

    closesocket(newsocket);
    Q_free(hosts);

    return 0;
}
void Parse_Serverinfo(server_data *s, char *info)
{
    int i, j;
    char *pinfo;
    char *tmp;

    s->passed_filters = 1;
    s->support_teams = false; // by default server does't support team info per player

    if (strncmp(info, "\xFF\xFF\xFF\xFFn", 5))
    {
        SetPing(s, -1);
        return;
    }

    pinfo = strchr(info, '\n');
    if (pinfo != NULL)
        *(pinfo++) = 0;

    info += 5;

    while (*info == '\\'  &&  s->keysn < MAX_KEYS)
    {
        char *i2, *i3;
        i2 = strchr(info+1, '\\');
        if (i2 == NULL)
            break;
        i3 = strchr(i2+1, '\\');
        if (i3 == NULL)
            i3 = info + strlen(info);

        s->keys[s->keysn] = (char *) Q_malloc(i2-info);
        strlcpy(s->keys[s->keysn], info+1, i2-info);

        s->values[s->keysn] = (char *) Q_malloc(i3-i2);
        strlcpy(s->values[s->keysn], i2+1, i3-i2);

        s->keysn++;

        info = i3;
    }

    // read players

    for (i = s->spectatorsn = s->playersn = 0; pinfo  &&  strchr(pinfo, '\n'); i++)
    {
        qbool spec;
        int id, frags, time, ping, slen;
        char name[100], skin[100], team[100];
        char *nameptr = name;
        int top, bottom;
        int pos;

        if (s->playersn + s->spectatorsn >= MAX_PLAYERS)
            break;  // man

        pos = 0;
        pos += ReadInt(pinfo+pos, &id);
        pos += ReadInt(pinfo+pos, &frags);
        pos += ReadInt(pinfo+pos, &time);
        pos += ReadInt(pinfo+pos, &ping);
        pos += ReadString(pinfo+pos, name);
        pos += ReadString(pinfo+pos, skin);
        pos += ReadInt(pinfo+pos, &top);
        pos += ReadInt(pinfo+pos, &bottom);
        pos += ReadString(pinfo+pos, team);

        if (team[0])
            s->support_teams = true; // seems server support team info per player

        if (ping > 0) { // seems player if relay on ping
            spec = false;
            s->playersn++;
        }
        else // spec
        {
            spec = true;
            slen = strlen(name);
            s->spectatorsn++;
            ping = -ping;

            if (name[0] == '\\' && name[1] == 's' && name[2] == '\\')
                nameptr = name+3; // strip \s\<name>
            else if (slen > 3 && name[slen-3] == '(' && name[slen-2] == 's' && name[slen-1] == ')')
                name[slen-3] = 0; // strip <name>(s) for old servers
        }

        s->players[i] = (playerinfo *)Q_malloc(sizeof(playerinfo));
        s->players[i]->id = id;
        s->players[i]->frags = frags;
        s->players[i]->time = time;
        s->players[i]->ping = ping;
        s->players[i]->spec = spec;

        s->players[i]->top = Sbar_ColorForMap(top);
        s->players[i]->bottom = Sbar_ColorForMap(bottom);

        strlcpy(s->players[i]->name, nameptr, sizeof(s->players[0]->name));
        strlcpy(s->players[i]->skin, skin, sizeof(s->players[0]->skin));
        strlcpy(s->players[i]->team, team, sizeof(s->players[0]->team));

        pinfo = strchr(pinfo, '\n') + 1;
    }

    {
    void *swap;
    int n;
    // sort players by frags
    n = s->playersn + s->spectatorsn - 2;
    for (i = 0; i <= n; i++)
        for (j = n; j >= i; j--)
            if (s->players[j] && s->players[j+1] && s->players[j]->frags < s->players[j+1]->frags)
            {
                swap = (void*)s->players[j];
                s->players[j] = s->players[j+1];
                s->players[j+1] = (playerinfo*)swap;
            }
    // sort keys
    n = s->keysn - 2;
    for (i = 0; i <= n; i++)
        for (j = n; j >= i; j--)
            if (strcasecmp(s->keys[j], s->keys[j+1]) > 0)
            {
                swap = (void*)s->keys[j];
                s->keys[j] = s->keys[j+1];
                s->keys[j+1] = (char*)swap;
                swap = (void*)s->values[j];
                s->values[j] = s->values[j+1];
                s->values[j+1] = (char*)swap;
            }
    }

    // fill-in display
	s->qwfwd = SB_IsServerQWfwd(s);

    tmp = ValueForKey(s, "hostname");
    if (tmp != NULL)
        snprintf (s->display.name, sizeof (s->display.name),"%-.*s", COL_NAME, tmp);
    else
        return;

    tmp = ValueForKey(s, "fraglimit");
    if (tmp != NULL)
        snprintf(s->display.fraglimit, sizeof (s->display.fraglimit), "%*.*s", COL_FRAGLIMIT, COL_FRAGLIMIT, strlen(tmp) > COL_FRAGLIMIT ? "999" : tmp);

    tmp = ValueForKey(s, "timelimit");
    if (tmp != NULL)
        snprintf(s->display.timelimit, sizeof (s->display.timelimit), "%*.*s", COL_TIMELIMIT, COL_TIMELIMIT, strlen(tmp) > COL_TIMELIMIT ? "99" : tmp);

    tmp = ValueForKey(s, "*gamedir");
    s->qizmo = false;
    if (tmp != NULL)
        snprintf(s->display.gamedir, sizeof (s->display.gamedir) ,"%.*s", COL_GAMEDIR, tmp==NULL ? "" : tmp);
    else
    {
        tmp = ValueForKey(s, "*progs");
        if (tmp != NULL  &&  !strcmp(tmp, "666"))
        {
            snprintf(s->display.gamedir, sizeof (s->display.gamedir), "qizmo");
            s->qizmo = true;
        }
    }

    tmp = ValueForKey(s, "map");
    if (tmp != NULL)
        snprintf(s->display.map, sizeof (s->display.map), "%-.*s", COL_MAP, tmp==NULL ? "" : tmp);

    tmp = ValueForKey(s, "maxclients");
    if (!tmp || strlen(tmp) > 2)
        tmp = "99";
    i = s->playersn > 99 ? 99 : s->playersn;
    if (i < 1) { s->occupancy = SERVER_EMPTY; }
    else if (i > 0 && i < atoi(tmp)) { s->occupancy = SERVER_NONEMPTY; }
    else { s->occupancy = SERVER_FULL; }
    if (tmp != NULL)
        snprintf(s->display.players, sizeof (s->display.players), "%2d/%-2s", i, tmp==NULL ? "" : tmp);
}