1 // Copyright 2009 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 // Platform specific code for POSIX goes here. This is not a platform on its 29 // own but contains the parts which are the same across POSIX platforms Linux, 30 // Mac OS, FreeBSD and OpenBSD. 31 32 #include <unistd.h> 33 #include <errno.h> 34 #include <time.h> 35 36 #include <sys/socket.h> 37 #include <sys/resource.h> 38 #include <sys/time.h> 39 #include <sys/types.h> 40 41 #include <arpa/inet.h> 42 #include <netinet/in.h> 43 #include <netdb.h> 44 45 #if defined(ANDROID) 46 #define LOG_TAG "v8" 47 #include <utils/Log.h> // LOG_PRI_VA 48 #endif 49 50 #include "v8.h" 51 52 #include "platform.h" 53 54 namespace v8 { 55 namespace internal { 56 57 // ---------------------------------------------------------------------------- 58 // Math functions 59 60 double modulo(double x, double y) { 61 return fmod(x, y); 62 } 63 64 65 double OS::nan_value() { 66 // NAN from math.h is defined in C99 and not in POSIX. 67 return NAN; 68 } 69 70 71 // ---------------------------------------------------------------------------- 72 // POSIX date/time support. 73 // 74 75 int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { 76 struct rusage usage; 77 78 if (getrusage(RUSAGE_SELF, &usage) < 0) return -1; 79 *secs = usage.ru_utime.tv_sec; 80 *usecs = usage.ru_utime.tv_usec; 81 return 0; 82 } 83 84 85 double OS::TimeCurrentMillis() { 86 struct timeval tv; 87 if (gettimeofday(&tv, NULL) < 0) return 0.0; 88 return (static_cast<double>(tv.tv_sec) * 1000) + 89 (static_cast<double>(tv.tv_usec) / 1000); 90 } 91 92 93 int64_t OS::Ticks() { 94 // gettimeofday has microsecond resolution. 95 struct timeval tv; 96 if (gettimeofday(&tv, NULL) < 0) 97 return 0; 98 return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec; 99 } 100 101 102 double OS::DaylightSavingsOffset(double time) { 103 if (isnan(time)) return nan_value(); 104 time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 105 struct tm* t = localtime(&tv); 106 if (NULL == t) return nan_value(); 107 return t->tm_isdst > 0 ? 3600 * msPerSecond : 0; 108 } 109 110 111 // ---------------------------------------------------------------------------- 112 // POSIX stdio support. 113 // 114 115 FILE* OS::FOpen(const char* path, const char* mode) { 116 return fopen(path, mode); 117 } 118 119 120 const char* OS::LogFileOpenMode = "w"; 121 122 123 void OS::Print(const char* format, ...) { 124 va_list args; 125 va_start(args, format); 126 VPrint(format, args); 127 va_end(args); 128 } 129 130 131 void OS::VPrint(const char* format, va_list args) { 132 #if defined(ANDROID) 133 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args); 134 #else 135 vprintf(format, args); 136 #endif 137 } 138 139 140 void OS::PrintError(const char* format, ...) { 141 va_list args; 142 va_start(args, format); 143 VPrintError(format, args); 144 va_end(args); 145 } 146 147 148 void OS::VPrintError(const char* format, va_list args) { 149 #if defined(ANDROID) 150 LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args); 151 #else 152 vfprintf(stderr, format, args); 153 #endif 154 } 155 156 157 int OS::SNPrintF(Vector<char> str, const char* format, ...) { 158 va_list args; 159 va_start(args, format); 160 int result = VSNPrintF(str, format, args); 161 va_end(args); 162 return result; 163 } 164 165 166 int OS::VSNPrintF(Vector<char> str, 167 const char* format, 168 va_list args) { 169 int n = vsnprintf(str.start(), str.length(), format, args); 170 if (n < 0 || n >= str.length()) { 171 str[str.length() - 1] = '\0'; 172 return -1; 173 } else { 174 return n; 175 } 176 } 177 178 179 // ---------------------------------------------------------------------------- 180 // POSIX string support. 181 // 182 183 char* OS::StrChr(char* str, int c) { 184 return strchr(str, c); 185 } 186 187 188 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { 189 strncpy(dest.start(), src, n); 190 } 191 192 193 // ---------------------------------------------------------------------------- 194 // POSIX socket support. 195 // 196 197 class POSIXSocket : public Socket { 198 public: 199 explicit POSIXSocket() { 200 // Create the socket. 201 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 202 } 203 explicit POSIXSocket(int socket): socket_(socket) { } 204 virtual ~POSIXSocket() { Shutdown(); } 205 206 // Server initialization. 207 bool Bind(const int port); 208 bool Listen(int backlog) const; 209 Socket* Accept() const; 210 211 // Client initialization. 212 bool Connect(const char* host, const char* port); 213 214 // Shutdown socket for both read and write. 215 bool Shutdown(); 216 217 // Data Transimission 218 int Send(const char* data, int len) const; 219 int Receive(char* data, int len) const; 220 221 bool SetReuseAddress(bool reuse_address); 222 223 bool IsValid() const { return socket_ != -1; } 224 225 private: 226 int socket_; 227 }; 228 229 230 bool POSIXSocket::Bind(const int port) { 231 if (!IsValid()) { 232 return false; 233 } 234 235 sockaddr_in addr; 236 memset(&addr, 0, sizeof(addr)); 237 addr.sin_family = AF_INET; 238 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 239 addr.sin_port = htons(port); 240 int status = bind(socket_, 241 reinterpret_cast<struct sockaddr *>(&addr), 242 sizeof(addr)); 243 return status == 0; 244 } 245 246 247 bool POSIXSocket::Listen(int backlog) const { 248 if (!IsValid()) { 249 return false; 250 } 251 252 int status = listen(socket_, backlog); 253 return status == 0; 254 } 255 256 257 Socket* POSIXSocket::Accept() const { 258 if (!IsValid()) { 259 return NULL; 260 } 261 262 int socket = accept(socket_, NULL, NULL); 263 if (socket == -1) { 264 return NULL; 265 } else { 266 return new POSIXSocket(socket); 267 } 268 } 269 270 271 bool POSIXSocket::Connect(const char* host, const char* port) { 272 if (!IsValid()) { 273 return false; 274 } 275 276 // Lookup host and port. 277 struct addrinfo *result = NULL; 278 struct addrinfo hints; 279 memset(&hints, 0, sizeof(addrinfo)); 280 hints.ai_family = AF_INET; 281 hints.ai_socktype = SOCK_STREAM; 282 hints.ai_protocol = IPPROTO_TCP; 283 int status = getaddrinfo(host, port, &hints, &result); 284 if (status != 0) { 285 return false; 286 } 287 288 // Connect. 289 status = connect(socket_, result->ai_addr, result->ai_addrlen); 290 freeaddrinfo(result); 291 return status == 0; 292 } 293 294 295 bool POSIXSocket::Shutdown() { 296 if (IsValid()) { 297 // Shutdown socket for both read and write. 298 int status = shutdown(socket_, SHUT_RDWR); 299 close(socket_); 300 socket_ = -1; 301 return status == 0; 302 } 303 return true; 304 } 305 306 307 int POSIXSocket::Send(const char* data, int len) const { 308 int status = send(socket_, data, len, 0); 309 return status; 310 } 311 312 313 int POSIXSocket::Receive(char* data, int len) const { 314 int status = recv(socket_, data, len, 0); 315 return status; 316 } 317 318 319 bool POSIXSocket::SetReuseAddress(bool reuse_address) { 320 int on = reuse_address ? 1 : 0; 321 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 322 return status == 0; 323 } 324 325 326 bool Socket::Setup() { 327 // Nothing to do on POSIX. 328 return true; 329 } 330 331 332 int Socket::LastError() { 333 return errno; 334 } 335 336 337 uint16_t Socket::HToN(uint16_t value) { 338 return htons(value); 339 } 340 341 342 uint16_t Socket::NToH(uint16_t value) { 343 return ntohs(value); 344 } 345 346 347 uint32_t Socket::HToN(uint32_t value) { 348 return htonl(value); 349 } 350 351 352 uint32_t Socket::NToH(uint32_t value) { 353 return ntohl(value); 354 } 355 356 357 Socket* OS::CreateSocket() { 358 return new POSIXSocket(); 359 } 360 361 362 } } // namespace v8::internal 363