Apple SSL backend using Network framework (#2482)

This commit is contained in:
sauwming 2020-09-29 11:31:01 +08:00 committed by GitHub
parent a184b14f8c
commit fb8a7772ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 2406 additions and 141 deletions

View File

@ -5956,6 +5956,12 @@ case $target in
ac_os_objs="$ac_os_objs sock_qos_bsd.o"
;;
esac
# SSL
case $target in
*darwin*)
ac_os_objs="$ac_os_objs ssl_sock_apple.o"
;;
esac
# UUID
case $target in
*android*)

View File

@ -490,6 +490,12 @@ case $target in
ac_os_objs="$ac_os_objs sock_qos_bsd.o"
;;
esac
# SSL
case $target in
*darwin*)
ac_os_objs="$ac_os_objs ssl_sock_apple.o"
;;
esac
# UUID
case $target in
*android*)

View File

@ -986,7 +986,11 @@
#define PJ_SSL_SOCK_IMP_NONE 0 /**< Disable SSL socket. */
#define PJ_SSL_SOCK_IMP_OPENSSL 1 /**< Using OpenSSL. */
#define PJ_SSL_SOCK_IMP_GNUTLS 2 /**< Using GnuTLS. */
#define PJ_SSL_SOCK_IMP_DARWIN 3 /**< Using Apple's Secure
Transport (deprecated in
MacOS 10.15 & iOS 13.0)*/
#define PJ_SSL_SOCK_IMP_APPLE 4 /**< Using Apple's Network
framework. */
/**
* Select which SSL socket implementation to use. Currently pjlib supports

View File

@ -131,6 +131,12 @@ struct pj_ioqueue_t
static pj_status_t replace_udp_sock(pj_ioqueue_key_t *h);
#endif
#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \
(PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_APPLE)
/* Call SSL Network framework poll */
pj_status_t ssl_network_event_poll();
#endif
/* Include implementation for common abstraction after we declare
* pj_ioqueue_key_t and pj_ioqueue_t.
*/
@ -926,6 +932,12 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout)
PJ_ASSERT_RETURN(ioqueue, -PJ_EINVAL);
#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \
(PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_APPLE)
/* Call SSL Network framework event poll */
ssl_network_event_poll();
#endif
/* Lock ioqueue before making fd_set copies */
pj_lock_acquire(ioqueue->lock);

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
/* $Id$ */
/*
* Copyright (C) 2019-2019 Teluu Inc. (http://www.teluu.com)
*
@ -409,32 +408,42 @@ static pj_status_t ssl_create(pj_ssl_sock_t *ssock)
~PJ_SSL_SOCK_PROTO_SSL2;
}
if (ssock->param.proto & PJ_SSL_SOCK_PROTO_SSL2) {
if (!min_proto) min_proto = kSSLProtocol2;
max_proto = kSSLProtocol2;
}
if (ssock->param.proto & PJ_SSL_SOCK_PROTO_SSL3) {
if (!min_proto) min_proto = kSSLProtocol3;
max_proto = kSSLProtocol3;
}
if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1) {
if (!min_proto) min_proto = kTLSProtocol1;
max_proto = kTLSProtocol1;
}
if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_1) {
if (!min_proto) min_proto = kTLSProtocol11;
max_proto = kTLSProtocol11;
}
if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_2) {
if (!min_proto) min_proto = kTLSProtocol12;
if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_3) {
max_proto = kTLSProtocol13;
} else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_2) {
max_proto = kTLSProtocol12;
} else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_1) {
max_proto = kTLSProtocol11;
} else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1) {
max_proto = kTLSProtocol1;
} else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_SSL3) {
max_proto = kSSLProtocol3;
} else {
PJ_LOG(3, (THIS_FILE, "Unsupported TLS/SSL protocol"));
return PJ_EINVAL;
}
if (min_proto != kSSLProtocolUnknown) {
if (ssock->param.proto & PJ_SSL_SOCK_PROTO_SSL3) {
min_proto = kSSLProtocol3;
} else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1) {
min_proto = kTLSProtocol1;
} else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_1) {
min_proto = kTLSProtocol11;
} else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_2) {
min_proto = kTLSProtocol12;
} else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_3) {
min_proto = kTLSProtocol13;
}
/* According to the doc, we can't set min/max proto for TLS protocol
* higher than 1.0. The runtime error given is -9830 (Illegal parameter).
*/
if (min_proto != kSSLProtocolUnknown && min_proto <= kTLSProtocol1) {
err = SSLSetProtocolVersionMin(ssl_ctx, min_proto);
if (err != noErr) pj_status_from_err(dssock, "SetVersionMin", err);
}
if (max_proto != kSSLProtocolUnknown) {
if (max_proto != kSSLProtocolUnknown && max_proto <= kTLSProtocol1) {
err = SSLSetProtocolVersionMax(ssl_ctx, max_proto);
if (err != noErr) pj_status_from_err(dssock, "SetVersionMax", err);
}

View File

@ -1,4 +1,3 @@
/* $Id$ */
/*
* Copyright (C) 2019-2019 Teluu Inc. (http://www.teluu.com)
*
@ -33,6 +32,18 @@
enum { MAX_BIND_RETRY = 100 };
#ifndef SSL_SOCK_IMP_USE_OWN_NETWORK
static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
void *data,
pj_size_t size,
pj_status_t status,
pj_size_t *remainder);
static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
pj_ioqueue_op_key_t *send_key,
pj_ssize_t sent);
#endif
#ifdef SSL_SOCK_IMP_USE_CIRC_BUF
/*
*******************************************************************
@ -172,7 +183,7 @@ static pj_status_t circ_write(circ_buf_t *cb,
* Helper functions.
*******************************************************************
*/
#ifndef SSL_SOCK_IMP_USE_OWN_NETWORK
/* Close sockets */
static void ssl_close_sockets(pj_ssl_sock_t *ssock)
{
@ -203,6 +214,7 @@ static void ssl_close_sockets(pj_ssl_sock_t *ssock)
if (sock != PJ_INVALID_SOCKET)
pj_sock_close(sock);
}
#endif
/* When handshake completed:
* - notify application
@ -494,6 +506,10 @@ static pj_status_t flush_circ_buf_output(pj_ssl_sock_t *ssock,
pj_lock_release(ssock->write_mutex);
/* Send it */
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
status = network_send(ssock, &wdata->key, wdata->data.content, &len,
flags);
#else
if (ssock->param.sock_type == pj_SOCK_STREAM()) {
status = pj_activesock_send(ssock->asock, &wdata->key,
wdata->data.content, &len,
@ -505,6 +521,7 @@ static pj_status_t flush_circ_buf_output(pj_ssl_sock_t *ssock,
(pj_sockaddr_t*)&ssock->rem_addr,
ssock->addr_len);
}
#endif
if (status != PJ_EPENDING) {
/* When the sending is not pending, remove the wdata from send
@ -626,7 +643,7 @@ static void ssl_on_destroy(void *arg)
/*
*******************************************************************
* Active socket callbacks.
* Network callbacks.
*******************************************************************
*/
@ -644,16 +661,15 @@ static void ssl_on_destroy(void *arg)
((pj_int8_t*)(asock_rbuf) + \
ssock->param.read_buffer_size)
static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
static pj_bool_t ssock_on_data_read (pj_ssl_sock_t *ssock,
void *data,
pj_size_t size,
pj_status_t status,
pj_size_t *remainder)
{
pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
if (status != PJ_SUCCESS)
goto on_error;
/* Socket error or closed */
if (data && size > 0) {
pj_status_t status_;
@ -789,12 +805,10 @@ on_error:
return PJ_FALSE;
}
static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
static pj_bool_t ssock_on_data_sent (pj_ssl_sock_t *ssock,
pj_ioqueue_op_key_t *send_key,
pj_ssize_t sent)
{
pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
write_data_t *wdata = (write_data_t*)send_key->user_data;
pj_ioqueue_op_key_t *app_key = wdata->app_key;
pj_ssize_t sent_len;
@ -845,19 +859,45 @@ static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
return PJ_TRUE;
}
static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
pj_sock_t newsock,
const pj_sockaddr_t *src_addr,
int src_addr_len)
static pj_status_t get_localaddr(pj_ssl_sock_t *ssock,
pj_sockaddr_t *addr,
int *namelen)
{
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
return network_get_localaddr(ssock, &ssock->local_addr,
&ssock->addr_len);
#else
return pj_sock_getsockname(ssock->sock, &ssock->local_addr,
&ssock->addr_len);
#endif
}
static pj_bool_t ssock_on_accept_complete (pj_ssl_sock_t *ssock_parent,
pj_sock_t newsock,
void *newconn,
const pj_sockaddr_t *src_addr,
int src_addr_len,
pj_status_t accept_status)
{
pj_ssl_sock_t *ssock_parent = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
pj_ssl_sock_t *ssock;
#ifndef SSL_SOCK_IMP_USE_OWN_NETWORK
pj_activesock_cb asock_cb;
#endif
pj_activesock_cfg asock_cfg;
unsigned i;
pj_status_t status;
if (accept_status != PJ_SUCCESS) {
if (ssock_parent->param.cb.on_accept_complete2) {
(*ssock_parent->param.cb.on_accept_complete2)(ssock_parent, NULL,
src_addr,
src_addr_len,
accept_status);
}
return PJ_TRUE;
}
/* Create new SSL socket instance */
status = pj_ssl_sock_create(ssock_parent->pool,
&ssock_parent->newsock_param, &ssock);
@ -875,31 +915,9 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
goto on_return;
}
/* Apply QoS, if specified */
status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
&ssock->param.qos_params, 1,
ssock->pool->obj_name, NULL);
if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
goto on_return;
/* Apply socket options, if specified */
if (ssock->param.sockopt_params.cnt) {
status = pj_sock_setsockopt_params(ssock->sock,
&ssock->param.sockopt_params);
if (status != PJ_SUCCESS && !ssock->param.sockopt_ignore_error)
goto on_return;
}
/* Update local address */
/* Set local address */
ssock->addr_len = src_addr_len;
status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
&ssock->addr_len);
if (status != PJ_SUCCESS) {
/* This fails on few envs, e.g: win IOCP, just tolerate this and
* use parent local address instead.
*/
pj_sockaddr_cp(&ssock->local_addr, &ssock_parent->local_addr);
}
pj_sockaddr_cp(&ssock->local_addr, &ssock_parent->local_addr);
/* Set remote address */
pj_sockaddr_cp(&ssock->rem_addr, src_addr);
@ -925,12 +943,6 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
return PJ_ENOMEM;
}
/* Create active socket */
pj_activesock_cfg_default(&asock_cfg);
asock_cfg.async_cnt = ssock->param.async_cnt;
asock_cfg.concurrency = ssock->param.concurrency;
asock_cfg.whole_data = PJ_TRUE;
/* If listener socket has group lock, automatically create group lock
* for the new socket.
*/
@ -947,6 +959,33 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
ssl_on_destroy);
}
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
status = network_setup_connection(ssock, newconn);
if (status != PJ_SUCCESS)
goto on_return;
#else
/* Apply QoS, if specified */
status = pj_sock_apply_qos2(ssock->sock, ssock->param.qos_type,
&ssock->param.qos_params, 1,
ssock->pool->obj_name, NULL);
if (status != PJ_SUCCESS && !ssock->param.qos_ignore_error)
goto on_return;
/* Apply socket options, if specified */
if (ssock->param.sockopt_params.cnt) {
status = pj_sock_setsockopt_params(ssock->sock,
&ssock->param.sockopt_params);
if (status != PJ_SUCCESS && !ssock->param.sockopt_ignore_error)
goto on_return;
}
/* Create active socket */
pj_activesock_cfg_default(&asock_cfg);
asock_cfg.async_cnt = ssock->param.async_cnt;
asock_cfg.concurrency = ssock->param.concurrency;
asock_cfg.whole_data = PJ_TRUE;
pj_bzero(&asock_cb, sizeof(asock_cb));
asock_cb.on_data_read = asock_on_data_read;
asock_cb.on_data_sent = asock_on_data_sent;
@ -970,6 +1009,16 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
PJ_IOQUEUE_ALWAYS_ASYNC);
if (status != PJ_SUCCESS)
goto on_return;
#endif
/* Update local address */
status = get_localaddr(ssock, &ssock->local_addr, &ssock->addr_len);
if (status != PJ_SUCCESS) {
/* This fails on few envs, e.g: win IOCP, just tolerate this and
* use parent local address instead.
*/
pj_sockaddr_cp(&ssock->local_addr, &ssock_parent->local_addr);
}
/* Prepare write/send state */
pj_assert(ssock->send_buf.max_len == 0);
@ -1009,39 +1058,13 @@ on_return:
on_handshake_complete(ssock, status);
}
/* Must return PJ_TRUE whatever happened, as active socket must
* continue listening.
*/
/* Must return PJ_TRUE whatever happened, as we must continue listening */
return PJ_TRUE;
}
static pj_bool_t asock_on_accept_complete2(pj_activesock_t *asock,
pj_sock_t newsock,
const pj_sockaddr_t *src_addr,
int src_addr_len,
pj_status_t status)
{
pj_bool_t ret = PJ_TRUE;
if (status != PJ_SUCCESS) {
pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
if (ssock->param.cb.on_accept_complete2) {
(*ssock->param.cb.on_accept_complete2) (ssock, NULL,
src_addr, src_addr_len,
status);
}
} else {
ret = asock_on_accept_complete(asock, newsock, src_addr, src_addr_len);
}
return ret;
}
static pj_bool_t asock_on_connect_complete (pj_activesock_t *asock,
static pj_bool_t ssock_on_connect_complete (pj_ssl_sock_t *ssock,
pj_status_t status)
{
pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
unsigned i;
if (status != PJ_SUCCESS)
@ -1049,8 +1072,7 @@ static pj_bool_t asock_on_connect_complete (pj_activesock_t *asock,
/* Update local address */
ssock->addr_len = sizeof(pj_sockaddr);
status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,
&ssock->addr_len);
status = get_localaddr(ssock, &ssock->local_addr, &ssock->addr_len);
if (status != PJ_SUCCESS)
goto on_return;
@ -1076,10 +1098,16 @@ static pj_bool_t asock_on_connect_complete (pj_activesock_t *asock,
}
/* Start read */
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
status = network_start_read(ssock, ssock->param.async_cnt,
(unsigned)ssock->param.read_buffer_size,
ssock->asock_rbuf, 0);
#else
status = pj_activesock_start_read2(ssock->asock, ssock->pool,
(unsigned)ssock->param.read_buffer_size,
ssock->asock_rbuf,
PJ_IOQUEUE_ALWAYS_ASYNC);
#endif
if (status != PJ_SUCCESS)
goto on_return;
@ -1112,6 +1140,51 @@ on_return:
return on_handshake_complete(ssock, status);
}
#ifndef SSL_SOCK_IMP_USE_OWN_NETWORK
static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
void *data,
pj_size_t size,
pj_status_t status,
pj_size_t *remainder)
{
pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
return ssock_on_data_read(ssock, data, size, status, remainder);
}
static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
pj_ioqueue_op_key_t *send_key,
pj_ssize_t sent)
{
pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
return ssock_on_data_sent(ssock, send_key, sent);
}
static pj_bool_t asock_on_accept_complete2(pj_activesock_t *asock,
pj_sock_t newsock,
const pj_sockaddr_t *src_addr,
int src_addr_len,
pj_status_t status)
{
pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
return ssock_on_accept_complete(ssock, newsock, NULL,
src_addr, src_addr_len, status);
}
static pj_bool_t asock_on_connect_complete (pj_activesock_t *asock,
pj_status_t status)
{
pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)
pj_activesock_get_user_data(asock);
return ssock_on_connect_complete(ssock, status);
}
#endif
/*
*******************************************************************
@ -1277,6 +1350,8 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
/* Create secure socket */
ssock = ssl_alloc(pool);
if (!ssock)
return PJ_ENOMEM;
ssock->pool = pool;
ssock->info_pool = info_pool;
ssock->sock = PJ_INVALID_SOCKET;
@ -1503,7 +1578,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_read2 (pj_ssl_sock_t *ssock,
for (i=0; i<ssock->param.async_cnt; ++i) {
if (ssock->asock_rbuf[i]) {
pj_size_t remainder = 0;
asock_on_data_read(ssock->asock, ssock->asock_rbuf[i], 0,
ssock_on_data_read(ssock, ssock->asock_rbuf[i], 0,
PJ_SUCCESS, &remainder);
}
}
@ -1765,9 +1840,11 @@ pj_ssl_sock_start_accept2(pj_ssl_sock_t *ssock,
int addr_len,
const pj_ssl_sock_param *newsock_param)
{
pj_status_t status;
#ifndef SSL_SOCK_IMP_USE_OWN_NETWORK
pj_activesock_cb asock_cb;
pj_activesock_cfg asock_cfg;
pj_status_t status;
#endif
PJ_ASSERT_RETURN(ssock && pool && localaddr && addr_len, PJ_EINVAL);
@ -1779,6 +1856,14 @@ pj_ssl_sock_start_accept2(pj_ssl_sock_t *ssock,
return PJ_EINVAL;
}
ssock->is_server = PJ_TRUE;
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
status = network_start_accept(ssock, pool, localaddr, addr_len,
newsock_param);
if (status != PJ_SUCCESS)
goto on_error;
#else
/* Create socket */
status = pj_sock_socket(ssock->param.sock_af, ssock->param.sock_type, 0,
&ssock->sock);
@ -1859,8 +1944,7 @@ pj_ssl_sock_start_accept2(pj_ssl_sock_t *ssock,
&ssock->addr_len);
if (status != PJ_SUCCESS)
pj_sockaddr_cp(&ssock->local_addr, localaddr);
ssock->is_server = PJ_TRUE;
#endif
return PJ_SUCCESS;
@ -1893,9 +1977,14 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_connect2(
pj_ssl_sock_t *ssock,
pj_ssl_start_connect_param *connect_param)
{
pj_status_t status;
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
status = network_start_connect(ssock, connect_param);
if (status != PJ_EPENDING)
goto on_error;
#else
pj_activesock_cb asock_cb;
pj_activesock_cfg asock_cfg;
pj_status_t status;
pj_pool_t *pool = connect_param->pool;
const pj_sockaddr_t *localaddr = connect_param->localaddr;
@ -1971,22 +2060,6 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_connect2(
/* Save remote address */
pj_sockaddr_cp(&ssock->rem_addr, remaddr);
/* Start timer */
if (ssock->param.timer_heap &&
(ssock->param.timeout.sec != 0 || ssock->param.timeout.msec != 0))
{
pj_assert(ssock->timer.id == TIMER_NONE);
status = pj_timer_heap_schedule_w_grp_lock(ssock->param.timer_heap,
&ssock->timer,
&ssock->param.timeout,
TIMER_HANDSHAKE_TIMEOUT,
ssock->param.grp_lock);
if (status != PJ_SUCCESS) {
ssock->timer.id = TIMER_NONE;
status = PJ_SUCCESS;
}
}
status = pj_activesock_start_connect(ssock->asock, pool, remaddr,
addr_len);
@ -2007,6 +2080,24 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_connect2(
* once the socket is established.
*/
#endif
/* Start timer */
if (ssock->param.timer_heap &&
(ssock->param.timeout.sec != 0 || ssock->param.timeout.msec != 0))
{
pj_assert(ssock->timer.id == TIMER_NONE);
status = pj_timer_heap_schedule_w_grp_lock(ssock->param.timer_heap,
&ssock->timer,
&ssock->param.timeout,
TIMER_HANDSHAKE_TIMEOUT,
ssock->param.grp_lock);
if (status != PJ_SUCCESS) {
ssock->timer.id = TIMER_NONE;
status = PJ_SUCCESS;
}
}
/* Update SSL state */
ssock->is_server = PJ_FALSE;

View File

@ -1,4 +1,3 @@
/* $Id$ */
/*
* Copyright (C) 2019-2019 Teluu Inc. (http://www.teluu.com)
*
@ -263,5 +262,33 @@ static pj_status_t ssl_read(pj_ssl_sock_t *ssock, void *data, int *size);
static pj_status_t ssl_write(pj_ssl_sock_t *ssock, const void *data,
pj_ssize_t size, int *nwritten);
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
static void ssl_close_sockets(pj_ssl_sock_t *ssock);
static pj_status_t network_send(pj_ssl_sock_t *ssock,
pj_ioqueue_op_key_t *send_key,
const void *data,
pj_ssize_t *size,
unsigned flags);
static pj_status_t network_start_read(pj_ssl_sock_t *ssock,
unsigned async_count,
unsigned buff_size,
void *readbuf[],
pj_uint32_t flags);
static pj_status_t network_start_accept(pj_ssl_sock_t *ssock,
pj_pool_t *pool,
const pj_sockaddr_t *localaddr,
int addr_len,
const pj_ssl_sock_param *newsock_param);
static pj_status_t network_start_connect(pj_ssl_sock_t *ssock,
pj_ssl_start_connect_param *connect_param);
static pj_status_t network_setup_connection(pj_ssl_sock_t *ssock,
void *connection);
static pj_status_t network_get_localaddr(pj_ssl_sock_t *ssock,
pj_sockaddr_t *addr,
int *namelen);
#endif
#endif /* __SSL_SOCK_IMP_COMMON_H__ */

View File

@ -22,7 +22,8 @@
#define CERT_DIR "../build/"
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_DARWIN)
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_DARWIN) || \
(PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_APPLE)
/* If we use Darwin SSL, use the cert in DER format. */
# define CERT_CA_FILE CERT_DIR "cacert.der"
#else
@ -174,10 +175,13 @@ static pj_bool_t ssl_on_connect_complete(pj_ssl_sock_t *ssock,
goto on_return;
}
if (status == PJ_SUCCESS)
if (status == PJ_SUCCESS) {
st->sent += size;
else
} else {
if (status == PJ_EPENDING)
status = PJ_SUCCESS;
break;
}
}
on_return:
@ -196,7 +200,8 @@ on_return:
static pj_bool_t ssl_on_accept_complete(pj_ssl_sock_t *ssock,
pj_ssl_sock_t *newsock,
const pj_sockaddr_t *src_addr,
int src_addr_len)
int src_addr_len,
pj_status_t accept_status)
{
struct test_state *parent_st = (struct test_state*)
pj_ssl_sock_get_user_data(ssock);
@ -207,6 +212,14 @@ static pj_bool_t ssl_on_accept_complete(pj_ssl_sock_t *ssock,
pj_status_t status;
PJ_UNUSED_ARG(src_addr_len);
if (accept_status != PJ_SUCCESS) {
if (newsock) {
st = (struct test_state*) pj_ssl_sock_get_user_data(newsock);
st->err = accept_status;
}
return PJ_FALSE;
}
/* Duplicate parent test state to newly accepted test state */
st = (struct test_state*)pj_pool_zalloc(parent_st->pool, sizeof(struct test_state));
@ -245,10 +258,13 @@ static pj_bool_t ssl_on_accept_complete(pj_ssl_sock_t *ssock,
goto on_return;
}
if (status == PJ_SUCCESS)
if (status == PJ_SUCCESS) {
st->sent += size;
else
} else {
if (status == PJ_EPENDING)
status = PJ_SUCCESS;
break;
}
}
on_return:
@ -304,8 +320,11 @@ static pj_bool_t ssl_on_data_read(pj_ssl_sock_t *ssock,
goto on_return;
}
if (status == PJ_SUCCESS)
if (status == PJ_SUCCESS) {
st->sent += size_;
} else if (status == PJ_EPENDING) {
status = PJ_SUCCESS;
}
}
/* Verify echoed data when specified to */
@ -526,6 +545,7 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
{
pj_pool_t *pool = NULL;
pj_ioqueue_t *ioqueue = NULL;
pj_timer_heap_t *timer = NULL;
pj_ssl_sock_t *ssock_serv = NULL;
pj_ssl_sock_t *ssock_cli = NULL;
pj_ssl_sock_param param;
@ -543,12 +563,18 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
goto on_return;
}
status = pj_timer_heap_create(pool, 4, &timer);
if (status != PJ_SUCCESS) {
goto on_return;
}
pj_ssl_sock_param_default(&param);
param.cb.on_accept_complete = &ssl_on_accept_complete;
param.cb.on_accept_complete2 = &ssl_on_accept_complete;
param.cb.on_connect_complete = &ssl_on_connect_complete;
param.cb.on_data_read = &ssl_on_data_read;
param.cb.on_data_sent = &ssl_on_data_sent;
param.ioqueue = ioqueue;
param.timer_heap = timer;
param.ciphers = ciphers;
/* Init default bind address */
@ -733,12 +759,25 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
PJ_LOG(3, ("", ".....Sent/recv: %d/%d bytes", state_cli.sent, state_cli.recv));
on_return:
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_DARWIN) || \
(PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_APPLE)
if (status != PJ_SUCCESS) {
PJ_LOG(3, ("", "Apple SSL requires the private key to be "
"inside the Keychain. So double click on "
"the file pjlib/build/privkey.p12 to "
"place it in the Keychain. "
"The password is \"pjsip\"."));
}
#endif
if (ssock_serv)
pj_ssl_sock_close(ssock_serv);
if (ssock_cli && !state_cli.err && !state_cli.done)
pj_ssl_sock_close(ssock_cli);
if (ioqueue)
pj_ioqueue_destroy(ioqueue);
if (timer)
pj_timer_heap_destroy(timer);
if (pool)
pj_pool_release(pool);
@ -892,14 +931,6 @@ static int client_non_ssl(unsigned ms_timeout)
pj_str_t privkey_file = pj_str(CERT_PRIVKEY_FILE);
pj_str_t privkey_pass = pj_str(CERT_PRIVKEY_PASS);
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_DARWIN)
PJ_LOG(3, ("", "Darwin SSL requires the private key to be "
"inside the Keychain. So double click on "
"the file pjlib/build/privkey.p12 to "
"place it in the Keychain. "
"The password is \"pjsip\"."));
#endif
#if (defined(TEST_LOAD_FROM_FILES) && TEST_LOAD_FROM_FILES==1)
status = pj_ssl_cert_load_from_files(pool, &ca_file, &cert_file,
&privkey_file, &privkey_pass,
@ -932,7 +963,7 @@ static int client_non_ssl(unsigned ms_timeout)
}
pj_ssl_sock_param_default(&param);
param.cb.on_accept_complete = &ssl_on_accept_complete;
param.cb.on_accept_complete2 = &ssl_on_accept_complete;
param.cb.on_data_read = &ssl_on_data_read;
param.cb.on_data_sent = &ssl_on_data_sent;
param.ioqueue = ioqueue;
@ -1263,7 +1294,7 @@ static int perf_test(unsigned clients, unsigned ms_handshake_timeout)
}
pj_ssl_sock_param_default(&param);
param.cb.on_accept_complete = &ssl_on_accept_complete;
param.cb.on_accept_complete2 = &ssl_on_accept_complete;
param.cb.on_connect_complete = &ssl_on_connect_complete;
param.cb.on_data_read = &ssl_on_data_read;
param.cb.on_data_sent = &ssl_on_data_sent;
@ -1531,19 +1562,28 @@ int ssl_sock_test(void)
if (ret == 0)
return PJ_EBUG;
/* We can't set min/max proto for TLS protocol higher than 1.0. */
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_DARWIN)
PJ_LOG(3,("", "..echo test w/ incompatible proto: server TLSv1.2 vs client TLSv1.3"));
ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1_2, PJ_SSL_SOCK_PROTO_TLS1_3,
-1, -1,
PJ_FALSE, PJ_FALSE);
if (ret == 0)
return PJ_EBUG;
#endif
/* We can't seem to enable certain ciphers only. SSLSetEnabledCiphers() is
* deprecated and we only have sec_protocol_options_append_tls_ciphersuite(),
* but there's no API to remove certain or all ciphers.
*/
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_APPLE)
PJ_LOG(3,("", "..echo test w/ incompatible ciphers"));
ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,
PJ_TLS_RSA_WITH_DES_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
PJ_FALSE, PJ_FALSE);
if (ret == 0)
return PJ_EBUG;
#endif
PJ_LOG(3,("", "..echo test w/ client cert required but not provided"));
ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,
@ -1568,8 +1608,7 @@ int ssl_sock_test(void)
PJ_LOG(3,("", "..client non-SSL (handshake timeout 5 secs)"));
ret = client_non_ssl(5000);
/* PJ_TIMEDOUT won't be returned as accepted socket is deleted silently */
if (ret != 0)
if (ret != PJ_ETIMEDOUT)
return ret;
#endif