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#ifdef __solaris__
37#include <thread.h>
38#else
39#include <pthread.h>
40#include <poll.h>
41#endif
42
43#include "socket_md.h"
44#include "sysSocket.h"
45
46int
47dbgsysListen(int fd, int backlog) {
48 return listen(fd, backlog);
49}
50
51int
52dbgsysConnect(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
61int
62dbgsysFinishConnect(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
73int
74dbgsysAccept(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
87int
88dbgsysRecvFrom(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
98int
99dbgsysSendTo(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
109int
110dbgsysRecv(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
119int
120dbgsysSend(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
129int
130dbgsysGetAddrInfo(const char *hostname, const char *service,
131 const struct addrinfo *hints,
132 struct addrinfo **results) {
133 return getaddrinfo(hostname, service, hints, results);
134}
135
136void
137dbgsysFreeAddrInfo(struct addrinfo *info) {
138 freeaddrinfo(info);
139}
140
141unsigned short
142dbgsysHostToNetworkShort(unsigned short hostshort) {
143 return htons(hostshort);
144}
145
146int
147dbgsysSocket(int domain, int type, int protocol) {
148 return socket(domain, type, protocol);
149}
150
151int dbgsysSocketClose(int fd) {
152 int rv;
153
154 /* AIX recommends to repeat the close call on EINTR */
155#if defined(_AIX)
156 do {
157 rv = close(fd);
158 } while (rv == -1 && errno == EINTR);
159#else
160 rv = close(fd);
161#endif
162
163 return rv;
164}
165
166int
167dbgsysBind(int fd, struct sockaddr *name, socklen_t namelen) {
168 return bind(fd, name, namelen);
169}
170
171uint32_t
172dbgsysHostToNetworkLong(uint32_t hostlong) {
173 return htonl(hostlong);
174}
175
176unsigned short
177dbgsysNetworkToHostShort(unsigned short netshort) {
178 return ntohs(netshort);
179}
180
181int
182dbgsysGetSocketName(int fd, struct sockaddr *name, socklen_t *namelen) {
183 return getsockname(fd, name, namelen);
184}
185
186uint32_t
187dbgsysNetworkToHostLong(uint32_t netlong) {
188 return ntohl(netlong);
189}
190
191
192int
193dbgsysSetSocketOption(int fd, jint cmd, jboolean on, jvalue value)
194{
195 if (cmd == TCP_NODELAY) {
196 struct protoent *proto = getprotobyname("TCP");
197 int tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
198 uint32_t onl = (uint32_t)on;
199
200 if (setsockopt(fd, tcp_level, TCP_NODELAY,
201 (char *)&onl, sizeof(uint32_t)) < 0) {
202 return SYS_ERR;
203 }
204 } else if (cmd == SO_LINGER) {
205 struct linger arg;
206 arg.l_onoff = on;
207 arg.l_linger = (on) ? (unsigned short)value.i : 0;
208 if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
209 (char*)&arg, sizeof(arg)) < 0) {
210 return SYS_ERR;
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
231int
232dbgsysConfigureBlocking(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
244int
245dbgsysPoll(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
272int
273dbgsysGetLastIOError(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__
281int
282dbgsysTlsAlloc() {
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
291void
292dbgsysTlsFree(int index) {
293 /* no-op */
294}
295
296void
297dbgsysTlsPut(int index, void *value) {
298 thr_setspecific((thread_key_t)index, value) ;
299}
300
301void *
302dbgsysTlsGet(int index) {
303 void* r = NULL;
304 thr_getspecific((thread_key_t)index, &r);
305 return r;
306}
307
308#else
309int
310dbgsysTlsAlloc() {
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
319void
320dbgsysTlsFree(int index) {
321 pthread_key_delete((pthread_key_t)index);
322}
323
324void
325dbgsysTlsPut(int index, void *value) {
326 pthread_setspecific((pthread_key_t)index, value) ;
327}
328
329void *
330dbgsysTlsGet(int index) {
331 return pthread_getspecific((pthread_key_t)index);
332}
333
334#endif
335
336long
337dbgsysCurrentTimeMillis() {
338 struct timeval t;
339 gettimeofday(&t, 0);
340 return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
341}
342