Uzenet

Topics regarding the Uzebox hardware/AVCore/BaseBoard (i.e: PCB, resistors, connectors, part list, schematics, hardware issues, etc.) should go here.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Uzenet

Post by D3thAdd3r »

Some rhetorical ranting updates here about the random stuff I am thinking on. The emulator has been improved in several increments and I will release an updated version soonish and put it on Github. I think it mostly behaves like the real thing, but I need more complex programs to test it further. Getting it to build on Linux is a top priority so more people can use it.

I decided to get Pong working solid over the internet before Megatris, as it is probably the easiest game to network and also because it likely suffers from the fact there isn't always 2 people around wanting to play Uzebox. It is getting there and I think it would be a better example of a networked game to make the whole thing look less scary. The system itself is based on minimal data about key events we have authority on, like when a ball bounces off your paddle or you miss and a score happens. As long as predictions are correct the game will effectively have no latency, when wrong, the ball warps back to the last confirmed location by the remote side who had authority and it gets predicted from there. Time is "dilated" then by 1/2 round trip latency, but you always get at least as much reaction time as you would have in a local 2 player game. Whoever the ball is currently headed to, has authority on the balls position and score. This takes latency out of the equation for paddle movement..you cannot "miss because of lag" since your state is trusted in that case, and it trades it for possible visual decoherence that is corrected as quickly as the next packet arrives: should the received remote paddle position(which is from the past the moment you get it) not be the same position the collision event occurred on the remote side's screen. The other option, assuming no packets get delayed, will theoretically never have warps/missed predictions like this happen. The downside is latency on all paddle movements at all times, you push a button and it happens later, you release it stops moving after a while. In reality this mechanism constantly "jutters" moving objects as you receive data randomly in the middle of frames anyway. Simple but bad.

So somewhere I was talking about packets per second being an issue, and it still is. For setting up and retrieving non-performance data the "AT+CIPSEND=XX\r\n" one shot packet is ideal because you send the data and it awaits your next command. Your code is very separately doing something and making sure it worked anyway. I now find "AT+CIPSEND\r\n", which enters into "unvarnished transmission" mode, is the clear winner both in simplicity and speed for some types of gameplay you might want to network. You can get 50 packets per second out, you can't do it with normal "varnished mode". You do not need to keep sending "AT+CIPSEND=XX" and waiting an unknown time for it to finish before sending more, instead you just write data you want to send as fast as you like and it captures it all in 50hz windows as individual packets to the remote side. This simplifies in some ways the string handling of the state machine, and in other ways can be more difficult to unpack the data, though this can happen any time you use stream based TCP(due to Nagle algorithm which has good and bad points). So I have began to change my opinions quite a bit on some items. The new emulator version now supports unvarnished mode with an idealized 50hz based directly off Uzebox clock.

The problem with the unvarnished mode, is that you do not control the clock so you cannot know what data will go in what packet. The receiving end does not get a clearly delimited packet that would indicate where messages written start and end like sockets based UDP on normal machines can do. If you are sending 3 bytes of data, it could be 2 bytes in 1 packet, followed by the remaining byte in a second packet or any other possibility as the data gets longer. So you need to make the state machine handle this by interpreting everything as a stream across any number of packets, with symbols that represent chunks or a fixed size update packet; it isn't so hard really. The bad thing is this doesn't work out so well for UDP at all, because there is no guarantee a packet gets there or that the order you receive them was the same they were sent. The vast majority of time on a good connection they do get there, and in the same order(which is it's biggest plus against the TCP Nagle window delay), but in case they don't, the only way to fix it here is use a checksum across the entire replicated game state and code a mechanism to recover from desyncs. It is doable, but it puts the barrier much higher. I am falling away from the idea of UDP for most things, since performance is it's only benefit, and the peculiar way you must interface with the ESP8266 to pump out any real amount of data, is biased against the instant packet way UDP normally works. Why there is any delay at all on a UDP "SEND=XX" is beyond me, but there is, and you can't hit high packets per second without unvarnished mode.

I don't think the network logic will be anything that's difficult to understand. The harder part for now, is determining the best uniform way for all games to start. To save flash and complexity in every networked game, I am relying on NOT resetting the ESP at the beginning of the program and instead depending on the connection state it was in from the game browser program. Then the game treats the ESP as connected to the person we want to play with, and stops all networking if any error happens. To play another game with someone else you must reflash the browser program and find someone, then reset and flash the game you agreed to play. This is not emulated yet and probably wont be trivial.
User avatar
Jubatian
Posts: 1563
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Uzenet

Post by Jubatian »

How you describe the networked pong gave me an idea.

You essentially seem to turn it into a turn-based strategy game with fixed turn duration (the time it takes for the ball reaching your paddle). Maybe you could explore this a bit further for paddle movements ("your" paddle can always be real time, as you describe now, it seems it would lag). As it seems now it would work like after the opponent bounces the ball back + lag, you get the ball position, from where you side continues, so you could precisely "plan" your move. As soon as you bounce the ball, the control passes to the opponent, and you see only predicted stuff. This concept as far as I see would result in the ball getting "stuck" (position corrected) to the opponent's paddle for the time equalling the turnaround (to visually smooth out this, the game might try to predict the turnaround time based on past experience, and set the velocity of the leaving ball accordingly, so on the player's screen it likely arrives on the opponent's paddle when the opponent's bounce arrives: this would visually turn a slow network into looking like as if your bounce back was slower than the opponent's; another alternative might be making the ball stuck at the position where you bounced it back, so you would see approximately what your opponent was likely experiencing except for his paddle's lag on your display).

Just ideas. Maybe useful, maybe not.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Uzenet

Post by D3thAdd3r »

Let me think about that a bit whether there will be such noticeable issues at high latency. For sure on a missed prediction it will be noticeable in that case and it will get worse the more lag. Paddle positions are always behind but maybe there it is worth it to predict forward by estimated latency (as if he held the last known direction until we hear otherwise)or something.

I forgot to mention a key part im my ramblings also that might make the concept more clear on what it means to do. When the predicted state hits the predicted opponents paddle, it saves it, then later compares it to the authoritative remote state from the past. If it is found our version of the past does not match then it must be reconcilled because our present time prediction will be wrong. The ball will warp and continue from the remote sides definition. At least this is all in theory, it is not yet playable to test.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Uzenet

Post by D3thAdd3r »

I got a nice little title screen and made a semi-true-to-original Pong logo withconnection logic menu going using the quite attractive looking 8x8 font hidden inside Pong.
pong's hidden gradient font
pong's hidden gradient font
ponguzenetmenu.jpg (44.04 KiB) Viewed 6842 times
Connects to Uzenet OK great, quickly I realized an error in my design. It is extra work, but the logic was designed to communicate through the Uzenet game server to setup the game and determine who should listen for a connection and who should connect. Basically the one connecting asks the server for the IP address of the other, both agree they have the info they need, then disconnect from Uzenet and 1 starts listening while the other starts connecting. This was to have the lowest possible latency of point to point between clients, instead of the latency from each client to Uzenet added together. I now realize I overlooked something critical.

The "unvarnished transmission mode" only works when CIPMUX=0, or, single connection mode. That would be ideal still, except "AT+CIPSERVER.." to listen for a connection requires CIPMUX=1! So I said some of my favorite profanities as I often do when such things comes to light. It is essentially a choice between higher latency or more packets per second. I must pick more packets per second here, because otherwise the other sides paddle movement will not be smooth at 2-5 packets a second..I think that is a good trade, but only real testing on high latency can determine that for this game. Progress is being made yet, a rather cheesy CPU player will be serving for initial testing purposes.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Uzenet

Post by D3thAdd3r »

A lot of rewrites, I am now going in a mildly OOP direction for the server. I don't like over use of OOP, but using a bit seems to make this all much easier. I have been writing things that are very difficult to change as the design progresses so far. Unless arguments for another method can be made, it seems after lots of research and playing with code that would be very similar among different games, there is 1 solution that is the best mixture of pros and cons for: a basic level of security, easy backwards compatibility in the future, small code space to implement into games, and limited use of ram for RX buffers in games.

The concept in place now, there are no anonymous Uzenet users; they must be on the existing white list to play. Any machine connecting to the server does not need to know who the player is, only a unique identifier. This is identifier is not retrieved from flash, eeprom, or SD because that is extra resources and more difficult. The game grabs the ESP8266s MAC address via "AT+CIPAPMAC?\r\n"(which is set to unique ID once, in the setup utility) and spits the output of that to the server, which responds with the player name for display if the number matches a registered user to indicate success. There is no way for a user to change the ID, because then one bad user can use this to undermine the 48bit space in less time than from the outside. The ID can be changed manually in the file on uzebox.net via PM.

The reason for not using a longer string is because it requires a larger RX buffer and the minimum is already 32 with this method, unless you want to do sub-frame timing logic. For brute force attack(which we would use forced time delays against), considering 100 Uzenet users out of the 281,474,976,710,656 possible numbers, my rough calculation is that each attempt has a 1/2,814,749,767,106.56 probability of finding a valid user number. Then always listening on uzebox.net, but only calling accept() once every 500ms(a small login delay for all users to connect), it would "probably" take 44,627 years of attempts to find one. The unique IDs are made from a cropped version of a real UUID/GUID 128 bit number.

It's baseline security, and things could always be backed up on uzebox.net should the white list get compromised. Then again, if compromised, about the best they could do is make a bot that beats you terribly at some game and make you mad. Hopefully obscurity helps us here without requiring more elaborate validation methods. I would think giving VNC access for several trusted users(I guess some baseline of trusted users can vote who else is trusted) would be ideal, because problems could be tackled quickly even if a couple administrators go away for a while. Not worried about any issues related with that, just that no one would put sensitive information on any connected device.

Well, I'm logged in in a better finalized way, that's it so far.
User avatar
Jubatian
Posts: 1563
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Uzenet

Post by Jubatian »

Rather avoid mixing in IT security bits without knowing what you are doing. The MAC address in this scheme would essentially serve as a password, which is sent over the network in plain text (or binary). If someone really wanted to hack something there, he could sniff that instead of brute forcing.

There isn't much to protect here. I think for example even Battle for Wesnoth runs pretty much without any particular protection in the IT security sense (players have passwords, but I guess it is just transmitted as plaintext, so nothing more than basic user identification), and that certainly has a wider user base than Uzebox. There wouldn't be any service ever here which would involve money in any manner, neither it is too viable to attempt injecting viruses (you could only probably screw some crappy Windows system by such an attempt by uploading stuff on the SD which would autostart if inserted in such a misconfigured mess, but even to pull off that some sloppy SD writing software being present on the Uzebox is necessary).

The ESP8266 might have support for proper encryption, the Uzebox itself certainly has no such capabilities (of course it would be possible to implement some real authentication, but it would need lots of ROM space, which can not be afforded in this system, thinking about anything alike would only be viable if it could execute instructions from RAM). So I think the MAC address is fine, so long it is possible to be changed if it becomes necessary (if by some occasion something still happens, and the user needs a new "password").
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Uzenet

Post by D3thAdd3r »

If it also passes your logical sanity check, then I feel affirmed the method is good enough for our obscure+non-sensitive purposes.

If someone is on the same wifi network as the user, Wireshark would instantly leave these secrets bare...though I guess that makes it good for debugging :) There exists some SSL stuff for ESP826 you can compile into custom firmware, but information is difficult to find and no AT firmware provides access it seems.

This is just a guess, but there could be some novel "lightweight" way to implement asymmetric key encryption where the MAC is used as a 48bit(quite weak) private key and uzebox.net has a private+public key as well. Maybe only botnets and world governments can cheat at Uzenet then, or a GPU cracks it in an hour who knows. It would be a lot of work, then open sourced, might be so easy to defeat it isn't worth the effort. Social engineering would probably be the easiest way to break it, but I would hope no "hacker's" ego would grow larger by breaking good faith open source entertainment software anyway.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Uzenet

Post by D3thAdd3r »

More bits and pieces, it is all coming together still. UzeNet has an updated page, please check it out and let me know if the IRC client works for you. It automatically connects to irc.uzebox.net#lobby(running UnrealIRCd server), and there is the essential setup for a new score system that is much more flexible than the old idea. The page itself is programmatically created by the server any time a new score gets added. There is not much for score data to be shown yet, you can talk to the bot on IRC if you like but he wont say anything smart nor do I care about playing in that direction.

The idea once the IRC client for Uzebox side is working, will be to allow users to pre-arrange a game to play with specific players, exit and load rom, then just login to the server which performs that match previously agreed to without extra code on Uzebox. So it seems no 1 thing can get done until tons of little things get done.

I am looking at using an existing IRC bot that has an API which will allow services to be performed through IRC(the bot will be an admin and implement commands you send to it with unlimited privilege and always logged in). Also I am hoping it is easier to develop more expansive features in a scripting language with good string stuff built in. I am leaning towards bot called Sopel which is based off Python and looks easy to add stuff to. Does anyone have an opinion on scripting language to use for UN stuff moving forward? I feel like there is a benefit to using them for novel little features where the server does things and sends the output to Uzebox. I simply like Python because I have a rough acquaintance with it but if anyone is interested in possibly adding things in the future, now is the time to suggest an alternate language.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Uzenet

Post by D3thAdd3r »

The forums are a little slow right now so I will continue to spew random updates on this. I unfortunately have no time to develop any games, a process that I feel quite a bit more comfortable and faster at, but ultimately this is really what I want to do for my "big picture" item.

I am basically only working on the server at this point and there is now a lot of code. Testing is done with Pong as I continually streamline the process and investigate what other games might need to do that have different requirements. The result is things continually being tweaked and added on the server, while at the same time the code that is in Pong continues to get smaller and easier to understand. This is really what I dreamed about since the beginning.

I wrote some stuff on the wiki no one probably noticed. I was entertaining allowing python scripts to be ran arbitrarily by any registered user(one of many similar reasons that the entire network is simpler if we can trust all participants..ie. no anonymous users). I like Python but scraped this, there is no advantage over a C/C++ compiled program when most any bot or server logic handler will in large parts contain copies of the game logic that runs on Uzebox in C for simulation.

The current state allows any logged in user to create an instance of a "Bot" that is in the official list of binaries/commands. This program can do anything it is programmed to do. It is passed a super user ID and whatever command line arguments are desired when it is spawned and must log in and interact with the server just like any other client over sockets. The difference is it could simply act like a second AI player mimicking the message system of normal Uzebox clients in a game, or the client programs, depending on how you design things, can trust it to arbitrate game world state for more advanced networking games. Basically Uzebox can spawn multiple Bots at will and they can do anything a PC can do and the Uzebox can do anything it cares to do with it's output. It is totally game agnostic in that sense.

I am refactoring this more, but currently the code on Pong which does everything from resetting the module to requesting a bot to play against and reaching the point where game play logic has a direct UART pipe to a ready opponent(in this case AI) is this:

Code: Select all

	uint8_t error = 0;
	NetRole = 255;
	uint8_t y = 12;

	DrawMenuScreen();
	Print(2,y+=2,	PSTR("RESETTING NETWORK..."));

	NetHardReset();

	error = 1;
	if(!NetWaitForStringP(PSTR("GOT IP\r\n"),240))//wait for module to boot and connect to wifi before continuing
		goto NETWORK_ERROR;

	Print(2,y+=2,	PSTR("FOUND ESP8266 MODULE!"));

	WaitVsync(1);
	NetSendStringWaitP(PSTR("ATE0\r\n"),1);//make sure echo is off, always works
	NetSendStringWaitP(PSTR("AT+CIPMUX=0\r\n"),1);//turn on mux(to enable listen server if client 0)
	//NetSendStringWaitP(PSTR("AT+UART_CUR=8,1,0,0\r\n"),1);//use a faster baudrate for better performance
	InitUartRxBuffer();//get rid of startup text and ATE0 response which we will assume worked, else connection fails anyway
	

	Print(2,y+=2,	PSTR("CONNECTING TO UZENET..."));

	error = 2;
	if(!NetSendStringWaitResponseP(PSTR("AT+CIPSTART=0,\"TCP\",\"localhost\",58000\r\n"),PSTR("Linked\r\n"),60*3))//connect to match making server, wait up to 3 seconds
		goto NETWORK_ERROR;

	NetSendStringWaitP(PSTR("AT+CIPAPMAC?\r\n"),1);//request our MAC, which is our Uzenet Unique ID
	NetSendStringWaitP(PSTR("AT+CIPSEND\r\n"),2);//enter unvarnished tranmission mode

	error = 3;
	if(!NetTransmitRx(11,12+5,8))// eat leading " +CIPAPMAC:" ", transmit mac address, eat trailing " \r\nOK\r\n> "
		goto NETWORK_ERROR;

	error = 4;
	if(!NetWaitDataAvailable(14,120))
		goto NETWORK_ERROR;
	NetBufferRx(0,14,OurNetName,0);
//NetDumpRx();

	y -= 2;
	Print(2,y+=2,		PSTR("CONNECTED TO UZENET!   "));
	WaitVsync(1);//make sure the whole packet is here

	Print(2,y+=2,PSTR("WELCOME"));

	PrintRam(10,y,OurNetName);
	PrintChar(10+NetStrlen(OurNetName),y,'!');

	Print(2,y+=2,PSTR("WAITING FOR OPPONENT..."));
	Print(2,y+=2,PSTR("PRESS B TO VS PONGBOT"));

	NetSendStringP(PSTR("I4PONGBJ71PONGBOTRN2"));
	//"I4PONG" = set game to(name length 4)"PONG"
	//B = join any room
	//J71PONGBOT = spawn(name length 7) 1 instance of "PONGBOT"
	//M = get what client number we are in the room, where 0 is player 1
	//R = we are ready to play
	//N2 = send us "++" when 2 players are ready(including ourself as 1)
	error = 5;
	if(!NetWaitDataAvailable(1,120))//wait until we know which player we are
		goto NETWORK_ERROR;
	NetRole = UartReadChar()+1;
	error = 6;
	if(NetRole < 1 || NetRole > 2)
		goto NETWORK_ERROR;


	uint8_t counter = 0;
	error = 7;
	while(1){//wait for an available player to be ready
		WaitVsync(1);
		counter++;//TODO, update some waiting animation
		if(UartUnreadCount() > 1){
			if(UartReadChar() != 'N' || UartReadChar() != '+')//did server let us know other player is ready or are we getting some error?
				goto NETWORK_ERROR;
		}
	}
	//we are ready to play! Get the name of the other player
	UartSendChar('O');
	UartSendChar('0'+(NetRole == 1)?1:0);
	
	error = 8;
	if(!NetWaitDataAvailable(14+1,120))
		NetBufferRx(1,14,TheirNetName,0);//eat 'O' ,buffer their name, there should be no other data yet
	error = 9;
	WaitVsync(1);
	if(UartUnreadCount())//did server send more data than expected? Some misunderstanding happened(doesn't happen).
		goto NETWORK_ERROR;
///now any bytes we receive are from our opponent since we did not instruct the server to do anything but pass through a direct link
This will get smaller as I continue to refactor to the point where reduction runs against flexibility. This is exhaustive error handling for things that would rarely happen and in some instances probably never happen. There are more clever ways to discover if something went wrong later, but it sacrifices the ability to know exactly where things went wrong. It is also built with a comprehensive user display to show the user progress, which in more tight games could be eliminated with a simply animation and no text updates: pass or fail. In the current state I have yet to see any part not work after > 100 iterations of testing.

There is other stuff like adding high scores and stuff, requesting a time(with time zone correction), and more to come.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Uzenet

Post by D3thAdd3r »

I just sent out a whole swarm of PMs to users that I researched posts and seemed trust worthy members, and have logged in within the last few months. That was really time consuming so forgive the very generic stock PM content, normally I would be a bit more personable to the individual I am addressing if it wasn't required to message in such quantity :oops:

I am working on the setup program soon to add the feature required to save the unique ID each of you was sent to the ESP8266 flash. After this UzeNet programs will work without requiring you to do anything. If I missed you and didn't send a UzeNet ID and you would like one, PM me and I will generate it and add you to the white list. Depending on the content, the user should have > 20 meaningful posts on the forums, or have made a demo/game/proof of concept...or at least a meaningful PM. When the demos are release please log in an check your PMs, thanks!
Post Reply