Skip to content

Commit e0c972f

Browse files
committed
sequential proxy initial commit
1 parent 1a1f262 commit e0c972f

File tree

7 files changed

+401
-8
lines changed

7 files changed

+401
-8
lines changed

proxylab-handout/Makefile

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,28 @@ LDFLAGS = -lpthread
1111

1212
all: proxy
1313

14-
csapp.o: csapp.c csapp.h
15-
$(CC) $(CFLAGS) -c csapp.c
1614

17-
proxy.o: proxy.c csapp.h
18-
$(CC) $(CFLAGS) -c proxy.c
15+
%.o: %.c
16+
$(CC) $(CFLAGS) -c $<
1917

20-
proxy: proxy.o csapp.o
18+
H_FILES = util.h dstring.h csapp.h
19+
20+
OBJ_SRC = csapp.c dstring.c util.c
21+
22+
PROXY_SRC = $(OBJ_SRC) proxy.c
23+
24+
PROXY_OBJ = $(PROXY_SRC:%c=%o)
25+
26+
27+
proxy: $(PROXY_OBJ) $(H_FILES)
28+
$(CC) $(LDFLAGS) $(PROXY_OBJ) -o $@
29+
30+
TEST_SRC = $(OBJ_SRC) test.c
31+
32+
TEST_OBJ = $(TEST_SRC:%c=%o)
33+
34+
test: $(TEST_OBJ) $(H_FILES)
35+
$(CC) $(LDFLAGS) $(TEST_OBJ) -o $@
2136

2237
# Creates a tarball in ../proxylab-handin.tar that you should then
2338
# hand in to Autolab. DO NOT MODIFY THIS!
@@ -26,4 +41,3 @@ handin:
2641

2742
clean:
2843
rm -f *~ *.o proxy core *.tar *.zip *.gzip *.bzip *.gz
29-

proxylab-handout/dstring.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "dstring.h"
2+
#include <math.h>
3+
#include <string.h>
4+
5+
#define DEFAULT_LENGTH 1024
6+
7+
void string_malloc(string *pstr)
8+
{
9+
pstr->size = DEFAULT_LENGTH;
10+
pstr->cstr = (char *)malloc(pstr->size * sizeof(char));
11+
pstr->len = 0;
12+
pstr->cstr[0] = '\0';
13+
}
14+
15+
void string_free(string *pstr)
16+
{
17+
pstr->len = 0;
18+
pstr->size = 0;
19+
free(pstr->cstr);
20+
}
21+
22+
/* ceil_divide: a divide by b, return ceil value
23+
* Assert a > b.
24+
*/
25+
inline static size_t ceil_divide(size_t a, size_t b)
26+
{
27+
return (size_t)(ceil((float)a / (float) b));
28+
}
29+
30+
/* string_append : append cstr to the end of pstr.
31+
* Assert cstr and pstr is not overlapped.
32+
*
33+
* TODO: support overlapping
34+
*/
35+
void string_append(string *pstr, const char *cstr)
36+
{
37+
size_t cstr_len = strlen(cstr);
38+
if (pstr->len + cstr_len + 1 <= pstr->size) {
39+
strcpy(&pstr->cstr[pstr->len], cstr);
40+
pstr->len += cstr_len;
41+
} else {
42+
size_t multiplier = ceil_divide((cstr_len + pstr->len + 1) , pstr->size);
43+
size_t new_size = multiplier * pstr->size;
44+
char *new_str = (char *)malloc(new_size*sizeof(char));
45+
strcpy(new_str, pstr->cstr);
46+
strcpy(&new_str[pstr->len], cstr);
47+
pstr->cstr = new_str;
48+
pstr->len = pstr->len + cstr_len + 1;
49+
pstr->size = new_size;
50+
}
51+
}

proxylab-handout/dstring.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef __DSTRING_H__
2+
#define __DSTRING_H__
3+
4+
#include <stdlib.h>
5+
6+
typedef struct string {
7+
char *cstr;
8+
size_t size; /* content size */
9+
size_t len; /* string length */
10+
} string;
11+
12+
#define string_length(str) ((str).len)
13+
#define string_cstr(str) ((str).cstr)
14+
#define string_size(str) ((str).size)
15+
#define string_ref(str, i) (string_cstr(str)[(i)])
16+
17+
void string_malloc(string *pstr);
18+
19+
void string_free(string *pstr);
20+
21+
void string_append(string *pstr, const char *cstr);
22+
23+
#endif

