1 /* 2 * Copyright (c) 1998, 2013, 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 200 if(on) { 201 arg.l_linger = (unsigned short)value.i; 202 if(setsockopt(fd, SOL_SOCKET, SO_LINGER, 203 (char*)&arg, sizeof(arg)) < 0) { 204 return SYS_ERR; 205 } 206 } else { 207 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, 208 (char*)&arg, sizeof(arg)) < 0) { 209 return SYS_ERR; 210 } 211 } 212 } else if (cmd == SO_SNDBUF) { 213 jint buflen = value.i; 214 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, 215 (char *)&buflen, sizeof(buflen)) < 0) { 216 return SYS_ERR; 217 } 218 } else if (cmd == SO_REUSEADDR) { 219 int oni = (int)on; 220 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 221 (char *)&oni, sizeof(oni)) < 0) { 222 return SYS_ERR; 223 224 } 225 } else { 226 return SYS_ERR; 227 } 228 return SYS_OK; 229 } 230 231 int 232 dbgsysConfigureBlocking(int fd, jboolean blocking) { 233 int flags = fcntl(fd, F_GETFL); 234 235 if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK)) { 236 return fcntl(fd, F_SETFL, flags | O_NONBLOCK); 237 } 238 if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK)) { 239 return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 240 } 241 return 0; 242 } 243 244 int 245 dbgsysPoll(int fd, jboolean rd, jboolean wr, long timeout) { 246 struct pollfd fds[1]; 247 int rv; 248 249 fds[0].fd = fd; 250 fds[0].events = 0; 251 if (rd) { 252 fds[0].events |= POLLIN; 253 } 254 if (wr) { 255 fds[0].events |= POLLOUT; 256 } 257 fds[0].revents = 0; 258 259 rv = poll(&fds[0], 1, timeout); 260 if (rv >= 0) { 261 rv = 0; 262 if (fds[0].revents & POLLIN) { 263 rv |= DBG_POLLIN; 264 } 265 if (fds[0].revents & POLLOUT) { 266 rv |= DBG_POLLOUT; 267 } 268 } 269 return rv; 270 } 271 272 int 273 dbgsysGetLastIOError(char *buf, jint size) { 274 char *msg = strerror(errno); 275 strncpy(buf, msg, size-1); 276 buf[size-1] = '\0'; 277 return 0; 278 } 279 280 #ifdef __solaris__ 281 int 282 dbgsysTlsAlloc() { 283 thread_key_t tk; 284 if (thr_keycreate(&tk, NULL)) { 285 perror("thr_keycreate"); 286 exit(-1); 287 } 288 return (int)tk; 289 } 290 291 void 292 dbgsysTlsFree(int index) { 293 /* no-op */ 294 } 295 296 void 297 dbgsysTlsPut(int index, void *value) { 298 thr_setspecific((thread_key_t)index, value) ; 299 } 300 301 void * 302 dbgsysTlsGet(int index) { 303 void* r = NULL; 304 thr_getspecific((thread_key_t)index, &r); 305 return r; 306 } 307 308 #else 309 int 310 dbgsysTlsAlloc() { 311 pthread_key_t key; 312 if (pthread_key_create(&key, NULL)) { 313 perror("pthread_key_create"); 314 exit(-1); 315 } 316 return (int)key; 317 } 318 319 void 320 dbgsysTlsFree(int index) { 321 pthread_key_delete((pthread_key_t)index); 322 } 323 324 void 325 dbgsysTlsPut(int index, void *value) { 326 pthread_setspecific((pthread_key_t)index, value) ; 327 } 328 329 void * 330 dbgsysTlsGet(int index) { 331 return pthread_getspecific((pthread_key_t)index); 332 } 333 334 #endif 335 336 long 337 dbgsysCurrentTimeMillis() { 338 struct timeval t; 339 gettimeofday(&t, 0); 340 return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000); 341 } 342