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