kopia lustrzana https://github.com/SP8EBC/ParaTNC
http client rx done callback
rodzic
241975c43a
commit
169f255eab
|
@ -12,6 +12,7 @@ RM := rm -rf
|
|||
-include system/src/umb_master/subdir.mk
|
||||
-include system/src/stm32l4-hal-driver/subdir.mk
|
||||
-include system/src/modbus_rtu/subdir.mk
|
||||
-include system/src/http_client/subdir.mk
|
||||
-include system/src/gsm/subdir.mk
|
||||
-include system/src/drivers/l4/subdir.mk
|
||||
-include system/src/drivers/subdir.mk
|
||||
|
|
|
@ -35,6 +35,7 @@ system/src/diag \
|
|||
system/src/drivers \
|
||||
system/src/drivers/l4 \
|
||||
system/src/gsm \
|
||||
system/src/http_client \
|
||||
system/src/modbus_rtu \
|
||||
system/src/stm32l4-hal-driver \
|
||||
system/src/umb_master \
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* http_client.h
|
||||
*
|
||||
* Created on: Mar 10, 2022
|
||||
* Author: mateusz
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_GSM_HTTP_CLIENT_H_
|
||||
#define INCLUDE_GSM_HTTP_CLIENT_H_
|
||||
|
||||
#include "gsm/sim800c.h"
|
||||
|
||||
#define HTTP_CLIENT_OK 0
|
||||
#define HTTP_CLIENT_TIMEOUT -100
|
||||
#define HTTP_CLIENT_TOO_LONG_RESPONSE -110
|
||||
|
||||
void http_client_init(gsm_sim800_state_t * state, srl_context_t * serial_context);
|
||||
uint8_t http_client_async_get(char * url, uint8_t url_ln, uint16_t response_ln_limit);
|
||||
uint8_t http_client_async_post(char * url, uint8_t url_ln, char * data_to_post, uint8_t data_ln);
|
||||
|
||||
char * http_client_get_server_response();
|
||||
uint16_t http_client_get_latest_http_code();
|
||||
|
||||
#endif /* INCLUDE_GSM_HTTP_CLIENT_H_ */
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* http_client.h
|
||||
*
|
||||
* Created on: Mar 10, 2022
|
||||
* Author: mateusz
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_GSM_HTTP_CLIENT_H_
|
||||
#define INCLUDE_GSM_HTTP_CLIENT_H_
|
||||
|
||||
/**
|
||||
* This library supports only HTTP/1.1 and chunked Trasfer-Encoding as described here:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding
|
||||
*/
|
||||
|
||||
#include "gsm/sim800c.h"
|
||||
|
||||
#define HTTP_CLIENT_OK 0
|
||||
#define HTTP_CLIENT_TIMEOUT -100
|
||||
#define HTTP_CLIENT_TOO_LONG_RESPONSE -110
|
||||
#define HTTP_CLIENT_HEADERS_OVERFLOW -120
|
||||
#define HTTP_CLIENT_DISCONNECTED -130 // this is set if remote server disconnected in unexpected moment
|
||||
|
||||
#define HEADER_BUFFER_LN 64
|
||||
|
||||
/**
|
||||
* HTTP code returned by the latest query. It is zeroed after each successful call to async
|
||||
* function. This indicate that a request is currently in progress. Negative values means some
|
||||
* non HTTP error, like communication timeout or response longer than expected
|
||||
*/
|
||||
extern int16_t http_client_http_code;
|
||||
|
||||
/**
|
||||
* Content lenght received from HTTP response headers or chunked encoding
|
||||
*/
|
||||
extern uint16_t http_client_content_lenght;
|
||||
|
||||
/**
|
||||
* Temporary buffer for processing
|
||||
*/
|
||||
extern char http_client_header_buffer[HEADER_BUFFER_LN];
|
||||
|
||||
/**
|
||||
* Index used to walk through 'http_client_header_buffer'
|
||||
*/
|
||||
extern uint8_t http_client_header_index;
|
||||
|
||||
void http_client_init(gsm_sim800_state_t * state, srl_context_t * serial_context);
|
||||
uint8_t http_client_async_get(char * url, uint8_t url_ln, uint16_t response_ln_limit);
|
||||
uint8_t http_client_async_post(char * url, uint8_t url_ln, char * data_to_post, uint8_t data_ln);
|
||||
|
||||
char * http_client_get_server_response();
|
||||
uint16_t http_client_get_latest_http_code();
|
||||
|
||||
#endif /* INCLUDE_GSM_HTTP_CLIENT_H_ */
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* http_client_rx_callback.h
|
||||
*
|
||||
* Created on: Mar 19, 2022
|
||||
* Author: mateusz
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_HTTP_CLIENT_HTTP_CLIENT_RX_CALLBACK_H_
|
||||
#define INCLUDE_HTTP_CLIENT_HTTP_CLIENT_RX_CALLBACK_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t http_client_rx_done_callback(uint8_t current_data, const uint8_t * const rx_buffer, uint16_t rx_bytes_counter);
|
||||
|
||||
#endif /* INCLUDE_HTTP_CLIENT_HTTP_CLIENT_RX_CALLBACK_H_ */
|
|
@ -1,107 +0,0 @@
|
|||
#include "gsm/http_client.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const char * DISCONNECTED = "CLOSED\0";
|
||||
static const char * CONTENT_LN = "Content-Length: \0";
|
||||
|
||||
#define WAIT_FOR_CONTENT_LENGHT 0xFFFFu
|
||||
|
||||
/**
|
||||
* Content lenght received from HTTP response headers
|
||||
*/
|
||||
uint16_t http_client_content_lenght = 0;
|
||||
|
||||
/**
|
||||
* HTTP code returned by the latest query. It is zeroed after each successful call to async
|
||||
* function. This indicate that a request is currently in progress. Negative values means some
|
||||
* non HTTP error, like communication timeout or response longer than expected
|
||||
*/
|
||||
int16_t http_client_http_code = 0;
|
||||
|
||||
/**
|
||||
* Temporary buffer for processing
|
||||
*/
|
||||
static char http_client_header_buffer[32];
|
||||
|
||||
/**
|
||||
* Index used to walk through 'http_client_header_buffer'
|
||||
*/
|
||||
static uint8_t http_client_header_index = 0;
|
||||
|
||||
/**
|
||||
* This static function is used as a termination callback for serial I/O with GPRS module.
|
||||
* It ends transmission in one of three cases
|
||||
* 1. All data is received according to size specified by Content-Lenght field in response header
|
||||
* 2. If user set 'response_ln_limit' to non zero value and 'response_ln_limit' characters have been received (it also set HTTP_CLIENT_TOO_LONG_RESPONSE)
|
||||
* 3. If connection has been closed by remote server
|
||||
*
|
||||
*/
|
||||
static uint8_t http_client_rx_done_callback(uint8_t current_data, const uint8_t * const rx_buffer, uint16_t rx_bytes_counter) {
|
||||
|
||||
uint8_t out = 0;
|
||||
|
||||
int compare_result = 0;
|
||||
|
||||
// check if we wait for content lenght
|
||||
if (http_client_content_lenght == WAIT_FOR_CONTENT_LENGHT) {
|
||||
// copy current character to temporary buffer
|
||||
http_client_header_buffer[http_client_header_index++] = (char)current_data;
|
||||
|
||||
// check if
|
||||
if (current_data == '\r') {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// if this is maybe the last character of 'CLOSED'
|
||||
if ((char)current_data == 'D') {
|
||||
// check 6 previous characters
|
||||
compare_result = strncmp(DISCONNECTED, (const char *) (rx_buffer + rx_bytes_counter - 6), 6);
|
||||
|
||||
// terminate reception if 'CLOSED' has been found.
|
||||
if (compare_result == 0) {
|
||||
out = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if this is maybe an end of content lenght
|
||||
else if (http_client_content_lenght == 0 && (char)current_data == 'h') {
|
||||
// check 14 previous characters
|
||||
compare_result = strncmp(CONTENT_LN, rx_buffer + rx_bytes_counter - 14, 14);
|
||||
|
||||
// terminate reception if 'CLOSED' has been found.
|
||||
if (compare_result == 0) {
|
||||
// set waiting for
|
||||
http_client_content_lenght = WAIT_FOR_CONTENT_LENGHT;
|
||||
|
||||
// clear the buffer where header value will be stored
|
||||
memset (http_client_header_buffer, 0x00, sizeof(http_client_header_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void http_client_init(gsm_sim800_state_t * state, srl_context_t * serial_context) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint8_t http_client_async_get(char * url, uint8_t url_ln, uint16_t response_ln_limit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t http_client_async_post(char * url, uint8_t url_ln, char * data_to_post, uint8_t data_ln) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char * http_client_get_server_response() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t http_client_get_latest_http_code() {
|
||||
return http_client_http_code;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#include "http_client/http_client.h"
|
||||
#include "http_client/http_client_rx_callback.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Content lenght received from HTTP response headers or chunked encoding
|
||||
*/
|
||||
uint16_t http_client_content_lenght = 0;
|
||||
|
||||
/**
|
||||
* HTTP code returned by the latest query. It is zeroed after each successful call to async
|
||||
* function. This indicate that a request is currently in progress. Negative values means some
|
||||
* non HTTP error, like communication timeout or response longer than expected
|
||||
*/
|
||||
int16_t http_client_http_code = 0;
|
||||
|
||||
/**
|
||||
* Temporary buffer for processing
|
||||
*/
|
||||
char http_client_header_buffer[HEADER_BUFFER_LN];
|
||||
|
||||
/**
|
||||
* Index used to walk through 'http_client_header_buffer'
|
||||
*/
|
||||
uint8_t http_client_header_index = 0;
|
||||
|
||||
|
||||
void http_client_init(gsm_sim800_state_t * state, srl_context_t * serial_context) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint8_t http_client_async_get(char * url, uint8_t url_ln, uint16_t response_ln_limit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t http_client_async_post(char * url, uint8_t url_ln, char * data_to_post, uint8_t data_ln) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char * http_client_get_server_response() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t http_client_get_latest_http_code() {
|
||||
return http_client_http_code;
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* http_client_rx_callback.c
|
||||
*
|
||||
* Created on: Mar 19, 2022
|
||||
* Author: mateusz
|
||||
*/
|
||||
|
||||
#include "http_client/http_client_rx_callback.h"
|
||||
#include "http_client/http_client.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const char * DISCONNECTED = "CLOSED\0";
|
||||
|
||||
static const char * CONTENT_LN = "Content-Length: \0";
|
||||
#define CONTENT_LN_LN 16
|
||||
static const char * TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\0";
|
||||
#define TRANSFER_ENCODING_CHUNKED_LN 26
|
||||
static const char * HTTP_HEADER = "HTTP/\0";
|
||||
#define HTTP_HEADER_LN 5
|
||||
static const char * BLANK_NEWLINE = "\r\n\0";
|
||||
|
||||
#define WAIT_FOR_CONTENT_LENGHT 0xFFFFu
|
||||
#define CONTENT_IN_CHUNKS 0xFFFEu
|
||||
|
||||
typedef enum http_client_header_field {
|
||||
|
||||
HEADER_HTTP,
|
||||
HEADER_CONTENT_LN,
|
||||
HEADER_TRANSFER_ENCODING_CHUNKED,
|
||||
HEADER_END,
|
||||
HEADER_UNKNOWN
|
||||
} http_client_header_field_t;
|
||||
|
||||
// set to one if we are still parsing HTTP response header
|
||||
static uint8_t http_client_response_header_processing = 1;
|
||||
|
||||
/**
|
||||
* This function is responsible for checking what HTTP header has been received
|
||||
*/
|
||||
static http_client_header_field_t http_client_check_what_field_it_is(char * buffer, uint16_t buffer_ln) {
|
||||
|
||||
http_client_header_field_t out = HEADER_UNKNOWN;
|
||||
|
||||
if (strncmp(CONTENT_LN, buffer, CONTENT_LN_LN) == 0) {
|
||||
out = HEADER_CONTENT_LN;
|
||||
}
|
||||
else if (strncmp(TRANSFER_ENCODING_CHUNKED, buffer, TRANSFER_ENCODING_CHUNKED_LN) == 0) {
|
||||
out = HEADER_TRANSFER_ENCODING_CHUNKED;
|
||||
}
|
||||
else if (strncmp(HTTP_HEADER, buffer, HTTP_HEADER_LN) == 0) {
|
||||
out = HEADER_HTTP;
|
||||
}
|
||||
else if (strncmp(BLANK_NEWLINE, buffer, 2) == 0) {
|
||||
out = HEADER_END;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used as a termination callback for serial I/O with GPRS module.
|
||||
* It ends transmission in one of three cases
|
||||
* 1. All data is received according to size specified by Content-Lenght field in response header
|
||||
* 2. If user set 'response_ln_limit' to non zero value and 'response_ln_limit' characters have been received (it also set HTTP_CLIENT_TOO_LONG_RESPONSE)
|
||||
* 3. If connection has been closed by remote server
|
||||
*
|
||||
* It assumes that 'http_client_header_buffer' is zeroed
|
||||
*
|
||||
*/
|
||||
uint8_t http_client_rx_done_callback(uint8_t current_data, const uint8_t * const rx_buffer, uint16_t rx_bytes_counter) {
|
||||
|
||||
uint8_t out = 0;
|
||||
|
||||
int compare_result = 0;
|
||||
|
||||
// local buffer used to fetch HTTP error code or similar short things
|
||||
char local_buffer[9];
|
||||
|
||||
// if this is maybe the last character of 'CLOSED'
|
||||
if ((char)current_data == 'D') {
|
||||
// check 6 previous characters
|
||||
compare_result = strncmp(DISCONNECTED, (const char *) (rx_buffer + rx_bytes_counter - 6), 6);
|
||||
|
||||
// terminate reception if 'CLOSED' has been found.
|
||||
if (compare_result == 0) {
|
||||
out = 1;
|
||||
|
||||
http_client_http_code = HTTP_CLIENT_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
// check if we wait for content length
|
||||
if (http_client_response_header_processing == 1) {
|
||||
// copy current character to temporary buffer
|
||||
http_client_header_buffer[http_client_header_index++] = (char)current_data;
|
||||
|
||||
// we have an overflow during processing HTTP headers
|
||||
if (http_client_header_index >= HEADER_BUFFER_LN) {
|
||||
out = 1;
|
||||
|
||||
// set an error code also
|
||||
http_client_http_code = HTTP_CLIENT_HEADERS_OVERFLOW;
|
||||
}
|
||||
else {
|
||||
// check if this is newline
|
||||
if (current_data == '\n') {
|
||||
// if yes parse the content of HTTP header buffer
|
||||
http_client_header_field_t field = http_client_check_what_field_it_is(http_client_header_buffer, HEADER_BUFFER_LN);
|
||||
|
||||
memset(local_buffer, 0x0, 0x9);
|
||||
|
||||
switch (field) {
|
||||
|
||||
// fetch the HTTP return code
|
||||
case HEADER_HTTP: {
|
||||
// copy last 6 characters of header >> 0000 48 54 54 50 2f 31 2e 31 20 32 30 30 20 0d 0a HTTP/1.1 200 .. <<
|
||||
memcpy(local_buffer, http_client_header_buffer + http_client_header_index - 6, 6);
|
||||
|
||||
// convert to int
|
||||
http_client_http_code = atoi(local_buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
case HEADER_CONTENT_LN: {
|
||||
// content ln may vary, so we need to copy data starting from the begining not the end
|
||||
strncpy(local_buffer, http_client_header_buffer + http_client_header_index + 16, 6);
|
||||
|
||||
// convert to integer value
|
||||
http_client_content_lenght = atoi(local_buffer);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HEADER_TRANSFER_ENCODING_CHUNKED: {
|
||||
/**
|
||||
* 0000 54 72 61 6e 73 66 65 72 2d 45 6e 63 6f 64 69 6e Transfer-Encodin
|
||||
* 0010 67 3a 20 63 68 75 6e 6b 65 64 0d 0a g: chunked..
|
||||
*
|
||||
*/
|
||||
|
||||
// set that the content will be sent in chunks
|
||||
http_client_content_lenght = CONTENT_IN_CHUNKS;
|
||||
|
||||
// this is not the end of the header as such as neighter 'Transfer-Encoding' nor
|
||||
// 'Content-Lenght' need to occur as the last thing in response
|
||||
break;
|
||||
}
|
||||
|
||||
case HEADER_END: {
|
||||
http_client_response_header_processing = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// not all headers needs to be processed
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// clear temporary buffer
|
||||
memset (http_client_header_buffer, 0x00, HEADER_BUFFER_LN);
|
||||
http_client_header_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// we know the lenght of response or we are waiting for first chunk
|
||||
if (http_client_content_lenght == CONTENT_IN_CHUNKS) {
|
||||
|
||||
// save content data until we get chunk size
|
||||
http_client_header_buffer[http_client_header_index++] = (char)current_data;
|
||||
|
||||
// if this is a first newline
|
||||
if ((char)current_data == '\n') {
|
||||
// everything what is now in 'http_client_header_buffer' is the size of chunk in hex!!
|
||||
http_client_content_lenght = strtol(http_client_header_buffer, 0, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return out;
|
||||
}
|
Ładowanie…
Reference in New Issue