access control mods
This commit is contained in:
+37
-2
@@ -280,10 +280,12 @@ void *pext;
|
||||
{
|
||||
struct extmsg msg;
|
||||
unsigned long bytesAvailable;
|
||||
unsigned long actualextsize;
|
||||
unsigned long extsize;
|
||||
unsigned long bytesSent;
|
||||
|
||||
msg = *pmsg;
|
||||
actualextsize = pmsg->m_postsize;
|
||||
extsize = CA_MESSAGE_ALIGN(pmsg->m_postsize);
|
||||
msg.m_postsize = htons(extsize);
|
||||
|
||||
@@ -342,8 +344,26 @@ void *pext;
|
||||
bytesSent = cacRingBufferWrite(
|
||||
&piiu->send,
|
||||
pext,
|
||||
extsize);
|
||||
assert(bytesSent == extsize);
|
||||
actualextsize);
|
||||
assert(bytesSent == actualextsize);
|
||||
/*
|
||||
* force pad bytes at the end of the message to nill
|
||||
* if present
|
||||
*/
|
||||
{
|
||||
static nullBuff[32];
|
||||
int n;
|
||||
|
||||
n = extsize-actualextsize;
|
||||
if(n){
|
||||
assert(n<=sizeof(nullBuff));
|
||||
bytesSent = cacRingBufferWrite(
|
||||
&piiu->send,
|
||||
nullBuff,
|
||||
n);
|
||||
assert(bytesSent == n);
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
@@ -1557,6 +1577,10 @@ void *pvalue
|
||||
if (INVALID_DB_REQ(type))
|
||||
return ECA_BADTYPE;
|
||||
|
||||
if(!chix->ar.read_access){
|
||||
return ECA_NORDACCESS;
|
||||
}
|
||||
|
||||
if (count > chix->count)
|
||||
return ECA_BADCOUNT;
|
||||
|
||||
@@ -1633,6 +1657,9 @@ int ca_array_get_callback
|
||||
if (count > chix->count)
|
||||
return ECA_BADCOUNT;
|
||||
|
||||
if(!chix->ar.read_access){
|
||||
return ECA_NORDACCESS;
|
||||
}
|
||||
|
||||
#ifdef vxWorks
|
||||
if (!chix->piiu) {
|
||||
@@ -1768,6 +1795,10 @@ void *usrarg;
|
||||
if(INVALID_DB_FIELD(type))
|
||||
return ECA_BADTYPE;
|
||||
|
||||
if(!chix->ar.write_access){
|
||||
return ECA_NOWTACCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for valid count
|
||||
*/
|
||||
@@ -2054,6 +2085,10 @@ void *pvalue;
|
||||
if(INVALID_DB_FIELD(type))
|
||||
return ECA_BADTYPE;
|
||||
|
||||
if(!chix->ar.write_access){
|
||||
return ECA_NOWTACCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for valid count
|
||||
*/
|
||||
|
||||
+9
-1
@@ -210,6 +210,10 @@ char *pname;
|
||||
NULL,
|
||||
CONN_ROUTINE,
|
||||
NULL), NULL);
|
||||
#if 0
|
||||
status = ca_replace_access_rights_event(chix1, ar_event);
|
||||
SEVCHK(status,NULL);
|
||||
#endif
|
||||
|
||||
status = ca_pend_io(1000.0);
|
||||
SEVCHK(status, NULL);
|
||||
@@ -238,6 +242,10 @@ char *pname;
|
||||
lib$init_timer();
|
||||
#endif /*VMS*/
|
||||
|
||||
printf("Read Access=%d Write Access=%d\n",
|
||||
ca_read_access(chix1),
|
||||
ca_write_access(chix1));
|
||||
|
||||
/*
|
||||
* verify we dont jam up on many uninterrupted
|
||||
* solicitations
|
||||
@@ -453,7 +461,7 @@ char *pname;
|
||||
assert(conn_get_cb_count == 3);
|
||||
|
||||
printf("-- Put/Gets done- waiting for Events --\n");
|
||||
status = ca_pend_event(2000.0);
|
||||
status = ca_pend_event(10.0);
|
||||
if (status == ECA_TIMEOUT) {
|
||||
|
||||
free(ptr);
|
||||
|
||||
+8
-7
@@ -1425,9 +1425,10 @@ struct ioc_in_use *piiu;
|
||||
chix->count = 0;
|
||||
chix->state = cs_prev_conn;
|
||||
chix->id.sid = ~0L;
|
||||
chix->ar.read_access = FALSE;
|
||||
chix->ar.write_access = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* remove IOC from the hash table
|
||||
*/
|
||||
@@ -1460,18 +1461,18 @@ struct ioc_in_use *piiu;
|
||||
chix = (chid) &piiu->chidlist.node.next;
|
||||
while(chix = (chid) chix->node.next){
|
||||
LOCKEVENTS;
|
||||
if(chix->access_rights_func){
|
||||
struct access_rights_handler_args args;
|
||||
args.chid = chix;
|
||||
args.ar = chix->ar;
|
||||
(*chix->access_rights_func)(args);
|
||||
}
|
||||
if(chix->connection_func){
|
||||
struct connection_handler_args args;
|
||||
args.chid = chix;
|
||||
args.op = CA_OP_CONN_DOWN;
|
||||
(*chix->connection_func)(args);
|
||||
}
|
||||
if(chix->access_rights_func){
|
||||
struct access_rights_handler_args args;
|
||||
args.chid = chix;
|
||||
args.ar = chix->ar;
|
||||
(*chix->access_rights_func)(args);
|
||||
}
|
||||
UNLOCKEVENTS;
|
||||
chix->piiu = piiuCast;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ static char *iocmsghSccsId = "$Id$ CA version 4.1";
|
||||
#define IOC_WRITE_NOTIFY 19 /* notify after write chan value */
|
||||
#define IOC_CLIENT_NAME 20 /* CA V4.1 identify client */
|
||||
#define IOC_HOST_NAME 21 /* CA V4.1 identify client */
|
||||
#define IOC_ACCESS_RIGHTS 22 /* CA V4.1 asynch access rights chg */
|
||||
|
||||
/*
|
||||
* for use with build and search and not_found (if search fails and
|
||||
@@ -79,6 +80,14 @@ static char *iocmsghSccsId = "$Id$ CA version 4.1";
|
||||
#define BI_ROUND(A) ((((unsigned long)A)+1)>>1)
|
||||
#define BI_SIZEOF(A) (BI_ROUND(sizeof(A)))
|
||||
|
||||
/*
|
||||
* For communicating access rights to the clients
|
||||
*
|
||||
* (placed in m_available hdr field of IOC_ACCESS_RIGHTS cmmd
|
||||
*/
|
||||
#define CA_ACCESS_RIGHT_READ (1<<0)
|
||||
#define CA_ACCESS_RIGHT_WRITE (1<<1)
|
||||
|
||||
/*
|
||||
* Required Message Alignment
|
||||
*
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ static char *os_depenhSccsId = "$Id$";
|
||||
#endif /*VMS*/
|
||||
|
||||
#ifndef CA_OS_CONFIGURED
|
||||
/* # error Please define one of vxWorks, UNIX or VMS */
|
||||
@@@@@@ Please define one of vxWorks, UNIX or VMS @@@@@@
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
|
||||
@@ -648,6 +648,29 @@ struct in_addr *pnet_addr;
|
||||
UNLOCKEVENTS;
|
||||
break;
|
||||
}
|
||||
case IOC_ACCESS_RIGHTS:
|
||||
{
|
||||
int ar;
|
||||
chid chan;
|
||||
|
||||
LOCK;
|
||||
chan = bucketLookupItem(pBucket, piiu->curMsg.m_cid);
|
||||
UNLOCK;
|
||||
assert(chan);
|
||||
|
||||
ar = ntohl(piiu->curMsg.m_available);
|
||||
chan->ar.read_access = (ar&CA_ACCESS_RIGHT_READ)?1:0;
|
||||
chan->ar.write_access = (ar&CA_ACCESS_RIGHT_WRITE)?1:0;
|
||||
|
||||
if (chan->access_rights_func) {
|
||||
struct access_rights_handler_args args;
|
||||
|
||||
args.chid = chan;
|
||||
args.ar = chan->ar;
|
||||
(*chan->access_rights_func) (args);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ca_printf("CAC: post_msg(): Corrupt cmd in msg %x\n",
|
||||
piiu->curMsg.m_cmmd);
|
||||
@@ -683,6 +706,7 @@ struct in_addr *pnet_addr;
|
||||
IIU *allocpiiu;
|
||||
IIU *chpiiu;
|
||||
unsigned short *pMinorVersion;
|
||||
int v41;
|
||||
|
||||
/*
|
||||
* ignore broadcast replies for deleted channels
|
||||
@@ -758,6 +782,18 @@ struct in_addr *pnet_addr;
|
||||
chan->count = piiu->curMsg.m_count;
|
||||
chan->id.sid = piiu->curMsg.m_cid;
|
||||
|
||||
/*
|
||||
* Assume that we have access once connected briefly
|
||||
* until the server is able to tell us the correct
|
||||
* state for backwards compatibility.
|
||||
*
|
||||
* Their access rights call back does not get
|
||||
* called for the first time until the information
|
||||
* arrives however.
|
||||
*/
|
||||
chan->ar.read_access = TRUE;
|
||||
chan->ar.write_access = TRUE;
|
||||
|
||||
/*
|
||||
* Starting with CA V4.1 the minor version number
|
||||
* is appended to the end of each search reply.
|
||||
@@ -771,6 +807,10 @@ struct in_addr *pnet_addr;
|
||||
allocpiiu->minor_version_number = CA_UKN_MINOR_VERSION;
|
||||
}
|
||||
|
||||
v41 = CA_V41(
|
||||
CA_PROTOCOL_VERSION,
|
||||
allocpiiu->minor_version_number);
|
||||
|
||||
if(chpiiu != allocpiiu){
|
||||
|
||||
/*
|
||||
@@ -850,6 +890,20 @@ struct in_addr *pnet_addr;
|
||||
CLRPENDRECV(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* if less than v4.1 then the server will never
|
||||
* send access rights so we know that there
|
||||
* will always be access and call their call back
|
||||
* here
|
||||
*/
|
||||
if (chan->access_rights_func && !v41) {
|
||||
struct access_rights_handler_args args;
|
||||
|
||||
args.chid = chan;
|
||||
args.ar = chan->ar;
|
||||
(*chan->access_rights_func) (args);
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
|
||||
+313
-122
@@ -164,6 +164,11 @@ ASCLIENTPVT ascpvt,
|
||||
asClientStatus type
|
||||
);
|
||||
|
||||
LOCAL void no_read_access_event(
|
||||
struct client *client,
|
||||
struct event_ext *pevext
|
||||
);
|
||||
|
||||
LOCAL unsigned long bucketID;
|
||||
|
||||
|
||||
@@ -255,10 +260,11 @@ struct message_buffer *recv
|
||||
break;
|
||||
}
|
||||
|
||||
evext.mp = mp;
|
||||
evext.msg = *mp;
|
||||
evext.pciu = pciu;
|
||||
evext.send_lock = TRUE;
|
||||
evext.get = TRUE;
|
||||
evext.pdbev = NULL;
|
||||
evext.size = dbr_size_n(mp->m_type, mp->m_count);
|
||||
|
||||
/*
|
||||
@@ -569,7 +575,9 @@ struct client *client
|
||||
&prsrv_cast_client->addrq,
|
||||
&pciu->node);
|
||||
UNLOCK_CLIENT(prsrv_cast_client);
|
||||
|
||||
pciu->client = client;
|
||||
|
||||
LOCK_CLIENT(client);
|
||||
ellAdd(&client->addrq, &pciu->node);
|
||||
UNLOCK_CLIENT(client);
|
||||
@@ -582,6 +590,13 @@ struct client *client
|
||||
*/
|
||||
pciu->client->minor_version_number = mp->m_available;
|
||||
|
||||
/*
|
||||
* register for asynch updates of access rights changes
|
||||
* (only after the lock is released, we are added to
|
||||
* the correct client, and the clients version is
|
||||
* known)
|
||||
*/
|
||||
asRegisterClientCallback(pciu->asClientPVT, casAccessRightsCB);
|
||||
}
|
||||
|
||||
|
||||
@@ -935,21 +950,36 @@ struct client *client
|
||||
}
|
||||
memset(pevext,0,size);
|
||||
pevext->msg = *mp;
|
||||
pevext->mp = &pevext->msg; /* for speed- see
|
||||
* IOC_READ */
|
||||
pevext->pciu = pciu;
|
||||
pevext->send_lock = TRUE;
|
||||
pevext->size = dbr_size_n(mp->m_type, mp->m_count);
|
||||
pevext->mask = ((struct monops *) mp)->m_info.m_mask;
|
||||
pevext->get = FALSE;
|
||||
|
||||
LOCK_CLIENT(client);
|
||||
ellAdd( &pciu->eventq, &pevext->node);
|
||||
UNLOCK_CLIENT(client);
|
||||
|
||||
/*
|
||||
* dont set up the event if no read access
|
||||
*/
|
||||
if(!asCheckGet(pciu->asClientPVT)){
|
||||
pevext->pdbev = NULL;
|
||||
no_read_access_event(client, pevext);
|
||||
return;
|
||||
}
|
||||
|
||||
pevext->pdbev = (struct event_block *)(pevext+1);
|
||||
|
||||
status = db_add_event(
|
||||
client->evuser,
|
||||
&pciu->addr,
|
||||
read_reply,
|
||||
pevext,
|
||||
(unsigned) ((struct monops *) mp)->m_info.m_mask,
|
||||
(struct event_block *)(pevext+1));
|
||||
pevext->mask,
|
||||
pevext->pdbev);
|
||||
if (status == ERROR) {
|
||||
pevext->pdbev = NULL;
|
||||
LOCK_CLIENT(client);
|
||||
send_err(
|
||||
mp,
|
||||
@@ -957,21 +987,9 @@ struct client *client
|
||||
client,
|
||||
RECORD_NAME(&pciu->addr));
|
||||
UNLOCK_CLIENT(client);
|
||||
FASTLOCK(&rsrv_free_eventq_lck);
|
||||
ellAdd(&rsrv_free_eventq, &pevext->node);
|
||||
FASTUNLOCK(&rsrv_free_eventq_lck);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only add to the list if we can get enough
|
||||
* memory. If not, attempts to delete it
|
||||
* from the client will cause a warning message
|
||||
* to be printed since it will not be found on
|
||||
* the list.
|
||||
*/
|
||||
ellAdd( &pciu->eventq, &pevext->node);
|
||||
|
||||
/*
|
||||
* always send it once at event add
|
||||
*/
|
||||
@@ -998,7 +1016,7 @@ struct client *client
|
||||
* messages sent by the server).
|
||||
*/
|
||||
|
||||
db_post_single_event((struct event_block *)(pevext+1));
|
||||
db_post_single_event(pevext->pdbev);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1016,10 +1034,10 @@ struct extmsg *mp,
|
||||
struct client *client
|
||||
)
|
||||
{
|
||||
FAST struct extmsg *reply;
|
||||
FAST struct event_ext *pevext;
|
||||
struct extmsg *reply;
|
||||
struct event_ext *pevext;
|
||||
struct channel_in_use *pciu;
|
||||
FAST int status;
|
||||
int status;
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -1041,11 +1059,18 @@ struct client *client
|
||||
}
|
||||
}
|
||||
|
||||
while (pevext = (struct event_ext *) ellGet(&pciu->eventq)) {
|
||||
while (TRUE){
|
||||
LOCK_CLIENT(client);
|
||||
pevext = (struct event_ext *) ellGet(&pciu->eventq);
|
||||
UNLOCK_CLIENT(client);
|
||||
|
||||
status = db_cancel_event((struct event_block *)(pevext+1));
|
||||
if (status){
|
||||
taskSuspend(0);
|
||||
if(!pevext){
|
||||
break;
|
||||
}
|
||||
|
||||
if(pevext->pdbev){
|
||||
status = db_cancel_event(pevext->pdbev);
|
||||
assert(status == OK);
|
||||
}
|
||||
FASTLOCK(&rsrv_free_eventq_lck);
|
||||
ellAdd(&rsrv_free_eventq, &pevext->node);
|
||||
@@ -1111,11 +1136,10 @@ struct extmsg *mp,
|
||||
struct client *client
|
||||
)
|
||||
{
|
||||
struct extmsg *reply;
|
||||
struct event_ext *pevext;
|
||||
ELLLIST *peventq;
|
||||
int status;
|
||||
struct channel_in_use *pciu;
|
||||
struct channel_in_use *pciu;
|
||||
struct extmsg *reply;
|
||||
struct event_ext *pevext;
|
||||
int status;
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -1127,46 +1151,60 @@ struct client *client
|
||||
logBadId(client, mp);
|
||||
return;
|
||||
}
|
||||
peventq = &pciu->eventq;
|
||||
|
||||
for (pevext = (struct event_ext *) peventq->node.next;
|
||||
pevext;
|
||||
pevext = (struct event_ext *) pevext->node.next)
|
||||
if (pevext->msg.m_available == mp->m_available) {
|
||||
status = db_cancel_event((struct event_block *)(pevext+1));
|
||||
if (status == ERROR)
|
||||
taskSuspend(0);
|
||||
ellDelete(peventq, &pevext->node);
|
||||
|
||||
/*
|
||||
* send delete confirmed message
|
||||
*/
|
||||
LOCK_CLIENT(client);
|
||||
reply = (struct extmsg *) ALLOC_MSG(client, 0);
|
||||
if (!reply) {
|
||||
UNLOCK_CLIENT(client);
|
||||
taskSuspend(0);
|
||||
}
|
||||
*reply = pevext->msg;
|
||||
reply->m_postsize = 0;
|
||||
|
||||
END_MSG(client);
|
||||
UNLOCK_CLIENT(client);
|
||||
|
||||
FASTLOCK(&rsrv_free_eventq_lck);
|
||||
ellAdd(&rsrv_free_eventq, &pevext->node);
|
||||
FASTUNLOCK(&rsrv_free_eventq_lck);
|
||||
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Not Found- return an error message
|
||||
* search events on this channel for a match
|
||||
* (there are usually very few monitors per channel)
|
||||
*/
|
||||
LOCK_CLIENT(client);
|
||||
send_err(mp, ECA_BADMONID, client, RECORD_NAME(&pciu->addr));
|
||||
for (pevext = (struct event_ext *) ellFirst(&pciu->eventq);
|
||||
pevext;
|
||||
pevext = (struct event_ext *) ellNext(&pevext->node)){
|
||||
|
||||
if (pevext->msg.m_available == mp->m_available) {
|
||||
ellDelete(&pciu->eventq, &pevext->node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UNLOCK_CLIENT(client);
|
||||
|
||||
return;
|
||||
/*
|
||||
* Not Found- return an exception event
|
||||
*/
|
||||
if(!pevext){
|
||||
LOCK_CLIENT(client);
|
||||
send_err(mp, ECA_BADMONID, client, RECORD_NAME(&pciu->addr));
|
||||
UNLOCK_CLIENT(client);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cancel monitor activity in progress
|
||||
*/
|
||||
if(pevext->pdbev){
|
||||
status = db_cancel_event(pevext->pdbev);
|
||||
assert(status == OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* send delete confirmed message
|
||||
*/
|
||||
LOCK_CLIENT(client);
|
||||
reply = (struct extmsg *) ALLOC_MSG(client, 0);
|
||||
if (!reply) {
|
||||
UNLOCK_CLIENT(client);
|
||||
assert(0);
|
||||
}
|
||||
*reply = pevext->msg;
|
||||
reply->m_postsize = 0;
|
||||
|
||||
END_MSG(client);
|
||||
UNLOCK_CLIENT(client);
|
||||
|
||||
FASTLOCK(&rsrv_free_eventq_lck);
|
||||
ellAdd(&rsrv_free_eventq, &pevext->node);
|
||||
FASTUNLOCK(&rsrv_free_eventq_lck);
|
||||
}
|
||||
|
||||
|
||||
@@ -1185,7 +1223,6 @@ db_field_log *pfl
|
||||
)
|
||||
{
|
||||
struct event_ext *pevext = pArg;
|
||||
struct extmsg *mp = pevext->mp;
|
||||
struct client *client = pevext->pciu->client;
|
||||
struct channel_in_use *pciu = pevext->pciu;
|
||||
struct extmsg *reply;
|
||||
@@ -1206,18 +1243,18 @@ db_field_log *pfl
|
||||
|
||||
reply = (struct extmsg *) ALLOC_MSG(client, pevext->size);
|
||||
if (!reply) {
|
||||
send_err(mp, ECA_TOLARGE, client, RECORD_NAME(paddr));
|
||||
send_err(&pevext->msg, ECA_TOLARGE, client, RECORD_NAME(paddr));
|
||||
if (!eventsRemaining)
|
||||
cas_send_msg(client,!pevext->send_lock);
|
||||
if (pevext->send_lock)
|
||||
UNLOCK_CLIENT(client);
|
||||
if (!eventsRemaining)
|
||||
cas_send_msg(client,FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* setup response message
|
||||
*/
|
||||
*reply = *mp;
|
||||
*reply = pevext->msg;
|
||||
reply->m_postsize = pevext->size;
|
||||
reply->m_cid = (unsigned long)pciu->cid;
|
||||
|
||||
@@ -1226,52 +1263,37 @@ db_field_log *pfl
|
||||
*/
|
||||
v41 = CA_V41(CA_PROTOCOL_VERSION,client->minor_version_number);
|
||||
if(!asCheckGet(pciu->asClientPVT)){
|
||||
if(v41){
|
||||
status = ECA_NORDACCESS;
|
||||
}
|
||||
else{
|
||||
status = ECA_GETFAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* I cant wait to redesign this protocol from scratch!
|
||||
*/
|
||||
if(!v41||reply->m_cmmd==IOC_READ||reply->m_cmmd==IOC_READ_BUILD){
|
||||
if(reply->m_cmmd==IOC_READ||
|
||||
reply->m_cmmd==IOC_READ_BUILD){
|
||||
if(v41){
|
||||
status = ECA_NORDACCESS;
|
||||
}
|
||||
else{
|
||||
status = ECA_GETFAIL;
|
||||
}
|
||||
/*
|
||||
* old client & plain get & search/get
|
||||
* continue to return an exception
|
||||
* on failure
|
||||
*/
|
||||
send_err(mp, status, client, RECORD_NAME(paddr));
|
||||
send_err(&pevext->msg, status,
|
||||
client, RECORD_NAME(paddr));
|
||||
}
|
||||
else{
|
||||
/*
|
||||
* New clients recv the status of the
|
||||
* operation directly to the
|
||||
* event/put/get callback.
|
||||
*
|
||||
* Fetched value is zerod in case they
|
||||
* use it even when the status indicates
|
||||
* failure.
|
||||
*
|
||||
* The m_cid field in the protocol
|
||||
* header is abused to carry the status
|
||||
*/
|
||||
bzero((char *)(reply+1), pevext->size);
|
||||
reply->m_cid = status;
|
||||
END_MSG(client);
|
||||
no_read_access_event(client, pevext);
|
||||
}
|
||||
if (pevext->send_lock)
|
||||
UNLOCK_CLIENT(client);
|
||||
if (!eventsRemaining)
|
||||
cas_send_msg(client,FALSE);
|
||||
cas_send_msg(client,!pevext->send_lock);
|
||||
if (pevext->send_lock){
|
||||
UNLOCK_CLIENT(client);
|
||||
}
|
||||
return;
|
||||
}
|
||||
status = db_get_field(
|
||||
paddr,
|
||||
mp->m_type,
|
||||
pevext->msg.m_type,
|
||||
reply + 1,
|
||||
mp->m_count,
|
||||
pevext->msg.m_count,
|
||||
pfl);
|
||||
if (status < 0) {
|
||||
/*
|
||||
@@ -1283,8 +1305,8 @@ db_field_log *pfl
|
||||
* continue to return an exception
|
||||
* on failure
|
||||
*/
|
||||
send_err(mp, ECA_GETFAIL, client, RECORD_NAME(paddr));
|
||||
log_header(mp, 0);
|
||||
send_err(&pevext->msg, ECA_GETFAIL, client, RECORD_NAME(paddr));
|
||||
log_header(&pevext->msg, 0);
|
||||
}
|
||||
else{
|
||||
/*
|
||||
@@ -1326,7 +1348,8 @@ db_field_log *pfl
|
||||
* force string message size to be the true size rounded to even
|
||||
* boundary
|
||||
*/
|
||||
if (mp->m_type == DBR_STRING && mp->m_count == 1) {
|
||||
if (pevext->msg.m_type == DBR_STRING
|
||||
&& pevext->msg.m_count == 1) {
|
||||
/* add 1 so that the string terminator will be shipped */
|
||||
strcnt = strlen((char *)(reply + 1)) + 1;
|
||||
reply->m_postsize = strcnt;
|
||||
@@ -1340,7 +1363,7 @@ db_field_log *pfl
|
||||
* them up like db requests when the OPI does not keep up.
|
||||
*/
|
||||
if (!eventsRemaining)
|
||||
cas_send_msg(client,FALSE);
|
||||
cas_send_msg(client,!pevext->send_lock);
|
||||
|
||||
if (pevext->send_lock)
|
||||
UNLOCK_CLIENT(client);
|
||||
@@ -1348,6 +1371,66 @@ db_field_log *pfl
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* no_read_access_event()
|
||||
*
|
||||
* !! LOCK needs to applied by caller !!
|
||||
*
|
||||
* substantial complication introduced here by the need for backwards
|
||||
* compatibility
|
||||
*/
|
||||
LOCAL void no_read_access_event(
|
||||
struct client *client,
|
||||
struct event_ext *pevext
|
||||
)
|
||||
{
|
||||
struct extmsg *reply;
|
||||
int v41;
|
||||
|
||||
v41 = CA_V41(CA_PROTOCOL_VERSION,client->minor_version_number);
|
||||
|
||||
/*
|
||||
* continue to return an exception
|
||||
* on failure to pre v41 clients
|
||||
*/
|
||||
if(!v41){
|
||||
send_err(
|
||||
&pevext->msg,
|
||||
ECA_GETFAIL,
|
||||
client,
|
||||
RECORD_NAME(&pevext->pciu->addr));
|
||||
return;
|
||||
}
|
||||
|
||||
reply = (struct extmsg *) ALLOC_MSG(client, pevext->size);
|
||||
if (!reply) {
|
||||
send_err(
|
||||
&pevext->msg,
|
||||
ECA_TOLARGE,
|
||||
client,
|
||||
RECORD_NAME(&pevext->pciu->addr));
|
||||
return;
|
||||
}
|
||||
else{
|
||||
/*
|
||||
* New clients recv the status of the
|
||||
* operation directly to the
|
||||
* event/put/get callback.
|
||||
*
|
||||
* Fetched value is zerod in case they
|
||||
* use it even when the status indicates
|
||||
* failure.
|
||||
*
|
||||
* The m_cid field in the protocol
|
||||
* header is abused to carry the status
|
||||
*/
|
||||
bzero((char *)(reply+1), pevext->size);
|
||||
reply->m_cid = ECA_NORDACCESS;
|
||||
END_MSG(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -1388,7 +1471,6 @@ struct extmsg *mp,
|
||||
struct client *client
|
||||
)
|
||||
{
|
||||
ELLLIST *addrq = &client->addrq;
|
||||
struct extmsg *search_reply;
|
||||
struct extmsg *get_reply;
|
||||
unsigned short *pMinorVersion;
|
||||
@@ -1454,10 +1536,29 @@ struct client *client
|
||||
LOCK_CLIENT(client);
|
||||
send_err(mp, ECA_ALLOCMEM, client, "No room for security table");
|
||||
UNLOCK_CLIENT(client);
|
||||
free(pchannel);
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
ellAdd(&rsrv_free_addrq, &pchannel->node);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
return;
|
||||
}
|
||||
asPutClientPvt(pchannel->asClientPVT, pchannel);
|
||||
|
||||
/*
|
||||
* Existing build() interface to the client does not provide mechanism
|
||||
* to inform them that the channel connected but the value
|
||||
* couldnt be fetched so search/get combined op
|
||||
* to no read access channel not allowed.
|
||||
*/
|
||||
if (mp->m_cmmd == IOC_BUILD && !asCheckGet(pchannel->asClientPVT)) {
|
||||
LOCK_CLIENT(client);
|
||||
send_err(mp, ECA_NORDACCESS, client, RECORD_NAME(&tmp_addr));
|
||||
UNLOCK_CLIENT(client);
|
||||
asRemoveClient(&pchannel->asClientPVT);
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
ellAdd(&rsrv_free_addrq, &pchannel->node);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
return;
|
||||
}
|
||||
asRegisterClientCallback(pchannel->asClientPVT, casAccessRightsCB);
|
||||
|
||||
/*
|
||||
* allocate a server id and enter the channel pointer
|
||||
@@ -1473,7 +1574,9 @@ struct client *client
|
||||
send_err(mp, ECA_ALLOCMEM, client, "No room for hash table");
|
||||
UNLOCK_CLIENT(client);
|
||||
asRemoveClient(&pchannel->asClientPVT);
|
||||
free(pchannel);
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
ellAdd(&rsrv_free_addrq, &pchannel->node);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1485,9 +1588,9 @@ struct client *client
|
||||
|
||||
|
||||
if (mp->m_cmmd == IOC_BUILD) {
|
||||
FAST short type = (mp + 1)->m_type;
|
||||
FAST unsigned int count = (mp + 1)->m_count;
|
||||
FAST unsigned int size;
|
||||
short type = (mp + 1)->m_type;
|
||||
unsigned int count = (mp + 1)->m_count;
|
||||
unsigned int size;
|
||||
|
||||
/*
|
||||
* must be large enough to hold both the search and the build-get
|
||||
@@ -1511,16 +1614,24 @@ struct client *client
|
||||
pchannel->sid,
|
||||
pchannel);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
free(pchannel);
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
ellAdd(&rsrv_free_addrq, &pchannel->node);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
return;
|
||||
} else {
|
||||
struct event_ext evext;
|
||||
|
||||
evext.mp = mp + 1;
|
||||
evext.pciu = pchannel;
|
||||
evext.mp->m_cid = sid;
|
||||
evext.msg = *(mp+1);
|
||||
/*
|
||||
* this allows extra build replies
|
||||
* to be dicarded
|
||||
*/
|
||||
evext.msg.m_cmmd = IOC_READ_BUILD;
|
||||
evext.msg.m_cid = sid;
|
||||
evext.send_lock = FALSE;
|
||||
evext.size = dbr_size_n(type, count);
|
||||
evext.pdbev = NULL;
|
||||
evext.get = TRUE;
|
||||
|
||||
/*
|
||||
@@ -1531,12 +1642,6 @@ struct client *client
|
||||
* is not flushed once each call.
|
||||
*/
|
||||
read_reply(&evext, &tmp_addr, TRUE, NULL);
|
||||
|
||||
/*
|
||||
* this allows extra build replies
|
||||
* to be dicarded
|
||||
*/
|
||||
get_reply->m_cmmd = IOC_READ_BUILD;
|
||||
}
|
||||
}
|
||||
search_reply = (struct extmsg *)
|
||||
@@ -1563,7 +1668,7 @@ struct client *client
|
||||
END_MSG(client);
|
||||
|
||||
/* store the addr block on the cast queue until it is claimed */
|
||||
ellAdd(addrq, &pchannel->node);
|
||||
ellAdd(&client->addrq, &pchannel->node);
|
||||
|
||||
UNLOCK_CLIENT(client);
|
||||
|
||||
@@ -1781,13 +1886,99 @@ LOCAL struct channel_in_use *MPTOPCIU(struct extmsg *mp)
|
||||
/*
|
||||
* casAccessRightsCB()
|
||||
*
|
||||
* If access right state changes then inform the client.
|
||||
*
|
||||
*/
|
||||
LOCAL void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type)
|
||||
{
|
||||
struct client *pclient;
|
||||
struct channel_in_use *pciu;
|
||||
struct extmsg *reply;
|
||||
struct event_ext *pevext;
|
||||
int status;
|
||||
unsigned ar;
|
||||
int v41;
|
||||
|
||||
pciu = asGetClientPvt(ascpvt);
|
||||
if(!pciu){
|
||||
printf("casAccessRightsCB() without channel pointer ??\n");
|
||||
return;
|
||||
}
|
||||
pclient = pciu->client;
|
||||
assert(pclient);
|
||||
v41 = CA_V41(CA_PROTOCOL_VERSION,pclient->minor_version_number);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case asClientCOAR:
|
||||
/*
|
||||
* noop if this is an old client
|
||||
*/
|
||||
if(!v41){
|
||||
break;
|
||||
}
|
||||
|
||||
ar = 0; /* none */
|
||||
if(asCheckGet(ascpvt)){
|
||||
ar |= CA_ACCESS_RIGHT_READ;
|
||||
}
|
||||
if(asCheckPut(ascpvt)){
|
||||
ar |= CA_ACCESS_RIGHT_WRITE;
|
||||
}
|
||||
|
||||
LOCK_CLIENT(pclient);
|
||||
reply = (struct extmsg *)ALLOC_MSG(pclient, 0);
|
||||
assert(reply);
|
||||
|
||||
*reply = nill_msg;
|
||||
reply->m_cmmd = IOC_ACCESS_RIGHTS;
|
||||
reply->m_cid = pciu->cid;
|
||||
reply->m_available = ar;
|
||||
|
||||
END_MSG(pclient);
|
||||
|
||||
/*
|
||||
* Update all event call backs
|
||||
*/
|
||||
for (pevext = (struct event_ext *) ellFirst(&pciu->eventq);
|
||||
pevext;
|
||||
pevext = (struct event_ext *) ellNext(&pevext->node)){
|
||||
|
||||
if(pevext->pdbev && !(ar&CA_ACCESS_RIGHT_READ)){
|
||||
status = db_cancel_event(pevext->pdbev);
|
||||
assert(status == OK);
|
||||
pevext->pdbev = NULL;
|
||||
}
|
||||
else if(!pevext->pdbev && ar&CA_ACCESS_RIGHT_READ){
|
||||
pevext->pdbev =
|
||||
(struct event_block *)(pevext+1);
|
||||
|
||||
status = db_add_event(
|
||||
pclient->evuser,
|
||||
&pciu->addr,
|
||||
read_reply,
|
||||
pevext,
|
||||
pevext->mask,
|
||||
pevext->pdbev);
|
||||
if (status == ERROR) {
|
||||
pevext->pdbev = NULL;
|
||||
send_err(
|
||||
&pevext->msg,
|
||||
ECA_ADDFAIL,
|
||||
pclient,
|
||||
RECORD_NAME(&pciu->addr));
|
||||
}
|
||||
}
|
||||
|
||||
if(pevext->pdbev){
|
||||
db_post_single_event(pevext->pdbev);
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK_CLIENT(pclient);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+48
-21
@@ -45,23 +45,24 @@
|
||||
*/
|
||||
|
||||
static char *sccsId = "$Id$";
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <ellLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <types.h>
|
||||
#include <sockLib.h>
|
||||
#include <socket.h>
|
||||
#include <in.h>
|
||||
#include <unistd.h>
|
||||
#include <logLib.h>
|
||||
#include <string.h>
|
||||
#include <usrLib.h>
|
||||
#include <errnoLib.h>
|
||||
#include <stdio.h>
|
||||
#include <tickLib.h>
|
||||
#include <sysLib.h>
|
||||
|
||||
#include <ellLib.h>
|
||||
#include <taskwd.h>
|
||||
#include <db_access.h>
|
||||
#include <task_params.h>
|
||||
@@ -272,8 +273,14 @@ LOCAL int terminate_one_client(struct client *client)
|
||||
}
|
||||
}
|
||||
|
||||
pciu = (struct channel_in_use *) & client->addrq;
|
||||
while (pciu = (struct channel_in_use *) pciu->node.next){
|
||||
while(TRUE){
|
||||
LOCK_CLIENT(client);
|
||||
pciu = (struct channel_in_use *) ellGet(&client->addrq);
|
||||
UNLOCK_CLIENT(client);
|
||||
if(!pciu){
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* put notify in progress needs to be deleted
|
||||
*/
|
||||
@@ -283,19 +290,27 @@ LOCAL int terminate_one_client(struct client *client)
|
||||
}
|
||||
}
|
||||
|
||||
while (pevext = (struct event_ext *) ellGet(&pciu->eventq)) {
|
||||
while (TRUE){
|
||||
/*
|
||||
* AS state change could be using this list
|
||||
*/
|
||||
LOCK_CLIENT(client);
|
||||
pevext = (struct event_ext *) ellGet(&pciu->eventq);
|
||||
UNLOCK_CLIENT(client);
|
||||
if(!pevext){
|
||||
break;
|
||||
}
|
||||
|
||||
status = db_cancel_event(
|
||||
(struct event_block *)(pevext + 1));
|
||||
if (status)
|
||||
taskSuspend(0);
|
||||
if(pevext->pdbev){
|
||||
status = db_cancel_event(pevext->pdbev);
|
||||
assert(status == OK);
|
||||
}
|
||||
FASTLOCK(&rsrv_free_eventq_lck);
|
||||
ellAdd(&rsrv_free_eventq, &pevext->node);
|
||||
FASTUNLOCK(&rsrv_free_eventq_lck);
|
||||
}
|
||||
status = db_flush_extra_labor_event(client->evuser);
|
||||
if (status)
|
||||
taskSuspend(0);
|
||||
assert(status==OK);
|
||||
if(pciu->pPutNotify){
|
||||
free(pciu->pPutNotify);
|
||||
}
|
||||
@@ -322,6 +337,14 @@ LOCAL int terminate_one_client(struct client *client)
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* place per channel block onto the
|
||||
* free list
|
||||
*/
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
ellAdd(&rsrv_free_addrq, &pciu->node);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
}
|
||||
|
||||
if (client->evuser) {
|
||||
@@ -338,13 +361,6 @@ LOCAL int terminate_one_client(struct client *client)
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* free dbaddr str */
|
||||
FASTLOCK(&rsrv_free_addrq_lck);
|
||||
ellConcat(
|
||||
&rsrv_free_addrq,
|
||||
&client->addrq);
|
||||
FASTUNLOCK(&rsrv_free_addrq_lck);
|
||||
|
||||
if(FASTLOCKFREE(&client->putNotifyLock)<0){
|
||||
logMsg("CAS: couldnt free sem\n",
|
||||
NULL,
|
||||
@@ -448,6 +464,7 @@ int client_stat(void)
|
||||
*/
|
||||
LOCAL void log_one_client(struct client *client)
|
||||
{
|
||||
int i;
|
||||
struct channel_in_use *pciu;
|
||||
struct sockaddr_in *psaddr;
|
||||
char *pproto;
|
||||
@@ -487,6 +504,7 @@ LOCAL void log_one_client(struct client *client)
|
||||
|
||||
bytes_reserved = 0;
|
||||
bytes_reserved += sizeof(struct client);
|
||||
LOCK_CLIENT(client);
|
||||
pciu = (struct channel_in_use *) client->addrq.node.next;
|
||||
while (pciu){
|
||||
bytes_reserved += sizeof(struct channel_in_use);
|
||||
@@ -499,6 +517,7 @@ LOCAL void log_one_client(struct client *client)
|
||||
}
|
||||
pciu = (struct channel_in_use *) ellNext(&pciu->node);
|
||||
}
|
||||
UNLOCK_CLIENT(client);
|
||||
|
||||
psaddr = &client->addr;
|
||||
printf("\tRemote address %u.%u.%u.%u Remote port %d state=%s\n",
|
||||
@@ -511,13 +530,21 @@ LOCAL void log_one_client(struct client *client)
|
||||
printf( "\tChannel count %d\n", ellCount(&client->addrq));
|
||||
printf( "\t%d bytes allocated\n", bytes_reserved);
|
||||
|
||||
LOCK_CLIENT(client);
|
||||
pciu = (struct channel_in_use *) client->addrq.node.next;
|
||||
i=0;
|
||||
while (pciu){
|
||||
printf( "\t%s(%d) ",
|
||||
printf( "\t%s(%d%c%c)",
|
||||
pciu->addr.precord,
|
||||
pciu->eventq.count);
|
||||
ellCount(&pciu->eventq),
|
||||
asCheckGet(pciu->asClientPVT)?'r':'-',
|
||||
asCheckPut(pciu->asClientPVT)?'w':'-');
|
||||
pciu = (struct channel_in_use *) ellNext(&pciu->node);
|
||||
if( ++i % 3 == 0){
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
UNLOCK_CLIENT(client);
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
* pend which could lock up the cast server.
|
||||
*/
|
||||
|
||||
static char *sccsId = "@(#)cast_server.c 1.17\t8/5/93";
|
||||
static char *sccsId = "$Id$";
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <ellLib.h>
|
||||
@@ -253,7 +253,7 @@ int cast_server(void)
|
||||
}
|
||||
|
||||
if(CASDEBUG>2)
|
||||
count = prsrv_cast_client->addrq.count;
|
||||
count = ellCount(&prsrv_cast_client->addrq);
|
||||
|
||||
status = camessage(
|
||||
prsrv_cast_client,
|
||||
@@ -273,11 +273,12 @@ int cast_server(void)
|
||||
}
|
||||
}
|
||||
|
||||
if(prsrv_cast_client->addrq.count){
|
||||
if(CASDEBUG>2){
|
||||
if(CASDEBUG>2){
|
||||
if(ellCount(&prsrv_cast_client->addrq)){
|
||||
logMsg( "CAS: Fnd %d name matches (%d tot)\n",
|
||||
prsrv_cast_client->addrq.count-count,
|
||||
prsrv_cast_client->addrq.count,
|
||||
ellCount(&prsrv_cast_client->addrq)
|
||||
-count,
|
||||
ellCount(&prsrv_cast_client->addrq),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
+10
-5
@@ -125,9 +125,10 @@ struct channel_in_use{
|
||||
struct event_ext{
|
||||
ELLNODE node;
|
||||
struct extmsg msg;
|
||||
struct extmsg *mp; /* for speed (IOC_READ) */
|
||||
struct channel_in_use *pciu;
|
||||
struct event_block *pdbev; /* ptr to db event block */
|
||||
unsigned size; /* for speed */
|
||||
unsigned mask;
|
||||
char modified; /* mod & ev flw ctrl enbl */
|
||||
char send_lock; /* lock send buffer */
|
||||
char get; /* T: get F: monitor */
|
||||
@@ -157,10 +158,14 @@ GLBLTYPE struct client *prsrv_cast_client;
|
||||
GLBLTYPE BUCKET *pCaBucket;
|
||||
|
||||
#define LOCK_CLIENT(CLIENT)\
|
||||
FASTLOCK(&(CLIENT)->lock);
|
||||
{\
|
||||
FASTLOCK(&(CLIENT)->lock);\
|
||||
}
|
||||
|
||||
#define UNLOCK_CLIENT(CLIENT)\
|
||||
FASTUNLOCK(&(CLIENT)->lock);
|
||||
{ \
|
||||
FASTUNLOCK(&(CLIENT)->lock);\
|
||||
}
|
||||
|
||||
#define EXTMSGPTR(CLIENT)\
|
||||
((struct extmsg *) &(CLIENT)->send.buf[(CLIENT)->send.stk])
|
||||
@@ -177,9 +182,9 @@ FASTUNLOCK(&(CLIENT)->lock);
|
||||
(CLIENT)->send.stk += sizeof(struct extmsg) + EXTMSGPTR(CLIENT)->m_postsize
|
||||
|
||||
|
||||
#define LOCK_CLIENTQ FASTLOCK(&clientQlock)
|
||||
#define LOCK_CLIENTQ FASTLOCK(&clientQlock);
|
||||
|
||||
#define UNLOCK_CLIENTQ FASTUNLOCK(&clientQlock)
|
||||
#define UNLOCK_CLIENTQ FASTUNLOCK(&clientQlock);
|
||||
|
||||
struct client *existing_client();
|
||||
int camsgtask();
|
||||
|
||||
Reference in New Issue
Block a user