Related
There are two clients and a server in the application. The two clients communicate with each other via the server. When one client sends a message to the server, the server stores the message as a text file in the server, where file name is clientid_timestamp.txt. The server then sends the file to the other client that reads the file and displays its content on its terminal.
I have written the code for the client and the server given below.The issue that I am facing is that the client is not able to get the file from the server print it's contents.It doesn't show an output in the terminal.
Server side image in terminal
client side image in terminal
Server code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
#define MAX_CLIENTS 3
#define BUFFER_SZ 2048
#define SIZE 1024
static _Atomic unsigned int cli_count = 0;
static int uid = 10;
/* Client structure */
typedef struct{
struct sockaddr_in address;
int sockfd;
int uid;
char name[32];
} client_t;
client_t *clients[MAX_CLIENTS];
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
void str_overwrite_stdout() {
printf("\r%s", "> ");
fflush(stdout);
}
void print_client_addr(struct sockaddr_in addr){
printf("%d.%d.%d.%d",
addr.sin_addr.s_addr & 0xff,
(addr.sin_addr.s_addr & 0xff00) >> 8,
(addr.sin_addr.s_addr & 0xff0000) >> 16,
(addr.sin_addr.s_addr & 0xff000000) >> 24);
}
/* Add clients to queue */
void queue_add(client_t *cl){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(!clients[i]){
clients[i] = cl;
break;
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Remove clients to queue */
void queue_remove(int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid == uid){
clients[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
void send_file(int sockfd){
int n;
char data[SIZE] = {0};
FILE *fp = fopen("clientid_timestamp.txt", "r");
if (fp == NULL){
printf("Error opening file!\n");
exit(1);
}
while(fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
printf("hello");
bzero(data, SIZE);
}
}
/* Send message to all clients except sender */
void send_message(char *s, int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i<MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid != uid){
printf("MESSAGE SENT TO %s:%d \n",inet_ntoa(clients[i]->address.sin_addr),ntohs(clients[i]->address.sin_port));
send_file(clients[i]->uid);
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Handle all communication with the client */
void *handle_client(void *arg){
char buff_out[BUFFER_SZ];
char name[32];
int leave_flag = 0;
cli_count++;
client_t *cli = (client_t *)arg;
// Name
bzero(buff_out, BUFFER_SZ);
while(1){
if (leave_flag) {
break;
}
int receive = recv(cli->sockfd, buff_out, BUFFER_SZ, 0);
if (receive > 0){
if(strlen(buff_out) > 0){
FILE *f = fopen("clientid_timestamp.txt", "w");
if (f == NULL){
printf("Error opening file!\n");
exit(1);
}
/* print some text */
fprintf(f, "%s", buff_out);
send_message(buff_out, cli->uid);
fclose(f);
printf("\n");
}
}
else {
printf("ERROR: -1\n");
leave_flag = 1;
}
bzero(buff_out, BUFFER_SZ);
}
/* Delete client from queue and yield thread */
close(cli->sockfd);
queue_remove(cli->uid);
free(cli);
cli_count--;
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
int option = 1;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
signal(SIGPIPE, SIG_IGN);
if(setsockopt(listenfd, SOL_SOCKET,(SO_REUSEPORT | SO_REUSEADDR),(char*)&option,sizeof(option)) < 0){
perror("ERROR: setsockopt failed");
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
char exit[] = "exit_client";
char accepted[] = "accept_client";
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
send(connfd, exit, strlen(exit), 0);
close(connfd);
continue;
}
else{
send(connfd, accepted, strlen(accepted), 0);
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
printf("Client Connected : ");
printf("%s:%d \n",inet_ntoa(cli->address.sin_addr),ntohs(cli->address.sin_port));
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
/* Client settings */
}
return EXIT_SUCCESS;
}
Client Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define LENGTH 2048
#define MAX 10000
// Global variables
volatile sig_atomic_t flag = 0;
int sockfd = 0;
char name[32];
void str_overwrite_stdout() {
printf("%s", "> ");
fflush(stdout);
}
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
void catch_ctrl_c_and_exit(int sig) {
flag = 1;
}
void send_msg_handler() {
char message[LENGTH] = {};
char buffer[LENGTH + 32] = {};
while(1) {
str_overwrite_stdout();
fgets(message, LENGTH, stdin);
//str_trim_lf(message, LENGTH);
if (strcmp(message, "exit") == 0) {
break;
} else {
sprintf(buffer, "%s\n", message);
send(sockfd, buffer, strlen(buffer), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 32);
}
catch_ctrl_c_and_exit(2);
}
void recv_msg_handler() {
while (1) {
int n;
FILE *fp;
char buff[1024]="",*ptr=buff;
int bytes=0,bytes_received;
while(bytes_received = recv(sockfd,ptr, 1, 0)){
printf("%s\n",ptr);
if(bytes_received==-1){
perror("recieve");
exit(3);
}
if(*ptr=='\n' ) break;
ptr++; //each times we increment it it points to the buffer element
}
*ptr=0;
ptr=buff;
printf("%s\n",ptr);
str_overwrite_stdout();
}
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
signal(SIGINT, catch_ctrl_c_and_exit);
struct sockaddr_in server_addr;
/* Socket settings */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
// Connect to Server
int err = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err == -1) {
printf("ERROR: connect\n");
return EXIT_FAILURE;
}
char exit_client[] = "exit_client";
char buff[MAX];
bzero(buff, sizeof(buff));
recv(sockfd, buff, 1024, 0);
if((strcmp(buff, exit_client) == 0)){
printf("limit exceeded , closing the client \n");
close(sockfd);
return EXIT_SUCCESS;
}
else{
printf("client accepted by the server and limit not exceeded \n");
}
printf("=== WELCOME TO THE CHATROOM ===\n");
pthread_t send_msg_thread;
if(pthread_create(&send_msg_thread, NULL, (void *) send_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
pthread_t recv_msg_thread;
if(pthread_create(&recv_msg_thread, NULL, (void *) recv_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
while (1){
if(flag){
printf("\nBye\n");
break;
}
}
close(sockfd);
return EXIT_SUCCESS;
}
EDIT-1
I have made the changes suggested by the user stackinside and the code now works , but I have being facing a new issue for the past few hours and I am not able to wrap my head around it as what could the reason for it.
The issue that arises now is that the client is only able to send the message once to other client and vice versa and then it is not able to send any more messages except a new line.The updated code based on the changes I made
client side image in terminal
server side image in terminal
Server code :
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
#define MAX_CLIENTS 3
#define BUFFER_SZ 2048
#define SIZE 1024
static _Atomic unsigned int cli_count = 0;
static int uid = 10;
/* Client structure */
typedef struct{
struct sockaddr_in address;
int sockfd;
int uid;
char name[32];
} client_t;
client_t *clients[MAX_CLIENTS];
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
void str_overwrite_stdout() {
printf("\r%s", "> ");
fflush(stdout);
}
void print_client_addr(struct sockaddr_in addr){
printf("%d.%d.%d.%d",
addr.sin_addr.s_addr & 0xff,
(addr.sin_addr.s_addr & 0xff00) >> 8,
(addr.sin_addr.s_addr & 0xff0000) >> 16,
(addr.sin_addr.s_addr & 0xff000000) >> 24);
}
/* Add clients to queue */
void queue_add(client_t *cl){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(!clients[i]){
clients[i] = cl;
break;
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Remove clients to queue */
void queue_remove(int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid == uid){
clients[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
void send_file(int sockfd){
int n;
char data[SIZE] = {0};
FILE *fp = fopen("clientid_timestamp.txt", "r");
if (fp == NULL){
printf("Error opening file!\n");
exit(1);
}
while(fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
}
/* Send message to all clients except sender */
void send_message(char *s, int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i<MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid != uid){
printf("MESSAGE SENT TO %s:%d \n",inet_ntoa(clients[i]->address.sin_addr),ntohs(clients[i]->address.sin_port));
send_file(clients[i]->sockfd);
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Handle all communication with the client */
void *handle_client(void *arg){
char buff_out[BUFFER_SZ];
char name[32];
int leave_flag = 0;
cli_count++;
client_t *cli = (client_t *)arg;
// Name
bzero(buff_out, BUFFER_SZ);
while(1){
if (leave_flag) {
break;
}
int receive = recv(cli->sockfd, buff_out, BUFFER_SZ, 0);
if (receive > 0){
if(strlen(buff_out) > 0){
FILE *f = fopen("clientid_timestamp.txt", "w");
if (f == NULL){
printf("Error opening file!\n");
exit(1);
}
/* print some text */
fprintf(f, "%s", buff_out);
fclose(f);
send_message(buff_out, cli->uid);
printf("\n");
}
}
else {
printf("ERROR: -1\n");
leave_flag = 1;
}
bzero(buff_out, BUFFER_SZ);
}
/* Delete client from queue and yield thread */
close(cli->sockfd);
queue_remove(cli->uid);
free(cli);
cli_count--;
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
int option = 1;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
signal(SIGPIPE, SIG_IGN);
if(setsockopt(listenfd, SOL_SOCKET,(SO_REUSEPORT | SO_REUSEADDR),(char*)&option,sizeof(option)) < 0){
perror("ERROR: setsockopt failed");
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
char exit[] = "exit_client";
char accepted[] = "accept_client";
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
send(connfd, exit, strlen(exit), 0);
close(connfd);
continue;
}
else{
send(connfd, accepted, strlen(accepted), 0);
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
printf("Client Connected : ");
printf("%s:%d \n",inet_ntoa(cli->address.sin_addr),ntohs(cli->address.sin_port));
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
/* Client settings */
}
return EXIT_SUCCESS;
}
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define LENGTH 2048
#define MAX 10000
// Global variables
volatile sig_atomic_t flag = 0;
int sockfd = 0;
char name[32];
void str_overwrite_stdout() {
printf("%s", "> ");
fflush(stdout);
}
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
void catch_ctrl_c_and_exit(int sig) {
flag = 1;
}
void send_msg_handler() {
char message[LENGTH] = {};
char buffer[LENGTH + 32] = {};
while(1) {
str_overwrite_stdout();
fgets(message, LENGTH, stdin);
str_trim_lf(message, LENGTH);
if (strcmp(message, "exit") == 0) {
break;
} else {
sprintf(buffer, "%s\n", message);
send(sockfd, buffer, strlen(buffer), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 32);
}
catch_ctrl_c_and_exit(2);
}
void recv_msg_handler() {
int n;
FILE *fp;
char buff[1024]="",*ptr=buff;
int bytes=0,bytes_received;
while (1) {
while(bytes_received = recv(sockfd,ptr, 1, 0)){
if(bytes_received==-1){
perror("recieve");
exit(3);
}
if(*ptr=='\n' ) break;
ptr++; //each times we increment it it points to the buffer element
}
*ptr=0;
str_trim_lf(buff, strlen(buff));
ptr=buff;
printf("%s \n",ptr);
str_overwrite_stdout();
}
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
signal(SIGINT, catch_ctrl_c_and_exit);
struct sockaddr_in server_addr;
/* Socket settings */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
// Connect to Server
int err = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err == -1) {
printf("ERROR: connect\n");
return EXIT_FAILURE;
}
char exit_client[] = "exit_client";
char buff[MAX];
bzero(buff, sizeof(buff));
recv(sockfd, buff, 1024, 0);
if((strcmp(buff, exit_client) == 0)){
printf("limit exceeded , closing the client \n");
close(sockfd);
return EXIT_SUCCESS;
}
else{
printf("client accepted by the server and limit not exceeded \n");
}
printf("=== WELCOME TO THE CHATROOM ===\n");
pthread_t send_msg_thread;
if(pthread_create(&send_msg_thread, NULL, (void *) send_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
pthread_t recv_msg_thread;
if(pthread_create(&recv_msg_thread, NULL, (void *) recv_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
while (1){
if(flag){
printf("\nBye\n");
break;
}
}
close(sockfd);
return EXIT_SUCCESS;
}
EDIT-2
So now I changed the fgets to freads and removed all the unnecessary bzero and changed the strlen to sizeof as suggested by the comments of user207421 , Martin James and stackinside .It finally works , I agree there is still a lot of room for optimisation , but it works for now and thanks for the effort.
client side image in terminal
Server side image in terminal
Client side code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define LENGTH 2048
#define MAX 10000
#define CHUNK_SIZE 512
// Global variables
volatile sig_atomic_t flag = 0;
int sockfd = 0;
char name[32];
void str_overwrite_stdout() {
printf("%s", "> ");
fflush(stdout);
}
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
void catch_ctrl_c_and_exit(int sig) {
flag = 1;
}
void send_msg_handler() {
char message[LENGTH] = {};
char buffer[LENGTH + 32] = {};
while(1) {
str_overwrite_stdout();
fgets(message, LENGTH, stdin);
str_trim_lf(message, LENGTH);
if (strcmp(message, "exit") == 0) {
break;
}
else {
sprintf(buffer, "%s\n", message);
send(sockfd, buffer, sizeof(buffer), 0);
}
bzero(message, LENGTH);
bzero(buffer, LENGTH + 32);
}
catch_ctrl_c_and_exit(2);
}
void recv_msg_handler() {
while (1) {
int n;
FILE *fp;
char buff[1024],*ptr=buff;
int bytes=0,bytes_received;
int file_size;
recv(sockfd, buff, CHUNK_SIZE, 0);
file_size = atoi(buff);
str_trim_lf(buff, sizeof(buff));
printf("%s \n",buff);
str_overwrite_stdout();
}
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
signal(SIGINT, catch_ctrl_c_and_exit);
struct sockaddr_in server_addr;
/* Socket settings */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
// Connect to Server
int err = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (err == -1) {
printf("ERROR: connect\n");
return EXIT_FAILURE;
}
char exit_client[] = "exit_client";
char buff[MAX];
bzero(buff, sizeof(buff));
recv(sockfd, buff, 1024, 0);
if((strcmp(buff, exit_client) == 0)){
printf("limit exceeded , closing the client \n");
close(sockfd);
return EXIT_SUCCESS;
}
else{
printf("client accepted by the server and limit not exceeded \n");
}
printf("=== WELCOME TO THE CHATROOM ===\n");
pthread_t send_msg_thread;
if(pthread_create(&send_msg_thread, NULL, (void *) send_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
pthread_t recv_msg_thread;
if(pthread_create(&recv_msg_thread, NULL, (void *) recv_msg_handler, NULL) != 0){
printf("ERROR: pthread\n");
return EXIT_FAILURE;
}
while (1){
if(flag){
printf("\nBye\n");
break;
}
}
close(sockfd);
return EXIT_SUCCESS;
}
Server side:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
#define MAX_CLIENTS 3
#define BUFFER_SZ 2048
#define SIZE 1024
#define CHUNK_SIZE 512
static _Atomic unsigned int cli_count = 0;
static int uid = 10;
/* Client structure */
typedef struct{
struct sockaddr_in address;
int sockfd;
int uid;
char name[32];
} client_t;
client_t *clients[MAX_CLIENTS];
void str_trim_lf (char* arr, int length) {
int i;
for (i = 0; i < length; i++) { // trim \n
if (arr[i] == '\n') {
arr[i] = '\0';
break;
}
}
}
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;
void str_overwrite_stdout() {
printf("\r%s", "> ");
fflush(stdout);
}
void print_client_addr(struct sockaddr_in addr){
printf("%d.%d.%d.%d",
addr.sin_addr.s_addr & 0xff,
(addr.sin_addr.s_addr & 0xff00) >> 8,
(addr.sin_addr.s_addr & 0xff0000) >> 16,
(addr.sin_addr.s_addr & 0xff000000) >> 24);
}
/* Add clients to queue */
void queue_add(client_t *cl){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(!clients[i]){
clients[i] = cl;
break;
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Remove clients to queue */
void queue_remove(int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i < MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid == uid){
clients[i] = NULL;
break;
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
void send_file(int sockfd){
int n;
char data[SIZE] = {0};
FILE *fp = fopen("clientid_timestamp.txt", "r");
if (fp == NULL){
printf("Error opening file!\n");
exit(1);
}
char file_data[CHUNK_SIZE];
size_t nbytes = 0;
while ( (nbytes = fread(data, sizeof(char), CHUNK_SIZE,fp)) > 0){
if (send(sockfd, data, nbytes, 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
}
}
/* Send message to all clients except sender */
void send_message(char *s, int uid){
pthread_mutex_lock(&clients_mutex);
for(int i=0; i<MAX_CLIENTS; ++i){
if(clients[i]){
if(clients[i]->uid != uid){
printf("MESSAGE SENT TO %s:%d \n",inet_ntoa(clients[i]->address.sin_addr),ntohs(clients[i]->address.sin_port));
send_file(clients[i]->sockfd);
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
/* Handle all communication with the client */
void *handle_client(void *arg){
char buff_out[BUFFER_SZ];
char name[32];
int leave_flag = 0;
cli_count++;
client_t *cli = (client_t *)arg;
// Name
bzero(buff_out, BUFFER_SZ);
while(1){
if (leave_flag) {
break;
}
int receive = recv(cli->sockfd, buff_out, BUFFER_SZ, 0);
if (receive > 0){
if(strlen(buff_out) > 0){
FILE *f = fopen("clientid_timestamp.txt", "w");
if (f == NULL){
printf("Error opening file!\n");
exit(1);
}
/* print some text */
fprintf(f, "%s", buff_out);
fclose(f);
send_message(buff_out, cli->uid);
printf("\n");
}
}
else {
printf("ERROR: -1\n");
leave_flag = 1;
}
}
/* Delete client from queue and yield thread */
close(cli->sockfd);
queue_remove(cli->uid);
free(cli);
cli_count--;
pthread_detach(pthread_self());
return NULL;
}
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
int option = 1;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
signal(SIGPIPE, SIG_IGN);
if(setsockopt(listenfd, SOL_SOCKET,(SO_REUSEPORT | SO_REUSEADDR),(char*)&option,sizeof(option)) < 0){
perror("ERROR: setsockopt failed");
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
char exit[] = "exit_client";
char accepted[] = "accept_client";
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
send(connfd, exit, sizeof(exit), 0);
close(connfd);
continue;
}
else{
send(connfd, accepted, sizeof(accepted), 0);
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
printf("Client Connected : ");
printf("%s:%d \n",inet_ntoa(cli->address.sin_addr),ntohs(cli->address.sin_port));
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
/* Client settings */
}
return EXIT_SUCCESS;
}
Server side:
send_file(clients[i]->uid); ought to be send_file(clients[i]->sockfd);
fclose(f); should probably go before send_message(buff_out, cli->uid);
Client side:
printf("%s\n",ptr); (before if(bytes_received==-1)) ought to be removed
There are other inconsistencies, unused variables, etc. This reivew is very limited.
I know this is kinda lame question, but what am I doing wrong in my code ? Basically, I wanna create communication on local IP using UDP, also send some files etc. The problem is, that when I get to freeing my structures after using them/converting them to/from char* the program just crashes. What is even more weird, the program does not crash when debugging and stepping through using CLion debugger. What am I doing wrong? Here is my source code:
The error seems to happen, when I can not allocate more memory (so logically, I need to free some) when sending a file over network. Sending messages works just fine
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
// PKS2Visual.cpp : Defines the entry point for the console application.
//
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <time.h>
#define BREAKSOMETHING 0
#pragma comment(lib, "ws2_32.lib")
int fragSize = 1500;
int isInside = 0;
SOCKET s1, s2;
struct sockaddr_in server, myClient, otherClient;
int main() {
char mode;
printf("Enter fragment size:\n");
scanf("%d", &fragSize);
p2pMode();
}
DWORD WINAPI receiveThreadFunc(LPVOID lpParam) {
int slen = sizeof(otherClient);
int doRun = 1;
int sizee;
char msgBuffer[1519];
char fileName[1519];
int receivingFile = 0;
while (doRun) {
printf("Waiting for data...\n\n");
if ((recvfrom(s1, msgBuffer, 1519, 0, (struct sockaddr *) &otherClient,
&slen)) == SOCKET_ERROR) {
printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
continue;
}
//printf("Received packet from %s:%d\n", inet_ntoa(otherClient.sin_addr), ntohs(otherClient.sin_port));
PacketData *packetData = dataToPacket(msgBuffer);
if (packetData == NULL) {
continue;
}
char flag = packetData->flag;
switch (flag) {
case 's': {
PacketData *packetDataAck = createPacket('a');
char *messageToSend2 = packetToData(packetDataAck, &sizee);
if (sendto(s1, messageToSend2, 18, 0, (struct sockaddr *) &otherClient, slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
//free(packetDataAck);
//free(messageToSend2);
break;
}
case 'm': {
if (receivingFile) {
FILE *fptr;
fptr = fopen(fileName, "a");
fprintf(fptr, "%s", packetData->data);
printf("Packet contains data: %s\n", packetData->data);
fclose(fptr);
if(packetData->fragNum == packetData->fragTotal){
receivingFile = 0;
}
} else {
printf("Received packet n. %d\n", packetData->fragNum);
printf("Packet data length: %d\n", packetData->len);
printf("Packet contains data: %s\n", packetData->data);
}
break;
}
case 'f': {
strcpy(fileName, packetData->data);
printf("Receiving file: %s\n", fileName);
printf("Receiving file: %s\n", packetData->data);
receivingFile = 1;
break;
}
default: {
doRun = 0;
break;
}
}
free(packetData);
}
return 0;
}
DWORD WINAPI sendThreadFunc(LPVOID lpParam) {
PacketData **fragments = NULL;
int doRun = 1;
char msgBuffer[1500];
int actualSize = 0;
int slen = sizeof(myClient);
while (1) {
printf("Enter message or -e to end messaging and return to menu:\n");
fflush(stdin);
scanf("%1500[^\n]", msgBuffer);
getc(stdin);
if (strcmp(msgBuffer, "-e") == 0) {
isInside = 0;
return 0;
}
if (strlen(msgBuffer) >= 1499) {
continue;
}
fragments = makeFragments(msgBuffer);
int numFragments = fragments[0]->fragTotal;
printf("Number of fragments: %d\n", numFragments);
PacketData *packetData = createPacket('s');
if (packetData == NULL) {
printf("Could not init packet 's'\n");
continue;
}
char *sync = packetToData(packetData, &actualSize);
if (sendto(s2, sync, 18, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
printf("First fragment sent.\n");
free(packetData);
char *ack = (char *) calloc(18, sizeof(char));
if (recvfrom(s2, ack, 18, 0, (struct sockaddr *) &myClient, &slen) ==
SOCKET_ERROR) {
printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
continue;
}
free(ack);
printf("Server confirmed first packet.\n");
for (int i = 0; i < fragments[0]->fragTotal; i++) {
char *msgBuffer2 = packetToData(fragments[i], &actualSize);
if (sendto(s2, msgBuffer2, actualSize + 1, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
}
free(fragments);
}
return 0;
}
DWORD WINAPI sendFileFunc(LPVOID lpParam) {
char msgBuffer[1500];
int actualSize = 0;
int slen = sizeof(myClient);
while (1) {
printf("Enter file name or -e to return to menu:\n");
fflush(stdin);
scanf("%1500[^\n]", msgBuffer);
getc(stdin);
if (strcmp(msgBuffer, "-e") == 0) {
isInside = 0;
return 0;
}
if (strlen(msgBuffer) >= 1499) {
continue;
}
//Get file length:
FILE *fl = fopen(msgBuffer, "r");
if (fl == NULL) {
printf("Invalid name, try again\n");
continue;
}
fseek(fl, 0, SEEK_END);
long fileLength = ftell(fl);
fclose(fl);
int numFragments = (fileLength - 1) / fragSize + 2;
printf("Number of fragments: %d\n", numFragments);
PacketData *packetData = createPacket('s');
if (packetData == NULL) {
printf("Could not init packet 's'\n");
continue;
}
char *sync = packetToData(packetData, &actualSize);
if (sendto(s2, sync, 18, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
printf("First fragment sent.\n");
free(packetData);
char *ack = (char *) calloc(18, sizeof(char));
if (recvfrom(s2, ack, 18, 0, (struct sockaddr *) &myClient, &slen) ==
SOCKET_ERROR) {
printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
continue;
}
//free(ack);
PacketData *fragments = NULL;
fragments = (PacketData *) malloc(sizeof(PacketData));
fragments->data = (char *) malloc(fragSize * sizeof(char));
strncpy(fragments->data, msgBuffer, strlen(msgBuffer));
fragments->data[strlen(msgBuffer)] = '\0';
fragments->flag = 'f';
fragments->len = strlen(msgBuffer);
fragments->fragNum = (unsigned int) (1);
fragments->fragTotal = (unsigned int) numFragments - 1;
fragments->CRC = (unsigned int) calculate_crc(msgBuffer, strlen(msgBuffer));
//Sending the first fragment with 'f' flag
char *toSend = packetToData(fragments, &actualSize);
if (sendto(s2, toSend, actualSize + 1, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
printf("Server confirmed first packet.\n");
size_t n = 0;
int counter = 0;
int fragNum = 2;
int c;
FILE *f2 = fopen(msgBuffer, "r");
if(f2 == NULL){
printf("File was null\n");
continue;
}
while ((c = fgetc(f2)) != EOF) {
msgBuffer[n++] = (char) c;
counter++;
if (counter == fragSize) {
n = 0;
counter = 0;
printf("Allocating fragment number: %d\n", fragNum);
PacketData *fragments2 = NULL;
fragments2 = (PacketData *) malloc(sizeof(PacketData));
if(fragments2 == NULL){
printf("Incorrect malloc\n");
break;
}
fragments2->data = (char *) malloc((fragSize+1) * sizeof(char));
if(fragments2->data == NULL){
printf("Incorrect malloc2\n");
break;
}
strncpy(fragments2->data, msgBuffer, fragSize);
printf("Copying data to fragment number: %d\n", fragNum);
fragments2->data[strlen(msgBuffer)] = '\0';
fragments2->flag = 'm';
fragments2->len = (unsigned int) fragSize;
fragments2->fragNum = (unsigned int) (fragNum);
fragments2->fragTotal = (unsigned int) numFragments - 1;
fragments2->CRC = (unsigned int) calculate_crc(msgBuffer, fragSize);
printf("Allocated fragment number: %d\n", fragNum);
fragNum++;
char *toSend = packetToData(fragments2, &actualSize);
if (sendto(s2, toSend, actualSize + 1, 0, (struct sockaddr *) &myClient,
slen) == SOCKET_ERROR) {
printf("sendto() failed with error code : %d\n", WSAGetLastError());
continue;
}
printf("Sent fragment number: %d\n", fragNum);
}
}
fclose(fl);
}
return 0;
}
void p2pMode() {
int serverPort, clientPort;
char *serverAddr = (char *) malloc(20 * sizeof(char));
WSADATA wsa;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
printf("Failed. Error Code : %d", WSAGetLastError());
getchar();
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
char hostname[128] = "";
char menuBuffer;
gethostname(hostname, sizeof(hostname));
struct hostent *ent = gethostbyname(hostname);
struct in_addr ip_addr = *(struct in_addr *) (ent->h_addr);
printf("Your IP Address: %s\n", inet_ntoa(ip_addr));
printf("Enter other PC IP Address:\n");
scanf("%s", serverAddr);
if (!strcmp(serverAddr, "localhost"))
serverAddr = (char *) "127.0.0.1";
printf("Enter your listening port:\n");
scanf("%d", &clientPort);
printf("Enter other PC's port:\n");
scanf("%d", &serverPort);
if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket : %d", WSAGetLastError());
}
if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(inet_ntoa(ip_addr));
server.sin_port = htons(clientPort);
myClient.sin_family = AF_INET;
myClient.sin_port = htons(serverPort);
myClient.sin_addr.S_un.S_addr = inet_addr(serverAddr);
if (bind(s1, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
free(serverAddr);
DWORD dwThreadId, dwThreadId2, dwThreadId3, dwThrdParam = 1;
CreateThread(
NULL, // default security attributes
10000, // use default stack size
receiveThreadFunc, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
while (1) {
if (!isInside) {
printf("For messages, write 'm', for file 'f'\n");
scanf("%c", &menuBuffer);
switch (menuBuffer) {
case 'm':
CreateThread(
NULL, // default security attributes
10000, // use default stack size
sendThreadFunc, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId2); // returns the thread identifier
isInside = 1;
break;
case 'f':
CreateThread(
NULL, // default security attributes
10000, // use default stack size
sendFileFunc, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId3); // returns the thread identifier
isInside = 1;
break;
}
}
}
}
char *packetToData(PacketData *packet, int *size) { // convert packet into sendable data
int sizee = packet->len + 18;
*size = sizee;
char *temp = (char *) calloc(sizee, sizeof(char));
char *out;
if (temp == NULL) {
return NULL;
}
out = temp;
*(temp) = packet->flag;
*(unsigned int *) (temp + 2) = packet->CRC;
*(unsigned int *) (temp + 6) = packet->fragNum;
*(unsigned int *) (temp + 10) = packet->fragTotal;
*(unsigned int *) (temp + 14) = packet->len;
temp = (temp + 18);
int i;
for (i = 0; i < packet->len; i++) { // copy data
temp[i] = packet->data[i];
}
temp[i] = '\0';
return out;
}
PacketData *dataToPacket(char *data) { // convert received data into packet
printf("Data received: %s\n", data);
PacketData *packet = (PacketData *) malloc(sizeof(PacketData));
if (packet == NULL)
return NULL;
packet->flag = *(data);
packet->CRC = *(unsigned int *) (data + 2);
packet->fragNum = *(unsigned int *) (data + 6);
packet->fragTotal = *(unsigned int *) (data + 10);
packet->len = *(unsigned int *) (data + 14);
packet->data = (char *) malloc(packet->len);
char *packetdata = (data + 18);
int i;
for (i = 0; i < packet->len; i++) { // copy data
packet->data[i] = packetdata[i];
}
packet->data[i] = '\0';
return packet;
}
PacketData *createPacket(char flag) {
PacketData *packetData = (PacketData *) malloc(sizeof(PacketData));
packetData->flag = flag;
packetData->len = 0;
packetData->CRC = 0;
packetData->fragNum = 1;
packetData->fragTotal = 1;
return packetData;
}
int calculate_crc(char *buf, int size) {
int crcHash = 10;
for (int i = 0; i < size; i++) {
crcHash += buf[i];
crcHash *= 31;
crcHash %= 30000;
}
return crcHash;
}
struct packetData **makeFragments(char *message) {
int i;
printf("Message length: %d\n", strlen(message));
int fragCount = (strlen(message) - 1) / fragSize + 1;
if (fragCount == 0) {
fragCount++;
}
PacketData **fragments = (PacketData **) malloc((fragCount) * sizeof(PacketData *));
printf("Allocated %d fragments\n", fragCount);
for (i = 0; i < fragCount; i++) {
fragments[i] = (PacketData *) malloc(sizeof(PacketData));
fragments[i]->data = (char *) malloc(fragSize * sizeof(char));
int toCopy = 0;
if (strlen(message) > fragSize) {
toCopy = fragSize;
} else {
toCopy = strlen(message);
}
strncpy(fragments[i]->data, message, toCopy);
fragments[i]->data[toCopy] = '\0';
fragments[i]->flag = 'm';
fragments[i]->len = (unsigned int) toCopy;
fragments[i]->fragNum = (unsigned int) (i + 1);
fragments[i]->fragTotal = (unsigned int) fragCount;
fragments[i]->CRC = (unsigned int) calculate_crc(message, toCopy);
message += fragSize;
}
printf("Fragments needed: %d\n", fragments[0]->fragTotal);
return fragments;
}
and here is my header if someone needed to run it:
//
// Created by lukas on 11/19/2018.
//
#include <winsock2.h>
#include <windows.h>
#ifndef PKS2C_MAIN_H
#define PKS2C_MAIN_H
#endif //PKS2C_MAIN_H
typedef struct packetData {
char flag;
unsigned int CRC;
unsigned int fragNum;
unsigned int fragTotal;
unsigned int len;
char *data;
} PacketData;
struct packetData **makeFragments(char *message);
struct packetData **makeFileFragments(char *message);
char *packetToData(PacketData *packet, int *size);
PacketData *dataToPacket(char *data);
PacketData *createPacket(char flag);
void p2pMode();
int calculate_crc(char *buf, int size);
DWORD WINAPI receiveThread(LPVOID lpParam);
DWORD WINAPI sendThread(LPVOID lpParam);
SOCKET s1, s2;
struct sockaddr_in server, myClient, otherClient;
Problem is to make UDP server send data to an array of clients, that already make a connection to a server. All clients IPs are stored on the server side linkedlist, but for some reason, i am able to send response only, and only to the last made connection from the client.
So basic description of what I want to achieve is:
few clients made a connection and i can see their messages
every client's IP is stored in linkedlist
if there is more than 1 client stored in linkedlist, program will go through every IP in its storage, and if IP of current client is DIFFERENT from what is stored in linkedlist -> server is sending to this IP last message from current client
on the server side, if message was typed, program will go through every IP stored in LinkedList and send this message to every client
server.c
#include "server.h"
#include "linkedList.h"
volatile sig_atomic_t dones = 0;
void server(){
pthread_t r, s;
int server_d;
struct sockaddr_in server, client;
struct params args;
linkedList** iter = getIteratorList();
if((server_d = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("\nsocket");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
bzero(server.sin_zero, 8);
args.client = &client;
args.server_d = &server_d;
args.iter = iter;
if(bind(server_d, (struct sockaddr*)&server, sizeof(struct sockaddr)) == -1){
perror("\nbind");
exit(-1);
}
pthread_create(&r, NULL, receives, (void*)&args);
pthread_create(&s, NULL, sends, (void*)&args);
pthread_join(s, NULL);
}
void* receives(void* data){
int flag = 0;
struct params* args = data;
int* server_d = args->server_d;
struct sockaddr_in* client = args->client;
linkedList** iter = args->iter;
unsigned int length = sizeof(struct sockaddr_in);
char buffer[BUFFER_MAX];
struct sockaddr_in tmp;
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = terms;
sigaction(SIGINT, &action, NULL);
bzero(buffer, BUFFER_MAX);
while(!dones){
if(flag == 0){
if(recvfrom(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)client, &length) > 0){
flag = 1;
decrypt(buffer);
printf("[%s]:%s", inet_ntoa(client->sin_addr), buffer);
//some new staff
if(checkList(inet_ntoa(client->sin_addr)) != 1){
addList(*client);
printf("[DEBUG]clients IP is stored. size of LL: %d\n", sizeList());
}
if(sizeList() > 1){
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[DEBUG]Stored IP[%d]: %s\n", i, (*iter)->address);
nextList();
}
}
beginList();
for(int i = 0; i < sizeList(); i++){
if (strcmp((*iter)->address, inet_ntoa(client->sin_addr)) != 0){
printf("[DEBUG]there is a client to send a message to. message: %s", buffer);
printf("[DEBUG]resend: %s --> %s\n",inet_ntoa(client->sin_addr), (*iter)->address);
tmp.sin_addr.s_addr = inet_addr((*iter)->address);
tmp.sin_family = client->sin_family;
tmp.sin_port = client->sin_port;
bzero(tmp.sin_zero, 8);
printf("[DEBUG]IP in tmp.sin_addr: %s\n", inet_ntoa(tmp.sin_addr));
printf("[DEBUG]IP in client->sin_addr: %s\n", inet_ntoa(client->sin_addr));
printf("[DEBUG]message send: %d\n", (int)sendto(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)&tmp, sizeof(struct sockaddr_in)));
nextList();
}else{
nextList();
}
}
// end of new staff
}
bzero(buffer, BUFFER_MAX);
}else{
if(recvfrom(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)client, &length) == 0){
flag = 0;
}else{
decrypt(buffer);
printf("[%s]:%s", inet_ntoa(client->sin_addr), buffer);
//some new staff
if(checkList(inet_ntoa(client->sin_addr)) != 1){
addList(*client);
printf("[DEBUG]clients IP is stored. size of LL: %d\n", sizeList());
}
if(sizeList() > 1){
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[DEBUG]Stored IP[%d]: %s\n", i, (*iter)->address);
nextList();
}
}
beginList();
for(int i = 0; i < sizeList(); i++){
if (strcmp((*iter)->address, inet_ntoa(client->sin_addr)) != 0){
printf("[DEBUG]there is a client to send a message to. message: %s", buffer);
printf("[DEBUG]resend: %s --> %s\n",inet_ntoa(client->sin_addr), (*iter)->address);
tmp.sin_addr.s_addr = inet_addr((*iter)->address);
tmp.sin_family = client->sin_family;
tmp.sin_port = client->sin_port;
bzero(tmp.sin_zero, 8);
printf("[DEBUG]IP in tmp.sin_addr: %s\n", inet_ntoa(tmp.sin_addr));
printf("[DEBUG]IP in client->sin_addr: %s\n", inet_ntoa(client->sin_addr));
printf("[DEBUG]message send: %d\n", (int)sendto(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)&tmp, sizeof(struct sockaddr_in)));
nextList();
}else{
nextList();
}
}
// end of new staff
}
bzero(buffer, BUFFER_MAX);
}
}
printf("Server terminated.\n");
return NULL;
}
void* sends(void* data){
struct params* args = data;
int* server_d = args->server_d;
struct sockaddr_in* client = args->client;
linkedList** iter = args->iter;
char buffer[BUFFER_MAX];
struct sockaddr_in tmp;
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = terms;
sigaction(SIGINT, &action, NULL);
while(!dones){
bzero(buffer, BUFFER_MAX);
fgets(buffer, BUFFER_MAX - 1, stdin);
encrypt(buffer);
/*
if(sendto(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)client, sizeof(struct sockaddr_in)) == -1){
printf("Message was not sent...\n");
}
*/
tmp.sin_addr.s_addr = client->sin_addr.s_addr;
tmp.sin_family = client->sin_family;
tmp.sin_port = client->sin_port;
bzero(tmp.sin_zero, 8);
beginList();
for(int i = 0; i < sizeList(); i++){
tmp.sin_addr.s_addr = inet_addr((*iter)->address);
printf("[DEBUG]sending to address: %s\n", inet_ntoa(tmp.sin_addr));
sendto(*server_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)&tmp, sizeof(struct sockaddr_in));
nextList();
}
}
printf("Server terminated.\n");
return NULL;
}
void terms(int signum){
dones = 1;
if(clearList() == 0) printf("\n\nLinkedList was succesfully deleted.\n");
printf("\nTerminating server...\n");
}
server.h
#ifndef SERVER_H_
#define SERVER_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include "const.h"
#include "encrypt.h"
#include "linkedList.h"
struct params{
struct sockaddr_in* client;
int* server_d;
linkedList** iter;
};
volatile sig_atomic_t dones;
void server();
void* receives(void*);
void* sends(void*);
void terms(int);
#endif
linkedList.h
#ifndef LINKED_LIST_
#define LINKED_LIST_
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
typedef struct ll{
int socket;
char* address;
struct ll* next;
struct ll* prev;
} linkedList;
linkedList* initList(struct sockaddr_in);
linkedList* addList(struct sockaddr_in);
linkedList* removeList(char*);
unsigned short int clearList();
unsigned short int sizeList();
linkedList* nextList();
linkedList* prevList();
linkedList* beginList();
linkedList* endList();
linkedList** getIteratorList();
unsigned short int checkList(char*);
#endif
linkedList.c
#include "linkedList.h"
static linkedList* iterator = NULL;
linkedList* initList(struct sockaddr_in p_new){
iterator = (linkedList*) malloc(sizeof(linkedList));
if(iterator == NULL) return NULL;
iterator->next = NULL;
iterator->prev = NULL;
iterator->address = (char*)malloc(sizeof(char)*16);
strcpy(iterator->address, inet_ntoa(p_new.sin_addr));
return iterator;
}
linkedList* addList(struct sockaddr_in p_new){
if(iterator == NULL){
return initList(p_new);
}
endList();
iterator->next = (linkedList*) malloc(sizeof(linkedList));
if(iterator->next == NULL) return NULL;
iterator->next->next = NULL;
iterator->next->prev = iterator;
iterator->next->address = (char*)malloc(sizeof(char)*16);
strcpy(iterator->next->address, inet_ntoa(p_new.sin_addr));
return iterator = iterator->next;
}
linkedList* removeList(char* p_address){
beginList();
for(int i = 0; i < sizeList(); i++){
if(strcmp(iterator->address, p_address) == 0){
if(iterator->prev == NULL){
iterator = iterator->next;
free(iterator->prev->address);
free(iterator->prev);
iterator->prev = NULL;
return iterator;
}else if(iterator->next == NULL){
iterator = iterator->prev;
free(iterator->next->address);
free(iterator->next);
iterator->next = NULL;
return iterator;
}else{
linkedList* tmp = iterator->next;
iterator->prev->next = iterator->next;
iterator->next->prev = iterator->prev;
free(iterator->address);
free(iterator);
return iterator = tmp;
}
}else{
nextList();
}
}
beginList();
return iterator;
}
unsigned short int clearList(){
if (iterator == NULL) return 404;
endList();
while( (iterator->next != NULL && iterator->prev != NULL) ){
iterator = iterator->prev;
free(iterator->next->address);
free(iterator->next);
iterator->next = NULL;
}
free(iterator);
iterator = NULL;
return 0;
}
unsigned short int sizeList(){
unsigned short int size = 0;
unsigned int tmp_range = 0;
if(iterator == NULL) return size;
while(iterator->prev != NULL){
tmp_range++;
prevList();
}
while(iterator->next != NULL){
size++;
nextList();
}
size++;
beginList();
for(int i = 0; i < tmp_range; i++){
nextList();
}
return size;
}
linkedList* nextList(){
if (iterator == NULL) return NULL;
if(iterator->next == NULL) return iterator; else return iterator = iterator->next;
}
linkedList* prevList(){
if (iterator == NULL) return NULL;
if(iterator->prev == NULL) return iterator; else return iterator = iterator->prev;
}
linkedList* beginList(){
if (iterator == NULL) return NULL;
while(iterator->prev != NULL){
prevList();
}
return iterator;
}
linkedList* endList(){
if (iterator == NULL) return NULL;
while(iterator->next != NULL){
nextList();
}
return iterator;
}
linkedList** getIteratorList(){
return &iterator;
}
unsigned short int checkList(char* p_str){
if(iterator == NULL) return 0;
beginList();
for(int i = 0; i < sizeList(); i++){
if(strcmp(iterator->address, p_str) == 0){
return 1;
}else nextList();
}
beginList();
return 0;
}
client.h
#ifndef CLIENT_H_
#define CLIENT_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include "const.h"
#include "encrypt.h"
struct paramc{
struct sockaddr_in* server;
int* client_d;
};
volatile sig_atomic_t donec;
void client(char*);
void* receivec(void*);
void* sendc(void*);
void termc(int);
#endif
client.c
#include "client.h"
volatile sig_atomic_t donec = 0;
void client(char* address){
pthread_t r, s;
int client_d;
struct sockaddr_in server;
struct paramc args;
if((client_d = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("\nsocket");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = inet_addr(address);
bzero(server.sin_zero, 8);
args.server = &server;
args.client_d = &client_d;
pthread_create(&r, NULL, receivec, (void*)&args);
pthread_create(&s, NULL, sendc, (void*)&args);
pthread_join(s, NULL);
}
void* receivec(void* data){
struct paramc* args = data;
struct sockaddr_in* server = args->server;
int* client_d = args->client_d;
unsigned int length = sizeof(struct sockaddr_in);
char buffer[BUFFER_MAX];
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = termc;
sigaction(SIGINT, &action, NULL);
while(!donec){
if(recvfrom(*client_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)server, &length) > 0){
decrypt(buffer);
printf("[%s]:%s", inet_ntoa(server->sin_addr), buffer);
bzero(buffer, BUFFER_MAX);
}
}
printf("Client terminated.\n");
return NULL;
}
void* sendc(void* data){
struct paramc* args = data;
struct sockaddr_in* server = args->server;
int* client_d = args->client_d;
char buffer[BUFFER_MAX];
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = termc;
sigaction(SIGINT, &action, NULL);
while(!donec){
bzero(buffer, BUFFER_MAX);
fgets(buffer, BUFFER_MAX - 1, stdin);
encrypt(buffer);
sendto(*client_d, buffer, BUFFER_MAX - 1, 0, (struct sockaddr*)server, sizeof(struct sockaddr_in));
}
printf("Client terminated.\n");
return NULL;
}
void termc(int signum){
donec = 1;
printf("\nTerminating client...\n");
}
const.h
#ifndef CONST_H_
#define CONST_H_
#define PORT 15151
#define BUFFER_MAX 1024
#endif
main.c
#include "server.h"
#include "client.h"
//#define linkedlist_test
#ifdef linkedlist_test
#include "linkedList.h"
#endif
int main(int argc, char* argv[]){
#ifndef linkedlist_test
system("clear");
if(argc < 2){
server();
}else{
client(argv[1]);
}
#endif
#ifdef linkedlist_test
struct sockaddr_in test1;
test1.sin_family = AF_INET;
test1.sin_port = htons(PORT);
test1.sin_addr.s_addr = inet_addr("192.168.1.101");
bzero(test1.sin_zero, 8);
struct sockaddr_in test2;
test2.sin_family = AF_INET;
test2.sin_port = htons(PORT);
test2.sin_addr.s_addr = inet_addr("192.168.1.102");
bzero(test2.sin_zero, 8);
struct sockaddr_in test3;
test3.sin_family = AF_INET;
test3.sin_port = htons(PORT);
test3.sin_addr.s_addr = inet_addr("192.168.1.103");
bzero(test3.sin_zero, 8);
struct sockaddr_in test4;
test4.sin_family = AF_INET;
test4.sin_port = htons(PORT);
test4.sin_addr.s_addr = inet_addr("192.168.1.104");
bzero(test4.sin_zero, 8);
struct sockaddr_in test5;
test5.sin_family = AF_INET;
test5.sin_port = htons(PORT);
test5.sin_addr.s_addr = inet_addr("192.168.1.105");
bzero(test5.sin_zero, 8);
linkedList** iterator = getIteratorList();
printf("address: %p/%p\torder: %d\n", *iterator, addList(test1), sizeList());
printf("address: %p/%p\torder: %d\n", *iterator, addList(test2), sizeList());
printf("address: %p/%p\torder: %d\n", *iterator, addList(test3), sizeList());
printf("address: %p/%p\torder: %d\n", *iterator, addList(test4), sizeList());
printf("address: %p/%p\torder: %d\n", *iterator, addList(test5), sizeList());
printf("vypis testovych struktur priamo:\n%s\n", inet_ntoa(test1.sin_addr));
printf("%s\n", inet_ntoa(test2.sin_addr));
printf("%s\n", inet_ntoa(test3.sin_addr));
printf("%s\n", inet_ntoa(test4.sin_addr));
printf("%s\n", inet_ntoa(test5.sin_addr));
printf("========================\n");
checkList("192.168.1.104");
printf("checkList() test: adresa -//-.104 sa nachadza: %p, plna adresa je %s\n", (*iterator), (*iterator)->address);
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[%p]list\'s output [%d]: %s\n", *iterator, i, (*iterator)->address);
nextList();
}
printf("========================\n");
removeList("192.168.1.102");
printf("deleting 192.168.1.102\n");
printf("size: %d\n", sizeList());
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[%p]list\'s output [%d]: %s\n", *iterator, i, (*iterator)->address);
nextList();
}
printf("========================\n");
removeList("192.168.1.101");
printf("deleting 192.168.1.101\n");
printf("size: %d\n", sizeList());
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[%p]list\'s output [%d]: %s\n", *iterator, i, (*iterator)->address);
nextList();
}
printf("========================\n");
removeList("192.168.1.105");
printf("deleting 192.168.1.105\n");
printf("size: %d\n", sizeList());
beginList();
for(int i = 0; i < sizeList(); i++){
printf("[%p]list\'s output [%d]: %s\n", *iterator, i, (*iterator)->address);
nextList();
}
printf("========================\n");
printf("removing the whole list\n");
if(clearList() == 0) printf("successfully removed\n"); else printf("some chiki-briki is not right. FAILUREEE!");
printf("size: %d\n", sizeList());
printf("========================\n");
#endif
return 0;
}
encrypt.c and encrypt.h are just two functions char* encrypt(char*) and char* decrypt(char*) that did nothing with a string --> WIP
I got "Conditional jump or move depends on uninitialised value(s)" , and it is coming from function process_server(). I have tried to figure out where it is coming, but to no avail.
Message from valgrind.
==2468== Conditional jump or move depends on uninitialised value(s)
==2468== at 0x402B3D: process_server (in /home/emeka/Desktop/dump/project/serverd)
==2468== by 0x402DB3: main (in /home/emeka/Desktop/dump/project/serverd)
==2468==
#include "signal.h"
#include "string.h"
#include "sys/types.h"
#include "unistd.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "netdb.h"
#include "stdlib.h"
#include "ctype.h"
#include "stdio.h"
#include "utility.h"
#include "route.c"
#include "tokenize.c"
#include "bridge.c"
#define PORT 1253
#define ADDRESS "127.0.0.1"
#define START "start"
#define STOP "stop"
#define LISTENQ 4
typedef struct sockaddr SA;
//#define INET6_ADDRSTRLEN 3000
requested_data *re_data;
int switch_ch;
struct sockaddr_in serveraddr;
int start_server(int port){
int listenid;
int optval=1;
typedef struct sockaddr SA;
if((listenid = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
error_message("Error in startServer <Failed to create socket>");
}
if (setsockopt(listenid, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int)) < 0)
return -1;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if(bind(listenid, (SA*)&serveraddr, sizeof(serveraddr)) < 0) {
error_message("Error in startServer <Failed to bind socket>");
}
if(listen(listenid, LISTENQ) < 0) {
error_message("Error in startServer <Failed to listen>");
}
return listenid;
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
void process_server(int listenid){
char remoteIP[INET6_ADDRSTRLEN];
int fd, read_size;
const int buffer_size = 1000;
char *client_message = malloc(sizeof(char) * buffer_size);
if(!client_message){
printf("Not enough memory");
abort();
}
struct sockaddr_storage remoteaddr; // client address
socklen_t addrlen;
addrlen = sizeof remoteaddr;
char *gen, gen_int = 0, supplied_answer;
while((fd = accept(listenid, (struct sockaddr *)&remoteaddr, &addrlen))) {
while((read_size = recv(fd, client_message, buffer_size, 0)) > 0) {
printf("%s", client_message);
re_data = router(client_message, read_size);
printf("Method %s --url::%s=+++\n", re_data->method, re_data->url);
switch_ch = 1;
free(client_message);
client_message = malloc(sizeof(char) * buffer_size);
if(!client_message){
printf("Not enough memory");
abort();
}
break;
}
printf("DE server: new connection from %s on "
"socket %d\n",
inet_ntop(remoteaddr.ss_family,
get_in_addr((struct sockaddr*)&remoteaddr),
remoteIP, INET6_ADDRSTRLEN),fd);
str_query *rem_data;
str_query *header_meta = re_data->meta_data;
while(header_meta){
if(strncasecmp(re_data->method, "PUT", 3) == 0){
if(strncasecmp(re_data->url, "/answer", 7) == 0){
if(strlen(re_data->url) == 7){
if(strncasecmp(header_meta->req_name, "question", 8) == 0){
int res_int = parse_input(header_meta->req_value);
if(gen_int == res_int && supplied_answer == res_int){
send(fd, "HTTP status 200 OK" , 18, 0);
} else {
send(fd, "400 Bad Request" , 15, 0);
}
printf("\n Resulted from computation of %s result :: %d\n", header_meta->req_name, res_int);
}
}
}
}
if(switch_ch){
if(strncasecmp(re_data->url, "/question" , 9) == 0){
if(strncasecmp(re_data->method, "GET", 3) == 0){
gen = pmain();
send(fd, gen, strlen(gen), 0);
gen_int = parse_input(gen);
switch_ch = 0;
printf("\n Resulted from generated computation of %s result :: %d\n", header_meta->req_name, gen_int);
free(gen);
}
}
}
if(strncasecmp(header_meta->req_name, "answer", 8) == 0){
supplied_answer = atoi(header_meta->req_value);
}
printf("\nname %s value %s\n", header_meta->req_name, header_meta->req_value);
rem_data = header_meta;
header_meta = header_meta->next;
free(rem_data->req_name);
free(rem_data->req_value);
free(rem_data);
}
if(!client_message){
free(client_message);
}
free(re_data);
close(fd);
}
return;
}
int main(int argc, char **argv) {
int port, pid, server_conn = 1;
int internet_address_len = 15;
char serAdd[internet_address_len];
char strAction[7];
if(argc == 1) {
port = PORT;
strcpy(serAdd, ADDRESS);
} else if(argc == 2){
port = atoi(argv[1]);
strcpy(serAdd, ADDRESS);
} else if(argc == 3) {
port = atoi(argv[1]);
int n = strlen(argv[2]);
strncpy(serAdd, argv[2], n);
if(n >= internet_address_len){
error_message("Internet address is incorrect");
}
serAdd[n] = '\0';
}
printf("\n\tDE is a basic server built to carry out simple things\n"
"\t----- -----\n"
"\t| | |\n"
"\t| | -----\n"
"\t| | |\n"
"\t----- -----\n"
"\tMethods implemented [Get & Put]\n"
"\tTo start type start\n"
"\tTo stop type stop\nDE]");
scanf("%s", strAction);
if (strcmp(strAction, START) == 0){
printf("Server %sed\n", START);
int listenid = start_server(port);
printf("listen on port %d & listening is %d\nDE]", port,listenid);
signal(SIGPIPE, SIG_IGN);
while(server_conn) {
pid =fork();
if(pid == 0) {
process_server(listenid);
break;
}
scanf("%s", strAction);
if (strcmp(strAction, STOP) == 0) {
close(listenid);
return 0;
}
}
}
return 0;
}
I am writing a C HTTP server for a class. I have a rough implementation working, but I am stuck on this issue. I am trying to multi-thread the GET requests sent from a browser, but the server is just closing the connection after ~10 requests.
Here is the code:
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#define SERVPORT 5004
#define BUFSIZE 4096
#define MAXCONNECT 3
#define MAX_THREADS 8
struct data
{
int i;
};
void * clientHandler(void *info);
void sendError(char *msg);
char * getDate();
int sendall(int send_socket, char *buf, int *len);
int parseSrc(char src[]);
char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen);
char date[100];
char http200[50] = "HTTP/1.1 200 OK\n";
char http400[50] = "HTTP/1.1 400 Bad Request\n";
char http404[50] = "HTTP/1.1 404 Not Found\n";
int main()
{
printf("Starting server..\n");
int servSock, clntSock, fd;
struct sockaddr_in server, client;
unsigned int len, clntSize;
fd_set master;
fd_set read_fds;
int fdmax;
int i;
if( (servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
sendError("socket");
FD_ZERO(&master);
FD_ZERO(&read_fds);
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(SERVPORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
for(i=0; i<=10; i++)
{
printf("Trying port %d...\n", (ntohs(server.sin_port) + i));
if( bind(servSock, (struct sockaddr *)&server, sizeof(server)) == -1)
server.sin_port = htons(SERVPORT + i);
else if(i < 10)
break; //socket connected succesfully
else
sendError("bind");
}
printf("Successfully bound to port %d!\n", ntohs(server.sin_port));
if( listen(servSock, MAXCONNECT) == -1)
sendError("listen");
printf("Listening...\n");
FD_SET(servSock, &master);
fdmax = servSock;
pthread_t threads[MAX_THREADS];
while(1)
{
read_fds = master;
int num_threads = 0;
if( select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1)
sendError("select");
for(i = 0; i <= fdmax; i++)
{
if(FD_ISSET(i, &read_fds))
{
if(i == servSock)
{
clntSize = sizeof(client);
if( (clntSock = accept(servSock, (struct sockaddr *)&client, &clntSize)) == -1)
sendError("accept");
FD_SET(clntSock, &master);
if(clntSock > fdmax)
fdmax = clntSock;
char s[50];
printf("Connected to %s\n", get_ip_str((struct sockaddr *)&client, s, sizeof(s)));
}
else
{
//clientHandler(i);
struct data *info;
info = malloc(sizeof(struct data));
info->i = i;
if(pthread_create(&threads[i], NULL, (void *)clientHandler, (void *)info))
sendError("pthread");
num_threads++;
}
}
}
if(num_threads > MAX_THREADS)
{
num_threads = 0;
pthread_join(threads[num_threads], NULL);
}
}
for(i = 0; i < MAX_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
}
void *clientHandler(void *info)
{
struct data *myinfo = (struct data*) info;
int clntSock = myinfo->i;
char buf[BUFSIZE];
int recd;
if( (recd = recv(clntSock, buf, BUFSIZE, 0)) == -1)
sendError("recieve1");
while(recd > 0)
{
char cmd[5] = "/0";
char src[100] = "/0";
char prt[100] = "/0";
memset(&cmd, 0, sizeof(cmd));
memset(&src, 0, sizeof(src));
memset(&prt, 0, sizeof(prt));
sscanf(buf, "%4s%99s%99s", cmd, src, prt);
char cmdget[5] = "GET";
if(strcmp(cmd, cmdget) == 0) //GET command
{
int len;
if(src[0] == '/')
memmove(src, src+1, strlen(src));
if(strlen(src) == 0)
strcpy(src, "index.html");
FILE *fp;
fp = fopen(src, "r");
if(fp == NULL)
{
len = strlen(http404);
if(sendall(clntSock, http404, &len) == -1)
sendError("send 404");
break;
}
struct stat buf;
fstat(fileno(fp), &buf);
char contLen[50] = "Content-Length: ";
sprintf(contLen, "%s%d\n", contLen, (int)buf.st_size);
char contType[100] = "Content-Type: ";
char *tempType;
tempType = strrchr(src, '.');
if(strcmp(tempType, ".html") == 0) //.html
strcat(contType, "text/html\n");
else if(strcmp(tempType, ".txt") == 0) //.txt
strcat(contType, "text/txt\n");
else if(strcmp(tempType, ".css") == 0) //.css
strcat(contType, "text/css\n");
else if(strcmp(tempType, ".jpg") == 0) //.jpg
strcat(contType, "image/jpg\n");
else if(strcmp(tempType, ".png") == 0) //.png
strcat(contType, "image/png\n");
else if(strcmp(tempType, ".gif") == 0) //.gif
strcat(contType, "image/gif\n");
else if(strcmp(tempType, ".js") == 0) //.js
strcat(contType, "application/javascript\n");
else
{
char fileErrorTemp[50] = "Unknown filetype: ";
strcat(fileErrorTemp, tempType);
sendError(fileErrorTemp);
}
char tempDate[100] = "";
strcpy(tempDate, getDate());
char tempMsg[500] = "";
strcat(tempMsg, http200);
strcat(tempMsg, tempDate);
strcat(tempMsg, contType);
strcat(tempMsg, contLen);
strcat(tempMsg, "\n");
len = strlen(tempMsg);
if( sendall(clntSock, tempMsg, &len) == -1)
sendError("send 200");
printf("Sent client: %s # %s", http200, tempDate);
printf(" Sending %s\n", src);
if( sendfile(fp, clntSock) == -1)
sendError("file send");
}
else //Unknown or bad command
{
int http400len = strlen(http400);
if( send(clntSock, http400, strlen(http400), 0) == -1)
sendError("send 400");
}
printf("Waiting to receive...\n");
if( (recd = recv(clntSock,buf, BUFSIZE, 0)) == -1)
sendError("recieve1");
//printf("%d\n", recd);
}
close(clntSock);
return;
}
void sendError(char *msg)
{
perror(msg);
exit(-1);
}
char * getDate() //return date in "Date: Tue, 16 Feb 2010 19:21:24 GMT" format
{
memset(&date, 0, sizeof(date));
strcpy(date, "Date: ");
time_t rawtime = time(0);
struct tm * info;
time(&rawtime);
info = gmtime(&rawtime);
char wday[5];
char mon[5];
switch(info->tm_wday){
case 0: strcpy(wday, "Mon");
case 1: strcpy(wday, "Tue");
case 2: strcpy(wday, "Wed");
case 3: strcpy(wday, "Thu");
case 4: strcpy(wday, "Fri");
case 5: strcpy(wday, "Sat");
case 6: strcpy(wday, "Sun");
}
switch(info->tm_mon){
case 0: strcpy(mon, "Jan");
case 1: strcpy(mon, "Feb");
case 2: strcpy(mon, "Mar");
case 3: strcpy(mon, "Apr");
case 4: strcpy(mon, "May");
case 5: strcpy(mon, "Jun");
case 6: strcpy(mon, "Jul");
case 7: strcpy(mon, "Aug");
case 8: strcpy(mon, "Sep");
case 9: strcpy(mon, "Oct");
case 10: strcpy(mon, "Nov");
case 11: strcpy(mon, "Dec");
}
char temp[5];
strcat(date, wday);
strcat(date, ", ");
sprintf(temp, "%2d", info->tm_mday);
strcat(date, temp);
strcat(date, " ");
strcat(date, mon);
sprintf(temp, " %4d ", (info->tm_year + 1900));
strcat(date, temp);
sprintf(temp, "%d:", info->tm_hour);
strcat(date, temp);
sprintf(temp, "%.2d:", info->tm_min);
strcat(date, temp);
sprintf(temp, "%.2d", info->tm_sec);
strcat(date, temp);
strcat(date, " UTC\n");
return date;
}
int sendall(int send_socket, char *buf, int *len)
{
int total = 0;
int bytesleft = *len;
int n;
while(total < *len)
{
n = send(send_socket, (buf + total), bytesleft, 0);
if(n == -1)
break;
total += n;
bytesleft -= n;
}
*len = total;
if(n==-1)
return -1;
else
return 0;
}
int sendfile(FILE* fp, int clntSock)
{
while(1)
{
unsigned char buff[256]={0};
int nread = fread(buff, 1, 256, fp);
if(nread > 0)
write(clntSock, buff, nread);
if(nread < 256)
{
if(feof(fp))
break; //eof
if(ferror(fp))
return -1;
}
}
return 0;
}
int parseSrc(char src[])
{
printf("%s", src);
if(src[0] == '/')
{
printf("SLASH");
src++;
return 2;
}
printf("%s", src);
return 1;
}
char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen)
{
switch(sa->sa_family)
{
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen);
break;
default:
strncpy(s, "Unknown AF", maxlen);
return NULL;
}
return s;
}
I am really stuck. Any help would be greatly appreciated!