Skip to content

Commit 0b4a375

Browse files
committed
add some comments
1 parent 48dc9de commit 0b4a375

File tree

6 files changed

+163
-32
lines changed

6 files changed

+163
-32
lines changed

proxylab-handout/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ handin:
4040
(make clean; cd ..; tar cvf proxylab-handin.tar proxylab-handout --exclude tiny --exclude nop-server.py --exclude proxy --exclude driver.sh --exclude port-for-user.pl --exclude free-port.sh --exclude ".*")
4141

4242
clean:
43-
rm -f *~ *.o proxy core *.tar *.zip *.gzip *.bzip *.gz
43+
rm -f *~ *.o proxy core *.tar *.zip *.gzip *.bzip *.gz test

proxylab-handout/cache.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
/*
2+
* cache.c - lru cache
3+
*/
4+
15
#include "cache.h"
26

7+
/* return the cache size of the node */
38
#define node_cache_size(pnode) (((pnode)->value_len)*sizeof(char))
49

10+
/* create_empty_node */
511
static lru_cache_node_t *create_empty_node()
612
{
7-
lru_cache_node_t *pnode = (lru_cache_node_t*)Malloc(sizeof(lru_cache_node_t));
13+
lru_cache_node_t *pnode = (lru_cache_node_t*)malloc(
14+
sizeof(lru_cache_node_t));
15+
if (pnode == NULL) return NULL;
816
pnode->value_len = 0;
917
pnode->key[0] = '\0';
1018
pnode->value = NULL;
@@ -13,11 +21,14 @@ static lru_cache_node_t *create_empty_node()
1321
return pnode;
1422
}
1523

24+
/* free_node */
1625
static void free_node(lru_cache_node_t *pnode)
1726
{
1827
free(pnode->value);
1928
free(pnode);
2029
}
30+
31+
/* create_node_from -- create a node from (key, value) pair */
2132
static lru_cache_node_t *create_node_from(
2233
const char *key,
2334
const char *value,
@@ -34,6 +45,7 @@ static lru_cache_node_t *create_node_from(
3445
return pnode;
3546
}
3647

48+
/* lru_cache_init -- init lru cache */
3749
void lru_cache_init(lru_cache_t *pcache, size_t max_cache_size)
3850
{
3951
pcache->max_cache_size = max_cache_size;
@@ -42,6 +54,7 @@ void lru_cache_init(lru_cache_t *pcache, size_t max_cache_size)
4254
pcache->sentinel->prev = pcache->sentinel;
4355
}
4456

57+
/* lru_cache_free -- free the lru cache */
4558
void lru_cache_free(lru_cache_t *pcache)
4659
{
4760
lru_cache_node_t *cur, *next = NULL;
@@ -55,6 +68,7 @@ void lru_cache_free(lru_cache_t *pcache)
5568
}
5669

5770

71+
/* lru_cache_insert_next -- insert a node to the list */
5872
static inline void lru_cache_insert_next(lru_cache_t *pcache,
5973
lru_cache_node_t *prev,
6074
lru_cache_node_t *pnode)
@@ -67,6 +81,7 @@ static inline void lru_cache_insert_next(lru_cache_t *pcache,
6781
pcache->cache_size += node_cache_size(pnode);
6882
}
6983

84+
/* lru_cache_remove -- remove the node from the list */
7085
static inline void lru_cache_remove(lru_cache_t *pcache,
7186
lru_cache_node_t *cur)
7287
{
@@ -76,6 +91,8 @@ static inline void lru_cache_remove(lru_cache_t *pcache,
7691
}
7792

7893
/*
94+
* lru_cache_raise -- raise the position of the node as the most
95+
* recently visited node
7996
* assert prev->next != NULL
8097
*/
8198
static void lru_cache_raise(lru_cache_t *pcache, lru_cache_node_t *cur)
@@ -85,19 +102,22 @@ static void lru_cache_raise(lru_cache_t *pcache, lru_cache_node_t *cur)
85102
lru_cache_insert_next(pcache, pcache->sentinel, cur);
86103
}
87104

105+
/* lru_cache_find -- find a node according to the key */
88106
lru_cache_node_t *lru_cache_find(lru_cache_t *pcache, const char *key)
89107
{
90108
lru_cache_node_t *cur;
91109
for (cur = pcache->sentinel->next;
92110
cur != pcache->sentinel; cur = cur->next) {
93111
if (strcasecmp(cur->key, key) == 0) {
112+
/* If a node is found, it's visited once */
94113
lru_cache_raise(pcache, cur);
95114
return cur;
96115
}
97116
}
98117
return NULL;
99118
}
100119

120+
/* lru_cache_insert -- insert a new node to the lru cache */
101121
void lru_cache_insert(lru_cache_t *pcache,
102122
const char *key,
103123
const char *value,
@@ -106,6 +126,10 @@ void lru_cache_insert(lru_cache_t *pcache,
106126
lru_cache_node_t *pnode = create_node_from(key, value, value_len);
107127
lru_cache_insert_next(pcache, pcache->sentinel, pnode);
108128
while (pcache->cache_size > pcache->max_cache_size) {
109-
lru_cache_remove(pcache, lru_cache_tail(pcache));
129+
/* remove the least recently used node */
130+
lru_cache_node_t *node_to_remove = lru_cache_tail(pcache);
131+
lru_cache_remove(pcache, node_to_remove);
132+
/* free the removed node */
133+
free_node(node_to_remove);
110134
}
111135
}

proxylab-handout/cache.h

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
1+
/*
2+
* cache.h - lru cache
3+
*/
4+
15
#ifndef __CACHE_H__
26
#define __CACHE_H__
37

48
#include "csapp.h"
59

610
typedef struct lru_cache_node_t {
7-
char *value;
8-
size_t value_len;
11+
char *value; /* cache content. This is not a null terminated string */
12+
size_t value_len; /* size of the cache */
913
// for simplicity, assume key is a null terminated string
10-
char key[MAXLINE];
11-
struct lru_cache_node_t *next;
12-
struct lru_cache_node_t *prev;
14+
char key[MAXLINE]; /* key - value */
15+
struct lru_cache_node_t *next; /* next node */
16+
struct lru_cache_node_t *prev; /* prev node */
1317
} lru_cache_node_t;
1418

19+
/* lru cache is implemented as a bidirectional list */
1520
typedef struct lru_cache_t {
16-
size_t max_cache_size;
17-
lru_cache_node_t *sentinel;
21+
size_t max_cache_size; /* maximum size allowed for the cache.
22+
If this is exceeded,
23+
we simply evict the least recently used block */
24+
lru_cache_node_t *sentinel; /* sentinel node is a fake node */
1825
lru_cache_node_t *front; /* front points to most recently used */
1926
// lru_cache_node_t *tail; /* tail points to least recently used */
20-
size_t cache_size;
27+
size_t cache_size; /* the size of the cache */
2128
} lru_cache_t;
2229

30+
/* lru cache operations */
2331
void lru_cache_init(lru_cache_t *pcache, size_t max_cache_size);
2432
void lru_cache_free(lru_cache_t *pcache);
2533

2634
lru_cache_node_t *lru_cache_find(lru_cache_t *pcache, const char *key);
2735

28-
void lru_cache_insert(lru_cache_t *pcache, const char *key, const char *value, size_t value_len);
36+
void lru_cache_insert(lru_cache_t *pcache,
37+
const char *key, const char *value, size_t value_len);
2938

3039
#define lru_cache_tail(pcache) ((pcache)->sentinel->prev)
3140

proxylab-handout/proxy.c

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* proxy.c -- a simple http proxy supporting GET operation
3+
*/
4+
15
#include <stdio.h>
26
#include <stdlib.h>
37
#include <assert.h>
@@ -6,13 +10,17 @@
610
#include "bytes.h"
711
#include "cache.h"
812

9-
#define DEBUG
13+
// #define DEBUG
14+
#undef DEBUG
1015

1116
/* Recommended max cache and object sizes */
1217
#define MAX_CACHE_SIZE 1049000
1318
#define MAX_OBJECT_SIZE 102400
1419

20+
/* global lru cache */
1521
lru_cache_t lru_cache;
22+
23+
/* mutex to protect the lru cache update operations */
1624
sem_t mutex;
1725

1826

@@ -22,60 +30,98 @@ static const char *accept_hdr = "Accept: text/html,application/xhtml+xml,applica
2230
static const char *accept_encoding_hdr = "Accept-Encoding: gzip, deflate\r\n";
2331

2432

33+
/* usage */
2534
void usage()
2635
{
27-
// TODO
36+
printf("Usage: proxy [port]\n");
2837
exit(-1);
2938
}
3039

3140

3241

42+
/* forward_response -- forward the response back to the client
43+
* key: the formatted url of the content. Used for lru_cache
44+
* infd: the file descriptor of remote server. We read response from infd
45+
* outfd: the client file descriptor. We write response back to outfd
46+
*/
3347
void forward_response(const char *key, int infd, int outfd)
3448
{
3549
rio_t rio;
3650
rio_readinitb(&rio, infd);
3751

52+
/* Since we don't know the length of the response, we extend
53+
* the response buffer dynamically.
54+
* First, we read MAXLINE number of bytes into the buffer.
55+
* Then we append the buffer to the response buffer.
56+
*/
57+
58+
/* temporary buffer */
3859
char buf[MAXLINE];
60+
61+
/* response buffer */
3962
struct Bytes response;
63+
64+
/* allocate and initialize the response buffer */
4065
bytes_malloc(&response);
4166

67+
/* num_bytes is the number of bytes read for each rio_readnb operation */
4268
int num_bytes;
4369
while ((num_bytes=rio_readnb_ww(&rio, buf, MAXLINE)) > 0) {
4470
bytes_appendn(&response, buf, num_bytes);
4571
}
72+
73+
/* The remote connection may be closed during the read operation.
74+
* The return value is < 0.
75+
*/
4676
if (num_bytes < 0) {
47-
return ;
77+
/* goto is used here to make sure that response is freed
78+
*/
79+
goto FORWARD_RESPONSE_RETURN;
4880
}
4981

5082
#ifdef DEBUG
5183
fprintf(stderr, "response length: %zu\n", bytes_length(response));
5284
#endif
5385

86+
/* the client may have closed the connection */
5487
if (!rio_writen_ww(outfd,
5588
bytes_buf(response),
5689
bytes_length(response))) {
5790
goto FORWARD_RESPONSE_RETURN;
5891
}
5992

93+
/* cache the response if necessary */
6094
if (bytes_length(response) < MAX_OBJECT_SIZE) {
6195
sem_wait(&mutex);
6296
lru_cache_insert(&lru_cache, key, bytes_buf(response),
6397
bytes_length(response));
6498
sem_post(&mutex);
6599
}
66100
FORWARD_RESPONSE_RETURN:
101+
/* free the response */
67102
bytes_free(&response);
68103
}
69104

105+
/* forward -- forward the request to remote server and the response from
106+
* remote server
107+
*/
70108
void forward(int fromfd)
71109
{
72110
rio_t rio;
73111
rio_readinitb(&rio, fromfd);
74-
char linebuf[MAXLINE], method[MAXLINE], uri[MAXLINE],
75-
version[MAXLINE], host[MAXLINE],
76-
port[MAXLINE], dir[MAXLINE],
77-
request_buf[MAXBUF],
78-
header_name[MAXLINE],
112+
char linebuf[MAXLINE], // temporary buffer for each line we read
113+
method[MAXLINE], // http method
114+
uri[MAXLINE], // uri
115+
version[MAXLINE], // http version.
116+
host[MAXLINE],
117+
port[MAXLINE],
118+
dir[MAXLINE], // the director after the host in the uri
119+
/* TODO: is it necessary to use a dynamic buffer to store
120+
* the request?
121+
* For all the cases tested now, seems it's not necessary
122+
*/
123+
request_buf[MAXBUF], // The request is stored in the buffer
124+
header_name[MAXLINE], // used for parsing the header
79125
header_value[MAXLINE];
80126

81127
if (!rio_readlineb_ww(&rio, linebuf, MAXLINE)) {
@@ -95,7 +141,13 @@ void forward(int fromfd)
95141

96142
char formated_uri[MAXLINE];
97143
sprintf(formated_uri, "%s:%s%s", host, port, dir);
144+
145+
/*
146+
* if we find the content in the cache, we return it directly.
147+
* TODO: What if the content has been modifed?
148+
*/
98149
sem_wait(&mutex);
150+
99151
lru_cache_node_t *pnode = lru_cache_find(&lru_cache, formated_uri);
100152

101153
if (pnode) {
@@ -109,10 +161,11 @@ void forward(int fromfd)
109161
* forwarded as HTTP/1.0
110162
*/
111163
sprintf(request_buf, "%s %s %s\r\n", method, dir, "HTTP/1.0");
112-
// sprintf(request_buf, "%s %s %s\r\n", method, dir, version);
113164

165+
/* if the header contains host, we forward it directly.
166+
* Otherwise we fill the host according to the uri
167+
*/
114168
int has_host = 0;
115-
// request headers
116169
if (rio_readlineb_ww(&rio, linebuf, MAXLINE) < 0) {
117170
return;
118171
}
@@ -126,18 +179,22 @@ void forward(int fromfd)
126179
strcasecmp(header_name, "Accept-Encoding") == 0 ||
127180
strcasecmp(header_name, "Connection") == 0 ||
128181
strcasecmp(header_name, "Proxy-Connection") == 0) {
129-
// ignore
182+
// we have default values for these headers
130183
} else {
184+
// for other headers, we forward it directly
131185
sprintf(request_buf, "%s%s", request_buf, linebuf);
132186
}
133187
if (rio_readlineb_ww(&rio, linebuf, MAXLINE) < 0) {
134188
return;
135189
}
136190
}
137191
if (!has_host) {
192+
/* add host according to uri parsing result */
138193
sprintf(request_buf, "%s%s: %s:%s\r\n", request_buf, "Host",
139194
host, port);
140195
}
196+
197+
/* add default value for these headers */
141198
sprintf(request_buf, "%s%s", request_buf,
142199
user_agent_hdr);
143200
sprintf(request_buf, "%s%s", request_buf,
@@ -161,13 +218,12 @@ void forward(int fromfd)
161218
return;
162219
}
163220

164-
// receive data
165-
// read_response(clientfd);
166-
221+
/* forward the response of the server to the client */
167222
forward_response(formated_uri, clientfd, fromfd);
168223
close_ww(clientfd);
169224
}
170225

226+
/* thread -- the things to do for each thread */
171227
void *thread(void *vargp)
172228
{
173229
int connfd = *((int*)vargp);
@@ -179,12 +235,18 @@ void *thread(void *vargp)
179235
}
180236

181237

238+
/* sigpipe_handler -- handle sig pipe
239+
* SIGPIPE is generated when the connection is closed by another end early.
240+
* */
182241
void sigpipe_handler(int sig)
183242
{
243+
#ifdef DEBUG
184244
fprintf(stderr, "[WARNING] Catch a sigpipe signal\n");
245+
#endif
185246
}
186247

187248

249+
/* main */
188250
int main(int argc, char **argv)
189251
{
190252
if (argc != 2) {

0 commit comments

Comments
 (0)