// get reply from server. Caller must free buf // int RPC_CLIENT::get_reply(char*& mbuf) { char buf[8193]; MFILE mf; int n; while (1) { n = recv(sock, buf, 8192, 0); if (n <= 0) return ERR_READ; buf[n]=0; mf.puts(buf); if (strchr(buf, '\003')) break; } mf.get_buf(mbuf, n); return 0; }
/// Get reply from server. /// Caller must free the buffer. /// /// \param[in,out] mbuf Reference to a pointer which will point to the /// string received from the rpc-server. /// \return Zero on success, ERR_READ on error. int RPC_CLIENT::get_reply(char*& mbuf) { MFILE mf; int n; while (true) { char buf[8193]; n = recv(sock, buf, sizeof(buf) - 1, 0); if (n <= 0) { return ERR_READ; } buf[n]=0; mf.puts(buf); if (strchr(buf, '\003')) { break; } } mf.get_buf(mbuf, n); return 0; }
int GUI_RPC_CONN::handle_rpc() { int n, retval=0; MIOFILE mf; MFILE m; char* p; mf.init_mfile(&m); int left = GUI_RPC_REQ_MSG_SIZE - request_nbytes; #ifdef _WIN32 n = recv(sock, request_msg+request_nbytes, left, 0); #else n = read(sock, request_msg+request_nbytes, left); #endif if (n <= 0) { request_nbytes = 0; return ERR_READ; } request_nbytes += n; // buffer full? if (request_nbytes >= GUI_RPC_REQ_MSG_SIZE) { request_nbytes = 0; return ERR_READ; } request_msg[request_nbytes] = 0; if (!strncmp(request_msg, "OPTIONS", 7)) { char buf[1024]; sprintf(buf, "HTTP/1.1 200 OK\n" "Server: BOINC client\n" "Access-Control-Allow-Origin: *\n" "Access-Control-Allow-Methods: POST, GET, OPTIONS\n" "Content-Length: 0\n" "Keep-Alive: timeout=2, max=100\n" "Connection: Keep-Alive\n" "Content-Type: text/plain\n\n" ); send(sock, buf, strlen(buf), 0); request_nbytes = 0; if (log_flags.gui_rpc_debug) { msg_printf(0, MSG_INFO, "[gui_rpc] processed OPTIONS" ); } return 0; } bool http_request; if (complete_post_request(request_msg)) { http_request = true; } else { p = strchr(request_msg, 3); if (p) { *p = 0; http_request = false; } else { if (log_flags.gui_rpc_debug) { msg_printf(0, MSG_INFO, "[gui_rpc] partial GUI RPC Command = '%s'\n", request_msg ); } return 0; } } request_nbytes = 0; if (log_flags.gui_rpc_debug) { msg_printf(0, MSG_INFO, "[gui_rpc] GUI RPC Command = '%s'\n", request_msg ); } // Policy: // - the first auth failure gets an error message; after that, disconnect // - if we get an unexpected auth1 or auth2, disconnect mf.printf("<boinc_gui_rpc_reply>\n"); if (match_req(request_msg, "auth1")) { if (got_auth1 && auth_needed) { retval = ERR_AUTHENTICATOR; } else { handle_auth1(mf); got_auth1 = true; } } else if (match_req(request_msg, "auth2")) { if ((!got_auth1 || got_auth2) && auth_needed) { retval = ERR_AUTHENTICATOR; } else { retval = handle_auth2(request_msg, mf); got_auth2 = true; } } else if (auth_needed && !is_local) { auth_failure(mf); if (sent_unauthorized) { retval = ERR_AUTHENTICATOR; } sent_unauthorized = true; // operations that require authentication only for non-local clients start here. // Use this only for information that should be available to people // sharing this computer (e.g. what jobs are running) // but not for anything sensitive (passwords etc.) } else if (match_req(request_msg, "exchange_versions")) { handle_exchange_versions(mf); } else if (match_req(request_msg, "get_state")) { gstate.write_state_gui(mf); } else if (match_req(request_msg, "get_results")) { bool active_only = false; parse_bool(request_msg, "active_only", active_only); mf.printf("<results>\n"); gstate.write_tasks_gui(mf, active_only); mf.printf("</results>\n"); } else if (match_req(request_msg, "get_screensaver_tasks")) { handle_get_screensaver_tasks(mf); } else if (match_req(request_msg, "result_show_graphics")) { handle_result_show_graphics(request_msg, mf); } else if (match_req(request_msg, "get_file_transfers")) { gstate.write_file_transfers_gui(mf); } else if (match_req(request_msg, "get_simple_gui_info")) { handle_get_simple_gui_info(mf); } else if (match_req(request_msg, "get_project_status")) { handle_get_project_status(mf); } else if (match_req(request_msg, "get_disk_usage")) { handle_get_disk_usage(mf); } else if (match_req(request_msg, "get_messages")) { handle_get_messages(request_msg, mf); } else if (match_req(request_msg, "get_message_count")) { handle_get_message_count(request_msg, mf); } else if (match_req(request_msg, "get_host_info")) { handle_get_host_info(request_msg, mf); } else if (match_req(request_msg, "get_statistics")) { handle_get_statistics(request_msg, mf); } else if (match_req(request_msg, "get_newer_version")) { handle_get_newer_version(mf); } else if (match_req(request_msg, "get_cc_status")) { handle_get_cc_status(this, mf); } else if (match_req(request_msg, "get_all_projects_list")) { read_all_projects_list_file(mf); } else if (match_req(request_msg, "get_notices_public")) { handle_get_notices(request_msg, *this, mf, true); clear_notice_refresh(); // Operations that require authentication start here } else if (auth_needed) { auth_failure(mf); if (sent_unauthorized) { retval = ERR_AUTHENTICATOR; } sent_unauthorized = true; } else if (match_req(request_msg, "project_nomorework")) { handle_project_op(request_msg, mf, "nomorework"); } else if (match_req(request_msg, "project_allowmorework")) { handle_project_op(request_msg, mf, "allowmorework"); } else if (match_req(request_msg, "project_detach_when_done")) { handle_project_op(request_msg, mf, "detach_when_done"); } else if (match_req(request_msg, "project_dont_detach_when_done")) { handle_project_op(request_msg, mf, "dont_detach_when_done"); } else if (match_req(request_msg, "set_network_mode")) { handle_set_network_mode(request_msg, mf); } else if (match_req(request_msg, "run_benchmarks")) { handle_run_benchmarks(request_msg, mf); } else if (match_req(request_msg, "get_proxy_settings")) { handle_get_proxy_settings(request_msg, mf); } else if (match_req(request_msg, "set_proxy_settings")) { handle_set_proxy_settings(request_msg, mf); } else if (match_req(request_msg, "network_available")) { handle_network_available(request_msg, mf); } else if (match_req(request_msg, "abort_file_transfer")) { handle_file_transfer_op(request_msg, mf, "abort"); } else if (match_req(request_msg, "project_detach")) { handle_project_op(request_msg, mf, "detach"); } else if (match_req(request_msg, "abort_result")) { handle_result_op(request_msg, mf, "abort"); } else if (match_req(request_msg, "suspend_result")) { handle_result_op(request_msg, mf, "suspend"); } else if (match_req(request_msg, "resume_result")) { handle_result_op(request_msg, mf, "resume"); } else if (match_req(request_msg, "project_suspend")) { handle_project_op(request_msg, mf, "suspend"); } else if (match_req(request_msg, "project_resume")) { handle_project_op(request_msg, mf, "resume"); } else if (match_req(request_msg, "set_run_mode")) { handle_set_run_mode(request_msg, mf); } else if (match_req(request_msg, "set_gpu_mode")) { handle_set_gpu_mode(request_msg, mf); } else if (match_req(request_msg, "quit")) { handle_quit(request_msg, mf); } else if (match_req(request_msg, "auth_monitor")) { handle_auth_monitor(request_msg, is_local, mf); } else if (match_req(request_msg, "update_project_apps")) { handle_update_projects_apps(request_msg, is_local, mf); } else if (match_req(request_msg, "update_project_apps_poll")) { handle_update_projects_apps_poll(request_msg, is_local, mf); } else if (match_req(request_msg, "acct_mgr_info")) { handle_acct_mgr_info(request_msg, mf); } else if (match_req(request_msg, "read_global_prefs_override")) { mf.printf("<success/>\n"); gstate.read_global_prefs(); gstate.request_schedule_cpus("Preferences override"); gstate.request_work_fetch("Preferences override"); } else if (match_req(request_msg, "get_project_init_status")) { handle_get_project_init_status(request_msg, mf); } else if (match_req(request_msg, "get_global_prefs_file")) { handle_get_global_prefs_file(mf); } else if (match_req(request_msg, "get_global_prefs_working")) { handle_get_global_prefs_working(mf); } else if (match_req(request_msg, "get_global_prefs_override")) { handle_get_global_prefs_override(mf); } else if (match_req(request_msg, "set_global_prefs_override")) { handle_set_global_prefs_override(request_msg, mf); } else if (match_req(request_msg, "get_cc_config")) { handle_get_cc_config(mf); } else if (match_req(request_msg, "set_cc_config")) { handle_set_cc_config(request_msg, mf); } else if (match_req(request_msg, "read_cc_config")) { mf.printf("<success/>\n"); read_config_file(false); config.show(); log_flags.show(); gstate.set_ncpus(); gstate.request_schedule_cpus("Core client configuration"); gstate.request_work_fetch("Core client configuration"); #ifndef USE_REC } else if (match_req(request_msg, "set_debts")) { handle_set_debts(request_msg, mf); #endif } else if (match_req(request_msg, "get_notices")) { handle_get_notices(request_msg, *this, mf, false); clear_notice_refresh(); } else if (match_req(request_msg, "battery_info")) { handle_battery_info(request_msg, is_local, mf); } else { // RPCs after this point require authentication, // and enable network communication for 5 minutes, // overriding other factors. // Things like attaching projects, etc. // double saved_time = gstate.gui_rpcs.time_of_last_rpc_needing_network; gstate.gui_rpcs.time_of_last_rpc_needing_network = gstate.now; if (match_req(request_msg, "retry_file_transfer")) { handle_file_transfer_op(request_msg, mf, "retry"); } else if (match_req(request_msg, "project_reset")) { handle_project_op(request_msg, mf, "reset"); } else if (match_req(request_msg, "project_update")) { handle_project_op(request_msg, mf, "update"); } else if (match_req(request_msg, "get_project_config")) { handle_get_project_config(request_msg, mf); } else if (match_req(request_msg, "get_project_config_poll")) { handle_get_project_config_poll(request_msg, mf); } else if (match_req(request_msg, "lookup_account")) { handle_lookup_account(request_msg, mf); } else if (match_req(request_msg, "lookup_account_poll")) { handle_lookup_account_poll(request_msg, mf); } else if (match_req(request_msg, "create_account")) { handle_create_account(request_msg, mf); } else if (match_req(request_msg, "create_account_poll")) { handle_create_account_poll(request_msg, mf); } else if (match_req(request_msg, "project_attach")) { handle_project_attach(request_msg, mf); } else if (match_req(request_msg, "project_attach_poll")) { handle_project_attach_poll(request_msg, mf); } else if (match_req(request_msg, "acct_mgr_rpc")) { handle_acct_mgr_rpc(request_msg, mf); } else if (match_req(request_msg, "acct_mgr_rpc_poll")) { handle_acct_mgr_rpc_poll(request_msg, mf); // DON'T JUST ADD NEW RPCS HERE - THINK ABOUT THEIR // AUTHENTICATION AND NETWORK REQUIREMENTS FIRST } else { mf.printf("<error>unrecognized op: %s</error>\n", request_msg); gstate.gui_rpcs.time_of_last_rpc_needing_network = saved_time; } } mf.printf("</boinc_gui_rpc_reply>\n\003"); m.get_buf(p, n); if (http_request) { char buf[1024]; sprintf(buf, "HTTP/1.1 200 OK\n" "Date: Fri, 31 Dec 1999 23:59:59 GMT\n" "Server: BOINC client\n" "Connection: close\n" "Content-Type: text/xml; charset=utf-8\n" "Content-Length: %d\n\n", n ); send(sock, buf, strlen(buf), 0); } if (p) { send(sock, p, n, 0); p[n-1]=0; // replace 003 with NULL if (log_flags.gui_rpc_debug) { if (n > 128) p[128] = 0; msg_printf(0, MSG_INFO, "[gui_rpc] GUI RPC reply: '%s'\n", p ); } free(p); } return retval; }
int GUI_RPC_CONN::handle_rpc() { char request_msg[4096]; int n, retval=0; MIOFILE mf; MFILE m; char* p; mf.init_mfile(&m); // read the request message in one read() // so that the core client won't hang because // of malformed request msgs // #ifdef _WIN32 n = recv(sock, request_msg, 4095, 0); #else n = read(sock, request_msg, 4095); #endif if (n <= 0) return ERR_READ; request_msg[n-1] = 0; // replace 003 with NULL if (log_flags.guirpc_debug) { msg_printf(0, MSG_INFO, "[guirpc_debug] GUI RPC Command = '%s'\n", request_msg ); } // Policy: // - the first auth failure gets an error message; after that, disconnect // - if we get an unexpected auth1 or auth2, disconnect mf.printf("<boinc_gui_rpc_reply>\n"); if (match_req(request_msg, "auth1")) { if (got_auth1 && auth_needed) { retval = ERR_AUTHENTICATOR; } else { handle_auth1(mf); got_auth1 = true; } } else if (match_req(request_msg, "auth2")) { if ((!got_auth1 || got_auth2) && auth_needed) { retval = ERR_AUTHENTICATOR; } else { retval = handle_auth2(request_msg, mf); got_auth2 = true; } } else if (auth_needed && !is_local) { auth_failure(mf); if (sent_unauthorized) { retval = ERR_AUTHENTICATOR; } sent_unauthorized = true; // operations that require authentication only for non-local clients start here. // Use this only for information that should be available to people // sharing this computer (e.g. what jobs are running) // but not for anything sensitive (passwords etc.) } else if (match_req(request_msg, "exchange_versions")) { handle_exchange_versions(mf); } else if (match_req(request_msg, "get_state")) { gstate.write_state_gui(mf); } else if (match_req(request_msg, "get_results")) { bool active_only = false; parse_bool(request_msg, "active_only", active_only); mf.printf("<results>\n"); gstate.write_tasks_gui(mf, active_only); mf.printf("</results>\n"); } else if (match_req(request_msg, "get_screensaver_tasks")) { handle_get_screensaver_tasks(mf); } else if (match_req(request_msg, "result_show_graphics")) { handle_result_show_graphics(request_msg, mf); } else if (match_req(request_msg, "get_file_transfers")) { gstate.write_file_transfers_gui(mf); } else if (match_req(request_msg, "get_simple_gui_info")) { handle_get_simple_gui_info(mf); } else if (match_req(request_msg, "get_project_status")) { handle_get_project_status(mf); } else if (match_req(request_msg, "get_disk_usage")) { handle_get_disk_usage(mf); } else if (match_req(request_msg, "get_messages")) { handle_get_messages(request_msg, mf); } else if (match_req(request_msg, "get_message_count")) { handle_get_message_count(request_msg, mf); } else if (match_req(request_msg, "get_host_info")) { handle_get_host_info(request_msg, mf); } else if (match_req(request_msg, "get_statistics")) { handle_get_statistics(request_msg, mf); } else if (match_req(request_msg, "get_newer_version")) { handle_get_newer_version(mf); } else if (match_req(request_msg, "get_cc_status")) { handle_get_cc_status(this, mf); } else if (match_req(request_msg, "get_all_projects_list")) { read_all_projects_list_file(mf); // Operations that require authentication start here } else if (auth_needed) { auth_failure(mf); if (sent_unauthorized) { retval = ERR_AUTHENTICATOR; } sent_unauthorized = true; } else if (match_req(request_msg, "project_nomorework")) { handle_project_op(request_msg, mf, "nomorework"); } else if (match_req(request_msg, "project_allowmorework")) { handle_project_op(request_msg, mf, "allowmorework"); } else if (match_req(request_msg, "project_detach_when_done")) { handle_project_op(request_msg, mf, "detach_when_done"); } else if (match_req(request_msg, "project_dont_detach_when_done")) { handle_project_op(request_msg, mf, "dont_detach_when_done"); } else if (match_req(request_msg, "set_network_mode")) { handle_set_network_mode(request_msg, mf); } else if (match_req(request_msg, "run_benchmarks")) { handle_run_benchmarks(request_msg, mf); } else if (match_req(request_msg, "get_proxy_settings")) { handle_get_proxy_settings(request_msg, mf); } else if (match_req(request_msg, "set_proxy_settings")) { handle_set_proxy_settings(request_msg, mf); } else if (match_req(request_msg, "network_available")) { handle_network_available(request_msg, mf); } else if (match_req(request_msg, "abort_file_transfer")) { handle_file_transfer_op(request_msg, mf, "abort"); } else if (match_req(request_msg, "project_detach")) { handle_project_op(request_msg, mf, "detach"); } else if (match_req(request_msg, "abort_result")) { handle_result_op(request_msg, mf, "abort"); } else if (match_req(request_msg, "suspend_result")) { handle_result_op(request_msg, mf, "suspend"); } else if (match_req(request_msg, "resume_result")) { handle_result_op(request_msg, mf, "resume"); } else if (match_req(request_msg, "project_suspend")) { handle_project_op(request_msg, mf, "suspend"); } else if (match_req(request_msg, "project_resume")) { handle_project_op(request_msg, mf, "resume"); } else if (match_req(request_msg, "set_run_mode")) { handle_set_run_mode(request_msg, mf); } else if (match_req(request_msg, "set_gpu_mode")) { handle_set_gpu_mode(request_msg, mf); } else if (match_req(request_msg, "quit")) { handle_quit(request_msg, mf); } else if (match_req(request_msg, "acct_mgr_info")) { handle_acct_mgr_info(request_msg, mf); } else if (match_req(request_msg, "read_global_prefs_override")) { mf.printf("<success/>\n"); gstate.read_global_prefs(); gstate.request_schedule_cpus("Preferences override"); gstate.request_work_fetch("Preferences override"); } else if (match_req(request_msg, "get_project_init_status")) { handle_get_project_init_status(request_msg, mf); } else if (match_req(request_msg, "get_global_prefs_file")) { handle_get_global_prefs_file(mf); } else if (match_req(request_msg, "get_global_prefs_working")) { handle_get_global_prefs_working(mf); } else if (match_req(request_msg, "get_global_prefs_override")) { handle_get_global_prefs_override(mf); } else if (match_req(request_msg, "set_global_prefs_override")) { handle_set_global_prefs_override(request_msg, mf); } else if (match_req(request_msg, "get_cc_config")) { handle_get_cc_config(mf); } else if (match_req(request_msg, "set_cc_config")) { handle_set_cc_config(request_msg, mf); } else if (match_req(request_msg, "read_cc_config")) { mf.printf("<success/>\n"); read_config_file(false); msg_printf(0, MSG_INFO, "Re-read config file"); config.show(); log_flags.show(); gstate.set_ncpus(); gstate.request_schedule_cpus("Core client configuration"); gstate.request_work_fetch("Core client configuration"); } else if (match_req(request_msg, "set_debts")) { handle_set_debts(request_msg, mf); } else { // RPCs after this point require authentication, // and enable network communication for 5 minutes, overriding other factors. // Things like attaching projects, etc. // double saved_time = gstate.gui_rpcs.time_of_last_rpc_needing_network; gstate.gui_rpcs.time_of_last_rpc_needing_network = gstate.now; if (match_req(request_msg, "retry_file_transfer")) { handle_file_transfer_op(request_msg, mf, "retry"); } else if (match_req(request_msg, "project_reset")) { handle_project_op(request_msg, mf, "reset"); } else if (match_req(request_msg, "project_update")) { handle_project_op(request_msg, mf, "update"); } else if (match_req(request_msg, "get_project_config")) { handle_get_project_config(request_msg, mf); } else if (match_req(request_msg, "get_project_config_poll")) { handle_get_project_config_poll(request_msg, mf); } else if (match_req(request_msg, "lookup_account")) { handle_lookup_account(request_msg, mf); } else if (match_req(request_msg, "lookup_account_poll")) { handle_lookup_account_poll(request_msg, mf); } else if (match_req(request_msg, "create_account")) { handle_create_account(request_msg, mf); } else if (match_req(request_msg, "create_account_poll")) { handle_create_account_poll(request_msg, mf); } else if (match_req(request_msg, "project_attach")) { handle_project_attach(request_msg, mf); } else if (match_req(request_msg, "project_attach_poll")) { handle_project_attach_poll(request_msg, mf); } else if (match_req(request_msg, "acct_mgr_rpc")) { handle_acct_mgr_rpc(request_msg, mf); } else if (match_req(request_msg, "acct_mgr_rpc_poll")) { handle_acct_mgr_rpc_poll(request_msg, mf); // DON'T JUST ADD NEW RPCS HERE - THINK ABOUT THEIR // AUTHENTICATION AND NETWORK REQUIREMENTS FIRST } else { mf.printf("<error>unrecognized op: %s</error>\n", request_msg); gstate.gui_rpcs.time_of_last_rpc_needing_network = saved_time; } } mf.printf("</boinc_gui_rpc_reply>\n\003"); m.get_buf(p, n); if (p) { send(sock, p, n, 0); p[n-1]=0; // replace 003 with NULL if (log_flags.guirpc_debug) { if (n > 50) p[50] = 0; msg_printf(0, MSG_INFO, "[guirpc_debug] GUI RPC reply: '%s'\n", p ); } free(p); } return retval; }