Page MenuHomePhorge

No OneTemporary

Size
15 KB
Referenced Files
None
Subscribers
None
diff --git a/Makefile b/Makefile
index b0e89ce..9807776 100644
--- a/Makefile
+++ b/Makefile
@@ -1,74 +1,74 @@
MIX = mix
MYHTMLEX_CFLAGS = -g -O2 -std=c99 -pedantic -Wcomment -Wall
# we need to compile position independent code
MYHTMLEX_CFLAGS += -fpic -DPIC
# For some reason __erl_errno is undefined unless _REENTRANT is defined
MYHTMLEX_CFLAGS += -D_REENTRANT
# myhtmlex is using stpcpy, as defined in gnu string.h
# MYHTMLEX_CFLAGS += -D_GNU_SOURCE
# base on the same posix c source as myhtml
# MYHTMLEX_CFLAGS += -D_POSIX_C_SOURCE=199309
# turn warnings into errors
# MYHTMLEX_CFLAGS += -Werror
# ignore unused variables
# MYHTMLEX_CFLAGS += -Wno-unused-variable
# ignore unused parameter warnings
MYHTMLEX_CFLAGS += -Wno-unused-parameter
# set erlang include path
ERLANG_PATH = $(shell erl -eval 'io:format("~s", [lists:concat([code:root_dir(), "/erts-", erlang:system_info(version)])])' -s init stop -noshell)
MYHTMLEX_CFLAGS += -I$(ERLANG_PATH)/include
# expecting myhtml as a submodule in c_src/
# that way we can pin a version and package the whole thing in hex
# hex does not allow for non-app related dependencies.
MYHTML_PATH = c_src/myhtml
MYHTML_STATIC = $(MYHTML_PATH)/lib/libmyhtml_static.a
MYHTMLEX_CFLAGS += -I$(MYHTML_PATH)/include
# that would be used for a dynamically linked build
# MYHTMLEX_CFLAGS += -L$(MYHTML_PATH)/lib
MYHTMLEX_LDFLAGS = -shared
# C-Node
ERL_INTERFACE = $(wildcard $(ERLANG_PATH)/../lib/erl_interface-*)
CNODE_CFLAGS = $(MYHTMLEX_CFLAGS)
CNODE_CFLAGS += -L$(ERL_INTERFACE)/lib
CNODE_CFLAGS += -I$(ERL_INTERFACE)/include
CNODE_CFLAGS += -lerl_interface -lei
# platform specific
UNAME = $(shell uname -s)
ifeq ($(wilcard Makefile.$(UNAME)),)
include Makefile.$(UNAME)
endif
.PHONY: all
all: myhtmlex
myhtmlex: priv/myhtmlex.so
$(MIX) compile
$(MYHTML_STATIC): $(MYHTML_PATH)
$(MAKE) -C $(MYHTML_PATH) library
priv/myhtmlex.so: c_src/myhtmlex.c $(MYHTML_STATIC)
$(CC) $(MYHTMLEX_CFLAGS) $(MYHTMLEX_LDFLAGS) -o $@ $< $(MYHTML_STATIC)
priv/cclient: c_src/cclient.c $(MYHTML_STATIC)
- $(CC) $(CNODE_CFLAGS) -o $@ $< $(MYHTML_STATIC)
+ $(CC) -o $@ $< $(MYHTML_STATIC) $(CNODE_CFLAGS)
clean: clean-myhtml
$(RM) -r priv/myhtmlex*
$(RM) priv/cclient
$(RM) myhtmlex-*.tar
$(RM) -r package-test
clean-myhtml:
$(MAKE) -C $(MYHTML_PATH) clean
publish: clean
$(MIX) hex.publish
diff --git a/c_src/cserver.c b/c_src/cserver.c
deleted file mode 100644
index 6ca69ed..0000000
--- a/c_src/cserver.c
+++ /dev/null
@@ -1,500 +0,0 @@
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <errno.h>
-
-#include "erl_interface.h"
-#include "ei.h"
-
-#include <myhtml/myhtml.h>
-#include <myhtml/mynamespace.h>
-
-#define BUFFER_SIZE 1000
-
-typedef struct _binding_t {
- int fd;
- int port;
- ErlConnect conn;
-} binding_t;
-
-typedef struct _thread_state_t {
- int fd;
- int idx;
- char *node;
-
- myhtml_tree_t* tree;
-} thread_state_t;
-
-typedef struct _prefab_t {
- ETERM* atom_nil;
- ETERM* atom_comment;
- ETERM* empty_list;
-} prefab_t;
-
-binding_t
-bind_any_port();
-void
-accept_loop(binding_t* binding);
-void
-*thread_receive_messages(void*); // receives thread_state_t* state
-void
-handle_emsg(thread_state_t* state, ErlMessage* emsg);
-void
-handle_send(thread_state_t* state, ErlMessage* emsg);
-ETERM*
-decode(thread_state_t* state, ErlMessage* emsg, ETERM* bin, ETERM* args);
-ETERM*
-build_tree(prefab_t* prefab, myhtml_tree_t* tree, myhtml_tree_node_t* node, unsigned char* parse_flags);
-ETERM*
-build_node_children(prefab_t* prefab, myhtml_tree_t* tree, myhtml_tree_node_t* parent, unsigned char* parse_flags);
-ETERM*
-build_node_attrs(prefab_t* prefab, myhtml_tree_t* tree, myhtml_tree_node_t* node);
-ETERM*
-err_term(const char* error_atom);
-
-static int TIDX = 0; // thread index
-
-const unsigned char FLAG_HTML_ATOMS = 1 << 0;
-const unsigned char FLAG_NIL_SELF_CLOSING = 1 << 1;
-const unsigned char FLAG_COMMENT_TUPLE3 = 1 << 2;
-
-int main(int argc, char **argv) {
- if (argc != 4 || !strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")) {
- printf("\nUsage: ./priv/cnode_server <sname> <hostname> <cookie>\n\n");
- printf(" sname the short name you want this c-node to connect as\n");
- printf(" hostname the hostname\n");
- printf(" cookie the authentication cookie\n");
- return 0;
- }
-
- char *sname = argv[1];
- char *hostname = argv[2];
- char *cookie = argv[3];
- /* gethostname(hostname, 256); */
- char full_name[1024];
- stpcpy(stpcpy(stpcpy(full_name, sname), "@"), hostname);
-
- struct in_addr addr;
- addr.s_addr = htonl(INADDR_ANY);
-
- // initialize all of Erl_Interface
- erl_init(NULL, 0);
-
- printf("initialising %s\n", full_name); fflush(stdout);
- if ( erl_connect_xinit(hostname, sname, full_name, &addr, cookie, 0) == -1 )
- erl_err_quit("error erl_connect_init");
-
- // create a listen socket
- binding_t binding = bind_any_port();
- if (binding.fd < 0)
- erl_err_quit("error bind_any_port");
-
- // publish our port
- if (erl_publish(binding.port) == -1)
- erl_err_quit("error erl_publish");
-
- // signal to stdout that we are ready, do not fflush yet
- printf("%s ready\n", full_name);
-
- // accept loop
- accept_loop(&binding);
-}
-
-void
-accept_loop(binding_t* binding)
-{
- thread_state_t* state;
- pthread_t thread;
- pthread_attr_t attr;
- int fd;
- ErlConnect conn;
- myhtml_t* myhtml = myhtml_create();
- myhtml_init(myhtml, MyHTML_OPTIONS_DEFAULT, 1, 0);
-
- // now it is really time to flush stdout
- fflush(stdout);
-
- // initialising phtread attributes
- if (pthread_attr_init(&attr)) {
- fprintf(stderr, "error while init pthread attr struct\n\r"); fflush(stderr);
- return; // TODO: DIE
- }
- if ((pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))) {
- fprintf(stderr, "error while setting pthread attributes\n\r"); fflush(stderr);
- return; // TODO: DIE
- }
-
- // spawn a new thread for each connected erlang client
- for(;;) {
- while((fd = erl_accept(binding->fd, &conn)) == ERL_ERROR)
- fprintf(stderr, "error accepting connection\n"); fflush(stderr);
-
- if((state = (thread_state_t*)malloc(sizeof(thread_state_t))) == NULL) {
- fprintf(stderr, "error allocating memory for new thread\n"); fflush(stderr);
- return; // TODO: DIE
- }
-
- if((state->node = (char*)malloc(strlen(conn.nodename)+1)) == NULL) {
- fprintf(stderr, "error allocating memory for new state\n"); fflush(stderr);
- return; // TODO: DIE
- }
-
- state->fd = fd;
- state->idx = TIDX;
- strcpy(state->node, binding->conn.nodename);
- state->tree = myhtml_tree_create();
- myhtml_tree_init(state->tree, myhtml);
-
- printf("node joined\n"); fflush(stdout);
- if (pthread_create(&thread, &attr, thread_receive_messages, state)) {
- fprintf(stderr, "error pthread_create\n\r"); fflush(stderr);
- return; // TODO: DIE
- }
- TIDX++;
- }
-
- return;
-}
-
-void
-*thread_receive_messages(void *arg)
-{
- thread_state_t *state = (thread_state_t*)arg;
- bool looping = true;
- /* unsigned char buffer[BUFFER_SIZE]; */
- ErlMessage emsg;
- // TODO: get erl_xreceive_msg to work
- // making use of reallocatable buffer sizes
- /* unsigned char **bufferpp; */
- /* int *buffer_size; */
- /* buffer_size = malloc(sizeof(int)); */
- /* *buffer_size = BUFFER_SIZE; */
- /* *bufferpp = malloc(*buffer_size); */
- int buffer_size = BUFFER_SIZE;
- unsigned char* bufferpp = (unsigned char*)malloc(BUFFER_SIZE);
-
- while (looping) {
- // erl_xreceive_msg adapts the buffer width
- switch( erl_xreceive_msg(state->fd, &bufferpp, &buffer_size, &emsg) )
- // erl_receive_msg, uses a fixed buffer width
- /* switch( erl_receive_msg(state->fd, buffer, BUFFER_SIZE, &emsg) ) */
- {
- case ERL_TICK:
- // ignore
- break;
- case ERL_ERROR:
- // On failure, the function returns ERL_ERROR and sets erl_errno to one of:
- //
- // EMSGSIZE
- // Buffer is too small.
- // ENOMEM
- // No more memory is available.
- // EIO
- // I/O error.
- //
- // TODO: what is the correct reaction?
- looping = false;
- break;
- default:
- handle_emsg(state, &emsg);
- }
- }
-
- free(state->node);
- free(state);
- printf("lost node\n"); fflush(stdout);
- return 0;
-}
-
-void
-handle_emsg(thread_state_t* state, ErlMessage* emsg)
-{
- switch(emsg->type)
- {
- case ERL_REG_SEND:
- case ERL_SEND:
- handle_send(state, emsg);
- break;
- case ERL_LINK:
- case ERL_UNLINK:
- break;
- case ERL_EXIT:
- break;
- }
- // its our responsibility to free these pointers
- erl_free_compound(emsg->msg);
- erl_free_compound(emsg->to);
- erl_free_compound(emsg->from);
-}
-
-void
-handle_send(thread_state_t* state, ErlMessage* emsg)
-{
- ETERM *decode_pattern = erl_format("{decode, Bin, Args}");
- ETERM *response;
-
- if (erl_match(decode_pattern, emsg->msg))
- {
- ETERM *bin = erl_var_content(decode_pattern, "Bin");
- ETERM *args = erl_var_content(decode_pattern, "Args");
-
- response = decode(state, emsg, bin, args);
-
- // free allocated resources
- erl_free_term(bin);
- erl_free_term(args);
- }
- else
- {
- response = err_term("unknown_call");
- return;
- }
-
- // send response
- erl_send(state->fd, emsg->from, response);
-
- // free allocated resources
- erl_free_compound(response);
- erl_free_term(decode_pattern);
-
- // free the free-list
- erl_eterm_release();
-
- return;
-}
-
-ETERM*
-err_term(const char* error_atom)
-{
- /* ETERM* tuple2[] = {erl_mk_atom("error"), erl_mk_atom(error_atom)}; */
- /* return erl_mk_tuple(tuple2, 2); */
- return erl_format("{error, ~w}", erl_mk_atom(error_atom));
-}
-
-ETERM*
-decode(thread_state_t* state, ErlMessage* emsg, ETERM* bin, ETERM* args)
-{
- unsigned char parse_flags = 0;
- prefab_t prefab;
-
- // prepare reusable prefab terms
- prefab.atom_nil = erl_mk_atom("nil");
- prefab.atom_comment = erl_mk_atom("comment");
- prefab.empty_list = erl_mk_empty_list();
-
- if (!ERL_IS_BINARY(bin) || !ERL_IS_LIST(args))
- {
- return err_term("badarg");
- }
-
- // get contents of binary argument
- char* binary = (char*)ERL_BIN_PTR(bin);
- size_t binary_len = ERL_BIN_SIZE(bin);
-
- // parse tree
- mystatus_t status = myhtml_parse(state->tree, MyENCODING_UTF_8, binary, binary_len);
- if (status != MyHTML_STATUS_OK)
- {
- return err_term("myhtml_parse_failed");
- }
-
- // build tree
- myhtml_tree_node_t *root = myhtml_tree_get_document(state->tree);
- return build_tree(&prefab, state->tree, myhtml_node_last_child(root), &parse_flags);
-}
-
-ETERM*
-build_tree(prefab_t* prefab, myhtml_tree_t* tree, myhtml_tree_node_t* node, unsigned char* parse_flags)
-{
- ETERM* result;
- myhtml_tag_id_t tag_id = myhtml_node_tag_id(node);
- /* myhtml_namespace_t tag_ns = myhtml_node_namespace(node); */
-
- if (tag_id == MyHTML_TAG__TEXT)
- {
- size_t text_len;
- const char* node_text = myhtml_node_text(node, &text_len);
- result = erl_mk_binary(node_text, text_len);
- }
- else if (tag_id == MyHTML_TAG__COMMENT)
- {
- size_t comment_len;
- const char* node_comment = myhtml_node_text(node, &comment_len);
- ETERM* comment = erl_mk_binary(node_comment, comment_len);
-
- if (*parse_flags & FLAG_COMMENT_TUPLE3)
- {
- /* ETERM* tuple3[] = {prefab->atom_comment, prefab->empty_list, comment}; */
- /* result = erl_mk_tuple(tuple3, 3); */
- result = erl_format("{comment, [], ~w}", comment);
- }
- else
- {
- /* ETERM* tuple2[] = {prefab->atom_comment, comment}; */
- /* result = erl_mk_tuple(tuple2, 2); */
- result = erl_format("{comment, ~w}", comment);
- }
- }
- else
- {
- ETERM* tag;
- ETERM* attrs;
- ETERM* children;
-
- // get name of tag
- size_t tag_name_len;
- const char *tag_name = myhtml_tag_name_by_id(tree, tag_id, &tag_name_len);
- // get namespace of tag
- /* size_t tag_ns_len; */
- /* const char *tag_ns_name_ptr = myhtml_namespace_name_by_id(tag_ns, &tag_ns_len); */
- /* char *tag_ns_buffer; */
- /* char buffer [tag_ns_len + tag_name_len + 1]; */
- /* char *tag_string = buffer; */
- /* size_t tag_string_len; */
-
- tag = erl_mk_binary(tag_name, tag_name_len);
-
- // attributes
- attrs = build_node_attrs(prefab, tree, node);
-
- // children
- children = build_node_children(prefab, tree, node, parse_flags);
-
- /* ETERM* tuple3[] = {tag, attrs, children}; */
- /* result = erl_mk_tuple(tuple3, 3); */
- result = erl_format("{~w, ~w, ~w}", tag, attrs, children);
- }
-
- return result;
-}
-
-ETERM*
-build_node_children(prefab_t* prefab, myhtml_tree_t* tree, myhtml_tree_node_t* parent, unsigned char* parse_flags)
-{
- if (myhtml_node_is_close_self(parent) && (*parse_flags & FLAG_NIL_SELF_CLOSING))
- {
- /* prefab->atom_nil; */
- return erl_mk_atom("nil");
- }
-
- myhtml_tree_node_t* child = myhtml_node_last_child(parent);
- if (child == NULL)
- {
- if (myhtml_node_is_void_element(parent) && (*parse_flags & FLAG_NIL_SELF_CLOSING))
- {
- /* return prefab->atom_nil; */
- return erl_mk_atom("nil");
- }
- /* else */
- /* { */
- /* return prefab->empty_list; */
- /* } */
- }
-
- ETERM* list = erl_mk_empty_list();
-
- while (child)
- {
- ETERM* node_tuple = build_tree(prefab, tree, child, parse_flags);
- list = erl_cons(node_tuple, list);
-
- // get previous child, building the list from reverse
- child = myhtml_node_prev(child);
- }
-
- return list;
-}
-
-ETERM*
-build_node_attrs(prefab_t* prefab, myhtml_tree_t* tree, myhtml_tree_node_t* node)
-{
- myhtml_tree_attr_t* attr = myhtml_node_attribute_last(node);
-
- /* if (attr == NULL) */
- /* { */
- /* return prefab->empty_list; */
- /* } */
-
- ETERM* list = erl_mk_empty_list();
-
- while (attr)
- {
- ETERM* name;
- ETERM* value;
- ETERM* attr_tuple;
-
- size_t attr_name_len;
- const char *attr_name = myhtml_attribute_key(attr, &attr_name_len);
- size_t attr_value_len;
- const char *attr_value = myhtml_attribute_value(attr, &attr_value_len);
-
- if (attr_value) {
- value = erl_mk_binary(attr_value, attr_value_len);
- } else {
- value = erl_mk_binary(attr_name, attr_name_len);
- }
- name = erl_mk_binary(attr_name, attr_name_len);
-
- /* ETERM* tuple2[] = {name, value}; */
- /* attr_tuple = erl_mk_tuple(tuple2, 2); */
- attr_tuple = erl_format("{~w, ~w}", name, value);
-
- list = erl_cons(attr_tuple, list);
-
- // get prev attribute, building the list from reverse
- attr = myhtml_attribute_prev(attr);
- }
-
- return list;
-}
-
-binding_t
-bind_any_port()
-{
- int port = 40000;
- binding_t result;
- result.fd = -1;
- struct sockaddr_in addr;
- int on = 1;
- int bind_result;
-
- if ((result.fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- {
- return result;
- }
-
- setsockopt(result.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
- memset((void*) &addr, 0, (size_t) sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(port);
-
- while(
- (bind_result = bind(result.fd, (struct sockaddr*) &addr, sizeof(addr))) < 0
- && errno == EADDRINUSE
- )
- {
- port++;
- addr.sin_port = htons(port);
- }
- if (bind_result < 0)
- {
- return result;
- }
- else
- {
- result.port = port;
-
- listen(result.fd, 5);
-
- return result;
- }
-}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 8:37 PM (1 d, 20 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55441
Default Alt Text
(15 KB)

Event Timeline