aboutsummaryrefslogtreecommitdiff
path: root/dependencies/nDPIsrvd.h
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2020-11-13 14:15:23 +0100
committerToni Uhlig <matzeton@googlemail.com>2020-11-13 14:26:51 +0100
commit7853c79cd66394e13e9962c5cfebc20dbbf7cbe5 (patch)
tree4f96ba2aa399537550aa61055b03eecff49ea3bc /dependencies/nDPIsrvd.h
parent7362da8c5fac01b97ee2060eb3e640ed8565ea24 (diff)
Renamed misleading "contrib" subfolder to "dependencies".
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'dependencies/nDPIsrvd.h')
-rw-r--r--dependencies/nDPIsrvd.h223
1 files changed, 223 insertions, 0 deletions
diff --git a/dependencies/nDPIsrvd.h b/dependencies/nDPIsrvd.h
new file mode 100644
index 000000000..320fdac08
--- /dev/null
+++ b/dependencies/nDPIsrvd.h
@@ -0,0 +1,223 @@
+#ifndef NDPISRVD_H
+#define NDPISRVD_H 1
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "jsmn/jsmn.h"
+
+struct nDPIsrvd_socket
+{
+ int fd;
+ int socket_family;
+
+ union {
+ struct
+ {
+ char const * dst_ip;
+ unsigned short dst_port;
+ } ip_socket;
+ struct
+ {
+ char * path;
+ } unix_socket;
+ } address;
+
+ struct
+ {
+ char raw[NETWORK_BUFFER_MAX_SIZE];
+ size_t used;
+ char * json_string;
+ size_t json_string_start;
+ unsigned long long int json_string_length;
+ } buffer;
+
+ struct
+ {
+ jsmn_parser parser;
+ jsmntok_t tokens[128];
+ int current_token;
+ int tokens_found;
+ } jsmn;
+};
+
+#define FIRST_ENUM_VALUE 1
+
+enum nDPIsrvd_connect_return
+{
+ CONNECT_OK = FIRST_ENUM_VALUE,
+ CONNECT_ERROR_SOCKET,
+ CONNECT_ERROR_PTON,
+ CONNECT_ERROR,
+ CONNECT_LAST_ENUM_VALUE
+};
+
+enum nDPIsrvd_read_return
+{
+ READ_OK = CONNECT_LAST_ENUM_VALUE,
+ READ_PEER_DISCONNECT,
+ READ_ERROR,
+ READ_LAST_ENUM_VALUE
+};
+
+enum nDPIsrvd_parse_return
+{
+ PARSE_OK = READ_LAST_ENUM_VALUE,
+ PARSE_INVALID_OPENING_CHAR,
+ PARSE_SIZE_EXCEEDS_CONVERSION_LIMIT,
+ PARSE_SIZE_MISSING,
+ PARSE_STRING_TOO_BIG,
+ PARSE_INVALID_CLOSING_CHAR,
+ PARSE_JSMN_ERROR,
+ PARSE_LAST_ENUM_VALUE
+};
+
+enum nDPIsrvd_callback_return
+{
+ CALLBACK_OK = PARSE_LAST_ENUM_VALUE,
+ CALLBACK_ERROR,
+ CALLBACK_LAST_ENUM_VALUE
+};
+
+typedef enum nDPIsrvd_callback_return (*json_callback)(struct nDPIsrvd_socket * const sock, void * user_data);
+
+static inline struct nDPIsrvd_socket * nDPIsrvd_init(void)
+{
+ struct nDPIsrvd_socket * sock = (struct nDPIsrvd_socket *)malloc(sizeof(*sock));
+
+ if (sock != NULL)
+ {
+ sock->fd = -1;
+ sock->socket_family = -1;
+ }
+ return sock;
+}
+
+static inline enum nDPIsrvd_connect_return nDPIsrvd_connect_ip(struct nDPIsrvd_socket * const sock,
+ char const * dst_ip,
+ unsigned short dst_port)
+{
+ struct sockaddr_in remote_addr = {};
+
+ sock->socket_family = remote_addr.sin_family = AF_INET;
+ sock->fd = socket(sock->socket_family, SOCK_STREAM, 0);
+
+ if (sock->fd < 0)
+ {
+ return CONNECT_ERROR_SOCKET;
+ }
+
+ if (inet_pton(sock->socket_family, &dst_ip[0], &remote_addr.sin_addr) != 1)
+ {
+ return CONNECT_ERROR_PTON;
+ }
+ remote_addr.sin_port = htons(dst_port);
+
+ if (connect(sock->fd, (struct sockaddr *)&remote_addr, sizeof(remote_addr)) != 0)
+ {
+ return CONNECT_ERROR;
+ }
+
+ return CONNECT_OK;
+}
+
+static inline enum nDPIsrvd_connect_return nDPIsrvd_connect_unix(struct nDPIsrvd_socket * const sock,
+ char const * const path)
+{
+ (void)sock;
+ (void)path;
+
+ return CONNECT_OK;
+}
+
+static inline enum nDPIsrvd_read_return nDPIsrvd_read(struct nDPIsrvd_socket * const sock)
+{
+ ssize_t bytes_read =
+ read(sock->fd, sock->buffer.raw + sock->buffer.used, sizeof(sock->buffer.raw) - sock->buffer.used);
+
+ if (bytes_read == 0)
+ {
+ return READ_PEER_DISCONNECT;
+ }
+ if (bytes_read < 0)
+ {
+ return READ_ERROR;
+ }
+
+ sock->buffer.used += bytes_read;
+
+ return READ_OK;
+}
+
+static inline enum nDPIsrvd_parse_return nDPIsrvd_parse(struct nDPIsrvd_socket * const sock,
+ json_callback cb,
+ void * user_data)
+{
+ while (sock->buffer.used >= nDPIsrvd_JSON_BYTES + 1)
+ {
+ if (sock->buffer.raw[nDPIsrvd_JSON_BYTES] != '{')
+ {
+ return PARSE_INVALID_OPENING_CHAR;
+ }
+
+ errno = 0;
+ sock->buffer.json_string_length = strtoull((const char *)sock->buffer.raw, &sock->buffer.json_string, 10);
+ sock->buffer.json_string_length += sock->buffer.json_string - sock->buffer.raw;
+ sock->buffer.json_string_start = sock->buffer.json_string - sock->buffer.raw;
+
+ if (errno == ERANGE)
+ {
+ return PARSE_SIZE_EXCEEDS_CONVERSION_LIMIT;
+ }
+ if (sock->buffer.json_string == sock->buffer.raw)
+ {
+ return PARSE_SIZE_MISSING;
+ }
+ if (sock->buffer.json_string_length > sizeof(sock->buffer.raw))
+ {
+ return PARSE_STRING_TOO_BIG;
+ }
+ if (sock->buffer.json_string_length > sock->buffer.used)
+ {
+ break;
+ }
+
+ if (sock->buffer.raw[sock->buffer.json_string_length - 1] != '}')
+ {
+ return PARSE_INVALID_CLOSING_CHAR;
+ }
+
+ jsmn_init(&sock->jsmn.parser);
+ sock->jsmn.tokens_found = jsmn_parse(&sock->jsmn.parser,
+ (char *)(sock->buffer.raw + sock->buffer.json_string_start),
+ sock->buffer.json_string_length - sock->buffer.json_string_start,
+ sock->jsmn.tokens,
+ sizeof(sock->jsmn.tokens) / sizeof(sock->jsmn.tokens[0]));
+ if (sock->jsmn.tokens_found < 0 || sock->jsmn.tokens[0].type != JSMN_OBJECT)
+ {
+ return PARSE_JSMN_ERROR;
+ }
+
+ for (sock->jsmn.current_token = 1; sock->jsmn.current_token < sock->jsmn.tokens_found;
+ sock->jsmn.current_token++)
+ {
+ cb(sock, user_data);
+ }
+
+ memmove(sock->buffer.raw,
+ sock->buffer.raw + sock->buffer.json_string_length,
+ sock->buffer.used - sock->buffer.json_string_length);
+ sock->buffer.used -= sock->buffer.json_string_length;
+ sock->buffer.json_string_length = 0;
+ sock->buffer.json_string_start = 0;
+ }
+
+ return PARSE_OK;
+}
+
+#endif