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 #ifdef __linux__
  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) {
  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) {
  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     return recvfrom(fd, buf, nBytes, flags, from, fromlen);
  92 }
  93 
  94 int
  95 dbgsysSendTo(int fd, char *buf, int len,
  96                 int flags, struct sockaddr *to, int tolen) {
  97     return sendto(fd, buf, len, flags, to, tolen);
  98 }
  99 
 100 int
 101 dbgsysRecv(int fd, char *buf, int nBytes, int flags) {
 102     return recv(fd, buf, nBytes, flags);
 103 }
 104 
 105 int
 106 dbgsysSend(int fd, char *buf, int nBytes, int flags) {
 107     return send(fd, buf, nBytes, flags);
 108 }
 109 
 110 struct hostent *
 111 dbgsysGetHostByName(char *hostname) {
 112     return gethostbyname(hostname);
 113 }
 114 
 115 unsigned short
 116 dbgsysHostToNetworkShort(unsigned short hostshort) {
 117     return htons(hostshort);
 118 }
 119 
 120 int
 121 dbgsysSocket(int domain, int type, int protocol) {
 122     return socket(domain, type, protocol);
 123 }
 124 
 125 int dbgsysSocketClose(int fd) {
 126     return close(fd);
 127 }
 128 
 129 int
 130 dbgsysBind(int fd, struct sockaddr *name, int namelen) {
 131     return bind(fd, name, namelen);
 132 }
 133 
 134 uint32_t
 135 dbgsysInetAddr(const char* cp) {
 136     return (uint32_t)inet_addr(cp);
 137 }
 138 
 139 uint32_t
 140 dbgsysHostToNetworkLong(uint32_t hostlong) {
 141     return htonl(hostlong);
 142 }
 143 
 144 unsigned short
 145 dbgsysNetworkToHostShort(unsigned short netshort) {
 146     return ntohs(netshort);
 147 }
 148 
 149 int
 150 dbgsysGetSocketName(int fd, struct sockaddr *name, int *namelen) {
 151     return getsockname(fd, name, namelen);
 152 }
 153 
 154 uint32_t
 155 dbgsysNetworkToHostLong(uint32_t netlong) {
 156     return ntohl(netlong);
 157 }
 158 
 159 
 160 int
 161 dbgsysSetSocketOption(int fd, jint cmd, jboolean on, jvalue value)
 162 {
 163     if (cmd == TCP_NODELAY) {
 164         struct protoent *proto = getprotobyname("TCP");
 165         int tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
 166         uint32_t onl = (uint32_t)on;
 167 
 168         if (setsockopt(fd, tcp_level, TCP_NODELAY,
 169                        (char *)&onl, sizeof(uint32_t)) < 0) {
 170                 return SYS_ERR;
 171         }
 172     } else if (cmd == SO_LINGER) {
 173         struct linger arg;
 174         arg.l_onoff = on;
 175 
 176         if(on) {
 177             arg.l_linger = (unsigned short)value.i;
 178             if(setsockopt(fd, SOL_SOCKET, SO_LINGER,
 179                           (char*)&arg, sizeof(arg)) < 0) {
 180                 return SYS_ERR;
 181             }
 182         } else {
 183             if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
 184                            (char*)&arg, sizeof(arg)) < 0) {
 185                 return SYS_ERR;
 186             }
 187         }
 188     } else if (cmd == SO_SNDBUF) {
 189         jint buflen = value.i;
 190         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
 191                        (char *)&buflen, sizeof(buflen)) < 0) {
 192             return SYS_ERR;
 193         }
 194     } else if (cmd == SO_REUSEADDR) {
 195         int oni = (int)on;
 196         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
 197                        (char *)&oni, sizeof(oni)) < 0) {
 198             return SYS_ERR;
 199 
 200         }
 201     } else {
 202         return SYS_ERR;
 203     }
 204     return SYS_OK;
 205 }
 206 
 207 int
 208 dbgsysConfigureBlocking(int fd, jboolean blocking) {
 209     int flags = fcntl(fd, F_GETFL);
 210 
 211     if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK)) {
 212         return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 213     }
 214     if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK)) {
 215         return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
 216     }
 217     return 0;
 218 }
 219 
 220 int
 221 dbgsysPoll(int fd, jboolean rd, jboolean wr, long timeout) {
 222     struct pollfd fds[1];
 223     int rv;
 224 
 225     fds[0].fd = fd;
 226     fds[0].events = 0;
 227     if (rd) {
 228         fds[0].events |= POLLIN;
 229     }
 230     if (wr) {
 231         fds[0].events |= POLLOUT;
 232     }
 233     fds[0].revents = 0;
 234 
 235     rv = poll(&fds[0], 1, timeout);
 236     if (rv >= 0) {
 237         rv = 0;
 238         if (fds[0].revents & POLLIN) {
 239             rv |= DBG_POLLIN;
 240         }
 241         if (fds[0].revents & POLLOUT) {
 242             rv |= DBG_POLLOUT;
 243         }
 244     }
 245     return rv;
 246 }
 247 
 248 int
 249 dbgsysGetLastIOError(char *buf, jint size) {
 250     char *msg = strerror(errno);
 251     strncpy(buf, msg, size-1);
 252     buf[size-1] = '\0';
 253     return 0;
 254 }
 255 
 256 #ifdef __solaris__
 257 int
 258 dbgsysTlsAlloc() {
 259     thread_key_t tk;
 260     if (thr_keycreate(&tk, NULL)) {
 261         perror("thr_keycreate");
 262         exit(-1);
 263     }
 264     return (int)tk;
 265 }
 266 
 267 void
 268 dbgsysTlsFree(int index) {
 269    /* no-op */
 270 }
 271 
 272 void
 273 dbgsysTlsPut(int index, void *value) {
 274     thr_setspecific((thread_key_t)index, value) ;
 275 }
 276 
 277 void *
 278 dbgsysTlsGet(int index) {
 279     void* r = NULL;
 280     thr_getspecific((thread_key_t)index, &r);
 281     return r;
 282 }
 283 
 284 #endif
 285 
 286 #ifdef __linux__
 287 int
 288 dbgsysTlsAlloc() {
 289     pthread_key_t key;
 290     if (pthread_key_create(&key, NULL)) {
 291         perror("pthread_key_create");
 292         exit(-1);
 293     }
 294     return (int)key;
 295 }
 296 
 297 void
 298 dbgsysTlsFree(int index) {
 299     pthread_key_delete((pthread_key_t)index);
 300 }
 301 
 302 void
 303 dbgsysTlsPut(int index, void *value) {
 304     pthread_setspecific((pthread_key_t)index, value) ;
 305 }
 306 
 307 void *
 308 dbgsysTlsGet(int index) {
 309     return pthread_getspecific((pthread_key_t)index);
 310 }
 311 
 312 #endif
 313 
 314 long
 315 dbgsysCurrentTimeMillis() {
 316     struct timeval t;
 317     gettimeofday(&t, 0);
 318     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
 319 }