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