#!/usr/bin/python3
## Global Modules
import threading, time, json, syslog
LOG_AUTH=syslog.LOG_AUTH
## Semi-local modules
from websock import WebSocketServer, WebSocket
## Local Modules
from utils import stdout, now
#from consts import *
import protocol, security, traceback
###############################################################
# Configuration
f=open("pass.json", "r")
p=json.load(f)
f.close()
PORT=p["PORT"]
SECURE=p["SSL"]
clients = []
###############################################################
# Main Class
class WebSocketConn(WebSocket):
def handle(self):
global clients
"""
Called when websocket frame is received.
To access the frame data call self.data.
i.e. The client sent us a message \o/
If the frame is Text then self.data is a unicode object.
If the frame is Binary then self.data is a bytearray object.
"""
print("Message received from %s - %s" % (self.address[0], self.data))
try:
r=protocol.parse(self.data)
print("Status: %s" % str(r[0]))
print("Reply: %s" % r[1])
if r[0] is not True:
stdout("%s - %s" % (self.address[0], r[1]))
syslog.syslog(LOG_AUTH, "%s - %s" % (self.address[0], r[1]))
self.send_message("NACK\n")
security.score(self, 5)
else:
self.send_message(r[1])
except:
traceback.print_exc()
self.send_message("ERROR\n")
print("Message sent")
#stdout(self.address[0] + u' - %s' % (self.data))
#self.send_message('ACK')
def connected(self):
global clients, blacklist
"""
Called when a websocket client connects to the server.
"""
#print(self.address, 'connected')
#for client in clients:
# print(repr(client))
# client.send_message(self.address[0] + u' - connected')
stdout(self.address[0] + u' - connected')
# Blacklisted
if (security.is_banned(self.address[0])):
stdout("Found in K-Line, connection was dropped.")
self.close(self, status=1000, reason="K-Lined")
# TODO: Drop OLD connections when same ID tries to connect
if (False):
self.close(self, status=1000, reason='Unrecognized')
else:
clients.append(self)
# Extend self class
self.MS_score = 0
self.MS_auth = False
def handle_close(self):
global clients
"""
Called when a websocket server gets a Close frame from a client.
"""
clients.remove(self)
print(self.address, 'closed')
#for client in clients:
# client.send_message(self.address[0] + u' - disconnected')
stdout(self.address[0] + u' - disconnected')
##########################
# Useful functions:
# send_message()
# send_fragment_start() / send_fragment() / send_fragment_end()
#
##########################
def MainWebsocket():
if SECURE:
server = WebSocketServer('', PORT, WebSocketConn,
certfile="certificate.pem", keyfile="key.pem")
print("Begin Secure Websocket at %d" % PORT)
else:
server = WebSocketServer('', PORT, WebSocketConn)
print("Begin UNENCRYPTED Websocket at %d" % PORT)
t = threading.Thread(target=server.serve_forever)
t.daemon = True # Main server should not be a daemon?
t.start()
return
#while True:
# time.sleep(86400)
# Broadcast function
def sendmsg(m, t="raw"):
global clients
# Format message according to type
if t == "ping":
msg="pong"
else:
msg=u"%s" % m
# Send message
for c in clients:
c.send_message(msg)
return
###############################################################
# Begin stuff
stdout("Starting at: T-%d" % (now()))
syslog.openlog()
MainWebsocket()
try:
print("Serving at port %d" % PORT)
while True:
command=str(input("> "))
# No command inserted? Do nothing
if command == "":
continue
# We have a command, prepare it for processing
stdout("CONSOLE: %s" % command)
cmd=command.split(' ')[0].lower()
com=" ".join(command.split(' ')[1:])
# Parse the command
if cmd in ["broadcast", "global", "msg", "say"]:
sendmsg("NOTICE:" + com)
elif cmd in ["ban", "block", "nuke"]:
security.ban_ip(com)
elif cmd in ["exit", "quit", "close", "term", "end"]:
stdout("Preparing to close server...")
sendmsg("NOTICE:Server is going down for scheduled maintenance. Please close, wait five minutes, and then re-open the app.")
break
else:
stdout("ERROR: Unknown command.")
except:
stdout("Abrupt error: Terminating!")
traceback.print_exc()
# TODO: Cleanup here
time.sleep(0.5)
for c in clients:
c.close(reason="Server is shutting down")
print("Server finished.")