Skip to content

Http support #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactoring
jamesalbert committed Jun 22, 2019
commit 1a54aaead8899b3015841160ca3b73024ddaa1c7
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
PKG_CONFIG = PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 pkg-config
COMPILER_DIR = src/compiler/
RUNTIME_DIR = src/runtime/
SHARED_DIR = src/shared/
@@ -12,6 +13,15 @@ SRC = $(wildcard $(COMPILER_DIR)*.c) \
$(wildcard $(UTILS_DIR)/*.c) \
$(wildcard $(OPT_DIR)/*.c)

OPENSSL_ENABLED = true
OPENSSL_INSTALLED = $(shell $(PKG_CONFIG) --libs openssl 2>&1 1>/dev/null && echo true || echo false)
$(info OPENSSL_ENABLED: $(OPENSSL_ENABLED))
$(info OPENSSL_INSTALLED: $(OPENSSL_INSTALLED))
ifeq ($(OPENSSL_ENABLED),true)
ifeq ($(OPENSSL_INSTALLED),false)
$(error OpenSSL is enabled, but not installed)
endif
endif
INCLUDE = -I$(COMPILER_DIR) -I$(RUNTIME_DIR) -I$(SHARED_DIR) -I$(UTILS_DIR) -I$(OPT_DIR)
CFLAGS = $(INCLUDE) -std=gnu99 -fgnu89-inline -fPIC -DBUILD_GRAVITY_API
OBJ = $(SRC:.c=.o)
@@ -26,6 +36,10 @@ else
# MacOS
LIBTARGET = libgravity.dylib
LDFLAGS = -lm
ifeq ($(OPENSSL_ENABLED),true)
CFLAGS += $(shell $(PKG_CONFIG) --cflags openssl) -DGRAVITY_OPENSSL_ENABLED
LDFLAGS += $(shell $(PKG_CONFIG) --libs openssl)
endif
else ifeq ($(UNAME_S),OpenBSD)
# OpenBSD
CFLAGS += -D_WITH_GETLINE
@@ -46,6 +60,10 @@ else
# Linux
LIBTARGET = libgravity.so
LDFLAGS = -lm -lrt
ifeq ($(OPENSSL_ENABLED),true)
CFLAGS += $(shell $(PKG_CONFIG) --cflags openssl) -DGRAVITY_OPENSSL_ENABLED
LDFLAGS += $(shell $(PKG_CONFIG) --libs openssl)
endif
endif
endif

449 changes: 312 additions & 137 deletions src/optionals/gravity_http.c

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions src/optionals/gravity_http.h
Original file line number Diff line number Diff line change
@@ -11,6 +11,56 @@

#include "gravity_value.h"


typedef struct {
const char *name; // name of header; e.g. Last-Modified
const char *value; // value of header
} Header;

typedef struct {
Header *headers;
char *body;
char *hostname;
int status_code;
char *status_message;
int headercount;
} Response;

typedef struct {
char *body;
char *scheme;
char *hostname;
char *path;
int port;
char *method;
gravity_map_t *data;
bool use_ssl;
int fd;
void *conn;
void *ctx;
} Request;

// http library
static Request *http_request_new(gravity_vm *vm, char *hostname, char *path, int port, char *method, gravity_map_t *data);
static void http_request_ssl_init_ctx(Request *req);
static void http_request_connect_ssl(Request *req);
static struct addrinfo *http_get_host_info(char *host, int port);
static void http_request_connect_tcp(Request *req);
static Response *http_request_connect(gravity_vm *vm, char *hostname, char *path, int port, char *method, gravity_map_t *data);
static Response *http_response_new(gravity_vm *vm, Request *req);
static void http_response_free(Response *resp);
static void http_response_parse_header(Response *resp, char *header);
static int8_t http_response_parse_line(Response *resp, char *line);
static void http_response_slurp_body(Response *resp, char **bk);
static void http_response_parse(Response *resp, char *source);
static ssize_t http_request_send(gravity_vm *vm, Request *req);
static Response *http_response_receive(gravity_vm *vm, Request *req);
static bool http_request (gravity_vm *vm, gravity_map_t *options, uint32_t rindex);
static bool http_get (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex);
static bool http_post (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex);


// gravity bindings
void gravity_http_register (gravity_vm *vm);
void gravity_http_free (void);
bool gravity_ishttp_class (gravity_class_t *c);
2 changes: 1 addition & 1 deletion src/shared/gravity_hash.c
Original file line number Diff line number Diff line change
@@ -174,7 +174,7 @@ gravity_hash_t *gravity_hash_create (uint32_t size, gravity_hash_compute_fn comp
return hashtable;
}

gravity_hash_t *gravity_hash_create_from (gravity_hash_t *from_hash) {
gravity_hash_t *gravity_hash_dup (gravity_hash_t *from_hash) {
if (from_hash->size < GRAVITYHASH_DEFAULT_SIZE) from_hash->size = GRAVITYHASH_DEFAULT_SIZE;

gravity_hash_t *hashtable = (gravity_hash_t *)mem_alloc(NULL, sizeof(gravity_hash_t));
2 changes: 1 addition & 1 deletion src/shared/gravity_hash.h
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ typedef bool (*gravity_hash_compare_fn) (gravity_value_t value1, gravity_

// PUBLIC functions
GRAVITY_API gravity_hash_t *gravity_hash_create (uint32_t size, gravity_hash_compute_fn compute, gravity_hash_isequal_fn isequal, gravity_hash_iterate_fn free, void *data);
GRAVITY_API gravity_hash_t *gravity_hash_create_from (gravity_hash_t *from_hash);
GRAVITY_API gravity_hash_t *gravity_hash_dup (gravity_hash_t *from_hash);
GRAVITY_API void gravity_hash_free (gravity_hash_t *hashtable);
GRAVITY_API bool gravity_hash_isempty (gravity_hash_t *hashtable);
GRAVITY_API bool gravity_hash_remove (gravity_hash_t *hashtable, gravity_value_t key);
33 changes: 29 additions & 4 deletions src/shared/gravity_value.c
Original file line number Diff line number Diff line change
@@ -2057,6 +2057,18 @@ gravity_list_t *gravity_list_new (gravity_vm *vm, uint32_t n) {
return list;
}

gravity_value_t gravity_list_to_value(gravity_vm *vm, gravity_list_t *list) {
gravity_list_t *copy = mem_alloc(NULL, sizeof(gravity_list_t));
copy->array = list->array;

gravity_value_t value;
value.isa = gravity_class_list;
value.p = (gravity_object_t *)copy;

if (vm) gravity_vm_transfer(vm, (gravity_object_t*) copy);
return value;
}

gravity_list_t *gravity_list_from_array (gravity_vm *vm, uint32_t n, gravity_value_t *p) {
gravity_list_t *list = (gravity_list_t *)mem_alloc(NULL, sizeof(gravity_list_t));

@@ -2227,7 +2239,11 @@ static void gravity_map_stringify_iterator(gravity_hash_t *hashtable, gravity_va
// INT
if (VALUE_ISA_INT(v)) {
substr = mem_alloc(NULL, strlen(key_string) + sizeof(int64_t) + 10 * sizeof(char));
#ifdef __APPLE__
sprintf(substr, "%s\"%s\": %lld", delimiter, key_string, (int64_t)v.n);
#else
sprintf(substr, "%s\"%s\": %ld", delimiter, key_string, (int64_t)v.n);
#endif
gravity_string_concat_cstring(NULL, map_string, substr);
return;
}
@@ -2259,20 +2275,29 @@ static void gravity_map_stringify_iterator(gravity_hash_t *hashtable, gravity_va
return;
}

if (VALUE_ISA_LIST(v)) {
gravity_list_t *value_list = VALUE_AS_LIST(v);
char *value_list_string = VALUE_AS_CSTRING(convert_value2string(NULL, v));
substr = mem_alloc(NULL, strlen(key_string) + strlen(value_list_string) + 10 * sizeof(char));
sprintf(substr, "%s%s: %s", delimiter, key_string, value_list_string);
gravity_string_concat_cstring(NULL, map_string, substr);
return;
}

// should never reach this point
assert(0);
}

char *gravity_map_to_string(gravity_vm *vm, gravity_map_t *map) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not to reuse convert_map2string defined in gravity_core.c?

gravity_string_t *map_string = gravity_string_new(NULL, "", 1000, 0);
gravity_string_t *map_string = gravity_string_new(NULL, "", 0, 0);
gravity_hash_iterate(map->hash, gravity_map_stringify_iterator, map_string);
gravity_string_concat_cstring(NULL, map_string, "}");
return map_string->s;
}

gravity_value_t gravity_map_to_value (gravity_vm *vm, gravity_map_t *map) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure to understand the use case of this...

Copy link
Author

@jamesalbert jamesalbert Jun 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcobambini Wouldn't you say there's a need for _to_value functions for all types? E.g. if I want to create a map with a key associated to an array, I'd have no way of doing that without doing something like:

gravity_map_t *response = gravity_map_new(vm, 32);
gravity_list_t *headers = gravity_list_new(vm, 32);
gravity_map_insert(vm, response,
    gravity_string_to_value("Headers"),
    gravity_list_to_value(headers));

If there's a way for already doing something like this, let me know. I'm cleaning up the implementation at the moment, currently trying to get something like this going

Copy link
Author

@jamesalbert jamesalbert Jun 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use the map_to_value method in a similar fashion in src/optionals/gravity_http.c

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I guess VALUE_FROM_OBJECT might be helpful in this case 😎

// allocate the size of a string
gravity_hash_t *h = gravity_hash_create_from(map->hash);
gravity_hash_t *h = gravity_hash_dup(map->hash);
gravity_map_t *m = mem_alloc(vm, gravity_map_size(vm, map));
m->hash = h;

@@ -2360,12 +2385,12 @@ inline gravity_string_t *gravity_string_new (gravity_vm *vm, char *s, uint32_t l
}

inline void gravity_string_concat_cstring (gravity_vm *vm, gravity_string_t *obj, char *cstring) {
uint32_t len = (uint32_t)(strlen(obj->s) + strlen(cstring));
uint32_t len = (uint32_t)(obj->len + strlen(cstring));
uint32_t alloc = MAXNUM(len+1, DEFAULT_MINSTRING_SIZE);
obj->s = mem_realloc(NULL, obj->s, alloc);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of always perform a men_realloc you should first check if (obj->alloc - obj->len) is big enough

memcpy(obj->s + obj->len, cstring, 1 + strlen(cstring));
obj->len = len;
obj->alloc = alloc;
strcat(obj->s, cstring);
}

inline void gravity_string_set (gravity_string_t *obj, char *s, uint32_t len) {
1 change: 1 addition & 0 deletions src/shared/gravity_value.h
Original file line number Diff line number Diff line change
@@ -522,6 +522,7 @@ GRAVITY_API const char *gravity_object_debug (gravity_object_t *obj, bo

// MARK: - LIST -
GRAVITY_API gravity_list_t *gravity_list_new (gravity_vm *vm, uint32_t n);
GRAVITY_API gravity_value_t gravity_list_to_value (gravity_vm *vm, gravity_list_t *list);
GRAVITY_API gravity_list_t *gravity_list_from_array (gravity_vm *vm, uint32_t n, gravity_value_t *p);
GRAVITY_API void gravity_list_free (gravity_vm *vm, gravity_list_t *list);
GRAVITY_API void gravity_list_append_list (gravity_vm *vm, gravity_list_t *list1, gravity_list_t *list2);
4 changes: 4 additions & 0 deletions src/utils/gravity_utils.c
Original file line number Diff line number Diff line change
@@ -323,6 +323,10 @@ int string_cmp (const char *s1, const char *s2) {
return strcmp(s1, s2);
}

bool string_starts_with(const char *s1, const char *s2) {
return strncmp(s1, s2, strlen(s2)) == 0;
}

const char *string_dup (const char *s1) {
size_t len = (size_t)strlen(s1);
char *s = (char *)mem_alloc(NULL, len + 1);
1 change: 1 addition & 0 deletions src/utils/gravity_utils.h
Original file line number Diff line number Diff line change
@@ -47,6 +47,7 @@ const char *directory_read (DIRREF ref, char *out);
int string_nocasencmp (const char *s1, const char *s2, size_t n);
int string_casencmp (const char *s1, const char *s2, size_t n);
int string_cmp (const char *s1, const char *s2);
bool string_starts_with(const char *s1, const char *s2);
const char *string_dup (const char *s1);
const char *string_ndup (const char *s1, size_t n);
void string_reverse (char *p);