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