1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-27 13:26:38 +02:00

relay: add commands "sync" and "desync" in WeeChat protocol

This commit is contained in:
Sebastien Helleu
2011-12-17 17:39:19 +01:00
parent f0b8181395
commit 16ae7e2663
7 changed files with 812 additions and 59 deletions
+117 -10
View File
@@ -4,7 +4,7 @@ Sébastien Helleu <flashcode@flashtux.org>
This document is the specification of WeeChat relay protocol: the protocol used
to relay WeeChat data to clients, which are mostly remote interfaces (GUI).
to relay WeeChat data to clients, which are mostly remote interfaces.
[WARNING]
This document is a *DRAFT*. +
@@ -24,7 +24,7 @@ The following terms are used in this document:
* 'relay': this is the WeeChat with relay plugin, which acts as "server" and
allows 'clients' to connect
* 'client': this is another software, connected to 'relay' via a network
connection; in most cases, this 'client' is a remote GUI
connection; in most cases, this 'client' is a remote interface
[[network_diagram]]
Network diagram
@@ -46,7 +46,7 @@ The 'clients' are connected to 'relay' like shown in this diagram:
└─────────────┘ └─────────────────────┘╘══════════╛└──────────────────────┘
network servers ncurses interface relay graphical interfaces
network servers ncurses interface relay remote interfaces
protocol
........................................
@@ -95,6 +95,8 @@ List of available commands (detail in next chapters):
| infolist | Request infolist
| nicklist | Request nicklist
| input | Send data to a buffer (text or command)
| sync | Synchronize buffer(s) (get updates for buffer(s))
| desync | Desynchronize buffer(s) (stop updates for buffer(s))
| quit | Disconnect from 'relay'
|=====================================================
@@ -280,6 +282,82 @@ input core.weechat /help filter
input irc.freenode.#weechat hello guys!
----------------------------------------
[[command_sync]]
sync
~~~~
Synchronize one or more buffers, to get updates.
Syntax:
----------------------------------------
sync [<buffer>[,<buffer>...] <options>]
----------------------------------------
Arguments:
* 'buffer': pointer ('0x12345') or full name of buffer (for example:
'core.weechat' or 'irc.freenode.#weechat'); name '*' can be used to
specify all buffers
* 'options': one of following keywords, separated by commas (default is
'buffer,nicklist'):
** 'buffer': receive signals about buffer (new lines, buffer renamed/moved/...)
** 'nicklist': receive nicklist after changes
Examples:
----------------------------------------
# synchronize all buffers with nicklist (the 3 commands are equivalent)
sync
sync *
sync * buffer,nicklist
# synchronize core buffer
sync core.buffer
# synchronize #weechat channel, without nicklist
sync irc.freenode.#weechat buffer
----------------------------------------
[[command_desync]]
desync
~~~~~~
Desynchronize one or more buffers, to stop updates.
[NOTE]
This will remove 'options' for buffers. If some options are still active for
buffers, the client will still receive updates for buffers.
Syntax:
----------------------------------------
desync [<buffer>[,<buffer>...] <options>]
----------------------------------------
Arguments:
* 'buffer': pointer ('0x12345') or full name of buffer (for example:
'core.weechat' or 'irc.freenode.#weechat'); name '*' can be used to
specify all buffers
* 'options': one of following keywords, separated by commas (default is
'buffer,nicklist'):
** 'buffer': receive signals about buffer (new lines, buffer renamed/moved...)
** 'nicklist': receive nicklist after changes
Examples:
----------------------------------------
# desynchronize all buffers
desync
# desynchronize nicklist for #weechat channel (keep buffer updates)
desync irc.freenode.#weechat nicklist
# desynchronize #weechat channel
desync irc.freenode.#weechat
----------------------------------------
[[command_quit]]
quit
~~~~
@@ -346,11 +424,40 @@ There are two different identifiers ('id'):
WeeChat reserved identifiers:
[width="100%",cols="^2m,8,8",options="header"]
[width="100%",cols="4m,3,2,15",options="header"]
|=====================================================
| Id | Description | Object(s) sent
| _line_added | Line added in a buffer (NOT DEVELOPED) | hdata, type: line_data
| ... | TO BE COMPLETED | ...
| Identifier | Description | Hdata type | Hdata content
| _buffer_opened | Buffer opened | buffer |
'number' (integer), 'full_name' (string), 'short_name' (string), +
'nicklist' (integer), 'title' (string), +
'prev_buffer' (pointer), 'next_buffer' (pointer)
| _buffer_moved | Buffer moved | buffer |
'number' (integer), 'full_name' (string), +
'prev_buffer' (pointer), 'next_buffer' (pointer)
| _buffer_merged | Buffer merged | buffer |
'number' (integer), 'full_name' (string), +
'prev_buffer' (pointer), 'next_buffer' (pointer)
| _buffer_renamed | Buffer renamed | buffer |
'number' (integer), 'full_name' (string), 'short_name' (string)
| _buffer_title_changed | Buffer moved | buffer |
'number' (integer), 'full_name' (string), 'title' (string)
| _buffer_line_added | Line added in buffer | line_data |
'buffer' (pointer), 'date' (time), 'displayed' (char), 'prefix' (string),
'message' (string)
| _buffer_closing | Buffer closing | buffer |
'number' (integer), 'full_name' (string)
| _nicklist | Nicklist for a buffer | nicklist_item |
'group' (char), 'visible' (char), 'level' (integer), +
'name' (string), 'color' (string), +
'prefix' (string), 'prefix_color' (string)
|=====================================================
[[message_objects]]
@@ -360,7 +467,7 @@ Objects
Objects are identified by 3 letters, called 'type'. Following types are
available:
[width="100%",cols="^2m,8,8",options="header"]
[width="60%",cols="^2m,5,7",options="header"]
|=====================================================
| Type | Value | Length
| chr | Signed char | 1 byte
@@ -682,7 +789,7 @@ Typical session
║ ║ ║
╟─────────────────────────────────────► ║ ║
║ cmd: hdata buffer ... ╟─────────────────────────► ║
║ request hdata ║ read hdata values
sync ... ║ request hdata ║ read hdata values
║ ║ ║
║ ║ ◄─────────────────────────╢
║ ◄─────────────────────────────────────╢ hdata ║
@@ -698,7 +805,7 @@ create buffers ║ msg: hda buffer ║
║ ║ ║ signal received
║ ║ ◄─────────────────────────╢ (hooked by relay)
║ ◄─────────────────────────────────────╢ signal XXX ║
update buffers ║ msg: event XXX ║ ║
update buffers ║ msg: id: "_buffer_..." ║ ║
║ ║ ║
║ ........ ║ ........ ║
║ ║ ║
+44 -38
View File
@@ -599,7 +599,7 @@ relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
void *pointer,
const char *arguments)
{
struct t_infolist *infolist;
struct t_infolist *ptr_infolist;
const char *fields;
char **list_fields;
void *buf_ptr;
@@ -607,8 +607,8 @@ relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
int pos_count_items, count_items, pos_count_vars, count_vars;
uint32_t count32;
infolist = weechat_infolist_get (name, pointer, arguments);
if (!infolist)
ptr_infolist = weechat_infolist_get (name, pointer, arguments);
if (!ptr_infolist)
return;
/* start infolist in message */
@@ -620,9 +620,9 @@ relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
count_items = 0;
relay_weechat_msg_add_int (msg, 0);
while (weechat_infolist_next (infolist))
while (weechat_infolist_next (ptr_infolist))
{
fields = weechat_infolist_fields (infolist);
fields = weechat_infolist_fields (ptr_infolist);
if (fields)
{
list_fields = weechat_string_split (fields, ",", 0, 0, &num_fields);
@@ -643,24 +643,24 @@ relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
case 'i':
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_INT);
relay_weechat_msg_add_int (msg,
weechat_infolist_integer (infolist,
weechat_infolist_integer (ptr_infolist,
list_fields[i] + 2));
break;
case 's':
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_STRING);
relay_weechat_msg_add_string (msg,
weechat_infolist_string (infolist,
weechat_infolist_string (ptr_infolist,
list_fields[i] + 2));
break;
case 'p':
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_POINTER);
relay_weechat_msg_add_pointer (msg,
weechat_infolist_pointer (infolist,
weechat_infolist_pointer (ptr_infolist,
list_fields[i] + 2));
break;
case 'b':
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_BUFFER);
buf_ptr = weechat_infolist_buffer (infolist,
buf_ptr = weechat_infolist_buffer (ptr_infolist,
list_fields[i] + 2,
&buf_size);
relay_weechat_msg_add_buffer (msg, buf_ptr, buf_size);
@@ -668,7 +668,7 @@ relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
case 't':
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_TIME);
relay_weechat_msg_add_time (msg,
weechat_infolist_time (infolist,
weechat_infolist_time (ptr_infolist,
list_fields[i] + 2));
break;
}
@@ -688,7 +688,7 @@ relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
count32 = htonl ((uint32_t)count_items);
relay_weechat_msg_set_bytes (msg, pos_count_items, &count32, 4);
weechat_infolist_free (infolist);
weechat_infolist_free (ptr_infolist);
}
/*
@@ -726,6 +726,10 @@ relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg,
(char)weechat_hdata_integer(ptr_hdata_nick,
ptr_nick,
"visible"));
relay_weechat_msg_add_int (msg,
weechat_hdata_integer (ptr_hdata_nick,
ptr_nick,
"level"));
relay_weechat_msg_add_string (msg,
weechat_hdata_string (ptr_hdata_nick,
ptr_nick,
@@ -742,10 +746,6 @@ relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg,
weechat_hdata_string (ptr_hdata_nick,
ptr_nick,
"prefix_color"));
relay_weechat_msg_add_int (msg,
weechat_hdata_integer (ptr_hdata_nick,
ptr_nick,
"level"));
count++;
}
else
@@ -757,6 +757,10 @@ relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg,
(char)weechat_hdata_integer(ptr_hdata_group,
ptr_group,
"visible"));
relay_weechat_msg_add_int (msg,
weechat_hdata_integer (ptr_hdata_group,
ptr_group,
"level"));
relay_weechat_msg_add_string (msg,
weechat_hdata_string (ptr_hdata_group,
ptr_group,
@@ -767,10 +771,6 @@ relay_weechat_msg_add_nicklist_buffer (struct t_relay_weechat_msg *msg,
"color"));
relay_weechat_msg_add_string (msg, NULL); /* prefix */
relay_weechat_msg_add_string (msg, NULL); /* prefix_color */
relay_weechat_msg_add_int (msg,
weechat_hdata_integer (ptr_hdata_group,
ptr_group,
"level"));
count++;
}
weechat_nicklist_get_next_item (buffer, &ptr_group, &ptr_nick);
@@ -794,10 +794,11 @@ relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg,
uint32_t count32;
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HDATA);
relay_weechat_msg_add_string (msg, "buffer/nick_group");
relay_weechat_msg_add_string (msg, "buffer/nicklist_item");
relay_weechat_msg_add_string (msg,
"group:chr,visible:chr,name:str,color:str,"
"prefix:str,prefix_color:str,level:int");
"group:chr,visible:chr,level:int,"
"name:str,color:str,"
"prefix:str,prefix_color:str");
/* "count" will be set later, with number of objects in hdata */
pos_count = msg->data_size;
@@ -827,7 +828,8 @@ relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg,
void
relay_weechat_msg_send (struct t_relay_client *client,
struct t_relay_weechat_msg *msg)
struct t_relay_weechat_msg *msg,
int display_in_raw_buffer)
{
uint32_t size32;
char compression;
@@ -862,18 +864,20 @@ relay_weechat_msg_send (struct t_relay_client *client,
num_sent = send (client->sock, dest, dest_size + 5, 0);
/* 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);
if (num_sent < 0)
if (display_in_raw_buffer)
{
relay_raw_print (client, RELAY_RAW_FLAG_SEND,
"error: %s", strerror (errno));
"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);
if (num_sent < 0)
{
relay_raw_print (client, RELAY_RAW_FLAG_SEND,
"error: %s", strerror (errno));
}
}
free (dest);
@@ -894,13 +898,15 @@ relay_weechat_msg_send (struct t_relay_client *client,
num_sent = send (client->sock, msg->data, msg->data_size, 0);
/* display message in raw buffer */
relay_raw_print (client, RELAY_RAW_FLAG_SEND,
"obj: %d bytes", msg->data_size);
if (num_sent < 0)
if (display_in_raw_buffer)
{
relay_raw_print (client, RELAY_RAW_FLAG_SEND,
"error: %s", strerror (errno));
"obj: %d bytes", msg->data_size);
if (num_sent < 0)
{
relay_raw_print (client, RELAY_RAW_FLAG_SEND,
"error: %s", strerror (errno));
}
}
}
@@ -64,9 +64,6 @@ extern void relay_weechat_msg_add_pointer (struct t_relay_weechat_msg *msg,
void *pointer);
extern void relay_weechat_msg_add_time (struct t_relay_weechat_msg *msg,
time_t time);
extern void relay_weechat_msg_add_hdata1 (struct t_relay_weechat_msg *msg,
const char *name, const char *list,
const char *keys);
extern void relay_weechat_msg_add_hdata (struct t_relay_weechat_msg *msg,
const char *path, const char *keys);
extern void relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
@@ -76,7 +73,8 @@ extern void relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
extern void relay_weechat_msg_add_nicklist (struct t_relay_weechat_msg *msg,
struct t_gui_buffer *buffer);
extern void relay_weechat_msg_send (struct t_relay_client *client,
struct t_relay_weechat_msg *msg);
struct t_relay_weechat_msg *msg,
int display_in_raw_buffer);
extern void relay_weechat_msg_free (struct t_relay_weechat_msg *msg);
#endif /* __WEECHAT_RELAY_WEECHAT_MSG_H */
@@ -49,6 +49,7 @@ relay_weechat_protocol_get_buffer (const char *arg)
long unsigned int value;
int rc;
char *pos, *plugin;
struct t_hdata *ptr_hdata;
ptr_buffer = NULL;
@@ -56,7 +57,18 @@ relay_weechat_protocol_get_buffer (const char *arg)
{
rc = sscanf (arg, "%lx", &value);
if ((rc != EOF) && (rc != 0))
ptr_buffer = (void *)value;
ptr_buffer = (struct t_gui_buffer *)value;
if (ptr_buffer)
{
ptr_hdata = weechat_hdata_get ("buffer");
if (!weechat_hdata_check_pointer (ptr_hdata,
weechat_hdata_get_list (ptr_hdata, "gui_buffers"),
ptr_buffer))
{
/* invalid pointer! */
ptr_buffer = NULL;
}
}
}
else
{
@@ -133,7 +145,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(hdata)
{
relay_weechat_msg_add_hdata (msg, argv[0],
(argc > 1) ? argv_eol[1] : NULL);
relay_weechat_msg_send (client, msg);
relay_weechat_msg_send (client, msg, 1);
relay_weechat_msg_free (msg);
}
@@ -159,7 +171,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(info)
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_INFO);
relay_weechat_msg_add_string (msg, argv[0]);
relay_weechat_msg_add_string (msg, info);
relay_weechat_msg_send (client, msg);
relay_weechat_msg_send (client, msg, 1);
relay_weechat_msg_free (msg);
}
@@ -193,7 +205,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(infolist)
args = argv_eol[2];
}
relay_weechat_msg_add_infolist (msg, argv[0], (void *)value, args);
relay_weechat_msg_send (client, msg);
relay_weechat_msg_send (client, msg, 1);
relay_weechat_msg_free (msg);
}
@@ -224,7 +236,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(nicklist)
if (msg)
{
relay_weechat_msg_add_nicklist (msg, ptr_buffer);
relay_weechat_msg_send (client, msg);
relay_weechat_msg_send (client, msg, 1);
relay_weechat_msg_free (msg);
}
@@ -248,6 +260,460 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(input)
return WEECHAT_RC_OK;
}
/*
* relay_weechat_protocol_signal_buffer_cb: callback for "buffer_*" signals
*/
int
relay_weechat_protocol_signal_buffer_cb (void *data, const char *signal,
const char *type_data,
void *signal_data)
{
struct t_relay_client *ptr_client;
struct t_gui_line *ptr_line;
struct t_hdata *ptr_hdata_line, *ptr_hdata_line_data;
struct t_gui_line_data *ptr_line_data;
struct t_gui_buffer *ptr_buffer;
struct t_relay_weechat_msg *msg;
char cmd_hdata[64];
/* make C compiler happy */
(void) signal;
(void) type_data;
ptr_client = (struct t_relay_client *)data;
if (!ptr_client || !relay_client_valid (ptr_client))
return WEECHAT_RC_OK;
if (strcmp (signal, "buffer_opened") == 0)
{
ptr_buffer = (struct t_gui_buffer *)signal_data;
if (!ptr_buffer)
return WEECHAT_RC_OK;
msg = relay_weechat_msg_new ("_buffer_opened");
if (msg)
{
snprintf (cmd_hdata, sizeof (cmd_hdata),
"buffer:0x%lx", (long unsigned int)ptr_buffer);
relay_weechat_msg_add_hdata (msg, cmd_hdata,
"number,full_name,short_name,"
"nicklist,title,"
"prev_buffer,next_buffer");
relay_weechat_msg_send (ptr_client, msg, 0);
relay_weechat_msg_free (msg);
}
}
else if (strcmp (signal, "buffer_moved") == 0)
{
ptr_buffer = (struct t_gui_buffer *)signal_data;
if (!ptr_buffer)
return WEECHAT_RC_OK;
msg = relay_weechat_msg_new ("_buffer_moved");
if (msg)
{
snprintf (cmd_hdata, sizeof (cmd_hdata),
"buffer:0x%lx", (long unsigned int)ptr_buffer);
relay_weechat_msg_add_hdata (msg, cmd_hdata,
"number,full_name,"
"prev_buffer,next_buffer");
relay_weechat_msg_send (ptr_client, msg, 0);
relay_weechat_msg_free (msg);
}
}
else if (strcmp (signal, "buffer_merged") == 0)
{
ptr_buffer = (struct t_gui_buffer *)signal_data;
if (!ptr_buffer)
return WEECHAT_RC_OK;
msg = relay_weechat_msg_new ("_buffer_merged");
if (msg)
{
snprintf (cmd_hdata, sizeof (cmd_hdata),
"buffer:0x%lx", (long unsigned int)ptr_buffer);
relay_weechat_msg_add_hdata (msg, cmd_hdata,
"number,full_name,"
"prev_buffer,next_buffer");
relay_weechat_msg_send (ptr_client, msg, 0);
relay_weechat_msg_free (msg);
}
}
else if (strcmp (signal, "buffer_renamed") == 0)
{
ptr_buffer = (struct t_gui_buffer *)signal_data;
if (!ptr_buffer)
return WEECHAT_RC_OK;
msg = relay_weechat_msg_new ("_buffer_renamed");
if (msg)
{
snprintf (cmd_hdata, sizeof (cmd_hdata),
"buffer:0x%lx", (long unsigned int)ptr_buffer);
relay_weechat_msg_add_hdata (msg, cmd_hdata,
"number,full_name,short_name");
relay_weechat_msg_send (ptr_client, msg, 0);
relay_weechat_msg_free (msg);
}
}
else if (strcmp (signal, "buffer_title_changed") == 0)
{
ptr_buffer = (struct t_gui_buffer *)signal_data;
if (!ptr_buffer)
return WEECHAT_RC_OK;
msg = relay_weechat_msg_new ("_buffer_title_changed");
if (msg)
{
snprintf (cmd_hdata, sizeof (cmd_hdata),
"buffer:0x%lx", (long unsigned int)ptr_buffer);
relay_weechat_msg_add_hdata (msg, cmd_hdata,
"number,full_name,title");
relay_weechat_msg_send (ptr_client, msg, 0);
relay_weechat_msg_free (msg);
}
}
else if (strcmp (signal, "buffer_line_added") == 0)
{
ptr_line = (struct t_gui_line *)signal_data;
if (!ptr_line)
return WEECHAT_RC_OK;
ptr_hdata_line = weechat_hdata_get ("line");
if (!ptr_hdata_line)
return WEECHAT_RC_OK;
ptr_hdata_line_data = weechat_hdata_get ("line_data");
if (!ptr_hdata_line_data)
return WEECHAT_RC_OK;
ptr_line_data = weechat_hdata_pointer (ptr_hdata_line, ptr_line, "data");
if (!ptr_line_data)
return WEECHAT_RC_OK;
ptr_buffer = weechat_hdata_pointer (ptr_hdata_line_data, ptr_line_data,
"buffer");
if (!ptr_buffer)
return WEECHAT_RC_OK;
/* check if buffer is synchronized (== able to receive events) */
if (weechat_hashtable_has_key (RELAY_WEECHAT_DATA(ptr_client, buffers_sync),
"*")
|| weechat_hashtable_has_key (RELAY_WEECHAT_DATA(ptr_client, buffers_sync),
weechat_buffer_get_string (ptr_buffer,
"full_name")))
{
msg = relay_weechat_msg_new ("_buffer_line_added");
if (msg)
{
snprintf (cmd_hdata, sizeof (cmd_hdata),
"line_data:0x%lx",
(long unsigned int)ptr_line_data);
relay_weechat_msg_add_hdata (msg, cmd_hdata,
"buffer,date,displayed,prefix,message");
relay_weechat_msg_send (ptr_client, msg, 0);
relay_weechat_msg_free (msg);
}
}
}
else if (strcmp (signal, "buffer_closing") == 0)
{
ptr_buffer = (struct t_gui_buffer *)signal_data;
if (!ptr_buffer)
return WEECHAT_RC_OK;
msg = relay_weechat_msg_new ("_buffer_closing");
if (msg)
{
snprintf (cmd_hdata, sizeof (cmd_hdata),
"buffer:0x%lx", (long unsigned int)ptr_buffer);
weechat_hashtable_remove (RELAY_WEECHAT_DATA(ptr_client, buffers_nicklist),
cmd_hdata + 7);
relay_weechat_msg_add_hdata (msg, cmd_hdata,
"number,full_name");
relay_weechat_msg_send (ptr_client, msg, 0);
relay_weechat_msg_free (msg);
}
}
return WEECHAT_RC_OK;
}
/*
* relay_weechat_protocol_nicklist_map_cb: callback for entries in hashtable
* "buffers_nicklist" of client
* (send nicklist for each buffer in
* this hashtable)
*/
void
relay_weechat_protocol_nicklist_map_cb (void *data,
struct t_hashtable *hashtable,
const void *key,
const void *value)
{
struct t_relay_client *ptr_client;
int rc;
long unsigned int buffer;
struct t_hdata *ptr_hdata;
struct t_relay_weechat_msg *msg;
/* make C compiler happy */
(void) hashtable;
(void) value;
ptr_client = (struct t_relay_client *)data;
rc = sscanf (key, "%lx", &buffer);
if ((rc != EOF) && (rc != 0))
{
ptr_hdata = weechat_hdata_get ("buffer");
if (ptr_hdata)
{
if (weechat_hdata_check_pointer (ptr_hdata,
weechat_hdata_get_list (ptr_hdata, "gui_buffers"),
(void *)buffer))
{
msg = relay_weechat_msg_new ("_nicklist");
if (msg)
{
relay_weechat_msg_add_nicklist (msg, (struct t_gui_buffer *)buffer);
relay_weechat_msg_send (ptr_client, msg, 1);
relay_weechat_msg_free (msg);
}
}
}
}
}
/*
* relay_weechat_protocol_timer_nicklist_cb: callback for nicklist timer
*/
int
relay_weechat_protocol_timer_nicklist_cb (void *data, int remaining_calls)
{
struct t_relay_client *ptr_client;
/* make C compiler happy */
(void) remaining_calls;
ptr_client = (struct t_relay_client *)data;
if (!ptr_client || !relay_client_valid (ptr_client))
return WEECHAT_RC_OK;
weechat_hashtable_map (RELAY_WEECHAT_DATA(ptr_client, buffers_nicklist),
&relay_weechat_protocol_nicklist_map_cb,
ptr_client);
weechat_hashtable_remove_all (RELAY_WEECHAT_DATA(ptr_client, buffers_nicklist));
RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist) = NULL;
return WEECHAT_RC_OK;
}
/*
* relay_weechat_protocol_signal_nicklist_cb: callback for "nicklist_*" signals
*/
int
relay_weechat_protocol_signal_nicklist_cb (void *data, const char *signal,
const char *type_data,
void *signal_data)
{
struct t_relay_client *ptr_client;
char *pos, *str_buffer;
/* make C compiler happy */
(void) signal;
(void) type_data;
ptr_client = (struct t_relay_client *)data;
if (!ptr_client || !relay_client_valid (ptr_client))
return WEECHAT_RC_OK;
pos = strchr ((char *)signal_data, ',');
if (!pos)
return WEECHAT_RC_OK;
str_buffer = weechat_strndup (signal_data, pos - (char *)signal_data);
if (!str_buffer)
return WEECHAT_RC_OK;
weechat_hashtable_set (RELAY_WEECHAT_DATA(ptr_client, buffers_nicklist),
str_buffer, "1");
free (str_buffer);
if (RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist))
{
weechat_unhook (RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist));
RELAY_WEECHAT_DATA(ptr_client, hook_timer_nicklist) = NULL;
}
relay_weechat_hook_timer_nicklist (ptr_client);
return WEECHAT_RC_OK;
}
/*
* relay_weechat_protocol_cb_sync: 'sync' command from client
*/
RELAY_WEECHAT_PROTOCOL_CALLBACK(sync)
{
char **buffers, **flags, *full_name;
int num_buffers, num_flags, i, add_flags, *ptr_old_flags, new_flags;
struct t_gui_buffer *ptr_buffer;
RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0);
buffers = weechat_string_split ((argc > 0) ? argv[1] : "*", ",", 0, 0,
&num_buffers);
if (buffers)
{
add_flags = RELAY_WEECHAT_PROTOCOL_SYNC_BUFFER |
RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST;
if (argc > 1)
{
flags = weechat_string_split (argv[2], ",", 0, 0, &num_flags);
if (flags)
{
add_flags = 0;
for (i = 0; i < num_flags; i++)
{
if (strcmp (flags[i], "buffer") == 0)
add_flags |= RELAY_WEECHAT_PROTOCOL_SYNC_BUFFER;
else if (strcmp (flags[i], "nicklist") == 0)
add_flags |= RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST;
}
if (add_flags == 0)
{
add_flags = RELAY_WEECHAT_PROTOCOL_SYNC_BUFFER |
RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST;
}
weechat_string_free_split (flags);
}
}
for (i = 0; i < num_buffers; i++)
{
full_name = NULL;
if (strcmp (buffers[i], "*") == 0)
{
full_name = strdup ("*");
}
else
{
ptr_buffer = relay_weechat_protocol_get_buffer (buffers[i]);
if (ptr_buffer)
full_name = strdup (weechat_buffer_get_string (ptr_buffer,
"full_name"));
}
if (full_name)
{
ptr_old_flags = weechat_hashtable_get (RELAY_WEECHAT_DATA(client, buffers_sync),
full_name);
new_flags = ((ptr_old_flags) ? *ptr_old_flags : 0);
new_flags |= add_flags;
weechat_hashtable_set (RELAY_WEECHAT_DATA(client, buffers_sync),
full_name,
&new_flags);
free (full_name);
}
}
weechat_string_free_split (buffers);
}
if (!RELAY_WEECHAT_DATA(client, hook_signal_buffer))
relay_weechat_hook_signals (client);
return WEECHAT_RC_OK;
}
/*
* relay_weechat_protocol_cb_desync: 'desync' command from client
*/
RELAY_WEECHAT_PROTOCOL_CALLBACK(desync)
{
char **buffers, **flags, *full_name;
int num_buffers, num_flags, i, sub_flags, *ptr_old_flags, new_flags;
struct t_gui_buffer *ptr_buffer;
RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0);
buffers = weechat_string_split ((argc > 0) ? argv[1] : "*", ",", 0, 0,
&num_buffers);
if (buffers)
{
sub_flags = RELAY_WEECHAT_PROTOCOL_SYNC_BUFFER |
RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST;
if (argc > 1)
{
flags = weechat_string_split (argv[2], ",", 0, 0, &num_flags);
if (flags)
{
sub_flags = 0;
for (i = 0; i < num_flags; i++)
{
if (strcmp (flags[i], "buffer") == 0)
sub_flags |= RELAY_WEECHAT_PROTOCOL_SYNC_BUFFER;
else if (strcmp (flags[i], "nicklist") == 0)
sub_flags |= RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST;
}
if (sub_flags == 0)
{
sub_flags = RELAY_WEECHAT_PROTOCOL_SYNC_BUFFER |
RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST;
}
weechat_string_free_split (flags);
}
}
for (i = 0; i < num_buffers; i++)
{
full_name = NULL;
if (strcmp (buffers[i], "*") == 0)
{
full_name = strdup ("*");
}
else
{
ptr_buffer = relay_weechat_protocol_get_buffer (buffers[i]);
if (ptr_buffer)
full_name = strdup (weechat_buffer_get_string (ptr_buffer,
"full_name"));
}
if (full_name)
{
ptr_old_flags = weechat_hashtable_get (RELAY_WEECHAT_DATA(client, buffers_sync),
full_name);
new_flags = ((ptr_old_flags) ? *ptr_old_flags : 0);
new_flags &= ~sub_flags;
if (new_flags)
{
weechat_hashtable_set (RELAY_WEECHAT_DATA(client, buffers_sync),
full_name,
&new_flags);
}
else
{
weechat_hashtable_remove (RELAY_WEECHAT_DATA(client, buffers_sync),
full_name);
}
free (full_name);
}
}
weechat_string_free_split (buffers);
}
if (weechat_hashtable_get_integer (RELAY_WEECHAT_DATA(client, buffers_sync),
"items_count") == 0)
{
relay_weechat_unhook_signals (client);
}
return WEECHAT_RC_OK;
}
/*
* relay_weechat_protocol_cb_test: 'test' command from client
*/
@@ -281,7 +747,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(test)
relay_weechat_msg_add_pointer (msg, &msg);
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_TIME);
relay_weechat_msg_add_time (msg, 1321993456);
relay_weechat_msg_send (client, msg);
relay_weechat_msg_send (client, msg, 1);
relay_weechat_msg_free (msg);
}
@@ -317,6 +783,8 @@ relay_weechat_protocol_recv (struct t_relay_client *client, char *data)
{ "infolist", &relay_weechat_protocol_cb_infolist },
{ "nicklist", &relay_weechat_protocol_cb_nicklist },
{ "input", &relay_weechat_protocol_cb_input },
{ "sync", &relay_weechat_protocol_cb_sync },
{ "desync", &relay_weechat_protocol_cb_desync },
{ "test", &relay_weechat_protocol_cb_test },
{ "quit", &relay_weechat_protocol_cb_quit },
{ NULL, NULL }
@@ -20,6 +20,9 @@
#ifndef __WEECHAT_RELAY_WEECHAT_PROTOCOL_H
#define __WEECHAT_RELAY_WEECHAT_PROTOCOL_H 1
#define RELAY_WEECHAT_PROTOCOL_SYNC_BUFFER 1
#define RELAY_WEECHAT_PROTOCOL_SYNC_NICKLIST 2
#define RELAY_WEECHAT_PROTOCOL_CALLBACK(__command) \
int \
relay_weechat_protocol_cb_##__command ( \
@@ -57,6 +60,16 @@ struct t_relay_weechat_protocol_cb
t_relay_weechat_cmd_func *cmd_function; /* callback */
};
extern int relay_weechat_protocol_signal_buffer_cb (void *data,
const char *signal,
const char *type_data,
void *signal_data);
extern int relay_weechat_protocol_signal_nicklist_cb (void *data,
const char *signal,
const char *type_data,
void *signal_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);
+151 -1
View File
@@ -66,6 +66,55 @@ relay_weechat_compression_search (const char *compression)
return -1;
}
/*
* relay_weechat_hook_signals: hook signals for a client
*/
void
relay_weechat_hook_signals (struct t_relay_client *client)
{
RELAY_WEECHAT_DATA(client, hook_signal_buffer) =
weechat_hook_signal ("buffer_*",
&relay_weechat_protocol_signal_buffer_cb,
client);
RELAY_WEECHAT_DATA(client, hook_signal_nicklist) =
weechat_hook_signal ("nicklist_*",
&relay_weechat_protocol_signal_nicklist_cb,
client);
}
/*
* relay_weechat_unhook_signals: unhook signals for a client
*/
void
relay_weechat_unhook_signals (struct t_relay_client *client)
{
if (RELAY_WEECHAT_DATA(client, hook_signal_buffer))
{
weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_buffer));
RELAY_WEECHAT_DATA(client, hook_signal_buffer) = NULL;
}
if (RELAY_WEECHAT_DATA(client, hook_signal_nicklist))
{
weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_nicklist));
RELAY_WEECHAT_DATA(client, hook_signal_nicklist) = NULL;
}
}
/*
* relay_weechat_hook_timer_nicklist: timer to update nicklists for a client
*/
void
relay_weechat_hook_timer_nicklist (struct t_relay_client *client)
{
RELAY_WEECHAT_DATA(client, hook_timer_nicklist) =
weechat_hook_timer (100, 0, 1,
&relay_weechat_protocol_timer_nicklist_cb,
client);
}
/*
* relay_weechat_recv: read data from client
*/
@@ -124,7 +173,7 @@ relay_weechat_recv (struct t_relay_client *client, const char *data)
void
relay_weechat_close_connection (struct t_relay_client *client)
{
(void) client;
relay_weechat_unhook_signals (client);
}
/*
@@ -148,6 +197,21 @@ relay_weechat_alloc (struct t_relay_client *client)
#else
RELAY_WEECHAT_DATA(client, compression) = 0;
#endif
RELAY_WEECHAT_DATA(client, buffers_sync) =
weechat_hashtable_new (16,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_INTEGER,
NULL,
NULL);
RELAY_WEECHAT_DATA(client, hook_signal_buffer) = NULL;
RELAY_WEECHAT_DATA(client, hook_signal_nicklist) = NULL;
RELAY_WEECHAT_DATA(client, buffers_nicklist) =
weechat_hashtable_new (16,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL,
NULL);
RELAY_WEECHAT_DATA(client, hook_timer_nicklist) = NULL;
}
}
@@ -161,12 +225,70 @@ relay_weechat_alloc_with_infolist (struct t_relay_client *client,
struct t_infolist *infolist)
{
struct t_relay_weechat_data *weechat_data;
int index, rc, value_int;
char name[64];
const char *key, *value;
client->protocol_data = malloc (sizeof (*weechat_data));
if (client->protocol_data)
{
/* general stuff */
RELAY_WEECHAT_DATA(client, password_ok) = weechat_infolist_integer (infolist, "password_ok");
RELAY_WEECHAT_DATA(client, compression) = weechat_infolist_integer (infolist, "compression");
/* sync of buffers */
RELAY_WEECHAT_DATA(client, buffers_sync) = weechat_hashtable_new (16,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL,
NULL);
index = 0;
while (1)
{
snprintf (name, sizeof (name), "buffers_sync_name_%05d", index);
key = weechat_infolist_string (infolist, name);
if (!key)
break;
snprintf (name, sizeof (name), "buffers_sync_value_%05d", index);
value = weechat_infolist_string (infolist, name);
rc = sscanf (value, "%d", &value_int);
if ((rc == EOF) || (rc == 0))
value_int = 0;
weechat_hashtable_set (RELAY_WEECHAT_DATA(client, buffers_sync),
key,
&value_int);
index++;
}
RELAY_WEECHAT_DATA(client, hook_signal_buffer) = NULL;
RELAY_WEECHAT_DATA(client, hook_signal_nicklist) = NULL;
RELAY_WEECHAT_DATA(client, buffers_nicklist) =
weechat_hashtable_new (16,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL,
NULL);
index = 0;
while (1)
{
snprintf (name, sizeof (name), "buffers_nicklist_name_%05d", index);
key = weechat_infolist_string (infolist, name);
if (!key)
break;
snprintf (name, sizeof (name), "buffers_nicklist_value_%05d", index);
value = weechat_infolist_string (infolist, name);
weechat_hashtable_set (RELAY_WEECHAT_DATA(client, buffers_sync),
key,
value);
index++;
}
RELAY_WEECHAT_DATA(client, hook_timer_nicklist) = NULL;
if (weechat_hashtable_get_integer (RELAY_WEECHAT_DATA(client, buffers_sync),
"items_count") > 0)
relay_weechat_hook_signals (client);
if (weechat_hashtable_get_integer (RELAY_WEECHAT_DATA(client, buffers_sync),
"items_count") > 0)
relay_weechat_hook_timer_nicklist (client);
}
}
@@ -178,7 +300,20 @@ void
relay_weechat_free (struct t_relay_client *client)
{
if (client->protocol_data)
{
if (RELAY_WEECHAT_DATA(client, buffers_sync))
weechat_hashtable_free (RELAY_WEECHAT_DATA(client, buffers_sync));
if (RELAY_WEECHAT_DATA(client, hook_signal_buffer))
weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_buffer));
if (RELAY_WEECHAT_DATA(client, hook_signal_nicklist))
weechat_unhook (RELAY_WEECHAT_DATA(client, hook_signal_nicklist));
if (RELAY_WEECHAT_DATA(client, buffers_nicklist))
weechat_hashtable_free (RELAY_WEECHAT_DATA(client, buffers_nicklist));
free (client->protocol_data);
client->protocol_data = NULL;
}
}
/*
@@ -197,6 +332,10 @@ relay_weechat_add_to_infolist (struct t_infolist_item *item,
return 0;
if (!weechat_infolist_new_var_integer (item, "compression", RELAY_WEECHAT_DATA(client, compression)))
return 0;
if (!weechat_hashtable_add_to_infolist (RELAY_WEECHAT_DATA(client, buffers_sync), item, "buffers_sync"))
return 0;
if (!weechat_hashtable_add_to_infolist (RELAY_WEECHAT_DATA(client, buffers_nicklist), item, "buffers_nicklist"))
return 0;
return 1;
}
@@ -213,5 +352,16 @@ relay_weechat_print_log (struct t_relay_client *client)
{
weechat_log_printf (" password_ok. . . . . . : %d", RELAY_WEECHAT_DATA(client, password_ok));
weechat_log_printf (" compression. . . . . . : %d", RELAY_WEECHAT_DATA(client, compression));
weechat_log_printf (" buffers_sync . . . . . : 0x%lx (hashtable: '%s')",
RELAY_WEECHAT_DATA(client, buffers_sync),
weechat_hashtable_get_string (RELAY_WEECHAT_DATA(client, buffers_sync),
"keys_values"));
weechat_log_printf (" hook_signal_buffer . . : 0x%lx", RELAY_WEECHAT_DATA(client, hook_signal_buffer));
weechat_log_printf (" hook_signal_nicklist . : 0x%lx", RELAY_WEECHAT_DATA(client, hook_signal_nicklist));
weechat_log_printf (" buffers_nicklist . . . : 0x%lx (hashtable: '%s')",
RELAY_WEECHAT_DATA(client, buffers_nicklist),
weechat_hashtable_get_string (RELAY_WEECHAT_DATA(client, buffers_nicklist),
"keys_values"));
weechat_log_printf (" hook_timer_nicklist. . : 0x%lx", RELAY_WEECHAT_DATA(client, hook_timer_nicklist));
}
}
+11
View File
@@ -37,9 +37,20 @@ struct t_relay_weechat_data
{
int password_ok; /* password received and ok? */
int compression; /* compression type */
/* sync of buffers */
struct t_hashtable *buffers_sync; /* buffers synchronized (events */
/* received for these buffers) */
struct t_hook *hook_signal_buffer; /* hook for signals "buffer_xxx" */
struct t_hook *hook_signal_nicklist; /* hook for signals "nicklist_xxx"*/
struct t_hashtable *buffers_nicklist; /* send nicklist for these buffers*/
struct t_hook *hook_timer_nicklist; /* timer for sending nicklist */
};
extern int relay_weechat_compression_search (const char *compression);
extern void relay_weechat_hook_signals (struct t_relay_client *client);
extern void relay_weechat_unhook_signals (struct t_relay_client *client);
extern void relay_weechat_hook_timer_nicklist (struct t_relay_client *client);
extern void relay_weechat_recv (struct t_relay_client *client,
const char *data);
extern void relay_weechat_close_connection (struct t_relay_client *client);