mirror of
https://github.com/osnr/TabFS.git
synced 2024-06-26 17:30:30 +02:00
fs: Attempt to switch to native messaging. It relays 1 message ok!
This commit is contained in:
parent
09291ea6bc
commit
64bd1f3948
|
@ -379,7 +379,7 @@ function tryConnect() {
|
||||||
/* console.log('hello', port);*/
|
/* console.log('hello', port);*/
|
||||||
/* updateToolbarIcon();*/
|
/* updateToolbarIcon();*/
|
||||||
port.onMessage.addListener(onMessage);
|
port.onMessage.addListener(onMessage);
|
||||||
port.onDisconnect.addListener(p => {log(p)});
|
port.onDisconnect.addListener(p => {log('disconnect', p)});
|
||||||
|
|
||||||
/* ws = new WebSocket("ws://localhost:8888");
|
/* ws = new WebSocket("ws://localhost:8888");
|
||||||
* updateToolbarIcon();
|
* updateToolbarIcon();
|
||||||
|
|
|
@ -20,7 +20,7 @@ LIBS = -losxfuse
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
tabfs: common.c tabfs.c
|
tabfs: tabfs.c
|
||||||
$(CC) $(CFLAGS_OSXFUSE) $(CFLAGS_EXTRA) -o $@ $^ $(LIBS)
|
$(CC) $(CFLAGS_OSXFUSE) $(CFLAGS_EXTRA) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
68
fs/common.c
68
fs/common.c
|
@ -1,68 +0,0 @@
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdatomic.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static int tabfs_to_ws[2];
|
|
||||||
static int ws_to_tabfs[2];
|
|
||||||
|
|
||||||
void common_init() {
|
|
||||||
if (pipe(tabfs_to_ws)) exit(1);
|
|
||||||
if (pipe(ws_to_tabfs)) exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We probably technically need memory fences here? especially on
|
|
||||||
// non-x86?? Are these right? idk. See
|
|
||||||
// https://stackoverflow.com/questions/35837539/does-the-use-of-an-anonymous-pipe-introduce-a-memory-barrier-for-interthread-com
|
|
||||||
// https://preshing.com/20120913/acquire-and-release-semantics/
|
|
||||||
|
|
||||||
void common_send_tabfs_to_ws(char *request_data) {
|
|
||||||
atomic_thread_fence(memory_order_release);
|
|
||||||
write(tabfs_to_ws[1], &request_data, sizeof(request_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
char *common_receive_tabfs_to_ws(fd_set_filler_fn_t filler) {
|
|
||||||
fd_set read_fds, write_fds, except_fds;
|
|
||||||
FD_ZERO(&read_fds);
|
|
||||||
FD_ZERO(&write_fds);
|
|
||||||
FD_ZERO(&except_fds);
|
|
||||||
|
|
||||||
int max_fd = filler(&read_fds, &write_fds, &except_fds);
|
|
||||||
|
|
||||||
FD_SET(tabfs_to_ws[0], &read_fds);
|
|
||||||
if (tabfs_to_ws[0] > max_fd) { max_fd = tabfs_to_ws[0]; }
|
|
||||||
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = 0;
|
|
||||||
timeout.tv_usec = 200000;
|
|
||||||
|
|
||||||
select(max_fd + 1, &read_fds, &write_fds, &except_fds, &timeout);
|
|
||||||
|
|
||||||
if (!FD_ISSET(tabfs_to_ws[0], &read_fds)) {
|
|
||||||
// We can't read from tabfs_to_ws right now. Could be that it
|
|
||||||
// timed out, could be that we got a websocket event instead,
|
|
||||||
// whatever.
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *request_data;
|
|
||||||
read(tabfs_to_ws[0], &request_data, sizeof(request_data));
|
|
||||||
atomic_thread_fence(memory_order_acquire);
|
|
||||||
|
|
||||||
return request_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void common_send_ws_to_tabfs(char *response_data) {
|
|
||||||
atomic_thread_fence(memory_order_release);
|
|
||||||
write(ws_to_tabfs[1], &response_data, sizeof(response_data));
|
|
||||||
}
|
|
||||||
char *common_receive_ws_to_tabfs() {
|
|
||||||
char *response_data;
|
|
||||||
read(ws_to_tabfs[0], &response_data, sizeof(response_data));
|
|
||||||
atomic_thread_fence(memory_order_acquire);
|
|
||||||
|
|
||||||
return response_data;
|
|
||||||
}
|
|
34
fs/common.h
34
fs/common.h
|
@ -1,34 +0,0 @@
|
||||||
// common provides an interface for tabfs.c (which talks to FUSE) to
|
|
||||||
// talk to ws.c (which talks to the browser over WebSocket).
|
|
||||||
|
|
||||||
#ifndef COMMON_H
|
|
||||||
#define COMMON_H
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#define DEBUG(...)
|
|
||||||
|
|
||||||
void common_init();
|
|
||||||
|
|
||||||
typedef int (*fd_set_filler_fn_t)(fd_set*, fd_set*, fd_set*);
|
|
||||||
|
|
||||||
// All send and receive calls are blocking!
|
|
||||||
|
|
||||||
void common_send_tabfs_to_ws(char *request_data);
|
|
||||||
// This function is called by the ws thread; it blocks waiting for
|
|
||||||
// tabfs thread to send a request _from FUSE_, which means that the ws
|
|
||||||
// thread wouldn't be able to hear about events _from the browser_
|
|
||||||
// while blocked here (including important ones, like 'the browser
|
|
||||||
// wants to connect to us!').
|
|
||||||
//
|
|
||||||
// The hack solution is that ws passes a function `filler` to add the
|
|
||||||
// WebSocket file descriptors to the set that
|
|
||||||
// `common_receive_tabfs_to_ws` polls, so it _also_ waits on
|
|
||||||
// _browser-side_ events from the WebSocket file descriptors, not just
|
|
||||||
// FUSE-side events.
|
|
||||||
char *common_receive_tabfs_to_ws(fd_set_filler_fn_t filler);
|
|
||||||
|
|
||||||
void common_send_ws_to_tabfs(char *response_data);
|
|
||||||
char *common_receive_ws_to_tabfs();
|
|
||||||
|
|
||||||
#endif
|
|
27
fs/tabfs.c
27
fs/tabfs.c
|
@ -1,6 +1,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <fuse.h>
|
#include <fuse.h>
|
||||||
|
@ -11,26 +12,26 @@
|
||||||
#include "base64/base64.h"
|
#include "base64/base64.h"
|
||||||
#include "base64/base64.c"
|
#include "base64/base64.c"
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static cJSON *send_request_then_await_response(cJSON *req) {
|
static cJSON *send_request_then_await_response(cJSON *req) {
|
||||||
// Will be freed at receiver (ws.c, receive_tabfs_request_then_send_to_browser).
|
|
||||||
char *request_data = cJSON_Print(req);
|
char *request_data = cJSON_Print(req);
|
||||||
common_send_tabfs_to_ws(request_data);
|
unsigned int request_len = strlen(request_data);
|
||||||
|
write(1, (char *) &request_len, 4); // stdout
|
||||||
|
write(1, request_data, request_len);
|
||||||
|
|
||||||
char *response_data = common_receive_ws_to_tabfs();
|
unsigned int response_len;
|
||||||
|
read(0, (char *) &response_len, 4); // stdin
|
||||||
|
char *response_data = malloc(response_len);
|
||||||
|
read(0, response_data, response_len);
|
||||||
if (response_data == NULL) {
|
if (response_data == NULL) {
|
||||||
// Connection is dead.
|
// Connection is dead.
|
||||||
return cJSON_Parse("{ \"error\": 5 }");
|
return cJSON_Parse("{ \"error\": 5 }");
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON *resp = cJSON_Parse((const char *) response_data);
|
cJSON *resp = cJSON_Parse((const char *) response_data);
|
||||||
// Was allocated by sender (ws.c, websocket_frame).
|
|
||||||
free(response_data);
|
free(response_data);
|
||||||
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This helper macro is used to implement all the FUSE fs operations.
|
// This helper macro is used to implement all the FUSE fs operations.
|
||||||
//
|
//
|
||||||
// It constructs a JSON object to represent the incoming request, then
|
// It constructs a JSON object to represent the incoming request, then
|
||||||
|
@ -229,10 +230,10 @@ static struct fuse_operations tabfs_filesystem_operations = {
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
common_init();
|
FILE* log = fopen("log.txt", "w");
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
/* pthread_t websocket_thread; */
|
fprintf(log, "arg%d: [%s]\n", i, argv[i]); fflush(log);
|
||||||
/* pthread_create(&websocket_thread, NULL, websocket_main, NULL); */
|
}
|
||||||
|
char* fuse_argv[] = {argv[0], "-odirect_io", "-s", "-f", "mnt"};
|
||||||
return fuse_main(argc, argv, &tabfs_filesystem_operations, NULL);
|
return fuse_main(5, fuse_argv, &tabfs_filesystem_operations, NULL);
|
||||||
}
|
}
|
||||||
|
|
174
fs/ws.c
174
fs/ws.c
|
@ -1,174 +0,0 @@
|
||||||
// WebSocket server.
|
|
||||||
// Side thread that gets spawned.
|
|
||||||
|
|
||||||
#define WBY_STATIC
|
|
||||||
#define WBY_IMPLEMENTATION
|
|
||||||
#define WBY_USE_FIXED_TYPES
|
|
||||||
#define WBY_USE_ASSERT
|
|
||||||
#include "mmx/web.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
static struct wby_server server;
|
|
||||||
static struct wby_con *con = NULL;
|
|
||||||
|
|
||||||
static int fill_fd_set_with_ws_sockets(fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) {
|
|
||||||
// Based on web.h:1936 (start of wby_update)
|
|
||||||
|
|
||||||
int max_fd = 0;
|
|
||||||
FD_SET(server.socket, read_fds);
|
|
||||||
FD_SET(server.socket, except_fds);
|
|
||||||
max_fd = WBY_SOCK(server.socket);
|
|
||||||
|
|
||||||
if (con == NULL) { return max_fd; }
|
|
||||||
|
|
||||||
struct wby_connection *conn = (struct wby_connection *) con;
|
|
||||||
wby_socket socket = WBY_SOCK(conn->socket);
|
|
||||||
FD_SET(socket, read_fds);
|
|
||||||
FD_SET(socket, except_fds);
|
|
||||||
if (conn->state == WBY_CON_STATE_SEND_CONTINUE) {
|
|
||||||
FD_SET(socket, write_fds);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socket > max_fd) { max_fd = socket; }
|
|
||||||
return max_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void receive_tabfs_request_then_send_to_browser() {
|
|
||||||
char *request_data = common_receive_tabfs_to_ws(fill_fd_set_with_ws_sockets);
|
|
||||||
if (request_data == NULL) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (con == NULL) {
|
|
||||||
common_send_ws_to_tabfs(NULL);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
wby_frame_begin(con, WBY_WSOP_TEXT_FRAME);
|
|
||||||
wby_write(con, request_data, strlen(request_data));
|
|
||||||
wby_frame_end(con);
|
|
||||||
|
|
||||||
done:
|
|
||||||
// Was allocated by sender (tabfs.c, send_request_then_await_response).
|
|
||||||
if (request_data != NULL) { free(request_data); }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
dispatch(struct wby_con *connection, void *userdata) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
websocket_connect(struct wby_con *connection, void *userdata) {
|
|
||||||
/* connection bound userdata */
|
|
||||||
connection->user_data = NULL;
|
|
||||||
if (0 == strcmp(connection->request.uri, "/"))
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
websocket_connected(struct wby_con *connection, void *userdata) {
|
|
||||||
printf("WebSocket connected\n");
|
|
||||||
con = connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_DATA_LENGTH 131072
|
|
||||||
|
|
||||||
static int
|
|
||||||
websocket_frame(struct wby_con *connection, const struct wby_frame *frame, void *userdata)
|
|
||||||
{
|
|
||||||
// Will be freed at receiver (tabfs.c, send_request_then_await_response).
|
|
||||||
unsigned char *data = calloc(1, MAX_DATA_LENGTH);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
DEBUG("WebSocket frame incoming\n");
|
|
||||||
DEBUG(" Frame OpCode: %d\n", frame->opcode);
|
|
||||||
DEBUG(" Final frame?: %s\n", (frame->flags & WBY_WSF_FIN) ? "yes" : "no");
|
|
||||||
DEBUG(" Masked? : %s\n", (frame->flags & WBY_WSF_MASKED) ? "yes" : "no");
|
|
||||||
DEBUG(" Data Length : %d\n", (int) frame->payload_length);
|
|
||||||
|
|
||||||
if ((unsigned long) frame->payload_length > MAX_DATA_LENGTH) {
|
|
||||||
printf("Data too long!\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i < frame->payload_length) {
|
|
||||||
unsigned char buffer[16];
|
|
||||||
int remain = frame->payload_length - i;
|
|
||||||
size_t read_size = remain > (int) sizeof buffer ? sizeof buffer : (size_t) remain;
|
|
||||||
size_t k;
|
|
||||||
|
|
||||||
DEBUG("%08x ", (int) i);
|
|
||||||
if (0 != wby_read(connection, buffer, read_size))
|
|
||||||
break;
|
|
||||||
for (k = 0; k < read_size; ++k)
|
|
||||||
DEBUG("%02x ", buffer[k]);
|
|
||||||
for (k = read_size; k < 16; ++k)
|
|
||||||
DEBUG(" ");
|
|
||||||
DEBUG(" | ");
|
|
||||||
for (k = 0; k < read_size; ++k)
|
|
||||||
DEBUG("%c", isprint(buffer[k]) ? buffer[k] : '?');
|
|
||||||
DEBUG("\n");
|
|
||||||
for (k = 0; k < read_size; ++k)
|
|
||||||
data[i + k] = buffer[k];
|
|
||||||
i += (int)read_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int) strlen((const char *) data) != frame->payload_length) {
|
|
||||||
printf("Null in data! [%s]\n", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
common_send_ws_to_tabfs((char *) data);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void websocket_closed(struct wby_con *connection, void *userdata) {
|
|
||||||
printf("WebSocket closed\n");
|
|
||||||
|
|
||||||
if (con == connection) con = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_log(const char* text) {
|
|
||||||
DEBUG("[debug] %s\n", text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *websocket_main(void *threadid) {
|
|
||||||
void *memory = NULL;
|
|
||||||
wby_size needed_memory = 0;
|
|
||||||
|
|
||||||
struct wby_config config;
|
|
||||||
memset(&config, 0, sizeof config);
|
|
||||||
config.userdata = NULL;
|
|
||||||
config.address = "127.0.0.1";
|
|
||||||
config.port = 8888;
|
|
||||||
config.connection_max = 4;
|
|
||||||
config.request_buffer_size = 2048;
|
|
||||||
config.io_buffer_size = 8192;
|
|
||||||
config.log = test_log;
|
|
||||||
config.dispatch = dispatch;
|
|
||||||
config.ws_connect = websocket_connect;
|
|
||||||
config.ws_connected = websocket_connected;
|
|
||||||
config.ws_frame = websocket_frame;
|
|
||||||
config.ws_closed = websocket_closed;
|
|
||||||
|
|
||||||
wby_init(&server, &config, &needed_memory);
|
|
||||||
memory = calloc(needed_memory, 1);
|
|
||||||
wby_start(&server, memory);
|
|
||||||
|
|
||||||
printf("Awaiting WebSocket connection from Chrome extension.\n");
|
|
||||||
for (;;) {
|
|
||||||
receive_tabfs_request_then_send_to_browser();
|
|
||||||
wby_update(&server); // We receive stuff from the browser here.
|
|
||||||
}
|
|
||||||
|
|
||||||
wby_stop(&server);
|
|
||||||
free(memory);
|
|
||||||
#if defined(_WIN32)
|
|
||||||
WSACleanup();
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in a new issue