Commits

Ivan Vučica committed 3a7ec0c

Attempted to copypaste tons of session code, while reducing XMPP and XML dependencies.

Comments (0)

Files changed (1)

libjingle-p2ponly.cpp

 #include <talk/p2p/base/session.h>
 #include <talk/p2p/base/sessionmanager.h>
 #include <talk/base/helpers.h> // talk_base::CreateRandomId
-
+#include <talk/base/logging.h> // LOG(), LS_ERROR
 
 cricket::P2PTransportChannel *p2pTransportChannel;
 cricket::HttpPortAllocator *httpPortAllocator;
 
 class libjinglep2ponlySession : public cricket::BaseSession
 {
+    
+public:
+    
+    
+    bool Initiate(const std::string &to,
+                  const cricket::SessionDescription* sdesc) 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        // c/p
+        
+        ASSERT(signaling_thread_->IsCurrent());
+        cricket::SessionError error;
+        
+        // Only from STATE_INIT
+        if (state_ != STATE_INIT)
+            return false;
+        
+        // Setup for signaling.
+        remote_name_ = to;
+        initiator_ = true;
+        set_local_description(sdesc);
+        if (!CreateTransportProxies(GetEmptyTransportInfos(sdesc->contents()),
+                                    &error)) {
+            LOG(LS_ERROR) << "Could not create transports: " << error.text;
+            return false;
+        }
+        
+        if (!SendInitiateMessage(sdesc, &error)) {
+            LOG(LS_ERROR) << "Could not send initiate message: " << error.text;
+            return false;
+        }
+        
+        SetState(cricket::Session::STATE_SENTINITIATE);
+        
+        SpeculativelyConnectAllTransportChannels();
+        return true;
+    }
+    
+    
+    
+    void OnIncomingMessage(const cricket::SessionMessage& msg) {
+        ASSERT(signaling_thread_->IsCurrent());
+        ASSERT(state_ == STATE_INIT || msg.from == remote_name_);
+        /*
+        if (current_protocol_== cricket::PROTOCOL_HYBRID) {
+            if (msg.protocol == cricket::PROTOCOL_GINGLE) {
+                current_protocol_ = cricket::PROTOCOL_GINGLE;
+            } else {
+                current_protocol_ = cricket::PROTOCOL_JINGLE;
+            }
+        }
+        */
+        bool valid = false;
+        cricket::MessageError error;
+        switch (msg.type) {
+            case cricket::ACTION_SESSION_INITIATE:
+                valid = OnInitiateMessage(msg, &error);
+                break;
+            case cricket::ACTION_SESSION_INFO:
+                valid = OnInfoMessage(msg);
+                break;
+            case cricket::ACTION_SESSION_ACCEPT:
+                valid = OnAcceptMessage(/*msg, &error*/);
+                break;
+            case cricket::ACTION_SESSION_REJECT:
+                valid = OnRejectMessage(msg, &error);
+                break;
+            case cricket::ACTION_SESSION_TERMINATE:
+                valid = OnTerminateMessage(msg, &error);
+                break;
+            case cricket::ACTION_TRANSPORT_INFO:
+                valid = OnTransportInfoMessage(msg, &error);
+                break;
+            case cricket::ACTION_TRANSPORT_ACCEPT:
+                valid = OnTransportAcceptMessage(msg, &error);
+                break;
+            case cricket::ACTION_NOTIFY:
+            case cricket::ACTION_UPDATE:
+                // TODO: Process these non-standard messages, but
+                // only once we figure out how in a jingle-specific way (or
+                // remove the need altogether).  For now, just don't send an
+                // error back, because it disrupts call establishment.
+                valid = true;
+                break;
+            default:
+                /*
+                 // TODO needed
+                valid = BadMessage(buzz::QN_STANZA_BAD_REQUEST,
+                                   "unknown session message type",
+                                   &error);
+                 */
+                break;
+        }
+        
+        if (valid) 
+        {
+            SendAcknowledgementMessage(/*msg.stanza*/);
+        } 
+        else 
+        {
+            /*
+             // TODO
+            SignalErrorMessage(this, msg.stanza, error.type,
+                               "modify", error.text, NULL);
+             */
+            printf("%s: Error message\n", __PRETTY_FUNCTION__);
+        }
+    }
+    
+
+
+    
+private:
 	virtual cricket::TransportChannel *CreateChannel(
                                              const std::string& content_name,
                                              const std::string& channel_name)
 		// TODO
 		return NULL;
 	}
