bool unfilterData( const ByteBuffer &filteredByteBuffer, ByteBuffer &unfilteredByteBuffer, std::size_t unfilteredDataLen, const std::vector<FilterPtr> &filters) { ThreadLocalCached< std::vector<ByteBuffer> > tlcUnfilteredByteBuffers; std::vector<ByteBuffer> &unfilteredByteBuffers = tlcUnfilteredByteBuffers.get(); bool ret = unfilterData( filteredByteBuffer, unfilteredByteBuffers, unfilteredDataLen, filters); if (unfilteredByteBuffers.empty()) { unfilteredByteBuffer = ByteBuffer(); } else if (unfilteredByteBuffers.size() == 1) { unfilteredByteBuffer = unfilteredByteBuffers[0]; } else { // TODO: maybe check for adjacent buffers, in which case one should not need to make a copy copyByteBuffers(unfilteredByteBuffers, unfilteredByteBuffer); } return ret; }
void RcfSession::onWriteCompleted() { RCF_LOG_3()(this) << "RcfServer - completed sending of response."; { Lock lock(mIoStateMutex); if (mWritingPingBack) { mWritingPingBack = false; typedef std::vector<ByteBuffer> ByteBuffers; ThreadLocalCached< ByteBuffers > tlcQueuedBuffers; ByteBuffers & queuedBuffers = tlcQueuedBuffers.get(); queuedBuffers = mQueuedSendBuffers; mQueuedSendBuffers.clear(); if (!queuedBuffers.empty()) { lock.unlock(); getSessionState().postWrite(queuedBuffers); RCF_ASSERT(queuedBuffers.empty()); } return; } } typedef std::vector<RcfSession::OnWriteCompletedCallback> OnWriteCompletedCallbacks; ThreadLocalCached< OnWriteCompletedCallbacks > tlcOwcc; OnWriteCompletedCallbacks &onWriteCompletedCallbacks = tlcOwcc.get(); extractOnWriteCompletedCallbacks(onWriteCompletedCallbacks); std::for_each( onWriteCompletedCallbacks.begin(), onWriteCompletedCallbacks.end(), boost::bind( &RcfSession::OnWriteCompletedCallback::operator(), _1, boost::ref(*this))); onWriteCompletedCallbacks.resize(0); mIn.clear(); mOut.clear(); if (!mCloseSessionAfterWrite) { getSessionState().postRead(); } }
bool filterData( const std::vector<ByteBuffer> &unfilteredData, std::vector<ByteBuffer> &filteredData, const std::vector<FilterPtr> &filters) { std::size_t bytesTransferred = 0; std::size_t bytesTransferredTotal = 0; WriteProxy writeProxy; writeProxy.setPreFilter(*filters.back()); filters.back()->setPostFilter(writeProxy); filters.front()->setPreFilter(writeProxy); std::size_t unfilteredDataLen = lengthByteBuffers(unfilteredData); while (bytesTransferredTotal < unfilteredDataLen) { ThreadLocalCached< std::vector<ByteBuffer> > tlcSlicedByteBuffers; std::vector<ByteBuffer> &slicedByteBuffers = tlcSlicedByteBuffers.get(); sliceByteBuffers(slicedByteBuffers, unfilteredData, bytesTransferredTotal); filters.front()->write(slicedByteBuffers); // TODO: error handling bytesTransferred = writeProxy.getBytesTransferred(); bytesTransferredTotal += bytesTransferred; } RCF_ASSERT_EQ(bytesTransferredTotal , unfilteredDataLen); filteredData.resize(0); std::copy( writeProxy.getByteBuffers().begin(), writeProxy.getByteBuffers().end(), std::back_inserter(filteredData)); return bytesTransferredTotal == unfilteredDataLen; }
void RcfSession::sendSessionResponse() { mIn.clearByteBuffer(); ThreadLocalCached< std::vector<ByteBuffer> > tlcByteBuffers; std::vector<ByteBuffer> &byteBuffers = tlcByteBuffers.get(); mOut.extractByteBuffers(byteBuffers); const std::vector<FilterPtr> &filters = mFilters; ThreadLocalCached< std::vector<ByteBuffer> > tlcEncodedByteBuffers; std::vector<ByteBuffer> &encodedByteBuffers = tlcEncodedByteBuffers.get(); ThreadLocalCached< std::vector<FilterPtr> > tlcNoFilters; std::vector<FilterPtr> &noFilters = tlcNoFilters.get(); mRequest.encodeToMessage( encodedByteBuffers, byteBuffers, mFiltered ? filters : noFilters); RCF_LOG_3()(this)(lengthByteBuffers(byteBuffers))(lengthByteBuffers(encodedByteBuffers)) << "RcfServer - sending response."; byteBuffers.resize(0); bool okToWrite = false; { Lock lock(mIoStateMutex); unregisterForPingBacks(); if (mWritingPingBack) { mQueuedSendBuffers = encodedByteBuffers; encodedByteBuffers.resize(0); byteBuffers.resize(0); } else { okToWrite = true; } } if (okToWrite) { getSessionState().postWrite(encodedByteBuffers); RCF_ASSERT(encodedByteBuffers.empty()); RCF_ASSERT(byteBuffers.empty()); } setTlsRcfSessionPtr(); }
// returns -2 for timeout, -1 for error, otherwise number of bytes sent (> 0) int timedSend( I_PollingFunctor &pollingFunctor, int &err, int fd, const std::vector<ByteBuffer> &byteBuffers, std::size_t maxSendSize, int flags) { RCF_UNUSED_VARIABLE(flags); std::size_t bytesRemaining = lengthByteBuffers(byteBuffers); std::size_t bytesSent = 0; while (true) { std::size_t bytesToSend = RCF_MIN(bytesRemaining, maxSendSize); ThreadLocalCached< std::vector<WSABUF> > tlcWsabufs; std::vector<WSABUF> &wsabufs = tlcWsabufs.get(); forEachByteBuffer( boost::bind(&appendWsabuf, boost::ref(wsabufs), _1), byteBuffers, bytesSent, bytesToSend); int count = 0; int myErr = 0; #ifdef BOOST_WINDOWS { DWORD cbSent = 0; int ret = WSASend( fd, &wsabufs[0], static_cast<DWORD>(wsabufs.size()), &cbSent, 0, NULL, NULL); count = (ret == 0) ? cbSent : -1; myErr = Platform::OS::BsdSockets::GetLastError(); } #else { msghdr hdr = {0}; hdr.msg_iov = &wsabufs[0]; hdr.msg_iovlen = wsabufs.size(); count = sendmsg(fd, &hdr, 0); myErr = Platform::OS::BsdSockets::GetLastError(); } #endif if (count >= 0) { RCF_ASSERT_LTEQ(count , static_cast<int>(bytesRemaining)); bytesRemaining -= count; bytesSent += count; err = 0; return static_cast<int>(bytesSent); } else if (myErr == Platform::OS::BsdSockets::ERR_EWOULDBLOCK) { // can't get WSA_IO_PENDING here, since the socket isn't overlapped int ret = pollingFunctor(fd, myErr, false); if (ret != 0) { err = myErr; return ret; } } else { err = myErr; return -1; } } }
void RcfSession::processJsonRpcRequest() { ByteBuffer readByteBuffer = getSessionState().getReadByteBuffer(); RCF_LOG_3()(this)(readByteBuffer.getLength()) << "RcfServer - received JSON-RPC packet from transport."; CurrentRcfSessionSentry guard(*this); boost::scoped_ptr<JsonRpcResponse> jsonResponsePtr; bool isOneway = false; boost::uint64_t jsonRequestId = 0; try { JsonRpcRequest jsonRequest(readByteBuffer); jsonRequestId = jsonRequest.getRequestId(); jsonResponsePtr.reset( new JsonRpcResponse(jsonRequestId) ); std::string jsonRpcName = jsonRequest.getMethodName(); isOneway = jsonRequest.isNotification(); RcfServer::JsonRpcMethod jsonRpcMethod; { ReadLock lock(mRcfServer.mStubMapMutex); RcfServer::JsonRpcMethods::iterator iter = mRcfServer.mJsonRpcMethods.find(jsonRpcName); if (iter != mRcfServer.mJsonRpcMethods.end()) { jsonRpcMethod = iter->second; } } if (jsonRpcMethod) { jsonRpcMethod(jsonRequest, *jsonResponsePtr); } else { std::string errMsg = "Unknown JSON-RPC method name: " + jsonRpcName; jsonResponsePtr->getJsonResponse()["error"] = errMsg; } } catch(...) { std::string errMsg; try { throw; } catch(const RCF::Exception & e) { errMsg = e.getErrorString(); } catch(const std::exception & e) { errMsg = e.what(); } catch(const std::string & jsonSpiritErrMsg) { errMsg = jsonSpiritErrMsg; } catch(...) { errMsg = "Caught C++ exception of unknown type."; } jsonResponsePtr.reset( new JsonRpcResponse(jsonRequestId) ); jsonResponsePtr->getJsonResponse()["result"] = json_spirit::mValue(); jsonResponsePtr->getJsonResponse()["error"] = errMsg; } setTlsRcfSessionPtr(); if (isOneway) { onWriteCompleted(); } else { json_spirit::mObject & obj = jsonResponsePtr->getJsonResponse(); MemOstreamPtr osPtr = getObjectPool().getMemOstreamPtr(); json_spirit::write_stream(json_spirit::mValue(obj), *osPtr, json_spirit::pretty_print); ByteBuffer buffer(osPtr->str(), static_cast<std::size_t>(osPtr->tellp()), osPtr); ThreadLocalCached< std::vector<ByteBuffer> > tlcByteBuffers; std::vector<ByteBuffer> & buffers = tlcByteBuffers.get(); buffers.push_back(buffer); getSessionState().postWrite(buffers); } }