~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/base/win32socketserver.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libjingle
 
3
 * Copyright 2004--2005, Google Inc.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *
 
8
 *  1. Redistributions of source code must retain the above copyright notice,
 
9
 *     this list of conditions and the following disclaimer.
 
10
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 
11
 *     this list of conditions and the following disclaimer in the documentation
 
12
 *     and/or other materials provided with the distribution.
 
13
 *  3. The name of the author may not be used to endorse or promote products
 
14
 *     derived from this software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
19
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
21
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
22
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
23
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
24
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
25
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
 */
 
27
 
 
28
#include "talk/base/win32socketserver.h"
 
29
#include "talk/base/byteorder.h"
 
30
#include "talk/base/common.h"
 
31
#include "talk/base/logging.h"
 
32
#include "talk/base/winping.h"
 
33
#include "talk/base/win32window.h"
 
34
#include <ws2tcpip.h>  // NOLINT
 
35
 
 
36
namespace talk_base {
 
37
 
 
38
///////////////////////////////////////////////////////////////////////////////
 
39
// Win32Socket
 
40
///////////////////////////////////////////////////////////////////////////////
 
41
 
 
42
// TODO: Move this to a common place where PhysicalSocketServer can
 
43
// share it.
 
44
// Standard MTUs
 
45
static const uint16 PACKET_MAXIMUMS[] = {
 
46
  65535,    // Theoretical maximum, Hyperchannel
 
47
  32000,    // Nothing
 
48
  17914,    // 16Mb IBM Token Ring
 
49
  8166,     // IEEE 802.4
 
50
  // 4464   // IEEE 802.5 (4Mb max)
 
51
  4352,     // FDDI
 
52
  // 2048,  // Wideband Network
 
53
  2002,     // IEEE 802.5 (4Mb recommended)
 
54
  // 1536,  // Expermental Ethernet Networks
 
55
  // 1500,  // Ethernet, Point-to-Point (default)
 
56
  1492,     // IEEE 802.3
 
57
  1006,     // SLIP, ARPANET
 
58
  // 576,   // X.25 Networks
 
59
  // 544,   // DEC IP Portal
 
60
  // 512,   // NETBIOS
 
61
  508,      // IEEE 802/Source-Rt Bridge, ARCNET
 
62
  296,      // Point-to-Point (low delay)
 
63
  68,       // Official minimum
 
64
  0,        // End of list marker
 
65
};
 
66
 
 
67
static const uint32 IP_HEADER_SIZE = 20;
 
68
static const uint32 ICMP_HEADER_SIZE = 8;
 
69
 
 
70
// TODO: Enable for production builds also? Use FormatMessage?
 
71
#ifdef _DEBUG
 
72
LPCSTR WSAErrorToString(int error, LPCSTR *description_result) {
 
73
  LPCSTR string = "Unspecified";
 
74
  LPCSTR description = "Unspecified description";
 
75
  switch (error) {
 
76
    case ERROR_SUCCESS:
 
77
      string = "SUCCESS";
 
78
      description = "Operation succeeded";
 
79
      break;
 
80
    case WSAEWOULDBLOCK:
 
81
      string = "WSAEWOULDBLOCK";
 
82
      description = "Using a non-blocking socket, will notify later";
 
83
      break;
 
84
    case WSAEACCES:
 
85
      string = "WSAEACCES";
 
86
      description = "Access denied, or sharing violation";
 
87
      break;
 
88
    case WSAEADDRNOTAVAIL:
 
89
      string = "WSAEADDRNOTAVAIL";
 
90
      description = "Address is not valid in this context";
 
91
      break;
 
92
    case WSAENETDOWN:
 
93
      string = "WSAENETDOWN";
 
94
      description = "Network is down";
 
95
      break;
 
96
    case WSAENETUNREACH:
 
97
      string = "WSAENETUNREACH";
 
98
      description = "Network is up, but unreachable";
 
99
      break;
 
100
    case WSAENETRESET:
 
101
      string = "WSANETRESET";
 
102
      description = "Connection has been reset due to keep-alive activity";
 
103
      break;
 
104
    case WSAECONNABORTED:
 
105
      string = "WSAECONNABORTED";
 
106
      description = "Aborted by host";
 
107
      break;
 
108
    case WSAECONNRESET:
 
109
      string = "WSAECONNRESET";
 
110
      description = "Connection reset by host";
 
111
      break;
 
112
    case WSAETIMEDOUT:
 
113
      string = "WSAETIMEDOUT";
 
114
      description = "Timed out, host failed to respond";
 
115
      break;
 
116
    case WSAECONNREFUSED:
 
117
      string = "WSAECONNREFUSED";
 
118
      description = "Host actively refused connection";
 
119
      break;
 
120
    case WSAEHOSTDOWN:
 
121
      string = "WSAEHOSTDOWN";
 
122
      description = "Host is down";
 
123
      break;
 
124
    case WSAEHOSTUNREACH:
 
125
      string = "WSAEHOSTUNREACH";
 
126
      description = "Host is unreachable";
 
127
      break;
 
128
    case WSAHOST_NOT_FOUND:
 
129
      string = "WSAHOST_NOT_FOUND";
 
130
      description = "No such host is known";
 
131
      break;
 
132
  }
 
133
  if (description_result) {
 
134
    *description_result = description;
 
135
  }
 
136
  return string;
 
137
}
 
138
 
 
139
void ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {
 
140
  LPCSTR description_string;
 
141
  LPCSTR error_string = WSAErrorToString(error, &description_string);
 
142
  LOG(LS_INFO) << context << " = " << error
 
143
    << " (" << error_string << ":" << description_string << ") ["
 
144
    << address.ToString() << "]";
 
145
}
 
146
#else
 
147
void ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {}
 
148
#endif
 
149
 
 
150
/////////////////////////////////////////////////////////////////////////////
 
151
// Win32Socket::EventSink
 
152
/////////////////////////////////////////////////////////////////////////////
 
153
 
 
154
#define WM_SOCKETNOTIFY  (WM_USER + 50)
 
155
#define WM_DNSNOTIFY     (WM_USER + 51)
 
156
 
 
157
struct Win32Socket::DnsLookup {
 
158
  HANDLE handle;
 
159
  uint16 port;
 
160
  char buffer[MAXGETHOSTSTRUCT];
 
161
};
 
162
 
 
163
class Win32Socket::EventSink : public Win32Window {
 
164
 public:
 
165
  explicit EventSink(Win32Socket * parent) : parent_(parent) { }
 
166
 
 
167
  void Dispose();
 
168
 
 
169
  virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
 
170
                         LRESULT& result);
 
171
  virtual void OnNcDestroy();
 
172
 
 
173
 private:
 
174
  bool OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result);
 
175
  bool OnDnsNotify(WPARAM wParam, LPARAM lParam, LRESULT& result);
 
176
 
 
177
  Win32Socket * parent_;
 
178
};
 
179
 
 
180
void Win32Socket::EventSink::Dispose() {
 
181
  parent_ = NULL;
 
182
  if (::IsWindow(handle())) {
 
183
    ::DestroyWindow(handle());
 
184
  } else {
 
185
    delete this;
 
186
  }
 
187
}
 
188
 
 
189
bool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam,
 
190
                                       LPARAM lParam, LRESULT& result) {
 
191
  switch (uMsg) {
 
192
  case WM_SOCKETNOTIFY:
 
193
  case WM_TIMER:
 
194
    return OnSocketNotify(uMsg, wParam, lParam, result);
 
195
  case WM_DNSNOTIFY:
 
196
    return OnDnsNotify(wParam, lParam, result);
 
197
  }
 
198
  return false;
 
199
}
 
200
 
 
201
bool Win32Socket::EventSink::OnSocketNotify(UINT uMsg, WPARAM wParam,
 
202
                                            LPARAM lParam, LRESULT& result) {
 
203
  result = 0;
 
204
 
 
205
  int wsa_event = WSAGETSELECTEVENT(lParam);
 
206
  int wsa_error = WSAGETSELECTERROR(lParam);
 
207
 
 
208
  // Treat connect timeouts as close notifications
 
209
  if (uMsg == WM_TIMER) {
 
210
    wsa_event = FD_CLOSE;
 
211
    wsa_error = WSAETIMEDOUT;
 
212
  }
 
213
 
 
214
  if (parent_)
 
215
    parent_->OnSocketNotify(static_cast<SOCKET>(wParam), wsa_event, wsa_error);
 
216
  return true;
 
217
}
 
