Mongoose net_if and ssl_if refactoring

A major cleanup, disentangling net_if and ssl_if.
Pulled a lot of common logic into the core and reduced size of net_if implementations.

CL: Mongoose net_if and ssl_if refactoring

PUBLISHED_FROM=29bd4dcb264a1fd96b3dd164e2d880e1c2c0921e
This commit is contained in:
Deomid Ryabkov authored and Cesanta Bot committed 2018-03-30 23:19:49 +00:00
1 parent c80f4c5313
commit 3e33e57707
17 files changed
+1358 -2007

No files matched your search

+20 -74
View File
@@ -50,15 +50,7 @@ void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) {
if (nc->iface == NULL || nc->mgr == NULL) continue;
switch (sig) {
case MG_SIG_CONNECT_RESULT: {
#if MG_ENABLE_SSL
if (cs->err == 0 && (nc->flags & MG_F_SSL) &&
!(nc->flags & MG_F_SSL_HANDSHAKE_DONE)) {
mg_lwip_ssl_do_hs(nc);
} else
#endif
{
mg_if_connect_cb(nc, cs->err);
}
mg_if_connect_cb(nc, cs->err);
break;
}
case MG_SIG_CLOSE_CONN: {
@@ -68,11 +60,8 @@ void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) {
}
case MG_SIG_RECV: {
cs->recv_pending = 0;
if (nc->flags & MG_F_UDP) {
mg_lwip_handle_recv_udp(nc);
} else {
mg_lwip_handle_recv_tcp(nc);
}
mg_if_can_recv_cb(nc);
mbuf_trim(&nc->recv_mbuf);
break;
}
case MG_SIG_TOMBSTONE: {
@@ -87,7 +76,8 @@ void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) {
}
void mg_lwip_if_init(struct mg_iface *iface) {
LOG(LL_INFO, ("%p Mongoose init", iface));
LOG(LL_INFO, ("Mongoose %s, LwIP %u.%u.%u", MG_VERSION, LWIP_VERSION_MAJOR,
LWIP_VERSION_MINOR, LWIP_VERSION_REVISION));
iface->data = MG_CALLOC(1, sizeof(struct mg_ev_mgr_lwip_data));
}
@@ -126,42 +116,7 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
tmp = nc->next;
n++;
if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) ||
((nc->flags & MG_F_SEND_AND_CLOSE) && (nc->flags & MG_F_UDP) &&
(nc->send_mbuf.len == 0))) {
mg_close_conn(nc);
continue;
}
mg_if_poll(nc, now);
mg_if_timer(nc, now);
#if MG_ENABLE_SSL
if ((nc->flags & MG_F_SSL) && cs != NULL && cs->pcb.tcp != NULL &&
cs->pcb.tcp->state == ESTABLISHED) {
if (((nc->flags & MG_F_WANT_WRITE) ||
((nc->send_mbuf.len > 0) &&
(nc->flags & MG_F_SSL_HANDSHAKE_DONE))) &&
cs->pcb.tcp->snd_buf > 0) {
/* Can write more. */
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_send(nc);
} else {
mg_lwip_ssl_do_hs(nc);
}
}
if (cs->rx_chain != NULL || (nc->flags & MG_F_WANT_READ)) {
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_recv(nc);
} else {
mg_lwip_ssl_do_hs(nc);
}
}
} else
#endif /* MG_ENABLE_SSL */
{
if (nc->send_mbuf.len > 0 && !(nc->flags & MG_F_CONNECTING)) {
mg_lwip_send_more(nc);
}
}
if (!mg_if_poll(nc, now)) continue;
if (nc->sock != INVALID_SOCKET &&
!(nc->flags & (MG_F_UDP | MG_F_LISTENING)) && cs->pcb.tcp != NULL &&
cs->pcb.tcp->unsent != NULL) {
@@ -175,14 +130,17 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
}
if (nc->sock != INVALID_SOCKET) {
/* Try to consume data from cs->rx_chain */
mg_lwip_consume_rx_chain_tcp(nc);
/*
* If the connection is about to close, and rx_chain is finally empty,
* send the MG_SIG_CLOSE_CONN signal
*/
if (cs->draining_rx_chain && cs->rx_chain == NULL) {
if (mg_lwip_if_can_send(nc, cs)) {
mg_if_can_send_cb(nc);
mbuf_trim(&nc->send_mbuf);
}
if (cs->rx_chain != NULL) {
mg_if_can_recv_cb(nc);
} else if (cs->draining_rx_chain) {
/*
* If the connection is about to close, and rx_chain is finally empty,
* send the MG_SIG_CLOSE_CONN signal
*/
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
}
}
@@ -210,21 +168,9 @@ uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) {
}
num_timers++;
}
if (nc->send_mbuf.len > 0
#if MG_ENABLE_SSL
|| (nc->flags & MG_F_WANT_WRITE)
#endif
) {
int can_send = 0;
/* We have stuff to send, but can we? */
if (nc->flags & MG_F_UDP) {
/* UDP is always ready for sending. */
can_send = (cs->pcb.udp != NULL);
} else {
can_send = (cs->pcb.tcp != NULL && cs->pcb.tcp->snd_buf > 0);
}
/* We want and can send, request a poll immediately. */
if (can_send) return 0;
/* We want and can send data, request a poll immediately. */
if (nc->sock != INVALID_SOCKET && mg_lwip_if_can_send(nc, cs)) {
return 0;
}
}
uint32_t timeout_ms = ~0;
+79 -163
View File
@@ -57,10 +57,6 @@
typedef void (*tcpip_callback_fn)(void *arg);
#endif
void mg_lwip_ssl_do_hs(struct mg_connection *nc);
void mg_lwip_ssl_send(struct mg_connection *nc);
void mg_lwip_ssl_recv(struct mg_connection *nc);
void mg_lwip_if_init(struct mg_iface *iface);
void mg_lwip_if_free(struct mg_iface *iface);
void mg_lwip_if_add_conn(struct mg_connection *nc);
@@ -132,10 +128,12 @@ static void mg_lwip_tcp_error_cb(void *arg, err_t err) {
static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
struct pbuf *p, err_t err) {
struct mg_connection *nc = (struct mg_connection *) arg;
DBG(("%p %p %u %d", nc, tpcb, (p != NULL ? p->tot_len : 0), err));
struct mg_lwip_conn_state *cs =
(nc ? (struct mg_lwip_conn_state *) nc->sock : NULL);
DBG(("%p %p %p %p %u %d", nc, cs, tpcb, p, (p != NULL ? p->tot_len : 0),
err));
if (p == NULL) {
if (nc != NULL && !(nc->flags & MG_F_CLOSE_IMMEDIATELY)) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
if (cs->rx_chain != NULL) {
/*
* rx_chain still contains non-consumed data, don't close the
@@ -153,7 +151,6 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
tcp_abort(tpcb);
return ERR_ARG;
}
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
/*
* If we get a chain of more than one segment at once, we need to bump
* refcount on the subsequent bufs to make them independent.
@@ -168,7 +165,7 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
} else if (pbuf_clen(cs->rx_chain) >= 4) {
/* ESP SDK has a limited pool of 5 pbufs. We must not hog them all or RX
* will be completely blocked. We already have at least 4 in the chain,
* this one is, so we have to make a copy and release this one. */
* this one is the last, so we have to make a copy and release this one. */
struct pbuf *np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
if (np != NULL) {
pbuf_copy(np, p);
@@ -176,58 +173,9 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
p = np;
}
}
mgos_unlock();
mg_lwip_recv_common(nc, p);
return ERR_OK;
}
static void mg_lwip_consume_rx_chain_tcp(struct mg_connection *nc) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
if (cs->rx_chain == NULL) return;
#if MG_ENABLE_SSL
if (nc->flags & MG_F_SSL) {
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
mg_lwip_ssl_recv(nc);
} else {
mg_lwip_ssl_do_hs(nc);
}
return;
}
#endif
mgos_lock();
while (cs->rx_chain != NULL && nc->recv_mbuf.len < nc->recv_mbuf_limit) {
struct pbuf *seg = cs->rx_chain;
size_t seg_len = (seg->len - cs->rx_offset);
size_t buf_avail = (nc->recv_mbuf_limit - nc->recv_mbuf.len);
size_t len = MIN(seg_len, buf_avail);
char *data = (char *) MG_MALLOC(len);
if (data == NULL) {
mgos_unlock();
DBG(("OOM"));
return;
}
pbuf_copy_partial(seg, data, len, cs->rx_offset);
cs->rx_offset += len;
if (cs->rx_offset == cs->rx_chain->len) {
cs->rx_chain = pbuf_dechain(cs->rx_chain);
pbuf_free(seg);
cs->rx_offset = 0;
}
mgos_unlock();
mg_if_recv_tcp_cb(nc, data, len, 1 /* own */);
mgos_lock();
}
mgos_unlock();
}
static void mg_lwip_handle_recv_tcp(struct mg_connection *nc) {
mg_lwip_consume_rx_chain_tcp(nc);
if (nc->send_mbuf.len > 0) {
mg_lwip_mgr_schedule_poll(nc->mgr);
}
return ERR_OK;
}
static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb,
@@ -313,13 +261,14 @@ static void mg_lwip_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p,
/* Logic in the recv handler requires that there be exactly one data pbuf. */
p = pbuf_coalesce(p, PBUF_RAW);
pbuf_chain(sap, p);
mgos_lock();
mg_lwip_recv_common(nc, sap);
mgos_unlock();
(void) pcb;
}
static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
mgos_lock();
if (cs->rx_chain == NULL) {
cs->rx_chain = p;
} else {
@@ -329,32 +278,30 @@ static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p) {
cs->recv_pending = 1;
mg_lwip_post_signal(MG_SIG_RECV, nc);
}
mgos_unlock();
}
static void mg_lwip_handle_recv_udp(struct mg_connection *nc) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
static int mg_lwip_if_udp_recv(struct mg_connection *nc, void *buf, size_t len,
union socket_address *sa, size_t *sa_len) {
/*
* For UDP, RX chain consists of interleaved address and packet bufs:
* Address pbuf followed by exactly one data pbuf (recv_cb took care of that).
*/
while (cs->rx_chain != NULL) {
struct pbuf *sap = cs->rx_chain;
struct pbuf *p = sap->next;
cs->rx_chain = pbuf_dechain(p);
size_t data_len = p->len;
char *data = (char *) MG_MALLOC(data_len);
if (data != NULL) {
pbuf_copy_partial(p, data, data_len, 0);
pbuf_free(p);
mg_if_recv_udp_cb(nc, data, data_len,
(union socket_address *) sap->payload, sap->len);
pbuf_free(sap);
} else {
pbuf_free(p);
pbuf_free(sap);
}
int res = 0;
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
if (nc->sock == INVALID_SOCKET) return -1;
mgos_lock();
if (cs->rx_chain != NULL) {
struct pbuf *ap = cs->rx_chain;
struct pbuf *dp = ap->next;
cs->rx_chain = pbuf_dechain(dp);
res = MIN(dp->len, len);
pbuf_copy_partial(dp, buf, res, 0);
pbuf_free(dp);
pbuf_copy_partial(ap, sa, MIN(*sa_len, ap->len), 0);
pbuf_free(ap);
}
mgos_unlock();
return res;
}
static void mg_lwip_if_connect_udp_tcpip(void *arg) {
@@ -376,13 +323,6 @@ void mg_lwip_if_connect_udp(struct mg_connection *nc) {
tcpip_callback(mg_lwip_if_connect_udp_tcpip, nc);
}
void mg_lwip_accept_conn(struct mg_connection *nc, struct tcp_pcb *tpcb) {
union socket_address sa;
SET_ADDR(&sa, &tpcb->remote_ip);
sa.sin.sin_port = htons(tpcb->remote_port);
mg_if_accept_tcp_cb(nc, &sa, sizeof(sa.sin));
}
static void tcp_close_tcpip(void *arg) {
tcp_close((struct tcp_pcb *) arg);
}
@@ -390,17 +330,11 @@ static void tcp_close_tcpip(void *arg) {
void mg_lwip_handle_accept(struct mg_connection *nc) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
if (cs->pcb.tcp == NULL) return;
#if MG_ENABLE_SSL
if (cs->lc->flags & MG_F_SSL) {
if (mg_ssl_if_conn_accept(nc, cs->lc) != MG_SSL_OK) {
LOG(LL_ERROR, ("SSL error"));
tcpip_callback(tcp_close_tcpip, cs->pcb.tcp);
}
} else
#endif
{
mg_lwip_accept_conn(nc, cs->pcb.tcp);
}
union socket_address sa;
struct tcp_pcb *tpcb = cs->pcb.tcp;
SET_ADDR(&sa, &tpcb->remote_ip);
sa.sin.sin_port = htons(tpcb->remote_port);
mg_if_accept_tcp_cb(nc, &sa, sizeof(sa.sin));
}
static err_t mg_lwip_accept_cb(void *arg, struct tcp_pcb *newtpcb, err_t err) {
@@ -557,14 +491,13 @@ static void mg_lwip_tcp_write_tcpip(void *arg) {
ctx->ret = len;
}
static int mg_lwip_tcp_write(struct mg_connection *nc, const void *data,
uint16_t len) {
struct mg_lwip_tcp_write_ctx ctx = {.nc = nc, .data = data, .len = len};
int mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len) {
struct mg_lwip_tcp_write_ctx ctx = {.nc = nc, .data = buf, .len = len};
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
if (nc->sock == INVALID_SOCKET) return -1;
struct tcp_pcb *tpcb = cs->pcb.tcp;
if (tpcb == NULL) {
return -1;
}
if (tpcb == NULL) return -1;
if (tpcb->snd_buf <= 0) return 0;
tcpip_callback(mg_lwip_tcp_write_tcpip, &ctx);
return ctx.ret;
}
@@ -582,18 +515,10 @@ static void udp_sendto_tcpip(void *arg) {
ctx->ret = udp_sendto(ctx->upcb, ctx->p, ctx->ip, ctx->port);
}
static int mg_lwip_udp_send(struct mg_connection *nc, const void *data,
uint16_t len) {
static int mg_lwip_if_udp_send(struct mg_connection *nc, const void *data,
size_t len) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
if (cs->pcb.udp == NULL) {
/*
* In case of UDP, this usually means, what
* async DNS resolve is still in progress and connection
* is not ready yet
*/
DBG(("%p socket is not connected", nc));
return -1;
}
if (nc->sock == INVALID_SOCKET || cs->pcb.udp == NULL) return -1;
struct udp_pcb *upcb = cs->pcb.udp;
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
#if defined(LWIP_IPV4) && LWIP_IPV4 && defined(LWIP_IPV6) && LWIP_IPV6
@@ -602,46 +527,28 @@ static int mg_lwip_udp_send(struct mg_connection *nc, const void *data,
ip_addr_t ip = {.addr = nc->sa.sin.sin_addr.s_addr};
#endif
u16_t port = ntohs(nc->sa.sin.sin_port);
if (p == NULL) {
DBG(("OOM"));
return 0;
}
if (p == NULL) return 0;
memcpy(p->payload, data, len);
struct udp_sendto_ctx ctx = {.upcb = upcb, .p = p, .ip = &ip, .port = port};
tcpip_callback(udp_sendto_tcpip, &ctx);
cs->err = ctx.ret;
pbuf_free(p);
return (cs->err == ERR_OK ? len : -1);
return (cs->err == ERR_OK ? (int) len : -2);
}
static void mg_lwip_send_more(struct mg_connection *nc) {
int num_sent = 0;
if (nc->sock == INVALID_SOCKET) return;
if (nc->flags & MG_F_UDP) {
num_sent = mg_lwip_udp_send(nc, nc->send_mbuf.buf, nc->send_mbuf.len);
DBG(("%p mg_lwip_udp_send %u = %d", nc, nc->send_mbuf.len, num_sent));
} else {
num_sent = mg_lwip_tcp_write(nc, nc->send_mbuf.buf, nc->send_mbuf.len);
DBG(("%p mg_lwip_tcp_write %u = %d", nc, nc->send_mbuf.len, num_sent));
static int mg_lwip_if_can_send(struct mg_connection *nc,
struct mg_lwip_conn_state *cs) {
int can_send = 0;
if (nc->send_mbuf.len > 0 || (nc->flags & MG_F_WANT_WRITE)) {
/* We have stuff to send, but can we? */
if (nc->flags & MG_F_UDP) {
/* UDP is always ready for sending. */
can_send = (cs->pcb.udp != NULL);
} else {
can_send = (cs->pcb.tcp != NULL && cs->pcb.tcp->snd_buf > 0);
}
}
if (num_sent == 0) return;
if (num_sent > 0) {
mg_if_sent_cb(nc, num_sent);
} else {
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
}
}
void mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf,
size_t len) {
mbuf_append(&nc->send_mbuf, buf, len);
mg_lwip_mgr_schedule_poll(nc->mgr);
}
void mg_lwip_if_udp_send(struct mg_connection *nc, const void *buf,
size_t len) {
mbuf_append(&nc->send_mbuf, buf, len);
mg_lwip_mgr_schedule_poll(nc->mgr);
return can_send;
}
struct tcp_recved_ctx {
@@ -654,27 +561,35 @@ void tcp_recved_tcpip(void *arg) {
tcp_recved(ctx->tpcb, ctx->len);
}
void mg_lwip_if_recved(struct mg_connection *nc, size_t len) {
if (nc->flags & MG_F_UDP) return;
static int mg_lwip_if_tcp_recv(struct mg_connection *nc, void *buf,
size_t len) {
int res = 0;
char *bufp = buf;
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
if (nc->sock == INVALID_SOCKET || cs->pcb.tcp == NULL) {
DBG(("%p invalid socket", nc));
return;
if (nc->sock == INVALID_SOCKET) return -1;
mgos_lock();
while (cs->rx_chain != NULL && len > 0) {
struct pbuf *seg = cs->rx_chain;
size_t seg_len = (seg->len - cs->rx_offset);
size_t copy_len = MIN(len, seg_len);
pbuf_copy_partial(seg, bufp, copy_len, cs->rx_offset);
len -= copy_len;
res += copy_len;
bufp += copy_len;
cs->rx_offset += copy_len;
if (cs->rx_offset == cs->rx_chain->len) {
cs->rx_chain = pbuf_dechain(cs->rx_chain);
pbuf_free(seg);
cs->rx_offset = 0;
}
}
DBG(("%p %p %u %u", nc, cs->pcb.tcp, len,
(cs->rx_chain ? cs->rx_chain->tot_len : 0)));
struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = len};
#if MG_ENABLE_SSL
if (!(nc->flags & MG_F_SSL)) {
mgos_unlock();
if (res > 0) {
struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = res};
tcpip_callback(tcp_recved_tcpip, &ctx);
} else {
/* Currently SSL acknowledges data immediately.
* TODO(rojer): Find a way to propagate mg_lwip_if_recved. */
}
#else
tcpip_callback(tcp_recved_tcpip, &ctx);
#endif
mbuf_trim(&nc->recv_mbuf);
return res;
}
int mg_lwip_if_create_conn(struct mg_connection *nc) {
@@ -763,7 +678,8 @@ void mg_lwip_if_sock_set(struct mg_connection *nc, sock_t sock) {
mg_lwip_if_connect_udp, \
mg_lwip_if_tcp_send, \
mg_lwip_if_udp_send, \
mg_lwip_if_recved, \
mg_lwip_if_tcp_recv, \
mg_lwip_if_udp_recv, \
mg_lwip_if_create_conn, \
mg_lwip_if_destroy_conn, \
mg_lwip_if_sock_set, \
+2 -2
View File
@@ -30,9 +30,9 @@ struct mg_lwip_conn_state {
/* Last SSL write size, for retries. */
int last_ssl_write_size;
/* Whether MG_SIG_RECV is already pending for this connection */
int recv_pending : 1;
int recv_pending;
/* Whether the connection is about to close, just `rx_chain` needs to drain */
int draining_rx_chain : 1;
int draining_rx_chain;
};
enum mg_sig_type {
-197
View File
@@ -1,197 +0,0 @@
/*
* Copyright (c) 2014-2016 Cesanta Software Limited
* All rights reserved
*/
#if MG_ENABLE_SSL && MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
#include "common/mg_mem.h"
#include "common/cs_dbg.h"
#include <lwip/pbuf.h>
#include <lwip/tcp.h>
#ifndef MG_LWIP_SSL_IO_SIZE
#define MG_LWIP_SSL_IO_SIZE 1024
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
void mg_lwip_ssl_do_hs(struct mg_connection *nc) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
int server_side = (nc->listener != NULL);
enum mg_ssl_if_result res;
if (nc->flags & MG_F_CLOSE_IMMEDIATELY) return;
res = mg_ssl_if_handshake(nc);
DBG(("%p %lu %d %d", nc, nc->flags, server_side, res));
if (res != MG_SSL_OK) {
if (res == MG_SSL_WANT_WRITE) {
nc->flags |= MG_F_WANT_WRITE;
cs->err = 0;
} else if (res == MG_SSL_WANT_READ) {
/*
* Nothing to do in particular, we are callback-driven.
* What we definitely do not need anymore is SSL reading (nothing left).
*/
nc->flags &= ~MG_F_WANT_READ;
cs->err = 0;
} else {
cs->err = res;
if (server_side) {
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
} else {
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
}
}
} else {
cs->err = 0;
nc->flags &= ~MG_F_WANT_WRITE;
/*
* Handshake is done. Schedule a read immediately to consume app data
* which may already be waiting.
*/
nc->flags |= (MG_F_SSL_HANDSHAKE_DONE | MG_F_WANT_READ);
if (server_side) {
mg_lwip_accept_conn(nc, cs->pcb.tcp);
} else {
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
}
}
}
void mg_lwip_ssl_send(struct mg_connection *nc) {
if (nc->sock == INVALID_SOCKET) {
DBG(("%p invalid socket", nc));
return;
}
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
/* It's ok if the buffer is empty. Return value of 0 may also be valid. */
int len = cs->last_ssl_write_size;
if (len == 0) {
len = MIN(MG_LWIP_SSL_IO_SIZE, nc->send_mbuf.len);
}
int ret = mg_ssl_if_write(nc, nc->send_mbuf.buf, len);
DBG(("%p SSL_write %u = %d", nc, len, ret));
if (ret > 0) {
mg_if_sent_cb(nc, ret);
cs->last_ssl_write_size = 0;
} else if (ret < 0) {
/* This is tricky. We must remember the exact data we were sending to retry
* exactly the same send next time. */
cs->last_ssl_write_size = len;
}
if (ret == len) {
nc->flags &= ~MG_F_WANT_WRITE;
} else if (ret == MG_SSL_WANT_WRITE) {
nc->flags |= MG_F_WANT_WRITE;
} else {
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
}
}
void mg_lwip_ssl_recv(struct mg_connection *nc) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
/* Don't deliver data before connect callback */
if (nc->flags & MG_F_CONNECTING) return;
while (nc->recv_mbuf.len < nc->recv_mbuf_limit) {
char *buf = (char *) MG_MALLOC(MG_LWIP_SSL_IO_SIZE);
if (buf == NULL) return;
int ret = mg_ssl_if_read(nc, buf, MG_LWIP_SSL_IO_SIZE);
DBG(("%p %p SSL_read %u = %d", nc, cs->rx_chain, MG_LWIP_SSL_IO_SIZE, ret));
if (ret <= 0) {
MG_FREE(buf);
if (ret == MG_SSL_WANT_WRITE) {
nc->flags |= MG_F_WANT_WRITE;
return;
} else if (ret == MG_SSL_WANT_READ) {
/*
* Nothing to do in particular, we are callback-driven.
* What we definitely do not need anymore is SSL reading (nothing left).
*/
nc->flags &= ~MG_F_WANT_READ;
cs->err = 0;
return;
} else {
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
return;
}
} else {
mg_if_recv_tcp_cb(nc, buf, ret, 1 /* own */);
}
}
}
#ifdef KR_VERSION
ssize_t kr_send(int fd, const void *buf, size_t len) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) fd;
int ret = mg_lwip_tcp_write(cs->nc, buf, len);
DBG(("%p mg_lwip_tcp_write %u = %d", cs->nc, len, ret));
if (ret == 0) ret = KR_IO_WOULDBLOCK;
return ret;
}
ssize_t kr_recv(int fd, void *buf, size_t len) {
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) fd;
struct pbuf *seg = cs->rx_chain;
if (seg == NULL) {
DBG(("%u - nothing to read", len));
return KR_IO_WOULDBLOCK;
}
size_t seg_len = (seg->len - cs->rx_offset);
DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len));
len = MIN(len, seg_len);
pbuf_copy_partial(seg, buf, len, cs->rx_offset);
cs->rx_offset += len;
tcp_recved(cs->pcb.tcp, len);
if (cs->rx_offset == cs->rx_chain->len) {
cs->rx_chain = pbuf_dechain(cs->rx_chain);
pbuf_free(seg);
cs->rx_offset = 0;
}
return len;
}
#elif MG_SSL_IF == MG_SSL_IF_MBEDTLS
int ssl_socket_send(void *ctx, const unsigned char *buf, size_t len) {
struct mg_connection *nc = (struct mg_connection *) ctx;
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
int ret = mg_lwip_tcp_write(cs->nc, buf, len);
if (ret == 0) ret = MBEDTLS_ERR_SSL_WANT_WRITE;
LOG(LL_DEBUG, ("%p %d -> %d", nc, len, ret));
return ret;
}
int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len) {
struct mg_connection *nc = (struct mg_connection *) ctx;
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
struct pbuf *seg = cs->rx_chain;
if (seg == NULL) {
DBG(("%u - nothing to read", len));
return MBEDTLS_ERR_SSL_WANT_READ;
}
size_t seg_len = (seg->len - cs->rx_offset);
DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len));
mgos_lock();
len = MIN(len, seg_len);
pbuf_copy_partial(seg, buf, len, cs->rx_offset);
cs->rx_offset += len;
/* TCP PCB may be NULL if connection has already been closed
* but we still have data to deliver to SSL. */
if (cs->pcb.tcp != NULL) tcp_recved(cs->pcb.tcp, len);
if (cs->rx_offset == cs->rx_chain->len) {
cs->rx_chain = pbuf_dechain(cs->rx_chain);
pbuf_free(seg);
cs->rx_offset = 0;
}
mgos_unlock();
LOG(LL_DEBUG, ("%p <- %d", nc, (int) len));
return len;
}
#endif
#endif /* MG_ENABLE_SSL && MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
+2
View File
@@ -22,7 +22,9 @@
#endif
#define MG_NET_IF MG_NET_IF_SIMPLELINK
#ifndef MG_SSL_IF
#define MG_SSL_IF MG_SSL_IF_SIMPLELINK
#endif
/* Only SPIFFS supports directories, SLFS does not. */
#if defined(CC3220_FS_SPIFFS) && !defined(MG_ENABLE_DIRECTORY_LISTING)
+55 -115
View File
@@ -17,7 +17,7 @@ static sock_t mg_open_listening_socket(struct mg_connection *nc,
union socket_address *sa, int type,
int proto);
void mg_set_non_blocking_mode(sock_t sock) {
static void mg_set_non_blocking_mode(sock_t sock) {
SlSockNonblocking_t opt;
#if SL_MAJOR_VERSION_NUM < 2
opt.NonblockingEnabled = 1;
@@ -31,17 +31,19 @@ static int mg_is_error(int n) {
return (n < 0 && n != SL_ERROR_BSD_EALREADY && n != SL_ERROR_BSD_EAGAIN);
}
void mg_sl_if_connect_tcp(struct mg_connection *nc,
const union socket_address *sa) {
static void mg_sl_if_connect_tcp(struct mg_connection *nc,
const union socket_address *sa) {
int proto = 0;
#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET;
#endif
sock_t sock = sl_Socket(AF_INET, SOCK_STREAM, proto);
if (sock < 0) {
nc->err = sock;
goto out;
}
mg_sock_set(nc, sock);
#if MG_ENABLE_SSL
#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
nc->err = sl_set_ssl_opts(sock, nc);
if (nc->err != 0) goto out;
#endif
@@ -51,7 +53,7 @@ out:
ntohs(sa->sin.sin_port), nc->sock, proto, nc->err));
}
void mg_sl_if_connect_udp(struct mg_connection *nc) {
static void mg_sl_if_connect_udp(struct mg_connection *nc) {
sock_t sock = sl_Socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
nc->err = sock;
@@ -61,7 +63,8 @@ void mg_sl_if_connect_udp(struct mg_connection *nc) {
nc->err = 0;
}
int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
static int mg_sl_if_listen_tcp(struct mg_connection *nc,
union socket_address *sa) {
int proto = 0;
if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET;
sock_t sock = mg_open_listening_socket(nc, sa, SOCK_STREAM, proto);
@@ -70,27 +73,50 @@ int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
return 0;
}
int mg_sl_if_listen_udp(struct mg_connection *nc, union socket_address *sa) {
static int mg_sl_if_listen_udp(struct mg_connection *nc,
union socket_address *sa) {
sock_t sock = mg_open_listening_socket(nc, sa, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) return (errno ? errno : 1);
mg_sock_set(nc, sock);
return 0;
}
void mg_sl_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len) {
mbuf_append(&nc->send_mbuf, buf, len);
static int mg_sl_if_tcp_send(struct mg_connection *nc, const void *buf,
size_t len) {
int n = (int) sl_Send(nc->sock, buf, len, 0);
if (n < 0 && !mg_is_error(n)) n = 0;
return n;
}
void mg_sl_if_udp_send(struct mg_connection *nc, const void *buf, size_t len) {
mbuf_append(&nc->send_mbuf, buf, len);
static int mg_sl_if_udp_send(struct mg_connection *nc, const void *buf,
size_t len) {
int n = sl_SendTo(nc->sock, buf, len, 0, &nc->sa.sa, sizeof(nc->sa.sin));
if (n < 0 && !mg_is_error(n)) n = 0;
return n;
}
void mg_sl_if_recved(struct mg_connection *nc, size_t len) {
(void) nc;
(void) len;
static int mg_sl_if_tcp_recv(struct mg_connection *nc, void *buf, size_t len) {
int n = sl_Recv(nc->sock, buf, len, 0);
if (n == 0) {
/* Orderly shutdown of the socket, try flushing output. */
nc->flags |= MG_F_SEND_AND_CLOSE;
} else if (n < 0 && !mg_is_error(n)) {
n = 0;
}
return n;
}
int mg_sl_if_create_conn(struct mg_connection *nc) {
static int mg_sl_if_udp_recv(struct mg_connection *nc, void *buf, size_t len,
union socket_address *sa, size_t *sa_len) {
SlSocklen_t sa_len_t = *sa_len;
int n = sl_RecvFrom(nc->sock, buf, MG_UDP_RECV_BUFFER_SIZE, 0,
(SlSockAddr_t *) sa, &sa_len_t);
*sa_len = sa_len_t;
if (n < 0 && !mg_is_error(n)) n = 0;
return n;
}
static int mg_sl_if_create_conn(struct mg_connection *nc) {
(void) nc;
return 1;
}
@@ -121,7 +147,6 @@ static int mg_accept_conn(struct mg_connection *lc) {
DBG(("%p conn from %s:%d", nc, inet_ntoa(sa.sin.sin_addr),
ntohs(sa.sin.sin_port)));
mg_sock_set(nc, sock);
if (nc->flags & MG_F_SSL) nc->flags |= MG_F_SSL_HANDSHAKE_DONE;
mg_if_accept_tcp_cb(nc, &sa, sa_len);
return 1;
}
@@ -135,11 +160,11 @@ static sock_t mg_open_listening_socket(struct mg_connection *nc,
(sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6);
sock_t sock = sl_Socket(sa->sa.sa_family, type, proto);
if (sock < 0) return sock;
#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
if ((r = sl_set_ssl_opts(sock, nc)) < 0) goto clean;
#endif
if ((r = sl_Bind(sock, &sa->sa, sa_len)) < 0) goto clean;
if (type != SOCK_DGRAM) {
#if MG_ENABLE_SSL
if ((r = sl_set_ssl_opts(sock, nc)) < 0) goto clean;
#endif
if ((r = sl_Listen(sock, SOMAXCONN)) < 0) goto clean;
}
mg_set_non_blocking_mode(sock);
@@ -151,86 +176,18 @@ clean:
return sock;
}
static void mg_write_to_socket(struct mg_connection *nc) {
struct mbuf *io = &nc->send_mbuf;
int n = 0;
if (nc->flags & MG_F_UDP) {
n = sl_SendTo(nc->sock, io->buf, io->len, 0, &nc->sa.sa,
sizeof(nc->sa.sin));
DBG(("%p %d %d %d %s:%hu", nc, nc->sock, n, errno,
inet_ntoa(nc->sa.sin.sin_addr), ntohs(nc->sa.sin.sin_port)));
} else {
n = (int) sl_Send(nc->sock, io->buf, io->len, 0);
DBG(("%p %d bytes -> %d", nc, n, nc->sock));
}
if (n > 0) {
mg_if_sent_cb(nc, n);
} else if (n < 0 && mg_is_error(n)) {
/* Something went wrong, drop the connection. */
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
}
}
MG_INTERNAL size_t recv_avail_size(struct mg_connection *conn, size_t max) {
size_t avail;
if (conn->recv_mbuf_limit < conn->recv_mbuf.len) return 0;
avail = conn->recv_mbuf_limit - conn->recv_mbuf.len;
return avail > max ? max : avail;
}
static void mg_handle_tcp_read(struct mg_connection *conn) {
int n = 0;
char *buf = (char *) MG_MALLOC(MG_TCP_RECV_BUFFER_SIZE);
if (buf == NULL) {
DBG(("OOM"));
return;
}
n = (int) sl_Recv(conn->sock, buf,
recv_avail_size(conn, MG_TCP_RECV_BUFFER_SIZE), 0);
DBG(("%p %d bytes <- %d", conn, n, conn->sock));
if (n > 0) {
mg_if_recv_tcp_cb(conn, buf, n, 1 /* own */);
} else {
MG_FREE(buf);
}
if (n == 0) {
/* Orderly shutdown of the socket, try flushing output. */
conn->flags |= MG_F_SEND_AND_CLOSE;
} else if (mg_is_error(n)) {
conn->flags |= MG_F_CLOSE_IMMEDIATELY;
}
}
static void mg_handle_udp_read(struct mg_connection *nc) {
char *buf = (char *) MG_MALLOC(MG_UDP_RECV_BUFFER_SIZE);
if (buf == NULL) return;
union socket_address sa;
socklen_t sa_len = sizeof(sa);
int n = sl_RecvFrom(nc->sock, buf, MG_UDP_RECV_BUFFER_SIZE, 0,
(SlSockAddr_t *) &sa, &sa_len);
DBG(("%p %d bytes from %s:%d", nc, n, inet_ntoa(nc->sa.sin.sin_addr),
ntohs(nc->sa.sin.sin_port)));
if (n > 0) {
mg_if_recv_udp_cb(nc, buf, n, &sa, sa_len);
} else {
MG_FREE(buf);
}
}
#define _MG_F_FD_CAN_READ 1
#define _MG_F_FD_CAN_WRITE 1 << 1
#define _MG_F_FD_ERROR 1 << 2
void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
DBG(("%p fd=%d fd_flags=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock,
DBG(("%p fd=%d fd_flags=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->sock,
fd_flags, nc->flags, (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
if (!mg_if_poll(nc, now)) return;
if (nc->flags & MG_F_CONNECTING) {
if (nc->flags & MG_F_UDP || nc->err != SL_ERROR_BSD_EALREADY) {
if ((nc->flags & MG_F_UDP) || nc->err != SL_ERROR_BSD_EALREADY) {
mg_if_connect_cb(nc, nc->err);
} else {
/* In SimpleLink, to get status of non-blocking connect() we need to wait
@@ -252,9 +209,6 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
) {
nc->err = 0;
}
if (nc->flags & MG_F_SSL && nc->err == 0) {
nc->flags |= MG_F_SSL_HANDSHAKE_DONE;
}
mg_if_connect_cb(nc, nc->err);
}
}
@@ -264,28 +218,21 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
if (fd_flags & _MG_F_FD_CAN_READ) {
if (nc->flags & MG_F_UDP) {
mg_handle_udp_read(nc);
mg_if_can_recv_cb(nc);
} else {
if (nc->flags & MG_F_LISTENING) {
mg_accept_conn(nc);
} else {
mg_handle_tcp_read(nc);
mg_if_can_recv_cb(nc);
}
}
}
if (!(nc->flags & MG_F_CLOSE_IMMEDIATELY)) {
if ((fd_flags & _MG_F_FD_CAN_WRITE) && nc->send_mbuf.len > 0) {
mg_write_to_socket(nc);
}
if (!(fd_flags & (_MG_F_FD_CAN_READ | _MG_F_FD_CAN_WRITE))) {
mg_if_poll(nc, now);
}
mg_if_timer(nc, now);
if (fd_flags & _MG_F_FD_CAN_WRITE) {
mg_if_can_send_cb(nc);
}
DBG(("%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, nc->flags,
DBG(("%p after fd=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->sock, nc->flags,
(int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
}
@@ -406,14 +353,6 @@ time_t mg_sl_if_poll(struct mg_iface *iface, int timeout_ms) {
mg_mgr_handle_conn(nc, fd_flags, now);
}
for (nc = mgr->active_connections; nc != NULL; nc = tmp) {
tmp = nc->next;
if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) ||
(nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE))) {
mg_close_conn(nc);
}
}
return now;
}
@@ -464,7 +403,8 @@ void sl_restart_cb(struct mg_mgr *mgr) {
mg_sl_if_connect_udp, \
mg_sl_if_tcp_send, \
mg_sl_if_udp_send, \
mg_sl_if_recved, \
mg_sl_if_tcp_recv, \
mg_sl_if_udp_recv, \
mg_sl_if_create_conn, \
mg_sl_if_destroy_conn, \
mg_sl_if_sock_set, \
+70 -42
View File
@@ -54,6 +54,31 @@ enum mg_ssl_if_result mg_ssl_if_conn_init(
return MG_SSL_OK;
}
enum mg_ssl_if_result mg_ssl_if_conn_accept(struct mg_connection *nc,
struct mg_connection *lc) {
/* SimpleLink does everything for us, nothing for us to do. */
(void) nc;
(void) lc;
return MG_SSL_OK;
}
enum mg_ssl_if_result mg_ssl_if_handshake(struct mg_connection *nc) {
/* SimpleLink has already performed the handshake, nothing to do. */
return MG_SSL_OK;
}
int mg_ssl_if_read(struct mg_connection *nc, void *buf, size_t len) {
/* SimpelLink handles TLS, so this is just a pass-through. */
int n = nc->iface->vtable->tcp_recv(nc, buf, len);
if (n == 0) nc->flags |= MG_F_WANT_READ;
return n;
}
int mg_ssl_if_write(struct mg_connection *nc, const void *buf, size_t len) {
/* SimpelLink handles TLS, so this is just a pass-through. */
return nc->iface->vtable->tcp_send(nc, buf, len);
}
void mg_ssl_if_conn_close_notify(struct mg_connection *nc) {
/* Nothing to do */
(void) nc;
@@ -154,56 +179,59 @@ int sl_set_ssl_opts(int sock, struct mg_connection *nc) {
const struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
DBG(("%p ssl ctx: %p", nc, ctx));
if (ctx != NULL) {
DBG(("%p %s,%s,%s,%s", nc, (ctx->ssl_cert ? ctx->ssl_cert : "-"),
(ctx->ssl_key ? ctx->ssl_cert : "-"),
(ctx->ssl_ca_cert ? ctx->ssl_ca_cert : "-"),
(ctx->ssl_server_name ? ctx->ssl_server_name : "-")));
if (ctx->ssl_cert != NULL && ctx->ssl_key != NULL) {
char *ssl_cert = sl_pem2der(ctx->ssl_cert);
char *ssl_key = sl_pem2der(ctx->ssl_key);
if (ssl_cert != NULL && ssl_key != NULL) {
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert,
strlen(ssl_cert));
LOG(LL_INFO, ("CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err));
if (ctx == NULL) return 0;
DBG(("%p %s,%s,%s,%s", nc, (ctx->ssl_cert ? ctx->ssl_cert : "-"),
(ctx->ssl_key ? ctx->ssl_cert : "-"),
(ctx->ssl_ca_cert ? ctx->ssl_ca_cert : "-"),
(ctx->ssl_server_name ? ctx->ssl_server_name : "-")));
if (ctx->ssl_cert != NULL && ctx->ssl_key != NULL) {
char *ssl_cert = sl_pem2der(ctx->ssl_cert), *ssl_key = NULL;
if (ssl_cert != NULL) {
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert,
strlen(ssl_cert));
MG_FREE(ssl_cert);
LOG(LL_DEBUG, ("CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err));
ssl_key = sl_pem2der(ctx->ssl_key);
if (ssl_key != NULL) {
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key,
strlen(ssl_key));
LOG(LL_INFO, ("PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err));
MG_FREE(ssl_key);
LOG(LL_DEBUG, ("PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err));
} else {
err = -1;
}
MG_FREE(ssl_cert);
MG_FREE(ssl_key);
} else {
err = -1;
}
if (err != 0) return err;
}
if (ctx->ssl_ca_cert != NULL) {
if (ctx->ssl_ca_cert[0] != '\0') {
char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert);
if (ssl_ca_cert != NULL) {
err =
sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME,
ssl_ca_cert, strlen(ssl_ca_cert));
LOG(LL_DEBUG, ("CA_FILE_NAME %s -> %d", ssl_ca_cert, err));
} else {
err = -1;
}
MG_FREE(ssl_ca_cert);
if (err != 0) return err;
}
if (ctx->ssl_ca_cert != NULL) {
if (ctx->ssl_ca_cert[0] != '\0') {
char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert);
if (ssl_ca_cert != NULL) {
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_CA_FILE_NAME, ssl_ca_cert,
strlen(ssl_ca_cert));
LOG(LL_INFO, ("CA_FILE_NAME %s -> %d", ssl_ca_cert, err));
} else {
err = -1;
}
MG_FREE(ssl_ca_cert);
if (err != 0) return err;
}
}
if (ctx->ssl_server_name != NULL) {
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
ctx->ssl_server_name, strlen(ctx->ssl_server_name));
DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err));
/* Domain name verificationw as added in a NWP service pack, older
* versions return SL_ERROR_BSD_ENOPROTOOPT. There isn't much we can do
* about it,
* so we ignore the error. */
if (err != 0 && err != SL_ERROR_BSD_ENOPROTOOPT) return err;
}
}
if (ctx->ssl_server_name != NULL) {
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
ctx->ssl_server_name, strlen(ctx->ssl_server_name));
DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err));
/* Domain name verificationw as added in a NWP service pack, older
* versions return SL_ERROR_BSD_ENOPROTOOPT. There isn't much we can do
* about it,
* so we ignore the error. */
if (err != 0 && err != SL_ERROR_BSD_ENOPROTOOPT) return err;
}
return 0;
}