// The contents of this file are subject to the BOINC Public License // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://boinc.berkeley.edu/license_1.0.txt // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations // under the License. // // The Original Code is the Berkeley Open Infrastructure for Network Computing. // // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 // University of California at Berkeley. All Rights Reserved. // // Contributor(s): // #ifdef _WIN32 #include "boinc_win.h" #endif #ifndef _WIN32 #include #include #include #include #include #include #include #include #include #include #include #endif #include "parse.h" #include "error_numbers.h" #include "miofile.h" #include "gui_rpc_client.h" using std::string; using std::vector; int RPC_CLIENT::init(char* host) { int retval; sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(GUI_RPC_PORT); if (host) { hostent* hep = gethostbyname(host); if (!hep) { perror("gethostbyname"); return ERR_GETHOSTBYNAME; } addr.sin_addr.s_addr = *(int*)hep->h_addr_list[0]; } else { #ifdef _WIN32 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); #else addr.sin_addr.s_addr = htonl(INADDR_ANY); #endif } sock = socket(AF_INET, SOCK_STREAM, 0); if (sock <= 0) { perror("socket"); return ERR_SOCKET; } retval = connect(sock, (const sockaddr*)(&addr), sizeof(addr)); if (retval) { #ifdef _WIN32 printf( "Windows Socket Error '%d'\n", WSAGetLastError() ); #endif perror("connect"); return ERR_CONNECT; } return 0; } RPC_CLIENT::~RPC_CLIENT() { } int RPC_CLIENT::send_request(char* p) { int n = send(sock, p, strlen(p), 0); if (n < 0) return ERR_WRITE; return 0; } // get reply from server. Caller must free buf // int RPC_CLIENT::get_reply(char*& mbuf) { char buf[1025]; MFILE mf; int n; while (1) { n = recv(sock, buf, 1024, 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 RPC_CLIENT::get_state(CC_STATE& state) { char buf[256]; PROJECT* project; char* mbuf=0; int retval; retval = send_request("\n"); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; MIOFILE fin; fin.init_buf(mbuf); while (fin.fgets(buf, 256)) { if (match_tag(buf, "")) break; else if (match_tag(buf, "")) { project = new PROJECT; project->parse(fin); state.projects.push_back(project); continue; } else if (match_tag(buf, "")) { APP* app = new APP; app->parse(fin); app->project = project; state.apps.push_back(app); continue; } else if (match_tag(buf, "")) { APP_VERSION* app_version = new APP_VERSION; app_version->parse(fin); app_version->project = project; app_version->app = state.lookup_app(app_version->app_name); state.app_versions.push_back(app_version); continue; } else if (match_tag(buf, "")) { WORKUNIT* wu = new WORKUNIT; wu->parse(fin); wu->project = project; wu->app = state.lookup_app(wu->app_name); wu->avp = state.lookup_app_version(wu->app_name, wu->version_num); state.wus.push_back(wu); continue; } else if (match_tag(buf, "")) { RESULT* result = new RESULT; result->parse(fin); result->project = project; result->wup = state.lookup_wu(result->wu_name); result->app = result->wup->app; state.results.push_back(result); continue; } } if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::get_results(RESULTS& t) { char buf[256]; char* mbuf=0; int retval; retval = send_request("\n"); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; MIOFILE fin; fin.init_buf(mbuf); while (fin.fgets(buf, 256)) { if (match_tag(buf, "")) break; else if (match_tag(buf, "")) { RESULT* rp = new RESULT; rp->parse(fin); t.results.push_back(rp); continue; } } if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::get_file_transfers(FILE_TRANSFERS& t) { char buf[256]; char* mbuf=0; int retval; retval = send_request("\n"); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; MIOFILE fin; fin.init_buf(mbuf); while (fin.fgets(buf, 256)) { if (match_tag(buf, "")) break; else if (match_tag(buf, "")) { FILE_TRANSFER* fip = new FILE_TRANSFER; fip->parse(fin); t.file_transfers.push_back(fip); continue; } } if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::get_project_status(std::vector& projects) { char buf[256]; char* mbuf=0; int retval; retval = send_request("\n"); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; MIOFILE fin; fin.init_buf(mbuf); while (fin.fgets(buf, 256)) { if (match_tag(buf, "")) break; else if (match_tag(buf, "")) { PROJECT project; project.parse(fin); projects.push_back(project); continue; } } if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::get_disk_usage(std::vector& projects) { char buf[256]; char* mbuf=0; int retval; retval = send_request("\n"); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; MIOFILE fin; fin.init_buf(mbuf); while (fin.fgets(buf, 256)) { if (match_tag(buf, "")) break; else if (match_tag(buf, "")) { PROJECT project; project.parse(fin); projects.push_back(project); continue; } } if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::show_graphics(char* project, char* result_name, bool full_screen) { char buf[256]; char* mbuf=0; int retval; if (project) { sprintf(buf, "\n" "%s\n" "%s\n" "%s" "\n", result_name, full_screen?"\n":"" ); } else { sprintf(buf, "\n%s\n", full_screen?"\n":"" ); } retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::project_reset(char* url) { char buf[256]; char* mbuf=0; int retval; sprintf(buf, "\n" " %s\n" "\n", url ); retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::project_attach(char* url, char* auth) { char buf[256]; char* mbuf=0; int retval; sprintf(buf, "\n" " %s\n" " %s\n" "\n", url, auth ); retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::project_detach(char* url) { char buf[256]; char* mbuf=0; int retval; sprintf(buf, "\n" " %s\n" "\n", url ); retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::project_update(char* url) { char buf[256]; char* mbuf=0; int retval; sprintf(buf, "\n" " %s\n" "\n", url ); retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } char* mode_name(int mode) { char* p; switch (mode) { case RUN_MODE_ALWAYS: p=""; break; case RUN_MODE_NEVER: p=""; break; case RUN_MODE_AUTO: p=""; break; } return p; } int RPC_CLIENT::set_run_mode(int mode) { char *p, buf[256]; char* mbuf=0; int retval; sprintf(buf, "\n%s\n\n", mode_name(mode)); retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::get_run_mode(int& mode) { char buf[256]; char* mbuf=0; int retval; retval = send_request("\n"); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; MIOFILE fin; fin.init_buf(mbuf); mode = -1; while (fin.fgets(buf, 256)) { if (match_tag(buf, mode_name(RUN_MODE_ALWAYS))) mode = RUN_MODE_ALWAYS; if (match_tag(buf, mode_name(RUN_MODE_NEVER))) mode = RUN_MODE_NEVER; if (match_tag(buf, mode_name(RUN_MODE_AUTO))) mode = RUN_MODE_AUTO; } return 0; } int RPC_CLIENT::set_network_mode(int mode) { char buf[256]; char* mbuf=0; int retval; sprintf(buf, "\n" "%s" "\n", mode_name(mode) ); retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::get_network_mode(int& mode) { char buf[256]; char* mbuf=0; int retval; retval = send_request("\n"); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; MIOFILE fin; fin.init_buf(mbuf); mode = -1; while (fin.fgets(buf, 256)) { if (match_tag(buf, mode_name(RUN_MODE_ALWAYS))) mode = RUN_MODE_ALWAYS; if (match_tag(buf, mode_name(RUN_MODE_NEVER))) mode = RUN_MODE_NEVER; if (match_tag(buf, mode_name(RUN_MODE_AUTO))) mode = RUN_MODE_AUTO; } return 0; } int RPC_CLIENT::run_benchmarks() { char buf[256]; char* mbuf=0; int retval; retval = send_request("\n"); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::set_proxy_settings(PROXY_INFO& pi) { char buf[256]; char* mbuf=0; int retval; sprintf(buf, "\n%s%s" " %s\n" " %d\n" " %s\n" " %d\n" " %d\n" " %d\n" " %d\n" " %d\n", pi.use_http_proxy?" \n":"", pi.use_socks_proxy?" \n":"", pi.socks_server_name, pi.socks_server_port, pi.http_server_name, pi.http_server_port, pi.http_user_name, pi.http_user_passwd, pi.socks5_user_name, pi.socks5_user_passwd ); retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; if (mbuf) free(mbuf); return 0; } int RPC_CLIENT::get_messages( int nmessages, int seqno, vector& msgs ) { char buf[256]; char* mbuf; int retval; sprintf(buf, "\n" " %d\n" " %d\n" "\n", nmessages, seqno ); retval = send_request(buf); if (retval) return retval; retval = get_reply(mbuf); if (retval) return retval; MIOFILE fin; fin.init_buf(mbuf); while (fin.fgets(buf, 256)) { puts(buf); if (match_tag(buf, "")) continue; if (match_tag(buf, "")) break; if (match_tag(buf, "")) { MESSAGE_DESC md; while (fin.fgets(buf, 256)) { puts(buf); if (match_tag(buf, "")) break; if (parse_str(buf, "", md.project)) continue; if (match_tag(buf, "" )) { copy_element_contents(fin, "", md.body); continue; } if (parse_int(buf, "", md.priority)) continue; if (parse_int(buf, "")) return 0; else if (parse_str(buf, "", name)) continue; else if (match_tag(buf, "")) { generated_locally = true; continue; } else if (match_tag(buf, "")) { uploaded = true; continue; } else if (match_tag(buf, "")) { upload_when_present = true; continue; } else if (match_tag(buf, "")) { sticky = true; continue; } else if (match_tag(buf, "")) { pers_xfer_active = true; continue; } else if (match_tag(buf, "")) { xfer_active = true; continue; } else if (parse_int(buf, "", num_retries)) continue; else if (parse_double(buf, "", bytes_xferred)) continue; else if (parse_double(buf, "", file_offset)) continue; else if (parse_double(buf, "", xfer_speed)) continue; else if (parse_str(buf, "", hostname)) continue; } return ERR_XML_PARSE; } void FILE_TRANSFER::print() { printf(" name: %s\n", name.c_str()); printf(" generated locally: %s\n", generated_locally?"yes":"no"); printf(" uploaded: %s\n", uploaded?"yes":"no"); printf(" upload when present: %s\n", upload_when_present?"yes":"no"); printf(" sticky: %s\n", sticky?"yes":"no"); printf(" generated locally: %s\n", generated_locally?"yes":"no"); } int PROJECT::parse(MIOFILE& in) { char buf[256]; memset(this, 0, sizeof(*this)); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", master_url)) continue; else if (parse_double(buf, "", resource_share)) continue; else if (parse_str(buf, "", project_name)) continue; else if (parse_str(buf, "", user_name)) continue; else if (parse_str(buf, "", team_name)) continue; else if (parse_double(buf, "", user_total_credit)) continue; else if (parse_double(buf, "", user_expavg_credit)) continue; else if (parse_double(buf, "", host_total_credit)) continue; else if (parse_double(buf, "", host_expavg_credit)) continue; else if (parse_int(buf, "", nrpc_failures)) continue; else if (parse_int(buf, "", master_fetch_failures)) continue; else if (parse_int(buf, "", min_rpc_time)) continue; else if (match_tag(buf, "")) { master_url_fetch_pending = true; continue; } else if (match_tag(buf, "")) { sched_rpc_pending = true; continue; } else if (match_tag(buf, "")) { tentative = true; continue; } } return ERR_XML_PARSE; } void PROJECT::print() { printf(" name: %s\n", project_name.c_str()); printf(" master URL: %s\n", master_url.c_str()); printf(" user_name: %s\n", user_name.c_str()); printf(" team_name: %s\n", team_name.c_str()); printf(" resource share: %f\n", resource_share); printf(" user_total_credit: %f\n", user_total_credit); printf(" user_expavg_credit: %f\n", user_expavg_credit); printf(" host_total_credit: %f\n", host_total_credit); printf(" host_expavg_credit: %f\n", host_expavg_credit); printf(" nrpc_failures: %d\n", nrpc_failures); printf(" master_fetch_failures: %d\n", master_fetch_failures); printf(" master fetch pending: %s\n", master_url_fetch_pending?"yes":"no"); printf(" scheduler RPC pending: %s\n", sched_rpc_pending?"yes":"no"); printf(" tentative: %s\n", tentative?"yes":"no"); } int APP::parse(MIOFILE& in) { char buf[256]; memset(this, 0, sizeof(*this)); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", name)) continue; } return ERR_XML_PARSE; } void APP::print() { printf(" name: %s\n", name.c_str()); printf(" Project: %s\n", project->project_name.c_str()); } int APP_VERSION::parse(MIOFILE& in) { char buf[256]; memset(this, 0, sizeof(*this)); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", app_name)) continue; else if (parse_int(buf, "", version_num)) continue; } return ERR_XML_PARSE; } void APP_VERSION::print() { printf(" application: %s\n", app->name.c_str()); printf(" version: %.2f\n", version_num/100.0); printf(" project: %s\n", project->project_name.c_str()); } int WORKUNIT::parse(MIOFILE& in) { char buf[256]; memset(this, 0, sizeof(*this)); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", name)) continue; else if (parse_str(buf, "", app_name)) continue; else if (parse_int(buf, "", version_num)) continue; else if (parse_double(buf, "", rsc_fpops_est)) continue; else if (parse_double(buf, "", rsc_fpops_bound)) continue; else if (parse_double(buf, "", rsc_memory_bound)) continue; else if (parse_double(buf, "", rsc_disk_bound)) continue; } return ERR_XML_PARSE; } void WORKUNIT::print() { printf(" name: %s\n", name.c_str()); printf(" FP estimate: %f\n", rsc_fpops_est); printf(" FP bound: %f\n", rsc_fpops_bound); printf(" memory bound: %f\n", rsc_memory_bound); printf(" disk bound: %f\n", rsc_disk_bound); } int RESULT::parse(MIOFILE& in) { char buf[256]; memset(this, 0, sizeof(*this)); while (in.fgets(buf, 256)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", name)) continue; else if (parse_str(buf, "", wu_name)) continue; else if (parse_int(buf, "", report_deadline)) continue; else if (match_tag(buf, "")) { ready_to_report = true; continue; } else if (match_tag(buf, "")) { got_server_ack = true; continue; } else if (parse_double(buf, "", final_cpu_time)) continue; else if (parse_int(buf, "", state)) continue; else if (parse_int(buf, "", exit_status)) continue; else if (parse_int(buf, "", signal)) continue; else if (parse_int(buf, "", active_task_state)) continue; else if (match_tag(buf, "")) { copy_element_contents(in, "", stderr_out); } else if (parse_int(buf, "", app_version_num)) continue; else if (parse_double(buf, "", checkpoint_cpu_time)) continue; else if (parse_double(buf, "", current_cpu_time)) continue; else if (parse_double(buf, "", fraction_done)) continue; } return ERR_XML_PARSE; } void RESULT::print() { printf(" name: %s\n", name.c_str()); printf(" WU name: %s\n", wup->name.c_str()); printf(" ready to report: %s\n", ready_to_report?"yes":"no"); printf(" got server ack: %s\n", got_server_ack?"yes":"no"); printf(" final CPU time: %f\n", final_cpu_time); printf(" state: %d\n", state); printf(" exit_status: %d\n", exit_status); printf(" signal: %d\n", signal); printf(" active_task_state: %d\n", active_task_state); printf(" stderr_out: %s\n", stderr_out.c_str()); printf(" app version num: %d\n", app_version_num); printf(" checkpoint CPU time: %f\n", checkpoint_cpu_time); printf(" current CPU time: %f\n", current_cpu_time); printf(" fraction done: %f\n", fraction_done); } APP* CC_STATE::lookup_app(string& str) { unsigned int i; for (i=0; iname == str) return apps[i]; } printf("CAN'T FIND APP %s\n", str.c_str()); return 0; } WORKUNIT* CC_STATE::lookup_wu(string& str) { unsigned int i; for (i=0; iname == str) return wus[i]; } printf("CAN'T FIND WU %s\n", str.c_str()); return 0; } RESULT* CC_STATE::lookup_result(string& str) { unsigned int i; for (i=0; iname == str) return results[i]; } printf("CAN'T FIND RESULT %s\n", str.c_str()); return 0; } APP_VERSION* CC_STATE::lookup_app_version(string& str, int version_num) { unsigned int i; for (i=0; iapp_name == str && app_versions[i]->version_num == version_num) return app_versions[i]; } return 0; }