/* * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include #include #include #include #include #include #include #include #include #include #include #include namespace Swift { JingleSessionImpl::JingleSessionImpl(const JID& initiator, const JID& peerJID, const std::string& id, IQRouter* router) : JingleSession(initiator, id), iqRouter(router), peerJID(peerJID) { SWIFT_LOG(debug) << "initiator: " << initiator << ", peerJID: " << peerJID << std::endl; } void JingleSessionImpl::handleIncomingAction(JinglePayload::ref action) { if (action->getAction() == JinglePayload::SessionTerminate) { notifyListeners(&JingleSessionListener::handleSessionTerminateReceived, action->getReason()); return; } if (action->getAction() == JinglePayload::SessionInfo) { notifyListeners(&JingleSessionListener::handleSessionInfoReceived, action); return; } JingleContentPayload::ref content = action->getPayload(); if (!content) { SWIFT_LOG(debug) << "no content payload!" << std::endl; return; } JingleContentID contentID(content->getName(), content->getCreator()); JingleDescription::ref description = content->getDescriptions().empty() ? JingleDescription::ref() : content->getDescriptions()[0]; JingleTransportPayload::ref transport = content->getTransports().empty() ? JingleTransportPayload::ref() : content->getTransports()[0]; switch(action->getAction()) { case JinglePayload::SessionAccept: notifyListeners(&JingleSessionListener::handleSessionAcceptReceived, contentID, description, transport); return; case JinglePayload::TransportAccept: notifyListeners(&JingleSessionListener::handleTransportAcceptReceived, contentID, transport); return; case JinglePayload::TransportInfo: notifyListeners(&JingleSessionListener::handleTransportInfoReceived, contentID, transport); return; case JinglePayload::TransportReject: notifyListeners(&JingleSessionListener::handleTransportRejectReceived, contentID, transport); return; case JinglePayload::TransportReplace: notifyListeners(&JingleSessionListener::handleTransportReplaceReceived, contentID, transport); return; // following unused Jingle actions case JinglePayload::ContentAccept: case JinglePayload::ContentAdd: case JinglePayload::ContentModify: case JinglePayload::ContentReject: case JinglePayload::ContentRemove: case JinglePayload::DescriptionInfo: case JinglePayload::SecurityInfo: // handled elsewhere case JinglePayload::SessionInitiate: case JinglePayload::SessionInfo: case JinglePayload::SessionTerminate: case JinglePayload::UnknownAction: return; } assert(false); } void JingleSessionImpl::sendInitiate(const JingleContentID& id, JingleDescription::ref description, JingleTransportPayload::ref transport) { JinglePayload::ref payload = boost::make_shared(JinglePayload::SessionInitiate, getID()); payload->setInitiator(getInitiator()); JingleContentPayload::ref content = boost::make_shared(); content->setCreator(id.getCreator()); content->setName(id.getName()); content->addDescription(description); content->addTransport(transport); payload->addPayload(content); sendSetRequest(payload); } void JingleSessionImpl::sendTerminate(JinglePayload::Reason::Type reason) { JinglePayload::ref payload = boost::make_shared(JinglePayload::SessionTerminate, getID()); payload->setReason(JinglePayload::Reason(reason)); payload->setInitiator(getInitiator()); sendSetRequest(payload); } void JingleSessionImpl::sendInfo(boost::shared_ptr info) { JinglePayload::ref payload = boost::make_shared(JinglePayload::SessionInfo, getID()); payload->addPayload(info); sendSetRequest(payload); } void JingleSessionImpl::sendAccept(const JingleContentID& id, JingleDescription::ref description, JingleTransportPayload::ref transPayload) { JinglePayload::ref payload = createPayload(); JingleContentPayload::ref content = boost::make_shared(); content->setCreator(id.getCreator()); content->setName(id.getName()); content->addTransport(transPayload); content->addDescription(description); payload->setAction(JinglePayload::SessionAccept); payload->addPayload(content); // put into IQ:set and send it away sendSetRequest(payload); } void JingleSessionImpl::sendTransportAccept(const JingleContentID& id, JingleTransportPayload::ref transPayload) { JinglePayload::ref payload = createPayload(); JingleContentPayload::ref content = boost::make_shared(); content->setCreator(id.getCreator()); content->setName(id.getName()); content->addTransport(transPayload); payload->setAction(JinglePayload::TransportAccept); payload->addPayload(content); // put into IQ:set and send it away sendSetRequest(payload); } std::string JingleSessionImpl::sendTransportInfo(const JingleContentID& id, JingleTransportPayload::ref transPayload) { JinglePayload::ref payload = createPayload(); JingleContentPayload::ref content = boost::make_shared(); content->setCreator(id.getCreator()); content->setName(id.getName()); content->addTransport(transPayload); payload->setAction(JinglePayload::TransportInfo); payload->addPayload(content); return sendSetRequest(payload); } void JingleSessionImpl::sendTransportReject(const JingleContentID& id, JingleTransportPayload::ref transPayload) { JinglePayload::ref payload = createPayload(); JingleContentPayload::ref content = boost::make_shared(); content->setCreator(id.getCreator()); content->setName(id.getName()); content->addTransport(transPayload); payload->setAction(JinglePayload::TransportReject); payload->addPayload(content); sendSetRequest(payload); } void JingleSessionImpl::sendTransportReplace(const JingleContentID& id, JingleTransportPayload::ref transPayload) { JinglePayload::ref payload = createPayload(); JingleContentPayload::ref content = boost::make_shared(); content->setCreator(id.getCreator()); content->setName(id.getName()); content->addTransport(transPayload); payload->setAction(JinglePayload::TransportReplace); payload->addContent(content); sendSetRequest(payload); } std::string JingleSessionImpl::sendSetRequest(JinglePayload::ref payload) { boost::shared_ptr > request = boost::make_shared >( IQ::Set, peerJID, payload, iqRouter); pendingRequests.insert(std::make_pair( request, request->onResponse.connect(boost::bind(&JingleSessionImpl::handleRequestResponse, this, request)))); return request->send(); } JinglePayload::ref JingleSessionImpl::createPayload() const { JinglePayload::ref payload = boost::make_shared(); payload->setSessionID(getID()); payload->setInitiator(getInitiator()); return payload; } void JingleSessionImpl::handleRequestResponse(RequestRef request) { RequestsMap::iterator i = pendingRequests.find(request); assert(i != pendingRequests.end()); if (i->first->getPayloadGeneric()->getAction() == JinglePayload::TransportInfo) { notifyListeners(&JingleSessionListener::handleTransportInfoAcknowledged, i->first->getID()); } i->second.disconnect(); pendingRequests.erase(i); } }