Hello everybody

A long time ago I started a project called RicBot http://cboard.cprogramming.com/showthread.php?t=75223

Which I just left and didn't bother with anymore, I decided I would go back to it again though. So today I added a little piece of code which will know it has timedout if it didn't send or receive any data within 150 seconds.

There is something I want to do to it, but I'm not sure how, so I'm looking for suggestions. As it is, it receives the data and then loops through the main body of code. This is not a very good method. The data should be parsed into strings. So that each string is a single line of data. Like a little parsing function which seperates strings if they have '\r', '\n' or a combination of both.

So that once it has parsed the string, into several strings it loops through the main body, does what it needs with the string, then loops again with the next string. Also if the data doesn't end with a '\r', '\n' or combination of both, it will save that piece of data until the next time it receives data through the socket, and will add the new data received from the socket to the end of the current string. Then parse that string.

It doesn't have to split it into seperate strings I guess, there is no point in having an array of them I guess. Probably just the main string which receives the data, then that goes into another string to store it. It parses it for lines, puts the first line into the main string which will go through the code, and then stores the rest until it comes back again, then it puts the next string into the main string and loops through the code etc.


I am not sure how to do this, here is the code I got so far.

Code:
/* This is RicBot, written by John */

#pragma warning(disable: 4786)
#include <winsock2.h>
#pragma comment(lib,"WS2_32.lib")
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
/////////////////////////////
//This isn't multithreaded yet, so the code below isn't
//needed but I have added it from an older program I made 
//to save me time ;)
//#include <process.h>
//Using MSVC++
//For Win32 Release
//Project -> Settings -> C/C++ -> Code Generation
//Use-Runtime Library -> Multithreaded
//#pragma comment(lib, "libcmt.lib")
//For Win32 Debug
//Project -> Settings -> C/C++ -> Code Generation
//Use-Runtime Library -> Debug Multithreaded
//#pragma comment(lib, "libcmtd.lib")
///////////////////////////////
SOCKET IRC_socket; //Global

using namespace std;

//#define RicBot
#define AUTHENTICATION

//Function Prototypes
int CreateSock();
int ConnectIRCSock(int Port, string IP);
int SendIRC_func(string SendData_string);
int RecvIRC_func(string &RecvData_string);
int OnConnect(string BotNick, string IP);
int ReConnect(int Port, string IP, string BotNick);
int CheckForTimeout(int Port, string IP, string BotNick);
int CheckForPing(string RecvData_string);
int Get_Nick_Ident_Host(string RecvData_string);
int JoinChannel(string Channel);
int MessageChannel(string Message, string Channel);
string RandomNick(string BotNick);

struct IdentNickHostInfo {
	string Nick;
	string Ident;
	string Host;
} AuthInfo;

int PingTime = 0, TimeElapsed = 0;

