Esempio n. 1
0
int check_msg(client_t* client, msg_t* msg)
{
    size_t msg_data_len;
    if (msg->zone.clip)
    {
        if (msg->zone.last) msg_data_len = msg_data_length(msg) % client->max_length;
        else msg_data_len = client->max_length;
    }
    else msg_data_len = msg_data_length(msg);
    if (checksum(msg, sizeof(msg_t) + msg_data_len))
    {
        SYSLOG(LOG_ERR, "Invalid msg");
        return 0;
    }
    return 1;
}
Esempio n. 2
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. 3
0
static void tcp_process(fd_set* set, vector_t* for_del)
{
    active_vector_iterator_t iter = active_vector_begin(&this.clients);
    while (!active_vector_is_end(iter))
    {
        client_t* client = iter.data;
        if (FD_ISSET(client->fd, set))
        {
            ssize_t rc = read_pre(client->fd, client->read, client->want);
            if (rc <= 0)
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK) goto end;
                perror("read");
                vector_push_back(for_del, (void*)(long)active_vector_iterator_idx(iter), sizeof(active_vector_iterator_idx(iter)));
                goto end;
            }
            client->read += rc;
            client->want -= rc;
            if (client->want == 0)
            {
                if (IS_CLIENT_STATUS_WAITING_HEADER(client->status))
                {
                    size_t len = msg_data_length((msg_t*)client->buffer);
                    if (len)
                    {
                        msg_t* msg = (msg_t*)client->buffer;
                        client->status = (client->status & ~CLIENT_STATUS_WAITING_HEADER) | CLIENT_STATUS_WAITING_BODY;
                        if (msg->zone.clip)
                        {
                            if (msg->zone.last) client->want = len % client->max_length;
                            else client->want = client->max_length;
                        }
                        else client->want = len;
                        client->buffer_len = sizeof(msg_t) + client->want;
                        client->buffer = group_pool_room_realloc(&this.group_pool, client->buffer, sizeof(msg_t) + client->want);
                        if (client->buffer == NULL)
                        {
                            SYSLOG(LOG_ERR, "Not enough memory");
                            vector_push_back(for_del, (void*)(long)active_vector_iterator_idx(iter), sizeof(active_vector_iterator_idx(iter)));
                            exit(1);
                        }
                        client->read = ((msg_t*)client->buffer)->data;
                    }
                    else process_msg(client, (msg_t*)client->buffer, for_del, active_vector_iterator_idx(iter));
                }
                else process_msg(client, (msg_t*)client->buffer, for_del, active_vector_iterator_idx(iter));
            }
        }
        checkout_ttl(&client->recv_table);
