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