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