218
 
 
219
bool Win32Socket::EventSink::OnDnsNotify(WPARAM wParam, LPARAM lParam,
 
220
                                         LRESULT& result) {
 
221
  result = 0;
 
222
 
 
223
  int error = WSAGETASYNCERROR(lParam);
 
224
  if (parent_)
 
225
    parent_->OnDnsNotify(reinterpret_cast<HANDLE>(wParam), error);
 
226
  return true;
 
227
}
 
228
 
 
229
void Win32Socket::EventSink::OnNcDestroy() {
 
230
  if (parent_) {
 
231
    LOG(LS_ERROR) << "EventSink hwnd is being destroyed, but the event sink"
 
232
                     " hasn't yet been disposed.";
 
233
  } else {
 
234
    delete this;
 
235
  }
 
236
}
 
237
 
 
238
/////////////////////////////////////////////////////////////////////////////
 
239
// Win32Socket
 
240
/////////////////////////////////////////////////////////////////////////////
 
241
 
 
242
Win32Socket::Win32Socket()
 
243
    : socket_(INVALID_SOCKET), error_(0), state_(CS_CLOSED), connect_time_(0),
 
244
      closing_(false), close_error_(0), sink_(NULL), dns_(NULL) {
 
245
}
 
246
 
 
247
Win32Socket::~Win32Socket() {
 
248
  Close();
 
249
}
 
250
 
 
251
bool Win32Socket::CreateT(int family, int type) {
 
252
  Close();
 
253
  int proto = (SOCK_DGRAM == type) ? IPPROTO_UDP : IPPROTO_TCP;
 
254
  socket_ = ::WSASocket(family, type, proto, NULL, NULL, 0);
 
255
  if (socket_ == INVALID_SOCKET) {
 
256
    UpdateLastError();
 
257
    return false;
 
258
  }
 
259
  if ((SOCK_DGRAM == type) && !SetAsync(FD_READ | FD_WRITE)) {
 
260
    return false;
 
261
  }
 
262
  return true;
 
263
}
 
264
 
 
265
int Win32Socket::Attach(SOCKET s) {
 
266
  ASSERT(socket_ == INVALID_SOCKET);
 
267
  if (socket_ != INVALID_SOCKET)
 
268
    return SOCKET_ERROR;
 
269
 
 
270
  ASSERT(s != INVALID_SOCKET);
 
271
  if (s == INVALID_SOCKET)
 
272
    return SOCKET_ERROR;
 
273
 
 
274
  socket_ = s;
 
275
  state_ = CS_CONNECTED;
 
276
 
 
277
  if (!SetAsync(FD_READ | FD_WRITE | FD_CLOSE))
 
278
    return SOCKET_ERROR;
 
279
 
 
280
  return 0;
 
281
}
 
282
 
 
283
void Win32Socket::SetTimeout(int ms) {
 
284
  if (sink_)
 
285
    ::SetTimer(sink_->handle(), 1, ms, 0);
 
286
}
 
287
 
 
288
SocketAddress Win32Socket::GetLocalAddress() const {
 
289
  sockaddr_storage addr;
 
290
  socklen_t addrlen = sizeof(addr);
 
291
  int result = ::getsockname(socket_, reinterpret_cast<sockaddr*>(&addr),
 
292
                             &addrlen);
 
293
  SocketAddress address;
 
294
  if (result >= 0) {
 
295
    SocketAddressFromSockAddrStorage(addr, &address);
 
296
  } else {
 
297
    LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
 
298
                    << socket_;
 
299
  }
 
300
  return address;
 
301
}
 
302
 
 
303
SocketAddress Win32Socket::GetRemoteAddress() const {
 
304
  sockaddr_storage addr;
 
305
  socklen_t addrlen = sizeof(addr);
 
306
  int result = ::getpeername(socket_, reinterpret_cast<sockaddr*>(&addr),
 
307
                             &addrlen);
 
308
  SocketAddress address;
 
309
  if (result >= 0) {
 
310
    SocketAddressFromSockAddrStorage(addr, &address);
 
311
  } else {
 
312
    LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
 
313
                    << socket_;
 
314
  }
 
315
  return address;
 
316
}
 
