Hello,
Let’s assume I’ve got multiple RemObjects SDK services (as in separate executables, not RODL services) built as stand-alone Delphi VCL services (as in the Windows services concept) all running on the same Server. I’d like all services to be accessible through one single TCP Port on that Server: For my target audience configuring multiple routers and firewalls to allow access to multiple ports on the same system would be a deal-breaker. At the moment I’m using a simple client-server architecture where the SQL service runs on the Server and everyone connects to that single SQL service. This requires only one TCP port to be opened, and even that proves difficult at times. I guess a good name for what I’m trying to do is PROXY: I’d like to create a PROXY server that redirects all requests to services (as in other executable processes) that can actually handle the requests.
For analogy, if the Server was running a Web server (IIS or Apache), my multiple services would be CGI Servers, or Apache modules, or ISAPI modules installed in different directories of the server or accessed as name-based virtual servers. Externally they’d only use one port (most likely the HTTP port) so all firewalls and routers would only need to be configured to allow access to that one port. In this example the server opening the TCP port (IIS or Apache) knows practically nothing about what each individual service is going to do.
I’m hoping there’s a way to implement this as a RemObjects-SDK based solution so I’d get the opportunity to use other channels beyond HTTP: At a minimum I’d like to use both an IndyTCP-based channel and a HTTP-channel; The HTTP would be used if the IndyTCP can’t get through (for example from the Internet). The connection from this RemObjects SDK server to the real implementation would go over whatever channel is most efficient and easier to implement. For example a named-pipe channel: that would not interfere with AV software the client might have on that Server.
The solution I’ve attempted right now for the proxy server involves a fake class factory (something that implements IROClassFactory_ZeroConfig and says it can handle anything) and a IROInvoker that attempts dispatching the message to an other server, without trying to understand the message. So far it’s failing on the Real server when the real server tries to read the InterfaceName from whatever it receives. I’m going to hammer this a bit more as I think it might work, but I’m thinking of alternative implementations as well:
-
Maybe I should write a Channel implementation? This might allow me to use something HTTP or TCP based for the leg between the Client application and the Proxy server, then switch to something else (the mentioned Named Pipe) for the final leg to the Real server.
-
Maybe I should use a SOCKS proxy? I don’t particularly like this, but it can be done with off-the-component-palette components and it allows my multiple servers to be separate processes. First of all I don’t like this because it forces me to use a TCP-based channel for the connection to the Real server, can’t use Named Pipes.
-
Maybe I should give the HTTP Server based solution a bit more thought? It’d be very hard as my multiple services absolutely need to be separate processes. They can’t all load into the same process (as Apache modules would). And configuring multiple app domains in ISS doesn’t look like the kind of job my target audience would handle.
P.S: Here’s the code I’ve got in my proxy IROInvoker; I guess this is the most important piece of code in my attempted implementation:
function TFakeInvoker.HandleMessage(const aFactory: IROClassFactory; const aMessage: IROMessage; const aTransport: IROTransport; out oResponseOptions: TROResponseOptions): boolean;
var Ch: TROWinInetHTTPChannel;
begin
Ch := TROWinInetHTTPChannel.Create(nil);
try
Ch.TargetURL := ‘http://127.0.0.1:8098/bin’;
(Ch as IROTransportChannel).Dispatch(aMessage);
finally Ch.Free;
end;
end;
Thank you,
Cosmin Prund