summaryrefslogtreecommitdiff
path: root/clickclack.py
blob: 7ba5c9798df7dcc1f50759c0460207160807347d (about) (plain) (blame)
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
#!/usr/bin/env python
# ~/clickclack.py -s -r <(echo 'CAPAB START 1206\r\nSERVER test.1459.io dummy 1S2 :moo.\r\nBURST %s\r\nENDBURST\r\n' socat stdio openssl:127.0.0.1:6005,cert=1S1.cert,key=1S1.key,snihost=chaos.1459.io,commonname=chaos.1459.io

CLIENT_MODE = True
DEBUG = False
CONN_SEND = b''
import select, subprocess, sys, os, tty, termios, time


def parse_irc_line(line):
	source = b''
	cmd = b''
	_trailing = None
	args = []
	if line[0:1] == b':':
		source_pieces = line.split(None, 1)
		source = source_pieces[0][1:]
		line = source_pieces[1]
	if b' :' in line:
		trailing_pieces = line.split(b' :', 1)
		_trailing = trailing_pieces[1]
		line = trailing_pieces[0]
	cmd, *args = line.split()
	if _trailing is not None:
		args.append(_trailing)
	return (source, cmd, args)

def format_irc_args(args):
	if b' ' in args[-1]:
		args[-1] = b':' + args[-1]
	return b' '.join(args)

if __name__ == '__main__':
	argv = sys.argv[1:]
	while len(argv) and len(argv[0]) and argv[0][0] == '-':
		opt = argv[0][1:]
		del argv[0]
		if opt == 's':
			CLIENT_MODE = False
		elif opt == 'r':
			CONN_SEND = argv[0]
			del argv[0]
		elif opt == '-':
			break
		else: #h
			print(f'Usage: {sys.argv[0]} [-h|-s|-r "send on connect file"|--] [socat command...]', file=sys.stderr)
			sys.exit()

	proc = subprocess.Popen(argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	conn_send_cmds = open(CONN_SEND, 'rb').read()
	conn_send_cmds = conn_send_cmds.replace(b'%s', bytes(str(time.time()).encode('ascii')))
	proc.stdin.write(conn_send_cmds)
	proc.stdin.flush()

	os.set_blocking(proc.stdout.fileno(), False)
	os.set_blocking(proc.stderr.fileno(), False)
	child_buffer = bytearray()
	while True:
		if DEBUG: print('selecting')
		rd = select.select([proc.stdout, proc.stderr, sys.stdin.buffer], [], [])[0]
		for f in rd:
			if DEBUG: print(f'reading {f!r}')
			if f is proc.stdout:
				if DEBUG: print(f'writing to stdout')
				child_buffer += f.read()
				child_buffer.replace(b'\r',b'')
				if b'\n' in child_buffer:
					lines = child_buffer.split(b'\n')
					for line in lines[:-1]:
						if line == b'': continue
						source, cmd, args = parse_irc_line(line)
						sys.stdout.buffer.write(line+b'\r\n')
						sys.stdout.buffer.flush()
						if cmd == b'PING':
							if CLIENT_MODE:
								pong = b'PONG %s\r\n' % (format_irc_args(args))
							else:
								pong = b'PONG %s\r\n' % (source)
							sys.stdout.buffer.write(pong)
							sys.stdout.buffer.flush()
							proc.stdin.write(pong)
							proc.stdin.flush()
					child_buffer = lines[-1]
			if f is proc.stderr:
				if DEBUG: print(f'writing to stderr')
				sys.stderr.buffer.write(f.read())
				sys.stderr.buffer.flush()
			if f is sys.stdin.buffer:
				if DEBUG: print(f'writing to child')
				proc.stdin.write(f.readline())
				proc.stdin.flush()