Skip to content

Bilingual Doughnuts Server – Telnet & Browser

February 22, 2016

This is the worst sort of brute force programming but it works.  Once I had the general non-blocking telnet server running I basically copied the http server code and changed all the names for telnet (e.g. bagelsinit became tBagelsInit) then hacked at it til it worked.

The basic framework of the server just cycles through the active ports.  If there’s a session it checks which port it’s on and calls either the web server or the telnet server.  The telnet server uses a ‘previous status’ to tell when it’s called the first time for a session and initializes the game and sets a sockMode variable for that socket to ‘G’ for guessing.  The main() program will keep calling it as long as the session is established(remember that the web server closes the session each time); the telnet server discards control characters and watches for a carriage return.  When it gets a cr, if it’s in guess mode, it takes a turn.  If not it will let you enter q for quit or t to display a table or a null line to restart the game.

16-02-22 telnet

Functionally it seems ok but the code structure is hacky with switches and things happening at different levels – not pretty!  It’s only a few dozen lines though so cleaning it up shouldn’t be a huge job(ok, twelve dozen but still..).

One funny thing is that it separates sessions and modes by socket but it records scores and secrets by ip address.  That means I can run multiple sessions from my laptop simultaneously and nothing bad happens to the program but, for example, if a new game starts via telnet, the secret that the browser was trying to guess is replaced.  The browser can keep guessing and eventually win but a user would probably be pretty confused.  I’m not sure there’s anything I can do about that.


void tBagelsInit(unsigned char sock){//initialize bagels game for telnet on socket N
	games++;
	pages++;
	sendConst(tInst1,sock); 	// Now Send the instructions
	sendConst(tInst2,sock); 	// Now Finish the instructions
	sendConst(tgprompt,sock); 	// Now Send the prompt
	thisip.l=getip(sock);
	thisipslot=getipslot(thisip.l);//finds or assigns a slot for the ip
	setsecret();
	strcpy((char*)secrets[thisipslot],(char*)secret);
	printf("Telnet IP: %d.%d.%d.%d,slot %d,secret %s\n",
		thisip.c[0],thisip.c[1],thisip.c[2],thisip.c[3],thisipslot,secrets[thisipslot]);
	sockMode[sock]='G';//Telnet guessing mode - expect a guess
}
void tCongratulate(unsigned char sock){
	char strbuf[8];
	ipgames[thisipslot]++;//increment win count
	sendConst("You have won ",sock);
		sendStr(itoa10(ipgames[thisipslot],strbuf),sock);
	sendConst(" games ",sock);
	if (ipgames[thisipslot]>maxipgames){//high scode
		maxipgames=ipgames[thisipslot];
		maxip.l=thisip.l;
		sendConst(" - A new high score!",sock);
	}else{
		sendConst("\n\rHigh score is ",sock); sendip(maxip.c,sock); sendConst(" with ",sock);
		sendStr(itoa10(maxipgames,strbuf),sock);
		sendConst(" wins\n\r",sock);
	}
}

void tSendResp(int pico, int fermi,unsigned char sock){
	unsigned int i;
	pages++;
	sendConst("  I say ",sock);
	if (fermi==3){
		sendConst("YOU GOT IT!\r\n",sock);
		tCongratulate(sock);
		sendConst("\n\rHit Enter to play again, or q to quit\n\r:",sock);
		sockMode[sock]='C';//no longer guessing
	} else {//once we're here we're going to send the guess form
		if (pico<0){//flag for duplicate digits
			sendConst("Oh, maybe I didn't tell you.  No two digits are the same.\r\n",sock);
		} else if ((pico+fermi)==0){
			sendConst("Doughnuts!",sock);
		} else{
			for(i=0;i<pico;i++) sendConst("Pico ",sock);
			for(i=0;i<fermi;i++) sendConst("Fermi ",sock);
		}
		sendConst("\r\n",sock);
		sendConst("Try Again\r\n:",sock); 	// ask for another guess
	}
}
void tBagelsTurn(unsigned char* guess,unsigned char sock){
	int i, /*ipslot,*/ pico=0, fermi=0;
	thisipslot=getipslot(thisip.l);
	if(strcmp(secrets[thisipslot],"999")){//as long as we have an actual secret
		ipturns[thisipslot]++; //count the turn
		printf("Guess: %d.%d.%d.%d,slot %d,secret %s\n",
			thisip.c[0],thisip.c[1],thisip.c[2],thisip.c[3],thisipslot,secrets[thisipslot]);
		strcpy((char*)secret,(char*)secrets[thisipslot]);
		cpyguess(guess,buf);
		for (i=0;i<3;i++){
			if (guess[i]==secret[i]){
				fermi++;
			}
		}
		if (guess[0]==secret[1]||guess[0]==secret[2]){pico++;}
		if (guess[1]==secret[0]||guess[1]==secret[2]){pico++;}
		if (guess[2]==secret[0]||guess[2]==secret[1]){pico++;}
		if (guess[0]==guess[1]||guess[0]==guess[2]||guess[1]==guess[2]||strlen((char *)guess)!=3){pico=-1;}
		tSendResp(pico, fermi,sock);
	}else{
		printf("Uninitialized secret for IP %d.%d.%d.%d in slot %d\n",
			thisip.c[0],thisip.c[1],thisip.c[2],thisip.c[3],thisipslot);
		tBagelsInit(sock);
	}
}
void tSendTable(unsigned char sock){
	unsigned int i;
	char buf[64];
	sendConst("Client Table/Secret/Games/Turns\n\r",sock);
	for (i=0;i<numslots;i++){
		if (regip[i].c[3]!=0){
			sendip(regip[i].c,sock);
			sendConst("/",sock);
			sendStr((char *)secrets[i],sock);
			sendConst("/",sock);
			sendStr(itoa10(ipgames[i],buf),sock);
			sendConst("/",sock);
			sendStr(itoa10(ipturns[i],buf),sock);
			sendConst("\n\r",sock);
		}
	}
}
void processTelnetLine(unsigned int rsize,unsigned char sock){
	if ('G'==sockMode[sock]){
		tBagelsTurn(buf,sock);
		flush(rsize,sock);
	}else if (buf[0]=='q'){
		sendConst("\n\rbye\n\r",sock);
		printf("disconnecting socket %d\n",sock);
		flush(rsize,sock);
		wizCmd(CR_DISCON,sock);// Disconnect the connection- we're done here
		sockPrevStat[sock]=SOCK_CLOSED;
	}else if (buf[0]=='t'){
		tSendTable(sock);
		sendConst(":",sock);
		flush(rsize,sock);
		return;
	} else{
		tBagelsInit(sock);
		flush(rsize,sock);
	}
}
void welcomeTelnet(unsigned char sock){
	sendConst("Oh Hello\r\n",sock);
	printf("S %d telnet session begins\n",sock);
	sockMode[sock]='C';//telnet command mode
	tBagelsInit(sock);
}

void processTelnetData(unsigned char sock){
	unsigned int rsize=wizGetCtl16(SnRX_RSR,sock);
	recv(buf,min(MAX_BUF-1,rsize),sock);//read what's there
	buf[rsize]=0;//make sure it's terminated
	printf("%d %02X %02X %02X\n",rsize,buf[0],buf[1],buf[2]);
	if (buf[0]==0xff){//looks like negotiation sequence
		flush(rsize,sock); //dump it
	}else if (!strchr(buf,0x0d)){//if no cr
		return;//just keep trucking
	}else {
		processTelnetLine(rsize,sock);//take a turn
	}
	return;
}

void handleTelnetSession(unsigned char sock){	//handle a telnet session once it's established
	//unsigned int rsize;
	if (sockPrevStat[sock]==SOCK_LISTEN){// first entry
		welcomeTelnet(sock);
		sockPrevStat[sock]=SOCK_ESTABLISHED;
	}
	if (wizGetCtl16(SnRX_RSR,sock)){//check for data available
		processTelnetData(sock);
	}
}

Advertisements
Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: