OLD | NEW |
| (Empty) |
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 | |
7 * | |
8 * http://www.apache.org/licenses/LICENSE-2.0 | |
9 * | |
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. | |
15 */ | |
16 | |
17 /* | |
18 * | |
19 * @author Mladen Turk | |
20 * @version $Id: network.c 1607296 2014-07-02 08:45:42Z kkolinko $ | |
21 */ | |
22 | |
23 #include "tcn.h" | |
24 | |
25 #ifdef TCN_DO_STATISTICS | |
26 | |
27 #include "apr_atomic.h" | |
28 | |
29 static volatile apr_uint32_t sp_created = 0; | |
30 static volatile apr_uint32_t sp_closed = 0; | |
31 static volatile apr_uint32_t sp_cleared = 0; | |
32 static volatile apr_uint32_t sp_accepted = 0; | |
33 static volatile apr_uint32_t sp_max_send = 0; | |
34 static volatile apr_uint32_t sp_min_send = 10000000; | |
35 static volatile apr_uint32_t sp_num_send = 0; | |
36 static volatile apr_off_t sp_tot_send = 0; | |
37 static volatile apr_uint32_t sp_max_recv = 0; | |
38 static volatile apr_uint32_t sp_min_recv = 10000000; | |
39 static volatile apr_uint32_t sp_num_recv = 0; | |
40 static volatile apr_off_t sp_tot_recv = 0; | |
41 static volatile apr_uint32_t sp_err_recv = 0; | |
42 static volatile apr_uint32_t sp_tmo_recv = 0; | |
43 static volatile apr_uint32_t sp_rst_recv = 0; | |
44 static volatile apr_status_t sp_erl_recv = 0; | |
45 | |
46 static volatile apr_size_t sf_max_send = 0; | |
47 static volatile apr_size_t sf_min_send = 10000000; | |
48 static volatile apr_uint32_t sf_num_send = 0; | |
49 static volatile apr_off_t sf_tot_send = 0; | |
50 | |
51 void sp_network_dump_statistics() | |
52 { | |
53 fprintf(stderr, "Network Statistics ......\n"); | |
54 fprintf(stderr, "Sockets created : %d\n", sp_created); | |
55 fprintf(stderr, "Sockets accepted : %d\n", sp_accepted); | |
56 fprintf(stderr, "Sockets closed : %d\n", sp_closed); | |
57 fprintf(stderr, "Sockets cleared : %d\n", sp_cleared); | |
58 fprintf(stderr, "Total send calls : %d\n", sp_num_send); | |
59 fprintf(stderr, "Minimum send length : %d\n", sp_min_send); | |
60 fprintf(stderr, "Maximum send length : %d\n", sp_max_send); | |
61 fprintf(stderr, "Average send length : %.2f\n", (double)sp_tot_send/(dou
ble)sp_num_send); | |
62 fprintf(stderr, "Total recv calls : %d\n", sp_num_recv); | |
63 fprintf(stderr, "Minimum recv length : %d\n", sp_min_recv); | |
64 fprintf(stderr, "Maximum recv length : %d\n", sp_max_recv); | |
65 fprintf(stderr, "Average recv length : %.2f\n", (double)sp_tot_recv/(dou
ble)sp_num_recv); | |
66 fprintf(stderr, "Receive timeouts : %d\n", sp_tmo_recv); | |
67 fprintf(stderr, "Receive errors : %d\n", sp_err_recv); | |
68 fprintf(stderr, "Receive resets : %d\n", sp_rst_recv); | |
69 fprintf(stderr, "Last receive error : %d\n", sp_erl_recv); | |
70 | |
71 fprintf(stderr, "Total sendfile calls : %d\n", sf_num_send); | |
72 fprintf(stderr, "Minimum sendfile length : %" APR_SIZE_T_FMT "\n", sf_min_se
nd); | |
73 fprintf(stderr, "Maximum sendfile length : %" APR_SIZE_T_FMT "\n", sf_max_se
nd); | |
74 | |
75 } | |
76 | |
77 #endif /* TCN_DO_STATISTICS */ | |
78 | |
79 extern apr_pool_t *tcn_global_pool; | |
80 static apr_status_t sp_socket_cleanup(void *data) | |
81 { | |
82 tcn_socket_t *s = (tcn_socket_t *)data; | |
83 | |
84 if (s->net && s->net->cleanup) | |
85 (*s->net->cleanup)(s->opaque); | |
86 if (s->sock) { | |
87 apr_socket_t *as = s->sock; | |
88 s->sock = NULL; | |
89 apr_socket_close(as); | |
90 } | |
91 #ifdef TCN_DO_STATISTICS | |
92 apr_atomic_inc32(&sp_cleared); | |
93 #endif | |
94 return APR_SUCCESS; | |
95 } | |
96 | |
97 #if defined(DEBUG) || defined(_DEBUG) | |
98 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
99 APR_socket_send(apr_socket_t *sock, const char *buf, apr_size_t *len) | |
100 { | |
101 return apr_socket_send(sock, buf, len); | |
102 } | |
103 | |
104 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
105 APR_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len) | |
106 { | |
107 return apr_socket_recv(sock, buf, len); | |
108 } | |
109 | |
110 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
111 APR_socket_sendv(apr_socket_t *sock, const struct iovec *vec, | |
112 apr_int32_t nvec, apr_size_t *len) | |
113 { | |
114 return apr_socket_sendv(sock, vec, nvec, len); | |
115 } | |
116 | |
117 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
118 APR_socket_shutdown(apr_socket_t *sock, apr_shutdown_how_e how) | |
119 { | |
120 return apr_socket_shutdown(sock, how); | |
121 } | |
122 | |
123 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
124 APR_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t) | |
125 { | |
126 return apr_socket_timeout_set(sock, t); | |
127 } | |
128 | |
129 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
130 APR_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t) | |
131 { | |
132 return apr_socket_timeout_get(sock, t); | |
133 } | |
134 | |
135 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
136 APR_socket_opt_set(apr_socket_t *sock, apr_int32_t opt, apr_int32_t on) | |
137 { | |
138 return apr_socket_opt_set(sock, opt, on); | |
139 } | |
140 | |
141 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
142 APR_socket_opt_get(apr_socket_t *sock, apr_int32_t opt, apr_int32_t *on) | |
143 { | |
144 return apr_socket_opt_get(sock, opt, on); | |
145 } | |
146 | |
147 #else | |
148 #define APR_socket_send apr_socket_send | |
149 #define APR_socket_recv apr_socket_recv | |
150 #define APR_socket_sendv apr_socket_sendv | |
151 #define APR_socket_shutdown apr_socket_shutdown | |
152 #define APR_socket_timeout_set apr_socket_timeout_set | |
153 #define APR_socket_timeout_get apr_socket_timeout_get | |
154 #define APR_socket_opt_set apr_socket_opt_set | |
155 #define APR_socket_opt_get apr_socket_opt_get | |
156 #endif | |
157 | |
158 static tcn_nlayer_t apr_socket_layer = { | |
159 TCN_SOCKET_APR, | |
160 NULL, | |
161 NULL, | |
162 APR_socket_shutdown, | |
163 APR_socket_opt_get, | |
164 APR_socket_opt_set, | |
165 APR_socket_timeout_get, | |
166 APR_socket_timeout_set, | |
167 APR_socket_send, | |
168 APR_socket_sendv, | |
169 APR_socket_recv | |
170 }; | |
171 | |
172 TCN_IMPLEMENT_CALL(jlong, Socket, create)(TCN_STDARGS, jint family, | |
173 jint type, jint protocol, | |
174 jlong pool) | |
175 { | |
176 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
177 apr_pool_t *c = NULL; | |
178 apr_socket_t *s = NULL; | |
179 tcn_socket_t *a = NULL; | |
180 apr_int32_t f, t; | |
181 | |
182 UNREFERENCED(o); | |
183 TCN_ASSERT(pool != 0); | |
184 GET_S_FAMILY(f, family); | |
185 GET_S_TYPE(t, type); | |
186 | |
187 TCN_THROW_IF_ERR(apr_pool_create(&c, p), c); | |
188 | |
189 a = (tcn_socket_t *)apr_pcalloc(c, sizeof(tcn_socket_t)); | |
190 TCN_CHECK_ALLOCATED(a); | |
191 TCN_THROW_IF_ERR(apr_pool_create(&a->child, c), a->child); | |
192 a->pool = c; | |
193 | |
194 if (family >= 0) { | |
195 a->net = &apr_socket_layer; | |
196 TCN_THROW_IF_ERR(apr_socket_create(&s, | |
197 f, t, protocol, c), a); | |
198 } | |
199 apr_pool_cleanup_register(c, (const void *)a, | |
200 sp_socket_cleanup, | |
201 apr_pool_cleanup_null); | |
202 | |
203 #ifdef TCN_DO_STATISTICS | |
204 sp_created++; | |
205 #endif | |
206 a->sock = s; | |
207 if (family >= 0) | |
208 a->net = &apr_socket_layer; | |
209 a->opaque = s; | |
210 return P2J(a); | |
211 cleanup: | |
212 if (c) | |
213 apr_pool_destroy(c); | |
214 return 0; | |
215 | |
216 } | |
217 | |
218 TCN_IMPLEMENT_CALL(void, Socket, destroy)(TCN_STDARGS, jlong sock) | |
219 { | |
220 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
221 apr_socket_t *as; | |
222 UNREFERENCED_STDARGS; | |
223 TCN_ASSERT(sock != 0); | |
224 | |
225 as = s->sock; | |
226 s->sock = NULL; | |
227 apr_pool_cleanup_kill(s->pool, s, sp_socket_cleanup); | |
228 if (s->net && s->net->cleanup) { | |
229 (*s->net->cleanup)(s->opaque); | |
230 s->net = NULL; | |
231 } | |
232 if (as) { | |
233 apr_socket_close(as); | |
234 } | |
235 | |
236 apr_pool_destroy(s->pool); | |
237 } | |
238 | |
239 TCN_IMPLEMENT_CALL(jlong, Socket, pool)(TCN_STDARGS, jlong sock) | |
240 { | |
241 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
242 apr_pool_t *n; | |
243 | |
244 UNREFERENCED(o); | |
245 TCN_ASSERT(sock != 0); | |
246 TCN_THROW_IF_ERR(apr_pool_create(&n, s->pool), n); | |
247 cleanup: | |
248 return P2J(n); | |
249 } | |
250 | |
251 TCN_IMPLEMENT_CALL(jlong, Socket, get)(TCN_STDARGS, jlong sock, jint what) | |
252 { | |
253 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
254 UNREFERENCED_STDARGS; | |
255 TCN_ASSERT(sock != 0); | |
256 | |
257 switch (what) { | |
258 case TCN_SOCKET_GET_POOL: | |
259 return P2J(s->pool); | |
260 break; | |
261 case TCN_SOCKET_GET_IMPL: | |
262 return P2J(s->opaque); | |
263 break; | |
264 case TCN_SOCKET_GET_APRS: | |
265 return P2J(s->sock); | |
266 break; | |
267 case TCN_SOCKET_GET_TYPE: | |
268 return (jlong)(s->net->type); | |
269 break; | |
270 } | |
271 return 0; | |
272 } | |
273 | |
274 TCN_IMPLEMENT_CALL(jint, Socket, shutdown)(TCN_STDARGS, jlong sock, | |
275 jint how) | |
276 { | |
277 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
278 | |
279 UNREFERENCED_STDARGS; | |
280 TCN_ASSERT(sock != 0); | |
281 return (jint)(*s->net->shutdown)(s->opaque, how); | |
282 } | |
283 | |
284 TCN_IMPLEMENT_CALL(jint, Socket, close)(TCN_STDARGS, jlong sock) | |
285 { | |
286 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
287 jint rv = APR_SUCCESS; | |
288 apr_socket_t *as; | |
289 UNREFERENCED_STDARGS; | |
290 TCN_ASSERT(sock != 0); | |
291 | |
292 as = s->sock; | |
293 s->sock = NULL; | |
294 apr_pool_cleanup_kill(s->pool, s, sp_socket_cleanup); | |
295 if (s->child) { | |
296 apr_pool_clear(s->child); | |
297 } | |
298 #ifdef TCN_DO_STATISTICS | |
299 apr_atomic_inc32(&sp_closed); | |
300 #endif | |
301 if (s->net && s->net->close) { | |
302 rv = (*s->net->close)(s->opaque); | |
303 s->net = NULL; | |
304 } | |
305 if (as) { | |
306 rv = (jint)apr_socket_close(as); | |
307 } | |
308 return rv; | |
309 } | |
310 | |
311 TCN_IMPLEMENT_CALL(jint, Socket, bind)(TCN_STDARGS, jlong sock, | |
312 jlong sa) | |
313 { | |
314 jint rv = APR_SUCCESS; | |
315 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
316 apr_sockaddr_t *a = J2P(sa, apr_sockaddr_t *); | |
317 | |
318 UNREFERENCED_STDARGS; | |
319 TCN_ASSERT(sock != 0); | |
320 TCN_ASSERT(s->sock != NULL); | |
321 rv = (jint)apr_socket_bind(s->sock, a); | |
322 return rv; | |
323 } | |
324 | |
325 TCN_IMPLEMENT_CALL(jint, Socket, listen)(TCN_STDARGS, jlong sock, | |
326 jint backlog) | |
327 { | |
328 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
329 | |
330 UNREFERENCED_STDARGS; | |
331 TCN_ASSERT(sock != 0); | |
332 TCN_ASSERT(s->sock != NULL); | |
333 return (jint)apr_socket_listen(s->sock, backlog); | |
334 } | |
335 | |
336 TCN_IMPLEMENT_CALL(jlong, Socket, acceptx)(TCN_STDARGS, jlong sock, | |
337 jlong pool) | |
338 { | |
339 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
340 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
341 apr_socket_t *n = NULL; | |
342 tcn_socket_t *a = NULL; | |
343 | |
344 UNREFERENCED(o); | |
345 TCN_ASSERT(sock != 0); | |
346 | |
347 if (s->net->type == TCN_SOCKET_APR) { | |
348 TCN_ASSERT(s->sock != NULL); | |
349 a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t)); | |
350 TCN_CHECK_ALLOCATED(a); | |
351 a->pool = p; | |
352 apr_pool_cleanup_register(a->pool, (const void *)a, | |
353 sp_socket_cleanup, | |
354 apr_pool_cleanup_null); | |
355 | |
356 TCN_THROW_IF_ERR(apr_socket_accept(&n, s->sock, p), n); | |
357 } | |
358 else { | |
359 tcn_ThrowAPRException(e, APR_ENOTIMPL); | |
360 goto cleanup; | |
361 } | |
362 if (n) { | |
363 #ifdef TCN_DO_STATISTICS | |
364 apr_atomic_inc32(&sp_accepted); | |
365 #endif | |
366 a->net = &apr_socket_layer; | |
367 a->sock = n; | |
368 a->opaque = n; | |
369 } | |
370 | |
371 cleanup: | |
372 return P2J(a); | |
373 } | |
374 | |
375 TCN_IMPLEMENT_CALL(jlong, Socket, accept)(TCN_STDARGS, jlong sock) | |
376 { | |
377 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
378 apr_pool_t *p = NULL; | |
379 apr_socket_t *n = NULL; | |
380 tcn_socket_t *a = NULL; | |
381 | |
382 UNREFERENCED(o); | |
383 TCN_ASSERT(sock != 0); | |
384 | |
385 TCN_THROW_IF_ERR(apr_pool_create(&p, s->child), p); | |
386 if (s->net->type == TCN_SOCKET_APR) { | |
387 TCN_ASSERT(s->sock != NULL); | |
388 a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t)); | |
389 TCN_CHECK_ALLOCATED(a); | |
390 TCN_THROW_IF_ERR(apr_socket_accept(&n, s->sock, p), n); | |
391 | |
392 a->pool = p; | |
393 apr_pool_cleanup_register(a->pool, (const void *)a, | |
394 sp_socket_cleanup, | |
395 apr_pool_cleanup_null); | |
396 | |
397 } | |
398 else { | |
399 tcn_ThrowAPRException(e, APR_ENOTIMPL); | |
400 goto cleanup; | |
401 } | |
402 if (n) { | |
403 #ifdef TCN_DO_STATISTICS | |
404 apr_atomic_inc32(&sp_accepted); | |
405 #endif | |
406 a->net = &apr_socket_layer; | |
407 a->sock = n; | |
408 a->opaque = n; | |
409 } | |
410 return P2J(a); | |
411 cleanup: | |
412 if (tcn_global_pool && p && s->sock) | |
413 apr_pool_destroy(p); | |
414 return 0; | |
415 } | |
416 | |
417 TCN_IMPLEMENT_CALL(jint, Socket, connect)(TCN_STDARGS, jlong sock, | |
418 jlong sa) | |
419 { | |
420 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
421 apr_sockaddr_t *a = J2P(sa, apr_sockaddr_t *); | |
422 | |
423 UNREFERENCED_STDARGS; | |
424 TCN_ASSERT(sock != 0); | |
425 TCN_ASSERT(s->sock != NULL); | |
426 return (jint)apr_socket_connect(s->sock, a); | |
427 } | |
428 | |
429 TCN_IMPLEMENT_CALL(jint, Socket, send)(TCN_STDARGS, jlong sock, | |
430 jbyteArray buf, jint offset, jint tosend) | |
431 { | |
432 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
433 apr_size_t nbytes = (apr_size_t)tosend; | |
434 apr_status_t ss; | |
435 | |
436 UNREFERENCED(o); | |
437 if (!sock) { | |
438 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
439 return -(jint)APR_ENOTSOCK; | |
440 } | |
441 TCN_ASSERT(s->opaque != NULL); | |
442 if(!s->net) { | |
443 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
444 return -(jint)APR_EINVALSOCK; | |
445 } | |
446 #ifdef TCN_DO_STATISTICS | |
447 sp_max_send = TCN_MAX(sp_max_send, nbytes); | |
448 sp_min_send = TCN_MIN(sp_min_send, nbytes); | |
449 sp_tot_send += nbytes; | |
450 sp_num_send++; | |
451 #endif | |
452 | |
453 if (tosend <= TCN_BUFFER_SZ) { | |
454 jbyte sb[TCN_BUFFER_SZ]; | |
455 (*e)->GetByteArrayRegion(e, buf, offset, tosend, &sb[0]); | |
456 ss = (*s->net->send)(s->opaque, (const char *)&sb[0], &nbytes); | |
457 } | |
458 else { | |
459 jbyte *sb = (jbyte *)malloc(nbytes); | |
460 if (sb == NULL) | |
461 return -APR_ENOMEM; | |
462 (*e)->GetByteArrayRegion(e, buf, offset, tosend, sb); | |
463 ss = (*s->net->send)(s->opaque, (const char *)sb, &nbytes); | |
464 free(sb); | |
465 } | |
466 if (ss == APR_SUCCESS || ((APR_STATUS_IS_EAGAIN(ss) || ss == TCN_EAGAIN) &&
nbytes > 0)) | |
467 return (jint)nbytes; | |
468 else { | |
469 TCN_ERROR_WRAP(ss); | |
470 return -(jint)ss; | |
471 } | |
472 } | |
473 | |
474 TCN_IMPLEMENT_CALL(void, Socket, setsbb)(TCN_STDARGS, jlong sock, | |
475 jobject buf) | |
476 { | |
477 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
478 UNREFERENCED(o); | |
479 if (!sock) { | |
480 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
481 return; | |
482 } | |
483 TCN_ASSERT(s->opaque != NULL); | |
484 if (buf) | |
485 s->jsbbuff = (char *)(*e)->GetDirectBufferAddress(e, buf); | |
486 else | |
487 s->jsbbuff = NULL; | |
488 } | |
489 | |
490 TCN_IMPLEMENT_CALL(void, Socket, setrbb)(TCN_STDARGS, jlong sock, | |
491 jobject buf) | |
492 { | |
493 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
494 UNREFERENCED(o); | |
495 if (!sock) { | |
496 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
497 return; | |
498 } | |
499 TCN_ASSERT(s->opaque != NULL); | |
500 if (buf) | |
501 s->jrbbuff = (char *)(*e)->GetDirectBufferAddress(e, buf); | |
502 else | |
503 s->jrbbuff = NULL; | |
504 } | |
505 | |
506 TCN_IMPLEMENT_CALL(jint, Socket, sendb)(TCN_STDARGS, jlong sock, | |
507 jobject buf, jint offset, jint len) | |
508 { | |
509 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
510 apr_size_t nbytes = (apr_size_t)len; | |
511 apr_size_t sent = 0; | |
512 char *bytes; | |
513 apr_status_t ss = APR_SUCCESS; | |
514 | |
515 UNREFERENCED(o); | |
516 if (!sock) { | |
517 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
518 return -(jint)APR_ENOTSOCK; | |
519 } | |
520 TCN_ASSERT(s->opaque != NULL); | |
521 TCN_ASSERT(buf != NULL); | |
522 if(!s->net) { | |
523 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
524 return -(jint)APR_EINVALSOCK; | |
525 } | |
526 #ifdef TCN_DO_STATISTICS | |
527 sp_max_send = TCN_MAX(sp_max_send, nbytes); | |
528 sp_min_send = TCN_MIN(sp_min_send, nbytes); | |
529 sp_tot_send += nbytes; | |
530 sp_num_send++; | |
531 #endif | |
532 | |
533 bytes = (char *)(*e)->GetDirectBufferAddress(e, buf); | |
534 | |
535 while (sent < nbytes) { | |
536 apr_size_t wr = nbytes - sent; | |
537 ss = (*s->net->send)(s->opaque, bytes + offset + sent, &wr); | |
538 if (ss != APR_SUCCESS) | |
539 break; | |
540 sent += wr; | |
541 } | |
542 | |
543 if (ss == APR_SUCCESS || ((APR_STATUS_IS_EAGAIN(ss) || ss == TCN_EAGAIN) &&
sent > 0)) | |
544 return (jint)sent; | |
545 else { | |
546 TCN_ERROR_WRAP(ss); | |
547 return -(jint)ss; | |
548 } | |
549 } | |
550 | |
551 TCN_IMPLEMENT_CALL(jint, Socket, sendib)(TCN_STDARGS, jlong sock, | |
552 jobject buf, jint offset, jint len) | |
553 { | |
554 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
555 apr_size_t nbytes = (apr_size_t)len; | |
556 char *bytes; | |
557 apr_status_t ss = APR_SUCCESS; | |
558 | |
559 UNREFERENCED(o); | |
560 if (!sock) { | |
561 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
562 return -(jint)APR_ENOTSOCK; | |
563 } | |
564 TCN_ASSERT(s->opaque != NULL); | |
565 TCN_ASSERT(buf != NULL); | |
566 if(!s->net) { | |
567 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
568 return -(jint)APR_EINVALSOCK; | |
569 } | |
570 #ifdef TCN_DO_STATISTICS | |
571 sp_max_send = TCN_MAX(sp_max_send, nbytes); | |
572 sp_min_send = TCN_MIN(sp_min_send, nbytes); | |
573 sp_tot_send += nbytes; | |
574 sp_num_send++; | |
575 #endif | |
576 | |
577 bytes = (char *)(*e)->GetDirectBufferAddress(e, buf); | |
578 | |
579 ss = (*s->net->send)(s->opaque, bytes + offset, &nbytes); | |
580 | |
581 if (ss == APR_SUCCESS || ((APR_STATUS_IS_EAGAIN(ss) || ss == TCN_EAGAIN) &&
nbytes > 0)) | |
582 return (jint)nbytes; | |
583 else { | |
584 TCN_ERROR_WRAP(ss); | |
585 return -(jint)ss; | |
586 } | |
587 } | |
588 | |
589 TCN_IMPLEMENT_CALL(jint, Socket, sendbb)(TCN_STDARGS, jlong sock, | |
590 jint offset, jint len) | |
591 { | |
592 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
593 apr_size_t nbytes = (apr_size_t)len; | |
594 apr_size_t sent = 0; | |
595 apr_status_t ss = APR_SUCCESS; | |
596 | |
597 UNREFERENCED(o); | |
598 if (!sock) { | |
599 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
600 return -(jint)APR_ENOTSOCK; | |
601 } | |
602 TCN_ASSERT(s->opaque != NULL); | |
603 TCN_ASSERT(s->jsbbuff != NULL); | |
604 if(!s->net) { | |
605 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
606 return -(jint)APR_EINVALSOCK; | |
607 } | |
608 #ifdef TCN_DO_STATISTICS | |
609 sp_max_send = TCN_MAX(sp_max_send, nbytes); | |
610 sp_min_send = TCN_MIN(sp_min_send, nbytes); | |
611 sp_tot_send += nbytes; | |
612 sp_num_send++; | |
613 #endif | |
614 | |
615 while (sent < nbytes) { | |
616 apr_size_t wr = nbytes - sent; | |
617 ss = (*s->net->send)(s->opaque, s->jsbbuff + offset + sent, &wr); | |
618 if (ss != APR_SUCCESS || wr == 0) | |
619 break; | |
620 sent += wr; | |
621 } | |
622 if (ss == APR_SUCCESS || ((APR_STATUS_IS_EAGAIN(ss) || ss == TCN_EAGAIN) &&
sent > 0)) | |
623 return (jint)sent; | |
624 else { | |
625 TCN_ERROR_WRAP(ss); | |
626 return -(jint)ss; | |
627 } | |
628 } | |
629 | |
630 TCN_IMPLEMENT_CALL(jint, Socket, sendibb)(TCN_STDARGS, jlong sock, | |
631 jint offset, jint len) | |
632 { | |
633 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
634 apr_size_t nbytes = (apr_size_t)len; | |
635 apr_status_t ss = APR_SUCCESS; | |
636 | |
637 UNREFERENCED(o); | |
638 if (!sock) { | |
639 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
640 return -(jint)APR_ENOTSOCK; | |
641 } | |
642 TCN_ASSERT(s->opaque != NULL); | |
643 TCN_ASSERT(s->jsbbuff != NULL); | |
644 if(!s->net) { | |
645 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
646 return -(jint)APR_EINVALSOCK; | |
647 } | |
648 #ifdef TCN_DO_STATISTICS | |
649 sp_max_send = TCN_MAX(sp_max_send, nbytes); | |
650 sp_min_send = TCN_MIN(sp_min_send, nbytes); | |
651 sp_tot_send += nbytes; | |
652 sp_num_send++; | |
653 #endif | |
654 | |
655 ss = (*s->net->send)(s->opaque, s->jsbbuff + offset, &nbytes); | |
656 | |
657 if (ss == APR_SUCCESS || ((APR_STATUS_IS_EAGAIN(ss) || ss == TCN_EAGAIN) &&
nbytes > 0)) | |
658 return (jint)nbytes; | |
659 else { | |
660 TCN_ERROR_WRAP(ss); | |
661 return -(jint)ss; | |
662 } | |
663 } | |
664 | |
665 TCN_IMPLEMENT_CALL(jint, Socket, sendv)(TCN_STDARGS, jlong sock, | |
666 jobjectArray bufs) | |
667 { | |
668 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
669 jsize nvec; | |
670 jsize i; | |
671 struct iovec vec[APR_MAX_IOVEC_SIZE]; | |
672 jobject ba[APR_MAX_IOVEC_SIZE]; | |
673 apr_size_t written = 0; | |
674 apr_status_t ss; | |
675 | |
676 UNREFERENCED(o); | |
677 TCN_ASSERT(sock != 0); | |
678 TCN_ASSERT(s->opaque != NULL); | |
679 if(!s->net) { | |
680 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
681 return -(jint)APR_EINVALSOCK; | |
682 } | |
683 | |
684 nvec = (*e)->GetArrayLength(e, bufs); | |
685 if (nvec >= APR_MAX_IOVEC_SIZE) | |
686 return (jint)(-APR_ENOMEM); | |
687 | |
688 for (i = 0; i < nvec; i++) { | |
689 ba[i] = (*e)->GetObjectArrayElement(e, bufs, i); | |
690 vec[i].iov_len = (*e)->GetArrayLength(e, ba[i]); | |
691 vec[i].iov_base = (void *)((*e)->GetByteArrayElements(e, ba[i], NULL)); | |
692 } | |
693 | |
694 ss = (*s->net->sendv)(s->opaque, vec, nvec, &written); | |
695 | |
696 for (i = 0; i < nvec; i++) { | |
697 (*e)->ReleaseByteArrayElements(e, ba[i], (jbyte*)vec[i].iov_base, JNI_AB
ORT); | |
698 } | |
699 if (ss == APR_SUCCESS || ((APR_STATUS_IS_EAGAIN(ss) || ss == TCN_EAGAIN) &&
written > 0)) | |
700 return (jint)written; | |
701 else { | |
702 TCN_ERROR_WRAP(ss); | |
703 return -(jint)ss; | |
704 } | |
705 } | |
706 | |
707 TCN_IMPLEMENT_CALL(jint, Socket, sendto)(TCN_STDARGS, jlong sock, | |
708 jlong where, jint flag, | |
709 jbyteArray buf, jint offset, jint tosen
d) | |
710 { | |
711 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
712 apr_sockaddr_t *w = J2P(where, apr_sockaddr_t *); | |
713 apr_size_t nbytes = (apr_size_t)tosend; | |
714 jbyte *bytes; | |
715 apr_int32_t nb; | |
716 apr_status_t ss; | |
717 | |
718 UNREFERENCED(o); | |
719 TCN_ASSERT(sock != 0); | |
720 TCN_ASSERT(s->sock != NULL); | |
721 | |
722 apr_socket_opt_get(s->sock, APR_SO_NONBLOCK, &nb); | |
723 if (nb) | |
724 bytes = (*e)->GetPrimitiveArrayCritical(e, buf, NULL); | |
725 else | |
726 bytes = (*e)->GetByteArrayElements(e, buf, NULL); | |
727 TCN_ASSERT(bytes != NULL); | |
728 ss = apr_socket_sendto(s->sock, w, flag, (char *)(bytes + offset), &nbytes); | |
729 | |
730 if (nb) | |
731 (*e)->ReleasePrimitiveArrayCritical(e, buf, bytes, 0); | |
732 else | |
733 (*e)->ReleaseByteArrayElements(e, buf, bytes, JNI_ABORT); | |
734 if (ss == APR_SUCCESS) | |
735 return (jint)nbytes; | |
736 else { | |
737 TCN_ERROR_WRAP(ss); | |
738 return -(jint)ss; | |
739 } | |
740 } | |
741 | |
742 TCN_IMPLEMENT_CALL(jint, Socket, recv)(TCN_STDARGS, jlong sock, | |
743 jbyteArray buf, jint offset, jint toread) | |
744 { | |
745 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
746 apr_size_t nbytes = (apr_size_t)toread; | |
747 apr_status_t ss; | |
748 | |
749 UNREFERENCED(o); | |
750 TCN_ASSERT(sock != 0); | |
751 TCN_ASSERT(s->opaque != NULL); | |
752 if(!s->net) { | |
753 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
754 return -(jint)APR_EINVALSOCK; | |
755 } | |
756 | |
757 if (toread <= TCN_BUFFER_SZ) { | |
758 char sb[TCN_BUFFER_SZ]; | |
759 | |
760 if ((ss = (*s->net->recv)(s->opaque, sb, &nbytes)) == APR_SUCCESS) | |
761 (*e)->SetByteArrayRegion(e, buf, offset, (jsize)nbytes, (jbyte*)&sb[
0]); | |
762 } | |
763 else { | |
764 jbyte *bytes = (*e)->GetByteArrayElements(e, buf, NULL); | |
765 if ((ss = (*s->net->recv)(s->opaque, (char*)(bytes + offset), | |
766 &nbytes)) == APR_SUCCESS) | |
767 (*e)->ReleaseByteArrayElements(e, buf, bytes, | |
768 nbytes ? 0 : JNI_ABORT); | |
769 } | |
770 #ifdef TCN_DO_STATISTICS | |
771 if (ss == APR_SUCCESS) { | |
772 sp_max_recv = TCN_MAX(sp_max_recv, nbytes); | |
773 sp_min_recv = TCN_MIN(sp_min_recv, nbytes); | |
774 sp_tot_recv += nbytes; | |
775 sp_num_recv++; | |
776 } | |
777 else { | |
778 if (APR_STATUS_IS_ETIMEDOUT(ss) || | |
779 APR_STATUS_IS_TIMEUP(ss)) | |
780 sp_tmo_recv++; | |
781 else if (APR_STATUS_IS_ECONNABORTED(ss) || | |
782 APR_STATUS_IS_ECONNRESET(ss) || | |
783 APR_STATUS_IS_EOF(ss)) | |
784 sp_rst_recv++; | |
785 else { | |
786 sp_err_recv++; | |
787 sp_erl_recv = ss; | |
788 } | |
789 } | |
790 #endif | |
791 if (ss == APR_SUCCESS) | |
792 return (jint)nbytes; | |
793 else { | |
794 TCN_ERROR_WRAP(ss); | |
795 return -(jint)ss; | |
796 } | |
797 } | |
798 | |
799 TCN_IMPLEMENT_CALL(jint, Socket, recvt)(TCN_STDARGS, jlong sock, | |
800 jbyteArray buf, jint offset, | |
801 jint toread, jlong timeout) | |
802 { | |
803 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
804 apr_size_t nbytes = (apr_size_t)toread; | |
805 apr_status_t ss; | |
806 apr_interval_time_t pt; | |
807 apr_interval_time_t nt = J2T(timeout); | |
808 | |
809 UNREFERENCED(o); | |
810 TCN_ASSERT(sock != 0); | |
811 TCN_ASSERT(s->opaque != NULL); | |
812 TCN_ASSERT(buf != NULL); | |
813 if(!s->net) { | |
814 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
815 return -(jint)APR_EINVALSOCK; | |
816 } | |
817 | |
818 if ((ss = (*s->net->timeout_get)(s->opaque, &pt)) != APR_SUCCESS) { | |
819 TCN_ERROR_WRAP(ss); | |
820 return -(jint)ss; | |
821 } | |
822 if (pt != nt) { | |
823 if ((ss = (*s->net->timeout_set)(s->opaque, nt)) != APR_SUCCESS) | |
824 goto cleanup; | |
825 } | |
826 if (toread <= TCN_BUFFER_SZ) { | |
827 jbyte sb[TCN_BUFFER_SZ]; | |
828 if ((ss = (*s->net->recv)(s->opaque, (char *)&sb[0], &nbytes)) == APR_SU
CCESS) | |
829 (*e)->SetByteArrayRegion(e, buf, offset, (jsize)nbytes, &sb[0]); | |
830 } | |
831 else { | |
832 jbyte *sb = (jbyte *)malloc(nbytes); | |
833 if (sb == NULL) | |
834 return -APR_ENOMEM; | |
835 if ((ss = (*s->net->recv)(s->opaque, (char *)sb, &nbytes)) == APR_SUCCES
S) | |
836 (*e)->SetByteArrayRegion(e, buf, offset, (jsize)nbytes, &sb[0]); | |
837 free(sb); | |
838 } | |
839 if (pt != nt) { | |
840 if ((ss = (*s->net->timeout_set)(s->opaque, pt)) != APR_SUCCESS) | |
841 goto cleanup; | |
842 } | |
843 | |
844 #ifdef TCN_DO_STATISTICS | |
845 if (ss == APR_SUCCESS) { | |
846 sp_max_recv = TCN_MAX(sp_max_recv, nbytes); | |
847 sp_min_recv = TCN_MIN(sp_min_recv, nbytes); | |
848 sp_tot_recv += nbytes; | |
849 sp_num_recv++; | |
850 } | |
851 else { | |
852 if (APR_STATUS_IS_ETIMEDOUT(ss) || | |
853 APR_STATUS_IS_TIMEUP(ss)) | |
854 sp_tmo_recv++; | |
855 else if (APR_STATUS_IS_ECONNABORTED(ss) || | |
856 APR_STATUS_IS_ECONNRESET(ss) || | |
857 APR_STATUS_IS_EOF(ss)) | |
858 sp_rst_recv++; | |
859 else { | |
860 sp_err_recv++; | |
861 sp_erl_recv = ss; | |
862 } | |
863 } | |
864 #endif | |
865 cleanup: | |
866 if (ss == APR_SUCCESS) | |
867 return (jint)nbytes; | |
868 else { | |
869 TCN_ERROR_WRAP(ss); | |
870 return -(jint)ss; | |
871 } | |
872 } | |
873 | |
874 TCN_IMPLEMENT_CALL(jint, Socket, recvb)(TCN_STDARGS, jlong sock, | |
875 jobject buf, jint offset, jint len) | |
876 { | |
877 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
878 apr_status_t ss; | |
879 apr_size_t nbytes = (apr_size_t)len; | |
880 char *bytes; | |
881 | |
882 UNREFERENCED(o); | |
883 if (!sock) { | |
884 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
885 return -(jint)APR_ENOTSOCK; | |
886 } | |
887 TCN_ASSERT(s->opaque != NULL); | |
888 TCN_ASSERT(buf != NULL); | |
889 if(!s->net) { | |
890 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
891 return -(jint)APR_EINVALSOCK; | |
892 } | |
893 | |
894 bytes = (char *)(*e)->GetDirectBufferAddress(e, buf); | |
895 TCN_ASSERT(bytes != NULL); | |
896 ss = (*s->net->recv)(s->opaque, bytes + offset, &nbytes); | |
897 #ifdef TCN_DO_STATISTICS | |
898 if (ss == APR_SUCCESS) { | |
899 sp_max_recv = TCN_MAX(sp_max_recv, nbytes); | |
900 sp_min_recv = TCN_MIN(sp_min_recv, nbytes); | |
901 sp_tot_recv += nbytes; | |
902 sp_num_recv++; | |
903 } | |
904 else { | |
905 if (APR_STATUS_IS_ETIMEDOUT(ss) || | |
906 APR_STATUS_IS_TIMEUP(ss)) | |
907 sp_tmo_recv++; | |
908 else if (APR_STATUS_IS_ECONNABORTED(ss) || | |
909 APR_STATUS_IS_ECONNRESET(ss) || | |
910 APR_STATUS_IS_EOF(ss)) | |
911 sp_rst_recv++; | |
912 else { | |
913 sp_err_recv++; | |
914 sp_erl_recv = ss; | |
915 } | |
916 } | |
917 #endif | |
918 if (ss == APR_SUCCESS) | |
919 return (jint)nbytes; | |
920 else { | |
921 TCN_ERROR_WRAP(ss); | |
922 return -(jint)ss; | |
923 } | |
924 } | |
925 | |
926 TCN_IMPLEMENT_CALL(jint, Socket, recvbb)(TCN_STDARGS, jlong sock, | |
927 jint offset, jint len) | |
928 { | |
929 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
930 apr_status_t ss; | |
931 apr_size_t nbytes = (apr_size_t)len; | |
932 | |
933 UNREFERENCED(o); | |
934 if (!sock) { | |
935 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
936 return -(jint)APR_ENOTSOCK; | |
937 } | |
938 TCN_ASSERT(sock != 0); | |
939 TCN_ASSERT(s->opaque != NULL); | |
940 TCN_ASSERT(s->jrbbuff != NULL); | |
941 if(!s->net) { | |
942 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
943 return -(jint)APR_EINVALSOCK; | |
944 } | |
945 | |
946 ss = (*s->net->recv)(s->opaque, s->jrbbuff + offset, &nbytes); | |
947 #ifdef TCN_DO_STATISTICS | |
948 if (ss == APR_SUCCESS) { | |
949 sp_max_recv = TCN_MAX(sp_max_recv, nbytes); | |
950 sp_min_recv = TCN_MIN(sp_min_recv, nbytes); | |
951 sp_tot_recv += nbytes; | |
952 sp_num_recv++; | |
953 } | |
954 else { | |
955 if (APR_STATUS_IS_ETIMEDOUT(ss) || | |
956 APR_STATUS_IS_TIMEUP(ss)) | |
957 sp_tmo_recv++; | |
958 else if (APR_STATUS_IS_ECONNABORTED(ss) || | |
959 APR_STATUS_IS_ECONNRESET(ss) || | |
960 APR_STATUS_IS_EOF(ss)) | |
961 sp_rst_recv++; | |
962 else { | |
963 sp_err_recv++; | |
964 sp_erl_recv = ss; | |
965 } | |
966 } | |
967 #endif | |
968 if (ss == APR_SUCCESS) | |
969 return (jint)nbytes; | |
970 else if (APR_STATUS_IS_EOF(ss)) | |
971 return 0; | |
972 else { | |
973 TCN_ERROR_WRAP(ss); | |
974 return -(jint)ss; | |
975 } | |
976 } | |
977 | |
978 TCN_IMPLEMENT_CALL(jint, Socket, recvbt)(TCN_STDARGS, jlong sock, | |
979 jobject buf, jint offset, | |
980 jint len, jlong timeout) | |
981 { | |
982 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
983 apr_status_t ss; | |
984 apr_size_t nbytes = (apr_size_t)len; | |
985 char *bytes; | |
986 apr_interval_time_t pt; | |
987 apr_interval_time_t nt = J2T(timeout); | |
988 | |
989 UNREFERENCED(o); | |
990 if (!sock) { | |
991 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
992 return -(jint)APR_ENOTSOCK; | |
993 } | |
994 TCN_ASSERT(buf != NULL); | |
995 TCN_ASSERT(s->opaque != NULL); | |
996 if(!s->net) { | |
997 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
998 return -(jint)APR_EINVALSOCK; | |
999 } | |
1000 | |
1001 bytes = (char *)(*e)->GetDirectBufferAddress(e, buf); | |
1002 TCN_ASSERT(bytes != NULL); | |
1003 | |
1004 if ((ss = (*s->net->timeout_get)(s->opaque, &pt)) != APR_SUCCESS) { | |
1005 TCN_ERROR_WRAP(ss); | |
1006 return -(jint)ss; | |
1007 } | |
1008 if (pt != nt) { | |
1009 if ((ss = (*s->net->timeout_set)(s->opaque, nt)) != APR_SUCCESS) { | |
1010 TCN_ERROR_WRAP(ss); | |
1011 return -(jint)ss; | |
1012 } | |
1013 } | |
1014 ss = (*s->net->recv)(s->opaque, bytes + offset, &nbytes); | |
1015 if (pt != nt) { | |
1016 if ((ss = (*s->net->timeout_set)(s->opaque, pt)) != APR_SUCCESS) { | |
1017 TCN_ERROR_WRAP(ss); | |
1018 return -(jint)ss; | |
1019 } | |
1020 } | |
1021 | |
1022 #ifdef TCN_DO_STATISTICS | |
1023 if (ss == APR_SUCCESS) { | |
1024 sp_max_recv = TCN_MAX(sp_max_recv, nbytes); | |
1025 sp_min_recv = TCN_MIN(sp_min_recv, nbytes); | |
1026 sp_tot_recv += nbytes; | |
1027 sp_num_recv++; | |
1028 } | |
1029 else { | |
1030 if (APR_STATUS_IS_ETIMEDOUT(ss) || | |
1031 APR_STATUS_IS_TIMEUP(ss)) | |
1032 sp_tmo_recv++; | |
1033 else if (APR_STATUS_IS_ECONNABORTED(ss) || | |
1034 APR_STATUS_IS_ECONNRESET(ss) || | |
1035 APR_STATUS_IS_EOF(ss)) | |
1036 sp_rst_recv++; | |
1037 else { | |
1038 sp_err_recv++; | |
1039 sp_erl_recv = ss; | |
1040 } | |
1041 } | |
1042 #endif | |
1043 if (ss == APR_SUCCESS) | |
1044 return (jint)nbytes; | |
1045 else { | |
1046 TCN_ERROR_WRAP(ss); | |
1047 return -(jint)ss; | |
1048 } | |
1049 } | |
1050 | |
1051 TCN_IMPLEMENT_CALL(jint, Socket, recvbbt)(TCN_STDARGS, jlong sock, | |
1052 jint offset, | |
1053 jint len, jlong timeout) | |
1054 { | |
1055 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1056 apr_status_t ss; | |
1057 apr_size_t nbytes = (apr_size_t)len; | |
1058 apr_interval_time_t pt; | |
1059 apr_interval_time_t nt = J2T(timeout); | |
1060 | |
1061 UNREFERENCED_STDARGS; | |
1062 UNREFERENCED(o); | |
1063 if (!sock) { | |
1064 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
1065 return -(jint)APR_ENOTSOCK; | |
1066 } | |
1067 TCN_ASSERT(s->jrbbuff != NULL); | |
1068 TCN_ASSERT(s->opaque != NULL); | |
1069 if(!s->net) { | |
1070 tcn_ThrowAPRException(e, APR_EINVALSOCK); | |
1071 return -(jint)APR_EINVALSOCK; | |
1072 } | |
1073 | |
1074 if ((ss = (*s->net->timeout_get)(s->opaque, &pt)) != APR_SUCCESS) { | |
1075 TCN_ERROR_WRAP(ss); | |
1076 return -(jint)ss; | |
1077 } | |
1078 if (pt != nt) { | |
1079 if ((ss = (*s->net->timeout_set)(s->opaque, nt)) != APR_SUCCESS) { | |
1080 TCN_ERROR_WRAP(ss); | |
1081 return -(jint)ss; | |
1082 } | |
1083 } | |
1084 ss = (*s->net->recv)(s->opaque, s->jrbbuff + offset, &nbytes); | |
1085 if (pt != nt) { | |
1086 if ((ss = (*s->net->timeout_set)(s->opaque, pt)) != APR_SUCCESS) { | |
1087 TCN_ERROR_WRAP(ss); | |
1088 return -(jint)ss; | |
1089 } | |
1090 } | |
1091 | |
1092 #ifdef TCN_DO_STATISTICS | |
1093 if (ss == APR_SUCCESS) { | |
1094 sp_max_recv = TCN_MAX(sp_max_recv, nbytes); | |
1095 sp_min_recv = TCN_MIN(sp_min_recv, nbytes); | |
1096 sp_tot_recv += nbytes; | |
1097 sp_num_recv++; | |
1098 } | |
1099 else { | |
1100 if (APR_STATUS_IS_ETIMEDOUT(ss) || | |
1101 APR_STATUS_IS_TIMEUP(ss)) | |
1102 sp_tmo_recv++; | |
1103 else if (APR_STATUS_IS_ECONNABORTED(ss) || | |
1104 APR_STATUS_IS_ECONNRESET(ss) || | |
1105 APR_STATUS_IS_EOF(ss)) | |
1106 sp_rst_recv++; | |
1107 else { | |
1108 sp_err_recv++; | |
1109 sp_erl_recv = ss; | |
1110 } | |
1111 } | |
1112 #endif | |
1113 if (ss == APR_SUCCESS) | |
1114 return (jint)nbytes; | |
1115 else { | |
1116 TCN_ERROR_WRAP(ss); | |
1117 return -(jint)ss; | |
1118 } | |
1119 } | |
1120 | |
1121 TCN_IMPLEMENT_CALL(jint, Socket, recvfrom)(TCN_STDARGS, jlong from, | |
1122 jlong sock, jint flags, | |
1123 jbyteArray buf, jint offset, jint tore
ad) | |
1124 { | |
1125 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1126 apr_sockaddr_t *f = J2P(from, apr_sockaddr_t *); | |
1127 apr_size_t nbytes = (apr_size_t)toread; | |
1128 jbyte *bytes = (*e)->GetByteArrayElements(e, buf, NULL); | |
1129 apr_status_t ss; | |
1130 | |
1131 UNREFERENCED(o); | |
1132 if (!sock) { | |
1133 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
1134 return -(jint)APR_ENOTSOCK; | |
1135 } | |
1136 TCN_ASSERT(s->sock != NULL); | |
1137 TCN_ASSERT(buf != NULL); | |
1138 ss = apr_socket_recvfrom(f, s->sock, (apr_int32_t)flags, (char*)(bytes + off
set), &nbytes); | |
1139 | |
1140 (*e)->ReleaseByteArrayElements(e, buf, bytes, | |
1141 nbytes ? 0 : JNI_ABORT); | |
1142 if (ss == APR_SUCCESS) | |
1143 return (jint)nbytes; | |
1144 else { | |
1145 TCN_ERROR_WRAP(ss); | |
1146 return -(jint)ss; | |
1147 } | |
1148 } | |
1149 | |
1150 TCN_IMPLEMENT_CALL(jint, Socket, optSet)(TCN_STDARGS, jlong sock, | |
1151 jint opt, jint on) | |
1152 { | |
1153 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1154 | |
1155 UNREFERENCED(o); | |
1156 if (!s->sock) { | |
1157 return APR_ENOTSOCK; | |
1158 } | |
1159 else | |
1160 return (jint)(*s->net->opt_set)(s->opaque, (apr_int32_t)opt, (apr_int32_
t)on); | |
1161 } | |
1162 | |
1163 TCN_IMPLEMENT_CALL(jint, Socket, optGet)(TCN_STDARGS, jlong sock, | |
1164 jint opt) | |
1165 { | |
1166 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1167 apr_int32_t on = 0; | |
1168 | |
1169 UNREFERENCED(o); | |
1170 if (!s->sock) | |
1171 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
1172 else { | |
1173 TCN_THROW_IF_ERR((*s->net->opt_get)(s->opaque, (apr_int32_t)opt, | |
1174 &on), on); | |
1175 } | |
1176 cleanup: | |
1177 return (jint)on; | |
1178 } | |
1179 | |
1180 TCN_IMPLEMENT_CALL(jint, Socket, timeoutSet)(TCN_STDARGS, jlong sock, | |
1181 jlong timeout) | |
1182 { | |
1183 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1184 | |
1185 UNREFERENCED(o); | |
1186 TCN_ASSERT(s->opaque != NULL); | |
1187 if (!sock) { | |
1188 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
1189 return APR_ENOTSOCK; | |
1190 } | |
1191 return (jint)(*s->net->timeout_set)(s->opaque, J2T(timeout)); | |
1192 } | |
1193 | |
1194 TCN_IMPLEMENT_CALL(jlong, Socket, timeoutGet)(TCN_STDARGS, jlong sock) | |
1195 { | |
1196 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1197 apr_interval_time_t timeout; | |
1198 | |
1199 UNREFERENCED(o); | |
1200 if (!sock) { | |
1201 tcn_ThrowAPRException(e, APR_ENOTSOCK); | |
1202 return 0; | |
1203 } | |
1204 TCN_ASSERT(s->opaque != NULL); | |
1205 | |
1206 TCN_THROW_IF_ERR((*s->net->timeout_get)(s->opaque, &timeout), timeout); | |
1207 cleanup: | |
1208 return (jlong)timeout; | |
1209 } | |
1210 | |
1211 TCN_IMPLEMENT_CALL(jboolean, Socket, atmark)(TCN_STDARGS, jlong sock) | |
1212 { | |
1213 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1214 apr_int32_t mark; | |
1215 | |
1216 UNREFERENCED_STDARGS; | |
1217 TCN_ASSERT(sock != 0); | |
1218 TCN_ASSERT(s->sock != NULL); | |
1219 | |
1220 if (apr_socket_atmark(s->sock, &mark) != APR_SUCCESS) | |
1221 return JNI_FALSE; | |
1222 return mark ? JNI_TRUE : JNI_FALSE; | |
1223 } | |
1224 | |
1225 #if APR_HAS_SENDFILE | |
1226 | |
1227 TCN_IMPLEMENT_CALL(jlong, Socket, sendfile)(TCN_STDARGS, jlong sock, | |
1228 jlong file, | |
1229 jobjectArray headers, | |
1230 jobjectArray trailers, | |
1231 jlong offset, jlong len, | |
1232 jint flags) | |
1233 { | |
1234 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1235 apr_file_t *f = J2P(file, apr_file_t *); | |
1236 jsize nh = 0; | |
1237 jsize nt = 0; | |
1238 jsize i; | |
1239 struct iovec hvec[APR_MAX_IOVEC_SIZE]; | |
1240 struct iovec tvec[APR_MAX_IOVEC_SIZE]; | |
1241 jobject hba[APR_MAX_IOVEC_SIZE]; | |
1242 jobject tba[APR_MAX_IOVEC_SIZE]; | |
1243 apr_off_t off = (apr_off_t)offset; | |
1244 apr_size_t written = (apr_size_t)len; | |
1245 apr_hdtr_t hdrs; | |
1246 apr_status_t ss; | |
1247 | |
1248 UNREFERENCED(o); | |
1249 TCN_ASSERT(sock != 0); | |
1250 TCN_ASSERT(file != 0); | |
1251 | |
1252 if (s->net->type != TCN_SOCKET_APR) | |
1253 return (jint)(-APR_ENOTIMPL); | |
1254 if (headers) | |
1255 nh = (*e)->GetArrayLength(e, headers); | |
1256 if (trailers) | |
1257 nt = (*e)->GetArrayLength(e, trailers); | |
1258 /* Check for overflow */ | |
1259 if (nh >= APR_MAX_IOVEC_SIZE || nt >= APR_MAX_IOVEC_SIZE) | |
1260 return (jint)(-APR_ENOMEM); | |
1261 | |
1262 for (i = 0; i < nh; i++) { | |
1263 hba[i] = (*e)->GetObjectArrayElement(e, headers, i); | |
1264 hvec[i].iov_len = (*e)->GetArrayLength(e, hba[i]); | |
1265 hvec[i].iov_base = (void *)((*e)->GetByteArrayElements(e, hba[i], NULL))
; | |
1266 } | |
1267 for (i = 0; i < nt; i++) { | |
1268 tba[i] = (*e)->GetObjectArrayElement(e, trailers, i); | |
1269 tvec[i].iov_len = (*e)->GetArrayLength(e, tba[i]); | |
1270 tvec[i].iov_base = (void *)((*e)->GetByteArrayElements(e, tba[i], NULL))
; | |
1271 } | |
1272 hdrs.headers = &hvec[0]; | |
1273 hdrs.numheaders = nh; | |
1274 hdrs.trailers = &tvec[0]; | |
1275 hdrs.numtrailers = nt; | |
1276 | |
1277 | |
1278 ss = apr_socket_sendfile(s->sock, f, &hdrs, &off, &written, (apr_int32_t)fla
gs); | |
1279 | |
1280 #ifdef TCN_DO_STATISTICS | |
1281 sf_max_send = TCN_MAX(sf_max_send, written); | |
1282 sf_min_send = TCN_MIN(sf_min_send, written); | |
1283 sf_tot_send += written; | |
1284 sf_num_send++; | |
1285 #endif | |
1286 | |
1287 for (i = 0; i < nh; i++) { | |
1288 (*e)->ReleaseByteArrayElements(e, hba[i], (jbyte*)hvec[i].iov_base, JNI_
ABORT); | |
1289 } | |
1290 | |
1291 for (i = 0; i < nt; i++) { | |
1292 (*e)->ReleaseByteArrayElements(e, tba[i], (jbyte*)tvec[i].iov_base, JNI_
ABORT); | |
1293 } | |
1294 /* Return Number of bytes actually sent, | |
1295 * including headers, file, and trailers | |
1296 */ | |
1297 if (ss == APR_SUCCESS) | |
1298 return (jlong)written; | |
1299 else { | |
1300 TCN_ERROR_WRAP(ss); | |
1301 return -(jlong)ss; | |
1302 } | |
1303 } | |
1304 | |
1305 TCN_IMPLEMENT_CALL(jlong, Socket, sendfilen)(TCN_STDARGS, jlong sock, | |
1306 jlong file, | |
1307 jlong offset, jlong len, | |
1308 jint flags) | |
1309 { | |
1310 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1311 apr_file_t *f = J2P(file, apr_file_t *); | |
1312 apr_off_t off = (apr_off_t)offset; | |
1313 apr_size_t written = (apr_size_t)len; | |
1314 apr_hdtr_t hdrs; | |
1315 apr_status_t ss; | |
1316 | |
1317 UNREFERENCED_STDARGS; | |
1318 TCN_ASSERT(sock != 0); | |
1319 TCN_ASSERT(file != 0); | |
1320 | |
1321 if (s->net->type != TCN_SOCKET_APR) | |
1322 return (jint)(-APR_ENOTIMPL); | |
1323 | |
1324 hdrs.headers = NULL; | |
1325 hdrs.numheaders = 0; | |
1326 hdrs.trailers = NULL; | |
1327 hdrs.numtrailers = 0; | |
1328 | |
1329 | |
1330 ss = apr_socket_sendfile(s->sock, f, &hdrs, &off, &written, (apr_int32_t)fla
gs); | |
1331 | |
1332 #ifdef TCN_DO_STATISTICS | |
1333 sf_max_send = TCN_MAX(sf_max_send, written); | |
1334 sf_min_send = TCN_MIN(sf_min_send, written); | |
1335 sf_tot_send += written; | |
1336 sf_num_send++; | |
1337 #endif | |
1338 | |
1339 /* Return Number of bytes actually sent, | |
1340 * including headers, file, and trailers | |
1341 */ | |
1342 if (ss == APR_SUCCESS) | |
1343 return (jlong)written; | |
1344 else { | |
1345 TCN_ERROR_WRAP(ss); | |
1346 return -(jlong)ss; | |
1347 } | |
1348 } | |
1349 | |
1350 #else /* APR_HAS_SENDIFLE */ | |
1351 | |
1352 TCN_IMPLEMENT_CALL(jlong, Socket, sendfile)(TCN_STDARGS, jlong sock, | |
1353 jlong file, | |
1354 jobjectArray headers, | |
1355 jobjectArray trailers, | |
1356 jlong offset, jlong len, | |
1357 jint flags) | |
1358 { | |
1359 | |
1360 UNREFERENCED_STDARGS; | |
1361 UNREFERENCED(sock); | |
1362 UNREFERENCED(file); | |
1363 UNREFERENCED(headers); | |
1364 UNREFERENCED(trailers); | |
1365 UNREFERENCED(offset); | |
1366 UNREFERENCED(len); | |
1367 UNREFERENCED(flags); | |
1368 return -(jlong)APR_ENOTIMPL; | |
1369 } | |
1370 | |
1371 TCN_IMPLEMENT_CALL(jlong, Socket, sendfilen)(TCN_STDARGS, jlong sock, | |
1372 jlong file, | |
1373 jlong offset, jlong len, | |
1374 jint flags) | |
1375 { | |
1376 UNREFERENCED_STDARGS; | |
1377 UNREFERENCED(sock); | |
1378 UNREFERENCED(file); | |
1379 UNREFERENCED(offset); | |
1380 UNREFERENCED(len); | |
1381 UNREFERENCED(flags); | |
1382 return -(jlong)APR_ENOTIMPL; | |
1383 } | |
1384 | |
1385 #endif /* APR_HAS_SENDIFLE */ | |
1386 | |
1387 | |
1388 TCN_IMPLEMENT_CALL(jint, Socket, acceptfilter)(TCN_STDARGS, | |
1389 jlong sock, | |
1390 jstring name, | |
1391 jstring args) | |
1392 { | |
1393 #if APR_HAS_SO_ACCEPTFILTER | |
1394 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1395 TCN_ALLOC_CSTRING(name); | |
1396 TCN_ALLOC_CSTRING(args); | |
1397 apr_status_t rv; | |
1398 | |
1399 | |
1400 UNREFERENCED(o); | |
1401 rv = apr_socket_accept_filter(s->sock, J2S(name), | |
1402 J2S(args) ? J2S(args) : ""); | |
1403 TCN_FREE_CSTRING(name); | |
1404 TCN_FREE_CSTRING(args); | |
1405 return (jint)rv; | |
1406 #else | |
1407 UNREFERENCED_STDARGS; | |
1408 UNREFERENCED(sock); | |
1409 UNREFERENCED(name); | |
1410 UNREFERENCED(args); | |
1411 return (jint)APR_ENOTIMPL; | |
1412 #endif | |
1413 } | |
1414 | |
1415 TCN_IMPLEMENT_CALL(jint, Socket, dataSet)(TCN_STDARGS, jlong sock, | |
1416 jstring key, jobject data) | |
1417 { | |
1418 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
1419 apr_status_t rv = APR_SUCCESS; | |
1420 TCN_ALLOC_CSTRING(key); | |
1421 | |
1422 UNREFERENCED(o); | |
1423 TCN_ASSERT(sock != 0); | |
1424 | |
1425 rv = apr_socket_data_set(s->sock, data, J2S(key), NULL); | |
1426 TCN_FREE_CSTRING(key); | |
1427 return rv; | |
1428 } | |
1429 | |
1430 TCN_IMPLEMENT_CALL(jobject, Socket, dataGet)(TCN_STDARGS, jlong socket, | |
1431 jstring key) | |
1432 { | |
1433 tcn_socket_t *s = J2P(socket, tcn_socket_t *); | |
1434 TCN_ALLOC_CSTRING(key); | |
1435 void *rv = NULL; | |
1436 | |
1437 UNREFERENCED(o); | |
1438 TCN_ASSERT(socket != 0); | |
1439 | |
1440 if (apr_socket_data_get(&rv, J2S(key), s->sock) != APR_SUCCESS) { | |
1441 rv = NULL; | |
1442 } | |
1443 TCN_FREE_CSTRING(key); | |
1444 return rv; | |
1445 } | |
OLD | NEW |