void L1InterfaceStub::processServiceDeallocateRequest(CDataAccessor & accessor) { UInt32 channel_id = accessor.getChannelID(); LOG4CPLUS_INFO(logger, "L1InterfaceStub::processServiceDeallocateRequest() => " "Channel deallocate request id = " + convertIntegerToString(channel_id)); ConnectivityAgentError ret = deallocateChannel(channel_id ); accessor.setOpCode(E_DEALLOCATE_CHANNEL_RESP); UInt32 data = ret.getCode(); accessor.setData(reinterpret_cast<UInt8 *>(&data), sizeof(UInt32)); sendRequest(accessor); if (ret.isNoError()) { LOG4CPLUS_INFO(logger, "L1InterfaceStub::processServiceDeallocateRequest() => " "channel successfully deallocated. " "Notifying client"); iviLink::Ipc::DirectionID dirId; bool found = false; mRegistryMutex.lock(); tChannelsRegistryMap::iterator iter = mL1ChannelRegistry.find(accessor.getChannelID()); if (mL1ChannelRegistry.end() != iter) { dirId = iter->second.mClientDir; found = true; LOG4CPLUS_INFO(logger, "L1InterfaceStub::processServiceDeallocateRequest() => " "channel found in registry - removing"); mL1ChannelRegistry.erase(accessor.getChannelID()); } mRegistryMutex.unlock(); if (found) { accessor.setOpCode(E_DEALLOCATE_CHANNEL_NTF); UInt8* buf = new UInt8[accessor.getObjectSize()]; accessor.copyToRawArray(buf); BaseError err = mpIpc->asyncRequest(mMsgIdGen.next(), buf, accessor.getObjectSize(), &dirId); if (!err.isNoError()) { LOG4CPLUS_WARN(logger, static_cast<std::string>(err)); } delete[] buf; } } // ret == OK }
void testRawArray() { //setup UInt8 data[] = "012"; CDataAccessor a; a.setChannelID(123); a.setErrorCode(234); a.setOpCode(345); a.setData(data, sizeof(data)); UInt8 array[100]; a.printContent(); // test UInt32 size = a.getObjectSize(); a.copyToRawArray(array); CPPUNIT_ASSERT_EQUAL(sizeof(data) + 4*4, size); CDataAccessor b(array, size); b.printContent(); CPPUNIT_ASSERT_EQUAL(123u, b.getChannelID()); CPPUNIT_ASSERT_EQUAL(234u, b.getErrorCode()); CPPUNIT_ASSERT_EQUAL(345u, b.getOpCode()); CPPUNIT_ASSERT_EQUAL(sizeof(data), b.getDataSize()); CPPUNIT_ASSERT(0 == memcmp(data, b.getData(), sizeof(data))); }
void L1InterfaceStub::OnDisconnected() { LOG4CPLUS_INFO(logger, "L1InterfaceStub::OnDisconnected(): " "Connectivity Agents disconnected=>sending notfications to all clients"); mSCProtocol.sendConnectionLost(); CDataAccessor responceDA; responceDA.setOpCode(E_CONNECTION_LOST_NTF); for (tClientDirections::iterator iter = mClientDirections.begin(); iter != mClientDirections.end(); ++iter) { UInt8* buf = new UInt8[responceDA.getObjectSize()]; responceDA.copyToRawArray(buf); mpIpc->asyncRequest(mMsgIdGen.next(), buf, responceDA.getObjectSize(), &(*iter)); delete [] buf; } }
ERROR_CODE CConnectivityAgentProxy::sendData(const UInt32 channel_id, UInt8 const* data, const UInt32 size) { LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::sendData() => channel " + convertIntegerToString(channel_id) + ", size " + convertIntegerToString(size)); ERROR_CODE ret = ERR_FAIL; const int MAX_BUF_SIZE = 0xFFFF; if ((data != NULL) && ((Int32) size > 0) && (size < MAX_BUF_SIZE)) { mRegistryMutex.lockRead(); bool found = (mChannelRegistry.find(channel_id) != mChannelRegistry.end()); mRegistryMutex.unlockRead(); if (found) { CDataAccessor requestDA; requestDA.setChannelID(channel_id); requestDA.setOpCode(E_SEND_DATA); requestDA.setData(data, size); UInt8 buf[MAX_BUF_SIZE]; requestDA.copyToRawArray(buf); assert(requestDA.getObjectSize() <= MAX_BUF_SIZE); if (requestDA.getObjectSize() > MAX_BUF_SIZE) { LOG4CPLUS_ERROR(logger, "CConnectivityAgentProxy::sendData() => ERROR: \ requestDA.getObjectSize() > max buf size"); } UInt32 respSize = 0; CError err = mpIpc->request(mMsgIdGen.next(), buf, requestDA.getObjectSize(), NULL, respSize); if (err.isNoError()) { ret = ERR_OK; } else { LOG4CPLUS_WARN(logger, static_cast<std::string>(err)); } } else
bool L1InterfaceStub::processClientDeallocateByWD(CDataAccessor & accessor, const iviLink::Ipc::DirectionID dirId) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); UInt32 channel_id = accessor.getChannelID(); if(CA_SERVICE_CHANNEL !=channel_id) { LOG4CPLUS_INFO(logger, "L1InterfaceStub::processClientDeallocateByWD() => " "Deallocate Channel Request: ChID = " + convertIntegerToString(channel_id)); mRegistryMutex.lock(); tChannelsRegistryMap::iterator iter = mL1ChannelRegistry.find(channel_id); if (iter != mL1ChannelRegistry.end()) { iter->second.mClientDir = dirId; // so that Negotiator receives the response iter->second.mState = E_TRANSITION_CLIENT; accessor.setOpCode(E_DEALLOCATE_CHANNEL); sendRequest(accessor); assert(mTimeoutManager); mTimeoutManager->addSubscriber(new RequestTimeout(static_cast<tOpCode> (accessor.getOpCode()),channel_id,this ), 250000); accessor.setErrorCode(0); } else { LOG4CPLUS_INFO(logger, "L1InterfaceStub::processClientDeallocateByWD() " "=> Deallocate Channel Request: ChID = " + convertIntegerToString(channel_id) + " NOT FOUND!"); accessor.setErrorCode(ConnectivityAgentError::ERROR_NOT_FOUND); } mRegistryMutex.unlock(); } else { accessor.setErrorCode(ConnectivityAgentError::ERROR_OTHER); } return true; }
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); } } }
ConnectivityAgentError L1InterfaceStub::receiveData(Buffer & buffer, UInt32 channel_id) { LOG4CPLUS_TRACE(logger, "L1InterfaceStub::receiveData() => channel " + convertIntegerToString(channel_id)); UInt32 offset = 0; CDataAccessor accessor; ConnectivityAgentError result; // TODO ipc errors processing // TODO incorrect data processing assert(buffer.getFilledSize() <= buffer.getMaxSize()); LOG4CPLUS_INFO(logger, "L1InterfaceStub::receiveData() => buf size " + convertIntegerToString(buffer.getFilledSize())); if(channel_id == CA_SERVICE_CHANNEL) { //> If data received from service channel - process service request do { UInt32 begin = offset; UInt16 buf_length = ByteOrder::ntoh16(*reinterpret_cast<UInt16*> (buffer.getData() + offset)); offset += 2; LOG4CPLUS_INFO(logger, "L1InterfaceStub::receiveData() => buf_length " + convertIntegerToString(buf_length)); assert(begin + buf_length <= buffer.getFilledSize()); UInt32 operation = ByteOrder::ntoh32(*reinterpret_cast<UInt32*> (buffer.getData() + offset)); offset += 4; accessor.setOpCode(operation); UInt32 channel_id = ByteOrder::ntoh32(*reinterpret_cast<UInt32*> (buffer.getData() + offset)); offset += 4; accessor.setChannelID(channel_id); UInt32 data_size = ByteOrder::ntoh32(*reinterpret_cast<UInt32*> (buffer.getData() + offset)); offset += 4; UInt32 error_code = ByteOrder::ntoh32(*reinterpret_cast<UInt32*> (buffer.getData() + offset)); offset += 4; accessor.setErrorCode(error_code); accessor.setData(buffer.getData() + offset, data_size); offset += data_size; accessor.printContent(); ///>Process service request tServiceCallbacksMap::iterator iter = mServiceCallbacksMap.find(static_cast<tOpCode>(operation)); if (iter !=mServiceCallbacksMap.end()) { ///> This funny language structure is just callback invocation. ///> Not obvious, huh? =) (this->*iter->second)(accessor); result.setNoError(); } else { LOG4CPLUS_WARN(logger, "L1InterfaceStub::receiveData() => " "UNKNOWN SERVICE REQUEST = " + convertIntegerToString(operation) + "!!!"); } } while (offset < buffer.getFilledSize()); LOG4CPLUS_INFO(logger, "L1InterfaceStub::receiveData() => offset " + convertIntegerToString(offset) + "!!!"); assert(buffer.getFilledSize() == offset); } else { //> Or pack to accessor and send to client accessor.setOpCode(E_RECEIVE_DATA_NTF); accessor.setChannelID(channel_id); assert (buffer.getFilledSize() > 0); accessor.setData(buffer.getData(),buffer.getFilledSize()); accessor.printContent(); UInt8* buf = new UInt8[accessor.getObjectSize()]; accessor.copyToRawArray(buf); BaseError ipcError = mpIpc->asyncRequest(mMsgIdGen.next(), buf, accessor.getObjectSize(), &mL1ChannelRegistry[channel_id].mClientDir); // TODO use find, and not [] delete [] buf; if (ipcError.isNoError()) { result.setNoError(); } else { result.setErrorCode(ConnectivityAgentError::ERROR_REQUEST_FAILED); } } return result; }
void L1InterfaceStub::RequestTimeout::onTimeout() { CDataAccessor resp; UInt32 data = ERR_TIMEOUT; if (mEnabled) { switch (mRequest) { case E_ALLOCATE_CHANNEL: { mpOwner->mRegistryMutex.lock(); bool found = (mpOwner->mL1ChannelRegistry.find(mChannelID) != mpOwner->mL1ChannelRegistry.end()); mpOwner->mRegistryMutex.unlock(); if (found) { LOG4CPLUS_INFO(logger, "L1InterfaceStub::RequestTimeout::onTimeout()=> channel " + convertIntegerToString(mChannelID) + " allocated!"); } else { LOG4CPLUS_WARN(logger, "L1InterfaceStub::RequestTimeout::onTimeout()=> Channel " + convertIntegerToString(mChannelID) + " allocation timeout!"); resp.setChannelID(mChannelID); resp.setOpCode(E_ALLOCATE_CHANNEL_RESP); resp.setData(reinterpret_cast<UInt8 *>(&data), sizeof(UInt32)); resp.setErrorCode(ConnectivityAgentError::ERROR_TIMEOUT); mpOwner->mRequestedMapMutex.lock(); mpOwner->mRequestedMap.erase(mChannelID); mpOwner->mRequestedMapMutex.unlock(); mpOwner->sendRequest(resp); } break; } case E_DEALLOCATE_CHANNEL: { iviLink::Ipc::DirectionID client_dir; bool found = false; mpOwner->mRegistryMutex.lock(); { tChannelsRegistryMap::iterator iter = mpOwner->mL1ChannelRegistry.find(mChannelID); found = (iter != mpOwner->mL1ChannelRegistry.end()); if (found) { client_dir = iter->second.mClientDir; } } mpOwner->mRegistryMutex.unlock(); if (found) { LOG4CPLUS_INFO(logger, "L1InterfaceStub::RequestTimeout::onTimeout() => " "Channel deallocation timeout!"); resp.setChannelID(mChannelID); resp.setOpCode(E_DEALLOCATE_CHANNEL_RESP); resp.setData(reinterpret_cast<UInt8 *>(&data), sizeof(UInt32)); resp.setErrorCode(ConnectivityAgentError::ERROR_TIMEOUT); UInt8* buf = new UInt8[resp.getObjectSize()]; resp.copyToRawArray(buf); BaseError err = mpOwner->mpIpc->asyncRequest(mpOwner->mMsgIdGen.next(), buf, resp.getObjectSize(), &client_dir); if (!err.isNoError()) { LOG4CPLUS_WARN(logger, static_cast<std::string>(err)); } delete [] buf; } else { LOG4CPLUS_INFO(logger, "L1InterfaceStub::RequestTimeout::onTimeout() => " "channel Deallocated!"); } break; } default: break; } } }
ERROR_CODE CConnectivityAgentProxy::deallocateChannel(UInt32 channel_id) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::deallocateChannel(chID = " + convertIntegerToString(channel_id) + ")"); ERROR_CODE ret = ERR_NOTFOUND; mRegistryMutex.lockWrite(); // Channel info will be saved in info and removed from registry here. // In case of some errors, it will be restored in registry. tChannelInfo info; tChannelsRegistryMap::iterator iter = mChannelRegistry.find(channel_id); if (iter == mChannelRegistry.end()) { LOG4CPLUS_ERROR(logger, "CConnectivityAgentProxy::deallocateChannel(chID = " + convertIntegerToString(channel_id) + ") => ERROR: Channel not found! "); } else { ret = ERR_OK; info = iter->second; iter->second.mChannelBuffer.forgetData(); mChannelRegistry.erase(iter); mChannelOnDeallocSet.insert(channel_id); } mRegistryMutex.unlockWrite(); if (ret != ERR_OK) return ret; CDataAccessor requestDA; requestDA.setChannelID(channel_id); requestDA.setOpCode(E_DEALLOCATE_CHANNEL); UInt8* buf = new UInt8[requestDA.getObjectSize()]; requestDA.copyToRawArray(buf); // response will be sent later as a separate request UInt32 respSize = 0; CError err = mpIpc->request(mMsgIdGen.next(), buf, requestDA.getObjectSize(), NULL, respSize); delete[] buf; if (!err.isNoError()) { LOG4CPLUS_WARN(logger, static_cast<std::string>(err)); ret = ERR_FAIL; } else { CDataAccessor responseDA; mDeallocateRequestResultCond.lock(); { LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::deallocateChannel waiting for mLastRequestResultDA"); while (mDeallocateRequestResultMap.find(channel_id) == mDeallocateRequestResultMap.end()) { LOG4CPLUS_INFO(logger, "before wait"); mDeallocateRequestResultCond.wait(); LOG4CPLUS_INFO(logger, "after wait"); } responseDA = mDeallocateRequestResultMap[channel_id]; mDeallocateRequestResultMap.erase(channel_id); } mDeallocateRequestResultCond.unlock(); if (responseDA.getData()) { if ((E_DEALLOCATE_CHANNEL_RESP == responseDA.getOpCode()) && (channel_id == responseDA.getChannelID())) { UInt32 data = 0; memcpy(&data, responseDA.getData(), sizeof(UInt32)); responseDA.resetAll(); ret = static_cast<ERROR_CODE>(data); } else { LOG4CPLUS_ERROR(logger, "CConnectivityAgentProxy::deallocateChannel() => ERROR: wrong response type(" + convertIntegerToString(responseDA.getOpCode()) + ") from Agent !!! "); ret = ERR_WRONG_SEQUENCE; } } else { LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::deallocateChannel() => " "channel already deleted form other side"); ret = ERR_OK; } } if (ret != ERR_OK) { // something gone wrong, we need to restore information in registry mRegistryMutex.lockWrite(); if (mChannelRegistry.find(channel_id) != mChannelRegistry.end()) { LOG4CPLUS_WARN(logger, "CConnectivityAgentProxy::deallocateChannel: " "something gone wrong and I'm unable to restore channel info - " "there is a channel in registry with such id"); } else { mChannelRegistry[channel_id] = info; info.mChannelBuffer.forgetData(); LOG4CPLUS_INFO(logger, "CConnectivityAgentProxy::deallocateChannel:" "unable to delete channel " + convertIntegerToString(channel_id) + ", so channel info is restored"); } mRegistryMutex.unlockWrite(); } mRegistryMutex.lockWrite(); mChannelOnDeallocSet.erase(channel_id); mRegistryMutex.unlockWrite(); return ret; }
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; }