-private:
+    
+    /////////////////
+    
+    
     libjinglep2ponlySession(libjinglep2ponlySessionManager *session_manager,
             const std::string& local_name, const std::string& initiator_name,
             const std::string& sid, const std::string& content_type
             SessionClient* client
              */
             );
-    // implemented below session manager, since we need to use a
-    // method from session manager to pass stuff to constructor
+    // above constructor is implemented below session manager, since
+    // we need to use a method from session manager to pass stuff to 
+    // the BaseSession constructor
+    
     friend class libjinglep2ponlySessionManager;
 
+    
+    cricket::TransportProxy* GetOrCreateTransportProxy(const std::string& content_name);
+    // also needs access into session manager, also implemented below
+    
+    cricket::TransportProxy* GetTransportProxy(const cricket::Transport* transport) 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        // c/p
+        for (cricket::TransportMap::iterator iter = transports_.begin();
+             iter != transports_.end(); ++iter) 
+        {
+            cricket::TransportProxy* transproxy = iter->second;
+            if (transproxy->impl() == transport) 
+            {
+                return transproxy;
+            }
+        }
+        return NULL;
+    }
+    
+    cricket::TransportProxy* GetTransportProxy(const std::string& content_name) 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        // c/p
+        cricket::TransportMap::iterator iter = transports_.find(content_name);
+        return (iter != transports_.end()) ? iter->second : NULL;
+    }
+
+    
+    void OnTransportConnecting(cricket::Transport* transport) {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        // c/p
+        // This is an indication that we should begin watching the writability
+        // state of the transport.
+        OnTransportWritable(transport);
+    }
+    
+    void OnTransportWritable(cricket::Transport* transport);
+    // defined below since it needs session manager
+    
+    void OnTransportRequestSignaling(cricket::Transport* transport) {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        // c/p
+        
+        ASSERT(signaling_thread_->IsCurrent());
+        SignalRequestSignaling(this);
+    }
+    
+    void OnTransportCandidatesReady(cricket::Transport* transport,
+                                    const cricket::Candidates& candidates) 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        // c/p
+        
+        ASSERT(signaling_thread_->IsCurrent());
+        cricket::TransportProxy* transproxy = GetTransportProxy(transport);
+        if (transproxy != NULL) {
+            if (!transproxy->negotiated()) {
+                transproxy->AddSentCandidates(candidates);
+            }
+            cricket::SessionError error;
+            if (!SendTransportInfoMessage(cricket::TransportInfo(transproxy->content_name(), transproxy->type(),
+                                                        candidates),
+                                          &error)) {
+                LOG(LS_ERROR) << "Could not send transport info message: "
+                << error.text;
+                return;
+            }
+        }
+    }
+    
+    void OnTransportSendError(cricket::Transport* transport,
+                                       const buzz::XmlElement* stanza,
+                                       const buzz::QName& name,
+                                       const std::string& type,
+                                       const std::string& text,
+                                       const buzz::XmlElement* extra_info) {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        // c/p
+        ASSERT(signaling_thread_->IsCurrent());
+        //SignalErrorMessage(this, stanza, name, type, text, extra_info);
+        
+    }
+    
+    void OnTransportChannelGone(cricket::Transport* transport,
+                                         const std::string& name) {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        // c/p
+        ASSERT(signaling_thread_->IsCurrent());
+        SignalChannelGone(this, name);
+    }
+    
+    
     libjinglep2ponlySessionManager* session_manager_;
     std::string initiator_name_;
     std::string content_type_;
     //cricket::TransportParser *transport_parser_;
     bool initiator_;
     std::string current_protocol_;