317
 
 
318
int Win32Socket::Bind(const SocketAddress& addr) {
 
319
  ASSERT(socket_ != INVALID_SOCKET);
 
320
  if (socket_ == INVALID_SOCKET)
 
321
    return SOCKET_ERROR;
 
322
 
 
323
  sockaddr_storage saddr;
 
324
  size_t len = addr.ToSockAddrStorage(&saddr);
 
325
  int err = ::bind(socket_,
 
326
                   reinterpret_cast<sockaddr*>(&saddr),
 
327
                   static_cast<int>(len));
 
328
  UpdateLastError();
 
329
  return err;
 
330
}
 
331
 
 
332
int Win32Socket::Connect(const SocketAddress& addr) {
 
333
  if ((socket_ == INVALID_SOCKET) && !CreateT(AF_INET, SOCK_STREAM))
 
334
    return SOCKET_ERROR;
 
335
 
 
336
  if (!sink_ && !SetAsync(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE))
 
337
    return SOCKET_ERROR;
 
338
 
 
339
  // If we have an IP address, connect now.
 
340
  if (!addr.IsUnresolved()) {
 
341
    return DoConnect(addr);
 
342
  }
 
343
 
 
344
  LOG_F(LS_INFO) << "async dns lookup (" << addr.IPAsString() << ")";
 
345
  DnsLookup * dns = new DnsLookup;
 
346
  // TODO: Replace with IPv6 compatible lookup.
 
347
  dns->handle = WSAAsyncGetHostByName(sink_->handle(), WM_DNSNOTIFY,
 
348
        addr.IPAsString().c_str(), dns->buffer, sizeof(dns->buffer));
 
349
 
 
350
  if (!dns->handle) {
 
351
    LOG_F(LS_ERROR) << "WSAAsyncGetHostByName error: " << WSAGetLastError();
 
352
    delete dns;
 
353
    UpdateLastError();
 
354
    Close();
 
355
    return SOCKET_ERROR;
 
356
  }
 
357
 
 
358
  dns->port = addr.port();
 
359
  dns_ = dns;
 
360
  state_ = CS_CONNECTING;
 
361
  return 0;
 
362
}
 
363
 
 
364
int Win32Socket::DoConnect(const SocketAddress& addr) {
 
365
  sockaddr_storage saddr;
 
366
  size_t len = addr.ToSockAddrStorage(&saddr);
 
367
  connect_time_ = Time();
 
368
  int result = connect(socket_,
 
369
                       reinterpret_cast<SOCKADDR*>(&saddr),
 
370
                       static_cast<int>(len));
 
371
  if (result != SOCKET_ERROR) {
 
372
    state_ = CS_CONNECTED;
 
373
  } else {
 
374
    int code = WSAGetLastError();
 
375
    if (code == WSAEWOULDBLOCK) {
 
376
      state_ = CS_CONNECTING;
 
377
    } else {
 
378
      ReportWSAError("WSAAsync:connect", code, addr);
 
379
      error_ = code;
 
380
      Close();
 
381
      return SOCKET_ERROR;
 
382
    }
 
383
  }
 
384
  addr_ = addr;
 
385
 
 
386
  return 0;
 
387
}
 
388
 
 
389
int Win32Socket::GetError() const {
 
390
  return error_;
 
391
}
 
392
 
 
393
void Win32Socket::SetError(int error) {
 
394
  error_ = error;
 
395
}
 
396
 
 
397
Socket::ConnState Win32Socket::GetState() const {
 
398
  return state_;
 
399
}
 
400
 
 
401
int Win32Socket::GetOption(Option opt, int* value) {
 
402
  int slevel;
 
403
  int sopt;
 
404
  if (TranslateOption(opt, &slevel, &sopt) == -1)
 
405
    return -1;
 
406
 
 
407
  char* p = reinterpret_cast<char*>(value);
 
408
  int optlen = sizeof(value);
 
409
  return ::getsockopt(socket_, slevel, sopt, p, &optlen);
 
410
}
 
411
 
 
412
int Win32Socket::SetOption(Option opt, int value) {
 
413
  int slevel;
 
414
  int sopt;
 
415
  if (TranslateOption(opt, &slevel, &sopt) == -1)
 
416
    return -1;
 
417
 
 
418
  const char* p = reinterpret_cast<const char*>(&value);
 
419
  return ::setsockopt(socket_, slevel, sopt, p, sizeof(value));
 
420
}
 
