summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenoit Perrin2013-05-16 11:58:56 (EDT)
committerEugene Tarassov2013-05-18 22:18:53 (EDT)
commit9bc23a4d23a5a6fddf508188569339cf58906278 (patch)
tree339131343531d87b42a908da1e046cbb44b5c8f9
parent962a045efe4176923cc4de502de06b80bbfc9cb8 (diff)
downloadorg.eclipse.tcf.agent-9bc23a4d23a5a6fddf508188569339cf58906278.zip
org.eclipse.tcf.agent-9bc23a4d23a5a6fddf508188569339cf58906278.tar.gz
org.eclipse.tcf.agent-9bc23a4d23a5a6fddf508188569339cf58906278.tar.bz2
Bug 408260 - Chained tcf servers do not report correct list of services
When several TCF servers are chained between a client and an agent (using Locator.redirect command), the services list of the TCF chain from the client perspective is not correctly consolidated and reported. After the server is redirected to another TCF entity, it intercepts all Locator.redirect commands from the client to update its internal list of services.
-rw-r--r--server/tcf/main/server.c97
1 files changed, 95 insertions, 2 deletions
diff --git a/server/tcf/main/server.c b/server/tcf/main/server.c
index dbf1d5a..84a9a08 100644
--- a/server/tcf/main/server.c
+++ b/server/tcf/main/server.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2012 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2013 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -19,8 +19,9 @@
#include <tcf/config.h>
-#include <tcf/framework/myalloc.h>
#include <tcf/framework/exceptions.h>
+#include <tcf/framework/json.h>
+#include <tcf/framework/myalloc.h>
#include <tcf/framework/proxy.h>
#include <tcf/services/linenumbers.h>
#include <tcf/services/symbols.h>
@@ -28,6 +29,8 @@
#include <tcf/services/context-proxy.h>
#include <tcf/main/server.h>
+#include <assert.h>
+
static Protocol * proto;
static TCFBroadcastGroup * bcg;
@@ -38,6 +41,87 @@ static void channel_new_connection(ChannelServer * serv, Channel * c) {
channel_start(c);
}
+typedef struct RedirectInfo {
+ Channel * host;
+ char token[256];
+} RedirectInfo;
+
+static void command_redirect_done (Channel * c, void * client_data, int error) {
+ RedirectInfo * info = (RedirectInfo *)client_data;
+
+ if (!is_channel_closed(info->host)) {
+ int err = error;
+
+ if (err == 0) {
+ /*
+ * When we are sure that the redirect command succeeded, update the
+ * state of the host channel to react correctly on the new Hello
+ * message from the target, sending a new Hello event to the host
+ * with all the services of the target agent plus the ones of this
+ * TCF entity.
+ */
+
+ assert (c->state == ChannelStateHelloSent);
+ assert (info->host->state == ChannelStateConnected);
+
+ info->host->state = ChannelStateHelloReceived;
+
+ /*
+ * Notify close of the host channel upon redirection; a
+ * notification about a new openning is sent when the Hello event
+ * is received from the target.
+ */
+
+ notify_channel_closed(info->host);
+ }
+
+ write_stringz(&info->host->out, "R");
+ write_stringz(&info->host->out, info->token);
+ write_errno(&info->host->out, err);
+ write_stream(&info->host->out, MARKER_EOM);
+ }
+
+ channel_unlock(info->host);
+ loc_free (info);
+}
+
+static void read_peer_attr(InputStream * inp, const char * name, void * x) {
+ peer_server_addprop((PeerServer *)x, loc_strdup(name), json_read_alloc_string(inp));
+}
+
+static void command_locator_redirect(char * token, Channel * c, void * args) {
+ char id[256];
+ PeerServer * ps = NULL;
+ Channel * target = (Channel *)args;
+ RedirectInfo * info = (RedirectInfo *)loc_alloc_zero(sizeof(RedirectInfo));
+
+ if (peek_stream(&c->inp) == '{') {
+ ps = peer_server_alloc();
+ json_read_struct(&c->inp, read_peer_attr, ps);
+ }
+ else {
+ json_read_string(&c->inp, id, sizeof(id));
+ }
+
+ json_test_char(&c->inp, MARKER_EOA);
+ json_test_char(&c->inp, MARKER_EOM);
+
+ channel_lock(c);
+ info->host = c;
+ strlcpy(info->token, token, sizeof(info->token));
+
+ /* Send the redirect command to the next TCF entity */
+
+ if (ps != NULL) {
+ send_redirect_command_by_props(target, ps, command_redirect_done, info);
+ }
+ else {
+ send_redirect_command_by_id(target, id, command_redirect_done, info);
+ }
+
+ if (ps != NULL) peer_server_free(ps);
+}
+
static void channel_redirection_listener(Channel * host, Channel * target) {
if (target->state == ChannelStateStarted) {
#if defined(SERVICE_LineNumbers) && SERVICE_LineNumbers
@@ -77,6 +161,15 @@ static void channel_redirection_listener(Channel * host, Channel * target) {
create_context_proxy(host, target, forward_pm);
#endif
}
+ /*
+ * Intercept the Locator.redirect command to update the local list of
+ * services with the ones from the next TCF entity (agent), and send a
+ * consolidate list to the previous TCF entity (client). This is
+ * required in the case of more than one server between the client and
+ * the agent.
+ */
+ add_command_handler2(host->protocol, "Locator", "redirect",
+ command_locator_redirect, target);
}
}