source: irc.h @ 7de07a0

Last change on this file since 7de07a0 was 7de07a0, checked in by dequis <dx@…>, at 2018-07-12T08:42:45Z

Use GString for irc->sendbuffer (simpler and faster)

The old code managed growing the buffer manually and called strlen()
very often. GString has a length field and the logic to grow the buffer
is none of our business. Probably smarter, too.

This takes a "blist all" of 14k users from 8.2 to 1.3 seconds.

  • Property mode set to 100644
File size: 12.9 KB
RevLine 
[5ebff60]1/********************************************************************\
[b7d3cc34]2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[0e788f5]4  * Copyright 2002-2013 Wilmer van der Gaast and others                *
[b7d3cc34]5  \********************************************************************/
6
[3ddb7477]7/* The IRC-based UI (for now the only one)                              */
[b7d3cc34]8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
[6f10697]22  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  USA
[b7d3cc34]24*/
25
26#ifndef _IRC_H
27#define _IRC_H
28
[d179fd90]29#include <sys/socket.h>
30
[b7d3cc34]31#define IRC_MAX_LINE 512
[5a71d9c]32#define IRC_MAX_ARGS 16
[30093fa]33#define IRC_WORD_WRAP 425
[b7d3cc34]34
35#define IRC_LOGIN_TIMEOUT 60
36#define IRC_PING_STRING "PinglBee"
37
[b919363]38#define UMODES "abisw"     /* Allowed umodes (although they mostly do nothing) */
39#define UMODES_PRIV "Ro"   /* Allowed, but not by user directly */
40#define UMODES_KEEP "R"    /* Don't allow unsetting using /MODE */
[65016a6]41#define CMODES "ntC"       /* Allowed modes */
[b919363]42#define CMODE "t"          /* Default mode */
43#define UMODE "s"          /* Default mode */
44
45#define CTYPES "&#"        /* Valid channel name prefixes */
[b7d3cc34]46
[5ebff60]47typedef enum {
[bd9b00f]48        USTATUS_OFFLINE = 0,
[f6f5eee]49        USTATUS_AUTHORIZED = 1, /* Gave the correct server password (PASS). */
50        USTATUS_LOGGED_IN = 2,  /* USER+NICK(+PASS) finished. */
51        USTATUS_IDENTIFIED = 4, /* To NickServ (root). */
52        USTATUS_SHUTDOWN = 8,   /* Now used to indicate we're shutting down.
53                                   Currently just blocks irc_vawrite(). */
[0ef1c92]54        USTATUS_CAP_PENDING = 16,
[58b63de6]55        USTATUS_SASL_PLAIN_PENDING = 32,
[060d066]56
57        /* Not really status stuff, but other kinds of flags: For slightly
58           better password security, since the only way to send passwords
59           to the IRC server securely (i.e. not echoing to screen or written
60           to logfiles) is the /OPER command, try to use that command for
61           stuff that matters. */
62        OPER_HACK_IDENTIFY = 0x100,
[fda194f]63        OPER_HACK_IDENTIFY_NOLOAD = 0x01100,
64        OPER_HACK_IDENTIFY_FORCE  = 0x02100,
[060d066]65        OPER_HACK_REGISTER = 0x200,
[35987a1]66        OPER_HACK_ACCOUNT_PASSWORD = 0x400,
[5ebff60]67        OPER_HACK_ANY = 0x3700, /* To check for them all at once. */
68
[c608891]69        IRC_UTF8_NICKS = 0x10000, /* Disable ASCII restrictions on buddy nicks. */
[b7d3cc34]70} irc_status_t;
71
[355e2ad]72typedef enum {
[58b63de6]73        CAP_SASL = (1 << 0),
[687ec88]74        CAP_MULTI_PREFIX = (1 << 1),
[d63f37c]75        CAP_EXTENDED_JOIN = (1 << 2),
[80c2f3c]76        CAP_AWAY_NOTIFY = (1 << 3),
[c54bb11]77        CAP_USERHOST_IN_NAMES = (1 << 4),
[355e2ad]78} irc_cap_flag_t;
79
[3ddb7477]80struct irc_user;
81
[5ebff60]82typedef struct irc {
[b7d3cc34]83        int fd;
84        irc_status_t status;
85        double last_pong;
86        int pinging;
[7de07a0]87        GString *sendbuffer;
[b7d3cc34]88        char *readbuffer;
[f9756bd]89        GIConv iconv, oconv;
[b7d3cc34]90
[3ddb7477]91        struct irc_user *root;
92        struct irc_user *user;
[5ebff60]93
[a199d33]94        char *password; /* HACK: Used to save the user's password, but before
95                           logging in, this may contain a password we should
96                           send to identify after USER/NICK are received. */
[8e6ecfe]97        char *auth_backend;
[b7d3cc34]98
99        char umode[8];
[5ebff60]100
[b7d3cc34]101        struct query *queries;
[2c2df7d]102        GSList *file_transfers;
[5ebff60]103
[4be8239]104        GSList *users, *channels;
[fd45e1d1]105        struct irc_channel *default_channel;
[3ddb7477]106        GHashTable *nick_user_hash;
[92c8d41]107        GHashTable *watches; /* See irc_cmd_watch() */
[b7d3cc34]108
109        gint r_watch_source_id;
110        gint w_watch_source_id;
111        gint ping_source_id;
[6c2404e]112        gint login_source_id; /* To slightly delay some events at login time. */
[5ebff60]113
[0c85c08]114        struct otr *otr; /* OTR state and book keeping, used by the OTR plugin.
115                            TODO: Some mechanism for plugindata. */
[5ebff60]116
[3ddb7477]117        struct bee *b;
[dc96e6e]118        guint32 caps;
[b7d3cc34]119} irc_t;
120
[5ebff60]121typedef enum {
[92c8d41]122        /* Replaced with iu->last_channel IRC_USER_PRIVATE = 1, */
[eb50495]123        IRC_USER_AWAY = 2,
[5ebff60]124
[ad2d8bc]125        IRC_USER_OTR_ENCRYPTED = 0x10000,
126        IRC_USER_OTR_TRUSTED   = 0x20000,
[74f1cde]127} irc_user_flags_t;
128
[5ebff60]129typedef struct irc_user {
[b95932e]130        irc_t *irc;
[5ebff60]131
[3ddb7477]132        char *nick;
133        char *user;
134        char *host;
135        char *fullname;
[5ebff60]136
[2fe5eb9]137        /* Nickname in lowercase for case insensitive searches */
[3ddb7477]138        char *key;
[5ebff60]139
[74f1cde]140        irc_user_flags_t flags;
[92c8d41]141        struct irc_channel *last_channel;
[5ebff60]142
[1c8e5f7]143        GString *pastebuf; /* Paste buffer (combine lines into a multiline msg). */
[619dd18]144        guint pastebuf_timer;
[1c8e5f7]145        time_t away_reply_timeout; /* Only send a 301 if this time passed. */
[5ebff60]146
[d860a8d]147        struct bee_user *bu;
[5ebff60]148
[280c56a]149        const struct irc_user_funcs *f;
[3ddb7477]150} irc_user_t;
151
[5ebff60]152struct irc_user_funcs {
153        gboolean (*privmsg)(irc_user_t *iu, const char *msg);
154        gboolean (*ctcp)(irc_user_t *iu, char * const* ctcp);
[280c56a]155};
156
157extern const struct irc_user_funcs irc_user_root_funcs;
158extern const struct irc_user_funcs irc_user_self_funcs;
159
[5ebff60]160typedef enum {
[1c40aa7]161        IRC_CHANNEL_JOINED = 1, /* The user is currently in the channel. */
162        IRC_CHANNEL_TEMP = 2,   /* Erase the channel when the user leaves,
163                                   and don't save it. */
[5ebff60]164
[eb37735]165        /* Hack: Set this flag right before jumping into IM when we expect
166           a call to imcb_chat_new(). */
167        IRC_CHANNEL_CHAT_PICKME = 0x10000,
[4be8239]168} irc_channel_flags_t;
169
[5ebff60]170typedef struct irc_channel {
[4be8239]171        irc_t *irc;
172        char *name;
[280c56a]173        char mode[8];
174        int flags;
[5ebff60]175
[4be8239]176        char *topic;
[83e92bf]177        char *topic_who;
178        time_t topic_time;
[5ebff60]179
[1c8e5f7]180        GSList *users; /* struct irc_channel_user */
[f7ca587]181        struct irc_user *last_target;
[4be8239]182        struct set *set;
[5ebff60]183
[1c8e5f7]184        GString *pastebuf; /* Paste buffer (combine lines into a multiline msg). */
[619dd18]185        guint pastebuf_timer;
[5ebff60]186
[280c56a]187        const struct irc_channel_funcs *f;
[aea8b68]188        void *data;
[4be8239]189} irc_channel_t;
190
[5ebff60]191struct irc_channel_funcs {
192        gboolean (*privmsg)(irc_channel_t *ic, const char *msg);
193        gboolean (*join)(irc_channel_t *ic);
194        gboolean (*part)(irc_channel_t *ic, const char *msg);
195        gboolean (*topic)(irc_channel_t *ic, const char *new_topic);
196        gboolean (*invite)(irc_channel_t *ic, irc_user_t *iu);
197        void (*kick)(irc_channel_t *ic, irc_user_t *iu, const char *msg);
198
199        gboolean (*_init)(irc_channel_t *ic);
200        gboolean (*_free)(irc_channel_t *ic);
[280c56a]201};
202
[5ebff60]203typedef enum {
[e54112f]204        IRC_CHANNEL_USER_OP = 1,
205        IRC_CHANNEL_USER_HALFOP = 2,
206        IRC_CHANNEL_USER_VOICE = 4,
[94d5da9c]207        IRC_CHANNEL_USER_NONE = 8,
[e54112f]208} irc_channel_user_flags_t;
209
[5ebff60]210typedef struct irc_channel_user {
[e54112f]211        irc_user_t *iu;
212        int flags;
213} irc_channel_user_t;
214
[5ebff60]215typedef enum {
[a5c6ebd]216        IRC_CC_TYPE_DEFAULT  = 0x00001,
217        IRC_CC_TYPE_REST     = 0x00002, /* Still not implemented. */
218        IRC_CC_TYPE_GROUP    = 0x00004,
219        IRC_CC_TYPE_ACCOUNT  = 0x00008,
220        IRC_CC_TYPE_PROTOCOL = 0x00010,
221        IRC_CC_TYPE_MASK     = 0x000ff,
222        IRC_CC_TYPE_INVERT   = 0x00100,
[9ac3ed1]223} irc_control_channel_type_t;
224
[5ebff60]225struct irc_control_channel {
[9ac3ed1]226        irc_control_channel_type_t type;
227        struct bee_group *group;
[a067771]228        struct account *account;
[7a6ba50]229        struct prpl *protocol;
[7b8238d]230        char modes[5];
[9ac3ed1]231};
232
[d860a8d]233extern const struct bee_ui_funcs irc_ui_funcs;
234
[5ebff60]235typedef enum {
[006a84f]236        IRC_CDU_SILENT,
237        IRC_CDU_PART,
238        IRC_CDU_KICK,
239} irc_channel_del_user_type_t;
240
[0c85c08]241/* These are a glued a little bit to the core/bee layer and a little bit to
242   IRC. The first user is OTR, and I guess at some point we'll get to shape
243   this a little bit more as other uses come up. */
[5ebff60]244typedef struct irc_plugin {
[0c85c08]245        /* Called at the end of irc_new(). Can be used to add settings, etc. */
[5ebff60]246        gboolean (*irc_new)(irc_t *irc);
[0c85c08]247        /* At the end of irc_free(). */
[5ebff60]248        void (*irc_free)(irc_t *irc);
249
[934db064]250        /* Problem with the following two functions is ordering if multiple
251           plugins are handling them. Let's keep fixing that problem for
252           whenever it becomes important. */
[5ebff60]253
[0c85c08]254        /* Called by bee_irc_user_privmsg_cb(). Return NULL if you want to
255           abort sending the msg. */
[5ebff60]256        char* (*filter_msg_out)(irc_user_t * iu, char *msg, int flags);
[0c85c08]257        /* Called by bee_irc_user_msg(). Return NULL if you swallowed the
258           message and don't want anything to go to the user. */
[5ebff60]259        char* (*filter_msg_in)(irc_user_t * iu, char *msg, int flags);
260
[2dcaf9a]261        /* From storage.c functions. Ideally these should not be used
262           and instead data should be stored in settings which will get
263           saved automatically. Consider these deprecated! */
[5ebff60]264        void (*storage_load)(irc_t *irc);
265        void (*storage_save)(irc_t *irc);
266        void (*storage_remove)(const char *nick);
[0c85c08]267} irc_plugin_t;
268
269extern GSList *irc_plugins; /* struct irc_plugin */
270
[3ddb7477]271/* irc.c */
[b7d3cc34]272extern GSList *irc_connection_list;
273
[5ebff60]274irc_t *irc_new(int fd);
[d179fd90]275void irc_set_hosts(irc_t *irc, const struct sockaddr *remote_addr, const socklen_t remote_addrlen);
[5ebff60]276void irc_abort(irc_t *irc, int immed, char *format, ...) G_GNUC_PRINTF(3, 4);
277void irc_free(irc_t *irc);
278void irc_setpass(irc_t *irc, const char *pass);
[b7d3cc34]279
[5ebff60]280void irc_process(irc_t *irc);
281char **irc_parse_line(char *line);
282char *irc_build_line(char **cmd);
[b7d3cc34]283
[5ebff60]284void irc_write(irc_t *irc, char *format, ...) G_GNUC_PRINTF(2, 3);
285void irc_write_all(int now, char *format, ...) G_GNUC_PRINTF(2, 3);
286void irc_vawrite(irc_t *irc, char *format, va_list params);
[b7d3cc34]287
[5ebff60]288void irc_flush(irc_t *irc);
289void irc_switch_fd(irc_t *irc, int fd);
290void irc_sync(irc_t *irc);
291void irc_desync(irc_t *irc);
[f1c2b21]292
[5ebff60]293int irc_check_login(irc_t *irc);
[3ddb7477]294
[5ebff60]295void irc_umode_set(irc_t *irc, const char *s, gboolean allow_priv);
[b919363]296
[5ebff60]297void register_irc_plugin(const struct irc_plugin *p);
[0c85c08]298
[4be8239]299/* irc_channel.c */
[5ebff60]300irc_channel_t *irc_channel_new(irc_t *irc, const char *name);
301irc_channel_t *irc_channel_by_name(irc_t *irc, const char *name);
302irc_channel_t *irc_channel_get(irc_t *irc, char *id);
303int irc_channel_free(irc_channel_t *ic);
304void irc_channel_free_soon(irc_channel_t *ic);
305int irc_channel_add_user(irc_channel_t *ic, irc_user_t *iu);
306int irc_channel_del_user(irc_channel_t *ic, irc_user_t *iu, irc_channel_del_user_type_t type, const char *msg);
307irc_channel_user_t *irc_channel_has_user(irc_channel_t *ic, irc_user_t *iu);
308struct irc_channel *irc_channel_with_user(irc_t *irc, irc_user_t *iu);
309int irc_channel_set_topic(irc_channel_t *ic, const char *topic, const irc_user_t *who);
310void irc_channel_user_set_mode(irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags);
311void irc_channel_set_mode(irc_channel_t *ic, const char *s);
312void irc_channel_auto_joins(irc_t *irc, struct account *acc);
[1dcbd3e]313void irc_channel_printf(irc_channel_t *ic, char *format, ...) G_GNUC_PRINTF(2, 3);
[5ebff60]314gboolean irc_channel_name_ok(const char *name);
315void irc_channel_name_strip(char *name);
316int irc_channel_name_cmp(const char *a_, const char *b_);
[a9b1e0e]317char *irc_channel_name_gen(irc_t *irc, const char *name);
[e3e2059]318gboolean irc_channel_name_hint(irc_channel_t *ic, const char *name);
[5ebff60]319void irc_channel_update_ops(irc_channel_t *ic, char *value);
[687ec88]320char irc_channel_user_get_prefix(irc_channel_user_t *icu);
[5ebff60]321char *set_eval_irc_channel_ops(struct set *set, char *value);
322gboolean irc_channel_wants_user(irc_channel_t *ic, irc_user_t *iu);
[4be8239]323
[3ddb7477]324/* irc_commands.c */
[5ebff60]325void irc_exec(irc_t *irc, char **cmd);
[3ddb7477]326
327/* irc_send.c */
[5ebff60]328void irc_send_num(irc_t *irc, int code, char *format, ...) G_GNUC_PRINTF(3, 4);
329void irc_send_login(irc_t *irc);
330void irc_send_motd(irc_t *irc);
331const char *irc_user_msgdest(irc_user_t *iu);
[1dcbd3e]332void irc_rootmsg(irc_t *irc, char *format, ...) G_GNUC_PRINTF(2, 3);
333void irc_usermsg(irc_user_t *iu, char *format, ...) G_GNUC_PRINTF(2, 3);
334void irc_usernotice(irc_user_t *iu, char *format, ...) G_GNUC_PRINTF(2, 3);
[5ebff60]335void irc_send_join(irc_channel_t *ic, irc_user_t *iu);
336void irc_send_part(irc_channel_t *ic, irc_user_t *iu, const char *reason);
337void irc_send_quit(irc_user_t *iu, const char *reason);
338void irc_send_kick(irc_channel_t *ic, irc_user_t *iu, irc_user_t *kicker, const char *reason);
339void irc_send_names(irc_channel_t *ic);
340void irc_send_topic(irc_channel_t *ic, gboolean topic_change);
341void irc_send_whois(irc_user_t *iu);
342void irc_send_who(irc_t *irc, GSList *l, const char *channel);
343void irc_send_msg(irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix);
344void irc_send_msg_raw(irc_user_t *iu, const char *type, const char *dst, const char *msg);
345void irc_send_msg_f(irc_user_t *iu, const char *type, const char *dst, const char *format, ...) G_GNUC_PRINTF(4, 5);
346void irc_send_nick(irc_user_t *iu, const char *new_nick);
347void irc_send_channel_user_mode_diff(irc_channel_t *ic, irc_user_t *iu,
348                                     irc_channel_user_flags_t old_flags, irc_channel_user_flags_t new_flags);
349void irc_send_invite(irc_user_t *iu, irc_channel_t *ic);
[0ef1c92]350void irc_send_cap(irc_t *irc, char *subcommand, char *body);
[80c2f3c]351void irc_send_away_notify(irc_user_t *iu);
[3ddb7477]352
353/* irc_user.c */
[5ebff60]354irc_user_t *irc_user_new(irc_t *irc, const char *nick);
355int irc_user_free(irc_t *irc, irc_user_t *iu);
356irc_user_t *irc_user_by_name(irc_t *irc, const char *nick);
357int irc_user_set_nick(irc_user_t *iu, const char *new_nick);
358gint irc_user_cmp(gconstpointer a_, gconstpointer b_);
359const char *irc_user_get_away(irc_user_t *iu);
360void irc_user_quit(irc_user_t *iu, const char *msg);
[b7d3cc34]361
[21c87a7]362/* irc_util.c */
[5ebff60]363char *set_eval_timezone(struct set *set, char *value);
364char *irc_format_timestamp(irc_t *irc, time_t msg_ts);
[345577b]365char *set_eval_self_messages(struct set *set, char *value);
[b7d3cc34]366
[13c1a9f]367/* irc_im.c */
[5ebff60]368void bee_irc_channel_update(irc_t *irc, irc_channel_t *ic, irc_user_t *iu);
369void bee_irc_user_nick_reset(irc_user_t *iu);
[13c1a9f]370
[355e2ad]371/* irc_cap.c */
372void irc_cmd_cap(irc_t *irc, char **cmd);
373
[b7d3cc34]374#endif
Note: See TracBrowser for help on using the repository browser.