Created
October 18, 2016 10:35
-
-
Save jsaak/433380daaf72a789cbd3794a25b4bf56 to your computer and use it in GitHub Desktop.
buggy implementation of websocket to tcp gateway, do not use it unless you correct the errors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <uv.h> | |
#include "libwebsockets.h" | |
struct lws_context *context; | |
uv_loop_t loop; | |
static int callback_gateway(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); | |
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); | |
#define MAX_BUFFER_COUNT 16 | |
struct per_session_data_gateway { | |
uv_tcp_t socket; | |
uv_connect_t req_connect; | |
uv_write_t req_write; | |
struct lws *wsi; | |
uv_buf_t buffers[MAX_BUFFER_COUNT]; | |
int buffer_nread[MAX_BUFFER_COUNT]; | |
int buffer_counter; | |
}; | |
struct per_session_data__http { | |
int dummy; | |
}; | |
static struct lws_protocols protocols[] = { | |
{ | |
"http-only", | |
callback_http, | |
sizeof (struct per_session_data__http), | |
0, | |
}, | |
{ | |
"binary", | |
callback_gateway, | |
sizeof(struct per_session_data_gateway), | |
4096, | |
}, | |
{ NULL, NULL, 0, 0 } | |
}; | |
//set gateway as the default protocol | |
static const struct lws_protocol_vhost_options pvo_opt = { | |
NULL, | |
NULL, | |
"default", | |
"1" | |
}; | |
static const struct lws_protocol_vhost_options pvo = { | |
NULL, | |
&pvo_opt, | |
"gateway", | |
"" | |
}; | |
int main() { | |
//init libuv | |
uv_loop_init(&loop); | |
//init libwebsockets | |
struct lws_context_creation_info info; | |
memset(&info, 0, sizeof info); | |
info.port = 3344; | |
info.protocols = protocols; | |
info.options = LWS_SERVER_OPTION_LIBUV; | |
info.timeout_secs = 5; | |
info.gid = -1; | |
info.uid = -1; | |
info.pvo = &pvo; | |
context = lws_create_context(&info); | |
if (context == NULL) { | |
lwsl_err("libwebsocket init failed\n"); | |
return -1; | |
} | |
lws_uv_initloop(context, &loop, 0); | |
uv_run(&loop, UV_RUN_DEFAULT); | |
uv_loop_close(&loop); | |
lws_context_destroy(context); | |
} | |
static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { | |
//buf->base = malloc(suggested_size+LWS_PRE); | |
//buf->base += LWS_PRE; | |
//buf->len = suggested_size; | |
buf->base = malloc(4096); | |
buf->base += LWS_PRE; | |
buf->len = 4096-LWS_PRE; | |
} | |
static void on_close(uv_handle_t* handle) { | |
printf("on_close\n"); | |
} | |
static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { | |
printf("on_read %d\n",nread); | |
if (nread >= 0) { | |
if (nread > 0) { | |
struct per_session_data_gateway *psd = stream->data; | |
psd->buffers[psd->buffer_counter] = *buf; //store buf | |
psd->buffer_nread[psd->buffer_counter] = nread; | |
psd->buffer_counter++; | |
lws_callback_on_writable(psd->wsi); | |
} | |
} else { | |
printf("on_read error: %s\n", uv_strerror(nread)); | |
uv_close((uv_handle_t*)stream, on_close); //TODO | |
} | |
} | |
static void on_connect(uv_connect_t* connection, int status) { | |
printf("on_connect %d\n",status); | |
if (status) { | |
//printf("-\n"); | |
} else { | |
connection->handle->data = connection->data; | |
int ret = uv_read_start(connection->handle, alloc_cb, on_read); | |
//printf("%d\n",ret); | |
} | |
} | |
void on_write(uv_write_t* req, int status) { | |
printf("on_write %d\n",status); | |
if (status) { | |
printf("uv_write error: %s\n", uv_strerror(status)); | |
return; | |
} | |
} | |
static void my_write(struct per_session_data_gateway *psd, void* data, size_t len) { | |
printf("my_write %d\n",len); | |
uv_buf_t buffer; | |
buffer.base = data; | |
buffer.len = len; | |
uv_write(&psd->req_write, (uv_stream_t*)&psd->socket, &buffer, 1, on_write); | |
} | |
static int callback_gateway(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { | |
struct per_session_data_gateway *psd = (struct per_session_data_gateway *)user; | |
switch(reason) { | |
case LWS_CALLBACK_ESTABLISHED: | |
uv_tcp_init(&loop, &psd->socket); | |
struct sockaddr_in dest; | |
uv_ip4_addr("127.0.0.1", 3333, &dest); | |
psd->req_connect.data = psd; //store psd | |
psd->wsi = wsi; | |
psd->buffer_counter = 0; | |
uv_tcp_connect(&psd->req_connect, &psd->socket, (const struct sockaddr*)&dest, on_connect); | |
break; | |
case LWS_CALLBACK_CLOSED: | |
uv_close((uv_handle_t*)&psd->socket, on_close); | |
printf("uv_close\n"); | |
break; | |
case LWS_CALLBACK_RECEIVE: | |
my_write(psd,in,len); | |
break; | |
case LWS_CALLBACK_SERVER_WRITEABLE: | |
printf("on_callback_writeable buffer_counter:%d\n",psd->buffer_counter); | |
if (psd->buffer_counter > 0) { | |
uv_buf_t* buf = &psd->buffers[(psd->buffer_counter)-1]; | |
lws_write(wsi,buf->base,psd->buffer_nread[psd->buffer_counter-1],LWS_WRITE_BINARY); | |
//free buffer and set it to 0 | |
//TODO lehet már ilyenkor? | |
free(buf->base-LWS_PRE); | |
//(buf->base)-LWS_PRE = 0; | |
//buf->base = 0; | |
psd->buffer_counter--; | |
if (psd->buffer_counter > 0) { | |
lws_callback_on_writable(wsi); | |
} | |
} | |
break; | |
default: | |
break; | |
} | |
return 0; | |
} | |
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { | |
int ret; | |
switch(reason) { | |
case LWS_CALLBACK_HTTP: | |
ret = lws_serve_http_file(wsi, "./my_websockify.c", "text/plain", NULL, 0); | |
//return 1; | |
break; | |
default: | |
break; | |
} | |
return 0; | |
} | |
void stop_gateway() { | |
if (context) { | |
lws_libuv_stop(context); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment