michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Original author: ekr@rtfm.com michael@0: michael@0: // Some of this code is cut-and-pasted from nICEr. Copyright is: michael@0: michael@0: /* michael@0: Copyright (c) 2007, Adobe Systems, Incorporated michael@0: All rights reserved. michael@0: michael@0: Redistribution and use in source and binary forms, with or without michael@0: modification, are permitted provided that the following conditions are michael@0: met: michael@0: michael@0: * Redistributions of source code must retain the above copyright michael@0: notice, this list of conditions and the following disclaimer. michael@0: michael@0: * Redistributions in binary form must reproduce the above copyright michael@0: notice, this list of conditions and the following disclaimer in the michael@0: documentation and/or other materials provided with the distribution. michael@0: michael@0: * Neither the name of Adobe Systems, Network Resonance nor the names of its michael@0: contributors may be used to endorse or promote products derived from michael@0: this software without specific prior written permission. michael@0: michael@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: */ michael@0: michael@0: // This is a wrapper around the nICEr ICE stack michael@0: #ifndef nricemediastream_h__ michael@0: #define nricemediastream_h__ michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "sigslot.h" michael@0: michael@0: #include "mozilla/RefPtr.h" michael@0: #include "mozilla/Scoped.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIEventTarget.h" michael@0: #include "nsITimer.h" michael@0: michael@0: #include "m_cpp_utils.h" michael@0: michael@0: michael@0: namespace mozilla { michael@0: michael@0: typedef struct nr_ice_media_stream_ nr_ice_media_stream; michael@0: michael@0: class NrIceCtx; michael@0: michael@0: struct NrIceAddr { michael@0: std::string host; michael@0: uint16_t port; michael@0: std::string transport; michael@0: }; michael@0: michael@0: /* A summary of a candidate, for use in asking which candidate michael@0: pair is active */ michael@0: struct NrIceCandidate { michael@0: enum Type { michael@0: ICE_HOST, michael@0: ICE_SERVER_REFLEXIVE, michael@0: ICE_PEER_REFLEXIVE, michael@0: ICE_RELAYED michael@0: }; michael@0: michael@0: NrIceAddr cand_addr; michael@0: NrIceAddr local_addr; michael@0: Type type; michael@0: std::string codeword; michael@0: }; michael@0: michael@0: struct NrIceCandidatePair { michael@0: michael@0: enum State { michael@0: STATE_FROZEN, michael@0: STATE_WAITING, michael@0: STATE_IN_PROGRESS, michael@0: STATE_FAILED, michael@0: STATE_SUCCEEDED, michael@0: STATE_CANCELLED michael@0: }; michael@0: michael@0: State state; michael@0: uint64_t priority; michael@0: // Set regardless of who nominated it. Does not necessarily mean that it is michael@0: // ready to be selected (ie; nominated by peer, but our check has not michael@0: // succeeded yet.) Note: since this implementation uses aggressive nomination, michael@0: // when we are the controlling agent, this will always be set if the pair is michael@0: // in STATE_SUCCEEDED. michael@0: bool nominated; michael@0: // Set if this candidate pair has been selected. Note: Since we are using michael@0: // aggressive nomination, this could change frequently as ICE runs. michael@0: bool selected; michael@0: NrIceCandidate local; michael@0: NrIceCandidate remote; michael@0: // TODO(bcampen@mozilla.com): Is it important to put the foundation in here? michael@0: std::string codeword; michael@0: }; michael@0: michael@0: // Abstract base class for opaque values. michael@0: class NrIceOpaque { michael@0: public: michael@0: virtual ~NrIceOpaque() {} michael@0: }; michael@0: michael@0: class NrIceMediaStream { michael@0: public: michael@0: static RefPtr Create(NrIceCtx *ctx, michael@0: const std::string& name, michael@0: int components); michael@0: ~NrIceMediaStream(); michael@0: michael@0: enum State { ICE_CONNECTING, ICE_OPEN, ICE_CLOSED}; michael@0: michael@0: State state() const { return state_; } michael@0: michael@0: // The name of the stream michael@0: const std::string& name() const { return name_; } michael@0: michael@0: // Get all the candidates michael@0: std::vector GetCandidates() const; michael@0: michael@0: nsresult GetLocalCandidates(std::vector* candidates) const; michael@0: nsresult GetRemoteCandidates(std::vector* candidates) const; michael@0: michael@0: // Get all candidate pairs, whether in the check list or triggered check michael@0: // queue, in priority order. |out_pairs| is cleared before being filled. michael@0: nsresult GetCandidatePairs(std::vector* out_pairs) const; michael@0: michael@0: // Get the default candidate as host and port michael@0: nsresult GetDefaultCandidate(int component, std::string *host, int *port); michael@0: michael@0: // Parse remote attributes michael@0: nsresult ParseAttributes(std::vector& candidates); michael@0: michael@0: // Parse trickle ICE candidate michael@0: nsresult ParseTrickleCandidate(const std::string& candidate); michael@0: michael@0: // Disable a component michael@0: nsresult DisableComponent(int component); michael@0: michael@0: // Get the candidate pair currently active. It's the michael@0: // caller's responsibility to free these. michael@0: nsresult GetActivePair(int component, michael@0: NrIceCandidate** local, NrIceCandidate** remote); michael@0: michael@0: // The number of components michael@0: int components() const { return components_; } michael@0: michael@0: // The underlying nICEr stream michael@0: nr_ice_media_stream *stream() { return stream_; } michael@0: // Signals to indicate events. API users can (and should) michael@0: // register for these. michael@0: michael@0: // Send a packet michael@0: nsresult SendPacket(int component_id, const unsigned char *data, size_t len); michael@0: michael@0: // Set your state to ready. Called by the NrIceCtx; michael@0: void Ready(); michael@0: michael@0: // Close the stream. Called by the NrIceCtx. michael@0: // Different from the destructor because other people michael@0: // might be holding RefPtrs but we want those writes to fail once michael@0: // the context has been destroyed. michael@0: void Close(); michael@0: michael@0: // Set an opaque value. Owned by the media stream. michael@0: void SetOpaque(NrIceOpaque *opaque) { opaque_ = opaque; } michael@0: michael@0: // Get the opaque michael@0: NrIceOpaque* opaque() const { return opaque_; } michael@0: michael@0: sigslot::signal2 michael@0: SignalCandidate; // A new ICE candidate: michael@0: sigslot::signal1 SignalReady; // Candidate pair ready. michael@0: sigslot::signal1 SignalFailed; // Candidate pair failed. michael@0: sigslot::signal4 michael@0: SignalPacketReceived; // Incoming packet michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceMediaStream) michael@0: michael@0: private: michael@0: NrIceMediaStream(NrIceCtx *ctx, const std::string& name, michael@0: int components) : michael@0: state_(ICE_CONNECTING), michael@0: ctx_(ctx), michael@0: name_(name), michael@0: components_(components), michael@0: stream_(nullptr), michael@0: opaque_(nullptr) {} michael@0: michael@0: DISALLOW_COPY_ASSIGN(NrIceMediaStream); michael@0: michael@0: State state_; michael@0: NrIceCtx *ctx_; michael@0: const std::string name_; michael@0: const int components_; michael@0: nr_ice_media_stream *stream_; michael@0: ScopedDeletePtr opaque_; michael@0: }; michael@0: michael@0: michael@0: } // close namespace michael@0: #endif