Apple SSL backend using Network framework (#2482)
This commit is contained in:
parent
a184b14f8c
commit
fb8a7772ef
|
@ -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*)
|
||||
|
|
|
@ -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*)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
@ -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(¶m);
|
||||
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(¶m);
|
||||
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(¶m);
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue