server

Status
Niet open voor verdere reacties.

laurens800

Gebruiker
Lid geworden
20 mei 2007
Berichten
5
ik zoek iemand die dit kan vertalen naar c++

Code:
import java.sql.*;

public class server {
	// some misc functions
	public static void print_debug(String str)
	{
		System.out.print(str);				// comment this line out if you want to get rid of debug messages
	}
	public static void println_debug(String str)
	{
		System.out.println(str);
	}
	public static void print(String str)
	{
		System.out.print(str);
	}
	public static void println(String str)
	{
		System.out.println(str);
	}
	public static String Hex(byte data[], int offset, int len)
	{
		String temp = "";
		for(int cntr = 0; cntr < len; cntr++) {
			int num = data[offset+cntr] & 0xFF;
			String myStr;
			if(num < 16) myStr = "0";
			else myStr = "";
			temp += myStr + Integer.toHexString(num) + " ";
		}
		return temp.toUpperCase().trim();
	}
	public static int random(int range) {
		return (int)(java.lang.Math.random() * (range+1));
	}

	public static boolean shutdownServer = false;
	public static void main(java.lang.String args[])
	{
		clientHandler = new ClientHandler(null);
		(new Thread(clientHandler)).start();			// launch server listener

		while(!shutdownServer) {
			// could do game updating stuff in here...
			// maybe do all the major stuff here in a big loop and just do the packet
			// sending/receiving in the client subthreads. The actual packet forming code
			// will reside within here and all created packets are then relayed by the subthreads.
			// This way we avoid all the sync'in issues
			// The rough outline could look like:
			// doPlayers()		// updates all player related stuff
			// doNpcs()		// all npc related stuff
			// doObjects()
			// doWhatever()
			try { Thread.sleep(2000); } catch(java.lang.Exception _ex) { }
		}

		// shut down the server
		clientHandler.kill();
		clientHandler = null;
	}

	private static ClientHandler clientHandler = null; 	// handles all the clients
	private static java.net.ServerSocket clientListener = null;
	private static boolean shutdownClientHandler;			// signals ClientHandler to shut down
	private static int serverlistenerPort = 43000;//43594 default

	public static class ClientHandler implements Runnable {
		private java.net.Socket mySock;
	    private java.io.InputStream in;
	    private java.io.OutputStream out;
		public String myName = null;			// name of the connecting client
		public stream inStream = null, outStream = null;
		public Cryption inStreamDecryption = null, outStreamDecryption = null;
		public boolean clientConnected = false;
		public ClientHandler(java.net.Socket s) {
			mySock = s;
			myName = "";
			if(s != null) {
				try {
			        in = s.getInputStream();
			        out = s.getOutputStream();
				} catch(java.io.IOException ioe) {
					ioe.printStackTrace();
				}
			}
			else {
				in = null;
				out = null;
			}
		}
		public void flushOutStream() throws java.io.IOException
		{
			out.write(outStream.buffer, 0, outStream.currentOffset);
			outStream.currentOffset = 0;		// reset
		}
		// forces to read forceRead bytes from the client - block until we have received those
		public void fillInStream(int forceRead) throws java.io.IOException
		{
			inStream.currentOffset = 0;
			in.read(inStream.buffer, 0, forceRead);
		}

		public void run() {
			if(clientListener == null) {
				// setup the listener
				try {
					shutdownClientHandler = false;
					clientListener = new java.net.ServerSocket(serverlistenerPort, 1, null);
					System.out.println("Starting Untouched Server on " + clientListener.getInetAddress().getHostAddress() + ":" + clientListener.getLocalPort());
					while(true) {
						java.net.Socket s = clientListener.accept();
						s.setTcpNoDelay(true);
						String connectingHost = s.getInetAddress().getHostName();
						if(true) {
							System.out.println("ClientHandler: Accepted from "+connectingHost+":"+s.getPort());
							(new Thread(new ClientHandler(s))).start();
						}
						else {
							System.out.println("ClientHandler: Rejected "+connectingHost+":"+s.getPort());
							s.close();
						}
					}
				} catch(java.io.IOException ioe) {
					if(!shutdownClientHandler)
						System.out.println("Error: Unable to startup listener on "+serverlistenerPort+" - port already in use?");
					else System.out.println("ClientHandler was shut down.");
				}
				return; 	// we're done in here
			}


			if(mySock == null) return;		// no socket there - closed

			// we accepted a new connection
			outStream = new stream(new byte[100000]);
			outStream.currentOffset = 0;
			inStream = new stream(new byte[10000]);
			inStream.currentOffset = 0;

			// handle the login stuff
			long serverSessionKey = 0, clientSessionKey = 0;
			// randomize server part of the session key
			serverSessionKey = ((long)(java.lang.Math.random() * 99999999D) << 32) + (long)(java.lang.Math.random() * 99999999D);

			try {
				fillInStream(2);
				if(inStream.readUnsignedByte() != 14) {
					shutdownError("Expected login Id 14 from client.");
					return;
				}
				// this is part of the usename. Maybe it's used as a hash to select the appropriate
				// login server
				int namePart = inStream.readUnsignedByte();
				for(int i = 0; i < 8; i++) out.write(0);		// is being ignored by the client

				// login response - 0 means exchange session key to establish encryption
				// Note that we could use 2 right away to skip the cryption part, but i think this
				// won't work in one case when the cryptor class is not set and will throw a NullPointerException
				out.write(0);

				// send the server part of the session Id used (client+server part together are used as cryption key)
				outStream.writeQWord(serverSessionKey);
				flushOutStream();
				fillInStream(2);
				int loginType = inStream.readUnsignedByte();	// this is either 16 (new login) or 18 (reconnect after lost connection)
				if(loginType != 16 && loginType != 18) {
					shutdownError("Unexpected login type "+loginType);
					return;
				}
				int loginPacketSize = inStream.readUnsignedByte();
				int loginEncryptPacketSize = loginPacketSize-(36+1+1+2);	// the size of the RSA encrypted part (containing password)
				println_debug("LoginPacket size: "+loginPacketSize+", RSA packet size: "+loginEncryptPacketSize);
				if(loginEncryptPacketSize <= 0) {
					shutdownError("Zero RSA packet size!");
					return;
				}
				fillInStream(loginPacketSize);
				if(inStream.readUnsignedByte() != 255 || inStream.readUnsignedWord() != 317) {
					shutdownError("Wrong login packet magic ID (expected 255, 317)");
					return;
				}
				int lowMemoryVersion = inStream.readUnsignedByte();
				println_debug("Client type: "+((lowMemoryVersion==1) ? "low" : "high")+" memory version");
				for(int i = 0; i < 9; i++) {
					println_debug("dataFileVersion["+i+"]: 0x"+Integer.toHexString(inStream.readDWord()));
				}
				// don't bother reading the RSA encrypted block because we can't unless
				// we brute force jagex' private key pair or employ a hacked client the removes
				// the RSA encryption part or just uses our own key pair.
				// Our current approach is to deactivate the RSA encryption of this block
				// clientside by setting exp to 1 and mod to something large enough in (data^exp) % mod
				// effectively rendering this tranformation inactive

				loginEncryptPacketSize--;		// don't count length byte
				int tmp = inStream.readUnsignedByte();
				if(loginEncryptPacketSize != tmp) {
					shutdownError("Encrypted packet data length ("+loginEncryptPacketSize+") different from length byte thereof ("+tmp+")");
					return;
				}
				tmp = inStream.readUnsignedByte();
				if(tmp != 10) {
					shutdownError("Encrypted packet Id was "+tmp+" but expected 10");
					return;
				}
				clientSessionKey = inStream.readQWord();
				serverSessionKey = inStream.readQWord();
				println("UserId: "+inStream.readDWord());
				myName = inStream.readString();
				String password = inStream.readString();
				println("Indent: "+myName+":"+password);

				int sessionKey[] = new int[4];
				sessionKey[0] = (int)(clientSessionKey >> 32);
				sessionKey[1] = (int)clientSessionKey;
				sessionKey[2] = (int)(serverSessionKey >> 32);
				sessionKey[3] = (int)serverSessionKey;

				for(int i = 0; i < 4; i++)
					println_debug("inStreamSessionKey["+i+"]: 0x"+Integer.toHexString(sessionKey[i]));

				inStreamDecryption = new Cryption(sessionKey);
				for(int i = 0; i < 4; i++) sessionKey[i] += 50;

				for(int i = 0; i < 4; i++)
					println_debug("outStreamSessionKey["+i+"]: 0x"+Integer.toHexString(sessionKey[i]));

				outStreamDecryption = new Cryption(sessionKey);
				outStream.packetEncryption = outStreamDecryption;

				out.write(2);		// login response (1: wait 2seconds, 2=login successfull, 4=ban :-)
				out.write(0);		// mod level: 0=normal player, 1=player mod, 2=real mod
				out.write(0);		// no log

			} catch(java.lang.Exception __ex) {
				System.out.println("Untouched Server: Exception!");
				__ex.printStackTrace(); 
				shutdown();
				return;
			}
			// End of login procedure


			// those packets were sniffed from a real session and split into parts
			int mapRegionX = 0x182, mapRegionY = 0x195; 	// change those to get a different starting point
			//int mapRegionX = 270, mapRegionY = 350; 	// change those to get a different starting point

			// initiate loading of new map area
			outStream.createFrame(73);
			outStream.writeWordA(mapRegionX);
			outStream.writeWord(mapRegionY);

			// players initialization
			outStream.createFrame(81);
			outStream.writeWord(0); 		// placeholder for size of this packet.
			int ofs = outStream.currentOffset;
			outStream.initBitAccess();

			// update this player
			outStream.writeBits(1, 1);		// set to true if updating thisPlayer
			outStream.writeBits(2, 3);		// updateType - 3=jump to pos
			// the following applies to type 3 only
			outStream.writeBits(2, 0);		// height level (0-3)
			outStream.writeBits(1, 1);		// set to true, if discarding walking queue (after teleport e.g.)
			outStream.writeBits(1, 1);		// set to true, if this player is not in local list yet???
			outStream.writeBits(7, 0x20);	// y-position
			outStream.writeBits(7, 0x20);	// x-position

			// update other players...?!
			outStream.writeBits(8, 0);		// number of players to add

			// add new players???
			outStream.writeBits(11, 2047);	// magic EOF
			outStream.finishBitAccess();

			outStream.writeByte(0);		// ???? needed that to stop client from crashing

			outStream.writeFrameSizeWord(outStream.currentOffset - ofs);

			CreateNoobyItems();


			// the major part was done, now we're just looping reading incoming packets
			// and sending out some testing ****...
			packetType = -1;
			packetSize = 0;
			clientConnected = true;
			int walkingSteps = 0;
			int currentCoord = 0x20;
			while(clientConnected) {
				while(interpreteIncommingPackets());
				if(!clientConnected) break;

				// here we place the code that handles the outgoing stuff

				// some n00by walking packet
				outStream.createFrame(81);
				outStream.writeWord(0); 		// placeholder for size of this packet.
				ofs = outStream.currentOffset;

				// update thisPlayer
				outStream.initBitAccess();
				outStream.writeBits(1, 1);		// set to true if updating thisPlayer

				// walk code
/*				outStream.writeBits(2, 1);		// updateType - 1=walk in direction
				outStream.writeBits(3, 1);		// direction
				outStream.writeBits(1, 0);		// set to true, if this player is not in local list yet???
*/

				// run code
				outStream.writeBits(2, 2);		// updateType - 2=run in direction
				outStream.writeBits(3, 1);		// direction step 1
				outStream.writeBits(3, 1);		// direction step 2
				outStream.writeBits(1, 0);		// set to true, if this player is not in local list yet???


				outStream.writeBits(8, 0);		// no other players...
				outStream.finishBitAccess();

				outStream.writeFrameSizeWord(outStream.currentOffset - ofs);	// write size

				currentCoord+=2;		// +=1 for walking
				if(currentCoord > 90) {
					if(mapRegionY > 500) {
						//outStream.createFrame(109); 	// log out
						//println("Forcing log out of client!");
						println("Next row...");
						mapRegionX += 8;
						mapRegionY = 350;
						outStream.createFrame(73);
						outStream.writeWordA(mapRegionX);
						outStream.writeWord(mapRegionY);
						try {
							flushOutStream();
							Thread.sleep(2000); // wait some time until client loaded new area
						} catch(Exception x) {}





					// teleport packet
					outStream.createFrame(81);
					outStream.writeWord(0); 		// placeholder for size of this packet.
					ofs = outStream.currentOffset;

					// update thisPlayer
					outStream.initBitAccess();
					outStream.writeBits(1, 1);		// set to true if updating thisPlayer

					outStream.writeBits(2, 3);		// updateType - 3=jump to pos
					// the following applies to type 3 only
					outStream.writeBits(2, 0);		// height level (0-3)
					outStream.writeBits(1, 1);		// set to true, if discarding walking queue (after teleport e.g.)
					outStream.writeBits(1, 0);		// set to true, if this player is not in local list yet???
					outStream.writeBits(7, 0x20);	// y-position
					outStream.writeBits(7, 0x20);	// x-position

					// update other players...?!
					outStream.writeBits(8, 0);		// number of players that follow

					outStream.finishBitAccess();

					outStream.writeFrameSizeWord(outStream.currentOffset - ofs);
					
					currentCoord = 0x20;





					}
					else {
						outStream.createFrame(73);
						outStream.writeWordA(mapRegionX);
						mapRegionY += 8;
						currentCoord -= 8*8;		// granularity of a map region is 8
						outStream.writeWord(mapRegionY);
						println("Entering map region "+mapRegionX+","+mapRegionY);
						CreateNoobyItems();
						try {
							flushOutStream();
							Thread.sleep(2000); // wait some time until client loaded new area
						} catch(Exception x) {}
					}
				}


				if(!clientConnected) break;

				timeOutCounter++;
				if(timeOutCounter++ > 200) {
					println("Client lost connection: timeout");
					break;
				}

				// send all cummulated packets to the client
				try {
					flushOutStream();
					Thread.sleep(500);		// TODO: think about a way to sync all this stuff and about timing
				} catch(java.lang.Exception __ex) {
					System.out.println("Untouched Server: Exception!");
					__ex.printStackTrace(); 
					clientConnected = false;
				}
			}

			// we're done
			shutdown();
		}

		public void shutdownError(String errorMessage)
		{
			println("Fatal: "+errorMessage);
			shutdown();
		}
		public void shutdown()
		{
			try {
				System.out.println("ClientHandler: Client "+myName+" disconnected.");
				if(in != null) in.close();
				if(out != null) out.close();
				mySock.close();
				mySock = null;
				in = null;
				out = null;
			} catch(java.io.IOException ioe) {
				ioe.printStackTrace();
			}
		}

		public void kill()
		{
			try {
				shutdownClientHandler = true;
				if(clientListener != null) clientListener.close();
				clientListener = null;
			} catch(java.lang.Exception __ex) {
				__ex.printStackTrace();
			}
		}

	// just testing...
	public void CreateNoobyItems()
	{
		// this performs very slow for huge amount of items
/*		for(int x = 1; x < 100; x++) {
			for(int y = 1; y < 100; y++) {
				outStream.createFrame(85);
				outStream.writeByteC(y); 	// baseY
				outStream.writeByteC(x); 	// baseX

				outStream.createFrame(44);
				outStream.writeWordBigEndianA(random(1,1000)); 	// objectType
				outStream.writeWord(1);						// amount
				outStream.writeByte(0);						// x(4 MSB) y(LSB) coords
			}
		} */
		// send all items combined to larger clusters
		for(int x = 0; x < 11; x++) {
			for(int y = 0; y < 11; y++) {
				outStream.createFrame(60);
				outStream.writeWord(0); 		// placeholder for size of this packet.
				int ofs = outStream.currentOffset;

				outStream.writeByte(y*8); 	// baseY
				outStream.writeByteC(x*8); 	// baseX
				// here come the actual packets
				for(int kx = 0; kx < 8; kx++) {
					for(int ky = 0; ky < 8; ky++) {
						outStream.writeByte(44);		// formerly createFrame, but its just a plain byte in this encapsulated packet
						outStream.writeWordBigEndianA(random(1000)); 	// objectType
						outStream.writeWord(1);						// amount
						outStream.writeByte(kx*16+ky);						// x(4 MSB) y(LSB) coords
					}
				}

				outStream.writeFrameSizeWord(outStream.currentOffset - ofs);
			}
		}
	}

	public int packetSize = 0, packetType = 0;
	public int timeOutCounter = 0;
	public boolean interpreteIncommingPackets()
	{
		try {
			int avail = in.available();
			if(avail == 0) return false;

			// Important note: doesn't work yet because we don't know the lengths of any possible
			// incoming packets so we can't parse them and might miss the one or other ending up
			// with screwing the encryption
			if(packetType == -1) {
				packetType = in.read() & 0xff;
				if(inStreamDecryption != null)
					packetType = packetType - inStreamDecryption.getNextKey() & 0xff;
				avail--;
                packetSize = avail;
            }

			fillInStream(packetSize);
            timeOutCounter = 0;

			packetType = -1;
		} catch(java.lang.Exception __ex) {
			System.out.println("Untouched Server: Exception!");
			__ex.printStackTrace(); 
			clientConnected = false;
		}
		return true;
	}

	}		// class ClientHandler end

}
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan