aboutsummaryrefslogtreecommitdiffstats
path: root/thirdparty/apps/testapp/lb
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/apps/testapp/lb')
-rw-r--r--thirdparty/apps/testapp/lb/api.h169
-rw-r--r--thirdparty/apps/testapp/lb/lb.c1290
-rw-r--r--thirdparty/apps/testapp/lb/lb.h731
3 files changed, 2190 insertions, 0 deletions
diff --git a/thirdparty/apps/testapp/lb/api.h b/thirdparty/apps/testapp/lb/api.h
new file mode 100644
index 0000000..f930227
--- /dev/null
+++ b/thirdparty/apps/testapp/lb/api.h
@@ -0,0 +1,169 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _API_H_
+#define _API_H_
+
+#if defined(NSOCKET)
+#define VERSION_NAME "NSTACK"
+#define _socket nstack_socket
+#define _fcntl nstack_fcntl
+#define _bind nstack_bind
+#define _listen nstack_listen
+#define _accept nstack_accept
+#define _accept4 nstack_accept4
+#define _connect nstack_connect
+#define _close nstack_close
+#define _shutdown nstack_shutdown
+#define _recv nstack_recv
+#define _send nstack_send
+#define _getsockname nstack_getsockname
+#define _getpeername nstack_getpeername
+#define _getsockopt nstack_getsockopt
+#define _setsockopt nstack_setsockopt
+#define _recvfrom nstack_recvfrom
+#define _sendto nstack_sendto
+#define _read nstack_read
+#define _write nstack_write
+#define _epoll_create nstack_epoll_create
+#define _epoll_ctl nstack_epoll_ctl
+#define _epoll_wait nstack_epoll_wait
+#elif defined(LWIP)
+#define VERSION_NAME "LWIP"
+#define _socket lwip_socket
+#define _fcntl lwip_fcntl
+#define _bind lwip_bind
+#define _listen lwip_listen
+#define _accept lwip_accept
+#define _accept4 lwip_accept4
+#define _connect lwip_connect
+#define _close lwip_close
+#define _shutdown lwip_shutdown
+#define _recv lwip_recv
+#define _send lwip_send
+#define _getsockname lwip_getsockname
+#define _getpeername lwip_getpeername
+#define _getsockopt lwip_getsockopt
+#define _setsockopt lwip_setsockopt
+#define _recvfrom lwip_recvfrom
+#define _sendto lwip_sendto
+#define _read lwip_read
+#define _write lwip_write
+#define _epoll_create lwip_epoll_create
+#define _epoll_ctl lwip_epoll_ctl
+#define _epoll_wait lwip_epoll_wait
+#else
+#define VERSION_NAME "POSIX"
+#define _socket socket
+#define _fcntl fcntl
+#define _bind bind
+#define _listen listen
+#define _accept accept
+#define _accept4 accept4
+#define _connect connect
+#define _close close
+#define _shutdown shutdown
+#define _recv recv
+#define _send send
+#define _getsockname getsockname
+#define _getpeername getpeername
+#define _getsockopt getsockopt
+#define _setsockopt setsockopt
+#define _recvfrom recvfrom
+#define _sendto sendto
+#define _read read
+#define _write write
+#define _epoll_create epoll_create
+#define _epoll_ctl epoll_ctl
+#define _epoll_wait epoll_wait
+#endif
+
+#endif /* #ifndef _API_H_ */
+
+#ifndef SOCKET_WARP_LB_H_
+#define SOCKET_WARP_LB_H_
+
+inline static int
+set_nonblock_v (int fd, int nonblock)
+{
+ int fl = _fcntl (fd, F_GETFL, 0);
+
+ if (fl < 0)
+ return fl;
+
+ if (nonblock)
+ {
+ if (fl & O_NONBLOCK)
+ return 0;
+ fl |= O_NONBLOCK;
+ }
+ else
+ {
+ if (0 == (fl & O_NONBLOCK))
+ return 0;
+ fl &= ~(O_NONBLOCK);
+ }
+
+ return _fcntl (fd, F_SETFL, fl | O_NONBLOCK);
+}
+
+inline static int
+set_nonblock (int fd)
+{
+ int fl = _fcntl (fd, F_GETFL, 0);
+ if (fl < 0)
+ return fl;
+ return _fcntl (fd, F_SETFL, fl | O_NONBLOCK);
+}
+
+inline static int
+set_nodelay (int fd, int nodelay)
+{
+ return _setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay,
+ sizeof (nodelay));
+}
+
+inline static int
+set_rcvtimeo (int fd, int us)
+{
+ struct timeval timeout = {.tv_sec = us / USOFS,.tv_usec = us % USOFS };
+ return _setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
+ sizeof (timeout));
+}
+
+inline static int
+set_reuseaddr (int fd, int reuseaddr)
+{
+ return _setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuseaddr,
+ sizeof (reuseaddr));
+}
+
+inline static int
+set_reuseport (int fd, int reuseport)
+{
+ return _setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (char *) &reuseport,
+ sizeof (reuseport));
+}
+
+inline static int
+set_sndtimeo (int fd, int us)
+{
+ struct timeval timeout = {.tv_sec = us / USOFS,.tv_usec = us % USOFS };
+ return _setsockopt (fd, SOL_SOCKET, SO_SNDTIMEO, &timeout,
+ sizeof (timeout));
+}
+
+#endif /* #ifndef SOCKET_WARP_LB_H_ */
diff --git a/thirdparty/apps/testapp/lb/lb.c b/thirdparty/apps/testapp/lb/lb.c
new file mode 100644
index 0000000..058ddce
--- /dev/null
+++ b/thirdparty/apps/testapp/lb/lb.c
@@ -0,0 +1,1290 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "lb.h"
+
+int enable_debug = 1;
+
+#ifdef COLOR_LB_H_
+
+const static struct lb_color lb_color_list[2] = {
+ [LB_DEF_COLOR] = {
+ .clear = "\033[0m",
+ .high = "\033[1m",
+ .uline = "\033[4m",
+ .flash = "\033[5m",
+ .rev = "\033[7m",
+
+ .fblack = "\033[30m",
+ .fr__ = "\033[31m",
+ .f_g_ = "\033[32m",
+ .f__b = "\033[34m",
+ .frg_ = "\033[33m",
+ .fr_b = "\033[35m",
+ .f_gb = "\033[36m",
+ .fwhite = "\033[37m",
+
+ .bblack = "\033[40m",
+ .br__ = "\033[41m",
+ .b_g_ = "\033[42m",
+ .b__b = "\033[44m",
+ .brg_ = "\033[43m",
+ .br_b = "\033[45m",
+ .b_gb = "\033[46m",
+ .bwhite = "\033[47m",
+ },
+ [LB_NO_COLOR] = {
+ .clear = "",
+ .high = "",
+ .uline = "",
+ .flash = "",
+ .rev = "",
+
+ .fblack = "",
+ .fr__ = "",
+ .f_g_ = "",
+ .f__b = "",
+ .frg_ = "",
+ .fr_b = "",
+ .f_gb = "",
+ .fwhite = "",
+
+ .bblack = "",
+ .br__ = "",
+ .b_g_ = "",
+ .b__b = "",
+ .brg_ = "",
+ .br_b = "",
+ .b_gb = "",
+ .bwhite = "",
+ },
+};
+
+const struct lb_color *lb_color = &lb_color_list[0];
+int lb_color_index = 0;
+
+void
+lb_set_color (int index)
+{
+ lb_color_index = index;
+ lb_color = &lb_color_list[index];
+}
+
+#endif
+
+#ifdef FORMAT_LB_H_
+
+static __thread char s_fmt_buf[64][64];
+static __thread uint32_t s_fmt_id = 0;
+
+#if 0
+const char *
+f_in6 (const struct in6_addr *ip6)
+{
+ char *buf = s_fmt_buf[(s_fmt_id++) & 63];
+ char *p = buf;
+ int i;
+
+ for (i = 0; i < 8; ++i)
+ {
+ uint16_t c, v = htons (ip6->s6_addr16[i]);
+
+ c = v >> 12;
+ if (c > 9)
+ *p++ = 'A' + c - 10;
+ else if (c > 0)
+ *p++ = '0' + c;
+
+ c = (v >> 8) & 0xF;
+ if (c > 9)
+ *p++ = 'A' + c - 10;
+ else if (v > 0x00FF)
+ *p++ = '0' + c;
+
+ c = (v >> 4) & 0xF;
+ if (c > 9)
+ *p++ = 'A' + c - 10;
+ else if (v > 0x000F)
+ *p++ = '0' + c;
+
+ c = v & 0xF;
+ if (c > 9)
+ *p++ = 'A' + c - 10;
+ else
+ *p++ = '0' + c;
+
+ *p++ = ':';
+ }
+
+ p--;
+ *p = 0;
+ return buf;
+}
+#endif
+
+static int
+f_in6_f (char *buf, int len, uint16_t val)
+{
+ uint16_t v;
+ int num = 0;
+
+ if (val > 0xFFF)
+ {
+ if (num >= len)
+ return -1;
+ v = val >> 12;
+ if (v < 10)
+ buf[num++] = v + '0';
+ else
+ buf[num++] = v + 'a' - 10;
+ }
+ if (val > 0xff)
+ {
+ if (num >= len)
+ return -1;
+ v = (val >> 8) & 0xF;
+ if (v < 10)
+ buf[num++] = v + '0';
+ else
+ buf[num++] = v + 'a' - 10;
+ }
+ if (val > 0xf)
+ {
+ if (num >= len)
+ return -1;
+ v = (val >> 4) & 0xF;
+ if (v < 10)
+ buf[num++] = v + '0';
+ else
+ buf[num++] = v + 'a' - 10;
+ }
+
+ if (num >= len)
+ return -1;
+ v = val & 0xF;
+ if (v < 10)
+ buf[num++] = v + '0';
+ else
+ buf[num++] = v + 'a' - 10;
+
+ return num;
+}
+
+static void
+f_in6_z (const struct in6_addr *addr, int *pos, int *num)
+{
+ int zero_pos = 8, zero_num = 0;
+ int try_pos = -1, try_num = 0;
+ int i;
+
+ for (i = 0; i < 8; ++i)
+ {
+ if (addr->s6_addr16[i] == 0)
+ {
+ if (try_num)
+ {
+ try_num++;
+ }
+ else
+ {
+ try_pos = i;
+ try_num = 1;
+ }
+ }
+ else if (try_num)
+ {
+ if (try_num > zero_num)
+ {
+ zero_pos = try_pos;
+ zero_num = try_num;
+ }
+ try_num = 0;
+ }
+ }
+
+ if (try_num && try_num > zero_num)
+ {
+ *pos = try_pos;
+ *num = try_num;
+ }
+ else
+ {
+ *pos = zero_pos;
+ *num = zero_num;
+ }
+}
+
+int
+f_in6_s (char *buf, int size, const struct in6_addr *addr)
+{
+ int ret, i, num = 0;
+ int zero_pos, zero_num;
+
+ f_in6_z (addr, &zero_pos, &zero_num);
+
+ if (zero_pos == 0)
+ {
+ if (num >= size)
+ return -1;
+ buf[num++] = ':';
+ }
+ else
+ {
+ for (i = 0; i < zero_pos; ++i)
+ {
+ ret = f_in6_f (&buf[num], size - num, htons (addr->s6_addr16[i]));
+ if (ret < 0)
+ return -1;
+ num += ret;
+ if (num >= size)
+ return -1;
+ buf[num++] = ':';
+ }
+ if (zero_pos == 8)
+ {
+ buf[--num] = 0;
+ return num;
+ }
+ }
+
+ if (zero_pos + zero_num == 8)
+ {
+ if (num >= size)
+ return -1;
+ buf[num++] = ':';
+ }
+ else
+ {
+ for (i = zero_pos + zero_num; i < 8; ++i)
+ {
+ if (num >= size)
+ return -1;
+ buf[num++] = ':';
+ ret = f_in6_f (&buf[num], size - num, htons (addr->s6_addr16[i]));
+ if (ret < 0)
+ return -1;
+ num += ret;
+ }
+ }
+
+ if (num >= size)
+ return -1;
+ buf[num] = 0;
+
+ return num;
+}
+
+const char *
+f_in6_r (const struct in6_addr *addr, char *buf, int buflen)
+{
+ if (f_in6_s (buf, buflen, addr) <= 0)
+ return NULL;
+ return buf;
+}
+
+const char *
+f_in6 (const struct in6_addr *addr)
+{
+ char *buf = s_fmt_buf[(s_fmt_id++) & 63];
+ return f_in6_r (addr, buf, sizeof (s_fmt_buf[0]));
+}
+
+const char *
+f_inaddr (const struct sockaddr_in *addr)
+{
+ char *buf = s_fmt_buf[(s_fmt_id++) & 63];
+ char *p = buf;
+ const uint8_t *ip = (uint8_t *) & addr->sin_addr.s_addr;
+ const uint16_t pt = ntohs (addr->sin_port);
+
+#define IPP(v) do { \
+ if (v > 99) { *p++ = '0' + v / 100 % 10; } \
+ if (v > 9) { *p++ = '0' + v / 10 % 10; } \
+ *p++ = '0' + v % 10; \
+} while (0)
+
+#define PTP(v) do { \
+ if (v > 9999) { *p++ = '0' + v / 10000 % 10; } \
+ if (v > 999) { *p++ = '0' + v / 1000 % 10; } \
+ IPP(v); \
+} while (0)
+
+ IPP (ip[0]);
+ *p++ = '.';
+ IPP (ip[1]);
+ *p++ = '.';
+ IPP (ip[2]);
+ *p++ = '.';
+ IPP (ip[3]);
+ *p++ = ':';
+ PTP (pt);
+ *p = 0;
+
+ return buf;
+}
+
+const char *
+f_in6addr (const struct sockaddr_in6 *addr)
+{
+ char *p, *buf = s_fmt_buf[(s_fmt_id++) & 63];
+ const uint16_t pt = htons (addr->sin6_port);
+ int len = f_in6_s (buf, sizeof (s_fmt_buf[0]), &addr->sin6_addr);
+
+ if (len < 0)
+ return "";
+
+ p = buf + len;
+ *p++ = '.';
+ PTP (pt);
+ *p = 0;
+
+ return buf;
+}
+
+inline static int
+r_uint_use (uint64_t val)
+{
+ const static uint64_t LB_VAL[21] = {
+ 0,
+ 9,
+ 99,
+ 999,
+ 9999,
+ 99999,
+ 999999,
+ 9999999,
+ 99999999,
+ 999999999,
+ 9999999999,
+ 99999999999,
+ 999999999999,
+ 9999999999999,
+ 99999999999999,
+ 999999999999999,
+ 9999999999999999,
+ 99999999999999999,
+ 999999999999999999,
+ 9999999999999999999u,
+ 18446744073709551615u,
+ /* --%%%***+++###^^^@@@ */
+ };
+
+ int a = 1, b = 20;
+
+ do
+ {
+ int i = (a + b) / 2;
+ if (val > LB_VAL[i])
+ a = i + 1;
+ else
+ b = i;
+ }
+ while (a != b);
+
+ return a;
+}
+
+inline static int
+r_uint_wide (uint64_t val)
+{
+ int wide = r_uint_use (val);
+
+ wide = wide + (wide - 1) / 3;
+
+ return wide;
+}
+
+inline static void
+r_uint_fmt (char *buf, uint64_t val, int wide)
+{
+ char *p = buf + wide;
+
+ *p-- = 0;
+
+ while (1)
+ {
+ *p-- = ('0' + val % 10);
+ if ((val /= 10) == 0)
+ break;
+
+ *p-- = ('0' + val % 10);
+ if ((val /= 10) == 0)
+ break;
+
+ *p-- = ('0' + val % 10);
+ if ((val /= 10) == 0)
+ break;
+
+ *p-- = ',';
+ }
+
+ while (p >= buf)
+ *p-- = ' ';
+}
+
+int
+r_uint (char *buf, uint64_t val, int wide)
+{
+ const int size = r_uint_wide (val);
+
+ if (size > wide)
+ wide = size;
+
+ r_uint_fmt (buf, val, wide);
+
+ return wide;
+}
+
+inline int
+s_uint (char *buf, uint64_t val)
+{
+ char *p = buf;
+
+#define F_NUM(n) if (val >= n) { *p++ = '0' + val / n % 10; }
+#define C_NUM(n) if (val >= n) { *p++ = '0' + val / n % 10; *p++ = ','; }
+
+ if (val >= 10000000ul)
+ {
+ if (val >= 1000000000000ul)
+ {
+ F_NUM (10000000000000000000ul);
+ C_NUM (1000000000000000000ul);
+ F_NUM (100000000000000000ul);
+ F_NUM (10000000000000000ul);
+ C_NUM (1000000000000000ul);
+ F_NUM (100000000000000ul);
+ F_NUM (10000000000000ul);
+ C_NUM (1000000000000ul);
+ }
+ F_NUM (100000000000ul);
+ F_NUM (10000000000ul);
+ C_NUM (1000000000ul);
+ F_NUM (100000000ul);
+ F_NUM (10000000ul);
+ }
+ C_NUM (1000000ul);
+ F_NUM (100000ul);
+ F_NUM (10000ul);
+ C_NUM (1000ul);
+ F_NUM (100ul);
+ F_NUM (10ul);
+ *p++ = '0' + val % 10;
+ *p = 0;
+
+#undef F_NUM
+#undef C_NUM
+ return p - buf;
+}
+
+const char *
+f_uint (uint64_t val)
+{
+ char *buf = s_fmt_buf[(s_fmt_id++) & 63];
+ (void) s_uint (buf, val);
+ return buf;
+}
+
+#endif
+#ifdef PARSE_LB_H_
+
+#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
+#define IS_hex(c) ((c) >= 'a' && (c) <= 'f')
+#define IS_HEX(c) ((c) >= 'A' && (c) <= 'F')
+
+uint64_t
+p_hex (const char *arg, const char **end)
+{
+ int i;
+ uint64_t val = 0;
+
+ while (*arg)
+ {
+ if (IS_DIGIT (*arg))
+ val = (val << 4) | (uint64_t) (*arg++ - '0');
+ else if (IS_hex (*arg))
+ val = (val << 4) | (uint64_t) (*arg++ - 'a' + 0xa);
+ else if (IS_HEX (*arg))
+ val = (val << 4) | (uint64_t) (*arg++ - 'A' + 0xA);
+ else
+ break;
+ if (val > 0x0FFFffffFFFFffff)
+ break;
+ }
+
+ if (end)
+ *end = arg;
+ return val;
+}
+
+#define P_UINT_RET(ret, out) ((*end = (out)), (ret))
+
+uint64_t
+p_uint (const char *arg, uint64_t max, const char **end)
+{
+ int i;
+ uint64_t v;
+ const char *out;
+
+ if (!end)
+ end = &out;
+
+ if (!arg)
+ goto P_UINT_ERR;
+
+ if (*arg == '0')
+ {
+ if (IS_DIGIT (arg[1]))
+ goto P_UINT_ERR;
+ return P_UINT_RET (0, arg + 1);
+ }
+
+ if (!IS_DIGIT (*arg))
+ return P_UINT_RET (0, NULL);
+
+ v = *arg++ - '0';
+ if (v > max)
+ goto P_UINT_ERR;
+
+ for (i = 2; i <= 19; ++i)
+ {
+ if (!IS_DIGIT (*arg))
+ return P_UINT_RET (v, arg);
+ v = v * 10 + (*arg++ - '0');
+ if (v > max)
+ goto P_UINT_ERR;
+ }
+
+ if (IS_DIGIT (*arg))
+ {
+ uint64_t n;
+ if (v > (UINT64_MAX / 10))
+ goto P_UINT_ERR;
+ n = v * 10;
+ if (UINT64_MAX - n > (*arg - '0'))
+ goto P_UINT_ERR;
+ v = n + (*arg - '0');
+ if (v > max)
+ goto P_UINT_ERR;
+ arg++;
+ if (IS_DIGIT (*arg))
+ goto P_UINT_ERR;
+ }
+
+ return P_UINT_RET (v, arg);
+
+P_UINT_ERR:
+ return P_UINT_RET (UINT64_MAX, NULL);
+}
+
+inline uint32_t
+p_ip (const char **arg)
+{
+ uint32_t b1, b2, b3, b4;
+ const char *p = *arg;
+
+ b1 = (uint32_t) p_uint (p, 255, &p);
+ if (!p || *p++ != '.')
+ goto P_IP_ERR;
+ b2 = (uint32_t) p_uint (p, 255, &p);
+ if (!p || *p++ != '.')
+ goto P_IP_ERR;
+ b3 = (uint32_t) p_uint (p, 255, &p);
+ if (!p || *p++ != '.')
+ goto P_IP_ERR;
+ b4 = (uint32_t) p_uint (p, 255, &p);
+ if (!p)
+ goto P_IP_ERR;
+
+ *arg = p;
+ return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+
+P_IP_ERR:
+ *arg = NULL;
+ return 0;
+}
+
+int
+p_addr (const char *arg, struct sockaddr_in *addr)
+{
+ uint16_t port;
+
+ if (*arg != ':')
+ {
+ uint32_t ip = p_ip (&arg);
+ if (!arg)
+ return -1;
+ addr->sin_addr.s_addr = htonl (ip);
+ if (*arg == 0)
+ return 0;
+ if (*arg != ':')
+ return -1;
+ arg++;
+ }
+
+ port = (uint16_t) p_uint (arg, 0xffff, &arg);
+ if (!arg || *arg != 0)
+ return -1;
+ addr->sin_port = htons (port);
+
+ return 0;
+}
+
+const char *
+p_addr_set (const char *arg, struct inaddrs *addr, uint32_t flag)
+{
+ addr->ip = p_ip (&arg);
+ if (!arg)
+ return NULL;
+
+ if (!(flag & PA_NO_TO_IP) && *arg == '-')
+ {
+ uint8_t to;
+ to = (uint8_t) p_uint (arg + 1, 255, &arg);
+ if (!arg)
+ return NULL;
+ addr->ip_num = to - (uint8_t) addr->ip;
+ if (addr->ip_num >= 0)
+ ++addr->ip_num;
+ else if (flag & PA_MAY_INV_IP)
+ --addr->ip_num;
+ else
+ return NULL;
+ }
+ else if (!(flag & PA_NO_NUM_IP) && *arg == '+')
+ {
+ addr->ip_num = (int) p_uint (arg + 1, 0x7FFFffff, &arg);
+ if (!arg || addr->ip_num == 0 || 0xFFFFFFFF - addr->ip < addr->ip_num)
+ return NULL;
+ }
+ else
+ {
+ addr->ip_num = 1;
+ }
+
+ if ((flag & PA_DEF_PORT) == PA_NO_PORT)
+ return arg;
+
+ if (*arg != ':')
+ {
+ if ((flag & PA_DEF_PORT) == PA_MUST_PORT)
+ return NULL;
+ if ((flag & PA_DEF_PORT) == PA_DEF_PORT)
+ {
+ addr->port = (uint16_t) (flag);
+ addr->port_num = 1;
+ }
+ else
+ {
+ addr->port = 0;
+ addr->port_num = 0;
+ }
+ return arg;
+ }
+
+ addr->port = (uint16_t) p_uint (arg + 1, 0xffff, &arg);
+ if (!arg)
+ return NULL;
+
+ if (!(flag & PA_NO_TO_PORT) && *arg == '-')
+ {
+ uint16_t to = (uint16_t) p_uint (arg + 1, 0xffff, &arg);
+ if (!arg || to < addr->port)
+ return NULL;
+ addr->port_num = to - addr->port + 1;
+ }
+ else if (!(flag & PA_NO_NUM_PORT) && *arg == '+')
+ {
+ addr->port_num = (uint16_t) p_uint (arg + 1, 0xffff, &arg);
+ if (!arg || addr->port_num == 0 || 0xFFFF - addr->port < addr->port_num)
+ return NULL;
+ }
+ else
+ {
+ addr->port_num = 1;
+ }
+
+ if (flag & PA_MULTI_ONE)
+ {
+ if (addr->ip_num > 1 && addr->port_num > 1)
+ return NULL;
+ }
+
+ return arg;
+}
+
+inline static const char *
+pal_trim (const char *arg, uint32_t flag)
+{
+ if (flag & PAL_NO_SPACE)
+ return arg;
+
+ if (flag & PAL_WITH_NL)
+ {
+ while (*arg == ' ' || *arg == '\t' || *arg == '\r' || *arg == '\n')
+ arg++;
+ }
+ else
+ {
+ while (*arg == ' ' || *arg == '\t')
+ arg++;
+ }
+
+ return arg;
+}
+
+int
+p_addr_list (const char *arg, struct inaddrs *list, int num, uint32_t flag,
+ const char **end)
+{
+ int count = 0;
+
+ while (count < num)
+ {
+ arg = pal_trim (arg, flag);
+ arg = p_addr_set (arg, list, flag);
+ count++;
+ if (!arg)
+ return -count;
+ arg = pal_trim (arg, flag);
+ if (*arg != ',')
+ break;
+ arg++;
+ list++;
+ }
+
+ if (end)
+ *end = arg;
+ else if (*arg)
+ return -count;
+
+ return count;
+}
+
+int
+addr_total (const struct inaddrs *list, int num, uint32_t mode)
+{
+ int total = 0;
+
+ mode &= PAL_CROSS_MASK;
+
+ for (--num; num >= 0; --num)
+ {
+ if (mode == PAL_IP_X_PORT || mode == PAL_PORT_X_IP)
+ {
+ total += list[num].ip_num * list[num].port_num;
+ }
+ else if (mode == PAL_INC_BOTH)
+ {
+ int iip = 0;
+ uint16_t iport = 0;
+ do
+ {
+ total++;
+ if (++iip == list[num].ip_num)
+ iip = 0;
+ if (++iport == list[num].port_num)
+ iport = 0;
+ }
+ while (iip != 0 && iport != 0);
+ }
+ else
+ return -1;
+ }
+
+ return total;
+}
+
+int
+addr_layout (const struct inaddrs *list, int list_num,
+ struct sockaddr_in *addr, int addr_num, uint32_t mode)
+{
+ uint16_t ipt;
+ int i, iip, count = 0;
+
+ mode &= PAL_CROSS_MASK;
+
+ if (mode == PAL_IP_X_PORT)
+ {
+ for (i = 0; i < list_num; ++i)
+ {
+ if (count + list[i].ip_num * list[i].port_num > addr_num)
+ return -1;
+ for (iip = 0; iip < list[i].ip_num; ++iip)
+ {
+ for (ipt = 0; ipt < list[i].port_num; ++ipt)
+ {
+ addr[count].sin_family = AF_INET;
+ addr[count].sin_addr.s_addr = htonl (list[i].ip + iip);
+ addr[count].sin_port = htons (list[i].port + ipt);
+ count++;
+ }
+ }
+ }
+ }
+ else if (mode == PAL_PORT_X_IP)
+ {
+ for (i = 0; i < list_num; ++i)
+ {
+ if (count + list[i].ip_num * list[i].port_num > addr_num)
+ return -1;
+ for (ipt = 0; ipt < list[i].port_num; ++ipt)
+ {
+ for (iip = 0; iip < list[i].ip_num; ++iip)
+ {
+ addr[count].sin_family = AF_INET;
+ addr[count].sin_addr.s_addr = htonl (list[i].ip + iip);
+ addr[count].sin_port = htons (list[i].port + ipt);
+ count++;
+ }
+ }
+ }
+ }
+ else if (mode == PAL_INC_BOTH)
+ {
+ for (i = 0; i < list_num; ++i)
+ {
+ do
+ {
+ if (count >= addr_num)
+ return -1;
+ addr[count].sin_family = AF_INET;
+ addr[count].sin_addr.s_addr = htonl (list[i].ip + iip);
+ addr[count].sin_port = htons (list[i].port + ipt);
+ count++;
+ if (++iip >= list[i].ip_num)
+ iip = 0;
+ if (++ipt >= list[i].port_num)
+ ipt = 0;
+ }
+ while (iip != 0 && ipt != 0);
+ }
+ }
+ else
+ {
+ return -1;
+ }
+
+ return count;
+}
+
+inline static const char *
+p_ip6_se (const char *p, uint16_t * val)
+{
+ int i;
+ uint32_t v = 0;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if (p[i] >= '0' && p[i] <= '9')
+ v = (v << 4) + p[i] - '0';
+ else if (p[i] >= 'a' && p[i] <= 'f')
+ v = (v << 4) + p[i] - 'a' + 10;
+ else if (p[i] >= 'A' && p[i] <= 'F')
+ v = (v << 4) + p[i] - 'A' + 10;
+ else
+ break;
+ }
+
+ if (i == 0)
+ return NULL;
+
+ *val = htons (v);
+ return p + i;
+}
+
+const char *
+p_ip6 (const char *pos, struct in6_addr *ip)
+{
+ int zero = -1, num = 0;
+ const char *last;
+
+ if (*pos == ':')
+ {
+ pos++;
+ if (*pos != ':')
+ return NULL;
+ pos++;
+ zero = 0;
+ }
+
+ last = pos;
+
+ while (*pos)
+ {
+ pos = p_ip6_se (pos, &ip->s6_addr16[num]);
+ if (!pos)
+ {
+ if (zero == num)
+ break;
+ return NULL;
+ }
+
+ num++;
+ if (num == 8)
+ break;
+
+ if (*pos == ':')
+ {
+ pos++;
+ if (*pos == ':')
+ {
+ if (zero >= 0)
+ return NULL;
+ zero = num;
+ pos++;
+ }
+ last = pos;
+ }
+ else if (*pos == '.')
+ {
+ if (num > 6)
+ return NULL;
+ *(uint32_t *) (&ip->s6_addr16[num - 1]) = htonl (p_ip (&last));
+ if (!last)
+ return NULL;
+ pos = last;
+ num++;
+ break;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (num == 0)
+ {
+ if (zero != 0)
+ return NULL;
+ ip->s6_addr32[0] = htonl (0);
+ ip->s6_addr32[1] = htonl (0);
+ ip->s6_addr32[2] = htonl (0);
+ ip->s6_addr32[3] = htonl (0);
+ return pos;
+ }
+
+ if (num < 8)
+ {
+ int i, cp;
+ if (zero < 0)
+ return NULL;
+ /* move */
+ for (i = num - 1, cp = 7; i >= zero; --i)
+ ip->s6_addr16[cp--] = ip->s6_addr16[i];
+ /* fill 0 */
+ for (i = num, cp = zero; i < 8; ++i)
+ ip->s6_addr16[cp++] = htons (0);
+ }
+ else if (zero >= 0)
+ {
+ return NULL;
+ }
+
+ return pos;
+}
+
+int
+p_addr6 (const char *arg, struct sockaddr_in6 *addr)
+{
+ uint16_t port;
+
+ if (*arg != '.')
+ {
+ arg = p_ip6 (arg, &addr->sin6_addr);
+ if (!arg)
+ return -1;
+ if (*arg == 0)
+ return 0;
+ if (*arg != '.')
+ return -1;
+ arg++;
+ }
+
+ port = (uint16_t) p_uint (arg, 0xffff, &arg);
+ if (!arg || *arg != 0)
+ return -1;
+ addr->sin6_port = htons (port);
+
+ return 0;
+}
+
+#endif
+#ifdef UNIT_LB_H_
+
+const static uint64_t UNITS[UNIT_NUM] = {
+ [UNIT_1] = 1,
+ [UNIT_k] = 1000,
+ [UNIT_m] = 1000 * 1000,
+ [UNIT_g] = 1000 * 1000 * 1000,
+ [UNIT_w] = 10000,
+ [UNIT_K] = 1024,
+ [UNIT_M] = 1024 * 1024,
+ [UNIT_G] = 1024 * 1024 * 1024,
+
+ [UNIT_hour] = 60 * 60,
+ [UNIT_min] = 60,
+ [UNIT_sec] = 1,
+
+ [UNIT_hn] = 1000ull * 1000 * 1000 * 60 * 60,
+ [UNIT_mn] = 1000ull * 1000 * 1000 * 60,
+ [UNIT_sn] = 1000 * 1000 * 1000,
+ [UNIT_1n] = 1000 * 1000 * 1000,
+ [UNIT_ms] = 1000 * 1000,
+ [UNIT_us] = 1000,
+ [UNIT_ns] = 1,
+
+ [UNIT_PC] = 1,
+};
+
+#define P_UNIT_END(ret, end) ({ \
+ *arg = (end); \
+ if (unit) *unit = UNITS[ret]; \
+ ret; \
+})
+
+int
+p_unit (const char **arg, int mask, uint64_t * unit)
+{
+ const char *opt = *arg;
+ int ret;
+
+ switch (*opt)
+ {
+ case 'w':
+ ret = UNIT_w;
+ break;
+ case 'm':
+ if ((mask & UB_ms) && opt[1] == 's')
+ return P_UNIT_END (UNIT_ms, opt + 2);
+ if (mask & UB_min)
+ return P_UNIT_END (UNIT_min, opt + 1);
+ ret = UNIT_m;
+ break;
+ case 'k':
+ ret = UNIT_k;
+ break;
+ case 'g':
+ ret = UNIT_g;
+ break;
+
+ case 'h':
+ ret = UNIT_hour;
+ break;
+ case 's':
+ ret = UNIT_sec;
+ break;
+ case 'u':
+ if ((mask & UB_us) && opt[1] == 's')
+ return P_UNIT_END (UNIT_us, opt + 2);
+ goto NO_UNIT;
+ case 'n':
+ if ((mask & UB_ns) && opt[1] == 's')
+ return P_UNIT_END (UNIT_ns, opt + 2);
+ goto NO_UNIT;
+
+ case '%':
+ ret = UNIT_PC;
+ break;
+
+ case 'K':
+ ret = UNIT_K;
+ break;
+ case 'M':
+ ret = UNIT_M;
+ break;
+ case 'G':
+ ret = UNIT_G;
+ break;
+
+ default:
+ goto NO_UNIT;
+ }
+
+ if ((1 << ret) & mask)
+ return P_UNIT_END (ret, opt + 1);
+
+NO_UNIT:
+ if (0 == (mask & UB_1))
+ return -1;
+
+ return P_UNIT_END (UNIT_1, opt);
+}
+
+#endif
+#ifdef CACHED_OUTPUT_LB_H_
+
+int
+co_app_ch (char buf[], char ch)
+{
+ struct cohead *head = (struct cohead *) buf;
+
+ buf += sizeof (struct cohead);
+
+ if (head->free > 3)
+ {
+ buf += (head->size - head->free);
+ buf[0] = ch;
+ buf[1] = 0;
+ head->free -= 1;
+ }
+ else
+ {
+ (void) fprintf (CO_OUT (head), "%s%c", buf, ch);
+ buf[0] = 0;
+ head->free = head->size;
+ }
+
+ return 1;
+}
+
+int
+co_append (char buf[], cosize_t max, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+ struct cohead *head = (struct cohead *) buf;
+
+ /* no space for max+1 size -> output if cached */
+ if (max >= head->free && head->free < head->size)
+ _co_flush (head);
+
+ /* enough space -> try cache format */
+ if (max < head->free)
+ {
+ char *p = buf + (sizeof (struct cohead) + head->size - head->free);
+ va_start (ap, fmt);
+ ret = vsnprintf (p, head->free, fmt, ap);
+ va_end (ap);
+ if (ret >= 0 && ret < head->free)
+ {
+ head->free -= ret;
+ return ret;
+ }
+ }
+
+ /* no space or format failed -> output if cached */
+ if (head->free != head->size)
+ _co_flush (head);
+
+ /* direct output */
+ va_start (ap, fmt);
+ ret = fprintf (CO_OUT (head), fmt, ap);
+ va_end (ap);
+
+ return ret;
+}
+
+int
+co_wr_uint (char buf[], uint64_t val, int wide)
+{
+ struct cohead *head = (struct cohead *) buf;
+ int size = r_uint_wide (val);
+ char *p;
+
+ if (size > wide)
+ wide = size;
+
+ if (head->free <= wide)
+ _co_flush (head);
+
+ if (head->free <= wide)
+ {
+ assert (0);
+ }
+
+ p = buf + (sizeof (struct cohead) + head->size - head->free);
+
+ r_uint_fmt (p, val, wide);
+
+ head->free -= wide;
+
+ return wide;
+}
+
+#endif
+
+#ifdef SYSTEM_LB_H_
+
+pthread_t
+lb_thread (void *(*proc) (void *), void *arg, const char *fmt, ...)
+{
+ pthread_t tid;
+ int ret;
+
+ ret = pthread_create (&tid, NULL, proc, arg);
+ if (ret)
+ return 0;
+
+ if (fmt)
+ {
+ char name[20];
+ va_list args;
+
+ va_start (args, fmt);
+ ret = vsnprintf (name, sizeof (name), fmt, args);
+ va_end (args);
+
+ if (ret > 0)
+ {
+ name[sizeof (name) - 1] = 0;
+ (void) pthread_setname_np (tid, name);
+ }
+ }
+
+ return tid;
+}
+
+static void
+lb_sigsegv_proc (int s)
+{
+ int num;
+ void *buf[128];
+
+ out ("Signal SIGSEGV, Segmentation fault!\n");
+
+ num = backtrace (buf, 128);
+ if (num > 0)
+ backtrace_symbols_fd (buf, num, STDOUT_FILENO);
+ exit (1);
+}
+
+void
+lb_sigsegv_setup ()
+{
+ struct sigaction s = { 0 };
+
+ (void) sigemptyset (&s.sa_mask);
+
+ s.sa_flags = SA_NODEFER;
+ s.sa_handler = (void *) lb_sigsegv_proc;
+ (void) sigaction (SIGSEGV, &s, NULL);
+}
+
+#endif
+
+#ifdef KERNEL_SYSCALL_API
+
+#define KAPI(name) (typeof name) *k_##name = ##name;
+#include "kapi.h"
+#undef API
+
+void
+kapi_init ()
+{
+#define KAPI(name) k_##name = ld_load;
+}
+
+#endif
diff --git a/thirdparty/apps/testapp/lb/lb.h b/thirdparty/apps/testapp/lb/lb.h
new file mode 100644
index 0000000..b7e4ddb
--- /dev/null
+++ b/thirdparty/apps/testapp/lb/lb.h
@@ -0,0 +1,731 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _LB_H_
+#define _LB_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <time.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <sys/poll.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/eventfd.h>
+#include <sys/syscall.h>
+#include <sys/sysinfo.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <sched.h>
+#include <getopt.h>
+#include <execinfo.h>
+#include <linux/futex.h>
+
+#define KB 1000
+#define MB (1000 * KB)
+#define GB (1000 * MB)
+#define TB (1000 * GB)
+
+#define MSOFS (1000)
+#define USOFS (1000 * 1000)
+#define NSOFS (1000 * 1000 * 1000)
+#define NSOFMS (1000 * 1000)
+
+#define NOINLINE __attribute__((noinline))
+#define no_inline __attribute__((noinline))
+
+#ifndef SO_REUSEPORT
+#define SO_REUSEPORT 15
+#endif
+
+#include "api.h"
+
+#define out(fmt, arg...) (void)printf(fmt, ##arg)
+
+#define info(fmt, arg...) (void)printf("%s[I:%d]%s " fmt, CR, __LINE__, CC, ##arg)
+#define wrn(fmt, arg...) (void)printf("%s[W:%d]%s " fmt, FR__, __LINE__, CC, ##arg)
+#define err(fmt, arg...) (void)fprintf(stderr, "%s[E:%d]%s " fmt, BR__, __LINE__, CC, ##arg)
+
+#define WRN(cond, fmt, arg...) do { if (cond) wrn(fmt, ##arg); } while (0)
+
+#define ERR_RETURN(cond, ret, fmt, arg...) do { \
+ if (cond) { \
+ if (fmt) err(fmt, ##arg); \
+ return ret; \
+ } \
+} while(0)
+
+#define ERR_GOTO(cond, TO, fmt, arg...) do { \
+ if (cond) { \
+ if (fmt) err(fmt, ##arg); \
+ goto TO; \
+ } \
+} while (0)
+
+#define DBGOPT "D"
+#define DBGOPT_LONG {"debug", 0, 0, 'D'},
+
+extern int enable_debug;
+
+#define DBG(fmt, arg...) do { \
+ if (enable_debug) \
+ out("[D:%d]%s " fmt, __LINE__, __func__, ##arg); \
+} while (0)
+
+#define T DBG("\n");
+
+#define CNT_OF(a) (sizeof(a) / sizeof(a[0]))
+
+#define OFF_OF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#define CON_OF(ptr, type, member) ({ \
+ const typeof( ((type*)0)->member ) *__mptr = (ptr); \
+ (type*)( (char*)__mptr - OFF_OF(type, member) ); \
+})
+#define NUM_OF(a) (sizeof((a)) / sizeof((a)[0]))
+
+#if 1
+#define TIMEPOINT
+
+#define TP(name) struct timespec _tp_##name; \
+ (void)clock_gettime(CLOCK_MONOTONIC, &_tp_##name)
+#define TO(from, to) do { \
+ struct timespec _t; \
+ LB_SUB_TS(_tp_##to, _tp_##from, _t); \
+ out("@TP>%s:%d:%s %lu.%09lu %s-%s\n", __FILE__, __LINE__, __func__, \
+ _t.tv_sec, _t.tv_nsec, #from, #to); \
+} while (0)
+#define TN(from, to, NUM) do { \
+ static uint64_t _n = 0; \
+ static struct timespec _t = {0}; \
+ _t.tv_nsec += (_tp_##to.tv_nsec - _tp_##from.tv_nsec); \
+ _t.tv_sec += (_tp_##to.tv_sec - _tp_##from.tv_sec); \
+ if (++_n >= NUM) { \
+ uint64_t _nsec = _t.tv_sec * 1000000000ul + _t.tv_nsec; \
+ _nsec /= _n; \
+ out("@TP<%lu>%s:%d:%s %lu.%09lu %s-%s\n", _n, __FILE__, __LINE__, __func__, \
+ _nsec/1000000000ul, _nsec%1000000000ul, #from, #to); \
+ _t.tv_sec = 0; \
+ _t.tv_nsec = 0; \
+ _n = 0; \
+ } \
+} while (0)
+#else
+
+#define TP(name) ((void)0)
+#define TO(from, to) ((void)0)
+#define TN(from, to, NUM) ((void)0)
+
+#endif
+
+#define TQ(name) do { TP(__); TO(name, __); } while (0)
+#define TM(name, NUM) do { TP(__); TN(name, __, NUM); } while (0)
+
+#define TO1(n1,n2) TO(n1,n2)
+#define TO2(n1,n2,n3) do { TO(n1,n2); TO1(n2,n3); } while(0)
+#define TO3(n1,n2,n3...) do { TO(n1,n2); TO2(n2,n3); } while(0)
+#define TO4(n1,n2,n3...) do { TO(n1,n2); TO3(n2,n3); } while(0)
+#define TO5(n1,n2,n3...) do { TO(n1,n2); TO4(n2,n3); } while(0)
+#define TO6(n1,n2,n3...) do { TO(n1,n2); TO5(n2,n3); } while(0)
+
+#define TE(N,n...) do { TP(__); TO##N(n, __);} while (0)
+
+#define tp1 TP(1)
+#define tq1 TQ(1)
+#define tp2 TP(2)
+#define tq2 TQ(2)
+#define tp3 TP(3)
+#define tq3 TQ(3)
+#define tp4 TP(4)
+#define tq4 TQ(4)
+#define tp5 TP(5)
+#define tq5 TQ(5)
+
+#ifndef COLOR_LB_H_
+#define COLOR_LB_H_
+
+struct lb_color
+{
+ const char *clear;
+ const char *high;
+ const char *uline;
+ const char *flash;
+ const char *rev;
+
+ const char *fblack;
+ const char *fr__;
+ const char *f_g_;
+ const char *f__b;
+ const char *frg_;
+ const char *fr_b;
+ const char *f_gb;
+ const char *fwhite;
+
+ const char *bblack;
+ const char *br__;
+ const char *b_g_;
+ const char *b__b;
+ const char *brg_;
+ const char *br_b;
+ const char *b_gb;
+ const char *bwhite;
+};
+
+enum
+{
+ LB_DEF_COLOR = 0,
+ LB_NO_COLOR = 1,
+};
+
+extern const struct lb_color *lb_color;
+extern int lb_color_index;
+void lb_set_color (int index);
+
+#define CC lb_color->clear
+#define CR lb_color->rev
+#define CH lb_color->high
+#define CU lb_color->uline
+#define CF lb_color->flash
+
+#define FBLACK lb_color->fblack
+#define FR__ lb_color->fr__
+#define F_G_ lb_color->f_g_
+#define F__B lb_color->f__b
+#define FRG_ lb_color->frg_
+#define FR_B lb_color->fr_b
+#define F_GB lb_color->f_gb
+#define FWHITE lb_color->fwhite
+
+#define BBLACK lb_color->bblack
+#define BR__ lb_color->br__
+#define B_G_ lb_color->b_g_
+#define B__B lb_color->b__b
+#define BRG_ lb_color->brg_
+#define BR_B lb_color->br_b
+#define B_GB lb_color->b_gb
+#define BWHITE lb_color->bwhite
+
+#endif
+
+#ifndef TIME_LB_H_
+#define TIME_LB_H_
+
+#define LB_RAND(num) ((int) ((random() / (RAND_MAX + 1.0)) * num))
+
+#define LB_TIME(now) (void)clock_gettime(CLOCK_MONOTONIC, &(now))
+#define LB_REALTIME(now) (void)clock_gettime(CLOCK_REALTIME, &(now))
+
+#define LB_SUB_OS(end, begin) ((end).tv_sec - (begin).tv_sec)
+#define LB_SUB_NS(end, begin) (((end).tv_sec - (begin).tv_sec) * NSOFS + (end).tv_nsec - (begin).tv_nsec)
+
+#define LB_SUB_TS(end, begin, out) ({ \
+ if ((end).tv_nsec >= (begin).tv_nsec) { \
+ (out).tv_nsec = (end).tv_nsec - (begin).tv_nsec; \
+ (out).tv_sec = (end).tv_sec - (begin).tv_sec; \
+ } else { \
+ (out).tv_nsec = (end).tv_nsec + NSOFS - (begin).tv_nsec; \
+ (out).tv_sec = (end).tv_sec - (begin).tv_sec - 1; \
+ } \
+})
+
+#define LB_CMP(end, begin) ((end).tv_sec > (begin).tv_sec ? 1 : ( \
+ (end).tv_sec < (begin).tv_sec ? -1 : (end).tv_nsec - (begin).tv_nsec))
+
+#define LB_CMP_SN(end, begin, sec, nsec) ({ \
+ time_t _s = (end).tv_sec - (begin).tv_sec; \
+ (_s > (sec)) || (_s == (sec) && (end).tv_nsec - (begin).tv_nsec >= (nsec)); \
+})
+
+#define LB_CMP_TS(end, begin, ts) LB_CMP_SN((end), (begin), (ts).tv_sec, (ts).tv_nsec)
+#define LB_CMP_S(end, begin, sec) LB_CMP_SN((end), (begin), (sec), 0)
+#define LB_CMP_NS(end, begin, nsec) LB_CMP_SN((end), (begin), 0, (nsec))
+
+#endif /* #ifndef TIME_LB_H_ */
+
+#ifndef MATH_LB_H_
+#define MATH_LB_H_
+
+/* return a * 10^9 / b */
+inline static uint64_t
+lb_gdiv (uint64_t a, uint64_t b)
+{
+ const uint64_t M = 0xFFFFffffFFFFfffful;
+ const uint64_t N = 1000 * 1000 * 1000;
+ const uint64_t P = 1000;
+
+ uint64_t r;
+
+ if (b == 0)
+ b = 1;
+
+ if (a <= M / N)
+ return a * N / b;
+
+ r = a / b;
+
+ a = a % b * P;
+ r = r * P + a / b;
+
+ a = a % b * P;
+ r = r * P + a / b;
+
+ a = a % b * P;
+ r = r * P + a / b;
+
+ return r;
+}
+
+inline static uint64_t
+lb_sdiv (uint64_t a, uint64_t b)
+{
+ if (b)
+ return a / b;
+ return 0;
+}
+
+#endif /* #ifndef MATH_LB_H_ */
+#ifndef RUN_LB_H_
+#define RUN_LB_H_
+
+struct lb_slot
+{
+ struct timespec begin;
+ uint64_t count;
+};
+
+struct lb_run
+{
+ uint32_t index;
+ uint32_t mask;
+ uint32_t rate;
+ uint32_t time;
+ uint64_t total;
+ struct lb_slot slot[0];
+};
+
+/* num:1 << N; time: ns */
+inline static void
+run_init (struct lb_run *run, uint32_t rate, uint32_t num, uint32_t time)
+{
+ int i;
+ struct lb_slot *slot = run->slot;
+ struct timespec begin;
+
+ LB_TIME (begin);
+
+ run->index = 0;
+ run->mask = num - 1;
+ run->rate = rate;
+ run->time = time;
+ run->total = 0;
+
+ for (i = 0; i < num; ++i, ++slot)
+ {
+ slot->begin = begin;
+ slot->count = 0;
+ }
+}
+
+/* return: the number should add for run to now */
+inline static int64_t
+run_test (struct lb_run *run, struct timespec *now)
+{
+ uint64_t time, num;
+ struct lb_slot *slot = run->slot;
+ struct lb_slot *cur = slot + (run->index & run->mask);
+
+ if (LB_CMP_NS (*now, cur->begin, run->time))
+ {
+ cur = slot + ((++run->index) & run->mask);
+ run->total -= cur->count;
+ cur->count = 0;
+ cur->begin = *now;
+ }
+
+ slot += ((run->index + 1) & run->mask);
+ time = LB_SUB_NS (*now, slot->begin);
+ num = time * run->rate;
+
+ if ((num % NSOFS) >= (NSOFS / 2))
+ return num / NSOFS - run->total + 1;
+ return num / NSOFS - run->total;
+}
+
+inline static int
+run_add (struct lb_run *run, int64_t num)
+{
+ run->total += num;
+ run->slot[run->index & run->mask].count += num;
+}
+
+#endif
+
+#ifndef FORMAT_LB_H_
+#define FORMAT_LB_H_
+
+const char *f_in6 (const struct in6_addr *ip6);
+const char *f_in6addr (const struct sockaddr_in6 *addr);
+const char *f_inaddr (const struct sockaddr_in *addr);
+const char *f_uint (uint64_t val);
+int s_uint (char *buf, uint64_t val);
+int r_uint (char *buf, uint64_t val, int size);
+
+#endif
+
+#ifndef PARSE_LB_H_
+#define PARSE_LB_H_
+
+uint64_t p_hex (const char *arg, const char **end);
+uint64_t p_uint (const char *arg, uint64_t max, const char **end);
+inline static long
+p_int (const char *arg, long max, const char **end)
+{
+ return (long) (unsigned long) p_uint (arg, (uint64_t) (unsigned long) max,
+ end);
+}
+
+struct inaddrs
+{
+ uint32_t ip;
+#if 0
+ uint32_t ip_num;
+ uint32_t ip_step;
+#else
+ int ip_num;
+#endif
+ uint16_t port;
+ uint16_t port_num;
+};
+
+uint32_t p_ip (const char **arg);
+int p_addr (const char *str, struct sockaddr_in *addr);
+const char *p_addr_set (const char *arg, struct inaddrs *addr, uint32_t flag);
+int p_addr_list (const char *arg, struct inaddrs *list, int num,
+ uint32_t flag, const char **end);
+int addr_total (const struct inaddrs *list, int num, uint32_t mode);
+int addr_layout (const struct inaddrs *list, int list_num,
+ struct sockaddr_in *addr, int addr_num, uint32_t mode);
+inline static int
+p_addrin_list (const char *arg, struct sockaddr_in **addr, int max,
+ uint32_t flag, const char **end)
+{
+ int num, total;
+ struct inaddrs list[max];
+ struct sockaddr_in *out;
+
+ num = p_addr_list (arg, list, max, flag, end);
+ if (num <= 0)
+ return -1;
+
+ total = addr_total (list, num, flag);
+ if (total > max)
+ return -1;
+
+ out = (struct sockaddr_in *) malloc (sizeof (struct sockaddr_in) * total);
+ if (!out)
+ return -1;
+
+ num = addr_layout (list, num, out, total, flag);
+
+ if (num != total)
+ {
+ free (out);
+ return -1;
+ }
+
+ *addr = out;
+ return num;
+}
+
+#define PA_DEFPORT_MASK 0x0000FFFF
+
+#define PA_NO_TO_IP 0x00010000
+#define PA_NO_NUM_IP 0x00020000
+#define PA_MAY_INV_IP 0x00040000
+#define PA_MULTI_ONE 0x00080000
+
+#define PA_NO_TO_PORT 0x00100000
+#define PA_NO_NUM_PORT 0x00200000
+#define PA_NO_PORT 0x00400000
+#define PA_MUST_PORT 0x00800000
+#define PA_DEF_PORT 0x00C00000
+
+#define PA_NO_TO_ALL (PA_NO_TO_IP | PA_NO_TO_PORT)
+#define PA_NO_NUM_ALL (PA_NO_NUM_IP | PA_NO_NUM_PORT)
+#define PA_SINGLE_IP (PA_NO_TO_IP | PA_NO_NUM_IP)
+#define PA_SINGLE_PORT (PA_NO_TO_PORT | PA_NO_NUM_PORT)
+
+#define PAL_NO_SPACE 0x10000000
+#define PAL_WITH_NL 0x20000000
+//#define PAL_SC_SPLIT 0x40000000
+
+#define PAL_CROSS_MASK 0x03000000
+#define PAL_IP_X_PORT 0x00000000
+#define PAL_INC_BOTH 0x01000000
+#define PAL_PORT_X_IP 0x02000000
+
+const char *p_ip6 (const char *pos, struct in6_addr *ip);
+inline static int
+inet6_aton (const char *cp, struct in6_addr *addr)
+{
+ cp = p_ip6 (cp, addr);
+ if (!cp || cp[0] != 0)
+ return 0;
+ return 1;
+}
+
+int p_addr6 (const char *arg, struct sockaddr_in6 *addr);
+
+#endif
+
+#ifndef UNIT_LB_H_
+#define UNIT_LB_H_
+
+enum unit_type
+{
+ UNIT_1,
+
+ UNIT_k,
+ UNIT_m,
+ UNIT_g,
+ UNIT_w,
+
+ UNIT_K,
+ UNIT_M,
+ UNIT_G,
+
+ UNIT_hour,
+ UNIT_min,
+ UNIT_sec,
+
+ UNIT_1n,
+ UNIT_hn,
+ UNIT_mn,
+ UNIT_sn,
+ UNIT_ms,
+ UNIT_us,
+ UNIT_ns,
+
+ UNIT_PC,
+
+ UNIT_NUM,
+
+ UB_1 = 1 << UNIT_1,
+
+ UB_k = 1 << UNIT_k,
+ UB_m = 1 << UNIT_m,
+ UB_g = 1 << UNIT_g,
+ UB_w = 1 << UNIT_w,
+
+ UB_K = 1 << UNIT_K,
+ UB_M = 1 << UNIT_M,
+ UB_G = 1 << UNIT_G,
+
+ UB_hour = 1 << UNIT_hour,
+ UB_min = 1 << UNIT_min,
+ UB_sec = 1 << UNIT_sec,
+
+ UB_hn = 1 << UNIT_hn,
+ UB_mn = 1 << UNIT_mn,
+ UB_sn = 1 << UNIT_sn,
+ UB_1n = 1 << UNIT_1n,
+ UB_ms = 1 << UNIT_ms,
+ UB_us = 1 << UNIT_us,
+ UB_ns = 1 << UNIT_ns,
+
+ UB_PC = 1 << UNIT_PC,
+
+ UB_T1U_MASK = 3 << UNIT_NUM,
+ UB_T1U_ns = 0 << UNIT_NUM,
+ UB_T1U_us = 1 << UNIT_NUM,
+ UB_T1U_ms = 2 << UNIT_NUM,
+ UB_T1U_s = 3 << UNIT_NUM,
+
+ UB_kmgw = UB_k | UB_m | UB_g | UB_w,
+ UB_KMG = UB_K | UB_M | UB_G,
+ UB_1kmgwKMG = UB_1 | UB_kmgw | UB_KMG,
+
+ UB_smun = UB_sn | UB_ms | UB_us | UB_ns,
+ UB_hms1 = UB_hour | UB_min | UB_sec | UB_1,
+
+};
+
+int p_unit (const char **arg, int mask, uint64_t * unit);
+
+inline static uint64_t
+p_value (const char *arg, uint64_t max, int mask, const char **end)
+{
+ uint64_t val = p_uint (arg, max, &arg);
+
+ if (arg)
+ {
+ uint64_t unit;
+ if (p_unit (&arg, mask, &unit) >= 0)
+ {
+ val *= unit;
+ if (val <= max)
+ {
+ if (end)
+ *end = arg;
+ return val;
+ }
+ }
+ }
+
+ if (end)
+ *end = NULL;
+ return 0;
+}
+
+#endif
+
+#ifndef CACHED_OUTPUT_LB_H_
+#define CACHED_OUTPUT_LB_H_
+
+typedef uint16_t cosize_t;
+
+struct cohead
+{
+ cosize_t size;
+ cosize_t free;
+};
+
+#define CO_OUT(head) stdout
+#define CO_INIT(buf) co_init(buf, sizeof(buf))
+
+inline static void
+co_init (char buf[], cosize_t size)
+{
+ struct cohead *head = (struct cohead *) buf;
+ head->size = size - sizeof (struct cohead);
+ head->free = head->size;
+ buf[sizeof (struct cohead)] = 0;
+}
+
+inline static void
+_co_flush (struct cohead *head)
+{
+ char *buf = (char *) (head + 1);
+ (void) fputs (buf, CO_OUT (head));
+ head->free = head->size;
+ *buf = 0;
+}
+
+inline static void
+co_flush (char buf[])
+{
+ struct cohead *head = (struct cohead *) buf;
+ if (head->free != head->size)
+ _co_flush (head);
+}
+
+int co_wr_uint (char buf[], uint64_t val, int wide);
+
+int co_app_ch (char buf[], char ch);
+#define co_ch_if(cond, buf, ch) ( \
+ (!!(cond)) ? co_app_ch((buf), (ch)) : 0)
+
+int co_append (char buf[], cosize_t max, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+#define co_app_if(cond, buf, max, fmt, arg...) ( \
+ (!!(cond)) ? co_append((buf), (max), (fmt), ##arg) : 0)
+#define co_app_fls(buf, max, fmt, arg...) do { \
+ co_append(buf, max, fmt, ##arg); \
+ co_flush(); \
+} while (0)
+
+#endif
+
+#ifndef SYSTEM_LB_H_
+#define SYSTEM_LB_H_
+
+inline static void
+futex_wait (volatile int *addr, int val)
+{
+ while (*addr == val)
+ {
+ (void) syscall (SYS_futex, addr, FUTEX_WAIT, val, NULL, NULL, 0);
+ }
+}
+
+inline static void
+futex_wake (volatile int *addr, int num)
+{
+ (void) syscall (SYS_futex, addr, FUTEX_WAKE, num, NULL, NULL, 0);
+}
+
+pthread_t lb_thread (void *(*proc) (void *), void *arg, const char *fmt, ...);
+
+inline static int
+lb_setcpu (pthread_t thread, int cpu)
+{
+ cpu_set_t set;
+ CPU_ZERO (&set);
+ CPU_SET (cpu, &set);
+ return pthread_setaffinity_np (thread, sizeof (set), &set);
+}
+
+inline static int
+lb_sleep (time_t sec, long nsec)
+{
+const struct timespec timeout = { tv_sec: sec, tv_nsec:nsec };
+ return nanosleep (&timeout, NULL);
+}
+
+void lb_sigsegv_setup ();
+
+#endif /* #ifndef SYSTEM_LB_H_ */
+
+#define FD_CLOSE(fd) do { \
+ if(fd >= 0) { \
+ _close(fd); \
+ fd = -1; \
+ } \
+} while(0)
+
+#define BUF_FREE(p) do { \
+ if (p) { \
+ free(p); \
+ p = NULL; \
+ } \
+} while (0)
+
+#endif
+
+#ifdef KERNEL_SYSCALL_API
+#define KERNEL_SYSCALL_API
+
+#define KAPI(name) extern (typeof name) *k_##name;
+#include "kapi.h"
+#undef API
+
+#endif