blob: ff906d41cab1c0398857c780d4376d12b13dc043 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "router_core_private.h"
#include <stdio.h>
// The AMQP 'error' type
//
// The AMQP standard defines an 'error' type for expressing various formal
// errors. Corresponds to a Proton Condition (pn_condition_t) that is associate
// with the Proton Disposition (pn_disposition_t).
//
struct qdr_error_t {
qdr_field_t *name; // symbol, e.g. "amqp:connection:forced"
qdr_field_t *description; // string
pn_data_t *info; // symbol-keyed map
};
ALLOC_DECLARE(qdr_error_t);
ALLOC_DEFINE(qdr_error_t);
qdr_error_t *qdr_error_from_pn(pn_condition_t *pn)
{
if (!pn)
return 0;
qdr_error_t *error = 0;
const char *name = pn_condition_get_name(pn);
const char *desc = pn_condition_get_description(pn);
pn_data_t *info = pn_condition_info(pn);
const bool info_ok = (info && pn_data_size(info) > 0);
if ((name && *name) || (desc && *desc) || info_ok) {
error = new_qdr_error_t();
ZERO(error);
if (name && *name)
error->name = qdr_field(name);
if (desc && *desc)
error->description = qdr_field(desc);
if (info_ok) {
error->info = pn_data(0);
pn_data_copy(error->info, info);
}
}
return error;
}
qdr_error_t *qdr_error(const char *name, const char *description)
{
qdr_error_t *error = new_qdr_error_t();
error->name = qdr_field(name);
error->description = qdr_field(description);
error->info = 0;
return error;
}
void qdr_error_free(qdr_error_t *error)
{
if (error == 0)
return;
qdr_field_free(error->name);
qdr_field_free(error->description);
if (error->info)
pn_data_free(error->info);
free_qdr_error_t(error);
}
void qdr_error_copy(qdr_error_t *from, pn_condition_t *to)
{
if (from == 0)
return;
if (from->name) {
unsigned char *name = qd_iterator_copy(from->name->iterator);
pn_condition_set_name(to, (char*) name);
free(name);
}
if (from->description) {
unsigned char *desc = qd_iterator_copy(from->description->iterator);
pn_condition_set_description(to, (char*) desc);
free(desc);
}
if (from->info)
pn_data_copy(pn_condition_info(to), from->info);
}
char *qdr_error_description(const qdr_error_t *err)
{
if (!err || !err->description || !err->description->iterator)
return 0;
int length = qd_iterator_length(err->description->iterator);
char *text = (char*) malloc(length + 1);
qd_iterator_ncopy(err->description->iterator, (unsigned char*) text, length);
text[length] = '\0';
return text;
}
char *qdr_error_name(const qdr_error_t *err)
{
if (!err || !err->name || !err->name->iterator)
return 0;
int length = qd_iterator_length(err->name->iterator);
char *text = (char*) malloc(length + 1);
qd_iterator_ncopy(err->name->iterator, (unsigned char*) text, length);
text[length] = '\0';
return text;
}
pn_data_t *qdr_error_info(const qdr_error_t *err)
{
if (err == 0)
return 0;
return err->info;
}