1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
* contributor license agreements. See the NOTICE file distributed with
3
* this work for additional information regarding copyright ownership.
4
* The ASF licenses this file to You under the Apache License, Version 2.0
5
* (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
/** UNIX AF_LOCAL network wrapper
20
* @version $Revision: 466585 $, $Date: 2006-10-22 00:16:34 +0200 (Sun, 22 Oct 2006) $
25
#include "apr_thread_mutex.h"
28
/* ### should be tossed in favor of APR */
30
#include <sys/un.h> /* for sockaddr_un */
32
#ifdef TCN_DO_STATISTICS
33
#include "apr_atomic.h"
35
static volatile apr_uint32_t uxp_created = 0;
36
static volatile apr_uint32_t uxp_closed = 0;
37
static volatile apr_uint32_t uxp_cleared = 0;
38
static volatile apr_uint32_t uxp_accepted = 0;
40
void uxp_network_dump_statistics()
42
fprintf(stderr, "NT Network Statistics ..\n");
43
fprintf(stderr, "Sockets created : %d\n", uxp_created);
44
fprintf(stderr, "Sockets accepted : %d\n", uxp_accepted);
45
fprintf(stderr, "Sockets closed : %d\n", uxp_closed);
46
fprintf(stderr, "Sockets cleared : %d\n", uxp_cleared);
51
#define DEFNAME "/var/run/tomcatnativesock"
52
#define DEFNAME_FMT "/var/run/tomcatnativesock%08x%08x"
54
#define DEFTIMEOUT 60000
56
#define TCN_UXP_UNKNOWN 0
57
#define TCN_UXP_CLIENT 1
58
#define TCN_UXP_ACCEPTED 2
59
#define TCN_UXP_SERVER 3
61
#define TCN_UNIX_MAXPATH 1024
64
apr_socket_t *sock; /* APR socket */
66
struct sockaddr_un uxaddr;
68
int mode; /* Client or server mode */
69
char name[TCN_UNIX_MAXPATH+1];
72
static apr_status_t APR_THREAD_FUNC
73
uxp_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
75
tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
79
con->timeout = (int)(apr_time_as_msec(t));
83
static apr_status_t APR_THREAD_FUNC
84
uxp_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
86
tcn_uxp_conn_t *con = (tcn_uxp_conn_t*)sock;
90
*t = con->timeout * 1000;
94
static APR_INLINE apr_status_t APR_THREAD_FUNC
95
uxp_socket_opt_set(apr_socket_t *sock, apr_int32_t opt, apr_int32_t on)
97
tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
98
return apr_socket_opt_set(con->sock, opt, on);
101
static APR_INLINE apr_status_t APR_THREAD_FUNC
102
uxp_socket_opt_get(apr_socket_t *sock, apr_int32_t opt, apr_int32_t *on)
104
tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
105
return apr_socket_opt_get(con->sock, opt, on);
108
static apr_status_t uxp_cleanup(void *data)
110
tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)data;
114
apr_socket_close(con->sock);
117
if (con->mode == TCN_UXP_SERVER) {
119
con->mode = TCN_UXP_UNKNOWN;
123
#ifdef TCN_DO_STATISTICS
124
apr_atomic_inc32(&uxp_cleared);
129
static apr_status_t APR_THREAD_FUNC
130
uxp_socket_shutdown(apr_socket_t *sock, apr_shutdown_how_e how)
132
tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
133
return apr_socket_shutdown(con->sock, how);
136
static apr_status_t APR_THREAD_FUNC
137
uxp_socket_close(apr_socket_t *sock)
139
#ifdef TCN_DO_STATISTICS
140
apr_atomic_inc32(&uxp_closed);
142
return uxp_cleanup(sock);
145
static apr_status_t APR_THREAD_FUNC
146
uxp_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len)
148
tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
149
return apr_socket_recv(con->sock, buf, len);
153
static apr_status_t APR_THREAD_FUNC
154
uxp_socket_send(apr_socket_t *sock, const char *buf,
157
tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
158
return apr_socket_send(con->sock, buf, len);
161
static apr_status_t APR_THREAD_FUNC
162
uxp_socket_sendv(apr_socket_t *sock,
163
const struct iovec *vec,
164
apr_int32_t nvec, apr_size_t *len)
166
tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
167
return apr_socket_sendv(con->sock, vec, nvec, len);
170
static apr_status_t uxp_socket_cleanup(void *data)
172
tcn_socket_t *s = (tcn_socket_t *)data;
174
if (s->net->cleanup) {
175
(*s->net->cleanup)(s->opaque);
176
s->net->cleanup = NULL;
178
#ifdef TCN_DO_STATISTICS
179
apr_atomic_inc32(&uxp_cleared);
184
static tcn_nlayer_t uxp_socket_layer = {
191
uxp_socket_timeout_get,
192
uxp_socket_timeout_set,
198
TCN_IMPLEMENT_CALL(jlong, Local, create)(TCN_STDARGS, jstring name,
201
apr_pool_t *p = J2P(pool, apr_pool_t *);
202
tcn_socket_t *s = NULL;
203
tcn_uxp_conn_t *con = NULL;
205
TCN_ALLOC_CSTRING(name);
208
TCN_ASSERT(pool != 0);
210
if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
211
tcn_ThrowAPRException(e, apr_get_netos_error());
214
#ifdef TCN_DO_STATISTICS
217
con = (tcn_uxp_conn_t *)apr_pcalloc(p, sizeof(tcn_uxp_conn_t));
219
con->mode = TCN_UXP_UNKNOWN;
220
con->timeout = DEFTIMEOUT;
222
con->uxaddr.sun_family = AF_UNIX;
224
strcpy(con->uxaddr.sun_path, J2S(name));
225
TCN_FREE_CSTRING(name);
228
strcpy(con->uxaddr.sun_path, DEFNAME);
229
s = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t));
231
s->net = &uxp_socket_layer;
233
apr_pool_cleanup_register(p, (const void *)s,
235
apr_pool_cleanup_null);
237
apr_os_sock_put(&(con->sock), &(con->sd), p);
243
TCN_IMPLEMENT_CALL(jint, Local, bind)(TCN_STDARGS, jlong sock,
246
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
247
UNREFERENCED_STDARGS;
249
TCN_ASSERT(sock != 0);
250
if (s->net->type == TCN_SOCKET_UNIX) {
252
tcn_uxp_conn_t *c = (tcn_uxp_conn_t *)s->opaque;
253
c->mode = TCN_UXP_SERVER;
254
rc = bind(c->sd, (struct sockaddr *)&(c->uxaddr), sizeof(c->uxaddr));
264
TCN_IMPLEMENT_CALL(jint, Local, listen)(TCN_STDARGS, jlong sock,
267
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
268
UNREFERENCED_STDARGS;
270
TCN_ASSERT(sock != 0);
271
if (s->net->type == TCN_SOCKET_UNIX) {
272
tcn_uxp_conn_t *c = (tcn_uxp_conn_t *)s->opaque;
273
c->mode = TCN_UXP_SERVER;
274
return apr_socket_listen(c->sock, (apr_int32_t)backlog);
280
TCN_IMPLEMENT_CALL(jlong, Local, accept)(TCN_STDARGS, jlong sock)
282
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
283
apr_pool_t *p = NULL;
284
tcn_socket_t *a = NULL;
285
tcn_uxp_conn_t *con = NULL;
288
TCN_ASSERT(sock != 0);
290
TCN_THROW_IF_ERR(apr_pool_create(&p, s->pool), p);
291
if (s->net->type == TCN_SOCKET_UNIX) {
293
tcn_uxp_conn_t *c = (tcn_uxp_conn_t *)s->opaque;
294
con = (tcn_uxp_conn_t *)apr_pcalloc(p, sizeof(tcn_uxp_conn_t));
296
con->mode = TCN_UXP_ACCEPTED;
297
con->timeout = c->timeout;
298
len = sizeof(c->uxaddr);
299
/* Block until a client connects */
300
con->sd = accept(c->sd, (struct sockaddr *)&(con->uxaddr), &len);
302
tcn_ThrowAPRException(e, apr_get_os_error());
307
tcn_ThrowAPRException(e, APR_ENOTIMPL);
311
#ifdef TCN_DO_STATISTICS
312
apr_atomic_inc32(&uxp_accepted);
314
a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t));
316
a->net = &uxp_socket_layer;
318
apr_pool_cleanup_register(p, (const void *)a,
320
apr_pool_cleanup_null);
321
apr_os_sock_put(&(con->sock), &(con->sd), p);
330
TCN_IMPLEMENT_CALL(jint, Local, connect)(TCN_STDARGS, jlong sock,
333
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
334
tcn_uxp_conn_t *con = NULL;
339
TCN_ASSERT(sock != 0);
340
if (s->net->type != TCN_SOCKET_UNIX)
342
con = (tcn_uxp_conn_t *)s->opaque;
343
if (con->mode != TCN_UXP_UNKNOWN)
346
rc = connect(con->sd, (const struct sockaddr *)&(con->uxaddr),
347
sizeof(con->uxaddr));
348
} while (rc == -1 && errno == EINTR);
350
if (rc == -1 && errno != EISCONN)
352
con->mode = TCN_UXP_CLIENT;