int restore_client(char*ipaddr, int port, char*clientpath, char*auxpath) /* Purpose:Restore the path of a specific client. Transmit the archives from my (the server's) local storage loc. Params: clientno - client# in g_clientlist[] clientpath - client's path to be restored Return: result (0=success, nonzero=failure) */ { struct s_server2client_msg_record rec_to_client; int res=0, socket_fd, len, i; char tmp[MAX_STR_LEN+1], infile[MAX_STR_LEN+1]; FILE*fin; log_it(info, "%s - restoration of %s commencing", ipaddr, clientpath); // FIXME - don't assume the latest backup contains the files we want ;) sprintf(tmp, "find /var/spool/monitas/%s -type f | sort | tail -n1", ipaddr); strcpy(infile, call_program_and_get_last_line_of_output(tmp)); log_it(debug, "Restoring from data file '%s'", infile); if (!does_file_exist(infile)) { log_it(error, "Backup '%s' not found. That should be impossible.", infile); return(1); } log_it(debug, "Restoring %s - archive=%s", ipaddr, infile); rec_to_client.msg_type = trigger_restore; strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); strncpy(rec_to_client.bodyAux, auxpath, sizeof(rec_to_client.bodyAux)); if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) { log_it(error, "restore_client - failed to send msg to client"); return(1); } if (!(fin=fopen(infile, "r"))) { log_it(fatal, "Failed to openin temp data file"); } res += transmit_file_to_socket(fin, socket_fd); len=read(socket_fd, (char*)&i, sizeof(i)); if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondorestore"); } else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondorestore"); } else if (i) { res++; log_it(error, "Client said, mondorestore returned an error."); } else { log_it(debug, "Client said, mondorestore returned OK"); } fclose(fin); close(socket_fd); if (res>0) { log_it(error, "%s - error(s) occurred while restoring %s", ipaddr, clientpath); rec_to_client.msg_type = restore_fail; sprintf(rec_to_client.body, "Failed to restore %s", clientpath); log_it(debug, rec_to_client.body); } else { log_it(info, "%s - restored %s ok", ipaddr, clientpath); rec_to_client.msg_type = restore_ok; sprintf(rec_to_client.body, "%s - restored ok", clientpath); log_it(debug, rec_to_client.body); } if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) { log_it(error, "Unable to notify %s of restore success/failure", ipaddr); i = find_client_in_clientlist(ipaddr); if (i>=0) { forcibly_logout_client(i); } } return(res); }
int handle_ping_request(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP) /* Purpose:Handle a ping request which has just been received from client. Params: skt - client's port to talk to rec_from_client - ping record received from client clientIP - client's IP address, in string Return: result (0=success, nonzero=failure) */ { struct s_server2client_msg_record rec_to_client; int i; i = find_client_in_clientlist(clientIP); if (i < 0) { log_it(error, "Hey, %s isn't logged in. I'm not going to pong him.", clientIP); } else { rec_to_client.msg_type = pong; /* reply to ping */ sprintf(rec_to_client.body, "Hey, I'm replying to client#%d's ping. Pong! (re: %s", i, rec_from_client->body); send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); log_it(debug, rec_to_client.body); } return(0); }
void Cpvp::send_msg_to_all_users(Cmessage* out, mapid_t homeid, uint32_t opid) { DEBUG_LOG("Cpvp::send_msg_to_all_users(homeid = %lu, opid = %u)", homeid, opid); std::map<mapid_t,Cgame_item>::iterator map_it = homeid_game_map.find(homeid); Cgame_item& game_item = map_it->second; home_proto_t head_pkg; init_pkg_proto(&(head_pkg) ,0,61002,0, homeid , opid); std::set<uint32_t>::iterator set_it; for(set_it=game_item.userid_set.begin();set_it!=game_item.userid_set.end();++set_it){ uint32_t userid=*set_it; DEBUG_LOG("START SEND PKG: userid=%u ",userid); std::map<uint32_t, stru_pre_user_info>::iterator it; it = user_info_map.find(userid); if (it != user_info_map.end()) { stru_pre_user_info* p_pre_user_info = &(it->second); head_pkg.id = userid; head_pkg.onlineid = p_pre_user_info->onlineid; if ( all_fds[p_pre_user_info->onlineid]){ send_msg_to_client(all_fds[p_pre_user_info->onlineid], (char*)&head_pkg, out); } DEBUG_LOG("START SEND PKG " ); } } }
int forcibly_logout_client(int clientno) /* Purpose: Logout specific client(#) by force. Params: Client# in g_clientlist[] array. Returns: 0=success, nonzero=failure to get other end to hear me;) NB: The client was definitely removed from our login table. If the client got the message, return 0; else, nonzero. */ { struct s_server2client_msg_record rec_to_client; char tmp[MAX_STR_LEN+1]; int res=0; log_it(info, "Forcibly logging %s out", g_clientlist.el[clientno].ipaddr); rec_to_client.msg_type = logout_ok; /* to confirm logout */ strcpy(rec_to_client.body, "Server is shutting down. You are forced to logout"); res=send_msg_to_client(&rec_to_client, g_clientlist.el[clientno].ipaddr, g_clientlist.el[clientno].port, NULL); if (--g_clientlist.items > 0) { log_it(debug, "Moving clientlist[%d] to clientlist[%d]", clientno, g_clientlist.items); sprintf(tmp, "Was ipaddr=%s; now is ipaddr=", g_clientlist.el[clientno].ipaddr); memcpy((void*)&g_clientlist.el[clientno], (void*)&g_clientlist.el[g_clientlist.items], sizeof(struct s_registered_client_record)); strcat(tmp, g_clientlist.el[clientno].ipaddr); /* FIXME: tmp must never contain '%'-sequences */ log_it(debug, tmp); } return(res); }
inline int Online::send_msg_to_user(fdsession_t* fdsess,uint32_t uid, int cmd, Cmessage *c_in) { char pkg_head[256]; svr_proto_t* ppr = reinterpret_cast<svr_proto_t*>(pkg_head ); ppr->id = uid; ppr->seq=0; ppr->len = sizeof(svr_proto_t); ppr->cmd = cmd; ppr->ret = 0; if (send_msg_to_client(fdsess , pkg_head ,c_in) == -1) { ERROR_RETURN(("failed to send msg to user: cmd=%u", ppr->cmd), -1); } DEBUG_LOG("send_msg_to_user:cmd=%u",cmd); return 0; }
inline int Online::send_msg_to_online(uint32_t onlineid, int cmd, Cmessage *c_in) { char pkg_head[256]; svr_proto_t* ppr = reinterpret_cast<svr_proto_t*>(pkg_head ); ppr->id = 0; ppr->seq=0; ppr->len = sizeof(svr_proto_t); ppr->cmd = cmd; ppr->ret = 0; const online_info_t* olinfo = get_online_info(onlineid); if (olinfo && send_msg_to_client(olinfo->fdsess , pkg_head ,c_in) == -1) { ERROR_RETURN(("failed to send pkg to online: olid=%u cmd=%u",onlineid, ppr->cmd), -1); } DEBUG_LOG("send_msg_to_online:olid=%u cmd=%u",onlineid,cmd); return 0; }
int handle_logout_request(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP) /* Purpose:Handle a logout request which has just been received from client. Params: skt - client's port to talk to rec_from_client - logout rq record received from client clientIP - client's IP address, in string Return: result (0=success, nonzero=failure) */ { struct s_server2client_msg_record rec_to_client; int i, res=0; i = find_client_in_clientlist(clientIP); if (i<0) { sprintf(rec_to_client.body, "Client is not logged in yet. How can I log him out?"); log_it(error, rec_to_client.body); rec_to_client.msg_type = logout_fail; res=1; } else if (g_clientlist.el[i].busy) { sprintf(rec_to_client.body, "Client is working. I shouldn't log him out."); log_it(error, rec_to_client.body); rec_to_client.msg_type = logout_fail; res=1; } else { sprintf(rec_to_client.body, "Removed client#%d from login table. Thanks for logging out.", i); for(; i<g_clientlist.items; i++) { memcpy((char*)(&g_clientlist.el[i]), (char*)(&g_clientlist.el[i+1]), sizeof(struct s_registered_client_record)); } strncpy(g_clientlist.el[i].hostname_pretty, "WTF? Someone teach Hugo to handle pointers properly, please!", sizeof(g_clientlist.el[i].hostname_pretty)); g_clientlist.items--; rec_to_client.msg_type = logout_ok; /* to confirm logout */ log_it(info, "Logout request from %s ACCEPTED", clientIP); } send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); return(res); }
void Cpvp::send_msg_to_a_user(Cmessage* msg,mapid_t homeid, userid_t uid, uint32_t opid) { DEBUG_LOG("Cpvp::send_msg_to_a_user(homeid = %lu, userid = %u, opid = %u)", homeid, uid, opid); home_proto_t head_pkg; init_pkg_proto(&(head_pkg) ,0,61002,0, homeid , opid); DEBUG_LOG("START SEND PKG: userid=%u ",uid); std::map<uint32_t, stru_pre_user_info>::iterator it = user_info_map.find(uid); if (it != user_info_map.end()) { stru_pre_user_info* p_pre_user_info = &(it->second); head_pkg.id= uid; head_pkg.onlineid= p_pre_user_info->onlineid; if ( all_fds[p_pre_user_info->onlineid]){ send_msg_to_client(all_fds[p_pre_user_info->onlineid], (char*)&head_pkg, msg); } DEBUG_LOG("START SEND PKG " ); } }
int handle_login_request(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP) /* Purpose:Handle a login request which has just been received from client. Params: skt - client's port to talk to rec_from_client - login rq record received from client clientIP - client's IP address, in string Return: result (0=success, nonzero=failure) */ { struct s_server2client_msg_record rec_to_client; int clientno; //FIXME - lock g_clientlist[] clientno = find_client_in_clientlist(clientIP); if (clientno>=0) { rec_to_client.msg_type = login_fail; sprintf(rec_to_client.body, "Sorry, you're already logged in!"); log_it(error, "Ignoring login rq from %s: he's already logged in.", clientIP); /* FIXME - ping client (which will have a child watching for incoming packets by now - you didn't forget to do that, did you? :)) - to find out if client is still running. If it's not then say OK, forget it, I'll kill that old connection and log you in anew. If it _is_ then say hey, you're already logged in; either you're an idiot or you're a hacker. */ } else { rec_to_client.msg_type = login_ok; /* to confirm login */ sprintf(rec_to_client.body, "Thanks for logging in."); clientno = g_clientlist.items; strncpy(g_clientlist.el[clientno].hostname_pretty, rec_from_client->body, sizeof(g_clientlist.el[clientno].hostname_pretty)); strncpy(g_clientlist.el[clientno].ipaddr, clientIP, sizeof(g_clientlist.el[clientno].ipaddr)); g_clientlist.el[clientno].port = rec_from_client->port; g_clientlist.el[clientno].busy = false; g_clientlist.items ++; log_it(info, "Login request from %s ACCEPTED", clientIP); strcpy(g_clientlist.el[clientno].last_progress_rpt, "Logged in"); } send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); return(0); }
int send_to_player(c_player *p, btlsw_proto_t *p_header, Cmessage *p_out, bool complete) { assert(p); p_header->id = p->m_id; TRACE_TLOG("send_to_player[%u]: u=%u, online_id=%u, seq=%u, ret=%u", p_header->cmd, p->m_id, p->get_online()->m_id, p_header->seq, p_header->ret); if (-1 == send_msg_to_client(p->get_online()->m_fdsess, (char *)p_header, p_out)) { ERROR_TLOG("send_to_player failed[%u] u=%u, online_id=%u, seq=%u", p_header->cmd, p->m_id, p->get_online()->m_id, p_header->seq); return -1; } if (complete) { p->clear_waitcmd(); } return 0; }
int backup_client(char*ipaddr, int port, char*clientpath) /* Purpose:Backup the path of a specific client. Receive the archives. Store them locally (on me, the server). Params: clientno - client# in g_clientlist[] clientpath - client's path to be backed up Return: result (0=success, nonzero=failure) */ { struct s_server2client_msg_record rec_to_client; int res=0, socket_fd, noof_archives, i, len; char tmp[MAX_STR_LEN+1], outfile[MAX_STR_LEN+1]; FILE*fout; log_it(info, "%s - backup of %s commencing", ipaddr, clientpath); sprintf(outfile, "/var/spool/monitas/%s/%lu.dat", ipaddr, time(NULL)); if (does_file_exist(outfile)) { log_it(error, "Backup storage location '%s' exists already. That should be impossible.", outfile); return(1); } if (make_hole_for_file(outfile)) { res++; log_it(error, "Cannot write archive to spool dir '%s'", outfile); } else if (!(fout=fopen(outfile, "w"))) { res++; log_it(fatal, "Failed to openout temp data file '%s'", outfile); } else { log_it(debug, "Backing up %s - archive=%s", ipaddr, outfile); rec_to_client.msg_type = trigger_backup; strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) { log_it(error, "backup_client - failed to send msg to client"); return(1); } res += receive_file_from_socket(fout, socket_fd); len=read(socket_fd, (char*)&i, sizeof(i)); if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondoarchive"); } else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondoarchive"); } else if (i) { res++; log_it(error, "Client said, mondoarchive returned an error."); } else { log_it(debug, "Client said, mondoarchive returned OK"); } fclose(fout); close(socket_fd); } /* Shuffle older backups off the mortal coil. Leave maximum of 4 backup files in /var/spool/monitas/[ipaddr] */ sprintf(tmp, "find /var/spool/monitas/%s -type f 2> /dev/null | grep -n \"\" | tail -n1 | cut -d':' -f1", ipaddr); noof_archives = atoi(call_program_and_get_last_line_of_output(tmp)); i = noof_archives - 3; if (i>0) { sprintf(tmp, "rm -f `find /var/spool/monitas/%s -type f | sort | head -n%d`", ipaddr, i); call_program_and_log_output(tmp); } /* Return success/failure value */ if (res>0) { log_it(error, "%s - error(s) occurred while backing up %s", ipaddr, clientpath); rec_to_client.msg_type = backup_fail; sprintf(rec_to_client.body, "Failed to backup %s", clientpath); log_it(debug, rec_to_client.body); unlink(outfile); } else { log_it(info, "%s - backed up %s ok", ipaddr, clientpath); rec_to_client.msg_type = backup_ok; sprintf(rec_to_client.body, "%s - backed up ok", clientpath); log_it(debug, rec_to_client.body); } if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) { res++; log_it(error, "Unable to notify %s of backup success/failure", ipaddr); i = find_client_in_clientlist(ipaddr); if (i>=0) { forcibly_logout_client(i); } log_it(info, "I'm assuming the backup was bad because the client cannot be reached."); unlink(outfile); } return(res); }