Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017 
<== Date ==> <== Thread ==>

Subject: [Merge] lp:~anj/epics-base/cas-intf-addr-list into lp:epics-base
From: Andrew Johnson <anj@aps.anl.gov>
To: mp+209803@code.launchpad.net
Date: Thu, 06 Mar 2014 22:29:44 -0000
Andrew Johnson has proposed merging lp:~anj/epics-base/cas-intf-addr-list into lp:epics-base.

Requested reviews:
  EPICS Core Developers (epics-core)

For more details, see:
https://code.launchpad.net/~anj/epics-base/cas-intf-addr-list/+merge/209803

Partially support EPICS_CAS_INTF_ADDR_LIST in rsrv.

This branch parses the environment parameter into a new global ELLIST.
If the resulting list is empty it adds a single entry of INADDR_ANY.
A warning message is printed if the list contains multiple entries.
The TCP and UDP servers then bind to the first entry in the list.

This approach can be extended to handle multiple entries in the future.

Did I miss anything?

-- 
https://code.launchpad.net/~anj/epics-base/cas-intf-addr-list/+merge/209803
Your team EPICS Core Developers is requested to review the proposed merge of lp:~anj/epics-base/cas-intf-addr-list into lp:epics-base.
=== modified file 'documentation/RELEASE_NOTES.html'
--- documentation/RELEASE_NOTES.html	2014-02-21 21:49:15 +0000
+++ documentation/RELEASE_NOTES.html	2014-03-06 22:28:58 +0000
@@ -15,6 +15,13 @@
 <h2 align="center">Changes between 3.15.0.1 and 3.15.0.2</h2>
 <!-- Insert new items immediately below here ... -->
 
+<h3>Implement EPICS_CAS_INTF_ADDR_LIST in rsrv</h3>
+
+<p>The IOC server can now bind to a single IP address (and optional port number)
+read from the standard environment parameter EPICS_CAS_INTF_ADDR_LIST.
+Additional addresses included in that parameter after the first will be ignored
+and a warning message displayed at iocInit time.</p>
+
 <h3>Added echo command to iocsh</h3>
 
 <p>The single argument string may contain escaped characters, which will be

=== modified file 'src/ca/client/CAref.html'
--- src/ca/client/CAref.html	2013-11-07 23:57:09 +0000
+++ src/ca/client/CAref.html	2014-03-06 22:28:58 +0000
@@ -796,7 +796,7 @@
     </tr>
     <tr>
       <td>EPICS_CAS_BEACON_ADDR_LIST</td>
-      <td>{N.N.N.NN.N.N.N:P...}</td>
+      <td>{N.N.N.N N.N.N.N:P ...}</td>
       <td>EPICS_CA_ADDR_LIST<sup>1</sup></td>
     </tr>
     <tr>
@@ -811,12 +811,12 @@
     </tr>
     <tr>
       <td>EPICS_CAS_INTF_ADDR_LIST</td>
-      <td>{N.N.N.NN.N.N.N:P...}</td>
+      <td>{N.N.N.N N.N.N.N:P ...}</td>
       <td>&lt;none&gt;</td>
     </tr>
     <tr>
       <td>EPICS_CAS_IGNORE_ADDR_LIST</td>
-      <td>{N.N.N.NN.N.N.N:P...}</td>
+      <td>{N.N.N.N N.N.N.N:P ...}</td>
       <td>&lt;none&gt;</td>
     </tr>
   </tbody>
@@ -874,8 +874,13 @@
 addresses in EPICS_CAS_INTF_ADDR_LIST and also to the broadcast addresses of
 the corresponding LAN interfaces will be accepted by the server. By default,
 the CA server is accessible from all network interfaces configured into its
-host. <em>In R3.14 and previous releases the CA server employed by iocCore does
-not implement this feature</em>.</p>
+host.</p>
+
+<p>In R3.14 and previous releases the CA server employed by iocCore did not
+implement the EPICS_CAS_INTF_ADDR_LIST feature. In this release the iocCore
+server will read the first IP address from the parameter variable and use that
+to select which interface to bind to. Any additional IP addresses will be
+ignored and a warning message displayed during IOC initialization.</p>
 
 <h4>Ignoring Process Variable Name Resolution Requests From Certain Hosts</h4>
 

