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