Initial commit
This commit is contained in:
parent
213e0a2d2b
commit
25c543fa3b
0
__init__.py
Normal file
0
__init__.py
Normal file
11
config.json
Normal file
11
config.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"host": "0.0.0.0",
|
||||||
|
"port": 7777,
|
||||||
|
"server": {
|
||||||
|
"password": "",
|
||||||
|
"hostname": "Python > C",
|
||||||
|
"max_players": 50,
|
||||||
|
"mode": "yay",
|
||||||
|
"language": "spoop"
|
||||||
|
}
|
||||||
|
}
|
4
handlers/__init__.py
Normal file
4
handlers/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
from . import mainHandler
|
||||||
|
from . import serverPingHandler
|
||||||
|
|
||||||
|
from . import handshakeHandler
|
3
handlers/handshakeHandler.py
Normal file
3
handlers/handshakeHandler.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
def handle(client, data):
|
||||||
|
print("![{}] -> Handshake".format(client.addr))
|
||||||
|
return
|
19
handlers/mainHandler.py
Normal file
19
handlers/mainHandler.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
from . import handshakeHandler
|
||||||
|
|
||||||
|
def handle(client, data):
|
||||||
|
print("?[{}] -> {} / {}".format(client.addr, data, data.hex()))
|
||||||
|
|
||||||
|
if client.state == 0: # Perform handshake if possible
|
||||||
|
client.state = 1
|
||||||
|
return b"\x1a\x1e\xd1\xd1"
|
||||||
|
if client.state == 1:
|
||||||
|
client.state = 2
|
||||||
|
return b"\x19\x00"
|
||||||
|
if client.state == 2:
|
||||||
|
client.state = 3
|
||||||
|
return b"\xe3\x00\x00"
|
||||||
|
if client.state == 3:
|
||||||
|
client.state = 4
|
||||||
|
return b"\xe3\x00\x00", b"\x00\x00\x42\x98\x0c\x11\x33\x45\x30\x42\x33\x33\x35\x32\x37\x34\x46\x39\x31\x43\x39\x39\x00"
|
||||||
|
|
||||||
|
return b"WUT?"
|
38
handlers/serverPingHandler.py
Normal file
38
handlers/serverPingHandler.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import struct
|
||||||
|
from objects import glob
|
||||||
|
|
||||||
|
def handle(client, data):
|
||||||
|
ping_ip = ".".join((str(x) for x in struct.unpack(b"<BBBB", data[4:8])))
|
||||||
|
|
||||||
|
print("![{}] -> Pinging to {}".format(client.addr, ping_ip))
|
||||||
|
|
||||||
|
if len(data) == 11: # We should add our data ontop
|
||||||
|
if data[-1:] in RESPONSE:
|
||||||
|
data += RESPONSE[data[-1:]]()
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def query_i():
|
||||||
|
len_hostname = len(glob.config["server"]["hostname"])
|
||||||
|
len_mode = len(glob.config["server"]["mode"])
|
||||||
|
len_language = len(glob.config["server"]["language"])
|
||||||
|
|
||||||
|
packet = struct.pack(b"<?HHI%dsI%dsI%ds" % (len_hostname, len_mode, len_language),
|
||||||
|
False,
|
||||||
|
get_online_players(),
|
||||||
|
glob.config["server"]["max_players"],
|
||||||
|
len_hostname,
|
||||||
|
glob.config["server"]["hostname"].encode(),
|
||||||
|
len_mode,
|
||||||
|
glob.config["server"]["mode"].encode(),
|
||||||
|
len_language,
|
||||||
|
glob.config["server"]["language"].encode())
|
||||||
|
|
||||||
|
return packet
|
||||||
|
|
||||||
|
def get_online_players(): #TODO
|
||||||
|
return 0
|
||||||
|
|
||||||
|
RESPONSE = { #TODO: r, c, d & p (https://wiki.sa-mp.com/wiki/Query_Mechanism)
|
||||||
|
b"i": query_i
|
||||||
|
}
|
36
main.py
Normal file
36
main.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
from importlib import reload
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import json
|
||||||
|
|
||||||
|
from objects import glob
|
||||||
|
from objects.server import Server
|
||||||
|
|
||||||
|
from objects import client
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("> Loading config")
|
||||||
|
with open("config.json", "r") as f:
|
||||||
|
glob.config = json.load(f)
|
||||||
|
|
||||||
|
print("> Starting server")
|
||||||
|
glob.server = Server(glob.config["host"], glob.config["port"])
|
||||||
|
glob.server.start()
|
||||||
|
|
||||||
|
# Terminal loop
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
cmd = input("> ")
|
||||||
|
if cmd == "quit" or cmd == "exit" or cmd == "stop":
|
||||||
|
exit(0)
|
||||||
|
else:
|
||||||
|
print("> Restarting...")
|
||||||
|
client.restart()
|
||||||
|
"""for module in sys.modules.values():
|
||||||
|
reload(module)
|
||||||
|
glob.server = Server(glob.config["host"], glob.config["port"])
|
||||||
|
glob.server.start()"""
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
3
objects/__init__.py
Normal file
3
objects/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from . import glob
|
||||||
|
from . import client
|
||||||
|
from . import server
|
50
objects/client.py
Normal file
50
objects/client.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
from importlib import reload
|
||||||
|
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
from handlers import serverPingHandler, mainHandler
|
||||||
|
|
||||||
|
class Client:
|
||||||
|
BUFF_SIZE = 65535
|
||||||
|
HANDLERS = {
|
||||||
|
re.compile(b"SAMP"): serverPingHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, server, addr):
|
||||||
|
self.server = server
|
||||||
|
self.addr = addr
|
||||||
|
self.state = 0
|
||||||
|
self.__writebuffer = []
|
||||||
|
|
||||||
|
def handle_data(self, data):
|
||||||
|
found = False
|
||||||
|
for pattern, handler in self.HANDLERS.items():
|
||||||
|
if pattern.match(data):
|
||||||
|
queue = handler.handle(self, data)
|
||||||
|
if queue:
|
||||||
|
self.write_to_buffer(queue)
|
||||||
|
found = True
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
queue = mainHandler.handle(self, data)
|
||||||
|
if queue:
|
||||||
|
self.write_to_buffer(queue)
|
||||||
|
#print("?[{}] -> {} / {}".format(self.addr, data, data.hex()))
|
||||||
|
|
||||||
|
def write_to_buffer(self, data):
|
||||||
|
if type(data) == bytes:
|
||||||
|
self.__writebuffer.append(data)
|
||||||
|
else:
|
||||||
|
self.__writebuffer += data
|
||||||
|
|
||||||
|
def write_buffer_size(self):
|
||||||
|
return len(self.__writebuffer)
|
||||||
|
|
||||||
|
def write_socket(self):
|
||||||
|
if len(self.__writebuffer) > 0:
|
||||||
|
write_chunk = self.__writebuffer.pop(0)
|
||||||
|
print("[{}] <- {}".format(self.addr, write_chunk))
|
||||||
|
self.server.socket.sendto(write_chunk, self.addr)
|
||||||
|
|
||||||
|
def restart():
|
||||||
|
reload(serverPingHandler)
|
2
objects/glob.py
Normal file
2
objects/glob.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
config = None
|
||||||
|
server = None
|
56
objects/server.py
Normal file
56
objects/server.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import socket
|
||||||
|
import select
|
||||||
|
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
from .client import Client
|
||||||
|
|
||||||
|
class Server(Thread):
|
||||||
|
BUFF_SIZE = 65535
|
||||||
|
|
||||||
|
def __init__(self, host, port):
|
||||||
|
super(Server, self).__init__()
|
||||||
|
self.daemon = True
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
self.socket.bind((self.host, self.port))
|
||||||
|
self.socket.setblocking(0)
|
||||||
|
|
||||||
|
self.clients = {}
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# Main server loop
|
||||||
|
while True:
|
||||||
|
(incomming, _, _) = select.select(
|
||||||
|
[self.socket],
|
||||||
|
[],
|
||||||
|
[], 1)
|
||||||
|
|
||||||
|
if incomming:
|
||||||
|
data, addr = self.socket.recvfrom(self.BUFF_SIZE)
|
||||||
|
|
||||||
|
if addr in self.clients:
|
||||||
|
self.clients[addr].handle_data(data)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.clients[addr] = Client(self, addr)
|
||||||
|
print("[Server] Accepted connection from {}:{}".format(addr[0], addr[1]))
|
||||||
|
self.clients[addr].handle_data(data)
|
||||||
|
except socket.error:
|
||||||
|
try:
|
||||||
|
self.socket.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
print("[Server] Something went very wrong...")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
clients = [x for x in self.clients.values()
|
||||||
|
if x.write_buffer_size() > 0]
|
||||||
|
|
||||||
|
for client in clients:
|
||||||
|
client.write_socket()
|
||||||
|
|
||||||
|
for c in self.clients.values():
|
||||||
|
print(c.__writebuffer)
|
68
proxy.py
Normal file
68
proxy.py
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
from threading import Thread
|
||||||
|
import select
|
||||||
|
|
||||||
|
class Proxy(Thread):
|
||||||
|
BUFF_SIZE = 65535
|
||||||
|
def __init__(self, listen, target):
|
||||||
|
Thread.__init__(self)
|
||||||
|
self.listen = listen
|
||||||
|
self.target = target
|
||||||
|
|
||||||
|
self.clients = []
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
client.bind(self.listen) # Listen
|
||||||
|
#master.listen(5)
|
||||||
|
|
||||||
|
target = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
target.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
target.connect(self.target) # Server
|
||||||
|
#target.
|
||||||
|
|
||||||
|
#client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
#client.connect(self.listen)
|
||||||
|
|
||||||
|
client.setblocking(0)
|
||||||
|
target.setblocking(0)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
(c, _, _) = select.select([client],[],[],0)
|
||||||
|
|
||||||
|
if c:
|
||||||
|
c_data, c_addr = client.recvfrom(self.BUFF_SIZE)
|
||||||
|
print("[C] data:{} addr:{}".format(c_data, c_addr))
|
||||||
|
if c_data:
|
||||||
|
if c_data[:2] == b"\x08\x1e":
|
||||||
|
print("Editing port check: {}".format(c_data.hex()))
|
||||||
|
c_data = b"\x08\x1e\x77\xda"
|
||||||
|
print("[C] -> {}".format(c_data.hex()))
|
||||||
|
target.sendto(c_data, self.target)
|
||||||
|
|
||||||
|
(s, _, _) = select.select([target],[],[],0)
|
||||||
|
|
||||||
|
if s:
|
||||||
|
s_data = target.recv(self.BUFF_SIZE)
|
||||||
|
print("[S] data:{}".format(s_data))
|
||||||
|
if s_data:
|
||||||
|
print("[C] <- {}".format(s_data.hex()))
|
||||||
|
client.sendto(s_data, c_addr)
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
if len(sys.argv) < 4:
|
||||||
|
print("Missing arguments.")
|
||||||
|
print("Usage: $ python proxy.py [proxy_port] [server_ip] [server_port]")
|
||||||
|
print("Sample: $ python proxy.py 7777 192.168.2.1 7777")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
LISTEN = ("0.0.0.0", int(sys.argv[1]))
|
||||||
|
TARGET = (sys.argv[2], int(sys.argv[3]))
|
||||||
|
|
||||||
|
##while True:
|
||||||
|
proxy = Proxy(LISTEN, TARGET)
|
||||||
|
proxy.start()
|
||||||
|
proxy.join()
|
||||||
|
print("Error?")
|
Reference in New Issue
Block a user