// 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 "stdafx.h" #endif #ifndef _WIN32 #include #include #include #include #include #include #include #include #endif #include "util.h" #include "error_numbers.h" #include "parse.h" #include "client_msgs.h" #include "client_state.h" GUI_RPC_CONN::GUI_RPC_CONN(int s) { sock = s; #ifdef _WIN32 fout = _fdopen(_dup(sock), "w"); #else fout = fdopen(dup(sock), "w"); #endif } GUI_RPC_CONN::~GUI_RPC_CONN() { #ifdef _WIN32 closesocket(sock); #else close(sock); fclose(fout); #endif } static PROJECT* get_project(char* buf, FILE* fout) { string url; if (!parse_str(buf, "", url)) { fprintf(fout, "Missing project URL\n"); return 0; } PROJECT* p = gstate.lookup_project(url.c_str()); if (!p) { fprintf(fout, "No such project\n"); return 0 ; } return p; } static void handle_result_show_graphics(char* buf, FILE* fout) { string result_name; PROJECT* p = get_project(buf, fout); if (!p) return; if (!parse_str(buf, "", result_name)) { fprintf(fout, "Missing result name\n"); return; } RESULT* rp = gstate.lookup_result(p, result_name.c_str()); if (!rp) { fprintf(fout, "No such result\n"); return; } ACTIVE_TASK* atp = gstate.lookup_active_task_by_result(rp); if (!atp) { fprintf(fout, "Result not active\n"); return; } atp->request_graphics_mode(MODE_WINDOW); fprintf(fout, "\n"); } static void handle_project_reset(char* buf, FILE* fout) { PROJECT* p = get_project(buf, fout); if (p) { gstate.reset_project(p); fprintf(fout, "\n"); } } static void handle_project_attach(char* buf, FILE* fout) { string url, authenticator; if (!parse_str(buf, "", url)) { fprintf(fout, "Missing URL\n"); return; } if (!parse_str(buf, "", authenticator)) { fprintf(fout, "Missing authenticator\n"); return; } gstate.add_project(url.c_str(), authenticator.c_str()); fprintf(fout, "\n"); } static void handle_project_detach(char* buf, FILE* fout) { PROJECT* p = get_project(buf, fout); if (p) { gstate.detach_project(p); fprintf(fout, "\n"); } } static void handle_project_update(char* buf, FILE* fout) { PROJECT* p = get_project(buf, fout); if (p) { p->sched_rpc_pending = true; p->min_rpc_time = 0; fprintf(fout, "\n"); } } static void handle_set_run_mode(char* buf, FILE* fout) { if (match_tag(buf, "")) { gstate.user_run_request = USER_RUN_REQUEST_ALWAYS; } else if (match_tag(buf, "")) { gstate.user_run_request = USER_RUN_REQUEST_NEVER; } else if (match_tag(buf, "")) { gstate.user_run_request = USER_RUN_REQUEST_AUTO; } else { fprintf(fout, "Missing mode\n"); return; } fprintf(fout, "\n"); } static void handle_run_benchmarks(char* buf, FILE* fout) { // TODO: suspend activities; make sure run at right priority // gstate.start_cpu_benchmarks(); fprintf(fout, "\n"); } static void handle_set_proxy_settings(char* buf, FILE* fout) { string socks_proxy_server_name,http_proxy_server_name; int socks_proxy_server_port,http_proxy_server_port; if (!parse_str(buf, "", socks_proxy_server_name)) { fprintf(fout, "SOCKS proxy server name missing\n"); return; } if (!parse_int(buf, "", socks_proxy_server_port)) { fprintf(fout, "SOCKS proxy server port missing\n"); return; } if (!parse_str(buf, "", http_proxy_server_name)) { fprintf(fout, "HTTP proxy server name missing\n"); return; } if (!parse_int(buf, "", http_proxy_server_port)) { fprintf(fout, "HTTP proxy server port missing\n"); return; } safe_strcpy(gstate.pi.socks_server_name, socks_proxy_server_name.c_str()); gstate.pi.socks_server_port = socks_proxy_server_port; safe_strcpy(gstate.pi.http_server_name, http_proxy_server_name.c_str()); gstate.pi.http_server_port = http_proxy_server_port; fprintf(fout, "\n"); } // params: // x // return at most this many messages // n // start at message n. // if no offset is given, return last n messages // void handle_get_messages(char* buf, FILE* fout) { int nmessages=-1, offset=-1, j; unsigned int i; parse_int(buf, "", nmessages); parse_int(buf, "", offset); if (nmessages < 0) { fprintf(fout, "No nmessages given\n"); return; } if (offset > (int)message_descs.size()) { offset = message_descs.size(); } if (offset < 0) { offset = message_descs.size()-nmessages; if (offset < 0) { offset = 0; } } fprintf(fout, "\n"); j = 0; for (i=offset; i\n" " %d\n" " %d\n" " %s\n" " \n", i, md.priority, md.message.c_str(), md.timestamp ); if (md.project) { fprintf(fout, " %s\n", md.project->get_project_name() ); } fprintf(fout, "\n"); } fprintf(fout, "\n"); } int GUI_RPC_CONN::handle_rpc() { char buf[1024]; int n; // read the request message in one read() // so that the core client won't hang because // of malformed request msgs // n = read(sock, buf, 1024); if (n <= 0) return -1; buf[n] = 0; printf("got %s\n", buf); if (match_tag(buf, "")) { handle_result_show_graphics(buf, fout); } else if (match_tag(buf, "")) { handle_project_reset(buf, fout); } else if (match_tag(buf, "")) { handle_project_attach(buf, fout); } else if (match_tag(buf, "")) { handle_project_detach(buf, fout); } else if (match_tag(buf, "")) { handle_project_update(buf, fout); } else if (match_tag(buf, "")) { handle_set_run_mode(buf, fout); } else if (match_tag(buf, "")) { handle_run_benchmarks(buf, fout); } else if (match_tag(buf, "")) { handle_set_proxy_settings(buf, fout); } else if (match_tag(buf, "")) { handle_get_messages(buf, fout); } else { fprintf(fout, "\n"); } fflush(fout); return 0; } int GUI_RPC_CONN_SET::insert(GUI_RPC_CONN* p) { gui_rpcs.push_back(p); return 0; } int GUI_RPC_CONN_SET::init() { sockaddr_in addr; int retval; lsock = socket(AF_INET, SOCK_STREAM, 0); if (lsock < 0) { perror("socket"); return ERR_SOCKET; } addr.sin_family = AF_INET; addr.sin_port = htons(GUI_RPC_PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); retval = bind(lsock, (const sockaddr*)(&addr), sizeof(addr)); if (retval) { perror("bind"); return ERR_BIND; } retval = listen(lsock, 999); if (retval) { perror("listen"); return ERR_LISTEN; } return 0; } bool GUI_RPC_CONN_SET::poll() { unsigned int i; fd_set read_fds, error_fds; int sock, n, retval; vector::iterator iter; GUI_RPC_CONN* gr; struct timeval tv; FD_ZERO(&read_fds); FD_ZERO(&error_fds); FD_SET(lsock, &read_fds); for (i=0; isock, &read_fds); FD_SET(gr->sock, &error_fds); } memset(&tv, 0, sizeof(tv)); n = select(FD_SETSIZE, &read_fds, 0, &error_fds, &tv); if (FD_ISSET(lsock, &read_fds)) { struct sockaddr_in addr; #ifdef _WIN32 int addr_len = sizeof(addr); sock = accept(lsock, (struct sockaddr*)&addr, &addr_len); #else size_t addr_len = sizeof(addr); sock = accept(lsock, (struct sockaddr*)&addr, &addr_len); #endif int peer_ip = (int) ntohl(addr.sin_addr.s_addr); printf("peer addr: %x\n", peer_ip); if (peer_ip != 0x7f000001) { msg_printf( NULL, MSG_ERROR, "GUI RPC request from non-local address 0x%x\n", peer_ip ); } else { GUI_RPC_CONN* gr = new GUI_RPC_CONN(sock); insert(gr); } } iter = gui_rpcs.begin(); while (iter != gui_rpcs.end()) { gr = *iter; if (FD_ISSET(gr->sock, &error_fds)) { delete gr; gui_rpcs.erase(iter); } else { iter++; } } iter = gui_rpcs.begin(); while (iter != gui_rpcs.end()) { gr = *iter; if (FD_ISSET(gr->sock, &read_fds)) { retval = gr->handle_rpc(); if (retval) { delete gr; gui_rpcs.erase(iter); continue; } } iter++; } return (n != 0); }