/*
 * libjingle
 * Copyright 2004--2008, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// SecureTunnelSessionClient and SecureTunnelSession.
// SecureTunnelSessionClient extends TunnelSessionClient to exchange
// certificates as part of the session description.
// SecureTunnelSession is a TunnelSession that wraps the underlying
// tunnel stream into an SSLStreamAdapter.

#ifndef WEBRTC_LIBJINGLE_SESSION_TUNNEL_SECURETUNNELSESSIONCLIENT_H_
#define WEBRTC_LIBJINGLE_SESSION_TUNNEL_SECURETUNNELSESSIONCLIENT_H_

#include <string>

#include "webrtc/libjingle/session/tunnel/tunnelsessionclient.h"
#include "webrtc/base/sslidentity.h"
#include "webrtc/base/sslstreamadapter.h"

namespace cricket {

class SecureTunnelSession;  // below

// SecureTunnelSessionClient

// This TunnelSessionClient establishes secure tunnels protected by
// SSL/TLS. The PseudoTcpChannel stream is wrapped with an
// SSLStreamAdapter. An SSLIdentity must be set or generated.
//
// The TunnelContentDescription is extended to include the client and
// server certificates. The initiator acts as the client. The session
// initiate stanza carries a description that contains the client's
// certificate, and the session accept response's description has the
// server certificate added to it.

class SecureTunnelSessionClient : public TunnelSessionClient {
 public:
  // The jid is used as the name for sessions for outgoing tunnels.
  // manager is the SessionManager to which we register this client
  // and its sessions.
  SecureTunnelSessionClient(const buzz::Jid& jid, SessionManager* manager);

  // Configures this client to use a preexisting SSLIdentity.
  // The client takes ownership of the identity object.
  // Use either SetIdentity or GenerateIdentity, and only once.
  void SetIdentity(rtc::SSLIdentity* identity);

  // Generates an identity from nothing.
  // Returns true if generation was successful.
  // Use either SetIdentity or GenerateIdentity, and only once.
  bool GenerateIdentity();

  // Returns our identity for SSL purposes, as either set by
  // SetIdentity() or generated by GenerateIdentity(). Call this
  // method only after our identity has been successfully established
  // by one of those methods.
  rtc::SSLIdentity& GetIdentity() const;

  // Inherited methods
  virtual void OnIncomingTunnel(const buzz::Jid& jid, Session *session);
  virtual bool ParseContent(SignalingProtocol protocol,
                            const buzz::XmlElement* elem,
                            ContentDescription** content,
                            ParseError* error);
  virtual bool WriteContent(SignalingProtocol protocol,
                            const ContentDescription* content,
                            buzz::XmlElement** elem,
                            WriteError* error);
  virtual SessionDescription* CreateOffer(
      const buzz::Jid &jid, const std::string &description);
  virtual SessionDescription* CreateAnswer(
      const SessionDescription* offer);

 protected:
  virtual TunnelSession* MakeTunnelSession(
      Session* session, rtc::Thread* stream_thread,
      TunnelSessionRole role);

 private:
  // Our identity (key and certificate) for SSL purposes. The
  // certificate part will be communicated within the session
  // description. The identity will be passed to the SSLStreamAdapter
  // and used for SSL authentication.
  rtc::scoped_ptr<rtc::SSLIdentity> identity_;

  DISALLOW_EVIL_CONSTRUCTORS(SecureTunnelSessionClient);
};

// SecureTunnelSession:
// A TunnelSession represents one session for one client. It
// provides the actual tunnel stream and handles state changes.
// A SecureTunnelSession is a TunnelSession that wraps the underlying
// tunnel stream into an SSLStreamAdapter.

class SecureTunnelSession : public TunnelSession {
 public:
  // This TunnelSession will tie together the given client and session.
  // stream_thread is passed to the PseudoTCPChannel: it's the thread
  // designated to interact with the tunnel stream.
  // role is either INITIATOR or RESPONDER, depending on who is
  // initiating the session.
  SecureTunnelSession(SecureTunnelSessionClient* client, Session* session,
                      rtc::Thread* stream_thread,
                      TunnelSessionRole role);

  // Returns the stream that implements the actual P2P tunnel.
  // This may be called only once. Caller is responsible for freeing
  // the returned object.
  virtual rtc::StreamInterface* GetStream();

 protected:
  // Inherited method: callback on accepting a session.
  virtual void OnAccept();

  // Helper method for GetStream() that Instantiates the
  // SSLStreamAdapter to wrap the PseudoTcpChannel's stream, and
  // configures it with our identity and role.
  rtc::StreamInterface* MakeSecureStream(
      rtc::StreamInterface* stream);

  // Our role in requesting the tunnel: INITIATOR or
  // RESPONDER. Translates to our role in SSL negotiation:
  // respectively client or server. Also indicates which slot of the
  // SecureTunnelContentDescription our cert goes into: client-cert or
  // server-cert respectively.
  TunnelSessionRole role_;

  // This is the stream representing the usable tunnel endpoint.  It's
  // a StreamReference wrapping the SSLStreamAdapter instance, which
  // further wraps a PseudoTcpChannel::InternalStream. The
  // StreamReference is because in the case of CreateTunnel(), the
  // stream endpoint is returned early, but we need to keep a handle
  // on it so we can setup the peer certificate when we receive it
  // later.
  rtc::scoped_ptr<rtc::StreamReference> ssl_stream_reference_;

  DISALLOW_EVIL_CONSTRUCTORS(SecureTunnelSession);
};

}  // namespace cricket

#endif  // WEBRTC_LIBJINGLE_SESSION_TUNNEL_SECURETUNNELSESSIONCLIENT_H_
