|
|
@ -17,8 +17,6 @@
|
|
|
|
#include <event.h>
|
|
|
|
#include <event.h>
|
|
|
|
#include <http_parser.h>
|
|
|
|
#include <http_parser.h>
|
|
|
|
|
|
|
|
|
|
|
|
#define DEBUG_LOGS 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct host_info{
|
|
|
|
struct host_info{
|
|
|
|
char *host;
|
|
|
|
char *host;
|
|
|
|
short port;
|
|
|
|
short port;
|
|
|
@ -88,7 +86,7 @@ hex_dump(struct worker_thread *wt, char *p, size_t sz) {
|
|
|
|
letters[i] = isprint(cur[i]) ? cur[i] : '.';
|
|
|
|
letters[i] = isprint(cur[i]) ? cur[i] : '.';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = limit; i < 16; i++) { /* pad on last line */
|
|
|
|
for (int i = limit; i < 16; i++) { /* pad on last line */
|
|
|
|
wt->debug(" ");
|
|
|
|
wt->debug(" "); /* 3 spaces for "%02x " */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wt->debug(" %.*s\n", limit, letters);
|
|
|
|
wt->debug(" %.*s\n", limit, letters);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -98,6 +96,10 @@ void
|
|
|
|
evbuffer_debug_dump(struct worker_thread *wt, struct evbuffer *buffer) {
|
|
|
|
evbuffer_debug_dump(struct worker_thread *wt, struct evbuffer *buffer) {
|
|
|
|
size_t sz = evbuffer_get_length(buffer);
|
|
|
|
size_t sz = evbuffer_get_length(buffer);
|
|
|
|
char *data = malloc(sz);
|
|
|
|
char *data = malloc(sz);
|
|
|
|
|
|
|
|
if (!data) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to allocate %ld bytes\n", sz);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
evbuffer_remove(buffer, data, sz);
|
|
|
|
evbuffer_remove(buffer, data, sz);
|
|
|
|
hex_dump(wt, data, sz);
|
|
|
|
hex_dump(wt, data, sz);
|
|
|
|
evbuffer_prepend(buffer, data, sz);
|
|
|
|
evbuffer_prepend(buffer, data, sz);
|
|
|
@ -106,6 +108,7 @@ evbuffer_debug_dump(struct worker_thread *wt, struct evbuffer *buffer) {
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
wait_for_possible_read(struct worker_thread *wt);
|
|
|
|
wait_for_possible_read(struct worker_thread *wt);
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
wait_for_possible_write(struct worker_thread *wt);
|
|
|
|
wait_for_possible_write(struct worker_thread *wt);
|
|
|
|
|
|
|
|
|
|
|
@ -114,8 +117,6 @@ ws_enqueue_frame(struct worker_thread *wt);
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
process_message(struct worker_thread *wt, size_t sz) {
|
|
|
|
process_message(struct worker_thread *wt, size_t sz) {
|
|
|
|
|
|
|
|
|
|
|
|
// printf("process_message\n");
|
|
|
|
|
|
|
|
if (wt->msg_received && wt->msg_received % 1000 == 0) {
|
|
|
|
if (wt->msg_received && wt->msg_received % 1000 == 0) {
|
|
|
|
printf("thread %d: %8d messages left (got %9d bytes so far).\n",
|
|
|
|
printf("thread %d: %8d messages left (got %9d bytes so far).\n",
|
|
|
|
wt->id,
|
|
|
|
wt->id,
|
|
|
@ -141,11 +142,7 @@ websocket_can_write(int fd, short event, void *ptr) {
|
|
|
|
struct worker_thread *wt = ptr;
|
|
|
|
struct worker_thread *wt = ptr;
|
|
|
|
wt->debug("%s (wt=%p, fd=%d)\n", __func__, wt, fd);
|
|
|
|
wt->debug("%s (wt=%p, fd=%d)\n", __func__, wt, fd);
|
|
|
|
|
|
|
|
|
|
|
|
if(event != EV_WRITE) {
|
|
|
|
switch (wt->state) {
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (wt->state)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case WS_INITIAL: { /* still sending initial HTTP request */
|
|
|
|
case WS_INITIAL: { /* still sending initial HTTP request */
|
|
|
|
ret = evbuffer_write(wt->wbuffer, fd);
|
|
|
|
ret = evbuffer_write(wt->wbuffer, fd);
|
|
|
|
wt->debug("evbuffer_write returned %d\n", ret);
|
|
|
|
wt->debug("evbuffer_write returned %d\n", ret);
|
|
|
@ -186,16 +183,13 @@ websocket_can_read(int fd, short event, void *ptr) {
|
|
|
|
struct worker_thread *wt = ptr;
|
|
|
|
struct worker_thread *wt = ptr;
|
|
|
|
wt->debug("%s (wt=%p)\n", __func__, wt);
|
|
|
|
wt->debug("%s (wt=%p)\n", __func__, wt);
|
|
|
|
|
|
|
|
|
|
|
|
if(event != EV_READ) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* read message */
|
|
|
|
/* read message */
|
|
|
|
ret = evbuffer_read(wt->rbuffer, fd, 65536);
|
|
|
|
ret = evbuffer_read(wt->rbuffer, fd, 65536);
|
|
|
|
wt->debug("evbuffer_read() returned %d; wt->state=%d. wt->rbuffer:\n", ret, wt->state);
|
|
|
|
wt->debug("evbuffer_read() returned %d; wt->state=%d. wt->rbuffer:\n", ret, wt->state);
|
|
|
|
evbuffer_debug_dump(wt, wt->rbuffer);
|
|
|
|
evbuffer_debug_dump(wt, wt->rbuffer);
|
|
|
|
if (ret == 0) {
|
|
|
|
if (ret == 0) {
|
|
|
|
wt->debug("We didn't read anything from the socket...\n");
|
|
|
|
wt->debug("We didn't read anything from the socket...\n");
|
|
|
|
|
|
|
|
event_base_loopexit(wt->base, NULL);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -278,9 +272,7 @@ wait_for_possible_write(struct worker_thread *wt) {
|
|
|
|
static int
|
|
|
|
static int
|
|
|
|
ws_on_headers_complete(http_parser *p) {
|
|
|
|
ws_on_headers_complete(http_parser *p) {
|
|
|
|
struct worker_thread *wt = p->data;
|
|
|
|
struct worker_thread *wt = p->data;
|
|
|
|
|
|
|
|
|
|
|
|
wt->debug("%s (wt=%p)\n", __func__, wt);
|
|
|
|
wt->debug("%s (wt=%p)\n", __func__, wt);
|
|
|
|
// TODO
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -341,8 +333,7 @@ worker_main(void *ptr) {
|
|
|
|
"Upgrade: WebSocket\r\n"
|
|
|
|
"Upgrade: WebSocket\r\n"
|
|
|
|
"Origin: http://%s:%d\r\n"
|
|
|
|
"Origin: http://%s:%d\r\n"
|
|
|
|
"Sec-WebSocket-Key: webdis-websocket-test-key\r\n"
|
|
|
|
"Sec-WebSocket-Key: webdis-websocket-test-key\r\n"
|
|
|
|
"\r\n"
|
|
|
|
"\r\n";
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct worker_thread *wt = ptr;
|
|
|
|
struct worker_thread *wt = ptr;
|
|
|
|
|
|
|
|
|
|
|
@ -400,8 +391,7 @@ worker_main(void *ptr) {
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void usage(const char *argv0, char *host_default, short port_default,
|
|
|
|
usage(const char* argv0, char *host_default, short port_default,
|
|
|
|
|
|
|
|
int thread_count_default, int messages_default) {
|
|
|
|
int thread_count_default, int messages_default) {
|
|
|
|
|
|
|
|
|
|
|
|
printf("Usage: %s [options]\n"
|
|
|
|
printf("Usage: %s [options]\n"
|
|
|
@ -447,8 +437,7 @@ main(int argc, char *argv[]) {
|
|
|
|
{"messages", required_argument, NULL, 'n'},
|
|
|
|
{"messages", required_argument, NULL, 'n'},
|
|
|
|
{"max-time", required_argument, NULL, 't'},
|
|
|
|
{"max-time", required_argument, NULL, 't'},
|
|
|
|
{"verbose", no_argument, NULL, 'v'},
|
|
|
|
{"verbose", no_argument, NULL, 'v'},
|
|
|
|
{0, 0, 0, 0}
|
|
|
|
{0, 0, 0, 0}};
|
|
|
|
};
|
|
|
|
|
|
|
|
while ((opt = getopt_long(argc, argv, "h:p:c:n:t:vs", long_options, NULL)) != -1) {
|
|
|
|
while ((opt = getopt_long(argc, argv, "h:p:c:n:t:vs", long_options, NULL)) != -1) {
|
|
|
|
switch (opt) {
|
|
|
|
switch (opt) {
|
|
|
|
case 'h':
|
|
|
|
case 'h':
|
|
|
|