2 # -*- coding: utf-8 -*-
4 # testproto.py - command-line program for testing protocol WeeChat/relay
6 # Copyright (C) 2013 Sebastien Helleu <flashcode@flashtux.org>
8 # This file is part of QWeeChat, a Qt remote GUI for WeeChat.
10 # QWeeChat is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 3 of the License, or
13 # (at your option) any later version.
15 # QWeeChat is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
25 # Usage: python testproto.py [-h] [-v] [-6] <hostname> <port>
27 # With initial commands: echo "init password=xxxx" | python testproto.py localhost 5000
28 # python testproto.py localhost 5000 < commands.txt
32 # 1: missing/invalid arguments (hostname or port)
33 # 2: connection to WeeChat/relay failed
34 # 3: I/O error with WeeChat/relay
37 import os
, sys
, socket
, select
, struct
, time
38 import protocol
# WeeChat/relay protocol
40 options
= { 'h': 0, 'v': 0, '6': 0 }
46 print('\nSyntax: python %s [-h] [-v] [-6] <hostname> <port>\n' % sys
.argv
[0])
47 print(' -h display this help')
48 print(' -v verbose mode: long objects view (two -v: display raw messages)')
49 print(' -6 connect using IPv6')
50 print(' hostname, port hostname (or IP address) and port of machine running WeeChat relay')
52 print('Some commands can be piped to the script, for example:')
53 print(' echo "init password=xxxx" | python %s localhost 5000' % sys
.argv
[0])
54 print(' python %s localhost 5000 < commands.txt' % sys
.argv
[0])
57 def connect(address
, ipv6
):
58 """Connect to WeeChat/relay."""
59 inet
= socket
.AF_INET6
if ipv6
else socket
.AF_INET
62 sock
= socket
.socket(inet
, socket
.SOCK_STREAM
)
67 print('Failed to connect to %s/%d using %s' % (address
[0], address
[1],
68 'IPv4' if inet
== socket
.AF_INET
else 'IPv6'))
70 print('Connected to %s/%d (%s)' % (hostname
, port
,
71 'IPv4' if inet
== socket
.AF_INET
else 'IPv6'))
74 def send(sock
, messages
):
75 """Send a text message to WeeChat/relay."""
78 for msg
in messages
.split('\n'):
81 sock
.sendall(msg
+ '\n')
82 print('\x1b[33m<-- %s\x1b[0m' % msg
)
84 print('Failed to send message')
85 return (False, has_quit
)
86 return (True, has_quit
)
89 """Decode a binary message received from WeeChat/relay."""
92 proto
= protocol
.Protocol()
93 message
= proto
.decode(message
, separator
='\n' if options
['v'] else ', ')
95 if options
['v'] >= 2 and message
.uncompressed
:
97 print('\x1b[32m--> message uncompressed (%d bytes):\n%s\x1b[0m'
98 % (message
.size_uncompressed
,
99 protocol
.hex_and_ascii(message
.uncompressed
, 20)))
100 # display decoded message
101 print('\x1b[32m--> %s\x1b[0m' % message
)
103 print('Error while decoding message from WeeChat')
108 """Main loop: read keyboard, send commands, read socket and decode and display received binary messages."""
111 prompt
= '\x1b[36mrelay> \x1b[0m'
112 sys
.stdout
.write(prompt
)
116 inr
, outr
, exceptr
= select
.select([sys
.stdin
, sock
], [], [], 1)
119 buf
= os
.read(fd
.fileno(), 4096)
123 messages
= message
.split('\n')
124 msgsent
= '\n'.join(messages
[:-1])
126 (send_ok
, has_quit
) = send(sock
, msgsent
)
131 message
= messages
[-1]
132 sys
.stdout
.write(prompt
+ message
)
138 while len(recvbuf
) >= 4:
140 length
= struct
.unpack('>i', recvbuf
[0:4])[0]
141 if len(recvbuf
) < length
:
142 # partial message, just wait for end of message
144 # more than one message?
145 if length
< len(recvbuf
):
146 # save beginning of another message
147 remainder
= recvbuf
[length
:]
148 recvbuf
= recvbuf
[0:length
]
149 if not decode(recvbuf
):
155 sys
.stdout
.write(prompt
+ message
)
160 # display help if arguments are missing
161 if len(sys
.argv
) < 3:
165 # read command line arguments
167 for arg
in sys
.argv
[1:]:
170 options
[opt
] = options
.get(opt
, 0) + 1
176 print('Invalid arguments')
183 # connect to WeeChat/relay
184 (sock
, inet
) = connect((hostname
, port
), options
['6'])
188 # send commands from standard input if some data is available
190 inr
, outr
, exceptr
= select
.select([sys
.stdin
], [], [], 0)
192 data
= os
.read(sys
.stdin
.fileno(), 4096)
194 (send_ok
, has_quit
) = send(sock
, data
.strip())
198 # open stdin to read user commands
199 sys
.stdin
= open('/dev/tty')
201 # main loop (wait commands, display messages received)