Groups | Blog | Home
all groups > dotnet remoting > august 2005 >

dotnet remoting : NAT and Remoting


venkats_n
8/21/2005 11:36:14 AM
I am developing an WinForms based application used 90% within a LAN and
10% across the Internet though the Internet use may increase over time.
This application uses the remoting technology.

The application does not work for Natted IP addresses.

I tried to work around this problem with the reference of the post "nat
routing, firewalls and remoting" in the same forum.

I have reached someplace, but I am now struggling to proceed further.
The steps I followed :

1. Created a Server Side Sink and registered it through the web.config
as I am using IIS as host for my remote object
<system.runtime.remoting>
<application>
<channels>
<channel ref="http">
<serverProviders>
<provider type="SinkAssembly.ServerSinkProvider, SinkAssembly"/>
<formatter ref="soap" typeFilterLevel="Full" />
</serverProviders>
</channel>
</channels>
.....

2. The sink looks somewhat like this :
public class ServerSink : BaseChannelSinkWithProperties,
IServerChannelSink
{

private IServerChannelSink _nextSink;

public ServerSink(IServerChannelSink next)
{
_nextSink = next;
}


public IServerChannelSink NextChannelSink
{
get
{
return _nextSink;
}
}
.....
.....
public ServerProcessing ProcessMessage(IServerChannelSinkStack
sinkStack,
IMessage requestMsg,
ITransportHeaders requestHeaders,
Stream requestStream,
out IMessage responseMsg,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
IPAddress ipAddress =
requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;

CallContext.SetData("ClientIP",ipAddress);

ServerProcessing srvProc = _nextSink.ProcessMessage(sinkStack,
requestMsg,
requestHeaders,
requestStream,
out responseMsg,
out responseHeaders,
out responseStream);


return ServerProcessing.Complete;
}

3. Created a Tracking Handler class.
public class TrackingHandler : ITrackingHandler
{
public void MarshaledObject(Object obj, ObjRef or)
{
....................
....................
IPAddress ipAddress = (IPAddress )CallContext.GetData("ClientIP");

object[] MyChannelData = new object[or.ChannelInfo.ChannelData.Length
];


for ( int i = or.ChannelInfo.ChannelData.GetLowerBound(0); i <=
or.ChannelInfo.ChannelData.GetUpperBound(0); i++ )
{
if(or.ChannelInfo.ChannelData[i] is ChannelDataStore)
{
//then manipulate the ChannelUris

}
}
..........................

4. Derieved all my Remote Object classes from a Base Class which looks
like this :

public abstract class RemotingBase : MarshalByRefObject
{

private static bool bProbingStarted = false;
private TrackingHandler trkHndlr = null;
..................
.........
....
...
..
public RemotingBase()
{
StartProbing ();
}

~RemotingBase()
{
StopProbing();
}


#region Methods for Tracking Handler

private void StartProbing ()
{
if (bProbingStarted != true)
{
StartRemoteServerTrackingHandler ();
bProbingStarted = true;
}
}


private void StopProbing ()
{
if (bProbingStarted == true)
{
StopRemoteServerTrackingHandler ();
bProbingStarted = false;
}
}


private void StartRemoteServerTrackingHandler ()
{
trkHndlr = new TrackingHandler();
TrackingServices.RegisterTrackingHandler (trkHndlr);
}


private void StopRemoteServerTrackingHandler()
{
if (null != trkHndlr)
{
TrackingServices.UnregisterTrackingHandler (trkHndlr);
}
}
................
}

Thanks and Regards,
Venkat
Allen Anderson
8/24/2005 4:00:03 PM
that original post was by me a long time ago before I learned more on this subject. I wrote an article about the solution I came to here

http://www.glacialcomponents.com/ArticleDetail.aspx?articleID=CAOMN

not sure if that will solve all your problems but that's how I did it.

-Allen


[quoted text, click to view]
Henry Willsun
8/25/2005 12:00:00 AM
Hi,

If third party solutions are Ok for you, you can take a look at Genuine
Channels (www.genuinechannels.com)

Regrds,
Henry.

[quoted text, click to view]

Venkatasubramanian Narasimhan
8/28/2005 3:48:54 AM

Thanks Allen. It was of great help.

This is what I did to get around the problem by making use of the
Tracking handler.

1. Since my remote application was hosted in IIS I included the
global.asax and took advantages of the events therein.
a. A Tracking handler is registered in the Application_Start event

protected void Application_Start(Object sender, EventArgs e)
{
TrackingServices.RegisterTrackingHandler(new TrackingHandler());
}

b. The Client IP is captured in the Application_BeginRequest event and
added to the remoting call context.The IP captured here is used in the
Tracking handler to determine whether the client machine accessing the
server application is internal to the LAN or an external machine.

protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
string ipAddress = context.Request.UserHostAddress.ToString();
System.Runtime.Remoting.Messaging.CallContext.SetData("ObservedIP",ip
Address);
}


2. Added a couple of keys to the web.config which is used in the
Tracking handler.
<!--IPExclusionList is a comma seperated list of INTERNAL IPs to be
excluded from the transformation in the Tracking handler-->
<add key="IPExclusionList" value="162.,127.0.0.1"/>

<!ExternalIP is the EXTERNAL IP used for the transformation in the
Tracking handler, if the client is an external client as inferred from
the exclusion list-->
<add key="ExternalIP" value="202.xxx.yyy.zz"/>

3. And finally the Tracking Handler

public class TrackingHandler : ITrackingHandler
{
private const string IPExclusionList = "IPExclusionList";
private const string ExternalIP = "ExternalIP";

public void MarshaledObject(Object obj, ObjRef or)
{
try
{
string ObservedIP =
Convert.ToString(CallContext.GetData("ObservedIP"));
string sExclusionList = String.Empty;
string []arrExclusionList;
bool isExcludedIP = false;
string strAddress = String.Empty;


if (ObservedIP == null || ObservedIP == String.Empty)
return;

if (or.ChannelInfo == null)
return;

if
(System.Configuration.ConfigurationSettings.AppSettings[IPExclusionList]
!= null)
{
sExclusionList =
System.Configuration.ConfigurationSettings.AppSettings[IPExclusionList].
ToString();
}
else
{
return;
}

if
(System.Configuration.ConfigurationSettings.AppSettings[ExternalIP] !=
null)
{
strAddress =
System.Configuration.ConfigurationSettings.AppSettings[ExternalIP].ToStr
ing().Trim();
}
else
{
return;
}

if (sExclusionList.Trim() != String.Empty)
{
arrExclusionList = sExclusionList.Split(',');
for(int i = 0; i < arrExclusionList.Length; i ++)
{
if(ObservedIP.IndexOf(arrExclusionList[i].Trim(),0) != -1)
{
isExcludedIP = true;
break;
}
}
}

if( !isExcludedIP && strAddress != String.Empty)
{
for ( int i = or.ChannelInfo.ChannelData.GetLowerBound(0);
i <= or.ChannelInfo.ChannelData.GetUpperBound(0); i++ )
{
// Check for the ChannelDataStore object that we don't want to
copy
if(or.ChannelInfo.ChannelData[i] is ChannelDataStore)
{
foreach(string uri in
((ChannelDataStore)or.ChannelInfo.ChannelData[i]).ChannelUris)
{
// this will get the first part of the uri
int nOffset = uri.IndexOf( "//" ) + 2;
string strNewUri = uri.Substring( 0, nOffset );
strNewUri += strAddress;
nOffset = uri.IndexOf( ":", nOffset );
strNewUri += uri.Substring( nOffset, uri.Length - nOffset );
string[] strarray = new string[1] { strNewUri };
ChannelDataStore cds = new ChannelDataStore( strarray );
or.ChannelInfo.ChannelData[i] = cds;
}
}
}
}

}

public void UnmarshaledObject(
object obj,
ObjRef or
)
{
}

public void DisconnectedObject(
object obj
)
{
}
}


Allen Anderson
8/31/2005 10:46:32 AM
excellent, glad that worked for you.

[quoted text, click to view]
Allen Anderson
8/31/2005 1:12:35 PM
no it's a problem with SAO and CAO. The solution I came up with was only applicable for CAO's but I'm told by many who implemented a solution based off my original article that they were able to make it work with SAO's as well.

-Allen
http://www.glacialcomponents.com
http://allenanderson.blogspot.com

[quoted text, click to view]
Ice
8/31/2005 1:48:25 PM
is this only a problem with CAO?

ice
[quoted text, click to view]

Ice
8/31/2005 5:12:53 PM
ok, i thot as much. was just checking.

ice
[quoted text, click to view]
applicable for CAO's but I'm told by many who implemented a solution based
off my original article that they were able to make it work with SAO's as
well.
[quoted text, click to view]

AddThis Social Bookmark Button