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