Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 27 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ This project is implemented using `C` and Parsing of HTTP referred from <a href

## Index

- [Project Theory](https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient#project-theory)
- [How to Run](https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient#How-to-Run)
- [Demo](https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient#Demo)
- [Contributing](https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient#contributing)
- [Project Theory](https://github.com/uddiGitHub/MultiThreadedProxyServerClient#project-theory)
- [How to Run](https://github.com/uddiGitHub/MultiThreadedProxyServerClient#How-to-Run)
- [Demo](https://github.com/uddiGitHub/MultiThreadedProxyServerClient#Demo)
- [Contributors](https://github.com/uddiGitHub/MultiThreadedProxyServerClient#Contributors)
- [Contributing](https://github.com/uddiGitHub/MultiThreadedProxyServerClient#contributing)

## Project Theory

[[Back to top]](https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient#index)
[[Back to top]](https://github.com/uddiGitHub/MultiThreadedProxyServerClient#index)

##### Introduction

##### Basic Working Flow of the Proxy Server:
![](https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient/blob/main/pics/UML.JPG)
![](https://github.com/uddiGitHub/MultiThreadedProxyServerClient/blob/main/pics/UML.JPG)

##### How did we implement Multi-threading?
- Used Semaphore instead of Condition Variables and pthread_join() and pthread_exit() function.
Expand All @@ -43,13 +44,16 @@ This project is implemented using `C` and Parsing of HTTP referred from <a href
- Semaphore
- Cache (LRU algorithm is used in it)

##### Access Control (Firewall)
- We implemented a blocklist feature that restricts users from accessing specific websites.
- A `blocklist.txt` file is loaded into memory when the server starts. Any HTTP request for a domain listed in this file is intercepted, and the proxy directly responds with a `403 Forbidden` error page.

##### Limitations ​
- If a URL opens multiple clients itself, then our cache will store each client’s response as a separate element in the linked list. So, during retrieval from the cache, only a chunk of response will be send and the website will not open
- Fixed size of cache element, so big websites may not be stored in cache.

##### How this project can be extended? ​
- This code can be implemented using multiprocessing that can speed up the process with parallelism.
- We can decide which type of websites should be allowed by extending the code.
- We can implement requests like POST with this code.


Expand All @@ -60,26 +64,31 @@ This project is implemented using `C` and Parsing of HTTP referred from <a href
## How to Run

```bash
$ git clone https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient.git
$ git clone https://github.com/uddiGitHub/MultiThreadedProxyServerClient.git
$ cd MultiThreadedProxyServerClient
$ make all
$ ./proxy <port no.>
```
`Open http://localhost:port/https://www.cs.princeton.edu/`

# Note:
- This code can only be run in Linux Machine. Please disable your browser cache.
- To run the proxy without cache Change the name of the file (`proxy_server_with_cache.c to proxy_server_without_cache.c`) MakeFile.
**Note:**
- This code can only be run in Linux or MacOS Machine. Please disable your browser cache.
- To run the proxy without cache, change the name of the file in the Makefile (`proxy_server_with_cache.c` to `proxy_server_without_cache.c`).

## Demo
![](https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient/blob/main/pics/cache.png)
![](https://github.com/uddiGitHub/MultiThreadedProxyServerClient/blob/main/pics/cache.png)

- When website is opened for the first time (`url not found`) then cache will be miss.
- Then if you again open that website again then `Data is retrieved from the cache` will be printed.

## Contributing
## Contributors

| Contributor | GitHub | Contributions |
| :--- | :--- | :--- |
| **Lovepreet Singh** | [Lovepreet-Singh-LPSK](https://github.com/Lovepreet-Singh-LPSK) | Original proxy server implementation (multi-threading, LRU caching, HTTP parsing) |
| **Uddipta Deka** | [uddiGitHub](https://github.com/uddiGitHub) | Implemented Firewall / Access Control feature: `blocklist.txt` loading, hostname blocking via `is_blocked()` check, and `403 Forbidden` response before request forwarding. Applied to both `proxy_server_with_cache.c` and `proxy_server_without_cache.c`. |

[[Back to top]](https://github.com/Lovepreet-Singh-LPSK/MultiThreadedProxyServerClient#index)
## Contributing
[Back to top](#index)

Feel free to add some useful. You can see `How this code can be extended`. Use ideas from there and feel free to fork and CHANGE.
Feel free to add some useful. You can see `How this code can be extended`. Use ideas from there and feel free to fork and CHANGE.

#### Enjoy CODE and pull requests are highly appreciated.
#### Enjoy CODE and pull requests are highly appreciated.
3 changes: 3 additions & 0 deletions blocklist.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
www.cs.princeton.edu
blocked.com
www.google.com
Binary file added proxy
Binary file not shown.
Binary file added proxy.o
Binary file not shown.
Binary file added proxy_parse.o
Binary file not shown.
52 changes: 46 additions & 6 deletions proxy_server_with_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,40 @@ pthread_mutex_t lock; //lock is used for locking the cache
cache_element* head; //pointer to the cache
int cache_size; //cache_size denotes the current size of the cache

#define MAX_BLOCKED_HOSTS 100
char blocked_hosts[MAX_BLOCKED_HOSTS][256];
int num_blocked_hosts = 0;

void load_blocklist() {
FILE *file = fopen("blocklist.txt", "r");
if (file == NULL) {
printf("No blocklist.txt found or unable to open. No hosts will be blocked.\n");
return;
}

char line[256];
while (fgets(line, sizeof(line), file)) {
// Remove newline character
line[strcspn(line, "\r\n")] = 0;
if (strlen(line) > 0 && num_blocked_hosts < MAX_BLOCKED_HOSTS) {
strcpy(blocked_hosts[num_blocked_hosts], line);
num_blocked_hosts++;
}
}
fclose(file);
printf("Loaded %d blocked hosts from blocklist.txt\n", num_blocked_hosts);
}

int is_blocked(char* host) {
if (host == NULL) return 0;
for (int i = 0; i < num_blocked_hosts; i++) {
if (strcmp(host, blocked_hosts[i]) == 0) {
return 1;
}
}
return 0;
}

int sendErrorMessage(int socket, int status_code)
{
char str[1024];
Expand Down Expand Up @@ -136,7 +170,7 @@ int connectRemoteServer(char* host_addr, int port_num)
}


int handle_request(int clientSocket, ParsedRequest *request, char *tempReq)
int handle_request(int clientSocket, struct ParsedRequest *request, char *tempReq)
{
char *buf = (char*)malloc(sizeof(char)*MAX_BYTES);
strcpy(buf, "GET ");
Expand Down Expand Up @@ -302,7 +336,7 @@ void* thread_fn(void* socketNew)
{
len = strlen(buffer);
//Parsing the request
ParsedRequest* request = ParsedRequest_create();
struct ParsedRequest* request = ParsedRequest_create();

//ParsedRequest_parse returns 0 on success and -1 on failure.On success it stores parsed request in
// the request
Expand All @@ -318,10 +352,15 @@ void* thread_fn(void* socketNew)

if( request->host && request->path && (checkHTTPversion(request->version) == 1) )
{
bytes_send_client = handle_request(socket, request, tempReq); // Handle GET request
if(bytes_send_client == -1)
{
sendErrorMessage(socket, 500);
if (is_blocked(request->host)) {
printf("Blocked request to %s\n", request->host);
sendErrorMessage(socket, 403);
} else {
bytes_send_client = handle_request(socket, request, tempReq); // Handle GET request
if(bytes_send_client == -1)
{
sendErrorMessage(socket, 500);
}
}

}
Expand Down Expand Up @@ -381,6 +420,7 @@ int main(int argc, char * argv[]) {
}

printf("Setting Proxy Server Port : %d\n",port_number);
load_blocklist();

//creating the proxy socket
proxy_socketId = socket(AF_INET, SOCK_STREAM, 0);
Expand Down
47 changes: 42 additions & 5 deletions proxy_server_without_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,39 @@ cache_element* head; //pointer to the cache

int cache_size=0; //cache_size denotes the current size of the cache

#define MAX_BLOCKED_HOSTS 100
char blocked_hosts[MAX_BLOCKED_HOSTS][256];
int num_blocked_hosts = 0;

void load_blocklist() {
FILE *file = fopen("blocklist.txt", "r");
if (file == NULL) {
printf("No blocklist.txt found or unable to open. No hosts will be blocked.\n");
return;
}

char line[256];
while (fgets(line, sizeof(line), file)) {
// Remove newline character
line[strcspn(line, "\r\n")] = 0;
if (strlen(line) > 0 && num_blocked_hosts < MAX_BLOCKED_HOSTS) {
strcpy(blocked_hosts[num_blocked_hosts], line);
num_blocked_hosts++;
}
}
fclose(file);
printf("Loaded %d blocked hosts from blocklist.txt\n", num_blocked_hosts);
}

int is_blocked(char* host) {
if (host == NULL) return 0;
for (int i = 0; i < num_blocked_hosts; i++) {
if (strcmp(host, blocked_hosts[i]) == 0) {
return 1;
}
}
return 0;
}

int sendErrorMessage(int socket, int status_code)

Expand Down Expand Up @@ -613,15 +645,19 @@ void* thread_fn(void* socketNew)
if( request->host && request->path && (checkHTTPversion(request->version) == 1) )

{
if (is_blocked(request->host)) {
printf("Blocked request to %s\n", request->host);
sendErrorMessage(socket, 403);
} else {
bytes_send_client = handle_request(socket, request, buffer, tempReq); // Handle GET request

bytes_send_client = handle_request(socket, request, buffer, tempReq); // Handle GET request

if(bytes_send_client == -1)
if(bytes_send_client == -1)

{
{

sendErrorMessage(socket, 500);
sendErrorMessage(socket, 500);

}
}


Expand Down Expand Up @@ -735,6 +771,7 @@ int main(int argc, char * argv[]) {


printf("Setting Proxy Server Port : %d\n",port_number);
load_blocklist();



Expand Down