diff options
-rw-r--r-- | src/afb-hreq.c | 40 | ||||
-rw-r--r-- | src/afb-hsrv.c | 7 | ||||
-rw-r--r-- | src/afb-websock.c | 13 | ||||
-rw-r--r-- | src/websock.c | 11 | ||||
-rw-r--r-- | src/websock.h | 1 | ||||
-rw-r--r-- | test/websock.html | 62 | ||||
-rw-r--r-- | test/websock.js | 111 |
7 files changed, 188 insertions, 57 deletions
diff --git a/src/afb-hreq.c b/src/afb-hreq.c index ece9b399..474b90e8 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -184,7 +184,34 @@ static const char *magic_mimetype_fd(int fd) #endif - +static const char *mimetype_fd_name(int fd, const char *filename) +{ + const char *result = NULL; + +#if defined(INFER_EXTENSION) + const char *extension = strrchr(filename, '.'); + if (extension) { + static const char *const known[][2] = { + { ".js", "text/javascript" }, + { ".html", "text/html" }, + { NULL, NULL } + }; + int i = 0; + while (known[i][0]) { + if (!strcasecmp(extension, known[i][0])) { + result = known[i][1]; + break; + } + i++; + } + } +#endif +#if defined(USE_MAGIC_MIME_TYPE) + if (result == NULL) + result = magic_mimetype_fd(fd); +#endif + return result; +} void afb_hreq_free(struct afb_hreq *hreq) { @@ -257,6 +284,7 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f char etag[1 + 2 * sizeof(int)]; const char *inm; struct MHD_Response *response; + const char *mimetype; /* Opens the file or directory */ if (filename[0]) { @@ -336,14 +364,10 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f response = MHD_create_response_from_fd((size_t) st.st_size, fd); status = MHD_HTTP_OK; -#if defined(USE_MAGIC_MIME_TYPE) /* set the type */ - { - const char *mimetype = magic_mimetype_fd(fd); - if (mimetype != NULL) - MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, mimetype); - } -#endif + mimetype = mimetype_fd_name(fd, filename); + if (mimetype != NULL) + MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, mimetype); } /* fills the value and send */ diff --git a/src/afb-hsrv.c b/src/afb-hsrv.c index 64cea9d5..977aea63 100644 --- a/src/afb-hsrv.c +++ b/src/afb-hsrv.c @@ -152,11 +152,8 @@ static int afb_hreq_websocket_switch(struct afb_hreq *hreq, void *data) if (!later) { struct afb_websock *ws = afb_websock_create(hreq); - if (ws == NULL) { - /* TODO */ - } else { - /* TODO */ - } + if (ws != NULL) + hreq->upgrade = 1; } return 1; } diff --git a/src/afb-websock.c b/src/afb-websock.c index dab4aa09..797724ce 100644 --- a/src/afb-websock.c +++ b/src/afb-websock.c @@ -220,15 +220,21 @@ static const struct afb_req_itf wsreq_itf = { struct afb_websock *afb_websock_create(struct afb_hreq *hreq) { + int fd; struct afb_websock *result; + fd = MHD_get_connection_info(hreq->connection, + MHD_CONNECTION_INFO_CONNECTION_FD)->connect_fd; + fd = dup(fd); + if (fd < 0) + return NULL; + result = malloc(sizeof * result); if (result == NULL) goto error; result->connection = hreq->connection; - result->fd = MHD_get_connection_info(hreq->connection, - MHD_CONNECTION_INFO_CONNECTION_FD)->connect_fd; + result->fd = fd; result->context = ctxClientGet(afb_hreq_context(hreq)); if (result->context == NULL) goto error2; @@ -255,6 +261,7 @@ error3: error2: free(result); error: + close(fd); return NULL; } @@ -346,7 +353,7 @@ static int aws_handle_json(struct afb_websock *aws, struct json_object *obj) goto error; verb = &api[lenapi+1]; for (lenverb = 0 ; verb[lenverb] && verb[lenverb] != '/' ; lenverb++); - if (!lenverb || !verb[lenverb]) + if (!lenverb || verb[lenverb]) goto error; /* allocates the request data */ diff --git a/src/websock.c b/src/websock.c index 41e47a0a..22e91be9 100644 --- a/src/websock.c +++ b/src/websock.c @@ -170,12 +170,12 @@ void websock_pong(struct websock *ws) void websock_text(struct websock *ws, const char *text, size_t length) { - websock_send(ws, OPCODE_TEXT, NULL, 0); + websock_send(ws, OPCODE_TEXT, text, length); } void websock_binary(struct websock *ws, const void *data, size_t length) { - websock_send(ws, OPCODE_BINARY, NULL, 0); + websock_send(ws, OPCODE_BINARY, data, length); } static int read_header(struct websock *ws) @@ -192,7 +192,7 @@ static int read_header(struct websock *ws) int websock_dispatch(struct websock *ws) { - loop: +loop: switch (ws->state) { case STATE_INIT: ws->lenhead = 0; @@ -201,7 +201,7 @@ int websock_dispatch(struct websock *ws) case STATE_START: /* read the header */ - if (!read_header(ws)) + if (read_header(ws)) return -1; else if (ws->lenhead < ws->szhead) return 0; @@ -262,7 +262,7 @@ int websock_dispatch(struct websock *ws) case STATE_LENGTH: /* continue to read the header */ - if (!read_header(ws)) + if (read_header(ws)) return -1; else if (ws->lenhead < ws->szhead) return 0; @@ -409,6 +409,7 @@ struct websock *websock_create(const struct websock_itf *itf, void *closure) if (result) { result->itf = itf; result->closure = closure; + result->maxlength = 65000; } return result; } diff --git a/src/websock.h b/src/websock.h index b67f36e1..235f9910 100644 --- a/src/websock.h +++ b/src/websock.h @@ -63,3 +63,4 @@ int websock_dispatch(struct websock *ws); struct websock *websock_create(const struct websock_itf *itf, void *closure); void websock_destroy(struct websock *ws); + diff --git a/test/websock.html b/test/websock.html index 1db33b2a..dd38e74a 100644 --- a/test/websock.html +++ b/test/websock.html @@ -1,47 +1,37 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> - <head> +<head> <title>WebSocket Echo</title> + <script type="text/javascript" src="websock.js"></script> <script type="text/javascript"> - <!-- - var ws; + var ws; - if ((typeof(WebSocket) == 'undefined') && - (typeof(MozWebSocket) != 'undefined')) { - WebSocket = MozWebSocket; - } - - function init() { - ws = new WebSocket("ws://localhost:1234/api/"); - ws.onopen = function(event) { - document.getElementById("main").style.visibility = "visible"; - document.getElementById("connected").innerHTML = "Connected to WebSocket server"; - }; - ws.onmessage = function(event) { - document.getElementById("output").innerHTML = event.data; - }; - ws.onerror = function(event) { alert("Received error"); }; - ws.onclose = function(event) { - ws = null; - document.getElementById("main").style.visibility = "hidden"; - document.getElementById("connected").innerHTML = "Connection Closed"; - } - } - - function send(message) { - if (ws) { - ws.send(message); - } - } - // --> + function onopen() { + document.getElementById("main").style.visibility = "visible"; + document.getElementById("connected").innerHTML = "Connected to WebSocket server"; + } + function onabort() { + document.getElementById("main").style.visibility = "hidden"; + document.getElementById("connected").innerHTML = "Connected Closed"; + } + function init() { + ws = new AfbWsItf("api", onopen, onabort, new AfbCtxItf("hello")); + } + function replyok(obj) { + document.getElementById("output").innerHTML = "OK: "+JSON.stringify(obj); + } + function replyerr(obj) { + document.getElementById("output").innerHTML = "ERROR: "+JSON.stringify(obj); + } + function send(message) { + ws.call("hello", "ping", {data:message}, replyok, replyerr); + } </script> - </head> - <body onload="init();"> + +<body onload="init();"> <h1>WebSocket Echo</h1> <div id="connected">Not Connected</div> <div id="main" style="visibility:hidden"> Enter Message: <input type="text" name="message" value="" size="80" onchange="send(this.value)"/><br/> Server says... <div id="output"></div> </div> - </body> -</html> + diff --git a/test/websock.js b/test/websock.js new file mode 100644 index 00000000..1ba136b4 --- /dev/null +++ b/test/websock.js @@ -0,0 +1,111 @@ + +AfbCtxItf = (function(){ + + var UUID = undefined; + var TOKEN = undefined; + + function AfbCtxItf(token, uuid) { + this.token = token; + this.uuid = uuid; + } + + AfbCtxItf.prototype = { + get token() {return TOKEN;}, + set token(tok) {if(tok) TOKEN=tok;}, + get uuid() {return UUID;}, + set uuid(id) {if(id) UUID=id;} + }; + + return AfbCtxItf; +})(); + + +AfbWsItf = (function(){ + + var CALL = 2; + var RETOK = 3; + var RETERR = 4; + + function AfbWsItf(base, onopen, onabort, ctx) { + var wl = window.location; + var u = "ws://"+wl.host+"/"+base; + this.ws = new (WebSocket || MozWebSocket)(u, [ "afb1", "afb2" ]); + this.pendings = {}; + this.counter = 0; + this.ctx = ctx || new AfbCtxItf(); + this.ws.onopen = onopen.bind(this); + this.ws.onerror = onerror.bind(this); + this.ws.onclose = onclose.bind(this); + this.ws.onmessage = onmessage.bind(this); + this.onopen = onopen; + this.onabort = onabort; + } + + function onerror(event) { + var f = this.onabort; + if (f) { + delete this.onopen; + delete this.onabort; + f && f(this); + } + this.onerror && this.onerror(this); + } + + function onopen(event) { + var f = this.onopen; + delete this.onopen; + delete this.onabort; + f && f(this); + } + + function onclose(event) { + for (var id in this.pendings) { + var ferr = this.pendings[id].onerror; + ferr && ferr(null, this); + } + this.pendings = {}; + this.onclose && this.onclose(); + } + + function onmessage(event) { + var obj = JSON.parse(event.data); + var code = obj[0]; + var id = obj[1]; + var ans = obj[2]; + this.ctx.token = obj[3]; + var pend; + if (id && id in this.pendings) { + pend = this.pendings[id]; + delete this.pendings[id]; + } + switch (code) { + case RETOK: + pend && pend.onsuccess && pend.onsuccess(ans, this); + break; + case RETERR: + default: + pend && pend.onerror && pend.onerror(ans, this); + break; + } + } + + function close() { + this.ws.close(); + } + + function call(api, verb, request, onsuccess, onerror) { + var id = String(++this.counter); + this.pendings[id] = { onsuccess: onsuccess, onerror: onerror }; + var arr = [CALL, id, api+"/"+verb, request ]; + if (this.ctx.token) arr.push(this.ctx.token); + this.ws.send(JSON.stringify(arr)); + } + + AfbWsItf.prototype = { + close: close, + call: call + }; + + return AfbWsItf; +})(); + |