platform-posix.cc revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
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 and FreeBSD. 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 54namespace v8 { 55namespace internal { 56 57 58// ---------------------------------------------------------------------------- 59// POSIX date/time support. 60// 61 62int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { 63 struct rusage usage; 64 65 if (getrusage(RUSAGE_SELF, &usage) < 0) return -1; 66 *secs = usage.ru_utime.tv_sec; 67 *usecs = usage.ru_utime.tv_usec; 68 return 0; 69} 70 71 72double OS::TimeCurrentMillis() { 73 struct timeval tv; 74 if (gettimeofday(&tv, NULL) < 0) return 0.0; 75 return (static_cast<double>(tv.tv_sec) * 1000) + 76 (static_cast<double>(tv.tv_usec) / 1000); 77} 78 79 80int64_t OS::Ticks() { 81 // gettimeofday has microsecond resolution. 82 struct timeval tv; 83 if (gettimeofday(&tv, NULL) < 0) 84 return 0; 85 return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec; 86} 87 88 89const char* OS::LocalTimezone(double time) { 90 if (isnan(time)) return ""; 91 time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 92 struct tm* t = localtime(&tv); 93 if (NULL == t) return ""; 94 return t->tm_zone; 95} 96 97 98double OS::DaylightSavingsOffset(double time) { 99 if (isnan(time)) return nan_value(); 100 time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 101 struct tm* t = localtime(&tv); 102 if (NULL == t) return nan_value(); 103 return t->tm_isdst > 0 ? 3600 * msPerSecond : 0; 104} 105 106 107double OS::LocalTimeOffset() { 108 time_t tv = time(NULL); 109 struct tm* t = localtime(&tv); 110 // tm_gmtoff includes any daylight savings offset, so subtract it. 111 return static_cast<double>(t->tm_gmtoff * msPerSecond - 112 (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 113} 114 115 116// ---------------------------------------------------------------------------- 117// POSIX stdio support. 118// 119 120FILE* OS::FOpen(const char* path, const char* mode) { 121 return fopen(path, mode); 122} 123 124 125const char* OS::LogFileOpenMode = "w"; 126 127 128void OS::Print(const char* format, ...) { 129 va_list args; 130 va_start(args, format); 131 VPrint(format, args); 132 va_end(args); 133} 134 135 136void OS::VPrint(const char* format, va_list args) { 137#if defined(ANDROID) 138 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args); 139#else 140 vprintf(format, args); 141#endif 142} 143 144 145void OS::PrintError(const char* format, ...) { 146 va_list args; 147 va_start(args, format); 148 VPrintError(format, args); 149 va_end(args); 150} 151 152 153void OS::VPrintError(const char* format, va_list args) { 154#if defined(ANDROID) 155 LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args); 156#else 157 vfprintf(stderr, format, args); 158#endif 159} 160 161 162int OS::SNPrintF(Vector<char> str, const char* format, ...) { 163 va_list args; 164 va_start(args, format); 165 int result = VSNPrintF(str, format, args); 166 va_end(args); 167 return result; 168} 169 170 171int OS::VSNPrintF(Vector<char> str, 172 const char* format, 173 va_list args) { 174 int n = vsnprintf(str.start(), str.length(), format, args); 175 if (n < 0 || n >= str.length()) { 176 str[str.length() - 1] = '\0'; 177 return -1; 178 } else { 179 return n; 180 } 181} 182 183 184// ---------------------------------------------------------------------------- 185// POSIX string support. 186// 187 188char* OS::StrChr(char* str, int c) { 189 return strchr(str, c); 190} 191 192 193void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { 194 strncpy(dest.start(), src, n); 195} 196 197 198// ---------------------------------------------------------------------------- 199// POSIX socket support. 200// 201 202class POSIXSocket : public Socket { 203 public: 204 explicit POSIXSocket() { 205 // Create the socket. 206 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 207 } 208 explicit POSIXSocket(int socket): socket_(socket) { } 209 virtual ~POSIXSocket() { Shutdown(); } 210 211 // Server initialization. 212 bool Bind(const int port); 213 bool Listen(int backlog) const; 214 Socket* Accept() const; 215 216 // Client initialization. 217 bool Connect(const char* host, const char* port); 218 219 // Shutdown socket for both read and write. 220 bool Shutdown(); 221 222 // Data Transimission 223 int Send(const char* data, int len) const; 224 int Receive(char* data, int len) const; 225 226 bool SetReuseAddress(bool reuse_address); 227 228 bool IsValid() const { return socket_ != -1; } 229 230 private: 231 int socket_; 232}; 233 234 235bool POSIXSocket::Bind(const int port) { 236 if (!IsValid()) { 237 return false; 238 } 239 240 sockaddr_in addr; 241 memset(&addr, 0, sizeof(addr)); 242 addr.sin_family = AF_INET; 243 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 244 addr.sin_port = htons(port); 245 int status = bind(socket_, 246 reinterpret_cast<struct sockaddr *>(&addr), 247 sizeof(addr)); 248 return status == 0; 249} 250 251 252bool POSIXSocket::Listen(int backlog) const { 253 if (!IsValid()) { 254 return false; 255 } 256 257 int status = listen(socket_, backlog); 258 return status == 0; 259} 260 261 262Socket* POSIXSocket::Accept() const { 263 if (!IsValid()) { 264 return NULL; 265 } 266 267 int socket = accept(socket_, NULL, NULL); 268 if (socket == -1) { 269 return NULL; 270 } else { 271 return new POSIXSocket(socket); 272 } 273} 274 275 276bool POSIXSocket::Connect(const char* host, const char* port) { 277 if (!IsValid()) { 278 return false; 279 } 280 281 // Lookup host and port. 282 struct addrinfo *result = NULL; 283 struct addrinfo hints; 284 memset(&hints, 0, sizeof(addrinfo)); 285 hints.ai_family = AF_INET; 286 hints.ai_socktype = SOCK_STREAM; 287 hints.ai_protocol = IPPROTO_TCP; 288 int status = getaddrinfo(host, port, &hints, &result); 289 if (status != 0) { 290 return false; 291 } 292 293 // Connect. 294 status = connect(socket_, result->ai_addr, result->ai_addrlen); 295 freeaddrinfo(result); 296 return status == 0; 297} 298 299 300bool POSIXSocket::Shutdown() { 301 if (IsValid()) { 302 // Shutdown socket for both read and write. 303 int status = shutdown(socket_, SHUT_RDWR); 304 close(socket_); 305 socket_ = -1; 306 return status == 0; 307 } 308 return true; 309} 310 311 312int POSIXSocket::Send(const char* data, int len) const { 313 int status = send(socket_, data, len, 0); 314 return status; 315} 316 317 318int POSIXSocket::Receive(char* data, int len) const { 319 int status = recv(socket_, data, len, 0); 320 return status; 321} 322 323 324bool POSIXSocket::SetReuseAddress(bool reuse_address) { 325 int on = reuse_address ? 1 : 0; 326 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 327 return status == 0; 328} 329 330 331bool Socket::Setup() { 332 // Nothing to do on POSIX. 333 return true; 334} 335 336 337int Socket::LastError() { 338 return errno; 339} 340 341 342uint16_t Socket::HToN(uint16_t value) { 343 return htons(value); 344} 345 346 347uint16_t Socket::NToH(uint16_t value) { 348 return ntohs(value); 349} 350 351 352uint32_t Socket::HToN(uint32_t value) { 353 return htonl(value); 354} 355 356 357uint32_t Socket::NToH(uint32_t value) { 358 return ntohl(value); 359} 360 361 362Socket* OS::CreateSocket() { 363 return new POSIXSocket(); 364} 365 366 367} } // namespace v8::internal 368