From aa0017f4b07867ace2f7e16a34b4ab994b468ffd Mon Sep 17 00:00:00 2001 From: phani Date: Mon, 16 Dec 2019 15:16:01 -0500 Subject: [PATCH] http request response using uv --- runtime/Makefile | 6 +- runtime/include/http.h | 50 ++++++ runtime/include/module.h | 19 ++ runtime/include/sandbox.h | 4 + runtime/include/types.h | 4 + runtime/src/http.c | 179 +++++++++++++++++++ runtime/src/libc/uvio.c | 36 ++-- runtime/src/runtime.c | 3 + runtime/src/sandbox.c | 32 +++- runtime/src/util.c | 61 ++++++- runtime/tests/test_empty.json | 8 +- runtime/tools/httpclient/Makefile | 10 ++ runtime/tools/httpclient/client.c | 276 ++++++++++++++++++++++++++++++ runtime/tools/udpclient/Makefile | 5 +- 14 files changed, 663 insertions(+), 30 deletions(-) create mode 100644 runtime/include/http.h create mode 100644 runtime/src/http.c create mode 100644 runtime/tools/httpclient/Makefile create mode 100644 runtime/tools/httpclient/client.c diff --git a/runtime/Makefile b/runtime/Makefile index 97293f4..adbc922 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -44,7 +44,7 @@ else ifeq ($(USE_MEM),USE_MEM_VM) CFILES += ${RTDIR}/memory/64bit_nix.c endif -all: clean runtime #tools +all: clean runtime tools runtime: @echo "Compiling runtime" @@ -57,10 +57,10 @@ tools: clean: @rm -f core - @echo "Cleaning up runtime" +# @echo "Cleaning up runtime" @rm -f ${RUNTIME} # @echo "Cleaning up tools" -# @${MAKE} -C tools clean + @${MAKE} -C tools clean fetch: @git submodule update --init --recursive diff --git a/runtime/include/http.h b/runtime/include/http.h new file mode 100644 index 0000000..3f0f2aa --- /dev/null +++ b/runtime/include/http.h @@ -0,0 +1,50 @@ +#ifndef SFRT_HTTP_H +#define SFRT_HTTP_H + +#include +#include +#include + +/* all in-memory ptrs.. don't mess around with that! */ +struct http_header { + char *key; + char *val; +}; + +struct http_resp_header { + char *hdr; + int len; +}; + +struct http_request { + struct http_header headers[HTTP_HEADERS_MAX]; + int nheaders; + char *body; + int bodylen; + // additional for http-parser + int last_was_value; + int header_end; + int message_begin, message_end; +}; + +struct http_response { + struct http_resp_header headers[HTTP_HEADERS_MAX]; + int nheaders; + char *body; + int bodylen; + char *status; + int stlen; + uv_buf_t bufs[HTTP_HEADERS_MAX * 2 + 3]; //max headers, one line for status code, remaining for body! +}; + +int http_request_body_get(char **body); +int http_request_parse(void); + +int http_response_header_set(char *h, int len); +int http_response_body_set(char *body, int len); +int http_response_status_set(char *status, int len); +int http_response_uv(void); + +void http_init(void); + +#endif /* SFRT_HTTP_H */ diff --git a/runtime/include/module.h b/runtime/include/module.h index a20109c..6eeb1cb 100644 --- a/runtime/include/module.h +++ b/runtime/include/module.h @@ -34,6 +34,11 @@ struct module { // so, using direct epoll for accepting connections. // uv_handle_t srvuv; unsigned long max_req_sz, max_resp_sz, max_rr_sz; // req/resp from http.. + int nreqhdrs, nresphdrs; + char reqhdrs[HTTP_HEADERS_MAX][HTTP_HEADER_MAXSZ]; + char rqctype[HTTP_HEADERVAL_MAXSZ]; + char rspctype[HTTP_HEADERVAL_MAXSZ]; + char resphdrs[HTTP_HEADERS_MAX][HTTP_HEADER_MAXSZ]; #endif }; @@ -43,6 +48,20 @@ void module_free(struct module *mod); struct module *module_find_by_name(char *name); struct module *module_find_by_sock(int sock); +static inline void +module_http_info(struct module *m, int nrq, char *rqs, char rqtype[], int nrs, char *rs, char rsptype[]) +{ +#ifndef STANDALONE + assert(m); + m->nreqhdrs = nrq; + m->nresphdrs = nrs; + memcpy(m->reqhdrs, rqs, HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX); + memcpy(m->resphdrs, rs, HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX); + strcpy(m->rqctype, rqtype); + strcpy(m->rspctype, rsptype); +#endif +} + static inline int module_is_valid(struct module *mod) { diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index fd62391..e3ba7c7 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -8,6 +8,7 @@ #include #include #include "deque.h" +#include struct io_handle { int fd; @@ -60,6 +61,9 @@ struct sandbox { struct sockaddr client; //client requesting connection! int csock; uv_tcp_t cuv; + http_parser hp; + struct http_request rqi; + struct http_response rsi; #endif char *read_buf; diff --git a/runtime/include/types.h b/runtime/include/types.h index c5886a7..72c6c76 100644 --- a/runtime/include/types.h +++ b/runtime/include/types.h @@ -153,4 +153,8 @@ typedef enum { #define MOD_REQ_RESP_DEFAULT (PAGE_SIZE) #define QUIESCENSE_TIME (1<<20) //cycles! +#define HTTP_HEADERS_MAX 4 +#define HTTP_HEADER_MAXSZ 32 +#define HTTP_HEADERVAL_MAXSZ 64 + #endif /* SFRT_TYPES_H */ diff --git a/runtime/src/http.c b/runtime/src/http.c new file mode 100644 index 0000000..6b638ef --- /dev/null +++ b/runtime/src/http.c @@ -0,0 +1,179 @@ +#include +#include +#include + +http_parser_settings settings; + +static inline int +http_on_msg_begin(http_parser *parser) +{ + struct http_request *r = parser->data; + + r->message_begin = 1; + r->last_was_value = 1; //should always start with a header.. + return 0; +} + +static inline int +http_on_msg_end(http_parser *parser) +{ + struct http_request *r = parser->data; + + r->message_end = 1; + return 0; +} + +static inline int +http_on_header_end(http_parser *parser) +{ + struct http_request *r = parser->data; + + r->header_end = 1; + return 0; +} + +static inline int +http_on_url(http_parser* parser, const char *at, size_t length) +{ + struct sandbox *s = sandbox_current(); + struct http_request *r = parser->data; + + assert(strncmp(s->mod->name, (at + 1), length - 1) == 0); + + return 0; +} + +static inline int +http_on_header_field(http_parser* parser, const char *at, size_t length) +{ + struct http_request *r = parser->data; + + if (r->last_was_value) r->nheaders ++; + assert(r->nheaders <= HTTP_HEADERS_MAX); + assert(length < HTTP_HEADER_MAXSZ); + + r->last_was_value = 0; + r->headers[r->nheaders - 1].key = (char *)at; //it is from the sandbox's req_resp_data, should persist. + + return 0; +} + +static inline int +http_on_header_value(http_parser* parser, const char *at, size_t length) +{ + struct http_request *r = parser->data; + + r->last_was_value = 1; + assert(r->nheaders <= HTTP_HEADERS_MAX); + assert(length < HTTP_HEADERVAL_MAXSZ); + + r->headers[r->nheaders - 1].val = (char *)at; //it is from the sandbox's req_resp_data, should persist. + + return 0; +} + +static inline int +http_on_body(http_parser* parser, const char *at, size_t length) +{ + struct http_request *r = parser->data; + struct sandbox *c = sandbox_current(); + + assert(length <= c->mod->max_req_sz); + r->body = (char *)at; + r->bodylen = length; + + return 0; +} + +int +http_request_body_get(char **b) +{ + struct sandbox *s = sandbox_current(); + struct http_request *r = &s->rqi; + + *b = r->body; + return r->bodylen; +} + +int +http_response_header_set(char *key, int len) +{ + // by now, req_resp_data should only be containing response! + struct sandbox *c = sandbox_current(); + struct http_response *r = &c->rsi; + + assert(r->nheaders < HTTP_HEADERS_MAX); + r->nheaders++; + r->headers[r->nheaders-1].hdr = key; + r->headers[r->nheaders-1].len = len; + + return 0; +} + +int http_response_body_set(char *body, int len) +{ + struct sandbox *c = sandbox_current(); + struct http_response *r = &c->rsi; + + assert(len < c->mod->max_resp_sz); + r->body = body; + r->bodylen = len; + + return 0; +} + +int http_response_status_set(char *status, int len) +{ + struct sandbox *c = sandbox_current(); + struct http_response *r = &c->rsi; + + r->status = status; + r->stlen = len; + + return 0; +} + +int http_response_uv(void) +{ + struct sandbox *c = sandbox_current(); + struct http_response *r = &c->rsi; + + int nb = 0; + + r->bufs[nb] = uv_buf_init(r->status, r->stlen); + nb++; + for (int i = 0; i < r->nheaders; i++) { + r->bufs[nb] = uv_buf_init(r->headers[i].hdr, r->headers[i].len); + nb++; + } + + if (r->body) { + r->bufs[nb] = uv_buf_init(r->body, r->bodylen); + nb++; + r->bufs[nb] = uv_buf_init(r->status + r->stlen - 2, 2); //for crlf + nb++; + } + + return nb; +} + +int +http_request_parse(void) +{ + struct sandbox *s = sandbox_current(); + http_parser_execute(&s->hp, &settings, s->req_resp_data, s->rr_data_len); + return 0; +} + +void +http_init(void) +{ + http_parser_settings_init(&settings); + settings.on_url = http_on_url; + settings.on_header_field = http_on_header_field; + settings.on_header_value = http_on_header_value; + settings.on_body = http_on_body; + settings.on_headers_complete = http_on_header_end; + settings.on_message_begin = http_on_msg_begin; + settings.on_message_complete = http_on_msg_end; +} diff --git a/runtime/src/libc/uvio.c b/runtime/src/libc/uvio.c index d0bef17..76a5d77 100644 --- a/runtime/src/libc/uvio.c +++ b/runtime/src/libc/uvio.c @@ -483,23 +483,33 @@ wasm_readv(i32 fd, i32 iov_offset, i32 iovcnt) i32 wasm_writev(i32 fd, i32 iov_offset, i32 iovcnt) { + struct sandbox *c = sandbox_current(); if (fd == 1 || fd == 2) { - int len = 0, r = 0; + //both 1 and 2 go to client. + int len = 0; struct wasm_iovec *iov = get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec)); - for (int i = 0; i < iovcnt; i+= RDWR_VEC_MAX) { - struct iovec bufs[RDWR_VEC_MAX] = { 0 }; - int j = 0; - for (j = 0; j < RDWR_VEC_MAX && i + j < iovcnt; j++) { - bufs[j].iov_base = get_memory_ptr_void(iov[i + j].base_offset, iov[i + j].len); - bufs[j].iov_len = iov[i + j].len; - } - - r = writev(fd, bufs, j); - if (r <= 0) break; - len += r; + for (int i = 0; i < iovcnt; i++) { + char *b = get_memory_ptr_void(iov[i].base_offset, iov[i].len); + memcpy(c->req_resp_data + c->rr_data_len, b, iov[i].len); + c->rr_data_len += iov[i].len; + len += iov[i].len; } - return r < 0 ? r : len; + return len; +// for (int i = 0; i < iovcnt; i+= RDWR_VEC_MAX) { +// struct iovec bufs[RDWR_VEC_MAX] = { 0 }; +// int j = 0; +// for (j = 0; j < RDWR_VEC_MAX && i + j < iovcnt; j++) { +// bufs[j].iov_base = get_memory_ptr_void(iov[i + j].base_offset, iov[i + j].len); +// bufs[j].iov_len = iov[i + j].len; +// } +// +// r = writev(fd, bufs, j); +// if (r <= 0) break; +// len += r; +// } +// +// return r < 0 ? r : len; } // TODO: read on other file types int d = io_handle_fd(fd); diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 7aa7c69..2c6ecaa 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -8,6 +8,7 @@ #include #include #include +#include struct deque_sandbox *glb_dq; pthread_mutex_t glbq_mtx = PTHREAD_MUTEX_INITIALIZER; @@ -288,6 +289,8 @@ runtime_init(void) softint_mask(SIGUSR1); softint_mask(SIGALRM); + + http_init(); } void diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 42508fc..6d35b3f 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -123,9 +123,9 @@ sandbox_client_request_get(void) int r = uv_read_start((uv_stream_t *)&curr->cuv, sb_alloc_callback, sb_read_callback); sandbox_block(); #endif - // TODO: http_request_parse + if (http_request_parse() != 0) return -1; - return curr->rr_data_len; + return 1; #else return 1; #endif @@ -137,17 +137,32 @@ sandbox_client_response_set(void) #ifndef STANDALONE struct sandbox *curr = sandbox_current(); - strcpy(curr->req_resp_data, "HTTP/1.1 200 OK\r\n\r\n"); +#ifndef USE_UVIO + strcpy(curr->req_resp_data + curr->rr_data_len, "HTTP/1.1 200 OK\r\n"); // TODO: response set in req_resp_data - curr->rr_data_len = strlen("HTTP/1.1 200 OK\r\n\r\n"); -#ifndef USE_UVIO + curr->rr_data_len += strlen("HTTP/1.1 200 OK\r\n"); + int r = send(curr->csock, curr->req_resp_data, curr->rr_data_len, 0); if (r < 0) perror("send"); #else + int bodylen = curr->rr_data_len; + if (bodylen > 0) { + http_response_body_set(curr->req_resp_data, bodylen); + char *key = curr->req_resp_data + curr->rr_data_len; + strcpy(key, "content-type: text/plain\r\n\r\n"); + http_response_header_set(key, strlen( "content-type: text/plain\r\n\r\n")); + curr->rr_data_len += strlen("content-type: text/plain\r\n\r\n"); + } + + char *st = curr->req_resp_data + curr->rr_data_len; + strcpy(st, "HTTP/1.1 200 OK\r\n"); + curr->rr_data_len += strlen("HTTP/1.1 200 OK\r\n"); + + http_response_status_set(st, strlen("HTTP/1.1 200 OK\r\n")); uv_write_t req = { .data = curr, }; - uv_buf_t bu = uv_buf_init(curr->req_resp_data, curr->rr_data_len); - int r = uv_write(&req, (uv_stream_t *)&curr->cuv, &bu, 1, sb_write_callback); + int n = http_response_uv(); + int r = uv_write(&req, (uv_stream_t *)&curr->cuv, curr->rsi.bufs, n, sb_write_callback); sandbox_block(); #endif return r; @@ -180,6 +195,8 @@ sandbox_entry(void) sandbox_args_setup(argc); #ifndef STANDALONE + http_parser_init(&curr->hp, HTTP_REQUEST); + curr->hp.data = &curr->rqi; #ifdef USE_UVIO int r = uv_tcp_init(runtime_uvio(), (uv_tcp_t *)&curr->cuv); assert(r == 0); @@ -190,6 +207,7 @@ sandbox_entry(void) if (sandbox_client_request_get() > 0) #endif { + curr->rr_data_len = 0; // TODO: do this on first write to body. alloc_linear_memory(); // perhaps only initialized for the first instance? or TODO! diff --git a/runtime/src/util.c b/runtime/src/util.c index ac3a27d..9d18dcb 100644 --- a/runtime/src/util.c +++ b/runtime/src/util.c @@ -7,6 +7,7 @@ #include #include #include +#include #define UTIL_MOD_LINE_MAX 1024 @@ -64,10 +65,24 @@ util_parse_modules_file_json(char *filename) char mname[MOD_NAME_MAX] = { 0 }; char mpath[MOD_PATH_MAX] = { 0 }; + char *rqhdrs; + char *rsphdrs; + i32 req_sz = 0; + i32 resp_sz = 0; i32 nargs = 0; u32 port = 0; i32 isactive = 0; - for (int j = 1; j < (toks[i].size * 2); j+=2) { + i32 nreqs = 0, nresps = 0; + int j = 1, ntoks = 2 * toks[i].size; + rqhdrs = (char *)malloc(HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX); + memset(rqhdrs, 0, HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX); + rsphdrs = (char *)malloc(HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX); + memset(rsphdrs, 0, HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX); + char rqtype[HTTP_HEADERVAL_MAXSZ] = { 0 }; + char rsptype[HTTP_HEADERVAL_MAXSZ] = { 0 }; + + for (; j < ntoks; ) { + int ntks = 1; char val[256] = { 0 }, key[32] = { 0 }; sprintf(val, "%.*s", toks[j + i + 1].end - toks[j + i + 1].start, filebuf + toks[j + i + 1].start); @@ -82,17 +97,57 @@ util_parse_modules_file_json(char *filename) nargs = atoi(val); } else if (strcmp(key, "active") == 0) { isactive = (strcmp(val, "yes") == 0); + } else if (strcmp(key, "http-req-headers") == 0) { + assert(toks[i + j + 1].type == JSMN_ARRAY); + + assert(toks[i + j + 1].size <= HTTP_HEADERS_MAX); + + nreqs = toks[i + j + 1].size; + ntks += nreqs; + ntoks += nreqs; + for (int k = 1; k <= toks[i + j + 1].size; k++) { + jsmntok_t *g = &toks[i + j + k + 1]; + char *r = rqhdrs + ((k-1)*HTTP_HEADER_MAXSZ); + assert(g->end - g->start < HTTP_HEADER_MAXSZ); + strncpy(r, filebuf + g->start, g->end - g->start); + } + } else if (strcmp(key, "http-resp-headers") == 0) { + assert(toks[i + j + 1].type == JSMN_ARRAY); + + assert(toks[i + j + 1].size <= HTTP_HEADERS_MAX); + + nresps = toks[i + j + 1].size; + ntks += nresps; + for (int k = 1; k <= toks[i + j + 1].size; k++) { + char *r = rsphdrs + ((k-1)*HTTP_HEADER_MAXSZ); + jsmntok_t *g = &toks[i + j + k + 1]; + assert(g->end - g->start < HTTP_HEADER_MAXSZ); + strncpy(r, filebuf + g->start, g->end - g->start); + } + ntoks += nresps; + } else if (strcmp(key, "http-req-size") == 0) { + req_sz = atoi(val); + } else if (strcmp(key, "http-resp-size") == 0) { + resp_sz = atoi(val); + } else if (strcmp(key, "http-req-content-type") == 0) { + strcpy(rqtype, val); + } else if (strcmp(key, "http-resp-content-type") == 0) { + strcpy(rsptype, val); } else { debuglog("Invalid (%s,%s)\n", key, val); } + j += ntks; } - i += (toks[i].size * 2); + i += ntoks; // do not load if it is not active if (isactive == 0) continue; - struct module *m = module_alloc(mname, mpath, nargs, 0, 0, 0, port, 0, 0); + struct module *m = module_alloc(mname, mpath, nargs, 0, 0, 0, port, req_sz, resp_sz); assert(m); + module_http_info(m, nreqs, rqhdrs, rqtype, nresps, rsphdrs, rsptype); nmods++; + free(rqhdrs); + free(rsphdrs); } free(filebuf); diff --git a/runtime/tests/test_empty.json b/runtime/tests/test_empty.json index c4e6539..018f57f 100644 --- a/runtime/tests/test_empty.json +++ b/runtime/tests/test_empty.json @@ -3,5 +3,11 @@ "name" : "empty", "path" : "empty_wasm.so", "port" : 10000, - "argsize" : 1 + "argsize" : 1, + "http-req-headers" : [ ], + "http-req-content-type" : "text/plain", + "http-req-size": 102400, + "http-resp-headers" : [ ], + "http-resp-size" : 10240, + "http-resp-content-type" : "text/plain" } diff --git a/runtime/tools/httpclient/Makefile b/runtime/tools/httpclient/Makefile new file mode 100644 index 0000000..b1b14dc --- /dev/null +++ b/runtime/tools/httpclient/Makefile @@ -0,0 +1,10 @@ +.PHONY: all client clean + +all: clean client + +client: client.c ../../http-parser/http_parser.c ../../http-parser/http_parser.h + @echo "Compiling httpclient" + @gcc -I../../http_parser/ ../../http-parser/http_parser.c client.c -g -o ../../bin/httpclient + +clean: + @rm -f ../../bin/httpclient diff --git a/runtime/tools/httpclient/client.c b/runtime/tools/httpclient/client.c new file mode 100644 index 0000000..0bdfa5f --- /dev/null +++ b/runtime/tools/httpclient/client.c @@ -0,0 +1,276 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SERVER_PORT 10000 +#define SERVER_ADDR "127.0.0.1" + +#define REQ_MAX 1024 +#define POST_MAX (1024*1024) +#define RESP_MAX 1024 +//#define GET_REQUEST "GET %s HTTP/1.0\r\n" +//#define GET_REQUEST "GET %s.ico HTTP/1.1\r\n" \ + "Host: 0.0.0.0=5000\r\n" \ + "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n" \ + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \ + "Accept-Language: en-us,en;q=0.5\r\n" \ + "Accept-Encoding: gzip,deflate\r\n" \ + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" \ + "Keep-Alive: 300\r\n" \ + "Connection: keep-alive\r\n" \ + "\r\n" + +//#define GET_REQUEST "GET /%s HTTP/1.1\r\n" \ +// "Host: 0.0.0.0=5000\r\n" \ +// "Accept: */*\r\n" \ +// "\r\n" +#define GET_REQUEST "GET /%s HTTP/1.1\r\n" \ + "Host: 0.0.0.0=xxxx\r\n" \ + "\r\n" + +#define POST_REQUEST "POST /%s HTTP/1.0\r\n" \ + "content-type: image/png\r\n" \ + "content-length: %lu\r\n" \ + "\r\n" + +#define POST_REQUEST_END "\r\n\r\n" + + +//Byte array of bitmap of 128 x 128 px: +char img [] = { +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0x83, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3, 0xc0, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf, 0xf0, 0x7f, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xfc, +0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, +0xfe, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, +0xff, 0xff, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xc1, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0x87, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xf, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xe1, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, +0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, +0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, +0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, +0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, +0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, +0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xf0, 0xf, 0xff, 0xff, 0xc7, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xc0, 0x3, 0xff, 0xff, +0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0x80, 0x1, 0xff, +0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xfe, 0xf, 0xf0, +0x7f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xfe, 0x1f, +0xf8, 0x7f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xfc, +0x7f, 0xfe, 0x3f, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, +0xf8, 0x7f, 0xfe, 0x1f, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, +0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x8f, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0x8f, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x8f, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0x8f, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xcf, 0xff, 0xf8, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xf8, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xf8, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xf8, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, +0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xf8, 0xff, 0xff, 0x1f, +0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xf8, 0x7f, 0xfe, +0x1f, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0x3f, +0xfc, 0x3f, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xfe, +0x1f, 0xf8, 0x7f, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, +0xff, 0x7, 0xe0, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, +0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x8f, 0xff, 0xff, 0xe0, 0x7, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0x8f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, +0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0x8f, 0xff, 0xf1, 0xff, 0xff, 0x9f, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xc0, 0xff, 0xff, 0x7, 0xff, 0xf1, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0xff, 0xff, 0x3, 0xff, 0xf1, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0x80, 0x0, 0x0, 0x1, 0xff, 0xe1, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0x18, 0x0, 0x0, 0x10, 0xff, 0xe3, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xfe, 0x18, 0x0, 0x0, 0x18, 0x7f, +0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xfc, 0x3f, 0xff, 0xff, 0xfc, +0x7f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xfc, 0x7f, 0xff, 0xff, +0xfe, 0x3f, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xf8, 0xff, 0xff, +0xff, 0xfe, 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xf8, 0xff, +0xff, 0xff, 0xff, 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xf1, +0xff, 0xe0, 0x3f, 0xff, 0x8f, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, +0xe1, 0xfc, 0x0, 0x1, 0xff, 0x8f, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xf1, 0xe3, 0xf0, 0x0, 0x0, 0x7f, 0xc7, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xf1, 0xc7, 0xf0, 0x3f, 0xe0, 0x3f, 0xc3, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xf1, 0xc7, 0xf1, 0xff, 0xfe, 0x3f, 0xe3, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xf8, 0x8f, 0xf1, 0xff, 0xfe, 0x7f, 0xf1, 0x1f, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xf8, 0xf, 0xf1, 0xff, 0xfc, 0x7f, 0xf1, 0x1f, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xf1, 0xff, 0xfc, 0x7f, 0xf8, 0x1f, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xf9, 0xff, 0xfc, 0x7f, 0xf8, 0x1f, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xf8, 0xff, 0xfc, 0x7f, 0xfc, 0x3f, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0xfe, +0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xf8, 0xff, +0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xf8, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, +0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, +0x7f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xfc, 0x7f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xfe, 0x3f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xfe, 0x3f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xfe, 0x3f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0x8f, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xf, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x1f, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }; + +int +connect_n_send(void) +{ + int sock; + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket"); + return -1; + } + + struct sockaddr_in srvaddr; + srvaddr.sin_family = AF_INET; + srvaddr.sin_port = htons(SERVER_PORT); + if (inet_aton(SERVER_ADDR, &srvaddr.sin_addr) == 0) { + perror("inet_addr"); + close(sock); + return -1; + } + + if (connect(sock, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) < 0) { + perror("connect"); + close(sock); + return -1; + } + + char *req = (char *)malloc(REQ_MAX); + assert(req); + memset(req, 0, REQ_MAX); + sprintf(req, GET_REQUEST, "empty"); +// char *req = (char *)malloc(POST_MAX); +// assert(req); +// memset(req, 0, POST_MAX); +// sprintf(req, POST_REQUEST, "HELLO", sizeof(img)); + int len = strlen(req); +// memcpy(req+len, img, sizeof(img)); +// strcat(req+len+sizeof(img), POST_REQUEST_END); +// len += sizeof(img) + strlen(POST_REQUEST_END); + char *resp = (char *)malloc(RESP_MAX); + assert(resp); + memset(resp, 0, RESP_MAX); + +// int fd = open("tmp_cli.png", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXO | S_IRWXG); +// if (fd < 0) { +// perror("open"); +// goto skip; +// } +// +// int sz = write(fd, img, sizeof(img)); +// if (sz < 0) { +// perror("write"); +// } +// close(fd); + +skip: + printf("Sending..\n"); + if (send(sock, req, len, 0) < 0) { + perror("send"); + close(sock); + return -1; + } + + printf("Receiving..\n"); + int r = 0, rcvd = 0; + while ((r = recv(sock, resp + rcvd, RESP_MAX, 0)) > 0) { + rcvd += r; + if (r < RESP_MAX) break; + resp = (char *)realloc(resp, rcvd + RESP_MAX); + assert(resp); + memset(resp + rcvd, 0, RESP_MAX); + } + + printf("Response: %s\n", resp); + free(resp); + free(req); + close(sock); + return 0; +} + +int +main(int argc, char **argv) +{ + while (1) { + int s = 0; + + printf("Test? (0 = exit)\n"); + scanf("%d", &s); + if (s == 0) break; + connect_n_send(); + } +} diff --git a/runtime/tools/udpclient/Makefile b/runtime/tools/udpclient/Makefile index 22cee3f..09ad4b2 100644 --- a/runtime/tools/udpclient/Makefile +++ b/runtime/tools/udpclient/Makefile @@ -1,9 +1,8 @@ +all: clean udp + udp: udpclient.c @echo "Compiling udpclient" @gcc udpclient.c -o ../../bin/udpclient -lpthread clean: - @echo "Cleaning up udpclient" @rm -f ../../bin/udpclient - -all: clean udp