summaryrefslogtreecommitdiff
path: root/src/plugins/relay
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/relay')
-rw-r--r--src/plugins/relay/irc/relay-irc.c3
-rw-r--r--src/plugins/relay/relay-client.c137
-rw-r--r--src/plugins/relay/relay-client.h17
-rw-r--r--src/plugins/relay/relay-raw.c33
-rw-r--r--src/plugins/relay/relay-raw.h5
-rw-r--r--src/plugins/relay/relay-websocket.c19
-rw-r--r--src/plugins/relay/relay-websocket.h9
-rw-r--r--src/plugins/relay/weechat/relay-weechat-msg.c6
8 files changed, 189 insertions, 40 deletions
diff --git a/src/plugins/relay/irc/relay-irc.c b/src/plugins/relay/irc/relay-irc.c
index 5731edd1a..00754f45e 100644
--- a/src/plugins/relay/irc/relay-irc.c
+++ b/src/plugins/relay/irc/relay-irc.c
@@ -236,7 +236,8 @@ relay_irc_sendf (struct t_relay_client *client, const char *format, ...)
if (message)
{
snprintf (message, length, "%s\r\n", str_message);
- relay_client_send (client, message, strlen (message), NULL);
+ relay_client_send (client, RELAY_CLIENT_MSG_STANDARD,
+ message, strlen (message), NULL);
free (message);
}
number++;
diff --git a/src/plugins/relay/relay-client.c b/src/plugins/relay/relay-client.c
index fbb00cebb..1e67c6aef 100644
--- a/src/plugins/relay/relay-client.c
+++ b/src/plugins/relay/relay-client.c
@@ -58,6 +58,9 @@ char *relay_client_status_name[] = /* name of status (for signal/info) */
char *relay_client_data_type_string[] = /* strings for data types */
{ "text", "binary" };
+char *relay_client_msg_type_string[] = /* prefix in raw buffer for message */
+{ "", "[PING]\n", "[PONG]\n" };
+
struct t_relay_client *relay_clients = NULL;
struct t_relay_client *last_relay_client = NULL;
int relay_client_count = 0; /* number of clients */
@@ -295,7 +298,8 @@ relay_client_recv_text (struct t_relay_client *client, const char *data)
pos - client->partial_message + 1);
if (raw_msg)
{
- relay_raw_print (client, RELAY_RAW_FLAG_RECV,
+ relay_raw_print (client, RELAY_CLIENT_MSG_STANDARD,
+ RELAY_RAW_FLAG_RECV,
raw_msg, strlen (raw_msg) + 1);
free (raw_msg);
}
@@ -336,7 +340,9 @@ relay_client_recv_text (struct t_relay_client *client, const char *data)
handshake = relay_websocket_build_handshake (client);
if (handshake)
{
- relay_client_send (client, handshake,
+ relay_client_send (client,
+ RELAY_CLIENT_MSG_STANDARD,
+ handshake,
strlen (handshake), NULL);
free (handshake);
client->websocket = 2;
@@ -411,7 +417,10 @@ relay_client_recv_text (struct t_relay_client *client, const char *data)
}
else
{
- /* receive text from client */
+ /*
+ * interpret text from client, according to the relay
+ * protocol used
+ */
switch (client->protocol)
{
case RELAY_PROTOCOL_WEECHAT:
@@ -442,6 +451,54 @@ relay_client_recv_text (struct t_relay_client *client, const char *data)
}
/*
+ * Reads text buffer from a client.
+ */
+
+void
+relay_client_recv_text_buffer (struct t_relay_client *client,
+ const char *buffer,
+ unsigned long long length_buffer)
+{
+ unsigned long long index;
+ unsigned char msg_type;
+
+ index = 0;
+ while (index < length_buffer)
+ {
+ msg_type = RELAY_CLIENT_MSG_STANDARD;
+
+ /*
+ * in case of websocket, we can receive PING from client:
+ * trace this PING in raw buffer and answer with a PONG
+ */
+ if (client->websocket == 2)
+ {
+ msg_type = (unsigned char)buffer[index];
+ if (msg_type == RELAY_CLIENT_MSG_PING)
+ {
+ /* print message in raw buffer */
+ relay_raw_print (client, RELAY_CLIENT_MSG_PING,
+ RELAY_RAW_FLAG_RECV | RELAY_RAW_FLAG_BINARY,
+ buffer + index + 1,
+ strlen (buffer + index + 1) + 1);
+ /* answer with a PONG */
+ relay_client_send (client,
+ RELAY_CLIENT_MSG_PONG,
+ buffer + index + 1,
+ strlen (buffer + index + 1),
+ NULL);
+ }
+ index++;
+ }
+
+ if (msg_type == RELAY_CLIENT_MSG_STANDARD)
+ relay_client_recv_text (client, buffer + index);
+
+ index += strlen (buffer + index) + 1;
+ }
+}
+
+/*
* Reads data from a client.
*/
@@ -449,10 +506,10 @@ int
relay_client_recv_cb (void *arg_client, int fd)
{
struct t_relay_client *client;
- static char buffer[4096], decoded[4096 + 1];
+ static char buffer[4096], decoded[8192 + 1];
const char *ptr_buffer;
int num_read, rc;
- unsigned long long decoded_length;
+ unsigned long long decoded_length, length_buffer;
/* make C compiler happy */
(void) fd;
@@ -474,6 +531,7 @@ relay_client_recv_cb (void *arg_client, int fd)
{
buffer[num_read] = '\0';
ptr_buffer = buffer;
+ length_buffer = num_read;
/*
* if we are receiving the first message from client, check if it looks
@@ -533,13 +591,14 @@ relay_client_recv_cb (void *arg_client, int fd)
return WEECHAT_RC_OK;
}
ptr_buffer = decoded;
+ length_buffer = decoded_length;
}
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);
+ relay_client_recv_text_buffer (client, ptr_buffer, length_buffer);
}
else
{
@@ -600,7 +659,9 @@ 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,
- int raw_flags[2], const char *raw_message[2],
+ enum t_relay_client_msg_type raw_msg_type[2],
+ int raw_flags[2],
+ const char *raw_message[2],
int raw_size[2])
{
struct t_relay_client_outqueue *new_outqueue;
@@ -622,6 +683,7 @@ relay_client_outqueue_add (struct t_relay_client *client,
new_outqueue->data_size = data_size;
for (i = 0; i < 2; i++)
{
+ new_outqueue->raw_msg_type[i] = RELAY_CLIENT_MSG_STANDARD;
new_outqueue->raw_flags[i] = 0;
new_outqueue->raw_message[i] = NULL;
new_outqueue->raw_size[i] = 0;
@@ -630,6 +692,7 @@ relay_client_outqueue_add (struct t_relay_client *client,
new_outqueue->raw_message[i] = malloc (raw_size[i]);
if (new_outqueue->raw_message[i])
{
+ new_outqueue->raw_msg_type[i] = raw_msg_type[i];
new_outqueue->raw_flags[i] = raw_flags[i];
memcpy (new_outqueue->raw_message[i], raw_message[i],
raw_size[i]);
@@ -708,10 +771,13 @@ relay_client_outqueue_free_all (struct t_relay_client *client)
*/
int
-relay_client_send (struct t_relay_client *client, const char *data,
+relay_client_send (struct t_relay_client *client,
+ enum t_relay_client_msg_type msg_type,
+ const char *data,
int data_size, const char *message_raw_buffer)
{
- int num_sent, raw_size[2], raw_flags[2], i;
+ int num_sent, raw_size[2], raw_flags[2], opcode, i;
+ enum t_relay_client_msg_type raw_msg_type[2];
char *websocket_frame;
unsigned long long length_frame;
const char *ptr_data, *raw_msg[2];
@@ -725,6 +791,7 @@ relay_client_send (struct t_relay_client *client, const char *data,
/* set raw messages */
for (i = 0; i < 2; i++)
{
+ raw_msg_type[i] = msg_type;
raw_flags[i] = RELAY_RAW_FLAG_SEND;
raw_msg[i] = NULL;
raw_size[i] = 0;
@@ -754,8 +821,10 @@ relay_client_send (struct t_relay_client *client, const char *data,
{
raw_msg[0] = data;
raw_size[0] = data_size;
- if ((client->websocket != 1)
- && (client->send_data_type == RELAY_CLIENT_DATA_BINARY))
+ if ((msg_type == RELAY_CLIENT_MSG_PING)
+ || (msg_type == RELAY_CLIENT_MSG_PONG)
+ || ((client->websocket != 1)
+ && (client->send_data_type == RELAY_CLIENT_DATA_BINARY)))
{
/*
* set binary flag if we send binary to client
@@ -774,7 +843,21 @@ relay_client_send (struct t_relay_client *client, const char *data,
/* if websocket is initialized, encode data in a websocket frame */
if (client->websocket == 2)
{
- websocket_frame = relay_websocket_encode_frame (client, data, data_size,
+ switch (msg_type)
+ {
+ case RELAY_CLIENT_MSG_PING:
+ opcode = WEBSOCKET_FRAME_OPCODE_PING;
+ break;
+ case RELAY_CLIENT_MSG_PONG:
+ opcode = WEBSOCKET_FRAME_OPCODE_PONG;
+ break;
+ default:
+ opcode = (client->send_data_type == RELAY_CLIENT_DATA_TEXT) ?
+ WEBSOCKET_FRAME_OPCODE_TEXT : WEBSOCKET_FRAME_OPCODE_BINARY;
+ break;
+ }
+ websocket_frame = relay_websocket_encode_frame (opcode, data,
+ data_size,
&length_frame);
if (websocket_frame)
{
@@ -792,7 +875,7 @@ relay_client_send (struct t_relay_client *client, const char *data,
if (client->outqueue)
{
relay_client_outqueue_add (client, ptr_data, data_size,
- raw_flags, raw_msg, raw_size);
+ raw_msg_type, raw_flags, raw_msg, raw_size);
}
else
{
@@ -809,8 +892,8 @@ relay_client_send (struct t_relay_client *client, const char *data,
{
if (raw_msg[i])
{
- relay_raw_print (client,
- raw_flags[i], raw_msg[i], raw_size[i]);
+ relay_raw_print (client, raw_msg_type[i], raw_flags[i],
+ raw_msg[i], raw_size[i]);
}
}
if (num_sent > 0)
@@ -821,9 +904,10 @@ 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, ptr_data + num_sent,
+ relay_client_outqueue_add (client,
+ ptr_data + num_sent,
data_size - num_sent,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
}
}
else if (num_sent < 0)
@@ -835,8 +919,10 @@ 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, ptr_data, data_size,
- raw_flags, raw_msg, raw_size);
+ relay_client_outqueue_add (client,
+ ptr_data, data_size,
+ raw_msg_type, raw_flags,
+ raw_msg, raw_size);
}
else
{
@@ -860,7 +946,8 @@ relay_client_send (struct t_relay_client *client, const char *data,
{
/* add message to queue (will be sent later) */
relay_client_outqueue_add (client, ptr_data, data_size,
- raw_flags, raw_msg, raw_size);
+ raw_msg_type, raw_flags,
+ raw_msg, raw_size);
}
else
{
@@ -949,10 +1036,12 @@ relay_client_timer_cb (void *data, int remaining_calls)
* (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]);
+ relay_raw_print (
+ ptr_client,
+ ptr_client->outqueue->raw_msg_type[i],
+ 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;
diff --git a/src/plugins/relay/relay-client.h b/src/plugins/relay/relay-client.h
index db2366aed..670c001d0 100644
--- a/src/plugins/relay/relay-client.h
+++ b/src/plugins/relay/relay-client.h
@@ -49,6 +49,17 @@ enum t_relay_client_data_type
RELAY_NUM_CLIENT_DATA_TYPES,
};
+/* type of message exchanged with the client (used for websockets) */
+
+enum t_relay_client_msg_type
+{
+ RELAY_CLIENT_MSG_STANDARD,
+ RELAY_CLIENT_MSG_PING,
+ RELAY_CLIENT_MSG_PONG,
+ /* number of message types */
+ RELAY_NUM_CLIENT_MSG_TYPES,
+};
+
/* macros for status */
#define RELAY_CLIENT_HAS_ENDED(client) \
@@ -61,6 +72,7 @@ struct t_relay_client_outqueue
{
char *data; /* data to send */
int data_size; /* number of bytes */
+ int raw_msg_type[2]; /* msgs types */
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 */
@@ -107,6 +119,7 @@ struct t_relay_client
};
extern char *relay_client_status_string[];
+extern char *relay_client_msg_type_string[];
extern struct t_relay_client *relay_clients;
extern struct t_relay_client *last_relay_client;
extern int relay_client_count;
@@ -117,7 +130,9 @@ extern struct t_relay_client *relay_client_search_by_id (int id);
extern int relay_client_status_search (const char *name);
extern void relay_client_set_desc (struct t_relay_client *client);
extern int relay_client_recv_cb (void *arg_client, int fd);
-extern int relay_client_send (struct t_relay_client *client, const char *data,
+extern int relay_client_send (struct t_relay_client *client,
+ enum t_relay_client_msg_type msg_type,
+ const char *data,
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,
diff --git a/src/plugins/relay/relay-raw.c b/src/plugins/relay/relay-raw.c
index 28a1b55b6..5b8d32209 100644
--- a/src/plugins/relay/relay-raw.c
+++ b/src/plugins/relay/relay-raw.c
@@ -218,17 +218,20 @@ relay_raw_message_add_to_list (time_t date, const char *prefix,
*/
void
-relay_raw_message_add (struct t_relay_client *client, int flags,
+relay_raw_message_add (struct t_relay_client *client,
+ enum t_relay_client_msg_type msg_type,
+ int flags,
const char *data, int data_size)
{
- char *buf, *buf2, prefix[256], prefix_arrow[16];
+ char *buf, *buf2, *buf3, prefix[256], prefix_arrow[16];
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, length;
struct t_relay_raw_message *new_raw_message;
buf = NULL;
buf2 = NULL;
+ buf3 = NULL;
if (flags & RELAY_RAW_FLAG_BINARY)
{
@@ -274,7 +277,12 @@ relay_raw_message_add (struct t_relay_client *client, int flags,
}
buf2[pos_buf2] = '\0';
}
+ }
+ if (!(flags & RELAY_RAW_FLAG_BINARY)
+ || (msg_type == RELAY_CLIENT_MSG_PING)
+ || (msg_type == RELAY_CLIENT_MSG_PONG))
+ {
/* build prefix with arrow */
prefix_arrow[0] = '\0';
switch (flags & (RELAY_RAW_FLAG_RECV | RELAY_RAW_FLAG_SEND))
@@ -319,10 +327,20 @@ relay_raw_message_add (struct t_relay_client *client, int flags,
}
}
+ length = strlen (relay_client_msg_type_string[msg_type]) +
+ strlen ((buf2) ? buf2 : ((buf) ? buf : data)) + 1;
+ buf3 = malloc (length);
+ if (buf3)
+ {
+ snprintf (buf3, length, "%s%s",
+ relay_client_msg_type_string[msg_type],
+ (buf2) ? buf2 : ((buf) ? buf : data));
+ }
+
new_raw_message = relay_raw_message_add_to_list (
time (NULL),
prefix,
- (buf2) ? buf2 : ((buf) ? buf : data));
+ (buf3) ? buf3 : ((buf2) ? buf2 : ((buf) ? buf : data)));
if (new_raw_message)
{
@@ -336,6 +354,8 @@ relay_raw_message_add (struct t_relay_client *client, int flags,
free (buf);
if (buf2)
free (buf2);
+ if (buf3)
+ free (buf3);
}
/*
@@ -343,14 +363,15 @@ relay_raw_message_add (struct t_relay_client *client, int flags,
*/
void
-relay_raw_print (struct t_relay_client *client, int flags,
+relay_raw_print (struct t_relay_client *client,
+ enum t_relay_client_msg_type msg_type, 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);
+ relay_raw_message_add (client, msg_type, flags, data, data_size);
}
/*
diff --git a/src/plugins/relay/relay-raw.h b/src/plugins/relay/relay-raw.h
index a4d8d4f02..4546a2b5d 100644
--- a/src/plugins/relay/relay-raw.h
+++ b/src/plugins/relay/relay-raw.h
@@ -20,6 +20,8 @@
#ifndef WEECHAT_RELAY_RAW_H
#define WEECHAT_RELAY_RAW_H 1
+#include "relay-client.h"
+
#define RELAY_RAW_BUFFER_NAME "relay_raw"
#define RELAY_RAW_PREFIX_RECV "-->"
#define RELAY_RAW_PREFIX_SEND "<--"
@@ -47,7 +49,8 @@ extern void relay_raw_open (int switch_to_buffer);
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,
+extern void relay_raw_print (struct t_relay_client *client,
+ enum t_relay_client_msg_type msg_type, int flags,
const char *data, int data_size);
extern void relay_raw_message_free_all ();
extern int relay_raw_add_to_infolist (struct t_infolist *infolist,
diff --git a/src/plugins/relay/relay-websocket.c b/src/plugins/relay/relay-websocket.c
index 95a59f4b4..e9c1fd410 100644
--- a/src/plugins/relay/relay-websocket.c
+++ b/src/plugins/relay/relay-websocket.c
@@ -29,6 +29,7 @@
#include "relay.h"
#include "relay-client.h"
#include "relay-config.h"
+#include "relay-websocket.h"
/*
@@ -249,7 +250,8 @@ relay_websocket_send_http (struct t_relay_client *client,
if (message)
{
snprintf (message, length, "HTTP/1.1 %s\r\n\r\n", http);
- relay_client_send (client, message, strlen (message), NULL);
+ relay_client_send (client, RELAY_CLIENT_MSG_STANDARD,
+ message, strlen (message), NULL);
free (message);
}
}
@@ -269,6 +271,7 @@ relay_websocket_decode_frame (const unsigned char *buffer,
unsigned long long *decoded_length)
{
unsigned long long i, index_buffer, length_frame_size, length_frame;
+ unsigned char opcode;
*decoded_length = 0;
index_buffer = 0;
@@ -276,6 +279,8 @@ relay_websocket_decode_frame (const unsigned char *buffer,
/* loop to decode all frames in message */
while (index_buffer + 2 <= buffer_length)
{
+ opcode = buffer[index_buffer] & 15;
+
/*
* 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)
@@ -311,13 +316,18 @@ relay_websocket_decode_frame (const unsigned char *buffer,
}
index_buffer += 4;
+ /* copy opcode in decoded data */
+ decoded[*decoded_length] = (opcode == WEBSOCKET_FRAME_OPCODE_PING) ?
+ RELAY_CLIENT_MSG_PING : RELAY_CLIENT_MSG_STANDARD;
+ *decoded_length += 1;
+
/* decode data using masks */
for (i = 0; i < length_frame; i++)
{
decoded[*decoded_length + i] = (int)((unsigned char)buffer[index_buffer + i]) ^ masks[i % 4];
}
decoded[*decoded_length + length_frame] = '\0';
- *decoded_length += length_frame;
+ *decoded_length += length_frame + 1;
index_buffer += length_frame;
}
@@ -334,7 +344,7 @@ relay_websocket_decode_frame (const unsigned char *buffer,
*/
char *
-relay_websocket_encode_frame (struct t_relay_client *client,
+relay_websocket_encode_frame (int opcode,
const char *buffer,
unsigned long long length,
unsigned long long *length_frame)
@@ -348,7 +358,8 @@ relay_websocket_encode_frame (struct t_relay_client *client,
if (!frame)
return NULL;
- frame[0] = (client->send_data_type == RELAY_CLIENT_DATA_TEXT) ? 0x81 : 0x82;
+ frame[0] = 0x80;
+ frame[0] |= opcode;
if (length <= 125)
{
diff --git a/src/plugins/relay/relay-websocket.h b/src/plugins/relay/relay-websocket.h
index 8d6e565b9..54eab904a 100644
--- a/src/plugins/relay/relay-websocket.h
+++ b/src/plugins/relay/relay-websocket.h
@@ -20,6 +20,13 @@
#ifndef WEECHAT_RELAY_WEBSOCKET_H
#define WEECHAT_RELAY_WEBSOCKET_H 1
+#define WEBSOCKET_FRAME_OPCODE_CONTINUATION 0x00
+#define WEBSOCKET_FRAME_OPCODE_TEXT 0x01
+#define WEBSOCKET_FRAME_OPCODE_BINARY 0x02
+#define WEBSOCKET_FRAME_OPCODE_CLOSE 0x08
+#define WEBSOCKET_FRAME_OPCODE_PING 0x09
+#define WEBSOCKET_FRAME_OPCODE_PONG 0x0A
+
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);
@@ -31,7 +38,7 @@ extern int relay_websocket_decode_frame (const unsigned char *buffer,
unsigned long long length,
unsigned char *decoded,
unsigned long long *decoded_length);
-extern char *relay_websocket_encode_frame (struct t_relay_client *client,
+extern char *relay_websocket_encode_frame (int opcode,
const char *buffer,
unsigned long long length,
unsigned long long *length_frame);
diff --git a/src/plugins/relay/weechat/relay-weechat-msg.c b/src/plugins/relay/weechat/relay-weechat-msg.c
index 8ddc1fc1f..b84ec94d4 100644
--- a/src/plugins/relay/weechat/relay-weechat-msg.c
+++ b/src/plugins/relay/weechat/relay-weechat-msg.c
@@ -1057,7 +1057,8 @@ relay_weechat_msg_send (struct t_relay_client *client,
msg->id);
/* send compressed data */
- relay_client_send (client, (const char *)dest, dest_size + 5,
+ relay_client_send (client, RELAY_CLIENT_MSG_STANDARD,
+ (const char *)dest, dest_size + 5,
raw_message);
free (dest);
@@ -1082,7 +1083,8 @@ relay_weechat_msg_send (struct t_relay_client *client,
/* send uncompressed data */
snprintf (raw_message, sizeof (raw_message),
"obj: %d bytes, id: %s", msg->data_size, msg->id);
- relay_client_send (client, msg->data, msg->data_size, raw_message);
+ relay_client_send (client, RELAY_CLIENT_MSG_STANDARD,
+ msg->data, msg->data_size, raw_message);
}
/*