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