📄 network.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
*
* @author Mladen Turk
* @version $Revision: 487786 $, $Date: 2006-12-16 12:05:57 +0100 (sam., 16 déc. 2006) $
*/
#include "tcn.h"
#ifdef TCN_DO_STATISTICS
#include "apr_atomic.h"
static volatile apr_uint32_t sp_created = 0;
static volatile apr_uint32_t sp_closed = 0;
static volatile apr_uint32_t sp_cleared = 0;
static volatile apr_uint32_t sp_accepted = 0;
static volatile apr_uint32_t sp_max_send = 0;
static volatile apr_uint32_t sp_min_send = 10000000;
static volatile apr_uint32_t sp_num_send = 0;
static volatile apr_off_t sp_tot_send = 0;
static volatile apr_uint32_t sp_max_recv = 0;
static volatile apr_uint32_t sp_min_recv = 10000000;
static volatile apr_uint32_t sp_num_recv = 0;
static volatile apr_off_t sp_tot_recv = 0;
static volatile apr_uint32_t sp_err_recv = 0;
static volatile apr_uint32_t sp_tmo_recv = 0;
static volatile apr_uint32_t sp_rst_recv = 0;
static volatile apr_status_t sp_erl_recv = 0;
static volatile apr_size_t sf_max_send = 0;
static volatile apr_size_t sf_min_send = 10000000;
static volatile apr_uint32_t sf_num_send = 0;
static volatile apr_off_t sf_tot_send = 0;
void sp_network_dump_statistics()
{
fprintf(stderr, "Network Statistics ......\n");
fprintf(stderr, "Sockets created : %d\n", sp_created);
fprintf(stderr, "Sockets accepted : %d\n", sp_accepted);
fprintf(stderr, "Sockets closed : %d\n", sp_closed);
fprintf(stderr, "Sockets cleared : %d\n", sp_cleared);
fprintf(stderr, "Total send calls : %d\n", sp_num_send);
fprintf(stderr, "Minimum send length : %d\n", sp_min_send);
fprintf(stderr, "Maximum send length : %d\n", sp_max_send);
fprintf(stderr, "Average send length : %.2f\n", (double)sp_tot_send/(double)sp_num_send);
fprintf(stderr, "Total recv calls : %d\n", sp_num_recv);
fprintf(stderr, "Minimum recv length : %d\n", sp_min_recv);
fprintf(stderr, "Maximum recv length : %d\n", sp_max_recv);
fprintf(stderr, "Average recv length : %.2f\n", (double)sp_tot_recv/(double)sp_num_recv);
fprintf(stderr, "Receive timeouts : %d\n", sp_tmo_recv);
fprintf(stderr, "Receive errors : %d\n", sp_err_recv);
fprintf(stderr, "Receive resets : %d\n", sp_rst_recv);
fprintf(stderr, "Last receive error : %d\n", sp_erl_recv);
fprintf(stderr, "Total sendfile calls : %d\n", sf_num_send);
fprintf(stderr, "Minimum sendfile lenght : %" APR_SIZE_T_FMT "\n", sf_min_send);
fprintf(stderr, "Maximum sendfile lenght : %" APR_SIZE_T_FMT "\n", sf_max_send);
}
#endif /* TCN_DO_STATISTICS */
static apr_status_t sp_socket_cleanup(void *data)
{
tcn_socket_t *s = (tcn_socket_t *)data;
if (s->net && s->net->cleanup)
(*s->net->cleanup)(s->opaque);
if (s->sock) {
apr_socket_t *as = s->sock;
s->sock = NULL;
apr_socket_close(as);
}
#ifdef TCN_DO_STATISTICS
apr_atomic_inc32(&sp_cleared);
#endif
return APR_SUCCESS;
}
#if defined(DEBUG) || defined(_DEBUG)
static APR_INLINE apr_status_t APR_THREAD_FUNC
APR_socket_send(apr_socket_t *sock, const char *buf, apr_size_t *len)
{
return apr_socket_send(sock, buf, len);
}
static APR_INLINE apr_status_t APR_THREAD_FUNC
APR_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len)
{
return apr_socket_recv(sock, buf, len);
}
static APR_INLINE apr_status_t APR_THREAD_FUNC
APR_socket_sendv(apr_socket_t *sock, const struct iovec *vec,
apr_int32_t nvec, apr_size_t *len)
{
return apr_socket_sendv(sock, vec, nvec, len);
}
static APR_INLINE apr_status_t APR_THREAD_FUNC
APR_socket_shutdown(apr_socket_t *sock, apr_shutdown_how_e how)
{
return apr_socket_shutdown(sock, how);
}
static APR_INLINE apr_status_t APR_THREAD_FUNC
APR_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
{
return apr_socket_timeout_set(sock, t);
}
static APR_INLINE apr_status_t APR_THREAD_FUNC
APR_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
{
return apr_socket_timeout_get(sock, t);
}
static APR_INLINE apr_status_t APR_THREAD_FUNC
APR_socket_opt_set(apr_socket_t *sock, apr_int32_t opt, apr_int32_t on)
{
return apr_socket_opt_set(sock, opt, on);
}
static APR_INLINE apr_status_t APR_THREAD_FUNC
APR_socket_opt_get(apr_socket_t *sock, apr_int32_t opt, apr_int32_t *on)
{
return apr_socket_opt_get(sock, opt, on);
}
#else
#define APR_socket_send apr_socket_send
#define APR_socket_recv apr_socket_recv
#define APR_socket_sendv apr_socket_sendv
#define APR_socket_shutdown apr_socket_shutdown
#define APR_socket_timeout_set apr_socket_timeout_set
#define APR_socket_timeout_get apr_socket_timeout_get
#define APR_socket_opt_set apr_socket_opt_set
#define APR_socket_opt_get apr_socket_opt_get
#endif
static tcn_nlayer_t apr_socket_layer = {
TCN_SOCKET_APR,
NULL,
NULL,
APR_socket_shutdown,
APR_socket_opt_get,
APR_socket_opt_set,
APR_socket_timeout_get,
APR_socket_timeout_set,
APR_socket_send,
APR_socket_sendv,
APR_socket_recv
};
TCN_IMPLEMENT_CALL(jlong, Socket, create)(TCN_STDARGS, jint family,
jint type, jint protocol,
jlong pool)
{
apr_pool_t *p = J2P(pool, apr_pool_t *);
apr_socket_t *s = NULL;
tcn_socket_t *a = NULL;
apr_int32_t f, t;
UNREFERENCED(o);
TCN_ASSERT(pool != 0);
GET_S_FAMILY(f, family);
GET_S_TYPE(t, type);
a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t));
TCN_CHECK_ALLOCATED(a);
a->pool = p;
if (family >= 0)
a->net = &apr_socket_layer;
apr_pool_cleanup_register(p, (const void *)a,
sp_socket_cleanup,
apr_pool_cleanup_null);
if (family >= 0) {
TCN_THROW_IF_ERR(apr_socket_create(&s,
f, t, protocol, p), a);
}
#ifdef TCN_DO_STATISTICS
sp_created++;
#endif
a->sock = s;
if (family >= 0)
a->net = &apr_socket_layer;
a->opaque = s;
apr_pool_create(&a->child, a->pool);
return P2J(a);
cleanup:
return 0;
}
TCN_IMPLEMENT_CALL(void, Socket, destroy)(TCN_STDARGS, jlong sock)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
apr_pool_cleanup_kill(s->pool, s, sp_socket_cleanup);
if (s->net && s->net->cleanup) {
(*s->net->cleanup)(s->opaque);
s->net = NULL;
}
if (s->sock) {
apr_socket_t *as = s->sock;
s->sock = NULL;
apr_socket_close(as);
}
apr_pool_destroy(s->pool);
}
TCN_IMPLEMENT_CALL(jlong, Socket, pool)(TCN_STDARGS, jlong sock)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
apr_pool_t *n;
UNREFERENCED(o);
TCN_ASSERT(sock != 0);
TCN_THROW_IF_ERR(apr_pool_create(&n, s->pool), n);
cleanup:
return P2J(n);
}
TCN_IMPLEMENT_CALL(jlong, Socket, get)(TCN_STDARGS, jlong sock, jint what)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
switch (what) {
case TCN_SOCKET_GET_POOL:
return P2J(s->pool);
break;
case TCN_SOCKET_GET_IMPL:
return P2J(s->opaque);
break;
case TCN_SOCKET_GET_APRS:
return P2J(s->sock);
break;
case TCN_SOCKET_GET_TYPE:
return (jlong)(s->net->type);
break;
}
return 0;
}
TCN_IMPLEMENT_CALL(jint, Socket, shutdown)(TCN_STDARGS, jlong sock,
jint how)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
return (jint)(*s->net->shutdown)(s->opaque, how);
}
TCN_IMPLEMENT_CALL(jint, Socket, close)(TCN_STDARGS, jlong sock)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
jint rv = APR_SUCCESS;
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
apr_pool_cleanup_kill(s->pool, s, sp_socket_cleanup);
if (s->child) {
apr_pool_clear(s->child);
}
#ifdef TCN_DO_STATISTICS
apr_atomic_inc32(&sp_closed);
#endif
if (s->net && s->net->close) {
rv = (*s->net->close)(s->opaque);
s->net = NULL;
}
if (s->sock) {
apr_socket_t *as = s->sock;
s->sock = NULL;
rv = (jint)apr_socket_close(as);
}
return rv;
}
TCN_IMPLEMENT_CALL(jint, Socket, bind)(TCN_STDARGS, jlong sock,
jlong sa)
{
jint rv = APR_SUCCESS;
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
apr_sockaddr_t *a = J2P(sa, apr_sockaddr_t *);
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
TCN_ASSERT(s->sock != NULL);
rv = (jint)apr_socket_bind(s->sock, a);
return rv;
}
TCN_IMPLEMENT_CALL(jint, Socket, listen)(TCN_STDARGS, jlong sock,
jint backlog)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
TCN_ASSERT(s->sock != NULL);
return (jint)apr_socket_listen(s->sock, backlog);
}
TCN_IMPLEMENT_CALL(jlong, Socket, acceptx)(TCN_STDARGS, jlong sock,
jlong pool)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
apr_pool_t *p = J2P(pool, apr_pool_t *);
apr_socket_t *n = NULL;
tcn_socket_t *a = NULL;
UNREFERENCED(o);
TCN_ASSERT(sock != 0);
if (s->net->type == TCN_SOCKET_APR) {
TCN_ASSERT(s->sock != NULL);
a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t));
TCN_CHECK_ALLOCATED(a);
a->pool = p;
apr_pool_cleanup_register(p, (const void *)a,
sp_socket_cleanup,
apr_pool_cleanup_null);
TCN_THROW_IF_ERR(apr_socket_accept(&n, s->sock, p), n);
}
else {
tcn_ThrowAPRException(e, APR_ENOTIMPL);
goto cleanup;
}
if (n) {
#ifdef TCN_DO_STATISTICS
apr_atomic_inc32(&sp_accepted);
#endif
a->net = &apr_socket_layer;
a->sock = n;
a->opaque = n;
}
cleanup:
return P2J(a);
}
TCN_IMPLEMENT_CALL(jlong, Socket, accept)(TCN_STDARGS, jlong sock)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
apr_pool_t *p = NULL;
apr_socket_t *n = NULL;
tcn_socket_t *a = NULL;
UNREFERENCED(o);
TCN_ASSERT(sock != 0);
TCN_THROW_IF_ERR(apr_pool_create(&p, s->pool), p);
if (s->net->type == TCN_SOCKET_APR) {
TCN_ASSERT(s->sock != NULL);
a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t));
TCN_CHECK_ALLOCATED(a);
a->pool = p;
apr_pool_cleanup_register(s->child, (const void *)a,
sp_socket_cleanup,
apr_pool_cleanup_null);
TCN_THROW_IF_ERR(apr_socket_accept(&n, s->sock, p), n);
}
else {
tcn_ThrowAPRException(e, APR_ENOTIMPL);
goto cleanup;
}
if (n) {
#ifdef TCN_DO_STATISTICS
apr_atomic_inc32(&sp_accepted);
#endif
a->net = &apr_socket_layer;
a->sock = n;
a->opaque = n;
}
return P2J(a);
cleanup:
return 0;
}
TCN_IMPLEMENT_CALL(jint, Socket, connect)(TCN_STDARGS, jlong sock,
jlong sa)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
apr_sockaddr_t *a = J2P(sa, apr_sockaddr_t *);
UNREFERENCED_STDARGS;
TCN_ASSERT(sock != 0);
TCN_ASSERT(s->sock != NULL);
return (jint)apr_socket_connect(s->sock, a);
}
TCN_IMPLEMENT_CALL(jint, Socket, send)(TCN_STDARGS, jlong sock,
jbyteArray buf, jint offset, jint tosend)
{
tcn_socket_t *s = J2P(sock, tcn_socket_t *);
apr_size_t nbytes = (apr_size_t)tosend;
apr_status_t ss;
UNREFERENCED(o);
if (!sock) {
tcn_ThrowAPRException(e, APR_ENOTSOCK);
return -(jint)APR_ENOTSOCK;
}
TCN_ASSERT(s->opaque != NULL);
#ifdef TCN_DO_STATISTICS
sp_max_send = TCN_MAX(sp_max_send, nbytes);
sp_min_send = TCN_MIN(sp_min_send, nbytes);
sp_tot_send += nbytes;
sp_num_send++;
#endif
if (tosend <= TCN_BUFFER_SZ) {
jbyte sb[TCN_BUFFER_SZ];
(*e)->GetByteArrayRegion(e, buf, offset, tosend, &sb[0]);
ss = (*s->net->send)(s->opaque, (const char *)&sb[0], &nbytes);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -