Comment 2 for bug 1012788

Revision history for this message
Jeff Hill (johill-lanl) wrote :

Hi Till,

Thanks for your efforts!

o I can imagine two programs using this facility in the same program simultaneously. For example, in the IOC
we might have both ca and asyn using it and need to configure the proxy address independently for both entities.

Perhaps what you should do is change the API so that the cac class constructor creates a proxy
create agent using a global factory that requires the EPICS
environment variable as its sole parameter. That way we can have EPICS_CA_SOCKS_PROXY and
ASYN_SOCKS_PROXY (or whatever the correct name is with asyn) in use at the same time. This approach would also
address my second bullet below. Once we we have created a proxy connect agent them it can be invoked in
tcpiiu.cpp each time that we connect w/o needing to pass in parameters.

(void) pProxyConnect->connect(); /* exception thrown on failure */

Of course the above API is C++. You can of course get the same thing in C as follows (if you prefer that).

extern NetworkProxy * epicsNetworkProxyCreate ( const ENV_PARAM * );
extern int epicsNetworkProxyConnect ( NetworkProxy * );
extern void epicsNetworkProxyDestroy ( NetworkProxy * );

Of course we would probably need to pass in the address of the connect proxy when creating a tcpiiu, and
cache that address within tcpiiu, but only ~cac would destroy the connect proxy.

o The epicsDefaultSocksProxySelector API returns a pointer to a shared structure which isn't released by the caller. This can cause concurrency issues later on if this structure was changing and multiple threads are using it simultaneously? Its a little more overhead but IMHO a better option would be just to return the structure by value, or better yet have the caller pass the address of the destination structure for the proxy's address. Furthermore, if the epicsSocksProxySelect just wraps back the destination address, which is passed in, then when there is no proxy we can simplify the code below, and have no if test to see if the returned structure is nill and also only one call to connect. The ca client code currently uses the osiSockAddr union defined in osiSock.h to wrap socket addresses so that we can have some flexibility wrt to different address structures in the future.

+ if ( ! ( proxy = epicsSocksProxySelect(addr, &desVers) ) ) {
+ return connect( sockfd, addr, addrlen );
+ }
+
+ /* Connect to proxy */
+ if ( (rval = connect( sockfd, proxy, sizeof(*proxy)) ) ) {
+ epicsSocketConvertErrnoToString(buf, sizeof(buf));
+ errlogPrintf("epicsConnectViaProxy() -- Unable to connect to proxy: %s\n", buf);
+ return rval;
+ }