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 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; }
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 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 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; }
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(); }