421
 
 
422
int Win32Socket::Send(const void* buffer, size_t length) {
 
423
  int sent = ::send(socket_,
 
424
                    reinterpret_cast<const char*>(buffer),
 
425
                    static_cast<int>(length),
 
426
                    0);
 
427
  UpdateLastError();
 
428
  return sent;
 
429
}
 
430
 
 
431
int Win32Socket::SendTo(const void* buffer, size_t length,
 
432
                        const SocketAddress& addr) {
 
433
  sockaddr_storage saddr;
 
434
  size_t addr_len = addr.ToSockAddrStorage(&saddr);
 
435
  int sent = ::sendto(socket_, reinterpret_cast<const char*>(buffer),
 
436
                      static_cast<int>(length), 0,
 
437
                      reinterpret_cast<sockaddr*>(&saddr),
 
438
                      static_cast<int>(addr_len));
 
439
  UpdateLastError();
 
440
  return sent;
 
441
}
 
442
 
 
443
int Win32Socket::Recv(void* buffer, size_t length) {
 
444
  int received = ::recv(socket_, static_cast<char*>(buffer),
 
445
                        static_cast<int>(length), 0);
 
446
  UpdateLastError();
 
447
  if (closing_ && received <= static_cast<int>(length))
 
448
    PostClosed();
 
449
  return received;
 
450
}
 
451
 
 
452
int Win32Socket::RecvFrom(void* buffer, size_t length,
 
453
                          SocketAddress* out_addr) {
 
454
  sockaddr_storage saddr;
 
455
  socklen_t addr_len = sizeof(saddr);
 
456
  int received = ::recvfrom(socket_, static_cast<char*>(buffer),
 
457
                            static_cast<int>(length), 0,
 
458
                            reinterpret_cast<sockaddr*>(&saddr), &addr_len);
 
459
  UpdateLastError();
 
460
  if (received != SOCKET_ERROR)
 
461
    SocketAddressFromSockAddrStorage(saddr, out_addr);
 
462
  if (closing_ && received <= static_cast<int>(length))
 
463
    PostClosed();
 
464
  return received;
 
465
}
 
466
 
 
467
int Win32Socket::Listen(int backlog) {
 
468
  int err = ::listen(socket_, backlog);
 
469
  if (!SetAsync(FD_ACCEPT))
 
470
    return SOCKET_ERROR;
 
471
 
 
472
  UpdateLastError();
 
473
  if (err == 0)
 
474
    state_ = CS_CONNECTING;
 
475
  return err;
 
476
}
 
477
 
 
478
Win32Socket* Win32Socket::Accept(SocketAddress* out_addr) {
 
479
  sockaddr_storage saddr;
 
480
  socklen_t addr_len = sizeof(saddr);
 
481
  SOCKET s = ::accept(socket_, reinterpret_cast<sockaddr*>(&saddr), &addr_len);
 
482
  UpdateLastError();
 
483
  if (s == INVALID_SOCKET)
 
484
    return NULL;
 
485
  if (out_addr)
 
486
    SocketAddressFromSockAddrStorage(saddr, out_addr);
 
487
  Win32Socket* socket = new Win32Socket;
 
488
  if (0 == socket->Attach(s))
 
489
    return socket;
 
490
  delete socket;
 
491
  return NULL;
 
492
}
 
493
 
 
494
int Win32Socket::Close() {
 
495
  int err = 0;
 
496
  if (socket_ != INVALID_SOCKET) {
 
497
    err = ::closesocket(socket_);
 
498
    socket_ = INVALID_SOCKET;
 
499
    closing_ = false;
 
500
    close_error_ = 0;
 
501
    UpdateLastError();
 
502
  }
 
503
  if (dns_) {
 
504
    WSACancelAsyncRequest(dns_->handle);
 
505
    delete dns_;
 
506
    dns_ = NULL;
 
507
  }
 
508
  if (sink_) {
 
509
    sink_->Dispose();
 
510
    sink_ = NULL;
 
511
  }
 
512
  addr_.Clear();
 
513
  state_ = CS_CLOSED;
 
514
  return err;
 
515
}
 
