socket_dispatcher.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1// Copyright (c) 2012 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 "content/renderer/p2p/socket_dispatcher.h"
6
7#include "base/bind.h"
8#include "base/memory/ref_counted.h"
9#include "base/message_loop/message_loop_proxy.h"
10#include "content/child/child_process.h"
11#include "content/common/p2p_messages.h"
12#include "content/renderer/p2p/host_address_request.h"
13#include "content/renderer/p2p/socket_client.h"
14#include "content/renderer/render_view_impl.h"
15#include "webkit/glue/network_list_observer.h"
16
17namespace content {
18
19P2PSocketDispatcher::P2PSocketDispatcher(
20    base::MessageLoopProxy* ipc_message_loop)
21    : message_loop_(ipc_message_loop),
22      network_notifications_started_(false),
23      network_list_observers_(
24          new ObserverListThreadSafe<webkit_glue::NetworkListObserver>()),
25      channel_(NULL) {
26}
27
28P2PSocketDispatcher::~P2PSocketDispatcher() {
29  network_list_observers_->AssertEmpty();
30  for (IDMap<P2PSocketClient>::iterator i(&clients_); !i.IsAtEnd();
31       i.Advance()) {
32    i.GetCurrentValue()->Detach();
33  }
34}
35
36void P2PSocketDispatcher::AddNetworkListObserver(
37    webkit_glue::NetworkListObserver* network_list_observer) {
38  network_list_observers_->AddObserver(network_list_observer);
39  network_notifications_started_ = true;
40  SendP2PMessage(new P2PHostMsg_StartNetworkNotifications());
41}
42
43void P2PSocketDispatcher::RemoveNetworkListObserver(
44    webkit_glue::NetworkListObserver* network_list_observer) {
45  network_list_observers_->RemoveObserver(network_list_observer);
46}
47
48void P2PSocketDispatcher::Send(IPC::Message* message) {
49  DCHECK(message_loop_->BelongsToCurrentThread());
50  if (!channel_) {
51    DLOG(WARNING) << "P2PSocketDispatcher::Send() - Channel closed.";
52    delete message;
53    return;
54  }
55
56  channel_->Send(message);
57}
58
59bool P2PSocketDispatcher::OnMessageReceived(const IPC::Message& message) {
60  bool handled = true;
61  IPC_BEGIN_MESSAGE_MAP(P2PSocketDispatcher, message)
62    IPC_MESSAGE_HANDLER(P2PMsg_NetworkListChanged, OnNetworkListChanged)
63    IPC_MESSAGE_HANDLER(P2PMsg_GetHostAddressResult, OnGetHostAddressResult)
64    IPC_MESSAGE_HANDLER(P2PMsg_OnSocketCreated, OnSocketCreated)
65    IPC_MESSAGE_HANDLER(P2PMsg_OnIncomingTcpConnection, OnIncomingTcpConnection)
66    IPC_MESSAGE_HANDLER(P2PMsg_OnSendComplete, OnSendComplete)
67    IPC_MESSAGE_HANDLER(P2PMsg_OnError, OnError)
68    IPC_MESSAGE_HANDLER(P2PMsg_OnDataReceived, OnDataReceived)
69    IPC_MESSAGE_UNHANDLED(handled = false)
70  IPC_END_MESSAGE_MAP()
71  return handled;
72}
73
74void P2PSocketDispatcher::OnFilterAdded(IPC::Channel* channel) {
75  DVLOG(1) << "P2PSocketDispatcher::OnFilterAdded()";
76  channel_ = channel;
77}
78
79void P2PSocketDispatcher::OnFilterRemoved() {
80  channel_ = NULL;
81}
82
83void P2PSocketDispatcher::OnChannelClosing() {
84  channel_ = NULL;
85}
86
87base::MessageLoopProxy* P2PSocketDispatcher::message_loop() {
88  return message_loop_.get();
89}
90
91int P2PSocketDispatcher::RegisterClient(P2PSocketClient* client) {
92  DCHECK(message_loop_->BelongsToCurrentThread());
93  return clients_.Add(client);
94}
95
96void P2PSocketDispatcher::UnregisterClient(int id) {
97  DCHECK(message_loop_->BelongsToCurrentThread());
98  clients_.Remove(id);
99}
100
101void P2PSocketDispatcher::SendP2PMessage(IPC::Message* msg) {
102  if (!message_loop_->BelongsToCurrentThread()) {
103    message_loop_->PostTask(FROM_HERE,
104                            base::Bind(&P2PSocketDispatcher::Send,
105                                       this, msg));
106    return;
107  }
108  Send(msg);
109}
110
111int P2PSocketDispatcher::RegisterHostAddressRequest(
112    P2PHostAddressRequest* request) {
113  DCHECK(message_loop_->BelongsToCurrentThread());
114  return host_address_requests_.Add(request);
115}
116
117void P2PSocketDispatcher::UnregisterHostAddressRequest(int id) {
118  DCHECK(message_loop_->BelongsToCurrentThread());
119  host_address_requests_.Remove(id);
120}
121
122void P2PSocketDispatcher::OnNetworkListChanged(
123    const net::NetworkInterfaceList& networks) {
124  network_list_observers_->Notify(
125      &webkit_glue::NetworkListObserver::OnNetworkListChanged, networks);
126}
127
128void P2PSocketDispatcher::OnGetHostAddressResult(
129    int32 request_id,
130    const net::IPAddressNumber& address) {
131  P2PHostAddressRequest* request = host_address_requests_.Lookup(request_id);
132  if (!request) {
133    VLOG(1) << "Received P2P message for socket that doesn't exist.";
134    return;
135  }
136
137  request->OnResponse(address);
138}
139
140void P2PSocketDispatcher::OnSocketCreated(
141    int socket_id, const net::IPEndPoint& address) {
142  P2PSocketClient* client = GetClient(socket_id);
143  if (client) {
144    client->OnSocketCreated(address);
145  }
146}
147
148void P2PSocketDispatcher::OnIncomingTcpConnection(
149    int socket_id, const net::IPEndPoint& address) {
150  P2PSocketClient* client = GetClient(socket_id);
151  if (client) {
152    client->OnIncomingTcpConnection(address);
153  }
154}
155
156void P2PSocketDispatcher::OnSendComplete(int socket_id) {
157  P2PSocketClient* client = GetClient(socket_id);
158  if (client) {
159    client->OnSendComplete();
160  }
161}
162
163void P2PSocketDispatcher::OnError(int socket_id) {
164  P2PSocketClient* client = GetClient(socket_id);
165  if (client) {
166    client->OnError();
167  }
168}
169
170void P2PSocketDispatcher::OnDataReceived(
171    int socket_id, const net::IPEndPoint& address,
172    const std::vector<char>& data) {
173  P2PSocketClient* client = GetClient(socket_id);
174  if (client) {
175    client->OnDataReceived(address, data);
176  }
177}
178
179P2PSocketClient* P2PSocketDispatcher::GetClient(int socket_id) {
180  P2PSocketClient* client = clients_.Lookup(socket_id);
181  if (client == NULL) {
182    // This may happen if the socket was closed, but the browser side
183    // hasn't processed the close message by the time it sends the
184    // message to the renderer.
185    VLOG(1) << "Received P2P message for socket that doesn't exist.";
186    return NULL;
187  }
188
189  return client;
190}
191
192}  // namespace content
193