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/network_list_observer.h" 14 #include "content/renderer/p2p/socket_client_impl.h" 15 #include "content/renderer/render_view_impl.h" 16 17 namespace content { 18 19 P2PSocketDispatcher::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<NetworkListObserver>()), 25 channel_(NULL) { 26 } 27 28 P2PSocketDispatcher::~P2PSocketDispatcher() { 29 network_list_observers_->AssertEmpty(); 30 for (IDMap<P2PSocketClientImpl>::iterator i(&clients_); !i.IsAtEnd(); 31 i.Advance()) { 32 i.GetCurrentValue()->Detach(); 33 } 34 } 35 36 void P2PSocketDispatcher::AddNetworkListObserver( 37 NetworkListObserver* network_list_observer) { 38 network_list_observers_->AddObserver(network_list_observer); 39 network_notifications_started_ = true; 40 SendP2PMessage(new P2PHostMsg_StartNetworkNotifications()); 41 } 42 43 void P2PSocketDispatcher::RemoveNetworkListObserver( 44 NetworkListObserver* network_list_observer) { 45 network_list_observers_->RemoveObserver(network_list_observer); 46 } 47 48 void 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 59 bool 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 74 void P2PSocketDispatcher::OnFilterAdded(IPC::Channel* channel) { 75 DVLOG(1) << "P2PSocketDispatcher::OnFilterAdded()"; 76 channel_ = channel; 77 } 78 79 void P2PSocketDispatcher::OnFilterRemoved() { 80 channel_ = NULL; 81 } 82 83 void P2PSocketDispatcher::OnChannelClosing() { 84 channel_ = NULL; 85 } 86 87 base::MessageLoopProxy* P2PSocketDispatcher::message_loop() { 88 return message_loop_.get(); 89 } 90 91 int P2PSocketDispatcher::RegisterClient(P2PSocketClientImpl* client) { 92 DCHECK(message_loop_->BelongsToCurrentThread()); 93 return clients_.Add(client); 94 } 95 96 void P2PSocketDispatcher::UnregisterClient(int id) { 97 DCHECK(message_loop_->BelongsToCurrentThread()); 98 clients_.Remove(id); 99 } 100 101 void 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 111 int P2PSocketDispatcher::RegisterHostAddressRequest( 112 P2PHostAddressRequest* request) { 113 DCHECK(message_loop_->BelongsToCurrentThread()); 114 return host_address_requests_.Add(request); 115 } 116 117 void P2PSocketDispatcher::UnregisterHostAddressRequest(int id) { 118 DCHECK(message_loop_->BelongsToCurrentThread()); 119 host_address_requests_.Remove(id); 120 } 121 122 void P2PSocketDispatcher::OnNetworkListChanged( 123 const net::NetworkInterfaceList& networks) { 124 network_list_observers_->Notify( 125 &NetworkListObserver::OnNetworkListChanged, networks); 126 } 127 128 void 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 140 void P2PSocketDispatcher::OnSocketCreated( 141 int socket_id, const net::IPEndPoint& address) { 142 P2PSocketClientImpl* client = GetClient(socket_id); 143 if (client) { 144 client->OnSocketCreated(address); 145 } 146 } 147 148 void P2PSocketDispatcher::OnIncomingTcpConnection( 149 int socket_id, const net::IPEndPoint& address) { 150 P2PSocketClientImpl* client = GetClient(socket_id); 151 if (client) { 152 client->OnIncomingTcpConnection(address); 153 } 154 } 155 156 void P2PSocketDispatcher::OnSendComplete(int socket_id) { 157 P2PSocketClientImpl* client = GetClient(socket_id); 158 if (client) { 159 client->OnSendComplete(); 160 } 161 } 162 163 void P2PSocketDispatcher::OnError(int socket_id) { 164 P2PSocketClientImpl* client = GetClient(socket_id); 165 if (client) { 166 client->OnError(); 167 } 168 } 169 170 void P2PSocketDispatcher::OnDataReceived( 171 int socket_id, const net::IPEndPoint& address, 172 const std::vector<char>& data, 173 const base::TimeTicks& timestamp) { 174 P2PSocketClientImpl* client = GetClient(socket_id); 175 if (client) { 176 client->OnDataReceived(address, data, timestamp); 177 } 178 } 179 180 P2PSocketClientImpl* P2PSocketDispatcher::GetClient(int socket_id) { 181 P2PSocketClientImpl* client = clients_.Lookup(socket_id); 182 if (client == NULL) { 183 // This may happen if the socket was closed, but the browser side 184 // hasn't processed the close message by the time it sends the 185 // message to the renderer. 186 VLOG(1) << "Received P2P message for socket that doesn't exist."; 187 return NULL; 188 } 189 190 return client; 191 } 192 193 } // namespace content 194