relay: add experimental websocket server support (RFC 6455) for irc and weechat protocols, new option relay.network.websocket_allowed_origins
It is a partial implementation of RFC 6455: fragmentation and control frames are not yet supported. Text and binary frames are supported.v2.8-utf8proc
parent
eb11921f16
commit
c2aeb69c46
|
@ -1,7 +1,7 @@
|
|||
WeeChat ChangeLog
|
||||
=================
|
||||
Sébastien Helleu <flashcode@flashtux.org>
|
||||
v0.4.1-dev, 2013-02-07
|
||||
v0.4.1-dev, 2013-02-10
|
||||
|
||||
|
||||
Version 0.4.1 (under dev!)
|
||||
|
@ -22,6 +22,8 @@ Version 0.4.1 (under dev!)
|
|||
* irc: add color in output of /names when result is on server buffer (channel
|
||||
not joined) (bug #38070)
|
||||
* perl: simplify code to load scripts
|
||||
* relay: add websocket server support (RFC 6455) for irc and weechat protocols,
|
||||
new option relay.network.websocket_allowed_origins
|
||||
* relay: add options "buffers" and "upgrade" for commands sync/desync in weechat
|
||||
protocol
|
||||
* relay: fix commands sync/desync in weechat protocol (bug #38215)
|
||||
|
|
|
@ -113,3 +113,8 @@
|
|||
** Typ: Zeichenkette
|
||||
** Werte: beliebige Zeichenkette (Standardwert: `"%h/ssl/relay.pem"`)
|
||||
|
||||
* [[option_relay.network.websocket_allowed_origins]] *relay.network.websocket_allowed_origins*
|
||||
** Beschreibung: `regular expression with origins allowed in websockets (case insensitive, use "(?-i)" at beginning to make it case sensitive), example: "^http://(www\.)?example\.(com|org)"`
|
||||
** Typ: Zeichenkette
|
||||
** Werte: beliebige Zeichenkette (Standardwert: `""`)
|
||||
|
||||
|
|
|
@ -2403,6 +2403,29 @@ um dann die Relay-Verbindung, mit SSL Verschlüsselung, anzulegen:
|
|||
/relay add ssl.weechat 9001
|
||||
----------------------------------------
|
||||
|
||||
// TRANSLATION MISSING
|
||||
[[relay_websocket]]
|
||||
Websocket
|
||||
^^^^^^^^^
|
||||
|
||||
WebSocket protocol (http://tools.ietf.org/html/rfc6455[RFC 6455]) is supported
|
||||
in Relay plugin for all protocols.
|
||||
|
||||
The WebSocket handshake is automatically detected and socket becomes ready for
|
||||
WebSocket if required headers are found in handshake and if origin is allowed
|
||||
(see option
|
||||
<<option_relay.network.websocket_allowed_origins,relay.network.websocket_allowed_origins>>).
|
||||
|
||||
A WebSocket can be opened in a HTML5 with a single line of JavaScript:
|
||||
|
||||
[source,js]
|
||||
----------------------------------------
|
||||
websocket = new WebSocket("ws://server.com:5000/weechat");
|
||||
----------------------------------------
|
||||
|
||||
The port (5000 in example) is the port defined in Relay plugin.
|
||||
The URI must always ends with "/weechat" (for both IRC and WeeChat protocols).
|
||||
|
||||
[[rmodifier_plugin]]
|
||||
Rmodifier Erweiterung
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -113,3 +113,8 @@
|
|||
** type: string
|
||||
** values: any string (default value: `"%h/ssl/relay.pem"`)
|
||||
|
||||
* [[option_relay.network.websocket_allowed_origins]] *relay.network.websocket_allowed_origins*
|
||||
** description: `regular expression with origins allowed in websockets (case insensitive, use "(?-i)" at beginning to make it case sensitive), example: "^http://(www\.)?example\.(com|org)"`
|
||||
** type: string
|
||||
** values: any string (default value: `""`)
|
||||
|
||||
|
|
|
@ -246,6 +246,7 @@ Plugins
|
|||
| relay-raw.c | Relay raw buffer
|
||||
| relay-server.c | Relay server
|
||||
| relay-upgrade.c | Save/restore relay data when upgrading WeeChat
|
||||
| relay-websocket.c | Websocket server functions for relay (RFC 6455)
|
||||
| irc/ | IRC proxy
|
||||
| relay-irc.c | Main IRC proxy functions
|
||||
| weechat/ | Relay for remote interface
|
||||
|
|
|
@ -2354,6 +2354,28 @@ And then add relay with SSL, for example:
|
|||
/relay add ssl.weechat 9001
|
||||
----------------------------------------
|
||||
|
||||
[[relay_websocket]]
|
||||
Websocket
|
||||
^^^^^^^^^
|
||||
|
||||
WebSocket protocol (http://tools.ietf.org/html/rfc6455[RFC 6455]) is supported
|
||||
in Relay plugin for all protocols.
|
||||
|
||||
The WebSocket handshake is automatically detected and socket becomes ready for
|
||||
WebSocket if required headers are found in handshake and if origin is allowed
|
||||
(see option
|
||||
<<option_relay.network.websocket_allowed_origins,relay.network.websocket_allowed_origins>>).
|
||||
|
||||
A WebSocket can be opened in a HTML5 with a single line of JavaScript:
|
||||
|
||||
[source,js]
|
||||
----------------------------------------
|
||||
websocket = new WebSocket("ws://server.com:5000/weechat");
|
||||
----------------------------------------
|
||||
|
||||
The port (5000 in example) is the port defined in Relay plugin.
|
||||
The URI must always ends with "/weechat" (for both IRC and WeeChat protocols).
|
||||
|
||||
[[rmodifier_plugin]]
|
||||
Rmodifier plugin
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -113,3 +113,8 @@
|
|||
** type: chaîne
|
||||
** valeurs: toute chaîne (valeur par défaut: `"%h/ssl/relay.pem"`)
|
||||
|
||||
* [[option_relay.network.websocket_allowed_origins]] *relay.network.websocket_allowed_origins*
|
||||
** description: `expression régulière avec les origines autorisées dans les websockets (insensible à la casse, utilisez "(?-i)" en début de chaîne pour la rendre insensible à la casse), exemple: "^http://(www\.)?example\.(com|org)"`
|
||||
** type: chaîne
|
||||
** valeurs: toute chaîne (valeur par défaut: `""`)
|
||||
|
||||
|
|
|
@ -2428,6 +2428,30 @@ Et ajoutez le relai avec SSL, par exemple :
|
|||
/relay add ssl.weechat 9001
|
||||
----------------------------------------
|
||||
|
||||
[[relay_websocket]]
|
||||
Websocket
|
||||
^^^^^^^^^
|
||||
|
||||
Le protocole WebSocket (http://tools.ietf.org/html/rfc6455[RFC 6455]) est
|
||||
supporté dans l'extension Relay pour tous les protocoles.
|
||||
|
||||
La poignée de main ("handshake") WebSocket est automatiquement détectée et le
|
||||
socket devient prêt pour WebSocket si les en-tête requis sont trouvés dans la
|
||||
poignée de main et si l'origine est autorisée (voir l'option
|
||||
<<option_relay.network.websocket_allowed_origins,relay.network.websocket_allowed_origins>>).
|
||||
|
||||
Un WebSocket peut être ouvert dans une page HTML5 avec une seule ligne de
|
||||
JavaScript :
|
||||
|
||||
[source,js]
|
||||
----------------------------------------
|
||||
websocket = new WebSocket("ws://server.com:5000/weechat");
|
||||
----------------------------------------
|
||||
|
||||
Le port (5000 dans l'exemple) est le port défini dans l'extension Relay.
|
||||
L'URI doit toujours se terminer par "/weechat" (pour les protocoles IRC et
|
||||
WeeChat).
|
||||
|
||||
[[rmodifier_plugin]]
|
||||
Extension Rmodifier
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -113,3 +113,8 @@
|
|||
** tipo: stringa
|
||||
** valori: qualsiasi stringa (valore predefinito: `"%h/ssl/relay.pem"`)
|
||||
|
||||
* [[option_relay.network.websocket_allowed_origins]] *relay.network.websocket_allowed_origins*
|
||||
** descrizione: `regular expression with origins allowed in websockets (case insensitive, use "(?-i)" at beginning to make it case sensitive), example: "^http://(www\.)?example\.(com|org)"`
|
||||
** tipo: stringa
|
||||
** valori: qualsiasi stringa (valore predefinito: `""`)
|
||||
|
||||
|
|
|
@ -2416,6 +2416,29 @@ E poi aggiungere il relay con SSL, ad esempio:
|
|||
/relay add ssl.weechat 9001
|
||||
----------------------------------------
|
||||
|
||||
// TRANSLATION MISSING
|
||||
[[relay_websocket]]
|
||||
Websocket
|
||||
^^^^^^^^^
|
||||
|
||||
WebSocket protocol (http://tools.ietf.org/html/rfc6455[RFC 6455]) is supported
|
||||
in Relay plugin for all protocols.
|
||||
|
||||
The WebSocket handshake is automatically detected and socket becomes ready for
|
||||
WebSocket if required headers are found in handshake and if origin is allowed
|
||||
(see option
|
||||
<<option_relay.network.websocket_allowed_origins,relay.network.websocket_allowed_origins>>).
|
||||
|
||||
A WebSocket can be opened in a HTML5 with a single line of JavaScript:
|
||||
|
||||
[source,js]
|
||||
----------------------------------------
|
||||
websocket = new WebSocket("ws://server.com:5000/weechat");
|
||||
----------------------------------------
|
||||
|
||||
The port (5000 in example) is the port defined in Relay plugin.
|
||||
The URI must always ends with "/weechat" (for both IRC and WeeChat protocols).
|
||||
|
||||
[[rmodifier_plugin]]
|
||||
Plugin Rmodifier
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -113,3 +113,8 @@
|
|||
** タイプ: 文字列
|
||||
** 値: 未制約文字列 (デフォルト値: `"%h/ssl/relay.pem"`)
|
||||
|
||||
* [[option_relay.network.websocket_allowed_origins]] *relay.network.websocket_allowed_origins*
|
||||
** 説明: `regular expression with origins allowed in websockets (case insensitive, use "(?-i)" at beginning to make it case sensitive), example: "^http://(www\.)?example\.(com|org)"`
|
||||
** タイプ: 文字列
|
||||
** 値: 未制約文字列 (デフォルト値: `""`)
|
||||
|
||||
|
|
|
@ -2270,6 +2270,29 @@ WeeChat が既に起動している場合、
|
|||
/relay add ssl.weechat 9001
|
||||
----------------------------------------
|
||||
|
||||
// TRANSLATION MISSING
|
||||
[[relay_websocket]]
|
||||
Websocket
|
||||
^^^^^^^^^
|
||||
|
||||
WebSocket protocol (http://tools.ietf.org/html/rfc6455[RFC 6455]) is supported
|
||||
in Relay plugin for all protocols.
|
||||
|
||||
The WebSocket handshake is automatically detected and socket becomes ready for
|
||||
WebSocket if required headers are found in handshake and if origin is allowed
|
||||
(see option
|
||||
<<option_relay.network.websocket_allowed_origins,relay.network.websocket_allowed_origins>>).
|
||||
|
||||
A WebSocket can be opened in a HTML5 with a single line of JavaScript:
|
||||
|
||||
[source,js]
|
||||
----------------------------------------
|
||||
websocket = new WebSocket("ws://server.com:5000/weechat");
|
||||
----------------------------------------
|
||||
|
||||
The port (5000 in example) is the port defined in Relay plugin.
|
||||
The URI must always ends with "/weechat" (for both IRC and WeeChat protocols).
|
||||
|
||||
[[rmodifier_plugin]]
|
||||
=== Rmodifier プラグイン ===
|
||||
|
||||
|
|
|
@ -217,6 +217,8 @@
|
|||
./src/plugins/relay/relay-server.h
|
||||
./src/plugins/relay/relay-upgrade.c
|
||||
./src/plugins/relay/relay-upgrade.h
|
||||
./src/plugins/relay/relay-websocket.c
|
||||
./src/plugins/relay/relay-websocket.h
|
||||
./src/plugins/relay/irc/relay-irc.c
|
||||
./src/plugins/relay/irc/relay-irc.h
|
||||
./src/plugins/relay/weechat/relay-weechat.c
|
||||
|
|
20
po/cs.po
20
po/cs.po
|
@ -20,7 +20,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-01-20 12:07+0100\n"
|
||||
"Last-Translator: Jiri Golembiovsky <golemj@gmail.com>\n"
|
||||
"Language-Team: weechat-dev <weechat-dev@nongnu.org>\n"
|
||||
|
@ -7684,6 +7684,18 @@ msgstr "%s%s: čtu data ze soketu: chyba %d %s"
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s%s: TLS handshake selhal"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s%s: TLS handshake selhal"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s%s: adresa \"%s\" nenalezena"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s%s: čtu data ze soketu: chyba %d %s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr "%s%s: čtu data ze soketu: chyba %d %s"
|
||||
|
@ -7936,6 +7948,12 @@ msgid ""
|
|||
"file with SSL certificate and private key (for serving clients with SSL)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr "maximální počet řádků v historii bufferu (0 = nekonečně)"
|
||||
|
|
23
po/de.po
23
po/de.po
|
@ -22,7 +22,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-04 08:34+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-01-20 12:07+0100\n"
|
||||
"Last-Translator: Nils Görs <weechatter@arcor.de>\n"
|
||||
"Language-Team: German <weechatter@arcor.de>\n"
|
||||
|
@ -8372,6 +8372,18 @@ msgstr "%s%s: TLS Handshake fehlgeschlagen für Client %s%s%s: Fehler %d %s"
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s%s: TLS Handshake Zeitüberschreitung für Client %s%s%s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s%s: TLS Handshake Zeitüberschreitung für Client %s%s%s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s%s: IP Adresse \"%s\" für Relay nicht gültig"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s%s: Fehler beim Senden von Daten an den Client %d (%s)"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr "%s%s: lese Daten von Socket für Client %s%s%s: Fehler %d %s"
|
||||
|
@ -8653,6 +8665,12 @@ msgstr ""
|
|||
"Datei mit SSL Zertifikat und privatem Schlüssel (zur Nutzung von Clients mit "
|
||||
"SSL)"
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr ""
|
||||
"maximale Anzahl an Zeilen im Verlaufsspeicher. Dies gilt für jeden IRC "
|
||||
|
@ -10316,9 +10334,6 @@ msgstr "Konstanten"
|
|||
#~ msgid "display message when (un)marking as away"
|
||||
#~ msgstr "bei Abwesenheit und Rückkehr eine Nachricht anzeigen"
|
||||
|
||||
#~ msgid "%s%s: error sending data to client %d (%s)"
|
||||
#~ msgstr "%s%s: Fehler beim Senden von Daten an den Client %d (%s)"
|
||||
|
||||
#~ msgid "display channel modes in \"buffer_name\" bar item"
|
||||
#~ msgstr "zeigt die Channel-Modi mittels \"buffer_name\" in der Bar-Item an"
|
||||
|
||||
|
|
20
po/es.po
20
po/es.po
|
@ -22,7 +22,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-01-20 12:07+0100\n"
|
||||
"Last-Translator: Elián Hanisch <lambdae2@gmail.com>\n"
|
||||
"Language-Team: weechat-dev <weechat-dev@nongnu.org>\n"
|
||||
|
@ -7929,6 +7929,18 @@ msgstr "%s%s: saludo TLS falló para el cliente %s%s%s: error %d %s"
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s%s: agotado el tiempo de espera del saludo TLS del cliente %s%s%s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s%s: agotado el tiempo de espera del saludo TLS del cliente %s%s%s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s%s: dirección IP \"%s\" no permitida por el repetidor"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s%s: leyendo datos en socket para el cliente %s%s%s: error %d %s"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr "%s%s: leyendo datos en socket para el cliente %s%s%s: error %d %s"
|
||||
|
@ -8197,6 +8209,12 @@ msgid ""
|
|||
"file with SSL certificate and private key (for serving clients with SSL)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr ""
|
||||
"número máximo de líneas del registro por cada canal IRC (0 = ilimitado)"
|
||||
|
|
26
po/fr.po
26
po/fr.po
|
@ -21,8 +21,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"PO-Revision-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-02-10 08:29+0100\n"
|
||||
"Last-Translator: Sebastien Helleu <flashcode@flashtux.org>\n"
|
||||
"Language-Team: weechat-dev <weechat-dev@nongnu.org>\n"
|
||||
"Language: French\n"
|
||||
|
@ -8143,6 +8143,19 @@ msgstr ""
|
|||
"%s%s: délai maximum dépassé pour la poignée de main (handshake) de TLS pour "
|
||||
"le client %s%s%s"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr ""
|
||||
"%s%s: poignée de main (handshake) websocket invalide pour le client %s%s%s"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s%s: origine \"%s\" non autorisée pour le websocket"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s%s: erreur de décodage d'un message websocket pour le client %s%s%s"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr ""
|
||||
|
@ -8422,6 +8435,15 @@ msgstr ""
|
|||
"fichier avec le certificat et la clé privée SSL (pour servir les clients "
|
||||
"avec SSL)"
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
"expression régulière avec les origines autorisées dans les websockets "
|
||||
"(insensible à la casse, utilisez \"(?-i)\" en début de chaîne pour la rendre "
|
||||
"insensible à la casse), exemple: \"^http://(www\\.)?example\\.(com|org)\""
|
||||
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr ""
|
||||
"nombre maximum de lignes dans l'historique par canal IRC (0 = sans limite)"
|
||||
|
|
20
po/hu.po
20
po/hu.po
|
@ -20,7 +20,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-01-20 12:07+0100\n"
|
||||
"Last-Translator: Andras Voroskoi <voroskoi@frugalware.org>\n"
|
||||
"Language-Team: weechat-dev <weechat-dev@nongnu.org>\n"
|
||||
|
@ -7183,6 +7183,18 @@ msgstr "%s adatküldési hiba az IRC szerveren\n"
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s gnutls kézfogás sikertelen\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s gnutls kézfogás sikertelen\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s cím \"%s\" nem található\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s adatküldési hiba az IRC szerveren\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr "%s adatküldési hiba az IRC szerveren\n"
|
||||
|
@ -7414,6 +7426,12 @@ msgid ""
|
|||
"file with SSL certificate and private key (for serving clients with SSL)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr ""
|
||||
|
|
20
po/it.po
20
po/it.po
|
@ -20,7 +20,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-03 16:17+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-02-03 12:13+0100\n"
|
||||
"Last-Translator: Marco Paolone <marcopaolone@gmail.com>\n"
|
||||
"Language-Team: weechat-dev <weechat-dev@nongnu.org>\n"
|
||||
|
@ -7945,6 +7945,18 @@ msgstr "%s%s: handshake TLS fallito per il client %s%s%s: errore %d %s"
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s%s: timeout per l'handshake per il client %s%s%s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s%s: timeout per l'handshake per il client %s%s%s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s%s: indirizzo IP \"%s\" non consentito per il relay"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s%s: lettura dei dati sul socket per il client %s%s%s: errore %d %s"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr "%s%s: lettura dei dati sul socket per il client %s%s%s: errore %d %s"
|
||||
|
@ -8223,6 +8235,12 @@ msgstr ""
|
|||
"file con il certificato SSL e la chiave privata (per servire i client con "
|
||||
"SSL)"
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr ""
|
||||
"numero massimo di righe nella cronologia per canale IRC (0 = nessun limite)"
|
||||
|
|
21
po/ja.po
21
po/ja.po
|
@ -20,7 +20,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-01-20 12:07+0100\n"
|
||||
"Last-Translator: AYANOKOUZI, Ryuunosuke <i38w7i3@yahoo.co.jp>\n"
|
||||
"Language-Team: Japanese <https://github.com/l/WeeChat>\n"
|
||||
|
@ -7860,6 +7860,19 @@ msgstr "%s%s: クライアント %s%s%s との TLS ハンドシェイクが失
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s%s: クライアント %s%s%s との TLS ハンドシェイクがタイムアウト"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s%s: クライアント %s%s%s との TLS ハンドシェイクがタイムアウト"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s%s: IP アドレス \"%s\" はリレーの許可がありません"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr ""
|
||||
"%s%s: クライアント %s%s%s のソケットからデータを読み取り中: エラー %d %s"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr ""
|
||||
|
@ -8130,6 +8143,12 @@ msgid ""
|
|||
"file with SSL certificate and private key (for serving clients with SSL)"
|
||||
msgstr "SSL 証明書と秘密鍵のファイル (SSL 接続を利用するクライアント用)"
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr "IRC チャンネルごとのバックログの最大行数 (0 = 制限無し)"
|
||||
|
||||
|
|
20
po/pl.po
20
po/pl.po
|
@ -21,7 +21,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-01-20 12:08+0100\n"
|
||||
"Last-Translator: Krzysztof Korościk <soltys@szluug.org>\n"
|
||||
"Language-Team: weechat-dev <weechat-dev@nongnu.org>\n"
|
||||
|
@ -8005,6 +8005,18 @@ msgstr ""
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s%s: upłynął czas na nawiązanie połączenia TLS dla klienta %s%s%s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s%s: upłynął czas na nawiązanie połączenia TLS dla klienta %s%s%s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s%s: adres IP \"%s\" nie posiada zezwolenia na połączenie"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s%s: odczyt danych z gniazda dla klienta %s%s%s: błąd %d %s"
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr "%s%s: odczyt danych z gniazda dla klienta %s%s%s: błąd %d %s"
|
||||
|
@ -8279,6 +8291,12 @@ msgstr ""
|
|||
"plik z certyfikatem SSL i kluczem prywatnym (dla obsługi klientów poprzez "
|
||||
"SSL)"
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr ""
|
||||
"maksymalna ilość linii w historii każdego bufora dla kanału IRC (0 = bez "
|
||||
|
|
20
po/pt_BR.po
20
po/pt_BR.po
|
@ -21,7 +21,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-01-20 12:08+0100\n"
|
||||
"Last-Translator: Sergio Durigan Junior <sergiosdj@gmail.com>\n"
|
||||
"Language-Team: weechat-dev <weechat-dev@nongnu.org>\n"
|
||||
|
@ -7339,6 +7339,18 @@ msgstr "%s%s: lendo dados no socket: erro %d %s"
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s%s: handshake TLS falhou"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s%s: handshake TLS falhou"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s%s: endereço IP \"%s\" não permitido para relay"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s%s: lendo dados no socket: erro %d %s"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr "%s%s: lendo dados no socket: erro %d %s"
|
||||
|
@ -7575,6 +7587,12 @@ msgid ""
|
|||
"file with SSL certificate and private key (for serving clients with SSL)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr "número máximo de linhas no histórico por buffer (0 = ilimitado)"
|
||||
|
|
20
po/ru.po
20
po/ru.po
|
@ -21,7 +21,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: WeeChat 0.4.1-dev\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: 2013-01-20 12:08+0100\n"
|
||||
"Last-Translator: Aleksey V Zapparov AKA ixti <ixti@member.fsf.org>\n"
|
||||
"Language-Team: weechat-dev <weechat-dev@nongnu.org>\n"
|
||||
|
@ -7209,6 +7209,18 @@ msgstr "%s ошибка при отправке данных IRC серверу\
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr "%s инициализация gnutls не удалось\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr "%s инициализация gnutls не удалось\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr "%s адрес \"%s\" не найден\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr "%s ошибка при отправке данных IRC серверу\n"
|
||||
|
||||
#, fuzzy, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr "%s ошибка при отправке данных IRC серверу\n"
|
||||
|
@ -7440,6 +7452,12 @@ msgid ""
|
|||
"file with SSL certificate and private key (for serving clients with SSL)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr "максимальное количество команд в истории (0 = не ограничено)"
|
||||
|
|
|
@ -210,6 +210,8 @@ SET(WEECHAT_SOURCES
|
|||
./src/plugins/relay/relay-server.h
|
||||
./src/plugins/relay/relay-upgrade.c
|
||||
./src/plugins/relay/relay-upgrade.h
|
||||
./src/plugins/relay/relay-websocket.c
|
||||
./src/plugins/relay/relay-websocket.h
|
||||
./src/plugins/relay/irc/relay-irc.c
|
||||
./src/plugins/relay/irc/relay-irc.h
|
||||
./src/plugins/relay/weechat/relay-weechat.c
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: flashcode@flashtux.org\n"
|
||||
"POT-Creation-Date: 2013-02-01 11:12+0100\n"
|
||||
"POT-Creation-Date: 2013-02-10 20:17+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -6318,6 +6318,18 @@ msgstr ""
|
|||
msgid "%s%s: TLS handshake timeout for client %s%s%s"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: invalid websocket handshake received for client %s%s%s"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: origin \"%s\" not allowed for websocket"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: error decoding websocket frame for client %s%s%s"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s: reading data on socket for client %s%s%s: error %d %s"
|
||||
msgstr ""
|
||||
|
@ -6534,6 +6546,12 @@ msgid ""
|
|||
"file with SSL certificate and private key (for serving clients with SSL)"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"regular expression with origins allowed in websockets (case insensitive, use "
|
||||
"\"(?-i)\" at beginning to make it case sensitive), example: \"^http://(www"
|
||||
"\\.)?example\\.(com|org)\""
|
||||
msgstr ""
|
||||
|
||||
msgid "maximum number of lines in backlog per IRC channel (0 = unlimited)"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ relay-info.c relay-info.h
|
|||
relay-network.c relay-network.h
|
||||
relay-raw.c relay-raw.h
|
||||
relay-server.c relay-server.h
|
||||
relay-upgrade.c relay-upgrade.h)
|
||||
relay-upgrade.c relay-upgrade.h
|
||||
relay-websocket.c relay-websocket.h)
|
||||
SET_TARGET_PROPERTIES(relay PROPERTIES PREFIX "")
|
||||
|
||||
SET (LINK_LIBS)
|
||||
|
|
|
@ -52,7 +52,9 @@ relay_la_SOURCES = relay.c \
|
|||
relay-server.c \
|
||||
relay-server.h \
|
||||
relay-upgrade.c \
|
||||
relay-upgrade.h
|
||||
relay-upgrade.h \
|
||||
relay-websocket.c \
|
||||
relay-websocket.h
|
||||
|
||||
relay_la_LDFLAGS = -module
|
||||
relay_la_LIBADD = $(RELAY_LFLAGS) $(ZLIB_LFLAGS) $(GNUTLS_LFLAGS)
|
||||
|
|
|
@ -231,13 +231,12 @@ relay_irc_sendf (struct t_relay_client *client, const char *format, ...)
|
|||
str_message = weechat_hashtable_get (hashtable_out, hash_key);
|
||||
if (!str_message)
|
||||
break;
|
||||
relay_raw_print (client, RELAY_RAW_FLAG_SEND, "%s", str_message);
|
||||
length = strlen (str_message) + 16 + 1;
|
||||
message = malloc (length);
|
||||
if (message)
|
||||
{
|
||||
snprintf (message, length, "%s\r\n", str_message);
|
||||
relay_client_send (client, message, strlen (message));
|
||||
relay_client_send (client, message, strlen (message), NULL);
|
||||
free (message);
|
||||
}
|
||||
number++;
|
||||
|
@ -1290,9 +1289,9 @@ relay_irc_recv_command_capab (struct t_relay_client *client,
|
|||
*/
|
||||
|
||||
void
|
||||
relay_irc_recv_one_msg (struct t_relay_client *client, char *data)
|
||||
relay_irc_recv (struct t_relay_client *client, const char *data)
|
||||
{
|
||||
char *pos, str_time[128], str_signal[128], str_server_channel[256];
|
||||
char str_time[128], str_signal[128], str_server_channel[256];
|
||||
char str_command[128], *target, **irc_argv;
|
||||
const char *irc_command, *irc_channel, *irc_args, *irc_args2;
|
||||
int irc_argc, redirect_msg;
|
||||
|
@ -1304,11 +1303,6 @@ relay_irc_recv_one_msg (struct t_relay_client *client, char *data)
|
|||
irc_argv = NULL;
|
||||
irc_argc = 0;
|
||||
|
||||
/* remove \r at the end of message */
|
||||
pos = strchr (data, '\r');
|
||||
if (pos)
|
||||
pos[0] = '\0';
|
||||
|
||||
/* display debug message */
|
||||
if (weechat_relay_plugin->debug >= 2)
|
||||
{
|
||||
|
@ -1320,9 +1314,6 @@ relay_irc_recv_one_msg (struct t_relay_client *client, char *data)
|
|||
data);
|
||||
}
|
||||
|
||||
/* display message in raw buffer */
|
||||
relay_raw_print (client, RELAY_RAW_FLAG_RECV, "%s", data);
|
||||
|
||||
/* parse IRC message */
|
||||
hash_parsed = relay_irc_message_parse (data);
|
||||
if (!hash_parsed)
|
||||
|
@ -1707,27 +1698,6 @@ end:
|
|||
weechat_string_free_split (irc_argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads data from a client.
|
||||
*/
|
||||
|
||||
void
|
||||
relay_irc_recv (struct t_relay_client *client, const char *data)
|
||||
{
|
||||
char **items;
|
||||
int items_count, i;
|
||||
|
||||
items = weechat_string_split (data, "\n", 0, 0, &items_count);
|
||||
if (items)
|
||||
{
|
||||
for (i = 0; i < items_count; i++)
|
||||
{
|
||||
relay_irc_recv_one_msg (client, items[i]);
|
||||
}
|
||||
weechat_string_free_split (items);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes connection with client.
|
||||
*/
|
||||
|
|
|
@ -63,7 +63,7 @@ enum t_relay_irc_server_capab
|
|||
};
|
||||
|
||||
extern void relay_irc_recv (struct t_relay_client *client,
|
||||
const char *data);
|
||||
const char *data);
|
||||
extern void relay_irc_close_connection (struct t_relay_client *client);
|
||||
extern void relay_irc_alloc (struct t_relay_client *client);
|
||||
extern void relay_irc_alloc_with_infolist (struct t_relay_client *client,
|
||||
|
|
|
@ -41,7 +41,9 @@
|
|||
#include "relay-config.h"
|
||||
#include "relay-buffer.h"
|
||||
#include "relay-network.h"
|
||||
#include "relay-raw.h"
|
||||
#include "relay-server.h"
|
||||
#include "relay-websocket.h"
|
||||
|
||||
|
||||
char *relay_client_status_string[] = /* strings for status */
|
||||
|
@ -49,6 +51,9 @@ char *relay_client_status_string[] = /* strings for status */
|
|||
N_("connected"), N_("auth failed"), N_("disconnected")
|
||||
};
|
||||
|
||||
char *relay_client_data_type_string[] = /* strings for data types */
|
||||
{ "text", "binary" };
|
||||
|
||||
struct t_relay_client *relay_clients = NULL;
|
||||
struct t_relay_client *last_relay_client = NULL;
|
||||
int relay_client_count = 0; /* number of clients */
|
||||
|
@ -216,6 +221,168 @@ relay_client_handshake_timer_cb (void *data, int remaining_calls)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reads text data from a client: splits data on '\n' and keep a partial message
|
||||
* if date does not end with '\n'.
|
||||
*/
|
||||
|
||||
void
|
||||
relay_client_recv_text (struct t_relay_client *client, const char *data)
|
||||
{
|
||||
char *new_partial, *raw_msg, **lines, *pos, *tmp, *handshake;
|
||||
int i, num_lines, length, rc;
|
||||
|
||||
if (client->partial_message)
|
||||
{
|
||||
new_partial = realloc (client->partial_message,
|
||||
strlen (client->partial_message) +
|
||||
strlen (data) + 1);
|
||||
if (!new_partial)
|
||||
return;
|
||||
client->partial_message = new_partial;
|
||||
strcat (client->partial_message, data);
|
||||
}
|
||||
else
|
||||
client->partial_message = strdup (data);
|
||||
|
||||
pos = strrchr (client->partial_message, '\n');
|
||||
if (pos)
|
||||
{
|
||||
/* print message in raw buffer */
|
||||
raw_msg = weechat_strndup (client->partial_message,
|
||||
pos - client->partial_message + 1);
|
||||
if (raw_msg)
|
||||
{
|
||||
relay_raw_print (client, RELAY_RAW_FLAG_RECV,
|
||||
raw_msg, strlen (raw_msg) + 1);
|
||||
free (raw_msg);
|
||||
}
|
||||
|
||||
pos[0] = '\0';
|
||||
|
||||
lines = weechat_string_split (client->partial_message, "\n",
|
||||
0, 0, &num_lines);
|
||||
if (lines)
|
||||
{
|
||||
for (i = 0; i < num_lines; i++)
|
||||
{
|
||||
/* remove final '\r' */
|
||||
length = strlen (lines[i]);
|
||||
if ((length > 0) && (lines[i][length - 1] == '\r'))
|
||||
lines[i][length - 1] = '\0';
|
||||
|
||||
/* if websocket is initializing */
|
||||
if (client->websocket == 1)
|
||||
{
|
||||
if (lines[i][0])
|
||||
{
|
||||
/* web socket is initializing, read HTTP headers */
|
||||
relay_websocket_save_header (client, lines[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* empty line means that we have received all HTTP
|
||||
* headers: then we check the validity of websocket, and
|
||||
* if it is OK, we'll do the handshake and answer to the
|
||||
* client
|
||||
*/
|
||||
rc = relay_websocket_client_handshake_valid (client);
|
||||
if (rc == 0)
|
||||
{
|
||||
/* handshake from client is valid */
|
||||
handshake = relay_websocket_build_handshake (client);
|
||||
if (handshake)
|
||||
{
|
||||
relay_client_send (client, handshake,
|
||||
strlen (handshake), NULL);
|
||||
free (handshake);
|
||||
client->websocket = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case -1:
|
||||
relay_websocket_send_http (client,
|
||||
"400 Bad Request");
|
||||
if (weechat_relay_plugin->debug >= 1)
|
||||
{
|
||||
weechat_printf_tags (NULL, "relay_client",
|
||||
_("%s%s: invalid websocket "
|
||||
"handshake received for "
|
||||
"client %s%s%s"),
|
||||
weechat_prefix ("error"),
|
||||
RELAY_PLUGIN_NAME,
|
||||
RELAY_COLOR_CHAT_CLIENT,
|
||||
client->desc,
|
||||
RELAY_COLOR_CHAT);
|
||||
}
|
||||
break;
|
||||
case -2:
|
||||
relay_websocket_send_http (client,
|
||||
"403 Forbidden");
|
||||
if (weechat_relay_plugin->debug >= 1)
|
||||
{
|
||||
weechat_printf_tags (NULL, "relay_client",
|
||||
_("%s%s: origin \"%s\" "
|
||||
"not allowed for websocket"),
|
||||
weechat_prefix ("error"),
|
||||
RELAY_PLUGIN_NAME,
|
||||
weechat_hashtable_get (client->http_headers,
|
||||
"Origin"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
relay_client_set_status (client, RELAY_STATUS_DISCONNECTED);
|
||||
}
|
||||
|
||||
/* remove HTTP headers */
|
||||
weechat_hashtable_free (client->http_headers);
|
||||
client->http_headers = NULL;
|
||||
|
||||
/*
|
||||
* discard all received data after the handshake
|
||||
* received from client, and return immediately
|
||||
*/
|
||||
free (client->partial_message);
|
||||
client->partial_message = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* receive text from client */
|
||||
switch (client->protocol)
|
||||
{
|
||||
case RELAY_PROTOCOL_WEECHAT:
|
||||
relay_weechat_recv (client, lines[i]);
|
||||
break;
|
||||
case RELAY_PROTOCOL_IRC:
|
||||
relay_irc_recv (client, lines[i]);
|
||||
break;
|
||||
case RELAY_NUM_PROTOCOLS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
weechat_string_free_split (lines);
|
||||
}
|
||||
if (pos[1])
|
||||
{
|
||||
tmp = strdup (pos + 1);
|
||||
free (client->partial_message);
|
||||
client->partial_message = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
free (client->partial_message);
|
||||
client->partial_message = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads data from a client.
|
||||
*/
|
||||
|
@ -224,7 +391,8 @@ int
|
|||
relay_client_recv_cb (void *arg_client, int fd)
|
||||
{
|
||||
struct t_relay_client *client;
|
||||
static char buffer[4096 + 2];
|
||||
static char buffer[4096], decoded[4096];
|
||||
const char *ptr_buffer;
|
||||
int num_read;
|
||||
|
||||
/* make C compiler happy */
|
||||
|
@ -245,18 +413,63 @@ relay_client_recv_cb (void *arg_client, int fd)
|
|||
|
||||
if (num_read > 0)
|
||||
{
|
||||
client->bytes_recv += num_read;
|
||||
buffer[num_read] = '\0';
|
||||
switch (client->protocol)
|
||||
ptr_buffer = buffer;
|
||||
|
||||
/*
|
||||
* if we are receiving the first message from client, check if it looks
|
||||
* like a websocket
|
||||
*/
|
||||
if (client->bytes_recv == 0)
|
||||
{
|
||||
case RELAY_PROTOCOL_WEECHAT:
|
||||
relay_weechat_recv (client, buffer);
|
||||
break;
|
||||
case RELAY_PROTOCOL_IRC:
|
||||
relay_irc_recv (client, buffer);
|
||||
break;
|
||||
case RELAY_NUM_PROTOCOLS:
|
||||
break;
|
||||
if (relay_websocket_is_http_get_weechat (buffer))
|
||||
{
|
||||
/*
|
||||
* web socket is just initializing for now, it's not accepted
|
||||
* (we will check later with "http_headers" if web socket is
|
||||
* valid or not)
|
||||
*/
|
||||
client->websocket = 1;
|
||||
client->http_headers = weechat_hashtable_new (32,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
client->bytes_recv += num_read;
|
||||
|
||||
if (client->websocket == 2)
|
||||
{
|
||||
/* websocket used, decode message */
|
||||
if (!relay_websocket_decode_frame ((unsigned char *)buffer, num_read,
|
||||
(unsigned char *)decoded))
|
||||
{
|
||||
/* error when decoding frame: close connection */
|
||||
weechat_printf_tags (NULL, "relay_client",
|
||||
_("%s%s: error decoding websocket frame "
|
||||
"for client %s%s%s"),
|
||||
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
|
||||
RELAY_COLOR_CHAT_CLIENT,
|
||||
client->desc,
|
||||
RELAY_COLOR_CHAT);
|
||||
relay_client_set_status (client, RELAY_STATUS_DISCONNECTED);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
ptr_buffer = decoded;
|
||||
}
|
||||
|
||||
if ((client->websocket == 1)
|
||||
|| (client->recv_data_type == RELAY_CLIENT_DATA_TEXT))
|
||||
{
|
||||
/* websocket initializing or text data for this client */
|
||||
relay_client_recv_text (client, ptr_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* receive buffer as-is (binary data) */
|
||||
/* currently, all supported protocols receive only text, no binary */
|
||||
}
|
||||
relay_buffer_refresh (NULL);
|
||||
}
|
||||
|
@ -310,10 +523,13 @@ relay_client_recv_cb (void *arg_client, int fd)
|
|||
*/
|
||||
|
||||
void
|
||||
relay_client_outqueue_add (struct t_relay_client *client, const char *data,
|
||||
int data_size)
|
||||
relay_client_outqueue_add (struct t_relay_client *client,
|
||||
const char *data, int data_size,
|
||||
int raw_flags[2], const char *raw_message[2],
|
||||
int raw_size[2])
|
||||
{
|
||||
struct t_relay_client_outqueue *new_outqueue;
|
||||
int i;
|
||||
|
||||
if (!client || !data || (data_size <= 0))
|
||||
return;
|
||||
|
@ -329,6 +545,23 @@ relay_client_outqueue_add (struct t_relay_client *client, const char *data,
|
|||
}
|
||||
memcpy (new_outqueue->data, data, data_size);
|
||||
new_outqueue->data_size = data_size;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
new_outqueue->raw_flags[i] = 0;
|
||||
new_outqueue->raw_message[i] = NULL;
|
||||
new_outqueue->raw_size[i] = 0;
|
||||
if (raw_message && raw_message[i] && (raw_size[i] > 0))
|
||||
{
|
||||
new_outqueue->raw_message[i] = malloc (raw_size[i]);
|
||||
if (new_outqueue->raw_message[i])
|
||||
{
|
||||
new_outqueue->raw_flags[i] = raw_flags[i];
|
||||
memcpy (new_outqueue->raw_message[i], raw_message[i],
|
||||
raw_size[i]);
|
||||
new_outqueue->raw_size[i] = raw_size[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new_outqueue->prev_outqueue = client->last_outqueue;
|
||||
new_outqueue->next_outqueue = NULL;
|
||||
|
@ -367,6 +600,10 @@ relay_client_outqueue_free (struct t_relay_client *client,
|
|||
/* free data */
|
||||
if (outqueue->data)
|
||||
free (outqueue->data);
|
||||
if (outqueue->raw_message[0])
|
||||
free (outqueue->raw_message[0]);
|
||||
if (outqueue->raw_message[1])
|
||||
free (outqueue->raw_message[1]);
|
||||
free (outqueue);
|
||||
|
||||
/* set new head */
|
||||
|
@ -389,18 +626,88 @@ relay_client_outqueue_free_all (struct t_relay_client *client)
|
|||
/*
|
||||
* Sends data to client (adds in out queue if it's impossible to send now).
|
||||
*
|
||||
* If "message_raw_buffer" is not NULL, it is used for display in raw buffer
|
||||
* and replaces display of data, which is default.
|
||||
*
|
||||
* Returns number of bytes sent to client, -1 if error.
|
||||
*/
|
||||
|
||||
int
|
||||
relay_client_send (struct t_relay_client *client, const char *data,
|
||||
int data_size)
|
||||
int data_size, const char *message_raw_buffer)
|
||||
{
|
||||
int num_sent;
|
||||
int num_sent, raw_size[2], raw_flags[2], i;
|
||||
char *websocket_frame;
|
||||
unsigned long long length_frame;
|
||||
const char *ptr_data, *raw_msg[2];
|
||||
|
||||
if (client->sock < 0)
|
||||
return -1;
|
||||
|
||||
ptr_data = data;
|
||||
websocket_frame = NULL;
|
||||
|
||||
/* set raw messages */
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
raw_flags[i] = RELAY_RAW_FLAG_SEND;
|
||||
raw_msg[i] = NULL;
|
||||
raw_size[i] = 0;
|
||||
}
|
||||
if (message_raw_buffer)
|
||||
{
|
||||
if (weechat_relay_plugin->debug >= 2)
|
||||
{
|
||||
raw_msg[0] = message_raw_buffer;
|
||||
raw_size[0] = strlen (message_raw_buffer) + 1;
|
||||
raw_msg[1] = data;
|
||||
raw_size[1] = data_size;
|
||||
raw_flags[1] |= RELAY_RAW_FLAG_BINARY;
|
||||
if ((client->websocket == 1)
|
||||
|| (client->send_data_type == RELAY_CLIENT_DATA_TEXT))
|
||||
{
|
||||
raw_size[1]--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
raw_msg[0] = message_raw_buffer;
|
||||
raw_size[0] = strlen (message_raw_buffer) + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
raw_msg[0] = data;
|
||||
raw_size[0] = data_size;
|
||||
if ((client->websocket != 1)
|
||||
&& (client->send_data_type == RELAY_CLIENT_DATA_BINARY))
|
||||
{
|
||||
/*
|
||||
* set binary flag if we send binary to client
|
||||
* (except if websocket == 1, which means that websocket is
|
||||
* initializing, and then we are sending HTTP data, as text)
|
||||
*/
|
||||
raw_flags[0] |= RELAY_RAW_FLAG_BINARY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* count the final '\0' in size */
|
||||
raw_size[0]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if websocket is initialized, encode data in a websocket frame */
|
||||
if (client->websocket == 2)
|
||||
{
|
||||
websocket_frame = relay_websocket_encode_frame (client, data, data_size,
|
||||
&length_frame);
|
||||
if (websocket_frame)
|
||||
{
|
||||
ptr_data = websocket_frame;
|
||||
data_size = length_frame;
|
||||
}
|
||||
}
|
||||
|
||||
num_sent = -1;
|
||||
|
||||
/*
|
||||
|
@ -409,19 +716,28 @@ relay_client_send (struct t_relay_client *client, const char *data,
|
|||
*/
|
||||
if (client->outqueue)
|
||||
{
|
||||
relay_client_outqueue_add (client, data, data_size);
|
||||
relay_client_outqueue_add (client, ptr_data, data_size,
|
||||
raw_flags, raw_msg, raw_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_GNUTLS
|
||||
if (client->ssl)
|
||||
num_sent = gnutls_record_send (client->gnutls_sess, data, data_size);
|
||||
num_sent = gnutls_record_send (client->gnutls_sess, ptr_data, data_size);
|
||||
else
|
||||
#endif
|
||||
num_sent = send (client->sock, data, data_size, 0);
|
||||
num_sent = send (client->sock, ptr_data, data_size, 0);
|
||||
|
||||
if (num_sent >= 0)
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (raw_msg[i])
|
||||
{
|
||||
relay_raw_print (client,
|
||||
raw_flags[i], raw_msg[i], raw_size[i]);
|
||||
}
|
||||
}
|
||||
if (num_sent > 0)
|
||||
{
|
||||
client->bytes_sent += num_sent;
|
||||
|
@ -430,8 +746,9 @@ relay_client_send (struct t_relay_client *client, const char *data,
|
|||
if (num_sent < data_size)
|
||||
{
|
||||
/* some data was not sent, add it to outqueue */
|
||||
relay_client_outqueue_add (client, data + num_sent,
|
||||
data_size - num_sent);
|
||||
relay_client_outqueue_add (client, ptr_data + num_sent,
|
||||
data_size - num_sent,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
else if (num_sent < 0)
|
||||
|
@ -443,7 +760,8 @@ relay_client_send (struct t_relay_client *client, const char *data,
|
|||
|| (num_sent == GNUTLS_E_INTERRUPTED))
|
||||
{
|
||||
/* add message to queue (will be sent later) */
|
||||
relay_client_outqueue_add (client, data, data_size);
|
||||
relay_client_outqueue_add (client, ptr_data, data_size,
|
||||
raw_flags, raw_msg, raw_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -466,7 +784,8 @@ relay_client_send (struct t_relay_client *client, const char *data,
|
|||
if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
|
||||
{
|
||||
/* add message to queue (will be sent later) */
|
||||
relay_client_outqueue_add (client, data, data_size);
|
||||
relay_client_outqueue_add (client, ptr_data, data_size,
|
||||
raw_flags, raw_msg, raw_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -486,6 +805,9 @@ relay_client_send (struct t_relay_client *client, const char *data,
|
|||
}
|
||||
}
|
||||
|
||||
if (websocket_frame)
|
||||
free (websocket_frame);
|
||||
|
||||
return num_sent;
|
||||
}
|
||||
|
||||
|
@ -497,7 +819,7 @@ int
|
|||
relay_client_timer_cb (void *data, int remaining_calls)
|
||||
{
|
||||
struct t_relay_client *ptr_client;
|
||||
int num_sent;
|
||||
int num_sent, i;
|
||||
char *buf;
|
||||
|
||||
/* make C compiler happy */
|
||||
|
@ -527,6 +849,26 @@ relay_client_timer_cb (void *data, int remaining_calls)
|
|||
}
|
||||
if (num_sent >= 0)
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (ptr_client->outqueue->raw_message
|
||||
&& ptr_client->outqueue->raw_message[i])
|
||||
{
|
||||
/*
|
||||
* print raw message and remove it from outqueue
|
||||
* (so that it is displayed only one time, even if
|
||||
* message is sent in many chunks)
|
||||
*/
|
||||
relay_raw_print (ptr_client,
|
||||
ptr_client->outqueue->raw_flags[i],
|
||||
ptr_client->outqueue->raw_message[i],
|
||||
ptr_client->outqueue->raw_size[i]);
|
||||
ptr_client->outqueue->raw_flags[i] = 0;
|
||||
free (ptr_client->outqueue->raw_message[i]);
|
||||
ptr_client->outqueue->raw_message[i] = NULL;
|
||||
ptr_client->outqueue->raw_size[i] = 0;
|
||||
}
|
||||
}
|
||||
if (num_sent > 0)
|
||||
{
|
||||
ptr_client->bytes_sent += num_sent;
|
||||
|
@ -644,6 +986,8 @@ relay_client_new (int sock, const char *address, struct t_relay_server *server)
|
|||
#ifdef HAVE_GNUTLS
|
||||
new_client->hook_timer_handshake = NULL;
|
||||
#endif
|
||||
new_client->websocket = 0;
|
||||
new_client->http_headers = NULL;
|
||||
new_client->address = strdup ((address) ? address : "?");
|
||||
new_client->status = RELAY_STATUS_CONNECTED;
|
||||
new_client->protocol = server->protocol;
|
||||
|
@ -656,6 +1000,22 @@ relay_client_new (int sock, const char *address, struct t_relay_server *server)
|
|||
new_client->last_activity = new_client->start_time;
|
||||
new_client->bytes_recv = 0;
|
||||
new_client->bytes_sent = 0;
|
||||
switch (new_client->protocol)
|
||||
{
|
||||
case RELAY_PROTOCOL_WEECHAT:
|
||||
new_client->recv_data_type = RELAY_CLIENT_DATA_TEXT;
|
||||
new_client->send_data_type = RELAY_CLIENT_DATA_BINARY;
|
||||
break;
|
||||
case RELAY_PROTOCOL_IRC:
|
||||
new_client->recv_data_type = RELAY_CLIENT_DATA_TEXT;
|
||||
new_client->send_data_type = RELAY_CLIENT_DATA_TEXT;
|
||||
break;
|
||||
default:
|
||||
new_client->recv_data_type = RELAY_CLIENT_DATA_TEXT;
|
||||
new_client->send_data_type = RELAY_CLIENT_DATA_TEXT;
|
||||
break;
|
||||
}
|
||||
new_client->partial_message = NULL;
|
||||
|
||||
relay_client_set_desc (new_client);
|
||||
|
||||
|
@ -792,6 +1152,8 @@ relay_client_new_with_infolist (struct t_infolist *infolist)
|
|||
new_client->gnutls_sess = NULL;
|
||||
new_client->hook_timer_handshake = NULL;
|
||||
#endif
|
||||
new_client->websocket = weechat_infolist_integer (infolist, "websocket");
|
||||
new_client->http_headers = NULL;
|
||||
new_client->address = strdup (weechat_infolist_string (infolist, "address"));
|
||||
new_client->status = weechat_infolist_integer (infolist, "status");
|
||||
new_client->protocol = weechat_infolist_integer (infolist, "protocol");
|
||||
|
@ -816,6 +1178,10 @@ relay_client_new_with_infolist (struct t_infolist *infolist)
|
|||
"%lu", &(new_client->bytes_recv));
|
||||
sscanf (weechat_infolist_string (infolist, "bytes_sent"),
|
||||
"%lu", &(new_client->bytes_sent));
|
||||
new_client->recv_data_type = weechat_infolist_integer (infolist, "recv_data_type");
|
||||
new_client->send_data_type = weechat_infolist_integer (infolist, "send_data_type");
|
||||
str = weechat_infolist_string (infolist, "partial_message");
|
||||
new_client->partial_message = (str) ? strdup (str) : NULL;
|
||||
|
||||
str = weechat_infolist_string (infolist, "desc");
|
||||
if (str)
|
||||
|
@ -972,8 +1338,12 @@ relay_client_free (struct t_relay_client *client)
|
|||
if (client->hook_timer_handshake)
|
||||
weechat_unhook (client->hook_timer_handshake);
|
||||
#endif
|
||||
if (client->http_headers)
|
||||
weechat_hashtable_free (client->http_headers);
|
||||
if (client->hook_fd)
|
||||
weechat_unhook (client->hook_fd);
|
||||
if (client->partial_message)
|
||||
free (client->partial_message);
|
||||
if (client->protocol_data)
|
||||
{
|
||||
switch (client->protocol)
|
||||
|
@ -1078,6 +1448,8 @@ relay_client_add_to_infolist (struct t_infolist *infolist,
|
|||
if (!weechat_infolist_new_var_pointer (ptr_item, "hook_timer_handshake", client->hook_timer_handshake))
|
||||
return 0;
|
||||
#endif
|
||||
if (!weechat_infolist_new_var_integer (ptr_item, "websocket", client->websocket))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_string (ptr_item, "address", client->address))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_integer (ptr_item, "status", client->status))
|
||||
|
@ -1108,6 +1480,12 @@ relay_client_add_to_infolist (struct t_infolist *infolist,
|
|||
snprintf (value, sizeof (value), "%lu", client->bytes_sent);
|
||||
if (!weechat_infolist_new_var_string (ptr_item, "bytes_sent", value))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_integer (ptr_item, "recv_data_type", client->recv_data_type))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_integer (ptr_item, "send_data_type", client->send_data_type))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_string (ptr_item, "partial_message", client->partial_message))
|
||||
return 0;
|
||||
|
||||
switch (client->protocol)
|
||||
{
|
||||
|
@ -1146,6 +1524,10 @@ relay_client_print_log ()
|
|||
weechat_log_printf (" gnutls_sess . . . . . : 0x%lx", ptr_client->gnutls_sess);
|
||||
weechat_log_printf (" hook_timer_handshake. : 0x%lx", ptr_client->hook_timer_handshake);
|
||||
#endif
|
||||
weechat_log_printf (" websocket . . . . . . : %d", ptr_client->websocket);
|
||||
weechat_log_printf (" http_headers. . . . . : 0x%lx (hashtable: '%s')",
|
||||
ptr_client->http_headers,
|
||||
weechat_hashtable_get_string (ptr_client->http_headers, "keys_values"));
|
||||
weechat_log_printf (" address . . . . . . . : '%s'", ptr_client->address);
|
||||
weechat_log_printf (" status. . . . . . . . : %d (%s)",
|
||||
ptr_client->status,
|
||||
|
@ -1162,6 +1544,13 @@ relay_client_print_log ()
|
|||
weechat_log_printf (" last_activity . . . . : %ld", ptr_client->last_activity);
|
||||
weechat_log_printf (" bytes_recv. . . . . . : %lu", ptr_client->bytes_recv);
|
||||
weechat_log_printf (" bytes_sent. . . . . . : %lu", ptr_client->bytes_sent);
|
||||
weechat_log_printf (" recv_data_type. . . . : %d (%s)",
|
||||
ptr_client->recv_data_type,
|
||||
relay_client_data_type_string[ptr_client->recv_data_type]);
|
||||
weechat_log_printf (" send_data_type. . . . : %d (%s)",
|
||||
ptr_client->send_data_type,
|
||||
relay_client_data_type_string[ptr_client->send_data_type]);
|
||||
weechat_log_printf (" partial_message . . . : '%s'", ptr_client->partial_message);
|
||||
weechat_log_printf (" protocol_data . . . . : 0x%lx", ptr_client->protocol_data);
|
||||
switch (ptr_client->protocol)
|
||||
{
|
||||
|
|
|
@ -39,6 +39,16 @@ enum t_relay_status
|
|||
RELAY_NUM_STATUS,
|
||||
};
|
||||
|
||||
/* type of data exchanged with client */
|
||||
|
||||
enum t_relay_client_data_type
|
||||
{
|
||||
RELAY_CLIENT_DATA_TEXT = 0, /* text messages */
|
||||
RELAY_CLIENT_DATA_BINARY, /* binary messages */
|
||||
/* number of data types */
|
||||
RELAY_NUM_CLIENT_DATA_TYPES,
|
||||
};
|
||||
|
||||
/* macros for status */
|
||||
|
||||
#define RELAY_CLIENT_HAS_ENDED(client) \
|
||||
|
@ -51,6 +61,9 @@ struct t_relay_client_outqueue
|
|||
{
|
||||
char *data; /* data to send */
|
||||
int data_size; /* number of bytes */
|
||||
int raw_flags[2]; /* flags for raw messages */
|
||||
char *raw_message[2]; /* msgs for raw buffer (can be NULL)*/
|
||||
int raw_size[2]; /* size (in bytes) of raw messages */
|
||||
struct t_relay_client_outqueue *next_outqueue; /* next msg in queue */
|
||||
struct t_relay_client_outqueue *prev_outqueue; /* prev msg in queue */
|
||||
};
|
||||
|
@ -67,6 +80,8 @@ struct t_relay_client
|
|||
gnutls_session_t gnutls_sess; /* gnutls session (only if SSL used) */
|
||||
struct t_hook *hook_timer_handshake; /* timer for doing gnutls handshake*/
|
||||
#endif
|
||||
int websocket; /* 0=not a ws, 1=init ws, 2=ws ready */
|
||||
struct t_hashtable *http_headers; /* HTTP headers for websocket */
|
||||
char *address; /* string with IP address */
|
||||
enum t_relay_status status; /* status (connecting, active,..) */
|
||||
enum t_relay_protocol protocol; /* protocol (irc,..) */
|
||||
|
@ -80,6 +95,9 @@ struct t_relay_client
|
|||
time_t last_activity; /* time of last byte received/sent */
|
||||
unsigned long bytes_recv; /* bytes received from client */
|
||||
unsigned long bytes_sent; /* bytes sent to client */
|
||||
enum t_relay_client_data_type recv_data_type; /* type recv from client */
|
||||
enum t_relay_client_data_type send_data_type; /* type sent to client */
|
||||
char *partial_message; /* partial text message received */
|
||||
void *protocol_data; /* data depending on protocol used */
|
||||
struct t_relay_client_outqueue *outqueue; /* queue for outgoing msgs */
|
||||
struct t_relay_client_outqueue *last_outqueue; /* last outgoing msg */
|
||||
|
@ -97,7 +115,7 @@ extern struct t_relay_client *relay_client_search_by_number (int number);
|
|||
extern struct t_relay_client *relay_client_search_by_id (int id);
|
||||
extern int relay_client_recv_cb (void *arg_client, int fd);
|
||||
extern int relay_client_send (struct t_relay_client *client, const char *data,
|
||||
int data_size);
|
||||
int data_size, const char *message_raw_buffer);
|
||||
extern int relay_client_timer_cb (void *data, int remaining_calls);
|
||||
extern struct t_relay_client *relay_client_new (int sock, const char *address,
|
||||
struct t_relay_server *server);
|
||||
|
|
|
@ -57,6 +57,7 @@ struct t_config_option *relay_config_network_ipv6;
|
|||
struct t_config_option *relay_config_network_max_clients;
|
||||
struct t_config_option *relay_config_network_password;
|
||||
struct t_config_option *relay_config_network_ssl_cert_key;
|
||||
struct t_config_option *relay_config_network_websocket_allowed_origins;
|
||||
|
||||
/* relay config, irc section */
|
||||
|
||||
|
@ -69,6 +70,7 @@ struct t_config_option *relay_config_irc_backlog_time_format;
|
|||
/* other */
|
||||
|
||||
regex_t *relay_config_regex_allowed_ips = NULL;
|
||||
regex_t *relay_config_regex_websocket_allowed_origins = NULL;
|
||||
struct t_hashtable *relay_config_hashtable_irc_backlog_tags = NULL;
|
||||
|
||||
|
||||
|
@ -187,6 +189,44 @@ relay_config_change_network_ssl_cert_key (void *data,
|
|||
relay_network_set_ssl_cert_key (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for changes on option "relay.network.websocker_allowed_origins".
|
||||
*/
|
||||
|
||||
void
|
||||
relay_config_change_network_websocket_allowed_origins (void *data,
|
||||
struct t_config_option *option)
|
||||
{
|
||||
const char *allowed_origins;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
(void) option;
|
||||
|
||||
if (relay_config_regex_websocket_allowed_origins)
|
||||
{
|
||||
regfree (relay_config_regex_websocket_allowed_origins);
|
||||
free (relay_config_regex_websocket_allowed_origins);
|
||||
relay_config_regex_websocket_allowed_origins = NULL;
|
||||
}
|
||||
|
||||
allowed_origins = weechat_config_string (relay_config_network_websocket_allowed_origins);
|
||||
if (allowed_origins && allowed_origins[0])
|
||||
{
|
||||
relay_config_regex_websocket_allowed_origins = malloc (sizeof (*relay_config_regex_websocket_allowed_origins));
|
||||
if (relay_config_regex_websocket_allowed_origins)
|
||||
{
|
||||
if (weechat_string_regcomp (relay_config_regex_websocket_allowed_origins,
|
||||
allowed_origins,
|
||||
REG_EXTENDED | REG_ICASE) != 0)
|
||||
{
|
||||
free (relay_config_regex_websocket_allowed_origins);
|
||||
relay_config_regex_websocket_allowed_origins = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for changes on option "relay.irc.backlog_tags".
|
||||
*/
|
||||
|
@ -606,6 +646,14 @@ relay_config_init ()
|
|||
"with SSL)"),
|
||||
NULL, 0, 0, "%h/ssl/relay.pem", NULL, 0, NULL, NULL,
|
||||
&relay_config_change_network_ssl_cert_key, NULL, NULL, NULL);
|
||||
relay_config_network_websocket_allowed_origins = weechat_config_new_option (
|
||||
relay_config_file, ptr_section,
|
||||
"websocket_allowed_origins", "string",
|
||||
N_("regular expression with origins allowed in websockets (case "
|
||||
"insensitive, use \"(?-i)\" at beginning to make it case sensitive), "
|
||||
"example: \"^http://(www\\.)?example\\.(com|org)\""),
|
||||
NULL, 0, 0, "", NULL, 0, NULL, NULL,
|
||||
&relay_config_change_network_websocket_allowed_origins, NULL, NULL, NULL);
|
||||
|
||||
/* section irc */
|
||||
ptr_section = weechat_config_new_section (relay_config_file, "irc",
|
||||
|
|
|
@ -51,6 +51,7 @@ extern struct t_config_option *relay_config_irc_backlog_tags;
|
|||
extern struct t_config_option *relay_config_irc_backlog_time_format;
|
||||
|
||||
extern regex_t *relay_config_regex_allowed_ips;
|
||||
extern regex_t *relay_config_regex_websocket_allowed_origins;
|
||||
extern struct t_hashtable *relay_config_hashtable_irc_backlog_tags;
|
||||
|
||||
extern int relay_config_create_option_port (void *data,
|
||||
|
|
|
@ -215,46 +215,99 @@ relay_raw_message_add_to_list (time_t date, const char *prefix,
|
|||
|
||||
/*
|
||||
* Adds a new raw message to list.
|
||||
*
|
||||
* Returns pointer to new raw message, NULL if error.
|
||||
*/
|
||||
|
||||
struct t_relay_raw_message *
|
||||
void
|
||||
relay_raw_message_add (struct t_relay_client *client, int flags,
|
||||
const char *message)
|
||||
const char *data, int data_size)
|
||||
{
|
||||
char *buf, *buf2, prefix[256], prefix_arrow[16];
|
||||
char str_hexa[(16 * 3) + 1], str_ascii[(16 * 2) + 1], str_line[256];
|
||||
const unsigned char *ptr_buf;
|
||||
const char *hexa = "0123456789ABCDEF";
|
||||
int pos_buf, pos_buf2, char_size, i;
|
||||
int pos_buf, pos_buf2, char_size, i, hexa_pos, ascii_pos;
|
||||
struct t_relay_raw_message *new_raw_message;
|
||||
|
||||
buf = weechat_iconv_to_internal (NULL, message);
|
||||
buf2 = malloc ((strlen (buf) * 3) + 1);
|
||||
if (buf2)
|
||||
buf = NULL;
|
||||
buf2 = NULL;
|
||||
|
||||
if (flags & RELAY_RAW_FLAG_BINARY)
|
||||
{
|
||||
ptr_buf = (buf) ? (unsigned char *)buf : (unsigned char *)message;
|
||||
pos_buf = 0;
|
||||
pos_buf2 = 0;
|
||||
while (ptr_buf[pos_buf])
|
||||
/* binary message */
|
||||
buf = malloc ((data_size * 6) + 128 + 1);
|
||||
if (buf)
|
||||
{
|
||||
if (ptr_buf[pos_buf] < 32)
|
||||
buf[0] = '\0';
|
||||
hexa_pos = 0;
|
||||
ascii_pos = 0;
|
||||
for (i = 0; i < data_size; i++)
|
||||
{
|
||||
buf2[pos_buf2++] = '\\';
|
||||
buf2[pos_buf2++] = hexa[ptr_buf[pos_buf] / 16];
|
||||
buf2[pos_buf2++] = hexa[ptr_buf[pos_buf] % 16];
|
||||
pos_buf++;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_size = weechat_utf8_char_size ((const char *)(ptr_buf + pos_buf));
|
||||
for (i = 0; i < char_size; i++)
|
||||
snprintf (str_hexa + hexa_pos, 4,
|
||||
"%02X ", (unsigned char)(data[i]));
|
||||
hexa_pos += 3;
|
||||
snprintf (str_ascii + ascii_pos, 3, "%c ",
|
||||
((((unsigned char)data[i]) < 32)
|
||||
|| (((unsigned char)data[i]) > 127)) ?
|
||||
'.' : (unsigned char)(data[i]));
|
||||
ascii_pos += 2;
|
||||
if (ascii_pos == 32)
|
||||
{
|
||||
buf2[pos_buf2++] = ptr_buf[pos_buf++];
|
||||
if (buf[0])
|
||||
strcat (buf, "\n");
|
||||
snprintf (str_line, sizeof (str_line),
|
||||
"%-48s %s", str_hexa, str_ascii);
|
||||
strcat (buf, str_line);
|
||||
hexa_pos = 0;
|
||||
ascii_pos = 0;
|
||||
}
|
||||
}
|
||||
if (ascii_pos > 0)
|
||||
{
|
||||
if (buf[0])
|
||||
strcat (buf, "\n");
|
||||
snprintf (str_line, sizeof (str_line),
|
||||
"%-48s %s", str_hexa, str_ascii);
|
||||
strcat (buf, str_line);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* text message */
|
||||
buf = weechat_iconv_to_internal (NULL, data);
|
||||
buf2 = weechat_string_replace (buf, "\r", "");
|
||||
if (buf2)
|
||||
{
|
||||
free (buf);
|
||||
buf = buf2;
|
||||
buf2 = NULL;
|
||||
}
|
||||
buf2 = malloc ((strlen (buf) * 3) + 1);
|
||||
if (buf2)
|
||||
{
|
||||
ptr_buf = (buf) ? (unsigned char *)buf : (unsigned char *)data;
|
||||
pos_buf = 0;
|
||||
pos_buf2 = 0;
|
||||
while (ptr_buf[pos_buf])
|
||||
{
|
||||
if ((ptr_buf[pos_buf] < 32) && (ptr_buf[pos_buf] != '\n'))
|
||||
{
|
||||
buf2[pos_buf2++] = '\\';
|
||||
buf2[pos_buf2++] = hexa[ptr_buf[pos_buf] / 16];
|
||||
buf2[pos_buf2++] = hexa[ptr_buf[pos_buf] % 16];
|
||||
pos_buf++;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_size = weechat_utf8_char_size ((const char *)(ptr_buf + pos_buf));
|
||||
for (i = 0; i < char_size; i++)
|
||||
{
|
||||
buf2[pos_buf2++] = ptr_buf[pos_buf++];
|
||||
}
|
||||
}
|
||||
}
|
||||
buf2[pos_buf2] = '\0';
|
||||
}
|
||||
buf2[pos_buf2] = '\0';
|
||||
}
|
||||
|
||||
/* build prefix with arrow */
|
||||
|
@ -302,35 +355,8 @@ relay_raw_message_add (struct t_relay_client *client, int flags,
|
|||
|
||||
new_raw_message = relay_raw_message_add_to_list (time (NULL),
|
||||
prefix,
|
||||
(buf2) ? buf2 : ((buf) ? buf : message));
|
||||
(buf2) ? buf2 : ((buf) ? buf : data));
|
||||
|
||||
if (buf)
|
||||
free (buf);
|
||||
if (buf2)
|
||||
free (buf2);
|
||||
|
||||
return new_raw_message;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints a message on relay raw buffer.
|
||||
*/
|
||||
|
||||
void
|
||||
relay_raw_print (struct t_relay_client *client, int flags,
|
||||
const char *format, ...)
|
||||
{
|
||||
struct t_relay_raw_message *new_raw_message;
|
||||
|
||||
weechat_va_format (format);
|
||||
if (!vbuffer)
|
||||
return;
|
||||
|
||||
/* auto-open Relay raw buffer if debug for irc plugin is >= 1 */
|
||||
if (!relay_raw_buffer && (weechat_relay_plugin->debug >= 1))
|
||||
relay_raw_open (0);
|
||||
|
||||
new_raw_message = relay_raw_message_add (client, flags, vbuffer);
|
||||
if (new_raw_message)
|
||||
{
|
||||
if (relay_raw_buffer)
|
||||
|
@ -339,7 +365,25 @@ relay_raw_print (struct t_relay_client *client, int flags,
|
|||
relay_raw_message_free (new_raw_message);
|
||||
}
|
||||
|
||||
free (vbuffer);
|
||||
if (buf)
|
||||
free (buf);
|
||||
if (buf2)
|
||||
free (buf2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints a message on relay raw buffer.
|
||||
*/
|
||||
|
||||
void
|
||||
relay_raw_print (struct t_relay_client *client, int flags,
|
||||
const char *data, int data_size)
|
||||
{
|
||||
/* auto-open Relay raw buffer if debug for irc plugin is >= 1 */
|
||||
if (!relay_raw_buffer && (weechat_relay_plugin->debug >= 1))
|
||||
relay_raw_open (0);
|
||||
|
||||
relay_raw_message_add (client, flags, data, data_size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#define RELAY_RAW_FLAG_RECV 1
|
||||
#define RELAY_RAW_FLAG_SEND 2
|
||||
#define RELAY_RAW_FLAG_BINARY 4
|
||||
|
||||
struct t_relay_raw_message
|
||||
{
|
||||
|
@ -47,7 +48,7 @@ extern struct t_relay_raw_message *relay_raw_message_add_to_list (time_t date,
|
|||
const char *prefix,
|
||||
const char *message);
|
||||
extern void relay_raw_print (struct t_relay_client *client, int flags,
|
||||
const char *format, ...);
|
||||
const char *data, int data_size);
|
||||
extern void relay_raw_message_free_all ();
|
||||
extern int relay_raw_add_to_infolist (struct t_infolist *infolist,
|
||||
struct t_relay_raw_message *raw_message);
|
||||
|
|
|
@ -286,7 +286,7 @@ relay_server_sock_cb (void *data, int fd)
|
|||
if (relay_config_regex_allowed_ips
|
||||
&& (regexec (relay_config_regex_allowed_ips, ptr_ip_address, 0, NULL, 0) != 0))
|
||||
{
|
||||
if (weechat_relay_plugin->debug >= 2)
|
||||
if (weechat_relay_plugin->debug >= 1)
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
_("%s%s: IP address \"%s\" not allowed for relay"),
|
||||
|
|
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* relay-websocket.c - websocket server functions for relay plugin (RFC 6455)
|
||||
*
|
||||
* Copyright (C) 2013 Sebastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "relay.h"
|
||||
#include "relay-client.h"
|
||||
#include "relay-config.h"
|
||||
|
||||
|
||||
/*
|
||||
* globally unique identifier that is concatenated to HTTP header
|
||||
* "Sec-WebSocket-Key"
|
||||
*/
|
||||
#define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
|
||||
|
||||
/*
|
||||
* Checks if a message is a HTTP GET with resource "/weechat".
|
||||
*
|
||||
* Returns:
|
||||
* 1: message is a HTTP GET with resource "/weechat"
|
||||
* 0: message is NOT a HTTP GET with resource "/weechat"
|
||||
*/
|
||||
|
||||
int
|
||||
relay_websocket_is_http_get_weechat (const char *message)
|
||||
{
|
||||
/* the message must start with "GET /weechat" */
|
||||
if (strncmp (message, "GET /weechat", 12) != 0)
|
||||
return 0;
|
||||
|
||||
/* after "GET /weechat", only a new line or " HTTP" is allowed */
|
||||
if ((message[12] != '\r') && (message[12] != '\n')
|
||||
&& (strncmp (message + 12, " HTTP", 5) != 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* valid HTTP GET for resource "/weechat" */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Saves a HTTP header in hashtable "http_header" of client.
|
||||
*/
|
||||
|
||||
void
|
||||
relay_websocket_save_header (struct t_relay_client *client,
|
||||
const char *message)
|
||||
{
|
||||
char *pos, *name;
|
||||
const char *ptr_value;
|
||||
|
||||
/* ignore the "GET" request */
|
||||
if (strncmp (message, "GET ", 4) == 0)
|
||||
return;
|
||||
|
||||
pos = strchr (message, ':');
|
||||
|
||||
/* not a valid header */
|
||||
if (!pos || (pos == message))
|
||||
return;
|
||||
|
||||
/* get header name */
|
||||
name = weechat_strndup (message, pos - message);
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
/* get pointer on header value */
|
||||
ptr_value = pos + 1;
|
||||
while (ptr_value[0] == ' ')
|
||||
{
|
||||
ptr_value++;
|
||||
}
|
||||
|
||||
/* add header in the hashtable */
|
||||
weechat_hashtable_set (client->http_headers, name, ptr_value);
|
||||
|
||||
free (name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if a client handshake is valid.
|
||||
*
|
||||
* A websocket query looks like:
|
||||
* GET /weechat HTTP/1.1
|
||||
* Upgrade: websocket
|
||||
* Connection: Upgrade
|
||||
* Host: myhost:5000
|
||||
* Origin: http://example.org.org
|
||||
* Pragma: no-cache
|
||||
* Cache-Control: no-cache
|
||||
* Sec-WebSocket-Key: fo1J9uHSsrfDP3BkwUylzQ==
|
||||
* Sec-WebSocket-Version: 13
|
||||
* Sec-WebSocket-Extensions: x-webkit-deflate-frame
|
||||
* Cookie: csrftoken=acb65377798f32dc377ebb50316a12b5
|
||||
*
|
||||
* Expected HTTP headers with values are:
|
||||
*
|
||||
* header | value
|
||||
* --------------------+----------------
|
||||
* "Upgrade" | "websocket"
|
||||
* "Sec-WebSocket-Key" | non-empty value
|
||||
*
|
||||
* If option relay.network.websocket_allowed_origins is set, the HTTP header
|
||||
* "Origin" is checked against this regex. If header "Origin" is not set or does
|
||||
* not match regex, the handshake is considered as invalid.
|
||||
*
|
||||
* Returns:
|
||||
* 0: handshake is valid
|
||||
* -1: handshake is invalid (headers missing or with bad value)
|
||||
* -2: origin is not allowed (option relay.network.websocket_allowed_origins)
|
||||
*/
|
||||
|
||||
int
|
||||
relay_websocket_client_handshake_valid (struct t_relay_client *client)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
/* check if we have header "Upgrade" with value "websocket" */
|
||||
value = weechat_hashtable_get (client->http_headers, "Upgrade");
|
||||
if (!value)
|
||||
return -1;
|
||||
if (strcmp (value, "websocket") != 0)
|
||||
return -1;
|
||||
|
||||
/* check if we have header "Sec-WebSocket-Key" with non-empty value */
|
||||
value = weechat_hashtable_get (client->http_headers, "Sec-WebSocket-Key");
|
||||
if (!value || !value[0])
|
||||
return -1;
|
||||
|
||||
if (relay_config_regex_websocket_allowed_origins)
|
||||
{
|
||||
value = weechat_hashtable_get (client->http_headers, "Origin");
|
||||
if (!value || !value[0])
|
||||
return -2;
|
||||
if (regexec (relay_config_regex_websocket_allowed_origins, value, 0,
|
||||
NULL, 0) != 0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* client handshake is valid */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Builds the handshake that will be returned to client, to initialize and use
|
||||
* the websocket.
|
||||
*
|
||||
* Returns a string with content of handshake to send to client, it looks like:
|
||||
* HTTP/1.1 101 Switching Protocols
|
||||
* Upgrade: websocket
|
||||
* Connection: Upgrade
|
||||
* Sec-WebSocket-Accept: 73OzoF/IyV9znm7Tsb4EtlEEmn4=
|
||||
*
|
||||
* Note: result must be freed after use.
|
||||
*/
|
||||
|
||||
char *
|
||||
relay_websocket_build_handshake (struct t_relay_client *client)
|
||||
{
|
||||
const char *sec_websocket_key;
|
||||
char *key, sec_websocket_accept[128], handshake[1024];
|
||||
unsigned char *result;
|
||||
gcry_md_hd_t hd;
|
||||
int length;
|
||||
|
||||
sec_websocket_key = weechat_hashtable_get (client->http_headers,
|
||||
"Sec-WebSocket-Key");
|
||||
if (!sec_websocket_key || !sec_websocket_key[0])
|
||||
return NULL;
|
||||
|
||||
length = strlen (sec_websocket_key) + strlen (WEBSOCKET_GUID) + 1;
|
||||
key = malloc (length);
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* concatenate header "Sec-WebSocket-Key" with the GUID
|
||||
* (globally unique identifier)
|
||||
*/
|
||||
snprintf (key, length, "%s%s", sec_websocket_key, WEBSOCKET_GUID);
|
||||
|
||||
/* compute 160-bit SHA1 on the key and encode it with base64 */
|
||||
gcry_md_open (&hd, GCRY_MD_SHA1, 0);
|
||||
length = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
|
||||
gcry_md_write (hd, key, strlen (key));
|
||||
result = gcry_md_read (hd, GCRY_MD_SHA1);
|
||||
weechat_string_encode_base64 ((char *)result, length, sec_websocket_accept);
|
||||
gcry_md_close (hd);
|
||||
|
||||
/* build the handshake (it will be sent as-is to client) */
|
||||
snprintf (handshake, sizeof (handshake),
|
||||
"HTTP/1.1 101 Switching Protocols\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
//"Sec-WebSocket-Protocol: chat\r\n"
|
||||
"Sec-WebSocket-Accept: %s\r\n"
|
||||
"\r\n",
|
||||
sec_websocket_accept);
|
||||
|
||||
return strdup (handshake);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends a HTTP message to client.
|
||||
*
|
||||
* Argument "http" is a HTTP code + message, for example:
|
||||
* "403 Forbidden".
|
||||
*/
|
||||
|
||||
void
|
||||
relay_websocket_send_http (struct t_relay_client *client,
|
||||
const char *http)
|
||||
{
|
||||
char *message;
|
||||
int length;
|
||||
|
||||
length = 32 + strlen (http) + 1;
|
||||
message = malloc (length);
|
||||
if (message)
|
||||
{
|
||||
snprintf (message, length, "HTTP/1.1 %s\r\n\r\n", http);
|
||||
relay_client_send (client, message, strlen (message), NULL);
|
||||
free (message);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes a websocket frame.
|
||||
*
|
||||
* Returns:
|
||||
* 1: frame decoded successfully
|
||||
* 0: error decoding frame (connection must be closed if it happens)
|
||||
*/
|
||||
|
||||
int
|
||||
relay_websocket_decode_frame (const unsigned char *buffer,
|
||||
unsigned long long length,
|
||||
unsigned char *decoded)
|
||||
{
|
||||
unsigned long long i, index, length_frame_size, length_frame;
|
||||
|
||||
if (length < 2)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* check if frame is masked: client MUST send a masked frame; if frame is
|
||||
* not masked, we MUST reject it and close the connection (see RFC 6455)
|
||||
*/
|
||||
if (!(buffer[1] & 128))
|
||||
return 0;
|
||||
|
||||
/* decode frame */
|
||||
index = 2;
|
||||
length_frame_size = 1;
|
||||
length_frame = buffer[1] & 127;
|
||||
if ((length_frame == 126) || (length_frame == 127))
|
||||
{
|
||||
length_frame_size = (length_frame == 126) ? 2 : 8;
|
||||
if (length < 1 + length_frame_size)
|
||||
return 0;
|
||||
length_frame = 0;
|
||||
for (i = 0; i < length_frame_size; i++)
|
||||
{
|
||||
length_frame += (unsigned long long)buffer[index + i] << ((length_frame_size - i - 1) * 8);
|
||||
}
|
||||
index += length_frame_size;
|
||||
}
|
||||
|
||||
if (length < 1 + length_frame_size + 4 + length_frame)
|
||||
return 0;
|
||||
|
||||
/* read masks (4 bytes) */
|
||||
int masks[4];
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
masks[i] = (int)((unsigned char)buffer[index + i]);
|
||||
}
|
||||
index += 4;
|
||||
|
||||
/* decode data using masks */
|
||||
for (i = 0; i < length_frame; i++)
|
||||
{
|
||||
decoded[i] = (int)((unsigned char)buffer[index + i]) ^ masks[i % 4];
|
||||
}
|
||||
decoded[length_frame] = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encodes data in a websocket frame.
|
||||
*
|
||||
* Returns websocket frame, NULL if error.
|
||||
* Argument "length_frame" is set with the length of frame built.
|
||||
*
|
||||
* Note: result must be freed after use.
|
||||
*/
|
||||
|
||||
char *
|
||||
relay_websocket_encode_frame (struct t_relay_client *client,
|
||||
const char *buffer,
|
||||
unsigned long long length,
|
||||
unsigned long long *length_frame)
|
||||
{
|
||||
unsigned char *frame;
|
||||
unsigned long long index;
|
||||
|
||||
*length_frame = 0;
|
||||
|
||||
frame = malloc (length + 10);
|
||||
if (!frame)
|
||||
return NULL;
|
||||
|
||||
frame[0] = (client->send_data_type == RELAY_CLIENT_DATA_TEXT) ? 0x81 : 0x82;
|
||||
|
||||
if (length <= 125)
|
||||
{
|
||||
/* length on one byte */
|
||||
frame[1] = length;
|
||||
index = 2;
|
||||
}
|
||||
else if ((length >= 126) && (length <= 65535))
|
||||
{
|
||||
/* length on 2 bytes */
|
||||
frame[1] = 126;
|
||||
frame[2] = (length >> 8) & 0xFF;
|
||||
frame[3] = length & 0xFF;
|
||||
index = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* length on 8 bytes */
|
||||
frame[1] = 127;
|
||||
frame[2] = (length >> 56) & 0xFF;
|
||||
frame[3] = (length >> 48) & 0xFF;
|
||||
frame[4] = (length >> 40) & 0xFF;
|
||||
frame[5] = (length >> 32) & 0xFF;
|
||||
frame[6] = (length >> 24) & 0xFF;
|
||||
frame[7] = (length >> 16) & 0xFF;
|
||||
frame[8] = (length >> 8) & 0xFF;
|
||||
frame[9] = length & 0xFF;
|
||||
index = 10;
|
||||
}
|
||||
|
||||
/* copy buffer after length */
|
||||
memcpy (frame + index, buffer, length);
|
||||
|
||||
*length_frame = index + length;
|
||||
|
||||
return (char *)frame;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Sebastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __WEECHAT_RELAY_WEBSOCKET_H
|
||||
#define __WEECHAT_RELAY_WEBSOCKET_H 1
|
||||
|
||||
extern int relay_websocket_is_http_get_weechat (const char *message);
|
||||
extern void relay_websocket_save_header (struct t_relay_client *client,
|
||||
const char *message);
|
||||
extern int relay_websocket_client_handshake_valid (struct t_relay_client *client);
|
||||
extern char *relay_websocket_build_handshake (struct t_relay_client *client);
|
||||
extern void relay_websocket_send_http (struct t_relay_client *client,
|
||||
const char *http);
|
||||
extern int relay_websocket_decode_frame (const unsigned char *buffer,
|
||||
int length,
|
||||
unsigned char *decoded);
|
||||
extern char *relay_websocket_encode_frame (struct t_relay_client *client,
|
||||
const char *buffer,
|
||||
unsigned long long length,
|
||||
unsigned long long *length_frame);
|
||||
|
||||
#endif /* __WEECHAT_RELAY_WEBSOCKET_H */
|
|
@ -958,7 +958,7 @@ relay_weechat_msg_send (struct t_relay_client *client,
|
|||
struct t_relay_weechat_msg *msg)
|
||||
{
|
||||
uint32_t size32;
|
||||
char compression;
|
||||
char compression, raw_message[1024];
|
||||
int rc;
|
||||
Bytef *dest;
|
||||
uLongf dest_size;
|
||||
|
@ -986,16 +986,17 @@ relay_weechat_msg_send (struct t_relay_client *client,
|
|||
dest[4] = 1;
|
||||
|
||||
/* display message in raw buffer */
|
||||
relay_raw_print (client, RELAY_RAW_FLAG_SEND,
|
||||
"obj: %d/%d bytes (%d%%, %ldms), id: %s",
|
||||
(int)dest_size + 5,
|
||||
msg->data_size,
|
||||
100 - ((((int)dest_size + 5) * 100) / msg->data_size),
|
||||
time_diff,
|
||||
msg->id);
|
||||
snprintf (raw_message, sizeof (raw_message),
|
||||
"obj: %d/%d bytes (%d%%, %ldms), id: %s",
|
||||
(int)dest_size + 5,
|
||||
msg->data_size,
|
||||
100 - ((((int)dest_size + 5) * 100) / msg->data_size),
|
||||
time_diff,
|
||||
msg->id);
|
||||
|
||||
/* send compressed data */
|
||||
relay_client_send (client, (const char *)dest, dest_size + 5);
|
||||
relay_client_send (client, (const char *)dest, dest_size + 5,
|
||||
raw_message);
|
||||
|
||||
free (dest);
|
||||
return;
|
||||
|
@ -1012,12 +1013,10 @@ relay_weechat_msg_send (struct t_relay_client *client,
|
|||
compression = 0;
|
||||
relay_weechat_msg_set_bytes (msg, 4, &compression, 1);
|
||||
|
||||
/* display message in raw buffer */
|
||||
relay_raw_print (client, RELAY_RAW_FLAG_SEND,
|
||||
"obj: %d bytes", msg->data_size);
|
||||
|
||||
/* send uncompressed data */
|
||||
relay_client_send (client, msg->data, msg->data_size);
|
||||
snprintf (raw_message, sizeof (raw_message),
|
||||
"obj: %d bytes", msg->data_size);
|
||||
relay_client_send (client, msg->data, msg->data_size, raw_message);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1053,7 +1053,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(quit)
|
|||
*/
|
||||
|
||||
void
|
||||
relay_weechat_protocol_recv (struct t_relay_client *client, char *data)
|
||||
relay_weechat_protocol_recv (struct t_relay_client *client, const char *data)
|
||||
{
|
||||
char *pos, *id, *command, **argv, **argv_eol;
|
||||
int i, argc, return_code;
|
||||
|
@ -1074,11 +1074,6 @@ relay_weechat_protocol_recv (struct t_relay_client *client, char *data)
|
|||
if (!data || !data[0] || RELAY_CLIENT_HAS_ENDED(client))
|
||||
return;
|
||||
|
||||
/* remove \r at the end of message */
|
||||
pos = strchr (data, '\r');
|
||||
if (pos)
|
||||
pos[0] = '\0';
|
||||
|
||||
/* display debug message */
|
||||
if (weechat_relay_plugin->debug >= 2)
|
||||
{
|
||||
|
@ -1090,9 +1085,6 @@ relay_weechat_protocol_recv (struct t_relay_client *client, char *data)
|
|||
data);
|
||||
}
|
||||
|
||||
/* display message in raw buffer */
|
||||
relay_raw_print (client, RELAY_RAW_FLAG_RECV, "cmd: %s", data);
|
||||
|
||||
/* extract id */
|
||||
id = NULL;
|
||||
if (data[0] == '(')
|
||||
|
|
|
@ -96,6 +96,6 @@ extern int relay_weechat_protocol_signal_upgrade_cb (void *data,
|
|||
extern int relay_weechat_protocol_timer_nicklist_cb (void *data,
|
||||
int remaining_calls);
|
||||
extern void relay_weechat_protocol_recv (struct t_relay_client *client,
|
||||
char *data);
|
||||
const char *data);
|
||||
|
||||
#endif /* __WEECHAT_RELAY_WEECHAT_PROTOCOL_H */
|
||||
|
|
|
@ -42,8 +42,6 @@
|
|||
char *relay_weechat_compression_string[] = /* strings for compressions */
|
||||
{ "off", "gzip" };
|
||||
|
||||
char *relay_weechat_partial_message = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Searches for a compression.
|
||||
|
@ -132,48 +130,7 @@ relay_weechat_hook_timer_nicklist (struct t_relay_client *client)
|
|||
void
|
||||
relay_weechat_recv (struct t_relay_client *client, const char *data)
|
||||
{
|
||||
char *new_partial, *pos, *tmp, **commands;
|
||||
int num_commands, i;
|
||||
|
||||
if (relay_weechat_partial_message)
|
||||
{
|
||||
new_partial = realloc (relay_weechat_partial_message,
|
||||
strlen (relay_weechat_partial_message) +
|
||||
strlen (data) + 1);
|
||||
if (!new_partial)
|
||||
return;
|
||||
relay_weechat_partial_message = new_partial;
|
||||
strcat (relay_weechat_partial_message, data);
|
||||
}
|
||||
else
|
||||
relay_weechat_partial_message = strdup (data);
|
||||
|
||||
pos = strrchr (relay_weechat_partial_message, '\n');
|
||||
if (pos)
|
||||
{
|
||||
pos[0] = '\0';
|
||||
commands = weechat_string_split (relay_weechat_partial_message, "\n",
|
||||
0, 0, &num_commands);
|
||||
if (commands)
|
||||
{
|
||||
for (i = 0; i < num_commands; i++)
|
||||
{
|
||||
relay_weechat_protocol_recv (client, commands[i]);
|
||||
}
|
||||
weechat_string_free_split (commands);
|
||||
}
|
||||
if (pos[1])
|
||||
{
|
||||
tmp = strdup (pos + 1);
|
||||
free (relay_weechat_partial_message);
|
||||
relay_weechat_partial_message = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
free (relay_weechat_partial_message);
|
||||
relay_weechat_partial_message = NULL;
|
||||
}
|
||||
}
|
||||
relay_weechat_protocol_recv (client, data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue