blob: 3f61f0cecffba65b2289b83bf449b48dee741a46 [file] [log] [blame] [raw]
/* -*- mode: c -*- */
#ifndef H_HTTP_WEBSOCKET_TEST_H
#define H_HTTP_WEBSOCKET_TEST_H
#include "bscrypt.h"
#include "websockets.h"
#include <stdio.h>
#include <stdlib.h>
/*****************************
A Websocket echo implementation
Test in browser with:
ws = new WebSocket("ws://localhost:3000"); ws.onmessage = function(e)
{console.log("Got message " + e.data.length + " bytes long"); for(var i = 0; i <
e.data.length ; i += 4) {if (e.data.slice(i, i+4) != "text") {console.log(
"incoming message corrupted? ", e.data.slice(i, i+4) ); return;};}; };
ws.onclose = function(e) {console.log("closed")}; ws.onopen = function(e)
{ws.send("hi");};
str = "text"; function size_test() { if(ws.readyState != 1) return;
if(str.length > 4194304) {console.log("str reached 4MiB!"); str = "test";
return;}; ws.send(str); str = str + str; window.setTimeout(size_test, 150); };
size_test();
*/
static void ws_open(ws_s *ws) {
fprintf(stderr, "Opened a new websocket connection (%p)\n", (void *)ws);
}
static void ws_echo(ws_s *ws, char *data, size_t size, uint8_t is_text) {
// echos the data to the current websocket
websocket_write(ws, data, size, is_text);
if (memcmp(data, "bomb me", 7) == 0) {
char *msg = malloc(1024 * 1024);
for (char *pos = msg; pos < msg + (1024 * 1024 - 1); pos += 8) {
memcpy(pos, "bomb(!) ", 8);
}
websocket_write(ws, msg, 1024 * 1024, is_text);
free(msg);
}
}
static void ws_shutdown(ws_s *ws) {
websocket_write(ws, "Shutting Down", 13, 1);
}
static void ws_close(ws_s *ws) {
fprintf(stderr, "Closed websocket connection (%p)\n", (void *)ws);
}
/*****************************
A Websocket Broadcast implementation
*/
static void ws_broadcast(ws_s *ws, char *data, size_t size, uint8_t is_text) {
websocket_write_each(.data = data, .length = size, .is_text = is_text);
(void)ws;
}
/*****************************
The HTTP implementation
*/
static void on_request(http_request_s *request) {
// to log we will start a response.
http_response_s *response = http_response_create(request);
// http_response_log_start(response);
// upgrade requests to broadcast will have the following properties:
if (request->upgrade) {
if (!strcmp(request->path, "/broadcast")) {
// Websocket upgrade will use our existing response (never leak
// responses).
websocket_upgrade(.request = request, .on_message = ws_broadcast,
.on_open = ws_open, .on_close = ws_close,
.on_shutdown = ws_shutdown, .response = response);
return;
}
// other upgrade requests will have the following properties:
websocket_upgrade(.request = request, .on_message = ws_echo,
.max_msg_size = 2097152, .on_open = ws_open,
.on_close = ws_close, .timeout = 10,
.on_shutdown = ws_shutdown, .response = response);
return;
}
// file dumping
if (!strcmp(request->path, "/dump.jpg")) {
fdump_s *data = bscrypt_fdump("./public_www/bo.jpg", 0);
if (data == NULL) {
fprintf(stderr, "Couldn't read file\n");
http_response_write_body(response, "Sorry, error!", 13);
http_response_finish(response);
return;
}
http_response_write_body(response, data->data, data->length);
http_response_finish(response);
free(data);
return;
}
if (!strcmp(request->path, "/dump.mov")) {
fdump_s *data = bscrypt_fdump("./public_www/rolex.mov", 0);
if (data == NULL) {
fprintf(stderr, "Couldn't read file\n");
http_response_write_body(response, "Sorry, error!", 13);
http_response_finish(response);
return;
}
http_response_write_body(response, data->data, data->length);
http_response_finish(response);
free(data);
return;
}
// HTTP response
http_response_write_body(response, "Hello World!", 12);
http_response_finish(response);
}
// /*****************************
// Print to screen protocol
// */
// struct prnt2scrn_protocol_s {
// protocol_s protocol;
// intptr_t uuid;
// };
// static void on_data(intptr_t uuid, protocol_s *protocol) {
// (void)(protocol);
// uint8_t buffer[1024];
// ssize_t len;
// while ((len = sock_read(uuid, buffer, 1024)) > 0) {
// if (len > 0)
// fprintf(stderr, "%.*s\n", (int)len, buffer);
// }
// fprintf(stderr, "returning from on_data\n");
// // sock_write(uuid, "HTTP/1.1 100 Continue\r\n\r\n", 25);
// }
// static void on_close(protocol_s *protocol) {
// fprintf(stderr, "Connection closed %p\n",
// (void *)(((struct prnt2scrn_protocol_s *)protocol)->uuid));
// free(protocol);
// }
//
// static protocol_s *on_open(intptr_t uuid, void *udata) {
// (void)(udata);
// struct prnt2scrn_protocol_s *prt = malloc(sizeof *prt);
// *prt = (struct prnt2scrn_protocol_s){
// .protocol.on_data = on_data, .protocol.on_close = on_close, .uuid =
// uuid};
// fprintf(stderr, "New connection %p\n", (void *)uuid);
// server_set_timeout(uuid, 10);
// return (void *)prt;
// }
/*****************************
The main function
*/
void listen2http_ws(const char *port, const char *public_folder) {
if (http_listen(port, NULL, .on_request = on_request,
.public_folder = public_folder, .log_static = 1))
perror("Couldn't initiate HTTP service"), exit(1);
}
#endif