// // Copyright (c) ZeroC, Inc. All rights reserved. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace Ice; using namespace Ice::Instrumentation; using namespace IceInternal; namespace IceUtilInternal { extern bool printStackTraces; } #ifdef ICE_CPP11_MAPPING Ice::MarshaledResult::MarshaledResult(const Ice::Current& current) : ostr(make_shared(current.adapter->getCommunicator(), Ice::currentProtocolEncoding)) { ostr->writeBlob(replyHdr, sizeof(replyHdr)); ostr->write(current.requestId); ostr->write(replyOK); } #endif IceInternal::IncomingBase::IncomingBase(Instance* instance, ResponseHandler* responseHandler, Ice::Connection* connection, const ObjectAdapterPtr& adapter, bool response, Byte compress, Int requestId) : _response(response), _compress(compress), _format(Ice::ICE_ENUM(FormatType, DefaultFormat)), _os(instance, Ice::currentProtocolEncoding), _responseHandler(responseHandler) { _current.adapter = adapter; #ifdef ICE_CPP11_MAPPING ::Ice::ConnectionI* conn = dynamic_cast<::Ice::ConnectionI*>(connection); _current.con = conn ? conn->shared_from_this() : nullptr; #else _current.con = connection; #endif _current.requestId = requestId; _current.encoding.major = 0; _current.encoding.minor = 0; } IceInternal::IncomingBase::IncomingBase(IncomingBase& other) : IceUtil::noncopyable(), // TODO, remove noncopyable base class _current(other._current), _servant(other._servant), _locator(other._locator), _cookie(other._cookie), _response(other._response), _compress(other._compress), _format(other._format), _os(other._os.instance(), Ice::currentProtocolEncoding), _responseHandler(other._responseHandler), _interceptorCBs(other._interceptorCBs) { _observer.adopt(other._observer); } OutputStream* IncomingBase::startWriteParams() { if(!_response) { throw MarshalException(__FILE__, __LINE__, "can't marshal out parameters for oneway dispatch"); } assert(_current.encoding >= Ice::Encoding_1_0); // Encoding for reply is known. _os.writeBlob(replyHdr, sizeof(replyHdr)); _os.write(_current.requestId); _os.write(replyOK); _os.startEncapsulation(_current.encoding, _format); return &_os; } void IncomingBase::endWriteParams() { if(_response) { _os.endEncapsulation(); } } void IncomingBase::writeEmptyParams() { if(_response) { assert(_current.encoding >= Ice::Encoding_1_0); // Encoding for reply is known. _os.writeBlob(replyHdr, sizeof(replyHdr)); _os.write(_current.requestId); _os.write(replyOK); _os.writeEmptyEncapsulation(_current.encoding); } } void IncomingBase::writeParamEncaps(const Byte* v, Ice::Int sz, bool ok) { if(!ok) { _observer.userException(); } if(_response) { assert(_current.encoding >= Ice::Encoding_1_0); // Encoding for reply is known. _os.writeBlob(replyHdr, sizeof(replyHdr)); _os.write(_current.requestId); _os.write(ok ? replyOK : replyUserException); if(sz == 0) { _os.writeEmptyEncapsulation(_current.encoding); } else { _os.writeEncapsulation(v, sz); } } } #ifdef ICE_CPP11_MAPPING void IceInternal::IncomingBase::setMarshaledResult(const Ice::MarshaledResult& result) { result.getOutputStream()->swap(_os); } #endif void IceInternal::IncomingBase::response(bool amd) { try { if(_locator && !servantLocatorFinished(amd)) { return; } assert(_responseHandler); if(_response) { _observer.reply(static_cast(_os.b.size() - headerSize - 4)); _responseHandler->sendResponse(_current.requestId, &_os, _compress, amd); } else { _responseHandler->sendNoResponse(); } } catch(const LocalException& ex) { _responseHandler->invokeException(_current.requestId, ex, 1, amd); // Fatal invocation exception } _observer.detach(); _responseHandler = 0; } void IceInternal::IncomingBase::exception(const std::exception& exc, bool amd) { try { if(_locator && !servantLocatorFinished(amd)) { return; } handleException(exc, amd); } catch(const LocalException& ex) { _responseHandler->invokeException(_current.requestId, ex, 1, amd); // Fatal invocation exception } } void IceInternal::IncomingBase::exception(const string& msg, bool amd) { try { if(_locator && !servantLocatorFinished(amd)) { return; } handleException(msg, amd); } catch(const LocalException& ex) { _responseHandler->invokeException(_current.requestId, ex, 1, amd); // Fatal invocation exception } } void IceInternal::IncomingBase::warning(const Exception& ex) const { Warning out(_os.instance()->initializationData().logger); ToStringMode toStringMode = _os.instance()->toStringMode(); out << "dispatch exception: " << ex; out << "\nidentity: " << identityToString(_current.id, toStringMode); out << "\nfacet: "; out << escapeString(_current.facet, "", toStringMode); out << "\noperation: " << _current.operation; if(_current.con) { try { for(Ice::ConnectionInfoPtr connInfo = _current.con->getInfo(); connInfo; connInfo = connInfo->underlying) { Ice::IPConnectionInfoPtr ipConnInfo = ICE_DYNAMIC_CAST(Ice::IPConnectionInfo, connInfo); if(ipConnInfo) { out << "\nremote host: " << ipConnInfo->remoteAddress << " remote port: " << ipConnInfo->remotePort; break; } } } catch(const Ice::LocalException&) { // Ignore. } } } void IceInternal::IncomingBase::warning(const string& msg) const { Warning out(_os.instance()->initializationData().logger); ToStringMode toStringMode = _os.instance()->toStringMode(); out << "dispatch exception: " << msg; out << "\nidentity: " << identityToString(_current.id, toStringMode); out << "\nfacet: " << escapeString(_current.facet, "", toStringMode); out << "\noperation: " << _current.operation; if(_current.con) { for(Ice::ConnectionInfoPtr connInfo = _current.con->getInfo(); connInfo; connInfo = connInfo->underlying) { Ice::IPConnectionInfoPtr ipConnInfo = ICE_DYNAMIC_CAST(Ice::IPConnectionInfo, connInfo); if(ipConnInfo) { out << "\nremote host: " << ipConnInfo->remoteAddress << " remote port: " << ipConnInfo->remotePort; break; } } } } bool IceInternal::IncomingBase::servantLocatorFinished(bool amd) { assert(_locator && _servant); try { _locator->finished(_current, _servant, _cookie); return true; } catch(const std::exception& ex) { handleException(ex, amd); } catch(...) { handleException("unknown c++ exception", amd); } return false; } void IceInternal::IncomingBase::handleException(const std::exception& exc, bool amd) { assert(_responseHandler); // Reset the stream, it's possible the marshalling of the response failed and left // the stream in an unknown state. _os.clear(); _os.b.clear(); if(const SystemException* ex = dynamic_cast(&exc)) { if(_responseHandler->systemException(_current.requestId, *ex, amd)) { return; } } if(dynamic_cast(&exc)) { RequestFailedException* rfe = const_cast(dynamic_cast(&exc)); if(rfe->id.name.empty()) { rfe->id = _current.id; } if(rfe->facet.empty() && !_current.facet.empty()) { rfe->facet = _current.facet; } if(rfe->operation.empty() && !_current.operation.empty()) { rfe->operation = _current.operation; } if(_os.instance()->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 1) { warning(*rfe); } if(_observer) { _observer.failed(rfe->ice_id()); } if(_response) { _os.writeBlob(replyHdr, sizeof(replyHdr)); _os.write(_current.requestId); if(dynamic_cast(rfe)) { _os.write(replyObjectNotExist); } else if(dynamic_cast(rfe)) { _os.write(replyFacetNotExist); } else if(dynamic_cast(rfe)) { _os.write(replyOperationNotExist); } else { assert(false); } _os.write(rfe->id); // // For compatibility with the old FacetPath. // if(rfe->facet.empty()) { _os.write(static_cast(0), static_cast(0)); } else { _os.write(&rfe->facet, &rfe->facet + 1); } _os.write(rfe->operation, false); _observer.reply(static_cast(_os.b.size() - headerSize - 4)); _responseHandler->sendResponse(_current.requestId, &_os, _compress, amd); } else { _responseHandler->sendNoResponse(); } } else if(const UserException* uex = dynamic_cast(&exc)) { _observer.userException(); // // The operation may have already marshaled a reply; we must overwrite that reply. // if(_response) { _os.writeBlob(replyHdr, sizeof(replyHdr)); _os.write(_current.requestId); _os.write(replyUserException); _os.startEncapsulation(_current.encoding, _format); _os.write(*uex); _os.endEncapsulation(); _observer.reply(static_cast(_os.b.size() - headerSize - 4)); _responseHandler->sendResponse(_current.requestId, &_os, _compress, amd); } else { _responseHandler->sendNoResponse(); } } else if(const Exception* ex = dynamic_cast(&exc)) { if(_os.instance()->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { warning(*ex); } if(_observer) { _observer.failed(ex->ice_id()); } if(_response) { _os.writeBlob(replyHdr, sizeof(replyHdr)); _os.write(_current.requestId); if(const UnknownLocalException* ule = dynamic_cast(&exc)) { _os.write(replyUnknownLocalException); _os.write(ule->unknown, false); } else if(const UnknownUserException* uue = dynamic_cast(&exc)) { _os.write(replyUnknownUserException); _os.write(uue->unknown, false); } else if(const UnknownException* ue = dynamic_cast(&exc)) { _os.write(replyUnknownException); _os.write(ue->unknown, false); } else if(const LocalException* le = dynamic_cast(&exc)) { _os.write(replyUnknownLocalException); ostringstream str; str << *le; if(IceUtilInternal::printStackTraces) { str << '\n' << ex->ice_stackTrace(); } _os.write(str.str(), false); } else if(const UserException* use = dynamic_cast(&exc)) { _os.write(replyUnknownUserException); ostringstream str; str << *use; if(IceUtilInternal::printStackTraces) { str << '\n' << ex->ice_stackTrace(); } _os.write(str.str(), false); } else { _os.write(replyUnknownException); ostringstream str; str << *ex; if(IceUtilInternal::printStackTraces) { str << '\n' << ex->ice_stackTrace(); } _os.write(str.str(), false); } _observer.reply(static_cast(_os.b.size() - headerSize - 4)); _responseHandler->sendResponse(_current.requestId, &_os, _compress, amd); } else { _responseHandler->sendNoResponse(); } } else { if(_os.instance()->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { warning(string("std::exception: ") + exc.what()); } if(_observer) { _observer.failed(typeid(exc).name()); } if(_response) { _os.writeBlob(replyHdr, sizeof(replyHdr)); _os.write(_current.requestId); _os.write(replyUnknownException); ostringstream str; str << "std::exception: " << exc.what(); _os.write(str.str(), false); _observer.reply(static_cast(_os.b.size() - headerSize - 4)); _responseHandler->sendResponse(_current.requestId, &_os, _compress, amd); } else { _responseHandler->sendNoResponse(); } } _observer.detach(); _responseHandler = 0; } void IceInternal::IncomingBase::handleException(const string& msg, bool amd) { if(_os.instance()->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { warning(msg); } assert(_responseHandler); // Reset the stream, it's possible the marshalling of the response failed and left // the stream in an unknown state. _os.clear(); _os.b.clear(); if(_observer) { _observer.failed("unknown"); } if(_response) { _os.writeBlob(replyHdr, sizeof(replyHdr)); _os.write(_current.requestId); _os.write(replyUnknownException); string reason = msg; _os.write(reason, false); _observer.reply(static_cast(_os.b.size() - headerSize - 4)); _responseHandler->sendResponse(_current.requestId, &_os, _compress, amd); } else { _responseHandler->sendNoResponse(); } _observer.detach(); _responseHandler = 0; } IceInternal::Incoming::Incoming(Instance* instance, ResponseHandler* responseHandler, Ice::Connection* connection, const ObjectAdapterPtr& adapter, bool response, Byte compress, Int requestId) : IncomingBase(instance, responseHandler, connection, adapter, response, compress, requestId), _inParamPos(0) { } #ifdef ICE_CPP11_MAPPING void IceInternal::Incoming::push(function response, function exception) { _interceptorCBs.push_front(make_pair(response, exception)); } #else void IceInternal::Incoming::push(const Ice::DispatchInterceptorAsyncCallbackPtr& cb) { _interceptorCBs.push_front(cb); } #endif void IceInternal::Incoming::pop() { _interceptorCBs.pop_front(); } void IceInternal::Incoming::startOver() { if(_inParamPos == 0) { // // That's the first startOver, so almost nothing to do // _inParamPos = _is->i; } else { // Reset input stream's position and clear response if(_inAsync) { _inAsync->kill(*this); _inAsync = 0; } _os.clear(); _os.b.clear(); _is->i = _inParamPos; } } void IceInternal::Incoming::invoke(const ServantManagerPtr& servantManager, InputStream* stream) { _is = stream; InputStream::Container::iterator start = _is->i; // // Read the current. // _is->read(_current.id); // // For compatibility with the old FacetPath. // string facet; { vector facetPath; _is->read(facetPath); if(!facetPath.empty()) { if(facetPath.size() > 1) { throw MarshalException(__FILE__, __LINE__); } facet.swap(facetPath[0]); } } _current.facet.swap(facet); _is->read(_current.operation, false); Byte b; _is->read(b); _current.mode = static_cast(b); Int sz = _is->readSize(); while(sz--) { pair pr; _is->read(const_cast(pr.first)); _is->read(pr.second); _current.ctx.insert(_current.ctx.end(), pr); } const CommunicatorObserverPtr& obsv = _is->instance()->initializationData().observer; if(obsv) { // Read the parameter encapsulation size. Ice::Int encapsSize; _is->read(encapsSize); _is->i -= 4; _observer.attach(obsv->getDispatchObserver(_current, static_cast(_is->i - start + encapsSize))); } // // Don't put the code above into the try block below. Exceptions // in the code above are considered fatal, and must propagate to // the caller of this operation. // if(servantManager) { _servant = servantManager->findServant(_current.id, _current.facet); if(!_servant) { _locator = servantManager->findServantLocator(_current.id.category); if(!_locator && !_current.id.category.empty()) { _locator = servantManager->findServantLocator(""); } if(_locator) { try { _servant = _locator->locate(_current, _cookie); } catch(const std::exception& ex) { skipReadParams(); // Required for batch requests. handleException(ex, false); return; } catch(...) { skipReadParams(); // Required for batch requests. handleException("unknown c++ exception", false); return; } } } } if(!_servant) { try { if(servantManager && servantManager->hasServant(_current.id)) { throw FacetNotExistException(__FILE__, __LINE__, _current.id, _current.facet, _current.operation); } else { throw ObjectNotExistException(__FILE__, __LINE__, _current.id, _current.facet, _current.operation); } } catch(const Ice::LocalException& ex) { skipReadParams(); // Required for batch requests handleException(ex, false); return; } } try { // // Dispatch in the incoming call // _servant->_iceDispatch(*this, _current); // // If the request was not dispatched asynchronously, send the response. // if(!_inAsync) { response(false); } } catch(const std::exception& ex) { if(_inAsync) { try { _inAsync->kill(*this); } catch(const Ice::ResponseSentException&) { const Ice::PropertiesPtr properties = _os.instance()->initializationData().properties; if(properties->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { if(const IceUtil::Exception* exc = dynamic_cast(&ex)) { warning(*exc); } else { warning(string("std::exception: ") + ex.what()); } } return; } } exception(ex, false); } catch(...) { if(_inAsync) { try { _inAsync->kill(*this); } catch(const Ice::ResponseSentException&) { const Ice::PropertiesPtr properties = _os.instance()->initializationData().properties; if(properties->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { warning("unknown c++ exception"); } return; } } exception("unknown c++ exception", false); } } const Current& IceInternal::IncomingRequest::getCurrent() { return _in.getCurrent(); }