ConnectivityAgentError L1InterfaceStub::allocateChannelLocally(const UInt32 channel_id, tRequestedChannelInfo const& req_info) { LOG4CPLUS_TRACE_METHOD(logger, "L1InterfaceStub::allocateChannelLocally" " channel_id" + convertIntegerToString(channel_id)); ConnectivityAgentError result; assert(mL1ChannelRegistry.find(channel_id) == mL1ChannelRegistry.end()); assert(req_info.mState == E_TRANSITION_AGENT || req_info.mState == E_TRANSITION_CLIENT); ///>FIXME Set up correct thresholds tL1ChannelInfo info; info.mType = req_info.mType; info.mClientDir = req_info.mClientDir; info.mState = req_info.mState; info.mLowerThresholdTime = 0; info.mUpperThresholdTime = 0xFFFFFFFF; result = CChannelAllocator::getInstance()->allocateChannel(info.mType, channel_id, info); LOG4CPLUS_INFO(logger, "L1InterfaceStub::allocateChannelLocally(): CChannelAllocator ret = " + convertIntegerToString((int)result.getCode())); /// @todo correct processing of error code and return values. PIlin, 31.08.12 //ret = ERR_OK; if (result.isNoError()) { mL1ChannelRegistry.insert(std::pair<UInt32,tL1ChannelInfo >(channel_id, info)); } return result; }
ConnectivityAgentError CTransmitDispatcher::openChannel(const UInt32 channel_id, const TChannelPriority prio, iviLink::ConnectivityAgent::L1::IBufferProducer& bufferProducer) { CSource* pSource = NULL; LOG4CPLUS_TRACE(logger, "CTransmitDispatcher::openChannel(chID = " + convertIntegerToString(channel_id) + ", prio = " + convertIntegerToString((int) prio) + ", bufProd = " + convertIntegerToString((intptr_t) &bufferProducer) + ")"); ConnectivityAgentError result = ConnectivityAgentError::NoError(); mRegistryMutex.lock(); TSourceList::iterator iter = mRegistry[static_cast<UInt8>(prio)].begin(); while (iter != mRegistry[static_cast<UInt8>(prio)].end()) { if (channel_id == static_cast<CSource*>(*iter)->getChannelID()) { result.setErrorCode(ConnectivityAgentError::ERROR_CHANNEL_BUSY); break; } ++iter; } if (iter == mRegistry[static_cast<UInt8>(prio)].end()) { pSource = new CSource(channel_id, mEventSem); LOG4CPLUS_INFO(logger, "CTransmitDispatcher::openChannel() number = " + convertIntegerToString(channel_id) + " prio = " + convertIntegerToString(static_cast<UInt8>(prio)) + " opening new channel"); pSource->registerProducer(&bufferProducer); bufferProducer.registerConsumer(pSource); mRegistry[prio].push_back(pSource); } mRegistryMutex.unlock(); return result; }
ConnectivityAgentError L1InterfaceStub::endAllocateChannel(const UInt32 channel_id, DirectionID& dirId) { ConnectivityAgentError result = ConnectivityAgentError::NoError(); mRegistryMutex.lock(); { tChannelsRegistryMap::iterator iter = mL1ChannelRegistry.find(channel_id); if (iter != mL1ChannelRegistry.end()) { tL1ChannelInfo & info = iter->second; if (E_TRANSITION_AGENT == info.mState) { result.setErrorCode(ConnectivityAgentError::ERROR_DEFERRED); } LOG4CPLUS_INFO(logger, "L1InterfaceStub::endAllocateChannel(): E_OPERATIONAL"); info.mState = E_OPERATIONAL; dirId = info.mClientDir; } else { // SEQ_E_4 result.setErrorCode(ConnectivityAgentError::ERROR_NOT_FOUND); LOG4CPLUS_ERROR(logger, "L1InterfaceStub::endAllocateChannel(): ERR_NOTFOUND"); } } mRegistryMutex.unlock(); return result; }
ConnectivityAgentError CCarrierAdapter::processFrame(iviLink::ConnectivityAgent::HAL::Frame & frame) { ConnectivityAgentError processResult = ConnectivityAgentError::NoError(); mFrameProcessingCondVar.lock(); while (!mIsFrameProcessingAllowed) { mFrameProcessingCondVar.wait(); } mFrameProcessingCondVar.unlock(); mFrameReceiverLock.lock(); if (mpFrameReceiver) { processResult = mpFrameReceiver->receiveFrame(frame); if(processResult.isNoError() || processResult.getCode() == ConnectivityAgentError::ERROR_RESEND_ACK) { if (!frame.isACK()) { sendACK(frame); } } else { LOG4CPLUS_INFO(logger, "CCarrierAdapter::receiveFrame ERROR mpFrameReceiver->receiveFrame returned " + convertIntegerToString((int)processResult.getCode()) + ". ACK is not send"); } } mFrameReceiverLock.unlock(); return processResult; }
ConnectivityAgentError CTcpCarrierAdapter::receiveRawArray(UInt8* pArray, UInt32 & size) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); ssize_t n = -1; int saved_errno = 0; ConnectivityAgentError receiveResult = ConnectivityAgentError::NoError(); mSocketMutex.lockRead(); { do { n = ::recv(mSocket, pArray, size, 0); } while (n == -1 && errno == EINTR); saved_errno = errno; } mSocketMutex.unlockRead(); if (n > 0) { size = n; } else { LOG4CPLUS_WARN(logger, "CTcpCarrierAdapter::receiveRawArray() recv error: " + convertIntegerToString(saved_errno) + strerror(saved_errno)); // connection lost mSelfpipe.signal(eGameOver); receiveResult.setErrorCode(ConnectivityAgentError::ERROR_BROKEN_PIPE); } return receiveResult; }
ConnectivityAgentError CTarget::receiveFrame(const iviLink::ConnectivityAgent::HAL::Frame& frame) { LOG4CPLUS_TRACE(logger, " CTarget::receiveFrame(): channel " + convertIntegerToString(mChannelID)); static bool firstFlag = true; ConnectivityAgentError result; assert(mChannelID == frame.mFrameHeader.channel_id); if((!firstFlag)&&(!mCarrierReplaced)&&(frame.mFrameHeader.number != mLastFrameNr + 1)) { LOG4CPLUS_ERROR(logger, "CTarget::receiveFrame error - ERR_WRONG_FRAME_SEQUENCE: frame.mFrameHeader.number = " + convertIntegerToString(frame.mFrameHeader.number) + ", mLastFrameNr + 1 = " + convertIntegerToString(mLastFrameNr + 1)); if(frame.mFrameHeader.number<=mLastFrameNr) { result.setErrorCode(ConnectivityAgentError::ERROR_RESEND_ACK); } else { result.setErrorCode(ConnectivityAgentError::ERROR_WRONG_FRAME_SEQUENCE); } } else if (mBufferQueue.empty()) { LOG4CPLUS_ERROR(logger, "CTarget::receiveFrame error - mBufferQueue.empty()"); result.setErrorCode(ConnectivityAgentError::ERROR_NO_FREE_BUFFERS_LEFT); } else { mBufferQueueMutex.lock(); Buffer* buf = mBufferQueue.front(); mBufferQueue.pop_front(); mBufferQueueMutex.unlock(); assert(buf); copyFromFrame(frame, *buf); assert(mpBufferConsumer); result = mpBufferConsumer->consumeBuffer(buf); if (result.isNoError()) { if(firstFlag) { firstFlag =false; } if(mCarrierReplaced) { mCarrierReplaced = false; } mLastFrameNr = frame.mFrameHeader.number; } } return result; }
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 CCarrierAdapter::haveData() { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); UInt8* pArray = reinterpret_cast<UInt8*>(&mFrame); // Reading as many as possible UInt32 size = sizeof(mFrame) - mFilledSize; ConnectivityAgentError receiveResult = receiveRawArray(pArray + mFilledSize, size); if (!receiveResult.isNoError()) { return; } UInt32 saved_size = mFilledSize; mFilledSize += size; while (mFilledSize >= sizeof(mFrame.mFrameHeader)) { // header done if (saved_size < sizeof(mFrame.mFrameHeader)) { // header become ready right now CFrameConverter::arrayToFrame(pArray, &mFrame); } const UInt32 full_size = mFrame.getSize() + sizeof(iviLink::ConnectivityAgent::HAL::Frame::FrameHeader); if (full_size <= mFilledSize) { // frame done // ! The error returned is not processed processFrame(mFrame); memmove(pArray, pArray + full_size, mFilledSize - full_size); mFilledSize -= full_size; saved_size = 0; } else { break; } } // while }
ConnectivityAgentError CTcpCarrierAdapter::CSelfpipe::readSignal(tSignal& signal) { LOG4CPLUS_TRACE(logger, __PRETTY_FUNCTION__); ConnectivityAgentError error = ConnectivityAgentError::NoError(); ssize_t res = -1; do { res = read(mSelfpipe[0], &signal, sizeof(signal)); } while (res == -1 && errno == EINTR); if (res == -1) { int saved_errno = errno; LOG4CPLUS_ERROR(logger, "selfpipe write error: " + convertIntegerToString(saved_errno) + strerror(saved_errno)); error.setErrorCode(ConnectivityAgentError::ERROR_OTHER); } return error; }
ConnectivityAgentError CTcpCarrierAdapter::waitHandshakeState(EHandshakeState state) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); ConnectivityAgentError waitResult = ConnectivityAgentError::NoError(); mHandshakeStateCondVar.lock(); { int rc = 0; timespec ts = CCondVar::calcAbsTimeout(mHandshakeTimeout); while (mHandshakeState != state && rc == 0) { rc = mHandshakeStateCondVar.waitTimeout(ts); } if (rc != 0 || mHandshakeState != state) waitResult.setErrorCode(ConnectivityAgentError::ERROR_HANDSHAKE_FAILED); } mHandshakeStateCondVar.unlock(); return waitResult; }
bool L1InterfaceStub::processClientAllocateRequest(CDataAccessor & accessor, const iviLink::Ipc::DirectionID dirId) { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); const UInt32 channel_id = accessor.getChannelID(); if(CA_SERVICE_CHANNEL == channel_id) { // SEQ_E_5 LOG4CPLUS_WARN(logger, "Channel CA_SERVICE_CHANNEL is not allowed to be open"); accessor.resetData(); accessor.setErrorCode(ConnectivityAgentError::ERROR_CHANNEL_BUSY); return true; } UInt32 prio = 0; memcpy(&prio, accessor.getData(), accessor.getDataSize()); LOG4CPLUS_INFO(logger, "L1InterfaceStub::processClientAllocateRequest() => " "Allocate Channel Request: ChID = " + convertIntegerToString(channel_id) + ", prio = " + convertIntegerToString(prio)); iviLink::Ipc::DirectionID tmpDirId = dirId; ConnectivityAgentError err = ConnectivityAgentError(ConnectivityAgentError::ERROR_OTHER); mRequestedMapMutex.lock(); mRegistryMutex.lock(); { err = beginAllocateChannel(static_cast<TChannelPriority>(prio), channel_id, true, tmpDirId); accessor.setErrorCode(err.getCode()); if (err.isNoError()) { LOG4CPLUS_INFO(logger, "L1InterfaceStub::processClientAllocateRequest() => " "all ok, sending request to other side" ); err = sendRequest(accessor); } } mRegistryMutex.unlock(); mRequestedMapMutex.unlock(); if (err.isNoError()) //> all ok { return false; } else { // something wrong, need message about error // SEQ_E_5 assert(err.getCode() != ConnectivityAgentError::ERROR_DEFERRED); accessor.resetData(); accessor.setErrorCode(err.getCode()); return true; } }
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; }
ConnectivityAgentError L1InterfaceStub::beginAllocateChannel(const TChannelPriority prio, const UInt32 channel_id, const bool client_side, DirectionID& dirId) { LOG4CPLUS_TRACE_METHOD(logger, "L1InterfaceStub::beginAllocateChannel(" + convertIntegerToString(channel_id) + ", " "client_side" + std::string(client_side ? "true" : "false") +")"); ConnectivityAgentError result; //if channel wasn't opened yet if (mL1ChannelRegistry.find(channel_id) == mL1ChannelRegistry.end()) { tRequestedChannelsMap::iterator iter = mRequestedMap.find(channel_id); if (iter == mRequestedMap.end()) // if channel wasn't requested yet ->request channel { // First call on SEQ_A and SEQ_B or SEQ_A DEFERRED tRequestedChannelInfo info; info.mType = prio; info.mState = (client_side ? E_TRANSITION_CLIENT : E_TRANSITION_AGENT); info.mClientDir = dirId; assert((client_side && dirId != -1) || (!client_side && dirId == -1)); LOG4CPLUS_INFO(logger, "L1InterfaceStub::beginAllocateChannel() =>insert request" " channel_id " + convertIntegerToString(channel_id) + " mState " + std::string(info.mState == E_TRANSITION_CLIENT ? "E_TRANSITION_CLIENT" : "E_TRANSITION_AGENT")); mRequestedMap.insert(std::pair<UInt32, tRequestedChannelInfo>(channel_id, info)); result = (client_side ? ConnectivityAgentError::NoError() : ConnectivityAgentError(ConnectivityAgentError::ERROR_DEFERRED)); } else { tRequestedChannelInfo & info = iter->second; //if channel was requested by other side if (!client_side || (client_side && info.mState == E_TRANSITION_AGENT)) { // SEQ_A DEFERRED or call from other side LOG4CPLUS_INFO(logger, "L1InterfaceStub::beginAllocateChannel() =>" "Opening channel locally"); if (client_side) { info.mClientDir = dirId; } else { dirId = info.mClientDir; } result = allocateChannelLocally(channel_id, info); assert(result.getCode() != ConnectivityAgentError::ERROR_DEFERRED); mRequestedMap.erase(channel_id); } else //channel was requested by Client Application not the first time { // SEQ_E_1 LOG4CPLUS_ERROR(logger, "L1InterfaceStub::beginAllocateChannel() => ERROR: " "allocation is in progress! "); result.setErrorCode(ConnectivityAgentError::ERROR_ALLOCATION_IN_PROGRESS); } } } else //channel already opened { // SEQ_E_2 LOG4CPLUS_ERROR(logger, "L1InterfaceStub::beginAllocateChannel() => ERROR: channel " "already exists! "); result.setErrorCode(ConnectivityAgentError::ERROR_CHANNEL_BUSY); } return result; }
ConnectivityAgentError CTcpCarrierAdapter::makeHandshake() { LOG4CPLUS_TRACE_METHOD(logger, __PRETTY_FUNCTION__); ConnectivityAgentError handshakeResult = ConnectivityAgentError::NoError(); mHandshakeStateCondVar.lock(); if (mHandshakeState != eHandshakeBefore) { LOG4CPLUS_ERROR(logger,"wrong handshake state" ); handshakeResult.setErrorCode(ConnectivityAgentError::ERROR_HANDSHAKE_FAILED); } mHandshakeStateCondVar.unlock(); if (!handshakeResult.isNoError()) return handshakeResult; // will return this in case of any handshake fail ConnectivityAgentError failedResult(ConnectivityAgentError::ERROR_HANDSHAKE_FAILED); const UInt32 size = 50; UInt8 pAddr[size]; memset(pAddr, 0, size); strncpy(reinterpret_cast<char*>(pAddr), this->getRemoteAddress(), size); if (mConnectionInfo.serverSocket) { LOG4CPLUS_INFO(logger, "CTcpCarrierAdapter::makeHandshake(): send AXIS ..."); handshakeAndVerStrAxis[4] = IVILINK_VERSION_MAJOR; handshakeAndVerStrAxis[5] = IVILINK_VERSION_MINOR; if (!sendPreparedArray(handshakeAndVerStrAxis, sizeof(handshakeAndVerStrAxis)).isNoError()) { LOG4CPLUS_ERROR(logger,"handshake AXIS send failed" ); return failedResult; } if (!waitHandshakeState(eHandshakeA).isNoError()) { LOG4CPLUS_ERROR(logger,"handshake not state A"); return failedResult; } if (!sendPreparedArray(pAddr, sizeof(pAddr)).isNoError()) { LOG4CPLUS_ERROR(logger,"handshake send addr failed"); return failedResult; } if (!waitHandshakeState(eHandshakeDone).isNoError()) { LOG4CPLUS_ERROR(logger,"handshake not state done"); return failedResult; } mGenderType = eServerGender; } else { if (!waitHandshakeState(eHandshakeA).isNoError()) { LOG4CPLUS_ERROR(logger,"handshake not state A"); return failedResult; } handshakeAndVerStrSixa[4] = IVILINK_VERSION_MAJOR; handshakeAndVerStrSixa[5] = IVILINK_VERSION_MINOR; if (!sendPreparedArray(handshakeAndVerStrSixa, sizeof(handshakeAndVerStrSixa)).isNoError()) { LOG4CPLUS_ERROR(logger,"handshake SIXA send failed" ); return failedResult; } if (!waitHandshakeState(eHandshakeDone).isNoError()) { LOG4CPLUS_ERROR(logger,"handshake not state done"); return failedResult; } if (!sendPreparedArray(pAddr, sizeof(pAddr)).isNoError()) { LOG4CPLUS_ERROR(logger,"handshake send addr failed"); return failedResult; } mGenderType = eClientGender; } return ConnectivityAgentError::NoError(); }