00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "msg_rpc.h"
00029 #include "imsg.h"
00030
00031 #include "base/string.hpp"
00032 #include "base/list.hpp"
00033 #include "base/memory.hpp"
00034 #include "base/template.hpp"
00035 #include "base/common.hpp"
00036 #include "base/except.h"
00037 #include "base/number.hpp"
00038
00039
00040 BEGIN_TERIMBER_NAMESPACE
00041 #pragma pack(4)
00042
00043 extern exception_table msgMsgTable;
00044
00045 #define prc_s_duplicate_endpoint RPC_S_DUPLICATE_ENDPOINT
00046
00047 exception_item rpcMsgs[] =
00048 {
00049 { rpc_s_ok, "Action succeeded" },
00050 { ept_s_cant_perform_op, "The server endpoint cannot perform the operation" },
00051 { ept_s_invalid_entry, "The entry is invalid" },
00052 { ept_s_not_registered, "There are no more endpoints available from the endpoint mapper" },
00053 { rpc_s_already_listening, "The RPC server is already listening" },
00054 { rpc_s_already_registered, "The object universal unique identifier (UUID) has already been registered" },
00055 { rpc_s_binding_has_no_auth, "The binding does not contain any authentication information" },
00056
00057 { rpc_s_call_cancelled, "The remote procedure call was cancelled" },
00058 { rpc_s_call_failed, "The remote procedure call failed" },
00059
00060 { rpc_s_cant_create_socket, "The endpoint cannot be created" },
00061 { rpc_s_comm_failure, "A communications failure occurred during a remote procedure call" },
00062 { rpc_s_connect_no_resources, "Not enough resources are available to complete this operation" },
00063 { rpc_s_cthread_create_failed, "RPC can not open more threads" },
00064 { rpc_s_endpoint_not_found, "No endpoint was found" },
00065 { rpc_s_entry_already_exists, "The entry already exists" },
00066 { rpc_s_entry_not_found, "The entry is not found" },
00067 { rpc_s_fault_addr_error, "An addressing error occurred in the RPC server" },
00068 { rpc_s_fault_fp_div_by_zero, "A floating-point operation at the RPC server caused a division by zero" },
00069 { rpc_s_fault_fp_overflow, "A floating-point overflow occurred at the RPC server" },
00070 { rpc_s_fault_fp_underflow, "A floating-point underflow occurred at the RPC server" },
00071 { rpc_s_fault_int_div_by_zero, "The RPC server attempted an integer division by zero" },
00072 { rpc_s_fault_invalid_bound, "The array bounds are invalid" },
00073 { rpc_s_fault_invalid_tag, "The tag is invalid" },
00074 { rpc_s_fault_remote_no_memory, "RPC server out of memory" },
00075 { rpc_s_fault_unspec, "The remote procedure call failed" },
00076 { rpc_s_incomplete_name, "The entry name is incomplete" },
00077 { rpc_s_interface_not_found, "The interface was not found" },
00078 { rpc_s_internal_error, "An internal error occurred in a remote procedure call (RPC)" },
00079 { rpc_s_inval_net_addr, "The network address is invalid" },
00080 { rpc_s_invalid_arg, "Invalid argument specified" },
00081 { rpc_s_invalid_binding, "The binding handle is invalid" },
00082 { rpc_s_invalid_endpoint_format, "The endpoint format is invalid" },
00083
00084 { rpc_s_invalid_name_syntax, "The name syntax is invalid" },
00085 { rpc_s_invalid_rpc_protseq, "The RPC protocol sequence is invalid" },
00086 { rpc_s_invalid_string_binding, "The string binding is invalid" },
00087 { rpc_s_invalid_vers_option, "The version option is invalid" },
00088 { rpc_s_max_calls_too_small, "The maximum number of calls is too small" },
00089 { rpc_s_mgmt_op_disallowed, "Access denied" },
00090 { rpc_s_name_service_unavailable, "The name service is unavailable" },
00091 { rpc_s_no_bindings, "There are no bindings" },
00092 { rpc_s_no_entry_name, "The binding does not contain an entry name" },
00093 { rpc_s_no_interfaces, "No interfaces have been registered" },
00094
00095 { rpc_s_no_memory, "Not enough memory" },
00096 { rpc_s_no_more_elements, "The list of RPC servers available for the binding of auto handles has been exhausted" },
00097 { rpc_s_no_more_bindings, "There are no more bindings" },
00098 { rpc_s_no_more_members, "There are no more members" },
00099 { rpc_s_no_ns_permission, "Access denied" },
00100 { rpc_s_no_princ_name, "No principal name registered" },
00101 { rpc_s_no_protseqs, "There are no protocol sequences" },
00102 { rpc_s_no_protseqs_registered, "No protocol sequences have been registered" },
00103 { rpc_s_not_rpc_tower, "The requested operation is not supported" },
00104 { rpc_s_not_supported, "No security context is available to allow impersonation" },
00105 { rpc_s_not_authorized, "Access denied" },
00106
00107 { rpc_s_object_not_found, "The object universal unique identifier (UUID) was not found" },
00108 { rpc_s_protocol_error, "A remote procedure call (RPC) protocol error occurred" },
00109 { rpc_s_protseq_not_supported, "The RPC protocol sequence is not supported" },
00110 { rpc_s_server_too_busy, "The RPC server is too busy to complete this operation" },
00111 { rpc_s_string_too_long, "The string is too long" },
00112 { rpc_s_type_already_registered, "The type universal unique identifier (UUID) has already been registered" },
00113 { rpc_s_unknown_authn_service, "The authentication service is unknown" },
00114 { rpc_s_unknown_authz_service, "The authorization service is unknown" },
00115 { rpc_s_unknown_if, "The interface is unknown" },
00116 { rpc_s_unknown_mgr_type, "The manager type is unknown" },
00117 { rpc_s_unknown_reject, "The remote procedure call failed and did not execute" },
00118 { rpc_s_unsupported_name_syntax, "The name syntax is not supported" },
00119 { rpc_s_unsupported_type, "The universal unique identifier (UUID) type is not supported" },
00120 { rpc_s_wrong_boot_time, "The remote procedure call failed and did not execute" },
00121 { rpc_s_wrong_kind_of_binding, "The binding handle is not the correct type" },
00122 { prc_s_duplicate_endpoint, "The duplicate endpoint" },
00123 { 0, 0 }
00124 };
00125
00126
00127 exception_table rpcMsgTable(rpcMsgs);
00128
00129 static
00130 inline
00131 ub1_t* uustring(char* x, size_t len, const guid_t& y)
00132 {
00133 str_template::strprint(x, len, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", y.Data1, y.Data2, y.Data3,
00134 y.Data4[0], y.Data4[1], y.Data4[2], y.Data4[3], y.Data4[4], y.Data4[5], y.Data4[6], y.Data4[7]);
00135 return (ub1_t*)x;
00136 }
00137
00138
00139
00140 static const char* g_protocol = "ncalrpc";
00141 static const char* g_protocol_ = "ncalrpc:";
00142
00143 static void rpcStatus(int status_)
00144 {
00145 if (status_ != rpc_s_ok)
00146 exception::_throw(status_, (exception_table*)&rpcMsgTable);
00147 }
00148
00149 static const IMSG_SERVER_EPV g_epv = {ServerConnect, ServerPostBlock};
00150 static char g_name[300];
00151
00152
00153 msg_rpc_global g_rpc_global;
00155 msg_rpc_global::msg_rpc_global() : _done(false), _rpcStarter(false)
00156 {
00157 }
00158
00159 void
00160 msg_rpc_global::init(size_t connections)
00161 {
00162 if (_done)
00163 return;
00164
00165 int status = 0;
00166
00167
00168 str_template::strcpy(g_name, g_protocol_, os_minus_one);
00169 if (gethostname(g_name + strlen(g_protocol_), 255))
00170 exception::_throw("Unknown computer name");
00171
00172
00173 rpc_server_use_protseq((ub1_t*)g_protocol, (int)connections, &status);
00174 rpcStatus(status);
00175
00176
00177 rpc_server_listen((int)RPC_C_LISTEN_MAX_CALLS_DEFAULT, &status);
00178 if (status != rpc_s_already_listening)
00179 {
00180 rpcStatus(status);
00181 _rpcStarter = true;
00182 }
00183 else
00184 _rpcStarter = false;
00185
00186 _done = true;
00187 }
00188
00189 void
00190 msg_rpc_global::_undo()
00191 {
00192 size_t status = 0;
00193
00194
00195 if (_rpcStarter)
00196 {
00197
00198 rpc_mgmt_stop_server_listening(0, &status);
00199 }
00200
00201 _done = false;
00202 }
00203
00204 msg_rpc_global::~msg_rpc_global()
00205 {
00206 if (_done)
00207 _undo();
00208 }
00209
00211
00212 class rpc2_communicator_keeper
00213 {
00214 public:
00215 rpc2_communicator_keeper(const guid_t& addr) : _address(addr) { _communicator = msg_communicator::loan_communicator(_address); }
00216 ~rpc2_communicator_keeper() { if (_communicator) msg_communicator::return_communicator(_address, _communicator); }
00217
00218 msg_communicator* operator->() { return _communicator; }
00219 msg_communicator* operator()() { return _communicator; }
00220 bool operator!() { return _communicator == 0; }
00221 operator bool() { return _communicator != 0; }
00222
00223 private:
00224 msg_communicator* _communicator;
00225 const guid_t& _address;
00226 };
00227
00229 msg_rpc_listener::msg_rpc_listener(msg_communicator* communicator_, const conf_listener& info_) :
00230 msg_listener(communicator_, info_)
00231 {
00232 }
00233
00234
00235 msg_rpc_listener::~msg_rpc_listener()
00236 {
00237 }
00238
00239
00240
00241 void
00242 msg_rpc_listener::v_on()
00243 {
00244 if (is_on())
00245 return;
00246
00247 int status = 0;
00248
00249 g_rpc_global.init(_info._connections);
00250
00251
00252 char buf[64];
00253 rpc_server_use_protseq_ep((ub1_t*)g_protocol, (int)_info._connections, uustring(buf, sizeof(buf), _info._address), &status);
00254 rpcStatus(status);
00255
00256
00257 rpc_server_register_if(ServerIMSG_ServerIfHandle, &_info._address, &g_epv, &status);
00258
00259 rpcStatus(status);
00260
00261
00262 rpc_binding_vector_t* vec = 0;
00263 rpc_server_inq_bindings(&vec, &status);
00264 rpcStatus(status);
00265
00266
00267
00268
00269 UUID_VECTOR uvec;
00270 uvec.Count = 1;
00271 uvec.Uuid[0] = (UUID*)&_info._address;
00272
00273 rpc_ep_register(ServerIMSG_ServerIfHandle, vec, &uvec, 0, &status);
00274
00275 if (vec)
00276 {
00277 size_t status_ = 0;
00278 rpc_binding_vector_free(&vec, &status_);
00279 }
00280
00281 rpcStatus(status);
00282
00283
00284 rpc_object_set_type(&_info._address, &_info._address, &status);
00285 rpcStatus(status);
00286
00287 msg_base::v_on();
00288 }
00289
00290
00291 void
00292 msg_rpc_listener::v_off()
00293 {
00294 if (!is_on())
00295 return;
00296
00297 msg_base::v_off();
00298
00299 int status = 0;
00300
00301
00302 rpc_binding_vector_t* vec = 0;
00303 rpc_server_inq_bindings(&vec, &status);
00304 rpcStatus(status);
00305
00306
00307
00308
00309
00310
00311 UUID_VECTOR uvec;
00312 uvec.Count = 1;
00313 uvec.Uuid[0] = (UUID*)&_info._address;
00314
00315 rpc_ep_unregister(ServerIMSG_ServerIfHandle, vec, &uvec, &status);
00316
00317 if (vec)
00318 {
00319 size_t status_ = 0;
00320 rpc_binding_vector_free(&vec, &status_);
00321 }
00322
00323 rpcStatus(status);
00324
00325
00326 rpc_object_set_type(&_info._address, 0, &status);
00327
00328
00329 rpc_server_unregister_if(ServerIMSG_ServerIfHandle, &_info._address, &status);
00330
00331 rpcStatus(status);
00332
00333 }
00334
00336 msg_rpc_connection::msg_rpc_connection(msg_communicator* communicator_, rpc_binding_handle_t handle_, const conf_listener& linfo, const conf_connection& info) :
00337 msg_connection(communicator_, linfo, info), _handle(handle_)
00338 {
00339 }
00340
00341 msg_rpc_connection::msg_rpc_connection(msg_communicator* communicator_, rpc_binding_handle_t handle_, const conf_connection& info) :
00342 msg_connection(communicator_, info), _handle(handle_)
00343 {
00344 }
00345
00346 msg_rpc_connection::~msg_rpc_connection()
00347 {
00348 size_t status = 0;
00349
00350 rpc_binding_free(&_handle, &status);
00351 }
00352
00353
00354
00355 void
00356 msg_rpc_connection::v_do_job(size_t ident, void* user_data)
00357 {
00358 assert(ident == queue_thread_ident);
00359
00360 msg_creator creator(_communicator);
00361
00362 msg_cpp* msg_ = 0;
00363 if (!pop(msg_))
00364 {
00365 assert(false);
00366 return;
00367 }
00368
00369 msg_pointer_t msg(creator);
00370 msg = msg_;
00371
00372 try
00373 {
00374 assert(_handle != 0);
00375
00376 send_msg(_communicator, this, _handle, msg);
00377
00378 _communicator->log_msg(msg);
00379
00380
00381 set_last_activity();
00382 }
00383 catch (exception&)
00384 {
00385
00386 _communicator->shutdown_connection(this);
00387 }
00388 }
00389
00390
00391 msg_connection*
00392 msg_rpc_connection::connect(msg_communicator* communicator_, const conf_connection& info_)
00393 {
00394 int status = 0;
00395 ub1_t* block_reply = 0;
00396 rpc_binding_handle_t handle = 0;
00397 msg_rpc_connection* connection = 0;
00398
00399 msg_creator creator(communicator_);
00400
00401 try
00402 {
00403
00404 char buf[64];
00405 ub1_t* full_bind_string = 0;
00406 uustring(buf, sizeof(buf), info_._address);
00407
00408 rpc_string_binding_compose((ub1_t*)buf, (ub1_t*)g_protocol, (ub1_t*)(g_name + strlen(g_protocol_)), (ub1_t*)buf, 0, &full_bind_string, &status);
00409 rpcStatus(status);
00410
00411 rpc_binding_from_string_binding(full_bind_string, &handle, &status);
00412 if (status != rpc_s_ok)
00413 {
00414 size_t s;
00415 rpc_string_free(&full_bind_string, &s);
00416 rpcStatus(status);
00417 }
00418
00419 rpc_string_free(&full_bind_string, &status);
00420
00421
00422 rpc_mgmt_set_com_timeout(handle, rpc_c_binding_min_timeout, &status);
00423 rpcStatus(status);
00424
00425
00426 connection = new msg_rpc_connection(communicator_, handle, info_);
00427 if (!connection)
00428 exception::_throw(MSG_RESULT_NOTMEMORY, &msgMsgTable);
00429
00430 msg_pointer_t msg(creator);
00431 msg = connection->prepare_handshake_msg();
00432
00433 msg->pack_msg(0);
00434 unsigned long size_reply = 0;
00435
00436 try
00437 {
00438
00439 ClientConnect(handle, ntohl(*(ub4_t*)msg->get_block()), msg->get_block(), &size_reply, &block_reply);
00440 }
00441 catch (...)
00442 {
00443
00444 exception::_throw(MSG_RESULT_CONNECTION_BROKEN, &msgMsgTable);
00445 }
00446
00447
00448 int body_size = (int)size_reply - (int)msg_cpp::block_size(0);
00449 if (!size_reply)
00450 exception::_throw(MSG_RESULT_ACCESS_DENIED, &msgMsgTable);
00451 if (body_size < 0 || !block_reply)
00452 exception::_throw(MSG_RESULT_INVALID_MSGFORMAT, &msgMsgTable);
00453
00454
00455 msg_pointer_t reply(creator, body_size);
00456
00457 memcpy(reply->get_block(), block_reply, size_reply);
00458
00459 reply->unpack_msg(0);
00460
00461
00462 connection->validate_handshake_reply(reply);
00463
00464
00465 communicator_->add_connection(connection);
00466
00467
00468 if (block_reply)
00469 midl_user_free(block_reply);
00470
00471 return connection;
00472 }
00473 catch (exception& x)
00474 {
00475
00476 if (block_reply)
00477 midl_user_free(block_reply);
00478
00479 if (handle)
00480 rpc_binding_free(&handle, &status);
00481
00482 if (!connection)
00483 delete connection;
00484
00485
00486 throw x;
00487 }
00488 }
00489
00490
00491 void
00492 msg_rpc_connection::send_msg(msg_communicator* communicator_, msg_rpc_connection* _this, rpc_binding_handle_t handle_, msg_cpp* msg_)
00493 {
00494
00495 msg_->pack_msg(_this->get_crypt_key());
00496 ub1_t* remoteError = 0;
00497
00498 try
00499 {
00500 communicator_->format_logging(0, __FILE__, __LINE__, en_log_info, "before ClientPostBlock, comm: %d, handle: %d", communicator_, handle_);
00501
00502 ClientPostBlock(handle_, ntohl(*(ub4_t*)msg_->get_block()), msg_->get_block(), &remoteError);
00503 }
00504 catch (...)
00505 {
00506 communicator_->format_logging(0, __FILE__, __LINE__, en_log_info, "failed ClientPostBlock, comm: %d, handle: %d", communicator_, handle_);
00507 exception::_throw(MSG_RESULT_CONNECTION_BROKEN, &msgMsgTable);
00508 }
00509
00510 communicator_->format_logging(0, __FILE__, __LINE__, en_log_info, "succeeded ClientPostBlock, comm: %d, handle: %d", communicator_, handle_);
00511
00512
00513 if (remoteError)
00514 {
00515
00516 if (msg_->_type == user_type_send || msg_->_type == user_type_send_async)
00517 {
00518 try
00519 {
00520
00521 msg_creator creator(communicator_);
00522 msg_pointer_t reply(creator, 0);
00523
00524 msg_pack::make_reply_msg(msg_, reply);
00525 msg_pack::make_error_msg(reply, (const char*)remoteError);
00526
00527 communicator_->comm_msg(reply);
00528 reply.detach();
00529 }
00530 catch (exception&)
00531 {
00532 }
00533 }
00534
00535
00536 midl_user_free(remoteError);
00537 }
00538 }
00539
00540 #ifdef __cplusplus
00541 extern "C"{
00542 #endif
00543
00544 void ServerConnect(rpc_binding_handle_t handle_, unsigned long szsend, unsigned char* sender, unsigned long* szrecv, unsigned char** receiver)
00545 {
00546 int status = 0;
00547 *szrecv = 0;
00548 *receiver = 0;
00549 rpc_binding_handle_t handle = 0;
00550 msg_rpc_connection* connection = 0;
00551
00552 try
00553 {
00554
00555 int body_size = (int)szsend - (int)msg_cpp::block_size(0);
00556 if (body_size < 0)
00557 exception::_throw(MSG_RESULT_INVALID_MSGFORMAT, &msgMsgTable);
00558
00559
00560
00561 guid_t address;
00562
00563 rpc_binding_inq_object(handle_, &address, &status);
00564 rpcStatus(status);
00565
00566
00567 rpc2_communicator_keeper keeper(address);
00568 msg_creator creator(keeper());
00569 msg_pointer_t msg(creator, body_size);
00570
00571
00572 memcpy(msg->get_block(), sender, szsend);
00573
00574 msg->unpack_msg(0);
00575
00576
00577 msg_listener* listener_ = 0;
00578 if (!keeper || !(listener_ = keeper->find_listener(rpc)) || !listener_->is_on())
00579 exception::_throw(MSG_RESULT_ACCESS_DENIED, &msgMsgTable);
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612 rpc_mgmt_set_com_timeout(handle, rpc_c_binding_min_timeout, &status);
00613 rpcStatus(status);
00614
00615
00616 conf_connection info_;
00617 info_ = listener_->get_info();
00618 connection = new msg_rpc_connection(keeper(), handle, listener_->get_info(), info_);
00619 if (!connection)
00620 exception::_throw(MSG_RESULT_NOTMEMORY, &msgMsgTable);
00621
00622
00623 msg_pointer_t reply(creator);
00624
00625 reply = connection->prepare_handshake_reply(msg);
00626
00627
00628 reply->pack_msg(0);
00629
00630 *szrecv = ntohl(*(ub4_t*)reply->get_block());
00631
00632 *receiver = (ub1_t*)midl_user_allocate(*szrecv);
00633 if (*receiver)
00634 memcpy(*receiver, reply->get_block(), *szrecv);
00635 else
00636 *szrecv = 0;
00637
00638
00639 keeper->add_connection(connection);
00640 }
00641 catch (exception&)
00642 {
00643
00644 if (connection)
00645 delete connection;
00646
00647
00648 if (handle)
00649 rpc_binding_free(&handle, &status);
00650 }
00651 }
00652
00653 void ServerPostBlock(rpc_binding_handle_t handle_, unsigned long sz, ub1_t* buf, ub1_t** reply)
00654 {
00655 int status = 0;
00656
00657 try
00658 {
00659
00660 guid_t address;
00661
00662 rpc_binding_inq_object(handle_, &address, &status);
00663 rpcStatus(status);
00664
00665
00666 rpc2_communicator_keeper keeper(address);
00667 msg_listener* listener_ = 0;
00668 if (!keeper || !(listener_ = keeper->find_listener(rpc)) || !listener_->is_on())
00669 exception::_throw(MSG_RESULT_ACCESS_DENIED, &msgMsgTable);
00670
00671 msg_communicator* communicator_ = keeper();
00672
00673 communicator_->format_logging(0, __FILE__, __LINE__, en_log_info, "inside ServerPostBlock, comm: %d, handle: %d", communicator_, handle_);
00674
00675
00676 int body_size = (int)sz - (int)msg_cpp::block_size(0);
00677 if (body_size < 0 || !buf)
00678 exception::_throw(MSG_RESULT_INVALID_MSGFORMAT, &msgMsgTable);
00679
00680
00681 msg_creator creator(keeper());
00682
00683 msg_pointer_t msg(creator, body_size);
00684
00685 memcpy(msg->get_block(), buf, sz);
00686
00687 msg->unpack_msg(0);
00688
00689
00690 msg_connection* con = 0;
00691 if (!(con = keeper->find_connection(msg->_sender)) ||
00692 !con->is_on() || con->is_block() || con->get_info()._session != msg->_sessionid)
00693 exception::_throw(MSG_RESULT_ACCESS_DENIED, &msgMsgTable);
00694
00695
00696 if (msg->_type & user_type_mask)
00697 {
00698
00699 if (con->get_rsa())
00700 msg->unpack_msg(con->get_crypt_key());
00701 }
00702 else if (msg->_type != system_type || msg->msgid != msg_id_ping)
00703
00704
00705 exception::_throw(MSG_RESULT_INVALID_MSGFORMAT, &msgMsgTable);
00706
00707
00708 con->process_incoming_message(msg);
00709
00710
00711 msg.detach();
00712 }
00713 catch (exception& x)
00714 {
00715
00716 const char* reason = x.what();
00717 size_t len = strlen(reason) + 1;
00718
00719 *reply = (ub1_t*)midl_user_allocate(len);
00720 if (*reply)
00721 memcpy(*reply, reason, len);
00722 }
00723 }
00724
00725 #ifdef __cplusplus
00726 }
00727 #endif
00728
00729 #pragma pack()
00730 END_TERIMBER_NAMESPACE