mirror of https://github.com/BOINC/boinc.git
*** empty log message ***
svn path=/trunk/boinc/; revision=2913
This commit is contained in:
parent
72ce699dda
commit
c236b95e8c
|
@ -1104,8 +1104,8 @@ AC_DEFUN([SAH_HEADER_STDCXX],[
|
|||
#
|
||||
# Revision Log:
|
||||
# $Log$
|
||||
# Revision 1.62 2004/01/17 18:47:03 davea
|
||||
# version 2.19
|
||||
# Revision 1.63 2004/01/21 07:07:05 davea
|
||||
# *** empty log message ***
|
||||
#
|
||||
# Revision 1.1 2003/12/11 18:38:24 korpela
|
||||
# Added checked macro files into boinc
|
||||
|
|
|
@ -9393,3 +9393,33 @@ David Jan 19 2004 (from Rom Walton)
|
|||
win_build/
|
||||
boinc_cli.vcproj
|
||||
boinc_ss.vcproj
|
||||
|
||||
David Jan 20 2004
|
||||
- added basic support for GUI RPCs in the core client.
|
||||
This allows GUIs to be implemented in a separate process.
|
||||
There can be multiple GUIs looking at the same core client.
|
||||
New classes:
|
||||
GUI_RPC_CONN: represents a connection to a GUI program
|
||||
GUI_RPC_CONN_SET: represents the set of all such connections
|
||||
has the usual poll() function.
|
||||
This is currently implemented only for UNIX, using UNIX domain sockets.
|
||||
Should be straightforward to do in Win using named pipes.
|
||||
- The isspace() macro crashes if called with a non-ASCII arg,
|
||||
so use it only after isascii()
|
||||
- reimplement strip_whitespace() to do the above,
|
||||
have it trim at both start and end,
|
||||
and make a version for string
|
||||
NOTE: the real problem is that user-supplied text is being
|
||||
kept in XML elements in the state file.
|
||||
Should escape it.
|
||||
|
||||
client/
|
||||
Makefile.am,in
|
||||
client_state.C,h
|
||||
gui_rpc_client.C,h (new)
|
||||
gui_rpc_server.C,h (new)
|
||||
gui_test.C
|
||||
|
||||
lib/
|
||||
parse.C
|
||||
util.C,h
|
||||
|
|
|
@ -26,6 +26,7 @@ boinc_client_SOURCES = \
|
|||
cs_statefile.C \
|
||||
file_names.C \
|
||||
file_xfer.C \
|
||||
gui_rpc_server.C \
|
||||
hostinfo.C \
|
||||
hostinfo_unix.C \
|
||||
http.C \
|
||||
|
|
|
@ -193,6 +193,7 @@ boinc_client_SOURCES = \
|
|||
cs_statefile.C \
|
||||
file_names.C \
|
||||
file_xfer.C \
|
||||
gui_rpc_server.C \
|
||||
hostinfo.C \
|
||||
hostinfo_unix.C \
|
||||
http.C \
|
||||
|
@ -256,6 +257,7 @@ am_boinc_client_OBJECTS = boinc_client-app.$(OBJEXT) \
|
|||
boinc_client-cs_statefile.$(OBJEXT) \
|
||||
boinc_client-file_names.$(OBJEXT) \
|
||||
boinc_client-file_xfer.$(OBJEXT) \
|
||||
boinc_client-gui_rpc_server.$(OBJEXT) \
|
||||
boinc_client-hostinfo.$(OBJEXT) \
|
||||
boinc_client-hostinfo_unix.$(OBJEXT) \
|
||||
boinc_client-http.$(OBJEXT) boinc_client-log_flags.$(OBJEXT) \
|
||||
|
@ -301,6 +303,7 @@ am__depfiles_maybe = depfiles
|
|||
@AMDEP_TRUE@ ./$(DEPDIR)/boinc_client-file_names.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/boinc_client-file_xfer.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/boinc_client-filesys.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/boinc_client-gui_rpc_server.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/boinc_client-hostinfo.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/boinc_client-hostinfo_unix.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/boinc_client-http.Po \
|
||||
|
@ -385,6 +388,7 @@ boinc_client-cs_scheduler.$(OBJEXT): cs_scheduler.C
|
|||
boinc_client-cs_statefile.$(OBJEXT): cs_statefile.C
|
||||
boinc_client-file_names.$(OBJEXT): file_names.C
|
||||
boinc_client-file_xfer.$(OBJEXT): file_xfer.C
|
||||
boinc_client-gui_rpc_server.$(OBJEXT): gui_rpc_server.C
|
||||
boinc_client-hostinfo.$(OBJEXT): hostinfo.C
|
||||
boinc_client-hostinfo_unix.$(OBJEXT): hostinfo_unix.C
|
||||
boinc_client-http.$(OBJEXT): http.C
|
||||
|
@ -440,6 +444,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boinc_client-file_names.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boinc_client-file_xfer.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boinc_client-filesys.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boinc_client-gui_rpc_server.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boinc_client-hostinfo.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boinc_client-hostinfo_unix.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boinc_client-http.Po@am__quote@
|
||||
|
@ -839,6 +844,28 @@ boinc_client-file_xfer.obj: file_xfer.C
|
|||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(boinc_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o boinc_client-file_xfer.obj `if test -f 'file_xfer.C'; then $(CYGPATH_W) 'file_xfer.C'; else $(CYGPATH_W) '$(srcdir)/file_xfer.C'`
|
||||
|
||||
boinc_client-gui_rpc_server.o: gui_rpc_server.C
|
||||
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(boinc_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT boinc_client-gui_rpc_server.o -MD -MP -MF "$(DEPDIR)/boinc_client-gui_rpc_server.Tpo" \
|
||||
@am__fastdepCXX_TRUE@ -c -o boinc_client-gui_rpc_server.o `test -f 'gui_rpc_server.C' || echo '$(srcdir)/'`gui_rpc_server.C; \
|
||||
@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/boinc_client-gui_rpc_server.Tpo" "$(DEPDIR)/boinc_client-gui_rpc_server.Po"; \
|
||||
@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/boinc_client-gui_rpc_server.Tpo"; exit 1; \
|
||||
@am__fastdepCXX_TRUE@ fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='gui_rpc_server.C' object='boinc_client-gui_rpc_server.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/boinc_client-gui_rpc_server.Po' tmpdepfile='$(DEPDIR)/boinc_client-gui_rpc_server.TPo' @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(boinc_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o boinc_client-gui_rpc_server.o `test -f 'gui_rpc_server.C' || echo '$(srcdir)/'`gui_rpc_server.C
|
||||
|
||||
boinc_client-gui_rpc_server.obj: gui_rpc_server.C
|
||||
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(boinc_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT boinc_client-gui_rpc_server.obj -MD -MP -MF "$(DEPDIR)/boinc_client-gui_rpc_server.Tpo" \
|
||||
@am__fastdepCXX_TRUE@ -c -o boinc_client-gui_rpc_server.obj `if test -f 'gui_rpc_server.C'; then $(CYGPATH_W) 'gui_rpc_server.C'; else $(CYGPATH_W) '$(srcdir)/gui_rpc_server.C'`; \
|
||||
@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/boinc_client-gui_rpc_server.Tpo" "$(DEPDIR)/boinc_client-gui_rpc_server.Po"; \
|
||||
@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/boinc_client-gui_rpc_server.Tpo"; exit 1; \
|
||||
@am__fastdepCXX_TRUE@ fi
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='gui_rpc_server.C' object='boinc_client-gui_rpc_server.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/boinc_client-gui_rpc_server.Po' tmpdepfile='$(DEPDIR)/boinc_client-gui_rpc_server.TPo' @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(boinc_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o boinc_client-gui_rpc_server.obj `if test -f 'gui_rpc_server.C'; then $(CYGPATH_W) 'gui_rpc_server.C'; else $(CYGPATH_W) '$(srcdir)/gui_rpc_server.C'`
|
||||
|
||||
boinc_client-hostinfo.o: hostinfo.C
|
||||
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(boinc_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT boinc_client-hostinfo.o -MD -MP -MF "$(DEPDIR)/boinc_client-hostinfo.Tpo" \
|
||||
@am__fastdepCXX_TRUE@ -c -o boinc_client-hostinfo.o `test -f 'hostinfo.C' || echo '$(srcdir)/'`hostinfo.C; \
|
||||
|
|
|
@ -272,6 +272,8 @@ int CLIENT_STATE::init() {
|
|||
// Just to be on the safe side; something may have been modified
|
||||
//
|
||||
set_client_state_dirty("init");
|
||||
|
||||
gui_rpcs.init("gui_rpc");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -338,6 +340,7 @@ bool CLIENT_STATE::do_something() {
|
|||
POLL_ACTION(scheduler_rpc , scheduler_rpc_poll );
|
||||
POLL_ACTION(garbage_collect , garbage_collect );
|
||||
POLL_ACTION(update_results , update_results );
|
||||
POLL_ACTION(gui_rpc , gui_rpcs.poll );
|
||||
} else {
|
||||
net_stats.poll(*net_xfers);
|
||||
// Call these functions in bottom to top order with
|
||||
|
@ -354,6 +357,7 @@ bool CLIENT_STATE::do_something() {
|
|||
POLL_ACTION(handle_pers_file_xfers , handle_pers_file_xfers );
|
||||
POLL_ACTION(garbage_collect , garbage_collect );
|
||||
POLL_ACTION(update_results , update_results );
|
||||
POLL_ACTION(gui_rpc , gui_rpcs.poll );
|
||||
}
|
||||
|
||||
retval = write_state_file_if_needed();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "app.h"
|
||||
#include "client_types.h"
|
||||
#include "file_xfer.h"
|
||||
#include "gui_rpc_server.h"
|
||||
#include "hostinfo.h"
|
||||
#include "http.h"
|
||||
#include "language.h"
|
||||
|
@ -73,6 +74,7 @@ public:
|
|||
GLOBAL_PREFS global_prefs;
|
||||
NET_STATS net_stats;
|
||||
SS_LOGIC ss_logic;
|
||||
GUI_RPC_CONN_SET gui_rpcs;
|
||||
LANGUAGE language;
|
||||
|
||||
int core_client_major_version;
|
||||
|
|
|
@ -941,7 +941,7 @@ int RESULT::write(FILE* out, bool to_server) {
|
|||
if (to_server) {
|
||||
fprintf(out, "<app_version>%d</app_version>\n", wup->version_num);
|
||||
fprintf(out,
|
||||
"<core_client_version>%d.%0.2d</core_client_version>\n",
|
||||
"<core_client_version>%d.%.2d</core_client_version>\n",
|
||||
gstate.core_client_major_version,
|
||||
gstate.core_client_minor_version
|
||||
);
|
||||
|
|
|
@ -209,15 +209,26 @@ bool FILE_XFER_SET::poll() {
|
|||
remove(fxp);
|
||||
i--;
|
||||
|
||||
// Restart the upload, using the newly obtained upload_offset
|
||||
fxp->file_xfer_retval = fxp->init_upload(*fxp->fip);
|
||||
// if the server's file size is bigger than ours,
|
||||
// something bad has happened (like a result
|
||||
// got sent to multiple users).
|
||||
// Pretend the file was successfully uploaded
|
||||
//
|
||||
if (fxp->fip->upload_offset >= fxp->fip->nbytes) {
|
||||
fxp->file_xfer_done = true;
|
||||
fxp->file_xfer_retval = 0;
|
||||
} else {
|
||||
// Restart the upload, using the newly obtained
|
||||
// upload_offset
|
||||
fxp->file_xfer_retval = fxp->init_upload(*fxp->fip);
|
||||
|
||||
if (!fxp->file_xfer_retval) {
|
||||
fxp->file_xfer_retval = insert(fxp);
|
||||
if (!fxp->file_xfer_retval) {
|
||||
fxp->file_xfer_done = false;
|
||||
fxp->file_xfer_retval = 0;
|
||||
fxp->http_op_retval = 0;
|
||||
fxp->file_xfer_retval = insert(fxp);
|
||||
if (!fxp->file_xfer_retval) {
|
||||
fxp->file_xfer_done = false;
|
||||
fxp->file_xfer_retval = 0;
|
||||
fxp->http_op_retval = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "error_numbers.h"
|
||||
#include "gui_rpc_client.h"
|
||||
|
||||
int RPC_CLIENT::init(char* path) {
|
||||
int sock, retval;
|
||||
sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, path);
|
||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
retval = connect(sock, (const sockaddr*)(&addr), sizeof(addr));
|
||||
if (retval) {
|
||||
perror("connect");
|
||||
exit(1);
|
||||
}
|
||||
fin = fdopen(dup(sock), "r");
|
||||
fout = fdopen(sock, "w");
|
||||
}
|
||||
|
||||
RPC_CLIENT::~RPC_CLIENT() {
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
int RPC_CLIENT::get_projects(vector<PROJECT>& projects) {
|
||||
char buf[256];
|
||||
int retval;
|
||||
|
||||
fprintf(fout, "<get_projects>\n");
|
||||
fflush(fout);
|
||||
while (fgets(buf, 256, fin)) {
|
||||
if (match_tag(buf, "<projects>")) continue;
|
||||
else if (match_tag(buf, "</projects>")) return 0;
|
||||
else if (match_tag(buf, "<project>")) {
|
||||
PROJECT project;
|
||||
retval = project.parse_state(fin);
|
||||
if (!retval) {
|
||||
projects.push_back(project);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "unrecognized: %s", buf);
|
||||
}
|
||||
}
|
||||
return ERR_XML_PARSE;
|
||||
}
|
||||
|
||||
int PROJECT::parse_state(FILE* in) {
|
||||
char buf[256];
|
||||
STRING256 string;
|
||||
|
||||
strcpy(project_name, "");
|
||||
strcpy(user_name, "");
|
||||
strcpy(team_name, "");
|
||||
resource_share = 100;
|
||||
exp_avg_cpu = 0;
|
||||
exp_avg_mod_time = 0;
|
||||
min_rpc_time = 0;
|
||||
min_report_min_rpc_time = 0;
|
||||
nrpc_failures = 0;
|
||||
master_url_fetch_pending = false;
|
||||
sched_rpc_pending = false;
|
||||
scheduler_urls.clear();
|
||||
while (fgets(buf, 256, in)) {
|
||||
if (match_tag(buf, "</project>")) return 0;
|
||||
else if (parse_str(buf, "<scheduler_url>", string.text, sizeof(string.text))) {
|
||||
scheduler_urls.push_back(string);
|
||||
continue;
|
||||
}
|
||||
else if (parse_str(buf, "<master_url>", master_url, sizeof(master_url))) continue;
|
||||
else if (parse_str(buf, "<project_name>", project_name, sizeof(project_name))) continue;
|
||||
else if (parse_str(buf, "<user_name>", user_name, sizeof(user_name))) continue;
|
||||
else if (parse_str(buf, "<team_name>", team_name, sizeof(team_name))) continue;
|
||||
else if (parse_double(buf, "<user_total_credit>", user_total_credit)) continue;
|
||||
else if (parse_double(buf, "<user_expavg_credit>", user_expavg_credit)) continue;
|
||||
else if (parse_int(buf, "<user_create_time>", (int &)user_create_time)) continue;
|
||||
else if (parse_int(buf, "<rpc_seqno>", rpc_seqno)) continue;
|
||||
else if (parse_int(buf, "<hostid>", hostid)) continue;
|
||||
else if (parse_double(buf, "<host_total_credit>", host_total_credit)) continue;
|
||||
else if (parse_double(buf, "<host_expavg_credit>", host_expavg_credit)) continue;
|
||||
else if (parse_int(buf, "<host_create_time>", (int &)host_create_time)) continue;
|
||||
else if (parse_double(buf, "<exp_avg_cpu>", exp_avg_cpu)) continue;
|
||||
else if (parse_int(buf, "<exp_avg_mod_time>", exp_avg_mod_time)) continue;
|
||||
else if (match_tag(buf, "<code_sign_key>")) {
|
||||
copy_element_contents(
|
||||
in,
|
||||
"</code_sign_key>",
|
||||
code_sign_key,
|
||||
sizeof(code_sign_key)
|
||||
);
|
||||
}
|
||||
else if (parse_int(buf, "<nrpc_failures>", nrpc_failures)) continue;
|
||||
else if (parse_int(buf, "<master_fetch_failures>", master_fetch_failures)) continue;
|
||||
else if (parse_int(buf, "<min_rpc_time>", (int&)min_rpc_time)) continue;
|
||||
else if (match_tag(buf, "<master_url_fetch_pending/>")) master_url_fetch_pending = true;
|
||||
else if (match_tag(buf, "<sched_rpc_pending/>")) sched_rpc_pending = true;
|
||||
else printf("PROJECT::parse_state(): unrecognized: %s\n", buf);
|
||||
}
|
||||
return ERR_XML_PARSE;
|
||||
}
|
||||
|
||||
PROJECT::PROJECT() {
|
||||
init();
|
||||
}
|
||||
|
||||
void PROJECT::init() {
|
||||
strcpy(master_url, "");
|
||||
strcpy(authenticator, "");
|
||||
project_specific_prefs = "";
|
||||
resource_share = 100;
|
||||
strcpy(project_name, "");
|
||||
strcpy(user_name, "");
|
||||
strcpy(team_name, "");
|
||||
user_total_credit = 0;
|
||||
user_expavg_credit = 0;
|
||||
user_create_time = 0;
|
||||
rpc_seqno = 0;
|
||||
hostid = 0;
|
||||
host_total_credit = 0;
|
||||
host_expavg_credit = 0;
|
||||
host_create_time = 0;
|
||||
exp_avg_cpu = 0;
|
||||
exp_avg_mod_time = 0;
|
||||
strcpy(code_sign_key, "");
|
||||
nrpc_failures = 0;
|
||||
min_rpc_time = 0;
|
||||
min_report_min_rpc_time = 0;
|
||||
master_fetch_failures = 0;
|
||||
resource_debt = 0;
|
||||
debt_order = 0;
|
||||
master_url_fetch_pending = false;
|
||||
sched_rpc_pending = false;
|
||||
tentative = false;
|
||||
}
|
||||
|
||||
PROJECT::~PROJECT() {
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "client_types.h"
|
||||
|
||||
class RPC_CLIENT {
|
||||
int sock;
|
||||
FILE* fin;
|
||||
FILE* fout;
|
||||
public:
|
||||
~RPC_CLIENT();
|
||||
int init(char*);
|
||||
int get_projects(vector<PROJECT>&);
|
||||
};
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
#include <vector.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "client_state.h"
|
||||
|
||||
GUI_RPC_CONN::GUI_RPC_CONN(int s) {
|
||||
sock = s;
|
||||
#ifndef _WIN32
|
||||
fout = fdopen(dup(sock), "w");
|
||||
#endif
|
||||
}
|
||||
|
||||
GUI_RPC_CONN::~GUI_RPC_CONN() {
|
||||
close(sock);
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
int GUI_RPC_CONN::handle_rpc() {
|
||||
char buf[256];
|
||||
int n;
|
||||
unsigned int i;
|
||||
|
||||
n = read(sock, buf, 256);
|
||||
if (n <= 0) return -1;
|
||||
buf[n] = 0;
|
||||
printf("got %s\n", buf);
|
||||
if (match_tag(buf, "<get_projects")) {
|
||||
fprintf(fout, "<projects>\n");
|
||||
for (i=0; i<gstate.projects.size(); i++) {
|
||||
PROJECT* p = gstate.projects[i];
|
||||
p->write_state(fout);
|
||||
}
|
||||
fprintf(fout, "</projects>\n");
|
||||
} else {
|
||||
fprintf(fout, "<unrecognized/>\n");
|
||||
}
|
||||
fflush(fout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GUI_RPC_CONN_SET::insert(GUI_RPC_CONN* p) {
|
||||
gui_rpcs.push_back(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GUI_RPC_CONN_SET::init(char* path) {
|
||||
sockaddr_un addr;
|
||||
int retval;
|
||||
|
||||
#ifndef _WIN32
|
||||
unlink(path);
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, path);
|
||||
lsock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (lsock < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
retval = bind(lsock, (const sockaddr*)(&addr), sizeof(addr));
|
||||
if (retval) {
|
||||
perror("bind");
|
||||
exit(1);
|
||||
}
|
||||
retval = listen(lsock, 999);
|
||||
if (retval) {
|
||||
perror("listen");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GUI_RPC_CONN_SET::poll() {
|
||||
#ifdef _WIN32
|
||||
return false;
|
||||
#else
|
||||
unsigned int i;
|
||||
fd_set read_fds, error_fds;
|
||||
int sock, n, retval;
|
||||
vector<GUI_RPC_CONN*>::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; i<gui_rpcs.size(); i++) {
|
||||
gr = gui_rpcs[i];
|
||||
FD_SET(gr->sock, &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)) {
|
||||
sock = accept(lsock, 0, 0);
|
||||
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);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
class GUI_RPC_CONN {
|
||||
public:
|
||||
int sock;
|
||||
FILE* fout;
|
||||
GUI_RPC_CONN(int);
|
||||
~GUI_RPC_CONN();
|
||||
int handle_rpc();
|
||||
};
|
||||
|
||||
class GUI_RPC_CONN_SET {
|
||||
vector<GUI_RPC_CONN*> gui_rpcs;
|
||||
int insert(GUI_RPC_CONN*);
|
||||
int lsock;
|
||||
public:
|
||||
bool poll();
|
||||
void init(char*);
|
||||
};
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "gui_rpc_client.h"
|
||||
|
||||
main() {
|
||||
RPC_CLIENT rpc;
|
||||
vector<PROJECT>projects;
|
||||
unsigned int i;
|
||||
|
||||
rpc.init("gui_rpc");
|
||||
rpc.get_projects(projects);
|
||||
for (i=0; i<projects.size(); i++) {
|
||||
PROJECT& project = projects[i];
|
||||
printf("%s: %s\n", project.master_url, project.project_name);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#! /bin/sh
|
||||
# From configure.ac Revision: 1.69 .
|
||||
# From configure.ac Revision: 1.70 .
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.57 for BOINC 2.19.
|
||||
#
|
||||
|
|
101
doc/upload.php
101
doc/upload.php
|
@ -25,77 +25,82 @@ Two RPC operations are used.
|
|||
<b>1) Get file size</b>
|
||||
<p>
|
||||
The request message has the form:
|
||||
<pre>
|
||||
<data_server_request>
|
||||
<core_client_major_version>1</core_client_major_version>
|
||||
<core_client_minor_version>1</core_client_minor_version>
|
||||
<get_file_size>filename</get_file_size>
|
||||
</data_server_request>
|
||||
</pre>
|
||||
<pre> ", htmlspecialchars("
|
||||
<data_server_request>
|
||||
<core_client_major_version>1</core_client_major_version>
|
||||
<core_client_minor_version>1</core_client_minor_version>
|
||||
<get_file_size>filename</get_file_size>
|
||||
</data_server_request>
|
||||
"), "</pre>
|
||||
|
||||
<p>
|
||||
The reply message has the form:
|
||||
<pre>
|
||||
<data_server_reply>
|
||||
<status>x</status>
|
||||
[ <message>text</message>
|
||||
| <file_size>nbytes</file_size> ]
|
||||
</data_server_reply>
|
||||
</pre>
|
||||
Status is
|
||||
<ul>
|
||||
<li> 0 on success.
|
||||
Nbytes is 0 if the file doesn't exist.
|
||||
<li> 1 on transient error.
|
||||
<pre> ", htmlspecialchars("
|
||||
<data_server_reply>
|
||||
<status>x</status>
|
||||
[ <message>text&<message>
|
||||
| <file_size>nbytes</file_size> ]
|
||||
</data_server_reply>
|
||||
"), "</pre>
|
||||
Status is";
|
||||
list_start();
|
||||
list_item("0", "Success. Nbytes is 0 if the file doesn't exist.");
|
||||
list_item("1", "Transient error.
|
||||
The client should try another data server, or try this one later.
|
||||
<li> -1 on permanent error.
|
||||
The client should give up on the result.
|
||||
</ul>
|
||||
");
|
||||
list_item("-1", "Permanent error. The client should give up on the result.");
|
||||
list_end();
|
||||
echo "
|
||||
In the error cases, the <file_size> element is omitted
|
||||
and the <message> element gives an explanation.
|
||||
<p>
|
||||
<b>2) Upload file</b>
|
||||
<p>
|
||||
Request message format:
|
||||
<pre>
|
||||
<data_server_request>
|
||||
<core_client_major_version>1</core_client_major_version>
|
||||
<core_client_minor_version>1</core_client_minor_version>
|
||||
<file_upload>
|
||||
<file_info>
|
||||
<pre> ", htmlspecialchars("
|
||||
<data_server_request>
|
||||
<core_client_major_version>1</core_client_major_version>
|
||||
<core_client_minor_version>1</core_client_minor_version>
|
||||
<file_upload>
|
||||
<file_info>
|
||||
...
|
||||
<xml_signature>
|
||||
<xml_signature>
|
||||
...
|
||||
</xml_signature>
|
||||
</file_info>
|
||||
<nbytes>x</nbytes>
|
||||
<offset>x</offset>
|
||||
<data>
|
||||
</xml_signature>
|
||||
</file_info>
|
||||
<nbytes>x</nbytes>
|
||||
<offset>x</offset>
|
||||
<data>
|
||||
... (nbytes bytes of data; may include non-ASCII data)
|
||||
</data>
|
||||
</pre>
|
||||
</data>
|
||||
"), "</pre>
|
||||
<p>
|
||||
The <file_info> element is the exact text sent from the
|
||||
scheduling server to the client.
|
||||
It includes a signature based on the project's file upload
|
||||
authentication key pair.
|
||||
<nbytes> is the amount of data being uploaded.
|
||||
<nbytes> is the size of the file.
|
||||
<offset> is the offset within the file.
|
||||
<p>
|
||||
Reply message format:
|
||||
<pre>
|
||||
<data_server_reply>
|
||||
<status>x</status>
|
||||
<message>text</message>
|
||||
</data_server_reply>
|
||||
</pre>
|
||||
Status is
|
||||
<ul>
|
||||
<li> 0 on success.
|
||||
<li> 1 on transient error.
|
||||
<pre> ", htmlspecialchars("
|
||||
<data_server_reply>
|
||||
<status>x</status>
|
||||
<message>text</message>
|
||||
</data_server_reply>
|
||||
"), "</pre>
|
||||
Status is ";
|
||||
|
||||
list_start();
|
||||
list_item("0", "success");
|
||||
list_item("1", "transient error;
|
||||
The client should try another data server, or try this one later.
|
||||
<li> -1 on permanent error.
|
||||
");
|
||||
list_item("-1", "Permanent error.
|
||||
The client should give up on the result.
|
||||
");
|
||||
list_end();
|
||||
echo "
|
||||
</ul>
|
||||
In the error cases, the <message> element gives an explanation.
|
||||
<p>
|
||||
|
|
10
lib/parse.C
10
lib/parse.C
|
@ -70,6 +70,7 @@ bool parse_double(const char* buf, const char* tag, double& x) {
|
|||
|
||||
// parse a string of the form ...<tag attrs>string</tag>...;
|
||||
// returns the "string" part.
|
||||
// "string" may not include '<'
|
||||
// Strips white space from ends.
|
||||
// Use "<tag", not "<tag>", if there might be attributes
|
||||
//
|
||||
|
@ -78,14 +79,13 @@ bool parse_str(const char* buf, const char* tag, char* dest, int len) {
|
|||
if (!p) return false;
|
||||
p = strchr(p, '>');
|
||||
++p;
|
||||
while (isspace(*p)) ++p;
|
||||
char* q = strchr(p, '<');
|
||||
if (!q) return false;
|
||||
while (isspace(*(q-1))) --q;
|
||||
char save_q = *q;
|
||||
*q = 0;
|
||||
safe_strncpy(dest, p, len);
|
||||
*q = save_q;
|
||||
strip_whitespace(dest);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -96,15 +96,15 @@ bool parse_str(const char* buf, const char* tag, string& dest) {
|
|||
if (!p) return false;
|
||||
p = strchr(p, '>');
|
||||
++p;
|
||||
while (isspace(*p)) ++p;
|
||||
char const* q = strchr(p, '<');
|
||||
if (!q) return false;
|
||||
while (isspace(*(q-1))) --q;
|
||||
dest.assign(p, q-p);
|
||||
strip_whitespace(dest);
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse a string of the form name="string"
|
||||
// parse a string of the form name="string";
|
||||
// returns string in dest
|
||||
//
|
||||
void parse_attr(const char* buf, const char* name, char* dest, int len) {
|
||||
char* p, *q;
|
||||
|
|
33
lib/util.C
33
lib/util.C
|
@ -289,15 +289,34 @@ void c2x(char *what) {
|
|||
strcpy(what, buf);
|
||||
}
|
||||
|
||||
// remove whitespace from start and end of a string
|
||||
//
|
||||
void strip_whitespace(char *str) {
|
||||
int read_pos=0, write_pos=0;
|
||||
while (str[read_pos]) {
|
||||
if (!isspace(str[read_pos])) {
|
||||
str[write_pos++] = str[read_pos];
|
||||
}
|
||||
read_pos++;
|
||||
int n;
|
||||
while (isascii(str[0]) && isspace(str[0])) {
|
||||
strcpy(str, str+1);
|
||||
}
|
||||
while (1) {
|
||||
n = strlen(str);
|
||||
if (n == 0) break;
|
||||
if (!isascii(str[n-1])) break;
|
||||
if (!isspace(str[n-1])) break;
|
||||
str[n-1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void strip_whitespace(string& str) {
|
||||
int n;
|
||||
while (isascii(str[0]) && isspace(str[0])) {
|
||||
str.erase(0, 1);
|
||||
}
|
||||
while (1) {
|
||||
n = str.length();
|
||||
if (n == 0) break;
|
||||
if (!isascii(str[n-1])) break;
|
||||
if (!isspace(str[n-1])) break;
|
||||
str.erase(n-1, 1);
|
||||
}
|
||||
str[write_pos] = 0;
|
||||
}
|
||||
|
||||
void unescape_url(char *url) {
|
||||
|
|
12
lib/util.h
12
lib/util.h
|
@ -40,6 +40,7 @@ extern int parse_command_line( char *, char ** );
|
|||
extern int lock_file(char*);
|
||||
extern void c2x(char *what);
|
||||
extern void strip_whitespace(char *str);
|
||||
extern void strip_whitespace(string&);
|
||||
extern void unescape_url(char *url);
|
||||
extern void escape_url(char *in, char*out);
|
||||
extern void escape_url_readable(char* in, char* out);
|
||||
|
@ -62,19 +63,16 @@ inline bool starts_with(string const& s, string const& prefix) {
|
|||
}
|
||||
|
||||
// http://lists.debian.org/debian-gcc/2002/debian-gcc-200204/msg00092.html
|
||||
inline void downcase_string(string::iterator begin, string::iterator end,
|
||||
string::iterator src)
|
||||
{
|
||||
inline void downcase_string(
|
||||
string::iterator begin, string::iterator end, string::iterator src
|
||||
) {
|
||||
std::transform(begin, end, src, (int(*)(int))tolower);
|
||||
}
|
||||
|
||||
inline void downcase_string(string& w)
|
||||
{
|
||||
inline void downcase_string(string& w) {
|
||||
downcase_string(w.begin(), w.end(), w.begin());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// NOTE: use #include <functional> to get max,min
|
||||
|
||||
// the __attribute((format...)) tags are GCC extensions that let the compiler
|
||||
|
|
Loading…
Reference in New Issue