File Conn.c changed (mode: 100644) (index 6fdb2aa..b435807) |
... |
... |
struct Conn_wpool *Conn_wpool_create(const unsigned short workers) |
202 |
202 |
int Conn_wpool_destroy(struct Conn_wpool *wp) |
int Conn_wpool_destroy(struct Conn_wpool *wp) |
203 |
203 |
{ |
{ |
204 |
204 |
int i; |
int i; |
205 |
|
struct Conn_wpool_worker *w; |
|
206 |
205 |
|
|
207 |
206 |
for (i = 0; i < wp->workers; i++) { |
for (i = 0; i < wp->workers; i++) { |
|
207 |
|
struct Conn_wpool_worker *w; |
|
208 |
|
|
208 |
209 |
w = &wp->ww[i]; |
w = &wp->ww[i]; |
209 |
210 |
|
|
210 |
211 |
if (w->inited == 0) |
if (w->inited == 0) |
|
... |
... |
char *Conn_dump(const void *buf_src0, const size_t len_src) |
433 |
434 |
unsigned int i, j; |
unsigned int i, j; |
434 |
435 |
char tmp[3]; |
char tmp[3]; |
435 |
436 |
char *buf_dst; |
char *buf_dst; |
436 |
|
unsigned char c; |
|
437 |
437 |
const unsigned char *buf_src = buf_src0; |
const unsigned char *buf_src = buf_src0; |
438 |
438 |
|
|
439 |
439 |
Log(30, "\tConn_dump(%p, len=%zu)\n", |
Log(30, "\tConn_dump(%p, len=%zu)\n", |
|
... |
... |
char *Conn_dump(const void *buf_src0, const size_t len_src) |
445 |
445 |
|
|
446 |
446 |
j = 0; |
j = 0; |
447 |
447 |
for (i = 0; i < len_src; i++) { |
for (i = 0; i < len_src; i++) { |
|
448 |
|
unsigned char c; |
|
449 |
|
|
448 |
450 |
c = buf_src[i]; |
c = buf_src[i]; |
449 |
451 |
if ((c < 32) || (c > 127)) { |
if ((c < 32) || (c > 127)) { |
450 |
452 |
buf_dst[j++] = '['; |
buf_dst[j++] = '['; |
|
... |
... |
char *Conn_dumphex(const void *buf_src0, const size_t len_src) |
467 |
469 |
unsigned int i, j; |
unsigned int i, j; |
468 |
470 |
char tmp[3]; |
char tmp[3]; |
469 |
471 |
char *buf_dst; |
char *buf_dst; |
470 |
|
unsigned char c; |
|
471 |
472 |
const unsigned char *buf_src = buf_src0; |
const unsigned char *buf_src = buf_src0; |
472 |
473 |
|
|
473 |
474 |
Log(30, "\tConn_dumphex(%p, len=%zu)\n", |
Log(30, "\tConn_dumphex(%p, len=%zu)\n", |
|
... |
... |
char *Conn_dumphex(const void *buf_src0, const size_t len_src) |
479 |
480 |
|
|
480 |
481 |
j = 0; |
j = 0; |
481 |
482 |
for (i = 0; i < len_src; i++) { |
for (i = 0; i < len_src; i++) { |
|
483 |
|
unsigned char c; |
|
484 |
|
|
482 |
485 |
c = buf_src[i]; |
c = buf_src[i]; |
483 |
486 |
snprintf(tmp, sizeof(tmp), "%02x", c); |
snprintf(tmp, sizeof(tmp), "%02x", c); |
484 |
487 |
buf_dst[j++] = tmp[0]; |
buf_dst[j++] = tmp[0]; |
|
... |
... |
__hot static void Conn_free_intern(struct Conn *C) |
774 |
777 |
C->next = NULL; |
C->next = NULL; |
775 |
778 |
} |
} |
776 |
779 |
|
|
|
780 |
|
if (C->private) { |
|
781 |
|
free(C->private); |
|
782 |
|
C->private = NULL; |
|
783 |
|
} |
|
784 |
|
|
777 |
785 |
/* Add it to free list of the worker pool */ |
/* Add it to free list of the worker pool */ |
778 |
786 |
if (likely(C->worker)) { |
if (likely(C->worker)) { |
779 |
787 |
struct Conn_wpool_worker *worker = C->worker; |
struct Conn_wpool_worker *worker = C->worker; |
|
... |
... |
static inline int Conn_change_obj(int epoll_fd, struct Conn *C, |
942 |
950 |
__hot static void Conn_default_cbs_recv(struct Conn *C) |
__hot static void Conn_default_cbs_recv(struct Conn *C) |
943 |
951 |
{ |
{ |
944 |
952 |
ssize_t n; |
ssize_t n; |
945 |
|
unsigned int max, xfer_in_this_call; |
|
|
953 |
|
unsigned int xfer_in_this_call; |
946 |
954 |
int r, xerrno; |
int r, xerrno; |
947 |
955 |
char *dump, call_callback; |
char *dump, call_callback; |
948 |
956 |
|
|
|
... |
... |
__hot static void Conn_default_cbs_recv(struct Conn *C) |
953 |
961 |
call_callback = 0; |
call_callback = 0; |
954 |
962 |
xfer_in_this_call = 0; |
xfer_in_this_call = 0; |
955 |
963 |
while (1) { |
while (1) { |
|
964 |
|
unsigned int max; |
|
965 |
|
|
956 |
966 |
if ((Conn_max_recv > 0) && (xfer_in_this_call >= Conn_max_recv)) { |
if ((Conn_max_recv > 0) && (xfer_in_this_call >= Conn_max_recv)) { |
957 |
967 |
Log(3, "\tRecv limit reached. Add to extra queue.\n"); |
Log(3, "\tRecv limit reached. Add to extra queue.\n"); |
958 |
968 |
break; |
break; |
|
... |
... |
__hot static void Conn_default_cbs_recv(struct Conn *C) |
1044 |
1054 |
__hot static void Conn_default_cbs_send(struct Conn *C) |
__hot static void Conn_default_cbs_send(struct Conn *C) |
1045 |
1055 |
{ |
{ |
1046 |
1056 |
ssize_t n; |
ssize_t n; |
1047 |
|
unsigned int max; |
|
1048 |
1057 |
int xerrno, r; |
int xerrno, r; |
1049 |
|
unsigned int count; |
|
1050 |
|
char *buf; |
|
1051 |
1058 |
char *dump; |
char *dump; |
1052 |
1059 |
|
|
1053 |
1060 |
Log(5, "%llu %s C=%p next=%p fd=%d head=%u tail=%u size=%u\n", |
Log(5, "%llu %s C=%p next=%p fd=%d head=%u tail=%u size=%u\n", |
|
... |
... |
__hot static void Conn_default_cbs_send(struct Conn *C) |
1055 |
1062 |
C->obuf_tail, C->obuf_size); |
C->obuf_tail, C->obuf_size); |
1056 |
1063 |
|
|
1057 |
1064 |
while (1) { |
while (1) { |
|
1065 |
|
unsigned int max, count; |
|
1066 |
|
char *buf; |
|
1067 |
|
|
1058 |
1068 |
buf = C->obuf + C->obuf_head; |
buf = C->obuf + C->obuf_head; |
1059 |
1069 |
count = Conn_oqlen(C); |
count = Conn_oqlen(C); |
1060 |
1070 |
if (unlikely(count == 0)) { |
if (unlikely(count == 0)) { |
|
... |
... |
static char *Conn_status_slot(struct Conn *C) |
1391 |
1401 |
char flags[128], flags_prefix[3], flags_postfix[2]; |
char flags[128], flags_prefix[3], flags_postfix[2]; |
1392 |
1402 |
char *local_addr, *remote_addr; |
char *local_addr, *remote_addr; |
1393 |
1403 |
int local_port, remote_port; |
int local_port, remote_port; |
1394 |
|
char flags_tmp[64]; |
|
1395 |
1404 |
|
|
1396 |
1405 |
/* flags */ |
/* flags */ |
1397 |
1406 |
strcpy(flags, ""); |
strcpy(flags, ""); |
|
... |
... |
static char *Conn_status_slot(struct Conn *C) |
1399 |
1408 |
strcpy(flags_postfix, ""); |
strcpy(flags_postfix, ""); |
1400 |
1409 |
|
|
1401 |
1410 |
if (C->auto_reconnect) { |
if (C->auto_reconnect) { |
|
1411 |
|
char flags_tmp[64]; |
|
1412 |
|
|
1402 |
1413 |
strcat(flags, flags_prefix); |
strcat(flags, flags_prefix); |
1403 |
1414 |
snprintf(flags_tmp, sizeof(flags_tmp), "autoreconnect_in_%ld/%u", |
snprintf(flags_tmp, sizeof(flags_tmp), "autoreconnect_in_%ld/%u", |
1404 |
1415 |
(C->tryat == 0) ? 0 : C->tryat - Conn_now.tv_sec, |
(C->tryat == 0) ? 0 : C->tryat - Conn_now.tv_sec, |
|
... |
... |
char *Conn_status(const unsigned int flags) |
1538 |
1549 |
gettimeofday(&Conn_now, NULL); |
gettimeofday(&Conn_now, NULL); |
1539 |
1550 |
/* TODO: "len += " is incorrect */ |
/* TODO: "len += " is incorrect */ |
1540 |
1551 |
tmp_len = snprintf(tmp, sizeof(tmp), |
tmp_len = snprintf(tmp, sizeof(tmp), |
1541 |
|
"Conn_pending=%d Conn_no/Conn_max=%d/%d Conn_total=%lu" |
|
1542 |
|
" Conn_uptime=%lus Conn_allocated=%d Conn_work_to_do=%u" |
|
|
1552 |
|
"Conn_pending=%u Conn_no/Conn_max=%u/%u Conn_total=%lu" |
|
1553 |
|
" Conn_uptime=%lus Conn_allocated=%u Conn_work_to_do=%u" |
1543 |
1554 |
" Conn_mem_structs=%llu Conn_mem_buffers_in/out=%llu/%llu\n", |
" Conn_mem_structs=%llu Conn_mem_buffers_in/out=%llu/%llu\n", |
1544 |
1555 |
Conn_pending, Conn_no, Conn_max, Conn_total, |
Conn_pending, Conn_no, Conn_max, Conn_total, |
1545 |
1556 |
Conn_now.tv_sec - Conn_start, Conn_allocated, Conn_work_to_do, |
Conn_now.tv_sec - Conn_start, Conn_allocated, Conn_work_to_do, |
1546 |
1557 |
Conn_mem_structs, Conn_mem_buffers_in, Conn_mem_buffers_out); |
Conn_mem_structs, Conn_mem_buffers_in, Conn_mem_buffers_out); |
1547 |
|
if (tmp_len < 0) |
|
|
1558 |
|
if (tmp_len < 0) { |
|
1559 |
|
free(buf); |
1548 |
1560 |
return strdup("snprintf error"); |
return strdup("snprintf error"); |
|
1561 |
|
} |
1549 |
1562 |
if (len + (unsigned int) tmp_len < max) { |
if (len + (unsigned int) tmp_len < max) { |
1550 |
1563 |
strcat(buf, tmp); |
strcat(buf, tmp); |
1551 |
1564 |
len += (unsigned int) tmp_len; |
len += (unsigned int) tmp_len; |
|
... |
... |
char *Conn_status(const unsigned int flags) |
1603 |
1616 |
else |
else |
1604 |
1617 |
per_slot = Conn_status_slot_html(C); |
per_slot = Conn_status_slot_html(C); |
1605 |
1618 |
tmp_len = snprintf(tmp, sizeof(tmp), "%s\n", per_slot); |
tmp_len = snprintf(tmp, sizeof(tmp), "%s\n", per_slot); |
1606 |
|
if (tmp_len < 0) |
|
|
1619 |
|
if (tmp_len < 0) { |
|
1620 |
|
free(buf); |
1607 |
1621 |
return strdup("snprintf error"); |
return strdup("snprintf error"); |
|
1622 |
|
} |
1608 |
1623 |
len += (unsigned int) tmp_len; |
len += (unsigned int) tmp_len; |
1609 |
1624 |
if (len < max) |
if (len < max) |
1610 |
1625 |
strcat(buf, tmp); |
strcat(buf, tmp); |
|
... |
... |
char *Conn_status(const unsigned int flags) |
1628 |
1643 |
tmp_len = snprintf(tmp, sizeof(tmp), "Total speed I/O: %s/%s" |
tmp_len = snprintf(tmp, sizeof(tmp), "Total speed I/O: %s/%s" |
1629 |
1644 |
" Total bytes I/O: %llu/%llu\n", |
" Total bytes I/O: %llu/%llu\n", |
1630 |
1645 |
speedi, speedo, bi, bo); |
speedi, speedo, bi, bo); |
1631 |
|
if (tmp_len < 0) |
|
|
1646 |
|
if (tmp_len < 0) { |
|
1647 |
|
free(buf); |
1632 |
1648 |
return strdup("snprintf error"); |
return strdup("snprintf error"); |
|
1649 |
|
} |
1633 |
1650 |
if (len + (unsigned int) tmp_len < max) { |
if (len + (unsigned int) tmp_len < max) { |
1634 |
1651 |
strcat(buf, tmp); |
strcat(buf, tmp); |
1635 |
1652 |
len += (unsigned int) tmp_len; |
len += (unsigned int) tmp_len; |
|
... |
... |
static void Conn_rtrim(char *s, const char *chars) |
1915 |
1932 |
*/ |
*/ |
1916 |
1933 |
void Conn_for_every_line(struct Conn *C, void (*cb)(struct Conn *C, char *line)) |
void Conn_for_every_line(struct Conn *C, void (*cb)(struct Conn *C, char *line)) |
1917 |
1934 |
{ |
{ |
1918 |
|
char *line; |
|
1919 |
|
size_t line_size; |
|
1920 |
|
|
|
1921 |
1935 |
if (cb == NULL) |
if (cb == NULL) |
1922 |
1936 |
return; |
return; |
1923 |
1937 |
|
|
1924 |
1938 |
while (1) { |
while (1) { |
|
1939 |
|
char *line; |
|
1940 |
|
size_t line_size; |
|
1941 |
|
|
1925 |
1942 |
/* TODO: Conn_get_line may also return the size */ |
/* TODO: Conn_get_line may also return the size */ |
1926 |
1943 |
line = Conn_get_line(C); |
line = Conn_get_line(C); |
1927 |
1944 |
if (line == NULL) |
if (line == NULL) |
|
... |
... |
void Conn_for_every_line(struct Conn *C, void (*cb)(struct Conn *C, char *line)) |
1944 |
1961 |
int Conn_printf(struct Conn *C, const char *format, ...) |
int Conn_printf(struct Conn *C, const char *format, ...) |
1945 |
1962 |
{ |
{ |
1946 |
1963 |
va_list ap; |
va_list ap; |
1947 |
|
char *s; |
|
1948 |
|
int d, r, ret; |
|
1949 |
|
ssize_t slen; |
|
1950 |
|
unsigned long len; |
|
1951 |
|
char tmp[64]; |
|
|
1964 |
|
int ret; |
1952 |
1965 |
|
|
1953 |
1966 |
ret = 0; |
ret = 0; |
1954 |
1967 |
va_start(ap, format); |
va_start(ap, format); |
1955 |
1968 |
while (likely(*format)) { |
while (likely(*format)) { |
|
1969 |
|
char *s; |
|
1970 |
|
ssize_t slen; |
|
1971 |
|
unsigned long len; |
|
1972 |
|
char tmp[64]; |
|
1973 |
|
int d, r; |
|
1974 |
|
|
1956 |
1975 |
/* Find first formatting char */ |
/* Find first formatting char */ |
1957 |
1976 |
s = strchr(format, '%'); |
s = strchr(format, '%'); |
1958 |
1977 |
if (unlikely(!s)) { |
if (unlikely(!s)) { |
|
... |
... |
__hot static struct Conn *Conn_alloc_prepare(struct Conn *C) |
2113 |
2132 |
__hot struct Conn *Conn_alloc(void) |
__hot struct Conn *Conn_alloc(void) |
2114 |
2133 |
{ |
{ |
2115 |
2134 |
struct Conn *C; |
struct Conn *C; |
2116 |
|
int r; |
|
2117 |
2135 |
|
|
2118 |
2136 |
Log(10, "%s Conn_no=%d Conn_max=%d\n", |
Log(10, "%s Conn_no=%d Conn_max=%d\n", |
2119 |
2137 |
__func__, Conn_no, Conn_max); |
__func__, Conn_no, Conn_max); |
|
... |
... |
__hot struct Conn *Conn_alloc(void) |
2125 |
2143 |
} |
} |
2126 |
2144 |
|
|
2127 |
2145 |
if (unlikely(Conn_free.head == NULL)) { |
if (unlikely(Conn_free.head == NULL)) { |
|
2146 |
|
int r; |
|
2147 |
|
|
2128 |
2148 |
r = pool_grow(&Conn_free, 4); |
r = pool_grow(&Conn_free, 4); |
2129 |
2149 |
if (unlikely(r != 0)) { |
if (unlikely(r != 0)) { |
2130 |
2150 |
snprintf(Conn_error, sizeof(Conn_error), |
snprintf(Conn_error, sizeof(Conn_error), |
|
... |
... |
__hot struct Conn *Conn_alloc(void) |
2147 |
2167 |
__hot static struct Conn *Conn_alloc_worker(struct Conn_wpool_worker *w) |
__hot static struct Conn *Conn_alloc_worker(struct Conn_wpool_worker *w) |
2148 |
2168 |
{ |
{ |
2149 |
2169 |
struct Conn *C; |
struct Conn *C; |
2150 |
|
int r; |
|
2151 |
2170 |
|
|
2152 |
2171 |
if (unlikely(w->free.head == NULL)) { |
if (unlikely(w->free.head == NULL)) { |
|
2172 |
|
int r; |
|
2173 |
|
|
2153 |
2174 |
r = pool_grow(&w->free, CONN_BULK_ALLOC); |
r = pool_grow(&w->free, CONN_BULK_ALLOC); |
2154 |
2175 |
if (unlikely(r != 0)) { |
if (unlikely(r != 0)) { |
2155 |
2176 |
snprintf(Conn_error, sizeof(Conn_error), |
snprintf(Conn_error, sizeof(Conn_error), |
|
... |
... |
__hot static void Conn_accept(struct Conn *C) |
2296 |
2317 |
*/ |
*/ |
2297 |
2318 |
static inline void Conn_poll_cb(struct Conn *C, const unsigned int revents) |
static inline void Conn_poll_cb(struct Conn *C, const unsigned int revents) |
2298 |
2319 |
{ |
{ |
2299 |
|
char poll_status[16]; |
|
2300 |
|
|
|
2301 |
2320 |
if (unlikely(Conn_debug_level > 5)) { |
if (unlikely(Conn_debug_level > 5)) { |
|
2321 |
|
char poll_status[16]; |
|
2322 |
|
|
2302 |
2323 |
Conn_poll_status(revents, poll_status); |
Conn_poll_status(revents, poll_status); |
2303 |
2324 |
Log(0, "%llu %s revents=%s\n", |
Log(0, "%llu %s revents=%s\n", |
2304 |
2325 |
C->id, __func__, poll_status); |
C->id, __func__, poll_status); |
|
... |
... |
static inline int Conn_dispatch_events(struct Conn_wpool_worker *w, |
2403 |
2424 |
{ |
{ |
2404 |
2425 |
int i, events; |
int i, events; |
2405 |
2426 |
struct Conn *C; |
struct Conn *C; |
2406 |
|
char sevents[16]; |
|
2407 |
2427 |
ssize_t r; |
ssize_t r; |
2408 |
2428 |
|
|
2409 |
2429 |
Log(10, "%s timeout2=%dms e_size=%hu...\n", __func__, |
Log(10, "%s timeout2=%dms e_size=%hu...\n", __func__, |
|
... |
... |
static inline int Conn_dispatch_events(struct Conn_wpool_worker *w, |
2428 |
2448 |
return 0; |
return 0; |
2429 |
2449 |
|
|
2430 |
2450 |
if (unlikely(Conn_debug_level > 8)) { |
if (unlikely(Conn_debug_level > 8)) { |
|
2451 |
|
char sevents[16]; |
|
2452 |
|
|
2431 |
2453 |
Log(0, "\tProcessing %d event(s):\n", events); |
Log(0, "\tProcessing %d event(s):\n", events); |
2432 |
2454 |
for (i = 0; i < events; i++) { |
for (i = 0; i < events; i++) { |
2433 |
2455 |
C = e[i].data.ptr; |
C = e[i].data.ptr; |
|
... |
... |
void Conn_split_free(struct Conn_split **s) |
2699 |
2721 |
struct Conn_split *Conn_split(const char *line0) |
struct Conn_split *Conn_split(const char *line0) |
2700 |
2722 |
{ |
{ |
2701 |
2723 |
char *p; |
char *p; |
2702 |
|
struct Conn_split *ret = NULL; |
|
|
2724 |
|
struct Conn_split *ret; |
2703 |
2725 |
struct Conn_split_cell *q; |
struct Conn_split_cell *q; |
2704 |
2726 |
char search_for; |
char search_for; |
2705 |
2727 |
char *left, *right; |
char *left, *right; |
|
... |
... |
char *Conn_strerror(void) |
2912 |
2934 |
return Conn_error; |
return Conn_error; |
2913 |
2935 |
} |
} |
2914 |
2936 |
|
|
|
2937 |
|
void Conn_set_error(const char *format, ...) |
|
2938 |
|
{ |
|
2939 |
|
va_list ap; |
|
2940 |
|
|
|
2941 |
|
va_start(ap, format); |
|
2942 |
|
vsnprintf(Conn_error, sizeof(Conn_error), format, ap); |
|
2943 |
|
va_end(ap); |
|
2944 |
|
} |
|
2945 |
|
|
2915 |
2946 |
/* |
/* |
2916 |
2947 |
* Difference between two timeval strutures, in milliseconds |
* Difference between two timeval strutures, in milliseconds |
2917 |
2948 |
*/ |
*/ |
|
... |
... |
int Conn_shutdown(void) |
3045 |
3076 |
*/ |
*/ |
3046 |
3077 |
__hot int Conn_enqueue_wait(struct Conn *C, const void *buf, const unsigned int count) |
__hot int Conn_enqueue_wait(struct Conn *C, const void *buf, const unsigned int count) |
3047 |
3078 |
{ |
{ |
3048 |
|
int r; |
|
3049 |
|
char *dump; |
|
3050 |
|
|
|
3051 |
3079 |
if (unlikely(Conn_debug_level >= 10)) { |
if (unlikely(Conn_debug_level >= 10)) { |
|
3080 |
|
char *dump; |
|
3081 |
|
|
3052 |
3082 |
dump = Conn_dump(buf, count); |
dump = Conn_dump(buf, count); |
3053 |
3083 |
Log(0, "%llu %s Try to enqueue %d byte(s) [%s]...\n", |
Log(0, "%llu %s Try to enqueue %d byte(s) [%s]...\n", |
3054 |
3084 |
C->id, __func__, count, dump); |
C->id, __func__, count, dump); |
|
... |
... |
__hot int Conn_enqueue_wait(struct Conn *C, const void *buf, const unsigned int |
3056 |
3086 |
} |
} |
3057 |
3087 |
|
|
3058 |
3088 |
if (unlikely(C->obuf_size - C->obuf_tail < count)) { |
if (unlikely(C->obuf_size - C->obuf_tail < count)) { |
|
3089 |
|
int r; |
|
3090 |
|
|
3059 |
3091 |
r = Conn_try_expand_buf(C, 0, count); |
r = Conn_try_expand_buf(C, 0, count); |
3060 |
3092 |
if (unlikely(r != 0)) |
if (unlikely(r != 0)) |
3061 |
3093 |
return -1; |
return -1; |
|
... |
... |
__cold static struct Conn *Conn_clone(struct Conn *C) |
3166 |
3198 |
static int Conn_prepare_socket(struct Conn *C, struct sockaddr *bind_psa, |
static int Conn_prepare_socket(struct Conn *C, struct sockaddr *bind_psa, |
3167 |
3199 |
socklen_t bind_sock_len) |
socklen_t bind_sock_len) |
3168 |
3200 |
{ |
{ |
3169 |
|
int fd, i, ret; |
|
|
3201 |
|
int fd, i; |
3170 |
3202 |
|
|
3171 |
3203 |
fd = socket(C->sock_domain, C->sock_type | SOCK_NONBLOCK | SOCK_CLOEXEC, |
fd = socket(C->sock_domain, C->sock_type | SOCK_NONBLOCK | SOCK_CLOEXEC, |
3172 |
3204 |
C->sock_protocol); |
C->sock_protocol); |
|
... |
... |
static int Conn_prepare_socket(struct Conn *C, struct sockaddr *bind_psa, |
3194 |
3226 |
} |
} |
3195 |
3227 |
|
|
3196 |
3228 |
if (C->type == CONN_TYPE_MASTER) { |
if (C->type == CONN_TYPE_MASTER) { |
|
3229 |
|
int ret; |
|
3230 |
|
|
3197 |
3231 |
i = 1; |
i = 1; |
3198 |
3232 |
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); |
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); |
3199 |
3233 |
|
|
File Conn_intern.h changed (mode: 100644) (index 29ae224..9529479) |
... |
... |
struct Conn_pool |
49 |
49 |
struct Conn *head, *tail; |
struct Conn *head, *tail; |
50 |
50 |
unsigned int allocated; |
unsigned int allocated; |
51 |
51 |
unsigned short next_block; |
unsigned short next_block; |
|
52 |
|
unsigned short pad; |
52 |
53 |
void *blocks[4096]; /* TODO: make it dynamic */ |
void *blocks[4096]; /* TODO: make it dynamic */ |
53 |
54 |
}; |
}; |
54 |
55 |
|
|
55 |
56 |
struct Conn_wpool_worker |
struct Conn_wpool_worker |
56 |
57 |
{ |
{ |
57 |
58 |
int epoll_fd; |
int epoll_fd; |
|
59 |
|
int timer_fd; |
58 |
60 |
struct epoll_event events[CONN_EVENTS_SLOTS]; |
struct epoll_event events[CONN_EVENTS_SLOTS]; |
59 |
|
unsigned char inited:1; |
|
|
61 |
|
unsigned short inited:1; |
|
62 |
|
unsigned short pad1:15; |
|
63 |
|
unsigned short id; /* Used for logging */ |
60 |
64 |
int control; /* socket to communicate with parent */ |
int control; /* socket to communicate with parent */ |
61 |
65 |
pid_t pid; |
pid_t pid; |
|
66 |
|
int pad2; |
62 |
67 |
struct Conn *conns_head, *conns_tail; |
struct Conn *conns_head, *conns_tail; |
63 |
|
unsigned short id; /* Used for logging */ |
|
64 |
|
int timer_fd; |
|
65 |
68 |
|
|
66 |
69 |
/* Keep track of free structures */ |
/* Keep track of free structures */ |
67 |
70 |
struct Conn_pool free; |
struct Conn_pool free; |
|
... |
... |
struct Conn_wpool |
75 |
78 |
{ |
{ |
76 |
79 |
int epoll_fd; |
int epoll_fd; |
77 |
80 |
unsigned short workers; |
unsigned short workers; |
78 |
|
struct Conn_wpool_worker *ww; |
|
79 |
81 |
unsigned short next; /* next worker to be choosen */ |
unsigned short next; /* next worker to be choosen */ |
80 |
82 |
unsigned short refs; |
unsigned short refs; |
|
83 |
|
unsigned short pad1; |
|
84 |
|
unsigned int pad2; |
|
85 |
|
struct Conn_wpool_worker *ww; |
81 |
86 |
}; |
}; |
82 |
87 |
|
|
83 |
88 |
/* |
/* |
|
... |
... |
struct Conn |
107 |
112 |
unsigned char state; |
unsigned char state; |
108 |
113 |
unsigned char error_state; |
unsigned char error_state; |
109 |
114 |
|
|
110 |
|
char *ibuf; |
|
111 |
|
unsigned int ibuf_size, ibuf_head, ibuf_tail; |
|
|
115 |
|
/* Flags */ |
|
116 |
|
unsigned char auto_reconnect:1; |
|
117 |
|
unsigned char close_after_send:1; |
|
118 |
|
unsigned char shutdown_after_send:1; |
|
119 |
|
unsigned char local_dirty:1; |
|
120 |
|
unsigned char remote_dirty:1; |
|
121 |
|
unsigned char pad1:3; |
112 |
122 |
|
|
113 |
|
char *obuf; |
|
|
123 |
|
unsigned int ibuf_size, ibuf_head, ibuf_tail; |
114 |
124 |
unsigned int obuf_size, obuf_head, obuf_tail; |
unsigned int obuf_size, obuf_head, obuf_tail; |
|
125 |
|
char *ibuf; |
|
126 |
|
char *obuf; |
115 |
127 |
|
|
116 |
128 |
struct timeval trecv, tsend; /* last time we saw an receive/send */ |
struct timeval trecv, tsend; /* last time we saw an receive/send */ |
117 |
129 |
unsigned int idle; /* idle time allowed TODO: ms? */ |
unsigned int idle; /* idle time allowed TODO: ms? */ |
|
... |
... |
struct Conn |
130 |
142 |
char addr[40], bind_addr[40]; |
char addr[40], bind_addr[40]; |
131 |
143 |
int port, bind_port; |
int port, bind_port; |
132 |
144 |
|
|
|
145 |
|
struct Conn_cbs cbs; /* Specific callbacks */ |
|
146 |
|
|
133 |
147 |
unsigned long long bi, bo; |
unsigned long long bi, bo; |
134 |
148 |
|
|
135 |
149 |
void *private; /* private use by user */ |
void *private; /* private use by user */ |
136 |
150 |
|
|
|
151 |
|
time_t start; |
|
152 |
|
|
|
153 |
|
unsigned long long id; /* the id of a connection */ |
|
154 |
|
|
|
155 |
|
int xerrno; |
|
156 |
|
|
137 |
157 |
/* reconnect stuff */ |
/* reconnect stuff */ |
138 |
158 |
unsigned int retries; |
unsigned int retries; |
139 |
159 |
unsigned int delay; /* delay between reconnects */ |
unsigned int delay; /* delay between reconnects */ |
140 |
160 |
unsigned int tryat; /* when we go to CONNECT_a state */ |
unsigned int tryat; /* when we go to CONNECT_a state */ |
141 |
161 |
|
|
142 |
|
int xerrno; |
|
143 |
|
|
|
144 |
|
time_t start; |
|
145 |
|
|
|
146 |
|
/* Flags - TODO: remove 'flags' field */ |
|
147 |
|
unsigned char auto_reconnect:1; |
|
148 |
|
unsigned char close_after_send:1; |
|
149 |
|
unsigned char shutdown_after_send:1; |
|
150 |
|
unsigned char local_dirty:1; |
|
151 |
|
unsigned char remote_dirty:1; |
|
152 |
|
|
|
153 |
162 |
/* bandwidth stuff */ |
/* bandwidth stuff */ |
154 |
|
struct timeval band_lasttime; /* last time tokens were added */ |
|
155 |
163 |
unsigned int band_tokens; /* 1 token -> 1000 bytes */ |
unsigned int band_tokens; /* 1 token -> 1000 bytes */ |
156 |
164 |
unsigned int band_factor; /* tokens cannot go past f * w */ |
unsigned int band_factor; /* tokens cannot go past f * w */ |
|
165 |
|
struct timeval band_lasttime; /* last time tokens were added */ |
157 |
166 |
unsigned int band_width; /* in 1000b increments */ |
unsigned int band_width; /* in 1000b increments */ |
158 |
167 |
|
|
159 |
|
unsigned long long id; /* the id of a connection */ |
|
160 |
|
|
|
161 |
|
struct Conn_cbs cbs; /* Specific callbacks */ |
|
162 |
|
|
|
|
168 |
|
unsigned int pad2; |
163 |
169 |
struct timeval time_open; /* When a connect succeded */ /* TODO: why not use start? */ |
struct timeval time_open; /* When a connect succeded */ /* TODO: why not use start? */ |
164 |
170 |
|
|
165 |
171 |
/* wpool */ |
/* wpool */ |
166 |
172 |
struct Conn_wpool *wp; /* Worker pool associated with this conn */ |
struct Conn_wpool *wp; /* Worker pool associated with this conn */ |
167 |
|
struct Conn_wpool_worker *worker; /* used to link C in active list of a worker */ |
|
|
173 |
|
struct Conn_wpool_worker |
|
174 |
|
*worker; /* used to link C in active list of a worker */ |
168 |
175 |
|
|
169 |
176 |
/* web server */ |
/* web server */ |
170 |
177 |
struct Conn_web *web; /* everything needed for web (urls etc.) - common for all childs */ |
struct Conn_web *web; /* everything needed for web (urls etc.) - common for all childs */ |
|
... |
... |
struct Conn_web_url |
190 |
197 |
char *path; |
char *path; |
191 |
198 |
void (*cb)(struct Conn *); |
void (*cb)(struct Conn *); |
192 |
199 |
unsigned char type:1; /* CONN_WEB_TYPE_* */ |
unsigned char type:1; /* CONN_WEB_TYPE_* */ |
|
200 |
|
unsigned char pad1:7; |
|
201 |
|
unsigned char pad2[7]; |
193 |
202 |
}; |
}; |
194 |
203 |
|
|
195 |
204 |
struct Conn_web |
struct Conn_web |
|
... |
... |
struct Conn_web |
200 |
209 |
struct Conn_web_request |
struct Conn_web_request |
201 |
210 |
{ |
{ |
202 |
211 |
unsigned char req_type:2; /* CONN_WEB_REQ_* */ /* TODO: replace with string representation to support more types? */ |
unsigned char req_type:2; /* CONN_WEB_REQ_* */ /* TODO: replace with string representation to support more types? */ |
|
212 |
|
unsigned char pad1:6; |
|
213 |
|
unsigned char http_protocol; /* 10, 11, 20 etc. */ |
|
214 |
|
unsigned char pad2[6]; |
203 |
215 |
char *url; /* requested url */ |
char *url; /* requested url */ |
204 |
216 |
char *paras; /* parameters */ /* TODO: should be make NULL after first request? */ |
char *paras; /* parameters */ /* TODO: should be make NULL after first request? */ |
205 |
|
unsigned char http_protocol; /* 10, 11, 20 etc. */ |
|
206 |
217 |
char *header; |
char *header; |
207 |
218 |
struct Conn_web_url *u; /* used for websocket */ /* TODO: really used? */ |
struct Conn_web_url *u; /* used for websocket */ /* TODO: really used? */ |
208 |
219 |
}; |
}; |
|
... |
... |
struct Conn_split_cell |
214 |
225 |
char *left; |
char *left; |
215 |
226 |
char *right; |
char *right; |
216 |
227 |
unsigned int right_len; |
unsigned int right_len; |
|
228 |
|
unsigned int pad; |
217 |
229 |
}; |
}; |
218 |
230 |
|
|
219 |
231 |
struct Conn_split |
struct Conn_split |
File Conn_web.c changed (mode: 100644) (index 14e0d5b..95be3de) |
... |
... |
void Conn_web_dispatch(struct Conn *C) |
200 |
200 |
struct Conn_web_url *u = NULL; |
struct Conn_web_url *u = NULL; |
201 |
201 |
char *end_header, *start_header, *sep, *url, *paras = ""; |
char *end_header, *start_header, *sep, *url, *paras = ""; |
202 |
202 |
char tmp[128]; |
char tmp[128]; |
203 |
|
unsigned char http_protocol = 11, tmp8; |
|
|
203 |
|
unsigned char http_protocol = 11; |
204 |
204 |
unsigned char req_type = 0; |
unsigned char req_type = 0; |
205 |
205 |
|
|
206 |
|
if (C->web_req->u) { |
|
207 |
|
Log(2, "%llu %s We have C->web_req->u; just call the callback\n", |
|
208 |
|
C->id, __func__); |
|
|
206 |
|
Log(10, "%llu %s\n", C->id, __func__); |
|
207 |
|
|
|
208 |
|
if (C->web_req->u) { // This is for websocket |
|
209 |
|
Log(10, "\tWe have C->web_req->u; just call the callback\n"); |
209 |
210 |
C->web_req->u->cb(C); |
C->web_req->u->cb(C); |
210 |
211 |
return; |
return; |
211 |
212 |
} |
} |
212 |
213 |
|
|
213 |
214 |
url = Conn_ibuf(C); |
url = Conn_ibuf(C); |
214 |
|
Log(1, "\turl=%s\n", url); |
|
215 |
215 |
|
|
216 |
216 |
end_header = Conn_strstr(C, "\r\n\r\n"); |
end_header = Conn_strstr(C, "\r\n\r\n"); |
217 |
217 |
if (end_header == NULL) |
if (end_header == NULL) |
|
... |
... |
void Conn_web_dispatch(struct Conn *C) |
220 |
220 |
/* parsing first line */ |
/* parsing first line */ |
221 |
221 |
sep = Conn_strstr(C, "\r\n"); |
sep = Conn_strstr(C, "\r\n"); |
222 |
222 |
*sep = '\0'; |
*sep = '\0'; |
223 |
|
start_header = sep + 1; |
|
|
223 |
|
start_header = sep + 2; |
|
224 |
|
|
|
225 |
|
Log(20, "\turl=%s\n", url); |
|
226 |
|
Log(20, "\theaders:\n%s\n", start_header); |
224 |
227 |
|
|
225 |
228 |
if (strncmp(url, "GET ", 4) == 0) { |
if (strncmp(url, "GET ", 4) == 0) { |
226 |
229 |
req_type = CONN_WEB_REQ_GET; |
req_type = CONN_WEB_REQ_GET; |
|
... |
... |
void Conn_web_dispatch(struct Conn *C) |
242 |
245 |
sep = strchr(url, ' '); |
sep = strchr(url, ' '); |
243 |
246 |
if (sep) |
if (sep) |
244 |
247 |
*sep = '\0'; |
*sep = '\0'; |
245 |
|
Log(2, "\tRequest req_type=%s [%s]!\n", |
|
|
248 |
|
Log(10, "\tRequest req_type=%s [%s]!\n", |
246 |
249 |
Conn_web_req_type(req_type), url); |
Conn_web_req_type(req_type), url); |
247 |
250 |
|
|
248 |
251 |
/* TODO: parse HTTP type */ |
/* TODO: parse HTTP type */ |
249 |
252 |
if (sep) { |
if (sep) { |
250 |
253 |
sep = strstr(sep + 1, "HTTP/"); |
sep = strstr(sep + 1, "HTTP/"); |
251 |
254 |
if (sep) { |
if (sep) { |
|
255 |
|
unsigned char tmp8; |
|
256 |
|
|
252 |
257 |
sep += 5; |
sep += 5; |
253 |
258 |
tmp8 = (unsigned char)(sep[0] - '0'); |
tmp8 = (unsigned char)(sep[0] - '0'); |
254 |
259 |
if ((sep[1] == '.') && (sep[2] != '\0')) |
if ((sep[1] == '.') && (sep[2] != '\0')) |
|
... |
... |
void Conn_web_dispatch(struct Conn *C) |
267 |
272 |
char *dump; |
char *dump; |
268 |
273 |
int match; |
int match; |
269 |
274 |
|
|
270 |
|
Log(2, "\tComparing [%s] with [%s]...\n", |
|
|
275 |
|
Log(10, "\tComparing [%s] with [%s]...\n", |
271 |
276 |
url, u->url); |
url, u->url); |
272 |
277 |
|
|
273 |
278 |
if (u->type == CONN_WEB_TYPE_PATH) |
if (u->type == CONN_WEB_TYPE_PATH) |
|
... |
... |
void Conn_web_dispatch(struct Conn *C) |
287 |
292 |
C->web_req->header = start_header; |
C->web_req->header = start_header; |
288 |
293 |
Conn_eat(C, end_header + 4 - Conn_ibuf(C)); |
Conn_eat(C, end_header + 4 - Conn_ibuf(C)); |
289 |
294 |
dump = Conn_dump(Conn_ibuf(C), Conn_iqlen(C)); |
dump = Conn_dump(Conn_ibuf(C), Conn_iqlen(C)); |
290 |
|
Log(0, "\tNOW ibuf (after eating header): [%s]\n", dump); |
|
|
295 |
|
Log(20, "\tNOW ibuf (after eating header): [%s]\n", dump); |
291 |
296 |
free(dump); |
free(dump); |
292 |
297 |
|
|
293 |
298 |
if (u->type == CONN_WEB_TYPE_PATH) { |
if (u->type == CONN_WEB_TYPE_PATH) { |
294 |
299 |
Conn_web_dispatch_path(C, u); |
Conn_web_dispatch_path(C, u); |
295 |
300 |
} else { |
} else { |
296 |
|
Log(0, "\tDEBUG: Set C->web->u!\n"); |
|
|
301 |
|
Log(20, "\tDEBUG: Set C->web->u!\n"); |
297 |
302 |
C->web_req->u = u; |
C->web_req->u = u; |
298 |
303 |
u->cb(C); |
u->cb(C); |
299 |
304 |
} |
} |
|
... |
... |
int Conn_web_header_lookup(char *out, const size_t out_size, |
351 |
356 |
|
|
352 |
357 |
hlen = strlen(h); |
hlen = strlen(h); |
353 |
358 |
while (1) { |
while (1) { |
354 |
|
Log(20, "\tpos=%p: %s\n", pos, pos); |
|
|
359 |
|
Log(20, "\tpos=%p [%c]\n", pos, pos[0]); |
355 |
360 |
if (strncmp(pos, "\r\n", 2) == 0) |
if (strncmp(pos, "\r\n", 2) == 0) |
356 |
361 |
return -1; |
return -1; |
357 |
362 |
|
|
|
... |
... |
int Conn_web_header_lookup(char *out, const size_t out_size, |
375 |
380 |
|
|
376 |
381 |
i = 0; |
i = 0; |
377 |
382 |
while (1) { |
while (1) { |
378 |
|
if ((i == out_size - 1) || (*pos == '\r')) { |
|
|
383 |
|
if ((i == out_size - 1) || (*pos == '\r') |
|
384 |
|
|| (*pos == '\n')) { |
379 |
385 |
out[i] = '\0'; |
out[i] = '\0'; |
380 |
386 |
return 1; |
return 1; |
381 |
387 |
} |
} |
|
... |
... |
int Conn_web_ws_parse(struct Conn_web_ws *w, struct Conn *C) |
466 |
472 |
Conn_eat(C, 2); |
Conn_eat(C, 2); |
467 |
473 |
|
|
468 |
474 |
if (w->opcode == 0x8) { |
if (w->opcode == 0x8) { |
469 |
|
Log(20, "\tremote sent close opcode\n"); |
|
|
475 |
|
Conn_set_error("remote sent close opcode"); |
470 |
476 |
return -1; |
return -1; |
471 |
477 |
} |
} |
472 |
478 |
|
|
473 |
479 |
if (unlikely(w->opcode != 0x1)) { |
if (unlikely(w->opcode != 0x1)) { |
474 |
|
Log(20, "\topcode is not 'text' (%hhu)\n", w->opcode); |
|
|
480 |
|
Conn_set_error("opcode is not 'text' (%hhu)", w->opcode); |
475 |
481 |
return -1; |
return -1; |
476 |
482 |
} |
} |
477 |
483 |
|
|
478 |
484 |
if (w->mask != 1) { |
if (w->mask != 1) { |
479 |
|
Log(20, "\tinput is not masked!\n"); |
|
|
485 |
|
Conn_set_error("input is not masked"); |
480 |
486 |
return -1; |
return -1; |
481 |
487 |
} |
} |
482 |
488 |
|
|
File examples/websocket1.c changed (mode: 100644) (index 422a5ed..38bdb13) |
18 |
18 |
#include <json.h> |
#include <json.h> |
19 |
19 |
|
|
20 |
20 |
/* Global variables */ |
/* Global variables */ |
21 |
|
static unsigned short debug = 20; |
|
|
21 |
|
static unsigned short debug = 1; // recommended 1 for production |
|
22 |
|
|
|
23 |
|
// Private data per client |
|
24 |
|
struct priv { |
|
25 |
|
char name[32]; |
|
26 |
|
}; |
22 |
27 |
|
|
23 |
28 |
struct Clients |
struct Clients |
24 |
29 |
{ |
{ |
|
... |
... |
static struct Clients *Clients_head, *Clients_tail; |
30 |
35 |
static void dump_Clients(void) |
static void dump_Clients(void) |
31 |
36 |
{ |
{ |
32 |
37 |
struct Clients *q; |
struct Clients *q; |
|
38 |
|
struct priv *priv; |
33 |
39 |
|
|
34 |
|
Log(0, "Dumping Clients:\n"); |
|
|
40 |
|
Log(10, "Dumping Clients:\n"); |
35 |
41 |
|
|
36 |
42 |
q = Clients_head; |
q = Clients_head; |
37 |
43 |
while (q) { |
while (q) { |
38 |
|
Log(0, "\tq=%p q->next=%p q->C->id=%llu\n", q, q->next, Conn_get_id(q->C)); |
|
|
44 |
|
priv = Conn_get_private(q->C); |
|
45 |
|
Log(10, "\tq=%p q->next=%p q->C->id=%llu name=%s\n", |
|
46 |
|
q, q->next, Conn_get_id(q->C), priv->name); |
39 |
47 |
q = q->next; |
q = q->next; |
40 |
48 |
} |
} |
41 |
49 |
} |
} |
|
... |
... |
static void dump_Clients(void) |
43 |
51 |
static void accept_cb(struct Conn *C) |
static void accept_cb(struct Conn *C) |
44 |
52 |
{ |
{ |
45 |
53 |
struct Clients *q; |
struct Clients *q; |
|
54 |
|
struct priv *priv; |
46 |
55 |
|
|
47 |
|
Log(0, "%llu %s\n", Conn_get_id(C), __func__); |
|
|
56 |
|
Log(1, "%llu %s from %s/%d\n", Conn_get_id(C), __func__, |
|
57 |
|
Conn_addr_remote(C), Conn_port_remote(C)); |
|
58 |
|
|
|
59 |
|
priv = malloc(sizeof(struct priv)); |
|
60 |
|
if (!priv) { |
|
61 |
|
Log(0, "\tCannot alloc memory for private area!\n"); |
|
62 |
|
Conn_close(C); |
|
63 |
|
return; |
|
64 |
|
} |
|
65 |
|
memset(priv, 0, sizeof(struct priv)); |
|
66 |
|
Conn_set_private(C, priv); |
48 |
67 |
|
|
49 |
68 |
q = malloc(sizeof(struct Clients)); |
q = malloc(sizeof(struct Clients)); |
50 |
69 |
if (!q) { |
if (!q) { |
|
... |
... |
static void process_json(struct Conn *C, struct json_object *j) |
100 |
119 |
const char *s_op, *s_answer, *s_text; |
const char *s_op, *s_answer, *s_text; |
101 |
120 |
struct json_object *op, *answer, *text; |
struct json_object *op, *answer, *text; |
102 |
121 |
struct Clients *q; |
struct Clients *q; |
|
122 |
|
struct priv *priv; |
103 |
123 |
|
|
104 |
|
Log(0, "%llu %s\n", Conn_get_id(C), __func__); |
|
|
124 |
|
Log(10, "%llu %s\n", Conn_get_id(C), __func__); |
105 |
125 |
|
|
106 |
|
Log(0, "json:\n%s\n", json_object_to_json_string_ext(j, |
|
|
126 |
|
priv = Conn_get_private(C); |
|
127 |
|
|
|
128 |
|
Log(10, "json:\n%s\n", json_object_to_json_string_ext(j, |
107 |
129 |
JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY)); |
JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY)); |
108 |
130 |
|
|
109 |
131 |
json_object_object_get_ex(j, "op", &op); |
json_object_object_get_ex(j, "op", &op); |
110 |
|
Log(0, "op=%p\n", op); |
|
111 |
132 |
s_op = json_object_get_string(op); |
s_op = json_object_get_string(op); |
112 |
133 |
if (!s_op) { |
if (!s_op) { |
113 |
134 |
Log(0, "\tNo s_op! Ignore it!\n"); |
Log(0, "\tNo s_op! Ignore it!\n"); |
114 |
135 |
return; |
return; |
115 |
136 |
} |
} |
116 |
|
Log(0, "\ts_op=[%s]\n", s_op); |
|
|
137 |
|
Log(10, "\ts_op=[%s]\n", s_op); |
117 |
138 |
|
|
118 |
139 |
answer = json_object_new_object(); |
answer = json_object_new_object(); |
119 |
140 |
if (!answer) { |
if (!answer) { |
|
... |
... |
static void process_json(struct Conn *C, struct json_object *j) |
122 |
143 |
return; |
return; |
123 |
144 |
} |
} |
124 |
145 |
|
|
125 |
|
if (strcmp(s_op, "ping") == 0) { |
|
126 |
|
Log(0, "\tWe have a ping!\n"); |
|
127 |
|
json_object_object_add(answer, "answer", |
|
128 |
|
json_object_new_string("answer value - ping")); |
|
|
146 |
|
if (strcmp(s_op, "init") == 0) { |
|
147 |
|
json_object_object_get_ex(j, "version", &text); |
|
148 |
|
s_text = json_object_get_string(text); |
|
149 |
|
|
|
150 |
|
Log(10, "\tWe have an init command [version=%s]!\n", s_text); |
|
151 |
|
json_object_object_add(answer, "op", |
|
152 |
|
json_object_new_string("init")); |
|
153 |
|
json_object_object_add(answer, "id", |
|
154 |
|
json_object_new_int64(Conn_get_id(C))); |
129 |
155 |
s_answer = json_object_to_json_string(answer); |
s_answer = json_object_to_json_string(answer); |
130 |
156 |
Conn_web_ws_enqueue(C, 1, 1, s_answer, strlen(s_answer)); |
Conn_web_ws_enqueue(C, 1, 1, s_answer, strlen(s_answer)); |
131 |
157 |
json_object_put(answer); |
json_object_put(answer); |
132 |
158 |
return; |
return; |
133 |
159 |
} |
} |
134 |
160 |
|
|
135 |
|
if (strcmp(s_op, "click") == 0) { |
|
136 |
|
Log(0, "\tWe have a click!\n"); |
|
137 |
|
json_object_object_add(answer, "answer", |
|
138 |
|
json_object_new_string("answer value - click")); |
|
|
161 |
|
if (strcmp(s_op, "ka") == 0) { |
|
162 |
|
Log(10, "\tWe have a ka!\n"); |
|
163 |
|
json_object_object_add(answer, "op", |
|
164 |
|
json_object_new_string("ka")); |
139 |
165 |
s_answer = json_object_to_json_string(answer); |
s_answer = json_object_to_json_string(answer); |
140 |
166 |
Conn_web_ws_enqueue(C, 1, 1, s_answer, strlen(s_answer)); |
Conn_web_ws_enqueue(C, 1, 1, s_answer, strlen(s_answer)); |
141 |
167 |
json_object_put(answer); |
json_object_put(answer); |
142 |
168 |
return; |
return; |
143 |
169 |
} |
} |
144 |
170 |
|
|
145 |
|
if (strcmp(s_op, "status") == 0) { |
|
146 |
|
Log(0, "\tWe have a status!\n"); |
|
147 |
|
json_object_object_add(answer, "answer", |
|
148 |
|
json_object_new_string("answer value - status")); |
|
149 |
|
s_answer = json_object_to_json_string(answer); |
|
150 |
|
Conn_web_ws_enqueue(C, 1, 1, s_answer, strlen(s_answer)); |
|
151 |
|
json_object_put(answer); |
|
|
171 |
|
if (strcmp(s_op, "set_name") == 0) { |
|
172 |
|
json_object_object_get_ex(j, "name", &text); |
|
173 |
|
s_text = json_object_get_string(text); |
|
174 |
|
Log(10, "\tWe have a set_name [%s]!\n", s_text); |
|
175 |
|
snprintf(priv->name, sizeof(priv->name), "%s", s_text); |
|
176 |
|
// TODO: notify everybody? |
|
177 |
|
// We do not answer |
152 |
178 |
return; |
return; |
153 |
179 |
} |
} |
154 |
180 |
|
|
155 |
181 |
if (strcmp(s_op, "msg") == 0) { |
if (strcmp(s_op, "msg") == 0) { |
|
182 |
|
char name[64]; |
156 |
183 |
|
|
157 |
184 |
json_object_object_get_ex(j, "text", &text); |
json_object_object_get_ex(j, "text", &text); |
158 |
185 |
s_text = json_object_get_string(text); |
s_text = json_object_get_string(text); |
159 |
|
Log(0, "\tWe have a msg [%s]!\n", s_text); |
|
160 |
|
|
|
161 |
|
json_object_object_add(answer, "answer", |
|
|
186 |
|
Log(10, "\tWe have a msg [%s]!\n", s_text); |
|
187 |
|
|
|
188 |
|
json_object_object_add(answer, "op", |
|
189 |
|
json_object_new_string("msg")); |
|
190 |
|
if (priv->name[0] == '\0') |
|
191 |
|
snprintf(name, sizeof(name), "%llu", Conn_get_id(C)); |
|
192 |
|
else |
|
193 |
|
snprintf(name, sizeof(name), "%s[%llu]", priv->name, Conn_get_id(C)); |
|
194 |
|
json_object_object_add(answer, "from", |
|
195 |
|
json_object_new_string(name)); |
|
196 |
|
json_object_object_add(answer, "msg", |
162 |
197 |
json_object_new_string(s_text)); |
json_object_new_string(s_text)); |
163 |
198 |
s_answer = json_object_to_json_string(answer); |
s_answer = json_object_to_json_string(answer); |
164 |
199 |
|
|
|
... |
... |
static void process_json(struct Conn *C, struct json_object *j) |
182 |
217 |
|
|
183 |
218 |
static void ws1(struct Conn *C) |
static void ws1(struct Conn *C) |
184 |
219 |
{ |
{ |
185 |
|
char *dump; |
|
|
220 |
|
char *dump, ip[64]; |
186 |
221 |
int r; |
int r; |
187 |
222 |
struct Conn_web_ws w; |
struct Conn_web_ws w; |
188 |
223 |
struct json_object *json; |
struct json_object *json; |
189 |
224 |
|
|
190 |
|
Log(0, "%llu %s\n", Conn_get_id(C), __func__); |
|
|
225 |
|
Log(5, "%llu %s\n", Conn_get_id(C), __func__); |
191 |
226 |
|
|
192 |
227 |
if (!Conn_web_is_ws(C)) { |
if (!Conn_web_is_ws(C)) { |
|
228 |
|
// Last chanse to extract something from header |
|
229 |
|
Conn_web_header_lookup(ip, sizeof(ip), C, "X-Original-IP"); |
|
230 |
|
Log(0, "IP=%s\n", ip); |
|
231 |
|
|
193 |
232 |
Conn_web_ws_negociate(C); |
Conn_web_ws_negociate(C); |
194 |
233 |
return; |
return; |
195 |
234 |
} |
} |
196 |
235 |
|
|
197 |
|
Log(2, "We already have an established ws connection\n"); |
|
|
236 |
|
Log(5, "\tWe already have an established ws connection\n"); |
198 |
237 |
r = Conn_web_ws_parse(&w, C); |
r = Conn_web_ws_parse(&w, C); |
199 |
238 |
if (r == -1) { |
if (r == -1) { |
200 |
|
Log(0, "\tProtocol erorr!\n"); |
|
|
239 |
|
Log(0, "\tProtocol error: %s!\n", Conn_strerror()); |
201 |
240 |
Conn_close(C); |
Conn_close(C); |
202 |
241 |
return; |
return; |
203 |
242 |
} |
} |
|
... |
... |
static void ws1(struct Conn *C) |
206 |
245 |
return; |
return; |
207 |
246 |
} |
} |
208 |
247 |
|
|
209 |
|
Conn_web_ws_log(&w); |
|
|
248 |
|
if (debug > 10) |
|
249 |
|
Conn_web_ws_log(&w); |
210 |
250 |
|
|
211 |
251 |
dump = Conn_dump(Conn_ibuf(C), Conn_iqlen(C)); |
dump = Conn_dump(Conn_ibuf(C), Conn_iqlen(C)); |
212 |
|
Log(0, "\tReceived: %s\n", dump); |
|
|
252 |
|
Log(5, "\tReceived: %s\n", dump); |
213 |
253 |
free(dump); |
free(dump); |
214 |
254 |
|
|
215 |
255 |
json = json_tokener_parse(Conn_ibuf(C)); |
json = json_tokener_parse(Conn_ibuf(C)); |