sdk-ameba-v4.0c_180328/component/common/application/mqtt/MQTTClient/MQTTFreertos.c
2019-04-02 16:34:25 +08:00

890 lines
24 KiB
C
Executable file

/*******************************************************************************
* Copyright (c) 2014, 2015 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Allan Stockdill-Mander - initial API and implementation and/or initial documentation
* Ian Craggs - convert to FreeRTOS
*******************************************************************************/
#include "MQTTFreertos.h"
#include "netdb.h"
#ifdef LWIP_IPV6
#undef LWIP_IPV6
#endif
#ifdef inet_ntop
#undef inet_ntop
#endif
#ifdef inet_pton
#undef inet_pton
#endif
#define LWIP_IPV6 0
#if LWIP_IPV6
#define inet_ntop(af,src,dst,size) \
(((af) == AF_INET6) ? ip6addr_ntoa_r((src),(dst),(size)) \
: (((af) == AF_INET) ? ipaddr_ntoa_r((src),(dst),(size)) : NULL))
#define inet_pton(af,src,dst) \
(((af) == AF_INET6) ? inet6_aton((src),(dst)) \
: (((af) == AF_INET) ? inet_aton((src),(dst)) : 0))
#else /* LWIP_IPV6 */
#define inet_ntop(af,src,dst,size) \
(((af) == AF_INET) ? ipaddr_ntoa_r((src),(dst),(size)) : NULL)
#define inet_pton(af,src,dst) \
(((af) == AF_INET) ? inet_aton((src),(dst)) : 0)
#endif /* LWIP_IPV6 */
int ThreadStart(Thread* thread, void (*fn)(void*), void* arg)
{
int rc = 0;
uint16_t usTaskStackSize = (configMINIMAL_STACK_SIZE * 5);
UBaseType_t uxTaskPriority = uxTaskPriorityGet(NULL); /* set the priority as the same as the calling task*/
rc = xTaskCreate(fn, /* The function that implements the task. */
"MQTTTask", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
arg, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
&thread->task); /* The task handle is not used. */
return rc;
}
void MutexInit(Mutex* mutex)
{
mutex->sem = xSemaphoreCreateMutex();
}
int MutexLock(Mutex* mutex)
{
return xSemaphoreTake(mutex->sem, portMAX_DELAY);
}
int MutexUnlock(Mutex* mutex)
{
return xSemaphoreGive(mutex->sem);
}
void TimerCountdownMS(Timer* timer, unsigned int timeout_ms)
{
timer->xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
vTaskSetTimeOutState(&timer->xTimeOut); /* Record the time at which this function was entered. */
}
void TimerCountdown(Timer* timer, unsigned int timeout)
{
TimerCountdownMS(timer, timeout * 1000);
}
int TimerLeftMS(Timer* timer)
{
xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait); /* updates xTicksToWait to the number left */
return (timer->xTicksToWait * portTICK_PERIOD_MS);
}
char TimerIsExpired(Timer* timer)
{
return xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait) == pdTRUE;
}
void TimerInit(Timer* timer)
{
timer->xTicksToWait = 0;
memset(&timer->xTimeOut, '\0', sizeof(timer->xTimeOut));
}
#if CONFIG_USE_POLARSSL
int FreeRTOS_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
TimeOut_t xTimeOut;
int recvLen = 0;
int so_error;
socklen_t errlen = sizeof(so_error);
vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
do
{
int rc = 0;
#if defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) && (LWIP_SO_SNDRCVTIMEO_NONSTANDARD == 0)
// timeout format is changed in lwip 1.5.0
struct timeval timeout;
timeout.tv_sec = xTicksToWait / 1000;
timeout.tv_usec = ( xTicksToWait % 1000 ) * 1000;
setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval));
#else
setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &xTicksToWait, sizeof(xTicksToWait));
#endif
#if (MQTT_OVER_SSL)
if (n->use_ssl) {
rc = ssl_read(n->ssl, buffer + recvLen, len - recvLen);
getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen);
if (so_error && so_error != EAGAIN) {
n->disconnect(n);
}
} else
#endif
rc = recv(n->my_socket, buffer + recvLen, len - recvLen, 0);
if (rc > 0)
recvLen += rc;
else if (rc < 0)
{
getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen);
if (so_error != EAGAIN) {
n->disconnect(n);
}
recvLen = rc;
break;
}
} while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
return recvLen;
}
int FreeRTOS_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
TimeOut_t xTimeOut;
int sentLen = 0;
int so_error;
socklen_t errlen = sizeof(so_error);
vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
do
{
int rc = 0;
#if defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) && (LWIP_SO_SNDRCVTIMEO_NONSTANDARD == 0)
// timeout format is changed in lwip 1.5.0
struct timeval timeout;
timeout.tv_sec = xTicksToWait / 1000;
timeout.tv_usec = ( xTicksToWait % 1000 ) * 1000;
setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval));
#else
setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &xTicksToWait, sizeof(xTicksToWait));
#endif
#if (MQTT_OVER_SSL)
if (n->use_ssl) {
rc = ssl_write(n->ssl, buffer + sentLen, len - sentLen);
getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen);
if (so_error && so_error != EAGAIN) {
n->disconnect(n);
}
} else
#endif
rc = send(n->my_socket, buffer + sentLen, len - sentLen, 0);
if (rc > 0)
sentLen += rc;
else if (rc < 0)
{
getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error != EAGAIN) {
n->disconnect(n);
}
sentLen = rc;
break;
}
} while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
return sentLen;
}
void FreeRTOS_disconnect(Network* n)
{
shutdown(n->my_socket, SHUT_RDWR);
close(n->my_socket);
n->my_socket = -1;
#if (MQTT_OVER_SSL)
if (n->use_ssl) {
ssl_free(n->ssl);
free(n->ssl);
n->ssl = NULL;
}
#endif
}
void NetworkInit(Network* n)
{
n->my_socket = -1;
n->mqttread = FreeRTOS_read;
n->mqttwrite = FreeRTOS_write;
n->disconnect = FreeRTOS_disconnect;
#if (MQTT_OVER_SSL)
n->use_ssl = 0;
n->ssl = NULL;
n->rootCA = NULL;
n->clientCA = NULL;
n->private_key = NULL;
#endif
}
#if (MQTT_OVER_SSL)
static int mqtt_tls_verify( void *data, x509_crt *crt, int depth, int *flags )
{
char buf[1024];
mqtt_printf(MQTT_DEBUG, "\nVerify requested for (Depth %d):\n", depth );
x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
mqtt_printf(MQTT_DEBUG, "%s", buf );
if( ( (*flags) & BADCERT_EXPIRED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! server certificate has expired\n" );
if( ( (*flags) & BADCERT_REVOKED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! server certificate has been revoked\n" );
if( ( (*flags) & BADCERT_CN_MISMATCH ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! CN mismatch\n" );
if( ( (*flags) & BADCERT_NOT_TRUSTED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! self-signed or not signed by a trusted CA\n" );
if( ( (*flags) & BADCRL_NOT_TRUSTED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! CRL not trusted\n" );
if( ( (*flags) & BADCRL_EXPIRED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! CRL expired\n" );
if( ( (*flags) & BADCERT_OTHER ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! other (unknown) flag\n" );
if ( ( *flags ) == 0 )
mqtt_printf(MQTT_DEBUG, " This certificate has no flags\n" );
return( 0 );
}
static int my_random(void *p_rng, unsigned char *output, size_t output_len)
{
rtw_get_random_bytes(output, output_len);
return 0;
}
#endif // #if (MQTT_OVER_SSL)
int NetworkConnect(Network* n, char* addr, int port)
{
struct sockaddr_in sAddr;
int retVal = -1;
struct hostent *hptr;
char **pptr;
char str[32];
int keepalive_enable = 1;
int keep_idle = 30;
if(n->my_socket >= 0){
n->disconnect(n);
}
if ((hptr = gethostbyname(addr)) == 0)
{
mqtt_printf(MQTT_DEBUG, "gethostbyname failed!");
goto exit;
}
pptr = hptr->h_addr_list;
for(; *pptr!=NULL; pptr++)
{
inet_ntop(hptr->h_addrtype, (const ip_addr_t *)*pptr, str, sizeof(str));
}
inet_ntop(hptr->h_addrtype, (const ip_addr_t *)hptr->h_addr, str, sizeof(str));
sAddr.sin_family = AF_INET;
sAddr.sin_port = htons(port);
sAddr.sin_addr.s_addr = inet_addr(str);
mqtt_printf(MQTT_DEBUG, "addr = %s", str);
if ((n->my_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
goto exit;
}
setsockopt( n->my_socket, SOL_SOCKET, SO_KEEPALIVE,
(const char *) &keepalive_enable, sizeof( keepalive_enable ) );
setsockopt( n->my_socket, IPPROTO_TCP, TCP_KEEPIDLE,
(const char *) &keep_idle, sizeof( keep_idle ) );
if ((retVal = connect(n->my_socket, (struct sockaddr*)&sAddr, sizeof(sAddr))) < 0)
{
close(n->my_socket);
mqtt_printf(MQTT_DEBUG, "Connect failed!!");
goto exit;
}
#if (MQTT_OVER_SSL)
x509_crt *root_crt;
x509_crt *client_crt;
pk_context *client_rsa;
root_crt = NULL;
client_crt = NULL;
client_rsa = NULL;
if ( n->use_ssl != 0 ) {
memory_set_own(pvPortMalloc, vPortFree);
n->ssl = (ssl_context *) malloc( sizeof(ssl_context) );
if ( n->ssl == NULL ) {
mqtt_printf(MQTT_DEBUG, "malloc ssl failed!");
goto err;
}
memset(n->ssl, 0, sizeof(ssl_context));
if ( ssl_init(n->ssl) != 0 ) {
mqtt_printf(MQTT_DEBUG, "init ssl failed!");
goto err;
}
ssl_set_endpoint(n->ssl, SSL_IS_CLIENT);
if (n->rootCA != NULL) {
root_crt = (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
if ( root_crt == NULL ) {
mqtt_printf(MQTT_DEBUG, "malloc root_crt failed!");
goto err;
}
memset(root_crt, 0, sizeof(x509_crt));
ssl_set_authmode( n->ssl, SSL_VERIFY_REQUIRED );
if (x509_crt_parse( root_crt, n->rootCA, strlen(n->rootCA) ) != 0) {
mqtt_printf(MQTT_DEBUG, "parse root_crt failed!");
goto err;
}
ssl_set_ca_chain( n->ssl, root_crt, NULL, NULL );
ssl_set_verify( n->ssl, mqtt_tls_verify, NULL );
mqtt_printf(MQTT_DEBUG, "root_crt parse done");
} else {
ssl_set_authmode(n->ssl, SSL_VERIFY_NONE);
}
if (n->clientCA != NULL && n->private_key != NULL) {
client_crt = (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
if ( client_crt == NULL ) {
mqtt_printf(MQTT_DEBUG, "malloc client_crt failed!");
goto err;
}
memset(client_crt, 0, sizeof(x509_crt));
x509_crt_init(client_crt);
client_rsa = (pk_context *) polarssl_malloc( sizeof(pk_context) );
if ( client_rsa == NULL ) {
mqtt_printf(MQTT_DEBUG, "malloc client_rsa failed!");
goto err;
}
memset(client_rsa, 0, sizeof(pk_context));
pk_init(client_rsa);
if ( x509_crt_parse(client_crt, n->clientCA, strlen(n->clientCA)) != 0 ) {
mqtt_printf(MQTT_DEBUG, "parse client_crt failed!");
goto err;
}
if ( pk_parse_key(client_rsa, n->private_key, strlen(n->private_key), NULL, 0) != 0 ) {
mqtt_printf(MQTT_DEBUG, "parse client_rsa failed!");
goto err;
}
ssl_set_own_cert(n->ssl, client_crt, client_rsa);
mqtt_printf(MQTT_DEBUG, "client_crt parse done");
}
ssl_set_rng(n->ssl, my_random, NULL);
ssl_set_bio(n->ssl, net_recv, &n->my_socket, net_send, &n->my_socket);
retVal = ssl_handshake(n->ssl);
if (retVal < 0) {
mqtt_printf(MQTT_DEBUG, "ssl handshake failed err:-0x%04X", -retVal);
goto err;
} else {
mqtt_printf(MQTT_DEBUG, "ssl handshake success");
}
}
if (client_rsa) {
pk_free(client_rsa);
polarssl_free(client_rsa);
}
if (client_crt) {
x509_crt_free(client_crt);
polarssl_free(client_crt);
}
if (root_crt) {
x509_crt_free(root_crt);
polarssl_free(root_crt);
}
goto exit;
err:
if (client_rsa) {
pk_free(client_rsa);
polarssl_free(client_rsa);
}
if (client_crt) {
x509_crt_free(client_crt);
polarssl_free(client_crt);
}
if (root_crt) {
x509_crt_free(root_crt);
polarssl_free(root_crt);
}
net_close(n->my_socket);
ssl_free(n->ssl);
free(n->ssl);
retVal = -1;
#endif // #if (MQTT_OVER_SSL)
exit:
return retVal;
}
#elif CONFIG_USE_MBEDTLS /* CONFIG_USE_POLARSSL */
int FreeRTOS_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
TimeOut_t xTimeOut;
int recvLen = 0;
int so_error;
socklen_t errlen = sizeof(so_error);
vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
do
{
int rc = 0;
#if defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) && (LWIP_SO_SNDRCVTIMEO_NONSTANDARD == 0)
// timeout format is changed in lwip 1.5.0
struct timeval timeout;
timeout.tv_sec = xTicksToWait / 1000;
timeout.tv_usec = ( xTicksToWait % 1000 ) * 1000;
setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval));
#else
setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &xTicksToWait, sizeof(xTicksToWait));
#endif
#if (MQTT_OVER_SSL)
if (n->use_ssl) {
rc = mbedtls_ssl_read(n->ssl, buffer + recvLen, len - recvLen);
getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen);
if (so_error && so_error != EAGAIN) {
n->disconnect(n);
}
} else
#endif
rc = recv(n->my_socket, buffer + recvLen, len - recvLen, 0);
if (rc > 0)
recvLen += rc;
else if (rc < 0)
{
getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen);
if (so_error != EAGAIN) {
n->disconnect(n);
}
recvLen = rc;
break;
}
} while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
return recvLen;
}
int FreeRTOS_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
TimeOut_t xTimeOut;
int sentLen = 0;
int so_error;
socklen_t errlen = sizeof(so_error);
vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
do
{
int rc = 0;
#if defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) && (LWIP_SO_SNDRCVTIMEO_NONSTANDARD == 0)
// timeout format is changed in lwip 1.5.0
struct timeval timeout;
timeout.tv_sec = xTicksToWait / 1000;
timeout.tv_usec = ( xTicksToWait % 1000 ) * 1000;
setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval));
#else
setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &xTicksToWait, sizeof(xTicksToWait));
#endif
#if (MQTT_OVER_SSL)
if (n->use_ssl) {
rc = mbedtls_ssl_write(n->ssl, buffer + sentLen, len - sentLen);
getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen);
if (so_error && so_error != EAGAIN) {
n->disconnect(n);
}
} else
#endif
rc = send(n->my_socket, buffer + sentLen, len - sentLen, 0);
if (rc > 0)
sentLen += rc;
else if (rc < 0)
{
getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error != EAGAIN) {
n->disconnect(n);
}
sentLen = rc;
break;
}
} while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
return sentLen;
}
void FreeRTOS_disconnect(Network* n)
{
shutdown(n->my_socket, SHUT_RDWR);
close(n->my_socket);
n->my_socket = -1;
#if (MQTT_OVER_SSL)
if (n->use_ssl) {
mbedtls_ssl_free(n->ssl);
mbedtls_ssl_config_free(n->conf);
free(n->ssl);
free(n->conf);
n->ssl = NULL;
n->conf = NULL;
}
#endif
}
void NetworkInit(Network* n)
{
n->my_socket = -1;
n->mqttread = FreeRTOS_read;
n->mqttwrite = FreeRTOS_write;
n->disconnect = FreeRTOS_disconnect;
#if (MQTT_OVER_SSL)
n->use_ssl = 0;
n->ssl = NULL;
n->conf = NULL;
n->rootCA = NULL;
n->clientCA = NULL;
n->private_key = NULL;
#endif
}
#if (MQTT_OVER_SSL)
static int mqtt_tls_verify( void *data, mbedtls_x509_crt *crt, int depth, int *flags )
{
char buf[1024];
mqtt_printf(MQTT_DEBUG, "\nVerify requested for (Depth %d):\n", depth );
mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
mqtt_printf(MQTT_DEBUG, "%s", buf );
if( ( (*flags) & MBEDTLS_X509_BADCERT_EXPIRED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! server certificate has expired\n" );
if( ( (*flags) & MBEDTLS_X509_BADCERT_REVOKED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! server certificate has been revoked\n" );
if( ( (*flags) & MBEDTLS_X509_BADCERT_CN_MISMATCH ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! CN mismatch\n" );
if( ( (*flags) & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! self-signed or not signed by a trusted CA\n" );
if( ( (*flags) & MBEDTLS_X509_BADCRL_NOT_TRUSTED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! CRL not trusted\n" );
if( ( (*flags) & MBEDTLS_X509_BADCRL_EXPIRED ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! CRL expired\n" );
if( ( (*flags) & MBEDTLS_X509_BADCERT_OTHER ) != 0 )
mqtt_printf(MQTT_DEBUG, " ! other (unknown) flag\n" );
if ( ( *flags ) == 0 )
mqtt_printf(MQTT_DEBUG, " This certificate has no flags\n" );
return( 0 );
}
static void* my_calloc(size_t nelements, size_t elementSize)
{
size_t size;
void *ptr = NULL;
size = nelements * elementSize;
ptr = pvPortMalloc(size);
if(ptr)
memset(ptr, 0, size);
return ptr;
}
static int my_random(void *p_rng, unsigned char *output, size_t output_len)
{
rtw_get_random_bytes(output, output_len);
return 0;
}
#endif // #if (MQTT_OVER_SSL)
int NetworkConnect(Network* n, char* addr, int port)
{
struct sockaddr_in sAddr;
int retVal = -1;
struct hostent *hptr;
char **pptr;
char str[32];
int keepalive_enable = 1;
int keep_idle = 30;
if(n->my_socket >= 0){
n->disconnect(n);
}
if ((hptr = gethostbyname(addr)) == 0)
{
mqtt_printf(MQTT_DEBUG, "gethostbyname failed!");
goto exit;
}
pptr = hptr->h_addr_list;
for(; *pptr!=NULL; pptr++)
{
inet_ntop(hptr->h_addrtype, (const ip_addr_t *)*pptr, str, sizeof(str));
}
inet_ntop(hptr->h_addrtype, (const ip_addr_t *)hptr->h_addr, str, sizeof(str));
sAddr.sin_family = AF_INET;
sAddr.sin_port = htons(port);
sAddr.sin_addr.s_addr = inet_addr(str);
mqtt_printf(MQTT_DEBUG, "addr = %s", str);
if ((n->my_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
goto exit;
}
setsockopt( n->my_socket, SOL_SOCKET, SO_KEEPALIVE,
(const char *) &keepalive_enable, sizeof( keepalive_enable ) );
setsockopt( n->my_socket, IPPROTO_TCP, TCP_KEEPIDLE,
(const char *) &keep_idle, sizeof( keep_idle ) );
if ((retVal = connect(n->my_socket, (struct sockaddr*)&sAddr, sizeof(sAddr))) < 0)
{
close(n->my_socket);
mqtt_printf(MQTT_DEBUG, "Connect failed!!");
goto exit;
}
#if (MQTT_OVER_SSL)
mbedtls_x509_crt *root_crt;
mbedtls_x509_crt *client_crt;
mbedtls_pk_context *client_rsa;
root_crt = NULL;
client_crt = NULL;
client_rsa = NULL;
if ( n->use_ssl != 0 ) {
mbedtls_platform_set_calloc_free(my_calloc, vPortFree);
n->ssl = (mbedtls_ssl_context *) malloc( sizeof(mbedtls_ssl_context) );
n->conf = (mbedtls_ssl_config *) malloc( sizeof(mbedtls_ssl_config) );
if (( n->ssl == NULL )||( n->conf == NULL )) {
mqtt_printf(MQTT_DEBUG, "malloc ssl failed!");
goto err;
}
mbedtls_ssl_init(n->ssl);
mbedtls_ssl_config_init(n->conf);
if (n->rootCA != NULL) {
root_crt = (mbedtls_x509_crt *) mbedtls_calloc( sizeof(mbedtls_x509_crt), 1);
if ( root_crt == NULL ) {
mqtt_printf(MQTT_DEBUG, "malloc root_crt failed!");
goto err;
}
mbedtls_x509_crt_init(root_crt);
if (mbedtls_x509_crt_parse( root_crt, n->rootCA, strlen(n->rootCA)+1 ) != 0) {
mqtt_printf(MQTT_DEBUG, "parse root_crt failed!");
goto err;
}
mbedtls_ssl_conf_ca_chain( n->conf, root_crt, NULL);
mbedtls_ssl_conf_authmode(n->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_conf_verify( n->conf, mqtt_tls_verify, NULL );
mqtt_printf(MQTT_DEBUG, "root_crt parse done");
} else {
mbedtls_ssl_conf_authmode(n->conf, MBEDTLS_SSL_VERIFY_NONE);
}
if (n->clientCA != NULL && n->private_key != NULL) {
client_crt = (mbedtls_x509_crt *) mbedtls_calloc( sizeof(mbedtls_x509_crt), 1);
if ( client_crt == NULL ) {
mqtt_printf(MQTT_DEBUG, "malloc client_crt failed!");
goto err;
}
mbedtls_x509_crt_init(client_crt);
client_rsa = (mbedtls_pk_context *) mbedtls_calloc( sizeof(mbedtls_pk_context), 1);
if ( client_rsa == NULL ) {
mqtt_printf(MQTT_DEBUG, "malloc client_rsa failed!");
goto err;
}
mbedtls_pk_init(client_rsa);
if ( mbedtls_x509_crt_parse(client_crt, n->clientCA, strlen(n->clientCA)+1) != 0 ) {
mqtt_printf(MQTT_DEBUG, "parse client_crt failed!");
goto err;
}
if ( mbedtls_pk_parse_key(client_rsa, n->private_key, strlen(n->private_key)+1, NULL, 0) != 0 ) {
mqtt_printf(MQTT_DEBUG, "parse client_rsa failed!");
goto err;
}
}
mbedtls_ssl_conf_own_cert(n->conf, client_crt, client_rsa);
mbedtls_ssl_set_bio(n->ssl, &n->my_socket, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_ssl_conf_rng(n->conf, my_random, NULL);
if((mbedtls_ssl_config_defaults(n->conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
mqtt_printf(MQTT_DEBUG, "ssl config defaults failed!");
goto err;
}
if((mbedtls_ssl_setup(n->ssl, n->conf)) != 0) {
mqtt_printf(MQTT_DEBUG,"mbedtls_ssl_setup failed!");
goto err;
}
retVal = mbedtls_ssl_handshake(n->ssl);
if (retVal < 0) {
mqtt_printf(MQTT_DEBUG, "ssl handshake failed err:-0x%04X", -retVal);
goto err;
} else {
mqtt_printf(MQTT_DEBUG, "ssl handshake success");
}
}
if (client_rsa) {
mbedtls_pk_free(client_rsa);
mbedtls_free(client_rsa);
}
if (client_crt) {
mbedtls_x509_crt_free(client_crt);
mbedtls_free(client_crt);
}
if (root_crt) {
mbedtls_x509_crt_free(root_crt);
mbedtls_free(root_crt);
}
goto exit;
err:
if (client_rsa) {
mbedtls_pk_free(client_rsa);
mbedtls_free(client_rsa);
}
if (client_crt) {
mbedtls_x509_crt_free(client_crt);
mbedtls_free(client_crt);
}
if (root_crt) {
mbedtls_x509_crt_free(root_crt);
mbedtls_free(root_crt);
}
mbedtls_net_free(&n->my_socket);
mbedtls_ssl_free(n->ssl);
mbedtls_ssl_config_free(n->conf);
free(n->ssl);
free(n->conf);
retVal = -1;
#endif // #if (MQTT_OVER_SSL)
exit:
return retVal;
}
#endif /* CONFIG_USE_POLARSSL */
#if 0
int NetworkConnectTLS(Network *n, char* addr, int port, SlSockSecureFiles_t* certificates, unsigned char sec_method, unsigned int cipher, char server_verify)
{
SlSockAddrIn_t sAddr;
int addrSize;
int retVal;
unsigned long ipAddress;
retVal = sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET);
if (retVal < 0) {
return -1;
}
sAddr.sin_family = AF_INET;
sAddr.sin_port = sl_Htons((unsigned short)port);
sAddr.sin_addr.s_addr = sl_Htonl(ipAddress);
addrSize = sizeof(SlSockAddrIn_t);
n->my_socket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET);
if (n->my_socket < 0) {
return -1;
}
SlSockSecureMethod method;
method.secureMethod = sec_method;
retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method));
if (retVal < 0) {
return retVal;
}
SlSockSecureMask mask;
mask.secureMask = cipher;
retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_MASK, &mask, sizeof(mask));
if (retVal < 0) {
return retVal;
}
if (certificates != NULL) {
retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_FILES, certificates->secureFiles, sizeof(SlSockSecureFiles_t));
if (retVal < 0)
{
return retVal;
}
}
retVal = sl_Connect(n->my_socket, (SlSockAddr_t *)&sAddr, addrSize);
if (retVal < 0) {
if (server_verify || retVal != -453) {
sl_Close(n->my_socket);
return retVal;
}
}
SysTickIntRegister(SysTickIntHandler);
SysTickPeriodSet(80000);
SysTickEnable();
return retVal;
}
#endif