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