proxylab-handout/proxy.c

Lines changed: 147 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,162 @@
11
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include "csapp.h"
4+
#include "dstring.h"
5+
#include "util.h"
6+
7+
// #define DEBUG
8+
#undef DEBUG
29

310
/* Recommended max cache and object sizes */
411
#define MAX_CACHE_SIZE 1049000
512
#define MAX_OBJECT_SIZE 102400
613

14+
715
/* You won't lose style points for including these long lines in your code */
816
static const char *user_agent_hdr = "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.3) Gecko/20120305 Firefox/10.0.3\r\n";
917
static const char *accept_hdr = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
1018
static const char *accept_encoding_hdr = "Accept-Encoding: gzip, deflate\r\n";
1119

12-
int main()
20+
21+
void usage()
22+
{
23+
// TODO
24+
exit(-1);
25+
}
26+
27+
28+
void read_response(int infd)
29+
{
30+
rio_t rio;
31+
Rio_readinitb(&rio, infd);
32+
33+
char buf[MAXLINE];
34+
35+
while (Rio_readlineb(&rio, buf, MAXLINE)) {
36+
// TODO: empty return
37+
38+
printf("%s", buf);
39+
}
40+
}
41+
42+
void forward_response(int infd, int outfd)
43+
{
44+
rio_t rio;
45+
Rio_readinitb(&rio, infd);
46+
47+
char buf[MAXLINE];
48+
struct string response;
49+
string_malloc(&response);
50+
51+
while (Rio_readlineb(&rio, buf, MAXLINE)) {
52+
string_append(&response, buf);
53+
Rio_readlineb(&rio, buf, MAXLINE);
54+
}
55+
#ifdef DEBUG
56+
fprintf(stderr, "response:\n%s", string_cstr(response));
57+
#endif
58+
59+
Rio_writen(outfd,
60+
string_cstr(response),
61+
string_length(response));
62+
63+
string_free(&response);
64+
}
65+
66+
void forward(int fromfd)
67+
{
68+
rio_t rio;
69+
Rio_readinitb(&rio, fromfd);
70+
char linebuf[MAXLINE], method[MAXLINE], uri[MAXLINE],
71+
version[MAXLINE], host[MAXLINE],
72+
port[MAXLINE], dir[MAXLINE],
73+
request_buf[MAXBUF],
74+
header_name[MAXLINE],
75+
header_value[MAXLINE];
76+
77+
if (!Rio_readlineb(&rio, linebuf, MAXLINE)) {
78+
return;
79+
}
80+
sscanf(linebuf, "%s %s %s", method, uri, version);
81+
if (strcasecmp(method, "GET")) {
82+
// TODO
83+
return;
84+
}
85+
parse_uri(uri, host, port, dir);
86+
#ifdef DEBUG
87+
fprintf(stderr, "host: %s port: %s dir: %s\n", host, port, dir);
88+
#endif
89+
90+
sprintf(request_buf, "%s %s %s\r\n", method, dir, version);
91+
int clientfd = Open_clientfd(
92+
host, port);
93+
94+
int has_host = 0;
95+
// request headers
96+
Rio_readlineb(&rio, linebuf, MAXLINE);
97+
while (strcmp(linebuf, "\r\n")) {
98+
parse_header(linebuf, header_name, header_value);
99+
// printf("header %s : %s\n", header_name, header_value);
100+
if (strcasecmp(header_name, "Host") == 0) {
101+
has_host = 1;
102+
sprintf(request_buf, "%s%s", request_buf, linebuf);
103+
} else if (strcasecmp(header_name, "User-Agent") == 0 ||
104+
strcasecmp(header_name, "Accept") == 0 ||
105+
strcasecmp(header_name, "Accept-Encoding") == 0 ||
106+
strcasecmp(header_name, "Connection") == 0 ||
107+
strcasecmp(header_name, "Proxy-Connection") == 0) {
108+
// ignore
109+
} else {
110+
sprintf(request_buf, "%s%s", request_buf, linebuf);
111+
}
112+
Rio_readlineb(&rio, linebuf, MAXLINE);
113+
}
114+
if (!has_host) {
115+
sprintf(request_buf, "%s%s: %s:%s\r\n", request_buf, "Host",
116+
host, port);
117+
}
118+
sprintf(request_buf, "%s%s", request_buf,
119+
user_agent_hdr);
120+
sprintf(request_buf, "%s%s", request_buf,
121+
accept_hdr);
122+
sprintf(request_buf, "%s%s", request_buf,
123+
accept_encoding_hdr);
124+
sprintf(request_buf, "%s%s:close\r\n", request_buf,
125+
"Connection");
126+
sprintf(request_buf, "%s%s:close\r\n", request_buf,
127+
"Proxy-Connection");
128+
sprintf(request_buf, "%s\r\n", request_buf);
129+
#ifdef DEBUG
130+
fprintf(stderr, "request buf:\n%s\n", request_buf);
131+
#endif
132+
Rio_writen(clientfd, request_buf, strlen(request_buf));
133+
134+
// receive data
135+
// read_response(clientfd);
136+
137+
forward_response(clientfd, fromfd);
138+
}
139+
140+
141+
142+
int main(int argc, char **argv)
13143
{
14-
printf("%s%s%s", user_agent_hdr, accept_hdr, accept_encoding_hdr);
144+
// printf("%s%s%s", user_agent_hdr, accept_hdr, accept_encoding_hdr);
15145

146+
if (argc != 2) {
147+
usage();
148+
}
149+
int listenfd = Open_listenfd(argv[1]);
150+
struct sockaddr_storage clientaddr;
151+
socklen_t clientlen = sizeof(clientaddr);
152+
while (1) {
153+
int connfd = Accept(listenfd,
154+
(SA *)&clientaddr,
155+
&clientlen);
156+
if (connfd == -1) {
157+
// TODO: error report
158+
}
159+
forward(connfd);
160+
}
16161
return 0;
17162
}

proxylab-handout/test.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "util.h"
2+
#include "dstring.h"
3+
#include "csapp.h"
4+
5+
#include <stdio.h>
6+
#include <string.h>
7+
8+
#define CHECK_STREQUAL(s1, s2) if (strcmp((s1), (s2))) { \
9+
fprintf(stderr, "[CHECK_STREQUAL] %s != %s\n", s1, s2); \
10+
}
11+
12+
#define CHECK_EQUAL(a, b) if ((a) == (b)) {\
13+
fprintf(stderr, "[CHECK_EQUAL] failed"); \
14+
}
15+
16+
void test_dstring1()
17+
{
18+
string str;
19+
string_malloc(&str);
20+
string_append(&str, "abc");
21+
CHECK_EQUAL(string_length(str), 3);
22+
string_free(&str);
23+
}
24+
25+
void test_dstring2()
26+
{
27+
string str;
28+
string_malloc(&str);
29+
for (int i = 0; i < 1024; i++) {
30+
string_append(&str, "a");
31+
}
32+
string_append(&str, "b");
33+
CHECK_EQUAL(string_length(str), 1025);
34+
CHECK_EQUAL(string_size(str), 2048);
35+
CHECK_EQUAL(string_ref(str, string_length(str)),
36+
'\0');
37+
for (int i = 0; i < 1024; i++) {
38+
CHECK_EQUAL(string_ref(str, i), 'a');
39+
}
40+
CHECK_EQUAL(string_ref(str, string_length(str)-1), 'b');
41+
string_free(&str);
42+
}
43+
44+
void test_parse_uri()
45+
{
46+
char host[MAXLINE];
47+
char port[MAXLINE];
48+
char dir[MAXLINE];
49+
parse_uri("http://www.cmu.edu/hub/index.html",
50+
host,
51+
port,
52+
dir
53+
);
54+
CHECK_STREQUAL(host, "www.cmu.edu");
55+
CHECK_STREQUAL(port, "80");
56+
CHECK_STREQUAL(dir, "/hub/index.html");
57+
parse_uri("www.cmu.edu:8000/hub/index.html", host, port, dir);
58+
CHECK_STREQUAL(host, "www.cmu.edu");
59+
CHECK_STREQUAL(port, "8000");
60+
CHECK_STREQUAL(dir, "/hub/index.html");
61+
}
62+
63+
int main()
64+
{
65+
test_parse_uri();
66+
test_dstring1();
67+
test_dstring2();
68+
return 0;
69+
}

0 commit comments

Comments
 (0)