void LongPollingMessageReceiver::processReceivedJsonObjects(const std::string& jsonObject) { JoynrMessage* msg = JsonSerializer::deserialize<JoynrMessage>(jsonObject); if (msg == nullptr) { JOYNR_LOG_ERROR(logger, "Unable to deserialize message. Raw message: {}", jsonObject); return; } if (msg->getType().empty()) { JOYNR_LOG_ERROR(logger, "received empty message - dropping Messages"); return; } if (!msg->containsHeaderExpiryDate()) { JOYNR_LOG_ERROR(logger, "received message [msgId=[{}] without decay time - dropping message", msg->getHeaderMessageId()); } if (msg->getType() == JoynrMessage::VALUE_MESSAGE_TYPE_REQUEST || msg->getType() == JoynrMessage::VALUE_MESSAGE_TYPE_SUBSCRIPTION_REQUEST || msg->getType() == JoynrMessage::VALUE_MESSAGE_TYPE_BROADCAST_SUBSCRIPTION_REQUEST) { // TODO ca: check if replyTo header info is available? std::string replyChannelId = msg->getHeaderReplyChannelId(); std::shared_ptr<system::RoutingTypes::ChannelAddress> address( new system::RoutingTypes::ChannelAddress(replyChannelId)); messageRouter->addNextHop(msg->getHeaderFrom(), address); } // messageRouter.route passes the message reference to the MessageRunnable, which copies it. // TODO would be nicer if the pointer would be passed to messageRouter, on to MessageRunnable, // and runnable should delete it. messageRouter->route(*msg); delete msg; }
bool LocalDomainAccessStore::insertDomainRoleEntry(const std::string& userId, Role::Enum role, const std::vector<std::string>& domains) { // Loop through the domains auto it = domains.begin(); while (it != domains.end()) { // Insert a record for each domain QSqlQuery query; std::string domain = *it; query.prepare(QtTypeUtil::toQt(UPDATE_DRE)); query.bindValue(BIND_UID, QtTypeUtil::toQt(userId)); query.bindValue(BIND_ROLE, role); query.bindValue(BIND_DOMAIN, QtTypeUtil::toQt(domain)); if (!query.exec()) { JOYNR_LOG_ERROR(logger, "Could not add domain entry {} {} {}", userId, role, domain); return false; } ++it; } // Assume success return true; }
void LongPollingMessageReceiver::checkServerTime() { std::string timeCheckUrl = bounceProxyUrl.getTimeCheckUrl().toString(); std::shared_ptr<IHttpGetBuilder> timeCheckRequestBuilder( HttpNetworking::getInstance()->createHttpGetBuilder(timeCheckUrl)); std::shared_ptr<HttpRequest> timeCheckRequest( timeCheckRequestBuilder->addHeader("Accept", "text/plain") ->withTimeout(settings.bounceProxyTimeout) ->build()); JOYNR_LOG_DEBUG(logger, "CheckServerTime: sending request to Bounce Proxy ({})", timeCheckUrl); std::chrono::system_clock::time_point localTimeBeforeRequest = std::chrono::system_clock::now(); HttpResult timeCheckResult = timeCheckRequest->execute(); std::chrono::system_clock::time_point localTimeAfterRequest = std::chrono::system_clock::now(); std::uint64_t localTime = (TypeUtil::toMilliseconds(localTimeBeforeRequest) + TypeUtil::toMilliseconds(localTimeAfterRequest)) / 2; if (timeCheckResult.getStatusCode() != 200) { JOYNR_LOG_ERROR(logger, "CheckServerTime: Bounce Proxy not reached [statusCode={}] [body={}]", timeCheckResult.getStatusCode(), QString(timeCheckResult.getBody()).toStdString()); } else { JOYNR_LOG_TRACE(logger, "CheckServerTime: reply received [statusCode={}] [body={}]", timeCheckResult.getStatusCode(), QString(timeCheckResult.getBody()).toStdString()); std::uint64_t serverTime = TypeUtil::toStdUInt64(QString(timeCheckResult.getBody()).toLongLong()); auto minMaxTime = std::minmax(serverTime, localTime); std::uint64_t diff = minMaxTime.second - minMaxTime.first; JOYNR_LOG_INFO( logger, "CheckServerTime [server time={}] [local time={}] [diff={} ms]", TypeUtil::toDateString(JoynrTimePoint(std::chrono::milliseconds(serverTime))), TypeUtil::toDateString(JoynrTimePoint(std::chrono::milliseconds(localTime))), diff); if (diff > 500) { JOYNR_LOG_ERROR(logger, "CheckServerTime: time difference to server is {} ms", diff); } } }
void Dispatcher::handlePublicationReceived(const JoynrMessage& message) { std::string jsonSubscriptionPublication = message.getPayload(); try { SubscriptionPublication subscriptionPublication = JsonSerializer::deserialize<SubscriptionPublication>(jsonSubscriptionPublication); std::string subscriptionId = subscriptionPublication.getSubscriptionId(); assert(subscriptionManager != nullptr); std::shared_ptr<ISubscriptionCallback> callback = subscriptionManager->getSubscriptionCallback(subscriptionId); if (!callback) { JOYNR_LOG_ERROR(logger, "Dropping reply for non/no more existing subscription with id = {}", subscriptionId); return; } subscriptionManager->touchSubscriptionState(subscriptionId); int typeId = callback->getTypeId(); // Get the publication interpreter - this has to be a reference to support // PublicationInterpreter polymorphism IPublicationInterpreter& interpreter = MetaTypeRegistrar::instance().getPublicationInterpreter(typeId); interpreter.execute(callback, subscriptionPublication); } catch (const std::invalid_argument& e) { JOYNR_LOG_ERROR( logger, "Unable to deserialize subscription publication object from: {} - error: {}", jsonSubscriptionPublication, e.what()); } }
void WebSocketLibJoynrMessagingSkeleton::onTextMessageReceived(const std::string& message) { // deserialize message and transmit JoynrMessage* joynrMsg = JsonSerializer::deserialize<JoynrMessage>(message); if (joynrMsg == nullptr || joynrMsg->getType().empty()) { JOYNR_LOG_ERROR(logger, "Unable to deserialize joynr message object from: {}", message); return; } JOYNR_LOG_TRACE(logger, "<<< INCOMING <<< {}", message); // message router copies joynr message when scheduling thread that handles // message delivery transmit(*joynrMsg); delete joynrMsg; }
void ParticipantIdStorage::writeStoreToFile() { std::lock_guard<std::mutex> lockAccessToFile(fileMutex); WriteLocker lockAccessToStorage(storageMutex); auto& writeIndex = storage.get<participantIdStorageTags::write>(); const size_t entries = writeIndex.size(); // The storage in memory is supposed to contain at least one entry at this point. if (entries == 0) { assert(entriesWrittenToDisk == 0); return; } if (entries > entriesWrittenToDisk) { JOYNR_LOG_TRACE( logger(), "Writing {} new entries to file.", entries - entriesWrittenToDisk); // write not present entries to File size_t writtenToDisk = 0; for (size_t i = entriesWrittenToDisk; i < entries; ++i, ++writtenToDisk) { auto entry = writeIndex[i]; try { joynr::util::appendStringToFile(fileName, entry.toIniForm()); } catch (const std::runtime_error& ex) { JOYNR_LOG_ERROR(logger(), "Cannot save ParticipantId to file. Next application lifecycle " "might not function correctly. Exception: ", ex.what()); entriesWrittenToDisk += writtenToDisk; return; } } assert(entries == entriesWrittenToDisk + writtenToDisk); entriesWrittenToDisk = entries; JOYNR_LOG_TRACE(logger(), "Storage on file contains now {} entries.", entriesWrittenToDisk); } else if (entries < entriesWrittenToDisk) { // This actually means that someone modified the file and inserted other entries. // Do nothing. } else { // In this case the number of entries written to disk matches those in the store. // Do nothing. } }
void Dispatcher::handleReplyReceived(const JoynrMessage& message) { // json request // lookup necessary data std::string jsonReply = message.getPayload(); // deserialize the jsonReply try { Reply reply = JsonSerializer::deserialize<Reply>(jsonReply); std::string requestReplyId = reply.getRequestReplyId(); std::shared_ptr<IReplyCaller> caller = replyCallerDirectory.lookup(requestReplyId); if (caller == nullptr) { // This used to be a fatal error, but it is possible that the replyCallerDirectory // removed // the caller // because its lifetime exceeded TTL JOYNR_LOG_INFO( logger, "caller not found in the ReplyCallerDirectory for requestid {}, ignoring", requestReplyId); return; } // Get the reply interpreter - this has to be a reference to support ReplyInterpreter // polymorphism int typeId = caller->getTypeId(); IReplyInterpreter& interpreter = MetaTypeRegistrar::instance().getReplyInterpreter(typeId); // pass reply interpreter.execute(caller, reply); // Clean up removeReplyCaller(requestReplyId); } catch (const std::invalid_argument& e) { JOYNR_LOG_ERROR(logger, "Unable to deserialize reply object from: {} - error {}", jsonReply, e.what()); } }
void Dispatcher::handleSubscriptionStopReceived(const JoynrMessage& message) { JOYNR_LOG_DEBUG(logger, "handleSubscriptionStopReceived"); std::string jsonSubscriptionStop = message.getPayload(); std::string subscriptionId; try { SubscriptionStop subscriptionStop = JsonSerializer::deserialize<SubscriptionStop>(jsonSubscriptionStop); subscriptionId = subscriptionStop.getSubscriptionId(); } catch (const std::invalid_argument& e) { JOYNR_LOG_ERROR(logger, "Unable to deserialize subscription stop object from: {} - error: {}", jsonSubscriptionStop, e.what()); return; } assert(publicationManager != nullptr); publicationManager->stopPublication(subscriptionId); }
void Dispatcher::handleBroadcastSubscriptionRequestReceived(const JoynrMessage& message) { JOYNR_LOG_TRACE(logger, "Starting handleBroadcastSubscriptionRequestReceived"); // Make sure that noone is registering a Caller at the moment, because a racing condition could // occour. std::lock_guard<std::mutex> lock(subscriptionHandlingMutex); assert(publicationManager != nullptr); std::string receiverId = message.getHeaderTo(); std::shared_ptr<RequestCaller> caller = requestCallerDirectory.lookup(receiverId); std::string jsonSubscriptionRequest = message.getPayload(); // PublicationManager is responsible for deleting SubscriptionRequests try { BroadcastSubscriptionRequest subscriptionRequest = JsonSerializer::deserialize<BroadcastSubscriptionRequest>(jsonSubscriptionRequest); if (!caller) { // Provider not registered yet // Dispatcher will call publicationManger->restore when a new provider is added to // activate // subscriptions for that provider publicationManager->add( message.getHeaderFrom(), message.getHeaderTo(), subscriptionRequest); } else { publicationManager->add(message.getHeaderFrom(), message.getHeaderTo(), caller, subscriptionRequest, messageSender); } } catch (const std::invalid_argument& e) { JOYNR_LOG_ERROR( logger, "Unable to deserialize broadcast subscription request object from: {} - error: {}", jsonSubscriptionRequest, e.what()); } }
void Dispatcher::handleRequestReceived(const JoynrMessage& message) { std::string senderId = message.getHeaderFrom(); std::string receiverId = message.getHeaderTo(); // json request // lookup necessary data std::string jsonRequest = message.getPayload(); std::shared_ptr<RequestCaller> caller = requestCallerDirectory.lookup(receiverId); if (caller == nullptr) { JOYNR_LOG_ERROR( logger, "caller not found in the RequestCallerDirectory for receiverId {}, ignoring", receiverId); return; } std::string interfaceName = caller->getInterfaceName(); // Get the request interpreter that has been registered with this interface name std::shared_ptr<IRequestInterpreter> requestInterpreter = InterfaceRegistrar::instance().getRequestInterpreter(interfaceName); // deserialize json try { Request request = JsonSerializer::deserialize<Request>(jsonRequest); std::string requestReplyId = request.getRequestReplyId(); JoynrTimePoint requestExpiryDate = message.getHeaderExpiryDate(); std::function<void(std::vector<Variant>)> onSuccess = [requestReplyId, requestExpiryDate, this, senderId, receiverId]( std::vector<Variant> returnValueVar) { Reply reply; reply.setRequestReplyId(requestReplyId); reply.setResponse(std::move(returnValueVar)); // send reply back to the original sender (ie. sender and receiver ids are reversed // on // purpose) JOYNR_LOG_DEBUG(logger, "Got reply from RequestInterpreter for requestReplyId {}", requestReplyId); JoynrTimePoint now = std::chrono::time_point_cast<std::chrono::milliseconds>( std::chrono::system_clock::now()); std::int64_t ttl = std::chrono::duration_cast<std::chrono::milliseconds>( requestExpiryDate - now).count(); messageSender->sendReply(receiverId, // receiver of the request is sender of reply senderId, // sender of request is receiver of reply MessagingQos(ttl), reply); }; std::function<void(const exceptions::JoynrException&)> onError = [requestReplyId, requestExpiryDate, this, senderId, receiverId]( const exceptions::JoynrException& exception) { Reply reply; reply.setRequestReplyId(requestReplyId); reply.setError(joynr::exceptions::JoynrExceptionUtil::createVariant(exception)); JOYNR_LOG_DEBUG(logger, "Got error reply from RequestInterpreter for requestReplyId {}", requestReplyId); JoynrTimePoint now = std::chrono::time_point_cast<std::chrono::milliseconds>( std::chrono::system_clock::now()); std::int64_t ttl = std::chrono::duration_cast<std::chrono::milliseconds>( requestExpiryDate - now).count(); messageSender->sendReply(receiverId, // receiver of the request is sender of reply senderId, // sender of request is receiver of reply MessagingQos(ttl), reply); }; // execute request requestInterpreter->execute(caller, request.getMethodName(), request.getParams(), request.getParamDatatypes(), onSuccess, onError); } catch (const std::invalid_argument& e) { JOYNR_LOG_ERROR(logger, "Unable to deserialize request object from: {} - error: {}", jsonRequest, e.what()); return; } }
void LongPollingMessageReceiver::run() { checkServerTime(); std::string createChannelUrl = bounceProxyUrl.getCreateChannelUrl(channelId).toString(); JOYNR_LOG_INFO(logger, "Running lpmr with channelId {}", channelId); std::shared_ptr<IHttpPostBuilder> createChannelRequestBuilder( HttpNetworking::getInstance()->createHttpPostBuilder(createChannelUrl)); std::shared_ptr<HttpRequest> createChannelRequest( createChannelRequestBuilder->addHeader("X-Atmosphere-tracking-id", receiverId) ->withContentType("application/json") ->withTimeout(settings.bounceProxyTimeout) ->build()); std::string channelUrl; while (channelUrl.empty() && !isInterrupted()) { JOYNR_LOG_DEBUG(logger, "sending create channel request"); HttpResult createChannelResult = createChannelRequest->execute(); if (createChannelResult.getStatusCode() == 201) { channelUrl = *createChannelResult.getHeaders().find("Location"); JOYNR_LOG_INFO(logger, "channel creation successfull; channel url: {}", channelUrl); channelCreatedSemaphore->notify(); } else { JOYNR_LOG_INFO(logger, "channel creation failed); status code: {}", createChannelResult.getStatusCode()); std::unique_lock<std::mutex> lock(interruptedMutex); interruptedWait.wait_for(lock, settings.createChannelRetryInterval); } } /** * register the channelUrl with the ChannelUrlDirectory (asynchronously) */ assert(channelUrlDirectory != nullptr); types::ChannelUrlInformation urlInformation; std::vector<std::string> urls = {channelUrl}; urlInformation.setUrls(urls); JOYNR_LOG_INFO( logger, "Adding channelId and Url of cluster controller to remote ChannelUrlDirectory {}", channelUrl); channelUrlDirectory->registerChannelUrlsAsync(channelId, urlInformation); while (!isInterrupted()) { std::shared_ptr<IHttpGetBuilder> longPollRequestBuilder( HttpNetworking::getInstance()->createHttpGetBuilder(channelUrl)); std::shared_ptr<HttpRequest> longPollRequest( longPollRequestBuilder->acceptGzip() ->addHeader("Accept", "application/json") ->addHeader("X-Atmosphere-tracking-id", receiverId) ->withTimeout(settings.longPollTimeout) ->build()); JOYNR_LOG_DEBUG(logger, "sending long polling request; url: {}", channelUrl); HttpResult longPollingResult = longPollRequest->execute(); if (!isInterrupted()) { // TODO: remove HttpErrorCodes and use constants. // there is a bug in atmosphere, which currently gives back 503 instead of 200 as a // result to longpolling. // Accepting 503 is a temporary workaround for this bug. As soon as atmosphere is fixed, // this should be removed // 200 does nott refect the state of the message body! It could be empty. if (longPollingResult.getStatusCode() == 200 || longPollingResult.getStatusCode() == 503) { Util::logSerializedMessage(logger, "long polling successful; contents: ", longPollingResult.getBody().data()); processReceivedInput(longPollingResult.getBody()); // Atmosphere currently cannot return 204 when a long poll times out, so this code // is currently never executed (2.2.2012) } else if (longPollingResult.getStatusCode() == 204) { JOYNR_LOG_DEBUG(logger, "long polling successfull);full; no data"); } else { std::string body("NULL"); if (!longPollingResult.getBody().isNull()) { body = QString(longPollingResult.getBody().data()).toStdString(); } JOYNR_LOG_ERROR(logger, "long polling failed; error message: {}; contents: {}", longPollingResult.getErrorMessage(), body); std::unique_lock<std::mutex> lock(interruptedMutex); interruptedWait.wait_for(lock, settings.createChannelRetryInterval); } } } }