A http proxy program I'm making randomly breaks.....
I've been making this proxy server program and it sometimes works to the point where if I set it as my proxy on firefox and load a page, I can see it for a second before it gives me a error, or more often, just doesn't load the page. It obviously gets requests from its connected clients and sends them off just fine, it's the part where it receives the webpage and sends it back to the clients piece by piece that I seem to be having trouble with.
So I was wondering if anyone could look over the bool rk(SOCKET sk,int snum) function in this code and tell me if I'm missing something blatantly obvious or not:
(300 lines with newly added comments)
Code:
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <sstream>//headers, duh
using namespace std;
#include <fstream>
#include <winsock2.h>
#include <windows.h>
//made with winsock as the libary
//as much as i like and use SDL I never got the networking to work right
string istr(int op)
{
stringstream bob; //int to string
bob<<op;
return bob.str();
}
BOOL InitConnection(SOCKET *wSock, char *SERV) //just makes it easier to understand code later on if i put this here
{
int port = 80;
struct hostent *host;
struct sockaddr_in sin;
int error;
host = gethostbyname(SERV);
memset( &sin, 0, sizeof sin );
sin.sin_family = AF_INET;
sin.sin_addr = *((in_addr *)host->h_addr);
sin.sin_port = htons(port);
error = connect((SOCKET)wSock, (sockaddr*)&sin, sizeof sin);
if(error != 0)
return false;
return true;
}
void easymsg(string text)
{
//cout<<text<<"\n";
}
bool *fours;
SOCKET *fc;
int error,kks;
char packe[512];
SOCKET ov;
int vnum = 1;
int maxclients;
int sendall(char *packets,int len)//a function to send a packet to all the clients at once
{
int sendouts = 0;
for(int seaa = 0; seaa<maxclients; seaa++)
{
if(fours[seaa])
{
sendouts++;
send(fc[seaa],packets,len,0);
}
}
return sendouts;
}
void ondis(int snum)//this function dictates what to do on a sudden disconect
{//snum is the number of the sockets pointer on the array of socket arrays
}
bool rk(SOCKET sk,int snum) //this function dictates what to do when it recives a packet
{ //sk is the sender's socket pointer and snum is the socket array value
int ooo = 0;
ooo = recv(sk,packe,sizeof(packe),0);
if(ooo > 0){
packe[ooo] = '\0';
string packstr = packe;
if(ooo < 1)
{
return true;
}
//yes, this program only supports GET for now, i'll add POST later
if(packstr.substr(0,3) == "GET")//if the packet sent is a valid HTTP GET request
{
int tid = packstr.find("Host:")+6;
string host = packstr.substr(tid,packstr.find("\n",tid)-tid-1); // the host header's value
string page = packstr.substr(11+host.length(),packstr.find("HTTP")-11-host.length()); //the page to get
//this program dosn't preserve any of the headers either
//only the Host header, and that's only because it's absolutly nessacary
cout<<"Get request recived:\nHost: "<<host<<"\nPage: "<<page<<"\n\n";
string von = host;
struct hostent *pHostEnt;
pHostEnt = gethostbyname(host.c_str()); //get the actual IP with a DNS inquery from the host value
struct sockaddr_in tmpSockAddr;
memcpy(&tmpSockAddr.sin_addr,pHostEnt->h_addr,pHostEnt->h_length);
char ip[17];
strcpy(ip,inet_ntoa(tmpSockAddr.sin_addr)); //a pointer to the actual IP
string response;
int resp_leng;
char buffer[2048]; //2048 bytes is the packet length for now, i experimented with a lot and just chose the value
struct sockaddr_in serveraddr;
int sock;// what's the difference between int sock; and SOCKET sock; anyway
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(ip);
serveraddr.sin_port = htons(80);
cout<<"Connecting.\n";
connect(sock, (struct sockaddr *) &serveraddr, sizeof(serveraddr));
string request = "";
request+="GET "+page+" HTTP/1.1\r\n"; //make the request from the host and page we clipped before
request+="Host: "+host+"\r\n";
request+="\r\n";
cout<<"Sending.\n";
send(sock, request.c_str(), request.length(), 0); //send off our request
response = "";
resp_leng= 2048;
cout<<"Reciving.\n";
int stime = time(NULL);
FD_SET Reader;
while ((resp_leng == 2048) && time(NULL) < stime+2) //while we're still receving at full length, with a timeout of 2 seconds per page
{
FD_ZERO(&Reader);
FD_SET(sock, &Reader);
select(0,&Reader,NULL,NULL,NULL);
if(FD_ISSET(sock,&Reader))//if it's got something the recive
{
resp_leng= recv(sock, (char*)&buffer, 2048, 0);
if (resp_leng>0)
{
response+= string(buffer).substr(0,resp_leng);//add it to our response string, which actaully isn't used in this version
cout<<" Getting. - "<<resp_leng<<" bytes.\n";
send(sk,(string(buffer).substr(0,resp_leng)).c_str(),resp_leng,0);//send it to the requesting client as soon as we get it
}
}
else
resp_leng = 0;
}
cout<<"Done.\n";
closesocket(sock);
closesocket(sk);//close both sockets, for it's a proxy, no stay-alive header here or anything
}
else
cout<<"\n\n Non GET request entered. \n\n"; //like i said, no other formats supported atm
return false;
}
return true;
}//end function
int ask()
{
int temp;
cin>>temp; //someday.....
return temp;
}
void pnt(string out)
{
//cout<<out<<"\n";
}
//the above functions are more important, i mod them
int PORT,password,psize,maxpax,portslist;
int main(int argc, char *argv[]) //begining of program, but nothing moddable or important here
{
PORT = 80;
psize = 2048;
maxclients = 10;
fours = new bool[maxclients-1];
fc = new SOCKET[maxclients-1];
for(int set00 = 0; set00<maxclients; set00++)
{
fours[set00] = false;
}
for(int nuler = 0; nuler<maxclients; nuler++)
{
fc[nuler] = 0;
}
WSAData wdat;
WSAStartup(MAKEWORD(2, 2),&wdat);
SOCKET server;
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN sinServer;
memset(&sinServer, 0, sizeof(sinServer));
sinServer.sin_family = AF_INET;
sinServer.sin_addr.s_addr = INADDR_ANY; // Where to start server?
sinServer.sin_port = htons(PORT); // Port
if(bind(server, (LPSOCKADDR)&sinServer, sizeof(sinServer)) == SOCKET_ERROR){ easymsg("Couldn't bind."); }
u_long iMode = 1;//non binding
if(listen(server,maxclients)){ easymsg("Listen failed."); }
ioctlsocket(server, FIONBIO, &iMode);
FD_SET Reader;
while (true){ //main server loop
FD_ZERO(&Reader);
FD_SET(server, &Reader);
for(int set1 = 0; set1<maxclients; set1++)
{
if(fours[set1]){ FD_SET(fc[set1], &Reader); }
}
if(error = select(0,&Reader,NULL,NULL,NULL))
{
//if(error == -1){ cout<<"Select error: "<<WSAGetLastError()<<"\n"; }
if(FD_ISSET(server,&Reader))
{
// cout<<"Server socket 'isset'\n";
bool somethingopen = false;
for(int set2 = 0; set2<maxclients; set2++)
{
if(!fours[set2])
{
somethingopen = true;
}
}
if(somethingopen){
SOCKET ATemp;
bool accepted = false;
if((ATemp = accept(server,NULL,NULL)) != INVALID_SOCKET){
ioctlsocket(ATemp,FIONBIO,&iMode);
for(int set3 = 0; set3<maxclients; set3++){
if((!fours[set3]) && !(accepted)){
fours[set3] = true;
fc[set3] = ATemp;
accepted = true;
}
}
if(!(accepted)){
ov = ATemp;
closesocket(ATemp);
closesocket(ov);
}
//cout<<"Accepted a client.\n";
kks+=1;
//cout<<kks<<" client connected.\n";
}
}
}
for(int set4 = 0; set4<maxclients; set4++)
{
if(fours[set4]){
if(FD_ISSET(fc[set4],&Reader)){
if(rk(fc[set4],set4)){
//cout<<"Closing socket 'array "+istr(set4)+" '. \n";
ondis(set4);
kks-=1;
//cout<<kks<<" clients connected.\n";
fours[set4] = false;
closesocket(fc[set4]);
char disca[256];
string discastr = "DIS"+istr(set4);
strcpy(disca,discastr.c_str());
for(int set8 = 0; set8<maxclients; set8++)
{
if(fours[set8])
{
}
}
}
}
}
}
}
}
closesocket(server);//quit
WSACleanup();
return 0;
}
//end