Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4eef815

Browse filesBrowse files
committed
Add support for lightweight webserver (ala Flask for python)
needs doco for the prerequisites (will be on wiki)
1 parent f5e3adf commit 4eef815
Copy full SHA for 4eef815

File tree

7 files changed

+266
-0
lines changed
Filter options

7 files changed

+266
-0
lines changed

‎examples/webserver/make.m

Copy file name to clipboard
+35Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
% make.m
2+
3+
cfg = coder.config('exe')
4+
cfg.TargetLang = 'C';
5+
cfg.MultiInstanceCode = true;
6+
7+
cfg.GenerateReport = true;
8+
%cfg.LaunchReport = true;
9+
10+
% build options
11+
cfg.GenerateExampleMain = 'DoNotGenerate';
12+
%cfg.GenCodeOnly = true;
13+
14+
cfg.GenerateComments = true;
15+
cfg.MATLABSourceComments = true; % lots of comments
16+
cfg.PreserveVariableNames = 'UserNames';
17+
cfg.CustomLibrary = '../../contrib/lib/libmicrohttpd.a ../../contrib/lib/libctemplate.a';
18+
cfg.CustomSource = 'main.c stl.c httpd.c'
19+
% want to include some files from this directory, but this doesnt work??
20+
21+
cfg.CustomInclude = '../../contrib/include ../../stl'
22+
cfg.BuildConfiguration = 'Faster Builds';
23+
%cfg.BuildConfiguration = 'Debug';
24+
25+
% would be nice if could set make -j to get some parallel building
26+
% happening.
27+
28+
29+
%{
30+
cfg.InlineThreshold = 0; % tone down the aggressive inlining
31+
codegen user.m thread1.m -args int32(0) thread2.m thread3.m -O disable:inline -config cfg
32+
%}
33+
34+
codegen user.m myserver.m -config cfg
35+

‎examples/webserver/myserver.m

Copy file name to clipboard
+15Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function myserver() % called from C
2+
3+
switch (webserver.url())
4+
case '/'
5+
stllog('hello from /')
6+
webserver.html('home here');
7+
case '/bob'
8+
%webserver.template('templates/home.html', values);
9+
stllog('bob');
10+
webserver.html('<html><body>hello <b>from</b> /bob</body></html>');
11+
case '/alice'
12+
vals.a = 1;
13+
vals.b = 2;
14+
webserver.template('templates/alice.html', vals);
15+
end
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<html>
2+
<body>
3+
<p>This is a test page</p>
4+
<p>a = <TMPL_VAR name="a"></p>
5+
<p>b = <TMPL_VAR name="b"></p>
6+
</body>
7+
</html>

‎examples/webserver/user.m

Copy file name to clipboard
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
function user() %#codegen
2+
3+
stllog('user program starts');
4+
5+
webserver(8080, 'myserver');
6+
7+
sleep(60);
8+
end

‎stl/httpd.c

Copy file name to clipboard
+145Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#include <sys/types.h>
2+
#ifndef _WIN32
3+
#include <sys/select.h>
4+
#include <sys/socket.h>
5+
#else
6+
#include <winsock2.h>
7+
#endif
8+
#include <microhttpd.h>
9+
#include <stdio.h>
10+
11+
#include "httpd.h"
12+
#include "ctemplate.h"
13+
#include "stl.h"
14+
#include <string.h>
15+
#include <errno.h>
16+
17+
static struct MHD_Daemon *daemon;
18+
static void (*request_matlab_callback)(void);
19+
TMPL_varlist *web_varlist;
20+
21+
static int
22+
print_out_key (void *cls, enum MHD_ValueKind kind, const char *key,
23+
const char *value)
24+
{
25+
(void)cls; /* Unused. Silent compiler warning. */
26+
(void)kind; /* Unused. Silent compiler warning. */
27+
printf ("%s: %s\n", key, value);
28+
return MHD_YES;
29+
}
30+
31+
static struct MHD_Connection *req_connection;
32+
static int req_response_status;
33+
static char *req_url;
34+
static char *req_method;
35+
36+
static int
37+
page_request (void *cls, struct MHD_Connection *connection,
38+
const char *url, const char *method,
39+
const char *version, const char *upload_data,
40+
size_t *upload_data_size, void **con_cls)
41+
{
42+
(void)cls; /* Unused. Silent compiler warning. */
43+
(void)version; /* Unused. Silent compiler warning. */
44+
(void)upload_data; /* Unused. Silent compiler warning. */
45+
(void)upload_data_size; /* Unused. Silent compiler warning. */
46+
(void)con_cls; /* Unused. Silent compiler warning. */
47+
/*
48+
printf ("New %s request for %s using version %s\n", method, url, version);
49+
50+
51+
MHD_get_connection_values (connection, MHD_HEADER_KIND, print_out_key,
52+
NULL);
53+
54+
55+
printf("URL %s\n", url);
56+
printf("version %s\n", version);
57+
printf("method %s\n", version);
58+
printf("upload data %s\n", upload_data);
59+
*/
60+
req_connection = connection;
61+
req_url = url;
62+
req_method = method;
63+
64+
web_varlist = NULL; // set the template list to empty
65+
66+
// free up the old list somewhere TMPL_free_varlist(varlist)
67+
68+
/*
69+
MHD_get_connection_values (connection, MHD_GET_ARGUMENT_KIND, print_out_key,
70+
NULL);
71+
*/
72+
req_response_status = MHD_NO;
73+
stl_log("web: %s request for URL %s using %s", method, url, version);
74+
request_matlab_callback();
75+
76+
return req_response_status;
77+
}
78+
79+
void
80+
web_html(char *html)
81+
{
82+
struct MHD_Response *response;
83+
84+
//stl_log("web_html: %s", html);
85+
86+
response = MHD_create_response_from_buffer(strlen(html), html, MHD_RESPMEM_MUST_COPY);
87+
MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html");
88+
req_response_status = MHD_queue_response(req_connection, MHD_HTTP_OK, response);
89+
MHD_destroy_response(response);
90+
}
91+
92+
/**
93+
* Return the URL for this request
94+
*/
95+
void
96+
web_url(char *buf, int buflen)
97+
{
98+
stl_log("web_url: %s", req_url);
99+
strncpy(buf, req_url, buflen);
100+
}
101+
102+
103+
104+
/**
105+
* Set a value for the template processor
106+
*/
107+
void web_setvalue(char *name, char *value)
108+
{
109+
stl_log("web_setvalue: %s %s", name, value);
110+
web_varlist = TMPL_add_var(web_varlist, stl_stralloc(name), stl_stralloc(value), NULL);
111+
}
112+
113+
/**
114+
* Invoke the template processor
115+
*/
116+
void web_template(char *filename)
117+
{
118+
char buffer[BUFSIZ];
119+
FILE *html = fmemopen(buffer, BUFSIZ, "w");
120+
121+
bzero(buffer, BUFSIZ);
122+
stl_log("web_template: %s", filename);
123+
TMPL_write(filename, 0, 0, web_varlist, html, stderr);
124+
stl_log("length %d", strlen(buffer));
125+
126+
web_html(buffer);
127+
}
128+
129+
void
130+
web_start(int32_t port, char *callback)
131+
{
132+
if (daemon)
133+
stl_error("web server already launched");
134+
135+
request_matlab_callback = stl_get_functionptr(callback);
136+
if (request_matlab_callback == NULL)
137+
stl_error("thread named [%s] not found", callback);
138+
139+
daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, port, NULL, NULL,
140+
&page_request, NULL, MHD_OPTION_END);
141+
if (daemon == NULL)
142+
stl_error("web server failed to launch: %s", strerror(errno));
143+
144+
stl_log("web server starting on port %u", port);
145+
}

‎stl/httpd.h

Copy file name to clipboard
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
void web_url(char *buf, int len);
3+
void web_start(int32_t port, char *callback);
4+
void web_html(char *html);
5+
void web_setvalue(char *name, char *value);
6+
void web_template(char *filename);

‎stl/webserver.m

Copy file name to clipboard
+50Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
classdef webserver < handle %#codegen
2+
properties
3+
arg
4+
end
5+
6+
methods(Static)
7+
8+
function obj = webserver(port, callback)
9+
port = int32(port);
10+
coder.cinclude('httpd.h');
11+
coder.ceval('web_start', port, cstring(callback));
12+
end
13+
14+
function u = url()
15+
coder.cinclude('httpd.h');
16+
17+
u = '';
18+
coder.varsize('u');
19+
20+
BUFSIZ = 256;
21+
buf = char(zeros(1,BUFSIZ)); % create a buffer to write into, all nulls
22+
23+
coder.ceval('web_url', coder.wref(buf), BUFSIZ); % evaluate the C function
24+
25+
% find the end of the string, where the first unwritten null is
26+
for i=1:BUFSIZ-1
27+
if buf(i) == 0
28+
% found a null, return variable length array up to here
29+
u = buf(1:i-1);
30+
return;
31+
end
32+
end
33+
end
34+
35+
function html(s)
36+
coder.ceval('web_html', cstring(s));
37+
end
38+
39+
function template(filename, values)
40+
coder.cinclude('httpd.h');
41+
42+
names = fieldnames(values);
43+
for i=1:length(names)
44+
name = names{i};
45+
coder.ceval('web_setvalue', cstring(name), cstring(num2str(values.(name))));
46+
end
47+
coder.ceval('web_template', cstring(filename));
48+
end
49+
end
50+
end

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.