1c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org/*
2c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
3c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org *
4c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org *  Use of this source code is governed by a BSD-style license
5c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org *  that can be found in the LICENSE file in the root of the source
6c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org *  tree. An additional intellectual property rights grant can be found
7c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org *  in the file PATENTS.  All contributing project authors may
8c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org */
10c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
11c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#include <string>
12c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
13c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#include "webrtc/base/gunit.h"
14c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#include "webrtc/base/ipaddress.h"
15c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#include "webrtc/base/socketstream.h"
16c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#include "webrtc/base/ssladapter.h"
17c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#include "webrtc/base/sslstreamadapter.h"
18b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund#include "webrtc/base/sslidentity.h"
19c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#include "webrtc/base/stream.h"
20c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#include "webrtc/base/virtualsocketserver.h"
21c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
22c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.orgstatic const int kTimeout = 5000;
23c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
24c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.orgstatic rtc::AsyncSocket* CreateSocket(const rtc::SSLMode& ssl_mode) {
25c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::SocketAddress address(rtc::IPAddress(INADDR_ANY), 0);
26c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
27c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::AsyncSocket* socket = rtc::Thread::Current()->
28c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      socketserver()->CreateAsyncSocket(
29c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      address.family(), (ssl_mode == rtc::SSL_MODE_DTLS) ?
30c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      SOCK_DGRAM : SOCK_STREAM);
31c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  socket->Bind(address);
32c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
33c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  return socket;
34c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org}
35c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
36c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.orgstatic std::string GetSSLProtocolName(const rtc::SSLMode& ssl_mode) {
37c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  return (ssl_mode == rtc::SSL_MODE_DTLS) ? "DTLS" : "TLS";
38c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org}
39c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
40c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.orgclass SSLAdapterTestDummyClient : public sigslot::has_slots<> {
41c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org public:
42c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  explicit SSLAdapterTestDummyClient(const rtc::SSLMode& ssl_mode)
43c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      : ssl_mode_(ssl_mode) {
44c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    rtc::AsyncSocket* socket = CreateSocket(ssl_mode_);
45c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
46c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ssl_adapter_.reset(rtc::SSLAdapter::Create(socket));
47c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
48a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_adapter_->SetMode(ssl_mode_);
49a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
50c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // Ignore any certificate errors for the purpose of testing.
51c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // Note: We do this only because we don't have a real certificate.
52c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // NEVER USE THIS IN PRODUCTION CODE!
53c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ssl_adapter_->set_ignore_bad_cert(true);
54c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
55c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ssl_adapter_->SignalReadEvent.connect(this,
56c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        &SSLAdapterTestDummyClient::OnSSLAdapterReadEvent);
57c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ssl_adapter_->SignalCloseEvent.connect(this,
58c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        &SSLAdapterTestDummyClient::OnSSLAdapterCloseEvent);
59c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
60c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
61a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  rtc::SocketAddress GetAddress() const {
62a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    return ssl_adapter_->GetLocalAddress();
63a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  }
64a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
65c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::AsyncSocket::ConnState GetState() const {
66c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    return ssl_adapter_->GetState();
67c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
68c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
69c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  const std::string& GetReceivedData() const {
70c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    return data_;
71c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
72c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
73c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  int Connect(const std::string& hostname, const rtc::SocketAddress& address) {
74a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    LOG(LS_INFO) << "Initiating connection with " << address;
75c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
76a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    int rv = ssl_adapter_->Connect(address);
77c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
78a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    if (rv == 0) {
79a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org      LOG(LS_INFO) << "Starting " << GetSSLProtocolName(ssl_mode_)
80a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org          << " handshake with " << hostname;
81c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
82a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org      if (ssl_adapter_->StartSSL(hostname.c_str(), false) != 0) {
83a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org        return -1;
84a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org      }
85a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    }
86a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
87a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    return rv;
88c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
89c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
90c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  int Close() {
91c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    return ssl_adapter_->Close();
92c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
93c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
94c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  int Send(const std::string& message) {
95c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    LOG(LS_INFO) << "Client sending '" << message << "'";
96c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
97c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    return ssl_adapter_->Send(message.data(), message.length());
98c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
99c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
100c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  void OnSSLAdapterReadEvent(rtc::AsyncSocket* socket) {
101c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    char buffer[4096] = "";
102c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
103c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // Read data received from the server and store it in our internal buffer.
104c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    int read = socket->Recv(buffer, sizeof(buffer) - 1);
105c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    if (read != -1) {
106c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      buffer[read] = '\0';
107c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
108c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      LOG(LS_INFO) << "Client received '" << buffer << "'";
109c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
110c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      data_ += buffer;
111c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    }
112c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
113c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
114c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  void OnSSLAdapterCloseEvent(rtc::AsyncSocket* socket, int error) {
115c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // OpenSSLAdapter signals handshake failure with a close event, but without
116c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // closing the socket! Let's close the socket here. This way GetState() can
117c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // return CS_CLOSED after failure.
118c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    if (socket->GetState() != rtc::AsyncSocket::CS_CLOSED) {
119c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      socket->Close();
120c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    }
121c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
122c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
123c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org private:
124c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  const rtc::SSLMode ssl_mode_;
125c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
126c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::scoped_ptr<rtc::SSLAdapter> ssl_adapter_;
127c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
128c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  std::string data_;
129c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org};
130c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
131c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.orgclass SSLAdapterTestDummyServer : public sigslot::has_slots<> {
132c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org public:
133b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  explicit SSLAdapterTestDummyServer(const rtc::SSLMode& ssl_mode,
1344e572470a3f181a043f9f9b98cc0153b7195b9f5torbjorng                                     const rtc::KeyParams& key_params)
135c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      : ssl_mode_(ssl_mode) {
136c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // Generate a key pair and a certificate for this host.
1374e572470a3f181a043f9f9b98cc0153b7195b9f5torbjorng    ssl_identity_.reset(rtc::SSLIdentity::Generate(GetHostname(), key_params));
138c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
139c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    server_socket_.reset(CreateSocket(ssl_mode_));
140c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
141a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    if (ssl_mode_ == rtc::SSL_MODE_TLS) {
142a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org      server_socket_->SignalReadEvent.connect(this,
143a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org          &SSLAdapterTestDummyServer::OnServerSocketReadEvent);
144c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
145a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org      server_socket_->Listen(1);
146a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    }
147c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
148c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    LOG(LS_INFO) << ((ssl_mode_ == rtc::SSL_MODE_DTLS) ? "UDP" : "TCP")
149c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        << " server listening on " << server_socket_->GetLocalAddress();
150c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
151c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
152c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::SocketAddress GetAddress() const {
153c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    return server_socket_->GetLocalAddress();
154c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
155c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
156c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  std::string GetHostname() const {
157c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // Since we don't have a real certificate anyway, the value here doesn't
158c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // really matter.
159c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    return "example.com";
160c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
161c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
162c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  const std::string& GetReceivedData() const {
163c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    return data_;
164c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
165c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
166c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  int Send(const std::string& message) {
167c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    if (ssl_stream_adapter_ == NULL
168c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        || ssl_stream_adapter_->GetState() != rtc::SS_OPEN) {
169c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      // No connection yet.
170c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      return -1;
171c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    }
172c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
173c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    LOG(LS_INFO) << "Server sending '" << message << "'";
174c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
175c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    size_t written;
176c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    int error;
177c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
178c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    rtc::StreamResult r = ssl_stream_adapter_->Write(message.data(),
179c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        message.length(), &written, &error);
180c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    if (r == rtc::SR_SUCCESS) {
181c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      return written;
182c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    } else {
183c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      return -1;
184c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    }
185c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
186c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
187a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  void AcceptConnection(const rtc::SocketAddress& address) {
188a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // Only a single connection is supported.
189a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ASSERT_TRUE(ssl_stream_adapter_ == NULL);
190c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
191a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // This is only for DTLS.
192a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ASSERT_EQ(rtc::SSL_MODE_DTLS, ssl_mode_);
193c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
194a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // Transfer ownership of the socket to the SSLStreamAdapter object.
195a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    rtc::AsyncSocket* socket = server_socket_.release();
196c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
197a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    socket->Connect(address);
198c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
199a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    DoHandshake(socket);
200a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  }
201c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
202a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  void OnServerSocketReadEvent(rtc::AsyncSocket* socket) {
203a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // Only a single connection is supported.
204a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ASSERT_TRUE(ssl_stream_adapter_ == NULL);
205c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
206a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    DoHandshake(server_socket_->Accept(NULL));
207c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
208c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
209c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  void OnSSLStreamAdapterEvent(rtc::StreamInterface* stream, int sig, int err) {
210c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    if (sig & rtc::SE_READ) {
211c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      char buffer[4096] = "";
212c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
213c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      size_t read;
214c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      int error;
215c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
216c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      // Read data received from the client and store it in our internal
217c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      // buffer.
218c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      rtc::StreamResult r = stream->Read(buffer,
219c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org          sizeof(buffer) - 1, &read, &error);
220c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      if (r == rtc::SR_SUCCESS) {
221c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        buffer[read] = '\0';
222c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
223c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        LOG(LS_INFO) << "Server received '" << buffer << "'";
224c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
225c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        data_ += buffer;
226c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      }
227c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    }
228c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
229c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
230c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org private:
231a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  void DoHandshake(rtc::AsyncSocket* socket) {
232a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    rtc::SocketStream* stream = new rtc::SocketStream(socket);
233a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
234a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_stream_adapter_.reset(rtc::SSLStreamAdapter::Create(stream));
235a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
236a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_stream_adapter_->SetMode(ssl_mode_);
237a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_stream_adapter_->SetServerRole();
238a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
239a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // SSLStreamAdapter is normally used for peer-to-peer communication, but
240a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // here we're testing communication between a client and a server
241a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // (e.g. a WebRTC-based application and an RFC 5766 TURN server), where
242a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // clients are not required to provide a certificate during handshake.
243a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // Accordingly, we must disable client authentication here.
244a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_stream_adapter_->set_client_auth_enabled(false);
245a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
246a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_stream_adapter_->SetIdentity(ssl_identity_->GetReference());
247a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
248a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    // Set a bogus peer certificate digest.
249a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    unsigned char digest[20];
250a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    size_t digest_len = sizeof(digest);
251a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_stream_adapter_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, digest,
252a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org        digest_len);
253a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
254a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_stream_adapter_->StartSSLWithPeer();
255a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
256a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    ssl_stream_adapter_->SignalEvent.connect(this,
257a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org        &SSLAdapterTestDummyServer::OnSSLStreamAdapterEvent);
258a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  }
259a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
260c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  const rtc::SSLMode ssl_mode_;
261c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
262c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::scoped_ptr<rtc::AsyncSocket> server_socket_;
263c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::scoped_ptr<rtc::SSLStreamAdapter> ssl_stream_adapter_;
264c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
265c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::scoped_ptr<rtc::SSLIdentity> ssl_identity_;
266c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
267c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  std::string data_;
268c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org};
269c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
270c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.orgclass SSLAdapterTestBase : public testing::Test,
271c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org                           public sigslot::has_slots<> {
272c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org public:
273b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  explicit SSLAdapterTestBase(const rtc::SSLMode& ssl_mode,
2744e572470a3f181a043f9f9b98cc0153b7195b9f5torbjorng                              const rtc::KeyParams& key_params)
275c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      : ssl_mode_(ssl_mode),
276c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        ss_scope_(new rtc::VirtualSocketServer(NULL)),
2774e572470a3f181a043f9f9b98cc0153b7195b9f5torbjorng        server_(new SSLAdapterTestDummyServer(ssl_mode_, key_params)),
278c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org        client_(new SSLAdapterTestDummyClient(ssl_mode_)),
279b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund        handshake_wait_(kTimeout) {}
280c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
281c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  void SetHandshakeWait(int wait) {
282c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    handshake_wait_ = wait;
283c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
284c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
285c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  void TestHandshake(bool expect_success) {
286c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    int rv;
287c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
288c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // The initial state is CS_CLOSED
289c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ASSERT_EQ(rtc::AsyncSocket::CS_CLOSED, client_->GetState());
290c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
291c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    rv = client_->Connect(server_->GetHostname(), server_->GetAddress());
292c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ASSERT_EQ(0, rv);
293c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
294c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // Now the state should be CS_CONNECTING
295c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ASSERT_EQ(rtc::AsyncSocket::CS_CONNECTING, client_->GetState());
296c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
297a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    if (ssl_mode_ == rtc::SSL_MODE_DTLS) {
298a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org      // For DTLS, call AcceptConnection() with the client's address.
299a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org      server_->AcceptConnection(client_->GetAddress());
300a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org    }
301a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
302c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    if (expect_success) {
303c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      // If expecting success, the client should end up in the CS_CONNECTED
304c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      // state after handshake.
305c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CONNECTED, client_->GetState(),
306c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org          handshake_wait_);
307c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
308c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake complete.";
309c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
310c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    } else {
311c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      // On handshake failure the client should end up in the CS_CLOSED state.
312c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CLOSED, client_->GetState(),
313c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org          handshake_wait_);
314c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
315c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org      LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake failed.";
316c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    }
317c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
318c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
319c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  void TestTransfer(const std::string& message) {
320c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    int rv;
321c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
322c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    rv = client_->Send(message);
323c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ASSERT_EQ(static_cast<int>(message.length()), rv);
324c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
325c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // The server should have received the client's message.
326c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    EXPECT_EQ_WAIT(message, server_->GetReceivedData(), kTimeout);
327c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
328c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    rv = server_->Send(message);
329c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    ASSERT_EQ(static_cast<int>(message.length()), rv);
330c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
331c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    // The client should have received the server's message.
332c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    EXPECT_EQ_WAIT(message, client_->GetReceivedData(), kTimeout);
333c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
334c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org    LOG(LS_INFO) << "Transfer complete.";
335c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  }
336c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
337c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org private:
338c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  const rtc::SSLMode ssl_mode_;
339c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
340c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  const rtc::SocketServerScope ss_scope_;
341c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
342c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::scoped_ptr<SSLAdapterTestDummyServer> server_;
343c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  rtc::scoped_ptr<SSLAdapterTestDummyClient> client_;
344c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
345c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  int handshake_wait_;
346c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org};
347c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
348b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlundclass SSLAdapterTestTLS_RSA : public SSLAdapterTestBase {
349b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund public:
350b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  SSLAdapterTestTLS_RSA()
3514e572470a3f181a043f9f9b98cc0153b7195b9f5torbjorng      : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KeyParams::RSA()) {}
352b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund};
353b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund
354b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlundclass SSLAdapterTestTLS_ECDSA : public SSLAdapterTestBase {
355c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org public:
356b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  SSLAdapterTestTLS_ECDSA()
3574e572470a3f181a043f9f9b98cc0153b7195b9f5torbjorng      : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KeyParams::ECDSA()) {}
358c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org};
359c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
360b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlundclass SSLAdapterTestDTLS_RSA : public SSLAdapterTestBase {
361a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org public:
362b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  SSLAdapterTestDTLS_RSA()
3634e572470a3f181a043f9f9b98cc0153b7195b9f5torbjorng      : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KeyParams::RSA()) {}
364b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund};
365b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund
366b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlundclass SSLAdapterTestDTLS_ECDSA : public SSLAdapterTestBase {
367b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund public:
368b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  SSLAdapterTestDTLS_ECDSA()
3694e572470a3f181a043f9f9b98cc0153b7195b9f5torbjorng      : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KeyParams::ECDSA()) {}
370a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org};
371c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
372c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org#if SSL_USE_OPENSSL
373c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
374c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org// Basic tests: TLS
375c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
376b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund// Test that handshake works, using RSA
377b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn GranlundTEST_F(SSLAdapterTestTLS_RSA, TestTLSConnect) {
378b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  TestHandshake(true);
379b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund}
380b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund
381b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund// Test that handshake works, using ECDSA
382b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn GranlundTEST_F(SSLAdapterTestTLS_ECDSA, TestTLSConnect) {
383b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  TestHandshake(true);
384b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund}
385b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund
386b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund// Test transfer between client and server, using RSA
387b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn GranlundTEST_F(SSLAdapterTestTLS_RSA, TestTLSTransfer) {
388c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  TestHandshake(true);
389b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  TestTransfer("Hello, world!");
390c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org}
391c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
392b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund// Test transfer between client and server, using ECDSA
393b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn GranlundTEST_F(SSLAdapterTestTLS_ECDSA, TestTLSTransfer) {
394c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  TestHandshake(true);
395c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org  TestTransfer("Hello, world!");
396c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org}
397c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
398a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org// Basic tests: DTLS
399a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
400b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund// Test that handshake works, using RSA
401b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn GranlundTEST_F(SSLAdapterTestDTLS_RSA, TestDTLSConnect) {
402b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  TestHandshake(true);
403b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund}
404b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund
405b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund// Test that handshake works, using ECDSA
406b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn GranlundTEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSConnect) {
407a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  TestHandshake(true);
408a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org}
409a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
410b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund// Test transfer between client and server, using RSA
411b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn GranlundTEST_F(SSLAdapterTestDTLS_RSA, TestDTLSTransfer) {
412a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  TestHandshake(true);
413a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org  TestTransfer("Hello, world!");
414a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org}
415a9b1ec024772564a190a4680cfa30414a5338cd4pthatcher@webrtc.org
416b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund// Test transfer between client and server, using ECDSA
417b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn GranlundTEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSTransfer) {
418b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  TestHandshake(true);
419b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund  TestTransfer("Hello, world!");
420b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund}
421c569a49a3dafdb5017961736c7715624dd059240tkchin@webrtc.org
422b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund#endif  // SSL_USE_OPENSSL
423