Home | History | Annotate | Download | only in src
      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