telepathygabble/src/gabble-error.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /*
       
     2  * gabble-error.c - Source for Gabble's error handling API
       
     3  * Copyright (C) 2006 Collabora Ltd.
       
     4  * 
       
     5  *   @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk>
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Lesser General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2.1 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Lesser General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Lesser General Public
       
    18  * License along with this library; if not, write to the Free Software
       
    19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    20  */
       
    21 
       
    22 #include <stdlib.h>
       
    23 #include <stdio.h>
       
    24 
       
    25 #include "gabble-error.h"
       
    26 #include "namespaces.h"
       
    27 
       
    28 #ifdef EMULATOR
       
    29 #include "libgabble_wsd_solution.h"
       
    30 
       
    31 	GET_STATIC_VAR_FROM_TLS(quark,gabble_error,GQuark)
       
    32 	#define quark (*GET_WSD_VAR_NAME(quark,gabble_error,s)())
       
    33 
       
    34 #endif
       
    35 
       
    36 #define MAX_LEGACY_ERRORS 3
       
    37 
       
    38 typedef struct {
       
    39     const gchar *name;
       
    40     const gchar *description;
       
    41     const gchar *type;
       
    42     guint specialises;
       
    43     const gchar *namespace;
       
    44     const guint16 legacy_errors[MAX_LEGACY_ERRORS];
       
    45 } XmppErrorSpec;
       
    46 
       
    47 static const XmppErrorSpec xmpp_errors[NUM_XMPP_ERRORS] =
       
    48 {
       
    49     {
       
    50       "redirect",
       
    51       "the recipient or server is redirecting requests for this information "
       
    52       "to another entity",
       
    53       "modify",
       
    54       0,
       
    55       NULL,
       
    56       { 302, 0, },
       
    57     },
       
    58 
       
    59     {
       
    60       "gone",
       
    61       "the recipient or server can no longer be contacted at this address",
       
    62       "modify",
       
    63       0,
       
    64       NULL,
       
    65       { 302, 0, },
       
    66     },
       
    67 
       
    68     {
       
    69       "bad-request",
       
    70       "the sender has sent XML that is malformed or that cannot be processed",
       
    71       "modify",
       
    72       0,
       
    73       NULL,
       
    74       { 400, 0, },
       
    75     },
       
    76     {
       
    77       "unexpected-request",
       
    78       "the recipient or server understood the request but was not expecting "
       
    79       "it at this time",
       
    80       "wait",
       
    81       0,
       
    82       NULL,
       
    83       { 400, 0, },
       
    84     },
       
    85     {
       
    86       "jid-malformed",
       
    87       "the sending entity has provided or communicated an XMPP address or "
       
    88       "aspect thereof (e.g., a resource identifier) that does not adhere "
       
    89       "to the syntax defined in Addressing Scheme (Section 3)",
       
    90       "modify",
       
    91       0,
       
    92       NULL,
       
    93       { 400, 0, },
       
    94     },
       
    95 
       
    96     {
       
    97       "not-authorized",
       
    98       "the sender must provide proper credentials before being allowed to "
       
    99       "perform the action, or has provided improper credentials",
       
   100       "auth",
       
   101       0,
       
   102       NULL,
       
   103       { 401, 0, },
       
   104     },
       
   105 
       
   106     {
       
   107       "payment-required",
       
   108       "the requesting entity is not authorized to access the requested "
       
   109       "service because payment is required",
       
   110       "auth",
       
   111       0,
       
   112       NULL,
       
   113       { 402, 0, },
       
   114     },
       
   115 
       
   116     {
       
   117       "forbidden",
       
   118       "the requesting entity does not possess the required permissions to "
       
   119       "perform the action",
       
   120       "auth",
       
   121       0,
       
   122       NULL,
       
   123       { 403, 0, },
       
   124     },
       
   125 
       
   126     {
       
   127       "item-not-found",
       
   128       "the addressed JID or item requested cannot be found",
       
   129       "cancel",
       
   130       0,
       
   131       NULL,
       
   132       { 404, 0, },
       
   133     },
       
   134     {
       
   135       "recipient-unavailable",
       
   136       "the intended recipient is temporarily unavailable",
       
   137       "wait",
       
   138       0,
       
   139       NULL,
       
   140       { 404, 0, },
       
   141     },
       
   142     {
       
   143       "remote-server-not-found",
       
   144       "a remote server or service specified as part or all of the JID of the "
       
   145       "intended recipient (or required to fulfill a request) could not be "
       
   146       "contacted within a reasonable amount of time",
       
   147       "cancel",
       
   148       0,
       
   149       NULL,
       
   150       { 404, 0, },
       
   151     },
       
   152 
       
   153     {
       
   154       "not-allowed",
       
   155       "the recipient or server does not allow any entity to perform the action",
       
   156       "cancel",
       
   157       0,
       
   158       NULL,
       
   159       { 405, 0, },
       
   160     },
       
   161 
       
   162     {
       
   163       "not-acceptable",
       
   164       "the recipient or server understands the request but is refusing to "
       
   165       "process it because it does not meet criteria defined by the recipient "
       
   166       "or server (e.g., a local policy regarding acceptable words in messages)",
       
   167       "modify",
       
   168       0,
       
   169       NULL,
       
   170       { 406, 0, },
       
   171     },
       
   172 
       
   173     {
       
   174       "registration-required",
       
   175       "the requesting entity is not authorized to access the requested service "
       
   176       "because registration is required",
       
   177       "auth",
       
   178       0,
       
   179       NULL,
       
   180       { 407, 0, },
       
   181     },
       
   182     {
       
   183       "subscription-required",
       
   184       "the requesting entity is not authorized to access the requested service "
       
   185       "because a subscription is required",
       
   186       "auth",
       
   187       0,
       
   188       NULL,
       
   189       { 407, 0, },
       
   190     },
       
   191 
       
   192     {
       
   193       "remote-server-timeout",
       
   194       "a remote server or service specified as part or all of the JID of the "
       
   195       "intended recipient (or required to fulfill a request) could not be "
       
   196       "contacted within a reasonable amount of time",
       
   197       "wait",
       
   198       0,
       
   199       NULL,
       
   200       { 408, 504, 0, },
       
   201     },
       
   202 
       
   203     {
       
   204       "conflict",
       
   205       "access cannot be granted because an existing resource or session exists "
       
   206       "with the same name or address",
       
   207       "cancel",
       
   208       0,
       
   209       NULL,
       
   210       { 409, 0, },
       
   211     },
       
   212 
       
   213     {
       
   214       "internal-server-error",
       
   215       "the server could not process the stanza because of a misconfiguration "
       
   216       "or an otherwise-undefined internal server error",
       
   217       "wait",
       
   218       0,
       
   219       NULL,
       
   220       { 500, 0, },
       
   221     },
       
   222     {
       
   223       "undefined-condition",
       
   224       "application-specific condition",
       
   225       NULL,
       
   226       0,
       
   227       NULL,
       
   228       { 500, 0, },
       
   229     },
       
   230     {
       
   231       "resource-constraint",
       
   232       "the server or recipient lacks the system resources necessary to service "
       
   233       "the request",
       
   234       "wait",
       
   235       0,
       
   236       NULL,
       
   237       { 500, 0, },
       
   238     },
       
   239 
       
   240     {
       
   241       "feature-not-implemented",
       
   242       "the feature requested is not implemented by the recipient or server and "
       
   243       "therefore cannot be processed",
       
   244       "cancel",
       
   245       0,
       
   246       NULL,
       
   247       { 501, 0, },
       
   248     },
       
   249 
       
   250     {
       
   251       "service-unavailable",
       
   252       "the server or recipient does not currently provide the requested "
       
   253       "service",
       
   254       "cancel",
       
   255       0,
       
   256       NULL,
       
   257       { 502, 503, 510, },
       
   258     },
       
   259 
       
   260     {
       
   261       "out-of-order",
       
   262       "the request cannot occur at this point in the state machine",
       
   263       "cancel",
       
   264       XMPP_ERROR_UNEXPECTED_REQUEST,
       
   265       NS_JINGLE_ERRORS,
       
   266       { 0, },
       
   267     },
       
   268 
       
   269     {
       
   270       "unknown-session",
       
   271       "the 'sid' attribute specifies a session that is unknown to the "
       
   272       "recipient",
       
   273       "cancel",
       
   274       XMPP_ERROR_BAD_REQUEST,
       
   275       NS_JINGLE_ERRORS,
       
   276       { 0, },
       
   277     },
       
   278 
       
   279     {
       
   280       "unsupported-transports",
       
   281       "the recipient does not support any of the desired content transport "
       
   282       "methods",
       
   283       "cancel",
       
   284       XMPP_ERROR_FEATURE_NOT_IMPLEMENTED,
       
   285       NS_JINGLE_ERRORS,
       
   286       { 0, },
       
   287     },
       
   288 
       
   289     {
       
   290       "unsupported-content",
       
   291       "the recipient does not support any of the desired content description"
       
   292       "formats",
       
   293       "cancel",
       
   294       XMPP_ERROR_FEATURE_NOT_IMPLEMENTED,
       
   295       NS_JINGLE_ERRORS,
       
   296       { 0, },
       
   297     },
       
   298 };
       
   299 
       
   300 GQuark
       
   301 gabble_xmpp_error_quark (void)
       
   302 {
       
   303 
       
   304 #ifndef EMULATOR
       
   305   static GQuark quark = 0;
       
   306 #endif
       
   307   
       
   308   if (!quark)
       
   309     quark = g_quark_from_static_string ("gabble-xmpp-error");
       
   310   return quark;
       
   311 }
       
   312 
       
   313 GabbleXmppError
       
   314 gabble_xmpp_error_from_node (LmMessageNode *error_node)
       
   315 {
       
   316   gint i, j;
       
   317   const gchar *error_code_str;
       
   318 
       
   319   /* First, try to look it up the modern way */
       
   320   if (error_node->children)
       
   321     {
       
   322       for (i = 0; i < NUM_XMPP_ERRORS; i++)
       
   323         {
       
   324           if (lm_message_node_get_child (error_node, xmpp_errors[i].name))
       
   325             {
       
   326               return i;
       
   327             }
       
   328         }
       
   329     }
       
   330 
       
   331   /* Ok, do it the legacy way */
       
   332   error_code_str = lm_message_node_get_attribute (error_node, "code");
       
   333   if (error_code_str)
       
   334     {
       
   335       gint error_code;
       
   336 
       
   337       error_code = atoi (error_code_str);
       
   338 
       
   339       for (i = 0; i < NUM_XMPP_ERRORS; i++)
       
   340         {
       
   341           const XmppErrorSpec *spec = &xmpp_errors[i];
       
   342 
       
   343           for (j = 0; j < MAX_LEGACY_ERRORS; j++)
       
   344             {
       
   345               gint cur_code = spec->legacy_errors[j];
       
   346               if (cur_code == 0)
       
   347                 break;
       
   348 
       
   349               if (cur_code == error_code)
       
   350                 return i;
       
   351             }
       
   352         }
       
   353     }
       
   354 
       
   355   return INVALID_XMPP_ERROR;
       
   356 }
       
   357 
       
   358 GError *
       
   359 gabble_xmpp_error_to_g_error (GabbleXmppError error)
       
   360 {
       
   361   if (error >= NUM_XMPP_ERRORS)
       
   362     return NULL;
       
   363 
       
   364   return g_error_new (GABBLE_XMPP_ERROR,
       
   365                       error,
       
   366                       xmpp_errors[error].description);
       
   367 }
       
   368 
       
   369 /*
       
   370  * See RFC 3920: 4.7 Stream Errors, 9.3 Stanza Errors.
       
   371  */
       
   372 LmMessageNode *
       
   373 gabble_xmpp_error_to_node (GabbleXmppError error,
       
   374                            LmMessageNode *parent_node,
       
   375                            const gchar *errmsg)
       
   376 {
       
   377   const XmppErrorSpec *spec, *extra;
       
   378   LmMessageNode *error_node, *node;
       
   379   gchar str[6];
       
   380 
       
   381   if (error >= NUM_XMPP_ERRORS)
       
   382     return NULL;
       
   383 
       
   384   if (xmpp_errors[error].specialises)
       
   385     {
       
   386       extra = &xmpp_errors[error];
       
   387       spec = &xmpp_errors[extra->specialises];
       
   388     }
       
   389   else
       
   390     {
       
   391       extra = NULL;
       
   392       spec = &xmpp_errors[error];
       
   393     }
       
   394 
       
   395   error_node = lm_message_node_add_child (parent_node, "error", NULL);
       
   396 
       
   397   sprintf (str, "%d", spec->legacy_errors[0]);
       
   398   lm_message_node_set_attribute (error_node, "code", str);
       
   399 
       
   400   if (spec->type)
       
   401     {
       
   402       lm_message_node_set_attribute (error_node, "type", spec->type);
       
   403     }
       
   404 
       
   405   node = lm_message_node_add_child (error_node, spec->name, NULL);
       
   406   lm_message_node_set_attribute (node, "xmlns", NS_XMPP_STANZAS);
       
   407 
       
   408   if (extra != NULL)
       
   409     {
       
   410       node = lm_message_node_add_child (error_node, extra->name, NULL);
       
   411       lm_message_node_set_attribute (node, "xmlns", extra->namespace);
       
   412     }
       
   413 
       
   414   if (NULL != errmsg)
       
   415     lm_message_node_add_child (error_node, "text", errmsg);
       
   416 
       
   417   return error_node;
       
   418 }
       
   419 
       
   420 const gchar *
       
   421 gabble_xmpp_error_string (GabbleXmppError error)
       
   422 {
       
   423   if (error < NUM_XMPP_ERRORS)
       
   424     return xmpp_errors[error].name;
       
   425   else
       
   426     return NULL;
       
   427 }
       
   428 
       
   429 const gchar *
       
   430 gabble_xmpp_error_description (GabbleXmppError error)
       
   431 {
       
   432   if (error < NUM_XMPP_ERRORS)
       
   433     return xmpp_errors[error].description;
       
   434   else
       
   435     return NULL;
       
   436 }
       
   437