Created
August 18, 2020 08:49
-
-
Save databoose/9ece0fc041a368e2b30c61c8e5f05b9c to your computer and use it in GitHub Desktop.
server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <arpa/inet.h> | |
#include <netinet/in.h> | |
#include <pthread.h> | |
#include <stdbool.h> | |
#include <dirent.h> | |
#define SA struct sockaddr // cast shortener | |
#define SERVER_TICKRATE 300 // every 300ms is a tick | |
#define SERVER_BACKLOG 50 // max 50 clients in queue | |
#define TIMEOUT_IN 13 | |
#define TIMEOUT_OUT 13 | |
#include "include/logger.h" | |
#include "include/main.h" | |
void showhelp() | |
{ | |
printf("\n"); | |
printf("clearscr : clears screen\n"); | |
printf("showthreads : shows current amount of running threads\n"); | |
printf("ban <ip address> : prevents \n"); | |
printf("help/cmds : shows help/cmds\n"); | |
printf("\n"); | |
} | |
void thread_store(enum THREAD_STORE_OPTION opt) { | |
FILE *fptr; | |
thread_logger *thl_threadstore = new_thread_logger(debug_mode); | |
if (opt == create) { | |
LOGF_DEBUG(thl_threadstore, 0, "Creating directory for shared memory storage", "printf"); | |
if (system("mkdir /dev/shm/linkup-varstore") <= -1) { | |
printf("possible system() error : %s (Error code %d)\n", strerror(errno), errno); | |
errno = 0; // keeping errno fresh incase current function didn't call it | |
} | |
} | |
if (opt == update) { | |
remove("/dev/shm/linkup-varstore/thread_count"); | |
if (system(appendcmd) <= -1) { //update file with new value | |
printf("possible system() error : %s (Error code %d)\n", strerror(errno), errno); | |
errno = 0; // keeping errno fresh incase current function didn't call it | |
} | |
fptr = fopen("/dev/shm/linkup-varstore/thread_count", "r"); | |
while (!feof(fptr)) | |
{ | |
if (fscanf(fptr, "%d", &thread_count) == 0) { | |
printf("possible fscaf error : %s (Error code %d)\n", strerror(errno), errno); | |
errno = 0; | |
} | |
} | |
fclose(fptr); | |
} | |
clear_thread_logger(thl_threadstore); | |
} | |
int lengthofchar(char* tempstring) | |
{ | |
int cnt; | |
int charcount; | |
charcount = 0; | |
for (cnt=0; tempstring[cnt]; cnt++) { | |
if (tempstring[cnt] != ' ') { | |
charcount++; | |
} | |
} | |
return charcount; | |
} | |
void cmd_input() { | |
thread_logger *thl_cmdinput = new_thread_logger(debug_mode); | |
LOGF_DEBUG(thl_cmdinput, 0 , "cmd input thread started", "printf"); | |
for (;;) | |
{ | |
// LOGF_DEBUG(thl_cmdinput, 0 , "for ;; ran", "printf"); | |
usleep(600); | |
char input_cmd[35]; | |
memset(&input_cmd[0], '\0', sizeof(input_cmd)); | |
int scanfret = scanf("%s", input_cmd); | |
if (scanfret > 1) { LOGF_DEBUG(thl_cmdinput, 0, "Potential error, scanf ret %d", scanfret); } | |
// printf("input_cmd : %s\n", input_cmd); | |
if (strstr(input_cmd, "clearscr") != NULL) { | |
printf("\e[1;1H\e[2J"); // POSIX clearscreen | |
printf("\n"); | |
} | |
else if (strstr(input_cmd, "showthreads") != NULL) { | |
thread_store(update); | |
printf("Connection threads : %d\n",thread_count - 2); // minus two because we're not including this cmd_input() thread and main thread | |
printf("\n"); | |
} | |
else if ((strcmp(input_cmd, "ban") == 0) || (banning == true)) { | |
if (banning == true) { | |
strcpy(ipaddr, input_cmd); | |
LOGF_INFO(thl_cmdinput, 0, "%s banned from opening connection threads", ipaddr, "printf"); | |
banning = false; // we aint banning anymore | |
} | |
if (strcmp(input_cmd, "ban") == 0) { banning = true; } | |
} | |
else if (strcmp(input_cmd, "help") == 0 || strcmp(input_cmd, "cmds") == 0) { showhelp(); } | |
else { printf("Command not recognized\n"); } | |
} | |
clear_thread_logger(thl_cmdinput); | |
pthread_exit(0); | |
} | |
void set_timeout(int servsockfd, int timeout_input_seconds, int timeout_output_seconds) | |
{ | |
/* | |
Setting options : | |
- SO_RCVTIMO, to set timeout for input operations | |
- SO_SNDTIMEO, to set timeout for output operations | |
*/ | |
struct timeval timeout; | |
timeout.tv_usec = 0; | |
timeout.tv_sec = 0; | |
timeout.tv_sec = timeout_input_seconds; | |
if (setsockopt(servsockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { | |
printf("setsockopt so_rcvtimeo unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
errno = 0; | |
} | |
else | |
{ | |
timeout.tv_sec = timeout_output_seconds; | |
if (setsockopt(servsockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { | |
printf("setsockopt so_sndtimo unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
errno = 0; | |
} | |
} | |
//printf("Timeout set\n"); | |
} | |
void handle_connection(void* p_clisock) // thread functions need to be a void pointer, and they need to accept any arg variable as a void pointer as well | |
{ | |
thread_logger *thl = new_thread_logger(debug_mode); | |
LOGF_DEBUG(thl, 0, "TID : %ld", (pthread_self() / 100000), NULL); | |
set_timeout(servsockfd, TIMEOUT_IN, TIMEOUT_OUT); | |
int clisock = *((int*)p_clisock); | |
free(p_clisock); // we don't need the pointer anymore. | |
// at this point, do whatever you want to here, the code below is specific to this application | |
char *verif_recv_str = "Ar4#8Pzw<&M00Nk"; | |
char verif_send_str[110] = "4Ex{Y**y8wOh!T00"; | |
char recv_buf[110]; | |
int recv_status; | |
recv_status = recv(clisock, (void *)recv_buf, (size_t)sizeof(recv_buf), 0); | |
if (recv_status == -1) { | |
LOGF_ERROR(thl, 0, "Error reading from socket : (TID : %ld)\n", (pthread_self() / 100000)); | |
LOGF_ERROR(thl, 0, "%s (%d) \n", strerror(errno), errno); | |
errno = 0; | |
close(clisock); | |
pthread_exit(0); | |
} | |
LOGF_DEBUG(thl, 0, "Waiting for verification string from client ... ", "printf"); | |
if (strcmp(verif_recv_str, recv_buf) == 0) | |
{ | |
LOGF_DEBUG(thl, 0, "Verified", "printf"); | |
memset(&recv_buf[0], '\0', sizeof(recv_buf)); | |
int send_status; | |
send_status = send(clisock, (void *)verif_send_str, (size_t)lengthofchar(verif_send_str), 0); | |
if (send_status == -1) { | |
printf("Error writing to socket : "); | |
printf("%s (Error code %d) \n", strerror(errno), errno); | |
errno = 0; | |
close(clisock); | |
pthread_exit(0); | |
} | |
} | |
clear_thread_logger(thl); | |
close(clisock); | |
pthread_exit(0); | |
} | |
int main(enum MAIN_OPTION opt) { | |
thread_logger *thl = new_thread_logger(debug_mode); | |
if (opt != skip_to_connloop) | |
{ | |
thread_store(create); | |
self_pid = getpid(); | |
sprintf(appendcmd, "ps hH p %d | wc -l > /dev/shm/linkup-varstore/thread_count", self_pid); | |
servsockfd = socket(AF_INET, SOCK_STREAM, 0); | |
struct sockaddr_in serv_addr; | |
struct sockaddr_in cli_addr; | |
serv_addr.sin_family = AF_INET; | |
serv_addr.sin_port = htons(64912); | |
serv_addr.sin_addr.s_addr = inet_addr("10.0.0.224"); | |
memset(&cli_addr, 0, sizeof(struct sockaddr_in)); //initializing cli_addr struct | |
if (setsockopt(servsockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) { | |
LOGF_ERROR(thl, 0, "setsockopt so_reuseaddr unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
errno = 0; | |
} | |
LOGF_DEBUG(thl, 0, "Set reuse", NULL); | |
LOGF_DEBUG(thl, 0, "Binding...", NULL); | |
int bind_status; | |
bind_status = bind(servsockfd, (SA*)&serv_addr, sizeof(serv_addr)); | |
if (bind_status == -1) { | |
LOGF_ERROR(thl, 0, "Bind unsuccessful : %s (Error code %d)", strerror(errno), errno); | |
errno = 0; | |
if (errno == 98) { | |
LOGF_ERROR(thl, 0, "More than one process running maybe?", NULL); | |
exit(0); | |
} | |
} | |
int listen_status; | |
LOGF_INFO(thl, 0, "Listening...", NULL); | |
listen_status = listen(servsockfd, SERVER_BACKLOG); // second param is backlog, aka how many connections can wait in one point in time | |
if (listen_status == -1) { | |
LOGF_ERROR(thl, 0, "Listen unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
errno = 0; | |
} | |
// user now has input | |
pthread_t input_thread; | |
pthread_create(&input_thread, NULL, (void *)cmd_input, NULL); | |
} | |
for (;;) { | |
usleep(SERVER_TICKRATE); | |
int clisock; | |
socklen_t cli_addr_size = sizeof(cli_addr); | |
clisock = accept(servsockfd, (SA*)&cli_addr, &cli_addr_size); // last two parameters should fill an optionable client struct for info | |
if (clisock >= 0) { | |
printf("\n"); | |
if (strcmp(inet_ntoa(cli_addr.sin_addr), ipaddr) == 0) { //if banned ip matches ipaddr string | |
LOGF_DEBUG(thl,0, "Banned IP address %s attempted to connect, refusing to open connection thread", inet_ntoa(cli_addr.sin_addr)); | |
main(skip_to_connloop); // half works, fixme | |
} | |
else { | |
LOGF_INFO(thl, 0, "Connection accepted from : %s:%d", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)); | |
pthread_t sckthread; | |
int *pclient = malloc(sizeof(int)); | |
*pclient = clisock; | |
pthread_create(&sckthread, NULL, (void *)handle_connection, pclient); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment