Skip to content

Instantly share code, notes, and snippets.

@sustrik
Created April 1, 2018 20:59
Show Gist options
  • Save sustrik/cfa658c749079de0eb4353957b63fb8d to your computer and use it in GitHub Desktop.
Save sustrik/cfa658c749079de0eb4353957b63fb8d to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "../libdill.h"
const char *html =
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
"<script>\n"
"function start() {\n"
" console.log('Boo!')\n"
" var s = new WebSocket('ws://localhost:5555')\n"
" s.onmessage = function (event) {\n"
" console.log(event.data);\n"
" document.getElementById('text').value = event.data;\n"
" }\n"
" console.log('Hoo!')\n"
"}\n"
"</script>\n"
"</head>\n"
"<body onload='start();'>\n"
"<input type='text' id='text' style='border:none'/>\n"
"</body>";
coroutine void worker(int s) {
s = http_attach(s);
assert(s >= 0);
char command[32];
char resource[32];
int rc = http_recvrequest(s, command, sizeof(command),
resource, sizeof(resource), -1);
assert(rc == 0);
int websocket = 0;
char response_key[WS_KEY_SIZE];
while(1) {
char name[256];
char value[256];
rc = http_recvfield(s, name, sizeof(name), value, sizeof(value), -1);
if(rc < 0 && errno == EPIPE) break;
assert(rc == 0);
if(strcasecmp(name, "Upgrade") == 0 &&
strcasecmp(value, "websocket") == 0) {
websocket = 1;
}
if(strcasecmp(name, "Sec-WebSocket-Key") == 0) {
rc = ws_response_key(value, response_key);
assert(rc == 0);
}
}
if(!websocket) {
rc = http_sendstatus(s, 200, "OK", -1);
assert(rc == 0);
s = http_detach(s, -1);
assert(s >= 0);
rc = bsend(s, html, strlen(html), -1);
assert(rc == 0);
rc = tcp_close(s, -1);
return;
}
rc = http_sendstatus(s, 101, "Switching Protocols", -1);
assert(rc == 0);
rc = http_sendfield(s, "Upgrade", "websocket", -1);
assert(rc == 0);
rc = http_sendfield(s, "Connection", "Upgrade", -1);
assert(rc == 0);
rc = http_sendfield(s, "Sec-WebSocket-Accept", response_key, -1);
assert(rc == 0);
s = http_detach(s, -1);
assert(s >= 0);
s = ws_attach_server(s, WS_NOHTTP | WS_TEXT, NULL, 0, NULL, 0, -1);
assert(s >= 0);
int i;
for(i = 9; i >= 0; --i) {
char c = '0' + i;
rc = msend(s, &c, 1, -1);
assert(rc == 0);
rc = msleep(now() + 1000);
assert(rc == 0);
}
rc = msend(s, "Boom!", 5, -1);
assert(rc == 0);
}
int main(void) {
struct ipaddr addr;
int rc = ipaddr_local(&addr, NULL, 5555, 0);
assert(rc == 0);
int ls = tcp_listen(&addr, 10);
assert(ls >= 0);
int workers = bundle();
assert(workers >= 0);
while(1) {
int s = tcp_accept(ls, NULL, -1);
assert(s >= 0);
rc = bundle_go(workers, worker(s));
assert(rc == 0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment