Merge trunk.
authorJelmer Vernooij <jelmer@samba.org>
Fri, 10 Apr 2009 15:29:15 +0000 (17:29 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Fri, 10 Apr 2009 15:29:15 +0000 (17:29 +0200)
Makefile
libirc/client.c
libirc/client.h
libirc/redirect.c [moved from src/redirect.c with 81% similarity]
libirc/redirect.h [moved from src/redirect.h with 83% similarity]
python/irc.c
src/internals.h
src/network.c

index d9505a983c124fc18c63e2fadf108bbaecf8a7f3..8a77d849000704e2683bb47941ba3fdb5d3b2530 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -44,6 +44,7 @@ doxygen:
 libircdir = libirc
 
 objs = src/posix.o \
+          src/redirect.o \
           src/cache.o \
           src/util.o \
           src/hooks.o \
@@ -52,7 +53,6 @@ objs = src/posix.o \
           src/settings.o \
           src/log.o \
           src/client.o \
-          src/redirect.o \
           src/gen_config.o \
           src/repl.o \
           src/linestack_file.o \
@@ -81,6 +81,7 @@ libirc_objs = \
           $(libircdir)/line.o \
           $(libircdir)/isupport.o \
           $(libircdir)/connection.o \
+          $(libircdir)/redirect.o \
           $(libircdir)/url.o \
           $(libircdir)/util.o \
           $(libircdir)/listener.o \
@@ -93,6 +94,7 @@ libirc_headers = \
                  $(libircdir)/isupport.h \
                  $(libircdir)/irc.h \
                  $(libircdir)/connection.h \
+                 $(libircdir)/redirect.h \
                  $(libircdir)/url.h \
                  $(libircdir)/listener.h \
                  $(libircdir)/util.h
index 2f55fc6b740ba5f0c18d0f616845276ce941efea..d25607e7a850e1c706b5e8ac4f607f1e304383e2 100644 (file)
@@ -463,6 +463,11 @@ const char *client_get_default_target(struct irc_client *c)
        return "*";
 }
 
+void client_ref_void(struct irc_client *c) 
+{
+       client_ref(c);
+}
+
 struct irc_client *client_ref(struct irc_client *c) 
 {
        if (c != NULL)
index bd2b72b02cace37af9e29f6ef0a77c8f5397e3f8..527e5d7bcea98837f37efdda3b2f507225b3dabd 100644 (file)
@@ -93,6 +93,7 @@ G_MODULE_EXPORT gboolean client_set_charset(struct irc_client *c, const char *na
 G_MODULE_EXPORT const char *client_get_default_target(struct irc_client *c);
 G_MODULE_EXPORT const char *client_get_own_hostmask(struct irc_client *c);
 G_MODULE_EXPORT struct irc_client *client_ref(struct irc_client *c);
+G_MODULE_EXPORT void client_ref_void(struct irc_client *c);
 G_MODULE_EXPORT void client_unref(struct irc_client *c);
 G_MODULE_EXPORT struct irc_client *irc_client_new(struct irc_transport *transport, const char *default_origin, const char *desc, struct irc_client_callbacks *callbacks);
 G_MODULE_EXPORT void clients_send_state(GList *clients, 
similarity index 81%
rename from src/redirect.c
rename to libirc/redirect.c
index ada15a9c3f4a693252559c909f03e2deb412d21f..d1c955c966905ad973e3d4645f0deadb2da0bcba 100644 (file)
@@ -33,10 +33,10 @@ struct query_stack_entry {
 struct query_stack {
        GList *entries;
        void (*unref_userdata) (void *);
-       void *(*ref_userdata) (void *);
+       void (*ref_userdata) (void *);
 };
 
-struct query_stack *new_query_stack(void *(*ref_userdata) (void *), void (*unref_userdata) (void *))
+struct query_stack *new_query_stack(void (*ref_userdata) (void *), void (*unref_userdata) (void *))
 {
        struct query_stack *stack = g_new0(struct query_stack, 1);
        if (stack == NULL) {
@@ -518,58 +518,6 @@ static struct query unknown_query = {
        handle_default
 };
 
-static gboolean handle_465(struct irc_network *n, const struct irc_line *l)
-{
-       network_log(LOG_ERROR, n, "Banned from server: %s", l->args[1]);
-       return TRUE;
-}
-
-static gboolean handle_451(struct irc_network *n, const struct irc_line *l)
-{
-       network_log(LOG_ERROR, n, "Not registered error, this is probably a bug...");
-       return TRUE;
-}
-
-static gboolean handle_462(struct irc_network *n, const struct irc_line *l)
-{
-       network_log(LOG_ERROR, n, "Double registration error, this is probably a bug...");
-       return TRUE;
-}
-
-static gboolean handle_463(struct irc_network *n, const struct irc_line *l)
-{
-       network_log(LOG_ERROR, n, "Host not privileged to connect");
-       return TRUE;
-}
-
-static gboolean handle_464(struct irc_network *n, const struct irc_line *l)
-{
-       network_log(LOG_ERROR, n, "Password mismatch");
-       return TRUE;
-}
-
-/* List of responses that should be sent to all clients */
-static const int response_all[] = { RPL_NOWAWAY, RPL_UNAWAY, 
-       ERR_NO_OP_SPLIT, RPL_HIDINGHOST,
-       ERR_NEEDREGGEDNICK, RPL_UMODEIS, RPL_SNOMASK,
-       RPL_LUSERCLIENT, RPL_LUSEROP, RPL_LUSERUNKNOWN, RPL_LUSERCHANNELS,
-       RPL_LUSERME, ERR_NO_OP_SPLIT, RPL_LOCALUSERS, RPL_GLOBALUSERS, 
-       RPL_NAMREPLY, RPL_ENDOFNAMES, RPL_TOPIC, RPL_TOPICWHOTIME, 
-       RPL_CHANNEL_HOMEPAGE, RPL_CREATIONTIME, RPL_LOGGEDINAS, 0 };
-static const int response_none[] = { ERR_NOMOTD, RPL_MOTDSTART, RPL_MOTD, 
-       RPL_ENDOFMOTD, 0 };
-static const struct {
-       int response;
-       gboolean (*handler) (struct irc_network *n, const struct irc_line *);
-} response_handler[] = {
-       { ERR_PASSWDMISMATCH, handle_464 },
-       { ERR_ALREADYREGISTERED, handle_462 },
-       { ERR_NOPERMFORHOST, handle_463 },
-       { ERR_NOTREGISTERED, handle_451 },
-       { ERR_YOUREBANNEDCREEP, handle_465 },
-       { 0, NULL }
-};
-
 /**
  * Check whether reply r is part of a specified list
  *
@@ -636,59 +584,6 @@ void *query_stack_match_response(struct query_stack *stack, const struct irc_lin
        return NULL;
 }
 
-/**
- * Redirect a response received from the server.
- *
- * @return TRUE if the message was redirected to zero or more clients, 
- *         FALSE if it was sent to all clients.
- */
-gboolean redirect_response(struct query_stack *stack, 
-                                                  struct irc_network *network,
-                                                  const struct irc_line *l)
-{
-       struct irc_client *c = NULL;
-       int n;
-       int i;
-
-       c = (struct irc_client *)query_stack_match_response(stack, l);
-       if (c != NULL) {
-               client_send_line(c, l);
-               return TRUE;
-       }
-       
-       n = irc_line_respcode(l);
-
-       /* See if this is a response that should be sent to all clients */
-       for (i = 0; response_all[i]; i++) {
-               if (response_all[i] == n) {
-                       clients_send(network->clients, l, c);
-                       return FALSE;
-               }
-       }
-
-       /* See if this is a response that shouldn't be sent to clients at all */
-       for (i = 0; response_none[i]; i++) {
-               if (response_none[i] == n) {
-                       return TRUE;
-               }
-       }
-
-       /* Handle response using custom function */
-       for (i = 0; response_handler[i].handler; i++) {
-               if (response_handler[i].response == n) {
-                       return response_handler[i].handler(network, l);
-               }
-       }
-
-       if (!c) {
-               network_log((g_list_length(network->clients) <= 1)?LOG_TRACE:LOG_WARNING, 
-                                       network, "Unable to redirect response %s", l->args[0]);
-               clients_send(network->clients, l, NULL);
-       }
-
-       return FALSE;
-}
-
 void query_stack_clear(struct query_stack *stack)
 {
        while (stack->entries != NULL) {
@@ -730,7 +625,8 @@ static int handle_default(const struct irc_line *l, struct query_stack *stack,
        struct query_stack_entry *s = g_new(struct query_stack_entry, 1);
        g_assert(l != NULL);
        g_assert(q != NULL);
-       s->userdata = stack->ref_userdata(userdata);
+       stack->ref_userdata(userdata);
+       s->userdata = userdata;
        s->time = time(NULL);
        s->query = q;
        stack->entries = g_list_append(stack->entries, s);
similarity index 83%
rename from src/redirect.h
rename to libirc/redirect.h
index 0d977ad1a220a412a27d8f890ffde08c28864914..f20001824d5c35b4c64a203d5b8b9bd175322886 100644 (file)
 
 struct query_stack;
 
-gboolean redirect_response(struct query_stack *stack, 
-                                                  struct irc_network *network,
-                                                  const struct irc_line *l);
 void *query_stack_match_response(struct query_stack *stack, const struct irc_line *l);
 gboolean query_stack_record(struct query_stack *stack, void *c, const struct irc_line *l);
-struct query_stack *new_query_stack(void *(*ref_userdata) (void *), void (*unref_userdata) (void *));
+struct query_stack *new_query_stack(void (*ref_userdata) (void *), void (*unref_userdata) (void *));
 void query_stack_clear(struct query_stack *n);
 void query_stack_free(struct query_stack *n);
 
index 024bcf0c94b1656d6b780205ec9bc28a0c64f1af..2df9faf728f6e7d5faa6e3f574cec399764afb7e 100644 (file)
@@ -20,6 +20,8 @@
 #include <Python.h>
 #include <stdbool.h>
 #include "ctrlproxy.h"
+#include "redirect.h"
+
 
 const char *get_my_hostname() { return NULL; /* FIXME */ }
 void log_global(enum log_level ll, const char *fmt, ...) { /* FIXME */}
@@ -1183,6 +1185,95 @@ static const struct irc_client_callbacks py_client_callbacks = {
     .welcome = py_welcome_client
 };
 
+typedef struct {
+    PyObject_HEAD
+    struct query_stack *stack;
+} PyQueryStackObject;
+
+static PyObject *py_query_stack_record(PyQueryStackObject *self, PyObject *args)
+{
+    PyObject *py_token, *py_line;
+    struct irc_line *line;
+
+    if (!PyArg_ParseTuple(args, "OO", &py_token, &py_line))
+        return NULL;
+
+    line = PyObject_AsLine(py_line);
+    if (line == NULL)
+        return NULL;
+
+    return PyBool_FromLong(query_stack_record(self->stack, py_token, line));
+}
+
+static PyObject *py_query_stack_redirect(PyQueryStackObject *self, PyObject *args)
+{
+    PyObject *py_network, *py_line;
+    struct irc_line *line;
+    PyObject *ret;
+
+    if (!PyArg_ParseTuple(args, "OO", &py_network, &py_line))
+        return NULL;
+
+    line = PyObject_AsLine(py_line);
+    if (line == NULL)
+        return NULL;
+
+    if (PyObject_TypeCheck(py_network, &PyNetworkStateType)) {
+        PyErr_SetNone(PyExc_TypeError);
+        return NULL;
+    }
+
+    ret = (PyObject *)query_stack_match_response(self->stack, line);
+    if (ret == NULL) {
+        Py_RETURN_NONE;
+    } else {
+        Py_INCREF(ret);
+        return ret;
+    }
+}
+
+static PyObject *py_query_stack_clear(PyQueryStackObject *self)
+{
+    query_stack_clear(self->stack);
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef py_query_stack_methods[] = {
+    { "record", (PyCFunction)py_query_stack_record, METH_VARARGS, NULL },
+    { "response", (PyCFunction)py_query_stack_redirect, METH_VARARGS, NULL },
+    { "clear", (PyCFunction)py_query_stack_clear, METH_NOARGS, NULL },
+    { NULL }
+};
+
+static int py_query_stack_dealloc(PyQueryStackObject *self)
+{
+    query_stack_free(self->stack);
+    PyObject_Del(self);
+    return 0;
+}
+
+static PyObject *py_query_stack_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyQueryStackObject *self = (PyQueryStackObject *)type->tp_alloc(type, 0);
+    if (self == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    self->stack = new_query_stack((void (*)(void *))Py_IncRef, (void (*)(void *))Py_DecRef);
+
+    return (PyObject *)self;
+}
+
+PyTypeObject PyQueryStackType = {
+    .tp_name = "QueryStack",
+    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_new = py_query_stack_new,
+    .tp_methods = py_query_stack_methods,
+    .tp_basicsize = sizeof(PyQueryStackObject),
+    .tp_dealloc = (destructor)py_query_stack_dealloc,
+};
+
 static PyMethodDef irc_methods[] = { 
     { NULL }
 };
@@ -1221,6 +1312,9 @@ void initirc(void)
     if (PyType_Ready(&PyGListIterType) < 0)
         return;
 
+    if (PyType_Ready(&PyQueryStackType) < 0)
+        return;
+
     m = Py_InitModule3("irc", irc_methods, 
                        "Simple IRC protocol module for Python.");
     if (m == NULL)
@@ -1240,5 +1334,7 @@ void initirc(void)
     PyModule_AddObject(m, "Client", (PyObject *)&PyClientType);
     Py_INCREF(&PyNetworkType);
     PyModule_AddObject(m, "Network", (PyObject *)&PyNetworkType);
+    Py_INCREF(&PyQueryStackType);
+    PyModule_AddObject(m, "QueryStack", (PyObject *)&PyQueryStackType);
 }
 
index 643409cea1cfb5a83249a1b54562d9d91f7205f7..bcb743dc00b9fbd04035e68133a9b86e3d3c6f20 100644 (file)
@@ -55,6 +55,11 @@ void fini_networks(struct global *);
 void kill_pending_clients(const char *reason);
 gboolean network_set_iochannel(struct irc_network *s, GIOChannel *ioc);
 
+/* redirect.c */
+gboolean redirect_response(struct query_stack *stack, 
+                                                  struct irc_network *network,
+                                                  const struct irc_line *l);
+
 /* state.c */
 void free_channels(struct irc_network *s);
 void network_nick_set_data(struct network_nick *n, const char *nick, const char *username, const char *host);
index 58ca1e8bfcb2f7fb55dc513a492c04e69e478e2e..d4531bda5b97d21bd364fb3c1fd6e0159b9cbcbb 100644 (file)
@@ -394,7 +394,7 @@ static void handle_network_disconnect(struct irc_network *n)
 static void handle_network_state_set(struct irc_network *s)
 {
        s->linestack = new_linestack(s, s->global->config);
-       s->queries = new_query_stack((void *(*)(void *))client_ref, (void (*)(void *))client_unref);
+       s->queries = new_query_stack((void (*)(void *))client_ref_void, (void (*)(void *))client_unref);
 }
 
 static gboolean process_to_server(struct irc_network *s, const struct irc_line *l)