1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/renderer_host/p2p_sockets_host.h"
#include "content/browser/renderer_host/p2p_socket_host.h"
#include "content/common/p2p_messages.h"
namespace {
// This function returns address of the first IPv4 enabled network
// interface it finds. This address is used for all sockets.
//
// TODO(sergeyu): This approach works only in the simplest case when
// host has only one network connection. Instead of binding all
// connections to this interface we must provide list of interfaces to
// the renderer, and let the PortAllocater in the renderer process
// choose local address.
bool GetLocalAddress(net::IPEndPoint* addr) {
net::NetworkInterfaceList networks;
if (!GetNetworkList(&networks))
return false;
for (net::NetworkInterfaceList::iterator it = networks.begin();
it != networks.end(); ++it) {
if (it->address.size() == net::kIPv4AddressSize) {
*addr = net::IPEndPoint(it->address, 0);
return true;
}
}
return false;
}
} // namespace
P2PSocketsHost::P2PSocketsHost() {
}
P2PSocketsHost::~P2PSocketsHost() {
}
void P2PSocketsHost::OnChannelClosing() {
BrowserMessageFilter::OnChannelClosing();
// Since the IPC channel is gone, close pending connections.
for (IDMap<P2PSocketHost, IDMapOwnPointer>::iterator i(&sockets_);
!i.IsAtEnd(); i.Advance()) {
sockets_.Remove(i.GetCurrentKey());
}
}
void P2PSocketsHost::OnDestruct() const {
BrowserThread::DeleteOnIOThread::Destruct(this);
}
bool P2PSocketsHost::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(P2PSocketsHost, message, *message_was_ok)
IPC_MESSAGE_HANDLER(P2PHostMsg_CreateSocket, OnCreateSocket)
IPC_MESSAGE_HANDLER(P2PHostMsg_Send, OnSend)
IPC_MESSAGE_HANDLER(P2PHostMsg_DestroySocket, OnDestroySocket)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
return handled;
}
void P2PSocketsHost::OnCreateSocket(
const IPC::Message& msg, P2PSocketType type, int socket_id,
const net::IPEndPoint& remote_address) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
NewRunnableMethod(this, &P2PSocketsHost::GetLocalAddressAndCreateSocket,
msg.routing_id(), type, socket_id, remote_address));
}
void P2PSocketsHost::GetLocalAddressAndCreateSocket(
int routing_id, P2PSocketType type, int socket_id,
const net::IPEndPoint& remote_address) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
net::IPEndPoint local_address;
if (!GetLocalAddress(&local_address)) {
LOG(ERROR) << "Failed to get local network address.";
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(this, &P2PSocketsHost::Send,
new P2PMsg_OnError(routing_id, socket_id)));
return;
}
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(this, &P2PSocketsHost::FinishCreateSocket, routing_id,
local_address, type, socket_id, remote_address));
}
void P2PSocketsHost::FinishCreateSocket(
int routing_id, const net::IPEndPoint& local_address, P2PSocketType type,
int socket_id, const net::IPEndPoint& remote_address) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (sockets_.Lookup(socket_id)) {
LOG(ERROR) << "Received P2PHostMsg_CreateSocket for socket "
"that already exists.";
return;
}
if (type != P2P_SOCKET_UDP) {
Send(new P2PMsg_OnError(routing_id, socket_id));
return;
}
scoped_ptr<P2PSocketHost> socket(
P2PSocketHost::Create(this, routing_id, socket_id, type));
if (!socket.get()) {
Send(new P2PMsg_OnError(routing_id, socket_id));
return;
}
if (socket->Init(local_address)) {
sockets_.AddWithID(socket.release(), socket_id);
}
}
void P2PSocketsHost::OnSend(const IPC::Message& msg, int socket_id,
const net::IPEndPoint& socket_address,
const std::vector<char>& data) {
P2PSocketHost* socket = sockets_.Lookup(socket_id);
if (!socket) {
LOG(ERROR) << "Received P2PHostMsg_Send for invalid socket_id.";
return;
}
socket->Send(socket_address, data);
}
void P2PSocketsHost::OnDestroySocket(const IPC::Message& msg, int socket_id) {
sockets_.Remove(socket_id);
}
|