OLD | NEW |
---|---|
(Empty) | |
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 "base/json/json_writer.h" | |
6 #include "base/stl_util.h" | |
7 #include "base/values.h" | |
8 #include "chrome/browser/extensions/api/socket/socket_api_controller.h" | |
9 #include "chrome/browser/profiles/profile.h" | |
10 #include "net/base/io_buffer.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/base/rand_callback.h" | |
13 #include "net/udp/datagram_socket.h" | |
14 #include "net/udp/udp_client_socket.h" | |
15 #include "net/udp/udp_socket.h" | |
16 | |
17 using namespace net; | |
18 | |
19 namespace extensions { | |
20 | |
21 // A Socket wraps a low-level socket and includes housekeeping information that | |
22 // we need to manage it in the context of an extension. | |
23 class Socket { | |
24 public: | |
25 explicit Socket(const Profile* profile, const std::string& src_extension_id, | |
Mihai Parparita -not on Chrome
2011/12/05 22:43:34
Nit: explicit should no longer be needed.
| |
26 const GURL& src_url); | |
27 ~Socket(); | |
28 | |
29 bool Connect(const net::IPEndPoint& ip_end_point); | |
30 void Close(); | |
31 int Write(const std::string message); | |
32 | |
33 private: | |
34 // TODO(miket): this metadata will enable us to pass events back to the | |
35 // extension that created this Socket. | |
36 const Profile* profile_; | |
37 int id_; | |
38 std::string src_extension_id_; | |
39 GURL src_url_; | |
40 | |
41 net::UDPClientSocket* udp_client_socket_; | |
42 bool is_connected_; | |
43 net::OldCompletionCallbackImpl<Socket> io_callback_; | |
44 | |
45 // A callback required by UDPClientSocket::Write(). | |
46 void OnIOComplete(int result); | |
47 }; | |
48 | |
49 Socket::Socket(const Profile* profile, const std::string& src_extension_id, | |
50 const GURL& src_url) | |
51 : profile_(profile), | |
52 src_extension_id_(src_extension_id), | |
53 src_url_(src_url), | |
54 udp_client_socket_(new UDPClientSocket( | |
55 DatagramSocket::DEFAULT_BIND, | |
56 RandIntCallback(), | |
57 NULL, | |
58 NetLog::Source())), | |
59 is_connected_(false), | |
60 ALLOW_THIS_IN_INITIALIZER_LIST( | |
61 io_callback_(this, &Socket::OnIOComplete)) {} | |
62 | |
63 Socket::~Socket() { | |
64 if (is_connected_) { | |
65 Close(); | |
66 } | |
67 } | |
68 | |
69 void Socket::OnIOComplete(int result) { | |
70 // We don't need to do anything. | |
71 } | |
72 | |
73 bool Socket::Connect(const net::IPEndPoint& ip_end_point) { | |
74 is_connected_ = udp_client_socket_->Connect(ip_end_point) == net::OK; | |
75 return is_connected_; | |
76 } | |
77 | |
78 void Socket::Close() { | |
79 is_connected_ = false; | |
80 udp_client_socket_->Close(); | |
81 } | |
82 | |
83 int Socket::Write(const std::string message) { | |
84 int length = message.length(); | |
85 scoped_refptr<StringIOBuffer> io_buffer(new StringIOBuffer(message)); | |
86 scoped_refptr<DrainableIOBuffer> buffer( | |
87 new DrainableIOBuffer(io_buffer, length)); | |
88 | |
89 int bytes_sent = 0; | |
90 while (buffer->BytesRemaining()) { | |
91 int rv = udp_client_socket_->Write(buffer, | |
92 buffer->BytesRemaining(), | |
93 &io_callback_); | |
94 if (rv <= 0) { | |
95 // We pass all errors, including ERROR_IO_PENDING, back to the caller. | |
96 return bytes_sent > 0 ? bytes_sent : rv; | |
97 } | |
98 bytes_sent += rv; | |
99 buffer->DidConsume(rv); | |
100 } | |
101 return bytes_sent; | |
102 } | |
103 | |
104 SocketController* SocketController::GetInstance() { | |
105 return Singleton<SocketController>::get(); | |
106 } | |
107 | |
108 SocketController::SocketController() : next_socket_id_(1) {} | |
109 | |
110 SocketController::~SocketController() { | |
111 STLDeleteValues(&socket_map_); | |
112 } | |
113 | |
114 Socket* SocketController::GetSocket(int socket_id) { | |
115 // TODO(miket): we should verify that the extension asking for the | |
116 // socket is the same one that created it. | |
117 SocketMap::iterator i = socket_map_.find(socket_id); | |
118 if (i != socket_map_.end()) | |
119 return i->second; | |
120 return NULL; | |
121 } | |
122 | |
123 int SocketController::CreateUdp(const Profile* profile, | |
124 const std::string& extension_id, | |
125 const GURL& src_url) { | |
126 Socket* socket = new Socket(profile, extension_id, src_url); | |
127 CHECK(socket); | |
128 socket_map_[next_socket_id_] = socket; | |
129 return next_socket_id_++; | |
130 } | |
131 | |
132 bool SocketController::DestroyUdp(int socket_id) { | |
133 Socket* socket = GetSocket(socket_id); | |
134 if (!socket) | |
135 return false; | |
136 delete socket; | |
137 socket_map_.erase(socket_id); | |
138 return true; | |
139 } | |
140 | |
141 // TODO(miket): it *might* be nice to be able to resolve DNS. I am not putting | |
142 // in interesting error reporting for this method because we clearly can't | |
143 // leave experimental without DNS resolution. | |
144 // | |
145 // static | |
146 bool SocketController::CreateIPEndPoint(const std::string address, int port, | |
147 net::IPEndPoint* ip_end_point) { | |
148 net::IPAddressNumber ip_number; | |
149 bool rv = net::ParseIPLiteralToNumber(address, &ip_number); | |
150 if (!rv) | |
151 return false; | |
152 *ip_end_point = net::IPEndPoint(ip_number, port); | |
153 return true; | |
154 } | |
155 | |
156 bool SocketController::ConnectUdp(int socket_id, const std::string address, | |
157 int port) { | |
158 Socket* socket = GetSocket(socket_id); | |
159 if (!socket) | |
160 return false; | |
161 net::IPEndPoint ip_end_point; | |
162 if (!CreateIPEndPoint(address, port, &ip_end_point)) | |
163 return false; | |
164 return socket->Connect(ip_end_point); | |
165 } | |
166 | |
167 void SocketController::CloseUdp(int socket_id) { | |
168 Socket* socket = GetSocket(socket_id); | |
169 if (socket) | |
170 socket->Close(); | |
171 } | |
172 | |
173 int SocketController::WriteUdp(int socket_id, const std::string message) { | |
174 Socket* socket = GetSocket(socket_id); | |
175 if (!socket) { | |
176 return -1; | |
177 } | |
178 return socket->Write(message); | |
179 } | |
180 | |
181 } // namespace extensions | |
OLD | NEW |