[SCM] Lisaac compiler branch, master, updated. lisaac-0.12-622-g522bd91
ontologiae
ontologiae at ordinateur-de-ontologiae-3.local
Tue Mar 30 17:28:34 UTC 2010
The following commit has been merged in the master branch:
commit 522bd91f9a3dbccd8dc20d8ca6d8bc607209a484
Author: ontologiae <ontologiae at ordinateur-de-ontologiae-3.local>
Date: Tue Mar 30 19:28:17 2010 +0200
Http server update
diff --git a/lib/standard/http/http_server.li b/lib/standard/http/http_server.li
index 346284c..85c4fad 100644
--- a/lib/standard/http/http_server.li
+++ b/lib/standard/http/http_server.li
@@ -19,16 +19,16 @@
// http://isaacproject.u-strasbg.fr/ //
///////////////////////////////////////////////////////////////////////////////
Section Header
-
+
+ name := HTTP_SERVER;
- copyright := "2003-2010 Sonntag Benoit";
- author := "Sonntag Benoit (sonntag at icps.u-strasbg.fr)";
- comment := "The main prototype";
-
+
- external :=
-`
+`
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
@@ -36,49 +36,64 @@ Section Header
#include <netinet/in.h>
#include <netdb.h>
-#include <sys/socket.h>
+#include <sys/socket.h>
struct sockaddr_in address;
`;
-
+
Section Inherit
- parent_object:OBJECT := OBJECT;
-
+
Section Private
-
+
//
// Parameters
//
-
+
+ h_socket:INTEGER;
-
+
- queue_size:INTEGER := 5;
-
+
- buffer:STRING := STRING.create 1024;
+ - tmp_header : HTTP_HEADER := HTTP_HEADER.create;
+
+ - post_block_list : HASHED_DICTIONARY(STRING,{HASHED_DICTIONARY(STRING,STRING);STRING}) := HASHED_DICTIONARY(STRING,{HASHED_DICTIONARY(STRING,STRING);STRING}).create;
+ // HASHED_DICTIONARY(
+ // STRING : post method name ,
+ //{HASHED_DICTIONARY(STRING,STRING);STRING} : Block with post method parameters arguments, and result
+ // )
+ //TODO : gestion des cookies !
+
//
// Error.
//
-
+
- socket_error:INTEGER := -1;
-
+
- error msg:ABSTRACT_STRING <-
(
msg.print; '\n'.print;
die_with_code 1;
);
-
+
Section Public
-
+
- log:STRING := STRING.create 1024;
+ - debug_flag : BOOLEAN;
- - listen port:INTEGER do act:{} <-
+ - set_debug_flag b : BOOLEAN <-
+ (
+ debug_flag := b;
+ );
+
+ - listen port:INTEGER action act:{} <-
( + h_server_socket,error,tmp:INTEGER;
+ n_address_size:INTEGER;
+ storage:NATIVE_ARRAY(CHARACTER);
-
- n_address_size := `sizeof(address)`:INTEGER;
+
+ n_address_size := `sizeof(address)`:INTEGER;
h_server_socket := `socket(AF_INET,SOCK_STREAM,0)`:INTEGER;
(h_server_socket = socket_error).if {
error "Error : create socket!";
@@ -88,100 +103,112 @@ Section Public
address.sin_port=htons(@port);
address.sin_family=AF_INET;
`;
-
+
error := `bind(@h_server_socket,(struct sockaddr*)&address,sizeof(address))`:INTEGER;
(error = socket_error).if {
error "Error : Bind()";
};
- `getsockname(@h_server_socket, (struct sockaddr *) &address,(socklen_t *)&@n_address_size)`;
-
- log.append "Opened socket as fd (";
- h_server_socket.append_in log;
- log.append ") on port (";
- `ntohs(address.sin_port)`:INTEGER.append_in log;
- log.append ") for stream i/o\n";
-
+ `getsockname(@h_server_socket, (struct sockaddr *) &address,(socklen_t *)&@n_address_size)`;
+ debug_flag.if {
+ log.append "Opened socket as fd (";
+ h_server_socket.append_in log;
+ log.append ") on port (";
+ `ntohs(address.sin_port)`:INTEGER.append_in log;
+ log.append ") for stream i/o\n";
+ };
+
/*
"Server\
\\nsin_family = ".print;
`address.sin_family`:INTEGER.print;
"\nsin_addr.s_addr = ".print;
- `address.sin_addr.s_addr`:INTEGER.print;
+ `address.sin_addr.s_addr`:INTEGER.print;
"\nsin_port = ".print;
`ntohs(address.sin_port)`:INTEGER.print;
- '\n'.print;
+ '\n'.print;
"\nMaking a listen queue of ".print;
queue_size.print;
" elements".print;
*/
-
- // establish listen queue
+
+ // establish listen queue
tmp := queue_size;
(`listen(@h_server_socket, at tmp)`:INTEGER = socket_error).if {
error "Could not listen";
};
{
- log.append "Waiting for a connection\n";
- // get the connected socket
+ debug_flag.if {
+ log.append "Waiting for a connection\n";
+ };
+ // get the connected socket
h_socket := `accept(@h_server_socket,(struct sockaddr*)&address,(socklen_t *)&@n_address_size)`:INTEGER;
- log.append "Got a connection\n";
- act.value;
+ debug_flag.if {
+ log.append "Got a connection\n";
+ };
+
+ // We have a connection, so act is valued
+ act.value;
}.endless_loop;
);
-
+
- send buf:ABSTRACT_STRING <-
( + storage:NATIVE_ARRAY(CHARACTER);
+ loc_h_socket,count:INTEGER;
-
- log.append "send buffer\n";
+ debug_flag.if {
+ log.append "send buffer\n";
+ };
storage := buf.to_external;
count := buf.count + 1;
loc_h_socket := h_socket;
`write(@loc_h_socket, at storage, at count)`;
);
-
+
- receive buf:STRING <-
// BSBS: Plutot faire un append que un copy
( + loc_h_socket,capacity:INTEGER;
+ storage:NATIVE_ARRAY(CHARACTER);
-
- log.append "receive buffer\n";
+
+ debug_flag.if {
+ log.append "receive buffer\n";
+ };
storage := buf.to_external;
capacity := buf.capacity;
loc_h_socket := h_socket;
`read(@loc_h_socket, at storage, at capacity)`;
buf.from_external storage;
- );
-
+ );
+
- close <-
- // close socket
+ // close socket
( + loc_h_socket:INTEGER;
- log.append "Closing the socket\n";
+ debug_flag.if {
+ log.append "Closing the socket\n";
+ };
loc_h_socket := h_socket;
(`close(@loc_h_socket)`:INTEGER = socket_error).if {
error "Could not close socket";
- };
- );
-
+ };
+ );
+
- convert buf:STRING to_dictionary dico:HASHED_DICTIONARY(STRING,STRING) <-
( + idx_start,idx_end,idx:INTEGER;
+ key,value:STRING;
+ sep:CHARACTER;
-
+
sep := ' ';
idx_start := buf.lower;
{
- idx_end := buf.index_of '\n' since idx_start;
+ idx_end := buf.index_of '\n' since idx_start;
idx := buf.index_of sep since idx_start;
(idx < idx_end).if {
- sep := ':';
+ sep := ':';
key := buf.substring idx_start to (idx-1);
- {buf.item (idx + 1) = ' '}.while_do {
- idx := idx + 1;
- };
- {buf.item (idx_end - 1) <= ' '}.while_do {
- idx_end := idx_end - 1;
+ {buf.item (idx + 1) = ' '}.while_do {
+ idx := idx + 1;
};
+ {buf.item (idx_end - 1) <= ' '}.while_do {
+ idx_end := idx_end - 1;
+ };
value := buf.substring (idx+1) to (idx_end-1);
dico.put value to key;
};
@@ -189,13 +216,65 @@ Section Public
}.do_while {idx_end <= buf.count};
);
+ - convert buf : STRING to_http_header header : HTTP_HEADER <-
+ ( + idx_start,idx_end,idx:INTEGER;
+ + key,value:STRING;
+ + sep:CHARACTER;
+
+ sep := ' ';
+ idx_start := buf.lower;
+ {
+ idx_end := buf.index_of '\n' since idx_start;
+ idx := buf.index_of sep since idx_start;
+ (idx < idx_end).if {
+ sep := ':';
+ key := buf.substring idx_start to (idx-1);
+ {buf.item (idx + 1) = ' '}.while_do {
+ idx := idx + 1;
+ };
+ {buf.item (idx_end - 1) <= ' '}.while_do {
+ idx_end := idx_end - 1;
+ };
+ value := buf.substring (idx+1) to (idx_end-1);
+ //dico.put value to key;
+
+ //TODO : Virer le http/1.1 à la fin de l'uri !
+
+ key.when "GET" then { header.set_verb "GET"; header.set_uri value;}
+ .when "POST" then { header.set_verb "POST"; header.set_uri value;}
+ .when "PUT" then { header.set_verb "PUT"; header.set_uri value;}
+ .when "DELETE" then { header.set_verb "DELETE"; header.set_uri value;}
+ .when "Host" then { header.set_host value;}
+ .when "User-Agent" then { header.set_user_agent value;}
+ .when "Accept" then { header.set_accept_mime value;}
+ .when "Accept-Encoding" then { header.set_accept_encoding value;}
+ .when "Accept-Charset" then { header.set_accept_charset value;}
+ .when "Keep-Alive" then { header.set_keep_alive value;}
+ .when "Connection" then { header.set_connection value;}
+ .when "Cookie" then { header.set_cookie value;}
+ .case_else { //("Unknown key :"+key).println;
+ };
+
+ debug_flag.if {
+ //"clé".count.println;
+ //key.count.println;
+ //("clé"+key).count.println;
+ //("Key="+key + " Value=".to_string+value).println;
+ };
+ };
+ idx_start := idx_end + 1;
+ }.do_while {idx_end <= buf.count};
+ );
+
+
+
//
// High level.
//
-
+
- send buf:ABSTRACT_STRING type_mime type:ABSTRACT_STRING <-
(
- buffer.copy
+ buffer.copy
"HTTP/1.1 200 OK\n\
\Date: ";
SYSTEM.get_current_date.append_in buffer;
@@ -206,7 +285,7 @@ Section Public
\Content-Length: ";
buf.count.append_in buffer;
buffer.append "\n\
- \Connection: close\n\
+ \Connection: close\n\
\Content-type: ";
buffer.append type;
buffer.append "\n\n";
@@ -215,3 +294,114 @@ Section Public
buffer.append "\n\n";
send buffer;
);
+
+
+ //
+ // Receiver manager
+ //
+
+ - receive_get_do blc : {HTTP_HEADER;} <-
+ ( + my_buf : STRING;
+ my_buf := STRING.create 512;
+ receive my_buf;
+ convert my_buf to_http_header tmp_header;
+ (tmp_header.verb ~= "GET").if {blc.value tmp_header;};
+ );
+
+ - receive_do_get get : {HTTP_HEADER;} post post : {HTTP_HEADER;} put put : {HTTP_HEADER;} delete del : {HTTP_HEADER;} <-
+ ( + my_buf : STRING;
+ my_buf := STRING.create 512;
+ receive my_buf;
+ convert my_buf to_http_header tmp_header;
+ tmp_header.verb.when "GET" then {get.value tmp_header;}
+ .when "POST" then {post.value tmp_header;}
+ .when "PUT" then {put.value tmp_header;}
+ .when "DELETE" then {del.value tmp_header;};
+ );
+
+
+
+
+ - receive_do_get get : {HTTP_HEADER;} post post : {HTTP_HEADER;} <-
+ ( + my_buf : STRING;
+ my_buf := STRING.create 512;
+ receive my_buf;
+ convert my_buf to_http_header tmp_header;
+ tmp_header.verb.when "GET" then {get.value tmp_header;}
+ .when "POST" then {post.value tmp_header;};
+ );
+
+
+ //
+ // Tools
+ //
+
+
+
+ - get_file uri : ABSTRACT_STRING : STRING <-
+ ( + filename : ABSTRACT_STRING;
+ filename := uri.substring 2 to (uri.count -1);
+ FS_MIN.open_as_string filename
+ );
+
+ // Pour le post : on reçoit une hash de clé/valeur ainsi qu'un nom de post : on regarde si on a un {HASH(STR,STR);STR} dans le HASH(STR, {HASH(STR,STR);STR}) et on l'exécute
+
+
+ - decode_parameters param : STRING : HASHED_DICTIONARY(STRING,STRING) <-
+ ( + res : HASHED_DICTIONARY(STRING,STRING);
+ + params : ARRAY(STRING);
+ res := HASHED_DICTIONARY(STRING,STRING).create;
+ // On cherche le premier ?
+ // Ensuite on split avec le &
+ // Chaque morceaux est splité avec le =
+
+ // Algo pas très perf...
+ params := (param.substring (param.substring_index ("?",1)) to (param.count - 1)).split_str "&";
+ params.foreach { e : STRING;
+ res.put (e.substring (e.substring_index ("=",0) - 1) to (e.count-1)) to (e.substring 0 to (e.substring_index ("=",0) - 1));
+ };
+ res
+ );
+
+
+ //
+ // POST manager
+ //
+
+
+ // Un pattern d'optim : à l'usage, le serveur recevra des requetes post et ira switcher sur le block correspondant.
+ // Au lieu d'utiliser l'infra de HASHED_DICTIONARY , peut être qu'il y aurait moyen de fire un bête switch sur le nom ?
+ - add_post name : ABSTRACT_STRING action blc : {HASHED_DICTIONARY(STRING,STRING); STRING} <-
+ (
+ post_block_list.put blc to name;
+ );
+
+
+
+
+ //
+ // Web Server
+ //
+
+
+ - start_server_on_port port : INTEGER <-
+ (
+ listen port action {
+ receive_get_do { h : HTTP_HEADER;
+ //TODO : Virer ce hack !!
+ s := h.uri;
+ s.replace_all "HTTP/1.1" with "";
+ ("Request with URI : " +s).printline;
+ my_buf := get_file s;
+ send my_buf type_mime "text/html";
+ } post { h : HTTP_HEADER;
+ //TODO : Virer ce hack !!
+ s := h.uri;
+ s.replace_all "HTTP/1.1" with "";
+ ("POST with URI : " +s).printline
+ // Decoupage des paramètres
+
+ };
+ close;
+ };
+ );
--
Lisaac compiler
More information about the Lisaac-commits
mailing list