-
-
Save alienelephant/25c6c45a034f5d5eb09b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
''' | |
code forked from https://gist.github.com/mdhowle/4212b0116edfab37c545 | |
''' | |
from sys import stdout | |
from twisted.python.log import startLogging | |
from twisted.internet import reactor | |
from twisted.internet.protocol import Factory, Protocol | |
import struct | |
# might be helpful later | |
class ServerConfig: | |
def __init__(self, server_name, server_ip, server_port, server_online_users=9999, server_status="up"): | |
# these are sane max length values for the fields. this should be changed to actual validation code | |
SERVER_NAME_MAX = 23 | |
SERVER_IP_MAX = 15 | |
SERVER_PORT_MAX = 5 | |
SERVER_STAT_MAX = 4 | |
SERVER_ONLINE_MAX = 4 | |
self.server_name = server_name[:self.SERVER_NAME_MAX] | |
self.server_name_len = struct.pack('B', len(self.server_name)) | |
self.server_ip = server_ip[:self.SERVER_IP_MAX] | |
self.server_ip_len = struct.pack('B', len(server_ip)) | |
self.server_port = server_port[:self.SERVER_PORT_MAX] | |
self.server_port_len = struct.pack('B', len(server_port)) | |
self.server_online_user = server_online_user[:SERVER_ONLINE_MAX] | |
self.server_online_users_len = struct.pack('B', len(server_online_users)) | |
self.server_status = server_status[:self.SERVER_STAT_MAX] | |
self.server_status_len = struct.pack('B', len(server_status)) | |
# unlikely to be using this anytime soon | |
class PatchServer(Protocol): # listens on port 6005 | |
def connectionMade(self): | |
print 'PATCH: Client connected: %s' % self.transport.getPeer() | |
def connectionLost(self, reason): | |
print "PATCH: Client disconnected: %s" % self.transport.getPeer() | |
def dataReceived(self, data): | |
if data.startswith("\x04"): | |
self.transport.write('\x18\x00\x00\x00') | |
self.transport.write('\x19\x00\x00\x00') | |
self.transport.write('\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') | |
elif data.startswith('\x08'): | |
self.transport.write('\x18\x00\x00\x00\x19\x00\x00\x00') | |
self.transport.write('\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') | |
elif data.startswith('\x0c'): # start sending patches ? | |
pass | |
else: | |
print data.encode('hex') | |
# router server generally works well | |
class RouteServer(Protocol): # listens on port 7002 | |
def connectionMade(self): | |
print "ROUTE: Client connected: %s" % self.transport.getPeer() | |
def connectionLost(self, reason): | |
print "ROUTE: Client disconnected: %s" % self.transport.getPeer() | |
## | |
# added some easy to config vars | |
def dataReceived(self, data): | |
server_version = '64' | |
#server_version = '52' | |
if data.startswith("\x14"): # patch server requested | |
self.transport.write('\x2c\x00\x00\x00') | |
self.transport.write('\x19\x00\x00\x00') | |
#self.transport.write('\x00\x00\x00\x00\x00\x00\x00\x00\x64\x00\x00\x00\x00\x00\x00\x00\x0d\x0050.247.16.101\x04\x006005\x00\x00\x02\x0046\x0d') | |
self.transport.write('\x00\x00\x00\x00\x00\x00\x00\x00\x64\x00\x00\x00\x00\x00\x00\x00\x0d\x0050.247.16.101\x04\x006005\x00\x00\x02\x00\x35\x38\x0d') | |
elif data.startswith("\x10"): # ROUTE server requested | |
head_data = '\x00\x00\x00\x19\x00\x00\x00' # not sure what this does, or what 0x19 is | |
head_data_2 = '\x00\x00\x00\x00\x00\x00\x00\x00\x64\x00\x00\x00\x00\x00\x00\x00' # not sure what this does, x64 seems to be the server version | |
end_data = '\x00\x00\x00\x00\x00\x00' # might be padding? | |
server_name_max = 23 | |
server_name = "Private Realm Server" # this has a max length of 23 | |
server_name_len = struct.pack('B', len(server_name[:server_name_max])) | |
server_ip = "192.168.1.100" | |
server_ip_len = struct.pack('B', len(server_ip)) | |
server_port = "8001" | |
server_port_len = struct.pack('B', len(server_port)) | |
server_online_users = "5555" # max of 4 (let's be realistic) | |
server_online_users_len = struct.pack('B', len(server_online_users[:4])) | |
server_status = "down" | |
server_status_len = struct.pack('B', len(server_status[:4])) | |
# create most of the packet | |
packet = head_data_2 \ | |
+ '\x02' + server_name_len + '\x00' + server_name[:server_name_max] \ | |
+ server_status_len + '\x00' + server_status \ | |
+ server_online_users_len + '\x00' + server_online_users \ | |
+ server_ip_len + '\x00' + server_ip \ | |
+ server_port_len + '\x00' + server_port \ | |
+ end_data | |
# complete packet creation | |
data_length = struct.pack('B', len(packet)) | |
packet = data_length + head_data + packet | |
# finally write the packet | |
self.transport.write(packet) | |
''' | |
orig for ref | |
self.transport.write('\x00\x00\x00\x00\x00\x00\x00\x00\x64\x00\x00\x00\x00\x00\x00\x00' | |
'\x02\x10\x00Matthew\'s Realm\x02\x00up\x04\x009999\x0d\x0050.247.16.101\x04\x008001' | |
'\x10\x00The Mists - Test\x02\x00up\x01\x000\x0d\x0050.247.16.101\x04\x008000' | |
'\x00\x00\x00\x00\x00\x00') | |
''' | |
# need to figure out user login procedure | |
class GameServer(Protocol): #8001 | |
def __init__(self, reactor): | |
self.reactor = reactor | |
def connectionMade(self): | |
print "GAME: Client connected: %s" % self.transport.getPeer() | |
# this is apparently the message size? | |
self.transport.write("\x78\x00\x00\x00") | |
self.transport.write("\x04\x00\x00\x00") | |
data = "\x70\xA7\x37\xA5\xF1\x02\x23\xEF\xEF\xCD\x8E\x2A\x8D\x02\x31\x2A\xAA\x00\x46\x22\x62\x7B\xBA\x66\xA0\x38\x20\xA1\x57\x77\x37\x9F\x9C\x18\x87\x9F\x9C\x77\x6A\xBD\x41\x6E\x5C\xF3\x9C\x77\x37\xA4\x9D\x77\x37\x9F\xCD\xBE\x33\x7F\x89\x1A\x87\x9F\x9C\x77\xC0\xBE\xFB\xD5\x92\xF7\xF9\x3A\x37\x9F\x9C\x77\x37\x9F\x9C\x77\x37\x9F\x9C\x77\x37\x9F\x7A\xEB\x2B\xB3\x8B\xF7\x38\x9F\x9C\x77\x37\x9F\x9C\x77\x37\x9F\x9F\x95\x37\xC6\x9C\xAD\x37\x9F\x9C\x77\x37\x9F\x9C\x77\x00\x00\x00\x00\x00\x00\xD0\x00\x00\x00\x04\x00\x00\x00\x09\x70\xD1\xE1\x58\xCB\xBC\x26\x56\x96\x27\x97\xEC\x42\x71\x66\x03\x40\xD0\x61\xF5\xCB\xEE\xCD\x28\xD4\xD0\xD6\x03\x45\xD1\xD6\x03\x40\x01\xDC\xFA\x65\x64\xD6\x03\x40\xD5\xD7\x03\x40\xD0\x07\x49\x44\x03\x34\x07\x37\xF5\x6A\x03\x40\xD0\xDB\x04\x40\xD0\xD6\x34\x86\xD8\x09\x61\x48\x73\x66\x03\x40\xD0\x59\xFC\x44\x4C\x13\xFA\x65\x64\xD6\x03\x40\xD5\xD7\x03\x40\xD0\x07\x49\x4C\x03\x34\x0F\xE3\x60\xD6\x03\x40\x53\xCF\x08\xBC\xF2\x59\xC9\x50\x53\xBF\x08\xB4\xD7\x09\x21\xC3\x96\xDA\xE3\x39\x0B\xF4\x77\x4F\x89\xE6\x03\x40\xD0\x90\x9B\x40\xD0\xD6\xEB\x40\xD0\xD6\x03\x9F\x2E\x31\x5B\x9D\x93\xD6\x50\x7B\xE0\x0A\xF2\xC0\xD1\xD6\x0B\x40\xD0\xD6\x03\x40\xD0\xD4\x05\x40\xD0\xD6\x03\x40\xD0\xD6\x03\x40\xD0\xD6\x03\x40\xD0\xD6\x0B\x4B\xD0\xEB\x03\x62\xD0\x09\x03\x83\xD0\x24\x03\x9E\xD0\x56\x03\x41\x55\xD6\x04\x40\x00\x00\x1A\x1C\x00\x40\x18\x00\x00\x00\xFD\xDC\x1A\xF4\xDD\x38\x6A\x30\x54\x96\x76\x88\x6C\x58\x34\x48\x00\x00\x00\x00\x00\x50\xEA\x1E\xFC\x8C\xF0\xEA" | |
# splitting up the data as show in winsock hook | |
self.transport.write(data[:120]) | |
self.transport.write(data[120:124]) | |
self.transport.write(data[124:336]) | |
self.transport.write(data[336:340]) | |
self.transport.write(data[340:]) | |
def connectionLost(self, reason): | |
print "GAME: Client disconnected: %s" % self.transport.getPeer() | |
def dataReceived(self, data): | |
print "GAME: Data received: ", data.encode('hex') | |
class GameFactory(Factory): | |
def buildProtocol(self, addr): | |
p = self.protocol(self.reactor) | |
p.factory = self | |
return p | |
if __name__ == '__main__': | |
startLogging(stdout) | |
routefactory = Factory() | |
routefactory.protocol = RouteServer | |
reactor.listenTCP(7002, routefactory) | |
patchfactory = Factory() | |
patchfactory.protocol = PatchServer | |
reactor.listenTCP(6005, patchfactory) | |
gamefactory = GameFactory() | |
gamefactory.reactor = reactor | |
gamefactory.protocol = GameServer | |
reactor.listenTCP(8001, gamefactory) | |
reactor.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment