]> git.feebdaed.xyz Git - socialize.git/commitdiff
add: skeleton
authorseantywork <seantywork@gmail.com>
Tue, 18 Feb 2025 07:19:21 +0000 (16:19 +0900)
committerseantywork <seantywork@gmail.com>
Tue, 18 Feb 2025 07:19:21 +0000 (16:19 +0900)
21 files changed:
.gitattributes [new file with mode: 0644]
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md
cmd/cli/main.c [new file with mode: 0644]
cmd/rat-chat/main.c [new file with mode: 0644]
config.json [new file with mode: 0644]
include/rat-chat/core.h [new file with mode: 0644]
include/rat-chat/front/core.h [new file with mode: 0644]
include/rat-chat/sock/core.h [new file with mode: 0644]
include/rat-chat/utils.h [new file with mode: 0644]
src/core.c [new file with mode: 0644]
src/hubfront/core.c [new file with mode: 0644]
src/hubsock/core.c [new file with mode: 0644]
src/utils.c [new file with mode: 0644]
tls/ca.crt [new file with mode: 0644]
tls/list.txt [new file with mode: 0644]
tls/sub.crt [new file with mode: 0644]
tls/sub.csr [new file with mode: 0644]
vendor/.gitignore [new file with mode: 0644]
vendor/README.md [new file with mode: 0644]

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..3ccf886
--- /dev/null
@@ -0,0 +1,11 @@
+*.html linguist-vendored
+*.css linguist-vendored
+*.hpp linguist-vendored
+*.py linguist-vendored
+*.js linguist-vendored
+*.go linguist-vendored
+*.c linguist-vendored=false
+*.h linguist-vendored=false
+*.cc linguist-vendored
+*.rs linguist-vendored
+*.sh linguist-vendored=false
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..067b105
--- /dev/null
@@ -0,0 +1,13 @@
+*.o
+*.out
+*.so
+*.a
+*.run
+*.cmd
+*.ko
+*.mod
+*.symvers
+*.order
+*.mod.c
+.vscode
+*.pem
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..1bcd41c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,93 @@
+
+
+GCC_DEV_FLAGS := -Wall -g
+
+GCC_REL_FLAGS := -Wall
+
+GCC_OBJ_FLAGS := -Wall -c
+
+DEP_PACKAGES := libssl-dev
+
+DEP_MONGOOSE := git clone https://github.com/seantywork/mongoose.git
+
+DEP_CJSON := git clone https://github.com/seantywork/cJSON.git
+
+INCLUDES := -I./include -I./vendor
+
+LIBS := -lpthread -lssl -lcrypto 
+
+
+OBJS := core.o
+OBJS += utils.o
+OBJS += sock.o
+OBJS += front.o
+
+DEP_OBJS := mongoose.o
+DEP_OBJS += cJSON.o
+
+
+all: 
+
+       @echo "rat-chat: dev, release"
+
+
+deps:
+
+       apt-get update
+
+       apt-get -y install $(DEP_PACKAGES)
+
+.PHONY: vendor
+vendor:
+
+       cd vendor && rm -rf mongoose && $(DEP_MONGOOSE)
+
+       cd vendor && rm -rf cJSON && $(DEP_CJSON)
+
+
+dev: $(OBJS) $(DEP_OBJS)
+
+       gcc $(GCC_DEV_FLAGS) $(INCLUDES) -o rat-chat.out cmd/rat-chat/main.c $(OBJS) $(DEP_OBJS) $(LIBS) 
+
+
+release: $(OBJS) $(DEP_OBJS)
+
+       gcc $(GCC_REL_FLAGS) $(INCLUDES) -o rat-chat.out cmd/rat-chat/main.c $(OBJS) $(DEP_OBJS) $(LIBS) 
+
+
+
+
+core.o:
+
+       gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o core.o src/core.c 
+
+
+utils.o:
+
+       gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o utils.o src/utils.c 
+
+sock.o:
+
+       gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o sock.o src/hubsock/core.c 
+
+front.o:
+
+       gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o front.o src/hubfront/core.c 
+
+
+mongoose.o:
+
+
+       gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o mongoose.o vendor/mongoose/mongoose.c 
+
+cJSON.o:
+
+       gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o cJSON.o vendor/cJSON/cJSON.c 
+
+
+
+
+clean:
+
+       rm -rf *.o *.out *.txt
+
index a84b96604437bba37acb686bdeef47601be950f0..77d8c999b7c4c494f1ddbe3267e69df8d5c78ce1 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
-# frankc
+# rat-chat
+
+a dumb way to share linux system info, excute commands, and ... also chat
\ No newline at end of file
diff --git a/cmd/cli/main.c b/cmd/cli/main.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/cmd/rat-chat/main.c b/cmd/rat-chat/main.c
new file mode 100644 (file)
index 0000000..6c3a564
--- /dev/null
@@ -0,0 +1,41 @@
+
+#include "rat-chat/sock/core.h"
+#include "rat-chat/front/core.h"
+
+#include "rat-chat/utils.h"
+FILE* LOGFP;
+
+pthread_mutex_t G_MTX;
+
+int main(){
+
+
+  srand((unsigned int)time(NULL));
+
+  LOGFP = fopen("log.txt","a");
+
+
+  pthread_t sock_tid;
+  pthread_t front_tid;
+
+  if (pthread_mutex_init(&G_MTX, NULL) != 0) { 
+      printf("mutex init has failed\n"); 
+      return -1; 
+  } 
+
+
+  pthread_create(&front_tid, NULL, (void*)front_listen_and_serve, NULL);
+
+  sleepms(500);
+
+  pthread_create(&sock_tid, NULL, (void*)sock_listen_and_serve, NULL);
+
+  sleepms(500);
+
+
+  pthread_join(front_tid, NULL);
+
+  fclose(LOGFP);
+
+
+}
\ No newline at end of file
diff --git a/config.json b/config.json
new file mode 100644 (file)
index 0000000..d291df5
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "users":[
+        {
+            "id": "seantywork@gmail.com",
+            "pw": "hackme"
+        }
+    ]
+
+}
diff --git a/include/rat-chat/core.h b/include/rat-chat/core.h
new file mode 100644 (file)
index 0000000..70f851f
--- /dev/null
@@ -0,0 +1,298 @@
+#ifndef _FRANK_HUB_H_
+#define _FRANK_HUB_H_
+
+
+
+#include <stdio.h> 
+#include <netdb.h> 
+#include <netinet/in.h> 
+#include <stdlib.h> 
+#include <string.h> 
+#include <stdint.h>
+#include <sys/socket.h> 
+#include <sys/types.h> 
+#include <unistd.h> 
+#include <time.h>
+#include <endian.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <sys/time.h>
+// ep headers
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <arpa/inet.h>
+// ssl headers
+#include <signal.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "mongoose/mongoose.h"
+#include "cJSON/cJSON.h"
+
+#define DEBUG_THIS 0
+
+#define HUB_WORD           8
+#define HUB_HEADER_BYTELEN HUB_WORD * 3
+#define HUB_BODY_BYTELEN   HUB_WORD * 1
+#define HUB_BODY_BYTEMAX   HUB_WORD * 1280 //10KB
+#define HUB_TIMEOUT_MS 5000
+#define HUB_HEADER_AUTHSOCK "AUTHSOCK"
+#define HUB_HEADER_AUTHFRONT "AUTHFRONT"
+#define HUB_HEADER_AUTHFRANK "AUTHFRANK"
+#define HUB_HEADER_SENDSOCK "SENDSOCK"
+#define HUB_HEADER_RECVSOCK "RECVSOCK"
+#define HUB_HEADER_SENDFRONT "SENDFRONT"
+#define HUB_HEADER_RECVFRONT "RECVFRONT"
+#define HUB_HEADER_SENDFRANK "SENDFRANK"
+#define HUB_HEADER_RECVFRANK "RECVFRANK"
+
+#define TRUE 1
+#define FALSE 0
+#define MAX_BUFF HUB_BODY_BYTEMAX
+#define MAX_CONN 80
+#define MAX_ID_LEN 1024
+#define MAX_PW_LEN 4096
+#define PORT_FRONT 3000
+#define PORT_SOCK 3001 
+
+
+#define ISSOCK 1
+#define ISFRONT 2
+#define CHAN_ISSOCK 3
+#define CHAN_ISFRONT 4
+
+
+
+#define MAX_DEVICE_NAME 40
+#define MAX_EVENTS_NO 400
+#define MAX_EVENT_TEXT_SIZE 10
+#define EVENTS_PER_PAGE 20
+
+#define MAX_USER_NAME 1024
+#define MAX_USER_PASS 2048
+#define MAX_USER_ACCESS_TOKEN 1024
+
+#define MAX_COOKIE_LEN 1024
+#define MAX_COOKIE_KEYLEN 32
+
+#define MAX_USERS 10
+
+#define MAX_PUBLIC_URI_LEN 512
+
+#define MAX_REQUEST_URI_LEN 1024 * 10
+#define MAX_CLIENT_ID_LEN 1024
+#define MAX_CLIENT_SECRET_LEN 1024
+#define MAX_POST_FIELDS_LEN 1024 * 10
+
+#define MAX_CODELEN 256
+#define GOAUTH_TOKENLEN 512
+
+#define MAX_REST_BUFF 1024 * 10
+#define MAX_WS_BUFF 1024 * 10
+
+#define WS_MAX_COMMAND_LEN 32
+#define WS_MAX_COMMAND_DATA_LEN WS_MAX_COMMAND_LEN * 8
+#define WS_MAX_COMMAND_RECV_LEN WS_MAX_COMMAND_LEN * 8 * 8
+
+#define WS_COMMAND_REQ_KEY "reqkey"
+#define WS_COMMAND_ROUNDTRIP "roundtrip"
+
+#define DEFAULT_RANDLEN 64
+
+
+
+#ifndef HTTP_URL
+#define HTTP_URL "http://0.0.0.0:3000"
+#endif
+
+
+#ifndef HTTPS_URL
+#define HTTPS_URL "https://0.0.0.0:3443"
+#endif
+
+
+#define IS_BIG_ENDIAN (!*(unsigned char *)&(uint16_t){1})
+
+#if __BIG_ENDIAN__
+# define htonll(x) (x)
+# define ntohll(x) (x)
+#else
+# define htonll(x) (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
+# define ntohll(x) (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
+#endif
+
+#ifndef SERVER_KEY
+# define SERVER_KEY "tls/sub_priv.pem"
+#endif
+
+#ifndef SERVER_CERT
+# define SERVER_CERT "tls/sub.crt"
+#endif
+
+#ifndef HUB_CA_CERT
+# define HUB_CA_CERT "tls/ca.crt"
+#endif
+
+#define DEFAULT_RANDLEN 64
+//#define WAIT 7   
+
+
+
+
+
+struct user {
+    char name[MAX_USER_NAME];
+    char pass[MAX_USER_PASS];
+};
+
+
+struct CHANNEL_CONTEXT {
+    int allocated;
+    int sockfd;
+    int frontfd;
+    char id[MAX_ID_LEN];
+    char pw[MAX_PW_LEN];
+    SSL *ssl;
+    SSL_CTX *ctx;
+    int fds[MAX_CONN];
+    SSL *ssls[MAX_CONN];
+    SSL_CTX *ctxs[MAX_CONN];
+};
+
+struct SOCK_CONTEXT {
+    int allocated;
+    int sockfd;
+    SSL *ssl;
+    SSL_CTX *ctx;
+    char id[MAX_ID_LEN];
+
+};
+
+
+
+
+struct HUB_PACKET {
+
+    int ctx_type;
+    char id[MAX_ID_LEN];
+    int fd;
+    uint8_t header[HUB_HEADER_BYTELEN];
+    uint64_t body_len;
+    uint8_t wbuff[MAX_BUFF];
+    uint8_t* rbuff;
+
+    int flag;
+
+};
+
+struct settings {
+    bool log_enabled;
+    int log_level;
+    long brightness;
+    char *device_name;
+  };
+
+
+int make_socket_non_blocking (int sfd);
+
+SSL_CTX *create_context();
+
+void configure_context(SSL_CTX *ctx);
+
+
+int sig_verify(const char* cert_pem, const char* intermediate_pem);
+
+int extract_common_name(uint8_t* common_name, const char* cert);
+
+int idpw_verify(char* idpw);
+
+int update_chanctx_from_userinfo(char* id, char* pw);
+
+int update_chanctx_from_sockctx(int fd, char* id);
+
+
+int get_chanctx_by_id(char* id);
+
+int get_chanctx_by_fd(int fd, int type);
+
+int set_sockctx_by_fd(int fd);
+
+int get_sockctx_by_fd(int fd);
+
+
+
+int calloc_chanctx();
+
+int free_chanctx(int idx);
+
+int calloc_sockctx();
+
+int free_sockctx(int idx, int memfree);
+
+
+
+
+int chanctx_write(int type, char* id, int write_len, uint8_t* wbuff);
+
+int chanctx_read(int type, char* id, int read_len, uint8_t* rbuff);
+
+int sockctx_write(int fd, int write_len, uint8_t* wbuff);
+
+int sockctx_read(int fd, int read_len, uint8_t* rbuff);
+
+
+
+
+void ctx_write_packet(struct HUB_PACKET* hp);
+
+
+void ctx_read_packet(struct HUB_PACKET* hp);
+
+
+
+
+extern char CA_CERT[MAX_PW_LEN];
+
+
+extern int s_sig_num;
+
+
+extern struct settings s_settings;
+
+extern uint64_t s_boot_timestamp; 
+
+extern char *s_json_header;
+
+extern struct mg_mgr mgr;
+
+
+extern struct CHANNEL_CONTEXT CHAN_CTX[MAX_CONN];
+
+extern struct SOCK_CONTEXT SOCK_CTX[MAX_CONN];
+
+
+
+extern FILE* LOGFP;
+extern pthread_mutex_t G_MTX;
+
+extern int SOCK_FD;
+extern int SOCK_SERVLEN;
+extern int SOCK_EPLFD;
+extern struct epoll_event SOCK_EVENT;
+extern struct epoll_event *SOCK_EVENTARRAY;
+
+
+extern int FRONT_FD;
+extern int FRONT_SERVLEN;
+extern int FRONT_EPLFD;
+extern struct epoll_event FRONT_EVENT;
+extern struct epoll_event *FRONT_EVENTARRAY;
+
+extern int MAX_SD;
+
+extern int OPT;
+
+
+
+#endif
\ No newline at end of file
diff --git a/include/rat-chat/front/core.h b/include/rat-chat/front/core.h
new file mode 100644 (file)
index 0000000..bdababe
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _FRANK_HUB_FRONT_H_
+#define _FRANK_HUB_FRONT_H_
+
+#include "rat-chat/core.h"
+
+
+
+
+
+
+void* front_listen_and_serve(void* varg);
+
+
+void sntp_fn(struct mg_connection *c, int ev, void *ev_data);
+
+void timer_sntp_fn(void *param);
+
+void route(struct mg_connection *c, int ev, void *ev_data);
+
+
+void front_handler(struct mg_connection *c, struct mg_ws_message *wm);
+
+
+void handle_healtiness_probe(struct mg_connection *c, struct mg_http_message *hm);
+
+
+int front_authenticate(struct mg_connection* c, struct mg_ws_message *wm, int* initial, char* command, char* data);
+
+void front_communicate(int chan_idx, char* command, char* data);
+
+
+
+
+
+
+#endif
\ No newline at end of file
diff --git a/include/rat-chat/sock/core.h b/include/rat-chat/sock/core.h
new file mode 100644 (file)
index 0000000..f3da997
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _FRANK_HUB_SOCK_H_
+#define _FRANK_HUB_SOCK_H_
+
+
+
+#include "rat-chat/core.h"
+
+
+
+void sock_listen_and_serve(void* varg);
+
+
+void sock_handle_conn();
+
+
+void sock_handle_client(int cfd);
+
+void sock_authenticate(int cfd);
+
+void sock_communicate(int chan_idx);
+
+#endif
\ No newline at end of file
diff --git a/include/rat-chat/utils.h b/include/rat-chat/utils.h
new file mode 100644 (file)
index 0000000..f6bd1f6
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _FRANK_HUB_UTILS_H_
+#define _FRANK_HUB_UTILS_H_
+
+
+
+#include "rat-chat/core.h"
+
+
+#define MAX_TIMESTR_LEN 80
+#define MAX_LOG_TXT_LEN 1024 
+#define MAX_FMT_ARG_LEN 128
+
+
+int read_file_to_buffer(uint8_t* buff, int max_buff_len, char* file_path);
+
+int gen_random_bytestream(uint8_t* bytes, size_t num_bytes);
+
+int bin2hex(uint8_t* hexarray, int arrlen, uint8_t* bytearray);
+
+
+
+
+
+
+
+void get_current_time_string(char* tstr);
+
+void sleepms(long ms);
+
+void fmt_logln(FILE *fp, char* fmt_out, ...);
+
+
+#endif
diff --git a/src/core.c b/src/core.c
new file mode 100644 (file)
index 0000000..406d660
--- /dev/null
@@ -0,0 +1,1095 @@
+#include "rat-chat/core.h"
+
+
+struct CHANNEL_CONTEXT CHAN_CTX[MAX_CONN];
+
+struct SOCK_CONTEXT SOCK_CTX[MAX_CONN];
+
+
+
+int make_socket_non_blocking (int sfd){
+    int flags, s;
+
+    flags = fcntl (sfd, F_GETFL, 0);
+    if (flags == -1)
+    {
+        perror ("fcntl get");
+        return -1;
+    }
+
+    flags |= O_NONBLOCK;
+    s = fcntl (sfd, F_SETFL, flags);
+    if (s == -1)
+    {
+        perror ("fcntl set");
+        return -2;
+    }
+
+    return 0;
+}
+
+
+SSL_CTX *create_context(){
+
+    const SSL_METHOD *method;
+    SSL_CTX *ctx;
+
+    method = TLS_server_method();
+
+    ctx = SSL_CTX_new(method);
+    if (!ctx) {
+        perror("Unable to create SSL context");
+        ERR_print_errors_fp(stderr);
+        exit(EXIT_FAILURE);
+    }
+
+    return ctx;
+}
+
+void configure_context(SSL_CTX *ctx){
+
+    if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT, SSL_FILETYPE_PEM) <= 0) {
+        ERR_print_errors_fp(stderr);
+        exit(EXIT_FAILURE);
+    }
+
+    if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= 0 ) {
+        ERR_print_errors_fp(stderr);
+        exit(EXIT_FAILURE);
+    }
+}
+
+int sig_verify(const char* cert_pem, const char* intermediate_pem){
+
+    BIO *b = BIO_new(BIO_s_mem());
+    BIO_puts(b, intermediate_pem);
+    X509 * issuer = PEM_read_bio_X509(b, NULL, NULL, NULL);
+    EVP_PKEY *signing_key=X509_get_pubkey(issuer);
+    BIO *c = BIO_new(BIO_s_mem());
+    BIO_puts(c, cert_pem);
+    X509 * x509 = PEM_read_bio_X509(c, NULL, NULL, NULL);
+    int result = X509_verify(x509, signing_key);
+    EVP_PKEY_free(signing_key);
+    BIO_free(b);
+    BIO_free(c);
+    X509_free(x509);
+    X509_free(issuer);
+    return result;
+}
+
+int extract_common_name(uint8_t* common_name, const char* cert) {
+
+    BIO *b = BIO_new(BIO_s_mem());
+    BIO_puts(b, cert);
+    X509 * x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
+
+    int ret_cn = -1;
+
+    int common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name(x509), NID_commonName, -1);
+    if (common_name_loc < 0) {
+        BIO_free(b);
+        X509_free(x509);
+        return ret_cn;
+    }
+    
+    X509_NAME_ENTRY * common_name_entry = X509_NAME_get_entry(X509_get_subject_name(x509), common_name_loc);
+    if (common_name_entry == NULL) {
+        BIO_free(b);
+        X509_free(x509);
+        return ret_cn;
+    }
+    
+    ASN1_STRING * common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
+    if (common_name_asn1 == NULL) {
+        BIO_free(b);
+        X509_free(x509);
+        return ret_cn;
+    }
+    
+    char const * common_name_str = (char const *) ASN1_STRING_get0_data(common_name_asn1);
+    
+    if (ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) {
+        BIO_free(b);
+        X509_free(x509);
+        return ret_cn;
+    }
+
+    strcpy(common_name, common_name_str);
+
+    ret_cn = 1;
+    
+    BIO_free(b);
+    X509_free(x509);
+
+    return ret_cn;
+}
+
+
+int idpw_verify(char* idpw){
+
+    int verify = -1;
+
+    char* token;
+
+    char* delim = ":";
+
+    uint8_t id[MAX_ID_LEN] = {0};
+    uint8_t pw[MAX_PW_LEN] = {0};
+
+    token = strtok(idpw, delim);
+    
+    int idx = 0;
+    
+    while( token != NULL ) {
+
+        if(idx > 1) {
+            break;
+        }
+
+        if(idx == 0){
+
+            strncpy(id, token, MAX_ID_LEN);
+
+        } else {
+
+            strncpy(pw, token, MAX_PW_LEN);
+
+        }
+        
+        token = strtok(NULL, delim);
+
+        idx += 1;
+    }
+
+    if(idx != 2){
+        return -1;
+    }
+
+    int chan_idx = get_chanctx_by_id(id);
+
+    if(chan_idx < 0){
+
+        return -2;
+
+    }
+
+    if(strncmp(CHAN_CTX[chan_idx].pw, pw, MAX_PW_LEN) != 0){
+
+        return -3;
+
+    }
+
+    int verified_idx = chan_idx;
+
+
+    return verified_idx;
+
+}
+
+int update_chanctx_from_userinfo(char* id, char* pw){
+
+    int ret_idx = -1;
+
+    int chan_idx = get_chanctx_by_id(id);
+
+    if(chan_idx < 0){
+
+
+        ret_idx = calloc_chanctx();
+
+        if(ret_idx < 0){
+
+            printf("id %s failed to calloc chanctx: max conn\n", id);
+
+            return -2;
+
+        }
+
+
+        strcpy(CHAN_CTX[ret_idx].id, id);
+        strcpy(CHAN_CTX[ret_idx].pw, pw);
+
+        chan_idx = ret_idx;
+
+        printf("id %s added to chanctx from userinfo\n", id);
+
+
+    } else {
+
+
+        strcpy(CHAN_CTX[chan_idx].pw, pw);
+
+
+        printf("id %s modified for existing chanctx from userinfo\n", id);
+
+
+    }
+
+
+
+    ret_idx = chan_idx;
+
+
+    return ret_idx;
+
+}
+
+
+int update_chanctx_from_sockctx(int fd, char* id){
+
+
+    int ret_idx = -1;
+
+
+    int sock_idx = get_sockctx_by_fd(fd);
+
+    if(sock_idx < 0){
+
+        printf("no sock fd associated with: %d\n",fd);
+
+        return -1;
+    }
+
+    int chan_idx = get_chanctx_by_id(id);
+
+
+    if(chan_idx < 0){
+
+        ret_idx = calloc_chanctx();
+
+        if(ret_idx < 0){
+
+            printf("sock fd %d failed to calloc chanctx: max conn\n", fd);
+
+            return -2;
+
+        }
+
+        chan_idx = ret_idx;
+
+        CHAN_CTX[chan_idx].sockfd = SOCK_CTX[sock_idx].sockfd;
+        CHAN_CTX[chan_idx].ssl = SOCK_CTX[sock_idx].ssl;
+        CHAN_CTX[chan_idx].ctx = SOCK_CTX[sock_idx].ctx;
+
+        free_sockctx(sock_idx, 0);
+
+        strcpy(CHAN_CTX[chan_idx].id, id);
+
+        printf("id %s added to chanctx %d from sock\n", id, chan_idx);
+
+    } else {
+
+
+        CHAN_CTX[chan_idx].sockfd = SOCK_CTX[sock_idx].sockfd;
+        CHAN_CTX[chan_idx].ssl = SOCK_CTX[sock_idx].ssl;
+        CHAN_CTX[chan_idx].ctx = SOCK_CTX[sock_idx].ctx;
+
+        free_sockctx(sock_idx, 0);
+
+        printf("id %s modified for existing chanctx from sock\n", id);
+
+
+    }
+
+    ret_idx = chan_idx;
+
+    return ret_idx;
+
+}
+
+
+int get_chanctx_by_id(char* id){
+
+
+    for(int i = 0; i < MAX_CONN; i++){
+
+        if(strcmp(CHAN_CTX[i].id, id) == 0){
+
+            return i;
+
+        }
+
+    }
+
+
+    return -1;
+}
+
+
+
+int get_chanctx_by_fd(int fd, int type){
+
+
+    if(type == ISSOCK){
+
+        for(int i = 0; i < MAX_CONN; i++){
+
+            if(CHAN_CTX[i].sockfd == fd){
+
+                return i;
+
+            }
+
+        }
+
+
+    }
+
+
+
+    return -1;
+}
+
+
+
+
+
+
+int set_sockctx_by_fd(int fd){
+
+
+    int new_idx = calloc_sockctx();
+
+    if(new_idx < 0){
+
+
+        return -1;
+
+    }
+
+    SOCK_CTX[new_idx].sockfd = fd;
+
+    return new_idx;
+}
+
+
+
+
+int get_sockctx_by_fd(int fd){
+
+
+    for(int i = 0; i < MAX_CONN; i++){
+
+
+        if(SOCK_CTX[i].sockfd == fd){
+
+            return i;
+
+        }
+
+
+    }
+
+
+
+    return -1;
+}
+
+
+
+
+
+
+int calloc_chanctx(){
+
+    for(int i = 0; i < MAX_CONN; i++){
+
+
+        if(CHAN_CTX[i].allocated == 0){
+
+            CHAN_CTX[i].allocated = 1;
+
+            CHAN_CTX[i].sockfd = 0;
+            CHAN_CTX[i].frontfd = 0;
+
+            memset(CHAN_CTX[i].id, 0, MAX_ID_LEN * sizeof(char));
+            memset(CHAN_CTX[i].pw, 0, MAX_PW_LEN * sizeof(char));        
+
+            CHAN_CTX[i].ssl = NULL;
+            CHAN_CTX[i].ctx = NULL;
+
+            return i;
+
+        }
+
+    }
+
+
+    return -1;
+}
+
+
+int free_chanctx(int idx){
+
+    if(idx >= MAX_CONN){
+
+        return -10;
+    }
+
+    if(CHAN_CTX[idx].allocated != 1){
+
+        return -1;
+
+    }
+
+    if (CHAN_CTX[idx].ssl != NULL){
+
+        SSL_shutdown(CHAN_CTX[idx].ssl);
+        SSL_free(CHAN_CTX[idx].ssl);
+
+    }
+
+    if (CHAN_CTX[idx].ctx != NULL){
+
+        SSL_CTX_free(CHAN_CTX[idx].ctx);
+
+    }
+
+    CHAN_CTX[idx].sockfd = 0;
+    CHAN_CTX[idx].frontfd = 0;
+
+
+    memset(CHAN_CTX[idx].id, 0, MAX_ID_LEN * sizeof(char));
+    memset(CHAN_CTX[idx].pw, 0, MAX_PW_LEN * sizeof(char));   
+
+    CHAN_CTX[idx].ssl = NULL;
+    CHAN_CTX[idx].ctx = NULL;
+
+    CHAN_CTX[idx].allocated = 0;
+
+    return 0;
+}
+
+
+int calloc_sockctx(){
+
+    for(int i = 0; i < MAX_CONN; i++){
+
+        if(SOCK_CTX[i].allocated == 0){
+
+            SOCK_CTX[i].ctx = NULL;
+            SOCK_CTX[i].ssl = NULL;
+            SOCK_CTX[i].sockfd = 0;
+
+            SOCK_CTX[i].allocated = 1;
+
+            return i;
+
+        }
+
+
+    }
+
+
+    return -1;
+}
+
+
+
+int free_sockctx(int idx, int memfree){
+
+
+    if (idx >= MAX_CONN){
+        return -10;
+    }
+
+    if(SOCK_CTX[idx].allocated != 1){
+        return -1;
+    }
+
+    if(memfree == 1){
+
+        SSL_shutdown(SOCK_CTX[idx].ssl);
+        SSL_free(SOCK_CTX[idx].ssl);
+        SSL_CTX_free(SOCK_CTX[idx].ctx);
+
+    } else {
+
+        SOCK_CTX[idx].ssl = NULL;
+        SOCK_CTX[idx].ctx = NULL;
+
+    }
+
+    SOCK_CTX[idx].sockfd = 0;
+    SOCK_CTX[idx].allocated = 0;
+
+
+    return 0;
+}
+
+
+int chanctx_write(int type, char* id, int write_len, uint8_t* wbuff){
+
+    if(type == ISSOCK){
+
+        int valwrite = 0;
+
+        int chan_idx = 0;
+
+        chan_idx = get_chanctx_by_id(id);
+
+        if(chan_idx < 0){
+
+            printf("write: no such id: %s\n", id);
+
+            return -1;
+        }
+
+
+        SSL* sslfd = CHAN_CTX[chan_idx].ssl;
+
+
+        valwrite = SSL_write(sslfd, wbuff, write_len);
+
+
+        if (valwrite <= 0){
+
+            printf("write: client gone: %d\n", valwrite);
+
+            return -2;
+
+        }
+
+        return valwrite;
+
+
+    }
+
+
+    printf("invalid chanctx write type: %d\n", type);
+
+    return -100;
+
+
+}
+
+int chanctx_read(int type, char* id, int read_len, uint8_t* rbuff){
+
+    if(type == ISSOCK){
+
+        int valread = 0;
+
+        int chan_idx = 0;
+
+        int ms_until_deadline = 0;
+
+        chan_idx = get_chanctx_by_id(id);
+
+        if(chan_idx < 0){
+
+            printf("read: no such id: %s\n", id);
+
+            return -1;
+        }
+
+
+        SSL* sslfd = CHAN_CTX[chan_idx].ssl;
+
+        uint8_t* rbuff_tmp = (uint8_t*)malloc(read_len * sizeof(uint8_t));
+
+        memset(rbuff_tmp, 0, read_len * sizeof(uint8_t));
+
+        int valread_tmp = 0;
+
+        struct timespec rnow;
+
+        clock_gettime(CLOCK_MONOTONIC_RAW, &rnow);
+
+        struct timespec rdeadline;
+
+        while(valread < read_len){
+
+            clock_gettime(CLOCK_MONOTONIC_RAW, &rdeadline);
+
+            ms_until_deadline = ((rdeadline.tv_sec - rnow.tv_sec) * 1000 + (rdeadline.tv_nsec - rnow.tv_nsec) / 1000000);
+
+            if(ms_until_deadline > HUB_TIMEOUT_MS){
+                
+                printf("time limit exceeded\n");
+
+                free(rbuff_tmp);
+
+                return -10;
+            }
+
+            valread_tmp = SSL_read(sslfd, (void*)rbuff_tmp, read_len);
+
+            if(valread_tmp <= 0){
+                
+                if(errno == EAGAIN){
+
+                    memset(rbuff_tmp, 0, read_len * sizeof(uint8_t));
+
+                    valread_tmp = 0;
+
+                    continue;
+                }
+
+                printf("read: client gone: %d\n", valread);
+
+                free(rbuff_tmp);
+
+                return -2;
+            }
+
+            for(int i = 0 ; i < valread_tmp; i++){
+
+                int idx = valread + i;
+
+                rbuff[idx] = rbuff_tmp[i];
+
+            }
+
+            valread += valread_tmp;        
+
+            memset(rbuff_tmp, 0, read_len * sizeof(uint8_t));
+
+            valread_tmp = 0;
+
+        }
+
+
+        free(rbuff_tmp);
+
+        return valread;
+
+
+    }
+
+
+    printf("invalid chanctx read type: %d\n", type);
+
+    return -100;
+
+
+}
+
+
+int sockctx_write(int fd, int write_len, uint8_t* wbuff){
+
+
+    int valwrite = 0;
+
+    int sock_idx = 0;
+
+    sock_idx = get_sockctx_by_fd(fd);
+
+    if(sock_idx < 0){
+
+        printf("write: no such fd: %d\n", fd);
+
+        return -1;
+    }
+
+    SSL* sslfd = SOCK_CTX[sock_idx].ssl;
+
+
+    valwrite = SSL_write(sslfd, (void*)wbuff, write_len);
+
+    if (valwrite <= 0){
+
+        printf("write: client gone: %d\n", valwrite);
+
+        return -2;
+
+    }
+
+    return valwrite;
+
+
+
+}
+
+int sockctx_read(int fd, int read_len, uint8_t* rbuff){
+
+
+
+    int valread = 0;
+
+    int sock_idx = 0;
+
+    int ms_until_deadline = 0;
+
+    sock_idx = get_sockctx_by_fd(fd);
+
+    if(sock_idx < 0){
+
+        printf("read: no such fd: %d\n", fd);
+
+        return -1;
+    }
+
+
+    SSL* sslfd = SOCK_CTX[sock_idx].ssl;
+
+    uint8_t* rbuff_tmp = (uint8_t*)malloc(read_len * sizeof(uint8_t));
+
+    memset(rbuff_tmp, 0, read_len * sizeof(uint8_t));
+
+    int valread_tmp = 0;
+
+    struct timespec rnow;
+
+    clock_gettime(CLOCK_MONOTONIC_RAW, &rnow);
+
+    struct timespec rdeadline;
+
+    while(valread < read_len){
+
+        clock_gettime(CLOCK_MONOTONIC_RAW, &rdeadline);
+
+        ms_until_deadline = ((rdeadline.tv_sec - rnow.tv_sec) * 1000 + (rdeadline.tv_nsec - rnow.tv_nsec) / 1000000);
+
+        if(ms_until_deadline > HUB_TIMEOUT_MS){
+            
+            printf("time limit exceeded\n");
+
+            free(rbuff_tmp);
+
+            return -10;
+        }
+
+        valread_tmp = SSL_read(sslfd, (void*)rbuff_tmp, read_len);
+
+        if(valread_tmp <= 0){
+
+            if(errno == EAGAIN){
+
+                memset(rbuff_tmp, 0, read_len * sizeof(uint8_t));
+
+                valread_tmp = 0;
+
+                continue;
+            }
+
+            printf("read: client gone: %d\n", valread);
+
+            free(rbuff_tmp);
+
+            return -2;
+        }
+
+        for(int i = 0 ; i < valread_tmp; i++){
+
+            int idx = valread + i;
+
+            rbuff[idx] = rbuff_tmp[i];
+
+        }
+
+        valread += valread_tmp;        
+
+        memset(rbuff_tmp, 0, read_len * sizeof(uint8_t));
+
+        valread_tmp = 0;
+
+    }
+
+    free(rbuff_tmp);
+
+    return valread;
+
+
+}
+
+
+
+
+
+
+
+void ctx_write_packet(struct HUB_PACKET* hp){
+
+    int valwrite = 0;
+
+
+    if(hp->ctx_type == CHAN_ISSOCK){
+        
+
+        valwrite = chanctx_write(ISSOCK, hp->id, HUB_HEADER_BYTELEN, hp->header);
+
+        if(valwrite <= 0){
+
+            printf("packet send header failed\n");
+
+            hp->flag = valwrite;
+
+            return;
+
+        }
+
+        uint8_t body_len_byte[HUB_BODY_BYTELEN] = {0};
+
+        uint64_t body_len_new = 0;
+
+        body_len_new = htonll(hp->body_len);
+
+        
+        memcpy(body_len_byte, &body_len_new, HUB_BODY_BYTELEN);
+
+
+        valwrite = chanctx_write(ISSOCK, hp->id, HUB_BODY_BYTELEN, body_len_byte);
+
+        if(valwrite <= 0){
+
+            printf("packet send body len failed\n");
+
+            hp->flag = valwrite;
+
+            return;
+
+        }
+
+        valwrite = chanctx_write(ISSOCK, hp->id, hp->body_len, hp->wbuff);
+
+
+        if(valwrite <= 0){
+
+            printf("packet send buff failed\n");
+
+            hp->flag = valwrite;
+
+            return;
+
+        } 
+
+        hp->flag = valwrite;
+
+        return;
+
+
+    }
+
+
+    if(hp->ctx_type == ISSOCK){
+
+        valwrite = sockctx_write(hp->fd, HUB_HEADER_BYTELEN, hp->header);
+
+        if(valwrite <= 0){
+
+            printf("packet send header failed\n");
+
+            hp->flag = valwrite;
+
+            return;
+
+        }
+
+        uint8_t body_len_byte[HUB_BODY_BYTELEN] = {0};
+
+        uint64_t body_len_new = 0;
+
+        body_len_new = htonll(hp->body_len);
+
+        memcpy(body_len_byte, &body_len_new, HUB_BODY_BYTELEN);
+
+        valwrite = sockctx_write(hp->fd, HUB_BODY_BYTELEN, body_len_byte);
+
+        if(valwrite <= 0){
+
+            printf("packet send body len failed\n");
+
+            hp->flag = valwrite;
+
+            return;
+
+        }
+
+        valwrite = sockctx_write(hp->fd, hp->body_len, hp->wbuff);
+
+        if(valwrite <= 0){
+
+            printf("packet send buff failed\n");
+
+            hp->flag = valwrite;
+
+            return;
+
+        } 
+
+        hp->flag = valwrite;
+
+        return;
+
+
+    }
+
+
+    printf("invalid ctx write packet type: %d\n", hp->ctx_type);
+
+    hp->flag = valwrite;
+
+
+    return;
+
+}
+
+
+void ctx_read_packet(struct HUB_PACKET* hp){
+
+    int valread = 0;
+
+    if(hp->ctx_type == CHAN_ISSOCK){
+
+        valread = chanctx_read(ISSOCK, hp->id, HUB_HEADER_BYTELEN, hp->header);
+
+        if(valread <= 0){
+
+            printf("packet recv header failed\n");
+
+            hp->flag = valread;
+
+            return;
+
+        }
+
+        uint8_t body_len_byte[HUB_BODY_BYTELEN] = {0};
+
+        uint64_t body_len = 0;
+
+        valread = chanctx_read(ISSOCK, hp->id, HUB_BODY_BYTELEN, body_len_byte);
+
+
+        if(valread <= 0){
+
+            printf("packet recv body len failed\n");
+
+            hp->flag = valread;
+
+            return;
+
+        }
+
+        memcpy(&body_len, body_len_byte, HUB_BODY_BYTELEN);
+
+        body_len = ntohll(body_len);
+
+        if(body_len > HUB_BODY_BYTEMAX){
+
+            printf("packet body len too long \n");
+
+            hp->flag = -10;
+
+            return;
+        }
+
+        hp->body_len = body_len;
+
+        hp->rbuff = (uint8_t*)malloc(hp->body_len * sizeof(uint8_t));
+
+        memset(hp->rbuff, 0, hp->body_len * sizeof(uint8_t));
+
+        valread = chanctx_read(ISSOCK, hp->id, hp->body_len, hp->rbuff);
+
+        if(valread <= 0){
+
+            printf("packet recv body failed\n");
+
+            free(hp->rbuff);
+
+            hp->flag = valread;
+
+            return;
+
+        }
+
+
+        hp->flag = valread;
+
+        return;
+
+
+    }
+
+
+
+
+
+    if(hp->ctx_type == ISSOCK){
+
+        valread = sockctx_read(hp->fd, HUB_HEADER_BYTELEN, hp->header);
+
+        if(valread <= 0){
+
+            printf("packet recv header failed\n");
+
+            hp->flag = valread;
+
+            return;
+
+        }
+
+        uint8_t body_len_byte[HUB_BODY_BYTELEN] = {0};
+
+        uint64_t body_len = 0;
+
+        valread = sockctx_read(hp->fd, HUB_BODY_BYTELEN, body_len_byte);
+
+        if(valread <= 0){
+
+            printf("packet recv body len failed\n");
+
+            hp->flag = valread;
+
+            return;
+
+        }
+
+        memcpy(&body_len, body_len_byte, HUB_BODY_BYTELEN);
+
+        body_len = ntohll(body_len);
+
+        if(body_len > HUB_BODY_BYTEMAX){
+
+            printf("packet body len too long \n");
+
+            hp->flag = -10;
+
+            return;
+        }
+
+        hp->body_len = body_len;
+
+        hp->rbuff = (uint8_t*)malloc(hp->body_len * sizeof(uint8_t));
+
+        memset(hp->rbuff, 0, hp->body_len * sizeof(uint8_t));
+
+        valread = sockctx_read(hp->fd, hp->body_len, hp->rbuff);
+
+        if(valread <= 0){
+
+            printf("packet recv body failed\n");
+
+            free(hp->rbuff);
+
+            hp->flag = valread;
+
+            return;
+
+        }
+
+        hp->flag = valread;
+
+        return;
+
+
+    }
+
+
+
+
+    printf("invalid ctx read packet type: %d\n", hp->ctx_type);
+
+    hp->flag = valread;
+
+    return;
+}
+
+
+
+
+
diff --git a/src/hubfront/core.c b/src/hubfront/core.c
new file mode 100644 (file)
index 0000000..c899687
--- /dev/null
@@ -0,0 +1,450 @@
+#include   "rat-chat/front/core.h"
+#include   "rat-chat/utils.h"
+
+
+struct settings s_settings = {true, 1, 57, NULL};
+
+uint64_t s_boot_timestamp = 0; 
+
+char* s_json_header =
+    "Content-Type: application/json\r\n"
+    "Cache-Control: no-cache\r\n";
+
+struct mg_mgr mgr;
+
+int s_sig_num = 0;
+
+
+void sntp_fn(struct mg_connection *c, int ev, void *ev_data) {
+  uint64_t *expiration_time = (uint64_t *) c->data;
+  if (ev == MG_EV_OPEN) {
+    *expiration_time = mg_millis() + 3000;  // Store expiration time in 3s
+  } else if (ev == MG_EV_SNTP_TIME) {
+    uint64_t t = *(uint64_t *) ev_data;
+    s_boot_timestamp = t - mg_millis();
+    c->is_closing = 1;
+  } else if (ev == MG_EV_POLL) {
+    if (mg_millis() > *expiration_time) c->is_closing = 1;
+  }
+}
+
+
+void timer_sntp_fn(void *param) {  // SNTP timer function. Sync up time
+  mg_sntp_connect(param, "udp://time.google.com:123", sntp_fn, NULL);
+}
+
+
+
+
+
+
+void handle_healtiness_probe(struct mg_connection *c, struct mg_http_message *hm){
+
+    char* ticket[MAX_USER_PASS] = {0};
+
+    char rest_buff[MAX_REST_BUFF] = {0};
+
+
+    cJSON* response = cJSON_CreateObject();
+
+    int datalen = 0;
+
+
+
+    cJSON_AddItemToObject(response, "status", cJSON_CreateString("success"));
+    cJSON_AddItemToObject(response, "data", cJSON_CreateString("fine"));
+
+    strcpy(rest_buff, cJSON_Print(response));
+
+    datalen = strlen(rest_buff);
+
+    mg_http_reply(c, 200, "", rest_buff);
+
+
+
+}
+
+
+
+
+void route(struct mg_connection *c, int ev, void *ev_data) {
+  
+  if (ev == MG_EV_ACCEPT) {
+  
+    if (c->fn_data != NULL) {  
+      struct mg_tls_opts opts = {0};
+      opts.cert = mg_unpacked("/certs/server_cert.pem");
+      opts.key = mg_unpacked("/certs/server_key.pem");
+      mg_tls_init(c, &opts);
+    }
+  
+  } else if (ev == MG_EV_HTTP_MSG) {
+
+    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
+
+    if (mg_match(hm->uri, mg_str("/api/healthz"), NULL)) {
+
+        handle_healtiness_probe(c, hm);
+
+    } 
+    
+    printf("WS UPGRADE!!!!!\n");
+
+    mg_ws_upgrade(c, hm, NULL);
+    
+    if(DEBUG_THIS == 1){
+
+        MG_DEBUG(("%lu %.*s %.*s -> %.*s", c->id, (int) hm->method.len,
+                hm->method.buf, (int) hm->uri.len, hm->uri.buf, (int) 3,
+                &c->send.buf[9]));
+
+    }
+
+  } else if (ev == MG_EV_WS_MSG) {
+
+    struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
+    
+    front_handler(c, wm);
+
+  }
+}
+
+
+
+void* front_listen_and_serve(void* varg){
+
+    mg_mgr_init(&mgr);
+
+    s_settings.device_name = strdup("rat-chat");
+
+    mg_http_listen(&mgr, HTTP_URL, route, NULL);
+
+
+    mg_timer_add(&mgr, 3600 * 1000, MG_TIMER_RUN_NOW | MG_TIMER_REPEAT,
+                timer_sntp_fn, &mgr);
+    
+    while (s_sig_num == 0) {
+        mg_mgr_poll(&mgr, 50);
+    }
+
+    mg_mgr_free(&mgr);
+
+}
+
+
+
+
+void front_handler(struct mg_connection *c, struct mg_ws_message *wm){
+
+    char ws_command[WS_MAX_COMMAND_LEN] = {0};
+
+    char ws_data[WS_MAX_COMMAND_DATA_LEN] = {0};
+
+    cJSON* response = cJSON_CreateObject();
+
+    pthread_mutex_lock(&G_MTX);
+
+    int datalen = 0;
+
+    int initial = 0;
+
+
+    int auth_chan_idx = front_authenticate(c, wm, &initial, ws_command, ws_data);
+
+    if (auth_chan_idx < 0){
+
+        pthread_mutex_unlock(&G_MTX);
+
+        return;
+
+    } 
+    
+    
+    if (initial == 1) {
+
+        fmt_logln(LOGFP, "connection authenticated");
+
+        pthread_mutex_unlock(&G_MTX);
+
+        return;
+
+    }
+
+    front_communicate(auth_chan_idx, ws_command, ws_data);
+
+    pthread_mutex_unlock(&G_MTX);
+    
+}
+
+
+
+int front_authenticate(struct mg_connection* c, struct mg_ws_message *wm, int* initial, char* command, char* data){
+
+
+    char ws_buff[MAX_WS_BUFF] = {0};
+
+    cJSON* response = cJSON_CreateObject();
+
+    int datalen = 0;
+
+    if(wm->data.len > MAX_WS_BUFF){
+
+        printf("failed handle ws: data too big\n");
+        cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail"));
+        cJSON_AddItemToObject(response, "data", cJSON_CreateString("null"));
+        
+        strcpy(ws_buff, cJSON_Print(response));
+
+        datalen = strlen(ws_buff);
+
+        mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT);
+        
+        return -1;
+    }
+
+
+    cJSON* req_obj = cJSON_Parse(wm->data.buf);
+
+    if(req_obj == NULL){
+
+        printf("failed handle ws: data invalid\n");
+
+
+        cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail"));
+        cJSON_AddItemToObject(response, "data", cJSON_CreateString("null"));
+        
+        strcpy(ws_buff, cJSON_Print(response));
+
+        datalen = strlen(ws_buff);
+
+        mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT);
+        
+        return -2;
+
+    }
+
+    cJSON* ws_command = cJSON_GetObjectItemCaseSensitive(req_obj, "command");
+
+    if(ws_command == NULL){
+
+        printf("failed handle ws: data invalid\n");
+
+        cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail"));
+        cJSON_AddItemToObject(response, "data", cJSON_CreateString("null"));
+        
+        strcpy(ws_buff, cJSON_Print(response));
+
+        datalen = strlen(ws_buff);
+
+        mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT);
+        
+        return -3;
+
+    }
+
+
+
+    printf("command: %s\n", ws_command->valuestring);
+
+    datalen = strlen(ws_command->valuestring);
+
+    if(datalen > WS_MAX_COMMAND_LEN){
+
+        printf("failed handle ws: command too long\n");
+
+        cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail"));
+        cJSON_AddItemToObject(response, "data", cJSON_CreateString("null"));
+        
+        strcpy(ws_buff, cJSON_Print(response));
+
+        datalen = strlen(ws_buff);
+
+        mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT);
+        
+        return -4;
+    }
+
+
+    cJSON* ws_data = cJSON_GetObjectItemCaseSensitive(req_obj, "data");
+
+    if(ws_data == NULL){
+
+        printf("failed handle ws: no data field\n");
+
+        cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail"));
+        cJSON_AddItemToObject(response, "data", cJSON_CreateString("null"));
+        
+        strcpy(ws_buff, cJSON_Print(response));
+
+        datalen = strlen(ws_buff);
+
+        mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT);
+        
+        return -5;
+
+    }
+
+    int ws_data_len = strlen(ws_data->valuestring);
+
+    if(ws_data_len > WS_MAX_COMMAND_DATA_LEN){
+
+        printf("failed handle ws: data len too long\n");
+
+        cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail"));
+        cJSON_AddItemToObject(response, "data", cJSON_CreateString("null"));
+        
+        strcpy(ws_buff, cJSON_Print(response));
+
+        datalen = strlen(ws_buff);
+
+        mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT);
+        
+        return -6;
+
+    }
+
+    int frontid = (int)c->id;
+
+    char user_id[MAX_ID_LEN] = {0};
+
+
+    // TODO:
+    //  simple check
+
+    int chan_idx = 0;
+
+    if (chan_idx < 0){
+
+        fmt_logln(LOGFP,"not registered to chan ctx, auth"); 
+
+        int v = idpw_verify(ws_data->valuestring);
+
+        if(v < 0){
+
+            fmt_logln(LOGFP,"invalid idpw"); 
+            printf("failed handle ws: invalid idpw\n");
+            cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail"));
+            cJSON_AddItemToObject(response, "data", cJSON_CreateString("invalid idpw"));
+            
+            strcpy(ws_buff, cJSON_Print(response));
+
+            datalen = strlen(ws_buff);
+
+            mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT);
+
+            return -10;
+
+        } else {
+
+            fmt_logln(LOGFP, "auth success");
+
+
+            fmt_logln(LOGFP, "initial auth success");
+
+            printf("handle ws: initial auth success\n");
+            cJSON_AddItemToObject(response, "status", cJSON_CreateString("success"));
+            cJSON_AddItemToObject(response, "data", cJSON_CreateString("accepted"));
+            
+            strcpy(ws_buff, cJSON_Print(response));
+
+            datalen = strlen(ws_buff);
+
+            mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT);
+
+            *initial = 1;
+
+        }
+
+    }
+
+    strcpy(command, ws_command->valuestring);
+
+    strcpy(data, ws_data->valuestring);
+
+    fmt_logln(LOGFP, "auth success");
+
+    return chan_idx;
+
+
+}
+
+
+void front_communicate(int chan_idx, char* command, char* data){
+
+    char ws_buff[MAX_WS_BUFF] = {0};
+
+    cJSON* response = cJSON_CreateObject();
+
+    int datalen = 0;
+
+    fmt_logln(LOGFP, "incoming front communication to sock");
+
+    int sockfd = CHAN_CTX[chan_idx].sockfd;
+
+    if(sockfd == 0){
+
+
+        fmt_logln(LOGFP, "no sock exists for communication");
+
+
+        return;
+
+    }
+
+
+    fmt_logln(LOGFP, "sock exists");
+
+    struct HUB_PACKET hp;
+
+    
+    if (strcmp(command, WS_COMMAND_ROUNDTRIP) == 0) {
+
+        fmt_logln(LOGFP, "roundtrip");
+
+
+        memset(hp.header, 0, HUB_HEADER_BYTELEN);
+
+        memset(hp.wbuff, 0, MAX_BUFF);
+
+        hp.ctx_type = CHAN_ISSOCK;
+
+        strcpy(hp.id, CHAN_CTX[chan_idx].id);
+
+        strcpy(hp.header, HUB_HEADER_SENDSOCK);
+
+        datalen = strlen(data);
+
+        hp.body_len = datalen;
+
+        strncpy(hp.wbuff, data, datalen);
+
+        hp.flag = 0;
+
+        ctx_write_packet(&hp);
+
+        if(hp.flag <= 0){
+
+            fmt_logln(LOGFP, "failed to send to sock");
+
+
+
+            return;
+        } 
+
+        fmt_logln(LOGFP, "send to sock");
+
+
+    } else {
+
+        printf("failed handle ws: no such command\n");
+
+        
+        return;
+
+    }
+
+    return;
+
+}
+
+
diff --git a/src/hubsock/core.c b/src/hubsock/core.c
new file mode 100644 (file)
index 0000000..58b1323
--- /dev/null
@@ -0,0 +1,513 @@
+#include   "rat-chat/sock/core.h"
+#include   "rat-chat/utils.h"
+
+int SOCK_FD;
+int SOCK_SERVLEN;
+int SOCK_EPLFD;
+struct epoll_event SOCK_EVENT;
+struct epoll_event *SOCK_EVENTARRAY;
+
+char CA_CERT[MAX_PW_LEN] = {0};
+
+void sock_listen_and_serve(void* varg){
+
+    int result = 0;
+
+    SSL_library_init();
+
+    result = read_file_to_buffer(CA_CERT, MAX_PW_LEN, HUB_CA_CERT);
+
+    if(result < 0){
+
+        fmt_logln(LOGFP, "failed to read ca cert");
+
+        return;
+
+    }
+
+
+
+    struct sockaddr_in SERVADDR;
+
+    for(int i = 0 ; i < MAX_CONN;i ++){
+
+        CHAN_CTX[i].ssl = NULL;
+        CHAN_CTX[i].ctx = NULL;
+
+
+    }
+
+
+    //signal(SIGPIPE, SIG_IGN);
+
+    SOCK_FD = socket(AF_INET, SOCK_STREAM, 0); 
+
+    if (SOCK_FD == -1) { 
+
+        fmt_logln(LOGFP, "socket creation failed");
+
+        exit(EXIT_FAILURE); 
+    } 
+    else {
+
+        fmt_logln(LOGFP, "socket successfully created");
+    }
+    /*
+    if( setsockopt(SOCKFD, SOL_SOCKET, SO_REUSEADDR, (char *)&OPT,  
+          sizeof(OPT)) < 0 )   
+    {   
+        perror("setsockopt");   
+        exit(EXIT_FAILURE);   
+    } 
+
+    */  
+     
+
+    bzero(&SERVADDR, sizeof(SERVADDR)); 
+   
+    SERVADDR.sin_family = AF_INET; 
+    SERVADDR.sin_addr.s_addr = htonl(INADDR_ANY); 
+    SERVADDR.sin_port = htons(PORT_SOCK); 
+   
+    if ((bind(SOCK_FD, (struct sockaddr*)&SERVADDR, sizeof(SERVADDR))) != 0) { 
+        
+
+        fmt_logln(LOGFP, "socket bind failed");
+
+        exit(EXIT_FAILURE); 
+    } 
+    
+    if(make_socket_non_blocking(SOCK_FD) < 0){
+
+        fmt_logln(LOGFP, "non-blocking failed");
+
+        exit(EXIT_FAILURE);
+    }
+    
+
+    if ((listen(SOCK_FD, MAX_CONN)) != 0) { 
+
+        fmt_logln(LOGFP, "listen failed");
+
+        exit(EXIT_FAILURE); 
+    } 
+    else{
+        SOCK_SERVLEN = sizeof(SERVADDR); 
+    }
+
+
+    SOCK_EPLFD = epoll_create1(0);
+
+    if(SOCK_EPLFD == -1){
+
+        fmt_logln(LOGFP, "epoll creation failed");
+
+        exit(EXIT_FAILURE);
+    }
+
+    SOCK_EVENT.data.fd = SOCK_FD;
+    SOCK_EVENT.events = EPOLLIN | EPOLLET;
+    
+    if (epoll_ctl(SOCK_EPLFD, EPOLL_CTL_ADD, SOCK_FD, &SOCK_EVENT) < 0){
+
+        fmt_logln(LOGFP,"epoll add failed");
+
+        exit(EXIT_FAILURE);
+    }    
+
+    SOCK_EVENTARRAY = calloc(MAX_CONN, sizeof(SOCK_EVENT));
+
+
+    while(TRUE){
+
+        int n, i ;
+
+        n = epoll_wait(SOCK_EPLFD, SOCK_EVENTARRAY, MAX_CONN, -1);
+
+        for (i = 0 ; i < n; i ++){
+
+            if (
+                (SOCK_EVENTARRAY[i].events & EPOLLERR) ||
+                (SOCK_EVENTARRAY[i].events & EPOLLHUP) ||
+                (!(SOCK_EVENTARRAY[i].events & EPOLLIN))
+            ){
+
+                fmt_logln(LOGFP, "epoll wait error");
+
+                close(SOCK_EVENTARRAY[i].data.fd);
+                
+                continue;
+
+            } else if (SOCK_FD == SOCK_EVENTARRAY[i].data.fd){
+
+                sock_handle_conn();
+
+                fmt_logln(LOGFP, "new sock conn successfully handled");
+
+            } else{
+
+                sock_handle_client(SOCK_EVENTARRAY[i].data.fd);
+
+                fmt_logln(LOGFP, "socket data successfully handled");
+
+
+            }
+
+        }
+
+
+    }
+
+
+    free(SOCK_EVENTARRAY);
+
+    close(SOCK_FD);
+
+    close(SOCK_EPLFD);
+
+
+}
+
+
+
+
+
+void sock_handle_conn(){
+
+
+    while(TRUE){
+
+        struct sockaddr in_addr;
+        socklen_t in_len;
+        int infd;
+        SSL *ssl;
+        SSL_CTX *ctx;
+
+        int ssl_accept_ret;
+
+        in_len = sizeof(in_addr);
+   
+        infd = accept(SOCK_FD, &in_addr, &in_len);
+
+        if(infd == -1){
+
+            if(
+                (errno == EAGAIN) ||
+                (errno == EWOULDBLOCK)
+            ){
+
+                fmt_logln(LOGFP, "all incoming sock connections handled");
+
+                break;
+
+            } else{
+                fmt_logln(LOGFP, "error handling incoming sock connection");
+
+                break;
+            }
+        }
+
+        ctx = create_context();
+
+        configure_context(ctx);
+
+        ssl = SSL_new(ctx);
+
+        SSL_set_fd(ssl, infd);
+    
+        if((ssl_accept_ret = SSL_accept(ssl)) < 1){
+
+            int sslerr =  SSL_get_error(ssl, 0);
+
+            fmt_logln(LOGFP, "error handling tls handshake");
+
+            if (ssl_accept_ret <=0 && (sslerr == SSL_ERROR_WANT_READ)) {
+
+                perror ("Need to wait until socket is readable.");
+
+                fmt_logln(LOGFP, "ssl: %s", "Need to wait until socket is readable");
+
+            } else if (ssl_accept_ret <=0 && (sslerr == SSL_ERROR_WANT_WRITE)) {
+
+                perror ("Need to wait until socket is writable.");
+
+                fmt_logln(LOGFP, "ssl: %s", "Need to wait until socket is writable");
+
+
+            } else {
+                perror ("Need to wait until socket is ready.");
+
+                fmt_logln(LOGFP, "ssl: %s", "Need to wait until socket is ready");
+
+            }
+
+            shutdown (infd, 2);
+            SSL_free (ssl);
+            SSL_CTX_free(ctx);
+
+            continue;
+
+        } 
+
+
+        if(make_socket_non_blocking(infd) < 0){
+
+            fmt_logln(LOGFP, "failed new conn non block");
+
+            exit(EXIT_FAILURE);
+        }
+
+        int sock_idx = set_sockctx_by_fd(infd);
+
+
+
+        if(sock_idx < 0){
+
+            fmt_logln(LOGFP, "failed new conn sockctx");
+
+            exit(EXIT_FAILURE);
+
+        }
+
+        SOCK_CTX[sock_idx].ctx = ctx;
+        SOCK_CTX[sock_idx].ssl = ssl;
+
+
+        SOCK_EVENT.data.fd = infd;
+        SOCK_EVENT.events = EPOLLIN | EPOLLET;
+
+        if (epoll_ctl(SOCK_EPLFD, EPOLL_CTL_ADD, infd, &SOCK_EVENT) < 0){
+
+            fmt_logln(LOGFP,"handle epoll add failed");  
+
+
+            exit(EXIT_FAILURE);
+
+        }  else {
+
+            fmt_logln(LOGFP,"handle epoll add success"); 
+
+        }
+
+
+
+    }
+
+
+
+}
+
+
+
+void sock_handle_client(int cfd){
+
+
+    pthread_mutex_lock(&G_MTX);
+
+    int chan_idx = get_chanctx_by_fd(cfd, ISSOCK);
+
+
+    if(chan_idx < 0){
+        
+        sock_authenticate(cfd);
+
+        pthread_mutex_unlock(&G_MTX);
+
+        return;
+    }
+
+    sock_communicate(chan_idx);
+
+    pthread_mutex_unlock(&G_MTX);
+
+    return;
+
+}
+
+
+
+void sock_authenticate(int cfd){
+
+    int valread;
+    int valwrite;
+
+    struct HUB_PACKET hp;
+
+
+    uint8_t id[MAX_ID_LEN] = {0};
+
+    int sock_idx = get_sockctx_by_fd(cfd);
+
+    fmt_logln(LOGFP,"not registered to chan ctx, auth"); 
+
+    if(sock_idx < 0){
+
+        fmt_logln(LOGFP,"failed to get sock idx"); 
+
+        return;
+    }
+
+
+    hp.ctx_type = ISSOCK;
+    hp.fd = SOCK_CTX[sock_idx].sockfd;
+    
+    ctx_read_packet(&hp);
+
+    if(hp.flag <= 0){
+
+
+        fmt_logln(LOGFP,"failed to read sock"); 
+
+        free_sockctx(sock_idx, 1);
+
+        return;
+
+    }
+    
+
+
+    int verified = sig_verify(hp.rbuff, CA_CERT);
+
+    if(verified < 1){
+
+        fmt_logln(LOGFP,"invalid signature"); 
+
+        free_sockctx(sock_idx, 1);
+
+        free(hp.rbuff);
+
+        return;
+
+    }
+
+    
+
+    int ret_cn = extract_common_name(id, hp.rbuff);
+
+    if(ret_cn != 1){
+
+        fmt_logln(LOGFP,"invalid id"); 
+
+        free_sockctx(sock_idx, 1);
+
+        free(hp.rbuff);
+
+        return;
+
+
+    }
+
+    fmt_logln(LOGFP, "id: %s", id);
+
+    free(hp.rbuff);
+
+    int chan_idx = update_chanctx_from_sockctx(cfd, id);
+
+    if (chan_idx < 0){
+
+        fmt_logln(LOGFP, "failed to update chanctx");
+
+        free_sockctx(sock_idx, 1);
+
+        return;
+
+    }
+
+
+    uint64_t body_len = strlen("SUCCESS") + 1;
+
+    memset(hp.header, 0, HUB_HEADER_BYTELEN);
+
+    memset(hp.wbuff, 0, MAX_BUFF);
+
+    hp.ctx_type = CHAN_ISSOCK;
+
+    strcpy(hp.header, HUB_HEADER_AUTHSOCK);
+
+    hp.body_len = body_len;
+
+    strcat(hp.wbuff,"SUCCESS");
+
+    strcpy(hp.id, id);
+
+    fmt_logln(LOGFP, "writing auth result..");
+    
+    ctx_write_packet(&hp);
+
+    if(hp.flag <= 0){
+
+        fmt_logln(LOGFP, "failed to send");
+
+        return;
+
+    }
+
+    fmt_logln(LOGFP, "sent");
+
+    return;
+
+
+}
+
+
+
+void sock_communicate(int chan_idx){
+
+    fmt_logln(LOGFP, "incoming sock communication to front");
+
+    int frontfd = CHAN_CTX[chan_idx].frontfd;
+
+    if(frontfd == 0){
+
+        fmt_logln(LOGFP, "no front exists for communication");
+
+        return;
+
+    }
+    
+    fmt_logln(LOGFP, "front exists");
+
+    struct HUB_PACKET hp;
+
+    hp.ctx_type = CHAN_ISSOCK;
+
+    strcpy(hp.id, CHAN_CTX[chan_idx].id);
+
+    ctx_read_packet(&hp);
+
+    if(hp.flag <= 0){
+
+        fmt_logln(LOGFP, "failed to communicate sock read");
+
+        return;
+
+    }
+
+    memset(hp.header, 0, HUB_HEADER_BYTELEN);
+
+    memset(hp.wbuff, 0, MAX_BUFF);
+
+    hp.ctx_type = CHAN_ISFRONT;
+
+    strcpy(hp.header, HUB_HEADER_RECVFRONT);
+
+    strncpy(hp.wbuff, hp.rbuff, hp.body_len);
+
+    hp.flag = 0;
+
+    free(hp.rbuff);
+
+    ctx_write_packet(&hp);
+
+    if(hp.flag <= 0){
+
+        fmt_logln(LOGFP, "failed to send to front");
+
+        return;
+    } 
+
+    fmt_logln(LOGFP, "send to front");
+
+    return;
+}
\ No newline at end of file
diff --git a/src/utils.c b/src/utils.c
new file mode 100644 (file)
index 0000000..7670b5e
--- /dev/null
@@ -0,0 +1,250 @@
+#include "rat-chat/utils.h"
+
+
+int read_file_to_buffer(uint8_t* buff, int max_buff_len, char* file_path){
+
+
+    int valread = 0 ;
+
+    int c;
+
+    FILE* fp;
+
+    fp = fopen(file_path, "r");
+
+    while(1) {
+
+        c = fgetc(fp);
+        if( feof(fp) ) {
+            break;
+        }
+
+
+        buff[valread] = c;
+
+        valread += 1;
+
+        if(valread > max_buff_len){
+
+            return -10;
+        }
+    
+   }
+
+    return valread;
+}
+
+int gen_random_bytestream(uint8_t* bytes, size_t num_bytes){
+  
+
+    if(num_bytes > MAX_PW_LEN){
+
+    return -1;
+
+    }
+
+
+    size_t i;
+
+    for (i = 0; i < num_bytes; i++){
+
+    bytes[i] = rand();
+
+    }
+
+    return 0;
+
+}
+
+int bin2hex(uint8_t* hexarray, int arrlen, uint8_t* bytearray){
+
+    int hexlen = 2;
+
+    int outstrlen = hexlen * arrlen + 1;
+
+    if (outstrlen > MAX_PW_LEN){
+
+        return -1;
+    }
+
+    memset(hexarray, 0, outstrlen * sizeof(char));
+
+    unsigned char* ptr = hexarray;
+
+    for(int i = 0 ; i < arrlen; i++){
+
+        sprintf(ptr + 2 * i, "%02X", bytearray[i]);
+    }
+
+    return 0;
+    
+}
+
+
+
+void get_current_time_string(char* tstr){
+
+
+    struct tm *info;
+    
+    int millisec;
+    char msec_str[5] = {0};
+
+    struct timeval tv;
+
+
+    gettimeofday(&tv, NULL);
+
+
+    millisec = tv.tv_usec / 1000;
+
+    if (millisec >= 1000){
+
+        millisec -= 1000;
+        tv.tv_sec += 1;
+
+    }
+
+
+
+
+    info = localtime(&tv.tv_sec);
+
+    strftime(tstr, MAX_TIMESTR_LEN, "%Y-%m-%d %H:%M:%S", info);
+
+    sprintf(msec_str, ".%03d", millisec);
+
+    strcat(tstr, msec_str);
+
+
+}
+
+void sleepms(long ms){
+
+
+    struct timespec ts;
+    int res;
+
+    ts.tv_sec = ms / 1000;
+    ts.tv_nsec = (ms % 1000) * 1000000;
+
+    nanosleep(&ts, &ts);
+
+
+
+}
+
+void fmt_logln(FILE *fp, char* fmt_out, ...){
+
+    va_list valist;
+
+    char log_str[MAX_LOG_TXT_LEN] = {0};
+
+    char log_fmt_str[MAX_LOG_TXT_LEN] = {0};
+
+    char fmt_arg[MAX_FMT_ARG_LEN] = {0};
+
+    char time_str[MAX_TIMESTR_LEN] = {0};
+
+
+
+    int arg_len = 0;
+
+    int str_len = strlen(fmt_out);
+
+    if(str_len < 1){
+        return;
+    }
+
+    for(int i = 0; i < str_len; i++){
+
+        if(fmt_out[i] == '%' && i != 0 && fmt_out[i - 1] != '\\'){
+
+            arg_len += 1;
+
+        }
+
+    }
+
+    get_current_time_string(time_str);
+
+    if(arg_len == 0){
+
+        sprintf(log_str, "[ %s ] %s\n", time_str, fmt_out);
+
+    } else {
+
+        char fmt_flag[3] = {0};
+
+        va_start(valist, arg_len);
+
+        int i = 0;
+
+        int fmt_i = 0;
+
+        for(;;){
+            
+            if(fmt_out[i] == '%' && i != 0 && i != (str_len - 1) && fmt_out[i - 1] != '\\'){
+
+                fmt_flag[0] = fmt_out[i];
+
+                i += 1;
+
+                fmt_flag[1] = fmt_out[i];
+
+                fmt_flag[2] = 0;
+
+                memset(fmt_arg, 0, MAX_FMT_ARG_LEN);
+
+                if(fmt_flag[1] == 'd'){
+
+                    int a = va_arg(valist, int);
+
+                    sprintf(fmt_arg, fmt_flag, a);
+
+
+                } else if (fmt_flag[1] == 's') {
+
+                    char* a = va_arg(valist, char*);
+
+                    sprintf(fmt_arg, fmt_flag, a);                    
+
+                }
+
+                strcat(log_fmt_str, fmt_arg);
+                
+                int added = strlen(fmt_arg);
+
+                i += 1;
+                fmt_i += added;
+
+
+            } else {
+
+                log_fmt_str[fmt_i] = fmt_out[i];
+
+                i += 1;
+                fmt_i += 1;
+
+            }
+
+
+            if(i >= str_len){
+                break;
+            }
+
+        }
+
+        va_end(valist);
+
+        sprintf(log_str, "[ %s ] %s\n", time_str, log_fmt_str);
+    }
+
+
+    fputs(log_str, fp);
+
+    fflush(fp);
+
+
+
+}
\ No newline at end of file
diff --git a/tls/ca.crt b/tls/ca.crt
new file mode 100644 (file)
index 0000000..f22de82
--- /dev/null
@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE-----
+MIIFFTCCAv2gAwIBAgIUKEjIY8AOTELEiqp/Rx/zYdclnVcwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPY2FAZmVlYmRhZWQueHl6MB4XDTI0MDUwNDAyMDUxOVoX
+DTM0MDUwMjAyMDUxOVowGjEYMBYGA1UEAwwPY2FAZmVlYmRhZWQueHl6MIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuiTwW9Fkha7BNq/tF+ZRePIvlDBw
+h/div9RmCbneMdd1qot5iuS2BXpuzVLlSwKEKoUntRSfIjRj2Q3NDJ95XGocsCuT
+Prj8Bt1t+Kwr5NwyOn1ea6mXMJnMqRlnQznDDWVj+/mVXdJzBc175viToCWk8F/b
+RyJhYQVUL8xXu+CiNQCkRuzdo6UBfTQBlpdoN0x44w5Td083En548qn4jAOhO+mw
+mrO8+WsAyMPNFBLNEXBKF1PN3nC7ryySRLlE/rxnDGxSShjDI0ItgNTFr6rhUenK
+d6n/czM72WdUkHPLPIEO6DN+EDfCPMl9gz/gy3Zrfxg/nuEwrV7GtT69+5diesSt
+AJ2BRUScF1RKVevuzOGB3w2SSiZO4CbxYvvwYQA0MLE9Uhvexkq1xGkkgEqOaFHd
+w3EoTT+Q7JXgA70vGXhp0tOMtkYSGN84gBvXZbB9g7gpZbaZe7L0Mn3tBqqWjEcF
+OdrquXyfP2/9dbCAnL6AVitGZ74UKbV4U1TxW//+ysDt6h3ns3M+y5krFdVe/FkY
+XIyzTJyyqZqtrqX8xG2F72KFCQ0lBTtQm664rufa7UoVE32Lt6b2GasHn8dJVDbj
+i06p07BHkiLNf3YbGPSebh3Sm258LaY+eTK/R/y/hRjxyDAka9ng8eps1m3vdewd
+4SCmLD1ou3b6rxsCAwEAAaNTMFEwHQYDVR0OBBYEFBgBUQHuYfawyeL0Z7ymU4QE
+jcylMB8GA1UdIwQYMBaAFBgBUQHuYfawyeL0Z7ymU4QEjcylMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggIBACf3RPLAjt+DAijU5YG41E0KZ5lQj3PT
+wla+5PB/8avVjgKvP1mkcGhYEq75DRT1T9MdnPRKUCqZCcRUb2nPQCaq/jNSOdbs
+OnlM9qJTZJezwOthUMCNwBMLJJbvTBBrLyaRXaCHN1wcfavIyGMCrqVKW0FfwhaF
+UgwAhG4maTw283lq+/j/9xoPuP7XHkbkRDW3TINS0dEQM1RNNKPVdyMOErKLNBaT
+9DRFWKjRXk2ZtBJ1XxAyT9LipfUVYgjETX/iVV3kknsngM2rtMpjb6W+9f7pfOuh
+gUacxpLflBVkzXYFgsLm6p+wg0l9V3zuaEZELIo2KgcT1jwpBgXvjtye5urKElkh
+JHr07raS8JFrF+L8lcjaXhb28lLDp4fRT8GHEl1/naASVvtZxlEEXnnrkJ6A0jD0
+Vt8balZMYZDoq+A4iYPk6LlHgsYOOnH87L7dhqED+xAZm6fzDZyilUioTVtmIOsC
+5/ybtUdYrK1n9PqfhA/awYYW2vY7M3HFkEjy+gf3VOcdFzpssSUJmyt359B/VRDR
+V5ISq4JA5CyoO/2yKbLEiKW7kY8DiiQjKQ+27zB+KUB0yVSO+xb1dm93zOE29yql
+3cQgBN2CW13Xe/rMNdu53ToE0FIwheRBXtiPsh+bw7MDUStbgIOz/mAszWcbLcai
+ZVo3eVTwCWoN
+-----END CERTIFICATE-----
diff --git a/tls/list.txt b/tls/list.txt
new file mode 100644 (file)
index 0000000..a2910b9
--- /dev/null
@@ -0,0 +1,4 @@
+sub_priv.pem
+sub_pub.pem
+sub.csr
+sub.crt
\ No newline at end of file
diff --git a/tls/sub.crt b/tls/sub.crt
new file mode 100644 (file)
index 0000000..79d54a5
--- /dev/null
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIEwzCCAqsCFGJACNTxHt8lNKG5UoBZHFyKF+frMA0GCSqGSIb3DQEBCwUAMBox
+GDAWBgNVBAMMD2NhQGZlZWJkYWVkLnh5ejAeFw0yNDA1MDQwMjA1MjFaFw0yNTA1
+MDQwMjA1MjFaMCIxIDAeBgNVBAMMF3NlYW50eXdvcmtAZmVlYmRhZWQueHl6MIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxP8l01USO8HYM9S/5q/9GnJu
+Xdx5dTOG4YpFaQdQ+hUfGaBc76D/FnRQE2XgL6r1DZ4tEwy3BZ1UXr3AiOzKQzse
+l8/E1ChgsF8RPXNNIFjkR9EHSMBjC5Wq6T0ATWG8CR/0I4VD7S3Tdd9caT41RbbJ
+WE3lY9S92hn47X+b6ae48UdMn+d2ZNpCQ22nk7chee/UJhQLTQv69IkvonYPJPP8
+PStkzq72xV8Mj28zU0D+Eua2BvDpA76DO08xPB9BprGgF2aqZ3yI63tFWy+kgEXF
+LPLsU6T+wA05dztewBuCQCdfs1NJWwF3JI2HUfDhRc05IO1aV1I6Dq1W9ZH5EyBz
+tGXOD/+ec46AR8h1gpEgir894MdxdP562y1zShRs8nm0DKjkeewgYQ6+2AaTq+jC
+H020y9nRFNIO4sXntl4xYsRVR9G90PosVbOv95NkgWpGWTW/6BtxjVQ/5iI1w9ae
+DmPD7NqD6cIC53TEPllWr1rv1xwO91ZIzoM/5PgLGBIhwWWXK6BDwVU4YOled0Yd
+jr6me7+95+QrEFK7M+Ar4sBnxSBn2BEc6rGOaeG8TbKBMkt4JQJuwbsIQcAWfQmD
+AGDoCzxT4+Y53Z+Rlc4SUurbPeoFE+1PsmnVyHQSyes29DzPQKUSUO67I36YP7fO
+AWNv/NQew7UzDFJV8kMCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAThTtYGycDU8a
+y50NIuz1laYfHLVRT95LSkzq3qZLiQk4ZEP0nVEEWMueY17ObaQ6WC9EY9r+JqAG
+Ng0eUcchVtQoCveeUjKXVQZNTc1pgW5UVHlfzbxgSlDGWB3wwssywMDeubnToalz
+1ksnBPLX7KWnmZWFCjU7jIBUdy0qYdVRH6IaWuAQZJ41FfszWfRnFAuaQFxnZtkt
+fjanuGYKQophT3tu8yCYFr6YqT44FrQ0DIJHRs5F9jUsg7aQTnWlmhmmDMxoPr0T
+ycObH4ZwHbexqzwJGH/ZoX0Sf/bFmFtf/K3xytt921cxMjF8MpjVIx6NrgSy8Ngr
+gRW+XiNW0aRlimYKu0ES9dhKRywXHH7R22sivRWdDWv1t1lo+Lr5EMTM68sO09+s
+KO6z0OKgyfBT7VHzPAsCo2tPFORBlEkh/siKEWyiMgWYN/3KIQT1HDjObmOyCuxE
+Yz7QuRKrHbkQPKu9zTVa6/stX8X82nSet5JPF/LIO5h+R971gkxIjpKHlBWJlvqw
+22UIkJ1s/05G1YqfRef6ADTWEN8xBWyiIhuIYcly/HI5DjMZ/J3VzSbk/JajSGIc
+lRqrn/I0Lfefb1gKZ9DNydzSIBwtv4jikYaLhov0jugSze8bSKf+ktR30JCXXtv2
+IPXwvSGLSRtzfqlRRu9Lx4RMvzSNY7I=
+-----END CERTIFICATE-----
diff --git a/tls/sub.csr b/tls/sub.csr
new file mode 100644 (file)
index 0000000..1cf4784
--- /dev/null
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIEZzCCAk8CAQAwIjEgMB4GA1UEAwwXc2VhbnR5d29ya0BmZWViZGFlZC54eXow
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDE/yXTVRI7wdgz1L/mr/0a
+cm5d3Hl1M4bhikVpB1D6FR8ZoFzvoP8WdFATZeAvqvUNni0TDLcFnVRevcCI7MpD
+Ox6Xz8TUKGCwXxE9c00gWORH0QdIwGMLlarpPQBNYbwJH/QjhUPtLdN131xpPjVF
+tslYTeVj1L3aGfjtf5vpp7jxR0yf53Zk2kJDbaeTtyF579QmFAtNC/r0iS+idg8k
+8/w9K2TOrvbFXwyPbzNTQP4S5rYG8OkDvoM7TzE8H0GmsaAXZqpnfIjre0VbL6SA
+RcUs8uxTpP7ADTl3O17AG4JAJ1+zU0lbAXckjYdR8OFFzTkg7VpXUjoOrVb1kfkT
+IHO0Zc4P/55zjoBHyHWCkSCKvz3gx3F0/nrbLXNKFGzyebQMqOR57CBhDr7YBpOr
+6MIfTbTL2dEU0g7ixee2XjFixFVH0b3Q+ixVs6/3k2SBakZZNb/oG3GNVD/mIjXD
+1p4OY8Ps2oPpwgLndMQ+WVavWu/XHA73VkjOgz/k+AsYEiHBZZcroEPBVThg6V53
+Rh2OvqZ7v73n5CsQUrsz4CviwGfFIGfYERzqsY5p4bxNsoEyS3glAm7BuwhBwBZ9
+CYMAYOgLPFPj5jndn5GVzhJS6ts96gUT7U+yadXIdBLJ6zb0PM9ApRJQ7rsjfpg/
+t84BY2/81B7DtTMMUlXyQwIDAQABoAAwDQYJKoZIhvcNAQELBQADggIBAJftxdPt
+5rCVHS3SWg7YzlQeHL1pIUtEM+YmK/BMr/3SI3l54CvrVl4yquADa3FUxhwEE9jq
+CguHqj0FxpPX9vyN9YfSUmWbn5zzYyifgkf4VVepDOvUhwl5NmP2HwpjgsV8dIaH
+e84a/V7AWdn3OE6+fZOhDtCeP0sJKQ8NyGGvs/UsAvRE8+JPXnf06P7/aGK5L4Cj
+wZoK6RyaoP0dR1rMZDWKQzd2ObhvffzfSEGdnZUNNSsIiTDktvZx46Yf9ZOxj+UB
+KKbajqB2VvOn10egBQ/VrJ2BimCp4GcPVICaMR65QDVcRPL7xErXMRQ2vWCb8Qep
+SB1Hj8Jji/OcDJO14goMuomnkawpHLiErtlekuKMBD3ILtjbfF73I8YaagmA0IGq
+81gk7W0JG/3VhchHhy3gRVxN3WgEnFFN8pCD5SOr0/diGmpCYoiUzfoC79bH0bIP
+CK2E0af4N4LZ+EXTKyGvCIwjNcMM7wiaJxOtwD5+83KHtkP4kfHklW4AFF9YcCDJ
+oG5V2SG+V7rtERnkTcCbm1NYh6oyB9VGa5bu9ln7MBxmkNjdECr4mklM3tBamvXw
+HZyYGkWzpSo+bA5CbxtEdga9pn4zt/R3sUf04JYIjYEF+XP0mAI4Q6kAHCS/T/hJ
+01UfO+W/ws6BnT1MVBiiglzpkN4S3Dn4jC9Z
+-----END CERTIFICATE REQUEST-----
diff --git a/vendor/.gitignore b/vendor/.gitignore
new file mode 100644 (file)
index 0000000..9b4f2c1
--- /dev/null
@@ -0,0 +1,2 @@
+mongoose
+cJSON
\ No newline at end of file
diff --git a/vendor/README.md b/vendor/README.md
new file mode 100644 (file)
index 0000000..e69de29