-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmp_webserver.c
132 lines (102 loc) · 3.05 KB
/
mp_webserver.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
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h> //addrinfo structure
#include <errno.h> //errno
#include <string.h> //memset()
#include <unistd.h> //close()
#include <signal.h>
#define PORT "http"
#define BACKLOG 100 //queue length
#define BUFFERSIZE 11000
//reaper function
void sigchld_handler(int s) {
int saved_errno = errno; //errno may be overwriten by waitpid()
while (waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
int main(void) {
int s, status, new_s, http_response_len, recv_len;
char ipstr[INET_ADDRSTRLEN];
struct addrinfo hints, *res, *p;
struct sockaddr_in client_addr;
socklen_t addrlen;
struct sigaction sa;
char response_buffer[BUFFERSIZE], recv_buffer[BUFFERSIZE];
printf("CMPE 207 HW2 mpwebsvr Hanbing Leng 354\n");
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (status = getaddrinfo(NULL, PORT, &hints, &res) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
for (p = res; p != NULL; p = p->ai_next) {
if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("socket");
continue;
}
if (bind(s, p->ai_addr, p->ai_addrlen) == -1) {
close(s);
perror("bind");
continue;
}
break;
}
freeaddrinfo(res);
if (p == NULL) {
fprintf(stderr, "failed to bind");
return 1;
}
if (listen(s, BACKLOG) == -1) {
perror("listen");
return 1;
}
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask); //initializes signalmask to empty
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
printf("waiting for connections...\n");
while (1) {
addrlen = sizeof client_addr;
new_s = accept(s, (struct sockaddr*)&client_addr, &addrlen);
if (new_s == -1) {
if (errno = EINTR)
continue;
perror("accept");
continue;
}
inet_ntop(AF_INET, &client_addr, ipstr, INET_ADDRSTRLEN);
printf("connection from %s\n", ipstr);
if (!fork()) { //child process
close(s);
int server_pid = (int)getpid();
struct sockaddr_in peeraddr;
socklen_t peeraddr_len;
peeraddr_len = sizeof peeraddr;
char peerip[INET_ADDRSTRLEN];
int peerport;
getpeername(new_s, (struct sockaddr*)&peeraddr, &peeraddr_len);
inet_ntop(AF_INET, &peeraddr.sin_addr, peerip, INET_ADDRSTRLEN); // peeraddr.sin_addr
peerport = ntohs(peeraddr.sin_port);
printf("server-pid=%d, client-ip=%s, client-port=%d\n", server_pid, peerip, peerport);
if ((recv_len = recv(new_s, recv_buffer, BUFFERSIZE, 0)) < 0) {
perror("recv");
return 1;
}
//no recursive read needed?
http_response_len = sprintf(response_buffer, "HTTP/1.1 200 OK\r\nClientID: %s\nClientPort: %d\n\r\n<!DOCTYPE html>\n<html><body><blockquote>\n%s\n</blockquote></body></html>\n", peerip, peerport, recv_buffer);
if (send(new_s, response_buffer, http_response_len, 0) == -1)
perror("send");
sleep(30);
close(new_s);
return 0;
}
close(new_s);
}
return 0;
}