Virtual Host Proxy Server

Environment: VC++ 6, Windows 95/98/NT

From time to time, I pick-up ideas from codeguru.com so I thought that I should contribute as well.

The program I’m submitting today is aimed at solving a problem that sounds simple but appears to be next to impossible: running multiple Web servers on a single Windows 95/98 machine.
If you are running NT, you can assign multiple IP addresses to your networks card, edit the hosts file to translate domain names into IP addresses and assign multiple Websites to Internet Information Server…

It’s a bit tricky but feasible. If you’re running Windows 95 or 98, it’s virtually impossible so I had to find a way around that.

What I’ve done is write a very simple proxy server that translate server names into a sub folder of your local machine so your can host as many Websites as you want with one single HTTP server.

Let’s imagine your web root is C:\WebRoot\, you will put the files for http://www.a.com into C:\WebRoot\www.a.com\. The files for www.b.com will go in C:\WebRoot\www.b.com\ and so on.

What the proxy will actually do is replace http://www.a.com/index.htm by http://127.0.0.1/www.a.com/index.htm on the fly (127.0.0.1 is equivalent to localhost and is by definition the IP address of your local machine).

So to test the program, what you really need is a Web server, something as simple as Personal Web Server (PWS) from Microsoft and a browser (Netscape Navigator, Internet Explorer or anything else).

You have to create the directories for the virtual servers as mentioned above and you have to configure your browser to use a proxy.

Here is an example with Internet Explorer 5.0 from Microsoft (Tools>Internet Options>Connections>LAN Settings)

As you can see, by default the proxy is running on port 5060.

Something else you have to be aware of is that the proxy doesn’t support HTTP 1.1.
The way HTTP 1.1 handles connections is slightly more complicated than HTTP 1.0.
To keep the code as simple as possible, I decided to support HTTP 1.0 only. Anyway it’s the default behavior of the browser when you go through a proxy as you can see on the following screenshot of IE5.

The code is very basic and there are numerous ways to improve it but a) it solved my problem and b) it’s short and easy to read.
It also provides a very good example on how to use the CSocket classes which are very high level classes and not very well documented.

// VirtualHostProxy.cpp 
//
// Virtual Host Proxy Server
// (c) Franck JEANNIN 1999 – fjeannin@linkguard.com
//
// Simulate multiple Web servers on one single Windows 95/98 machine 
//
// Does not support HTTP 1.1 (HTTP 1.0 only)
// Use high level MFC socket classes: CSocket
//

#include “stdafx.h”
#include <afxsock.h> // MFC socket extensions
#include <conio.h>

#define BUFFERSIZE 10000

#define SERVERNAMEMAXSIZE 256
#define PROXYPORT 5060

#define SERVERADDRESS “127.0.0.1”
#define SERVERPORT 80

char Buffer[BUFFERSIZE+SERVERNAMEMAXSIZE];

int main(int argc, char* argv[])
{
CSocket Proxy;
CSocket Client;
CSocket Server;

// initialize MFC
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
printf(“Fatal Error: MFC initialization failed\nPress any key\n”);
getch();
return -1;
}

// initialize Socket support
if (!AfxSocketInit())
{
printf(“Fatal Error: Socket initialization failed\nPress any key\n”);
getch();
return -1;
}

// create Proxy socket
if (!Proxy.Create(PROXYPORT))
{
printf(“Fatal Error: Proxy socket creation failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}

if (!Proxy.Listen(1))
{
printf(“Fatal Error: Proxy socket activation failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}
else
{
printf(“Virtual Host Proxy Server started on port %d\n(c) Franck JEANNIN 1999\n\n”,PROXYPORT);
}

while(1)
{
if (!Proxy.Accept(Client))
{
printf(“Fatal Error: Client connection to Proxy failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}

int n = Client.Receive(Buffer,BUFFERSIZE);

if (n == -1)
{
printf(“Fatal Error: Client transmission to Proxy failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}

Buffer[n] = 0;
printf(“Received from client: %s\n”,Buffer);

// calls to http://www.a.com/mypage.htm are transformed to calls to http://127.0.0.1/www.a.com/mypage.htm
char* p = strstr(Buffer,”//”);

if (p)
{
p += 2;
memmove(p+sizeof(SERVERADDRESS),p,n);
memcpy(p,SERVERADDRESS,sizeof(SERVERADDRESS)-1);
*(p+sizeof(SERVERADDRESS)-1) = ‘/’;
n += sizeof(SERVERADDRESS);
}

if (!Server.Create())
{
printf(“Fatal Error: Server socket creation failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}

if (!Server.Connect(SERVERADDRESS,SERVERPORT))
{
printf(“Fatal Error: Server socket connection to HTTP server failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}

n = Server.Send(Buffer,n);

if (n == -1)
{
printf(“Fatal Error: Proxy transmission to Server failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}

Buffer[n] = 0;
printf(“Sent to server: %s\n”,Buffer);

while ( (n = Server.Receive(Buffer,BUFFERSIZE)) != 0)
{

if (n == -1)
{
printf(“Fatal Error: Server transmission to Proxy failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}

Buffer[n] = 0;
printf(“Received from server: %s\n”,Buffer);

n = Client.Send(Buffer,n);

if (n == -1)
{
printf(“Fatal Error: Proxy transmission to Server failed\nError %d\n\nPress any key\n”,GetLastError());
getch();
return -1;
}

Buffer[n] = 0;
printf(“Sent to Client: %s\n”,Buffer);

printf(“Closing Client & Server sockets\n”);
Client.Close();
Server.Close();
}

return 0;
}

Download demo project – 47KB

History

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read