sub-invoke()

This commit is contained in:
udo
2021-10-29 14:17:00 +00:00
parent a65a3d1207
commit fa432a0482
14 changed files with 196 additions and 87 deletions
Binary file not shown.
+2 -3
View File
@@ -16,14 +16,13 @@ mkdir bin/assets > /dev/null 2>&1
mkdir work > /dev/null 2>&1 mkdir work > /dev/null 2>&1
COMPILER="clang++" COMPILER="clang++"
FLAGS="-w -Wall -$OPT_FLAG -std=c++17 -fpermissive -ffast-math" FLAGS="-g -w -Wall -$OPT_FLAG -std=c++17 -fpermissive -ffast-math"
LIBS="-ldl -lm -lpthread " LIBS="-ldl -lm -lpthread "
SRCFLAGS="-D EXEC_NAME=\"$GF\" -D PLATFORM_NAME=\"linux\"" SRCFLAGS="-D EXEC_NAME=\"$GF\" -D PLATFORM_NAME=\"linux\""
echo "Compliling executable..." echo "Compliling executable..."
#time -p time -p $COMPILER src/linux_fastcgi.cpp $SRCFLAGS $FLAGS $LIBS -o bin/$GF.$BUILDMODE.linux.bin 2>&1
$COMPILER src/linux_fastcgi.cpp $SRCFLAGS $FLAGS $LIBS -o bin/$GF.$BUILDMODE.linux.bin 2>&1
if [ $? -eq 0 ] if [ $? -eq 0 ]
then then
+89 -67
View File
@@ -1,31 +1,6 @@
#include <dlfcn.h>
#define RENDER() extern "C" void render() #define RENDER() extern "C" void render()
typedef void (*call_handler)(); string process_html_literal(SharedUnit* su, string content)
typedef void (*request_handler)(Request* request);
struct SharedUnit {
string file_name;
string so_name;
void* so_handle;
request_handler on_setup;
call_handler on_render;
string compiler_messages;
time_t last_compiled;
~SharedUnit()
{
if(so_handle)
{
dlclose(so_handle);
}
}
};
std::map<string, SharedUnit*> units;
string process_html_literal(string content, string file_name)
{ {
string pc; string pc;
string HT_START = "context->print(R\"("; string HT_START = "context->print(R\"(";
@@ -99,9 +74,10 @@ string process_html_literal(string content, string file_name)
return(HT_START + pc + HT_END); return(HT_START + pc + HT_END);
} }
string preprocess(string content, string file_name) string preprocess_shared_unit(SharedUnit* su)
{ {
string pc = "#include \""+get_cwd()+"/src/lib/uce_gen.h\" \n"; string content = file_get_contents(su->file_name);
string pc = "#include \""+context->server_state->config.COMPILER_SYS_PATH +"/src/lib/uce_gen.h\" \n";
string token = ""; string token = "";
string html_buffer = ""; string html_buffer = "";
u8 mode = 0; u8 mode = 0;
@@ -117,11 +93,11 @@ string preprocess(string content, string file_name)
u32 len = token.length() + 3 + end_pos - i; u32 len = token.length() + 3 + end_pos - i;
html_buffer.append(content.substr(i, len - (token.length() == 0 ? 3 : 0))); html_buffer.append(content.substr(i, len - (token.length() == 0 ? 3 : 0)));
i += len - 1; i += len - 1;
pc.append(process_html_literal(html_buffer, file_name)); pc.append(process_html_literal(su, html_buffer));
} }
else else
{ {
printf("(!) unterminated HTML literal <%s> in %s", token.c_str(), file_name.c_str()); printf("(!) unterminated HTML literal <%s> in %s", token.c_str(), su->file_name.c_str());
} }
mode = 0; mode = 0;
} }
@@ -160,9 +136,39 @@ string preprocess(string content, string file_name)
return(pc); return(pc);
} }
void load_shared_unit(SharedUnit* su) void setup_unit_paths(SharedUnit* su, string file_name)
{ {
su->file_name = file_name;
if(su->src_path.length() > 0) // we did this already
return;
su->src_path = dirname(file_name);
su->bin_path = context->server_state->config.BIN_DIRECTORY + su->src_path;
su->pre_path = context->server_state->config.BIN_DIRECTORY + su->src_path;
su->src_file_name = basename(file_name);
su->bin_file_name = su->src_file_name + ".so";
su->pre_file_name = su->src_file_name + ".cpp";
su->so_name = su->bin_path + "/" + su->bin_file_name;
}
void load_shared_unit(SharedUnit* su, string file_name)
{
setup_unit_paths(su, file_name);
su->on_render = 0; su->on_render = 0;
su->on_setup = 0;
su->compiler_messages = "";
if(!file_exists(su->so_name))
{
printf("(i) unit file not found: %s\n", su->so_name.c_str());
su->compiler_messages = "unit file not found";
return;
}
su->so_handle = dlopen(su->so_name.c_str(), RTLD_NOW); su->so_handle = dlopen(su->so_name.c_str(), RTLD_NOW);
if(su->so_handle) if(su->so_handle)
{ {
@@ -181,79 +187,95 @@ void load_shared_unit(SharedUnit* su)
} }
} }
SharedUnit* compile_shared_unit(string file_name) void compile_shared_unit(SharedUnit* su, string file_name)
{ {
SharedUnit* su = new SharedUnit(); setup_unit_paths(su, file_name);
string src_path = dirname(file_name); if(!file_exists(su->file_name))
string src_fn = basename(file_name); {
string dest_path = Config.BIN_DIRECTORY + src_path; su->compiler_messages = "source file not found";
string pp_fn = src_fn + ".cpp"; return;
string so_fn = src_fn + ".so"; }
su->file_name = file_name; shell_exec("mkdir -p " + shell_escape(su->pre_path));
su->so_name = dest_path + "/" + so_fn; file_put_contents(su->pre_path + "/" + su->pre_file_name, preprocess_shared_unit(su));
string pc = preprocess(file_get_contents(file_name), file_name); printf("Config.COMPILE_SCRIPT %s\n", string(su->pre_path + "/" + su->pre_file_name).c_str());
file_put_contents(dest_path + "/" + pp_fn, pc);
su->compiler_messages = trim(shell_exec(Config.COMPILE_SCRIPT+" "+ su->compiler_messages = trim(shell_exec(context->server_state->config.COMPILE_SCRIPT+" "+
shell_escape(src_path)+" "+ shell_escape(su->src_path)+" "+
shell_escape(dest_path)+" "+ shell_escape(su->bin_path)+" "+
shell_escape(src_fn)+" "+ shell_escape(su->file_name)+" "+
shell_escape(pp_fn)+" "+ shell_escape(su->pre_file_name)+" "+
shell_escape(so_fn) shell_escape(su->bin_file_name)
)); ));
if(su->compiler_messages.length() > 0) if(su->compiler_messages.length() > 0)
{
printf("%s \n", su->compiler_messages.c_str()); printf("%s \n", su->compiler_messages.c_str());
}
printf("(i) compiled unit %s\n", file_name.c_str()); else
{
load_shared_unit(su); load_shared_unit(su, file_name);
printf("(i) compiled unit %s\n", file_name.c_str());
return(su); }
} }
SharedUnit* get_shared_unit(string file_name) SharedUnit* get_shared_unit(string file_name)
{ {
SharedUnit* su = units[file_name]; SharedUnit* su = context->server_state->units[file_name];
if(su && su->last_compiled < file_mtime(file_name)) auto mod_time = file_mtime(file_name);
bool do_recompile = false;
if(su && (su->last_compiled < mod_time || mod_time == 0))
{ {
delete su; delete su;
su = 0; su = 0;
do_recompile = true;
} }
if(!su) if(!su)
{ {
su = units[file_name] = compile_shared_unit(file_name); su = new SharedUnit();
if(do_recompile)
{
compile_shared_unit(su, file_name);
}
else
{
load_shared_unit(su, file_name);
if(!su->so_handle)
compile_shared_unit(su, file_name);
}
context->server_state->units[file_name] = su;
} }
return(su); return(su);
} }
void invoke(Request* req, string file_name) void invoke(string file_name)
{ {
printf("(i) invoke(%s)\n", file_name.c_str());
auto su = get_shared_unit(file_name); auto su = get_shared_unit(file_name);
if(!su) if(!su)
{ {
printf("Error loading unit %s\n", su->file_name.c_str()); printf("Error loading unit %s\n", file_name.c_str());
context->print("Error loading unit: "+file_name);
} }
else if(!su->on_render) else if(!su->on_render)
{ {
req->print("Compiler error: "+su->compiler_messages); context->print("Compiler error: "+su->compiler_messages);
} }
else else
{ {
if(su->compiler_messages.length() > 0) if(su->compiler_messages.length() > 0)
req->print(su->compiler_messages); context->print(su->compiler_messages);
else else
{ {
su->on_setup(req); string prev_wd = get_cwd();
set_cwd(su->src_path);
su->on_setup(context);
su->on_render(); su->on_render();
set_cwd(prev_wd);
} }
} }
} }
void invoke(string file_name)
{
return(invoke(context, file_name));
}
+3 -2
View File
@@ -1,4 +1,4 @@
struct Settings { struct ServerSettings {
string BIN_DIRECTORY = "work"; string BIN_DIRECTORY = "work";
string COMPILE_SCRIPT = "scripts/compile"; string COMPILE_SCRIPT = "scripts/compile";
@@ -6,6 +6,7 @@ struct Settings {
string CONTENT_TYPE = "text/html; charset=utf-8"; string CONTENT_TYPE = "text/html; charset=utf-8";
string SOCKET_PATH = "/run/uce.sock"; string SOCKET_PATH = "/run/uce.sock";
string TMP_UPLOAD = "/tmp"; string TMP_UPLOAD = "/tmp";
string COMPILER_SYS_PATH = "";
u32 LISTEN_PORT = 9993; u32 LISTEN_PORT = 9993;
} Config; };
+6
View File
@@ -1,5 +1,6 @@
string shell_exec(string cmd) string shell_exec(string cmd)
{ {
printf("(i) shell_exec(%s)\n", cmd.c_str());
string data; string data;
FILE * stream; FILE * stream;
const int max_buffer = 256; const int max_buffer = 256;
@@ -98,6 +99,11 @@ string get_cwd()
return(std::filesystem::current_path()); return(std::filesystem::current_path());
} }
void set_cwd(string path)
{
chdir(path.c_str());
}
time_t file_mtime(string file_name) time_t file_mtime(string file_name)
{ {
struct stat info; struct stat info;
+37
View File
@@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include <sys/stat.h> #include <sys/stat.h>
#include <ctime> #include <ctime>
#include <dlfcn.h>
typedef std::string string; typedef std::string string;
@@ -33,11 +34,47 @@ typedef long long s64;
typedef std::map<string, string> StringMap; typedef std::map<string, string> StringMap;
typedef std::vector<string> StringList; typedef std::vector<string> StringList;
typedef void (*invoke_handler)(string file_name);
struct UploadedFile { struct UploadedFile {
string file_name; string file_name;
string tmp_name; string tmp_name;
u32 size; u32 size;
}; };
struct Request;
typedef void (*call_handler)();
typedef void (*request_handler)(Request* request);
struct SharedUnit {
string file_name;
string so_name;
string src_path;
string bin_path;
string pre_path;
string src_file_name;
string bin_file_name;
string pre_file_name;
void* so_handle;
request_handler on_setup;
call_handler on_render;
string compiler_messages;
time_t last_compiled;
~SharedUnit()
{
if(so_handle)
{
dlclose(so_handle);
}
}
};
#include "dtree.h" #include "dtree.h"
+14 -4
View File
@@ -3,9 +3,17 @@
#include "datastructures.h" #include "datastructures.h"
#include "sys.h" #include "sys.h"
#include "time.h" #include "time.h"
#include "uri.h"
struct FastCGIRequest { struct ServerState {
std::map<string, SharedUnit*> units;
ServerSettings config;
} server_state;
struct Request {
ServerState* server_state;
StringMap params; StringMap params;
StringMap get; StringMap get;
@@ -29,13 +37,15 @@ struct FastCGIRequest {
}; };
typedef FastCGIRequest Request; typedef Request FastCGIRequest;
Request* context; Request* context;
#include "uri.h"
#include "compiler.h"
extern "C" void set_current_request(Request* _request) extern "C" void set_current_request(Request* _request)
{ {
context = _request; context = _request;
} }
#include "compiler.h"
+1 -1
View File
@@ -177,7 +177,7 @@ struct URI {
{ {
nibble("=\"", field); nibble("=\"", field);
UploadedFile f; UploadedFile f;
f.tmp_name = Config.TMP_UPLOAD + to_string(rand()); f.tmp_name = context->server_state->config.TMP_UPLOAD + to_string(rand());
f.file_name = nibble("\"", field); f.file_name = nibble("\"", field);
string bin = field.substr(4, field.length()-6); string bin = field.substr(4, field.length()-6);
f.size = bin.length(); f.size = bin.length();
+15 -7
View File
@@ -38,9 +38,11 @@ int handle_complete(FastCGIRequest& request) {
// The event handler can also be a class member function. This // The event handler can also be a class member function. This
// event occurs when the parameters and standard input streams are // event occurs when the parameters and standard input streams are
// both closed, and thus the request is complete. // both closed, and thus the request is complete.
context = &request;
request.server_state = &server_state;
request.time_start = microtime(); request.time_start = microtime();
request.header["Content-Type"] = Config.CONTENT_TYPE; request.header["Content-Type"] = context->server_state->config.CONTENT_TYPE;
request.get = URI::parse_query(request.params["QUERY_STRING"]); request.get = URI::parse_query(request.params["QUERY_STRING"]);
string ct_info = request.params["CONTENT_TYPE"]; string ct_info = request.params["CONTENT_TYPE"];
@@ -59,7 +61,7 @@ int handle_complete(FastCGIRequest& request) {
} }
} }
invoke(&request, request.params["SCRIPT_FILENAME"]); invoke(request.params["SCRIPT_FILENAME"]);
string headers = var_dump(request.header, "", "\r\n") + "\r\n"; string headers = var_dump(request.header, "", "\r\n") + "\r\n";
request.out = headers + request.out; request.out = headers + request.out;
@@ -87,11 +89,17 @@ int main(int argc, char** argv)
server.data_handler(&handle_data); server.data_handler(&handle_data);
server.complete_handler(&handle_complete); server.complete_handler(&handle_complete);
if(Config.LISTEN_PORT) if(server_state.config.COMPILER_SYS_PATH == "")
server.listen(Config.LISTEN_PORT); server_state.config.COMPILER_SYS_PATH = get_cwd();
if(Config.SOCKET_PATH != "") server_state.config.BIN_DIRECTORY =
server.listen(Config.SOCKET_PATH); server_state.config.COMPILER_SYS_PATH + "/" + server_state.config.BIN_DIRECTORY;
chmod(Config.SOCKET_PATH.c_str(), S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); server_state.config.COMPILE_SCRIPT =
server_state.config.COMPILER_SYS_PATH + "/" + server_state.config.COMPILE_SCRIPT;
if(server_state.config.LISTEN_PORT)
server.listen(server_state.config.LISTEN_PORT);
if(server_state.config.SOCKET_PATH != "")
server.listen(server_state.config.SOCKET_PATH);
chmod(server_state.config.SOCKET_PATH.c_str(), S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
//server.process(100); //server.process(100);
//server.process(); //server.process();
+2 -1
View File
@@ -4,7 +4,7 @@ RENDER()
{ {
<html> <html>
<link rel="stylesheet" href='style.css?v=1'></link> <link rel="stylesheet" href='style.css'></link>
<h1> <h1>
<a href="index.uce">UCE Test</a>: <a href="index.uce">UCE Test</a>:
Index Index
@@ -13,6 +13,7 @@ RENDER()
<li><a href="hello.uce">Hello</a></li> <li><a href="hello.uce">Hello</a></li>
<li><a href="post.uce">Form Post</a></li> <li><a href="post.uce">Form Post</a></li>
<li><a href="post-multipart.uce">Form Multipart Post</a></li> <li><a href="post-multipart.uce">Form Multipart Post</a></li>
<li><a href="working-dir.uce">Working Directory</a></li>
</ul> </ul>
<pre><?= var_dump(context->params) ?></pre> <pre><?= var_dump(context->params) ?></pre>
</html> </html>
+2 -1
View File
@@ -65,7 +65,8 @@ textarea {
pre { pre {
height: 20%; height: 20%;
overflow: auto; overflow: auto;
padding. 8px; padding: 8px;
border: 2px solid rgba(0,0,0,0.2); border: 2px solid rgba(0,0,0,0.2);
background: rgba(100,100,100,0.15); background: rgba(100,100,100,0.15);
font-family: monospace;
} }
+6
View File
@@ -0,0 +1,6 @@
RENDER()
{
echo("Sub-Invoke Working dir: " + get_cwd() + "\n");
}
+19
View File
@@ -0,0 +1,19 @@
RENDER()
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Working Directory
</h1>
<pre><?
echo("Base WD: " + get_cwd() + "\n");
invoke("/Code/uce.openfu.com/uce/test/test2/working-dir-test.uce");
?></pre>
<pre><?= var_dump(context->params) ?></pre>
</>
}
-1
View File
@@ -16,7 +16,6 @@ Bugs
================================= =================================
- shell_escape() - shell_escape()
- include path - include path
- current request working directory
- preprocessor - preprocessor
- nested tags - nested tags