+    
+    cricket::TransportMap transports_;
+    bool allow_local_ips_;
+    
+    sigslot::signal1<libjinglep2ponlySession*> SignalRequestSignaling;  // When the session needs to send signaling messages, it beings by requesting signaling.  The client should handle this by calling OnSignalingReady once it is ready to send the messages. (These are called only by SessionManager.)
+    sigslot::signal2<libjinglep2ponlySession*, const std::string&> SignalChannelGone;   // Invoked when we notice that there is no matching channel on our peer.
+
+    
+    bool SendTransportInfoMessage(const cricket::TransportInfo& tinfo,
+                                  cricket::SessionError* error)
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+        return true;
+    }
+
+    
+    bool CreateTransportProxies(const cricket::TransportInfos& tinfos,
+                                cricket::SessionError* error) 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+
+        // c/p
+        for (cricket::TransportInfos::const_iterator tinfo = tinfos.begin();
+             tinfo != tinfos.end(); ++tinfo) {
+            if (tinfo->transport_type != transport_type_) {
+                error->SetText("No supported transport in offer.");
+                return false;
+            }
+            
+            GetOrCreateTransportProxy(tinfo->content_name);
+        }
+        return true;
+    }
+    
+    void SpeculativelyConnectAllTransportChannels() 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+
+        // c/p
+        for (cricket::TransportMap::iterator iter = transports_.begin(); iter != transports_.end(); ++iter) 
+        {
+            iter->second->SpeculativelyConnectChannels();
+        }
+    }
+    
+    
+    cricket::TransportInfos GetEmptyTransportInfos(const cricket::ContentInfos& contents) const 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+
+        // c/p
+        cricket::TransportInfos tinfos;
+        for (cricket::ContentInfos::const_iterator content = contents.begin(); content != contents.end(); ++content) 
+        {
+            tinfos.push_back(cricket::TransportInfo(content->name, transport_type_, cricket::Candidates()));
+        }
+        return tinfos;
+    }
+    
+    
+    bool SendInitiateMessage(const cricket::SessionDescription* sdesc,
+                             cricket::SessionError* error) 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+
+        // c/p
+        cricket::SessionInitiate init;
+        init.contents = sdesc->contents();
+        init.transports = GetEmptyTransportInfos(init.contents);
+        return SendMessage(cricket::ACTION_SESSION_INITIATE, init, error);
+    }
+    
+    
+    template <typename Action>
+    bool SendMessage(cricket::ActionType type, const Action& action,
+                              cricket::SessionError* error) 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+
+        // c/p
+        //talk_base::scoped_ptr<buzz::XmlElement> stanza(
+        //                                               new buzz::XmlElement(buzz::QN_IQ));
+        //if (!WriteActionMessage(type, action, stanza.get(), error))
+        //    return false;
+        
+        //SignalOutgoingMessage(this, stanza.get());
+        //return true;
+        
+        
+        return true;
+    }
+
+    void SendAcknowledgementMessage(/*const buzz::XmlElement* stanza*/) 
+    {
+        printf(" %s\n", __PRETTY_FUNCTION__);
+    }
+
+    //////////////////////////
+    
+    bool OnInitiateMessage(const cricket::SessionMessage& msg,
+                                    cricket::MessageError* error) {
+        if (!CheckState(STATE_INIT, error))
+            return false;
+        
+        cricket::SessionInitiate init;
+        if (!ParseSessionInitiate(msg.protocol, msg.action_elem,
+                                  GetContentParsers(), GetTransportParsers(),
+                                  &init, error))
+            return false;
+        
+        cricket::SessionError session_error;
+        if (!CreateTransportProxies(init.transports, &session_error)) {
+            printf("Stanza not acceptable: %s\n", session_error.text.c_str());
+            return false;
+            /*BadMessage(buzz::QN_STANZA_NOT_ACCEPTABLE,
+                              session_error.text, error);*/
+        }
+        
+        initiator_ = false;
+        remote_name_ = msg.from;
+        set_remote_description(new cricket::SessionDescription(init.ClearContents()));
+        SetState(STATE_RECEIVEDINITIATE);
+        
+        // Users of Session may listen to state change and call Reject().
+        if (state_ != STATE_SENTREJECT) {
+            if (!OnRemoteCandidates(init.transports/*, error*/))
+                return false;
+        }
+        return true;
+    }
+    
+    bool OnAcceptMessage(/*const cricket::SessionMessage& msg cricket::MessageError* error*/) {
+        /*
+         if (!CheckState(STATE_SENTINITIATE, error))
+            return false;
+         */
+        /*
+        cricket::SessionAccept accept;
+        if (!ParseSessionAccept(msg.protocol, msg.action_elem,
+                                GetContentParsers(), GetTransportParsers(),
+                                &accept, error))
+            return false;
+        
+        set_remote_description(new cricket::SessionDescription(accept.ClearContents()));
+        */
+        
+        cricket::TransportInfos transports;
+        // TODO these need to be filled and passed as argument of OnAcceptMessage
+        
+         SetState(STATE_RECEIVEDACCEPT);
+        
+        // Users of Session may listen to state change and call Reject().
+        if (state_ != STATE_SENTREJECT) {
+            if (!OnRemoteCandidates(/*accept.*/transports/*, error*/))
+                return false;
+        }
+        
+        return true;
+    }
+    
+    bool OnRejectMessage(const cricket::SessionMessage& msg, cricket::MessageError* error) {
+        if (!CheckState(STATE_SENTINITIATE, error))
+            return false;
+        
+        SetState(STATE_RECEIVEDREJECT);
+        return true;
+    }
+    
+    // Only used by app/win32/fileshare.cc.
+    bool OnInfoMessage(const cricket::SessionMessage& msg) {
+        //SignalInfoMessage(this, CopyOfXmlChildren(msg.action_elem));
+        return true;
+    }
+    
+    bool OnTerminateMessage(const cricket::SessionMessage& msg,
+                                     cricket::MessageError* error) {
+        /*
+        SessionTerminate term;
+        if (!ParseSessionTerminate(msg.protocol, msg.action_elem, &term, error))
+            return false;
+        
+        SignalReceivedTerminateReason(this, term.reason);
+         
+        if (term.debug_reason != buzz::STR_EMPTY) {
+            LOG(LS_VERBOSE) << "Received error on call: " << term.debug_reason;
+        }
+        
+        SetState(STATE_RECEIVEDTERMINATE);
+         */
+        return true;
+    }
+    
+    bool OnTransportInfoMessage(const cricket::SessionMessage& msg,
+                                         cricket::MessageError* error) {
+        cricket::TransportInfos tinfos;
+        /*
+        if (!ParseTransportInfos(msg.protocol, msg.action_elem,
+                                 initiator_description()->contents(),
+                                 GetTransportParsers(), &tinfos, error))
+            return false;
+        */
+        if (!OnRemoteCandidates(tinfos/*, error*/))
+            return false;
+        
+        return true;
+    }
+    
+    bool OnTransportAcceptMessage(const cricket::SessionMessage& msg,
+                                           cricket::MessageError* error) {
+        // TODO: Currently here only for compatibility with
+        // Gingle 1.1 clients (notably, Google Voice).
+        return true;
+    }
+
+    
+    
+    bool OnRemoteCandidates(const cricket::TransportInfos& tinfos/*, ParseError* error*/) {
+        for (cricket::TransportInfos::const_iterator tinfo = tinfos.begin();
+             tinfo != tinfos.end(); ++tinfo) {
+            cricket::TransportProxy* transproxy = GetTransportProxy(tinfo->content_name);
+            if (transproxy == NULL) {
+                //BadParse("Unknown content name: " + tinfo->content_name, error);
+                printf("Unknown content name: %s\n", tinfo->content_name.c_str());
+            }
+            
+            // Must complete negotiation before sending remote candidates, or
+            // there won't be any channel impls.
+            transproxy->CompleteNegotiation();
+            for (cricket::Candidates::const_iterator cand = tinfo->candidates.begin();
+                 cand != tinfo->candidates.end(); ++cand) {
+                if (!transproxy->impl()->VerifyCandidate(*cand, NULL/*error*/))
+                    return false;
+                
+                if (!transproxy->impl()->HasChannel(cand->name())) {
+                    /*
+                     buzz::XmlElement* extra_info =
+                     new buzz::XmlElement(QN_GINGLE_P2P_UNKNOWN_CHANNEL_NAME);
+                     extra_info->AddAttr(buzz::QN_NAME, cand->name());
+                     error->extra = extra_info;
+                     
+                     return BadParse("channel named in candidate does not exist: " +
+                     cand->name() + " for content: "+ tinfo->content_name,
+                     error);
+                     */
+                    
+                    printf("%s\n", (std::string() + "channel named in candidate does not exist: " +
+                            cand->name() + " for content: "+ tinfo->content_name).c_str());
+                }
+            }
+            transproxy->impl()->OnRemoteCandidates(tinfo->candidates);
+        }
+        
+        return true;
+    }
+
+
+    /////
+    bool CheckState(State state, cricket::MessageError* error) {
+        ASSERT(state_ == state);
+        if (state_ != state) {
+            /*
+            return BadMessage(buzz::QN_STANZA_NOT_ALLOWED,
+                              "message not allowed in current state",
+                              error);
+             */
+            printf("Message not allowed in current state\n");
+            return false;
+        }
+        return true;
+    }
+    cricket::ContentParserMap GetContentParsers() {
+        cricket::ContentParserMap parsers;
+        //parsers[content_type_] = client_;
+        return parsers;
+    }
+    cricket::TransportParserMap GetTransportParsers() {
+        cricket::TransportParserMap parsers;
+        //parsers[transport_type_] = transport_parser_;
+        return parsers;
+    }
+
+    
+
 };
 