end:
        iter = active_vector_next(iter);
    }
}
Esempio n. 4
0
ssize_t read_msg_t(client_t* client, msg_t** msg, double timeout)
{
    if (qtun->use_udp)
    {
        *msg = pool_room_realloc(&qtun->pool, RECV_ROOM_IDX, qtun->recv_buffer_len);
        return read_t(client, *msg, qtun->recv_buffer_len, timeout);
    }
    else
    {
        ssize_t rc;
        size_t len;

        *msg = pool_room_realloc(&qtun->pool, RECV_ROOM_IDX, sizeof(msg_t));
        if (*msg == NULL) return -2;
        rc = read_t(client, *msg, sizeof(**msg), timeout);
        if (rc <= 0)
        {
            pool_room_free(&qtun->pool, RECV_ROOM_IDX);
            *msg = NULL;
            return rc;
        }
        len = msg_data_length(*msg);
        *msg = pool_room_realloc(&qtun->pool, RECV_ROOM_IDX, sizeof(msg_t) + len);
        if (*msg == NULL) return -2;
        rc = read_t(client, (*msg)->data, len, timeout);
        if (rc <= 0 && len)
        {
            pool_room_free(&qtun->pool, RECV_ROOM_IDX);
            *msg = NULL;
            return rc;
        }

        if (checksum(*msg, sizeof(msg_t) + len))
        {
            SYSLOG(LOG_ERR, "Invalid msg");
            pool_room_free(&qtun->pool, RECV_ROOM_IDX);
            *msg = NULL;
            return -2;
        }

        SYSLOG(LOG_INFO, "read msg length: %lu", (unsigned long)len);
        return rc + sizeof(msg_t);
    }
}
Esempio n. 5
0
ssize_t send_msg_group(client_t* client, msg_group_t* g)
{
    size_t i;
    ssize_t written, ret = 0;
    size_t left, fixed;
    if (g->count == 0) return -1;

    left = msg_data_length(g->elements[0]);
    fixed = qtun->max_length;
    for (i = 0; i < g->count - 1UL; ++i)
    {
        written = write_c(client, g->elements[i], sizeof(msg_t) + fixed);
        if (written <= 0) return written;
        ret  += written;
        left -= fixed;
    }
    written = write_c(client, g->elements[g->count - 1], sizeof(msg_t) + left);
    if (written <= 0) return written;
    return ret + written;
}
Esempio n. 6
0
int connect_server(char* ip, unsigned short port)
{
    int fd, rc;
    struct sockaddr_in addr = {0};
    msg_t* msg;
    int flag = 1;

    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1)
    {
        perror("socket");
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    if (inet_aton(ip, &addr.sin_addr) == 0)
    {
        fprintf(stderr, "Convert ip address error!\n");
        close(fd);
        return -1;
    }

    rc = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
    if (rc == -1)
    {
        perror("connect");
        close(fd);
        return -1;
    }

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

    msg = new_login_msg(this.localip, 0, 1);
    if (msg)
    {
        write_n(fd, msg, sizeof(msg_t) + msg_data_length(msg));
        pool_room_free(&this.pool, MSG_ROOM_IDX);
        if (read_msg_t(fd, &msg, 5) > 0)
        {
            unsigned int ip;
            unsigned char mask;
            if (msg->compress != this.compress || msg->encrypt != this.encrypt)
            {
                fprintf(stderr, "compress algorithm or encrypt algorithm is not same\n");
                pool_room_free(&this.pool, RECV_ROOM_IDX);
                goto end;
            }
            if (!parse_login_reply_msg(msg, &ip, &mask)) goto end;
            pool_room_free(&this.pool, RECV_ROOM_IDX);
            if (ip == 0)
            {
                fprintf(stderr, "Not enough ip address\n");
                goto end;
            }
            if (ip != this.localip)
            {
                struct in_addr a;
                char saddr[16], daddr[16];
                a.s_addr = this.localip;
                strcpy(saddr, inet_ntoa(a));
                a.s_addr = ip;
                strcpy(daddr, inet_ntoa(a));
                fprintf(stderr, "%s is inuse, but %s is not inuse\n", saddr, daddr);
                goto end;
            }
            this.netmask = mask;
            this.keepalive = time(NULL);
            return fd;
        }
        fprintf(stderr, "read sys_login_reply message timeouted\n");
        goto end;
    }
    fprintf(stderr, "Not enough memory\n");
end:
    close(fd);
    return -1;
}
Esempio n. 7
0
static int client_process(int max, fd_set* set, int remotefd, int localfd)
{
    msg_t* msg;
    if (FD_ISSET(localfd, set))
    {
        unsigned char buffer[2048];
        ssize_t readen;

        readen = read(localfd, buffer, sizeof(buffer));
        if (readen > 0)
        {
            msg = new_msg(buffer, readen);
            if (msg)
            {
                write_n(remotefd, msg, sizeof(msg_t) + msg_data_length(msg));
                pool_room_free(&this.pool, MSG_ROOM_IDX);
                printf("send msg length: %lu\n", msg_data_length(msg));
            }
        }
    }
    if (FD_ISSET(remotefd, set))
    {
        ssize_t rc = read_pre(remotefd, this.client.read, this.client.want);
        if (rc == 0)
        {
            fprintf(stderr, "connection closed\n");
            return RETURN_CONNECTION_CLOSED;
        }
        else if (rc < 0)
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK) return RETURN_OK;
            fprintf(stderr, "read error\n");
            perror("read");
            return RETURN_READ_ERROR;
        }
        else
        {
            this.client.read += rc;
            this.client.want -= rc;
            if (this.client.want == 0)
            {
                if (IS_CLIENT_STATUS_WAITING_HEADER(this.client.status))
                {
                    size_t len = msg_data_length((msg_t*)this.client.buffer);
                    if (len)
                    {
                        this.client.status = (this.client.status & ~CLIENT_STATUS_WAITING_HEADER) | CLIENT_STATUS_WAITING_BODY;
                        this.client.want = len;
                        this.client.buffer = pool_room_realloc(&this.pool, RECV_ROOM_IDX, sizeof(msg_t) + this.client.want);
                        if (this.client.buffer == NULL)
                        {
                            fprintf(stderr, "Not enough memory\n");
                            exit(1);
                        }
                        this.client.read = ((msg_t*)this.client.buffer)->data;
                    }
                    else process_msg((msg_t*)this.client.buffer, localfd);
                }
                else process_msg((msg_t*)this.client.buffer, localfd);
            }
        }
    }
    return RETURN_OK;
}
Esempio n. 8
0
static void server_process_login(client_t* client, msg_t* msg, size_t idx, vector_t* for_del)
{
    sys_login_msg_t* login;
    msg_t* new_msg;
    int sys;
    void* data = NULL;
    unsigned short len;
    size_t room_id;

    if (!IS_CLIENT_STATUS_CHECKLOGIN(client->status))
    {
        SYSLOG(LOG_ERR, "Invalid status, want(%d) current(%d)", CLIENT_STATUS_CHECKLOGIN, client->status);
        close_client(for_del, idx);
        goto end;
    }
    if (msg->compress != this.compress || msg->encrypt != this.encrypt) // 算法不同直接将本地的加密压缩算法返回
    {
        msg->compress = this.compress;
        msg->encrypt = this.encrypt;
        msg->checksum = 0;
        msg->checksum = checksum(msg, sizeof(msg_t) + msg_data_length(msg));
        write_c(client, msg, sizeof(msg_t) + msg_data_length(msg));
        goto end;
    }
    if (!parse_msg(msg, &sys, &data, &len, &room_id))
    {
        SYSLOG(LOG_ERR, "parse sys_login_request failed");
        close_client(for_del, idx);
        goto end;
    }
    login = (sys_login_msg_t*)data;
    if (memcmp(login->check, SYS_MSG_CHECK, sizeof(login->check)) ||
        !check_ip_by_mask(login->ip, this.localip, this.netmask)) // 非法数据包
    {
        SYSLOG(LOG_ERR, "unknown sys_login_request message");
        close_client(for_del, idx);
        goto end;
    }
    if (login->ip == this.localip || active_vector_exists(&this.clients, compare_clients_by_local_ip, (void*)(long)login->ip, sizeof(login->ip)) >= 0) // IP已被占用
    {
        unsigned short i;
        unsigned int localip = login->ip & LEN2MASK(this.netmask);
        for (i = 1; i < LEN2MASK(32 - this.netmask); ++i)
        {
            unsigned int newip = (i << this.netmask) | localip;
            if (active_vector_exists(&this.clients, compare_clients_by_local_ip, (void*)(long)newip, sizeof(newip)) == -1 && newip != this.localip)
            {
                pool_room_free(&this.pool, room_id);
                data = NULL;
                new_msg = new_login_msg(newip, 0, this.netmask, 0);
                if (new_msg)
                {
                    write_c(client, new_msg, sizeof(msg_t) + msg_data_length(new_msg));
                    pool_room_free(&this.pool, MSG_ROOM_IDX);
                }
                else
                {
                    SYSLOG(LOG_ERR, "Can not create login message");
                    close_client(for_del, idx);
                }
                goto end;
            }
        }
        pool_room_free(&this.pool, room_id);
        data = NULL;
        new_msg = new_login_msg(0, 0, 0, 0);
        if (new_msg)
        {
            write_c(client, new_msg, sizeof(msg_t) + msg_data_length(new_msg));
            pool_room_free(&this.pool, MSG_ROOM_IDX);
        }
        else
        {
            SYSLOG(LOG_ERR, "Can not create login message");
            close_client(for_del, idx);
        }
    }
    else
    {
        unsigned int remote_ip = login->ip;
        unsigned short internal_mtu = ntohs(login->internal_mtu);
        pool_room_free(&this.pool, room_id);
        data = NULL;
        new_msg = new_login_msg(remote_ip, this.localip, this.netmask, 0);
        if (new_msg == NULL)
        {
            SYSLOG(LOG_ERR, "Can not create login message");
            close_client(for_del, idx);
            goto end;
        }
        client->local_ip = remote_ip;
        client->keepalive = (unsigned int)time(NULL);
        client->internal_mtu = internal_mtu;
        client->max_length = ROUND_UP(client->internal_mtu - sizeof(msg_t) - sizeof(struct iphdr) - (this.use_udp ? sizeof(struct udphdr) : sizeof(struct tcphdr)), 8);
        client->status = CLIENT_STATUS_NORMAL;
        if (this.use_udp && client->max_length + sizeof(msg_t) > this.recv_buffer_len)
        {
            this.recv_buffer_len = client->max_length + sizeof(msg_t);
            this.recv_buffer = pool_room_realloc(&this.pool, RECV_ROOM_IDX, this.recv_buffer_len);
            if (this.recv_buffer == NULL)
            {
                SYSLOG(LOG_INFO, "Not enough memory");
                close_client(for_del, idx);
                goto end;
            }
        }
#ifdef WIN32 // 将对端内网IP添加到ARP表
        {
            char cmd[1024];
            char str[16];
            struct in_addr a;
            a.s_addr = remote_ip;
            strcpy(str, inet_ntoa(a));
            sprintf(cmd, "arp -s %s ff-ff-ff-ff-ff-ff", str); // TODO: get mac from remote
            SYSTEM_NORMAL(cmd);
        }
#endif
        write_c(client, new_msg, sizeof(msg_t) + msg_data_length(new_msg));
        pool_room_free(&this.pool, MSG_ROOM_IDX);
    }
end:
    if (data) pool_room_free(&this.pool, room_id);
}