- add C implementation for wikipedia api
- add POST method for httpbin api
This commit is contained in:
1 parent
fdb050633f
commit
84f3e29d81
4 files changed
+297
-31
No files matched your search
+2
-1
@@ -3,4 +3,5 @@ project("MbedTLS Integration Example")
|
||||
|
||||
add_subdirectory(mbedtls)
|
||||
|
||||
add_subdirectory(httpbin/c)
|
||||
add_subdirectory(httpbin/c)
|
||||
add_subdirectory(wikipedia/c)
|
||||
+43
-30
@@ -11,8 +11,17 @@
|
||||
|
||||
#define SERVER_PORT "443"
|
||||
#define SERVER_NAME "httpbin.org"
|
||||
// #define GET_REQUEST "GET /get HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n"
|
||||
#define GET_REQUEST "GET /image HTTP/1.1\r\nHost: httpbin.org\r\naccept: image/webp\r\n\r\n"
|
||||
#define GET_REQUEST "GET /get HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n"
|
||||
#define GET_REQUEST_IMAGE "GET /image HTTP/1.1\r\nHost: httpbin.org\r\naccept: image/webp\r\n\r\n"
|
||||
#define POST_BODY "name=makora&project=MbedTLS Integration Example"
|
||||
#define POST_REQUEST "POST /post HTTP/1.1\r\n" \
|
||||
"Host: httpbin.org\r\n" \
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n" \
|
||||
"Content-Length: 47\r\n" \
|
||||
"Connection: close\r\n" \
|
||||
"\r\n" \
|
||||
POST_BODY
|
||||
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
static void my_debug(void *ctx, int level,
|
||||
@@ -128,8 +137,8 @@ int main(void) {
|
||||
mbedtls_printf("Sending HTTP request...");
|
||||
fflush(stdout);
|
||||
|
||||
size_t request_len = strlen(GET_REQUEST);
|
||||
if ((ret = mbedtls_ssl_write(&ssl, (const unsigned char*)GET_REQUEST, request_len)) < 0) {
|
||||
size_t request_len = strlen(POST_REQUEST);
|
||||
if ((ret = mbedtls_ssl_write(&ssl, (const unsigned char*)POST_REQUEST, request_len)) < 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
@@ -138,44 +147,48 @@ int main(void) {
|
||||
|
||||
mbedtls_printf("Receiving response:\n\n");
|
||||
|
||||
FILE *img_file = fopen("image.webp", "wb");
|
||||
if (img_file == NULL) {
|
||||
mbedtls_printf(" failed\n ! Could not create image file\n\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
int skip_headers = 0;
|
||||
// FILE *img_file = fopen("image.webp", "wb");
|
||||
// if (img_file == NULL) {
|
||||
// mbedtls_printf(" failed\n ! Could not create image file\n\n");
|
||||
// goto exit;
|
||||
// }
|
||||
|
||||
// int skip_headers = 0;
|
||||
int res_recv = 0;
|
||||
|
||||
while ((bytes_read = mbedtls_ssl_read(&ssl, buf, sizeof(buf) - 1)) > 0) {
|
||||
unsigned char *data_to_write = buf;
|
||||
size_t data_len = bytes_read;
|
||||
buf[bytes_read] = '\0'; // not needed for binary response
|
||||
mbedtls_printf("%s", (char *)buf);
|
||||
|
||||
if (!skip_headers) {
|
||||
unsigned char *header_end = (unsigned char *)strstr((const char *)buf, "\r\n\r\n");
|
||||
// unsigned char *data_to_write = buf;
|
||||
// size_t data_len = bytes_read;
|
||||
|
||||
// if (!skip_headers) {
|
||||
// unsigned char *header_end = (unsigned char *)strstr((const char *)buf, "\r\n\r\n");
|
||||
|
||||
if (header_end != NULL) {
|
||||
data_to_write = header_end + 4; // +4 to skip the "\r\n\r\n"
|
||||
data_len = bytes_read - (data_to_write - buf);
|
||||
skip_headers = 1;
|
||||
// if (header_end != NULL) {
|
||||
// data_to_write = header_end + 4; // +4 to skip the "\r\n\r\n"
|
||||
// data_len = bytes_read - (data_to_write - buf);
|
||||
// skip_headers = 1;
|
||||
|
||||
mbedtls_printf("Headers skipped, image data starts (%zu bytes in first chunk)\n", data_len);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// mbedtls_printf("Headers skipped, image data starts (%zu bytes in first chunk)\n", data_len);
|
||||
// } else {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
|
||||
size_t written = fwrite(data_to_write, 1, data_len, img_file);
|
||||
if (written != data_len) {
|
||||
mbedtls_printf(" failed\n ! Could not write to image file\n\n");
|
||||
fclose(img_file);
|
||||
goto exit;
|
||||
}
|
||||
// size_t written = fwrite(data_to_write, 1, data_len, img_file);
|
||||
// if (written != data_len) {
|
||||
// mbedtls_printf(" failed\n ! Could not write to image file\n\n");
|
||||
// fclose(img_file);
|
||||
// goto exit;
|
||||
// }
|
||||
|
||||
res_recv = 1;
|
||||
}
|
||||
|
||||
fclose(img_file);
|
||||
// fclose(img_file);
|
||||
|
||||
if (bytes_read < 0) {
|
||||
if (bytes_read == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
add_executable(wikipedia_c main.c)
|
||||
|
||||
target_link_libraries(wikipedia_c
|
||||
PRIVATE
|
||||
mbedtls
|
||||
)
|
||||
|
||||
target_include_directories(wikipedia_c
|
||||
PRIVATE
|
||||
${MBEDTLS_SOURCE_DIR}/include
|
||||
)
|
||||
@@ -0,0 +1,241 @@
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/build_info.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define SERVER_PORT "443"
|
||||
#define SERVER_NAME "en.wikipedia.org"
|
||||
#define GET_REQUEST_SEARCH "GET /w/api.php?action=query&list=search&srsearch=Operating%20systems&format=json HTTP/1.1\r\n" \
|
||||
"Host: en.wikipedia.org\r\n" \
|
||||
"User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36\r\n" \
|
||||
"Accept: application/json\r\n" \
|
||||
"Accept-Language: en-US,en;q=0.9\r\n" \
|
||||
"Accept-Encoding: identity\r\n" \
|
||||
"Connection: close\r\n\r\n"
|
||||
|
||||
#define GET_REQUEST_EXTRACT "GET /w/api.php?action=query&prop=extracts&exintro&explaintext&titles=One%20Piece&format=json HTTP/1.1\r\n" \
|
||||
"Host: en.wikipedia.org\r\n" \
|
||||
"User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36\r\n" \
|
||||
"Accept: application/json\r\n" \
|
||||
"Accept-Language: en-US,en;q=0.9\r\n" \
|
||||
"Accept-Encoding: identity\r\n" \
|
||||
"Connection: close\r\n\r\n"
|
||||
|
||||
#define GET_REQUEST_PAGEIMAGE "GET /w/api.php?action=query&prop=pageimages&titles=Cat&pithumbsize=500&format=json HTTP/1.1\r\n" \
|
||||
"Host: en.wikipedia.org\r\n" \
|
||||
"User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36\r\n" \
|
||||
"Accept: application/json\r\n" \
|
||||
"Accept-Language: en-US,en;q=0.9\r\n" \
|
||||
"Accept-Encoding: identity\r\n" \
|
||||
"Connection: close\r\n\r\n"
|
||||
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
static void my_debug(void *ctx, int level,
|
||||
const char *file, int line, const char *str)
|
||||
{
|
||||
((void) level);
|
||||
mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
|
||||
fflush((FILE *) ctx);
|
||||
}
|
||||
|
||||
static int response_handler(mbedtls_ssl_context *ssl, unsigned char *buf,
|
||||
ssize_t initial_bytes)
|
||||
{
|
||||
ssize_t bytes_read = initial_bytes;
|
||||
int total_bytes = initial_bytes;
|
||||
|
||||
buf[bytes_read] = '\0';
|
||||
|
||||
char *body_start = strstr((char *)buf, "\r\n\r\n");
|
||||
if (body_start) {
|
||||
body_start += 4;
|
||||
mbedtls_printf("%.*s\n", (int)(body_start - (char *)buf - 4), (char *)buf);
|
||||
mbedtls_printf("\n--- Response Body ---\n%s\n", body_start);
|
||||
} else {
|
||||
mbedtls_printf("%s", (char *)buf);
|
||||
}
|
||||
|
||||
|
||||
while ((bytes_read = mbedtls_ssl_read(ssl, buf, 8192 - 1)) > 0) {
|
||||
buf[bytes_read] = '\0';
|
||||
char *start = (char *)buf;
|
||||
|
||||
|
||||
if (isxdigit(buf[0]) && strchr((char *)buf, '\r')) {
|
||||
char *newline = strchr((char *)buf, '\n');
|
||||
if (newline) {
|
||||
start = newline + 1;
|
||||
if (start[0] == '\r') start++;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes_read > 2 && buf[0] != '0') {
|
||||
mbedtls_printf("%s", start);
|
||||
}
|
||||
|
||||
total_bytes += bytes_read;
|
||||
}
|
||||
|
||||
mbedtls_printf("\n\nReceived %d bytes\n\n", total_bytes);
|
||||
return total_bytes;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int ret;
|
||||
ssize_t bytes_read;
|
||||
unsigned char buf[8192];
|
||||
|
||||
mbedtls_net_context server_fd;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
|
||||
mbedtls_printf("Initializing TLS structures...");
|
||||
fflush(stdout);
|
||||
|
||||
mbedtls_net_init(&server_fd);
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
mbedtls_printf("Initializing PSA Crypto...");
|
||||
fflush(stdout);
|
||||
|
||||
psa_status_t psa_status = psa_crypto_init();
|
||||
if (psa_status != PSA_SUCCESS) {
|
||||
mbedtls_printf(" failed\n ! psa_crypto_init failed: %d\n\n", (int)psa_status);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
mbedtls_printf("Connecting to %s:%s...", SERVER_NAME, SERVER_PORT);
|
||||
fflush(stdout);
|
||||
|
||||
if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME,
|
||||
SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_net_set_block(&server_fd)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_net_set_block returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
mbedtls_printf("Configuring SSL/TLS...");
|
||||
fflush(stdout);
|
||||
|
||||
if ((ret = mbedtls_ssl_config_defaults(&conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
mbedtls_debug_set_threshold(DEBUG_LEVEL);
|
||||
mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
mbedtls_printf("Setting up SSL context...");
|
||||
fflush(stdout);
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
mbedtls_printf("Binding socket to TLS...");
|
||||
fflush(stdout);
|
||||
|
||||
mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
mbedtls_printf("Performing TLS handshake...");
|
||||
fflush(stdout);
|
||||
|
||||
while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
mbedtls_printf(" TLS version: %s\n", mbedtls_ssl_get_version(&ssl));
|
||||
mbedtls_printf(" Cipher: %s\n\n", mbedtls_ssl_get_ciphersuite(&ssl));
|
||||
|
||||
mbedtls_printf("Sending HTTP request...");
|
||||
fflush(stdout);
|
||||
|
||||
size_t request_len = strlen(GET_REQUEST_EXTRACT);
|
||||
if ((ret = mbedtls_ssl_write(&ssl, (const unsigned char*)GET_REQUEST_EXTRACT, request_len)) < 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok (%d bytes)\n\n", ret);
|
||||
|
||||
mbedtls_printf("Receiving response...\n");
|
||||
|
||||
bytes_read = mbedtls_ssl_read(&ssl, buf, sizeof(buf) - 1);
|
||||
|
||||
if (bytes_read > 0) {
|
||||
response_handler(&ssl, buf, bytes_read);
|
||||
|
||||
} else if (bytes_read < 0) {
|
||||
mbedtls_printf("Server delay detected, retrying with timeouts...\n");
|
||||
|
||||
for (int timeout_ms = 100; timeout_ms <= 5000; timeout_ms *= 2) {
|
||||
mbedtls_printf(" Trying %dms timeout...", timeout_ms);
|
||||
fflush(stdout);
|
||||
|
||||
bytes_read = mbedtls_ssl_read(&ssl, buf, sizeof(buf) - 1);
|
||||
if (bytes_read > 0) {
|
||||
mbedtls_printf(" SUCCESS!\n\n");
|
||||
response_handler(&ssl, buf, bytes_read);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_printf(" FAILED\n");
|
||||
mbedtls_printf("\nError: Server did not respond\n");
|
||||
} else {
|
||||
mbedtls_printf("\nConnection closed by server\n");
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_printf("Closing TLS connection...");
|
||||
fflush(stdout);
|
||||
|
||||
mbedtls_ssl_close_notify(&ssl);
|
||||
mbedtls_net_free(&server_fd);
|
||||
mbedtls_ssl_free(&ssl);
|
||||
mbedtls_ssl_config_free(&conf);
|
||||
|
||||
mbedtls_printf(" ok\n\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in new issue
Block a user