Esempio n. 1
0
int process_clip_msg(local_fd_type fd, client_t* client, msg_t* msg, size_t* room_id)
{
    size_t i;
    unsigned int ident = ntohl(msg->ident);
    size_t all_len = msg_data_length(msg);
    msg_group_t* group = msg_group_lookup(&client->recv_table, ident);
    if (!msg->zone.clip) return 0;
    if (group == NULL)
    {
        group = group_pool_room_alloc(&qtun->group_pool, sizeof(msg_group_t));
        if (group == NULL)
        {
            SYSLOG(LOG_ERR, "Not enough memory");
            return 0;
        }
        group->count = (unsigned short)ceil((double)all_len / client->max_length);
        group->elements = group_pool_room_alloc(&qtun->group_pool, sizeof(msg_t*) * group->count);
        memset(group->elements, 0, sizeof(msg_t*) * group->count);
        group->ident = ident;
        group->ttl_start = qtun->msg_ttl;
        if (!hash_set(&client->recv_table, (void*)(unsigned long)ident, sizeof(ident), group, sizeof(msg_group_t))) return 0;
    }
    if (qtun->msg_ttl - group->ttl_start > MSG_MAX_TTL) return 0; // expired
    for (i = 0; i < group->count; ++i)
    {
        if (group->elements[i] == NULL) // 收包顺序可能与发包顺序不同
        {
            size_t this_len = sizeof(msg_t) + (msg->zone.last ? all_len % client->max_length : client->max_length);
            msg_t* dup = group_pool_room_alloc(&qtun->group_pool, this_len);
            if (dup == NULL) break;
            memcpy(dup, msg, this_len);
            group->elements[i] = dup;
            if (i == group->count - 1)
            {
                void* buffer = NULL;
                unsigned short len = 0;
                if (parse_msg_group(client->max_length, group, &buffer, &len, room_id))
                {
                    ssize_t written;
#ifdef WIN32
                    WriteFile(fd, buffer, len, &written, NULL);
#else
                    written = write(fd, buffer, len);
#endif
                    SYSLOG(LOG_INFO, "write local length: %ld", written);
                    pool_room_free(&qtun->pool, *room_id);
                }
                else
                    SYSLOG(LOG_WARNING, "Parse message error");
                hash_del(&client->recv_table, (void*)(unsigned long)ident, sizeof(ident));
            }
            break;
        }
    }
    return 1;
}
Esempio n. 2
0
void* group_pool_room_realloc(group_pool_t* p, void* ptr, size_t len)
{
    group_pool_zone_t* zone = (group_pool_zone_t*)((char*)ptr - sizeof(group_pool_room_t*));
    group_pool_room_t* node = zone->node;
    void* ret;
    if (node->capacity >= len)
    {
        node->length = len;
        return ptr;
    }
    ret = group_pool_room_alloc(p, len);
    if (ret == NULL) return NULL;
    memcpy(ret, ptr, node->length);
    group_pool_room_free(p, ptr);
    return ret;
}
Esempio n. 3
0
static void accept_and_check()
{
    struct sockaddr_in srcaddr;
    socklen_t addrlen = sizeof(srcaddr);
    int fd = (int)accept(this.remotefd, (struct sockaddr*)&srcaddr, &addrlen);
    client_t* client;
#ifdef WIN32
    char flag = 1;
#else
    int flag = 1;
#endif
    hash_functor_t functor = {
        msg_ident_hash,
        msg_ident_compare,
        hash_dummy_dup,
        hash_dummy_dup,
        msg_group_free_hash,
        msg_group_free_hash_val
    };
    if (fd == -1) return;

    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)) == -1)
    {
        perror("setsockopt");
    }

    client = malloc(sizeof(*client));
    if (client == NULL)
    {
        SYSLOG(LOG_ERR, "Not enough memory");
        close(fd);
        return;
    }

    client->remote_ip = srcaddr.sin_addr.s_addr;
    client->remote_port = srcaddr.sin_addr.s_addr;
    client->fd = fd;
    client->addr = srcaddr;
    client->keepalive = (unsigned int)time(NULL);
    client->status = CLIENT_STATUS_CHECKLOGIN | CLIENT_STATUS_WAITING_HEADER;
    client->want = sizeof(msg_t);
    client->buffer = client->read = group_pool_room_alloc(&this.group_pool, client->want);
    client->buffer_len = client->want;
    if (client->buffer == NULL)
    {
        SYSLOG(LOG_ERR, "Not enough memory");
        free(client);
        close(fd);
        return;
    }
    if (!hash_init(&client->recv_table, functor, 11))
    {
        SYSLOG(LOG_ERR, "hash_init failed");
        group_pool_room_free(&this.group_pool, client->buffer);
        free(client);
        close(fd);
        return;
    }
    if (!active_vector_append(&this.clients, client, sizeof(*client)))
    {
        SYSLOG(LOG_ERR, "append to clients error");
        free(client);
        close(fd);
    }
}