=== modified file 'src/ioc/rsrv/caservertask.c'
--- src/ioc/rsrv/caservertask.c	2012-07-17 19:36:34 +0000
+++ src/ioc/rsrv/caservertask.c	2014-03-06 22:28:58 +0000
@@ -63,8 +63,9 @@
     unsigned priorityOfSelf = epicsThreadGetPrioritySelf ();
     unsigned priorityOfBeacons;
     epicsThreadBooleanStatus tbs;
+    osiSockAddrNode *pNode;
     struct sockaddr_in serverAddr;  /* server's address */
-    osiSocklen_t addrSize;
+    osiSocklen_t addrSize = (osiSocklen_t) sizeof(struct sockaddr_in);
     int status;
     SOCKET clientSock;
     epicsThreadId tid;
@@ -85,6 +86,24 @@
             (unsigned short) CA_SERVER_PORT );
     }
 
+    addAddrToChannelAccessAddressList ( &casIntfAddrList,
+        &EPICS_CAS_INTF_ADDR_LIST, ca_server_port, 0 );
+    if (ellCount(&casIntfAddrList) == 0) {
+        pNode = (osiSockAddrNode *) calloc ( 1, sizeof(*pNode) );
+        pNode->addr.ia.sin_family = AF_INET;
+        pNode->addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
+        pNode->addr.ia.sin_port = htons ( ca_server_port );
+        ellAdd ( &casIntfAddrList, &pNode->node );
+    }
+    else {
+        if (ellCount ( &casIntfAddrList ) > 1)
+            epicsPrintf ("CAS: Multiple entries in EPICS_CAS_INTF_ADDR_LIST, "
+                "only the first will be used.\n");
+        pNode = (osiSockAddrNode *) ellFirst ( &casIntfAddrList );
+    }
+
+    memcpy ( &serverAddr, &pNode->addr.ia, addrSize );
+
     if (IOC_sock != 0 && IOC_sock != INVALID_SOCKET) {
         epicsSocketDestroy ( IOC_sock );
     }
@@ -100,50 +119,43 @@
 
     epicsSocketEnableAddressReuseDuringTimeWaitState ( IOC_sock );
 
-    /* Zero the sock_addr structure */
-    memset ( (void *) &serverAddr, 0, sizeof ( serverAddr ) );
-    serverAddr.sin_family = AF_INET;
-    serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);
-    serverAddr.sin_port = htons ( ca_server_port );
-
     /* get server's Internet address */
-    status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) );
-	if ( status < 0 ) {
-		if ( SOCKERRNO == SOCK_EADDRINUSE ) {
-			/*
-			 * enable assignment of a default port
-			 * (so the getsockname() call below will
-			 * work correctly)
-			 */
-			serverAddr.sin_port = ntohs (0);
-			status = bind ( IOC_sock,
-                (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) );
-		}
-		if ( status < 0 ) {
+
+    status = bind(IOC_sock, (struct sockaddr *) &serverAddr, addrSize);
+    if ( status < 0 ) {
+        if ( SOCKERRNO == SOCK_EADDRINUSE ) {
+            /*
+             * enable assignment of a default port
+             * (so the getsockname() call below will
+             * work correctly)
+             */
+            serverAddr.sin_port = ntohs (0);
+            status = bind(IOC_sock, (struct sockaddr *) &serverAddr, addrSize);
+        }
+        if ( status < 0 ) {
             char sockErrBuf[64];
             epicsSocketConvertErrnoToString (
                 sockErrBuf, sizeof ( sockErrBuf ) );
             errlogPrintf ( "CAS: Socket bind error was \"%s\"\n",
                 sockErrBuf );
             epicsThreadSuspendSelf ();
-		}
+        }
         portChange = 1;
-	}
+    }
     else {
         portChange = 0;
     }
 
-	addrSize = ( osiSocklen_t ) sizeof ( serverAddr );
-	status = getsockname ( IOC_sock,
-			(struct sockaddr *)&serverAddr, &addrSize);
-	if ( status ) {
+    status = getsockname ( IOC_sock,
+            (struct sockaddr *)&serverAddr, &addrSize);
+    if ( status ) {
         char sockErrBuf[64];
         epicsSocketConvertErrnoToString (
             sockErrBuf, sizeof ( sockErrBuf ) );
-		errlogPrintf ( "CAS: getsockname() error %s\n",
-			sockErrBuf );
+        errlogPrintf ( "CAS: getsockname() error %s\n",
+            sockErrBuf );
         epicsThreadSuspendSelf ();
-	}
+    }
 
     ca_server_port = ntohs (serverAddr.sin_port);
 
@@ -274,6 +286,7 @@
         }
     }
     freeListInitPvt ( &rsrvLargeBufFreeListTCP, rsrvSizeofLargeBufTCP, 1 );
+    ellInit ( &casIntfAddrList );
     ellInit ( &beaconAddrList );
     prsrv_cast_client = NULL;
     pCaBucket = NULL;
@@ -948,16 +961,16 @@
 
 void casStatsFetch ( unsigned *pChanCount, unsigned *pCircuitCount )
 {
-	LOCK_CLIENTQ;
+    LOCK_CLIENTQ;
     {
         int circuitCount = ellCount ( &clientQ );
         if ( circuitCount < 0 ) {
-	        *pCircuitCount = 0;
+            *pCircuitCount = 0;
         }
         else {
-	        *pCircuitCount = (unsigned) circuitCount;
+            *pCircuitCount = (unsigned) circuitCount;
         }
         *pChanCount = rsrvChannelCount;
     }
-	UNLOCK_CLIENTQ;
+    UNLOCK_CLIENTQ;
 }

=== modified file 'src/ioc/rsrv/cast_server.c'
--- src/ioc/rsrv/cast_server.c	2009-07-09 16:37:24 +0000
+++ src/ioc/rsrv/cast_server.c	2014-03-06 22:28:58 +0000
@@ -115,23 +115,14 @@
  */
 void cast_server(void *pParm)
 {
-    struct sockaddr_in  sin;    
+    osiSockAddrNode     *paddrNode;
+    struct sockaddr_in  sin;
     int                 status;
     int                 count=0;
     struct sockaddr_in  new_recv_addr;
     osiSocklen_t        recv_addr_size;
-    unsigned short      port;
     osiSockIoctl_t      nchars;
 
-    if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) {
-        port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, 
-            (unsigned short) CA_SERVER_PORT );
-    }
-    else {
-        port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, 
-            (unsigned short) CA_SERVER_PORT );
-    }
-
     recv_addr_size = sizeof(new_recv_addr);
 
     if( IOC_cast_sock!=0 && IOC_cast_sock!=INVALID_SOCKET ) {
@@ -174,13 +165,11 @@
 #endif
 
     epicsSocketEnableAddressUseForDatagramFanout ( IOC_cast_sock );
-    
-    /*  Zero the sock_addr structure */
-    memset((char *)&sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = htonl(INADDR_ANY);
-    sin.sin_port = htons(port);
-    
+
+    paddrNode = (osiSockAddrNode *) ellFirst ( &casIntfAddrList );
+
+    memcpy(&sin, &paddrNode->addr.ia, sizeof (sin));
+
     /* get server's Internet address */
     if( bind(IOC_cast_sock, (struct sockaddr *)&sin, sizeof (sin)) < 0){
         char sockErrBuf[64];
@@ -245,7 +234,8 @@
              * see if the next message is for this same client.
              */
             if (prsrv_cast_client->send.stk>sizeof(caHdr)) {
-                status = memcmp( (void *)&prsrv_cast_client->addr, (void *)&new_recv_addr, recv_addr_size);
+                status = memcmp(&prsrv_cast_client->addr, 
+                    &new_recv_addr, recv_addr_size);
                 if(status){     
                     /* 
                      * if the address is different 

=== modified file 'src/ioc/rsrv/server.h'
--- src/ioc/rsrv/server.h	2012-06-22 23:16:26 +0000
+++ src/ioc/rsrv/server.h	2014-03-06 22:28:58 +0000
@@ -165,6 +165,7 @@
 GLBLTYPE unsigned short     ca_server_port;
 GLBLTYPE ELLLIST            clientQ; /* locked by clientQlock */
 GLBLTYPE ELLLIST            beaconAddrList;
+GLBLTYPE ELLLIST            casIntfAddrList;
 GLBLTYPE epicsMutexId       clientQlock;
 GLBLTYPE struct client      *prsrv_cast_client;
 GLBLTYPE BUCKET             *pCaBucket;


Navigate by Date:
Prev: Jenkins build is back to normal : epics-base-3.14-win32s #3 APS Jenkins
Next: epicsStr[n]CaseCmp() Andrew Johnson
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017 
Navigate by Thread:
Prev: Jenkins build is back to normal : epics-base-3.14-win32s #3 APS Jenkins
Next: epicsStr[n]CaseCmp() Andrew Johnson
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017 
ANJ, 16 May 2014 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·