Author: rhs
Date: Mon May 13 13:00:04 2013
New Revision: 1481834
URL: http://svn.apache.org/r1481834
Log:
PROTON-299: added address rewrite API to control what goes into the to field on
the wire, added default rewrite rules to remove credentials from URLs
Added:
qpid/proton/trunk/proton-c/src/messenger/transform.c
qpid/proton/trunk/proton-c/src/messenger/transform.h
Modified:
qpid/proton/trunk/proton-c/CMakeLists.txt
qpid/proton/trunk/proton-c/bindings/python/proton.py
qpid/proton/trunk/proton-c/include/proton/messenger.h
qpid/proton/trunk/proton-c/include/proton/object.h
qpid/proton/trunk/proton-c/src/messenger/messenger.c
qpid/proton/trunk/proton-c/src/object/object.c
qpid/proton/trunk/proton-c/src/tests/object.c
qpid/proton/trunk/proton-j/proton-api/src/main/resources/proton.py
qpid/proton/trunk/tests/python/proton_tests/message.py
qpid/proton/trunk/tests/python/proton_tests/messenger.py
Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
+++ qpid/proton/trunk/proton-c/CMakeLists.txt Mon May 13 13:00:04 2013
@@ -246,6 +246,7 @@ set (qpid-proton-core
src/messenger/messenger.c
src/messenger/store.c
+ src/messenger/transform.c
${CMAKE_CURRENT_BINARY_DIR}/encodings.h
${CMAKE_CURRENT_BINARY_DIR}/protocol.h
Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
+++ qpid/proton/trunk/proton-c/bindings/python/proton.py Mon May 13 13:00:04
2013
@@ -492,6 +492,9 @@ send. Defaults to zero.
def route(self, pattern, address):
self._check(pn_messenger_route(self._mng, pattern, address))
+ def rewrite(self, pattern, address):
+ self._check(pn_messenger_rewrite(self._mng, pattern, address))
+
class Message(object):
"""
The L{Message} class is a mutable holder of message content.
@@ -549,9 +552,8 @@ class Message(object):
props.clear()
if self.properties is not None:
props.put_object(self.properties)
+ body.clear()
if self.body is not None:
- # XXX: move this out when load/save are gone
- body.clear()
body.put_object(self.body)
def _post_decode(self):
Modified: qpid/proton/trunk/proton-c/include/proton/messenger.h
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/messenger.h?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/messenger.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/messenger.h Mon May 13 13:00:04
2013
@@ -452,6 +452,9 @@ PN_EXTERN int pn_messenger_incoming(pn_m
PN_EXTERN int pn_messenger_route(pn_messenger_t *messenger, const char
*pattern,
const char *address);
+PN_EXTERN int pn_messenger_rewrite(pn_messenger_t *messenger, const char
*pattern,
+ const char *address);
+
#ifdef __cplusplus
}
#endif
Modified: qpid/proton/trunk/proton-c/include/proton/object.h
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/object.h?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/object.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/object.h Mon May 13 13:00:04 2013
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <sys/types.h>
#include <proton/import_export.h>
@@ -86,7 +87,15 @@ PN_EXTERN const char *pn_string_get(pn_s
PN_EXTERN size_t pn_string_size(pn_string_t *string);
PN_EXTERN int pn_string_set(pn_string_t *string, const char *bytes);
PN_EXTERN int pn_string_setn(pn_string_t *string, const char *bytes, size_t n);
+PN_EXTERN ssize_t pn_string_put(pn_string_t *string, char *dst);
PN_EXTERN void pn_string_clear(pn_string_t *string);
+PN_EXTERN int pn_string_format(pn_string_t *string, const char *format, ...)
+ __attribute__ ((format (printf, 2, 3)));
+PN_EXTERN char *pn_string_buffer(pn_string_t *string);
+PN_EXTERN size_t pn_string_capacity(pn_string_t *string);
+PN_EXTERN int pn_string_resize(pn_string_t *string, size_t size);
+PN_EXTERN int pn_string_copy(pn_string_t *string, pn_string_t *src);
+
#ifdef __cplusplus
}
Modified: qpid/proton/trunk/proton-c/src/messenger/messenger.c
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/messenger/messenger.c?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/messenger/messenger.c (original)
+++ qpid/proton/trunk/proton-c/src/messenger/messenger.c Mon May 13 13:00:04
2013
@@ -23,6 +23,7 @@
#include <proton/driver.h>
#include <proton/util.h>
#include <proton/ssl.h>
+#include <proton/object.h>
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
@@ -32,23 +33,10 @@
#include "../platform.h"
#include "../platform_fmt.h"
#include "store.h"
+#include "transform.h"
typedef struct {
- const char *start;
- size_t size;
-} pn_group_t;
-
-#define MAX_GROUP (64)
-
-typedef struct {
- size_t groups;
- pn_group_t group[MAX_GROUP];
-} pn_matcher_t;
-
-#define PN_MAX_ADDR (1024)
-
-typedef struct {
- char text[PN_MAX_ADDR + 1];
+ pn_string_t *text;
bool passive;
char *scheme;
char *user;
@@ -58,18 +46,6 @@ typedef struct {
char *name;
} pn_address_t;
-typedef struct pn_route_t pn_route_t;
-
-#define PN_MAX_PATTERN (255)
-#define PN_MAX_ROUTE (255)
-
-struct pn_route_t {
- char pattern[PN_MAX_PATTERN + 1];
- char address[PN_MAX_ROUTE + 1];
- pn_route_t *next;
-};
-
-
struct pn_messenger_t {
char *name;
char *certificate;
@@ -90,11 +66,13 @@ struct pn_messenger_t {
size_t sub_count;
pn_subscription_t *incoming_subscription;
pn_error_t *error;
- pn_route_t *routes;
- pn_matcher_t matcher;
+ pn_transform_t *routes;
+ pn_transform_t *rewrites;
pn_address_t address;
pn_tracker_t outgoing_tracker;
pn_tracker_t incoming_tracker;
+ pn_string_t *original;
+ pn_string_t *rewritten;
};
struct pn_subscription_t {
@@ -217,9 +195,13 @@ pn_messenger_t *pn_messenger(const char
m->sub_count = 0;
m->incoming_subscription = NULL;
m->error = pn_error();
- m->routes = NULL;
+ m->routes = pn_transform();
+ m->rewrites = pn_transform();
m->outgoing_tracker = 0;
m->incoming_tracker = 0;
+ m->address.text = pn_string(NULL);
+ m->original = pn_string(NULL);
+ m->rewritten = pn_string(NULL);
}
return m;
@@ -302,6 +284,9 @@ static void pni_driver_reclaim(pn_driver
void pn_messenger_free(pn_messenger_t *messenger)
{
if (messenger) {
+ pn_free(messenger->rewritten);
+ pn_free(messenger->original);
+ pn_free(messenger->address.text);
free(messenger->name);
free(messenger->certificate);
free(messenger->private_key);
@@ -316,12 +301,8 @@ void pn_messenger_free(pn_messenger_t *m
free(messenger->subscriptions[i].scheme);
}
free(messenger->subscriptions);
- pn_route_t *route = messenger->routes;
- while (route) {
- pn_route_t *next = route->next;
- free(route);
- route = next;
- }
+ pn_free(messenger->rewrites);
+ pn_free(messenger->routes);
free(messenger);
}
}
@@ -750,111 +731,6 @@ static const char *default_port(const ch
return "5672";
}
-static void pni_sub(pn_matcher_t *matcher, size_t group, const char *text,
size_t matched)
-{
- if (group > matcher->groups) {
- matcher->groups = group;
- }
- matcher->group[group].start = text - matched;
- matcher->group[group].size = matched;
-}
-
-static bool pni_match_r(pn_matcher_t *matcher, const char *pattern, const char
*text, size_t group, size_t matched)
-{
- bool match;
-
- char p = *pattern;
- char c = *text;
-
- switch (p) {
- case '\0': return c == '\0';
- case '%':
- case '*':
- switch (c) {
- case '\0':
- match = pni_match_r(matcher, pattern + 1, text, group + 1, 0);
- if (match) pni_sub(matcher, group, text, matched);
- return match;
- case '/':
- if (p == '%') {
- match = pni_match_r(matcher, pattern + 1, text, group + 1, 0);
- if (match) pni_sub(matcher, group, text, matched);
- return match;
- }
- default:
- match = pni_match_r(matcher, pattern, text + 1, group, matched + 1);
- if (!match) {
- match = pni_match_r(matcher, pattern + 1, text, group + 1, 0);
- if (match) pni_sub(matcher, group, text, matched);
- }
- return match;
- }
- default:
- return c == p && pni_match_r(matcher, pattern + 1, text + 1, group, 0);
- }
-}
-
-static bool pni_match(pn_matcher_t *matcher, const char *pattern, const char
*text)
-{
- matcher->groups = 0;
- if (pni_match_r(matcher, pattern, text, 1, 0)) {
- matcher->group[0].start = text;
- matcher->group[0].size = strlen(text);
- return true;
- } else {
- matcher->groups = 0;
- return false;
- }
-}
-
-static size_t pni_substitute(pn_matcher_t *matcher, const char *pattern, char
*dest, size_t limit)
-{
- size_t result = 0;
-
- while (*pattern) {
- switch (*pattern) {
- case '$':
- pattern++;
- if (*pattern == '$') {
- if (result < limit) {
- *dest++ = *pattern++;
- }
- result++;
- } else {
- size_t idx = 0;
- while (isdigit(*pattern)) {
- idx *= 10;
- idx += *pattern++ - '0';
- }
-
- if (idx <= matcher->groups) {
- pn_group_t *group = &matcher->group[idx];
- for (size_t i = 0; i < group->size; i++) {
- if (result < limit) {
- *dest++ = group->start[i];
- }
- result++;
- }
- }
- }
- break;
- default:
- if (result < limit) {
- *dest++ = *pattern++;
- }
- result++;
- break;
- }
- }
-
- if (result < limit) {
- *dest = '\0';
- }
- result++;
-
- return result;
-}
-
static void pni_parse(pn_address_t *address)
{
address->passive = false;
@@ -864,8 +740,8 @@ static void pni_parse(pn_address_t *addr
address->host = NULL;
address->port = NULL;
address->name = NULL;
- parse_url(address->text, &address->scheme, &address->user, &address->pass,
- &address->host, &address->port, &address->name);
+ parse_url(pn_string_buffer(address->text), &address->scheme, &address->user,
+ &address->pass, &address->host, &address->port, &address->name);
if (address->host[0] == '~') {
address->passive = true;
address->host++;
@@ -875,23 +751,9 @@ static void pni_parse(pn_address_t *addr
static int pni_route(pn_messenger_t *messenger, const char *address)
{
pn_address_t *addr = &messenger->address;
- pn_route_t *route = messenger->routes;
- while (route) {
- if (pni_match(&messenger->matcher, route->pattern, address)) {
- size_t n = pni_substitute(&messenger->matcher, route->address,
addr->text, PN_MAX_ADDR);
- if (n < PN_MAX_ADDR) {
- pni_parse(addr);
- return 0;
- } else {
- return pn_error_format(messenger->error, PN_ERR,
- "routing address exceeded maximum length: (%s
-> %s)",
- route->pattern, route->address);
- }
- }
- route = route->next;
- }
-
- strcpy(addr->text, address);
+ int err = pn_transform_apply(messenger->routes, address, addr->text);
+ if (err) return pn_error_format(messenger->error, PN_ERR,
+ "transformation error");
pni_parse(addr);
return 0;
}
@@ -1171,6 +1033,48 @@ int pni_pump_out(pn_messenger_t *messeng
}
}
+static void pni_default_rewrite(pn_messenger_t *messenger, const char *address,
+ pn_string_t *dst)
+{
+ pn_address_t *addr = &messenger->address;
+ if (address && strstr(address, "@")) {
+ int err = pn_string_set(addr->text, address);
+ assert(!err);
+ pni_parse(addr);
+ if (addr->user || addr->pass)
+ {
+ pn_string_format(messenger->rewritten, "%s%s%s%s%s%s%s",
+ addr->scheme ? addr->scheme : "",
+ addr->scheme ? "://" : "",
+ addr->host,
+ addr->port ? ":" : "",
+ addr->port ? addr->port : "",
+ addr->name ? "/" : "",
+ addr->name ? addr->name : "");
+ }
+ }
+}
+
+static void pni_rewrite(pn_messenger_t *messenger, pn_message_t *msg)
+{
+ const char *address = pn_message_get_address(msg);
+ pn_string_set(messenger->original, address);
+
+ int err = pn_transform_apply(messenger->rewrites, address,
+ messenger->rewritten);
+ assert(!err);
+ if (!pn_transform_matched(messenger->rewrites)) {
+ pni_default_rewrite(messenger, pn_string_get(messenger->rewritten),
+ messenger->rewritten);
+ }
+ pn_message_set_address(msg, pn_string_get(messenger->rewritten));
+}
+
+static void pni_restore(pn_messenger_t *messenger, pn_message_t *msg)
+{
+ pn_message_set_address(msg, pn_string_get(messenger->original));
+}
+
int pn_messenger_put(pn_messenger_t *messenger, pn_message_t *msg)
{
if (!messenger) return PN_ARG_ERR;
@@ -1185,6 +1089,7 @@ int pn_messenger_put(pn_messenger_t *mes
messenger->outgoing_tracker = pn_tracker(OUTGOING, pni_entry_track(entry));
pn_buffer_t *buf = pni_entry_bytes(entry);
+ pni_rewrite(messenger, msg);
while (true) {
char *encoded = pn_buffer_bytes(buf).start;
size_t size = pn_buffer_capacity(buf);
@@ -1193,12 +1098,15 @@ int pn_messenger_put(pn_messenger_t *mes
err = pn_buffer_ensure(buf, 2*pn_buffer_capacity(buf));
if (err) {
pni_entry_free(entry);
+ pni_restore(messenger, msg);
return pn_error_format(messenger->error, err, "put: error growing
buffer");
}
} else if (err) {
+ pni_restore(messenger, msg);
return pn_error_format(messenger->error, err, "encode error: %s",
pn_message_error(msg));
} else {
+ pni_restore(messenger, msg);
pn_buffer_append(buf, encoded, size); // XXX
pn_link_t *sender = pn_messenger_target(messenger, address);
if (!sender) return 0;
@@ -1442,25 +1350,12 @@ int pn_messenger_incoming(pn_messenger_t
int pn_messenger_route(pn_messenger_t *messenger, const char *pattern, const
char *address)
{
- if (strlen(pattern) > PN_MAX_PATTERN || strlen(address) > PN_MAX_ROUTE) {
- return PN_ERR;
- }
- pn_route_t *route = (pn_route_t *) malloc(sizeof(pn_route_t));
- if (!route) return PN_ERR;
-
- strcpy(route->pattern, pattern);
- strcpy(route->address, address);
- route->next = NULL;
-
- pn_route_t *tail = messenger->routes;
- if (!tail) {
- messenger->routes = route;
- } else {
- while (tail->next) {
- tail = tail->next;
- }
- tail->next = route;
- }
+ pn_transform_rule(messenger->routes, pattern, address);
+ return 0;
+}
+int pn_messenger_rewrite(pn_messenger_t *messenger, const char *pattern, const
char *address)
+{
+ pn_transform_rule(messenger->rewrites, pattern, address);
return 0;
}
Added: qpid/proton/trunk/proton-c/src/messenger/transform.c
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/messenger/transform.c?rev=1481834&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/src/messenger/transform.c (added)
+++ qpid/proton/trunk/proton-c/src/messenger/transform.c Mon May 13 13:00:04
2013
@@ -0,0 +1,230 @@
+/*
+ *
+ * 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 <proton/object.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "transform.h"
+
+typedef struct {
+ const char *start;
+ size_t size;
+} pn_group_t;
+
+#define MAX_GROUP (64)
+
+typedef struct {
+ size_t groups;
+ pn_group_t group[MAX_GROUP];
+} pn_matcher_t;
+
+typedef struct {
+ pn_string_t *pattern;
+ pn_string_t *substitution;
+} pn_rule_t;
+
+struct pn_transform_t {
+ pn_list_t *rules;
+ pn_matcher_t matcher;
+ bool matched;
+};
+
+static void pn_rule_finalize(void *object)
+{
+ pn_rule_t *rule = (pn_rule_t *) object;
+ pn_free(rule->pattern);
+ pn_free(rule->substitution);
+}
+
+pn_rule_t *pn_rule(const char *pattern, const char *substitution)
+{
+ static pn_class_t clazz = {pn_rule_finalize};
+ pn_rule_t *rule = (pn_rule_t *) pn_new(sizeof(pn_rule_t), &clazz);
+ rule->pattern = pn_string(pattern);
+ rule->substitution = pn_string(substitution);
+ return rule;
+}
+
+static void pn_transform_finalize(void *object)
+{
+ pn_transform_t *transform = (pn_transform_t *) object;
+ pn_free(transform->rules);
+}
+
+pn_transform_t *pn_transform()
+{
+ static pn_class_t clazz = {pn_transform_finalize};
+ pn_transform_t *transform = (pn_transform_t *)
pn_new(sizeof(pn_transform_t), &clazz);
+ transform->rules = pn_list(0, PN_REFCOUNT);
+ transform->matched = false;
+ return transform;
+}
+
+void pn_transform_rule(pn_transform_t *transform, const char *pattern,
+ const char *substitution)
+{
+ assert(transform);
+ pn_rule_t *rule = pn_rule(pattern, substitution);
+ pn_list_add(transform->rules, rule);
+ pn_decref(rule);
+}
+
+static void pni_sub(pn_matcher_t *matcher, size_t group, const char *text,
size_t matched)
+{
+ if (group > matcher->groups) {
+ matcher->groups = group;
+ }
+ matcher->group[group].start = text - matched;
+ matcher->group[group].size = matched;
+}
+
+static bool pni_match_r(pn_matcher_t *matcher, const char *pattern, const char
*text, size_t group, size_t matched)
+{
+ bool match;
+
+ char p = *pattern;
+ char c = *text;
+
+ switch (p) {
+ case '\0': return c == '\0';
+ case '%':
+ case '*':
+ switch (c) {
+ case '\0':
+ match = pni_match_r(matcher, pattern + 1, text, group + 1, 0);
+ if (match) pni_sub(matcher, group, text, matched);
+ return match;
+ case '/':
+ if (p == '%') {
+ match = pni_match_r(matcher, pattern + 1, text, group + 1, 0);
+ if (match) pni_sub(matcher, group, text, matched);
+ return match;
+ }
+ default:
+ match = pni_match_r(matcher, pattern, text + 1, group, matched + 1);
+ if (!match) {
+ match = pni_match_r(matcher, pattern + 1, text, group + 1, 0);
+ if (match) pni_sub(matcher, group, text, matched);
+ }
+ return match;
+ }
+ default:
+ return c == p && pni_match_r(matcher, pattern + 1, text + 1, group, 0);
+ }
+}
+
+static bool pni_match(pn_matcher_t *matcher, const char *pattern, const char
*text)
+{
+ matcher->groups = 0;
+ if (pni_match_r(matcher, pattern, text, 1, 0)) {
+ matcher->group[0].start = text;
+ matcher->group[0].size = strlen(text);
+ return true;
+ } else {
+ matcher->groups = 0;
+ return false;
+ }
+}
+
+static size_t pni_substitute(pn_matcher_t *matcher, const char *pattern, char
*dest, size_t limit)
+{
+ size_t result = 0;
+
+ while (*pattern) {
+ switch (*pattern) {
+ case '$':
+ pattern++;
+ if (*pattern == '$') {
+ if (result < limit) {
+ *dest++ = *pattern;
+ }
+ pattern++;
+ result++;
+ } else {
+ size_t idx = 0;
+ while (isdigit(*pattern)) {
+ idx *= 10;
+ idx += *pattern++ - '0';
+ }
+
+ if (idx <= matcher->groups) {
+ pn_group_t *group = &matcher->group[idx];
+ for (size_t i = 0; i < group->size; i++) {
+ if (result < limit) {
+ *dest++ = group->start[i];
+ }
+ result++;
+ }
+ }
+ }
+ break;
+ default:
+ if (result < limit) {
+ *dest++ = *pattern;
+ }
+ pattern++;
+ result++;
+ break;
+ }
+ }
+
+ if (result < limit) {
+ *dest = '\0';
+ }
+
+ return result;
+}
+
+int pn_transform_apply(pn_transform_t *transform, const char *src,
+ pn_string_t *dst)
+{
+ for (size_t i = 0; i < pn_list_size(transform->rules); i++)
+ {
+ pn_rule_t *rule = (pn_rule_t *) pn_list_get(transform->rules, i);
+ if (pni_match(&transform->matcher, pn_string_get(rule->pattern), src)) {
+ transform->matched = true;
+ if (!pn_string_get(rule->substitution)) {
+ return pn_string_set(dst, NULL);
+ }
+
+ while (true) {
+ size_t capacity = pn_string_capacity(dst);
+ size_t n = pni_substitute(&transform->matcher,
+ pn_string_get(rule->substitution),
+ pn_string_buffer(dst), capacity);
+ int err = pn_string_resize(dst, n);
+ if (err) return err;
+ if (n <= capacity) {
+ return 0;
+ }
+ }
+ }
+ }
+
+ transform->matched = false;
+ return pn_string_set(dst, src);
+}
+
+bool pn_transform_matched(pn_transform_t *transform)
+{
+ return transform->matched;
+}
Added: qpid/proton/trunk/proton-c/src/messenger/transform.h
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/messenger/transform.h?rev=1481834&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/src/messenger/transform.h (added)
+++ qpid/proton/trunk/proton-c/src/messenger/transform.h Mon May 13 13:00:04
2013
@@ -0,0 +1,37 @@
+#ifndef _PROTON_TRANSFORM_H
+#define _PROTON_TRANSFORM_H 1
+
+/*
+ *
+ * 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 <proton/buffer.h>
+
+typedef struct pn_transform_t pn_transform_t;
+
+pn_transform_t *pn_transform();
+void pn_transform_rule(pn_transform_t *transform, const char *pattern,
+ const char *substitution);
+int pn_transform_apply(pn_transform_t *transform, const char *src,
+ pn_string_t *dest);
+bool pn_transform_matched(pn_transform_t *transform);
+
+
+#endif /* transform.h */
Modified: qpid/proton/trunk/proton-c/src/object/object.c
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/object/object.c?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/object/object.c (original)
+++ qpid/proton/trunk/proton-c/src/object/object.c Mon May 13 13:00:04 2013
@@ -21,7 +21,7 @@
#include <proton/error.h>
#include <proton/object.h>
-#include <sys/types.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@@ -585,10 +585,10 @@ int pn_string_set(pn_string_t *string, c
return pn_string_setn(string, bytes, bytes ? strlen(bytes) : 0);
}
-int pn_string_setn(pn_string_t *string, const char *bytes, size_t n)
+static int pn_string_grow(pn_string_t *string, size_t capacity)
{
bool grow = false;
- while (string->capacity < (n*sizeof(char) + 1)) {
+ while (string->capacity < (capacity*sizeof(char) + 1)) {
string->capacity *= 2;
grow = true;
}
@@ -602,6 +602,14 @@ int pn_string_setn(pn_string_t *string,
}
}
+ return 0;
+}
+
+int pn_string_setn(pn_string_t *string, const char *bytes, size_t n)
+{
+ int err = pn_string_grow(string, n);
+ if (err) return err;
+
if (bytes) {
memcpy(string->bytes, bytes, n*sizeof(char));
string->bytes[n] = '\0';
@@ -613,7 +621,66 @@ int pn_string_setn(pn_string_t *string,
return 0;
}
+ssize_t pn_string_put(pn_string_t *string, char *dst)
+{
+ assert(string);
+ assert(dst);
+
+ if (string->size != PNI_NULL_SIZE) {
+ memcpy(dst, string->bytes, string->size + 1);
+ }
+
+ return string->size;
+}
+
void pn_string_clear(pn_string_t *string)
{
pn_string_set(string, NULL);
}
+
+int pn_string_format(pn_string_t *string, const char *format, ...)
+{
+ va_list ap;
+
+ while (true) {
+ va_start(ap, format);
+ int err = vsnprintf(string->bytes, string->capacity, format, ap);
+ va_end(ap);
+ if (err < 0) {
+ return err;
+ } else if ((size_t) err >= string->capacity) {
+ pn_string_grow(string, err);
+ } else {
+ string->size = err;
+ return 0;
+ }
+ }
+}
+
+char *pn_string_buffer(pn_string_t *string)
+{
+ assert(string);
+ return string->bytes;
+}
+
+size_t pn_string_capacity(pn_string_t *string)
+{
+ assert(string);
+ return string->capacity - 1;
+}
+
+int pn_string_resize(pn_string_t *string, size_t size)
+{
+ assert(string);
+ int err = pn_string_grow(string, size);
+ if (err) return err;
+ string->size = size;
+ string->bytes[size] = '\0';
+ return 0;
+}
+
+int pn_string_copy(pn_string_t *string, pn_string_t *src)
+{
+ assert(string);
+ return pn_string_setn(string, pn_string_get(src), pn_string_size(src));
+}
Modified: qpid/proton/trunk/proton-c/src/tests/object.c
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/tests/object.c?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/tests/object.c (original)
+++ qpid/proton/trunk/proton-c/src/tests/object.c Mon May 13 13:00:04 2013
@@ -383,6 +383,18 @@ static void test_stringn(const char *val
pn_free(strsetn);
}
+static void test_string_format()
+{
+ pn_string_t *str = pn_string("");
+ assert(str);
+ int err = pn_string_format(str, "%s", "this is a string that should be long "
+ "enough to force growth but just in case we'll "
+ "tack this other really long string on for the "
+ "heck of it");
+ assert(err == 0);
+ pn_free(str);
+}
+
int main(int argc, char **argv)
{
for (size_t i = 0; i < 128; i++) {
@@ -420,5 +432,7 @@ int main(int argc, char **argv)
test_string("this has an embedded \000 in it");
test_stringn("this has an embedded \000 in it", 28);
+ test_string_format();
+
return 0;
}
Modified: qpid/proton/trunk/proton-j/proton-api/src/main/resources/proton.py
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-j/proton-api/src/main/resources/proton.py?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/proton-j/proton-api/src/main/resources/proton.py
(original)
+++ qpid/proton/trunk/proton-j/proton-api/src/main/resources/proton.py Mon May
13 13:00:04 2013
@@ -1051,6 +1051,9 @@ class Messenger(object):
def route(self, *args, **kwargs):
raise Skipped()
+ def rewrite(self, *args, **kwargs):
+ raise Skipped()
+
def start(self):
self.impl.start()
Modified: qpid/proton/trunk/tests/python/proton_tests/message.py
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/message.py?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/tests/python/proton_tests/message.py (original)
+++ qpid/proton/trunk/tests/python/proton_tests/message.py Mon May 13 13:00:04
2013
@@ -112,8 +112,7 @@ class CodecTest(Test):
self.msg.priority = 100
self.msg.address = "address"
self.msg.subject = "subject"
- body = 'Hello World!'
- self.msg.load(body)
+ self.msg.body = 'Hello World!'
data = self.msg.encode()
@@ -126,8 +125,7 @@ class CodecTest(Test):
assert self.msg.priority == msg2.priority, (self.msg.priority,
msg2.priority)
assert self.msg.address == msg2.address, (self.msg.address, msg2.address)
assert self.msg.subject == msg2.subject, (self.msg.subject, msg2.subject)
- saved = self.msg.save()
- assert saved == body, (body, saved)
+ assert self.msg.body == msg2.body, (self.msg.body, msg2.body)
class LoadSaveTest(Test):
Modified: qpid/proton/trunk/tests/python/proton_tests/messenger.py
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/messenger.py?rev=1481834&r1=1481833&r2=1481834&view=diff
==============================================================================
--- qpid/proton/trunk/tests/python/proton_tests/messenger.py (original)
+++ qpid/proton/trunk/tests/python/proton_tests/messenger.py Mon May 13
13:00:04 2013
@@ -25,32 +25,31 @@ from time import sleep, time
class Test(common.Test):
def setup(self):
- # Very high timeout expected to only be exceeded by a genuine functional
- # problem, not by CI server slowness.
- self.long_timeout_millis = 100000
-
self.server_credit = 10
self.server_received = 0
self.server = Messenger("server")
- self.server.timeout = self.long_timeout_millis
+ self.server.timeout = int(self.timeout*1000)
self.server.start()
self.server.subscribe("amqp://~0.0.0.0:12345")
self.server_thread = Thread(name="server-thread", target=self.run_server)
self.server_thread.daemon = True
self.server_is_running_event = Event()
self.running = True
+ self.server_thread_started = False
self.client = Messenger("client")
- self.client.timeout= self.long_timeout_millis
+ self.client.timeout = int(self.timeout*1000)
def start(self):
+ self.server_thread_started = True
self.server_thread.start()
- self.server_is_running_event.wait(self.long_timeout_millis/1000)
+ self.server_is_running_event.wait(self.timeout)
self.client.start()
def teardown(self):
try:
if self.running:
+ if not self.server_thread_started: self.start()
# send a message to cause the server to promptly exit
self.running = False
msg = Message()
@@ -59,7 +58,7 @@ class Test(common.Test):
self.client.send()
finally:
self.client.stop()
- self.server_thread.join()
+ self.server_thread.join(self.timeout)
self.client = None
self.server = None
@@ -104,7 +103,7 @@ class MessengerTest(Test):
while len(body) < size:
body = 2*body
body = body[:size]
- msg.load(body)
+ msg.body = body
self.client.put(msg)
self.client.send()
@@ -114,7 +113,7 @@ class MessengerTest(Test):
self.client.get(reply)
assert reply.subject == "Hello World!"
- rbod = reply.save()
+ rbod = reply.body
assert rbod == body, (rbod, body)
def testSendReceive(self):
@@ -303,7 +302,7 @@ class MessengerTest(Test):
msg = Message()
msg.address="amqp://0.0.0.0:12345"
msg.subject="Hello World!"
- msg.load("First the world, then the galaxy!")
+ msg.body = "First the world, then the galaxy!"
assert self.server_received == 0
self.client.put(msg)
self.client.send()
@@ -325,7 +324,7 @@ class MessengerTest(Test):
msg.address="amqp://0.0.0.0:12345/XXX"
msg.subject="Hello World!"
body = "First the world, then the galaxy!"
- msg.load(body)
+ msg.body = body
self.client.put(msg)
self.client.send()
@@ -335,14 +334,14 @@ class MessengerTest(Test):
self.client.get(reply)
assert reply.subject == "Hello World!"
- rbod = reply.save()
+ rbod = reply.body
assert rbod == body, (rbod, body)
msg = Message()
msg.address="amqp://0.0.0.0:12345/YYY"
msg.subject="Hello World!"
body = "First the world, then the galaxy!"
- msg.load(body)
+ msg.body = body
self.client.put(msg)
self.client.send()
@@ -352,7 +351,7 @@ class MessengerTest(Test):
self.client.get(reply)
assert reply.subject == "Hello World!"
- rbod = reply.save()
+ rbod = reply.body
assert rbod == body, (rbod, body)
def _DISABLE_test_proton268(self):
@@ -363,7 +362,7 @@ class MessengerTest(Test):
msg = Message()
msg.address="amqp://0.0.0.0:12345"
- msg.load( "X" * 1024 )
+ msg.body = "X" * 1024
for x in range( 100 ):
self.client.put( msg )
@@ -446,3 +445,120 @@ class MessengerTest(Test):
reply = Message()
self.client.get(reply)
assert reply.body == "test"
+
+ def echo_address(self, msg):
+ while self.server.incoming:
+ self.server.get(msg)
+ msg.body = msg.address
+ self.dispatch(msg)
+
+ def _testRewrite(self, original, rewritten):
+ self.start()
+ self.process_incoming = self.echo_address
+ self.client.route("*", "amqp://0.0.0.0:12345")
+
+ msg = Message()
+ msg.address = original
+ msg.body = "test"
+
+ self.client.put(msg)
+ assert msg.address == original
+ self.client.recv(1)
+ assert self.client.incoming == 1
+
+ echo = Message()
+ self.client.get(echo)
+ assert echo.body == rewritten, (echo.body, rewritten)
+ assert msg.address == original
+
+ def testDefaultRewriteH(self):
+ self._testRewrite("original", "original")
+
+ def testDefaultRewriteUH(self):
+ self._testRewrite("user@original", "original")
+
+ def testDefaultRewriteUPH(self):
+ self._testRewrite("user:pass@original", "original")
+
+ def testDefaultRewriteHP(self):
+ self._testRewrite("original:123", "original:123")
+
+ def testDefaultRewriteUHP(self):
+ self._testRewrite("user@original:123", "original:123")
+
+ def testDefaultRewriteUPHP(self):
+ self._testRewrite("user:pass@original:123", "original:123")
+
+ def testDefaultRewriteHN(self):
+ self._testRewrite("original/name", "original/name")
+
+ def testDefaultRewriteUHN(self):
+ self._testRewrite("user@original/name", "original/name")
+
+ def testDefaultRewriteUPHN(self):
+ self._testRewrite("user:pass@original/name", "original/name")
+
+ def testDefaultRewriteHPN(self):
+ self._testRewrite("original:123/name", "original:123/name")
+
+ def testDefaultRewriteUHPN(self):
+ self._testRewrite("user@original:123/name", "original:123/name")
+
+ def testDefaultRewriteUPHPN(self):
+ self._testRewrite("user:pass@original:123/name", "original:123/name")
+
+ def testDefaultRewriteSH(self):
+ self._testRewrite("amqp://original", "amqp://original")
+
+ def testDefaultRewriteSUH(self):
+ self._testRewrite("amqp://user@original", "amqp://original")
+
+ def testDefaultRewriteSUPH(self):
+ self._testRewrite("amqp://user:pass@original", "amqp://original")
+
+ def testDefaultRewriteSHP(self):
+ self._testRewrite("amqp://original:123", "amqp://original:123")
+
+ def testDefaultRewriteSUHP(self):
+ self._testRewrite("amqp://user@original:123", "amqp://original:123")
+
+ def testDefaultRewriteSUPHP(self):
+ self._testRewrite("amqp://user:pass@original:123", "amqp://original:123")
+
+ def testDefaultRewriteSHN(self):
+ self._testRewrite("amqp://original/name", "amqp://original/name")
+
+ def testDefaultRewriteSUHN(self):
+ self._testRewrite("amqp://user@original/name", "amqp://original/name")
+
+ def testDefaultRewriteSUPHN(self):
+ self._testRewrite("amqp://user:pass@original/name", "amqp://original/name")
+
+ def testDefaultRewriteSHPN(self):
+ self._testRewrite("amqp://original:123/name", "amqp://original:123/name")
+
+ def testDefaultRewriteSUHPN(self):
+ self._testRewrite("amqp://user@original:123/name",
"amqp://original:123/name")
+
+ def testDefaultRewriteSUPHPN(self):
+ self._testRewrite("amqp://user:pass@original:123/name",
"amqp://original:123/name")
+
+ def testRewriteSupress(self):
+ self.client.rewrite("*", None)
+ self._testRewrite("asdf", None)
+
+ def testRewrite(self):
+ self.client.rewrite("a", "b")
+ self._testRewrite("a", "b")
+
+ def testRewritePattern(self):
+ self.client.rewrite("amqp://%@*", "amqp://$2")
+ self._testRewrite("amqp://foo@bar", "amqp://bar")
+
+ def testRewriteToAt(self):
+ self.client.rewrite("amqp://%/*", "$2@$1")
+ self._testRewrite("amqp://domain/name", "name@domain")
+
+ def testRewriteOverrideDefault(self):
+ self.client.rewrite("*", "$1")
+ self._testRewrite("amqp://user:pass@host", "amqp://user:pass@host")
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]