516
 
 
517
int Win32Socket::EstimateMTU(uint16* mtu) {
 
518
  SocketAddress addr = GetRemoteAddress();
 
519
  if (addr.IsAny()) {
 
520
    error_ = ENOTCONN;
 
521
    return -1;
 
522
  }
 
523
 
 
524
  WinPing ping;
 
525
  if (!ping.IsValid()) {
 
526
    error_ = EINVAL;  // can't think of a better error ID
 
527
    return -1;
 
528
  }
 
529
 
 
530
  for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
 
531
    int32 size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
 
532
    WinPing::PingResult result = ping.Ping(addr.ip(), size, 0, 1, false);
 
533
    if (result == WinPing::PING_FAIL) {
 
534
      error_ = EINVAL;  // can't think of a better error ID
 
535
      return -1;
 
536
    }
 
537
    if (result != WinPing::PING_TOO_LARGE) {
 
538
      *mtu = PACKET_MAXIMUMS[level];
 
539
      return 0;
 
540
    }
 
541
  }
 
542
 
 
543
  ASSERT(false);
 
544
  return 0;
 
545
}
 
546
 
 
547
bool Win32Socket::SetAsync(int events) {
 
548
  ASSERT(NULL == sink_);
 
549
 
 
550
  // Create window
 
551
  sink_ = new EventSink(this);
 
552
  sink_->Create(NULL, L"EventSink", 0, 0, 0, 0, 10, 10);
 
553
 
 
554
  // start the async select
 
555
  if (WSAAsyncSelect(socket_, sink_->handle(), WM_SOCKETNOTIFY, events)
 
556
      == SOCKET_ERROR) {
 
557
    UpdateLastError();
 
558
    Close();
 
559
    return false;
 
560
  }
 
561
 
 
562
  return true;
 
563
}
 
564
 
 
565
bool Win32Socket::HandleClosed(int close_error) {
 
566
  // WM_CLOSE will be received before all data has been read, so we need to
 
567
  // hold on to it until the read buffer has been drained.
 
568
  char ch;
 
569
  closing_ = true;
 
570
  close_error_ = close_error;
 
571
  return (::recv(socket_, &ch, 1, MSG_PEEK) <= 0);
 
572
}
 
573
 
 
574
void Win32Socket::PostClosed() {
 
575
  // If we see that the buffer is indeed drained, then send the close.
 
576
  closing_ = false;
 
577
  ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY,
 
578
                socket_, WSAMAKESELECTREPLY(FD_CLOSE, close_error_));
 
579
}
 
580
 
 
581
void Win32Socket::UpdateLastError() {
 
582
  error_ = WSAGetLastError();
 
583
}
 
584
 
 
585
int Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) {
 
586
  switch (opt) {
 
587
    case OPT_DONTFRAGMENT:
 
588
      *slevel = IPPROTO_IP;
 
589
      *sopt = IP_DONTFRAGMENT;
 
590
      break;
 
591
    case OPT_RCVBUF:
 
592
      *slevel = SOL_SOCKET;
 
593
      *sopt = SO_RCVBUF;
 
594
      break;
 
595
    case OPT_SNDBUF:
 
596
      *slevel = SOL_SOCKET;
 
597
      *sopt = SO_SNDBUF;
 
598
      break;
 
599
    case OPT_NODELAY:
 
600
      *slevel = IPPROTO_TCP;
 
601
      *sopt = TCP_NODELAY;
 
602
      break;
 
603
    default:
 
604
      ASSERT(false);
 
605
      return -1;
 
606
  }
 
607
  return 0;
 
608
}
 
