#include "csapp.h"
#define DEFAULT_PORT "55556"
#define MAXPORT 6 /* port <= 65535, five digits */
#define VERBOSE_MSG(format, ...) \
if (verbose) {\
printf("proxy: " format "\n", ##__VA_ARGS__);\
}
int verbose = 1;
/* Recommended max cache and object sizes */
#define MAX_CACHE_SIZE 1049000
#define MAX_OBJECT_SIZE 102400
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.3) Gecko/20120305 \
Firefox/10.0.3\r\n";
int get_request_from_client(int listenfd, char *request, SA *clientaddr);
int request_and_reply(int connfd, char *request);
int parse_request(char *request, char *hostname, char *newrequest, char *port);
int main(int argc, char *argv[])
{
struct sockaddr_storage clientaddr;
char *port, request[MAXLINE];
int listenfd;
listenfd = Open_listenfd(port = (argc > 1? argv[1] : DEFAULT_PORT));
printf("proxy: proxy server listening on port %s\n", port);
for (;;) {
int connfd;
connfd = get_request_from_client(listenfd, request, (SA *)&clientaddr);
request_and_reply(connfd, request);
Close(connfd);
VERBOSE_MSG("clientfd%d closed, wait for next connection", connfd);
}
Close(listenfd);
return 0;
}
int get_request_from_client(int sockfd, char *request, SA *clientaddr)
{
socklen_t clientlen;
rio_t rp;
int connfd;
clientlen = sizeof(struct sockaddr_storage);
connfd = Accept(sockfd, clientaddr, &clientlen);
Rio_readinitb(&rp, connfd);
Rio_readlineb(&rp, request, MAXLINE);
VERBOSE_MSG("clientfd%d> %s", connfd, request);
return connfd;
}
/*
* request_and_reply - Establish connection to server and request.
* Get reply, and then echo it to client(connfd)
*/
int request_and_reply(int connfd, char *request)
{
int clientfd;
char hostname[MAXLINE], newrequest[MAX_OBJECT_SIZE], port[MAXPORT];
char buf[MAX_OBJECT_SIZE];
rio_t rp;
if (parse_request(request, hostname, newrequest, port) < 0) {
fprintf(stderr, "proxy: parse_request err\n");
exit(-1);
}
VERBOSE_MSG("request_to_server: \nhostname, %s\nport, %s\nnewrequest, %s",
hostname, port, newrequest);
clientfd = Open_clientfd(hostname, port);
VERBOSE_MSG("request_to_server: %s:%s connected on fd%d",
hostname, port, clientfd);
Rio_writen(clientfd, newrequest, strlen(newrequest));
VERBOSE_MSG("request_to_server: %s;fd%d< %s",
hostname, clientfd, newrequest);
Rio_readinitb(&rp, clientfd);
while (Rio_readlineb(&rp, buf, MAX_OBJECT_SIZE) != 0) {
Rio_writen(connfd, buf, strlen(buf));
}
Close(clientfd);
VERBOSE_MSG("fd%d closed", clientfd);
return 0;
}
int parse_request(char *request, char *hostname, char *newrequest, char *port)
{
char method[MAXLINE], uri[MAXLINE], version[MAXLINE];
sscanf(request, "%s %s %s", method, uri, version);
/* parse hostname from uri */
char *p = strstr(uri, "//");
p = p == NULL? uri : p + 2;
int c, i;
for (i = 0;
(c = *p) != '/' && c != '\0' && c != ':' && i < MAXLINE;
p++, i++) {
hostname[i] = c;
}
if (c != '/' && c != ':') {
fprintf(stderr, "proxy: out of range on hostname\n");
return -1;
}
hostname[i] = '\0';
/* make newrequest */
char file[MAXLINE];
if (c == '/') {
for (i = 0; (c = *p) != '\0' && c != ':' && i < MAXLINE; p++, i++)
file[i] = c;
if (i >= MAXLINE) {
fprintf(stderr, "proxy: out of range on file\n");
return -1;
}
file[i] = '\0';
} else { /* c == ':' */
file[0] = '/';
file[1] = '\0';
}
/* Get port if it is provided, if not, set it to default(80) */
if (c == ':')
strncpy(port, p + 1, MAXPORT);
else
strcpy(port, "80");
if (snprintf(newrequest, MAXLINE,
"%s %s %s\r\n"
"Host: %s\r\n"
"%s"
"\r\n",
method, file, "HTTP/1.0", hostname, user_agent_hdr) < 0) {
fprintf(stderr, "proxy: out of range on newrequest\n");
return -1;
}
return 0;
}
하루종일걸리넹......
댓글 0