Message ClientID keeping or generating new value. (.Net clients)

Hi guys,
Using Delphi Tokyo and version 9.4.109.1377. Same version on .net clients.

Server side is built with Delphi using Olympia and SuperTCP indy, with clients on .net and delphi.

There is a central service that all services/clients use to login into the infrastructure. Built on Delphi and another service use to send notifications, built on Delphi, both of them use Olympia so they can share sessions.

This problem is not happening with the Delphi clients, only .Net ones. It goes like these:

When service/program starts two proxies for services (a login one and notifications) are created and each of them has a message object/interface on them. If I review the proxies both of them have different message client ids. Thats fine.

After logging in, I pass down the Session Id directly from the session object from the delphi server, in good theory it should match the clientid of the message object from the login service, but in any case I overwrite it with the one coming back from the server. I change the ClientId on both message objects for both proxies.

When I use a Delphi Notification service proxy a notification goes out, notification service receives it, it is plugged to Olympia, he sees the GUID, it exists, does its thing.

When I use a .Net version of the same proxy, I can see how the message object has the client id obtained from the session but for some reason it reaches to the Delphi server with a different id. Most probably the original or a regenerated one.

Funny enough, if I disconnect the client and let it reconnect, I can see on the server how the guid being reported as being reconnecting is not the session id I overwrite but the same as the one that the server complaints is not found originally.

Ive spent several days looking for the moment these Ids are changing with no avail. Everywhere it seems to be respecting the change but once goes into the .net internals of RO, the original value might not be changed, or a new GUID is generated and things stop working.

We create the Delphi and .Net clients getting the best match message and transport for a given URI using the provided methods and we keep both channel and message as singleton per service on the client program so they can be reused on service proxies or even remote services. We do not pass a uri and let it generate everytime because we want to reuse the connection for events, identify specifically the clients, etc.

Proxies are created transient and they receive as parameters the message and channel singletons. So the only singleton aspect of it is the message and channel.

Could it be that on the proxy creation the id is stored somewhere and doesnt get change? The Delphi side of things works fine, i’ve spent days figuring out why the ID keeps changing on the .net side.

Any assistance will be a blessing.

Thank you.

Hi,

SuperTCP clients channels have the ClientId property (In .NET, it was named as ClientGuid) that overrides Message.ClientID.
can you check, that you have set it to correct value?

Hola Evgeny,

That’s confusing, I thought we use the Message client id as the GUID to be used on the Server side. From Delphi’s clients I just change the ClientID property on the Message.

The IMessage and even the concrete class BinMessage (.Net) expose a property called ClientID, just like Delphi so I overwrite that one. I dont do it on the channel, does it make a difference?

I’ll try your suggestion, is not like i have lots of options left :(.

I’ll have to cast the class on the interface cause IClientChannel doesnt exposed the property which makes the solution not very generic for other channels unless I manually specify them but oh well, desperation.

Hi,

in Delphi we have

    if (aMessage <> nil) and IsEqualGUID(ClientID, EmptyGUID) then
      ClientID := aMessage.ClientID;

so channel uses Message.ClientID if his ClientID wasn’t initialized. In .NET it may be implemented differently

Unfortunately there’s not much options left.

While this behavior is clearly an oversight and we’ll fix it for the next release, for the current one there’s no other option than to explicitly set the ClientGuid property

1 Like

Thanks, logged as bugs://82225

Thanks, logged as bugs://82226

OMG!

Kids will tell stories about the legendary Evgeny who guide us through the valley of darkness and show us the light at the end of the road.

It seems to be working altering the channel one. ClientGUID seems to be only available on ipsupertcp concrete implementation, it is not used on http channels or any other channel in .net? (gotta love the options we have on Delphi), what are our options on those channels?

Also on the .Net version assigning one channel to match the other one at creation will not work. It seems that right after validating the session, the guid gets overwritten so the assignment has to be done after logging in. This kill possible DI solutions (e.g. ninject) but seems to be the only valid solution.

1 Like

Thank you Anton, I’ll use the channel on the .net side of things until the next version. I’m just happy it got resolved i spin waaaay too much on this one. :slight_smile:

What do you mean here? I’ve tried the SuperTCP chat sample and there GUID assigned to the channel property was used as the session id server-side.

SuperHttp has the same property under different name (namely ConnectionID - a thing to fix as well)

It seems that when the channel and the message are created. The channel clientGuid gets a {000…00} guid, the message gets a new Guid.

So if I assigned all the client service channels guid to use the one from the client service used to log in, at creation (and before i logged in), it will assigned them {00…00} and then after logging it seems it will overwrite it and I’ll be forced to manually set them after that to have all the client service channels to match this new generated guid.

But If I manually set the GUID of the channel right after creation it will work. I think the client proxy on .net does something similar for the message channel and the delphi clients will do it too and because of the code Evgeny pasted it gets propagated to match the channel one, not having this issue.

On the .net one, the message will have an id, the channel will not and things will get kind of even out after logged in. Probably with your fixes it will get addressed.

Tat’s a new/fixed behavior of the SuperTCP channel:

A new property has been added to the SuperTCP client channel named ClientID . This property contains the ID of the connection between client and the server. Its value matches to the one used on the remote server as a Session ID. If the value of this property is not set explicitly then the channel is opened then its value will be borrowed from the message’s ClientID property or auto-generated based on the following logic:

  • If the channel is opened via an explicit call to the corresponding method/setting the Active property to true then channel ClientID property value is used. If this value is not set then an auto-generated Client ID is used.
  • If channel is opened implicitly during a remote server method and channel ClientID property is not set then the message CientID property value is used. If it is not set as well then an auto-generated Client ID is used.

Also the value of this property cannot be changed once the server connection is opened. An InvalidOperationException will be raised on any attempts to do so.

Existing ClientGuid property has been marked as Obsolete and will be removed in subsequent releases.

1 Like

Awesome Anton, thank you very much.

I’ll assume something similar happened to the superhttp client connection. Also, is this property reflected on the Interface IClientChannel? or we need to cast the interface to the underlying object?

SuperHTTP - not yet, it is in the work right now

You don’t need to perform cast / asses this property on the channel level anymore. Just set a ClientID for the Message instance and the channel will use it

1 Like

Is the message object on the .Net clients thread safe?

I’m saying this because we currently create the channel and the message as singletons for each service so we can identify the clients using the service. The channel (superxxxx) I will assume is thread safe, but the message, at least on the Delphi side seems not to be.

If thats the case, I will have to use the client id on the channel (casting) instead of the message and everytime i create an instance of the client proxy and create the message too. Am I correct?

Starting with v9.5 message instances are cloned by default when a remote server call is performed.

This behavior can be disabled via the CloneMessage property of the service proxy class, however it is strongly not advised to do.

At the same time concrete Message instances are NOT thread safe, i.e. it is not safe to use the same message instance from different threads simultaneously to write or read data.

bugs://82225 got closed with status fixed.

bugs://82226 got closed with status fixed.