Help with proper solutions to remoting problems
I'm going to shortly write what I want to do, the problems / questions I'm facing with the design descisions and the information I can't seem to find.
The goal is a client-server chat solution. A client gets a security object from the server, calls a function to verify who he / she is and hopefully the function will return a MarshalByRefObject from the server which represents what the client can do on the server.
I've seen tons of examples of a client marshaling a remote object from servers and calling its functions, but never once have I seen the server asking the client for an object as well by which it can communicate back.
Is it just me that finds polling a boolean on the server to see if there are message for me to download to be a bad design choice (to put it lightly)?
Is it possible for the client to send a class that inherits MarshalByRefObject to a function on the server interface (without having registered it as for example a well-known type), giving the server means to communicate back? Even if it's a class and it doesn't inherit MarshalByRefObject, will the class be marshaled to the server by means of MarshalByValue instead unless I specifically specify MarshalByRefObject; regardless of what type of object it is?
Let's say, for arguments' sake that the client has a server interface and the server has gotten a client interface sent to it. How, now, is it possible for me to know if that specific client times out, disconnects, gets hit up by a nuclear explosion?
What I've browsed and seen is that I can create a class that inherits ITrackingHandler and register it to the remoting channel, and such, be aware of when an object is marshaled, unmarshaled and/or disconnected. Question is, the functions receives an object and ObjByRef object, but how do I know which client it was that got disconnected? The object is most likely going to be the interface to the server singleton. Maybe I should check if the object is one of the MarshalByRefObject classes which clients have sent to the server and ignore the others?
Of course the client must also know if it has lost it's connection to the server, and such, should also register and implement the ITrackingHandler?
Hopefully by now you'll see my dilemma, what information / knowledge i'm missing and what it is that I want to create. I'm looking forward to reading your replies of wisdom and patience.
-- Update --
While waiting for replies I descided to go ahead and try some of my theories and questions. I created a server and client. Because i'm lazy i descided to just let the ServerForm class be the ISecurity and IServer remoting objects. I've registered my ISecurity interface and I can fetch it from the client side. The problem is when I call the super function:
IServer SignIn(IClient client)
whose purpose is to give the clients form in the form if a IClient and retrieve the ServerForm as a IServer. The function fails with a glorious SecurityException from the serializer. So, question is, is it because i'm passing the function the IClient object or trying to return the IServer object.
I'll keep on testing and updating this post in the mean time.
-- Update #2 --
The source of the problem wasn't with the function returning "this" as a IServer. The cause of the SecurityException was when i was trying to pass the ClientForm : IClient to the function as a parameter. Does anyone have a theory as to why this is so? Maybe it's because I haven't registered any types on the client for the server to marshal, but the reason for doing that is, well, the server doesn't know which client it'll be marshalling the item from? I don't know...
-- Update #3 --
I found an article on the matter, but they were doing the same thing as me and well, they don't mention any Can't access type System.Runtime.Remoting.ObjRef due to security reasons problems.
http://support.microsoft.com/kb/307600
I tried creating an empty class that inherited from IClient and MarshalByRefObject but i still get the same Security exception. This is my own machine, i'm admin, full rights, i even turned the channel security off but i still get the same exception. Maybe it's because of how my server registers it's IServer object but i doubt it.
RemotingServices.Marshal(this, "Security");
If i pass null instead of a IClient object then everything works, i can talk to the server using the IServer interface.
-- Update #4 --
I've been searching frantically for information. Apparently security was tightened after .Net 1.0 regarding serialization and remoting. The funny thing though, is that the article above is from 2007 and well .Net 2.0 has been around longer than that.
I found this example and placed it on the client side since it's there that i'm having problems:
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = TypeFilterLevel.Full;
Hashtable props = new Hashtable();
props.Add("port", "49201");
channel = new TcpChannel(props, null, provider);
ChannelServices.RegisterChannel(channel, true);
security = (ISecurity)RemotingServices.Connect(typeof(ISecurity), "tcp://localhost:49200/Security");
server = security.SignIn(this);
But this didn't solve my problem, i'm pretty much just grasping at whatever information i can find and trying different solutions.
-- Update #5 --
By placing the above code in both the client and server i was able to send the IClient object over to the server. Removing the custom BinaryServerFormatterSinkProviders results in exceptions or such. Now, if only a wise and experienced person would tell me why this was all neccessary and what it means it would be lovely and we could get back to the primary questions at the top.
Reading up more and more on what i've done makes me want to undo it, thinking of a better and safer way. One way that I would like to implement would be for the server to Marshal an object from the client, but the question i have then is, how can the server ask a specific client for an object? The examples that I've seen have all been regarding 1:1 conditions between a server and client.

