159 lines
3.6 KiB
Python
Executable File
159 lines
3.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import sys
|
|
import os
|
|
p = os.path.join
|
|
pUp = os.path.dirname
|
|
s = False
|
|
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
|
s = os.path.realpath(sys.executable)
|
|
else:
|
|
s = os.path.realpath(__file__)
|
|
sp = pUp(s)
|
|
|
|
# script start
|
|
import subprocess
|
|
import socket
|
|
import time
|
|
|
|
def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs)
|
|
|
|
bufferSize = 4096 # max buffer size in bytes for receiving data, lower values shouldn't reduce the delay
|
|
bufferSizeStdin = 128 # min buffer size for buffer, lower values DO reduce delay but raise CPU usage
|
|
timeout = 15 # timeout in seconds
|
|
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
unbufferedStdout = os.fdopen(sys.stdout.fileno(),"wb",0) # Make unbuffered stdout
|
|
useSSL = False
|
|
sslIgnoreCert = False
|
|
if "fstream_ssl" in os.environ and os.environ["fstream_ssl"] == "1": useSSL = True
|
|
if "fstream_ssl_ignoreCert" in os.environ and os.environ["fstream_ssl_ignoreCert"] == "1": sslIgnoreCert = True
|
|
|
|
def listToCommand(lst):
|
|
cmd = ""
|
|
for arg in lst:
|
|
arg = arg.replace("\\","\\\\")
|
|
arg = arg.replace(",","\\,")
|
|
cmd += arg + ","
|
|
|
|
return cmd[:-1]
|
|
|
|
def commandToList(cmd):
|
|
args = []
|
|
cArg = ""
|
|
escape = False
|
|
for letter in cmd:
|
|
if escape == True:
|
|
cArg += letter
|
|
escape = False
|
|
continue
|
|
|
|
if letter == "\\":
|
|
escape = True
|
|
continue
|
|
|
|
if letter == ",":
|
|
if cArg == "": continue
|
|
args.append(cArg)
|
|
cArg = ""
|
|
continue
|
|
|
|
cArg += letter
|
|
|
|
args.append(cArg)
|
|
|
|
return args
|
|
|
|
def recv(conn,l):
|
|
start = time.process_time()
|
|
timeo = conn.gettimeout()
|
|
bytes = b""
|
|
while l > 0:
|
|
b = conn.recv(l)
|
|
if b == b"": raise ConnectionResetError
|
|
if time.process_time() - start > timeo: raise TimeoutError
|
|
bytes += b
|
|
l -= len(b)
|
|
return bytes
|
|
|
|
def getResponse(connection,maxLength = 0):
|
|
data = b''
|
|
data = recv(connection,4)
|
|
if not data: return False
|
|
nul = recv(connection,1)
|
|
if not nul: return False
|
|
if nul != b"\x00": return False
|
|
requestLength = int.from_bytes(data,"big")
|
|
if maxLength != 0 and requestLength > maxLength: return False
|
|
return recv(connection,requestLength)
|
|
|
|
def sendResponse(connection,data):
|
|
connection.sendall(len(data).to_bytes(4,"big") + b"\x00" + data)
|
|
|
|
def stringToAddressTuple(addr):
|
|
rtn = addr.rsplit(":",1)
|
|
rtn[1] = int(rtn[1])
|
|
rtn = tuple(rtn)
|
|
return rtn
|
|
|
|
def main():
|
|
global serverAddr, useSSL, sslIgnoreCert, connection
|
|
serverAddr = stringToAddressTuple(sys.argv[1])
|
|
if useSSL: import ssl
|
|
|
|
eprint("Connecting to server...")
|
|
connection.settimeout(timeout)
|
|
connection.connect(serverAddr)
|
|
if useSSL:
|
|
eprint("Performing SSL handshake...")
|
|
if sys.version_info >= (3,10):
|
|
proto = ssl.PROTOCOL_TLS_CLIENT
|
|
else:
|
|
proto = ssl.PROTOCOL_TLS
|
|
|
|
ctx = ssl.SSLContext(proto)
|
|
if sslIgnoreCert:
|
|
ctx.check_hostname = False
|
|
ctx.verify_mode = ssl.CERT_NONE
|
|
|
|
connection = ctx.wrap_socket(
|
|
connection,
|
|
server_side = False
|
|
)
|
|
|
|
eprint("Sending payload...")
|
|
connection.sendall("\n\n".encode("ascii"))
|
|
sendResponse(connection,sys.argv[2].encode("utf-8"))
|
|
|
|
cmd = commandToList(sys.argv[2])
|
|
args = {}
|
|
for arg in cmd[1:]:
|
|
argSplit = arg.split("=",1)
|
|
args[argSplit[0]] = argSplit[1]
|
|
cmd = cmd[0]
|
|
|
|
if cmd == "watch":
|
|
try:
|
|
eprint("Receiving data...")
|
|
while True:
|
|
data = connection.recv(bufferSize)
|
|
if data == b"":
|
|
eprint("Connection closed.")
|
|
return
|
|
unbufferedStdout.write(data)
|
|
except:
|
|
connection.close()
|
|
raise
|
|
|
|
if cmd == "broadcast":
|
|
try:
|
|
eprint("Sending data...")
|
|
while True:
|
|
data = sys.stdin.buffer.read(bufferSizeStdin)
|
|
connection.sendall(data)
|
|
except:
|
|
connection.close()
|
|
raise
|
|
|
|
if __name__ == '__main__':
|
|
main()
|