updated client and server
This commit is contained in:
+41
-11
@@ -12,7 +12,8 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define PORT 7777
|
#define DEFAULT_PORT 7777
|
||||||
|
#define DEFAULT_IP "127.0.0.1"
|
||||||
#define BUFFER_SIZE 4096
|
#define BUFFER_SIZE 4096
|
||||||
#define USERNAME_MAX 50
|
#define USERNAME_MAX 50
|
||||||
#define INPUT_HEIGHT 3
|
#define INPUT_HEIGHT 3
|
||||||
@@ -34,6 +35,10 @@ int scroll_offset = 0;
|
|||||||
|
|
||||||
unsigned char aes_key[AES_KEY_SIZE];
|
unsigned char aes_key[AES_KEY_SIZE];
|
||||||
|
|
||||||
|
// Параметры подключения
|
||||||
|
char server_ip[256] = DEFAULT_IP;
|
||||||
|
int server_port = DEFAULT_PORT;
|
||||||
|
|
||||||
volatile int need_redraw = 0;
|
volatile int need_redraw = 0;
|
||||||
volatile int running = 1;
|
volatile int running = 1;
|
||||||
|
|
||||||
@@ -299,7 +304,6 @@ void scroll_down() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Формат пакета: [total_len:4][iv:12][tag:16][ciphertext:N]
|
|
||||||
void send_encrypted_message(int socket, const char *plaintext) {
|
void send_encrypted_message(int socket, const char *plaintext) {
|
||||||
unsigned char iv[AES_IV_SIZE];
|
unsigned char iv[AES_IV_SIZE];
|
||||||
RAND_bytes(iv, AES_IV_SIZE);
|
RAND_bytes(iv, AES_IV_SIZE);
|
||||||
@@ -324,7 +328,6 @@ void send_encrypted_message(int socket, const char *plaintext) {
|
|||||||
send(socket, ciphertext, ciphertext_len, 0);
|
send(socket, ciphertext, ciphertext_len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Получить и расшифровать сообщение
|
|
||||||
int receive_encrypted_message(int socket, char *plaintext, int max_len) {
|
int receive_encrypted_message(int socket, char *plaintext, int max_len) {
|
||||||
int net_total_len;
|
int net_total_len;
|
||||||
int valread = read(socket, &net_total_len, sizeof(int));
|
int valread = read(socket, &net_total_len, sizeof(int));
|
||||||
@@ -424,7 +427,14 @@ void handle_input() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Форматируем и отправляем на сервер, НЕ добавляем локально!
|
// Проверяем длину чтобы избежать truncation
|
||||||
|
int max_msg_len = BUFFER_SIZE - strlen(username) - 5;
|
||||||
|
if (max_msg_len < 0) max_msg_len = 0;
|
||||||
|
|
||||||
|
if ((int) strlen(input_buffer) > max_msg_len) {
|
||||||
|
input_buffer[max_msg_len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
char full_msg[BUFFER_SIZE];
|
char full_msg[BUFFER_SIZE];
|
||||||
int written = snprintf(full_msg, sizeof(full_msg), "[%s]: %s", username,
|
int written = snprintf(full_msg, sizeof(full_msg), "[%s]: %s", username,
|
||||||
input_buffer);
|
input_buffer);
|
||||||
@@ -435,7 +445,6 @@ void handle_input() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
send_encrypted_message(sock, full_msg);
|
send_encrypted_message(sock, full_msg);
|
||||||
// Сообщение появится когда придёт от сервера в receive_messages()
|
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
input_buffer[0] = '\0';
|
input_buffer[0] = '\0';
|
||||||
@@ -481,7 +490,6 @@ void receive_messages() {
|
|||||||
char plaintext[BUFFER_SIZE];
|
char plaintext[BUFFER_SIZE];
|
||||||
int len = receive_encrypted_message(sock, plaintext, BUFFER_SIZE);
|
int len = receive_encrypted_message(sock, plaintext, BUFFER_SIZE);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
// ВСЕ сообщения приходят через сервер — и свои, и чужие
|
|
||||||
add_chat_message(plaintext);
|
add_chat_message(plaintext);
|
||||||
} else if (len < 0) {
|
} else if (len < 0) {
|
||||||
add_chat_message("*** Ошибка расшифровки сообщения ***");
|
add_chat_message("*** Ошибка расшифровки сообщения ***");
|
||||||
@@ -498,18 +506,35 @@ void sigwinch_handler(int sig) {
|
|||||||
|
|
||||||
void parse_args(int argc, char *argv[]) {
|
void parse_args(int argc, char *argv[]) {
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"messagebuffer", required_argument, 0, 'm'}, {0, 0, 0, 0}};
|
{"messagebuffer", required_argument, 0, 'm'},
|
||||||
|
{"ip", required_argument, 0, 'i'},
|
||||||
|
{"port", required_argument, 0, 'p'},
|
||||||
|
{0, 0, 0, 0}};
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
while ((opt = getopt_long(argc, argv, "m:", long_options, NULL)) != -1) {
|
while ((opt = getopt_long(argc, argv, "m:i:p:", long_options, NULL)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'm':
|
case 'm':
|
||||||
msg_buffer_size = atoi(optarg);
|
msg_buffer_size = atoi(optarg);
|
||||||
if (msg_buffer_size < 10) msg_buffer_size = 10;
|
if (msg_buffer_size < 10) msg_buffer_size = 10;
|
||||||
if (msg_buffer_size > 10000) msg_buffer_size = 10000;
|
if (msg_buffer_size > 10000) msg_buffer_size = 10000;
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
strncpy(server_ip, optarg, sizeof(server_ip) - 1);
|
||||||
|
server_ip[sizeof(server_ip) - 1] = '\0';
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
server_port = atoi(optarg);
|
||||||
|
if (server_port < 1 || server_port > 65535) {
|
||||||
|
fprintf(stderr, "Invalid port: %s\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Usage: %s [-m N|--messagebuffer=N]\n", argv[0]);
|
fprintf(stderr,
|
||||||
|
"Usage: %s [-m N|--messagebuffer=N] [-i IP|--ip=IP] [-p "
|
||||||
|
"PORT|--port=PORT]\n",
|
||||||
|
argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,8 +565,13 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
server_addr.sin_family = AF_INET;
|
server_addr.sin_family = AF_INET;
|
||||||
server_addr.sin_port = htons(PORT);
|
server_addr.sin_port = htons(server_port);
|
||||||
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
|
if (inet_pton(AF_INET, server_ip, &server_addr.sin_addr) <= 0) {
|
||||||
|
fprintf(stderr, "Invalid address: %s\n", server_ip);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[INFO] Connecting to %s:%d\n", server_ip, server_port);
|
||||||
|
|
||||||
if (connect(sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) <
|
if (connect(sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) <
|
||||||
0) {
|
0) {
|
||||||
|
|||||||
+184
-148
@@ -1,4 +1,5 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <getopt.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -6,7 +7,8 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define PORT 7777
|
#define DEFAULT_PORT 7777
|
||||||
|
#define DEFAULT_IP "0.0.0.0"
|
||||||
#define BUFFER_SIZE 8192
|
#define BUFFER_SIZE 8192
|
||||||
#define MAX_CLIENTS 100
|
#define MAX_CLIENTS 100
|
||||||
#define HISTORY_SIZE 1000
|
#define HISTORY_SIZE 1000
|
||||||
@@ -15,16 +17,16 @@
|
|||||||
#define AES_TAG_SIZE 16
|
#define AES_TAG_SIZE 16
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int socket;
|
int socket;
|
||||||
char username[USERNAME_MAX];
|
char username[USERNAME_MAX];
|
||||||
} client_t;
|
} client_t;
|
||||||
|
|
||||||
client_t *clients[MAX_CLIENTS];
|
client_t *clients[MAX_CLIENTS];
|
||||||
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int data_len;
|
int data_len;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
} encrypted_message_t;
|
} encrypted_message_t;
|
||||||
|
|
||||||
encrypted_message_t message_history[HISTORY_SIZE];
|
encrypted_message_t message_history[HISTORY_SIZE];
|
||||||
@@ -32,180 +34,214 @@ int history_count = 0;
|
|||||||
int history_start = 0;
|
int history_start = 0;
|
||||||
pthread_mutex_t history_mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t history_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
// Параметры сервера
|
||||||
|
char bind_ip[256] = DEFAULT_IP;
|
||||||
|
int bind_port = DEFAULT_PORT;
|
||||||
|
|
||||||
void add_to_history(const unsigned char *data, int len) {
|
void add_to_history(const unsigned char *data, int len) {
|
||||||
pthread_mutex_lock(&history_mutex);
|
pthread_mutex_lock(&history_mutex);
|
||||||
int idx = (history_start + history_count) % HISTORY_SIZE;
|
int idx = (history_start + history_count) % HISTORY_SIZE;
|
||||||
|
|
||||||
free(message_history[idx].data);
|
free(message_history[idx].data);
|
||||||
message_history[idx].data = malloc(len);
|
message_history[idx].data = malloc(len);
|
||||||
memcpy(message_history[idx].data, data, len);
|
memcpy(message_history[idx].data, data, len);
|
||||||
message_history[idx].data_len = len;
|
message_history[idx].data_len = len;
|
||||||
|
|
||||||
if (history_count < HISTORY_SIZE) {
|
if (history_count < HISTORY_SIZE) {
|
||||||
history_count++;
|
history_count++;
|
||||||
} else {
|
} else {
|
||||||
history_start = (history_start + 1) % HISTORY_SIZE;
|
history_start = (history_start + 1) % HISTORY_SIZE;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&history_mutex);
|
pthread_mutex_unlock(&history_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_history(int socket) {
|
void send_history(int socket) {
|
||||||
pthread_mutex_lock(&history_mutex);
|
pthread_mutex_lock(&history_mutex);
|
||||||
|
|
||||||
int net_count = htonl(history_count);
|
int net_count = htonl(history_count);
|
||||||
write(socket, &net_count, sizeof(int));
|
write(socket, &net_count, sizeof(int));
|
||||||
|
|
||||||
for (int i = 0; i < history_count; i++) {
|
for (int i = 0; i < history_count; i++) {
|
||||||
int idx = (history_start + i) % HISTORY_SIZE;
|
int idx = (history_start + i) % HISTORY_SIZE;
|
||||||
int net_len = htonl(message_history[idx].data_len);
|
int net_len = htonl(message_history[idx].data_len);
|
||||||
write(socket, &net_len, sizeof(int));
|
write(socket, &net_len, sizeof(int));
|
||||||
write(socket, message_history[idx].data, message_history[idx].data_len);
|
write(socket, message_history[idx].data, message_history[idx].data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&history_mutex);
|
pthread_mutex_unlock(&history_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Рассылка ВСЕМ клиентам включая отправителя (-1 = всем)
|
|
||||||
void broadcast_to_all(const unsigned char *data, int len) {
|
void broadcast_to_all(const unsigned char *data, int len) {
|
||||||
pthread_mutex_lock(&clients_mutex);
|
pthread_mutex_lock(&clients_mutex);
|
||||||
for (int i = 0; i < MAX_CLIENTS; i++) {
|
for (int i = 0; i < MAX_CLIENTS; i++) {
|
||||||
if (clients[i]) {
|
if (clients[i]) {
|
||||||
int net_len = htonl(len);
|
int net_len = htonl(len);
|
||||||
send(clients[i]->socket, &net_len, sizeof(int), 0);
|
send(clients[i]->socket, &net_len, sizeof(int), 0);
|
||||||
send(clients[i]->socket, data, len, 0);
|
send(clients[i]->socket, data, len, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&clients_mutex);
|
}
|
||||||
|
pthread_mutex_unlock(&clients_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *handle_client(void *arg) {
|
void *handle_client(void *arg) {
|
||||||
client_t *cli = (client_t *)arg;
|
client_t *cli = (client_t *) arg;
|
||||||
|
|
||||||
int valread = read(cli->socket, cli->username, USERNAME_MAX);
|
int valread = read(cli->socket, cli->username, USERNAME_MAX);
|
||||||
if (valread <= 0) goto cleanup;
|
if (valread <= 0) goto cleanup;
|
||||||
cli->username[valread] = '\0';
|
cli->username[valread] = '\0';
|
||||||
cli->username[strcspn(cli->username, "\n")] = '\0';
|
cli->username[strcspn(cli->username, "\n")] = '\0';
|
||||||
|
|
||||||
printf("User '%s' connected\n", cli->username);
|
printf("User '%s' connected from %s\n", cli->username,
|
||||||
|
inet_ntoa(((struct sockaddr_in *) &cli)->sin_addr));
|
||||||
|
|
||||||
send_history(cli->socket);
|
send_history(cli->socket);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int net_total_len;
|
int net_total_len;
|
||||||
valread = read(cli->socket, &net_total_len, sizeof(int));
|
valread = read(cli->socket, &net_total_len, sizeof(int));
|
||||||
if (valread <= 0) break;
|
if (valread <= 0) break;
|
||||||
|
|
||||||
int total_len = ntohl(net_total_len);
|
int total_len = ntohl(net_total_len);
|
||||||
if (total_len <= 0 || total_len > BUFFER_SIZE) {
|
if (total_len <= 0 || total_len > BUFFER_SIZE) {
|
||||||
printf("Invalid length from %s: %d\n", cli->username, total_len);
|
printf("Invalid length from %s: %d\n", cli->username, total_len);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *data = malloc(total_len);
|
|
||||||
int total_read = 0;
|
|
||||||
while (total_read < total_len) {
|
|
||||||
valread = read(cli->socket, data + total_read, total_len - total_read);
|
|
||||||
if (valread <= 0) {
|
|
||||||
free(data);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
total_read += valread;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сохраняем
|
|
||||||
add_to_history(data, total_len);
|
|
||||||
|
|
||||||
// Рассылаем ВСЕМ включая отправителя
|
|
||||||
broadcast_to_all(data, total_len);
|
|
||||||
|
|
||||||
free(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char *data = malloc(total_len);
|
||||||
|
int total_read = 0;
|
||||||
|
while (total_read < total_len) {
|
||||||
|
valread = read(cli->socket, data + total_read, total_len - total_read);
|
||||||
|
if (valread <= 0) {
|
||||||
|
free(data);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
total_read += valread;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_to_history(data, total_len);
|
||||||
|
broadcast_to_all(data, total_len);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
printf("User '%s' disconnected\n", cli->username);
|
printf("User '%s' disconnected\n", cli->username);
|
||||||
close(cli->socket);
|
close(cli->socket);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&clients_mutex);
|
||||||
|
for (int i = 0; i < MAX_CLIENTS; i++) {
|
||||||
|
if (clients[i] == cli) {
|
||||||
|
clients[i] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&clients_mutex);
|
||||||
|
|
||||||
|
free(cli);
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_args(int argc, char *argv[]) {
|
||||||
|
static struct option long_options[] = {{"ip", required_argument, 0, 'i'},
|
||||||
|
{"port", required_argument, 0, 'p'},
|
||||||
|
{0, 0, 0, 0}};
|
||||||
|
|
||||||
|
int opt;
|
||||||
|
while ((opt = getopt_long(argc, argv, "i:p:", long_options, NULL)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'i':
|
||||||
|
strncpy(bind_ip, optarg, sizeof(bind_ip) - 1);
|
||||||
|
bind_ip[sizeof(bind_ip) - 1] = '\0';
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
bind_port = atoi(optarg);
|
||||||
|
if (bind_port < 1 || bind_port > 65535) {
|
||||||
|
fprintf(stderr, "Invalid port: %s\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Usage: %s [-i IP|--ip=IP] [-p PORT|--port=PORT]\n",
|
||||||
|
argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int server_fd, new_socket;
|
||||||
|
struct sockaddr_in address;
|
||||||
|
int opt = 1;
|
||||||
|
int addrlen = sizeof(address);
|
||||||
|
|
||||||
|
parse_args(argc, argv);
|
||||||
|
|
||||||
|
for (int i = 0; i < HISTORY_SIZE; i++) {
|
||||||
|
message_history[i].data = NULL;
|
||||||
|
message_history[i].data_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
|
||||||
|
perror("socket failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
|
||||||
|
perror("setsockopt");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
address.sin_port = htons(bind_port);
|
||||||
|
if (inet_pton(AF_INET, bind_ip, &address.sin_addr) <= 0) {
|
||||||
|
fprintf(stderr, "Invalid bind address: %s\n", bind_ip);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) {
|
||||||
|
perror("bind failed");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(server_fd, 3) < 0) {
|
||||||
|
perror("listen");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("E2E Encrypted Server listening on %s:%d\n", bind_ip, bind_port);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if ((new_socket = accept(server_fd, (struct sockaddr *) &address,
|
||||||
|
(socklen_t *) &addrlen)) < 0) {
|
||||||
|
perror("accept");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
client_t *cli = malloc(sizeof(client_t));
|
||||||
|
cli->socket = new_socket;
|
||||||
|
|
||||||
pthread_mutex_lock(&clients_mutex);
|
pthread_mutex_lock(&clients_mutex);
|
||||||
|
int added = 0;
|
||||||
for (int i = 0; i < MAX_CLIENTS; i++) {
|
for (int i = 0; i < MAX_CLIENTS; i++) {
|
||||||
if (clients[i] == cli) {
|
if (!clients[i]) {
|
||||||
clients[i] = NULL;
|
clients[i] = cli;
|
||||||
break;
|
added = 1;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&clients_mutex);
|
pthread_mutex_unlock(&clients_mutex);
|
||||||
|
|
||||||
free(cli);
|
if (!added) {
|
||||||
pthread_exit(NULL);
|
printf("Max clients reached\n");
|
||||||
}
|
close(new_socket);
|
||||||
|
free(cli);
|
||||||
int main() {
|
continue;
|
||||||
int server_fd, new_socket;
|
|
||||||
struct sockaddr_in address;
|
|
||||||
int opt = 1;
|
|
||||||
int addrlen = sizeof(address);
|
|
||||||
|
|
||||||
for (int i = 0; i < HISTORY_SIZE; i++) {
|
|
||||||
message_history[i].data = NULL;
|
|
||||||
message_history[i].data_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
|
|
||||||
perror("socket failed");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
|
|
||||||
perror("setsockopt");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
address.sin_family = AF_INET;
|
|
||||||
address.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
address.sin_port = htons(PORT);
|
|
||||||
|
|
||||||
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
|
|
||||||
perror("bind failed");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(server_fd, 3) < 0) {
|
pthread_t tid;
|
||||||
perror("listen");
|
pthread_create(&tid, NULL, handle_client, cli);
|
||||||
exit(EXIT_FAILURE);
|
pthread_detach(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("E2E Encrypted Server listening on port %d\n", PORT);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
|
|
||||||
perror("accept");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
client_t *cli = malloc(sizeof(client_t));
|
|
||||||
cli->socket = new_socket;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&clients_mutex);
|
|
||||||
int added = 0;
|
|
||||||
for (int i = 0; i < MAX_CLIENTS; i++) {
|
|
||||||
if (!clients[i]) {
|
|
||||||
clients[i] = cli;
|
|
||||||
added = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&clients_mutex);
|
|
||||||
|
|
||||||
if (!added) {
|
|
||||||
printf("Max clients reached\n");
|
|
||||||
close(new_socket);
|
|
||||||
free(cli);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_t tid;
|
|
||||||
pthread_create(&tid, NULL, handle_client, cli);
|
|
||||||
pthread_detach(tid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user