Sunday, 27 April 2014

Proxy Program with Cache

Cache generated only after a particular site is accessed by atleast 5 different users.



#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<netdb.h>
#include<errno.h>
#include<fstream>
using namespace std;

FILE *fp,*lp;

struct cachecount
{
 char request[100];
 int usersocks[20];
 int usernum;
 }tempcache;

int main(int argc , char* argv[])
{

 fp = fopen("cache.txt","w");
 char newhostname[100] = {0};
 char newpathname[100] = {0};
 int j = 0;
 int m ;
 pid_t pid;
 struct sockaddr_in address_in , server_addr , client_addr;
 struct hostent* host;
 int sockfd , newsockfd , status;

 if(argc<2)
 {
 printf("Enter Port Number\n");
 exit(0);
 }

 printf("Port Accepted \n");

 bzero((char *)&server_addr , sizeof(server_addr));
 bzero((char *)&client_addr , sizeof(client_addr));

 server_addr.sin_family = AF_INET;
 server_addr.sin_port = htons(atoi(argv[1]));
 server_addr.sin_addr.s_addr = INADDR_ANY;

 printf("Intializing Socket....\n");

 sockfd = socket (AF_INET , SOCK_STREAM , IPPROTO_TCP);
 if(sockfd < 0)
 {
 printf("Intialization Failed...\n");
 exit(0);
 }

 printf("Intialization Successful....\n");

 status = bind(sockfd, (struct sockaddr*)&server_addr , sizeof(server_addr));

 if(status < 0)
 {
 printf("Error on Binding...");
 exit(0);
 }

 listen(sockfd , 60);

 printf("Listening.....\n");

 socklen_t clilength = sizeof(client_addr);

 accepting:

 newsockfd = accept(sockfd , (struct sockaddr*)&client_addr , &clilength);

 if(newsockfd < 0)
 {
 printf("Cannot Accept Connection....\n");
 exit(0);
 }

 printf("Forking......\n");

 pid = fork();

 if(pid == 0)
 {
 struct sockaddr_in hostaddr;
 int flag = 0 , forksock, newforksock , n , port = 0 , i , j ;

 char buffer[10000] , part1[400], part2[400], part3[10];

 char hostname[100] , pathname[100];

 char* temp = NULL;

 bzero((char *)buffer,10000);

 recv(newsockfd , buffer , 10000 , 0);

 sscanf(buffer,"%s %s %s",part1,part2,part3);

 // Check if the request is in right format or else terminate it.


 if(strncmp(part1,"GET",3) == 0)
 {
 if(strncmp(part2,"http://",7) == 0)
 {
 if((strncmp(part3,"HTTP/1.1",8) == 0) || (strncmp(part3,"HTTP/1.0",8) == 0))
 {

 for( i = 0 , j = 7 ; j < strlen(part2) ; i++ , j++)  // Gets our hostname
 {
 if(part2[j] == '/')
 break;
 hostname[i] = part2[j];
 }
 hostname[i] = '\0';

 host = gethostbyname(hostname);  

 for( i = 0 , j ; part2[j] != ' ' ; i++ ,j++)     // Gets our pathname
 {
 pathname[i] = part2[j] ;
 }

 port = 80 ; // default

 printf("Details Of Accepted HTTP Request\n");
 printf("Hostname : %s\n",hostname);
 printf("Pathname : %s \n",pathname);
 printf("Port : 80 \n");

 bzero((char *)&hostaddr , sizeof(hostaddr));

 hostaddr.sin_port = htons(port);
 hostaddr.sin_family = AF_INET ;

 bcopy((char*)host->h_addr,(char*)&hostaddr.sin_addr.s_addr,host->h_length);

 forksock = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);

 newforksock = connect(forksock , (struct sockaddr*)&hostaddr , sizeof(struct sockaddr));
 if(newforksock < 0)
 {
 printf("Cannot Connect...Exiting\n");
 exit(0);
 }

 sprintf(buffer ,"Connected to %s IP - %s \n",part2,inet_ntoa(hostaddr.sin_addr));

 printf("\n%s\n",buffer);

 bzero((char *)buffer , sizeof(buffer));


 if(!(strlen(pathname) > 1))
 sprintf(buffer,"GET / %s \r\nHost: %s\r\nConnection : close\r\n\r\n",part3,hostname);
 else
 sprintf(buffer,"GET %s %s\r\nHost: %s\r\nConnection : close\r\n\r\n",pathname,part3,hostname);


 n = send(forksock , buffer , strlen(buffer), 0);

 printf("\n%s\n",buffer);


 for(m = 0 ; m<strlen(pathname) ; m++)
 {
 if(pathname[m] == '/')
 {
 newpathname[m] = '-';
 }
 else
 newpathname[m] = pathname[m];
 }





 strcpy(newhostname,hostname);
 strcat(newhostname,newpathname);
 strcat(newhostname,".txt");
 int newflag = -1,y;
 ifstream opened("cache.ca",ios::binary);
  opened.clear();
  for(int x=0;!opened.eof();x++)
 {
  opened.read((char*)&tempcache,sizeof(tempcache));
  if(strcmp(newhostname,tempcache.request)==0)
  { //new flag values ---> 1 = cache this time; 2 = cache exists; 3 = No cache but has entry ... -1 = no cache, no entry
   if(tempcache.usernum == 4)
   {
    for(y=0;y<tempcache.usernum;y++)
    {
     if(newsockfd == tempcache.usersocks[y])
     {
      break;
      }
     }
    if(y == 4)
    {
     newflag = 1;
     }
   
    }
   else if (tempcache.usernum >= 5)
   {
    newflag = 2;
    }
   else
   {
    newflag = 3;
    }
    break;
   }
 }
 opened.close();
 if(newflag == -1)
 {
  fstream saved("cache.ca",ios::in|ios::out|ios::binary|ios::app);
  strcpy(tempcache.request,newhostname);
  tempcache.usernum = 1;
  tempcache.usersocks[tempcache.usernum - 1] = newsockfd;
 
  saved.write((char*)&tempcache,sizeof(tempcache));
  saved.close();
  }
 else
 {
   fstream saved1("cache.ca",ios::in|ios::out|ios::binary);
   saved1.clear();
 
    for(int z=0;!saved1.eof();z++)
    {
     saved1.read((char*)&tempcache,sizeof(tempcache));
     if(strcmp(tempcache.request,newhostname)==0)
     {
      break;
      }
     }
  int r = saved1.tellg();
   saved1.seekg(r - sizeof(tempcache));
 
   int h;
   for(h=0;h<tempcache.usernum;h++)
   {
    if(newsockfd == tempcache.usersocks[h])
    {
     break;
    }
    }
  if(h == tempcache.usernum)
  {
   tempcache.usersocks[h] = newsockfd;
   tempcache.usernum++;
   }
 
   saved1.write((char*)&tempcache,sizeof(tempcache));
   saved1.close();
  }

 fp = fopen(newhostname,"r");
 if(fp == NULL || newflag == -1 || newflag == 1 || newflag == 3)
 {
 printf("Cache Doesn't Exists...Using Internet");
 }
 else
 {
 printf("Cache Found...");
 bzero((char *)buffer,sizeof(buffer));
 while(fgets(buffer,10000,fp))
 {
 send(newsockfd , buffer , strlen(buffer) , 0);
 }
 goto cache;
 }

 if(n < 0)
 {
 printf("Error\n");
 exit(0);
 }


 // creating text file as cache with hostname's name
 if(newflag == 1)
 {
  fp = fopen(newhostname,"w");

  printf("textfile made"); }

 do
 {
 bzero((char *)buffer , 500);
 n = recv(forksock , buffer , 500, 0);
 if(n < 0)
 {
 printf("Error\n");
 exit(0);
 }
 else
 {
 if (newflag == 1)
 { fprintf(fp,buffer); }

 send(newsockfd,buffer,strlen(buffer),0);
 }
 }while(n>0);
 }
 }
 }
 else
 {
 send(newsockfd , "400 : BAD REQUEST",18,0);
 }

 close(newsockfd);
 }
 else
 goto accepting;

 cache:

 fclose(fp);
 close(sockfd);
 return 0;
}

No comments:

Post a Comment