Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "jingle/glue/fake_socket_factory.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "jingle/glue/utils.h"
     10 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
     11 #include "third_party/libjingle/source/talk/base/asyncsocket.h"
     12 
     13 namespace jingle_glue {
     14 
     15 FakeUDPPacketSocket::FakeUDPPacketSocket(FakeSocketManager* fake_socket_manager,
     16                                          const net::IPEndPoint& address)
     17     : fake_socket_manager_(fake_socket_manager),
     18       endpoint_(address), state_(IS_OPEN), error_(0) {
     19   CHECK(IPEndPointToSocketAddress(endpoint_, &local_address_));
     20   fake_socket_manager_->AddSocket(this);
     21 }
     22 
     23 FakeUDPPacketSocket::~FakeUDPPacketSocket() {
     24   fake_socket_manager_->RemoveSocket(this);
     25 }
     26 
     27 talk_base::SocketAddress FakeUDPPacketSocket::GetLocalAddress() const {
     28   DCHECK(CalledOnValidThread());
     29   return local_address_;
     30 }
     31 
     32 talk_base::SocketAddress FakeUDPPacketSocket::GetRemoteAddress() const {
     33   DCHECK(CalledOnValidThread());
     34   return remote_address_;
     35 }
     36 
     37 int FakeUDPPacketSocket::Send(const void *data, size_t data_size,
     38                               talk_base::DiffServCodePoint dscp) {
     39   DCHECK(CalledOnValidThread());
     40   return SendTo(data, data_size, remote_address_, dscp);
     41 }
     42 
     43 int FakeUDPPacketSocket::SendTo(const void *data, size_t data_size,
     44                                 const talk_base::SocketAddress& address,
     45                                 talk_base::DiffServCodePoint dscp) {
     46   DCHECK(CalledOnValidThread());
     47 
     48   if (state_ == IS_CLOSED) {
     49     return ENOTCONN;
     50   }
     51 
     52   net::IPEndPoint destination;
     53   if (!SocketAddressToIPEndPoint(address, &destination)) {
     54     return EINVAL;
     55   }
     56 
     57   const char* data_char = reinterpret_cast<const char*>(data);
     58   std::vector<char> data_vector(data_char, data_char + data_size);
     59 
     60   fake_socket_manager_->SendPacket(endpoint_, destination, data_vector);
     61 
     62   return data_size;
     63 }
     64 
     65 int FakeUDPPacketSocket::Close() {
     66   DCHECK(CalledOnValidThread());
     67   state_ = IS_CLOSED;
     68   return 0;
     69 }
     70 
     71 talk_base::AsyncPacketSocket::State FakeUDPPacketSocket::GetState() const {
     72   DCHECK(CalledOnValidThread());
     73 
     74   switch (state_) {
     75     case IS_OPEN:
     76       return STATE_BOUND;
     77     case IS_CLOSED:
     78       return STATE_CLOSED;
     79   }
     80 
     81   NOTREACHED();
     82   return STATE_CLOSED;
     83 }
     84 
     85 int FakeUDPPacketSocket::GetOption(talk_base::Socket::Option opt, int* value) {
     86   DCHECK(CalledOnValidThread());
     87   return -1;
     88 }
     89 
     90 int FakeUDPPacketSocket::SetOption(talk_base::Socket::Option opt, int value) {
     91   DCHECK(CalledOnValidThread());
     92   return -1;
     93 }
     94 
     95 int FakeUDPPacketSocket::GetError() const {
     96   DCHECK(CalledOnValidThread());
     97   return error_;
     98 }
     99 
    100 void FakeUDPPacketSocket::SetError(int error) {
    101   DCHECK(CalledOnValidThread());
    102   error_ = error;
    103 }
    104 
    105 void FakeUDPPacketSocket::DeliverPacket(const net::IPEndPoint& from,
    106                                         const std::vector<char>& data) {
    107   DCHECK(CalledOnValidThread());
    108 
    109   talk_base::SocketAddress address;
    110   if (!jingle_glue::IPEndPointToSocketAddress(from, &address)) {
    111     // We should always be able to convert address here because we
    112     // don't expect IPv6 address on IPv4 connections.
    113     NOTREACHED();
    114     return;
    115   }
    116 
    117   SignalReadPacket(this, &data[0], data.size(), address,
    118                    talk_base::CreatePacketTime(0));
    119 }
    120 
    121 FakeSocketManager::FakeSocketManager()
    122     : message_loop_(base::MessageLoop::current()) {}
    123 
    124 FakeSocketManager::~FakeSocketManager() { }
    125 
    126 void FakeSocketManager::SendPacket(const net::IPEndPoint& from,
    127                                    const net::IPEndPoint& to,
    128                                    const std::vector<char>& data) {
    129   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    130 
    131   message_loop_->PostTask(
    132       FROM_HERE,
    133       base::Bind(&FakeSocketManager::DeliverPacket, this, from, to, data));
    134 }
    135 
    136 void FakeSocketManager::DeliverPacket(const net::IPEndPoint& from,
    137                                       const net::IPEndPoint& to,
    138                                       const std::vector<char>& data) {
    139   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    140 
    141   std::map<net::IPEndPoint, FakeUDPPacketSocket*>::iterator it =
    142       endpoints_.find(to);
    143   if (it == endpoints_.end()) {
    144     LOG(WARNING) << "Dropping packet with unknown destination: "
    145                  << to.ToString();
    146     return;
    147   }
    148   it->second->DeliverPacket(from, data);
    149 }
    150 
    151 void FakeSocketManager::AddSocket(FakeUDPPacketSocket* socket_factory) {
    152   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    153 
    154   endpoints_[socket_factory->endpoint()] = socket_factory;
    155 }
    156 
    157 void FakeSocketManager::RemoveSocket(FakeUDPPacketSocket* socket_factory) {
    158   DCHECK_EQ(base::MessageLoop::current(), message_loop_);
    159 
    160   endpoints_.erase(socket_factory->endpoint());
    161 }
    162 
    163 FakeSocketFactory::FakeSocketFactory(FakeSocketManager* socket_manager,
    164                                      const net::IPAddressNumber& address)
    165     : socket_manager_(socket_manager),
    166       address_(address),
    167       last_allocated_port_(0) {
    168 }
    169 
    170 FakeSocketFactory::~FakeSocketFactory() {
    171 }
    172 
    173 talk_base::AsyncPacketSocket* FakeSocketFactory::CreateUdpSocket(
    174     const talk_base::SocketAddress& local_address, int min_port, int max_port) {
    175   CHECK_EQ(min_port, 0);
    176   CHECK_EQ(max_port, 0);
    177   return new FakeUDPPacketSocket(
    178       socket_manager_.get(), net::IPEndPoint(address_, ++last_allocated_port_));
    179 }
    180 
    181 talk_base::AsyncPacketSocket* FakeSocketFactory::CreateServerTcpSocket(
    182     const talk_base::SocketAddress& local_address, int min_port, int max_port,
    183     int opts) {
    184   // TODO(sergeyu): Implement fake TCP sockets.
    185   NOTIMPLEMENTED();
    186   return NULL;
    187 }
    188 
    189 talk_base::AsyncPacketSocket* FakeSocketFactory::CreateClientTcpSocket(
    190     const talk_base::SocketAddress& local_address,
    191     const talk_base::SocketAddress& remote_address,
    192     const talk_base::ProxyInfo& proxy_info, const std::string& user_agent,
    193     int opts) {
    194   // TODO(sergeyu): Implement fake TCP sockets.
    195   NOTIMPLEMENTED();
    196   return NULL;
    197 }
    198 
    199 }  // namespace jingle_glue
    200