1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2013 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
17 
18 #ifndef BOINC_ASYNCRPC_H
19 #define BOINC_ASYNCRPC_H
20 
21 #if defined(__GNUG__) && !defined(__APPLE__)
22 #pragma interface "AsyncRPC.cpp"
23 #endif
24 
25 #ifndef __WXMAC__
26 
27 #define BOINC_Condition wxCondition
28 #define BOINC_Mutex wxMutex
29 
30 #else
31 
32 // Adapted from wxMac-2.8.10
33 #include <pthread.h>
34 
35 
36 #if 1
37 #define BOINC_Mutex wxMutex
38 #define BOINC_Condition wxCondition
39 #else
40 class BOINC_Mutex
41 {
42 public:
43     BOINC_Mutex( wxMutexType mutexType = wxMUTEX_DEFAULT );
44     ~BOINC_Mutex();
45 
46     wxMutexError Lock();
47     wxMutexError TryLock();
48     wxMutexError Unlock();
49 
IsOk()50     bool IsOk() const
51     { return m_isOk; }
52 
53 private:
54     pthread_mutex_t m_mutex;
55     bool m_isOk;
56 
57     // BOINC_Condition uses our m_mutex
58     friend class BOINC_Condition;
59 };
60 
61 
62 // Adapted from wxMac-2.8.10 but using native pthread_cond_*()
63 class BOINC_Condition
64 {
65 public:
66     BOINC_Condition(BOINC_Mutex& mutex);
67     ~BOINC_Condition();
IsOk()68     bool IsOk() const { return (m_BOINC_Mutex.IsOk() && mb_initOK); }
69     wxCondError Wait();
70     wxCondError WaitTimeout(unsigned long milliseconds);
71     void Signal();
72     void Broadcast();
73 
74 private:
75     BOINC_Mutex&                m_BOINC_Mutex;
76     pthread_cond_t              m_cond;
77     bool                        mb_initOK;
78 
79     DECLARE_NO_COPY_CLASS(BOINC_Condition)
80 };
81 
82 #endif
83 #endif
84 
85 class CMainDocument;    // Forward declaration
86 
87 enum RPC_SELECTOR {
88     RPC_AUTHORIZE = 1,
89     RPC_EXCHANGE_VERSIONS,
90     RPC_GET_STATE,
91     RPC_GET_RESULTS,
92     RPC_GET_FILE_TRANSFERS,
93     RPC_GET_SIMPLE_GUI_INFO1,
94     RPC_GET_SIMPLE_GUI_INFO2,
95     RPC_GET_PROJECT_STATUS1,
96     RPC_GET_PROJECT_STATUS2,
97     RPC_GET_ALL_PROJECTS_LIST,              // 10
98     RPC_GET_DISK_USAGE,
99     RPC_PROJECT_OP,
100     RPC_SET_RUN_MODE,
101     RPC_SET_GPU_MODE,
102     RPC_SET_NETWORK_MODE,
103     RPC_GET_SCREENSAVER_TASKS,
104     RPC_RUN_BENCHMARKS,
105     RPC_SET_PROXY_SETTINGS,
106     RPC_GET_PROXY_SETTINGS,
107     RPC_GET_MESSAGES,                       // 20
108     RPC_FILE_TRANSFER_OP,
109     RPC_RESULT_OP,
110     RPC_GET_HOST_INFO,
111     RPC_QUIT,
112     RPC_ACCT_MGR_INFO,
113     RPC_GET_STATISTICS,
114     RPC_NETWORK_AVAILABLE,
115     RPC_GET_PROJECT_INIT_STATUS,
116     RPC_GET_PROJECT_CONFIG,
117     RPC_GET_PROJECT_CONFIG_POLL,            // 30
118     RPC_LOOKUP_ACCOUNT,
119     RPC_LOOKUP_ACCOUNT_POLL,
120     RPC_CREATE_ACCOUNT,
121     RPC_CREATE_ACCOUNT_POLL,
122     RPC_PROJECT_ATTACH,
123     RPC_PROJECT_ATTACH_FROM_FILE,
124     RPC_PROJECT_ATTACH_POLL,
125     RPC_ACCT_MGR_RPC,
126     RPC_ACCT_MGR_RPC_POLL,
127     RPC_GET_NEWER_VERSION,                  // 40
128     RPC_READ_GLOBAL_PREFS_OVERRIDE,
129     RPC_READ_CC_CONFIG,
130     RPC_GET_CC_STATUS,
131     RPC_GET_GLOBAL_PREFS_FILE,
132     RPC_GET_GLOBAL_PREFS_WORKING,
133     RPC_GET_GLOBAL_PREFS_WORKING_STRUCT,
134     RPC_GET_GLOBAL_PREFS_OVERRIDE,
135     RPC_SET_GLOBAL_PREFS_OVERRIDE,
136     RPC_GET_GLOBAL_PREFS_OVERRIDE_STRUCT,
137     RPC_SET_GLOBAL_PREFS_OVERRIDE_STRUCT,   // 50
138     RPC_GET_NOTICES,
139     RPC_GET_CC_CONFIG,
140     RPC_SET_CC_CONFIG,
141 	RPC_SET_LANGUAGE,
142     NUM_RPC_SELECTORS
143 };
144 
145 
146 enum ASYNC_RPC_TYPE {
147     // Demand RPC: wait for completion before returning (usually
148     // a user-initiated request.)
149     RPC_TYPE_WAIT_FOR_COMPLETION = 1,
150     // Periodic RPC: post request on queue and return immediately
151     // (requested due to a timer interrupt.)
152     RPC_TYPE_ASYNC_NO_REFRESH,
153     // Periodic RPC as above, but on completion also process a
154     // wxEVT_FRAME_REFRESHVIEW event to refresh the display.
155     RPC_TYPE_ASYNC_WITH_REFRESH_AFTER,
156     // Periodic RPC as above, but on completion also process a
157     // wxEVT_FRAME_REFRESHVIEW event to refresh the display.
158     RPC_TYPE_ASYNC_WITH_REFRESH_EVENT_LOG_AFTER,
159     // Periodic RPC as above, but on completion also process a
160     // wxEVT_TASKBAR_REFRESH event to refresh the taskbar icon.
161     RPC_TYPE_ASYNC_WITH_UPDATE_TASKBAR_ICON_AFTER,
162     NUM_RPC_TYPES
163 };
164 
165 // Pass the following structure to CMainDocument::RequestRPC()
166 // The members are as follows:
167 //
168 //   arg1 is usually the buffer to read into
169 //
170 //   exchangeBuf is the (optional) buffer to exchange with after
171 //     completing the RPC, the buffer used by the Manager code.
172 //     Pass NULL if you don't want the buffer exchanged.
173 //
174 //  arg2, arg3, arg4 are additional arguments when needed by the
175 //      RPC call; their usage varies for different RPC requests.
176 //
177 //  rpcType is as described above
178 //
179 //  completionTime is a pointer to a wxDateTime variable into which
180 //      to write the completion time of the RPC.  It may be NULL.
181 //
182 //  resultPtr is a pointer to an int into which to write the result
183 //      returned by the RPC call.  It may be NULL.
184 //
185 //  retval is for internal use by the async RPC logic; do not use.
186 //
187 //  isActive is for internal use by the async RPC logic; do not use.
188 //
189 
190 struct ASYNC_RPC_REQUEST {
191     RPC_SELECTOR which_rpc;
192     void *arg1;
193     void *exchangeBuf;
194     void *arg2;
195     void *arg3;
196     void *arg4;
197     ASYNC_RPC_TYPE rpcType;
198     wxDateTime *completionTime;
199     double *RPCExecutionTime;
200     int *resultPtr;
201     int retval;
202     bool isActive;
203 
204     ASYNC_RPC_REQUEST();
205     ~ASYNC_RPC_REQUEST();
206 
207     void                        clear();
208     bool                        isSameAs(ASYNC_RPC_REQUEST& otherRequest);
209 };
210 
211 
212 class AsyncRPC
213 {
214 public:
215     AsyncRPC(CMainDocument *pDoc);
216     ~AsyncRPC();
217 
218     int RPC_Wait(
219             RPC_SELECTOR which_rpc, void* arg1 = NULL, void*
220             arg2 = NULL, void* arg3 = NULL, void* arg4 = NULL,
221             bool hasPriority = false
222     );
223 
224     // Manager must do all RPC data transfers through AsyncRPC calls, so
225     // this class must have methods corresponding to all RPC_CLIENT data
226     // transfer operations, but NOT init(), init_async(), close(), etc.
authorize(const char * passwd)227     int authorize(const char* passwd)
228             { return RPC_Wait(RPC_AUTHORIZE, (void*)passwd); }
exchange_versions(VERSION_INFO & arg1)229     int exchange_versions(VERSION_INFO& arg1)
230             { return RPC_Wait(RPC_EXCHANGE_VERSIONS, (void*)&arg1); }
get_state(CC_STATE & arg1)231     int get_state(CC_STATE& arg1)
232             { return RPC_Wait(RPC_GET_STATE, (void*)&arg1); }
get_results(RESULTS & arg1,bool & arg2)233     int get_results(RESULTS& arg1, bool& arg2)
234             { return RPC_Wait(RPC_GET_RESULTS, (void*)&arg1, (void*)&arg2); }
get_file_transfers(FILE_TRANSFERS & arg1)235     int get_file_transfers(FILE_TRANSFERS& arg1)
236             { return RPC_Wait(RPC_GET_FILE_TRANSFERS, (void*)&arg1); }
get_simple_gui_info(SIMPLE_GUI_INFO & arg1)237     int get_simple_gui_info(SIMPLE_GUI_INFO& arg1)
238             { return RPC_Wait(RPC_GET_SIMPLE_GUI_INFO1, (void*)&arg1); }
get_simple_gui_info(PROJECTS & arg1,CC_STATE & ccbuf,RESULTS & rbuf,bool & activeTasksOnly)239     int get_simple_gui_info(PROJECTS& arg1, CC_STATE& ccbuf, RESULTS& rbuf, bool& activeTasksOnly)
240             { return RPC_Wait(RPC_GET_SIMPLE_GUI_INFO2, (void*)&arg1, (void*)&ccbuf, (void*)&rbuf, (void*)&activeTasksOnly); }
get_project_status(PROJECTS & arg1,CC_STATE & arg2)241     int get_project_status(PROJECTS& arg1, CC_STATE& arg2)
242             { return RPC_Wait(RPC_GET_PROJECT_STATUS1, (void*)&arg1, (void*)&arg2); }
get_project_status(PROJECTS & arg1)243     int get_project_status(PROJECTS& arg1)
244             { return RPC_Wait(RPC_GET_PROJECT_STATUS2, (void*)&arg1); }
get_all_projects_list(ALL_PROJECTS_LIST & arg1)245     int get_all_projects_list(ALL_PROJECTS_LIST& arg1)
246             { return RPC_Wait(RPC_GET_ALL_PROJECTS_LIST, (void*)&arg1); }
get_disk_usage(DISK_USAGE & arg1)247     int get_disk_usage(DISK_USAGE& arg1)
248             { return RPC_Wait(RPC_GET_DISK_USAGE, (void*)&arg1); }
project_op(PROJECT & arg1,const char * op)249     int project_op(PROJECT& arg1, const char* op)
250             { return RPC_Wait(RPC_PROJECT_OP, (void*)&arg1, (void*)op); }
set_run_mode(int mode,double duration)251     int set_run_mode(int mode, double duration)
252             { return RPC_Wait(RPC_SET_RUN_MODE, (void*)&mode, (void*)&duration); }
253         // if duration is zero, change is permanent.
254         // otherwise, after duration expires,
255         // restore last permanent mode
set_gpu_mode(int mode,double duration)256     int set_gpu_mode(int mode, double duration)
257             { return RPC_Wait(RPC_SET_GPU_MODE, (void*)&mode, (void*)&duration); }
set_network_mode(int mode,double duration)258     int set_network_mode(int mode, double duration)
259             { return RPC_Wait(RPC_SET_NETWORK_MODE, (void*)&mode, (void*)&duration); }
get_screensaver_tasks(int & suspend_reason,RESULTS & rbuf)260     int get_screensaver_tasks(int& suspend_reason, RESULTS& rbuf)
261             { return RPC_Wait(RPC_GET_SCREENSAVER_TASKS, (void*)&suspend_reason, (void*)&rbuf); }
run_benchmarks()262     int run_benchmarks()
263             { return RPC_Wait(RPC_RUN_BENCHMARKS); }
set_proxy_settings(GR_PROXY_INFO & arg1)264     int set_proxy_settings(GR_PROXY_INFO& arg1)
265             { return RPC_Wait(RPC_SET_PROXY_SETTINGS, (void*)&arg1); }
get_proxy_settings(GR_PROXY_INFO & arg1)266     int get_proxy_settings(GR_PROXY_INFO& arg1)
267             { return RPC_Wait(RPC_GET_PROXY_SETTINGS, (void*)&arg1); }
get_messages(int seqno,MESSAGES & arg1)268     int get_messages(int seqno, MESSAGES& arg1)
269             { return RPC_Wait(RPC_GET_MESSAGES, (void*)&seqno, (void*)&arg1); }
get_notices(int seqno,NOTICES & arg1)270     int get_notices(int seqno, NOTICES& arg1)
271             { return RPC_Wait(RPC_GET_NOTICES, (void*)&seqno, (void*)&arg1); }
file_transfer_op(FILE_TRANSFER & arg1,const char * op)272     int file_transfer_op(FILE_TRANSFER& arg1, const char* op)
273             { return RPC_Wait(RPC_FILE_TRANSFER_OP, (void*)&arg1, (void*)op); }
result_op(RESULT & arg1,const char * op)274     int result_op(RESULT& arg1, const char* op)
275             { return RPC_Wait(RPC_RESULT_OP, (void*)&arg1, (void*)op); }
get_host_info(HOST_INFO & arg1)276     int get_host_info(HOST_INFO& arg1)
277             { return RPC_Wait(RPC_GET_HOST_INFO, (void*)&arg1); }
quit()278     int quit()
279             { return RPC_Wait(RPC_QUIT); }
acct_mgr_info(ACCT_MGR_INFO & arg1)280     int acct_mgr_info(ACCT_MGR_INFO& arg1)
281             { return RPC_Wait(RPC_ACCT_MGR_INFO, (void*)&arg1); }
get_statistics(PROJECTS & arg1)282     int get_statistics(PROJECTS& arg1)
283             { return RPC_Wait(RPC_GET_STATISTICS, (void*)&arg1); }
network_available()284     int network_available()
285             { return RPC_Wait(RPC_NETWORK_AVAILABLE); }
get_project_init_status(PROJECT_INIT_STATUS & pis)286     int get_project_init_status(PROJECT_INIT_STATUS& pis)
287             { return RPC_Wait(RPC_GET_PROJECT_INIT_STATUS, (void*)&pis); }
288 
289     // the following are asynch operations.
290     // Make the first call to start the op,
291     // call the second one periodically until it returns zero.
292     // TODO: do project update
293     //
get_project_config(std::string url)294     int get_project_config(std::string url)
295             { return RPC_Wait(RPC_GET_PROJECT_CONFIG, (void*)&url); }
get_project_config_poll(PROJECT_CONFIG & arg1)296     int get_project_config_poll(PROJECT_CONFIG& arg1)
297             { return RPC_Wait(RPC_GET_PROJECT_CONFIG_POLL, (void*)&arg1); }
lookup_account(ACCOUNT_IN & arg1)298     int lookup_account(ACCOUNT_IN& arg1)
299             { return RPC_Wait(RPC_LOOKUP_ACCOUNT, (void*)&arg1); }
lookup_account_poll(ACCOUNT_OUT & arg1)300     int lookup_account_poll(ACCOUNT_OUT& arg1)
301             { return RPC_Wait(RPC_LOOKUP_ACCOUNT_POLL, (void*)&arg1); }
create_account(ACCOUNT_IN & arg1)302     int create_account(ACCOUNT_IN& arg1)
303             { return RPC_Wait(RPC_CREATE_ACCOUNT, (void*)&arg1); }
create_account_poll(ACCOUNT_OUT & arg1)304     int create_account_poll(ACCOUNT_OUT& arg1)
305             { return RPC_Wait(RPC_CREATE_ACCOUNT_POLL, (void*)&arg1); }
project_attach(const char * url,const char * auth,const char * project_name)306     int project_attach(
307         const char* url, const char* auth, const char* project_name
308     )       { return RPC_Wait(RPC_PROJECT_ATTACH, (void*)url, (void*)auth, (void*)project_name); }
project_attach_from_file()309     int project_attach_from_file()
310             { return RPC_Wait(RPC_PROJECT_ATTACH_FROM_FILE); }
project_attach_poll(PROJECT_ATTACH_REPLY & arg1)311     int project_attach_poll(PROJECT_ATTACH_REPLY& arg1)
312             { return RPC_Wait(RPC_PROJECT_ATTACH_POLL, (void*)&arg1); }
313     int acct_mgr_rpc(
314         const char* url, const char* name, const char* passwd,
315         bool use_config_file=false
316     )       { return RPC_Wait(RPC_ACCT_MGR_RPC, (void*)url, (void*)name, (void*)passwd, (void*)use_config_file); }
acct_mgr_rpc_poll(ACCT_MGR_RPC_REPLY & arg1)317     int acct_mgr_rpc_poll(ACCT_MGR_RPC_REPLY& arg1)
318             { return RPC_Wait(RPC_ACCT_MGR_RPC_POLL, (void*)&arg1); }
319 
get_newer_version(std::string & version,std::string & version_download_url)320     int get_newer_version(std::string& version, std::string& version_download_url)
321             { return RPC_Wait(RPC_GET_NEWER_VERSION, (void*)&version, (void*)&version_download_url); }
read_global_prefs_override()322     int read_global_prefs_override()
323             { return RPC_Wait(RPC_READ_GLOBAL_PREFS_OVERRIDE); }
read_cc_config()324     int read_cc_config()
325             { return RPC_Wait(RPC_READ_CC_CONFIG); }
get_cc_status(CC_STATUS & arg1)326     int get_cc_status(CC_STATUS& arg1)
327             { return RPC_Wait(RPC_GET_CC_STATUS, (void*)&arg1); }
get_global_prefs_file(std::string & arg1)328     int get_global_prefs_file(std::string& arg1)
329             { return RPC_Wait(RPC_GET_GLOBAL_PREFS_FILE, (void*)&arg1); }
get_global_prefs_working(std::string & arg1)330     int get_global_prefs_working(std::string& arg1)
331             { return RPC_Wait(RPC_GET_GLOBAL_PREFS_WORKING, (void*)&arg1); }
get_global_prefs_working_struct(GLOBAL_PREFS & arg1,GLOBAL_PREFS_MASK & arg2)332     int get_global_prefs_working_struct(GLOBAL_PREFS& arg1, GLOBAL_PREFS_MASK& arg2)
333             { return RPC_Wait(RPC_GET_GLOBAL_PREFS_WORKING_STRUCT, (void*)&arg1, (void*)&arg2); }
get_global_prefs_override(std::string & arg1)334     int get_global_prefs_override(std::string& arg1)
335             { return RPC_Wait(RPC_GET_GLOBAL_PREFS_OVERRIDE, (void*)&arg1); }
set_global_prefs_override(std::string & arg1)336     int set_global_prefs_override(std::string& arg1)
337             { return RPC_Wait(RPC_SET_GLOBAL_PREFS_OVERRIDE, (void*)&arg1); }
get_global_prefs_override_struct(GLOBAL_PREFS & arg1,GLOBAL_PREFS_MASK & arg2)338     int get_global_prefs_override_struct(GLOBAL_PREFS& arg1, GLOBAL_PREFS_MASK& arg2)
339             { return RPC_Wait(RPC_GET_GLOBAL_PREFS_OVERRIDE_STRUCT, (void*)&arg1, (void*)&arg2); }
set_global_prefs_override_struct(GLOBAL_PREFS & arg1,GLOBAL_PREFS_MASK & arg2)340     int set_global_prefs_override_struct(GLOBAL_PREFS& arg1, GLOBAL_PREFS_MASK& arg2)
341             { return RPC_Wait(RPC_SET_GLOBAL_PREFS_OVERRIDE_STRUCT, (void*)&arg1, (void*)&arg2); }
get_cc_config(CC_CONFIG & arg1,LOG_FLAGS & arg2)342     int get_cc_config(CC_CONFIG& arg1, LOG_FLAGS& arg2)
343             { return RPC_Wait(RPC_GET_CC_CONFIG, (void*)&arg1, (void*)&arg2); }
set_cc_config(CC_CONFIG & arg1,LOG_FLAGS & arg2)344     int set_cc_config(CC_CONFIG& arg1, LOG_FLAGS& arg2)
345             { return RPC_Wait(RPC_SET_CC_CONFIG, (void*)&arg1, (void*)&arg2); }
346 private:
347     CMainDocument*              m_pDoc;
348 };
349 
350 
351 class RPCThread : public wxThread
352 {
353 public:
354     RPCThread(CMainDocument *pDoc,
355                 BOINC_Mutex* pRPC_Thread_Mutex,
356                 BOINC_Condition* pRPC_Thread_Condition,
357                 BOINC_Mutex* pRPC_Request_Mutex,
358                 BOINC_Condition* RPC_Request_Condition
359             );
360     virtual void                *Entry();
361 
362 private:
363     int                         ProcessRPCRequest();
364     CMainDocument*              m_pDoc;
365     BOINC_Mutex*                m_pRPC_Thread_Mutex;
366     BOINC_Condition*            m_pRPC_Thread_Condition;
367     BOINC_Mutex*                m_pRPC_Request_Mutex;
368     BOINC_Condition*            m_pRPC_Request_Condition;
369 };
370 
371 
372 class AsyncRPCDlg : public wxDialog
373 {
374     DECLARE_DYNAMIC_CLASS( AsyncRPCDlg )
375     DECLARE_EVENT_TABLE()
376 
377 public:
378     AsyncRPCDlg();
379     void                        OnRPCDlgTimer(wxTimerEvent &event);
380     void                        OnExit(wxCommandEvent& event);
381 };
382 
383 
384 class CRPCFinishedEvent : public wxEvent
385 {
386 public:
CRPCFinishedEvent(wxEventType evtType)387     CRPCFinishedEvent(wxEventType evtType)
388         : wxEvent(-1, evtType)
389         {
390             SetEventObject(wxTheApp);
391         }
392 
Clone()393     virtual wxEvent *Clone() const { return new CRPCFinishedEvent(*this); }
394 };
395 
396 BEGIN_DECLARE_EVENT_TYPES()
397 DECLARE_EVENT_TYPE( wxEVT_RPC_FINISHED, -1 )
398 END_DECLARE_EVENT_TYPES()
399 
400 #define EVT_RPC_FINISHED(fn) \
401     DECLARE_EVENT_TABLE_ENTRY(wxEVT_RPC_FINISHED, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL),
402 
403 
404 
405 #endif
406