+
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+
+
 class libjinglep2ponlySessionManager 
 // cannot be derived from SessionManager since our CreateSession
 // needs to return a BaseSession-derived class, not a
         } else {
             worker_thread_ = worker_thread;
         }
-        timeout_ = 50;
+        timeout_ = 5; //50;
     }
     virtual ~libjinglep2ponlySessionManager()
     {
                             const std::string& text,
                             const buzz::XmlElement* extra_info);
      */
+
 };
 
 libjinglep2ponlySession::libjinglep2ponlySession(libjinglep2ponlySessionManager *session_manager,
                          */
                         ) : cricket::BaseSession(session_manager->signaling_thread())
 {
+    printf(" %s\n", __PRETTY_FUNCTION__);
+    // c/p
+    
     ASSERT(session_manager->signaling_thread()->IsCurrent());
     ASSERT(client != NULL);
     session_manager_ = session_manager;
     current_protocol_ = cricket::PROTOCOL_HYBRID;
 
 }
+cricket::TransportProxy* libjinglep2ponlySession::GetOrCreateTransportProxy(const std::string& content_name)
+{
+    printf(" %s\n", __PRETTY_FUNCTION__);
+    // c/p
+    cricket::TransportProxy* transproxy = GetTransportProxy(content_name);
+    if (transproxy)
+        return transproxy;
+    
+    cricket::Transport* transport = new cricket::P2PTransport(signaling_thread_,
+                                                              session_manager_->worker_thread(),
+                                                              session_manager_->port_allocator());
+    transport->set_allow_local_ips(allow_local_ips_);
+    transport->SignalConnecting.connect(this, &libjinglep2ponlySession::OnTransportConnecting);
+    transport->SignalWritableState.connect(this, &libjinglep2ponlySession::OnTransportWritable);
+    transport->SignalRequestSignaling.connect(this, &libjinglep2ponlySession::OnTransportRequestSignaling);
+    transport->SignalCandidatesReady.connect(this, &libjinglep2ponlySession::OnTransportCandidatesReady);
+    transport->SignalTransportError.connect(this, &libjinglep2ponlySession::OnTransportSendError);
+    transport->SignalChannelGone.connect(this, &libjinglep2ponlySession::OnTransportChannelGone);
+    
+    transproxy = new cricket::TransportProxy(content_name, transport);
+    transports_[content_name] = transproxy;
+    
+    return transproxy;
+}
 
