| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 the V8 project 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 "platform/socket.h" | |
| 6 | |
| 7 #if V8_OS_POSIX | |
| 8 #include <sys/types.h> | |
| 9 #include <sys/socket.h> | |
| 10 | |
| 11 #include <netinet/in.h> | |
| 12 #include <netdb.h> | |
| 13 | |
| 14 #include <unistd.h> | |
| 15 #endif | |
| 16 | |
| 17 #include <errno.h> | |
| 18 | |
| 19 #include "checks.h" | |
| 20 #include "once.h" | |
| 21 | |
| 22 namespace v8 { | |
| 23 namespace internal { | |
| 24 | |
| 25 #if V8_OS_WIN | |
| 26 | |
| 27 static V8_DECLARE_ONCE(initialize_winsock) = V8_ONCE_INIT; | |
| 28 | |
| 29 | |
| 30 static void InitializeWinsock() { | |
| 31 WSADATA wsa_data; | |
| 32 int result = WSAStartup(MAKEWORD(1, 0), &wsa_data); | |
| 33 CHECK_EQ(0, result); | |
| 34 } | |
| 35 | |
| 36 #endif // V8_OS_WIN | |
| 37 | |
| 38 | |
| 39 Socket::Socket() { | |
| 40 #if V8_OS_WIN | |
| 41 // Be sure to initialize the WinSock DLL first. | |
| 42 CallOnce(&initialize_winsock, &InitializeWinsock); | |
| 43 #endif // V8_OS_WIN | |
| 44 | |
| 45 // Create the native socket handle. | |
| 46 native_handle_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
| 47 } | |
| 48 | |
| 49 | |
| 50 bool Socket::Bind(int port) { | |
| 51 ASSERT_GE(port, 0); | |
| 52 ASSERT_LT(port, 65536); | |
| 53 if (!IsValid()) return false; | |
| 54 struct sockaddr_in sin; | |
| 55 memset(&sin, 0, sizeof(sin)); | |
| 56 sin.sin_family = AF_INET; | |
| 57 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
| 58 sin.sin_port = htons(static_cast<uint16_t>(port)); | |
| 59 int result = ::bind( | |
| 60 native_handle_, reinterpret_cast<struct sockaddr*>(&sin), sizeof(sin)); | |
| 61 return result == 0; | |
| 62 } | |
| 63 | |
| 64 | |
| 65 bool Socket::Listen(int backlog) { | |
| 66 if (!IsValid()) return false; | |
| 67 int result = ::listen(native_handle_, backlog); | |
| 68 return result == 0; | |
| 69 } | |
| 70 | |
| 71 | |
| 72 Socket* Socket::Accept() { | |
| 73 if (!IsValid()) return NULL; | |
| 74 while (true) { | |
| 75 NativeHandle native_handle = ::accept(native_handle_, NULL, NULL); | |
| 76 if (native_handle == kInvalidNativeHandle) { | |
| 77 #if V8_OS_POSIX | |
| 78 if (errno == EINTR) continue; // Retry after signal. | |
| 79 #endif | |
| 80 return NULL; | |
| 81 } | |
| 82 return new Socket(native_handle); | |
| 83 } | |
| 84 } | |
| 85 | |
| 86 | |
| 87 bool Socket::Connect(const char* host, const char* port) { | |
| 88 ASSERT_NE(NULL, host); | |
| 89 ASSERT_NE(NULL, port); | |
| 90 if (!IsValid()) return false; | |
| 91 | |
| 92 // Lookup host and port. | |
| 93 struct addrinfo* info = NULL; | |
| 94 struct addrinfo hint; | |
| 95 memset(&hint, 0, sizeof(hint)); | |
| 96 hint.ai_family = AF_INET; | |
| 97 hint.ai_socktype = SOCK_STREAM; | |
| 98 hint.ai_protocol = IPPROTO_TCP; | |
| 99 int result = ::getaddrinfo(host, port, &hint, &info); | |
| 100 if (result != 0) { | |
| 101 return false; | |
| 102 } | |
| 103 | |
| 104 // Connect to the host on the given port. | |
| 105 for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) { | |
| 106 // Try to connect using this addr info. | |
| 107 while (true) { | |
| 108 result = ::connect( | |
| 109 native_handle_, ai->ai_addr, static_cast<int>(ai->ai_addrlen)); | |
| 110 if (result == 0) { | |
| 111 freeaddrinfo(info); | |
| 112 return true; | |
| 113 } | |
| 114 #if V8_OS_POSIX | |
| 115 if (errno == EINTR) continue; // Retry after signal. | |
| 116 #endif | |
| 117 break; | |
| 118 } | |
| 119 } | |
| 120 freeaddrinfo(info); | |
| 121 return false; | |
| 122 } | |
| 123 | |
| 124 | |
| 125 bool Socket::Shutdown() { | |
| 126 if (!IsValid()) return false; | |
| 127 // Shutdown socket for both read and write. | |
| 128 #if V8_OS_POSIX | |
| 129 int result = ::shutdown(native_handle_, SHUT_RDWR); | |
| 130 ::close(native_handle_); | |
| 131 #elif V8_OS_WIN | |
| 132 int result = ::shutdown(native_handle_, SD_BOTH); | |
| 133 ::closesocket(native_handle_); | |
| 134 #endif | |
| 135 native_handle_ = kInvalidNativeHandle; | |
| 136 return result == 0; | |
| 137 } | |
| 138 | |
| 139 | |
| 140 int Socket::Send(const char* buffer, int length) { | |
| 141 ASSERT(length <= 0 || buffer != NULL); | |
| 142 if (!IsValid()) return 0; | |
| 143 int offset = 0; | |
| 144 while (offset < length) { | |
| 145 int result = ::send(native_handle_, buffer + offset, length - offset, 0); | |
| 146 if (result == 0) { | |
| 147 break; | |
| 148 } else if (result > 0) { | |
| 149 ASSERT(result <= length - offset); | |
| 150 offset += result; | |
| 151 } else { | |
| 152 #if V8_OS_POSIX | |
| 153 if (errno == EINTR) continue; // Retry after signal. | |
| 154 #endif | |
| 155 return 0; | |
| 156 } | |
| 157 } | |
| 158 return offset; | |
| 159 } | |
| 160 | |
| 161 | |
| 162 int Socket::Receive(char* buffer, int length) { | |
| 163 if (!IsValid()) return 0; | |
| 164 if (length <= 0) return 0; | |
| 165 ASSERT_NE(NULL, buffer); | |
| 166 while (true) { | |
| 167 int result = ::recv(native_handle_, buffer, length, 0); | |
| 168 if (result < 0) { | |
| 169 #if V8_OS_POSIX | |
| 170 if (errno == EINTR) continue; // Retry after signal. | |
| 171 #endif | |
| 172 return 0; | |
| 173 } | |
| 174 return result; | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 | |
| 179 bool Socket::SetReuseAddress(bool reuse_address) { | |
| 180 if (!IsValid()) return 0; | |
| 181 int v = reuse_address ? 1 : 0; | |
| 182 int result = ::setsockopt(native_handle_, SOL_SOCKET, SO_REUSEADDR, | |
| 183 reinterpret_cast<char*>(&v), sizeof(v)); | |
| 184 return result == 0; | |
| 185 } | |
| 186 | |
| 187 | |
| 188 // static | |
| 189 int Socket::GetLastError() { | |
| 190 #if V8_OS_POSIX | |
| 191 return errno; | |
| 192 #elif V8_OS_WIN | |
| 193 // Be sure to initialize the WinSock DLL first. | |
| 194 CallOnce(&initialize_winsock, &InitializeWinsock); | |
| 195 | |
| 196 // Now we can safely perform WSA calls. | |
| 197 return ::WSAGetLastError(); | |
| 198 #endif | |
| 199 } | |
| 200 | |
| 201 } } // namespace v8::internal | |
| OLD | NEW |