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
dbgsysListen(int fd,int backlog)47 dbgsysListen(int fd, int backlog) {
48 return listen(fd, backlog);
49 }
50
51 int
dbgsysConnect(int fd,struct sockaddr * name,socklen_t namelen)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
dbgsysFinishConnect(int fd,int timeout)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
dbgsysAccept(int fd,struct sockaddr * name,socklen_t * namelen)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
dbgsysRecvFrom(int fd,char * buf,size_t nBytes,int flags,struct sockaddr * from,socklen_t * fromlen)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
dbgsysSendTo(int fd,char * buf,size_t len,int flags,struct sockaddr * to,socklen_t tolen)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
dbgsysRecv(int fd,char * buf,size_t nBytes,int flags)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
dbgsysSend(int fd,char * buf,size_t nBytes,int flags)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 *
dbgsysGetHostByName(char * hostname)130 dbgsysGetHostByName(char *hostname) {
131 return gethostbyname(hostname);
132 }
133
134 unsigned short
dbgsysHostToNetworkShort(unsigned short hostshort)135 dbgsysHostToNetworkShort(unsigned short hostshort) {
136 return htons(hostshort);
137 }
138
139 int
dbgsysSocket(int domain,int type,int protocol)140 dbgsysSocket(int domain, int type, int protocol) {
141 return socket(domain, type, protocol);
142 }
143
dbgsysSocketClose(int fd)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
dbgsysBind(int fd,struct sockaddr * name,socklen_t namelen)154 dbgsysBind(int fd, struct sockaddr *name, socklen_t namelen) {
155 return bind(fd, name, namelen);
156 }
157
158 uint32_t
dbgsysInetAddr(const char * cp)159 dbgsysInetAddr(const char* cp) {
160 return (uint32_t)inet_addr(cp);
161 }
162
163 uint32_t
dbgsysHostToNetworkLong(uint32_t hostlong)164 dbgsysHostToNetworkLong(uint32_t hostlong) {
165 return htonl(hostlong);
166 }
167
168 unsigned short
dbgsysNetworkToHostShort(unsigned short netshort)169 dbgsysNetworkToHostShort(unsigned short netshort) {
170 return ntohs(netshort);
171 }
172
173 int
dbgsysGetSocketName(int fd,struct sockaddr * name,socklen_t * namelen)174 dbgsysGetSocketName(int fd, struct sockaddr *name, socklen_t *namelen) {
175 return getsockname(fd, name, namelen);
176 }
177
178 uint32_t
dbgsysNetworkToHostLong(uint32_t netlong)179 dbgsysNetworkToHostLong(uint32_t netlong) {
180 return ntohl(netlong);
181 }
182
183
184 int
dbgsysSetSocketOption(int fd,jint cmd,jboolean on,jvalue value)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
dbgsysConfigureBlocking(int fd,jboolean blocking)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
dbgsysPoll(int fd,jboolean rd,jboolean wr,long timeout)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
dbgsysGetLastIOError(char * buf,jint size)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
dbgsysTlsAlloc()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
dbgsysTlsFree(int index)292 dbgsysTlsFree(int index) {
293 /* no-op */
294 }
295
296 void
dbgsysTlsPut(int index,void * value)297 dbgsysTlsPut(int index, void *value) {
298 thr_setspecific((thread_key_t)index, value) ;
299 }
300
301 void *
dbgsysTlsGet(int index)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
dbgsysTlsAlloc()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
dbgsysTlsFree(int index)320 dbgsysTlsFree(int index) {
321 pthread_key_delete((pthread_key_t)index);
322 }
323
324 void
dbgsysTlsPut(int index,void * value)325 dbgsysTlsPut(int index, void *value) {
326 pthread_setspecific((pthread_key_t)index, value) ;
327 }
328
329 void *
dbgsysTlsGet(int index)330 dbgsysTlsGet(int index) {
331 return pthread_getspecific((pthread_key_t)index);
332 }
333
334 #endif
335
336 long
dbgsysCurrentTimeMillis()337 dbgsysCurrentTimeMillis() {
338 struct timeval t;
339 gettimeofday(&t, 0);
340 return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
341 }
342