1 /*
   2  * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 //
  26 // Because the interruptible IO has been dropped for HotSpot/Linux,
  27 // the following HPI interface is very different from HotSparc.
  28 //
  29 
  30 #include <unistd.h>
  31 #include <sys/socket.h>
  32 #include <sys/poll.h>
  33 #include <sys/ioctl.h>
  34 #include <netdb.h>
  35 
  36 // HPI_FileInterface
  37 
  38 inline int hpi::close(int fd) {
  39   return ::close(fd);
  40 }
  41 
  42 inline size_t hpi::read(int fd, void *buf, unsigned int nBytes) {
  43   size_t res;
  44   RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res);
  45   return res;
  46 }
  47 
  48 inline size_t hpi::write(int fd, const void *buf, unsigned int nBytes) {
  49   size_t res;
  50   RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
  51   return res;
  52 }
  53 
  54 
  55 // HPI_SocketInterface
  56 
  57 inline int hpi::socket_close(int fd) {
  58   return ::close(fd);
  59 }
  60 
  61 inline int hpi::socket(int domain, int type, int protocol) {
  62   return ::socket(domain, type, protocol);
  63 }
  64 
  65 inline int hpi::recv(int fd, char *buf, int nBytes, int flags) {
  66   RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, (unsigned int) flags));
  67 }
  68 
  69 inline int hpi::send(int fd, char *buf, int nBytes, int flags) {
  70   RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, (unsigned int) flags));
  71 }
  72 
  73 inline int hpi::raw_send(int fd, char *buf, int nBytes, int flags) {
  74   return send(fd, buf, nBytes, flags);
  75 }
  76 
  77 inline int hpi::timeout(int fd, long timeout) {
  78   julong prevtime,newtime;
  79   struct timeval t;
  80 
  81   gettimeofday(&t, NULL);
  82   prevtime = ((julong)t.tv_sec * 1000)  +  t.tv_usec / 1000;
  83 
  84   for(;;) {
  85     struct pollfd pfd;
  86 
  87     pfd.fd = fd;
  88     pfd.events = POLLIN | POLLERR;
  89 
  90     int res = ::poll(&pfd, 1, timeout);
  91 
  92     if (res == OS_ERR && errno == EINTR) {
  93 
  94       // On Linux any value < 0 means "forever"
  95 
  96       if(timeout >= 0) {
  97         gettimeofday(&t, NULL);
  98         newtime = ((julong)t.tv_sec * 1000)  +  t.tv_usec / 1000;
  99         timeout -= newtime - prevtime;
 100         if(timeout <= 0)
 101           return OS_OK;
 102         prevtime = newtime;
 103       }
 104     } else
 105       return res;
 106   }
 107 }
 108 
 109 inline int hpi::listen(int fd, int count) {
 110   return ::listen(fd, count);
 111 }
 112 
 113 inline int hpi::connect(int fd, struct sockaddr *him, int len) {
 114   RESTARTABLE_RETURN_INT(::connect(fd, him, len));
 115 }
 116 
 117 inline int hpi::accept(int fd, struct sockaddr *him, int *len) {
 118   // This cast is from int to unsigned int on linux.  Since we
 119   // only pass the parameter "len" around the vm and don't try to
 120   // fetch it's value, this cast is safe for now. The java.net group
 121   // may need and want to change this interface someday if socklen_t goes
 122   // to 64 bits on some platform that we support.
 123   // Linux doc says this can't return EINTR, unlike accept() on Solaris
 124 
 125   return ::accept(fd, him, (socklen_t *)len);
 126 }
 127 
 128 inline int hpi::recvfrom(int fd, char *buf, int nBytes, int flags,
 129                          sockaddr *from, int *fromlen) {
 130   RESTARTABLE_RETURN_INT(::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen));
 131 }
 132 
 133 inline int hpi::sendto(int fd, char *buf, int len, int flags,
 134                         struct sockaddr *to, int tolen) {
 135   RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen));
 136 }
 137 
 138 inline int hpi::socket_available(int fd, jint *pbytes) {
 139   // Linux doc says EINTR not returned, unlike Solaris
 140   int ret = ::ioctl(fd, FIONREAD, pbytes);
 141 
 142   //%% note ioctl can return 0 when successful, JVM_SocketAvailable
 143   // is expected to return 0 on failure and 1 on success to the jdk.
 144   return (ret < 0) ? 0 : 1;
 145 }
 146 
 147 
 148 // following methods have been updated to avoid problems in
 149 // hpi's sockets calls based on sys_api_td.c (JDK1.3)
 150 
 151 /*
 152 HPIDECL(socket_shutdown, "socket_shutdown", _socket, SocketShutdown,
 153         int, "%d",
 154         (int fd, int howto),
 155         ("fd = %d, howto = %d", fd, howto),
 156         (fd, howto));
 157         */
 158 inline int hpi::socket_shutdown(int fd, int howto){
 159   return ::shutdown(fd, howto);
 160 }
 161 
 162 /*
 163 HPIDECL(bind, "bind", _socket, Bind,
 164         int, "%d",
 165         (int fd, struct sockaddr *him, int len),
 166         ("fd = %d, him = %p, len = %d",
 167          fd, him, len),
 168         (fd, him, len));
 169 */
 170 inline int hpi::bind(int fd, struct sockaddr *him, int len){
 171   return ::bind(fd, him, len);
 172 }
 173 
 174 /*
 175 HPIDECL(get_sock_name, "get_sock_name", _socket, GetSocketName,
 176         int, "%d",
 177         (int fd, struct sockaddr *him, int *len),
 178         ("fd = %d, him = %p, len = %p",
 179          fd, him, len),
 180         (fd, him, len));
 181         */
 182 inline int hpi::get_sock_name(int fd, struct sockaddr *him, int *len){
 183   return ::getsockname(fd, him, (socklen_t *)len);
 184 }
 185 
 186 /*
 187 HPIDECL(get_host_name, "get_host_name", _socket, GetHostName, int, "%d",
 188         (char *hostname, int namelen),
 189         ("hostname = %p, namelen = %d",
 190          hostname, namelen),
 191         (hostname, namelen));
 192         */
 193 inline int hpi::get_host_name(char* name, int namelen){
 194   return ::gethostname(name, namelen);
 195 }
 196 
 197 /*
 198 HPIDECL(get_sock_opt, "get_sock_opt", _socket, SocketGetOption, int, "%d",
 199         (int fd, int level, int optname, char *optval, int* optlen),
 200         ("fd = %d, level = %d, optname = %d, optval = %p, optlen = %p",
 201          fd, level, optname, optval, optlen),
 202         (fd, level, optname, optval, optlen));
 203         */
 204 inline int hpi::get_sock_opt(int fd, int level, int optname,
 205                              char *optval, int* optlen){
 206   return ::getsockopt(fd, level, optname, optval, (socklen_t *)optlen);
 207 }
 208 
 209 /*
 210 HPIDECL(set_sock_opt, "set_sock_opt", _socket, SocketSetOption, int, "%d",
 211         (int fd, int level, int optname, const char *optval, int optlen),
 212         ("fd = %d, level = %d, optname = %d, optval = %p, optlen = %d",
 213          fd, level, optname, optval, optlen),
 214         (fd, level, optname, optval, optlen));
 215         */
 216 inline int hpi::set_sock_opt(int fd, int level, int optname,
 217                              const char *optval, int optlen){
 218   return ::setsockopt(fd, level, optname, optval, optlen);
 219 }
 220 
 221 
 222 // Reconciliation History
 223 // hpi_solaris.hpp      1.9 99/08/30 16:31:23
 224 // End