telepathygabble/src/gabble-connection-manager.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /*
       
     2  * gabble-connection-manager.c - Source for GabbleConnectionManager
       
     3  * Copyright (C) 2005 Collabora Ltd.
       
     4  *  and/or its subsidiary/subsidiaries. All rights reserved.
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Lesser General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2.1 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * Lesser General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Lesser General Public
       
    17  * License along with this library; if not, write to the Free Software
       
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    19  */
       
    20 
       
    21 #include <dbus/dbus-glib.h>
       
    22 #include <dbus/dbus-protocol.h>
       
    23 #include <stdio.h>
       
    24 #include <stdlib.h>
       
    25 #include <string.h>
       
    26 
       
    27 #include "gabble-connection.h"
       
    28 #include "telepathy-constants.h"
       
    29 #include "telepathy-errors.h"
       
    30 #include "telepathy-helpers.h"
       
    31 
       
    32 #include "gabble-connection-manager.h"
       
    33 #include "gabble-connection-manager-glue.h"
       
    34 #include "gabble-connection-manager-signals-marshal.h"
       
    35 
       
    36 #include "gabble_enums.h"
       
    37 
       
    38 #define TP_TYPE_PARAM (dbus_g_type_get_struct ("GValueArray", \
       
    39       G_TYPE_STRING, \
       
    40       G_TYPE_UINT, \
       
    41       G_TYPE_STRING, \
       
    42       G_TYPE_VALUE, \
       
    43       G_TYPE_INVALID))
       
    44 
       
    45 #ifndef EMULATOR
       
    46 G_DEFINE_TYPE(GabbleConnectionManager, gabble_connection_manager, G_TYPE_OBJECT)
       
    47 #endif
       
    48 
       
    49 
       
    50 /* signal enum */
       
    51 enum
       
    52 {
       
    53     NEW_CONNECTION,
       
    54     NO_MORE_CONNECTIONS,
       
    55     LAST_SIGNAL 
       
    56 #ifdef EMULATOR    
       
    57     = LAST_SIGNAL_CON_MGR
       
    58 #endif
       
    59     
       
    60 };
       
    61 
       
    62 
       
    63 #ifdef EMULATOR
       
    64 #include "libgabble_wsd_solution.h"
       
    65 
       
    66 	GET_STATIC_ARRAY_FROM_TLS(signals,gabble_conmgr,guint)
       
    67 	#define signals (GET_WSD_VAR_NAME(signals,gabble_conmgr, s)())
       
    68 	
       
    69 	GET_STATIC_VAR_FROM_TLS(ssl,gabble_conmgr,gboolean)
       
    70 	#define ssl (*GET_WSD_VAR_NAME(ssl,gabble_conmgr,s)())
       
    71 	
       
    72 	GET_STATIC_VAR_FROM_TLS(httpport,gabble_conmgr,guint)
       
    73 	#define httpport (*GET_WSD_VAR_NAME(httpport,gabble_conmgr,s)())
       
    74 	
       
    75 	GET_STATIC_VAR_FROM_TLS(httpproxyport,gabble_conmgr,guint)
       
    76 	#define httpproxyport (*GET_WSD_VAR_NAME(httpproxyport,gabble_conmgr,s)())
       
    77 	
       
    78 	GET_STATIC_VAR_FROM_TLS(gabble_connection_manager_parent_class,gabble_conmgr,gpointer)
       
    79 	#define gabble_connection_manager_parent_class (*GET_WSD_VAR_NAME(gabble_connection_manager_parent_class,gabble_conmgr,s)())
       
    80 	
       
    81 	GET_STATIC_VAR_FROM_TLS(g_define_type_id,gabble_conmgr,GType)
       
    82 	#define g_define_type_id (*GET_WSD_VAR_NAME(g_define_type_id,gabble_conmgr,s)())
       
    83 	
       
    84 	
       
    85 static void gabble_connection_manager_init (GabbleConnectionManager *self); 
       
    86 static void gabble_connection_manager_class_init (GabbleConnectionManagerClass *klass); 
       
    87 static void gabble_connection_manager_class_intern_init (gpointer klass) 
       
    88 { 
       
    89 gabble_connection_manager_parent_class = g_type_class_peek_parent (klass); 
       
    90 gabble_connection_manager_class_init ((GabbleConnectionManagerClass*) klass); 
       
    91 } 
       
    92 EXPORT_C GType gabble_connection_manager_get_type (void) 
       
    93 { 
       
    94 
       
    95 if ((g_define_type_id == 0)) 
       
    96 { 
       
    97 static const GTypeInfo g_define_type_info = 
       
    98 	{ sizeof (GabbleConnectionManagerClass), (GBaseInitFunc) ((void *)0), (GBaseFinalizeFunc) ((void *)0), (GClassInitFunc) gabble_connection_manager_class_intern_init, (GClassFinalizeFunc) ((void *)0), ((void *)0), sizeof (GabbleConnectionManager), 0, (GInstanceInitFunc) gabble_connection_manager_init, ((void *)0) }; g_define_type_id = g_type_register_static ( ((GType) ((20) << (2))), g_intern_static_string ("GabbleConnectionManager"), &g_define_type_info, (GTypeFlags) 0); { {} ; } } return g_define_type_id; 
       
    99 	} ;
       
   100 
       
   101 
       
   102 #else
       
   103 
       
   104 static guint signals[LAST_SIGNAL] = {0};
       
   105 
       
   106 static gboolean ssl = TRUE;
       
   107 static guint httpport = 8080;
       
   108 static guint httpproxyport = 443;
       
   109 
       
   110 #endif
       
   111 
       
   112 /* private structure */
       
   113 typedef struct _GabbleConnectionManagerPrivate GabbleConnectionManagerPrivate;
       
   114 
       
   115 struct _GabbleConnectionManagerPrivate
       
   116 {
       
   117   gboolean dispose_has_run;
       
   118   GHashTable *connections;
       
   119 };
       
   120 
       
   121 #define GABBLE_CONNECTION_MANAGER_GET_PRIVATE(obj) \
       
   122     ((GabbleConnectionManagerPrivate *)obj->priv)
       
   123 
       
   124 /* type definition stuff */
       
   125 
       
   126 static void
       
   127 gabble_connection_manager_init (GabbleConnectionManager *self)
       
   128 {
       
   129   GabbleConnectionManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
       
   130       GABBLE_TYPE_CONNECTION_MANAGER, GabbleConnectionManagerPrivate);
       
   131 
       
   132   self->priv = priv;
       
   133 
       
   134   priv->connections = g_hash_table_new (g_direct_hash, g_direct_equal);
       
   135 }
       
   136 
       
   137 static void gabble_connection_manager_dispose (GObject *object);
       
   138 static void gabble_connection_manager_finalize (GObject *object);
       
   139 
       
   140 static void
       
   141 gabble_connection_manager_class_init (GabbleConnectionManagerClass *gabble_connection_manager_class)
       
   142 {
       
   143   GObjectClass *object_class = G_OBJECT_CLASS (gabble_connection_manager_class);
       
   144 
       
   145   g_type_class_add_private (gabble_connection_manager_class, sizeof (GabbleConnectionManagerPrivate));
       
   146 
       
   147   g_message("**NEW LOGS** inside gabble_connection_manager_class_init \n");
       
   148 
       
   149   object_class->dispose = gabble_connection_manager_dispose;
       
   150   object_class->finalize = gabble_connection_manager_finalize;
       
   151 
       
   152   signals [NEW_CONNECTION] =
       
   153     g_signal_new ("new-connection",
       
   154                   G_OBJECT_CLASS_TYPE (gabble_connection_manager_class),
       
   155                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
       
   156                   0,
       
   157                   NULL, NULL,
       
   158                   gabble_connection_manager_marshal_VOID__STRING_STRING_STRING,
       
   159                   G_TYPE_NONE, 3, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING);
       
   160 
       
   161   signals [NO_MORE_CONNECTIONS] =
       
   162     g_signal_new ("no-more-connections",
       
   163                   G_OBJECT_CLASS_TYPE (gabble_connection_manager_class),
       
   164                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
       
   165                   0,
       
   166                   NULL, NULL,
       
   167                   g_cclosure_marshal_VOID__VOID,
       
   168                   G_TYPE_NONE, 0);
       
   169 
       
   170   dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (gabble_connection_manager_class), &dbus_glib_gabble_connection_manager_object_info);
       
   171 }
       
   172 
       
   173 void
       
   174 gabble_connection_manager_dispose (GObject *object)
       
   175 {
       
   176   GabbleConnectionManager *self = GABBLE_CONNECTION_MANAGER (object);
       
   177   GabbleConnectionManagerPrivate *priv = GABBLE_CONNECTION_MANAGER_GET_PRIVATE (self);
       
   178 
       
   179   if (priv->dispose_has_run)
       
   180     return;
       
   181 
       
   182   priv->dispose_has_run = TRUE;
       
   183 
       
   184   /* release any references held by the object here */
       
   185 
       
   186   if (G_OBJECT_CLASS (gabble_connection_manager_parent_class)->dispose)
       
   187     G_OBJECT_CLASS (gabble_connection_manager_parent_class)->dispose (object);
       
   188 }
       
   189 
       
   190 void
       
   191 gabble_connection_manager_finalize (GObject *object)
       
   192 {
       
   193   GabbleConnectionManager *self = GABBLE_CONNECTION_MANAGER (object);
       
   194   GabbleConnectionManagerPrivate *priv = GABBLE_CONNECTION_MANAGER_GET_PRIVATE (self);
       
   195 
       
   196   g_hash_table_destroy(priv->connections);
       
   197 
       
   198   G_OBJECT_CLASS (gabble_connection_manager_parent_class)->finalize (object);
       
   199 }
       
   200 
       
   201 
       
   202 enum {
       
   203     JABBER_PARAM_ACCOUNT = 0,
       
   204     JABBER_PARAM_PASSWORD,
       
   205     JABBER_PARAM_SERVER,
       
   206     JABBER_PARAM_RESOURCE,
       
   207     JABBER_PARAM_PRIORITY,
       
   208     JABBER_PARAM_PORT,
       
   209     JABBER_PARAM_OLD_SSL,
       
   210     JABBER_PARAM_REGISTER,
       
   211     JABBER_PARAM_LOW_BANDWIDTH,
       
   212     JABBER_PARAM_HTTPS_PROXY_SERVER,
       
   213     JABBER_PARAM_HTTPS_PROXY_PORT,
       
   214     JABBER_PARAM_FALLBACK_CONFERENCE_SERVER,
       
   215     JABBER_PARAM_STUN_SERVER,
       
   216     JABBER_PARAM_STUN_PORT,
       
   217     JABBER_PARAM_IGNORE_SSL_ERRORS,
       
   218     JABBER_PARAM_ALIAS,
       
   219     LAST_JABBER_PARAM
       
   220 };
       
   221 /* private methods */
       
   222 
       
   223 static gboolean
       
   224 get_parameters (const char *proto, const GabbleParamSpec **params, GError **error)
       
   225 {
       
   226   if (!strcmp (proto, "jabber"))
       
   227     {
       
   228       *params = jabber_params;
       
   229     }
       
   230   else
       
   231     {
       
   232       g_debug ("%s: unknown protocol %s", G_STRFUNC, proto);
       
   233 
       
   234       g_set_error (error, TELEPATHY_ERRORS, NotImplemented,
       
   235           "unknown protocol %s", proto);
       
   236 
       
   237       return FALSE;
       
   238     }
       
   239 
       
   240   return TRUE;
       
   241 }
       
   242 
       
   243 static GValue *param_default_value (const GabbleParamSpec *params, int i)
       
   244 {
       
   245   GValue *value;
       
   246 
       
   247   value = g_new0(GValue, 1);
       
   248   g_value_init(value, params[i].gtype);
       
   249 
       
   250   /* TODO: this check could be stricter if we knew whether register
       
   251   was true. In practice REQUIRED and REGISTER always go together in
       
   252   the Gabble params, though */
       
   253   if (params[i].flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED & TP_CONN_MGR_PARAM_FLAG_REGISTER)
       
   254     {
       
   255       g_assert(params[i].def == NULL);
       
   256       goto OUT;
       
   257     }
       
   258 
       
   259   switch (params[i].dtype[0])
       
   260     {
       
   261       case DBUS_TYPE_STRING:
       
   262         g_value_set_static_string (value, (const gchar*) params[i].def);
       
   263         break;
       
   264       case DBUS_TYPE_INT16:
       
   265         g_value_set_int (value, GPOINTER_TO_INT (params[i].def));
       
   266         break;
       
   267       case DBUS_TYPE_UINT16:
       
   268         g_value_set_uint (value, GPOINTER_TO_INT (params[i].def));
       
   269         break;
       
   270       case DBUS_TYPE_BOOLEAN:
       
   271         g_value_set_boolean (value, GPOINTER_TO_INT (params[i].def));
       
   272         break;
       
   273       default:
       
   274         g_error("parameter_defaults: encountered unknown type %s on argument %s",
       
   275                 params[i].dtype, params[i].name);
       
   276     }
       
   277 
       
   278 OUT:
       
   279   return value;
       
   280 }
       
   281 
       
   282 static gboolean
       
   283 set_param_from_value (const GabbleParamSpec *paramspec,
       
   284                                      GValue *value,
       
   285                                GabbleParams *params,
       
   286                                     GError **error)
       
   287 {
       
   288   if (G_VALUE_TYPE (value) != paramspec->gtype)
       
   289     {
       
   290       g_debug ("%s: expected type %s for parameter %s, got %s",
       
   291                G_STRFUNC,
       
   292                g_type_name (paramspec->gtype), paramspec->name,
       
   293                G_VALUE_TYPE_NAME (value));
       
   294       g_set_error (error, TELEPATHY_ERRORS, InvalidArgument,
       
   295           "expected type %s for account parameter %s, got %s",
       
   296           g_type_name (paramspec->gtype), paramspec->name,
       
   297           G_VALUE_TYPE_NAME (value));
       
   298       return FALSE;
       
   299     }
       
   300 
       
   301   switch (paramspec->dtype[0])
       
   302     {
       
   303       case DBUS_TYPE_STRING:
       
   304         {
       
   305           const char *str = g_value_get_string (value);
       
   306           if (!str || *str == '\0')
       
   307             return FALSE;
       
   308           else
       
   309             *((char **) ((char *)params + paramspec->offset)) = g_value_dup_string (value);
       
   310         }
       
   311         break;
       
   312       case DBUS_TYPE_INT16:
       
   313         *((gint *) ((char *)params + paramspec->offset)) = g_value_get_int (value);
       
   314         break;
       
   315       case DBUS_TYPE_UINT16:
       
   316         *((guint *) ((char *)params + paramspec->offset)) = g_value_get_uint (value);
       
   317         break;
       
   318       case DBUS_TYPE_BOOLEAN:
       
   319         *((gboolean *) ((char *)params + paramspec->offset)) = g_value_get_boolean (value);
       
   320         break;
       
   321       default:
       
   322         g_error ("set_param_from_value: encountered unknown type %s on argument %s",
       
   323                  paramspec->dtype, paramspec->name);
       
   324         return FALSE;
       
   325     }
       
   326 
       
   327   return TRUE;
       
   328 }
       
   329 
       
   330 static gboolean
       
   331 parse_parameters (const GabbleParamSpec *paramspec,
       
   332                   GHashTable            *provided,
       
   333                   GabbleParams          *params,
       
   334                   GError               **error)
       
   335 {
       
   336   int unhandled;
       
   337   int i;
       
   338   guint mandatory_flag = TP_CONN_MGR_PARAM_FLAG_REQUIRED;
       
   339   GValue *value;
       
   340 
       
   341   unhandled = g_hash_table_size (provided);
       
   342 
       
   343   value = g_hash_table_lookup (provided, "register");
       
   344   if (value != NULL && G_VALUE_TYPE(value) == G_TYPE_BOOLEAN &&
       
   345       g_value_get_boolean(value))
       
   346     {
       
   347       mandatory_flag = TP_CONN_MGR_PARAM_FLAG_REGISTER;
       
   348     }
       
   349 
       
   350   for (i = 0; paramspec[i].name; i++)
       
   351     {
       
   352       value = g_hash_table_lookup (provided, paramspec[i].name);
       
   353 
       
   354       if (value == NULL)
       
   355         {
       
   356           if (paramspec[i].flags & mandatory_flag)
       
   357             {
       
   358               g_debug ("%s: missing mandatory param %s",
       
   359                        G_STRFUNC, paramspec[i].name);
       
   360               g_set_error (error, TELEPATHY_ERRORS, InvalidArgument,
       
   361                   "missing mandatory account parameter %s", paramspec[i].name);
       
   362               return FALSE;
       
   363             }
       
   364           else
       
   365             {
       
   366               g_debug ("%s: using default value for param %s",
       
   367                        G_STRFUNC, paramspec[i].name);
       
   368             }
       
   369         }
       
   370       else
       
   371         {
       
   372           if (!set_param_from_value (&paramspec[i], value, params, error))
       
   373             {
       
   374               g_set_error (error, TELEPATHY_ERRORS, InvalidArgument,
       
   375                   "invalid value for parameter %s", paramspec[i].name);
       
   376               return FALSE;
       
   377             }
       
   378 
       
   379           params->set_mask |= 1 << i;
       
   380 
       
   381           unhandled--;
       
   382           if (paramspec[i].gtype == G_TYPE_STRING)
       
   383             {
       
   384               if (0 == strcmp (paramspec[i].name, "password"))
       
   385                 {
       
   386                   g_debug ("%s: accepted value <hidden> for param password",
       
   387                       G_STRFUNC);
       
   388                 }
       
   389               else
       
   390                 {
       
   391                   g_debug ("%s: accepted value %s for param %s",
       
   392                       G_STRFUNC,
       
   393                       *((char **) ((char *)params + paramspec[i].offset)),
       
   394                       paramspec[i].name);
       
   395                 }
       
   396             }
       
   397           else
       
   398             {
       
   399               g_debug ("%s: accepted value %u for param %s", G_STRFUNC,
       
   400                        *((guint *) ((char *)params + paramspec[i].offset)), paramspec[i].name);
       
   401             }
       
   402         }
       
   403     }
       
   404 
       
   405   if (unhandled)
       
   406     {
       
   407       g_debug ("%s: unknown argument name provided", G_STRFUNC);
       
   408       g_set_error (error, TELEPATHY_ERRORS, InvalidArgument,
       
   409           "unknown argument name provided");
       
   410       return FALSE;
       
   411     }
       
   412 
       
   413   return TRUE;
       
   414 }
       
   415 
       
   416 static void
       
   417 free_params (GabbleParams *params)
       
   418 {
       
   419   g_free (params->account);
       
   420   g_free (params->password);
       
   421   g_free (params->server);
       
   422   g_free (params->resource);
       
   423   g_free (params->https_proxy_server);
       
   424   g_free (params->fallback_conference_server);
       
   425   g_free (params->stun_server);
       
   426   g_free (params->alias);
       
   427 }
       
   428 
       
   429 /**
       
   430  * connection_disconnected_cb:
       
   431  * @conn: #GabbleConnection
       
   432  * @data: data passed in callback
       
   433  *
       
   434  * Signal handler called when a connection object disconnects.
       
   435  * When they become disconnected, we can unref and discard
       
   436  * them, and they will disappear from the bus.
       
   437  */
       
   438 static void
       
   439 connection_disconnected_cb (GabbleConnection        *conn,
       
   440                             gpointer                 data)
       
   441 {
       
   442   GabbleConnectionManager *self = GABBLE_CONNECTION_MANAGER (data);
       
   443   GabbleConnectionManagerPrivate *priv = GABBLE_CONNECTION_MANAGER_GET_PRIVATE (self);
       
   444 
       
   445   g_assert (g_hash_table_lookup (priv->connections, conn));
       
   446   
       
   447   /* fix: this check should only be done if priv->connections is not null, and conn is not null */
       
   448   
       
   449   if( (priv->connections) && (conn))
       
   450       g_hash_table_remove (priv->connections, conn);
       
   451 
       
   452   /* end of fix */
       
   453   
       
   454   g_object_unref (conn);
       
   455 
       
   456   g_debug ("%s: dereferenced connection", G_STRFUNC);
       
   457   if(priv->connections)
       
   458     if (g_hash_table_size (priv->connections) == 0)
       
   459     {
       
   460       g_signal_emit (self, signals [NO_MORE_CONNECTIONS], 0);
       
   461       g_debug ("%s: emitting no more connections", G_STRFUNC);
       
   462     }
       
   463 
       
   464 
       
   465 }
       
   466 
       
   467 /* public methods */
       
   468 
       
   469 #ifdef SYMBIAN
       
   470 EXPORT_C
       
   471 #endif
       
   472 void
       
   473 _gabble_connection_manager_register (GabbleConnectionManager *self)
       
   474 {
       
   475   DBusGConnection *bus;
       
   476   DBusGProxy *bus_proxy;
       
   477   GError *error = NULL;
       
   478   guint request_name_result;
       
   479 
       
   480   g_assert (GABBLE_IS_CONNECTION_MANAGER (self));
       
   481 
       
   482   bus = tp_get_bus ();
       
   483   bus_proxy = tp_get_bus_proxy ();
       
   484 
       
   485   if (!dbus_g_proxy_call (bus_proxy, "RequestName", &error,
       
   486                           G_TYPE_STRING, GABBLE_CONN_MGR_BUS_NAME,
       
   487                           G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
       
   488                           G_TYPE_INVALID,
       
   489                           G_TYPE_UINT, &request_name_result,
       
   490                           G_TYPE_INVALID))
       
   491     g_error ("Failed to request bus name: %s", error->message);
       
   492 
       
   493   if (request_name_result == DBUS_REQUEST_NAME_REPLY_EXISTS)
       
   494     {
       
   495       g_warning ("Failed to acquire bus name, connection manager already running?");
       
   496       exit (1);
       
   497     }
       
   498 
       
   499   dbus_g_connection_register_g_object (bus, GABBLE_CONN_MGR_OBJECT_PATH, G_OBJECT (self));
       
   500 }
       
   501 
       
   502 /* dbus-exported methods */
       
   503 
       
   504 /**
       
   505  * gabble_connection_manager_get_parameters
       
   506  *
       
   507  * Implements D-Bus method GetParameters
       
   508  * on interface org.freedesktop.Telepathy.ConnectionManager
       
   509  *
       
   510  * @error: Used to return a pointer to a GError detailing any error
       
   511  *         that occurred, D-Bus will throw the error only if this
       
   512  *         function returns FALSE.
       
   513  *
       
   514  * Returns: TRUE if successful, FALSE if an error was thrown.
       
   515  */
       
   516 gboolean
       
   517 gabble_connection_manager_get_parameters (GabbleConnectionManager *self,
       
   518                                           const gchar *proto,
       
   519                                           GPtrArray **ret,
       
   520                                           GError **error)
       
   521 {
       
   522   const GabbleParamSpec *params = NULL;
       
   523   int i;
       
   524 
       
   525   if (!get_parameters (proto, &params, error))
       
   526     return FALSE;
       
   527 
       
   528   *ret = g_ptr_array_new ();
       
   529 
       
   530   for (i = 0; params[i].name; i++)
       
   531     {
       
   532       GValue *def_value;
       
   533       GValue param = { 0, };
       
   534 
       
   535       g_value_init (&param, TP_TYPE_PARAM);
       
   536       g_value_set_static_boxed (&param,
       
   537         dbus_g_type_specialized_construct (TP_TYPE_PARAM));
       
   538       
       
   539       def_value = param_default_value (params, i);
       
   540       dbus_g_type_struct_set (&param,
       
   541         0, params[i].name,
       
   542         1, params[i].flags,
       
   543         2, params[i].dtype,
       
   544         3, def_value,
       
   545         G_MAXUINT);
       
   546       g_value_unset(def_value);
       
   547       g_free(def_value);
       
   548 
       
   549       g_ptr_array_add (*ret, g_value_get_boxed (&param));
       
   550     }
       
   551 
       
   552   return TRUE;
       
   553 }
       
   554 
       
   555 
       
   556 /**
       
   557  * gabble_connection_manager_list_protocols
       
   558  *
       
   559  * Implements D-Bus method ListProtocols
       
   560  * on interface org.freedesktop.Telepathy.ConnectionManager
       
   561  *
       
   562  * @error: Used to return a pointer to a GError detailing any error
       
   563  *         that occurred, D-Bus will throw the error only if this
       
   564  *         function returns FALSE.
       
   565  *
       
   566  * Returns: TRUE if successful, FALSE if an error was thrown.
       
   567  */
       
   568 gboolean
       
   569 gabble_connection_manager_list_protocols (GabbleConnectionManager *self,
       
   570                                           gchar ***ret,
       
   571                                           GError **error)
       
   572 {
       
   573   const char *protocols[] = { "jabber", NULL };
       
   574   g_message("BINGO...gabble_connection_manager_list_protocols entered \n");
       
   575 
       
   576   *ret = g_strdupv ((gchar **)protocols);
       
   577 
       
   578   g_message("BINGO...leaving gabble_connection_manager_list_protocols \n");
       
   579 
       
   580   return TRUE;
       
   581 }
       
   582 
       
   583 
       
   584 #define SET_PROPERTY_IF_PARAM_SET(prop, param, member) \
       
   585   if ((params.set_mask & (1 << param)) != 0) \
       
   586     { \
       
   587       g_object_set (conn, prop, member, NULL); \
       
   588     }
       
   589 
       
   590 
       
   591 /**
       
   592  * gabble_connection_manager_request_connection
       
   593  *
       
   594  * Implements D-Bus method RequestConnection
       
   595  * on interface org.freedesktop.Telepathy.ConnectionManager
       
   596  *
       
   597  * @error: Used to return a pointer to a GError detailing any error
       
   598  *         that occurred, D-Bus will throw the error only if this
       
   599  *         function returns FALSE.
       
   600  *
       
   601  * Returns: TRUE if successful, FALSE if an error was thrown.
       
   602  */
       
   603 gboolean
       
   604 gabble_connection_manager_request_connection (GabbleConnectionManager *self,
       
   605                                               const gchar *proto,
       
   606                                               GHashTable *parameters,
       
   607                                               gchar **bus_name,
       
   608                                               gchar **object_path,
       
   609                                               GError **error)
       
   610 {
       
   611   GabbleConnectionManagerPrivate *priv;
       
   612   GabbleConnection *conn;
       
   613   const GabbleParamSpec *paramspec;
       
   614   GabbleParams params = { 0, };
       
   615 
       
   616   g_assert (GABBLE_IS_CONNECTION_MANAGER (self));
       
   617 
       
   618   priv = GABBLE_CONNECTION_MANAGER_GET_PRIVATE (self);
       
   619 
       
   620   if (!get_parameters (proto, &paramspec, error))
       
   621 		return FALSE;
       
   622   
       
   623 
       
   624   if (!parse_parameters (paramspec, parameters, &params, error))
       
   625     {
       
   626       free_params (&params);
       
   627       return FALSE;
       
   628     }
       
   629 
       
   630   conn = g_object_new (GABBLE_TYPE_CONNECTION,
       
   631                        "protocol",           proto,
       
   632                        "password",           params.password,
       
   633                        NULL);
       
   634   
       
   635   g_message("BINGO...after g_object_new \n");
       
   636 
       
   637   SET_PROPERTY_IF_PARAM_SET ("connect-server", JABBER_PARAM_SERVER,
       
   638                              params.server);
       
   639   SET_PROPERTY_IF_PARAM_SET ("resource", JABBER_PARAM_RESOURCE,
       
   640                              params.resource);
       
   641   SET_PROPERTY_IF_PARAM_SET ("priority", JABBER_PARAM_PRIORITY,
       
   642                              CLAMP (params.priority, G_MININT8, G_MAXINT8));
       
   643   SET_PROPERTY_IF_PARAM_SET ("port", JABBER_PARAM_PORT, params.port);
       
   644   SET_PROPERTY_IF_PARAM_SET ("old-ssl", JABBER_PARAM_OLD_SSL, params.old_ssl);
       
   645   SET_PROPERTY_IF_PARAM_SET ("register", JABBER_PARAM_REGISTER,
       
   646                              params.do_register);
       
   647   SET_PROPERTY_IF_PARAM_SET ("low-bandwidth", JABBER_PARAM_LOW_BANDWIDTH,
       
   648                              params.low_bandwidth);
       
   649   SET_PROPERTY_IF_PARAM_SET ("https-proxy-server",
       
   650                              JABBER_PARAM_HTTPS_PROXY_SERVER,
       
   651                              params.https_proxy_server);
       
   652   SET_PROPERTY_IF_PARAM_SET ("https-proxy-port", JABBER_PARAM_HTTPS_PROXY_PORT,
       
   653                              params.https_proxy_port);
       
   654   SET_PROPERTY_IF_PARAM_SET ("fallback-conference-server",
       
   655                              JABBER_PARAM_FALLBACK_CONFERENCE_SERVER,
       
   656                              params.fallback_conference_server);
       
   657   SET_PROPERTY_IF_PARAM_SET ("stun-server", JABBER_PARAM_STUN_SERVER,
       
   658                              params.stun_server);
       
   659   SET_PROPERTY_IF_PARAM_SET ("stun-port", JABBER_PARAM_STUN_PORT,
       
   660                              params.stun_port);
       
   661   SET_PROPERTY_IF_PARAM_SET ("ignore-ssl-errors",
       
   662                               JABBER_PARAM_IGNORE_SSL_ERRORS,
       
   663                               params.ignore_ssl_errors);
       
   664   SET_PROPERTY_IF_PARAM_SET ("alias", JABBER_PARAM_ALIAS, params.alias);
       
   665 
       
   666   // split up account into username, stream-server and resource
       
   667   if (!_gabble_connection_set_properties_from_account (conn, params.account, error))
       
   668     {
       
   669       goto ERROR;
       
   670     }
       
   671 
       
   672   // free memory allocated by param parser
       
   673   free_params(&params);
       
   674 
       
   675 // with hash table usage - end
       
   676 
       
   677 
       
   678   // register on bus and save bus name and object path
       
   679   if (!_gabble_connection_register (conn, bus_name, object_path, error))
       
   680     {
       
   681       g_debug ("%s failed: %s", G_STRFUNC, (*error)->message);
       
   682 
       
   683       goto ERROR;
       
   684     }
       
   685   
       
   686   /* bind to status change signals from the connection object */
       
   687   g_signal_connect (conn, "disconnected",
       
   688                              G_CALLBACK (connection_disconnected_cb),
       
   689                              self);
       
   690   
       
   691   /* store the connection, using a hash table as a set */
       
   692   g_hash_table_insert (priv->connections, conn, GINT_TO_POINTER(TRUE));
       
   693 
       
   694   /* emit the new connection signal */
       
   695   g_signal_emit (self, signals [NEW_CONNECTION], 0, *bus_name, *object_path, proto);
       
   696 
       
   697   return TRUE;
       
   698 
       
   699 ERROR:
       
   700   if (conn)
       
   701     g_object_unref (G_OBJECT (conn));
       
   702 
       
   703   g_message("ERROR...returning FALSE\n");
       
   704   return FALSE;
       
   705 }