loudmouth/lm-connection.c
changeset 528 5b46873eeef8
parent 519 b80401412e1c
child 529 6bb284696153
equal deleted inserted replaced
527:2e905f83be70 528:5b46873eeef8
    28  * An example of how to use Loudmouth with the synchronous API.
    28  * An example of how to use Loudmouth with the synchronous API.
    29  * <informalexample><programlisting>
    29  * <informalexample><programlisting>
    30  * int
    30  * int
    31  * main (int argc, char **argv)
    31  * main (int argc, char **argv)
    32  * {
    32  * {
    33  *       LmConnection *connection;
    33  *      LmConnection *connection;
    34  *       GError       *error = NULL;
    34  *      GError       *error = NULL;
    35  *       gint          i;
    35  *      gint          i;
    36  *   LmMessage    *m;
    36  *      LmMessage    *m;
    37  *
    37  *
    38  *       connection = lm_connection_new ("myserver");
    38  *      connection = lm_connection_new ("myserver");
    39  * 
    39  * 
    40  *       if (!lm_connection_open_and_block (connection, &amp;error)) {
    40  *      if (!lm_connection_open_and_block (connection, &amp;error)) {
    41  *               g_error ("Failed to open: &percnt;s\n", error->message);
    41  *          g_error ("Failed to open: &percnt;s\n", error->message);
    42  *       }
    42  *      }
    43  * 
    43  * 
    44  *       if (!lm_connection_authenticate_and_block (connection,
    44  *      if (!lm_connection_authenticate_and_block (connection,
    45  *                         "username", "password", 
    45  *                                                 "username", "password", 
    46  *                         "resource",
    46  *                                                 "resource",
    47  *                         &amp;error)) {
    47  *                                                 &amp;error)) {
    48  *      g_error ("Failed to authenticate: &percnt;s\n", error->message);
    48  *          g_error ("Failed to authenticate: &percnt;s\n", error->message);
    49  *  }
    49  *      }
    50  *  
    50  *  
    51  *  m = lm_message_new ("recipient", LM_MESSAGE_TYPE_MESSAGE);
    51  *      m = lm_message_new ("recipient", LM_MESSAGE_TYPE_MESSAGE);
    52  *  lm_message_node_add_child (m->node, "body", "message");
    52  *      lm_message_node_add_child (m->node, "body", "message");
    53  *  
    53  *  
    54  *  if (!lm_connection_send (connection, m, &amp;error)) {
    54  *      if (!lm_connection_send (connection, m, &amp;error)) {
    55  *      g_error ("Send failed: &percnt;s\n", error->message);
    55  *          g_error ("Send failed: &percnt;s\n", error->message);
    56  *  }
    56  *      }
    57  * 
    57  * 
    58  *  lm_message_unref (m);
    58  *      lm_message_unref (m);
    59  * 
    59  * 
    60  *  lm_connection_close (connection, NULL);
    60  *      lm_connection_close (connection, NULL);
    61  *  lm_connection_unref (connection);
    61  *      lm_connection_unref (connection);
    62  *  
    62  *  
    63  *         return 0;
    63  *      return 0;
    64  * }
    64  * }
    65  * </programlisting></informalexample>
    65  * </programlisting></informalexample>
    66  */
    66  */
    67 
    67 
    68 #include <config.h>
    68 #include <config.h>
   102     LmMessageHandler  *handler;
   102     LmMessageHandler  *handler;
   103 } HandlerData;
   103 } HandlerData;
   104 
   104 
   105 struct _LmConnection {
   105 struct _LmConnection {
   106     /* Parameters */
   106     /* Parameters */
   107     GMainContext *context;
   107     GMainContext      *context;
   108     gchar        *server;
   108     gchar             *server;
   109     gchar        *jid;
   109     gchar             *jid;
   110     gchar        *effective_jid;
   110     gchar             *effective_jid;
   111     guint         port;
   111     guint              port;
   112     gboolean      use_srv;
   112     gboolean           use_srv;
   113 
   113 
   114     LmOldSocket     *socket;
   114     LmOldSocket       *socket;
   115     LmSSL        *ssl;
   115     LmSSL             *ssl;
   116     LmProxy      *proxy;
   116     LmProxy           *proxy;
   117     LmParser     *parser;
   117     LmParser          *parser;
   118 
   118 
   119     gchar        *stream_id;
   119     gchar             *stream_id;
   120 
   120 
   121     GHashTable   *id_handlers;
   121     GHashTable        *id_handlers;
   122     GSList       *handlers[LM_MESSAGE_TYPE_UNKNOWN];
   122     GSList            *handlers[LM_MESSAGE_TYPE_UNKNOWN];
   123 
   123 
   124     /* XMPP1.0 stuff (SASL, resource binding, StartTLS) */
   124     /* XMPP1.0 stuff (SASL, resource binding, StartTLS) */
   125     gboolean      use_sasl;
   125     gboolean           use_sasl;
   126     LmSASL       *sasl;
   126     LmSASL            *sasl;
   127     gchar        *resource;
   127     gchar             *resource;
   128     LmMessageHandler *features_cb;
   128     LmMessageHandler  *features_cb;
   129     LmMessageHandler *starttls_cb;
   129     LmMessageHandler  *starttls_cb;
   130     gboolean      tls_started;
   130     gboolean           tls_started;
   131 
   131 
   132     /* Communication */
   132     /* Communication */
   133     guint         open_id;
   133     guint              open_id;
   134     LmCallback   *open_cb;
   134     LmCallback        *open_cb;
   135 
   135 
   136     gboolean      async_connect_waiting;
   136     gboolean           async_connect_waiting;
   137     gboolean      blocking;
   137     gboolean           blocking;
   138 
   138 
   139     gboolean      cancel_open;
   139     gboolean           cancel_open;
   140     LmCallback   *auth_cb;
   140     LmCallback        *auth_cb;
   141 
   141 
   142     LmCallback   *disconnect_cb;
   142     LmCallback        *disconnect_cb;
   143 
   143 
   144     LmMessageQueue *queue;
   144     LmMessageQueue    *queue;
   145 
   145 
   146     LmConnectionState state;
   146     LmConnectionState  state;
   147 
   147 
   148     guint          keep_alive_rate;
   148     guint              keep_alive_rate;
   149     LmFeaturePing *feature_ping;
   149     LmFeaturePing     *feature_ping;
   150 
   150 
   151     gint          ref_count;
   151     gint               ref_count;
   152 };
   152 };
   153 
   153 
   154 typedef enum {
   154 typedef enum {
   155     AUTH_TYPE_PLAIN  = 1,
   155     AUTH_TYPE_PLAIN  = 1,
   156     AUTH_TYPE_DIGEST = 2,
   156     AUTH_TYPE_DIGEST = 2,
   205 static void     connection_message_queue_cb  (LmMessageQueue      *queue,
   205 static void     connection_message_queue_cb  (LmMessageQueue      *queue,
   206                                               LmConnection        *connection);
   206                                               LmConnection        *connection);
   207 static void      
   207 static void      
   208 connection_signal_disconnect                 (LmConnection        *connection,
   208 connection_signal_disconnect                 (LmConnection        *connection,
   209                                               LmDisconnectReason   reason);
   209                                               LmDisconnectReason   reason);
   210 static void     connection_incoming_data     (LmOldSocket            *socket, 
   210 static void     connection_incoming_data     (LmOldSocket         *socket, 
   211                                               const gchar         *buf,
   211                                               const gchar         *buf,
   212                                               LmConnection        *connection);
   212                                               LmConnection        *connection);
   213 static void     connection_socket_closed_cb  (LmOldSocket            *socket,
   213 static void     connection_socket_closed_cb  (LmOldSocket            *socket,
   214                                               LmDisconnectReason   reason,
   214                                               LmDisconnectReason   reason,
   215                                               LmConnection        *connection);
   215                                               LmConnection        *connection);
   216 static void      
   216 static void      
   217 connection_socket_connect_cb                 (LmOldSocket            *socket,
   217 connection_socket_connect_cb                 (LmOldSocket         *socket,
   218                                               gboolean             result,
   218                                               gboolean             result,
   219                                               LmConnection        *connection);
   219                                               LmConnection        *connection);
   220 static gboolean
   220 static gboolean
   221 connection_get_server_from_jid              (const gchar          *jid,
   221 connection_get_server_from_jid               (const gchar         *jid,
   222                                              gchar               **server);
   222                                               gchar              **server);
   223 static void
   223 static void
   224 connection_send_stream_header               (LmConnection         *connection);
   224 connection_send_stream_header                (LmConnection        *connection);
   225 static LmHandlerResult 
   225 static LmHandlerResult 
   226 connection_features_cb                      (LmMessageHandler     *handler,
   226 connection_features_cb                       (LmMessageHandler    *handler,
   227                                              LmConnection         *connection,
   227                                               LmConnection        *connection,
   228                                              LmMessage            *message,
   228                                               LmMessage           *message,
   229                                              gpointer              user_data);
   229                                               gpointer             user_data);
   230 static gboolean connection_old_auth         (LmConnection         *connection,
   230 static gboolean connection_old_auth          (LmConnection        *connection,
   231                                              const gchar          *username,
   231                                               const gchar         *username,
   232                                              const gchar          *password,
   232                                               const gchar         *password,
   233                                              const gchar          *resource,
   233                                               const gchar         *resource,
   234                                              GError              **errror);
   234                                               GError             **errror);
   235 
   235 
   236 static void
   236 static void
   237 connection_free_handlers (LmConnection *connection)
   237 connection_free_handlers (LmConnection *connection)
   238 {
   238 {
   239     int i;
   239     int i;
   387 
   387 
   388     lm_message_queue_push_tail (connection->queue, m);
   388     lm_message_queue_push_tail (connection->queue, m);
   389 }
   389 }
   390 
   390 
   391 static void
   391 static void
   392 connection_ping_timed_out (LmFeaturePing *fp, 
   392 connection_ping_timed_out (LmFeaturePing *fp, LmConnection  *connection)
   393                            LmConnection  *connection)
       
   394 {
   393 {
   395     connection_do_close (connection);
   394     connection_do_close (connection);
   396     connection_signal_disconnect (connection,
   395     connection_signal_disconnect (connection,
   397                                   LM_DISCONNECT_REASON_PING_TIME_OUT);
   396                                   LM_DISCONNECT_REASON_PING_TIME_OUT);
   398 }
   397 }
   753 }
   752 }
   754 
   753 
   755 
   754 
   756 static LmHandlerResult
   755 static LmHandlerResult
   757 _lm_connection_starttls_cb (LmMessageHandler *handler,
   756 _lm_connection_starttls_cb (LmMessageHandler *handler,
   758                             LmConnection *connection,
   757                             LmConnection     *connection,
   759                             LmMessage *message,
   758                             LmMessage        *message,
   760                             gpointer user_data)
   759                             gpointer          user_data)
   761 {
   760 {
   762     if (lm_old_socket_starttls (connection->socket)) {
   761     if (lm_old_socket_starttls (connection->socket)) {
   763         connection->tls_started = TRUE;
   762         connection->tls_started = TRUE;
   764         connection_send_stream_header (connection);
   763         connection_send_stream_header (connection);
   765     } else {
   764     } else {
   797     
   796     
   798     g_return_if_fail (connection != NULL);
   797     g_return_if_fail (connection != NULL);
   799     g_return_if_fail (m != NULL);
   798     g_return_if_fail (m != NULL);
   800     
   799     
   801     connection->stream_id = g_strdup (lm_message_node_get_attribute (m->node,
   800     connection->stream_id = g_strdup (lm_message_node_get_attribute (m->node,
   802                                                                      "id"));;
   801                                                                      "id"));
   803 
   802 
   804     xmpp_version = lm_message_node_get_attribute (m->node, "version");
   803     xmpp_version = lm_message_node_get_attribute (m->node, "version");
   805     if (xmpp_version && strcmp (xmpp_version, "1.0") == 0) {
   804     if (xmpp_version && strcmp (xmpp_version, "1.0") == 0) {
   806         lm_verbose ("XMPP 1.0 stream received: %s\n",
   805         lm_verbose ("XMPP 1.0 stream received: %s\n",
   807                     connection->stream_id);
   806                     connection->stream_id);
   870     }
   869     }
   871 
   870 
   872     lm_verbose ("Stream error: Unrecognised error\n");
   871     lm_verbose ("Stream error: Unrecognised error\n");
   873     reason = LM_DISCONNECT_REASON_ERROR;
   872     reason = LM_DISCONNECT_REASON_ERROR;
   874     connection->stream_id = g_strdup (lm_message_node_get_attribute (m->node,
   873     connection->stream_id = g_strdup (lm_message_node_get_attribute (m->node,
   875                                                                      "id"));;
   874                                                                      "id"));
   876     connection_do_close (connection);
   875     connection_do_close (connection);
   877     connection_signal_disconnect (connection, reason);
   876     connection_signal_disconnect (connection, reason);
   878 }
   877 }
   879 
   878 
   880 static gint
   879 static gint
   897         lm_connection_unref (connection);
   896         lm_connection_unref (connection);
   898     }
   897     }
   899 }
   898 }
   900 
   899 
   901 static void
   900 static void
   902 connection_incoming_data (LmOldSocket     *socket, 
   901 connection_incoming_data (LmOldSocket  *socket, 
   903                           const gchar  *buf, 
   902                           const gchar  *buf, 
   904                           LmConnection *connection)
   903                           LmConnection *connection)
   905 {
   904 {
   906     lm_parser_parse (connection->parser, buf);
   905     lm_parser_parse (connection->parser, buf);
   907 }
   906 }
   914     connection_do_close (connection);
   913     connection_do_close (connection);
   915     connection_signal_disconnect (connection, reason);
   914     connection_signal_disconnect (connection, reason);
   916 }
   915 }
   917 
   916 
   918 static void
   917 static void
   919 connection_socket_connect_cb (LmOldSocket           *socket,
   918 connection_socket_connect_cb (LmOldSocket  *socket,
   920                               gboolean            result,
   919                               gboolean      result,
   921                               LmConnection       *connection)
   920                               LmConnection *connection)
   922 {
   921 {
   923     if (result == FALSE) {
   922     if (result == FALSE) {
   924         connection_do_close (connection);
   923         connection_do_close (connection);
   925 
   924 
   926         if (connection->open_cb) {
   925         if (connection->open_cb) {
   949 
   948 
   950     connection_send_stream_header (connection);
   949     connection_send_stream_header (connection);
   951 }
   950 }
   952 
   951 
   953 static gboolean
   952 static gboolean
   954 connection_get_server_from_jid (const gchar     *jid,
   953 connection_get_server_from_jid (const gchar *jid, gchar **server)
   955                                 gchar          **server)
       
   956 {
   954 {
   957     gchar *ch;
   955     gchar *ch;
   958     gchar *ch_end;
   956     gchar *ch_end;
   959 
   957 
   960     if (jid != NULL && (ch = strchr (jid, '@')) != NULL) {
   958     if (jid != NULL && (ch = strchr (jid, '@')) != NULL) {
  1058     }
  1056     }
  1059 }
  1057 }
  1060 
  1058 
  1061 static LmHandlerResult
  1059 static LmHandlerResult
  1062 connection_bind_reply (LmMessageHandler *handler,
  1060 connection_bind_reply (LmMessageHandler *handler,
  1063                        LmConnection    *connection,
  1061                        LmConnection     *connection,
  1064                        LmMessage       *message,
  1062                        LmMessage        *message,
  1065                        gpointer         user_data)
  1063                        gpointer          user_data)
  1066 {
  1064 {
  1067     LmMessage        *m;
  1065     LmMessage        *m;
  1068     LmMessageNode    *session_node;
  1066     LmMessageNode    *session_node;
  1069     LmMessageNode    *jid_node;
  1067     LmMessageNode    *jid_node;
  1070     int               result;
  1068     int               result;
  1418  * A synchronous call to close the connection. When returning the connection is considered to be closed and can be opened again with lm_connection_open().
  1416  * A synchronous call to close the connection. When returning the connection is considered to be closed and can be opened again with lm_connection_open().
  1419  * 
  1417  * 
  1420  * Return value: Returns #TRUE if no errors where detected, otherwise #FALSE.
  1418  * Return value: Returns #TRUE if no errors where detected, otherwise #FALSE.
  1421  **/
  1419  **/
  1422 gboolean
  1420 gboolean
  1423 lm_connection_close (LmConnection      *connection, 
  1421 lm_connection_close (LmConnection *connection, GError **error)
  1424                      GError           **error)
       
  1425 {
  1422 {
  1426     gboolean no_errors = TRUE;
  1423     gboolean no_errors = TRUE;
  1427     
  1424     
  1428     g_return_val_if_fail (connection != NULL, FALSE);
  1425     g_return_val_if_fail (connection != NULL, FALSE);
  1429 
  1426 
  1455     
  1452     
  1456     return no_errors;
  1453     return no_errors;
  1457 }
  1454 }
  1458 
  1455 
  1459 static void
  1456 static void
  1460 connection_sasl_auth_finished (LmSASL *sasl,
  1457 connection_sasl_auth_finished (LmSASL       *sasl,
  1461                                LmConnection *connection,
  1458                                LmConnection *connection,
  1462                                gboolean success,
  1459                                gboolean      success,
  1463                                const gchar *reason)
  1460                                const gchar  *reason)
  1464 {
  1461 {
  1465     if (!success) {
  1462     if (!success) {
  1466         lm_verbose ("SASL authentication failed, closing connection\n");
  1463         lm_verbose ("SASL authentication failed, closing connection\n");
  1467         connection_call_auth_cb (connection, FALSE);
  1464         connection_call_auth_cb (connection, FALSE);
  1468         return;
  1465         return;
  2066  * 
  2063  * 
  2067  * Registers a #LmMessageHandler to handle incoming messages of a certain type.
  2064  * Registers a #LmMessageHandler to handle incoming messages of a certain type.
  2068  * To unregister the handler call lm_connection_unregister_message_handler().
  2065  * To unregister the handler call lm_connection_unregister_message_handler().
  2069  **/
  2066  **/
  2070 void
  2067 void
  2071 lm_connection_register_message_handler  (LmConnection       *connection,
  2068 lm_connection_register_message_handler  (LmConnection      *connection,
  2072                                          LmMessageHandler   *handler,
  2069                                          LmMessageHandler  *handler,
  2073                                          LmMessageType       type,
  2070                                          LmMessageType      type,
  2074                                          LmHandlerPriority   priority)
  2071                                          LmHandlerPriority  priority)
  2075 {
  2072 {
  2076     HandlerData      *hd;
  2073     HandlerData      *hd;
  2077     
  2074     
  2078     g_return_if_fail (connection != NULL);
  2075     g_return_if_fail (connection != NULL);
  2079     g_return_if_fail (handler != NULL);
  2076     g_return_if_fail (handler != NULL);
  2096  * 
  2093  * 
  2097  * Unregisters a handler for @connection. @handler will no longer be called 
  2094  * Unregisters a handler for @connection. @handler will no longer be called 
  2098  * when incoming messages of @type arrive.
  2095  * when incoming messages of @type arrive.
  2099  **/
  2096  **/
  2100 void
  2097 void
  2101 lm_connection_unregister_message_handler (LmConnection      *connection,
  2098 lm_connection_unregister_message_handler (LmConnection     *connection,
  2102                                           LmMessageHandler  *handler,
  2099                                           LmMessageHandler *handler,
  2103                                           LmMessageType      type)
  2100                                           LmMessageType     type)
  2104 {
  2101 {
  2105     GSList *l;
  2102     GSList *l;
  2106     
  2103     
  2107     g_return_if_fail (connection != NULL);
  2104     g_return_if_fail (connection != NULL);
  2108     g_return_if_fail (handler != NULL);
  2105     g_return_if_fail (handler != NULL);