-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.c
188 lines (150 loc) · 6.17 KB
/
server.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/* Jose Wilfredo Aleman Espinoza
* Netid: ja918
*/
#include <stdio.h> /* perror(), fprintf(), sprintf() */
#include <stdlib.h> /* for atoi() */
#include <string.h> /* for memset() */
#include <sys/socket.h> /* socket(), bind(), listen(), accept(), recv(), send(), htonl(), htons() */
#include <sys/types.h>
#include <sys/stat.h> /* for open() */
#include <fcntl.h> /* for open() */
#include <netinet/in.h> // for struct sockaddr_in
#include <arpa/inet.h> /* for sockaddr_in */
#include <unistd.h> /* for close() */
#include <time.h> /* for time */
#include <ctype.h> /* for isspace */
#define MAXPENDING 5 /* Max outstanding connection requests */
#define RCVBUFSIZE 256 /* Size of receive buffer */
#define ERR_EXIT(msg) { perror(msg); exit(1); }
// Note: This function returns a pointer to a substring of the original string.
// If the given string was allocated dynamically, the caller must not overwrite
// that pointer with the returned value, since the original pointer must be
// deallocated using the same allocator with which it was allocated. The return
// value must NOT be deallocated using free() etc.
char *trimwhitespace(char *str)
{
char *end;
// Trim leading space
while(isspace((unsigned char)*str)) str++;
if(*str == 0) // All spaces?
return str;
// Trim trailing space
end = str + strlen(str) - 1;
while(end > str && isspace((unsigned char)*end)) end--;
// Write new null terminator
*(end+1) = 0;
return str;
}
int main(int argc, char *argv[]) {
int rv_sock, s_sock, port_num, msg_len;
char addr[10] = "127.0.0.1"; // IP Address
port_num = 5100; // Port number
char buffer[RCVBUFSIZE];
struct sockaddr_in serv_addr;
time_t ticks;
rv_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (rv_sock < 0) ERR_EXIT("ERROR opening socket");
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(addr);
serv_addr.sin_port = htons(port_num);
if (bind(rv_sock,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
ERR_EXIT("ERROR on binding");
exit(1);
}
if (listen(rv_sock, MAXPENDING) < 0){
ERR_EXIT("ERROR on listen");
exit(1);
}
ticks = time(NULL);
fprintf(stdout, "----- Network Server ----- \n");
fprintf(stdout, " -%.24s\r\n",ctime(&ticks));
printf("Server <address:port> : %s:%d\n", addr,port_num);
while ( 1 ) { /* Server runs forever */
fprintf(stdout, "\nWaiting for client to connect...\n");
s_sock = accept(rv_sock, NULL, NULL);
if (s_sock < 0) {
ERR_EXIT("ERROR on accept new client");
}
memset(buffer, 0, RCVBUFSIZE);
msg_len = recv(s_sock, buffer, RCVBUFSIZE, 0);
if (msg_len < 0){
ERR_EXIT("ERROR reading from socket");
}
// the client will ask either for a file or to bounce or to exit
char *msgType = ".txt";
char *cmd31 = "exit";
char *cmd32 = "EXIT";
// open the file
int fd;
char *input = buffer;
char *response = "";
// so far just txt files
if(strstr(input, msgType) != NULL) { // User asks for a file
// open the file, trim the input to get the filename
fd = open(trimwhitespace(input), O_RDONLY, 0600);
fprintf(stdout, "Client requested file: %s\n", input);
if (fd < 0) {
response = "ERROR: no such file";
msg_len = send(s_sock, response, strlen(response), 0);
fprintf(stdout, "\n%s\n", response);
} else {
// Print the content of the file and send it to the client
ssize_t read_bytes = 0;
memset(buffer, 0, RCVBUFSIZE);
while ((read_bytes = read(fd, buffer,RCVBUFSIZE)) > 0){
msg_len = send(s_sock, buffer, RCVBUFSIZE, 0);
fprintf(stdout, "%s",buffer);
memset(buffer, 0, RCVBUFSIZE);
}
fprintf(stdout, "\n --- End of the file. -- \n");
close(s_sock);
continue;
}
}
// Plain EXIT/exit
if(strcmp(trimwhitespace(input),cmd31) == 0 || strcmp(trimwhitespace(input),cmd32) == 0) {
response = "Client disconected.";
msg_len = send(s_sock, response, strlen(response), 0);
fprintf(stdout, "\n%s\n", response);
close(s_sock);
continue;
}
// Exit with code
if(strstr(input, cmd31) != NULL || strstr(input, cmd32) != NULL) { // User asks for a file
const char separator = ' ';
char * const sep_at = strchr(input, separator);
if(sep_at != NULL){
*sep_at = '\0'; /* overwrite first separator, creating two strings. */
response = "Client disconected with code: ";
char *str = malloc(strlen(sep_at + 1) + strlen(response));
strcat(str, response);
strcat(str, sep_at + 1);
fprintf(stdout,"%s\n", str);
msg_len = send(s_sock, str, strlen(str), 0);
str = "";
}
close(s_sock);
continue;
}
// The user is sending wrong syntax msgs just ignore
if (strlen(buffer) == 0){
close(s_sock);
continue;
}
else {
// User sent a bounce
response = "BOUNCE! - Message: ";
char *str = malloc(strlen(buffer) + strlen(response));
strcat(str, response);
strcat(str, buffer);
msg_len = send(s_sock, str, strlen(str), 0);
fprintf(stdout, "\n%s\n",str);
memset(buffer, 0, RCVBUFSIZE);
str = "";
}
if (msg_len < 0) ERR_EXIT("ERROR writing to socket");
close(s_sock);
}
/* NOT REACHED, because the server runs forever */
}