1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-30 16:24:09 +03:00

Restructured the lwip raw comat code.

Added replacements for the time functions on ESP8266.
This commit is contained in:
Slavey Karadzhov
2016-02-19 11:53:05 +01:00
parent 885ff3e8f0
commit 7c38865f66
5 changed files with 237 additions and 9 deletions

149
compat/README.md Normal file
View File

@ -0,0 +1,149 @@
If you are using [LWIP raw tcp mode](http://lwip.wikia.com/wiki/Raw/TCP) and want to add SSL support below are the steps that can help you to achieve this with the help of [axTLS]( http://axtls.sourceforge.net/ ).
First you have to include the `lwipr_compat.h` header.
```C
#include "compat/lwipr_compat.h"
```
Then in the code block where you initialize the tcp raw connection you should call `axl_init`.
Take a look at the example below:
```C
lwip_init();
/*
* The line below should be added AFTER the lwip_init code
* AND BEFORE the call to tcp_new()
* The parameter value 10 specifies how many SSL connections are expected
*/
axl_init(10);
// .. some more code
tcp = tcp_new();
tcp_sent(tcp, staticOnSent);
tcp_recv(tcp, staticOnReceive);
tcp_err(tcp, staticOnError);
tcp_poll(tcp, staticOnPoll, 4);
// ... and even more code
res = tcp_connect(tcp, &addr, port, staticOnConnected);
```
Now we should add in our `staticOnConnected` funciton code to create new ssl context and ssl object.
In the example below the `sslObj` and `sslContext` are defined as global
```C
// global definitions
SSL *sslObj = NULL;
SSLCTX* sslContext = NULL;
// and some more code...
err_t staticOnConnected(void *arg, struct tcp_pcb *tcp, err_t err)
{
int clientfd = -1;
uint32_t options = 0;
if (tcp == NULL) {
/* @TODO: Take care to handle error conditions */
return -1;
}
clientfd = axl_append(tcp);
if(clientfd == -1) {
printf("Unable to add LWIP tcp -> clientfd mapping\n");
return ERR_OK;
}
printf("Connected: ClientId: %d\n", clientfd);
#ifdef SSL_DEBUG
options |= SSL_DISPLAY_STATES | SSL_DISPLAY_BYTES;
#endif
// if you want to verify the server certificate later you can also add the following option
options |= SSL_SERVER_VERIFY_LATER
sslContext = ssl_ctx_new(SSL_CONNECT_IN_PARTS | options, 1); // !!! SSL_CONNECT_IN_PARTS must be in the flags !!!
sslObj = ssl_client_new(sslContext, clientfd, NULL, 0);
return ERR_OK;
}
```
Once we are connected we can send and receive information. For the receiving part we can do the following
```C
err_t staticOnReceive(void *arg, struct tcp_pcb *tcp, struct pbuf *p, err_t err)
{
uint8_t *read_buf = NULL;
int read_bytes = 0;
printf("Err: %d\n", err);
if(tcp == NULL || p == NULL) {
/* @TODO: Take care to handle error conditions */
return -1;
}
read_bytes = axl_ssl_read(sslObj, &read_buf, tcp, p);
if(read_bytes > 0) {
printf("Got data: %s", read_buf);
// @TODO: Do something useful with the read_buf
}
return ERR_OK;
}
```
In the receiving part you can also add debug code to display more information about the SSL handshake, once it was successul.
```C
err_t staticOnReceive(void *arg, struct tcp_pcb *tcp, struct pbuf *p, err_t err)
{
static int show_info = 0;
const char *common_name = NULL;
// ..
read_bytes = axl_ssl_read(sslObj, &read_buf, tcp, p);
if(read_bytes > 0) {
printf("Got data: %s", read_buf);
// @TODO: Do something useful with the read_buf
}
if(!show_info && ssl_handshake_status(sslObj) == SSL_OK) {
common_name = ssl_get_cert_dn(sslObj, SSL_X509_CERT_COMMON_NAME);
if (common_name) {
printf("Common Name:\t\t\t%s\n", common_name);
}
// These two funcitons below can be found in the axtls examples
display_session_id(sslObj);
display_cipher(sslObj);
show_info = 1;
}
return ERR_OK;
}
```
And for the sending part we can use the following code sample as a start
```C
void someSendingfunction() {
uint8_t *out_buf;
int out_bytes = 0;
// ... take care to store something in the out_buf
axl_ssl_write(sslObj, out_buf, out_bytes);
}
```
Good luck and send your success stories at slaff@attachix.com.

282
compat/lwipr_compat.c Normal file
View File

@ -0,0 +1,282 @@
/*
* Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP)
*
* Created on: Jan 15, 2016
* Author: Slavey Karadzhov
*/
#include "lwipr_compat.h"
AxlTcpDataArray axlFdArray;
#include <stdlib.h>
/* High Level "public" functions */
/**
* Function that should be called once we are ready to use the axTLS - LWIP raw compatibility
*/
void axl_init(int capacity) {
ax_fd_init(&axlFdArray, capacity);
}
/**
* Appends a tcp to the internal array. Returns client file descriptor
*/
int axl_append(struct tcp_pcb *tcp) {
return ax_fd_append(&axlFdArray, tcp);
}
/**
* Frees the internal mapping from this tcp. Returns the number of occurrences of the tcp
*/
int axl_free(struct tcp_pcb *tcp) {
int i;
int occurances = 0;
if(tcp == NULL) {
return 0;
}
AxlTcpDataArray *vector = &axlFdArray;
AXL_DEBUG("AXL: Freeing %d tcp item", vector->size);
for (i = 0; i < vector->size; i++) {
if (vector->data[i].tcp == tcp) {
if(vector->data[i].tcp_pbuf != NULL) {
pbuf_free(vector->data[i].tcp_pbuf);
vector->data[i].tcp_pbuf = NULL;
}
vector->data[i].tcp = NULL;
vector->data[i].pbuf_offset = 0;
occurances++;
}
}
return occurances;
}
/**
* Reads data from the SSL over TCP stream. Returns decrypted data.
* @param SSL *sslObj
* @param uint8_t **in_data - pointer to the decrypted incoming data, or NULL if nothing was read
* @param void *arg - possible arguments passed to the tcp raw layer during initialization
* @param tcp_pcb *tcp - pointer to the raw tcp object
* @param pbuf *p - pointer to the buffer with the TCP packet data
*
* @return int
* 0 - when everything is fine but there are no symbols to process yet
* < 0 - when there is an error
* > 0 - the length of the clear text characters that were read
*/
int axl_ssl_read(SSL *ssl, uint8_t **in_data, struct tcp_pcb *tcp, struct pbuf *p) {
int read_bytes = 0;
int total_bytes = 0;
int clientfd = -1;
AxlTcpData* data = NULL;
if (ssl == NULL) {
return ERR_AXL_INVALID_SSL;
}
clientfd = ax_fd_getfd(&axlFdArray, tcp);
if(clientfd == -1) {
return ERR_AXL_INVALID_CLIENTFD;
}
data = ax_fd_get(&axlFdArray, clientfd);
if(data == NULL) {
return ERR_AXL_INVALID_CLIENTFD_DATA;
}
if (p != NULL) {
data->tcp_pbuf = p;
data->pbuf_offset = 0;
}
AXL_DEBUG("READY TO READ SOME DATA\n");
tcp_recved(tcp, p->tot_len);
do {
WATCHDOG_FEED();
read_bytes = ssl_read(ssl, in_data);
AXL_DEBUG("axl_ssl_read: Read bytes: %d\n", read_bytes);
if(read_bytes < SSL_OK) {
/* An error has occurred. Give it back for further processing */
total_bytes = read_bytes;
break;
}
total_bytes+= read_bytes;
} while (p->tot_len - data->pbuf_offset > 0);
pbuf_free(p);
return total_bytes;
}
/*
* Lower Level LWIP RAW functions
*/
/*
* The LWIP tcp raw version of the SOCKET_WRITE(A, B, C)
*/
int ax_port_write(int clientfd, uint8_t *buf, uint16_t bytes_needed) {
AxlTcpData *data = NULL;
int tcp_len = 0;
err_t err = ERR_OK;
data = ax_fd_get(&axlFdArray, clientfd);
if(data == NULL) {
return ERR_AXL_INVALID_CLIENTFD;
}
if (data == NULL || data->tcp == NULL || buf == NULL || bytes_needed == 0) {
AXL_DEBUG("Return Zero.\n");
return 0;
}
if (tcp_sndbuf(data->tcp) < bytes_needed) {
tcp_len = tcp_sndbuf(data->tcp);
if(tcp_len == 0) {
AXL_DEBUG("The send buffer is full! We have problem.\n");
return 0;
}
} else {
tcp_len = bytes_needed;
}
if (tcp_len > 2 * data->tcp->mss) {
tcp_len = 2 * data->tcp->mss;
}
do {
err = tcp_write(data->tcp, buf, tcp_len, TCP_WRITE_FLAG_COPY);
if(err < SSL_OK) {
AXL_DEBUG("Got error: %d\n", err);
}
if (err == ERR_MEM) {
AXL_DEBUG("Not enough memory to write data with length: %d (%d)\n", tcp_len, bytes_needed);
tcp_len /= 2;
}
} while (err == ERR_MEM && tcp_len > 1);
AXL_DEBUG("send_raw_packet length %d(%d)\n", tcp_len, bytes_needed);
if (err == ERR_OK) {
err = tcp_output(data->tcp);
if(err != ERR_OK) {
AXL_DEBUG("tcp_output got err: %d\n", err);
}
}
return tcp_len;
}
/*
* The LWIP tcp raw version of the SOCKET_READ(A, B, C)
*/
int ax_port_read(int clientfd, uint8_t *buf, int bytes_needed) {
AxlTcpData *data = NULL;
uint8_t *read_buf = NULL;
uint8_t *pread_buf = NULL;
u16_t recv_len = 0;
data = ax_fd_get(&axlFdArray, clientfd);
if (data == NULL) {
return ERR_AXL_INVALID_CLIENTFD_DATA;
}
if(data->tcp_pbuf == NULL || data->tcp_pbuf->tot_len == 0) {
AXL_DEBUG("Nothing to read?! May be the connection needs resetting?\n");
return 0;
}
read_buf =(uint8_t*)calloc(data->tcp_pbuf->len + 1, sizeof(uint8_t));
pread_buf = read_buf;
if (pread_buf != NULL){
recv_len = pbuf_copy_partial(data->tcp_pbuf, read_buf, bytes_needed, data->pbuf_offset);
data->pbuf_offset += recv_len;
}
if (recv_len != 0) {
memcpy(buf, read_buf, recv_len);
}
if(bytes_needed < recv_len) {
AXL_DEBUG("Bytes needed: %d, Bytes read: %d\n", bytes_needed, recv_len);
}
free(pread_buf);
pread_buf = NULL;
return recv_len;
}
int ax_get_file(const char *filename, uint8_t **buf) {
*buf = 0;
return 0;
}
/*
* Utility functions
*/
void ax_fd_init(AxlTcpDataArray *vector, int capacity) {
vector->size = 0;
vector->capacity = capacity;
vector->data = (AxlTcpData*) malloc(sizeof(AxlTcpData) * vector->capacity);
}
int ax_fd_append(AxlTcpDataArray *vector, struct tcp_pcb *tcp) {
int index;
ax_fd_double_capacity_if_full(vector);
index = vector->size++;
vector->data[index].tcp = tcp;
vector->data[index].tcp_pbuf = NULL;
vector->data[index].pbuf_offset = 0;
return index;
}
AxlTcpData* ax_fd_get(AxlTcpDataArray *vector, int index) {
if (index >= vector->size || index < 0) {
AXL_DEBUG("Index %d out of bounds for vector of size %d\n", index,
vector->size);
return NULL;
}
return &(vector->data[index]);
}
int ax_fd_getfd(AxlTcpDataArray *vector, struct tcp_pcb *tcp) {
int i;
for (i = 0; i < vector->size; i++) {
if (vector->data[i].tcp == tcp) {
return i;
}
}
return -1;
}
void ax_fd_set(AxlTcpDataArray *vector, int index, struct tcp_pcb *tcp) {
AxlTcpData value;
while (index >= vector->size) {
ax_fd_append(vector, 0);
}
value.tcp = tcp;
value.tcp_pbuf = NULL;
value.pbuf_offset = 0;
vector->data[index] = value;
}
void ax_fd_double_capacity_if_full(AxlTcpDataArray *vector) {
if (vector->size >= vector->capacity) {
vector->capacity *= 2;
vector->data = (AxlTcpData*)realloc(vector->data, sizeof(AxlTcpData) * vector->capacity);
}
}
void ax_fd_free(AxlTcpDataArray *vector) {
free(vector->data);
}

95
compat/lwipr_compat.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP)
*
* Created on: Jan 15, 2016
* Author: Slavey Karadzhov
*/
#ifndef LWIPR_COMPAT_H
#define LWIPR_COMPAT_H
/*
* All those functions will run only if LWIP tcp raw mode is used
*/
#if LWIP_RAW==1
#ifdef __cplusplus
extern "C" {
#endif
#include "lwipr_platform.h"
#include "ssl/ssl.h"
#include "ssl/tls1.h"
#define ERR_AXL_INVALID_SSL -101
#define ERR_AXL_INVALID_TCP -102
#define ERR_AXL_INVALID_CLIENTFD -103
#define ERR_AXL_INVALID_CLIENTFD_DATA -104
#define SOCKET_READ(A, B, C) ax_port_read(A, B, C)
#define SOCKET_WRITE(A, B, C) ax_port_write(A, B, C)
/*
* Define the AXL_DEBUG function to add debug functionality
*/
#ifndef AXL_DEBUG
#define AXL_DEBUG(...)
#endif
/**
* Define watchdog function to be called during CPU intensive operations.
*/
#ifndef WATCHDOG_FEED
#define WATCHDOG_FEED()
#endif
typedef struct {
struct tcp_pcb *tcp;
struct pbuf *tcp_pbuf;
int pbuf_offset;
} AxlTcpData;
typedef struct {
int size; /* slots used so far */
int capacity; /* total available slots */
AxlTcpData *data; /* array of TcpData objects */
} AxlTcpDataArray;
/*
* High Level Functions - these are the ones that should be used directly
*/
void axl_init(int capacity);
int axl_append(struct tcp_pcb *tcp);
int axl_free(struct tcp_pcb *tcp);
#define axl_ssl_write(A, B, C) ssl_write(A, B, C)
int axl_ssl_read(SSL *sslObj, uint8_t **in_data, struct tcp_pcb *tcp, struct pbuf *p);
/*
* Lower Level Socket Functions - used internally from axTLS
*/
int ax_port_write(int clientfd, uint8_t *buf, uint16_t bytes_needed);
int ax_port_read(int clientfd, uint8_t *buf, int bytes_needed);
/*
* Lower Level Utility functions
*/
void ax_fd_init(AxlTcpDataArray *vector, int capacity);
int ax_fd_append(AxlTcpDataArray *vector, struct tcp_pcb *tcp);
AxlTcpData* ax_fd_get(AxlTcpDataArray *vector, int index);
int ax_fd_getfd(AxlTcpDataArray *vector, struct tcp_pcb *tcp);
void ax_fd_set(AxlTcpDataArray *vector, int index, struct tcp_pcb *tcp);
void ax_fd_double_capacity_if_full(AxlTcpDataArray *vector);
void ax_fd_free(AxlTcpDataArray *vector);
#ifdef __cplusplus
}
#endif
#endif /* LWIP_RAW==1 */
#endif /* LWIPR_COMPAT_H */

27
compat/lwipr_platform.h Normal file
View File

@ -0,0 +1,27 @@
/*
* lwipr_platform.h
*
* Created on: Feb 8, 2016
* Author: slavey
*
*/
#ifndef AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_
#define AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_
/* Add here all platform specific things */
// Some calls require the watchdog to be reset
#ifndef WATCHDOG_FEED
#define WATCHDOG_FEED()
#endif
/* SSL_DEBUG is for more information */
#ifndef SSL_DEBUG
#define AXL_DEBUG(...)
#endif
#endif /* AXTLS_8266_COMPAT_LWIPR_PLATFORM_H_ */