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
FakeUDPPacketSocket(FakeSocketManager * fake_socket_manager,const net::IPEndPoint & address)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
~FakeUDPPacketSocket()23 FakeUDPPacketSocket::~FakeUDPPacketSocket() {
24 fake_socket_manager_->RemoveSocket(this);
25 }
26
GetLocalAddress() const27 talk_base::SocketAddress FakeUDPPacketSocket::GetLocalAddress() const {
28 DCHECK(CalledOnValidThread());
29 return local_address_;
30 }
31
GetRemoteAddress() const32 talk_base::SocketAddress FakeUDPPacketSocket::GetRemoteAddress() const {
33 DCHECK(CalledOnValidThread());
34 return remote_address_;
35 }
36
Send(const void * data,size_t data_size,talk_base::DiffServCodePoint dscp)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
SendTo(const void * data,size_t data_size,const talk_base::SocketAddress & address,talk_base::DiffServCodePoint dscp)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
Close()65 int FakeUDPPacketSocket::Close() {
66 DCHECK(CalledOnValidThread());
67 state_ = IS_CLOSED;
68 return 0;
69 }
70
GetState() const71 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
GetOption(talk_base::Socket::Option opt,int * value)85 int FakeUDPPacketSocket::GetOption(talk_base::Socket::Option opt, int* value) {
86 DCHECK(CalledOnValidThread());
87 return -1;
88 }
89
SetOption(talk_base::Socket::Option opt,int value)90 int FakeUDPPacketSocket::SetOption(talk_base::Socket::Option opt, int value) {
91 DCHECK(CalledOnValidThread());
92 return -1;
93 }
94
GetError() const95 int FakeUDPPacketSocket::GetError() const {
96 DCHECK(CalledOnValidThread());
97 return error_;
98 }
99
SetError(int error)100 void FakeUDPPacketSocket::SetError(int error) {
101 DCHECK(CalledOnValidThread());
102 error_ = error;
103 }
104
DeliverPacket(const net::IPEndPoint & from,const std::vector<char> & data)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
FakeSocketManager()121 FakeSocketManager::FakeSocketManager()
122 : message_loop_(base::MessageLoop::current()) {}
123
~FakeSocketManager()124 FakeSocketManager::~FakeSocketManager() { }
125
SendPacket(const net::IPEndPoint & from,const net::IPEndPoint & to,const std::vector<char> & data)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
DeliverPacket(const net::IPEndPoint & from,const net::IPEndPoint & to,const std::vector<char> & data)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
AddSocket(FakeUDPPacketSocket * socket_factory)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
RemoveSocket(FakeUDPPacketSocket * socket_factory)157 void FakeSocketManager::RemoveSocket(FakeUDPPacketSocket* socket_factory) {
158 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
159
160 endpoints_.erase(socket_factory->endpoint());
161 }
162
FakeSocketFactory(FakeSocketManager * socket_manager,const net::IPAddressNumber & address)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
~FakeSocketFactory()170 FakeSocketFactory::~FakeSocketFactory() {
171 }
172
CreateUdpSocket(const talk_base::SocketAddress & local_address,int min_port,int max_port)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
CreateServerTcpSocket(const talk_base::SocketAddress & local_address,int min_port,int max_port,int opts)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
CreateClientTcpSocket(const talk_base::SocketAddress & local_address,const talk_base::SocketAddress & remote_address,const talk_base::ProxyInfo & proxy_info,const std::string & user_agent,int opts)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