just a short ping on this issue. Would be great if you could
manage to look at my issue.
Thanks!
Hi Peter
Im out of town until next week and will respond properly then
Scott
From: "Peter Hermsdorf" <peter.hermsdorf@xxxxxxxxx>
Date: Fri, Jun 29, 2018 12:09 am
To: ecf-dev@xxxxxxxxxxx
Subject: Re: [ecf-dev] Problem with Service Endpoint matching when using different network names
Hi Scott,
thanks for your suggestions.
I'm afraid to say that this does not solve all issues for us.
If i understand you correct, you were describing different ways to change the service endpoint on the server to match the one that the client uses to connect to the exported service on the server.
The problem is, we have setups where different client machines use different network names to connect to the same server instance. e.g.. clients in the local network of the server can use a local DNS to connect to the server by a locally known host name. We have other clients connecting via a remote network (VPN tunnel) and sometimes we can't use the local DNS setup trough that tunnel, but just the IP address or a completely different hostname for network configuration reasons.
I think what we need is a completely hostname (and port) agnostic way to match the service endpoints between the client and the server.
In other words: one thing is to define the network target (by hostname or IP and port) and the other thing would be to match the remote service once the client and server are connected by network (via the service name and version etc.).
I'm willing to implement some code to do that, if you could point me in the right direction....
Thanks! Bye Peter
Am 21.06.2018 um 19:14 schrieb Scott Lewis:
Hi Peter,
On 6/21/2018 2:08 AM, Peter Hermsdorf wrote:
Hi,
I need to bring up a issue that was already discussed earlier, eg.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=419744
and here
http://dev.eclipse.org/mhonarc/lists/ecf-dev/msg08047.html
The issue is, that in our setup, the service matching is not working when accessing the remote server using a different hostname than the machine uses itself (a little hard to express as non native speaker ;) see ENDPOINT definition below)
Scott's last comment on the problem was to get more information about our use case and environment so I'll try to provide the required information
* we have a lot of clients using remote services from one application server
* we use the ecf generic provider.
* the remote service "discovery" is done by generating an EndpointDescription on client side, as all clients know by configuration which server to speak to. We use something like this to define the service endpoint:
props.put(ENDPOINT_ID, "ecftcp://" + host + ":8889/server");
where host is the hostname or IP address under which the client can access the remote server - which is not necessarily the hostname or IP which is configured at the server itself (which is exactly the issue). So eg. the server is exporting the service under endpoint
ecftcp://myhostname.company.local:8889/server
whereas the client needs to access the server eg. by using
ecftcp://otherhostname.public.net:8889/server or by ecftcp://192.168.0.100:8889/server
as endpoint id.
and even case sensitivity does matter: Some Windows machines (for whatever reason) have hostnames like MYHOSTNAME.company.local. Clients then are required to use the exact hostname with the correct upper/lowercase to access the server.
* the remote services are imported on client side via
remoteServiceAdmin.importService(endpointDescription);
* the remote services are exported on server side using DS with additional properties, like:
@Component(immediate = true, property = {
"service.exported.interfaces=*",
"service.exported.configs=ecf.generic.server",
"ecf.generic.server.port=8889" })
public class MyserviceService implements IMyService {
* on server side we have a custom implementation of IHostContainerSelector which allows us to override
protected IRemoteServiceContainer createRSContainer
to add a custom RegistrySharedObject which customizes error handling ("exception to String serialization")
That's it i think.
So getting rid of the hostname part in the endpoint description and/or when matching would probably solve the problem...
Thanks for any hints on this issue!
Ok, thanks for the description of the issue. For this use case: i.e. hostname used by clients that are different from the bind address for the server...i.e. client wants to use:
otherhostname.public.net
and the server needs to expose/listen on this interface:
myhostname.company.local (or rather the ip address if the interface for this name)
For the generic provider, here are the remote service configuration properties
https://wiki.eclipse.org/ECF_Generic_Provider_Configuration_Properties#Remote_Service_Configuration_Properties
For the *external* address/name these are the relevant properties:
ecf.generic.server.hostname = otherhostname.public.net
ecf.generic.server.port = 8889
ecf.generic.server.path = /server
for example, these values will result in an external name of: ecftcp://otherhostname.public.net:8889/server. For the generic provider the name of the container and the external name must match.
There is also a service property:
ecf.generic.server.bindAddress = InetAddress.getByName("myhostname.company.local")
or InetAddress.getByName("13.91.95.74")...with your actual IP.
The bindAddress property ultimately specifies the *address that is passed to this ServerSocket constructor to listen on for the ecftcp server:
new ServerSocket(port, backlog, bindAddress)
https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#ServerSocket(int,%20int,%20java.net.InetAddress)
So I think the solution for your use case is to use all four of these service properties set appropriately...e.g.:
ecf.generic.server.hostname = otherhostname.public.net
ecf.generic.server.port = 8889
ecf.generic.server.path = /server
ecf.generic.server.bindAddress = InetAddress.getByName("myhostname.company.local")
Since I don't currently have access to a dual-homed server I haven't been able to test this fully, but really the only thing it does is to pass the bindAddress to the ServerSocket, rather than using the default ('0.0.0.0')...which is all interfaces.
I realize now that the use of the InetAddress instance in the service properties is a little clumsy...it would be better if it could also take a String...e.g.:
ecf.generic.server.bindAddress=myhostname.company.local
If the above works for you/your use case, I'll add this (support of String as well as InetAddress) in a new enhancement for 3.14.1.
BTW...since you are overriding the HostContainerSelector for another purpose, you could pass the bindAddress (and the other properties explicitly by overriding AbstractContainerSelector.createContainer, or AbstractContainerSelector.getContainerFactoryArguments. Be a little careful with this, however, as these methods are responsible for doing the RSA-specified handling of service properties (e.g. the ecf.generic.server. prefix is stripped off before the hostname, port, path, bindAddress are passed to the container instantiator as per RSA).
Another way to accomplish the above would be to also use the RemoteServiceAdmin on the server-side (in addition to the import/client side). i.e. you can explicitly export a service with:
RemoteServiceAdmin.exportService(ServiceReference,Map<String,?> overridingProperties);
The exportService is usually done by the BasicTopologyManager when a remote service is registered with a call to:
RemoteServiceAdmin.exportService(ref, null)
but you can do it yourself programmatically at any time after registration via the exportService. Note the overridingProperties...that allows you to set any properties you want (e.g. your four and the required service.exported.interfaces) that will be used to configure the server container, but then it doesn't require any properties set via @Component. This might be more convenient for you/your use case, since you may not want to have all of the properties and their values hard coded in the @Component metadata. With exportService you can also do things like use config admin to config your exports rather than putting app-specific info in the @Component properties.
The more that I think about it, the less I think you should look to override the HostContainerSelector...and rather use RemoteServiceAdmin.exportService if you need/want to do things programmatically on the export side.
Best regards,