Archived

This forum has been archived. Please start a new discussion on GitHub.

IceStorm with subsciber behind dynamic NAT

Hi all,
I'm developing an app with many subscribers installed behind ADSL routers. The publisher and IceStorm server have public IPs. I have a problem to receive message from IceStorm because subscribers are prive IPs, therefore IceStorm can not send message to. The ADSL routers only allow outgoing connections and are dynamic IPs, so I can not configure a NAT solution as refered in this post and this.
So anyone has another solution?
Thank you very much!

Comments

  • xdm
    xdm La Coruña, Spain
    Hi,

    You can use Glacier2 to solve that issue. Basically Glacier2 will allow you to receive invocations over the connection opened by the client. For details about Glacier2 read: There are also several Glacier2 demos included in Ice distribution, if you still have doubts after reading that, ask here again.
  • hi,

    I have the same problem.
    my network very simple:

    Subscriber(192.168.1.10) -- NAT ..... NAT <==> internate -- Public IP Server( 61.1.x.y)(Glacier2, IceStorm, Publisher all in same server )

    I run Clock demo:

    At Server side: ( IP: 61.1.x.y)
    config.glacier2:
    Glacier2.InstanceName=DemoGlacier2
    Glacier2.Client.Endpoints=tcp -h 61.1.x.y -p 4063
    Glacier2.Server.Endpoints=tcp -h localhost
    ......
    config.icebox: (No change)
    config.service: (No change)
    config.pub: (No change)


    At Client Side : (IP: dynamic 192.168.1.x)
    config.sub:
    Ice.Default.Router=DemoGlacier2/router:tcp -p 4063 -h 61.1.x.y
    Clock.Subscriber.Endpoints=tcp
    ......

    please help me! thanks in advance!
  • hi, all!
    I have changed my subscriber according the Glacier2 callback demo client program!
    // **********************************************************************
    //
    // Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
    //
    // This copy of Ice is licensed to you under the terms described in the
    // ICE_LICENSE file included in this distribution.
    //
    // **********************************************************************
    
    using Demo;
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    
    [assembly: CLSCompliant(true)]
    
    [assembly: AssemblyTitle("IceStormClockSubscriber")]
    [assembly: AssemblyDescription("IceStorm clock demo subscriber")]
    [assembly: AssemblyCompany("ZeroC, Inc.")]
    
    public class Subscriber
    {
        public class App : Glacier2.Application
        {
            public class ClockI : ClockDisp_
            {
                public override void tick(string date, Ice.Current current)
                {
                    System.Console.Out.WriteLine(date);
                }
            }
    
            public override Glacier2.SessionPrx createSession()
            {
                Glacier2.SessionPrx session;
                while (true)
                {
                    try
                    {
                        session = router().createSession("Demo", "Demo");
                        break;
                    }
                    catch (Glacier2.PermissionDeniedException ex)
                    {
                        Console.WriteLine("permission denied:\n" + ex.reason);
                    }
                    catch (Glacier2.CannotCreateSessionException ex)
                    {
                        Console.WriteLine("cannot create session:\n" + ex.reason);
                    }
                }
                return session;
            }
    
            public override int runWithSession(string[] args)
            {
                args = communicator().getProperties().parseCommandLineOptions("Clock", args);
    
                string topicName = "time";
                string id = null;
                string retryCount = null;
    
                IceStorm.TopicManagerPrx manager = IceStorm.TopicManagerPrxHelper.checkedCast(
                    communicator().propertyToProxy("TopicManager.Proxy"));
                if (manager == null)
                {
                    Console.WriteLine("invalid proxy");
                    return 1;
                }
    
                //
                // Retrieve the topic.
                //
                IceStorm.TopicPrx topic;
                try
                {
                    topic = manager.retrieve(topicName);
                }
                catch (IceStorm.NoSuchTopic)
                {
                    try
                    {
                        topic = manager.create(topicName);
                    }
                    catch (IceStorm.TopicExists)
                    {
                        Console.WriteLine("temporary error. try again.");
                        return 1;
                    }
                }
    
                Ice.ObjectAdapter adapter = communicator().createObjectAdapter("Clock.Subscriber");
                //
                // Add a servant for the Ice object. If --id is used the
                // identity comes from the command line, otherwise a UUID is
                // used.
                //
                // id is not directly altered since it is used below to
                // detect whether subscribeAndGetPublisher can raise
                // AlreadySubscribed.
                //
                Ice.Identity subId = new Ice.Identity(id, "");
                if (subId.name == null)
                {
                    subId.name = Guid.NewGuid().ToString();
                }
                Ice.ObjectPrx subscriber = adapter.add(new ClockI(), subId);
    
                Dictionary<string, string> qos = new Dictionary<string, string>();
                if (retryCount != null)
                {
                    qos["retryCount"] = retryCount;
                }
                //
                // Set up the proxy.
                //
                subscriber = subscriber.ice_oneway();
    
                try
                {
                    topic.subscribeAndGetPublisher(qos, subscriber);
                }
                catch (IceStorm.AlreadySubscribed)
                {
                    // If we're manually setting the subscriber id ignore.
                    if (id == null)
                    {
                        throw;
                    }
                    System.Console.Out.WriteLine("reactivating persistent subscriber");
                }
    
                adapter.activate();
    
                shutdownOnInterrupt();
                communicator().waitForShutdown();
    
                topic.unsubscribe(subscriber);
    
                return 0;
            }
        }
    
        public static int Main(string[] args)
        {
            App app = new App();
            return app.main(args, "config.sub");
        }
    }
    
    

    In my internet environment, the Glacier2 callback program work well!
    but the
  • hi, all!
    I have changed my subscriber according the Glacier2 callback demo client program!
    // **********************************************************************
    //
    // Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
    //
    // This copy of Ice is licensed to you under the terms described in the
    // ICE_LICENSE file included in this distribution.
    //
    // **********************************************************************
    
    using Demo;
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    
    [assembly: CLSCompliant(true)]
    
    [assembly: AssemblyTitle("IceStormClockSubscriber")]
    [assembly: AssemblyDescription("IceStorm clock demo subscriber")]
    [assembly: AssemblyCompany("ZeroC, Inc.")]
    
    public class Subscriber
    {
        public class App : Glacier2.Application
        {
            public class ClockI : ClockDisp_
            {
                public override void tick(string date, Ice.Current current)
                {
                    System.Console.Out.WriteLine(date);
                }
            }
    
            public override Glacier2.SessionPrx createSession()
            {
                Glacier2.SessionPrx session;
                while (true)
                {
                    try
                    {
                        session = router().createSession("Demo", "Demo");
                        break;
                    }
                    catch (Glacier2.PermissionDeniedException ex)
                    {
                        Console.WriteLine("permission denied:\n" + ex.reason);
                    }
                    catch (Glacier2.CannotCreateSessionException ex)
                    {
                        Console.WriteLine("cannot create session:\n" + ex.reason);
                    }
                }
                return session;
            }
    
            public override int runWithSession(string[] args)
            {
                args = communicator().getProperties().parseCommandLineOptions("Clock", args);
    
                string topicName = "time";
                string id = null;
                string retryCount = null;
    
                IceStorm.TopicManagerPrx manager = IceStorm.TopicManagerPrxHelper.checkedCast(
                    communicator().propertyToProxy("TopicManager.Proxy"));
                if (manager == null)
                {
                    Console.WriteLine("invalid proxy");
                    return 1;
                }
    
                //
                // Retrieve the topic.
                //
                IceStorm.TopicPrx topic;
                try
                {
                    topic = manager.retrieve(topicName);
                }
                catch (IceStorm.NoSuchTopic)
                {
                    try
                    {
                        topic = manager.create(topicName);
                    }
                    catch (IceStorm.TopicExists)
                    {
                        Console.WriteLine("temporary error. try again.");
                        return 1;
                    }
                }
    
    //            Ice.ObjectAdapter adapter = communicator().createObjectAdapter("Clock.Subscriber");
                Ice.ObjectAdapter adapter = objectAdapter();
    
                //
                // Add a servant for the Ice object. If --id is used the
                // identity comes from the command line, otherwise a UUID is
                // used.
                //
                // id is not directly altered since it is used below to
                // detect whether subscribeAndGetPublisher can raise
                // AlreadySubscribed.
                //
                Ice.Identity subId = new Ice.Identity(id, "");
                if (subId.name == null)
                {
                    subId.name = Guid.NewGuid().ToString();
                }
                Ice.ObjectPrx subscriber = adapter.add(new ClockI(), subId);
    
                Dictionary<string, string> qos = new Dictionary<string, string>();
                if (retryCount != null)
                {
                    qos["retryCount"] = retryCount;
                }
                //
                // Set up the proxy.
                //
                subscriber = subscriber.ice_oneway();
    
                try
                {
                    topic.subscribeAndGetPublisher(qos, subscriber);
                }
                catch (IceStorm.AlreadySubscribed)
                {
                    // If we're manually setting the subscriber id ignore.
                    if (id == null)
                    {
                        throw;
                    }
                    System.Console.Out.WriteLine("reactivating persistent subscriber");
                }
    
                adapter.activate();
    
                shutdownOnInterrupt();
                communicator().waitForShutdown();
    
                topic.unsubscribe(subscriber);
                router().destroySession();
    
                return 0;
            }
        }
    
        public static int Main(string[] args)
        {
            App app = new App();
            return app.main(args, "config.sub");
        }
    }
    
    

    In my internet environment, the Glacier2 callback program work well!
    but the icestorm Subscriber can not work.
  • benoit
    benoit Rennes, France
    Hi,

    The code looks fine. Do you get errors on the subscriber side? Did you enable tracing on the Glacier2 router to try to see if publisher messages were being sent to the Glacier2 router by IceStorm? Setting the following properties in the Glacier2 router configuration file should help to track down the issue:
    Glacier2.Trace.Session=1
    Glacier2.Client.Trace.Reject=1
    Glacier2.Client.Trace.Request=1
    Glacier2.Server.Trace.Reject=1
    Glacier2.Server.Trace.Request=1
    
    Cheers,
    Benoit.
  • Hi, Benoit
    Thank you for your quick reply.
    I trace the Glacier2 , log
    ...
    -- 07/01/13 15:36:24.521 glacier2router: Glacier2: routing (buffered)
    proxy = DemoIceStorm/topic.time -t -e 1.1:tcp -h localhost -p 10000
    operation = subscribeAndGetPublisher
    context =
    -- 07/01/13 15:36:24.946 glacier2router: Protocol: sending asynchronous request
    message type = 0 (request)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 150
    request id = 3
    identity = DemoIceStorm/topic.time
    facet =
    operation = subscribeAndGetPublisher
    mode = 0 (normal)
    context =
    encoding = 1.1
    -- 07/01/13 15:36:24.947 glacier2router: Network: sent 150 of 150 bytes via tcp
    local address = 127.0.0.1:50196
    remote address = 127.0.0.1:10000
    -- 07/01/13 15:36:24.966 glacier2router: Network: received 14 of 14 bytes via tcp
    local address = 127.0.0.1:50196
    remote address = 127.0.0.1:10000
    -- 07/01/13 15:36:24.967 glacier2router: Network: received 115 of 115 bytes via tcp
    local address = 127.0.0.1:50196
    remote address = 127.0.0.1:10000
    -- 07/01/13 15:36:24.967 glacier2router: Protocol: received reply
    message type = 2 (reply)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 129
    request id = 3
    reply status = 0 (ok)
    -- 07/01/13 15:36:24.967 glacier2router: Protocol: sending reply
    message type = 2 (reply)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 129
    request id = 11
    reply status = 0 (ok)
    -- 07/01/13 15:36:24.967 glacier2router: Network: sent 129 of 129 bytes via tcp
    local address = 61.191.190.24:4063
    remote address = 60.170.58.218:13717
    -- 07/01/13 15:36:28.419 glacier2router: Network: accepted tcp connection
    local address = 127.0.0.1:50195
    remote address = 127.0.0.1:50199
    -- 07/01/13 15:36:28.419 glacier2router: Protocol: sending validate connection
    message type = 3 (validate connection)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 14
    -- 07/01/13 15:36:28.419 glacier2router: Network: sent 14 of 14 bytes via tcp
    local address = 127.0.0.1:50195
    remote address = 127.0.0.1:50199
    -- 07/01/13 15:36:28.419 glacier2router: Network: received 14 of 14 bytes via tcp
    local address = 127.0.0.1:50195
    remote address = 127.0.0.1:50199
    -- 07/01/13 15:36:28.419 glacier2router: Network: received 76 of 76 bytes via tcp
    local address = 127.0.0.1:50195
    remote address = 127.0.0.1:50199
    -- 07/01/13 15:36:28.420 glacier2router: Protocol: received request
    message type = 0 (request)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 90
    request id = 0 (oneway)
    identity = 85a9b3aa-7f8b-42f7-9a30-8e9f2bbd078a
    facet =
    operation = tick
    mode = 0 (normal)
    context =
    encoding = 1.1
    -- 07/01/13 15:36:29.417 glacier2router: Network: received 14 of 14 bytes via tcp
    local address = 127.0.0.1:50195
    remote address = 127.0.0.1:50199
    -- 07/01/13 15:36:29.417 glacier2router: Network: received 76 of 76 bytes via tcp
    local address = 127.0.0.1:50195
    remote address = 127.0.0.1:50199
    -- 07/01/13 15:36:29.417 glacier2router: Protocol: received request
    message type = 0 (request)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 90
    request id = 0 (oneway)
    identity = 85a9b3aa-7f8b-42f7-9a30-8e9f2bbd078a
    facet =
    operation = tick
    mode = 0 (normal)
    context =
    encoding = 1.1
    ...

    why the glacier2 only received the message the operation = tick, but don't forward to my subscriber?
  • hi,all
    In my working environment, I must connect to internet through many times NAT that I can not control.
    I only know the localhost IP and the public internet IP.
    Can Glacier2 & IceStorm work?


    the Icestorm log:
    -- 07/01/13 18:20:37.100 icebox.exe-IceStorm: Network: failed to establish tcp connection
    local address: <not available>
    remote address: 192.168.0.10:25474
    Network.cpp:2348: Ice::ConnectFailedException:
    connect failed: 信号灯超时时间已到 (The semaphore timeout period has expired)
    -- 07/01/13 18:20:37.101 icebox.exe-IceStorm: Network: trying to establish tcp connection to 192.168.0.10:25474
  • benoit
    benoit Rennes, France
    Hi,

    Something is actually missing from your client code. The identity of the subscriber should be created with the Glacier2.Application.createCallbackIdentity method or you should use Glacier2.Application.addWithUUID method to register the servant with the Glacier2 session object adapter:
                Ice.Identity subId;
                if (subId.name == null)
                {
                    subId = createCallbackIdentity(Guid.NewGuid().ToString());
                }
                else
                {
                     subId = createCallbackIdentity(id);
                }
                Ice.ObjectPrx subscriber = adapter.add(new ClockI(), subId);
    

    Or just the following if you don't need to configure the identity:
                Ice.ObjectPrx subscriber = addWithUUID(new ClockI()); 
    

    The Glacier2 router should be able to route back the "tick" requests after this change. You must also make sure to subscribe to the topic with the proxy returned by the addWithUUID method. This proxy contains the Glacier2 router server endpoints and IceStorm should therefore not try to connect to the local IP address of your client but to the Glacier2 router server endpoints.

    Cheers,
    Benoit.
  • hi,Benoit
    Wonderful, It is what I want to do!!!!!!!!
    thanks, thank you very much!!!!