609
 
 
610
void Win32Socket::OnSocketNotify(SOCKET socket, int event, int error) {
 
611
  // Ignore events if we're already closed.
 
612
  if (socket != socket_)
 
613
    return;
 
614
 
 
615
  error_ = error;
 
616
  switch (event) {
 
617
    case FD_CONNECT:
 
618
      if (error != ERROR_SUCCESS) {
 
619
        ReportWSAError("WSAAsync:connect notify", error, addr_);
 
620
#ifdef _DEBUG
 
621
        int32 duration = TimeSince(connect_time_);
 
622
        LOG(LS_INFO) << "WSAAsync:connect error (" << duration
 
623
                     << " ms), faking close";
 
624
#endif
 
625
        state_ = CS_CLOSED;
 
626
        // If you get an error connecting, close doesn't really do anything
 
627
        // and it certainly doesn't send back any close notification, but
 
628
        // we really only maintain a few states, so it is easiest to get
 
629
        // back into a known state by pretending that a close happened, even
 
630
        // though the connect event never did occur.
 
631
        SignalCloseEvent(this, error);
 
632
      } else {
 
633
#ifdef _DEBUG
 
634
        int32 duration = TimeSince(connect_time_);
 
635
        LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)";
 
636
#endif
 
637
        state_ = CS_CONNECTED;
 
638
        SignalConnectEvent(this);
 
639
      }
 
640
      break;
 
641
 
 
642
    case FD_ACCEPT:
 
643
    case FD_READ:
 
644
      if (error != ERROR_SUCCESS) {
 
645
        ReportWSAError("WSAAsync:read notify", error, addr_);
 
646
      } else {
 
647
        SignalReadEvent(this);
 
648
      }
 
649
      break;
 
650
 
 
651
    case FD_WRITE:
 
652
      if (error != ERROR_SUCCESS) {
 
653
        ReportWSAError("WSAAsync:write notify", error, addr_);
 
654
      } else {
 
655
        SignalWriteEvent(this);
 
656
      }
 
657
      break;
 
658
 
 
659
    case FD_CLOSE:
 
660
      if (HandleClosed(error)) {
 
661
        ReportWSAError("WSAAsync:close notify", error, addr_);
 
662
        state_ = CS_CLOSED;
 
663
        SignalCloseEvent(this, error);
 
664
      }
 
665
      break;
 
666
  }
 
667
}
 
668
 
 
669
void Win32Socket::OnDnsNotify(HANDLE task, int error) {
 
670
  if (!dns_ || dns_->handle != task)
 
671
    return;
 
672
 
 
673
  uint32 ip = 0;
 
674
  if (error == 0) {
 
675
    hostent* pHost = reinterpret_cast<hostent*>(dns_->buffer);
 
676
    uint32 net_ip = *reinterpret_cast<uint32*>(pHost->h_addr_list[0]);
 
677
    ip = NetworkToHost32(net_ip);
 
678
  }
 
679
 
 
680
  LOG_F(LS_INFO) << "(" << SocketAddress::IPToString(ip)
 
681
                 << ", " << error << ")";
 
682
 
 
683
  if (error == 0) {
 
684
    SocketAddress address(ip, dns_->port);
 
685
    error = DoConnect(address);
 
686
  } else {
 
687
    Close();
 
688
  }
 
689
 
 
690
  if (error) {
 
691
    error_ = error;
 
692
    SignalCloseEvent(this, error_);
 
693
  } else {
 
694
    delete dns_;
 
695
    dns_ = NULL;
 
696
  }
 
697
}
 
698
 
 
699
///////////////////////////////////////////////////////////////////////////////
 
700
// Win32SocketServer
 
701
// Provides cricket base services on top of a win32 gui thread
 
702
///////////////////////////////////////////////////////////////////////////////
 
703
 
 
704
static UINT s_wm_wakeup_id = 0;
 
705
const TCHAR Win32SocketServer::kWindowName[] = L"libjingle Message Window";
 
706
 
 
707
Win32SocketServer::Win32SocketServer(MessageQueue* message_queue)
 
708
    : message_queue_(message_queue),
 
709
      wnd_(this),
 
710
      posted_(false),
 
711
      hdlg_(NULL) {
 
712
  if (s_wm_wakeup_id == 0)
 
713
    s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP");
 
714
  if (!wnd_.Create(NULL, kWindowName, 0, 0, 0, 0, 0, 0)) {
 
715
    LOG_GLE(LS_ERROR) << "Failed to create message window.";
 
716
  }
 
717
}
 
718
 
 
719
Win32SocketServer::~Win32SocketServer() {
 
720
  if (wnd_.handle() != NULL) {
 
721
    KillTimer(wnd_.handle(), 1);
 
722
    wnd_.Destroy();
 
723
  }
 
724
}
 
725
 
 
726
Socket* Win32SocketServer::CreateSocket(int type) {
 
727
  return CreateSocket(AF_INET, type);
 
728
}
 
729
 
 
730
Socket* Win32SocketServer::CreateSocket(int family, int type) {
 
731
  return CreateAsyncSocket(family, type);
 
732
}
 
733
 
 
734
AsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) {
 
735
  return CreateAsyncSocket(AF_INET, type);
 
736
}
 
737
 
 
738
AsyncSocket* Win32SocketServer::CreateAsyncSocket(int family, int type) {
 
739
  Win32Socket* socket = new Win32Socket;
 
740
  if (socket->CreateT(family, type)) {
 
741
    return socket;
 
742
  }
 
743
  delete socket;
 
744
  return NULL;
 
745
}
 
746
 
 
747
void Win32SocketServer::SetMessageQueue(MessageQueue* queue) {
 
748
  message_queue_ = queue;
 
749
}
 
750
 
 
751
bool Win32SocketServer::Wait(int cms, bool process_io) {
 
752
  BOOL b;
 
753
  if (process_io) {
 
754
    // Spin the Win32 message pump at least once, and as long as requested.
 
755
    // This is the Thread::ProcessMessages case.
 
756
    uint32 start = Time();
 
757
    do {
 
758
      MSG msg;
 
759
      SetTimer(wnd_.handle(), 0, cms, NULL);
 
760
      // Get the next available message. If we have a modeless dialog, give
 
761
      // give the message to IsDialogMessage, which will return true if it
 
762
      // was a message for the dialog that it handled internally.
 
763
      // Otherwise, dispatch as usual via Translate/DispatchMessage.
 
764
      b = GetMessage(&msg, NULL, 0, 0);
 
765
      if (b == -1) {
 
766
        LOG_GLE(LS_ERROR) << "GetMessage failed.";
 
767
        return false;
 
768
      } else if(b) {
 
769
        if (!hdlg_ || !IsDialogMessage(hdlg_, &msg)) {
 
770
          TranslateMessage(&msg);
 
771
          DispatchMessage(&msg);
 
772
        }
 
773
      }
 
774
      KillTimer(wnd_.handle(), 0);
 
775
    } while (b && TimeSince(start) < cms);
 
776
  } else if (cms != 0) {
 
777
    // Sit and wait forever for a WakeUp. This is the Thread::Send case.
 
778
    ASSERT(cms == -1);
 
779
    MSG msg;
 
780
    b = GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id);
 
781
    {
 
782
      CritScope scope(&cs_);
 
783
      posted_ = false;
 
784
    }
 
785
  } else {
 
786
    // No-op (cms == 0 && !process_io). This is the Pump case.
 
787
    b = TRUE;
 
788
  }
 
789
  return (b != FALSE);
 
790
}
 
791
 
 
792
void Win32SocketServer::WakeUp() {
 
793
  if (wnd_.handle()) {
 
794
    // Set the "message pending" flag, if not already set.
 
795
    {
 
796
      CritScope scope(&cs_);
 
797
      if (posted_)
 
798
        return;
 
799
      posted_ = true;
 
800
    }
 
801
 
 
802
    PostMessage(wnd_.handle(), s_wm_wakeup_id, 0, 0);
 
803
  }
 
804
}
 
805
 
 
806
void Win32SocketServer::Pump() {
 
807
  // Clear the "message pending" flag.
 
808
  {
 
809
    CritScope scope(&cs_);
 
810
    posted_ = false;
 
811
  }
 
812
 
 
813
  // Dispatch all the messages that are currently in our queue. If new messages
 
814
  // are posted during the dispatch, they will be handled in the next Pump.
 
815
  // We use max(1, ...) to make sure we try to dispatch at least once, since
 
816
  // this allow us to process "sent" messages, not included in the size() count.
 
817
  Message msg;
 
818
  for (size_t max_messages_to_process = _max<size_t>(1, message_queue_->size());
 
819
       max_messages_to_process > 0 && message_queue_->Get(&msg, 0, false);
 
820
       --max_messages_to_process) {
 
821
    message_queue_->Dispatch(&msg);
 
822
  }
 
823
 
 
824
  // Anything remaining?
 
825
  int delay = message_queue_->GetDelay();
 
826
  if (delay == -1) {
 
827
    KillTimer(wnd_.handle(), 1);
 
828
  } else {
 
829
    SetTimer(wnd_.handle(), 1, delay, NULL);
 
830
  }
 
831
}
 
832
 
 
833
bool Win32SocketServer::MessageWindow::OnMessage(UINT wm, WPARAM wp,
 
834
                                                 LPARAM lp, LRESULT& lr) {
 
835
  bool handled = false;
 
836
  if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) {
 
837
    ss_->Pump();
 
838
    lr = 0;
 
839
    handled = true;
 
840
  }
 
841
  return handled;
 
842
}
 
843
 
 
844
}  // namespace talk_base