-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
142 lines (125 loc) · 5.7 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# -*- coding: utf-8 -*-
from threading import Thread
import time
if not hasattr(time, 'time_ns'): # for Py3.6
time.time_ns = lambda: int(time.time() * 1e9)
from argparse import ArgumentParser
import logging,socket
from pywebhost.handler import Request
from pywebhost.modules import JSONMessageWrapper, WriteContentToRequest
from pywebhost.modules.websocket import WebsocketSessionWrapper
from ggpo import GGPOServer
from ggpo.handlers.client import GGPOClientSession
from ggpo.handlers.player import GGPOPlayerSession
from ggpo.handlers.nexus import GGPOGenericSTUNServer
from ggpo.models.quark import ts_from_quark
try:
import coloredlogs
coloredlogs.DEFAULT_LOG_FORMAT = '%(asctime)s [%(levelname).1s] %(name)s %(message)s'
coloredlogs.install(level=0)
except:
logging.getLogger().setLevel(0)
print('WARNING: coloredlogs is not installed. Using default logger.')
def get_ip():
# https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
if __name__ == '__main__':
argparse = ArgumentParser(description='GGPO Python3 Server')
argparse.add_argument('--port',help='HTTP/TCP/UDP port',default=7000,type=int)
argparse.add_argument('--no-interactive',help='Do not take interactive input from stdin.',default=False,action='store_true')
args = argparse.parse_args()
server = GGPOServer()
server.bind_and_active(('0.0.0.0',args.port))
def allow_cors(function):
def method(initator, request: Request, content):
request.send_header('Access-Control-Allow-Origin','*')
return function(initator,request,content)
return method
@server.route('/.*')
def static(initator, request: Request, content):
return WriteContentToRequest(request,'./web/dist/'+request.path,mime_type='')
@server.route('/')
def index(initator, request: Request, content):
return WriteContentToRequest(request,'./web/dist/'+'index.html',mime_type='text/html; charset=UTF-8')
@server.route('/channels')
@JSONMessageWrapper(read=False)
@allow_cors
def channels(initator, request: Request, content):
request.send_response(200)
return [channel.__dict__() for channel in server.channels.values()]
@server.route('/channels/chathistory')
@JSONMessageWrapper(read=False)
@allow_cors
def users(initator, request: Request, content):
channel = request.query['channel'][-1]
if not channel:return request.send_response(404)
request.send_response(200)
return server.channels[channel].chat_history
@server.route('/channels/users')
@JSONMessageWrapper(read=False)
@allow_cors
def users(initator, request: Request, content):
channel = request.query['channel'][-1]
if not channel:return request.send_response(404)
request.send_response(200)
clients = server.channels[channel].clients
return [{
'name': username, 'channel': client.channelobject.name,'status': client.status.name,
'quark_ts': ts_from_quark(client.quark)} for username, client in clients.items()
]
# Routing banners
@server.route('/banners/.*')
@allow_cors
def banners_static(initator, request: Request, content):
try:
WriteContentToRequest(request,'./banners/'+ request.path.split('/banners/')[-1] + '.png',mime_type='image/png')
except:
WriteContentToRequest(request,'./banners/default.png',mime_type='image/png')
@server.route('/portraits/.*')
@allow_cors
def portraits_static(initator, request: Request, content):
try:
WriteContentToRequest(request,'./portraits/'+ request.path.split('/portraits/')[-1] + '.png',mime_type='image/png')
except:
WriteContentToRequest(request,'.'+'/'.join(request.path.split('/')[:-1]) + '/default.png',mime_type='image/png')
@server.route('/sounds/.*')
@allow_cors
def sound_static(initator, request: Request, content):
WriteContentToRequest(request,'./sounds/'+ request.path.split('/sounds/')[-1] + '.wav',mime_type='audio/wav')
@server.route('/home.*')
@allow_cors
def home(initator, request: Request, content):
if request.path == '/home' or request.path == '/home/':
return WriteContentToRequest(request,'./home/index.html',mime_type='text/html; charset=UTF-8')
else:
WriteContentToRequest(request,'.' + request.path,partial_acknowledge=True)
@server.route('/ws')
@WebsocketSessionWrapper()
def websocket(initator, request: Request, content):
return GGPOClientSession
@server.route('/ggpo')
@WebsocketSessionWrapper()
def websocket3(initator, request: Request, content):
return GGPOPlayerSession
logging.getLogger('PyWebHost').setLevel(logging.CRITICAL)
logging.info('SERVING : http://127.0.0.1:%d' % args.port)
logging.info(' http://%s:%d' % (get_ip(),args.port))
logging.info(' udp://%s:%d' % (get_ip(),args.port))
udp_handler = GGPOGenericSTUNServer(server=server,port=args.port)
udp_handler.start()
serverThread = Thread(target=server.serve_forever,name="GGPOTCP",daemon=True)
serverThread.start()
if not args.no_interactive:
# The main thread spawns an interactive terminal for more administrative operations
from code import interact
interact(banner='* Console is now ready (Press Ctrl+D to exit).',local=locals())
else:
serverThread.join()