You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
3.1 KiB
C
136 lines
3.1 KiB
C
#define _GNU_SOURCE
|
|
#include "inbox_envelope.h"
|
|
|
|
// Submodules
|
|
#include "json/json.h"
|
|
#include "json/layout.h"
|
|
#include "http/server/request.h"
|
|
#include "http/server/header.h"
|
|
#include "ffdb/fs_list.h"
|
|
#include "collections/collection.h"
|
|
#include "collections/array.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <time.h>
|
|
|
|
#define OBJ_TYPE struct http_header
|
|
static struct json_object_field http_header_layout[] = {
|
|
JSON_FIELD_STRING( key, true ),
|
|
JSON_FIELD_STRING( value, true ),
|
|
JSON_FIELD_END,
|
|
};
|
|
#undef OBJ_TYPE
|
|
|
|
JSON_FIELD_TYPE_COMPOSITE( http_header )
|
|
|
|
#define OBJ_TYPE struct ap_envelope
|
|
static struct json_object_field envelope_layout[] = {
|
|
JSON_FIELD_STRING( when, true ),
|
|
JSON_FIELD_ARRAY_OF_TYPE( headers, true, http_header_composite_type ),
|
|
JSON_FIELD_BOOL( validated, false ),
|
|
JSON_FIELD_STRING( body, true ),
|
|
JSON_FIELD_END,
|
|
};
|
|
#undef OBJ_TYPE
|
|
|
|
struct ap_envelope* ap_envelope_from_id( int id )
|
|
{
|
|
char filename[512];
|
|
snprintf( filename, 512, "data/inbox/%d.json", id );
|
|
|
|
struct ap_envelope* env = malloc(sizeof(struct ap_envelope));
|
|
memset(env,0,sizeof(struct ap_envelope));
|
|
|
|
if( !json_read_object_layout_from_file_ex( filename, envelope_layout, env, jrol_flag_dont_ignore_unhandled ) ) {
|
|
ap_envelope_free(env);
|
|
return NULL;
|
|
}
|
|
|
|
return env;
|
|
}
|
|
|
|
void ap_envelope_free_composite( struct ap_envelope* env )
|
|
{
|
|
free(env->body);
|
|
for( int i = 0; i < env->headers.count; ++i ) {
|
|
struct http_header* h = &env->headers.items[i];
|
|
free( h->key );
|
|
free( h->value );
|
|
}
|
|
free(env->headers.items);
|
|
free(env->when);
|
|
}
|
|
void ap_envelope_free( struct ap_envelope* env )
|
|
{
|
|
if( !env ) { return; }
|
|
|
|
ap_envelope_free_composite(env);
|
|
|
|
free(env);
|
|
}
|
|
|
|
static void io_copy( FILE* in, FILE* out )
|
|
{
|
|
char buffer[512];
|
|
for(;;) {
|
|
int count = fread( buffer, 1, 512, in );
|
|
if( count == 0 ) { return; }
|
|
fwrite( buffer, 1, count, out );
|
|
}
|
|
}
|
|
|
|
bool envelope_create_from_request( struct http_request* req )
|
|
{
|
|
struct ap_envelope env;
|
|
memset( &env, 0, sizeof(env) );
|
|
|
|
// Read body in
|
|
FILE* body = http_request_get_request_data(req);
|
|
size_t s;
|
|
FILE* mem = open_memstream(&env.body, &s);
|
|
io_copy(body,mem);
|
|
fclose(mem);
|
|
env.body = realloc(env.body,s+1);
|
|
env.body[s] = '\0';
|
|
|
|
// Create timestamp
|
|
uint64_t time_ns;
|
|
struct timespec ts;
|
|
clock_gettime( CLOCK_REALTIME, &ts );
|
|
time_ns = (uint64_t)ts.tv_sec * 1000000000 + (uint64_t)ts.tv_nsec;
|
|
asprintf( &env.when, "%lu", time_ns );
|
|
|
|
// Get request headers
|
|
struct collection c = {
|
|
.ptr = &env.headers,
|
|
.vtable = &array_vtable,
|
|
.itable = &http_header_itable,
|
|
};
|
|
http_request_copy_headers( req, c );
|
|
|
|
// Deep copy header values
|
|
for( int i = 0; i < env.headers.count; ++i ) {
|
|
struct http_header* h = & env.headers.items[i];
|
|
h->key = strdup(h->key);
|
|
h->value = strdup(h->value);
|
|
}
|
|
|
|
// Get a space in the inbox
|
|
int head = fs_list_get( "data/inbox/HEAD" );
|
|
head += 1;
|
|
fs_list_set( "data/inbox/HEAD", head );
|
|
|
|
// Setup filenames
|
|
char filename[512];
|
|
snprintf( filename, 512, "data/inbox/%d.json", head );
|
|
|
|
json_write_object_layout_to_file( filename, "\t", envelope_layout, &env );
|
|
|
|
ap_envelope_free_composite(&env);
|
|
return true;
|
|
}
|