From 6d458439d9536be1736ba1a98c51040b64946284 Mon Sep 17 00:00:00 2001 From: dknn Date: Wed, 11 Jul 2012 18:06:01 +0200 Subject: Add disco for RTP + bugfix diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index c16d3b1..d907df6 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -124,7 +124,7 @@ void Client::handleConnected() { #ifdef SWIFT_EXPERIMENTAL_FT NetworkFactories *nf = getNetworkFactories(); fileTransferManager = new FileTransferManagerImpl(getJID(), jingleSessionManager, getIQRouter(), getEntityCapsProvider(), presenceOracle, nf->getConnectionFactory(), nf->getConnectionServerFactory(), nf->getTimerFactory(), nf->getNATTraverser()); - screenSharingManager = new ScreenSharingManagerImpl(getJID(), jingleSessionManager, getIQRouter(), nf->getUDPSocketFactory(), nf->getTimerFactory()); + screenSharingManager = new ScreenSharingManagerImpl(getJID(), jingleSessionManager, getIQRouter(), nf->getUDPSocketFactory(), nf->getTimerFactory(), presenceOracle, getEntityCapsProvider()); #else fileTransferManager = new DummyFileTransferManager(); #endif diff --git a/Swiften/Elements/DiscoInfo.cpp b/Swiften/Elements/DiscoInfo.cpp index 1683916..c20f989 100644 --- a/Swiften/Elements/DiscoInfo.cpp +++ b/Swiften/Elements/DiscoInfo.cpp @@ -23,6 +23,8 @@ const std::string DiscoInfo::JingleTransportsS5BFeature = std::string("urn:xmpp: const std::string DiscoInfo::Bytestream = std::string("http://jabber.org/protocol/bytestreams"); const std::string DiscoInfo::MessageDeliveryReceiptsFeature = std::string("urn:xmpp:receipts"); const std::string DiscoInfo::WhiteboardFeature = std::string("http://swift.im/whiteboard"); +const std::string DiscoInfo::JingleRTPFeature = std::string("urn:xmpp:jingle:apps:rtp:1"); +const std::string DiscoInfo::JingleTransportRawUDPFeature = std::string("urn:xmpp:jingle:transports:raw-udp:1"); bool DiscoInfo::Identity::operator<(const Identity& other) const { if (category_ == other.category_) { diff --git a/Swiften/Elements/DiscoInfo.h b/Swiften/Elements/DiscoInfo.h index 3334ac8..9ef3ab6 100644 --- a/Swiften/Elements/DiscoInfo.h +++ b/Swiften/Elements/DiscoInfo.h @@ -34,6 +34,8 @@ namespace Swift { static const std::string Bytestream; static const std::string MessageDeliveryReceiptsFeature; static const std::string WhiteboardFeature; + static const std::string JingleRTPFeature; + static const std::string JingleTransportRawUDPFeature; class Identity { public: diff --git a/Swiften/ScreenSharing/OutgoingScreenSharing.cpp b/Swiften/ScreenSharing/OutgoingScreenSharing.cpp index 3aa460c..da7eb3e 100644 --- a/Swiften/ScreenSharing/OutgoingScreenSharing.cpp +++ b/Swiften/ScreenSharing/OutgoingScreenSharing.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -21,8 +22,9 @@ namespace Swift { OutgoingScreenSharing::OutgoingScreenSharing(boost::shared_ptr session, UDPSocketFactory* udpSocketFactory, TimerFactory* timerFactory) : ScreenSharing(session, udpSocketFactory), contentID(JingleContentID(idGenerator.generateID(), JingleContentPayload::InitiatorCreator)), canceled(false), - sessionAccepted(false), socketConnected(false), timerFactory(timerFactory) + sessionAccepted(false), socketConnected(false), rtpSession(0), timerFactory(timerFactory) { + session->onSessionAcceptReceived.connect(boost::bind(&OutgoingScreenSharing::handleSessionAcceptReceived, this, _1, _2, _3)); } OutgoingScreenSharing::~OutgoingScreenSharing() @@ -43,7 +45,8 @@ void OutgoingScreenSharing::start() SWIFT_LOG(debug) << "Screen sharing: start" << std::endl; JingleRTPDescription::ref desc = boost::make_shared(JingleRTPDescription::Video); - desc->addPayloadType(RTPPayloadType(98, "VP8", 90000)); + payloadTypeUsed = RTPPayloadType(98, "VP8", 90000); + desc->addPayloadType(payloadTypeUsed); JingleRawUDPTransportPayload::ref transport = boost::make_shared(); addBestCandidate(transport); @@ -57,10 +60,9 @@ void OutgoingScreenSharing::start() void OutgoingScreenSharing::handleSocketConnected() { - SWIFT_LOG(debug) << "Screen sharing: UDP socket connected" << std::endl; - if (canceled) return; + SWIFT_LOG(debug) << "Screen sharing: UDP socket connected" << std::endl; socketConnected = true; if (sessionAccepted) @@ -69,10 +71,11 @@ void OutgoingScreenSharing::handleSocketConnected() void OutgoingScreenSharing::handleSessionAcceptReceived(const JingleContentID& /*id*/, boost::shared_ptr /*desc*/, boost::shared_ptr /*transport*/) { - SWIFT_LOG(debug) << "Screen sharing: accepted" << std::endl; - if (canceled) return; + SWIFT_LOG(debug) << "Screen sharing: accepted" << std::endl; + + // TODO: check desc and transport sessionAccepted = true; if (socketConnected) { @@ -97,9 +100,10 @@ void OutgoingScreenSharing::handleConnectionFailed() void OutgoingScreenSharing::startRTPSession() { - SWIFT_LOG(debug) << "Screen sharing: accepted and connect, start screen sharing" << std::endl; + SWIFT_LOG(debug) << "Screen sharing: accepted and connected, start sharing" << std::endl; // Session accepted and socket connected, we can start the rtp session + rtpSession = new RTPSessionImpl(serverSocket, payloadTypeUsed); } } diff --git a/Swiften/ScreenSharing/OutgoingScreenSharing.h b/Swiften/ScreenSharing/OutgoingScreenSharing.h index d93b476..c00d11e 100644 --- a/Swiften/ScreenSharing/OutgoingScreenSharing.h +++ b/Swiften/ScreenSharing/OutgoingScreenSharing.h @@ -8,6 +8,7 @@ #include #include +#include namespace Swift { class ConnectivityManager; @@ -15,6 +16,7 @@ namespace Swift { class JingleTransportPayload; class TimerFactory; class Timer; + class RTPSession; class OutgoingScreenSharing : public ScreenSharing { public: @@ -39,6 +41,8 @@ namespace Swift { bool canceled; bool sessionAccepted; bool socketConnected; + RTPSession* rtpSession; + RTPPayloadType payloadTypeUsed; TimerFactory* timerFactory; boost::shared_ptr connectionTimer; diff --git a/Swiften/ScreenSharing/RTPSession.h b/Swiften/ScreenSharing/RTPSession.h index bdb2861..4399b2d 100644 --- a/Swiften/ScreenSharing/RTPSession.h +++ b/Swiften/ScreenSharing/RTPSession.h @@ -14,19 +14,15 @@ namespace Swift { class UDPSocket; + class RTPPayloadType; class RTPSession { public: typedef boost::shared_ptr ref; - enum PayloadType { - VP8 = 98, - }; - public: virtual ~RTPSession() {} - virtual void create(boost::shared_ptr udpSocket, const HostAddressPort& remotePeer, PayloadType payloadType, int frequency) = 0; virtual void poll() = 0; virtual void checkIncomingPackets() = 0; virtual void sendPacket(const SafeByteArray& data, int timestampinc, bool marker = false) = 0; diff --git a/Swiften/ScreenSharing/RTPSessionImpl.cpp b/Swiften/ScreenSharing/RTPSessionImpl.cpp index eb67d4e..62b05d5 100644 --- a/Swiften/ScreenSharing/RTPSessionImpl.cpp +++ b/Swiften/ScreenSharing/RTPSessionImpl.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -22,33 +23,42 @@ namespace Swift { -RTPSessionImpl::RTPSessionImpl() - : RTPSession() -{ +bool Sender::SendRTP(const void *data, size_t len) { + send(data, len); + return true; } -RTPSessionImpl::~RTPSessionImpl() -{ +bool Sender::SendRTCP(const void* data, size_t len) { + send(data, len); + return true; } -void RTPSessionImpl::create(boost::shared_ptr udpSocket, const HostAddressPort &remotePeer, RTPSession::PayloadType payloadType, int frequency) -{ - this->udpSocket = udpSocket; - this->udpSocket->onDataRead.connect(boost::bind(&RTPSessionImpl::handleDataRead, this, _1)); +bool Sender::ComesFromThisSender (const jrtplib::RTPAddress* address) { + return RTPSessionImpl::nativeAddressToJRTPAddress(udpSocket->getLocalAddress()).IsSameAddress(address); +} - this->payloadType = payloadType; - this->frequency = frequency; - nativeAddressToJRTPAddress(remotePeer, jRTPRemotePeer); +void Sender::send(const void* data, size_t len) { + unsigned char *uint8Data = (unsigned char*)data; + udpSocket->send(SafeByteArray(uint8Data, uint8Data + len)); +} +RTPSessionImpl::RTPSessionImpl(boost::shared_ptr udpSocket, const RTPPayloadType &payloadType) + : udpSocket(udpSocket), payloadType(payloadType), jRTPRemotePeer(nativeAddressToJRTPAddress(udpSocket->getRemoteAddress())), sender(udpSocket) +{ jrtplib::RTPExternalTransmissionParams transparams(&sender, 0); - jrtplib::RTPSessionParams sessparams; // IMPORTANT: The local timestamp unit MUST be set, otherwise RTCP Sender Report info will be calculated wrong - sessparams.SetOwnTimestampUnit(1.0 / frequency); + sessparams.SetOwnTimestampUnit(1.0 / payloadType.getClockrate()); checkError(session.Create(sessparams, &transparams, jrtplib::RTPTransmitter::ExternalProto)); packetInjecter = static_cast(session.GetTransmissionInfo())->GetPacketInjector(); + + udpSocket->onDataRead.connect(boost::bind(&RTPSessionImpl::handleDataRead, this, _1)); +} + +RTPSessionImpl::~RTPSessionImpl() +{ } void RTPSessionImpl::poll() @@ -73,7 +83,7 @@ void RTPSessionImpl::checkIncomingPackets() void RTPSessionImpl::sendPacket(const SafeByteArray& data, int timestampinc, bool marker) { - checkError(session.SendPacket((void*)(&data[0]), data.size(), payloadType, marker, timestampinc)); + checkError(session.SendPacket((void*)(&data[0]), data.size(), payloadType.getID(), marker, timestampinc)); poll(); } @@ -101,7 +111,7 @@ void RTPSessionImpl::handleDataRead(boost::shared_ptr data) injectData(*data); } -void RTPSessionImpl::nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort, jrtplib::RTPIPv4Address& jRTPAddress) +jrtplib::RTPIPv4Address RTPSessionImpl::nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort) { // Split address std::vector subStrings; @@ -112,8 +122,7 @@ void RTPSessionImpl::nativeAddressToJRTPAddress(const HostAddressPort& hostAddre for (int i = 0; i < std::min(4, (int)subStrings.size()); ++i) ipNumbers[i] = boost::numeric_cast(boost::lexical_cast(subStrings[i])); - jRTPAddress.SetIP(ipNumbers); - jRTPAddress.SetPort(boost::numeric_cast(hostAddressPort.getPort())); + return jrtplib::RTPIPv4Address(ipNumbers, boost::numeric_cast(hostAddressPort.getPort())); } } diff --git a/Swiften/ScreenSharing/RTPSessionImpl.h b/Swiften/ScreenSharing/RTPSessionImpl.h index 657a34a..9bf08e5 100644 --- a/Swiften/ScreenSharing/RTPSessionImpl.h +++ b/Swiften/ScreenSharing/RTPSessionImpl.h @@ -7,6 +7,7 @@ #pragma once #include +#include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-parameter" @@ -16,26 +17,19 @@ #include namespace Swift { - // Temporary class - class Sender : public jrtplib::RTPExternalSender - { - public: - Sender() {} + class Sender : public jrtplib::RTPExternalSender { + public: + Sender(boost::shared_ptr udpSocket) : udpSocket(udpSocket) {} - virtual bool SendRTP (const void* /*data*/, size_t /*len*/) - { - return true; - } + virtual bool SendRTP(const void* data, size_t len); + virtual bool SendRTCP(const void* data, size_t len); + virtual bool ComesFromThisSender (const jrtplib::RTPAddress* address); - virtual bool SendRTCP (const void* /*data*/, size_t /*len*/) - { - return true; - } + private: + void send(const void* data, size_t len); - virtual bool ComesFromThisSender (const jrtplib::RTPAddress* /*address*/) - { - return false; - } + private: + boost::shared_ptr udpSocket; }; class RTPSessionImpl : public RTPSession { @@ -43,30 +37,28 @@ namespace Swift { typedef boost::shared_ptr ref; public: - RTPSessionImpl(); + RTPSessionImpl(boost::shared_ptr udpSocket, const RTPPayloadType& payloadType); virtual ~RTPSessionImpl(); - virtual void create(boost::shared_ptr udpSocket, const HostAddressPort &remotePeer, PayloadType payloadType, int frequency); virtual void poll(); virtual void checkIncomingPackets(); virtual void sendPacket(const SafeByteArray &data, int timestampinc, bool marker = false); virtual void injectData(const SafeByteArray &data); virtual void stop(int maxWaitMs = 100); - private: - static void nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort, jrtplib::RTPIPv4Address& jRTPAddress); + public: + static jrtplib::RTPIPv4Address nativeAddressToJRTPAddress(const HostAddressPort& hostAddressPort); private: - inline void checkError(int rtperr) const; + void checkError(int rtperr) const; void handleDataRead(boost::shared_ptr data); private: boost::shared_ptr udpSocket; - PayloadType payloadType; - int frequency; + RTPPayloadType payloadType; jrtplib::RTPIPv4Address jRTPRemotePeer; - jrtplib::RTPSession session; Sender sender; + jrtplib::RTPSession session; jrtplib::RTPExternalPacketInjecter *packetInjecter; }; } diff --git a/Swiften/ScreenSharing/ScreenSharing.cpp b/Swiften/ScreenSharing/ScreenSharing.cpp index fc7f672..532b73d 100644 --- a/Swiften/ScreenSharing/ScreenSharing.cpp +++ b/Swiften/ScreenSharing/ScreenSharing.cpp @@ -39,26 +39,26 @@ bool ScreenSharing::addBestCandidate(boost::shared_ptrcreateUDPSocket(); + serverSocket->bind(0); + + candidate.hostAddressPort = HostAddressPort(interface.getAddresses().front(), serverSocket->getLocalAddress().getPort()); candidate.type = JingleRawUDPTransportPayload::Candidate::Host; transport->addCandidate(candidate); - serverSocket = udpSocketFactory->createUDPSocket(); - serverSocket->bind(listeningPort); - return true; } } // else loopback for self sharing if (!interfaces.empty()) { - candidate.hostAddressPort = HostAddressPort(interfaces.front().getAddresses().front(), listeningPort); + serverSocket = udpSocketFactory->createUDPSocket(); + serverSocket->bind(0); + + candidate.hostAddressPort = HostAddressPort(interfaces.front().getAddresses().front(), serverSocket->getLocalAddress().getPort()); candidate.type = JingleRawUDPTransportPayload::Candidate::Host; transport->addCandidate(candidate); - serverSocket = udpSocketFactory->createUDPSocket(); - serverSocket->bind(listeningPort); - return true; } diff --git a/Swiften/ScreenSharing/ScreenSharing.h b/Swiften/ScreenSharing/ScreenSharing.h index 1f6f753..b1756b9 100644 --- a/Swiften/ScreenSharing/ScreenSharing.h +++ b/Swiften/ScreenSharing/ScreenSharing.h @@ -46,8 +46,6 @@ namespace Swift { bool addBestCandidate(boost::shared_ptr transport); protected: - static const int listeningPort = 28888; - IDGenerator idGenerator; boost::shared_ptr serverSocket; boost::shared_ptr clientSocket; diff --git a/Swiften/ScreenSharing/ScreenSharingManagerImpl.cpp b/Swiften/ScreenSharing/ScreenSharingManagerImpl.cpp index 4b88581..a747b81 100644 --- a/Swiften/ScreenSharing/ScreenSharingManagerImpl.cpp +++ b/Swiften/ScreenSharing/ScreenSharingManagerImpl.cpp @@ -6,14 +6,19 @@ #include +#include +#include +#include +#include #include #include namespace Swift { ScreenSharingManagerImpl::ScreenSharingManagerImpl(const JID& ownFullJID, JingleSessionManager *jingleSessionManager, IQRouter *iqRouter, - UDPSocketFactory* udpSocketFactory, TimerFactory* timerFactory) - : ownJID(ownFullJID)/*, jingleSM(jingleSessionManager), iqRouter(iqRouter), udpSocketFactory(udpSocketFactory), timerFactory(timerFactory)*/ + UDPSocketFactory* udpSocketFactory, TimerFactory* timerFactory, PresenceOracle* presenceOrable, + EntityCapsProvider* capsProvider) + : ownJID(ownFullJID)/*, jingleSM(jingleSessionManager), iqRouter(iqRouter), udpSocketFactory(udpSocketFactory), timerFactory(timerFactory)*/, capsProvider(capsProvider), presenceOracle(presenceOrable) { incomingSSManager = new IncomingScreenSharingManager(jingleSessionManager, iqRouter, udpSocketFactory); outgoingSSManager = new OutgoingScreenSharingManager(jingleSessionManager, iqRouter, udpSocketFactory, timerFactory); @@ -27,18 +32,38 @@ ScreenSharingManagerImpl::~ScreenSharingManagerImpl() boost::shared_ptr ScreenSharingManagerImpl::createOutgoingScreenSharing(const JID &to) { - JID receipient = to; - - if (receipient.isBare()) { - //boost::optional fullJID = highestPriorityJIDSupportingFileTransfer(receipient); - //if (fullJID.is_initialized()) { - // receipient = fullJID.get(); - //} else { - return boost::shared_ptr(); - //} + JID recipient = to; + + if (recipient.isBare()) { + boost::optional fullJID = highestPriorityJIDSupportingScreenSharing(recipient); + if (fullJID.is_initialized()) { + recipient = fullJID.get(); + } else { + return boost::shared_ptr(); + } + } + + return outgoingSSManager->createOutgoingScreenSharing(ownJID, recipient); +} + +boost::optional ScreenSharingManagerImpl::highestPriorityJIDSupportingScreenSharing(const JID& bareJID) { + int priority = INT_MIN; + JID fullRecipientJID; + + std::vector presences = presenceOracle->getAllPresence(bareJID); + foreach (Presence::ref pres, presences) { + if (pres->getPriority() > priority) { + DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom()); // look up caps from the jid + if (info && info->hasFeature(DiscoInfo::JingleFeature) + && info->hasFeature(DiscoInfo::JingleRTPFeature) + && info->hasFeature(DiscoInfo::JingleTransportRawUDPFeature)) { + priority = pres->getPriority(); + fullRecipientJID = pres->getFrom(); + } + } } - return outgoingSSManager->createOutgoingScreenSharing(ownJID, receipient); + return fullRecipientJID.isValid() ? boost::optional(fullRecipientJID) : boost::optional(); } } diff --git a/Swiften/ScreenSharing/ScreenSharingManagerImpl.h b/Swiften/ScreenSharing/ScreenSharingManagerImpl.h index 0075630..8e8ea78 100644 --- a/Swiften/ScreenSharing/ScreenSharingManagerImpl.h +++ b/Swiften/ScreenSharing/ScreenSharingManagerImpl.h @@ -16,16 +16,22 @@ namespace Swift { class IQRouter; class UDPSocketFactory; class TimerFactory; + class PresenceOracle; + class EntityCapsProvider; class ScreenSharingManagerImpl : public ScreenSharingManager { public: - ScreenSharingManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter *iqRouter, - UDPSocketFactory* udpSocketFactory, TimerFactory* timerFactory); + ScreenSharingManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* iqRouter, + UDPSocketFactory* udpSocketFactory, TimerFactory* timerFactory, PresenceOracle* presenceOrable, + EntityCapsProvider *capsProvider); virtual ~ScreenSharingManagerImpl(); virtual boost::shared_ptr createOutgoingScreenSharing(const JID& to); private: + boost::optional highestPriorityJIDSupportingScreenSharing(const JID &bareJID); + + private: IncomingScreenSharingManager* incomingSSManager; OutgoingScreenSharingManager* outgoingSSManager; @@ -35,5 +41,7 @@ namespace Swift { // IQRouter* iqRouter; // BoostUDPSocketFactory* udpSocketFactory; // TimerFactory* timerFactory; + EntityCapsProvider* capsProvider; + PresenceOracle* presenceOracle; }; } -- cgit v0.10.2-6-g49f6