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 #ifdef __solaris__
  37 #include <thread.h>
  38 #else
  39 #include <pthread.h>
  40 #include <poll.h>
  41 #endif
  42 
  43 #include "socket_md.h"
  44 #include "sysSocket.h"
  45 
  46 int
  47 dbgsysListen(int fd, int backlog) {
  48     return listen(fd, backlog);
  49 }
  50 
  51 int
  52 dbgsysConnect(int fd, struct sockaddr *name, socklen_t namelen) {
  53     int rv = connect(fd, name, namelen);
  54     if (rv < 0 && (errno == EINPROGRESS || errno == EINTR)) {
  55         return DBG_EINPROGRESS;
  56     } else {
  57         return rv;
  58     }
  59 }
  60 
  61 int
  62 dbgsysFinishConnect(int fd, int timeout) {
  63     int rv = dbgsysPoll(fd, 0, 1, timeout);
  64     if (rv == 0) {
  65         return DBG_ETIMEOUT;
  66     }
  67     if (rv > 0) {
  68         return 0;
  69     }
  70     return rv;
  71 }
  72 
  73 int
  74 dbgsysAccept(int fd, struct sockaddr *name, socklen_t *namelen) {
  75     int rv;
  76     for (;;) {
  77         rv = accept(fd, name, namelen);
  78         if (rv >= 0) {
  79             return rv;
  80         }
  81         if (errno != ECONNABORTED && errno != EINTR) {
  82             return rv;
  83         }
  84     }
  85 }
  86 
  87 int
  88 dbgsysRecvFrom(int fd, char *buf, size_t nBytes,
  89                   int flags, struct sockaddr *from, socklen_t *fromlen) {
  90     int rv;
  91     do {
  92         rv = recvfrom(fd, buf, nBytes, flags, from, fromlen);
  93     } while (rv == -1 && errno == EINTR);
  94 
  95     return rv;
  96 }
  97 
  98 int
  99 dbgsysSendTo(int fd, char *buf, size_t len,
 100                 int flags, struct sockaddr *to, socklen_t tolen) {
 101     int rv;
 102     do {
 103         rv = sendto(fd, buf, len, flags, to, tolen);
 104     } while (rv == -1 && errno == EINTR);
 105 
 106     return rv;
 107 }
 108 
 109 int
 110 dbgsysRecv(int fd, char *buf, size_t nBytes, int flags) {
 111     int rv;
 112     do {
 113         rv = recv(fd, buf, nBytes, flags);
 114     } while (rv == -1 && errno == EINTR);
 115 
 116     return rv;
 117 }
 118 
 119 int
 120 dbgsysSend(int fd, char *buf, size_t nBytes, int flags) {
 121     int rv;
 122     do {
 123         rv = send(fd, buf, nBytes, flags);
 124     } while (rv == -1 && errno == EINTR);
 125 
 126     return rv;
 127 }
 128 
 129 int
 130 dbgsysGetAddrInfo(const char *hostname, const char *service,
 131                   const struct addrinfo *hints,
 132                   struct addrinfo **results) {
 133     return getaddrinfo(hostname, service, hints, results);
 134 }
 135 
 136 void
 137 dbgsysFreeAddrInfo(struct addrinfo *info) {
 138     freeaddrinfo(info);
 139 }
 140 
 141 unsigned short
 142 dbgsysHostToNetworkShort(unsigned short hostshort) {
 143     return htons(hostshort);
 144 }
 145 
 146 int
 147 dbgsysSocket(int domain, int type, int protocol) {
 148     return socket(domain, type, protocol);
 149 }
 150 
 151 int dbgsysSocketClose(int fd) {
 152     int rv;
 153 
 154     /* AIX recommends to repeat the close call on EINTR */
 155 #if defined(_AIX)
 156     do {
 157         rv = close(fd);
 158     } while (rv == -1 && errno == EINTR);
 159 #else
 160     rv = close(fd);
 161 #endif
 162 
 163     return rv;
 164 }
 165 
 166 int
 167 dbgsysBind(int fd, struct sockaddr *name, socklen_t namelen) {
 168     return bind(fd, name, namelen);
 169 }
 170 
 171 uint32_t
 172 dbgsysHostToNetworkLong(uint32_t hostlong) {
 173     return htonl(hostlong);
 174 }
 175 
 176 unsigned short
 177 dbgsysNetworkToHostShort(unsigned short netshort) {
 178     return ntohs(netshort);
 179 }
 180 
 181 int
 182 dbgsysGetSocketName(int fd, struct sockaddr *name, socklen_t *namelen) {
 183     return getsockname(fd, name, namelen);
 184 }
 185 
 186 uint32_t
 187 dbgsysNetworkToHostLong(uint32_t netlong) {
 188     return ntohl(netlong);
 189 }
 190 
 191 
 192 int
 193 dbgsysSetSocketOption(int fd, jint cmd, jboolean on, jvalue value)
 194 {
 195     if (cmd == TCP_NODELAY) {
 196         struct protoent *proto = getprotobyname("TCP");
 197         int tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
 198         uint32_t onl = (uint32_t)on;
 199 
 200         if (setsockopt(fd, tcp_level, TCP_NODELAY,
 201                        (char *)&onl, sizeof(uint32_t)) < 0) {
 202                 return SYS_ERR;
 203         }
 204     } else if (cmd == SO_LINGER) {
 205         struct linger arg;
 206         arg.l_onoff = on;
 207         arg.l_linger = (on) ? (unsigned short)value.i : 0;
 208         if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
 209                        (char*)&arg, sizeof(arg)) < 0) {
 210           return SYS_ERR;
 211         }
 212     } else if (cmd == SO_SNDBUF) {
 213         jint buflen = value.i;
 214         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
 215                        (char *)&buflen, sizeof(buflen)) < 0) {
 216             return SYS_ERR;
 217         }
 218     } else if (cmd == SO_REUSEADDR) {
 219         int oni = (int)on;
 220         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
 221                        (char *)&oni, sizeof(oni)) < 0) {
 222             return SYS_ERR;
 223 
 224         }
 225     } else {
 226         return SYS_ERR;
 227     }
 228     return SYS_OK;
 229 }
 230 
 231 int
 232 dbgsysConfigureBlocking(int fd, jboolean blocking) {
 233     int flags = fcntl(fd, F_GETFL);
 234 
 235     if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK)) {
 236         return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 237     }
 238     if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK)) {
 239         return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
 240     }
 241     return 0;
 242 }
 243 
 244 int
 245 dbgsysPoll(int fd, jboolean rd, jboolean wr, long timeout) {
 246     struct pollfd fds[1];
 247     int rv;
 248 
 249     fds[0].fd = fd;
 250     fds[0].events = 0;
 251     if (rd) {
 252         fds[0].events |= POLLIN;
 253     }
 254     if (wr) {
 255         fds[0].events |= POLLOUT;
 256     }
 257     fds[0].revents = 0;
 258 
 259     rv = poll(&fds[0], 1, timeout);
 260     if (rv >= 0) {
 261         rv = 0;
 262         if (fds[0].revents & POLLIN) {
 263             rv |= DBG_POLLIN;
 264         }
 265         if (fds[0].revents & POLLOUT) {
 266             rv |= DBG_POLLOUT;
 267         }
 268     }
 269     return rv;
 270 }
 271 
 272 int
 273 dbgsysGetLastIOError(char *buf, jint size) {
 274     char *msg = strerror(errno);
 275     strncpy(buf, msg, size-1);
 276     buf[size-1] = '\0';
 277     return 0;
 278 }
 279 
 280 #ifdef __solaris__
 281 int
 282 dbgsysTlsAlloc() {
 283     thread_key_t tk;
 284     if (thr_keycreate(&tk, NULL)) {
 285         perror("thr_keycreate");
 286         exit(-1);
 287     }
 288     return (int)tk;
 289 }
 290 
 291 void
 292 dbgsysTlsFree(int index) {
 293    /* no-op */
 294 }
 295 
 296 void
 297 dbgsysTlsPut(int index, void *value) {
 298     thr_setspecific((thread_key_t)index, value) ;
 299 }
 300 
 301 void *
 302 dbgsysTlsGet(int index) {
 303     void* r = NULL;
 304     thr_getspecific((thread_key_t)index, &r);
 305     return r;
 306 }
 307 
 308 #else
 309 int
 310 dbgsysTlsAlloc() {
 311     pthread_key_t key;
 312     if (pthread_key_create(&key, NULL)) {
 313         perror("pthread_key_create");
 314         exit(-1);
 315     }
 316     return (int)key;
 317 }
 318 
 319 void
 320 dbgsysTlsFree(int index) {
 321     pthread_key_delete((pthread_key_t)index);
 322 }
 323 
 324 void
 325 dbgsysTlsPut(int index, void *value) {
 326     pthread_setspecific((pthread_key_t)index, value) ;
 327 }
 328 
 329 void *
 330 dbgsysTlsGet(int index) {
 331     return pthread_getspecific((pthread_key_t)index);
 332 }
 333 
 334 #endif
 335 
 336 long
 337 dbgsysCurrentTimeMillis() {
 338     struct timeval t;
 339     gettimeofday(&t, 0);
 340     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
 341 }