summaryrefslogtreecommitdiffstats
path: root/net/base
diff options
context:
space:
mode:
Diffstat (limited to 'net/base')
-rw-r--r--net/base/winsock_util.cc96
-rw-r--r--net/base/winsock_util.h31
2 files changed, 127 insertions, 0 deletions
diff --git a/net/base/winsock_util.cc b/net/base/winsock_util.cc
new file mode 100644
index 0000000..a3548d4
--- /dev/null
+++ b/net/base/winsock_util.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/winsock_util.h"
+
+#include "base/logging.h"
+#include "net/base/net_errors.h"
+
+namespace net {
+
+namespace {
+
+// Prevent the compiler from optimizing away the arguments so they appear
+// nicely on the stack in crash dumps.
+#pragma warning (disable: 4748)
+#pragma optimize( "", off )
+
+// Pass the important values as function arguments so that they are available
+// in crash dumps.
+void CheckEventWait(WSAEVENT hEvent, DWORD wait_rv, DWORD expected) {
+ if (wait_rv != expected) {
+ DWORD err = ERROR_SUCCESS;
+ if (wait_rv == WAIT_FAILED)
+ err = GetLastError();
+ CHECK(false); // Crash.
+ }
+}
+
+#pragma optimize( "", on )
+#pragma warning (default: 4748)
+
+} // namespace
+
+void AssertEventNotSignaled(WSAEVENT hEvent) {
+ DWORD wait_rv = WaitForSingleObject(hEvent, 0);
+ CheckEventWait(hEvent, wait_rv, WAIT_TIMEOUT);
+}
+
+bool ResetEventIfSignaled(WSAEVENT hEvent) {
+ // TODO(wtc): Remove the CHECKs after enough testing.
+ DWORD wait_rv = WaitForSingleObject(hEvent, 0);
+ if (wait_rv == WAIT_TIMEOUT)
+ return false; // The event object is not signaled.
+ CheckEventWait(hEvent, wait_rv, WAIT_OBJECT_0);
+ BOOL ok = WSAResetEvent(hEvent);
+ CHECK(ok);
+ return true;
+}
+
+// Map winsock error to Chromium error.
+int MapWinsockError(int os_error) {
+ // There are numerous Winsock error codes, but these are the ones we thus far
+ // find interesting.
+ switch (os_error) {
+ case WSAEACCES:
+ return ERR_ACCESS_DENIED;
+ case WSAENETDOWN:
+ return ERR_INTERNET_DISCONNECTED;
+ case WSAETIMEDOUT:
+ return ERR_TIMED_OUT;
+ case WSAECONNRESET:
+ case WSAENETRESET: // Related to keep-alive
+ return ERR_CONNECTION_RESET;
+ case WSAECONNABORTED:
+ return ERR_CONNECTION_ABORTED;
+ case WSAECONNREFUSED:
+ return ERR_CONNECTION_REFUSED;
+ case WSA_IO_INCOMPLETE:
+ case WSAEDISCON:
+ // WSAEDISCON is returned by WSARecv or WSARecvFrom for message-oriented
+ // sockets (where a return value of zero means a zero-byte message) to
+ // indicate graceful connection shutdown. We should not ever see this
+ // error code for TCP sockets, which are byte stream oriented.
+ LOG(DFATAL) << "Unexpected error " << os_error
+ << " mapped to net::ERR_UNEXPECTED";
+ return ERR_UNEXPECTED;
+ case WSAEHOSTUNREACH:
+ case WSAENETUNREACH:
+ return ERR_ADDRESS_UNREACHABLE;
+ case WSAEADDRNOTAVAIL:
+ return ERR_ADDRESS_INVALID;
+ case WSAENOTCONN:
+ return ERR_SOCKET_NOT_CONNECTED;
+ case WSAEAFNOSUPPORT:
+ return ERR_ADDRESS_UNREACHABLE;
+ case ERROR_SUCCESS:
+ return OK;
+ default:
+ LOG(WARNING) << "Unknown error " << os_error
+ << " mapped to net::ERR_FAILED";
+ return ERR_FAILED;
+ }
+}
+
+} // namespace net
diff --git a/net/base/winsock_util.h b/net/base/winsock_util.h
new file mode 100644
index 0000000..c26e63f
--- /dev/null
+++ b/net/base/winsock_util.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_WINSOCK_UTIL_H_
+#define NET_BASE_WINSOCK_UTIL_H_
+#pragma once
+
+#include <winsock2.h>
+
+namespace net {
+
+// Assert that the (manual-reset) event object is not signaled.
+void AssertEventNotSignaled(WSAEVENT hEvent);
+
+// If the (manual-reset) event object is signaled, resets it and returns true.
+// Otherwise, does nothing and returns false. Called after a Winsock function
+// succeeds synchronously
+//
+// Our testing shows that except in rare cases (when running inside QEMU),
+// the event object is already signaled at this point, so we call this method
+// to avoid a context switch in common cases. This is just a performance
+// optimization. The code still works if this function simply returns false.
+bool ResetEventIfSignaled(WSAEVENT hEvent);
+
+// Map winsock error to Chromium error.
+int MapWinsockError(int os_error);
+
+} // namespace net
+
+#endif // NET_BASE_WINSOCK_UTIL_H_