diff --git a/bin/uce_fastcgi.debug.linux.bin b/bin/uce_fastcgi.debug.linux.bin index 710a598..5e5a9bb 100755 Binary files a/bin/uce_fastcgi.debug.linux.bin and b/bin/uce_fastcgi.debug.linux.bin differ diff --git a/src/lib/compiler.h b/src/lib/compiler.h index 652a7ac..8b740f6 100644 --- a/src/lib/compiler.h +++ b/src/lib/compiler.h @@ -1,4 +1,4 @@ -#define RENDER() extern "C" void render() +#define RENDER() extern "C" void render(DTree& call) string process_html_literal(Request* context, SharedUnit* su, string content) { @@ -253,7 +253,7 @@ SharedUnit* get_shared_unit(Request* context, string file_name) return(su); } -void compiler_invoke(Request* context, string file_name) +void compiler_invoke(Request* context, string file_name, DTree& call_param) { if(file_name[0] != '/') { @@ -270,6 +270,7 @@ void compiler_invoke(Request* context, string file_name) } else if(!su->on_render) { + context->header["Content-Type"] = "text/plain"; context->print("Compiler error: "+su->compiler_messages); } else @@ -281,7 +282,7 @@ void compiler_invoke(Request* context, string file_name) string prev_wd = get_cwd(); set_cwd(su->src_path); su->on_setup(context); - su->on_render(); + su->on_render(call_param); set_cwd(prev_wd); } } diff --git a/src/lib/sys.h b/src/lib/sys.h index dbc827b..ca3b381 100644 --- a/src/lib/sys.h +++ b/src/lib/sys.h @@ -1,5 +1,10 @@ #include #include +#include +#include +#include +#include +#include string shell_exec(string cmd) { @@ -222,4 +227,94 @@ u64 parse_time(string time_string) return(int_val(trim(shell_exec("date -u -d '"+time_string+"' +'%s'")))); } +u64 socket_connect(string host, short port) +{ + /*struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; + };*/ + + auto sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(sockfd < 0) + { + echo("SOCKET ERROR (could not open socket)\n"); + perror("SOCKET ERROR "); + return(0); + } + + struct sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(host.c_str()); + + if(connect(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) + { + echo("SOCKET ERROR (could not connect to address " + string(host) + ":" + std::to_string(port) + ")\n"); + perror("SOCKET ERROR "); + return(0); + } + context->resources.sockets.push_back(sockfd); + return(sockfd); +} + +void socket_close(u64 sockfd) +{ + close(sockfd); +} + +bool socket_write(u64 sockfd, string data) +{ + return(write(sockfd, data.c_str(), data.length()) >= 0); +} + +string socket_read(u64 sockfd, u32 max_length = 1024*128, u32 timeout = 1) +{ + struct timeval tv; + tv.tv_sec = timeout; + tv.tv_usec = 0; + setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); + char buf[max_length+1]; + auto byte_count = recv(sockfd, buf, sizeof(buf), 0); + if(byte_count > 0) + { + buf[byte_count] = 0; + string result(buf, byte_count+1); + return(result); + } + return(""); +} + +u64 memcache_connect(string host = "127.0.0.1", short port = 11211) +{ + return(socket_connect(host, port)); +} + +string memcache_get_raw(u64 connection, string command) +{ + socket_write(connection, command+"\r\n"); + return(socket_read(connection)); // FIXME: do multi-chunk until END line is received! +} + +bool memcache_set(u64 connection, string key, string value, u64 expires_in = 60*60) +{ + // to do: escape key string + socket_write(connection, + // set KEY META_DATA EXPIRY_TIME LENGTH_IN_BYTES + string("set ") + (key) + " 0 " + std::to_string(expires_in) + " " + std::to_string(value.length()) + "\r\n" + + value + "\r\n"); + return("STORED" == trim(socket_read(connection))); +} + +string memcache_get(u64 connection, string key) +{ + // to do: escape key string + auto res = memcache_get_raw(connection, string("get ")+key); + +} diff --git a/src/lib/types.h b/src/lib/types.h index ec5a956..8e5ce02 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -39,11 +39,10 @@ typedef long long s64; typedef std::map StringMap; typedef std::list StringList; -typedef void (*invoke_handler)(string file_name); - struct Request; +struct DTree; -typedef void (*call_handler)(); +typedef void (*call_handler)(DTree& call_param); typedef void (*request_handler)(Request* request); string to_string(u64 v) { return(std::to_string(v)); } @@ -107,8 +106,6 @@ struct ServerState { }; -void compiler_invoke(Request* context, string file_name); - struct URI { StringMap query; @@ -145,6 +142,8 @@ string to_hex(ITYPE w, size_t hex_len = sizeof(ITYPE)<<1) #include "dtree.h" +void compiler_invoke(Request* context, string file_name, DTree& call_param); + struct Request { ServerState* server; @@ -172,9 +171,19 @@ struct Request { f64 time_start; f64 time_end; + struct Resources { + std::vector sockets; + } resources; + void invoke(string file_name) { - compiler_invoke(this, file_name); + DTree call_param; + compiler_invoke(this, file_name, call_param); + } + + void invoke(string file_name, DTree& call_param) + { + compiler_invoke(this, file_name, call_param); } void print(string s) @@ -182,6 +191,12 @@ struct Request { out.append(s); } + ~Request() + { + for(auto& sockfd : resources.sockets) + close(sockfd); + } + }; typedef Request FastCGIRequest; diff --git a/test/index.uce b/test/index.uce index fc97e3d..9124c20 100644 --- a/test/index.uce +++ b/test/index.uce @@ -19,6 +19,7 @@ RENDER()
  • Session
  • DTree
  • JSON
  • +
  • Memcached
  • params) ?>
    diff --git a/test/memcached.uce b/test/memcached.uce new file mode 100644 index 0000000..9f8eb2c --- /dev/null +++ b/test/memcached.uce @@ -0,0 +1,37 @@ + + +RENDER() +{ + DTree t; + + <> + +

    + UCE Test: + MemcacheD +

    + + Stats: + +
    + + Set/Get: + +
    + + Params +
    params) ?>
    + + +} diff --git a/test/text-json.uce b/test/text-json.uce deleted file mode 100644 index e683ac3..0000000 --- a/test/text-json.uce +++ /dev/null @@ -1,12 +0,0 @@ - - -RENDER() -{ - - DTree t; - - echo(json_encode(t)); - - echo(string("PATH: ") + context->server->config.COMPILER_SYS_PATH + "\n"); - -} diff --git a/todo.txt b/todo.txt index 4dcc579..d0f6344 100644 --- a/todo.txt +++ b/todo.txt @@ -4,7 +4,6 @@ Library - mysql - sha1 / md5 / meow - cache -- json_encode / json_decode - curl - random - pseudorandom @@ -14,8 +13,6 @@ Bugs ================================= - shell_escape() - we crash on illegal paths -- you should not be able to invoke() outside of DOCUMENT_ROOT -- invoke path should not be the same as cwd (cwd should be path of entry point file) Framework