Skip to content

Instantly share code, notes, and snippets.

@databoose
Created August 4, 2020 07:28
Show Gist options
  • Save databoose/85f0d7592bf43676428392e1cf3702c4 to your computer and use it in GitHub Desktop.
Save databoose/85f0d7592bf43676428392e1cf3702c4 to your computer and use it in GitHub Desktop.
server
#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>
#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 16
#define TIMEOUT_OUT 16
int servsockfd; // global so we can pass it around functions
int usleep(__useconds_t usec); // millisecond sleep
pid_t self_pid;
char cmd_str[26];
int lengthofchar(char* tempstring)
{
int cnt;
int charcount;
charcount = 0;
for(cnt=0; tempstring[cnt]; cnt++) {
if(tempstring[cnt] != ' ') {
charcount++;
}
}
return charcount;
}
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);
}
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);
}
}
//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
{
printf("Thread ID : %ld (",(pthread_self() / 100000));
printf("Thread count : ");
int sysret = system(cmd_str); // it should print here, but somehow prints before?
if(sysret == -1) {
printf("system() (getting thread count) unsuccessful : %s (Error code %d)\n", strerror(errno), errno);
}
set_timeout(servsockfd,TIMEOUT_IN,TIMEOUT_OUT);
/*
for(int i = 0; i < 10; i++) {
printf("(Job %ld) : ", (pthread_self() / 1000000));
printf("%d\n", i);
sleep(2);
}
*/
int clisock = *((int*)p_clisock);
free (p_clisock); // we don't need the pointer anymore.
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) {
printf("Error reading from socket : %s\n", strerror(errno));
printf("%s (%d) \n",strerror(errno),errno);
close(clisock);
pthread_exit(0);
}
printf("\nWaiting for verification string from client ... \n");
if (strcmp(verif_recv_str, recv_buf) == 0)
{
printf("[VERIFY SUCCESS] Verification string \"%s\" received\n", verif_recv_str);
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);
close(clisock);
pthread_exit(0);
}
}
close(clisock);
pthread_exit(0);
}
int main() {
self_pid = getpid();
sprintf(cmd_str, "ps hH p %d | wc -l\n", 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) {
printf("setsockopt so_reuseaddr unsuccessful : %s (Error code %d)\n", strerror(errno), errno);
}
printf("Set reuse\n");
printf("Binding...\n");
int bind_status;
bind_status = bind(servsockfd, (SA*)&serv_addr, sizeof(serv_addr));
if (bind_status == -1) {
printf("Bind unsuccessful : %s (Error code %d)\n", strerror(errno), errno);
if (errno == 98) {
printf("More than one process running maybe?\n");
exit(0);
}
}
int listen_status;
printf("Listening...\n");
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) {
printf("Listen unsuccessful : %s (Error code %d)\n", strerror(errno), errno);
}
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");
printf("Connection accepted from : %s:%d\n", 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