Index: camessage.c
===================================================================
RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/rsrv/camessage.c,v
retrieving revision 1.105.2.9
diff -u -b -r1.105.2.9 camessage.c
--- camessage.c	28 Nov 2006 18:50:53 -0000	1.105.2.9
+++ camessage.c	7 Nov 2007 19:02:45 -0000
@@ -493,11 +493,11 @@
     struct event_ext *pevext = pArg;
     struct client *pClient = pevext->pciu->client;
     struct channel_in_use *pciu = pevext->pciu;
+    const int readAccess = asCheckGet ( pciu->asClientPVT );
     int status;
     int strcnt;
     int v41;
 
-    if ( pevext->send_lock )
         SEND_LOCK ( pClient );
 
     /* 
@@ -526,8 +526,7 @@
             "server unable to load read (or subscription update) response into protocol buffer PV=\"%s\" max bytes=%u",
             RECORD_NAME ( paddr ), rsrvSizeofLargeBufTCP );
         if ( ! eventsRemaining )
-            cas_send_bs_msg ( pClient, ! pevext->send_lock );
-        if ( pevext->send_lock )
+            cas_send_bs_msg ( pClient, FALSE );
             SEND_UNLOCK ( pClient );
         return;
     }
@@ -535,13 +534,11 @@
     /*
      * verify read access
      */
-    if ( ! asCheckGet ( pciu->asClientPVT ) ) {
+    if ( ! readAccess ) {
         no_read_access_event ( pClient, pevext );
         if ( ! eventsRemaining )
-            cas_send_bs_msg ( pClient, !pevext->send_lock );
-        if ( pevext->send_lock ) {
+            cas_send_bs_msg ( pClient, FALSE );
             SEND_UNLOCK ( pClient );
-        }
         return;
     }
 
@@ -606,9 +603,8 @@
      * them up like db requests when the OPI does not keep up.
      */
     if ( ! eventsRemaining )
-        cas_send_bs_msg ( pClient, ! pevext->send_lock );
+        cas_send_bs_msg ( pClient, FALSE );
 
-    if ( pevext->send_lock )
         SEND_UNLOCK ( pClient );
 
     return;
@@ -619,14 +615,14 @@
  */
 LOCAL int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *pClient )
 {
-    struct channel_in_use *pciu;
+    struct channel_in_use *pciu = MPTOPCIU ( mp );
+    const int readAccess = asCheckGet ( pciu->asClientPVT );
     ca_uint32_t payloadSize;
     void *pPayload;
     int status;
     int strcnt;
     int v41;
 
-    pciu = MPTOPCIU ( mp );
     if ( ! pciu ) {
         logBadId ( pClient, mp, 0 );
         return RSRV_ERROR;
@@ -655,7 +651,7 @@
      * verify read access
      */
     v41 = CA_V41 ( pClient->minor_version_number );
-    if ( ! asCheckGet ( pciu->asClientPVT ) ) {
+    if ( ! readAccess ) {
         if ( v41 ) {
             status = ECA_NORDACCESS;
         }
@@ -719,7 +715,6 @@
 
     evext.msg = *mp;
     evext.pciu = pciu;
-    evext.send_lock = TRUE;
     evext.pdbev = NULL;
     evext.size = dbr_size_n ( mp->m_dataType, mp->m_count );
 
@@ -1038,7 +1033,7 @@
     }
 
     epicsMutexMustLock( client->chanListLock );
-    pchannel->state = rsrvCS_inService;
+    pchannel->state = rsrvCS_pendConnectResp;
     ellAdd ( &client->chanList, &pchannel->node );
     epicsMutexUnlock ( client->chanListLock );
 
@@ -1071,10 +1066,17 @@
     {
     case asClientCOAR:
         {
+            const int readAccess = asCheckGet ( pciu->asClientPVT );
             unsigned sigReq = 0;
 
             epicsMutexMustLock ( pclient->chanListLock );
-            if ( pciu->state == rsrvCS_inService ) {
+            if ( pciu->state == rsrvCS_pendConnectResp ) {
+                ellDelete ( &pclient->chanList, &pciu->node );
+                pciu->state = rsrvCS_pendConnectRespUpdatePendAR;
+                ellAdd ( &pclient->chanPendingUpdateARList, &pciu->node );
+                sigReq = 1;
+            }
+            else if ( pciu->state == rsrvCS_inService ) {
                 ellDelete ( &pclient->chanList, &pciu->node );
                 pciu->state = rsrvCS_inServiceUpdatePendAR;
                 ellAdd ( &pclient->chanPendingUpdateARList, &pciu->node );
@@ -1086,20 +1088,19 @@
             * Update all event call backs 
             */
             epicsMutexMustLock(pclient->eventqLock);
-
             for (pevext = (struct event_ext *) ellFirst(&pciu->eventq);
                 pevext;
                 pevext = (struct event_ext *) ellNext(&pevext->node)){
 
-                int readAccess = asCheckGet(pciu->asClientPVT);
-
-                if(pevext->pdbev && !readAccess){
-                    db_post_single_event(pevext->pdbev);
-                    db_event_disable(pevext->pdbev);
+                if ( pevext->pdbev ) {
+                    if ( readAccess ){
+                        db_event_enable ( pevext->pdbev );
+                        db_post_single_event ( pevext->pdbev );
+                    }
+                    else {
+                        db_post_single_event ( pevext->pdbev );
+                        db_event_disable ( pevext->pdbev );
                 }
-                else if(pevext->pdbev && readAccess){
-                    db_event_enable(pevext->pdbev);
-                    db_post_single_event(pevext->pdbev);
                 }
             }
             epicsMutexUnlock(pclient->eventqLock);
@@ -1156,12 +1157,49 @@
 }
 
 /*
+ * claim_ciu_reply()
+ */
+LOCAL void claim_ciu_reply ( struct channel_in_use * pciu )
+{
+    int v42 = CA_V42 ( pciu->client->minor_version_number );
+    access_rights_reply ( pciu );
+    if ( v42 ) {
+        int status;
+        ca_uint32_t nElem;
+        SEND_LOCK ( pciu->client );
+        if ( pciu->addr.no_elements < 0 ) {
+            nElem = 0;
+        }
+        else {
+            if ( ! CA_V49 ( pciu->client->minor_version_number ) ) {
+                if ( pciu->addr.no_elements >= 0xffff ) {
+                    nElem = 0xfffe;
+                }
+                else {
+                    nElem = (ca_uint32_t) pciu->addr.no_elements;
+                }
+            }
+            else {
+                nElem = (ca_uint32_t) pciu->addr.no_elements;
+            }
+        }
+        status = cas_copy_in_header ( 
+            pciu->client, CA_PROTO_CREATE_CHAN, 0u,
+            pciu->addr.dbr_field_type, nElem, pciu->cid, 
+            pciu->sid, NULL );
+        if ( status == ECA_NORMAL ) {
+            cas_commit_msg ( pciu->client, 0u );
+        }
+        SEND_UNLOCK(pciu->client);
+    }
+}
+
+/*
  * claim_ciu_action()
  */
 LOCAL int claim_ciu_action ( caHdrLargeArray *mp, 
                             void *pPayload, client *client )
 {
-    int v42;
     int status;
     struct channel_in_use *pciu;
 
@@ -1263,7 +1301,7 @@
         epicsMutexUnlock(prsrv_cast_client->chanListLock);
 
         epicsMutexMustLock(client->chanListLock);
-        pciu->state = rsrvCS_inService;
+        pciu->state = rsrvCS_pendConnectResp;
         pciu->client = client;
         ellAdd(&client->chanList, &pciu->node);
         epicsMutexUnlock(client->chanListLock);
@@ -1293,19 +1331,20 @@
      */
     asPutClientPvt(pciu->asClientPVT, pciu);
 
-    v42 = CA_V42(client->minor_version_number);
-
     /*
      * register for asynch updates of access rights changes
      */
     status = asRegisterClientCallback(
             pciu->asClientPVT, 
             casAccessRightsCB);
-    if(status == S_asLib_asNotActive){
+    if ( status == S_asLib_asNotActive ) {
+        epicsMutexMustLock ( client->chanListLock );
+        pciu->state = rsrvCS_inService;
+        epicsMutexUnlock ( client->chanListLock );
         /*
-         * force the initial update
+         * force the initial AR update followed by claim response
          */
-        access_rights_reply(pciu);
+        claim_ciu_reply ( pciu );
     }
     else if (status!=0) {
         log_header ("No room for access security state change subscription", 
@@ -1316,37 +1355,6 @@
         SEND_UNLOCK(client);
         return RSRV_ERROR;
     }
-
-    if(v42){
-        ca_uint32_t nElem;
-
-        SEND_LOCK ( client );
-
-        if ( pciu->addr.no_elements < 0 ) {
-            nElem = 0;
-        }
-        else {
-            if ( ! CA_V49 ( client->minor_version_number ) ) {
-                if ( pciu->addr.no_elements >= 0xffff ) {
-                    nElem = 0xfffe;
-                }
-                else {
-                    nElem = (ca_uint32_t) pciu->addr.no_elements;
-                }
-            }
-            else {
-                nElem = (ca_uint32_t) pciu->addr.no_elements;
-            }
-        }
-        status = cas_copy_in_header ( 
-            client, CA_PROTO_CREATE_CHAN, 0u,
-            pciu->addr.dbr_field_type, nElem, pciu->cid, 
-            pciu->sid, NULL );
-        if ( status == ECA_NORMAL ) {
-            cas_commit_msg ( client, 0u );
-        }
-        SEND_UNLOCK(client);
-    }
     return RSRV_OK;
 }
 
@@ -1479,9 +1487,19 @@
     pciu = ( struct channel_in_use * ) 
         ellGet ( & client->chanPendingUpdateARList );
     while ( pciu ) {
+        if ( pciu->state == rsrvCS_pendConnectRespUpdatePendAR ) {
+            claim_ciu_reply ( pciu );
+        }
+        else if ( pciu->state == rsrvCS_inServiceUpdatePendAR ) {
         access_rights_reply ( pciu );
+        }
+        else {
+            errlogPrintf (
+            "%s at %d: corrupt channel state detected durring AR update\n",
+                __FILE__, __LINE__);
+        }
         pciu->state = rsrvCS_inService;
-        ellAdd ( & client->chanList, &pciu->node );
+        ellAdd ( & client->chanList, & pciu->node );
         pciu = ( struct channel_in_use * ) 
             ellGet ( & client->chanPendingUpdateARList );
     }
@@ -1501,7 +1519,6 @@
     cas_send_bs_msg ( pClient, TRUE );
 }
 
-
 /*
  * putNotifyErrorReply
  */
@@ -1825,7 +1842,6 @@
 
     pevext->msg = *mp;
     pevext->pciu = pciu;
-    pevext->send_lock = TRUE;
     pevext->size = dbr_size_n(mp->m_dataType, mp->m_count);
     pevext->mask = ntohs ( pmi->m_mask );
 
@@ -1945,10 +1961,12 @@
      SEND_UNLOCK(client);
      
      epicsMutexMustLock ( client->chanListLock );
-     if ( pciu->state == rsrvCS_inService ) {
+     if ( pciu->state == rsrvCS_inService || 
+          pciu->state == rsrvCS_pendConnectResp  ) {
         ellDelete ( &client->chanList, &pciu->node );
      }
-     else if ( pciu->state == rsrvCS_inServiceUpdatePendAR ) {
+     else if ( pciu->state == rsrvCS_inServiceUpdatePendAR ||
+               pciu->state == rsrvCS_pendConnectRespUpdatePendAR ) {
         ellDelete ( &client->chanPendingUpdateARList, &pciu->node );
      }
      else {
@@ -1965,7 +1983,6 @@
       * remove from access control list
       */
      status = asRemoveClient(&pciu->asClientPVT);
-     assert(status == 0 || status == S_asLib_asNotActive);
      if(status != 0 && status != S_asLib_asNotActive){
          errMessage(status, RECORD_NAME(&pciu->addr));
          return RSRV_ERROR;
Index: server.h
===================================================================
RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/rsrv/server.h,v
retrieving revision 1.70
retrieving revision 1.67.2.4
diff -u -b -r1.70 -r1.67.2.4
--- server.h	29 Nov 2006 17:51:30 -0000	1.70
+++ server.h	17 Aug 2007 22:31:11 -0000	1.67.2.4
@@ -104,8 +104,11 @@
 
 enum rsrvChanState { 
     rsrvCS_invalid,
+    rsrvCS_pendConnectResp,
     rsrvCS_inService, 
-    rsrvCS_inServiceUpdatePendAR };
+    rsrvCS_pendConnectRespUpdatePendAR,
+    rsrvCS_inServiceUpdatePendAR 
+};
 
 /*
  * per channel structure 
@@ -136,7 +139,6 @@
     unsigned                size;       /* for speed */
     unsigned                mask;
     char                    modified;   /* mod & ev flw ctrl enbl */
-    char                    send_lock;  /* lock send buffer */
 };
 
 /*  NOTE: external used so they remember the state across loads */
