cvs: php4 /ext/ircg ircg.c php_ircg.h
| From: | Sascha Schumann | Date: | Sun, 29 Jul 2001 19:02:50 +0000 |
| Subject: | cvs: php4 /ext/ircg ircg.c php_ircg.h | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-6392@lists.php.net to get a copy of this message | ||
sas Sun Jul 29 15:02:50 2001 EDT
Modified files:
/php4/ext/ircg ircg.c php_ircg.h
Log:
Add a simple mechanism which enables IRCG users to retrieve the
error message which caused the irc connection to be killed. We maintain
a separate list for this purpose which performs automatic gc.
Index: php4/ext/ircg/ircg.c
diff -u php4/ext/ircg/ircg.c:1.87 php4/ext/ircg/ircg.c:1.88
--- php4/ext/ircg/ircg.c:1.87 Sat Jul 28 21:59:49 2001
+++ php4/ext/ircg/ircg.c Sun Jul 29 15:02:50 2001
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: ircg.c,v 1.87 2001/07/29 01:59:49 sas Exp $ */
+/* $Id: ircg.c,v 1.88 2001/07/29 19:02:50 sas Exp $ */
#include <time.h>
@@ -42,8 +42,7 @@
static HashTable h_fmt_msgs; /* Integer IDs to php_fmt_msgs_t * */
static int irconn_id = 1;
-static unsigned long irc_connects, irc_set_currents, irc_quit_handlers,
- irc_hash_hits, irc_hash_misses;
+static unsigned long irc_connects, irc_set_currents, irc_quit_handlers;
/* {{{ Format string numbers */
enum {
@@ -94,8 +93,9 @@
PHP_FE(ircg_nickname_escape, NULL)
PHP_FE(ircg_nickname_unescape, NULL)
PHP_FE(ircg_ignore_add, NULL)
- PHP_FE(ircg_ignore_del, NULL)
PHP_FE(ircg_disconnect, NULL)
+ PHP_FE(ircg_fetch_error_msg, NULL)
+ PHP_FE(ircg_ignore_del, NULL)
PHP_FE(ircg_is_conn_alive, NULL)
PHP_FE(ircg_lookup_format_messages, NULL)
PHP_FE(ircg_register_format_messages, NULL)
@@ -713,6 +713,105 @@
msg_send(conn, &m);
}
+/*
+ * This is an internal API which serves the purpose to store the reason
+ * for terminating a connection. The termination will cause the
+ * connection id to become invalid. A script can then use a
+ * function to retrieve the last error message which was received
+ * from the IRC server, and will usually present a nicely formatted
+ * error message to the end-user.
+ *
+ * We automatically garbage-collect every n-th login, so there is
+ * no need for a separate gc thread.
+ */
+
+struct errormsg {
+ smart_str msg;
+ int msgid;
+ int id;
+ struct errormsg *next;
+};
+
+static struct errormsg *errormsgs;
+
+static void error_msg_dtor(struct errormsg *m)
+{
+ smart_str_free_ex(&m->msg, 1);
+ free(m);
+}
+
+static void error_msg_gc(void)
+{
+ struct errormsg *m, *prev = NULL, *next;
+ int lim;
+
+ lim = irconn_id - 1000;
+
+ for (m = errormsgs; m; prev = m, m = m->next) {
+ if (m->id < lim) {
+ struct errormsg *to;
+ /* Check whether we have subsequent outdated records */
+
+ for (to = m->next; to; to = next) {
+ next = to->next;
+ if (m->id >= lim) break;
+ error_msg_dtor(to);
+ }
+
+ error_msg_dtor(m);
+
+ if (prev)
+ prev->next = to;
+ else
+ errormsgs = to;
+
+ if (!to) break;
+ m = to;
+ }
+ }
+}
+
+static void add_error_msg(smart_str *msg, int msgid, php_irconn_t *conn)
+{
+ struct errormsg *m;
+
+ for (m = errormsgs; m; m = m->next) {
+ if (m->id == conn->irconn_id) break;
+ }
+
+ if (!m) {
+ m = malloc(sizeof(*m));
+ m->msg.c = 0;
+ m->id = conn->irconn_id;
+ }
+
+ smart_str_append_ex(&m->msg, msg, 1);
+ m->msgid = msgid;
+ m->next = errormsgs;
+ errormsgs = m;
+
+ printf("stored msgid %d for %d at %p\n", msgid, conn->irconn_id, m);
+}
+
+static struct errormsg *lookup_and_remove_error_msg(int id)
+{
+ struct errormsg *m, *prev = NULL;
+
+ printf("looking up msg for %d\n", id);
+ for (m = errormsgs; m; prev = m, m = m->next) {
+ if (m->id == id) {
+ if (prev)
+ prev->next = m->next;
+ else
+ errormsgs = m->next;
+
+ printf("found it at %p\n", m);
+ return m;
+ }
+ }
+ printf("nope\n");
+ return NULL;
+}
static void error_handler(irconn_t *ircc, int id, int fatal, smart_str *msg, void *conn_data)
{
@@ -720,11 +819,15 @@
smart_str m = {0};
smart_str s_username;
smart_str tmp;
-
+
smart_str_setl(&tmp, "IRC SERVER", sizeof("IRC SERVER") - 1);
smart_str_setl(&s_username, ircc->username, ircc->username_len);
format_msg(MSG(conn, fatal ? FMT_MSG_FATAL_ERROR : FMT_MSG_ERROR), NULL,
&s_username, &tmp, msg, &m);
+
+ if (fatal) {
+ add_error_msg(msg, id, conn);
+ }
msg_send(conn, &m);
}
@@ -1021,6 +1124,29 @@
}
/* }}} */
+/* {{{ PHP_FUNCTION(ircg_fetch_error_msg)
+ */
+PHP_FUNCTION(ircg_fetch_error_msg)
+{
+ zval **args[2];
+ struct errormsg *m;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) == FAILURE)
+ WRONG_PARAM_COUNT;
+
+ convert_to_long_ex(args[0]);
+
+ m = lookup_and_remove_error_msg(Z_LVAL_PP(args[0]));
+
+ if (!m) RETURN_FALSE;
+
+ array_init(return_value);
+ add_index_long(return_value, 0, m->msgid);
+ add_index_stringl(return_value, 1, m->msg.c, m->msg.len, 1);
+ error_msg_dtor(m);
+}
+/* }}} */
+
/* {{{ PHP_FUNCTION(ircg_ignore_del)
*/
PHP_FUNCTION(ircg_ignore_del)
@@ -1338,7 +1464,7 @@
{
/* This should become an array very soon */
zval **p1, **p2, **p3, **p4 = NULL, **p5 = NULL, **p6;
- const char *username;
+ const char *username = 0;
const char *server = "0";
int port = 6667;
php_fmt_msgs_t *fmt_msgs = NULL;
@@ -1407,6 +1533,8 @@
}
conn->password = conn->ident = NULL;
irconn_id++;
+ if ((irconn_id % 1000) == 0)
+ error_msg_gc();
conn->irconn_id = irconn_id;
zend_hash_index_update(&h_irconn, irconn_id, &conn, sizeof(conn), NULL);
conn->buffer.c = NULL;
Index: php4/ext/ircg/php_ircg.h
diff -u php4/ext/ircg/php_ircg.h:1.13 php4/ext/ircg/php_ircg.h:1.14
--- php4/ext/ircg/php_ircg.h:1.13 Sat Jul 28 07:35:57 2001
+++ php4/ext/ircg/php_ircg.h Sun Jul 29 15:02:50 2001
@@ -42,6 +42,7 @@
PHP_FUNCTION(ircg_ignore_add);
PHP_FUNCTION(ircg_ignore_del);
PHP_FUNCTION(ircg_kick);
+PHP_FUNCTION(ircg_fetch_error_msg);
PHP_FUNCTION(ircg_topic);
PHP_FUNCTION(ircg_channel_mode);
PHP_FUNCTION(ircg_disconnect);