Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: net/udp/udp_socket_win.cc

Issue 6658027: UDP sockets implementation for windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: typo Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/udp/udp_socket_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 "net/udp/udp_socket_win.h"
6
7 #include <mstcpip.h>
8
9 #include "base/eintr_wrapper.h"
10 #include "base/logging.h"
11 #include "base/message_loop.h"
12 #include "base/memory_debug.h"
13 #include "base/metrics/stats_counters.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/ip_endpoint.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/net_log.h"
18 #include "net/base/net_util.h"
19 #include "net/base/winsock_init.h"
20 #include "net/base/winsock_util.h"
21
22 namespace net {
23
24 void UDPSocketWin::ReadDelegate::OnObjectSignaled(HANDLE object) {
25 DCHECK_EQ(object, socket_->read_overlapped_.hEvent);
26 socket_->DidCompleteRead();
27 }
28
29 void UDPSocketWin::WriteDelegate::OnObjectSignaled(HANDLE object) {
30 DCHECK_EQ(object, socket_->write_overlapped_.hEvent);
31 socket_->DidCompleteWrite();
32 }
33
34 UDPSocketWin::UDPSocketWin(net::NetLog* net_log,
35 const net::NetLog::Source& source)
36 : socket_(INVALID_SOCKET),
37 ALLOW_THIS_IN_INITIALIZER_LIST(read_delegate_(this)),
38 ALLOW_THIS_IN_INITIALIZER_LIST(write_delegate_(this)),
39 recv_from_address_(NULL),
40 read_callback_(NULL),
41 write_callback_(NULL),
42 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
43 EnsureWinsockInit();
44 scoped_refptr<NetLog::EventParameters> params;
45 if (source.is_valid())
46 params = new NetLogSourceParameter("source_dependency", source);
47 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
48 memset(&read_overlapped_, 0, sizeof(read_overlapped_));
49 read_overlapped_.hEvent = WSACreateEvent();
50 memset(&write_overlapped_, 0, sizeof(write_overlapped_));
51 write_overlapped_.hEvent = WSACreateEvent();
52 }
53
54 UDPSocketWin::~UDPSocketWin() {
55 Close();
56 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
57 }
58
59 void UDPSocketWin::Close() {
60 DCHECK(CalledOnValidThread());
61
62 if (!is_connected())
63 return;
64
65 if (read_callback_)
66 DoReadCallback(ERR_ABORTED);
67 if (write_callback_)
68 DoReadCallback(ERR_ABORTED);
69
70 read_watcher_.StopWatching();
71 write_watcher_.StopWatching();
72
73 closesocket(socket_);
74 socket_ = INVALID_SOCKET;
75 }
76
77 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
78 DCHECK(CalledOnValidThread());
79 DCHECK(address);
80 if (!is_connected())
81 return ERR_SOCKET_NOT_CONNECTED;
82
83 if (!remote_address_.get()) {
84 struct sockaddr_storage addr_storage;
85 int addr_len = sizeof(addr_storage);
86 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
87 if (getpeername(socket_, addr, &addr_len))
88 return MapWinsockError(WSAGetLastError());
89 scoped_ptr<IPEndPoint> address(new IPEndPoint());
90 if (!address->FromSockAddr(addr, addr_len))
91 return ERR_FAILED;
92 remote_address_.reset(address.release());
93 }
94
95 *address = *remote_address_;
96 return OK;
97 }
98
99 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
100 DCHECK(CalledOnValidThread());
101 DCHECK(address);
102 if (!is_connected())
103 return ERR_SOCKET_NOT_CONNECTED;
104
105 if (!local_address_.get()) {
106 struct sockaddr_storage addr_storage;
107 socklen_t addr_len = sizeof(addr_storage);
108 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
109 if (getsockname(socket_, addr, &addr_len))
110 return MapWinsockError(WSAGetLastError());
111 scoped_ptr<IPEndPoint> address(new IPEndPoint());
112 if (!address->FromSockAddr(addr, addr_len))
113 return ERR_FAILED;
114 local_address_.reset(address.release());
115 }
116
117 *address = *local_address_;
118 return OK;
119 }
120
121 int UDPSocketWin::RecvFrom(IOBuffer* buf,
122 int buf_len,
123 IPEndPoint* address,
124 CompletionCallback* callback) {
125 DCHECK(!recv_from_address_);
126 recv_from_address_ = address;
127 return Read(buf, buf_len, callback);
128 }
129
130 int UDPSocketWin::Read(IOBuffer* buf,
131 int buf_len,
132 CompletionCallback* callback) {
133 DCHECK(CalledOnValidThread());
134 DCHECK_NE(INVALID_SOCKET, socket_);
135 DCHECK(!read_callback_);
136 DCHECK(callback); // Synchronous operation not supported.
137 DCHECK_GT(buf_len, 0);
138
139 int nread = InternalRead(buf, buf_len);
140 if (nread != ERR_IO_PENDING)
141 return nread;
142
143 read_iobuffer_ = buf;
144 read_callback_ = callback;
145 return ERR_IO_PENDING;
146 }
147
148 int UDPSocketWin::SendTo(IOBuffer* buf,
149 int buf_len,
150 const IPEndPoint& address,
151 CompletionCallback* callback) {
152 send_to_address_.reset(new IPEndPoint(address));
153 return Write(buf, buf_len, callback);
154 }
155
156 int UDPSocketWin::Write(IOBuffer* buf,
157 int buf_len,
158 CompletionCallback* callback) {
159 DCHECK(CalledOnValidThread());
160 DCHECK_NE(INVALID_SOCKET, socket_);
161 DCHECK(!write_callback_);
162 DCHECK(callback); // Synchronous operation not supported.
163 DCHECK_GT(buf_len, 0);
164
165 int nwrite = InternalWrite(buf, buf_len);
166 if (nwrite != ERR_IO_PENDING)
167 return nwrite;
168
169 write_iobuffer_ = buf;
170 write_callback_ = callback;
171 return ERR_IO_PENDING;
172 }
173
174 int UDPSocketWin::Connect(const IPEndPoint& address) {
175 DCHECK(!is_connected());
176 DCHECK(!remote_address_.get());
177 int rv = CreateSocket(address);
178 if (rv < 0)
179 return rv;
180
181 struct sockaddr_storage addr_storage;
182 size_t addr_len = sizeof(addr_storage);
183 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
184 if (!address.ToSockAddr(addr, &addr_len))
185 return ERR_FAILED;
186
187 rv = connect(socket_, addr, addr_len);
188 if (rv < 0)
189 return MapWinsockError(WSAGetLastError());
190
191 remote_address_.reset(new IPEndPoint(address));
192 return rv;
193 }
194
195 int UDPSocketWin::Bind(const IPEndPoint& address) {
196 DCHECK(!is_connected());
197 DCHECK(!local_address_.get());
198 int rv = CreateSocket(address);
199 if (rv < 0)
200 return rv;
201
202 struct sockaddr_storage addr_storage;
203 size_t addr_len = sizeof(addr_storage);
204 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
205 if (!address.ToSockAddr(addr, &addr_len))
206 return ERR_FAILED;
207
208 rv = bind(socket_, addr, addr_len);
209 if (rv < 0)
210 return MapWinsockError(WSAGetLastError());
211
212 local_address_.reset(new IPEndPoint(address));
213 return rv;
214 }
215
216 int UDPSocketWin::CreateSocket(const IPEndPoint& address) {
217 socket_ = WSASocket(address.GetFamily(), SOCK_DGRAM, IPPROTO_UDP, NULL, 0,
218 WSA_FLAG_OVERLAPPED);
219 if (socket_ == INVALID_SOCKET)
220 return MapWinsockError(WSAGetLastError());
221 return OK;
222 }
223
224 void UDPSocketWin::DoReadCallback(int rv) {
225 DCHECK_NE(rv, ERR_IO_PENDING);
226 DCHECK(read_callback_);
227
228 // since Run may result in Read being called, clear read_callback_ up front.
229 CompletionCallback* c = read_callback_;
230 read_callback_ = NULL;
231 recv_from_address_ = NULL;
232 c->Run(rv);
233 }
234
235 void UDPSocketWin::DoWriteCallback(int rv) {
236 DCHECK_NE(rv, ERR_IO_PENDING);
237 DCHECK(write_callback_);
238
239 // since Run may result in Write being called, clear write_callback_ up front.
240 CompletionCallback* c = write_callback_;
241 write_callback_ = NULL;
242 send_to_address_.reset();
243 c->Run(rv);
244 }
245
246 void UDPSocketWin::DidCompleteRead() {
247 DWORD num_bytes, flags;
248 BOOL ok = WSAGetOverlappedResult(socket_, &read_overlapped_,
249 &num_bytes, FALSE, &flags);
250 WSAResetEvent(read_overlapped_.hEvent);
251 int result = ok ? num_bytes : MapWinsockError(WSAGetLastError());
252 if (ok) {
253 if (!ProcessSuccessfulRead(num_bytes))
254 result = ERR_FAILED;
255 }
256 read_iobuffer_ = NULL;
257 DoReadCallback(result);
258 }
259
260 bool UDPSocketWin::ProcessSuccessfulRead(int num_bytes) {
261 static base::StatsCounter read_bytes("udp.read_bytes");
262 read_bytes.Add(num_bytes);
263
264 // Convert address.
265 if (recv_from_address_) {
266 struct sockaddr* addr =
267 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_);
268 if (!recv_from_address_->FromSockAddr(addr, recv_addr_len_))
269 return false;
270 }
271
272 return true;
273 }
274
275 void UDPSocketWin::DidCompleteWrite() {
276 DWORD num_bytes, flags;
277 BOOL ok = WSAGetOverlappedResult(socket_, &write_overlapped_,
278 &num_bytes, FALSE, &flags);
279 WSAResetEvent(write_overlapped_.hEvent);
280 int result = ok ? num_bytes : MapWinsockError(WSAGetLastError());
281 if (ok)
282 ProcessSuccessfulWrite(num_bytes);
283 write_iobuffer_ = NULL;
284 DoWriteCallback(result);
285 }
286
287 void UDPSocketWin::ProcessSuccessfulWrite(int num_bytes) {
288 static base::StatsCounter write_bytes("udp.write_bytes");
289 write_bytes.Add(num_bytes);
290 }
291
292 int UDPSocketWin::InternalRead(IOBuffer* buf, int buf_len) {
293 recv_addr_len_ = sizeof(recv_addr_storage_);
294 struct sockaddr* addr =
295 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_);
296
297 WSABUF read_buffer;
298 read_buffer.buf = buf->data();
299 read_buffer.len = buf_len;
300
301 DWORD flags = 0;
302 DWORD num;
303 AssertEventNotSignaled(read_overlapped_.hEvent);
304 int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, addr,
305 &recv_addr_len_, &read_overlapped_, NULL);
306 if (rv == 0) {
307 if (ResetEventIfSignaled(read_overlapped_.hEvent)) {
308 // Because of how WSARecv fills memory when used asynchronously, Purify
309 // isn't able to detect that it's been initialized, so it scans for 0xcd
310 // in the buffer and reports UMRs (uninitialized memory reads) for those
311 // individual bytes. We override that in PURIFY builds to avoid the
312 // false error reports.
313 // See bug 5297.
314 base::MemoryDebug::MarkAsInitialized(read_buffer.buf, num);
315 if (!ProcessSuccessfulRead(num))
316 return ERR_FAILED;
317 return static_cast<int>(num);
318 }
319 } else {
320 int os_error = WSAGetLastError();
321 if (os_error != WSA_IO_PENDING)
322 return MapWinsockError(os_error);
323 }
324 read_watcher_.StartWatching(read_overlapped_.hEvent, &read_delegate_);
325 return ERR_IO_PENDING;
326 }
327
328 int UDPSocketWin::InternalWrite(IOBuffer* buf, int buf_len) {
329 struct sockaddr_storage addr_storage;
330 size_t addr_len = sizeof(addr_storage);
331 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
332
333 // Convert address.
334 if (!send_to_address_.get()) {
335 addr = NULL;
336 addr_len = 0;
337 } else {
338 if (!send_to_address_->ToSockAddr(addr, &addr_len))
339 return ERR_FAILED;
340 }
341
342 WSABUF write_buffer;
343 write_buffer.buf = buf->data();
344 write_buffer.len = buf_len;
345
346 DWORD flags = 0;
347 DWORD num;
348 AssertEventNotSignaled(write_overlapped_.hEvent);
349 int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
350 addr, addr_len, &write_overlapped_, NULL);
351 if (rv == 0) {
352 if (ResetEventIfSignaled(write_overlapped_.hEvent)) {
353 ProcessSuccessfulWrite(num);
354 return static_cast<int>(num);
355 }
356 } else {
357 int os_error = WSAGetLastError();
358 if (os_error != WSA_IO_PENDING)
359 return MapWinsockError(os_error);
360 }
361
362 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_);
363 return ERR_IO_PENDING;
364 }
365
366 } // namespace net
OLDNEW
« no previous file with comments | « net/udp/udp_socket_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698