-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.c
121 lines (100 loc) · 3.42 KB
/
util.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <dirent.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stddef.h>
#include "config.h"
#include "util.h"
static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
char *get_random_file(void) {
DIR *dir;
struct dirent *entry;
struct stat statbuf;
char *filepath = NULL;
int count = 0;
dir = opendir(TEXT_DIR);
if (dir == NULL) {
perror("opendir failed");
return NULL;
}
while ((entry = readdir(dir)) != NULL) {
char fullpath[MAX_PATH_LENGTH];
int path_length = snprintf(fullpath, sizeof(fullpath), "%s/%s", TEXT_DIR, entry->d_name);
if (path_length < 0 || (size_t)path_length >= sizeof(fullpath)) {
fprintf(stderr, "Path too long or encoding error: %s/%s\n", TEXT_DIR, entry->d_name);
continue;
}
if (stat(fullpath, &statbuf) == -1) {
perror("stat failed");
continue;
}
if (S_ISREG(statbuf.st_mode)) {
count++;
}
}
if (count == 0) {
closedir(dir);
return NULL;
}
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
srand(ts.tv_nsec); // Use nanoseconds for better randomness
int random_index = rand() % count;
rewinddir(dir);
int current_index = 0;
while ((entry = readdir(dir)) != NULL) {
char fullpath[MAX_PATH_LENGTH];
int path_length = snprintf(fullpath, sizeof(fullpath), "%s/%s", TEXT_DIR, entry->d_name);
if (path_length < 0 || (size_t)path_length >= sizeof(fullpath)) {
continue;
}
if (stat(fullpath, &statbuf) == -1) {
continue;
}
if (S_ISREG(statbuf.st_mode)) {
if (current_index == random_index) {
filepath = strdup(fullpath);
break;
}
current_index++;
}
}
closedir(dir);
return filepath;
}
void log_connection(const char *client_ip, time_t start_time, time_t end_time,
size_t bytes_transferred, int connection_closed_by_server,
const char *filename) {
pthread_mutex_lock(&log_mutex);
FILE *log_file = fopen(LOG_FILE, "a");
if (log_file == NULL) {
perror("fopen log file failed");
pthread_mutex_unlock(&log_mutex);
return;
}
char start_time_str[20];
strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%d %H:%M:%S", localtime(&start_time));
double duration = difftime(end_time, start_time);
fprintf(log_file, "SRC: %s | Time: %s | Duration: %.0fs | File: %s | Bytes: %zu | Closed by: %s\n",
client_ip, start_time_str, duration, filename ? filename : "N/A", bytes_transferred,
connection_closed_by_server ? "Server" : "Client");
fclose(log_file);
pthread_mutex_unlock(&log_mutex);
}
void 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);
s[maxlen - 1] = '\0'; // Ensure null-termination
}
}