📄 irc-proto.c
字号:
/* go through all channels */ while (client->channels) { channel = client->channel[0]; /* tell all clients in the channel about disconnecting */ for (i = 0; i < channel->clients; i++) { if (channel->client[i] == client) continue; cl = channel->client[i]; xsock = cl->sock; irc_printf (xsock, ":%s!%s@%s QUIT :%s\n", client->nick, client->user, client->host, reason); } /* delete this client of channel */ irc_leave_channel (cfg, client, channel); } /* send last error Message */ sock->flags &= ~SOCK_FLAG_KILLED; irc_printf (sock, "ERROR :" IRC_CLOSING_LINK "\n", client->host, reason); sock->flags |= SOCK_FLAG_KILLED; /* delete this client */ irc_delete_client (cfg, client); sock->data = NULL; return 0;}/* * This function is the default callback if the connection of * an IRC client gets lost. */intirc_disconnect (svz_socket_t *sock){ irc_config_t *cfg = sock->cfg; irc_client_t *client = sock->data; /* is it a valid IRC connection ? */ if (client) { irc_leave_all_channels (cfg, client, IRC_CONNECTION_LOST); } return 0;}/* * This is the idle callback for serveez. Here the IRC server could * send a PING to a IRC client. */intirc_idle (svz_socket_t *sock){ irc_config_t *cfg = sock->cfg; irc_client_t *client = sock->data; if (!client->registered) { if (irc_register_client (sock, client, cfg)) return -1; sock->idle_counter = 1; return 0; } /* * Shutdown this connection if the client did not respond * within a certain period of time. */ if (client->ping > 0) { return -1; } /* * Ping a client connection if necessary. */ if ((time (NULL) - sock->last_recv) >= IRC_PING_INTERVAL) { irc_printf (sock, "PING %s\n", cfg->host); client->ping++; } sock->idle_counter = IRC_PING_INTERVAL; return 0;}/* * This structures field contains all the callback routines necessary * to react like an IRC server. The actual routines are defined in the * irc-event.h and implemented in the irc-event-?.c files. */irc_callback_t irc_callback[] ={ { 0, "OPER", irc_oper_callback }, { 0, "INFO", irc_info_callback }, { 0, "KILL", irc_kill_callback }, { 0, "ERROR", irc_error_callback }, { 0, "WHOWAS", irc_whowas_callback }, { 0, "ADMIN", irc_admin_callback }, { 0, "TIME", irc_time_callback }, { 0, "LUSERS", irc_lusers_callback }, { 0, "STATS", irc_stats_callback }, { 0, "PING", irc_ping_callback }, { 0, "PONG", irc_pong_callback }, { 0, "VERSION", irc_version_callback }, { 0, "KICK", irc_kick_callback }, { 0, "AWAY", irc_away_callback }, { 0, "WHO", irc_who_callback }, { 0, "WHOIS", irc_whois_callback }, { 0, "MOTD", irc_motd_callback }, { 0, "INVITE", irc_invite_callback }, { 0, "LIST", irc_list_callback }, { 0, "NAMES", irc_names_callback }, { 0, "NOTICE", irc_note_callback }, { 0, "TOPIC", irc_topic_callback }, { 0, "MODE", irc_mode_callback }, { 0, "PRIVMSG", irc_priv_callback }, { 0, "USERHOST", irc_userhost_callback }, { 0, "ISON", irc_ison_callback }, { 0, "USERS", irc_users_callback }, { 0, "PART", irc_part_callback }, { 0, "QUIT", irc_quit_callback }, { 0, "JOIN", irc_join_callback }, { 0, "PASS", irc_pass_callback }, { 0, "USER", irc_user_callback }, { 0, "NICK", irc_nick_callback }, { 0, NULL, NULL }};intirc_handle_request (svz_socket_t *sock, char *request, int len){ irc_config_t *cfg = sock->cfg; irc_client_t *client = sock->data; int n; irc_parse_request (request, len); /* * FIXME: server handling not yet done. * Should be alike: get irc client by message prefix, otherwise special * server request handling */ if (sock->userflags & IRC_FLAG_SERVER) return 0; for (n = 0; irc_callback[n].request; n++) { if (!svz_strcasecmp (irc_callback[n].request, irc_request.request)) { irc_callback[n].count++; client->recv_bytes += len; client->recv_packets++; return irc_callback[n].func (sock, client, &irc_request); } } irc_printf (sock, ":%s %03d %s " ERR_UNKNOWNCOMMAND_TEXT "\n", cfg->host, ERR_UNKNOWNCOMMAND, client->nick ? client->nick : "", irc_request.request); return 0;}/* * Delete a channel from the channel list. Returns -1 if there was no * appropriate channel. */static intirc_delete_channel (irc_config_t *cfg, irc_channel_t *channel){ int n; if (svz_hash_contains (cfg->channels, channel)) { /* svz_free() all the channel ban entries */ for (n = 0; n < channel->bans; n++) irc_destroy_ban (channel->ban[n]); if (channel->ban) svz_free (channel->ban); svz_hash_delete (cfg->channels, channel->name); if (channel->topic) svz_free (channel->topic); if (channel->topic_by) svz_free (channel->topic_by); if (channel->key) svz_free (channel->key); if (channel->invite) svz_free (channel->invite); svz_free (channel->by); svz_free (channel->name); svz_free (channel); return 0; } return -1;}/* * Find a channel within the current channel list. Return NULL if * the channel has not been found. */irc_channel_t *irc_find_channel (irc_config_t *cfg, char *channel){ irc_channel_t *chan; chan = svz_hash_get (cfg->channels, channel); return chan;}/* * Find all matching channels in the current channel list. Return NULL if * no channel has not been found. You MUST svz_free() this list if non-NULL. * The delivered array is NULL terminated. */irc_channel_t **irc_regex_channel (irc_config_t *cfg, char *regex){ irc_channel_t **channel, **fchannel; int n, found, size; if ((channel = (irc_channel_t **) svz_hash_values (cfg->channels)) != NULL) { size = svz_hash_size (cfg->channels); fchannel = svz_malloc (sizeof (irc_channel_t *) * (size + 1)); for (found = n = 0; n < size; n++) { if (irc_string_regex (channel[n]->name, regex)) { fchannel[found++] = channel[n]; } } svz_hash_xfree (channel); /* return NULL if there is not channel */ if (!found) { svz_free (fchannel); return NULL; } fchannel[found++] = NULL; fchannel = svz_realloc (fchannel, sizeof (irc_channel_t *) * found); return fchannel; } return NULL;}/* * Add a new channel to the channel list. */static irc_channel_t *irc_add_channel (irc_config_t *cfg, char *name){ irc_channel_t *channel; if (irc_find_channel (cfg, name)) return NULL; channel = svz_malloc (sizeof (irc_channel_t)); memset (channel, 0, sizeof (irc_channel_t)); channel->name = svz_strdup (name); svz_hash_put (cfg->channels, name, channel); return channel;}/* * Add a client to the client history list. */voidirc_add_client_history (irc_config_t *cfg, irc_client_t *cl){ irc_client_history_t *client; client = svz_malloc (sizeof (irc_client_history_t)); client->nick = svz_strdup (cl->nick); client->user = svz_strdup (cl->user); client->host = svz_strdup (cl->host); client->real = svz_strdup (cl->real); client->next = cfg->history; cfg->history = client;}/* * Find a nick in the history client list. Return NULL if * no nick has not been found. Otherwise the first client found within * the history list. */irc_client_history_t *irc_find_nick_history (irc_config_t *cfg, irc_client_history_t *cl, char *nick){ irc_client_history_t *client; client = cl ? cl->next : cfg->history; for (; client; client = client->next) { if (!irc_string_equal (client->nick, nick)) { return client; } } return NULL;}/* * Delete all the client history. */voidirc_delete_client_history (irc_config_t *cfg){ irc_client_history_t *client; irc_client_history_t *old; for (client = cfg->history; client; client = old) { old = client->next; svz_free (client->nick); svz_free (client->user); svz_free (client->host); svz_free (client->real); svz_free (client); } cfg->history = NULL;}/* * Delete a client from the client list. Returns -1 if there was no * appropriate client. */intirc_delete_client (irc_config_t *cfg, irc_client_t *client){ int ret = 0; if (client->nick) { /* put this client into the history list */ irc_add_client_history (cfg, client); if (svz_hash_delete (cfg->clients, client->nick) == NULL) ret = -1; svz_free (client->nick); } /* free all client properties */ if (client->real) svz_free (client->real); if (client->user) svz_free (client->user); if (client->host) svz_free (client->host); if (client->server) svz_free (client->server); if (client->channel) svz_free (client->channel); if (client->pass) svz_free (client->pass); if (client->away) svz_free (client->away); svz_free (client); cfg->users--; return ret;}/* * Find a user@host within the current client list. Return NULL if * no client has not been found. */irc_client_t *irc_find_userhost (irc_config_t *cfg, char *user, char *host){ irc_client_t **client; irc_client_t *fclient; int n; if ((client = (irc_client_t **) svz_hash_values (cfg->clients)) != NULL) { for (n = 0; n < svz_hash_size (cfg->clients); n++) { if (!strcmp (client[n]->user, user) && !strcmp (client[n]->host, host)) { fclient = client[n]; svz_hash_xfree (client); return fclient; } } svz_hash_xfree (client); } return NULL;}/* * Find a nick within the current client list. Return NULL if * the nick has not been found. */irc_client_t *irc_find_nick (irc_config_t *cfg, char *nick){ irc_client_t *client; if ((client = svz_hash_get (cfg->clients, nick)) != NULL) { return client; } return NULL;}/* * Find all matching nicks in the current client list. Return NULL if * no nick has not been found. You MUST svz_free() this array if it is * non-NULL. The delivered clients are NULL terminated. */irc_client_t **irc_regex_nick (irc_config_t *cfg, char *regex){ irc_client_t **client, **fclient; int n, found, size; if ((client = (irc_client_t **) svz_hash_values (cfg->clients)) != NULL) { size = svz_hash_size (cfg->clients); fclient = svz_malloc (sizeof (irc_client_t *) * (size + 1)); for (found = n = 0; n < size; n++) { if (irc_string_regex (client[n]->nick, regex)) { fclient[found++] = client[n]; } } svz_hash_xfree (client); /* return NULL if there is not client */ if (!found) { svz_free (fclient); return NULL; } fclient[found++] = NULL; fclient = svz_realloc (fclient, sizeof (irc_client_t *) * found); return fclient; } return NULL;}/* * Add a new client to the client list. */irc_client_t *irc_add_client (irc_config_t *cfg, irc_client_t *client){ if (irc_find_nick (cfg, client->nick)) return NULL; svz_hash_put (cfg->clients, client->nick, client); return client;}/* * Create a new IRC client structure. This will be stored within the * miscellaneous data field in the socket structure (sock->data). */irc_client_t *irc_create_client (irc_config_t *cfg){ irc_client_t *client; client = svz_malloc (sizeof (irc_client_t)); memset (client, 0, sizeof (irc_client_t)); cfg->users++; return client;}/* * Print a formatted string to the socket SOCK. */intirc_printf (svz_socket_t *sock, const char *fmt, ...){ va_list args; static char buffer[VSNPRINTF_BUF_SIZE]; unsigned len; if (sock->flags & SOCK_FLAG_KILLED) return 0; va_start (args, fmt); len = svz_vsnprintf (buffer, VSNPRINTF_BUF_SIZE, fmt, args); va_end (args); /* Just to be sure... */ if (len > sizeof (buffer)) len = sizeof (buffer); if ((len = svz_sock_write (sock, buffer, len)) != 0) { sock->flags |= SOCK_FLAG_KILLED; } return len;}int have_irc = 1;#else /* ENABLE_IRC_PROTO */int have_irc = 0; /* Shut up compiler, remember for runtime */#endif /* ENABLE_IRC_PROTO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -