Пример #1
0
int send_to_client(ChatClient *cli, const char *msg, MsgType msg_type)
{
    ChatPacket *pkt = packet_new(SERV_NAME, cli->name);
    pkt->nmsg = 1;
    pkt->msg[0] = strdup(msg);
    pkt->time = gettime();
    pkt->type = get_msg_type(msg_type);
    cli->pktsnd = pkt;
    return client_flush(cli);
}
Пример #2
0
/**
 * @brief 客户端注册账号
 *
 * @param cli    客户端
 * @param user_name 用户名
 * @param pwd 密码
 *
 * @return 
 */
int client_register(ChatClient *cli)
{
    ChatPacket *pkt = packet_new(cli->name, SERV_NAME);
    pkt->nmsg = 2;
    pkt->msg[0] = strdup(g_cmd[CMD_REGISTER]);
    pkt->msg[1] = strdup(cli->password);
    pkt->time = gettime();
    cli->pktsnd = pkt;
    return client_flush(cli);
}
Пример #3
0
// 客户端的写协程处理过程
static void fiber_writer(user_client* client)
{
    client->set_waiter();
    client->set_waiting(true);

    while (true)
    {
        int mtype;

        // 等待消息通知
        client->wait(mtype);

        // 从本身消息队列中提取消息并发送至本客户端
        if (client_flush(client) == false)
        {
            printf("%s(%d), user: %s, flush error %s\r\n",
                   __FUNCTION__, __LINE__, client->get_name(),
                   acl::last_serror());
            break;
        }

#ifdef USE_CHAN
        if (mtype == MT_LOGOUT)
        {
            printf("%s(%d), user: %s, MT_LOGOUT\r\n",
                   __FUNCTION__, __LINE__, client->get_name());
            break;
        }
        if (mtype == MT_KICK)
        {
            printf("%s(%d), user: %s, MT_KICK\r\n",
                   __FUNCTION__, __LINE__, client->get_name());
            client->get_stream().write("You're kicked\r\n");
            break;
        }
#else
        if (client->exiting())
        {
            printf("%s(%d), user: %s exiting\r\n",
                   __FUNCTION__, __LINE__, client->get_name());
            break;
        }
#endif
    }

    client->set_waiting(false);
    printf(">>%s(%d), user: %s, logout\r\n", __FUNCTION__, __LINE__,
           client->get_name());

    // 通知该客户端退出
    client_logout(client);

    printf("-------__nwriter: %d-----\r\n", --__nwriter);
}
Пример #4
0
/******************************************************************
 * This function is called when an event occurs on a client socket
 ******************************************************************/
void client_cb(int fd, short events, void *arg)
{
    assert(arg != NULL);

    Client *cli = arg;
    int free = 0;

    // g_hash_table_foreach(g_jobqueue, _print_queue, NULL);

    if ((events & EV_WRITE) != 0) {
        event_del(&cli->evt);
        cli->evt.ev_events = EV_READ|EV_PERSIST;
        event_add(&cli->evt, NULL);
        if (client_flush(cli) < 0) {
            free = 1;
        }
    }
    if ((events & EV_READ) != 0) {
        int ret = 0;
        if (!cli->buffer_in) {
            cli->buffer_in = getBlock(HEADER_SIZE);
            incRef(cli->buffer_in);
            ret = client_recv(cli, HEADER_SIZE);
        }
        if (ret >= 0) {
            /* Make sure we don't over-read into the next packet */
            int psize = HEADER_SIZE;
            if (cli->buffer_in->nbytes >= HEADER_SIZE) {
                if (ntohl(*(uint32_t*)(cli->buffer_in->bytes + HEADER_OFFSET_MAGIC)) != MAGIC_REQUEST) {
                    free = 1;
                    g_warning("[%s] Invalid MAGIC", cli->id);
                    goto free_client;
                }
                psize = HEADER_SIZE + ntohl(*(uint32_t*)(cli->buffer_in->bytes + HEADER_OFFSET_SIZE));
                /* If the input block isn't large enough to receive the
                   entire packet then switch to one that is */
                if (psize > cli->buffer_in->size) {
                    #if DEBUG
                    g_debug("Switching to bigger block (pktsize=%d)", psize);
                    #endif

                    /* Create new (bigger) block */
                    MemBlock *block = getBlock(psize + 1); /* +1 for terminating NULL to make args easier to work with */
					if (!block) {
                        g_error("Failed to get block of size %d", psize);
						free = 1;
						goto free_client;
					}
                    incRef(block);

                    /* Copy bytes into new block */
                    block->nbytes = cli->buffer_in->nbytes;
                    memmove(block->bytes, cli->buffer_in->bytes, cli->buffer_in->nbytes);

                    /* Swap blocks */
                    decRef(cli->buffer_in);
                    cli->buffer_in = block;
                }
            }
            int num = psize - cli->buffer_in->nbytes;
            if (num > 0)
                ret = client_recv(cli, num);
        }
        if (ret < 0) {
            #if DEBUG
            g_debug("[%s] Connection on closed", cli->id);
            #endif
            free = 1;
        } else if (ret >= 0) {
            if (process_client(cli) != 0) {
                g_warning("[%s] Processing of client failed", cli->id);
                free = 1;
            }
        }
    }
    /*if ((events & (EV_READ|EV_WRITE)) == 0) {
        g_warning("[%s] unhandled event %d", __func__, events);
    }*/

free_client:
    if (free != 0) {
        #if DEBUG
        g_message("[%s] Client disconnected", cli->id);
        #endif

        /*printf("[%s] Removing client %d\n", __func__, cli->fd);*/
        close(cli->fd);
        cli->fd = -1;

        fail_working_jobs(cli);
        stop_all_listening(cli);
        unregister_all_abilities(cli);

        event_del(&cli->evt);
        g_ptr_array_remove_fast(g_clients, cli);

        client_free(cli);
    }
}
Пример #5
0
/**
 * @brief 分析客户端输入的数据
 *
 * @param cli     客户端数据结构
 * @param input   输入的数据
 *
 * @return 
 */
int client_parse_input(ChatClient *cli, char *input)
{
    int ret = 0;
    int file_flag = 0;

    input = str_strip(input);    //去掉字符串首尾的空格
    if(input == NULL)
    {
        return -1;
    }

    char *to = NULL;
    char *msg = NULL;
    ServerCmd cmd = CMD_LAST;
    packet_free(cli->pktsnd);  //清空发送数据包
    cli->pktsnd = NULL;

    if(strncmp("to ", input, 3) == 0) //比较前三个字符
    {
        input += 3;
        if(line_parse(input, ':', &to, &msg) == 0)   //以:为分隔符,将字符串分成两段
        {
            cli->pktsnd = packet_new(cli->name, to);
        }
    }
    else if(strncmp("file to ", input, 8) == 0)
    {
        input += 8;
        if(line_parse(input, ':', &to, &msg) == 0)   //以:为分隔符,将字符串分成两段
        {
            cli->pktsnd = packet_new(cli->name, to);
        }
        file_flag = 1;
    }
    else if(strcmp(input, "whoison") == 0)
    {
        cli->pktsnd = packet_new(cli->name, SERV_NAME);
        cmd = CMD_WHOISON;
        msg = (char *) g_cmd[cmd];
    }
    else if(strcmp(input, "showuser") == 0)
    {
        cli->pktsnd = packet_new(cli->name, SERV_NAME);
        cmd = CMD_SHOWUSER;
        msg = (char *) g_cmd[cmd];
    }
    else if(strcmp(input, "help") == 0)
    {
        printf("\rto usr: msg            --------- send msg to 'usr'\n");
        printf("file to usr: filepath  --------- send file to 'usr'\n");
        printf("whoison                --------- check server who is online\n");
        printf("howuser                --------- check all users who are registered\n");
        printf("logout/bye/exit        --------- logout and exit client\n");

        return 0;
    }
    else if(strcmp(input, "logout") == 0 ||
            strcmp(input, "exit")   == 0 ||
            strcmp(input, "bye")    == 0)
    {
        cli->pktsnd = packet_new(cli->name, SERV_NAME);
        cmd = CMD_LOGOUT;
        msg = (char *) g_cmd[cmd];
    }

    if(file_flag)
    {
        cli->pktsnd->type = get_msg_type(MSG_FILE_SEND);    //设置发送的是文件类型
        packet_add_msg(cli->pktsnd, msg);

        FILE *fp = fopen(msg, "r");
        char buffer[MAXLEN];

		if (fp == NULL)
		{
			printf("File: %s Not Found!\n", msg);
		}
        else
        {
            bzero(buffer, MAXLEN);
            while(fgets(buffer, MAXLEN, fp) != NULL)
			{
                packet_add_msg(cli->pktsnd, buffer);
                bzero(buffer, MAXLEN);
			}
			fclose(fp);
			printf("File:\t%s Transfer Finished!\n", msg);
        }
        ret = client_flush(cli);
    }
    if(msg && cli->pktsnd)
    {
        cli->pktsnd->type = get_msg_type(MSG_TEXT_SEND);    //设置发送的是文字类型
        packet_add_msg(cli->pktsnd, msg);
        ret = client_flush(cli);
        if(cmd==CMD_LOGOUT)
        {
            exit(0);
        }
    }
    return ret;
}