--- /dev/null
+*.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
--- /dev/null
+*.o
+*.out
+*.so
+*.a
+*.run
+*.cmd
+*.ko
+*.mod
+*.symvers
+*.order
+*.mod.c
+.vscode
+*.pem
--- /dev/null
+
+
+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
+
-# frankc
+# rat-chat
+
+a dumb way to share linux system info, excute commands, and ... also chat
\ No newline at end of file
--- /dev/null
+
+#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
--- /dev/null
+{
+ "users":[
+ {
+ "id": "seantywork@gmail.com",
+ "pw": "hackme"
+ }
+ ]
+
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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;
+}
+
+
+
+
+
--- /dev/null
+#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;
+
+}
+
+
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+-----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-----
--- /dev/null
+sub_priv.pem
+sub_pub.pem
+sub.csr
+sub.crt
\ No newline at end of file
--- /dev/null
+-----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-----
--- /dev/null
+-----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-----
--- /dev/null
+mongoose
+cJSON
\ No newline at end of file