void L1InterfaceStub::processServiceAllocateResponse(CDataAccessor & accessor) { const UInt32 channel_id = accessor.getChannelID(); ConnectivityAgentError err(static_cast<ConnectivityAgentError::AgentErrorCodes> (accessor.getErrorCode())); LOG4CPLUS_TRACE_METHOD(logger, "L1InterfaceStub::processServiceAllocateResponse() => " "Channel allocated responce id = " + convertIntegerToString(channel_id) + ", err = " + convertIntegerToString((int)err.getCode())); iviLink::Ipc::DirectionID dirId = -1; /// @todo better processing of error codes. PIlin, 31.08.12 /// There is the error case with wrong processing: /// 1) if response with error, obtain ERR_DEFERRED from failAllocateChannel and /// begin deallocation procedure. /// 2) if there is no known dirId, channel also needs to be deallocated, even /// if its allocation was successfull. /// /// Here we must initialize channel deallocation procedure, because we unable /// to send some message - there is no such in existing protocol. if (err.isNoError()) { err = endAllocateChannel(channel_id, dirId); if (err.getCode() == ConnectivityAgentError::ERROR_DEFERRED) { LOG4CPLUS_INFO(logger, "L1InterfaceStub::processServiceAllocateResponse() => " "was E_TRANSITION_AGENT, messaging to other side"); accessor.setErrorCode(BaseError::IVILINK_NO_ERROR); err = sendRequest(accessor); } } if (!err.isNoError() || dirId == -1) { // SEQ_E_4 LOG4CPLUS_ERROR(logger, "L1InterfaceStub::processServiceAllocateResponse() => " "failed channel allocation"); failAllocateChannel(channel_id, dirId); accessor.setErrorCode(err.getCode()); } if (dirId != -1) { LOG4CPLUS_INFO(logger, "L1InterfaceStub::processServiceAllocateResponse() => " "message about allocation result"); sendIpcNotification(accessor, dirId); } else { LOG4CPLUS_ERROR(logger, "L1InterfaceStub::processServiceAllocateResponse() => " "unknown client, failing channel"); } }
ConnectivityAgentError L1InterfaceStub::sendRequest( CDataAccessor & accessor) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); Buffer buf; UInt32 offset = 0; accessor.printContent(); buf.getFilledSize() = accessor.getObjectSize() + sizeof(UInt16); buf.reserveSize(buf.getFilledSize()); *reinterpret_cast<UInt16*> (buf.getData() + offset) = ByteOrder::hton16((UInt16)buf.getFilledSize()); offset += 2; *reinterpret_cast<UInt32*> (buf.getData() + offset) = ByteOrder::hton32(accessor.getOpCode()); offset += 4; *reinterpret_cast<UInt32*> (buf.getData() + offset) = ByteOrder::hton32(accessor.getChannelID()); offset += 4; *reinterpret_cast<UInt32*> (buf.getData() + offset) = ByteOrder::hton32(accessor.getDataSize()); offset += 4; *reinterpret_cast<UInt32*> (buf.getData() + offset) = ByteOrder::hton32(accessor.getErrorCode()); offset += 4; if (accessor.getDataSize()) { memcpy(buf.getData() + offset,accessor.getData(), accessor.getDataSize() ); } ConnectivityAgentError ret = mL1ChannelRegistry[CA_SERVICE_CHANNEL]. mpSourceAgent->fillBuffer(buf); buf.forgetData(); return ret; }
void CConnectivityAgentProxy::receiveAllocateChannelResponse(CDataAccessor & accessor) { UInt32 channel_id = accessor.getChannelID(); ERROR_CODE err = static_cast<ERROR_CODE>(accessor.getErrorCode()); LOG4CPLUS_TRACE_METHOD(logger, "CConnectivityAgentProxy::receiveAllocateChannelResponse" " channel_id = " + convertIntegerToString(channel_id) + " err = " + convertIntegerToString((int) err)); mAllocateRequestCond.lock(); { tAllocateRequestMap::iterator it = mAllocateRequestMap.find(channel_id); if (it == mAllocateRequestMap.end()) { LOG4CPLUS_WARN(logger, "CConnectivityAgentProxy::receiveAllocateChannelResponse() => channel is not requested"); } else { AllocateRequestInfo & info = it->second; info.mRequestDone = true; info.mResult = err; if (ERR_OK == err) { mRegistryMutex.lockWrite(); mChannelRegistry[channel_id].mType = info.mType; mChannelRegistry[channel_id].mpClient = info.mpClient; mChannelRegistry[channel_id].mChannelBuffer.reserveSize(MAX_SIZE); mRegistryMutex.unlockWrite(); } mAllocateRequestCond.broadcast(); } } mAllocateRequestCond.unlock(); }
void L1InterfaceStub::processServiceAllocateRequest(CDataAccessor & accessor) { const UInt32 channel_id = accessor.getChannelID(); const UInt32 prio = *reinterpret_cast<UInt32*>(accessor.getData()); ConnectivityAgentError err(static_cast<ConnectivityAgentError::AgentErrorCodes> (accessor.getErrorCode())); LOG4CPLUS_INFO(logger, "L1InterfaceStub::processServiceAllocateRequest()=>" "Allocate channel prio = " + convertIntegerToString(prio) + " id =" + convertIntegerToString(accessor.getChannelID())); iviLink::Ipc::DirectionID dirId = -1; accessor.setOpCode(E_ALLOCATE_CHANNEL_RESP); accessor.resetData(); if (!err.isNoError()) { // SEQ_E_3 failAllocateChannel(channel_id, dirId); accessor.setErrorCode(err.getCode()); } else { mRequestedMapMutex.lock(); mRegistryMutex.lock(); { err = beginAllocateChannel(static_cast<TChannelPriority>(prio), channel_id, false, dirId); if (err.getCode() != ConnectivityAgentError::ERROR_DEFERRED) { // sending the result to other side // SEQ_E_4 or ok accessor.setErrorCode(err.getCode()); sendRequest(accessor); } } mRegistryMutex.unlock(); mRequestedMapMutex.unlock(); if (err.getCode() == ConnectivityAgentError::ERROR_DEFERRED) { // all ok, we will wait for the client requesting this channel // setting timeout LOG4CPLUS_INFO(logger, "L1InterfaceStub::processServiceAllocateRequest() => " "channel wasn't requested yet ->set channel to wait and trigger timeout"); assert(mTimeoutManager); mTimeoutManager->addSubscriber( new RequestTimeout(E_ALLOCATE_CHANNEL,channel_id, this), 250000); return; } } if (!err.isNoError()) { // messagign about failed channel allocation // SEQ_E_4 if (dirId != -1) { sendIpcNotification(accessor, dirId); } } }
ERROR_CODE CConnectivityAgentProxy::allocateChannel(TChannelPriority prio, UInt32 channel_id, IChannelObserver* observer) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::allocateChannel(type = " + convertIntegerToString((int) prio) + ", id = " + convertIntegerToString(channel_id) + " ), this = " + convertIntegerToString((intptr_t) this)); ERROR_CODE ret = ERR_FAIL; if ((channel_id > 0) && (channel_id <= 0xFFFF) && (NULL != observer)) { mRegistryMutex.lockWrite(); bool channel_unknown = mChannelRegistry.find(channel_id) == mChannelRegistry.end(); mRegistryMutex.unlockWrite(); if (channel_unknown) { mAllocateRequestCond.lock(); bool channel_requested = mAllocateRequestMap.find(channel_id) != mAllocateRequestMap.end(); if (channel_requested) { ret = ERR_IN_PROGRESS; channel_unknown = false; LOG4CPLUS_WARN(logger, "CConnectivityAgentProxy::allocateChannel() => ERROR: channel allocation in progress!"); } else { LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::allocateChannel() => insert request"); mAllocateRequestMap.insert( std::make_pair(channel_id, AllocateRequestInfo(prio, observer, false, ERR_UNKNOWN))); } mAllocateRequestCond.unlock(); } if (channel_unknown) { CDataAccessor requestDA; requestDA.setChannelID(channel_id); requestDA.setOpCode(E_ALLOCATE_CHANNEL); UInt32 data = prio; requestDA.setData(reinterpret_cast<UInt8 *>(&data), sizeof(UInt32)); UInt8* buf = new UInt8[requestDA.getObjectSize()]; requestDA.copyToRawArray(buf); UInt8 respBuf[100]; UInt32 respSize = sizeof(respBuf); CError err = mpIpc->request(mMsgIdGen.next(), buf, requestDA.getObjectSize(), respBuf, respSize); delete[] buf; if (!err.isNoError()) { LOG4CPLUS_WARN(logger, static_cast<std::string>(err)); ret = ERR_FAIL; mAllocateRequestCond.lock(); mAllocateRequestMap.erase(channel_id); mAllocateRequestCond.unlock(); LOG4CPLUS_WARN(logger, "CConnectivityAgentProxy::allocateChannel() => ERROR: failed to send request"); } else { CDataAccessor responseDA; if (respSize > 0) { responseDA = CDataAccessor(respBuf, respSize); ret = static_cast<ERROR_CODE>(responseDA.getErrorCode()); mAllocateRequestCond.lock(); mAllocateRequestMap.erase(channel_id); mAllocateRequestCond.unlock(); LOG4CPLUS_WARN(logger, "CConnectivityAgentProxy::allocateChannel() => ERROR: got error response"); } else { mAllocateRequestCond.lock(); while (true) { tAllocateRequestMap::iterator it = mAllocateRequestMap.find(channel_id); if (it == mAllocateRequestMap.end()) { ret = ERR_FAIL; LOG4CPLUS_WARN(logger, "CConnectivityAgentProxy::allocateChannel() => ERROR: request was removed"); break; } AllocateRequestInfo & info = it->second; if (info.mRequestDone) { LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::allocateChannel() => request done"); ret = info.mResult; mAllocateRequestMap.erase(it); break; } LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::allocateChannel() => before wait"); mAllocateRequestCond.wait(); LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::allocateChannel() => after wait"); } mAllocateRequestCond.unlock(); } // if response empty } // if no ipc err } else { LOG4CPLUS_ERROR(logger, "CConnectivityAgentProxy::allocateChannel() => ERROR: channel already exists! "); ret = ERR_NUMBER_BUSY; } } return ret; }