// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef REMOTING_JINGLE_GLUE_JINGLE_CHANNEL_H_ #define REMOTING_JINGLE_GLUE_JINGLE_CHANNEL_H_ #include #include #include "base/basictypes.h" #include "base/condition_variable.h" #include "base/gtest_prod_util.h" #include "base/lock.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/task.h" #include "third_party/libjingle/source/talk/base/sigslot.h" namespace base { class WaitableEvent; } // namespace base namespace talk_base { class StreamInterface; } // namespace talk_base namespace media { class Buffer; class DataBuffer; } // namespace media namespace remoting { class JingleThread; class JingleChannel : public base::RefCountedThreadSafe { public: enum State { INITIALIZING, CONNECTING, OPEN, CLOSED, FAILED, }; class Callback { public: virtual ~Callback() {} // Called when state of the connection is changed. virtual void OnStateChange(JingleChannel* channel, State state) = 0; // Called when a new packet is received. virtual void OnPacketReceived(JingleChannel* channel, scoped_refptr data) = 0; }; virtual ~JingleChannel(); // Puts data to the write buffer. virtual void Write(scoped_refptr data); // Closes the tunnel. If specified, |closed_task| is executed after the // connection is successfully closed. virtual void Close(); virtual void Close(Task* closed_task); // Current state of the tunnel. State state() const { return state_; } // JID of the other end of the channel. const std::string& jid() const { return jid_; } // Number of bytes currently stored in the write buffer. size_t write_buffer_size(); protected: // Needs access to constructor, Init(). friend class JingleClient; // Constructor used by unit test only. // TODO(hclam): Have to suppress warnings in MSVC. JingleChannel(); // Used by JingleClient to create an instance of the channel. |callback| // must not be NULL. explicit JingleChannel(Callback* callback); // Initialized the channel. Ownership of the |stream| is transfered to // caller. Ownership of |thread| is not. void Init(JingleThread* thread, talk_base::StreamInterface* stream, const std::string& jid); private: friend class JingleChannelTest; FRIEND_TEST_ALL_PREFIXES(JingleChannelTest, Init); FRIEND_TEST_ALL_PREFIXES(JingleChannelTest, Write); FRIEND_TEST_ALL_PREFIXES(JingleChannelTest, Read); typedef std::deque > DataQueue; // Event handler for the stream. It passes stream events from the stream // to JingleChannel. class EventHandler : public sigslot::has_slots<> { protected: explicit EventHandler(JingleChannel* channel) : channel_(channel) {} // Constructor used only by unit test. EventHandler() : channel_(NULL) {} void OnStreamEvent(talk_base::StreamInterface* stream, int events, int error) { channel_->OnStreamEvent(stream, events, error); } private: friend class JingleChannel; JingleChannel* channel_; }; friend class EventHandler; // Event handler for the stream. void OnStreamEvent(talk_base::StreamInterface* stream, int events, int error); // Writes data from the buffer to the stream. Called // from OnStreamEvent() in the jingle thread. void DoWrite(); // Reads data from the stream and puts it to the read buffer. // Called from OnStreamEvent() in the jingle thread. void DoRead(); // Used by Close() to actually close the channel. void DoClose(); // Updates state and calels |callback_| if neccessary. void SetState(State new_state); // The thread this channel runs on. JingleThread* thread_; // The stream of this channel. scoped_ptr stream_; // Current state of the channel. State state_; // Callback that is called on channel events. Initialized in the constructor. // Must not be called if |closed_| is set to true. Callback* callback_; // |closed_| must be set to true after Close() is called. |state_lock_| must // be locked whenever closed_ is accessed. Lock state_lock_; bool closed_; scoped_ptr closed_task_; // Event handler for stream events. EventHandler event_handler_; // Jid of the other end of the channel. std::string jid_; // Write buffer. |write_lock_| should be locked when accessing |write_queue_| // and |write_buffer_size_|, but isn't necessary for |current_write_buf_|. // |current_write_buf_| is accessed only by the jingle thread. // |write_buffer_size_| stores number of bytes currently in |write_queue_| // and in |current_write_buf_|. DataQueue write_queue_; size_t write_buffer_size_; Lock write_lock_; scoped_refptr current_write_buf_; size_t current_write_buf_pos_; DISALLOW_COPY_AND_ASSIGN(JingleChannel); }; } // namespace remoting #endif // REMOTING_JINGLE_GLUE_JINGLE_CHANNEL_H_