Archived

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

ObjectAdapter questions

Hi All,

I have two clients behind NAT and server with public IP. I would like to have ObjectAdapter on this server. Is the following scenario possible?

1. Client1 registers on server adapter
2. Client2 gets reference to Client1 from server
3. Client2 invokes methods on Client1

Can I create the ObjectAdapter (on server) as in the example...:

Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default ‑p 10000");

...and then get the reference to this adapter in Client code?

Is it possible to configure ObjectAdapter with user accounts, i. e. user while registering to object adapter should provide username and password.

Comments

  • matthew
    matthew NL, Canada
    Clients do not get references to object adapters. Clients call objects hosted by an object adapter via a proxy (you can find more information on proxies in the Ice manual, or in "proxies" in http://www.zeroc.com/newsletter/issue23.pdf). The object on which the client calls is identified by the object identity. I suggest reviewing the newsletter articles, the Ice manual, and the Ice demos for more information.
    Is it possible to configure ObjectAdapter with user accounts, i. e. user while registering to object adapter should provide username and password.

    With respect to authentication, you would generally either use SSL, or more typically you'd have a session model in conjunction with Glacier2. See "Teach Yourself Glacier2 in 10 Minutes" in http://www.zeroc.com/newsletter/issue22.pdf
  • matthew wrote: »
    Clients do not get references to object adapters. Clients call objects hosted by an object adapter via a proxy

    Yes I know, I think I understand the idea of ICE - proxies, adapters etc. In my example I have two clients, which also enables remote methods. In no network environment I would register client1 and client2 on local object adapter, then client1 can get reference to client2 and invoke a method on it (client2 can get ref of client1 and do the same) - and this is what I have already done and it is working.

    Now I would like to run client1 on different host than client2 (both are in different networks). If they want to communicate, they need to get reference to each other. I thought that the simplest way will be to run ObjectAdapter on other, no NAT, machine and there register all clients. Am I wrong?
    The object on which the client calls is identified by the object identity. I suggest reviewing the newsletter articles, the Ice manual, and the Ice demos for more information.

    I want to create some kind of communicator, each user would have jabber like identifier - user@server, where server would be ObjectAdapter address and user would be the identity of the client under which it is registered on object adapter.
  • matthew
    matthew NL, Canada
    lukaszg84 wrote: »
    Now I would like to run client1 on different host than client2 (both are in different networks). If they want to communicate, they need to get reference to each other. I thought that the simplest way will be to run ObjectAdapter on other, no NAT, machine and there register all clients. Am I wrong?
    ...

    Sorry, after reading this I find myself confused about what you want to do. What do you mean "run ObjectAdapter" on other? No NAT? You mean the clients are not NATed?

    Perhaps the simplest thing to do is to draw a diagram of how you want the call flow & communications to work between various system elements.
  • Following slice interface:
    interface Client {
        void sendTextMessage(string message);
    };
    

    I also attached the diagram. All the clients implements the slice interface, all of clients should be able to communicate (sendTextMessage) with each other.

    I thought that the best way will be to have a server with external IP. On this server I will run ObjectAdapter, which holds references to all clients. Every client after start will register itself on this server. When client1 wants to invoke sendTextMessage method on client2, it needs a reference to client2 and gets this reference from the server.
  • matthew
    matthew NL, Canada
    On this server I will run ObjectAdapter, which holds references to all clients.

    At the risk of being pedantic, ObjectAdapters do not hold references to clients. You would have some registrar Ice object with which the clients themselves register. Something like:
    interface Registrar
    {
       void register(Client* client, string someClientIdentity);
       Client* lookup(string someClientIdentity);
    };
    

    If you have some authentication layer, then more likely you'd have this as part of the session establishment:
    interface Session
    {
       Client* lookup(string someClientIdentity);
       void logout();
    };
    
    interface SessionManager
    {
       Session* login(Client* client, string someClientIdentity, string someEncryptedPassword);
    };
    
    

    In either case for this use case, where you want the clients to talk with one another you have two alternatives:

    1/ Use the server as a relay for packets that flow between the clients. It looks like you don't want to use that.

    2/ Configure the Firewall & NAT to allow the clients to talk directly to one another. In this case, you'll need to ensure you publish the correct IP address for the proxies to the objects that reside in your clients. For information on doing that see the PublishedEndpoints property http://www.zeroc.com/doc/Ice-3.3.1/manual/PropRef.50.4.html.
  • matthew wrote: »
    interface Registrar
    {
       void register(Client* client, string someClientIdentity);
       Client* lookup(string someClientIdentity);
    };
    

    Thanks. This kind of code I already have. I thought that I can use some ICE mechanisms but unfortunatelly not :(
    1/ Use the server as a relay for packets that flow between the clients. It looks like you don't want to use that.

    2/ Configure the Firewall & NAT to allow the clients to talk directly to one another. In this case, you'll need to ensure you publish the correct IP address for the proxies to the objects that reside in your clients. For information on doing that see the PublishedEndpoints property http://www.zeroc.com/doc/Ice-3.3.1/manual/PropRef.50.4.html.

    Only first option is good solution. This client should run, no matter what configuration is done.

    Thanks for your replies.
  • matthew
    matthew NL, Canada
    You could choose to run a combination of the two approaches actually. That is you first try to establish a connect to the client, and if that fails then send to the other client through your server.

    I also suggest that you look into using bi-directional connections to permit clients to receive callbacks with no hole in the firewall, and no complicated NAT traversal.
  • matthew wrote: »
    I also suggest that you look into using bi-directional connections to permit clients to receive callbacks with no hole in the firewall, and no complicated NAT traversal.

    I wanted to ask about this.
    interface Registrar
    {
       void register(Client* client, string someClientIdentity);
       Client* lookup(string someClientIdentity);
       void relayTextMsg(string msg, string clientIdentity);
    };
    
    interface Client {
        void sendTextMessage(string message);
    };
    

    Additional question:
    Registrar = running on server with public IP.
    Client1, Client2 = behind NATs.

    Client1 and Client2 are registering on Registrar.
    Client1 lookups Client2 and gets its reference.
    Client1 realize that Client2 is behind the NAT, so the message must be relayed.
    Client1 invokes relayTextMsg()

    Now registrar must have access to Client2 behind NAT. You suggested using bi-directional connections. What is the cost of this solution? What if 100 or 1000 of clients opens bi-directional connection to the registrar?
  • matthew
    matthew NL, Canada
    Client1 invokes relayTextMsg()

    In fact, I would suggest if possible that you don't do this. You could implement this transparently in the server, by having the server do the reachability detection and returning either a proxy to the client object residing in the client, or a client object residing in the server (which then in turn relays to the client using the existing bi-directional connection).
    Now registrar must have access to Client2 behind NAT. You suggested using bi-directional connections. What is the cost of this solution? What if 100 or 1000 of clients opens bi-directional connection to the registrar?

    The cost is a connection per client. I would recommend reading Michi's scalability white paper (http://www.zeroc.com/articles/IcePerformanceWhitePaper.pdf). Assuming you use a suitable operating system, the number of connections is pretty irrelevant. The scalability itself is determined by the request rate (that is the number of requests that flow per second through the server), not the number of connections to the server.
  • matthew wrote: »
    bi-directional connection

    Has this connection any "keep-alive" mechanism? Client1 (behind NAT) opens bi-directional connection to Server, for a couple of hours nothing happens. Then server wishes to invoke some method on client.
  • matthew
    matthew NL, Canada
    The connection will not be closed, assuming that you disable ACM on both the client & the server.
  • matthew wrote: »
    The connection will not be closed, assuming that you disable ACM on both the client & the server.

    What about NAT serwer? When ACM is disabled, will ICE send some keep alive packets itself?
    The manual (http://www.zeroc.com/doc/Ice-3.3.1/manual/Connections.38.4.html ) says that in bi-directional connections ACM must be disabled.
  • matthew
    matthew NL, Canada
    Ice does not send keep alive packets itself. If you have something in your network infrastructure that requires that, then you will have to implement that yourself. Its not very difficult to do. See the SessionPingThread in demo/Glacier2/chat/Client.cpp for an example.