EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Message routing and forwarding with MsgConnect

Introduction

While MsgConnect was originally designed to be peer-to-peer information exchange framework, there are cases when direct communication between two nodes is not possible or desired. Imagine two peers of peer-to-peer network, both protected by firewalls. Or a corporate server behind a firewall, which requires access from external systems sometimes. One more application of indirect communication is a load-balancing system, where some intermediate node should define, where to route the request.

Load balancing strategies will be discusssed in a separate article, and now we will concentrate on routing basics.

This image shows usual configuration with two peers:

Node A sends a message to Node B by calling

MCMessenger messenger;
MCSocketTransport transport;
:
transport.setMessenger(messenger);
transport.setTransportMode(stmClient);
:
messenger.PostMessage("Socket:192.168.0.2:12340|SampleQueue", ... );

No routing is involved and it is supposed that the message should go directly to Node B.

Message routing

Now Node B is behind a firewall:

If Node A sends a message, connection will be blocked by firewall as shown on the above image. To avoid the problem, we need to employ a server RoutingServer:4321, as follows:

The things become somehow complicated. Node A sends a message to Node B, but involves MCRouter component:

Node A code:


MCMessenger messenger;
MCSocketTransport transport;
MCRouter router;
:
transport.setMessenger(messenger);
transport.setTransportMode(stmClient);
:
router.SetRoutingRule("192.168.0.2:12340", "10.1.1.1:4321");
messenger.PostMessage("Socket:192.168.0.2:12340|SampleQueue", ... );

RoutingServer code:


MCMessenger messenger;
MCSocketTransport transport;
:
transport.setMessenger(messenger);
transport.setTransportMode(stmServer);
transport.setRoutingAllowed(true);

Node B code:


MCMessenger messenger;
MCSocketTransport transport;
:
transport.setMessenger(messenger);
transport.setTransportMode(stmClient);
:
while (true)
{
    messenger.PostMessage("Socket:10.1.1.1:4321|InvalidQueue" , ...);
    :
}

What we've done:

  1. We told the messenger on Node A to route messages via RoutingServer
  2. We told the messenger on RoutingServer to dispatch all messages, which are delivered to RoutingServer but have different destination
  3. We told the messenger on Node B to post invalid messages to RoutingServer from time to time (this is described below).

This is how it works:

The messenger on Node A is told to deliver a message to 192.168.0.2:12340. It checks the routing table and finds out that the message is to be sent to RoutingServer instead.

RoutingServer receives the message and finds out that the message should have been sent to other destination. Since RoutingAllowed property of the RoutingServer's transport is true (i.e. routing is allowed), the message can be sent to Node B. However, RoutingServer's transport works in stmServer mode and so it can only wait until Node B connects and picks outgoing messages.

This is why Node B should send something to RoutingServer. When Node B sends something (an invalid/empty package) to RoutingServer, the connection is established and the message from RoutingServer is delivered to Node B automatically.

All routing on RoutingServer is done automatically by it's socket transport. Whether or not routing is done is defined by transport's RoutingAllowed property. Currently application has no control over message routing by intermediate notes, but there are plans to add OnRoutingRequest(Source, Destination) event so that application can decline or accept the request based on the address.

Note: Routing is supported not by all transports. SocketTransport, HTTPTransport and UDPTransport support routing, while DirectTransport and MMFTransport don't.

Message forwarding

While Message forwarding also involves intermediate nodes, this is different method.

First, the message is sent by Node A to Node B and Node B is a recipient. Application running at Node B decides whether to process the message or forward it to Node C or Node D. If the application forwards the message, it calls ForwardMessage() method. On the above scheme Node C handles the message as if it actually came from Node B.

Node A code:


MCMessenger messenger;
MCSocketTransport transport;
:
transport.setMessenger(messenger);
transport.setTransportMode(stmClient);
:
messenger.PostMessage("Socket:192.168.0.2:12340|SampleQueue", ... );

Node B code:


MCMessenger messenger;
MCSocketTransport transport;
:
transport.setMessenger(messenger);
transport.setTransportMode(stmP2P);
:
void OnMessage(void* resvd, void* Sender, MsgConnect::MCMessage& Message, bool& Handled)
{
    :
    if (MyDecidedToForwardFunc() == true)
    {
        messenger.ForwardMessage("Socket:192.168.0.3:12340|SampleQueue" , ...);
    :
    }
}

If the message is forwarded by Node B to Node C, the following happens:

  1. If the message was sent with one of SendMessage*() methods, it is put to special waiting list and Node A doesn't receive anything in reply until Node C replies
  2. Node C will reply (if necessary) back to Node B and then Node B will resend the reply back to Node A.

Forwarding of messages is useful when the final recipient is not known to sender, for example in load balancing systems or when the server is behind a corporate firewall. Also, forwarding of messages can be used when the intermediate server performs user authentication (and destination server doesn't have possibility to authenticate user due to some reasons).

Return to the list

|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!