blob: e2ef737c401a04d538703857ef640f771e90e67c [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 "qpid/dispatch/amqp.h"
#include <errno.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
const char * const QD_MA_PREFIX = "x-opt-qd.";
const char * const QD_MA_INGRESS = "x-opt-qd.ingress";
const uint8_t * const QD_MA_INGRESS_ENCODED = (uint8_t*) "\xA3\x10""x-opt-qd.ingress";
const char * const QD_MA_TRACE = "x-opt-qd.trace";
const uint8_t * const QD_MA_TRACE_ENCODED = (uint8_t*) "\xA3\x0E""x-opt-qd.trace";
const char * const QD_MA_TO = "x-opt-qd.to";
const uint8_t * const QD_MA_TO_ENCODED = (uint8_t*) "\xA3\x0B""x-opt-qd.to";
const char * const QD_MA_PHASE = "x-opt-qd.phase";
const uint8_t * const QD_MA_PHASE_ENCODED = (uint8_t*) "\xA3\x0E""x-opt-qd.phase";
const char * const QD_MA_STREAM = "x-opt-qd.stream";
const uint8_t * const QD_MA_STREAM_ENCODED = (uint8_t*) "\xA3\x0F""x-opt-qd.stream";
const char * const QD_MA_CLASS = "x-opt-qd.class"; // deprecated
const char * const QD_CAPABILITY_ROUTER_CONTROL = "qd.router";
const char * const QD_CAPABILITY_ROUTER_DATA = "qd.router-data";
const char * const QD_CAPABILITY_EDGE_DOWNLINK = "qd.router-edge-downlink";
const char * const QD_CAPABILITY_WAYPOINT_DEFAULT = "qd.waypoint";
const char * const QD_CAPABILITY_WAYPOINT1 = "qd.waypoint.1";
const char * const QD_CAPABILITY_WAYPOINT2 = "qd.waypoint.2";
const char * const QD_CAPABILITY_WAYPOINT3 = "qd.waypoint.3";
const char * const QD_CAPABILITY_WAYPOINT4 = "qd.waypoint.4";
const char * const QD_CAPABILITY_WAYPOINT5 = "qd.waypoint.5";
const char * const QD_CAPABILITY_WAYPOINT6 = "qd.waypoint.6";
const char * const QD_CAPABILITY_WAYPOINT7 = "qd.waypoint.7";
const char * const QD_CAPABILITY_WAYPOINT8 = "qd.waypoint.8";
const char * const QD_CAPABILITY_WAYPOINT9 = "qd.waypoint.9";
const char * const QD_CAPABILITY_FALLBACK = "qd.fallback";
const char * const QD_CAPABILITY_ANONYMOUS_RELAY = "ANONYMOUS-RELAY";
const char * const QD_CAPABILITY_STREAMING_LINKS = "qd.streaming-links";
const char * const QD_DYNAMIC_NODE_PROPERTY_ADDRESS = "x-opt-qd.address";
const char * const QD_CONNECTION_PROPERTY_PRODUCT_KEY = "product";
const char * const QD_CONNECTION_PROPERTY_PRODUCT_VALUE = "qpid-dispatch-router";
const char * const QD_CONNECTION_PROPERTY_VERSION_KEY = "version";
const char * const QD_CONNECTION_PROPERTY_COST_KEY = "qd.inter-router-cost";
const char * const QD_CONNECTION_PROPERTY_CONN_ID = "qd.conn-id";
const char * const QD_CONNECTION_PROPERTY_FAILOVER_LIST_KEY = "failover-server-list";
const char * const QD_CONNECTION_PROPERTY_FAILOVER_NETHOST_KEY = "network-host";
const char * const QD_CONNECTION_PROPERTY_FAILOVER_PORT_KEY = "port";
const char * const QD_CONNECTION_PROPERTY_FAILOVER_SCHEME_KEY = "scheme";
const char * const QD_CONNECTION_PROPERTY_FAILOVER_HOSTNAME_KEY = "hostname";
const char * const QD_CONNECTION_PROPERTY_ADAPTOR_KEY = "qd.adaptor";
const char * const QD_CONNECTION_PROPERTY_ANNOTATIONS_VERSION_KEY = "qd.annotations-version";
const char * const QD_TERMINUS_EDGE_ADDRESS_TRACKING = "_$qd.edge_addr_tracking";
const char * const QD_TERMINUS_ADDRESS_LOOKUP = "_$qd.addr_lookup";
const char * const QD_TERMINUS_HEARTBEAT = "_$qd.edge_heartbeat";
const qd_amqp_error_t QD_AMQP_OK = { 200, "OK" };
const qd_amqp_error_t QD_AMQP_CREATED = { 201, "Created" };
const qd_amqp_error_t QD_AMQP_NO_CONTENT = { 204, "No Content" }; // This is the response code if the delete of a manageable entity was successful.
const qd_amqp_error_t QD_AMQP_BAD_REQUEST = { 400, "Bad Request" };
const qd_amqp_error_t QD_AMQP_FORBIDDEN = { 403, "Forbidden" };
const qd_amqp_error_t QD_AMQP_NOT_FOUND = { 404, "Not Found" };
const qd_amqp_error_t QD_AMQP_NOT_IMPLEMENTED = { 501, "Not Implemented"};
const char * const QD_AMQP_COND_INTERNAL_ERROR = "amqp:internal-error";
const char * const QD_AMQP_COND_NOT_FOUND = "amqp:not-found";
const char * const QD_AMQP_COND_UNAUTHORIZED_ACCESS = "amqp:unauthorized-access";
const char * const QD_AMQP_COND_DECODE_ERROR = "amqp:decode-error";
const char * const QD_AMQP_COND_RESOURCE_LIMIT_EXCEEDED = "amqp:resource-limit-exceeded";
const char * const QD_AMQP_COND_NOT_ALLOWED = "amqp:not-allowed";
const char * const QD_AMQP_COND_INVALID_FIELD = "amqp:invalid-field";
const char * const QD_AMQP_COND_NOT_IMPLEMENTED = "amqp:not-implemented";
const char * const QD_AMQP_COND_RESOURCE_LOCKED = "amqp:resource-locked";
const char * const QD_AMQP_COND_PRECONDITION_FAILED = "amqp:precondition-failed";
const char * const QD_AMQP_COND_RESOURCE_DELETED = "amqp:resource-deleted";
const char * const QD_AMQP_COND_ILLEGAL_STATE = "amqp:illegal-state";
const char * const QD_AMQP_COND_FRAME_SIZE_TOO_SMALL = "amqp:frame-size-too-small";
const char * const QD_AMQP_COND_CONNECTION_FORCED = "amqp:connection:forced";
const char * const QD_AMQP_COND_MESSAGE_SIZE_EXCEEDED = "amqp:link:message-size-exceeded";
const char * const QD_AMQP_PORT_STR = "5672";
const char * const QD_AMQPS_PORT_STR = "5671";
const char * const QD_AMQP_DFLT_PROTO = "tcp";
/// Wrapper for getservbyname/getservbyname_r macOS compatibility.
/// Needed because getservbyname is thread safe on macOS, and getservbyname_r is not defined there.
static inline int qd_getservbyname(const char *name, const char *proto);
#ifdef __APPLE__
static inline int qd_getservbyname(const char *name, const char *proto) {
struct servent *serv_info = getservbyname(name, proto);
if (serv_info) {
return ntohs(serv_info->s_port);
} else {
return -1;
}
}
#else
static inline int qd_getservbyname(const char *name, const char *proto) {
struct servent serv_info;
struct servent *serv_info_res;
enum { buf_len = 4096 };
char buf[buf_len];
int r = getservbyname_r(name, proto, &serv_info, buf, buf_len, &serv_info_res);
if (r == 0 && serv_info_res != NULL) {
return ntohs(serv_info.s_port);
} else {
return -1;
}
}
#endif
int qd_port_int(const char *port_str) {
char *endptr;
unsigned long n;
// empty string?
if (*port_str == '\0') return -1;
// digits from beginning to end?
errno = 0;
n = strtoul(port_str, &endptr, 10);
if (*endptr == '\0') {
if (!errno && n >= 0 && n <= 0xFFFF)
return n;
else
return -1;
}
// digits halfway?
if (endptr != port_str) return -1;
// resolve service port
const int r = qd_getservbyname(port_str, QD_AMQP_DFLT_PROTO);
if (r != -1) return r;
// amqp(s) not defined in /etc/services?
if (!strcmp(port_str, "amqp")) return QD_AMQP_PORT_INT;
if (!strcmp(port_str, "amqps")) return QD_AMQPS_PORT_INT;
return -1;
}