A resposta do @ghoti funcionou bem e eu provavelmente vou continuar usando o stunnel como sugerido, mas esta questão me incomodou, então vou expandir o comentário de @JanDvorak, que afirmou ter feito alguns experimentos sem entrar em mais detalhes.
Eu usei o seguinte servidor websocket python, derivado do link
import struct
import SocketServer
from base64 import b64encode
from hashlib import sha1
from mimetools import Message
from StringIO import StringIO
class WebSocketsHandler(SocketServer.StreamRequestHandler):
magic = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
def setup(self):
SocketServer.StreamRequestHandler.setup(self)
print "connection established", self.client_address
def handle(self):
data = self.request.recv(1024).strip()
headers = Message(StringIO(data.split('\r\n', 1)[1]))
if headers.get("Upgrade", None) != "websocket":
return
print 'Handshaking...'
key = headers['Sec-WebSocket-Key']
digest = b64encode(sha1(key + self.magic).hexdigest().decode('hex'))
response = 'HTTP/1.1 101 Switching Protocols\r\n'
response += 'Upgrade: websocket\r\n'
response += 'Connection: Upgrade\r\n'
response += 'Sec-WebSocket-Accept: %s\r\n\r\n' % digest
self.request.send(response)
length = ord(self.rfile.read(2)[1]) & 127
if length == 126:
length = struct.unpack(">H", self.rfile.read(2))[0]
elif length == 127:
length = struct.unpack(">Q", self.rfile.read(8))[0]
masks = [ord(byte) for byte in self.rfile.read(4)]
decoded = ""
for char in self.rfile.read(length):
decoded += chr(ord(char) ^ masks[len(decoded) % 4])
print decoded
self.request.send(chr(129))
length = len(decoded)
if length <= 125:
self.request.send(chr(length))
elif length >= 126 and length <= 65535:
self.request.send(126)
self.request.send(struct.pack(">H", length))
else:
self.request.send(127)
self.request.send(struct.pack(">Q", length))
self.request.send(decoded)
self.finish()
if __name__ == "__main__":
server = SocketServer.TCPServer(
("localhost", 9000), WebSocketsHandler)
try:
server.serve_forever()
except KeyboardInterrupt:
print "Got ^C"
server.server_close();
print "bye!"
Combinei com o seguinte html que foi emprestado do link
<!DOCTYPE html>
<meta charset="utf-8" />
<title>WebSocket Test</title>
<script language="javascript" type="text/javascript">
var wsUri = "ws://localhost:9000/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onMessage(evt) {
writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
websocket.close();
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id="output"></div>
</html>
Isso funcionou bem, então coloquei no meio com a seguinte entrada de configuração:
ListenHTTP
Address 127.0.0.1
Port 9999
Service
BackEnd
Address 127.0.0.1
Port 9000
End
End
End
e mudou a porta no html de 9000 para 9999. Depois dessa mudança, parou de funcionar.
Analisando o tráfego com o wireshark, descobri que o pedido HTTP 101 para mudar o protocolo é encaminhado corretamente. Mas o primeiro pacote websocket subseqüente nunca é encaminhado por libra. Isso é confirmado pela saída print
do script do servidor python, que nunca recebe a mensagem WebSocket rocks
com a libra no meio.
Sempre que libra recebe uma mensagem do WebSocket, ela solta a mensagem e, em vez disso, grava e414 headers: request URI too long
no syslog. Olhando para o código-fonte libra isso parece ser porque libra tenta analisar cabeçalhos HTTP. Para fazer isso, ele primeiro procura por um EOL que não pode ser encontrado na mensagem WebSocket e, portanto, descarta a mensagem como inválida.
Portanto, parece que a resposta para a pergunta do OP é: o pound não pode fazer o WebSocket.
Eu escrevi um e-mail para a lista de mensagens sobre esse problema: link