/*
 *  Simple Demo single site proxy
 *  For Networking
 *  By James Skon, Mount Vernon Nazarene University
 *  Fall 2011
 */

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

#include <stdlib.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>

/* definitions for thread functions */
void *server_to_browser (void *args);
void *browser_to_server (void *args);

#define BROWSER_PORT 9000/* arbitrary */
#define QUEUE_SIZE 10
#define BUFSIZE 10240
#define HTTP  "http://" 

/* These socket variables are globel so both threads can access them */
int server_sock, browser_sock;  /* The sockets! */

void fatal(string mess)
{
  cout << mess << endl;
  exit(1);
}

void displayFirstLine(char *buffer)
{
  int len = strlen(buffer);
  for(int i=0; i<len; i++) {
    cout << buffer[i];
    if (buffer[i] == '\n') break;
  }
}



/* Analyze string, finding protocol, address, and port */
/* This version only works for HTTP, port 80 */
/* Need HTTPS, FTP, etc. */
/* Pass in str, the "GET" string, returns address of get, and port (80) */
int GetAddressAndPort( char *str, char *address, int *port)
{
  char buf[BUFSIZE];
  char command[512], proto[128], *p;
  int j, i;
  /* Given "GET http://www.mvnu.edu/ HTTP1.1" */
  /* returns command = "GET"                  */
  /*         buf = "http://www.mvnu.edu/"     */
  /*         proto = "HTTP1.1"                */
  sscanf(str,"%s%s%s",command,buf,proto);
  
  /* See if the address starts with "http://" */
  p=strstr(buf,HTTP);
  //HTTP
  if(p)   // if p not NULL, then it points to th the "h" in "http"
    {
      p+=strlen(HTTP);    // Go past the protocol to the address
      // search for "/" at end of address
      for(i=0;i<strlen(p);i++)
	if( *(p+i)=='/') break;
      // End string at "/"
      *(p+i)=0;
      // get address
      strcpy(address,p);
      p=strstr(str,HTTP);
      for(int j=0;j<i+strlen(HTTP);j++)
	*(p+j)=' ';  //to remove the host name: 
                     //GET http://www.njust.edu.cn/ HTTP1.1  ==> GET / HTTP1.1
      
      *port=80;      //default http port for now
    }
}


/* Read dat from browser, pass on to web server */
void *browser_to_server (void *a) {
  char buf[BUFSIZE];/* buffer for outgoing file */
  int bytes, p;
  char address[512];

  /* Pass everything from the browser on to the server */
  while (1) {

    bytes = recv(browser_sock, buf, BUFSIZE,0);/* read buffer from browser */
    
    GetAddressAndPort(buf, address, &p);
    cout << endl << "Brow: " << bytes << endl;
    cout.flush();
    if (bytes <= 0) {/* check for error (-1) or closed connection (0) */
      int bs = close(browser_sock); /* Close other connection */
      int ss = close(server_sock); /* Close this connection */
      cout << "#CloseBrow:" << bs << ":" << ss << endl;
      break;
    }
    send(server_sock, buf, bytes,0); /* write bytes to server */
    cout << "B:";
    displayFirstLine(buf);	
    //cout.write(buf,bytes);
	
  }
}

/* Read data from web server, pass on the browser */
void *server_to_browser (void *a) {
  char buf[BUFSIZE];/* buffer for outgoing file */
  int bytes;

  /* Pass everything from the server on to the client */
  while (1) {

    bytes = recv(server_sock, buf, BUFSIZE,0);/* read buffer from server */

    cout << " Serv: " << bytes;
    cout.flush();
    
    if (bytes <= 0) {/* check for error (-1) or closed connection (0) */
      int bs = close(browser_sock); /* Close other connection */
      int ss = close(server_sock); /* Close this connection */
      cout << "#CloseServ:" << bs << ":" << ss << endl;
      break;
    }
    
    send(browser_sock, buf, bytes, 0); /* write bytes to browser */
    cout << " S :";
    displayFirstLine(buf);	
  }
}

int main(int argc, char *argv[])
{
  pthread_t from_browser, to_browser;  /* Thread structures for the two threads */
  int on = 1, status, bytes;
  int browser_listen_sock;
  struct sockaddr_in browser_channel;  /* holds Browser's IP address */
  struct hostent *server_ip;           /* info about the web server */
  struct sockaddr_in server_channel;  /* holds web Server's IP address */
  char web_server[50];
  int web_server_port;
  char buf[BUFSIZE];/* buffer for outgoing file */

  /* Build address structure to bind to socket for browser connection. */
  memset(&browser_channel, 0, sizeof(browser_channel));/* zero channel */
  browser_channel.sin_family = AF_INET;
  browser_channel.sin_addr.s_addr = htonl(INADDR_ANY);
  browser_channel.sin_port = htons(BROWSER_PORT);

  /* Passive open. Wait for connection from browser. */
  browser_listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /* create socket */
  if (browser_listen_sock < 0) fatal("browser socket failed");
  setsockopt(browser_listen_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));

  status = bind(browser_listen_sock, (struct sockaddr *) &browser_channel, sizeof(browser_channel));
  if (status < 0) fatal("browser bind failed");

  // Wait for connection from a browser
  while (1) {
	status = listen(browser_listen_sock, QUEUE_SIZE);/* specify queue size */
	if (status < 0) fatal("browser listen failed");

	/* Socket is now set up and bound. Wait for connection and process it. */
	browser_sock = accept(browser_listen_sock, 0, 0);/* block for connection request */
	if (browser_sock < 0) fatal("accept from browser failed");

	/* read buffer from browser, search for server address */
	bytes = recv(browser_sock, buf, BUFSIZE,0);
	cout << "B1 :";
	displayFirstLine(buf);	
	GetAddressAndPort(buf, web_server, &web_server_port);
	cout << "B2 :";
	displayFirstLine(buf);	

	/* Get reference for web server */
	server_ip = gethostbyname(web_server);  /* look up host's IP address */
	if (!server_ip) 
	  cout << "web server gethostbyname failed for: " << web_server << endl;
	else {
	  cout << "Open server: " << web_server << ":" << web_server_port << endl;

	  /* Open up connection to web server */
	  server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	  if (server_sock < 0) fatal("socket to server");
	  memset(&server_channel, 0, sizeof(server_channel));
	  server_channel.sin_family= AF_INET;
	  memcpy(&server_channel.sin_addr.s_addr, server_ip->h_addr, server_ip->h_length);
	  server_channel.sin_port= htons(web_server_port);
	  status = connect(server_sock, (struct sockaddr *) &server_channel, sizeof(server_channel));
	  if (status < 0) fatal("web server connect failed");

	  /* Send first message on to server */
	  send(server_sock, buf, bytes,0); /* write bytes to server */

	  /* Start up two threads, one for each direction */
	  cout << "starting new threads" << endl; cout.flush();
	  pthread_create (&from_browser, NULL, browser_to_server, NULL);	
	  pthread_create (&to_browser, NULL, server_to_browser, NULL);	
	  pthread_join (from_browser, NULL);	
	  pthread_join (to_browser, NULL);
	  
	  cout << "Connections Closed!" << endl;
	}
  }
}
Topic revision: r1 - 2013-11-05 - JimSkon
 
This site is powered by the TWiki collaboration platformCopyright &© by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback