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