Ejemplo n.º 1
0
int do_sockets(fd_set* rfd, int next)
{
    struct timeval timeout;
    int ret, i;


    // can timeout until the next tick
    timeout.tv_sec = next / 1000;
    timeout.tv_usec = next % 1000 * 1000;


    memcpy(rfd, &readfds, sizeof(*rfd));
    ret = sSelect(fd_max, rfd, nullptr, nullptr, &timeout);

    if (ret == SOCKET_ERROR)
    {
        if (sErrno != S_EINTR)
        {
            ShowFatalError("do_sockets: select() failed, error code %d!\n", sErrno);
            exit(EXIT_FAILURE);
        }
        return 0; // interrupted by a signal, just loop and try again
    }

    last_tick = time(nullptr);

#if defined(WIN32)
    // on windows, enumerating all members of the fd_set is way faster if we access the internals
    for (i = 0; i < (int)rfd->fd_count; ++i)
    {
        int fd = sock2fd(rfd->fd_array[i]);
        if (session[fd])
        {
            session[fd]->func_recv(fd);

            if (fd != login_fd &&
                    fd != login_lobbydata_fd &&
                    fd != login_lobbyview_fd)
            {
                session[fd]->func_parse(fd);

                if (!session[fd])
                    continue;

                //				RFIFOFLUSH(fd);
            }
        }
    }
#else
    // otherwise assume that the fd_set is a bit-array and enumerate it in a standard way
    for (i = 1; ret && i < fd_max; ++i)
    {
        if (sFD_ISSET(i, rfd) && session[i])
        {
            session[i]->func_recv(i);

            if (session[i])
            {

                if (i != login_fd &&
                        i != login_lobbydata_fd &&
                        i != login_lobbyview_fd)
                {
                    session[i]->func_parse(i);

                    if (!session[i])
                        continue;

                    //							RFIFOFLUSH(fd);
                }
                --ret;
            }
        }
    }
#endif

    /*
        // parse input data on each socket
    for(i = 1; i < fd_max; i++)
    {
        if(!session[i])
            continue;

        if (session[i]->rdata_tick && DIFF_TICK(last_tick, session[i]->rdata_tick) > stall_time) {
            ShowInfo("Session #%d timed out\n", i);
            set_eof(i);
        }

        session[i]->func_parse(i);

        if(!session[i])
            continue;

        // after parse, check client's RFIFO size to know if there is an invalid packet (too big and not parsed)
        if (session[i]->rdata_size == RFIFO_SIZE && session[i]->max_rdata == RFIFO_SIZE) {
            set_eof(i);
            continue;
        }
        RFIFOFLUSH(i);
    }*/


    for (i = 1; i < fd_max; i++)
    {
        if (!session[i])
            continue;

        if (session[i]->wdata_size)
            session[i]->func_send(i);
    }
    return 0;
}
Ejemplo n.º 2
0
int32 do_sockets(fd_set* rfd, int32 next)
{
    struct timeval timeout;
    int32 ret;
    memcpy(rfd, &readfds, sizeof(*rfd));

    timeout.tv_sec = next / 1000;
    timeout.tv_usec = next % 1000 * 1000;

    ret = sSelect(fd_max, rfd, nullptr, nullptr, &timeout);

    if (ret == SOCKET_ERROR)
    {
        if (sErrno != S_EINTR)
        {
            ShowFatalError("do_sockets: select() failed, error code %d!\n", sErrno);
            do_final(EXIT_FAILURE);
        }
        return 0; // interrupted by a signal, just loop and try again
    }

    last_tick = time(nullptr);

    if (sFD_ISSET(map_fd, rfd))
    {
        struct sockaddr_in from;
        socklen_t fromlen = sizeof(from);

        int32 ret = recvudp(map_fd, g_PBuff, map_config.buffer_size, 0, (struct sockaddr*)&from, &fromlen);
        if (ret != -1)
        {
            // find player char
#   ifdef WIN32
            uint32 ip = ntohl(from.sin_addr.S_un.S_addr);
#   else
            uint32 ip = ntohl(from.sin_addr.s_addr);
#   endif

            uint64 port = ntohs(from.sin_port);
            uint64 ipp = ip;
            ipp |= port << 32;
            map_session_data_t* map_session_data = mapsession_getbyipp(ipp);

            if (map_session_data == nullptr)
            {
                map_session_data = mapsession_createsession(ip, ntohs(from.sin_port));
                if (map_session_data == nullptr)
                {
					map_session_list.erase(ipp);
                    return -1;
                }
            }

            map_session_data->last_update = time(nullptr);
            size_t size = ret;

            if (recv_parse(g_PBuff, &size, &from, map_session_data) != -1)
            {
                // если предыдущий пакет был потерян, то мы не собираем новый,
                // а отправляем предыдущий пакет повторно
                if (!parse(g_PBuff, &size, &from, map_session_data))
                {
                    send_parse(g_PBuff, &size, &from, map_session_data);
                }

                ret = sendudp(map_fd, g_PBuff, size, 0, (const struct sockaddr*)&from, fromlen);

                int8* data = g_PBuff;
                g_PBuff = map_session_data->server_packet_data;

                map_session_data->server_packet_data = data;
                map_session_data->server_packet_size = size;
            }
            if (map_session_data->shuttingDown > 0)
            {
                map_close_session(gettick(), map_session_data);
            }
        }
    }
    return 0;
}