Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/udp/udp_socket_win.h" | 5 #include "net/udp/udp_socket_win.h" |
| 6 | 6 |
| 7 #include <mstcpip.h> | 7 #include <mstcpip.h> |
| 8 | 8 |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/eintr_wrapper.h" | 10 #include "base/eintr_wrapper.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 static const int kBindRetries = 10; | 26 static const int kBindRetries = 10; |
| 27 static const int kPortStart = 1024; | 27 static const int kPortStart = 1024; |
| 28 static const int kPortEnd = 65535; | 28 static const int kPortEnd = 65535; |
| 29 | 29 |
| 30 } // namespace net | 30 } // namespace net |
| 31 | 31 |
| 32 namespace net { | 32 namespace net { |
| 33 | 33 |
| 34 void UDPSocketWin::ReadDelegate::OnObjectSignaled(HANDLE object) { | 34 // This class encapsulates all the state that has to be preserved as long as |
| 35 DCHECK_EQ(object, socket_->read_overlapped_.hEvent); | 35 // there is a network IO operation in progress. If the owner UDPSocketWin |
| 36 socket_->DidCompleteRead(); | 36 // is destroyed while an operation is in progress, the Core is detached and it |
| 37 // lives until the operation completes and the OS doesn't reference any resource | |
| 38 // declared on this class anymore. | |
| 39 class UDPSocketWin::Core : public base::RefCounted<Core> { | |
| 40 public: | |
| 41 explicit Core(UDPSocketWin* socket); | |
| 42 | |
| 43 // Start watching for the end of a read or write operation. | |
| 44 void WatchForRead(); | |
| 45 void WatchForWrite(); | |
| 46 | |
| 47 // The UDPSocketWin is going away. | |
| 48 void Detach() { socket_ = NULL; } | |
| 49 | |
| 50 // The separate OVERLAPPED variables for asynchronous operation. | |
| 51 OVERLAPPED read_overlapped_; | |
| 52 OVERLAPPED write_overlapped_; | |
| 53 | |
| 54 // The buffers used in Read() and Write(). | |
| 55 WSABUF read_buffer_; | |
| 56 WSABUF write_buffer_; | |
|
wtc
2012/09/12 01:40:29
It turns out these two buffers don't need to be me
wtc
2012/09/12 04:00:43
I have created a CL for TCPClientSocketWin:
http:/
szym
2012/09/12 15:14:06
That snippet from MSDN was the reason why I decide
| |
| 57 scoped_refptr<IOBuffer> read_iobuffer_; | |
| 58 scoped_refptr<IOBuffer> write_iobuffer_; | |
| 59 | |
| 60 private: | |
| 61 friend class base::RefCounted<Core>; | |
| 62 | |
| 63 class ReadDelegate : public base::win::ObjectWatcher::Delegate { | |
| 64 public: | |
| 65 explicit ReadDelegate(Core* core) : core_(core) {} | |
| 66 virtual ~ReadDelegate() {} | |
| 67 | |
| 68 // base::ObjectWatcher::Delegate methods: | |
| 69 virtual void OnObjectSignaled(HANDLE object); | |
| 70 | |
| 71 private: | |
| 72 Core* const core_; | |
| 73 }; | |
| 74 | |
| 75 class WriteDelegate : public base::win::ObjectWatcher::Delegate { | |
| 76 public: | |
| 77 explicit WriteDelegate(Core* core) : core_(core) {} | |
| 78 virtual ~WriteDelegate() {} | |
| 79 | |
| 80 // base::ObjectWatcher::Delegate methods: | |
| 81 virtual void OnObjectSignaled(HANDLE object); | |
| 82 | |
| 83 private: | |
| 84 Core* const core_; | |
| 85 }; | |
| 86 | |
| 87 ~Core(); | |
| 88 | |
| 89 // The socket that created this object. | |
| 90 UDPSocketWin* socket_; | |
| 91 | |
| 92 // |reader_| handles the signals from |read_watcher_|. | |
| 93 ReadDelegate reader_; | |
| 94 // |writer_| handles the signals from |write_watcher_|. | |
| 95 WriteDelegate writer_; | |
| 96 | |
| 97 // |read_watcher_| watches for events from Connect() and Read(). | |
|
wtc
2012/09/12 01:40:29
Delete "Connect() and"?
szym
2012/09/12 15:14:06
Done.
| |
| 98 base::win::ObjectWatcher read_watcher_; | |
| 99 // |write_watcher_| watches for events from Write(); | |
| 100 base::win::ObjectWatcher write_watcher_; | |
| 101 | |
| 102 DISALLOW_COPY_AND_ASSIGN(Core); | |
| 103 }; | |
| 104 | |
| 105 UDPSocketWin::Core::Core(UDPSocketWin* socket) | |
| 106 : socket_(socket), | |
| 107 ALLOW_THIS_IN_INITIALIZER_LIST(reader_(this)), | |
| 108 ALLOW_THIS_IN_INITIALIZER_LIST(writer_(this)) { | |
| 109 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); | |
| 110 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); | |
| 111 | |
| 112 read_overlapped_.hEvent = WSACreateEvent(); | |
| 113 write_overlapped_.hEvent = WSACreateEvent(); | |
| 37 } | 114 } |
| 38 | 115 |
| 39 void UDPSocketWin::WriteDelegate::OnObjectSignaled(HANDLE object) { | 116 UDPSocketWin::Core::~Core() { |
| 40 DCHECK_EQ(object, socket_->write_overlapped_.hEvent); | 117 // Make sure the message loop is not watching this object anymore. |
| 41 socket_->DidCompleteWrite(); | 118 read_watcher_.StopWatching(); |
| 119 write_watcher_.StopWatching(); | |
| 120 | |
| 121 WSACloseEvent(read_overlapped_.hEvent); | |
| 122 memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_)); | |
| 123 WSACloseEvent(write_overlapped_.hEvent); | |
| 124 memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_)); | |
| 42 } | 125 } |
| 43 | 126 |
| 127 void UDPSocketWin::Core::WatchForRead() { | |
| 128 // We grab an extra reference because there is an IO operation in progress. | |
| 129 // Balanced in ReadDelegate::OnObjectSignaled(). | |
| 130 AddRef(); | |
| 131 read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_); | |
| 132 } | |
| 133 | |
| 134 void UDPSocketWin::Core::WatchForWrite() { | |
| 135 // We grab an extra reference because there is an IO operation in progress. | |
| 136 // Balanced in WriteDelegate::OnObjectSignaled(). | |
| 137 AddRef(); | |
| 138 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); | |
| 139 } | |
| 140 | |
| 141 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) { | |
| 142 DCHECK_EQ(object, core_->read_overlapped_.hEvent); | |
| 143 if (core_->socket_) | |
| 144 core_->socket_->DidCompleteRead(); | |
| 145 | |
| 146 core_->Release(); | |
| 147 } | |
| 148 | |
| 149 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) { | |
| 150 DCHECK_EQ(object, core_->write_overlapped_.hEvent); | |
| 151 if (core_->socket_) | |
| 152 core_->socket_->DidCompleteWrite(); | |
| 153 | |
| 154 core_->Release(); | |
| 155 } | |
| 156 | |
| 157 //----------------------------------------------------------------------------- | |
| 158 | |
| 44 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, | 159 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, |
| 45 const RandIntCallback& rand_int_cb, | 160 const RandIntCallback& rand_int_cb, |
| 46 net::NetLog* net_log, | 161 net::NetLog* net_log, |
| 47 const net::NetLog::Source& source) | 162 const net::NetLog::Source& source) |
| 48 : socket_(INVALID_SOCKET), | 163 : socket_(INVALID_SOCKET), |
| 49 socket_options_(0), | 164 socket_options_(0), |
| 50 bind_type_(bind_type), | 165 bind_type_(bind_type), |
| 51 rand_int_cb_(rand_int_cb), | 166 rand_int_cb_(rand_int_cb), |
| 52 ALLOW_THIS_IN_INITIALIZER_LIST(read_delegate_(this)), | |
| 53 ALLOW_THIS_IN_INITIALIZER_LIST(write_delegate_(this)), | |
| 54 recv_from_address_(NULL), | 167 recv_from_address_(NULL), |
| 55 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | 168 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
| 56 EnsureWinsockInit(); | 169 EnsureWinsockInit(); |
| 57 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 170 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
| 58 source.ToEventParametersCallback()); | 171 source.ToEventParametersCallback()); |
| 59 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); | |
| 60 read_overlapped_.hEvent = WSACreateEvent(); | |
| 61 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); | |
| 62 write_overlapped_.hEvent = WSACreateEvent(); | |
| 63 if (bind_type == DatagramSocket::RANDOM_BIND) | 172 if (bind_type == DatagramSocket::RANDOM_BIND) |
| 64 DCHECK(!rand_int_cb.is_null()); | 173 DCHECK(!rand_int_cb.is_null()); |
| 65 } | 174 } |
| 66 | 175 |
| 67 UDPSocketWin::~UDPSocketWin() { | 176 UDPSocketWin::~UDPSocketWin() { |
| 68 Close(); | 177 Close(); |
| 69 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 178 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
| 70 } | 179 } |
| 71 | 180 |
| 72 void UDPSocketWin::Close() { | 181 void UDPSocketWin::Close() { |
| 73 DCHECK(CalledOnValidThread()); | 182 DCHECK(CalledOnValidThread()); |
| 74 | 183 |
| 75 if (!is_connected()) | 184 if (!is_connected()) |
| 76 return; | 185 return; |
| 77 | 186 |
| 78 // Zero out any pending read/write callback state. | 187 // Zero out any pending read/write callback state. |
| 79 read_callback_.Reset(); | 188 read_callback_.Reset(); |
| 80 recv_from_address_ = NULL; | 189 recv_from_address_ = NULL; |
| 81 write_callback_.Reset(); | 190 write_callback_.Reset(); |
| 82 | 191 |
| 83 read_watcher_.StopWatching(); | |
| 84 write_watcher_.StopWatching(); | |
| 85 | |
| 86 WSACloseEvent(read_overlapped_.hEvent); | |
| 87 memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_)); | |
| 88 WSACloseEvent(write_overlapped_.hEvent); | |
| 89 memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_)); | |
| 90 | |
| 91 closesocket(socket_); | 192 closesocket(socket_); |
| 92 socket_ = INVALID_SOCKET; | 193 socket_ = INVALID_SOCKET; |
| 194 | |
| 195 if (core_.get()) | |
|
wtc
2012/09/12 01:40:29
Is this null pointer check necessary? It is not in
szym
2012/09/12 02:23:45
It should, I added this in response to a failing t
| |
| 196 core_->Detach(); | |
| 197 core_ = NULL; | |
| 93 } | 198 } |
| 94 | 199 |
| 95 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { | 200 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { |
| 96 DCHECK(CalledOnValidThread()); | 201 DCHECK(CalledOnValidThread()); |
| 97 DCHECK(address); | 202 DCHECK(address); |
| 98 if (!is_connected()) | 203 if (!is_connected()) |
| 99 return ERR_SOCKET_NOT_CONNECTED; | 204 return ERR_SOCKET_NOT_CONNECTED; |
| 100 | 205 |
| 101 // TODO(szym): Simplify. http://crbug.com/126152 | 206 // TODO(szym): Simplify. http://crbug.com/126152 |
| 102 if (!remote_address_.get()) { | 207 if (!remote_address_.get()) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 DCHECK_NE(INVALID_SOCKET, socket_); | 253 DCHECK_NE(INVALID_SOCKET, socket_); |
| 149 DCHECK(read_callback_.is_null()); | 254 DCHECK(read_callback_.is_null()); |
| 150 DCHECK(!recv_from_address_); | 255 DCHECK(!recv_from_address_); |
| 151 DCHECK(!callback.is_null()); // Synchronous operation not supported. | 256 DCHECK(!callback.is_null()); // Synchronous operation not supported. |
| 152 DCHECK_GT(buf_len, 0); | 257 DCHECK_GT(buf_len, 0); |
| 153 | 258 |
| 154 int nread = InternalRecvFrom(buf, buf_len, address); | 259 int nread = InternalRecvFrom(buf, buf_len, address); |
| 155 if (nread != ERR_IO_PENDING) | 260 if (nread != ERR_IO_PENDING) |
| 156 return nread; | 261 return nread; |
| 157 | 262 |
| 158 read_iobuffer_ = buf; | |
| 159 read_callback_ = callback; | 263 read_callback_ = callback; |
| 160 recv_from_address_ = address; | 264 recv_from_address_ = address; |
| 161 return ERR_IO_PENDING; | 265 return ERR_IO_PENDING; |
| 162 } | 266 } |
| 163 | 267 |
| 164 int UDPSocketWin::Write(IOBuffer* buf, | 268 int UDPSocketWin::Write(IOBuffer* buf, |
| 165 int buf_len, | 269 int buf_len, |
| 166 const CompletionCallback& callback) { | 270 const CompletionCallback& callback) { |
| 167 return SendToOrWrite(buf, buf_len, NULL, callback); | 271 return SendToOrWrite(buf, buf_len, NULL, callback); |
| 168 } | 272 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 184 DCHECK(!callback.is_null()); // Synchronous operation not supported. | 288 DCHECK(!callback.is_null()); // Synchronous operation not supported. |
| 185 DCHECK_GT(buf_len, 0); | 289 DCHECK_GT(buf_len, 0); |
| 186 DCHECK(!send_to_address_.get()); | 290 DCHECK(!send_to_address_.get()); |
| 187 | 291 |
| 188 int nwrite = InternalSendTo(buf, buf_len, address); | 292 int nwrite = InternalSendTo(buf, buf_len, address); |
| 189 if (nwrite != ERR_IO_PENDING) | 293 if (nwrite != ERR_IO_PENDING) |
| 190 return nwrite; | 294 return nwrite; |
| 191 | 295 |
| 192 if (address) | 296 if (address) |
| 193 send_to_address_.reset(new IPEndPoint(*address)); | 297 send_to_address_.reset(new IPEndPoint(*address)); |
| 194 write_iobuffer_ = buf; | |
| 195 write_callback_ = callback; | 298 write_callback_ = callback; |
| 196 return ERR_IO_PENDING; | 299 return ERR_IO_PENDING; |
| 197 } | 300 } |
| 198 | 301 |
| 199 int UDPSocketWin::Connect(const IPEndPoint& address) { | 302 int UDPSocketWin::Connect(const IPEndPoint& address) { |
| 200 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, | 303 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, |
| 201 CreateNetLogUDPConnectCallback(&address)); | 304 CreateNetLogUDPConnectCallback(&address)); |
| 202 int rv = InternalConnect(address); | 305 int rv = InternalConnect(address); |
| 203 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); | 306 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); |
| 204 return rv; | 307 return rv; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 DCHECK(!write_callback_.is_null()); | 401 DCHECK(!write_callback_.is_null()); |
| 299 | 402 |
| 300 // since Run may result in Write being called, clear write_callback_ up front. | 403 // since Run may result in Write being called, clear write_callback_ up front. |
| 301 CompletionCallback c = write_callback_; | 404 CompletionCallback c = write_callback_; |
| 302 write_callback_.Reset(); | 405 write_callback_.Reset(); |
| 303 c.Run(rv); | 406 c.Run(rv); |
| 304 } | 407 } |
| 305 | 408 |
| 306 void UDPSocketWin::DidCompleteRead() { | 409 void UDPSocketWin::DidCompleteRead() { |
| 307 DWORD num_bytes, flags; | 410 DWORD num_bytes, flags; |
| 308 BOOL ok = WSAGetOverlappedResult(socket_, &read_overlapped_, | 411 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, |
| 309 &num_bytes, FALSE, &flags); | 412 &num_bytes, FALSE, &flags); |
| 310 WSAResetEvent(read_overlapped_.hEvent); | 413 WSAResetEvent(core_->read_overlapped_.hEvent); |
| 311 int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); | 414 int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); |
| 312 // Convert address. | 415 // Convert address. |
| 313 if (recv_from_address_ && result >= 0) { | 416 if (recv_from_address_ && result >= 0) { |
| 314 if (!ReceiveAddressToIPEndpoint(recv_from_address_)) | 417 if (!ReceiveAddressToIPEndpoint(recv_from_address_)) |
| 315 result = ERR_FAILED; | 418 result = ERR_FAILED; |
| 316 } | 419 } |
| 317 LogRead(result, read_iobuffer_->data()); | 420 LogRead(result, core_->read_iobuffer_->data()); |
| 318 read_iobuffer_ = NULL; | 421 core_->read_iobuffer_ = NULL; |
| 319 recv_from_address_ = NULL; | 422 recv_from_address_ = NULL; |
| 320 DoReadCallback(result); | 423 DoReadCallback(result); |
| 321 } | 424 } |
| 322 | 425 |
| 323 void UDPSocketWin::LogRead(int result, const char* bytes) const { | 426 void UDPSocketWin::LogRead(int result, const char* bytes) const { |
| 324 if (result < 0) { | 427 if (result < 0) { |
| 325 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); | 428 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); |
| 326 return; | 429 return; |
| 327 } | 430 } |
| 328 | 431 |
| 329 if (net_log_.IsLoggingAllEvents()) { | 432 if (net_log_.IsLoggingAllEvents()) { |
| 330 // Get address for logging, if |address| is NULL. | 433 // Get address for logging, if |address| is NULL. |
| 331 IPEndPoint address; | 434 IPEndPoint address; |
| 332 bool is_address_valid = ReceiveAddressToIPEndpoint(&address); | 435 bool is_address_valid = ReceiveAddressToIPEndpoint(&address); |
| 333 net_log_.AddEvent( | 436 net_log_.AddEvent( |
| 334 NetLog::TYPE_UDP_BYTES_RECEIVED, | 437 NetLog::TYPE_UDP_BYTES_RECEIVED, |
| 335 CreateNetLogUDPDataTranferCallback( | 438 CreateNetLogUDPDataTranferCallback( |
| 336 result, bytes, | 439 result, bytes, |
| 337 is_address_valid ? &address : NULL)); | 440 is_address_valid ? &address : NULL)); |
| 338 } | 441 } |
| 339 | 442 |
| 340 base::StatsCounter read_bytes("udp.read_bytes"); | 443 base::StatsCounter read_bytes("udp.read_bytes"); |
| 341 read_bytes.Add(result); | 444 read_bytes.Add(result); |
| 342 } | 445 } |
| 343 | 446 |
| 344 void UDPSocketWin::DidCompleteWrite() { | 447 void UDPSocketWin::DidCompleteWrite() { |
| 345 DWORD num_bytes, flags; | 448 DWORD num_bytes, flags; |
| 346 BOOL ok = WSAGetOverlappedResult(socket_, &write_overlapped_, | 449 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, |
| 347 &num_bytes, FALSE, &flags); | 450 &num_bytes, FALSE, &flags); |
| 348 WSAResetEvent(write_overlapped_.hEvent); | 451 WSAResetEvent(core_->write_overlapped_.hEvent); |
| 349 int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); | 452 int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); |
| 350 LogWrite(result, write_iobuffer_->data(), send_to_address_.get()); | 453 LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get()); |
| 351 | 454 |
| 352 send_to_address_.reset(); | 455 send_to_address_.reset(); |
| 353 write_iobuffer_ = NULL; | 456 core_->write_iobuffer_ = NULL; |
| 354 DoWriteCallback(result); | 457 DoWriteCallback(result); |
| 355 } | 458 } |
| 356 | 459 |
| 357 void UDPSocketWin::LogWrite(int result, | 460 void UDPSocketWin::LogWrite(int result, |
| 358 const char* bytes, | 461 const char* bytes, |
| 359 const IPEndPoint* address) const { | 462 const IPEndPoint* address) const { |
| 360 if (result < 0) { | 463 if (result < 0) { |
| 361 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result); | 464 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result); |
| 362 return; | 465 return; |
| 363 } | 466 } |
| 364 | 467 |
| 365 if (net_log_.IsLoggingAllEvents()) { | 468 if (net_log_.IsLoggingAllEvents()) { |
| 366 net_log_.AddEvent( | 469 net_log_.AddEvent( |
| 367 NetLog::TYPE_UDP_BYTES_SENT, | 470 NetLog::TYPE_UDP_BYTES_SENT, |
| 368 CreateNetLogUDPDataTranferCallback(result, bytes, address)); | 471 CreateNetLogUDPDataTranferCallback(result, bytes, address)); |
| 369 } | 472 } |
| 370 | 473 |
| 371 base::StatsCounter write_bytes("udp.write_bytes"); | 474 base::StatsCounter write_bytes("udp.write_bytes"); |
| 372 write_bytes.Add(result); | 475 write_bytes.Add(result); |
| 373 } | 476 } |
| 374 | 477 |
| 375 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len, | 478 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len, |
| 376 IPEndPoint* address) { | 479 IPEndPoint* address) { |
|
wtc
2012/09/12 01:40:29
I suggest copying
DCHECK(!core_->read_iobuffer_)
szym
2012/09/12 15:14:06
Done.
| |
| 377 recv_addr_len_ = sizeof(recv_addr_storage_); | 480 recv_addr_len_ = sizeof(recv_addr_storage_); |
| 378 struct sockaddr* addr = | 481 struct sockaddr* addr = |
| 379 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); | 482 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); |
| 380 | 483 |
| 381 WSABUF read_buffer; | 484 if (!core_) |
| 382 read_buffer.buf = buf->data(); | 485 core_ = new Core(this); |
|
wtc
2012/09/12 01:40:29
I think we can simply create Core in the UDPSocket
szym
2012/09/12 02:23:45
This will definitely be moved from here, either to
wtc
2012/09/12 04:00:43
I think TCPClientSocketWin creates Core lazily bec
szym
2012/09/12 15:14:06
It seems UDOSocketWin can be re-Connected or re-Bo
| |
| 383 read_buffer.len = buf_len; | 486 core_->read_iobuffer_ = buf; |
|
wtc
2012/09/12 01:40:29
BUG: this can be a reference leak. You need to rel
szym
2012/09/12 15:14:06
Done.
| |
| 487 core_->read_buffer_.buf = buf->data(); | |
| 488 core_->read_buffer_.len = buf_len; | |
| 384 | 489 |
| 385 DWORD flags = 0; | 490 DWORD flags = 0; |
| 386 DWORD num; | 491 DWORD num; |
| 387 CHECK_NE(INVALID_SOCKET, socket_); | 492 CHECK_NE(INVALID_SOCKET, socket_); |
| 388 AssertEventNotSignaled(read_overlapped_.hEvent); | 493 AssertEventNotSignaled(core_->read_overlapped_.hEvent); |
| 389 int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, addr, | 494 int rv = WSARecvFrom(socket_, &core_->read_buffer_, 1, &num, &flags, addr, |
| 390 &recv_addr_len_, &read_overlapped_, NULL); | 495 &recv_addr_len_, &core_->read_overlapped_, NULL); |
| 391 if (rv == 0) { | 496 if (rv == 0) { |
| 392 if (ResetEventIfSignaled(read_overlapped_.hEvent)) { | 497 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { |
| 393 int result = num; | 498 int result = num; |
| 394 // Convert address. | 499 // Convert address. |
| 395 if (address && result >= 0) { | 500 if (address && result >= 0) { |
| 396 if (!ReceiveAddressToIPEndpoint(address)) | 501 if (!ReceiveAddressToIPEndpoint(address)) |
| 397 result = ERR_FAILED; | 502 result = ERR_FAILED; |
| 398 } | 503 } |
| 399 LogRead(result, buf->data()); | 504 LogRead(result, buf->data()); |
| 400 return result; | 505 return result; |
| 401 } | 506 } |
| 402 } else { | 507 } else { |
| 403 int os_error = WSAGetLastError(); | 508 int os_error = WSAGetLastError(); |
| 404 if (os_error != WSA_IO_PENDING) { | 509 if (os_error != WSA_IO_PENDING) { |
| 405 int result = MapSystemError(os_error); | 510 int result = MapSystemError(os_error); |
| 406 LogRead(result, NULL); | 511 LogRead(result, NULL); |
| 407 return result; | 512 return result; |
| 408 } | 513 } |
| 409 } | 514 } |
| 410 read_watcher_.StartWatching(read_overlapped_.hEvent, &read_delegate_); | 515 core_->WatchForRead(); |
| 411 return ERR_IO_PENDING; | 516 return ERR_IO_PENDING; |
| 412 } | 517 } |
| 413 | 518 |
| 414 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len, | 519 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len, |
|
wtc
2012/09/12 01:40:29
IMPORTANT: All of my comments for UDPSocketWin::In
szym
2012/09/12 15:14:06
Done.
| |
| 415 const IPEndPoint* address) { | 520 const IPEndPoint* address) { |
| 416 SockaddrStorage storage; | 521 SockaddrStorage storage; |
| 417 struct sockaddr* addr = storage.addr; | 522 struct sockaddr* addr = storage.addr; |
| 418 // Convert address. | 523 // Convert address. |
| 419 if (!address) { | 524 if (!address) { |
| 420 addr = NULL; | 525 addr = NULL; |
| 421 storage.addr_len = 0; | 526 storage.addr_len = 0; |
| 422 } else { | 527 } else { |
| 423 if (!address->ToSockAddr(addr, &storage.addr_len)) { | 528 if (!address->ToSockAddr(addr, &storage.addr_len)) { |
| 424 int result = ERR_FAILED; | 529 int result = ERR_FAILED; |
| 425 LogWrite(result, NULL, NULL); | 530 LogWrite(result, NULL, NULL); |
| 426 return result; | 531 return result; |
| 427 } | 532 } |
| 428 } | 533 } |
| 429 | 534 |
| 430 WSABUF write_buffer; | 535 if (!core_.get()) |
| 431 write_buffer.buf = buf->data(); | 536 core_ = new Core(this); |
| 432 write_buffer.len = buf_len; | 537 core_->write_iobuffer_ = buf; |
| 538 core_->write_buffer_.buf = buf->data(); | |
| 539 core_->write_buffer_.len = buf_len; | |
| 433 | 540 |
| 434 DWORD flags = 0; | 541 DWORD flags = 0; |
| 435 DWORD num; | 542 DWORD num; |
| 436 AssertEventNotSignaled(write_overlapped_.hEvent); | 543 AssertEventNotSignaled(core_->write_overlapped_.hEvent); |
| 437 int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, | 544 int rv = WSASendTo(socket_, &core_->write_buffer_, 1, &num, flags, |
| 438 addr, storage.addr_len, &write_overlapped_, NULL); | 545 addr, storage.addr_len, &core_->write_overlapped_, NULL); |
| 439 if (rv == 0) { | 546 if (rv == 0) { |
| 440 if (ResetEventIfSignaled(write_overlapped_.hEvent)) { | 547 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { |
| 441 int result = num; | 548 int result = num; |
| 442 LogWrite(result, buf->data(), address); | 549 LogWrite(result, buf->data(), address); |
| 443 return result; | 550 return result; |
| 444 } | 551 } |
| 445 } else { | 552 } else { |
| 446 int os_error = WSAGetLastError(); | 553 int os_error = WSAGetLastError(); |
| 447 if (os_error != WSA_IO_PENDING) { | 554 if (os_error != WSA_IO_PENDING) { |
| 448 int result = MapSystemError(os_error); | 555 int result = MapSystemError(os_error); |
| 449 LogWrite(result, NULL, NULL); | 556 LogWrite(result, NULL, NULL); |
| 450 return result; | 557 return result; |
| 451 } | 558 } |
| 452 } | 559 } |
| 453 | 560 |
| 454 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); | 561 core_->WatchForWrite(); |
| 455 return ERR_IO_PENDING; | 562 return ERR_IO_PENDING; |
| 456 } | 563 } |
| 457 | 564 |
| 458 int UDPSocketWin::SetSocketOptions() { | 565 int UDPSocketWin::SetSocketOptions() { |
| 459 BOOL true_value = 1; | 566 BOOL true_value = 1; |
| 460 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { | 567 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
| 461 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, | 568 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, |
| 462 reinterpret_cast<const char*>(&true_value), | 569 reinterpret_cast<const char*>(&true_value), |
| 463 sizeof(true_value)); | 570 sizeof(true_value)); |
| 464 if (rv < 0) | 571 if (rv < 0) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 return DoBind(IPEndPoint(ip, 0)); | 603 return DoBind(IPEndPoint(ip, 0)); |
| 497 } | 604 } |
| 498 | 605 |
| 499 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { | 606 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { |
| 500 const struct sockaddr* addr = | 607 const struct sockaddr* addr = |
| 501 reinterpret_cast<const struct sockaddr*>(&recv_addr_storage_); | 608 reinterpret_cast<const struct sockaddr*>(&recv_addr_storage_); |
| 502 return address->FromSockAddr(addr, recv_addr_len_); | 609 return address->FromSockAddr(addr, recv_addr_len_); |
| 503 } | 610 } |
| 504 | 611 |
| 505 } // namespace net | 612 } // namespace net |
| OLD | NEW |