#ifdef RicBot
#pragma comment(linker,"/subsystem:windows")
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow){
#endif
#ifndef RicBot
#pragma comment(linker,"/subsystem:console")
int main(int argc, char* argv[]){
#endif

	string SendData_string, RecvData_string;
	int Port = 6667;
	string IP  = "";
	string BotNick = "";
	string Channel = "";
	//Nick/Ident/Host for Auth
	string AuthNick = "";
	string AuthIdent = "";
	string AuthHost = "";
	string CMDprefix = "!";
	//our commands
	string VersionCMD = "version";
	string Version = "RicBot";
	string ReconnectCMD = "reconnect";
	string KillCMD = "stop";
	string RawCMD = "raw";



	CreateSock();
	ConnectIRCSock(Port, IP);
	OnConnect(BotNick, IP);	
	PingTime = GetTickCount()/1000;

	while(1){
			
		CheckForTimeout(Port, IP, BotNick);

		if(RecvIRC_func(RecvData_string) == -1){
			Sleep(10000);
			ReConnect(Port, IP, BotNick);
		}

#ifndef RicBot
		cout<<RecvData_string;
#endif
		CheckForPing(RecvData_string);
		

		if(RecvData_string[0] == ':'){
			
			//--------------------------
			string strData = "";
			vector<string> SplitData;
			
			int i=0;
			while(RecvData_string[i] != '\r'){
				if(RecvData_string[i] == ' '){
					if(RecvData_string[i+1] != '\r'){
						SplitData.push_back(strData);
						strData = "";
						i++;
					}
				}
				strData = strData + RecvData_string[i];
				i++;
			}
			SplitData.push_back(strData);
			//--------------------------
			
			//here our server commands go.
			if(SplitData.size() >= 2){
				//We can join a channel now.
				if(SplitData[1] == "001"){
					JoinChannel(Channel);
				}
				//nick is in use, so change it.
				if(SplitData[1] == "433"){
					//(BotNick=RandomNick(BotNick));
					OnConnect(BotNick=RandomNick(BotNick), IP);
				}

			}
			if(SplitData.size() >= 4){
				if(SplitData[1] == "KICK" && SplitData[3] == BotNick){
					Sleep(3000);
					JoinChannel(Channel);
				}
			}

			//gets the nick/ident/host of user sending message. 
			if(Get_Nick_Ident_Host(RecvData_string) == 0){
				
				//here are our user commands
				if(SplitData.size() >= 4){
					
					//this line will remove the :
					SplitData[3] = SplitData[3].substr(1);
					//will check if our first character is our prefix
					if(SplitData[3][0] == CMDprefix[0]){
						
						//this will remove our prefix.
						SplitData[3] = SplitData[3].substr(1);
						
						//--------------------------
						//commands without Auth go here
						// if they have no arguments
						if(SplitData.size() >= 4){
							
							if(SplitData[3] == VersionCMD){
								MessageChannel(Version, Channel);
							}
						}
						
						//Here is our authentication check.
#ifdef AUTHENTICATION
						if(AuthInfo.Nick == AuthNick){
							if(AuthInfo.Ident == AuthIdent){
								if(AuthInfo.Host == AuthHost){
#endif
									//commands with Auth go here
									
									//-----------------------
									//if command has 0 arguments
									if(SplitData.size() == 4){

										if(SplitData[3] == ReconnectCMD){
											string QUIT = "QUIT Reconnecting...\r";
											SendIRC_func(QUIT);
											ReConnect(Port, IP, BotNick);
										}
										if(SplitData[3] == KillCMD){
											exit(0);
										}
									}
									
									//--------------------------
									//if command has 1 argument or more
									if(SplitData.size() >= 5){
										
										if(SplitData[3] == RawCMD){
											int sizerawmessage = (int)SplitData.size() - 4;
											ostringstream rawmessage;
											for(int i = 0; i < sizerawmessage; i++){
												rawmessage<<SplitData[i+4]<<" ";
											}
											rawmessage<<"\r";
											SendIRC_func(rawmessage.str());
										}
									}
								}
							}
						}
					}
#ifdef AUTHENTICATION	
				}
			}
		}
#endif

		RecvData_string = '\0';
	}

	
	return 0;
}

////////////////////////////////////////
int CreateSock(){

	WSADATA wsaData;
	
	int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
	if ( iResult != NO_ERROR )
		return -1;
	
	return 0;
}

////////////////////////////////////////
int ConnectIRCSock(int Port, string host){

	IRC_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	
	if (IRC_socket == INVALID_SOCKET){
		WSACleanup();
		return -2;
	}

	sockaddr_in remotehost;

	remotehost.sin_family = AF_INET;
	remotehost.sin_addr.s_addr = inet_addr(host.c_str());
	remotehost.sin_port = htons(Port);

	if (connect(IRC_socket, (SOCKADDR*) &remotehost, sizeof(remotehost) ) == SOCKET_ERROR){
		closesocket(IRC_socket);
		WSACleanup();
		return -1;
	}

	return 0;
}

////////////////////////////////////////
int SendIRC_func(string SendData_string){
	
	if (send(IRC_socket, SendData_string.c_str(), (int)SendData_string.size(), 0 ) <= 0){
		WSACleanup();
		return -1;
	}

	PingTime = GetTickCount()/1000;
	return 0;

}

////////////////////////////////////////
int RecvIRC_func(string &RecvData_string){
	
	char TempBuffer[1025]; //extra char for null terminating character
	int BytesRecv;
	if ((BytesRecv = recv(IRC_socket, TempBuffer, 1024, 0 )) <= 0){
		WSACleanup();
		return -1;
	}

	TempBuffer[BytesRecv] = '\0';
	RecvData_string = TempBuffer;
	PingTime = GetTickCount()/1000;

	return 0;

}

////////////////////////////////////////
int OnConnect(string BotNick, string IP){

	ostringstream tempstr;
	tempstr <<"Nick "<<BotNick<<'\n';
	SendIRC_func(tempstr.str());
	tempstr.str("");
	tempstr<<"USER "<<BotNick<<" \"\" \""<< IP <<
		"\" :"<<BotNick<<'\n';
	SendIRC_func(tempstr.str());
	
	return 0;
}

////////////////////////////////////////
int ReConnect(int Port, string IP, string BotNick){
		
	closesocket(IRC_socket);

	CreateSock();
	ConnectIRCSock(Port, IP);
	OnConnect(BotNick, IP);
	
	return 0;
}

////////////////////////////////////////
int CheckForTimeout(int Port, string IP, string BotNick){

	if(TimeElapsed < PingTime+150){
		TimeElapsed = GetTickCount()/1000;
		return -1;
	}
	
	Sleep(10000);
	ReConnect(Port, IP, BotNick);
	PingTime = GetTickCount()/1000;
	return 0;
}

////////////////////////////////////////
int CheckForPing(string RecvData_string){
	
	string ServerPing;
	ostringstream SendPong;
	int i = 0;
	
	//////////////////////////////////////////////////////
	/*if(RecvData_string[i] == 'P' && RecvData_string[i+1] == 'I' &&
		RecvData_string[i+2] == 'N' && RecvData_string[i+3] == 'G' ){
		i += 5;
		while(RecvData_string[i] != '\r'){
			ServerPing = ServerPing + RecvData_string[i];
			i++;
		}
		ServerPing = ServerPing + '\0';
		SendPong << "PONG " << ServerPing << '\n';
		SendIRC_func(SendPong.str());
		return -1;
	}*/
	if(RecvData_string[i] == 'P' && RecvData_string[i+1] == 'I' &&
		RecvData_string[i+2] == 'N' && RecvData_string[i+3] == 'G' ){

		RecvData_string[1] = 'O';
		SendIRC_func(RecvData_string);
	}


	//////////////////////////////////////////////////////
	while(i < (int)RecvData_string.size()){
		
		if(RecvData_string[i] == '\r' && RecvData_string[i+1] == '\n' &&
			RecvData_string[i+2] == 'P' && RecvData_string[i+3] == 'I' &&
			RecvData_string[i+4] == 'N' && RecvData_string[i+5] == 'G'){

			i += 7;
			while(RecvData_string[i] != '\r'){
				ServerPing = ServerPing + RecvData_string[i];
				i++;
			}
			ServerPing = ServerPing + '\0';
			SendPong << "PONG " << ServerPing << '\n';
			SendIRC_func(SendPong.str());
			return -2;
		}
		i++;
	}
	//////////////////////////////////////////////////////

	return 0;
}

////////////////////////////////////////
int Get_Nick_Ident_Host(string RecvData_string){
	
	int i = 1;
	AuthInfo.Nick = "";
	AuthInfo.Ident = "";
	AuthInfo.Host = "";
	////////////////////////////////////////////
	while(RecvData_string[i] != '!'){
		
		AuthInfo.Nick = AuthInfo.Nick + RecvData_string[i];
		i++;
		if(i == RecvData_string.size()){
			return -1;
		}
	}
	////////////////////////////////////////////
	i++;
	while(RecvData_string[i] != '@'){
		
		AuthInfo.Ident = AuthInfo.Ident + RecvData_string[i];
		i++;
		if(i == RecvData_string.size()){
			return -2;
		}
	}
	////////////////////////////////////////////
	i++;
	while(RecvData_string[i] != ' '){
		
		AuthInfo.Host = AuthInfo.Host + RecvData_string[i];
		i++;
		if(i == RecvData_string.size()){
			return -3;
		}
	}

	//cout<<"Nick is "<<AuthInfo.Nick<<endl;
	//cout<<"Ident is "<<AuthInfo.Ident<<endl;
	//cout<<"Host is "<<AuthInfo.Host<<endl;
	return 0;
}

////////////////////////////////////////
int JoinChannel(string Channel){

	ostringstream joinchan;
	joinchan << "JOIN " << Channel << "\r";
	SendIRC_func(joinchan.str());

	return 0;
}

////////////////////////////////////////
int MessageChannel(string Message, string Channel){

	ostringstream ChannelMessage;
	ChannelMessage << "PRIVMSG "<<Channel<< " :" <<Message<<"\r";
	SendIRC_func(ChannelMessage.str());
	return 0;
}

////////////////////////////////////////
string RandomNick(string BotNick){
	
	srand((unsigned)GetTickCount());
	int randomNum = rand()%10000;
	ostringstream Nick;
	Nick << BotNick << randomNum;

	return Nick.str();
}
(I didn't upload the code in a .cpp file because it doesn't keep the line breaks the way they are.)