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