1 /*
   2  * Copyright (c) 1998, 2019, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdlib.h>
  27 #include <sys/types.h>
  28 #include <sys/socket.h>
  29 #include <netinet/in.h>
  30 #include <arpa/inet.h>
  31 #include <unistd.h>
  32 #include <fcntl.h>
  33 #include <errno.h>
  34 #include <string.h>
  35 #include <sys/time.h>
  36 #include <pthread.h>
  37 #include <poll.h>
  38 
  39 #include "socket_md.h"
  40 #include "sysSocket.h"
  41 
  42 int
  43 dbgsysListen(int fd, int backlog) {
  44     return listen(fd, backlog);
  45 }
  46 
  47 int
  48 dbgsysConnect(int fd, struct sockaddr *name, socklen_t namelen) {
  49     int rv = connect(fd, name, namelen);
  50     if (rv < 0 && (errno == EINPROGRESS || errno == EINTR)) {
  51         return DBG_EINPROGRESS;
  52     } else {
  53         return rv;
  54     }
  55 }
  56 
  57 int
  58 dbgsysFinishConnect(int fd, int timeout) {
  59     int rv = dbgsysPoll(fd, 0, 1, timeout);
  60     if (rv == 0) {
  61         return DBG_ETIMEOUT;
  62     }
  63     if (rv > 0) {
  64         return 0;
  65     }
  66     return rv;
  67 }
  68 
  69 int
  70 dbgsysAccept(int fd, struct sockaddr *name, socklen_t *namelen) {
  71     int rv;
  72     for (;;) {
  73         rv = accept(fd, name, namelen);
  74         if (rv >= 0) {
  75             return rv;
  76         }
  77         if (errno != ECONNABORTED && errno != EINTR) {
  78             return rv;
  79         }
  80     }
  81 }
  82 
  83 int
  84 dbgsysRecvFrom(int fd, char *buf, size_t nBytes,
  85                   int flags, struct sockaddr *from, socklen_t *fromlen) {
  86     int rv;
  87     do {
  88         rv = recvfrom(fd, buf, nBytes, flags, from, fromlen);
  89     } while (rv == -1 && errno == EINTR);
  90 
  91     return rv;
  92 }
  93 
  94 int
  95 dbgsysSendTo(int fd, char *buf, size_t len,
  96                 int flags, struct sockaddr *to, socklen_t tolen) {
  97     int rv;
  98     do {
  99         rv = sendto(fd, buf, len, flags, to, tolen);
 100     } while (rv == -1 && errno == EINTR);
 101 
 102     return rv;
 103 }
 104 
 105 int
 106 dbgsysRecv(int fd, char *buf, size_t nBytes, int flags) {
 107     int rv;
 108     do {
 109         rv = recv(fd, buf, nBytes, flags);
 110     } while (rv == -1 && errno == EINTR);
 111 
 112     return rv;
 113 }
 114 
 115 int
 116 dbgsysSend(int fd, char *buf, size_t nBytes, int flags) {
 117     int rv;
 118     do {
 119         rv = send(fd, buf, nBytes, flags);
 120     } while (rv == -1 && errno == EINTR);
 121 
 122     return rv;
 123 }
 124 
 125 int
 126 dbgsysGetAddrInfo(const char *hostname, const char *service,
 127                   const struct addrinfo *hints,
 128                   struct addrinfo **results) {
 129     return getaddrinfo(hostname, service, hints, results);
 130 }
 131 
 132 void
 133 dbgsysFreeAddrInfo(struct addrinfo *info) {
 134     freeaddrinfo(info);
 135 }
 136 
 137 unsigned short
 138 dbgsysHostToNetworkShort(unsigned short hostshort) {
 139     return htons(hostshort);
 140 }
 141 
 142 int
 143 dbgsysSocket(int domain, int type, int protocol) {
 144     return socket(domain, type, protocol);
 145 }
 146 
 147 int dbgsysSocketClose(int fd) {
 148     int rv;
 149 
 150     /* AIX recommends to repeat the close call on EINTR */
 151 #if defined(_AIX)
 152     do {
 153         rv = close(fd);
 154     } while (rv == -1 && errno == EINTR);
 155 #else
 156     rv = close(fd);
 157 #endif
 158 
 159     return rv;
 160 }
 161 
 162 int
 163 dbgsysBind(int fd, struct sockaddr *name, socklen_t namelen) {
 164     return bind(fd, name, namelen);
 165 }
 166 
 167 uint32_t
 168 dbgsysHostToNetworkLong(uint32_t hostlong) {
 169     return htonl(hostlong);
 170 }
 171 
 172 unsigned short
 173 dbgsysNetworkToHostShort(unsigned short netshort) {
 174     return ntohs(netshort);
 175 }
 176 
 177 int
 178 dbgsysGetSocketName(int fd, struct sockaddr *name, socklen_t *namelen) {
 179     return getsockname(fd, name, namelen);
 180 }
 181 
 182 uint32_t
 183 dbgsysNetworkToHostLong(uint32_t netlong) {
 184     return ntohl(netlong);
 185 }
 186 
 187 
 188 int
 189 dbgsysSetSocketOption(int fd, jint cmd, jboolean on, jvalue value)
 190 {
 191     if (cmd == TCP_NODELAY) {
 192         struct protoent *proto = getprotobyname("TCP");
 193         int tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
 194         uint32_t onl = (uint32_t)on;
 195 
 196         if (setsockopt(fd, tcp_level, TCP_NODELAY,
 197                        (char *)&onl, sizeof(uint32_t)) < 0) {
 198                 return SYS_ERR;
 199         }
 200     } else if (cmd == SO_LINGER) {
 201         struct linger arg;
 202         arg.l_onoff = on;
 203         arg.l_linger = (on) ? (unsigned short)value.i : 0;
 204         if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
 205                        (char*)&arg, sizeof(arg)) < 0) {
 206           return SYS_ERR;
 207         }
 208     } else if (cmd == SO_SNDBUF) {
 209         jint buflen = value.i;
 210         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
 211                        (char *)&buflen, sizeof(buflen)) < 0) {
 212             return SYS_ERR;
 213         }
 214     } else if (cmd == SO_REUSEADDR) {
 215         int oni = (int)on;
 216         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
 217                        (char *)&oni, sizeof(oni)) < 0) {
 218             return SYS_ERR;
 219 
 220         }
 221     } else {
 222         return SYS_ERR;
 223     }
 224     return SYS_OK;
 225 }
 226 
 227 int
 228 dbgsysConfigureBlocking(int fd, jboolean blocking) {
 229     int flags = fcntl(fd, F_GETFL);
 230 
 231     if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK)) {
 232         return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 233     }
 234     if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK)) {
 235         return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
 236     }
 237     return 0;
 238 }
 239 
 240 int
 241 dbgsysPoll(int fd, jboolean rd, jboolean wr, long timeout) {
 242     struct pollfd fds[1];
 243     int rv;
 244 
 245     fds[0].fd = fd;
 246     fds[0].events = 0;
 247     if (rd) {
 248         fds[0].events |= POLLIN;
 249     }
 250     if (wr) {
 251         fds[0].events |= POLLOUT;
 252     }
 253     fds[0].revents = 0;
 254 
 255     rv = poll(&fds[0], 1, timeout);
 256     if (rv >= 0) {
 257         rv = 0;
 258         if (fds[0].revents & POLLIN) {
 259             rv |= DBG_POLLIN;
 260         }
 261         if (fds[0].revents & POLLOUT) {
 262             rv |= DBG_POLLOUT;
 263         }
 264     }
 265     return rv;
 266 }
 267 
 268 int
 269 dbgsysGetLastIOError(char *buf, jint size) {
 270     char *msg = strerror(errno);
 271     strncpy(buf, msg, size-1);
 272     buf[size-1] = '\0';
 273     return 0;
 274 }
 275 
 276 int
 277 dbgsysTlsAlloc() {
 278     pthread_key_t key;
 279     if (pthread_key_create(&key, NULL)) {
 280         perror("pthread_key_create");
 281         exit(-1);
 282     }
 283     return (int)key;
 284 }
 285 
 286 void
 287 dbgsysTlsFree(int index) {
 288     pthread_key_delete((pthread_key_t)index);
 289 }
 290 
 291 void
 292 dbgsysTlsPut(int index, void *value) {
 293     pthread_setspecific((pthread_key_t)index, value) ;
 294 }
 295 
 296 void *
 297 dbgsysTlsGet(int index) {
 298     return pthread_getspecific((pthread_key_t)index);
 299 }
 300 
 301 long
 302 dbgsysCurrentTimeMillis() {
 303     struct timeval t;
 304     gettimeofday(&t, 0);
 305     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
 306 }