Merge branch '3.15'

* 3.15:
  rsrv: fix recv() error handling on WIN32
  rsrv: export CASDEBUG to iocsh
  rsrv: flush any queued messages before forced disconnect
  rsrv: locking in cas_send_bs_msg()
  rsrv: missing send lock around send_err()
  rsrv: drop un-commited VERSION message
  rsrv: add some comments
  rsrv: avoid possible overflow in vsend_err()
  Use static strings for epicsInterruptContextMessage()

# Conflicts:
#	src/ioc/rsrv/camessage.c
This commit is contained in:
Michael Davidsaver
2017-08-01 17:20:21 +02:00
7 changed files with 44 additions and 30 deletions

View File

@@ -80,6 +80,10 @@ static int callbackIsInit;
static char *threadNamePrefix[NUM_CALLBACK_PRIORITIES] = {
"cbLow", "cbMedium", "cbHigh"
};
#define FULL_MSG(name) "callbackRequest: " name " ring buffer full\n"
static char *fullMessage[NUM_CALLBACK_PRIORITIES] = {
FULL_MSG("cbLow"), FULL_MSG("cbMedium"), FULL_MSG("cbHigh")
};
static unsigned int threadPriority[NUM_CALLBACK_PRIORITIES] = {
epicsThreadPriorityScanLow - 1,
epicsThreadPriorityScanLow + 4,
@@ -283,11 +287,7 @@ int callbackRequest(CALLBACK *pcallback)
pushOK = epicsRingPointerPush(mySet->queue, pcallback);
if (!pushOK) {
char msg[48] = "callbackRequest: ";
strcat(msg, threadNamePrefix[priority]);
strcat(msg, " ring buffer full\n");
epicsInterruptContextMessage(msg);
epicsInterruptContextMessage(fullMessage[priority]);
mySet->queueOverflow = TRUE;
return S_db_bufFull;
}

View File

@@ -9,6 +9,9 @@ variable(atExitDebug,int)
# Access security subroutines
variable(asCaDebug,int)
# CA server debug flag (very verbose) range[0,5]
variable(CASDEBUG,int)
# Static database access variables
variable(dbRecordsOnceOnly,int)
variable(dbRecordsAbcSorted,int)

View File

@@ -226,10 +226,10 @@ va_list args
/*
* add their context string into the protocol
*/
localStatus = epicsVsnprintf ( pMsgString, maxDiagLen, pformat, args );
localStatus = epicsVsnprintf ( pMsgString, maxDiagLen - size, pformat, args );
if ( localStatus >= 1 ) {
unsigned diagLen = ( unsigned ) localStatus;
if ( diagLen < maxDiagLen ) {
if ( diagLen < maxDiagLen - size ) {
size += (ca_uint32_t) (diagLen + 1u);
}
else {
@@ -237,7 +237,7 @@ va_list args
"caserver: vsend_err: epicsVsnprintf detected "
"error message truncation, pFormat = \"%s\"\n",
pformat );
size += maxDiagLen;
size = maxDiagLen;
pMsgString [ maxDiagLen - 1 ] = '\0';
}
}
@@ -2447,8 +2447,10 @@ int camessage ( struct client *client )
/* log and error for too old clients, but keep the connection open to avoid a
* re-connect loop.
*/
SEND_LOCK(client);
send_err ( &msg, ECA_DEFUNCT, client,
"CAS: Client version %u too old", client->minor_version_number );
SEND_UNLOCK(client);
log_header ( "CAS: Client version too old",
client, &msg, 0, nmsg );
client->recvBytesToDrain = msgsize - bytes_left;
@@ -2467,8 +2469,10 @@ int camessage ( struct client *client )
*/
if ( msgsize & 0x7 ) {
if (client->proto==IPPROTO_TCP) {
SEND_LOCK(client);
send_err ( &msg, ECA_INTERNAL, client,
"CAS: Missaligned protocol rejected" );
SEND_UNLOCK(client);
log_header ( "CAS: Missaligned protocol rejected",
client, &msg, 0, nmsg );
}
@@ -2486,9 +2490,11 @@ int camessage ( struct client *client )
casExpandRecvBuffer ( client, msgsize );
if ( msgsize > client->recv.maxstk ) {
if (client->proto==IPPROTO_TCP) {
SEND_LOCK(client);
send_err ( &msg, ECA_TOLARGE, client,
"CAS: Server unable to load large request message. Max bytes=%lu",
rsrvSizeofLargeBufTCP );
SEND_UNLOCK(client);
log_header ( "CAS: server unable to load large request message",
client, &msg, 0, nmsg );
}

View File

@@ -42,30 +42,18 @@
void camsgtask ( void *pParm )
{
struct client *client = (struct client *) pParm;
osiSockIoctl_t nchars;
int status;
casAttachThreadToClient ( client );
/*
* send the server's minor version number to the client
*/
status = cas_copy_in_header ( client, CA_PROTO_VERSION, 0,
0, CA_MINOR_PROTOCOL_REVISION, 0, 0, 0 );
if ( status != ECA_NORMAL ) {
LOCK_CLIENTQ;
ellDelete ( &clientQ, &client->node );
UNLOCK_CLIENTQ;
destroy_tcp_client ( client );
return;
}
while (castcp_ctl == ctlRun && !client->disconnect) {
osiSockIoctl_t check_nchars;
long nchars;
int status;
/*
* allow message to batch up if more are comming
*/
status = socket_ioctl (client->sock, FIONREAD, &nchars);
status = socket_ioctl (client->sock, FIONREAD, &check_nchars);
if (status < 0) {
char sockErrBuf[64];
@@ -75,7 +63,7 @@ void camsgtask ( void *pParm )
sockErrBuf);
cas_send_bs_msg(client, TRUE);
}
else if (nchars == 0){
else if (check_nchars == 0){
cas_send_bs_msg(client, TRUE);
}
@@ -151,6 +139,9 @@ void camsgtask ( void *pParm )
}
else {
char buf[64];
/* flush any queued messages before shutdown */
cas_send_bs_msg(client, 1);
client->recv.cnt = 0ul;

View File

@@ -37,11 +37,18 @@
* cas_send_bs_msg()
*
* (channel access server send message)
*
*
* Set lock_needed=1 unless SEND_LOCK() is held by caller
*/
void cas_send_bs_msg ( struct client *pclient, int lock_needed )
{
int status;
if ( lock_needed ) {
SEND_LOCK ( pclient );
}
if ( CASDEBUG > 2 && pclient->send.stk ) {
errlogPrintf ( "CAS: Sending a message of %d bytes\n", pclient->send.stk );
}
@@ -52,13 +59,11 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed )
pclient->sock, (unsigned) pclient->addr.sin_addr.s_addr );
}
pclient->send.stk = 0u;
if(lock_needed)
SEND_UNLOCK(pclient);
return;
}
if ( lock_needed ) {
SEND_LOCK ( pclient );
}
while ( pclient->send.stk && ! pclient->disconnect ) {
status = send ( pclient->sock, pclient->send.buf, pclient->send.stk, 0 );
if ( status >= 0 ) {

View File

@@ -7,12 +7,16 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include "osiSock.h"
#include "iocsh.h"
#define epicsExportSharedSymbols
#include "rsrv.h"
#include "server.h"
#include "rsrvIocRegister.h"
#include "epicsExport.h"
/* casr */
static const iocshArg casrArg0 = { "level",iocshArgInt};
static const iocshArg * const casrArgs[1] = {&casrArg0};
@@ -22,8 +26,9 @@ static void casrCallFunc(const iocshArgBuf *args)
casr(args[0].ival);
}
void rsrvIocRegister(void)
{
iocshRegister(&casrFuncDef,casrCallFunc);
}
epicsExportAddress(int, CASDEBUG);

View File

@@ -63,8 +63,10 @@ typedef struct caHdrLargeArray {
enum messageBufferType { mbtUDP, mbtSmallTCP, mbtLargeTCP };
struct message_buffer {
char *buf;
/*! points to first filled byte in buffer */
unsigned stk;
unsigned maxstk;
/*! points to first unused byte in buffer (after filled bytes) */
unsigned cnt;
enum messageBufferType type;
};
@@ -73,7 +75,9 @@ extern epicsThreadPrivateId rsrvCurrentClient;
typedef struct client {
ELLNODE node;
/*! guarded by SEND_LOCK() aka. client::lock */
struct message_buffer send;
/*! accessed by receive thread w/o locks cf. camsgtask() */
struct message_buffer recv;
epicsMutexId lock;
epicsMutexId putNotifyLock;