-
-
+void libjinglep2ponlySession::OnTransportWritable(cricket::Transport* transport)
+{
+    printf(" %s\n", __PRETTY_FUNCTION__);
+    // c/p
+    
+    ASSERT(signaling_thread_->IsCurrent());
+    
+    // If the transport is not writable, start a timer to make sure that it
+    // becomes writable within a reasonable amount of time.  If it does not, we
+    // terminate since we can't actually send data.  If the transport is writable,
+    // cancel the timer.  Note that writability transitions may occur repeatedly
+    // during the lifetime of the session.
+    signaling_thread_->Clear(this, /*MSG_TIMEOUT*/ 1);
+    if (transport->HasChannels() && !transport->writable()) {
+        signaling_thread_->PostDelayed(
+                                       session_manager_->session_timeout() * 1000, this, /*MSG_TIMEOUT*/ 1);
+    }
+}
 
 libjinglep2ponlySessionManager *sessionManager = NULL;
-
+libjinglep2ponlySession *session = NULL;
 int main()
 {
     networkManager = new talk_base::NetworkManager();
     //p2pTransportChannel = new cricket::P2PTransportChannel("Kanal", "sadrzaj", p2pTransport, httpPortAllocator);
     sessionManager = new libjinglep2ponlySessionManager(httpPortAllocator);
     
-    sessionManager->CreateSession("Local Session Name", "test-type");
+    session = sessionManager->CreateSession("Local Session Name", "test-type");
+    cricket::SessionDescription sessionDescription;
+    
+    session->Initiate("destination", &sessionDescription);
+    cricket::SessionMessage m;
+    m.type = cricket::ACTION_SESSION_ACCEPT;
+    session->OnIncomingMessage(m);
+    while(1)
+    {
+    
+    }
 	return 0;
 }