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
}