fstream/fstream-client.py

130 lines
3.2 KiB
Python

#!/usr/bin/env python3
import sys
oldexcepthook = sys.excepthook
def newexcepthook(type,value,traceback):
oldexcepthook(type,value,traceback)
#input("Press ENTER to quit.")
sys.excepthook = newexcepthook
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 threading
import queue
def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs)
bufferSize = 10000 # buffer size in bytes
queueLengthWait = 10 # How many buffers can be in the queue before waiting for it to empty? 0 for infinite, maxAccumulatedData comes into play. Raise for smoother playback, lower for less delay.
maxAccumulatedData = 50*1000*1000 # If queueLengthWait is 0, how much data can be in an outbound thread's queue at maximum before the connection is closed?
timeout = 15 # timeout in seconds
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
class stdoutThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.queue = queue.Queue()
def run(self):
while True:
data = self.queue.get(timeout=timeout)
sys.stdout.buffer.write(data)
class stdinThread(threading.Thread):
def __init__(self,connection):
threading.Thread.__init__(self)
self.queue = queue.Queue(queueLengthWait)
self.connection = connection
def run(self):
try:
while True:
accumulatedData = self.queue.qsize() * bufferSize
if queueLengthWait < 1:
eprint("Accumulated MB: " +str(accumulatedData/1000000))
if accumulatedData > maxAccumulatedData:
eprint("Accumulated data limit reached. Closing.")
self.connection.close()
self.queue = False
return
data = self.queue.get()
self.connection.sendall(data)
except:
self.connection.close()
self.queue = False
raise
def listToCommand(lst):
cmd = ""
for arg in lst:
arg = arg.replace("\\","\\\\")
arg = arg.replace(",","\\,")
#arg = arg.replace('"','\\"')
#if " " in arg: arg = '"' +arg+ '"'
cmd += arg + ","
return cmd[:-1]
def makePayload(lst):
cmdText = listToCommand(lst)
cmdBytes = cmdText.encode("utf-8")
while len(cmdBytes) < 1000:
cmdBytes += b" "
return cmdBytes
def stringToAddressTuple(addr):
rtn = addr.rsplit(":",1)
rtn[1] = int(rtn[1])
rtn = tuple(rtn)
return rtn
def main():
global serverAddr
serverAddr = stringToAddressTuple(sys.argv[1])
eprint("Connecting to server...")
connection.settimeout(timeout)
connection.connect(serverAddr)
eprint("Sending payload...")
connection.sendall(makePayload(sys.argv[2:]))
if sys.argv[2] == "watch":
try:
eprint("Receiving data...")
stdoutThr = stdoutThread()
stdoutThr.start()
while True:
data = connection.recv(bufferSize)
if data == b"": return
stdoutThr.queue.put(data)
except:
connection.close()
raise
if sys.argv[2] == "broadcast":
try:
eprint("Sending data...")
stdinThr = stdinThread(connection)
stdinThr.start()
while True:
data = sys.stdin.buffer.read(bufferSize)
stdinThr.queue.put(data)
except:
connection.close()
raise
if __name__ == '__main__':
main()