static int broadcast_to_client(CLIENT_MAP *client) { uint16_t fd_offset; uint16_t *fd; int i; int ret = 0; PROTO_HEAD *real_head; PROTO_HEAD_CONN_BROADCAST *head = (PROTO_HEAD_CONN_BROADCAST *)(client->buf); real_head = &head->real_head; fd_offset = htons(real_head->len) + offsetof(PROTO_HEAD_CONN_BROADCAST, real_head); fd = (uint16_t *)((char *)head + fd_offset); //check len if (fd_offset + sizeof(uint16_t) * head->num_fd != htons(head->len)) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: broadcast len wrong [%u] [%u]", __FUNCTION__, htons(real_head->len), htons(head->len)); return (-1); } for (i = 0; i < head->num_fd; ++i) { // if (send(fd[i], real_head, htons(real_head->len), 0) != htons(real_head->len)) { if (send_one_msg(fd[i], real_head, 1) != htons(real_head->len)) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: broadcast to client[%u] failed err[%d]", __FUNCTION__, fd[i], errno); ret = (-1); } } return (ret); }
static int send_logout_request(CLIENT_MAP *client) { PROTO_HEAD_CONN *head; LOGOUT_REQUEST *req; char sendbuf[sizeof(PROTO_HEAD_CONN) + sizeof(LOGOUT_REQUEST)]; head = (PROTO_HEAD_CONN *)(&sendbuf[0]); req = (LOGOUT_REQUEST *)(&sendbuf[sizeof(PROTO_HEAD_CONN)]); head->msg_id = htons(CS__MESSAGE__ID__LOGOUT_REQUEST); head->len = htons(sizeof(sendbuf)); head->fd = client->fd; req->reason = 0; CLIENT_MAP *server; server = get_first_client_map(&server_map_head); if (unlikely(!server)) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: do not have game server connected", __FUNCTION__); if (cache_to_gamesrv_buf((PROTO_HEAD *)head) != 0) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: cache_to_gamesrv_buf failed", __FUNCTION__); } return (0); } if (send_one_msg(server->fd, (PROTO_HEAD *)head, 0) != htons(head->len)) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: send to gameserver failed err[%d]", __FUNCTION__, errno); return (-1); } return (0); }
int fetch_role_handle(PROTO_HEAD *head, uint16_t fd, int len) { // int i; MYSQL_RES *res; MYSQL_ROW row; char sql[256]; FETCH_ROLE_DATA_RESPONSE *resp; char sendbuf[sizeof(PROTO_HEAD) + sizeof(*resp)]; FETCH_ROLE_DATA_REQUEST *request = (FETCH_ROLE_DATA_REQUEST *)head->data; resp = (FETCH_ROLE_DATA_RESPONSE *)(&sendbuf[sizeof(PROTO_HEAD)]); head = (PROTO_HEAD *)(&sendbuf[0]); resp->info.name[0] = '\0'; if (len != sizeof(PROTO_HEAD) + sizeof(FETCH_ROLE_DATA_REQUEST)) { log4c_category_log(mycat, LOG4C_PRIORITY_INFO, "%s: len[%d] with msg[%u] server[?] fail\n", __FUNCTION__, head->len, head->msg_id); return (-1); } sprintf(sql, "select id, name, profession, level, scene_id, pos_x, pos_y from DBRoleInfo where id = %lu", request->id); res = query(sql, 1, NULL); if (!res) { log4c_category_log(mycat, LOG4C_PRIORITY_INFO, "%s: can not fetch role %lu\n", __FUNCTION__, request->id); resp->result = -1; goto done; } row = fetch_row(res); if (!row) { log4c_category_log(mycat, LOG4C_PRIORITY_INFO, "%s: can not fetch role %lu\n", __FUNCTION__, request->id); resp->result = -1; goto done; } resp->result = 0; strcpy(resp->info.name, row[1]); resp->info.profession = atoi(row[2]); resp->info.level = atoi(row[3]); resp->info.scene_id = atoi(row[4]); resp->info.pos.pos_x = atoi(row[5]); resp->info.pos.pos_y = atoi(row[6]); // resp->bag.max_thing_num = 10; done: if (res) free_query(res); resp->id = request->id; head->len = htons(sizeof(sendbuf)); head->msg_id = htons(SERVER_PROTO_FETCH_ROLE_RESPONSE); send_one_msg(fd, head); // send(fd, sendbuf, sizeof(sendbuf), 0); return (0); }
/** *\brief 通过网络发送数据得发送函数,非阻塞的请求模式,需要上层自己控制。 *\param fs 定义了套接子得相关属性。 *\param msg 定义了需要发送得消息。 *\param mlen 定义了需要发送得消息得长度。 *\param timeout_usec 定义消息发送得超时时间。 *\retval E_OK 表示成功。 */ e_int32 fsocket_send(fsocket_t *fs, e_uint8 *msg, e_uint32 mlen, e_uint32 timeout_usec) { e_int32 ret; e_assert(fs&&fs->state, E_ERROR_INVALID_HANDLER); ret = semaphore_timeoutwait(&fs->send_sem, timeout_usec); e_assert(ret, E_ERROR_INVALID_CALL); ret = send_one_msg(fs, msg, mlen, timeout_usec); //处理完成,提醒可以发下一个请求了,非阻塞的请求模式 semaphore_post(&fs->send_sem); return ret; }
int send_to_game_srv(int fd, PROTO_HEAD *head) { if (send_one_msg(fd, head, 0) != htons(head->len)) { log4c_category_log(mycat, LOG4C_PRIORITY_INFO, "%s: failed, cache it", __FUNCTION__); if (cache_to_gamesrv_buf(head) != 0) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: cache_to_gamesrv_buf failed", __FUNCTION__); } return (-1); } return (0); }
static int send_all_cached_gamesrv_buf(int fd) { PROTO_HEAD *head; int i; int len; if (cached_len <= 0) return (0); for (i = 0; i < cached_len; i += len) { head = (PROTO_HEAD *)&cached_buf[i]; len = htons(head->len); if (send_one_msg(fd, head, 0) != len) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: send to gameserver failed err[%d]", __FUNCTION__, errno); cached_len = 0; return (-1); } } cached_len = 0; return (0); }
static int transfer_to_client(CLIENT_MAP *client) { uint16_t old_len, old_msgid; PROTO_HEAD *head; PROTO_HEAD_CONN *head_conn; uint16_t fd; assert(client); head = (PROTO_HEAD *)(client->buf + sizeof(uint16_t)); head_conn = (PROTO_HEAD_CONN *)(client->buf); if (head_conn->msg_id == SERVER_PROTO_BROADCAST) return broadcast_to_client(client); else if (htons(head_conn->msg_id) == SERVER_PROTO_KICK_ROLE_NOTIFY) return kick_role(client); fd = head_conn->fd; old_len = htons(head_conn->len); old_msgid = htons(head_conn->msg_id); head->msg_id = head_conn->msg_id; head->len = htons(old_len - sizeof(uint16_t)); if (old_len == 0) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: len wrong drop all msg", __FUNCTION__); return (-1); } // int ret = send(fd, head, htons(head->len), 0); int ret = send_one_msg(fd, head, 1); if (ret != htons(head->len)) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: send to client failed err[%d]", __FUNCTION__, errno); return (0); } head_conn->len = htons(old_len); head_conn->msg_id = htons(old_msgid); return (0); }
int create_role_handle(PROTO_HEAD *head, uint16_t fd, int len) { uint64_t effect = 0; CREATE_ROLE_REQUEST *req = (CREATE_ROLE_REQUEST *)&head->data; CREATE_ROLE_RESPONSE *resp; char sendbuf[sizeof(PROTO_HEAD) + sizeof(*resp)]; char sql[256]; char *p = sql; resp = (CREATE_ROLE_RESPONSE *)(&sendbuf[sizeof(PROTO_HEAD)]); head = (PROTO_HEAD *)(&sendbuf[0]); p += sprintf(sql, "insert into DBRoleInfo set id = %lu, profession = %u, scene_id = 1, pos_x = 1000, pos_y = 500, name = \'", req->id, req->profession); p += escape_string(p, req->name, strlen(req->name)); *p++ = '\''; *p++ = '\0'; query(sql, 1, &effect); if (effect != 1) { log4c_category_log(mycat, LOG4C_PRIORITY_INFO, "%s: execute query for %u %s failed\n", __FUNCTION__, req->id, req->name); resp->result = -1; goto done; } resp->result = 0; memcpy(resp->info.name, req->name, sizeof(resp->info.name)); resp->info.profession = req->profession; resp->info.level = 1; resp->info.scene_id = 1; resp->info.pos.pos_x = 1000; resp->info.pos.pos_y = 500; done: head->len = htons(sizeof(sendbuf)); head->msg_id = htons(SERVER_PROTO_CREATE_ROLE_RESPONSE); resp->id = req->id; send_one_msg(fd, head); return (0); }
static int transfer_to_gameserver(CLIENT_MAP *client) { uint16_t old_len; PROTO_HEAD *head; PROTO_HEAD_CONN *head_conn; CLIENT_MAP *server; assert(client); head = (PROTO_HEAD *)CLIENT_MAP_BUF_HEAD(client); head_conn = (PROTO_HEAD_CONN *)(client->buf); old_len = htons(head->len); head_conn->len = htons(old_len + sizeof(uint16_t)); head_conn->msg_id = head->msg_id; head_conn->fd = client->fd; server = get_first_client_map(&server_map_head); if (unlikely(!server)) { log4c_category_log(mycat, LOG4C_PRIORITY_INFO, "%s: do not have game server connected, cache it", __FUNCTION__); if (cache_to_gamesrv_buf((PROTO_HEAD *)head_conn) != 0) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: cache_to_gamesrv_buf failed", __FUNCTION__); } goto done; } if (send_one_msg(server->fd, (PROTO_HEAD *)head_conn, 0) != htons(head_conn->len)) { log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s: send to gameserver failed err[%d]", __FUNCTION__, errno); goto done; } done: head->len = htons(old_len); return (0); }
/** *\brief 网络连接发送请求函数。 *\param fs 定义了套接子得相关属性。 *\param msg 定义了发送请求消息。 *\param mlen 定义了发送请求消息长度。 *\param recv_buf 定义了接收缓存。 *\param recv_len 定义了接收消息长度。 *\param timeout_usec 定义了接收消息超时时间。 *\retval E_OK 表示成功。 */ e_int32 fsocket_request(fsocket_t *fs, e_uint8 *msg, e_uint32 mlen, e_uint8 *recv_buf, e_uint32 recv_len, e_uint32 timeout_usec) { e_int32 ret; e_uint8 req_id; e_uint8 s_id; int req_iid = -1, s_iid = -1; /* Timeval structs for handling timeouts */ e_uint32 beg_time, elapsed_time; e_assert(fs&&fs->state, E_ERROR_INVALID_HANDLER); // DMSG((STDOUT, "FAKE SOCKE [%s:%u] try request,current rq_id=%u...\r\n", fs->name, (unsigned int) fs->id,(unsigned int) fs->rq_id)); //请求发送锁 ret = semaphore_timeoutwait(&fs->send_sem, timeout_usec); e_assert(ret, E_ERROR_LOCK_FAILED); /* Acquire the elapsed time since epoch */ beg_time = GetTickCount(); //发送请求 ret = send_one_msg(fs, msg, mlen, timeout_usec); if (e_failed(ret)) goto END; //等待回复 elapsed_time = GetTickCount() - beg_time; while (timeout_usec <= 0 || (elapsed_time = GetTickCount() - beg_time) < timeout_usec) { if (timeout_usec <= 0) //没有设置超时,死等 { ret = wait_for_reply_forever(fs); } else { ret = wait_for_reply(fs, timeout_usec - elapsed_time); } if (!e_failed(ret)) { //取出消息,和请求号 recv_len = recv_len >= MSG_MAX_LEN ? MSG_MAX_LEN : recv_len; sscanf(fs->buf, "#%02X%02X%[^@]", &s_iid, &req_iid, recv_buf); s_id = s_iid & 0xFF; req_id = req_iid & 0xFF; //TODO:无视过时消息? if (req_id < fs->rq_id) { DMSG((STDOUT, "FAKE SOCKE [%s:%u:%u] 取到过时消息:id=%u \n忽略,继续等待下一个消息\n", fs->name, (unsigned int) fs->id, (unsigned int) fs->rq_id, (unsigned int) req_id)); continue; } else if (req_id > fs->rq_id) { // DMSG((STDOUT,"出现消息号异常,请检查!\n")); // while (1) // ; } break; } break; } END: //处理完成,提醒可以发下一个请求了 ret = semaphore_post(&fs->send_sem); e_assert(ret, E_ERROR_TIME_OUT); // DMSG( // (STDOUT, "[%s_%u_%u]FAKE SOCKET release send sem...\r\n", fs->name, (unsigned int)fs->id,(unsigned int)fs->rq_id)); elapsed_time = GetTickCount() - beg_time; if (MSG_LEVEL_VERBOSE) DMSG((STDOUT, "FAKE SOCKET [%s:%u:%u] request done in %u Ms...\r\n", fs->name, (unsigned int) fs->id, req_id, (int) (elapsed_time / 1000))); return E_OK; }