Merged changes from 3.15 branch, to revno 12807
This commit is contained in:
@@ -1146,16 +1146,10 @@ the output.</p>
|
||||
<td>Wide mode "name timestamp value stat sevr" (read PVs as
|
||||
DBR_TIME_xxx)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-n</td>
|
||||
<td>Print DBF_ENUM values as number (default are enum strings)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-d <type></td>
|
||||
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)
|
||||
|
||||
<p>or number of one of the following types:</p>
|
||||
|
||||
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)<br>
|
||||
or number of one of the following types:<br>
|
||||
<table border="1">
|
||||
<tbody>
|
||||
<tr>
|
||||
@@ -1272,6 +1266,14 @@ the output.</p>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><strong>Enum format:</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-n</td>
|
||||
<td>Print DBF_ENUM value as number (default is enum string)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><strong>Arrays:</strong></td>
|
||||
@@ -1303,15 +1305,15 @@ the output.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-e <nr></td>
|
||||
<td>Use %e format, with <nr> digits after the decimal point</td>
|
||||
<td>Use %e format, with a precision of <nr> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-f <nr></td>
|
||||
<td>Use %f format, with <nr> digits after the decimal point</td>
|
||||
<td>Use %f format, with a precision of <nr> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-g <nr></td>
|
||||
<td>Use %g format, with <nr> digits after the decimal point</td>
|
||||
<td>Use %g format, with a precision of <nr> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-s</td>
|
||||
@@ -1349,6 +1351,14 @@ the output.</p>
|
||||
<td>-0b</td>
|
||||
<td>Print as binary number</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><strong>Alternate output field separator:</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-F <ofs></td>
|
||||
<td>Use <ofs> as an alternate output field separator</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -1381,9 +1391,10 @@ the output.</p>
|
||||
<td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-m <mask></td>
|
||||
<td>Specify CA event mask to use, with <mask> being any combination
|
||||
of 'v' (value), 'a' (alarm), 'l' (log), 'p' (property). Default: va</td>
|
||||
<td>-m <msk></td>
|
||||
<td>Specify CA event mask to use. <msk> is any combination of<br>
|
||||
'v' (value), 'a' (alarm), 'l' (log/archive), 'p' (property).<br>
|
||||
Default event mask is 'va'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-p <prio></td>
|
||||
@@ -1405,8 +1416,8 @@ the output.</p>
|
||||
'n' = no timestamps<br>
|
||||
'r' = relative timestamps (time elapsed since start of program)<br>
|
||||
'i' = incremental timestamps (time elapsed since last update)<br>
|
||||
'I' = incremental timestamps (time elapsed since last update, by
|
||||
channel)</td>
|
||||
'I' = incremental timestamps (time since last update, by channel)<br>
|
||||
'r', 'i' or 'I' require 's' or 'c' to select the time source</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
@@ -1414,7 +1425,7 @@ the output.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-n</td>
|
||||
<td>Print DBF_ENUM values as number (default are enum strings)</td>
|
||||
<td>Print DBF_ENUM values as number (default is enum string)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
@@ -1422,16 +1433,15 @@ the output.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Value format: Print number of requested values, then list of
|
||||
values</td>
|
||||
<td>Array values: Print number of elements, then list of values</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Default:</td>
|
||||
<td>Print all values</td>
|
||||
<td>Default: Request and print all elements (dynamic arrays supported)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-# <count></td>
|
||||
<td>Print first <count> elements of an array</td>
|
||||
<td>-# <num></td>
|
||||
<td>Request and print up to <num> elements</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-S</td>
|
||||
@@ -1439,23 +1449,23 @@ the output.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><strong>Floating point type format:</strong></td>
|
||||
<td><strong>Floating point format:</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Default:</td>
|
||||
<td>Use %g format</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-e <nr></td>
|
||||
<td>Use %e format, with <nr> digits after the decimal point</td>
|
||||
<td>-e <num></td>
|
||||
<td>Use %e format, with a precision of <num> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-f <nr></td>
|
||||
<td>Use %f format, with <nr> digits after the decimal point</td>
|
||||
<td>-f <num></td>
|
||||
<td>Use %f format, with a precision of <num> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-g <nr></td>
|
||||
<td>Use %g format, with <nr> digits after the decimal point</td>
|
||||
<td>-g <num></td>
|
||||
<td>Use %g format, with a precision of <num> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-s</td>
|
||||
@@ -1497,21 +1507,27 @@ the output.</p>
|
||||
</table>
|
||||
|
||||
<h3><a name="caput">caput</a></h3>
|
||||
<pre>caput [options] <PV name> <value>
|
||||
<pre>caput [options] <PV name> <value> ...
|
||||
caput -a [options] <PV name> <no of elements> <value> ...</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Put value to a PV.</p>
|
||||
|
||||
<p>The specified value is written to the PV (as a string). The PV value is read
|
||||
before and after the write operation and printed as "Old" and "new" values on
|
||||
stdout.</p>
|
||||
<p>The specified value is written to the PV (as a string). The PV's value is
|
||||
read before and after the write operation and printed as "Old" and "New" values
|
||||
on stdout.</p>
|
||||
|
||||
<p>The array variant writes an array to the specified PV. The first numeric
|
||||
argument specifying the number of array elements is kept for compatibility with
|
||||
the array data format of caget - the actual number of values specified on the
|
||||
command line is used.</p>
|
||||
<p>There are two variants to the arguments for this command. For the scalar
|
||||
variant without the <code>-a</code> flag, all the value arguments provided after
|
||||
the PV name are concatenated with a single space character between them, and the
|
||||
resulting string (up to 40 characters long unless the <code>-S</code> flag is
|
||||
given) is written to the specified PV.</p>
|
||||
|
||||
<p>The array variant with the <code>-a</code> flag writes an array of string
|
||||
values to the specified PV. The numeric argument giving the number of array
|
||||
elements is actually ignored, the array length to be written is actually
|
||||
controlled by the number of values provided on the command line.</p>
|
||||
|
||||
<table border="1">
|
||||
<caption></caption>
|
||||
@@ -1550,12 +1566,16 @@ command line is used.</p>
|
||||
<td>-t</td>
|
||||
<td>Terse mode - print only successfully written value, without name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-l</td>
|
||||
<td>Long mode "name timestamp value stat sevr" (read PVs as DBR_TIME_xxx)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><strong>Enum Format:</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Default:</td>
|
||||
<td>Auto - try value as ENUM string, then as index number</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -1571,17 +1591,24 @@ command line is used.</p>
|
||||
<td><strong>Arrays:</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-a</td>
|
||||
<td>Put array data</td>
|
||||
<td>Default:</td>
|
||||
<td>Put scalar</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Value format: Print number of requested values, then list of
|
||||
values</td>
|
||||
<td>Value format: all value arguments concatenated with spaces</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-S</td>
|
||||
<td>Put string as an array of char (long string)</td>
|
||||
<td>Put string as an array of chars (long string)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-a</td>
|
||||
<td>Put array</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Value format: number of values, then list of values</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -149,9 +149,9 @@ cac::cac (
|
||||
iiuExistenceCount ( 0u ),
|
||||
cacShutdownInProgress ( false )
|
||||
{
|
||||
if ( ! osiSockAttach () ) {
|
||||
throwWithLocation ( caErrorCode (ECA_INTERNAL) );
|
||||
}
|
||||
if ( ! osiSockAttach () ) {
|
||||
throwWithLocation ( udpiiu :: noSocket () );
|
||||
}
|
||||
|
||||
try {
|
||||
long status;
|
||||
|
||||
@@ -61,11 +61,6 @@ static const double CA_CONN_VERIFY_PERIOD = 30.0; /* (sec) how often to request
|
||||
*/
|
||||
static const unsigned contiguousMsgCountWhichTriggersFlowControl = 10u;
|
||||
|
||||
class caErrorCode {
|
||||
public:
|
||||
caErrorCode ( int ) {};
|
||||
};
|
||||
|
||||
/*
|
||||
* CA internal functions
|
||||
*/
|
||||
|
||||
@@ -504,6 +504,7 @@ void ca_repeater ()
|
||||
if ( sockerrno == SOCK_EADDRINUSE ) {
|
||||
osiSockRelease ();
|
||||
debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) );
|
||||
delete [] pBuf;
|
||||
return;
|
||||
}
|
||||
char sockErrBuf[64];
|
||||
|
||||
@@ -44,12 +44,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if 0
|
||||
const unsigned mSecPerSec = 1000u;
|
||||
const unsigned uSecPerSec = 1000u * mSecPerSec;
|
||||
#endif
|
||||
|
||||
tcpSendThread::tcpSendThread (
|
||||
tcpSendThread::tcpSendThread (
|
||||
class tcpiiu & iiuIn, const char * pName,
|
||||
unsigned stackSize, unsigned priority ) :
|
||||
thread ( *this, pName, stackSize, priority ), iiu ( iiuIn )
|
||||
@@ -807,28 +802,6 @@ tcpiiu::tcpiiu (
|
||||
}
|
||||
}
|
||||
|
||||
# if 0
|
||||
//
|
||||
// windows has a really strange implementation of thess options
|
||||
// and we can avoid the need for this by using pthread_kill on unix
|
||||
//
|
||||
{
|
||||
struct timeval timeout;
|
||||
double pollInterval = connectionTimeout / 8.0;
|
||||
timeout.tv_sec = static_cast < long > ( pollInterval );
|
||||
timeout.tv_usec = static_cast < long >
|
||||
( ( pollInterval - timeout.tv_sec ) * uSecPerSec );
|
||||
// intentionally ignore status as we dont expect that all systems
|
||||
// will accept this request
|
||||
setsockopt ( this->sock, SOL_SOCKET, SO_SNDTIMEO,
|
||||
( char * ) & timeout, sizeof ( timeout ) );
|
||||
// intentionally ignore status as we dont expect that all systems
|
||||
// will accept this request
|
||||
setsockopt ( this->sock, SOL_SOCKET, SO_RCVTIMEO,
|
||||
( char * ) & timeout, sizeof ( timeout ) );
|
||||
}
|
||||
# endif
|
||||
|
||||
if ( isNameService() ) {
|
||||
pSearchDest->setCircuit ( this );
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ static epicsEventId epId;
|
||||
|
||||
void usage (void)
|
||||
{
|
||||
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value>\n"
|
||||
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value> ...\n"
|
||||
" caput -a [options] <PV name> <no of values> <PV value> ...\n\n"
|
||||
" -h: Help: Print this message\n"
|
||||
"Channel Access options:\n"
|
||||
@@ -71,9 +71,11 @@ void usage (void)
|
||||
" -n: Force interpretation of values as numbers\n"
|
||||
" -s: Force interpretation of values as strings\n"
|
||||
"Arrays:\n"
|
||||
" Default: Put scalar\n"
|
||||
" Value format: all value arguments concatenated with spaces\n"
|
||||
" -S: Put string as an array of chars (long string)\n"
|
||||
" -a: Put array\n"
|
||||
" Value format: number of requested values, then list of values\n"
|
||||
" -S: Put string as an array of char (long string)\n"
|
||||
" Value format: number of values, then list of values\n"
|
||||
"Alternate output field separator:\n"
|
||||
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
|
||||
"\nExample: caput my_channel 1.2\n"
|
||||
|
||||
@@ -930,10 +930,12 @@ bool udpiiu::pushDatagramMsg ( epicsGuard < epicsMutex > & guard,
|
||||
|
||||
caHdr * pbufmsg = ( caHdr * ) &this->xmitBuf[this->nBytesInXmitBuf];
|
||||
*pbufmsg = msg;
|
||||
memcpy ( pbufmsg + 1, pExt, extsize );
|
||||
if ( extsize != alignedExtSize ) {
|
||||
char *pDest = (char *) ( pbufmsg + 1 );
|
||||
memset ( pDest + extsize, '\0', alignedExtSize - extsize );
|
||||
if ( extsize ) {
|
||||
memcpy ( pbufmsg + 1, pExt, extsize );
|
||||
if ( extsize != alignedExtSize ) {
|
||||
char *pDest = (char *) ( pbufmsg + 1 );
|
||||
memset ( pDest + extsize, '\0', alignedExtSize - extsize );
|
||||
}
|
||||
}
|
||||
AlignedWireRef < epicsUInt16 > ( pbufmsg->m_postsize ) = alignedExtSize;
|
||||
this->nBytesInXmitBuf += msgsize;
|
||||
|
||||
@@ -1355,8 +1355,9 @@ gddStatus gdd::put ( const gdd * dd )
|
||||
}
|
||||
|
||||
aitUint32 srcAvailSize = srcElemCount - unusedSrcBelow;
|
||||
if ( srcAvailSize > this->getBounds()->size() ) {
|
||||
srcCopySize = this->getBounds()->size();
|
||||
aitUint32 destSize = this->getBounds()->size();
|
||||
if ( destSize > 0 && srcAvailSize > destSize ) {
|
||||
srcCopySize = destSize;
|
||||
}
|
||||
else {
|
||||
srcCopySize = srcAvailSize;
|
||||
|
||||
@@ -418,8 +418,10 @@ gddStatus gddApplicationTypeTable::freeDD(gdd* dd)
|
||||
}
|
||||
|
||||
// fprintf(stderr,"Adding DD to free_list %d\n",app);
|
||||
attr_table[group][app].sem.lock ();
|
||||
dd->setNext(attr_table[group][app].free_list);
|
||||
attr_table[group][app].free_list=dd;
|
||||
attr_table[group][app].sem.unlock ();
|
||||
}
|
||||
else if (attr_table[group][app].type==gddApplicationTypeNormal)
|
||||
{
|
||||
|
||||
@@ -308,7 +308,7 @@ void gdd::test()
|
||||
pdd->convertOffsetsToAddress();
|
||||
pdd->dump();
|
||||
pdd->unreference();
|
||||
delete buf;
|
||||
delete [] buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -510,7 +510,7 @@ void gddContainer::test(void)
|
||||
fprintf(stderr,"=====RE-DUMP OF ORIGINAL CONTAINER:\n");
|
||||
dump();
|
||||
cdd1->unreference();
|
||||
delete buf;
|
||||
delete [] buf;
|
||||
|
||||
// test copy(), Dup(), copyInfo()
|
||||
fprintf(stderr,"=======CREATING TEST CONTAINER FOR *COPY* TEST:\n");
|
||||
|
||||
@@ -170,7 +170,7 @@ static int parseDirectoryFP (FILE *pf, const char *pFileName)
|
||||
|
||||
status = aToIPAddr (hostNameStr, 0u, &ipa);
|
||||
if (status) {
|
||||
fprintf (pf, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
|
||||
fprintf (stderr, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
|
||||
hostNameStr, pFileName, pvNameStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
static const unsigned char CA_MINOR_PROTOCOL_REVISION = 12;
|
||||
static const unsigned char CA_MINOR_PROTOCOL_REVISION = 13;
|
||||
|
||||
typedef ca_uint32_t caResId;
|
||||
|
||||
|
||||
@@ -40,8 +40,13 @@ class casIntfOS;
|
||||
class casMonitor;
|
||||
class casChannelI;
|
||||
|
||||
caStatus convertContainerMemberToAtomic ( class gdd & dd,
|
||||
aitUint32 appType, aitUint32 elemCount );
|
||||
caStatus convertContainerMemberToAtomic (class gdd & dd,
|
||||
aitUint32 appType, aitUint32 requestedCount, aitUint32 nativeCount);
|
||||
|
||||
// Keep the old signature for backward compatibility
|
||||
inline caStatus convertContainerMemberToAtomic (class gdd & dd,
|
||||
aitUint32 appType, aitUint32 elemCount)
|
||||
{ return convertContainerMemberToAtomic(dd, appType, elemCount, elemCount); }
|
||||
|
||||
class caServerI :
|
||||
public caServerIO,
|
||||
|
||||
@@ -21,6 +21,7 @@ casChannelI::casChannelI ( casCoreClient & clientIn,
|
||||
casChannel & chanIn, casPVI & pvIn, ca_uint32_t cidIn ) :
|
||||
privateForPV ( clientIn, *this ),
|
||||
pv ( pvIn ),
|
||||
maxElem( pvIn.nativeCount() ),
|
||||
chan ( chanIn ),
|
||||
cid ( cidIn ),
|
||||
serverDeletePending ( false ),
|
||||
@@ -29,7 +30,7 @@ casChannelI::casChannelI ( casCoreClient & clientIn,
|
||||
}
|
||||
|
||||
casChannelI::~casChannelI ()
|
||||
{
|
||||
{
|
||||
this->privateForPV.client().removeFromEventQueue (
|
||||
*this, this->accessRightsEvPending );
|
||||
|
||||
@@ -48,7 +49,7 @@ void casChannelI::uninstallFromPV ( casEventSys & eventSys )
|
||||
this->privateForPV.removeSelfFromPV ( this->pv, dest );
|
||||
while ( casMonitor * pMon = dest.get () ) {
|
||||
eventSys.prepareMonitorForDestroy ( *pMon );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void casChannelI::show ( unsigned level ) const
|
||||
@@ -68,13 +69,13 @@ caStatus casChannelI::cbFunc (
|
||||
{
|
||||
caStatus stat = S_cas_success;
|
||||
{
|
||||
stat = this->privateForPV.client().accessRightsResponse (
|
||||
stat = this->privateForPV.client().accessRightsResponse (
|
||||
clientGuard, this );
|
||||
}
|
||||
if ( stat == S_cas_success ) {
|
||||
this->accessRightsEvPending = false;
|
||||
}
|
||||
return stat;
|
||||
if ( stat == S_cas_success ) {
|
||||
this->accessRightsEvPending = false;
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
caStatus casChannelI::read ( const casCtx & ctx, gdd & prototype )
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
@@ -31,55 +30,62 @@ class casChannelI : public tsDLNode < casChannelI >,
|
||||
public:
|
||||
casChannelI ( casCoreClient & clientIn, casChannel & chanIn,
|
||||
casPVI & pvIn, ca_uint32_t cidIn );
|
||||
~casChannelI ();
|
||||
~casChannelI ();
|
||||
void casChannelDestroyFromInterfaceNotify ();
|
||||
const caResId getCID ();
|
||||
const caResId getSID ();
|
||||
const caResId getCID ();
|
||||
const caResId getSID ();
|
||||
void uninstallFromPV ( casEventSys & eventSys );
|
||||
void installIntoPV ();
|
||||
void installIO ( casAsyncIOI & );
|
||||
void uninstallIO ( casAsyncIOI & );
|
||||
void installMonitor ( casMonitor & mon );
|
||||
casMonitor * removeMonitor ( ca_uint32_t clientIdIn );
|
||||
casPVI & getPVI () const;
|
||||
void clearOutstandingReads ();
|
||||
void postAccessRightsEvent ();
|
||||
casPVI & getPVI () const;
|
||||
void clearOutstandingReads ();
|
||||
void postAccessRightsEvent ();
|
||||
const gddEnumStringTable & enumStringTable () const;
|
||||
void setOwner ( const char * const pUserName,
|
||||
const char * const pHostName );
|
||||
bool readAccess () const;
|
||||
ca_uint32_t getMaxElem () const;
|
||||
void setOwner ( const char * const pUserName,
|
||||
const char * const pHostName );
|
||||
bool readAccess () const;
|
||||
bool writeAccess () const;
|
||||
bool confirmationRequested () const;
|
||||
bool confirmationRequested () const;
|
||||
caStatus read ( const casCtx & ctx, gdd & prototype );
|
||||
caStatus write ( const casCtx & ctx, const gdd & value );
|
||||
caStatus writeNotify ( const casCtx & ctx, const gdd & value );
|
||||
void show ( unsigned level ) const;
|
||||
void show ( unsigned level ) const;
|
||||
private:
|
||||
chanIntfForPV privateForPV;
|
||||
tsDLList < casAsyncIOI > ioList;
|
||||
casPVI & pv;
|
||||
tsDLList < casAsyncIOI > ioList;
|
||||
casPVI & pv;
|
||||
ca_uint32_t maxElem;
|
||||
casChannel & chan;
|
||||
caResId cid; // client id
|
||||
caResId cid; // client id
|
||||
bool serverDeletePending;
|
||||
bool accessRightsEvPending;
|
||||
//epicsShareFunc virtual void destroy ();
|
||||
caStatus cbFunc (
|
||||
bool accessRightsEvPending;
|
||||
//epicsShareFunc virtual void destroy ();
|
||||
caStatus cbFunc (
|
||||
casCoreClient &,
|
||||
epicsGuard < casClientMutex > &,
|
||||
epicsGuard < evSysMutex > & );
|
||||
void postDestroyEvent ();
|
||||
casChannelI ( const casChannelI & );
|
||||
casChannelI & operator = ( const casChannelI & );
|
||||
casChannelI ( const casChannelI & );
|
||||
casChannelI & operator = ( const casChannelI & );
|
||||
};
|
||||
|
||||
inline casPVI & casChannelI::getPVI () const
|
||||
{
|
||||
return this->pv;
|
||||
return this->pv;
|
||||
}
|
||||
|
||||
inline ca_uint32_t casChannelI::getMaxElem () const
|
||||
{
|
||||
return this->maxElem;
|
||||
}
|
||||
|
||||
inline const caResId casChannelI::getCID ()
|
||||
{
|
||||
return this->cid;
|
||||
return this->cid;
|
||||
}
|
||||
|
||||
inline const caResId casChannelI::getSID ()
|
||||
@@ -89,7 +95,7 @@ inline const caResId casChannelI::getSID ()
|
||||
|
||||
inline void casChannelI::postAccessRightsEvent ()
|
||||
{
|
||||
this->privateForPV.client().addToEventQueue ( *this, this->accessRightsEvPending );
|
||||
this->privateForPV.client().addToEventQueue ( *this, this->accessRightsEvPending );
|
||||
}
|
||||
|
||||
inline const gddEnumStringTable & casChannelI::enumStringTable () const
|
||||
@@ -108,7 +114,7 @@ inline void casChannelI::clearOutstandingReads ()
|
||||
}
|
||||
|
||||
inline void casChannelI::setOwner ( const char * const pUserName,
|
||||
const char * const pHostName )
|
||||
const char * const pHostName )
|
||||
{
|
||||
this->chan.setOwner ( pUserName, pHostName );
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "caHdrLargeArray.h"
|
||||
|
||||
class casStrmClient;
|
||||
|
||||
class casCtx {
|
||||
public:
|
||||
casCtx();
|
||||
@@ -41,6 +43,7 @@ private:
|
||||
casChannelI * pChannel;
|
||||
casPVI * pPV;
|
||||
unsigned nAsyncIO; // checks for improper use of async io
|
||||
friend class casStrmClient;
|
||||
};
|
||||
|
||||
inline const caHdrLargeArray * casCtx::getMsg() const
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* Author Jeffrey O. Hill
|
||||
@@ -30,9 +30,9 @@ casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
|
||||
& casDGClient::uknownMessageAction,
|
||||
& casDGClient::uknownMessageAction,
|
||||
|
||||
& casDGClient::uknownMessageAction,
|
||||
& casDGClient::searchAction,
|
||||
& casDGClient::uknownMessageAction,
|
||||
& casDGClient::uknownMessageAction,
|
||||
& casDGClient::searchAction,
|
||||
& casDGClient::uknownMessageAction,
|
||||
& casDGClient::uknownMessageAction,
|
||||
& casDGClient::uknownMessageAction,
|
||||
|
||||
@@ -64,9 +64,9 @@ casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
|
||||
//
|
||||
casDGClient::casDGClient ( caServerI & serverIn, clientBufMemoryManager & mgrIn ) :
|
||||
casCoreClient ( serverIn ),
|
||||
in ( *this, mgrIn, MAX_UDP_RECV + sizeof ( cadg ) ),
|
||||
in ( *this, mgrIn, MAX_UDP_RECV + sizeof ( cadg ) ),
|
||||
out ( *this, mgrIn ),
|
||||
seqNoOfReq ( 0 ),
|
||||
seqNoOfReq ( 0 ),
|
||||
minor_version_number ( 0 )
|
||||
{
|
||||
}
|
||||
@@ -92,15 +92,15 @@ void casDGClient::destroy()
|
||||
//
|
||||
void casDGClient::show (unsigned level) const
|
||||
{
|
||||
printf ( "casDGClient at %p\n",
|
||||
printf ( "casDGClient at %p\n",
|
||||
static_cast <const void *> ( this ) );
|
||||
if (level>=1u) {
|
||||
char buf[64];
|
||||
this->hostName (buf, sizeof(buf));
|
||||
printf ("Client Host=%s\n", buf);
|
||||
this->casCoreClient::show ( level - 1u );
|
||||
this->in.show ( level - 1u );
|
||||
this->out.show ( level - 1u );
|
||||
this->casCoreClient::show ( level - 1u );
|
||||
this->in.show ( level - 1u );
|
||||
this->out.show ( level - 1u );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ caStatus casDGClient::uknownMessageAction ()
|
||||
char pHostName[64u];
|
||||
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
|
||||
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
"bad request code=%u in DG\n", mp->m_cmmd );
|
||||
|
||||
return S_cas_badProtocol;
|
||||
@@ -135,7 +135,7 @@ caStatus casDGClient::searchAction()
|
||||
if ( mp->m_postsize <= 1 ) {
|
||||
char pHostName[64u];
|
||||
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
"empty PV name extension in UDP search request?\n" );
|
||||
return S_cas_success;
|
||||
}
|
||||
@@ -143,19 +143,19 @@ caStatus casDGClient::searchAction()
|
||||
if ( pChanName[0] == '\0' ) {
|
||||
char pHostName[64u];
|
||||
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
"zero length PV name in UDP search request?\n" );
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
// check for an unterminated string before calling server tool
|
||||
// by searching backwards through the string (some early versions
|
||||
// by searching backwards through the string (some early versions
|
||||
// of the client library might not be setting the pad bytes to nill)
|
||||
for ( unsigned i = mp->m_postsize-1; pChanName[i] != '\0'; i-- ) {
|
||||
if ( i <= 1 ) {
|
||||
char pHostName[64u];
|
||||
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
"unterminated PV name in UDP search request?\n" );
|
||||
return S_cas_success;
|
||||
}
|
||||
@@ -183,7 +183,7 @@ caStatus casDGClient::searchAction()
|
||||
// ask the server tool if this PV exists
|
||||
//
|
||||
this->userStartedAsyncIO = false;
|
||||
pvExistReturn pver =
|
||||
pvExistReturn pver =
|
||||
this->getCAS()->pvExistTest ( this->ctx, this->lastRecvAddr, pChanName );
|
||||
|
||||
//
|
||||
@@ -193,7 +193,7 @@ caStatus casDGClient::searchAction()
|
||||
//
|
||||
if ( this->userStartedAsyncIO ) {
|
||||
if ( pver.getStatus() != pverAsyncCompletion ) {
|
||||
errMessage (S_cas_badParameter,
|
||||
errMessage (S_cas_badParameter,
|
||||
"- assuming asynch IO status from caServer::pvExistTest()");
|
||||
}
|
||||
status = S_cas_success;
|
||||
@@ -212,13 +212,13 @@ caStatus casDGClient::searchAction()
|
||||
break;
|
||||
|
||||
case pverAsyncCompletion:
|
||||
errMessage (S_cas_badParameter,
|
||||
errMessage (S_cas_badParameter,
|
||||
"- unexpected asynch IO status from caServer::pvExistTest() ignored");
|
||||
status = S_cas_success;
|
||||
break;
|
||||
|
||||
default:
|
||||
errMessage (S_cas_badParameter,
|
||||
errMessage (S_cas_badParameter,
|
||||
"- invalid return from caServer::pvExistTest() ignored");
|
||||
status = S_cas_success;
|
||||
break;
|
||||
@@ -234,14 +234,14 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
|
||||
const pvExistReturn & retVal )
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
|
||||
if ( retVal.getStatus() != pverExistsHere ) {
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// starting with V4.1 the count field is used (abused)
|
||||
// by the client to store the minor version number of
|
||||
// by the client to store the minor version number of
|
||||
// the client.
|
||||
//
|
||||
// Old versions expect alloc of channel in response
|
||||
@@ -250,8 +250,8 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
|
||||
if ( !CA_V44(msg.m_count) ) {
|
||||
char pName[64u];
|
||||
this->hostName (pName, sizeof (pName));
|
||||
errlogPrintf (
|
||||
"client \"%s\" using EPICS R3.11 CA connect protocol was ignored\n",
|
||||
errlogPrintf (
|
||||
"client \"%s\" using EPICS R3.11 CA connect protocol was ignored\n",
|
||||
pName);
|
||||
//
|
||||
// old connect protocol was dropped when the
|
||||
@@ -264,19 +264,19 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
|
||||
}
|
||||
|
||||
//
|
||||
// cid field is abused to carry the IP
|
||||
// cid field is abused to carry the IP
|
||||
// address in CA_V48 or higher
|
||||
// (this allows a CA servers to serve
|
||||
// as a directory service)
|
||||
//
|
||||
// data type field is abused to carry the IP
|
||||
// data type field is abused to carry the IP
|
||||
// port number here CA_V44 or higher
|
||||
// (this allows multiple CA servers on one
|
||||
// host)
|
||||
//
|
||||
ca_uint32_t serverAddr;
|
||||
ca_uint16_t serverPort;
|
||||
if ( CA_V48( msg.m_count ) ) {
|
||||
if ( CA_V48( msg.m_count ) ) {
|
||||
struct sockaddr_in ina;
|
||||
if ( retVal.addrIsValid() ) {
|
||||
caNetAddr addr = retVal.getAddr();
|
||||
@@ -296,7 +296,7 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
|
||||
ina = addr.getSockIP();
|
||||
//
|
||||
// We dont fill in the servers address here
|
||||
// because the server was not bound to a particular
|
||||
// because the server was not bound to a particular
|
||||
// interface, and we would need to waste CPU performing
|
||||
// the following steps to determine the interface that
|
||||
// will be used:
|
||||
@@ -318,24 +318,24 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
|
||||
serverAddr = ~0U;
|
||||
serverPort = ntohs ( inetAddr.sin_port );
|
||||
}
|
||||
|
||||
|
||||
ca_uint16_t * pMinorVersion;
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
status = this->out.copyInHeader ( CA_PROTO_SEARCH,
|
||||
sizeof ( *pMinorVersion ), serverPort, 0,
|
||||
serverAddr, msg.m_available,
|
||||
status = this->out.copyInHeader ( CA_PROTO_SEARCH,
|
||||
sizeof ( *pMinorVersion ), serverPort, 0,
|
||||
serverAddr, msg.m_available,
|
||||
reinterpret_cast <void **> ( &pMinorVersion ) );
|
||||
//
|
||||
// Starting with CA V4.1 the minor version number
|
||||
// is appended to the end of each search reply.
|
||||
// This value is ignored by earlier clients.
|
||||
// This value is ignored by earlier clients.
|
||||
//
|
||||
if ( status == S_cas_success ) {
|
||||
AlignedWireRef < epicsUInt16 > tmp ( *pMinorVersion );
|
||||
tmp = CA_MINOR_PROTOCOL_REVISION;
|
||||
this->out.commitMsg ();
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -346,15 +346,11 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
|
||||
//
|
||||
caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
status = this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
|
||||
this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
|
||||
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, 0 );
|
||||
|
||||
if ( status == S_cas_success ) {
|
||||
this->out.commitMsg ();
|
||||
}
|
||||
this->out.commitMsg ();
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
@@ -408,8 +404,8 @@ void casDGClient::sendBeacon ( ca_uint32_t beaconNumber )
|
||||
//
|
||||
// casDGClient::xSend()
|
||||
//
|
||||
outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
|
||||
bufSizeT nBytesToSend, bufSizeT & nBytesSent )
|
||||
outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
|
||||
bufSizeT nBytesToSend, bufSizeT & nBytesSent )
|
||||
{
|
||||
bufSizeT totalBytes = 0;
|
||||
while ( totalBytes < nBytesToSend ) {
|
||||
@@ -422,7 +418,7 @@ outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
|
||||
unsigned sizeDG = pHdr->cadg_nBytes - sizeof ( *pHdr );
|
||||
|
||||
if ( pHdr->cadg_addr.isValid() ) {
|
||||
outBufClient::flushCondition stat =
|
||||
outBufClient::flushCondition stat =
|
||||
this->osdSend ( pDG, sizeDG, pHdr->cadg_addr );
|
||||
if ( stat != outBufClient::flushProgress ) {
|
||||
break;
|
||||
@@ -459,7 +455,7 @@ inBufClient::fillCondition casDGClient::xRecv (char *pBufIn, bufSizeT nBytesToRe
|
||||
|
||||
while (pAfter-pCurBuf >= static_cast<int>(MAX_UDP_RECV+sizeof(cadg))) {
|
||||
pHdr = reinterpret_cast < cadg * > ( pCurBuf );
|
||||
stat = this->osdRecv ( reinterpret_cast < char * > ( pHdr + 1 ),
|
||||
stat = this->osdRecv ( reinterpret_cast < char * > ( pHdr + 1 ),
|
||||
MAX_UDP_RECV, parm, nDGBytesRecv, pHdr->cadg_addr);
|
||||
if (stat==casFillProgress) {
|
||||
pHdr->cadg_nBytes = nDGBytesRecv + sizeof(*pHdr);
|
||||
@@ -491,7 +487,7 @@ inBufClient::fillCondition casDGClient::xRecv (char *pBufIn, bufSizeT nBytesToRe
|
||||
// this results in many small UDP frames which unfortunately
|
||||
// isnt particularly efficient
|
||||
//
|
||||
caStatus casDGClient::asyncSearchResponse (
|
||||
caStatus casDGClient::asyncSearchResponse (
|
||||
epicsGuard < casClientMutex > &, const caNetAddr & outAddr,
|
||||
const caHdrLargeArray & msg, const pvExistReturn & retVal,
|
||||
ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber )
|
||||
@@ -501,7 +497,7 @@ caStatus casDGClient::asyncSearchResponse (
|
||||
}
|
||||
|
||||
void * pRaw;
|
||||
const outBufCtx outctx = this->out.pushCtx
|
||||
const outBufCtx outctx = this->out.pushCtx
|
||||
( sizeof(cadg), MAX_UDP_SEND, pRaw );
|
||||
if ( outctx.pushResult() != outBufCtx::pushCtxSuccess ) {
|
||||
return S_cas_sendBlocked;
|
||||
@@ -565,9 +561,9 @@ caStatus casDGClient::processDG ()
|
||||
|
||||
// insert version header at the start of the reply message
|
||||
this->sendVersion ();
|
||||
|
||||
|
||||
cadg * pRespHdr = static_cast < cadg * > ( pRaw );
|
||||
|
||||
|
||||
//
|
||||
// select the next DG in the input stream and start processing it
|
||||
//
|
||||
@@ -597,7 +593,7 @@ caStatus casDGClient::processDG ()
|
||||
// a) it used all of the incoming DG or
|
||||
// b) it used all of the outgoing DG
|
||||
//
|
||||
// In either case commit the DG to the protocol stream and
|
||||
// In either case commit the DG to the protocol stream and
|
||||
// release the send lock
|
||||
//
|
||||
// if there are not additional messages passed the version header
|
||||
@@ -688,7 +684,7 @@ void casDGClient::hostName ( char *pBufIn, unsigned bufSizeIn ) const
|
||||
void casDGClient::sendVersion ()
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
caStatus status = this->out.copyInHeader ( CA_PROTO_VERSION, 0,
|
||||
caStatus status = this->out.copyInHeader ( CA_PROTO_VERSION, 0,
|
||||
0, CA_MINOR_PROTOCOL_REVISION, 0, 0, 0 );
|
||||
if ( ! status ) {
|
||||
this->out.commitMsg ();
|
||||
@@ -783,8 +779,8 @@ caStatus casDGClient::processMsg ()
|
||||
msgTmp.m_available = AlignedWireRef < epicsUInt32 > ( smallHdr.m_available );
|
||||
|
||||
if ( payloadSize & 0x7 ) {
|
||||
status = this->sendErr (
|
||||
& msgTmp, invalidResID, ECA_INTERNAL,
|
||||
status = this->sendErr (
|
||||
& msgTmp, invalidResID, ECA_INTERNAL,
|
||||
"CAS: Datagram request wasn't 8 byte aligned" );
|
||||
this->in.removeMsg ( bytesLeft );
|
||||
break;
|
||||
@@ -793,7 +789,7 @@ caStatus casDGClient::processMsg ()
|
||||
msgSize = hdrSize + payloadSize;
|
||||
if ( bytesLeft < msgSize ) {
|
||||
if ( msgSize > this->in.bufferSize() ) {
|
||||
status = this->sendErr ( & msgTmp, invalidResID, ECA_TOLARGE,
|
||||
status = this->sendErr ( & msgTmp, invalidResID, ECA_TOLARGE,
|
||||
"client's request didnt fit within the CA server's message buffer" );
|
||||
this->in.removeMsg ( bytesLeft );
|
||||
}
|
||||
@@ -805,7 +801,7 @@ caStatus casDGClient::processMsg ()
|
||||
if ( this->getCAS().getDebugLevel() > 5u ) {
|
||||
char pHostName[64u];
|
||||
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
|
||||
caServerI::dumpMsg ( pHostName, "?",
|
||||
caServerI::dumpMsg ( pHostName, "?",
|
||||
& msgTmp, rawMP + hdrSize, 0 );
|
||||
}
|
||||
|
||||
@@ -813,7 +809,7 @@ caStatus casDGClient::processMsg ()
|
||||
|
||||
//
|
||||
// Reset the context to the default
|
||||
// (guarantees that previous message does not get mixed
|
||||
// (guarantees that previous message does not get mixed
|
||||
// up with the current message)
|
||||
//
|
||||
this->ctx.setChannel ( NULL );
|
||||
@@ -840,16 +836,16 @@ caStatus casDGClient::processMsg ()
|
||||
}
|
||||
catch ( std::exception & except ) {
|
||||
this->in.removeMsg ( this->in.bytesPresent() );
|
||||
status = this->sendErr (
|
||||
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
|
||||
this->sendErr (
|
||||
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
|
||||
"C++ exception \"%s\" in CA circuit server",
|
||||
except.what () );
|
||||
status = S_cas_internal;
|
||||
}
|
||||
catch (...) {
|
||||
this->in.removeMsg ( this->in.bytesPresent() );
|
||||
status = this->sendErr (
|
||||
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
|
||||
this->sendErr (
|
||||
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
|
||||
"unexpected C++ exception in CA datagram server" );
|
||||
status = S_cas_internal;
|
||||
}
|
||||
@@ -860,37 +856,38 @@ caStatus casDGClient::processMsg ()
|
||||
//
|
||||
// casDGClient::sendErr()
|
||||
//
|
||||
caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
|
||||
caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
|
||||
ca_uint32_t cid, const int reportedStatus, const char *pformat, ... )
|
||||
{
|
||||
unsigned stringSize;
|
||||
char msgBuf[1024]; /* allocate plenty of space for the message string */
|
||||
if ( pformat ) {
|
||||
va_list args;
|
||||
va_start ( args, pformat );
|
||||
int status = vsprintf ( msgBuf, pformat, args );
|
||||
if ( status < 0 ) {
|
||||
errPrintf (S_cas_internal, __FILE__, __LINE__,
|
||||
"bad sendErr(%s)", pformat);
|
||||
stringSize = 0u;
|
||||
}
|
||||
else {
|
||||
stringSize = 1u + (unsigned) status;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned stringSize;
|
||||
char msgBuf[1024]; /* allocate plenty of space for the message string */
|
||||
if ( pformat ) {
|
||||
va_list args;
|
||||
va_start ( args, pformat );
|
||||
int status = vsprintf ( msgBuf, pformat, args );
|
||||
if ( status < 0 ) {
|
||||
errPrintf (S_cas_internal, __FILE__, __LINE__,
|
||||
"bad sendErr(%s)", pformat);
|
||||
stringSize = 0u;
|
||||
}
|
||||
else {
|
||||
stringSize = 1u + (unsigned) status;
|
||||
}
|
||||
va_end ( args );
|
||||
}
|
||||
else {
|
||||
stringSize = 0u;
|
||||
}
|
||||
|
||||
unsigned hdrSize = sizeof ( caHdr );
|
||||
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
|
||||
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
|
||||
CA_V49( this->minor_version_number ) ) {
|
||||
hdrSize += 2 * sizeof ( ca_uint32_t );
|
||||
}
|
||||
|
||||
caHdr * pReqOut;
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
caStatus status = this->out.copyInHeader ( CA_PROTO_ERROR,
|
||||
caStatus status = this->out.copyInHeader ( CA_PROTO_ERROR,
|
||||
hdrSize + stringSize, 0, 0, cid, reportedStatus,
|
||||
reinterpret_cast <void **> ( & pReqOut ) );
|
||||
if ( ! status ) {
|
||||
@@ -900,7 +897,7 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
|
||||
* copy back the request protocol
|
||||
* (in network byte order)
|
||||
*/
|
||||
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
|
||||
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
|
||||
CA_V49( this->minor_version_number ) ) {
|
||||
ca_uint32_t *pLW = ( ca_uint32_t * ) ( pReqOut + 1 );
|
||||
pReqOut->m_cmmd = htons ( curp->m_cmmd );
|
||||
@@ -945,7 +942,7 @@ caStatus casDGClient::echoAction ()
|
||||
void * pPayloadOut;
|
||||
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
caStatus status = this->out.copyInHeader ( mp->m_cmmd, mp->m_postsize,
|
||||
caStatus status = this->out.copyInHeader ( mp->m_cmmd, mp->m_postsize,
|
||||
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available,
|
||||
& pPayloadOut );
|
||||
if ( ! status ) {
|
||||
|
||||
@@ -388,14 +388,12 @@ caStatus casStrmClient::echoAction ( epicsGuard < casClientMutex > & )
|
||||
//
|
||||
// casStrmClient::verifyRequest()
|
||||
//
|
||||
caStatus casStrmClient::verifyRequest ( casChannelI * & pChan )
|
||||
caStatus casStrmClient::verifyRequest (casChannelI * & pChan , bool allowdyn)
|
||||
{
|
||||
const caHdrLargeArray * mp = this->ctx.getMsg();
|
||||
|
||||
//
|
||||
// channel exists for this resource id ?
|
||||
//
|
||||
chronIntId tmpId ( mp->m_cid );
|
||||
chronIntId tmpId ( ctx.msg.m_cid );
|
||||
pChan = this->chanTable.lookup ( tmpId );
|
||||
if ( ! pChan ) {
|
||||
return ECA_BADCHID;
|
||||
@@ -404,14 +402,15 @@ caStatus casStrmClient::verifyRequest ( casChannelI * & pChan )
|
||||
//
|
||||
// data type out of range ?
|
||||
//
|
||||
if ( mp->m_dataType > ((unsigned)LAST_BUFFER_TYPE) ) {
|
||||
if ( ctx.msg.m_dataType > ((unsigned)LAST_BUFFER_TYPE) ) {
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
|
||||
//
|
||||
// element count out of range ?
|
||||
//
|
||||
if ( mp->m_count > pChan->getPVI().nativeCount() || mp->m_count == 0u ) {
|
||||
if ( ctx.msg.m_count > pChan->getMaxElem() ||
|
||||
( !allowdyn && ctx.msg.m_count == 0u ) ) {
|
||||
return ECA_BADCOUNT;
|
||||
}
|
||||
|
||||
@@ -444,7 +443,7 @@ caStatus casStrmClient::readAction ( epicsGuard < casClientMutex > & guard )
|
||||
casChannelI * pChan;
|
||||
|
||||
{
|
||||
caStatus status = this->verifyRequest ( pChan );
|
||||
caStatus status = this->verifyRequest ( pChan, CA_V413 ( this->minor_version_number ) );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
if ( pChan ) {
|
||||
return this->sendErr ( guard, mp, pChan->getCID(),
|
||||
@@ -531,11 +530,15 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
|
||||
pChan->getCID(), status, ECA_GETFAIL );
|
||||
}
|
||||
|
||||
ca_uint32_t count = (msg.m_count == 0) ?
|
||||
(ca_uint32_t)desc.getDataSizeElements() :
|
||||
msg.m_count;
|
||||
|
||||
void * pPayload;
|
||||
{
|
||||
unsigned payloadSize = dbr_size_n ( msg.m_dataType, msg.m_count );
|
||||
unsigned payloadSize = dbr_size_n ( msg.m_dataType, count );
|
||||
caStatus localStatus = this->out.copyInHeader ( msg.m_cmmd, payloadSize,
|
||||
msg.m_dataType, msg.m_count, pChan->getCID (),
|
||||
msg.m_dataType, count, pChan->getCID (),
|
||||
msg.m_available, & pPayload );
|
||||
if ( localStatus ) {
|
||||
if ( localStatus==S_cas_hugeRequest ) {
|
||||
@@ -551,21 +554,21 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
|
||||
// (places the data in network format)
|
||||
//
|
||||
int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr(
|
||||
pPayload, msg.m_count, desc, pChan->enumStringTable() );
|
||||
pPayload, count, desc, pChan->enumStringTable() );
|
||||
if ( mapDBRStatus < 0 ) {
|
||||
desc.dump ();
|
||||
errPrintf ( S_cas_badBounds, __FILE__, __LINE__, "- get with PV=%s type=%u count=%u",
|
||||
pChan->getPVI().getName(), msg.m_dataType, msg.m_count );
|
||||
pChan->getPVI().getName(), msg.m_dataType, count );
|
||||
return this->sendErrWithEpicsStatus (
|
||||
guard, & msg, pChan->getCID(), S_cas_badBounds, ECA_GETFAIL );
|
||||
}
|
||||
int cacStatus = caNetConvert (
|
||||
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
|
||||
msg.m_dataType, pPayload, pPayload, true, count );
|
||||
if ( cacStatus != ECA_NORMAL ) {
|
||||
return this->sendErrWithEpicsStatus (
|
||||
guard, & msg, pChan->getCID(), S_cas_internal, cacStatus );
|
||||
}
|
||||
if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
|
||||
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
|
||||
unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
|
||||
this->out.commitMsg ( reducedPayloadSize );
|
||||
}
|
||||
@@ -585,7 +588,7 @@ caStatus casStrmClient::readNotifyAction ( epicsGuard < casClientMutex > & guard
|
||||
casChannelI * pChan;
|
||||
|
||||
{
|
||||
caStatus status = this->verifyRequest ( pChan );
|
||||
caStatus status = this->verifyRequest ( pChan, CA_V413 ( this->minor_version_number ) );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
return this->readNotifyFailureResponse ( guard, * mp, status );
|
||||
}
|
||||
@@ -656,11 +659,15 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
|
||||
return ecaStatus;
|
||||
}
|
||||
|
||||
ca_uint32_t count = (msg.m_count == 0) ?
|
||||
(ca_uint32_t)desc.getDataSizeElements() :
|
||||
msg.m_count;
|
||||
|
||||
void *pPayload;
|
||||
{
|
||||
unsigned size = dbr_size_n ( msg.m_dataType, msg.m_count );
|
||||
unsigned size = dbr_size_n ( msg.m_dataType, count );
|
||||
caStatus status = this->out.copyInHeader ( msg.m_cmmd, size,
|
||||
msg.m_dataType, msg.m_count, ECA_NORMAL,
|
||||
msg.m_dataType, count, ECA_NORMAL,
|
||||
msg.m_available, & pPayload );
|
||||
if ( status ) {
|
||||
if ( status == S_cas_hugeRequest ) {
|
||||
@@ -675,23 +682,23 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
|
||||
// convert gdd to db_access type
|
||||
//
|
||||
int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr ( pPayload,
|
||||
msg.m_count, desc, pChan->enumStringTable() );
|
||||
count, desc, pChan->enumStringTable() );
|
||||
if ( mapDBRStatus < 0 ) {
|
||||
desc.dump();
|
||||
errPrintf ( S_cas_badBounds, __FILE__, __LINE__,
|
||||
"- get notify with PV=%s type=%u count=%u",
|
||||
pChan->getPVI().getName(), msg.m_dataType, msg.m_count );
|
||||
pChan->getPVI().getName(), msg.m_dataType, count );
|
||||
return this->readNotifyFailureResponse ( guard, msg, ECA_NOCONVERT );
|
||||
}
|
||||
|
||||
int cacStatus = caNetConvert (
|
||||
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
|
||||
msg.m_dataType, pPayload, pPayload, true, count );
|
||||
if ( cacStatus != ECA_NORMAL ) {
|
||||
return this->sendErrWithEpicsStatus (
|
||||
guard, & msg, pChan->getCID(), S_cas_internal, cacStatus );
|
||||
}
|
||||
|
||||
if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
|
||||
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
|
||||
unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
|
||||
this->out.commitMsg ( reducedPayloadSize );
|
||||
}
|
||||
@@ -727,8 +734,8 @@ caStatus casStrmClient::readNotifyFailureResponse (
|
||||
// to be more efficent if it discovers that the source has less data
|
||||
// than the destination)
|
||||
//
|
||||
caStatus convertContainerMemberToAtomic ( gdd & dd,
|
||||
aitUint32 appType, aitUint32 elemCount )
|
||||
caStatus convertContainerMemberToAtomic ( gdd & dd,
|
||||
aitUint32 appType, aitUint32 requestedCount, aitUint32 nativeCount )
|
||||
{
|
||||
gdd * pVal;
|
||||
if ( dd.isContainer() ) {
|
||||
@@ -755,13 +762,13 @@ caStatus convertContainerMemberToAtomic ( gdd & dd,
|
||||
return S_cas_badType;
|
||||
}
|
||||
|
||||
if ( elemCount <= 1 ) {
|
||||
if ( nativeCount <= 1 ) {
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
// convert to atomic
|
||||
gddBounds bds;
|
||||
bds.setSize ( elemCount );
|
||||
bds.setSize ( requestedCount );
|
||||
bds.setFirst ( 0u );
|
||||
pVal->setDimension ( 1u, & bds );
|
||||
return S_cas_success;
|
||||
@@ -770,9 +777,9 @@ caStatus convertContainerMemberToAtomic ( gdd & dd,
|
||||
//
|
||||
// createDBRDD ()
|
||||
//
|
||||
static caStatus createDBRDD ( unsigned dbrType,
|
||||
unsigned elemCount, gdd * & pDD )
|
||||
{
|
||||
static caStatus createDBRDD ( unsigned dbrType,
|
||||
unsigned requestedCount, unsigned nativeCount, gdd * & pDD )
|
||||
{
|
||||
/*
|
||||
* DBR type has already been checked, but it is possible
|
||||
* that "gddDbrToAit" will not track with changes in
|
||||
@@ -799,7 +806,7 @@ static caStatus createDBRDD ( unsigned dbrType,
|
||||
|
||||
// fix the value element count
|
||||
caStatus status = convertContainerMemberToAtomic (
|
||||
*pDescRet, gddAppType_value, elemCount );
|
||||
*pDescRet, gddAppType_value, requestedCount, nativeCount );
|
||||
if ( status != S_cas_success ) {
|
||||
pDescRet->unreference ();
|
||||
return status;
|
||||
@@ -849,11 +856,27 @@ caStatus casStrmClient::monitorResponse (
|
||||
casChannelI & chan, const caHdrLargeArray & msg,
|
||||
const gdd & desc, const caStatus completionStatus )
|
||||
{
|
||||
aitUint32 elementCount = 0;
|
||||
if (desc.isContainer()) {
|
||||
aitUint32 index;
|
||||
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
|
||||
( desc.applicationType(), gddAppType_value, index );
|
||||
if ( gdds ) {
|
||||
return S_cas_badType;
|
||||
}
|
||||
elementCount = desc.getDD(index)->getDataSizeElements();
|
||||
} else {
|
||||
elementCount = desc.getDataSizeElements();
|
||||
}
|
||||
ca_uint32_t count = (msg.m_count == 0) ?
|
||||
(ca_uint32_t)elementCount :
|
||||
msg.m_count;
|
||||
|
||||
void * pPayload = 0;
|
||||
{
|
||||
ca_uint32_t size = dbr_size_n ( msg.m_dataType, msg.m_count );
|
||||
ca_uint32_t size = dbr_size_n ( msg.m_dataType, count );
|
||||
caStatus status = out.copyInHeader ( msg.m_cmmd, size,
|
||||
msg.m_dataType, msg.m_count, ECA_NORMAL,
|
||||
msg.m_dataType, count, ECA_NORMAL,
|
||||
msg.m_available, & pPayload );
|
||||
if ( status ) {
|
||||
if ( status == S_cas_hugeRequest ) {
|
||||
@@ -871,7 +894,8 @@ caStatus casStrmClient::monitorResponse (
|
||||
|
||||
gdd * pDBRDD = 0;
|
||||
if ( completionStatus == S_cas_success ) {
|
||||
caStatus status = createDBRDD ( msg.m_dataType, msg.m_count, pDBRDD );
|
||||
caStatus status = createDBRDD ( msg.m_dataType, count,
|
||||
chan.getMaxElem(), pDBRDD );
|
||||
if ( status != S_cas_success ) {
|
||||
caStatus ecaStatus;
|
||||
if ( status == S_cas_badType ) {
|
||||
@@ -892,7 +916,7 @@ caStatus casStrmClient::monitorResponse (
|
||||
pDBRDD->unreference ();
|
||||
errPrintf ( S_cas_noConvert, __FILE__, __LINE__,
|
||||
"no conversion between event app type=%d and DBR type=%d Element count=%d",
|
||||
desc.applicationType (), msg.m_dataType, msg.m_count);
|
||||
desc.applicationType (), msg.m_dataType, count);
|
||||
return monitorFailureResponse ( guard, msg, ECA_NOCONVERT );
|
||||
}
|
||||
}
|
||||
@@ -915,14 +939,14 @@ caStatus casStrmClient::monitorResponse (
|
||||
}
|
||||
|
||||
int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr (
|
||||
pPayload, msg.m_count, *pDBRDD, chan.enumStringTable() );
|
||||
pPayload, count, *pDBRDD, chan.enumStringTable() );
|
||||
if ( mapDBRStatus < 0 ) {
|
||||
pDBRDD->unreference ();
|
||||
return monitorFailureResponse ( guard, msg, ECA_NOCONVERT );
|
||||
}
|
||||
|
||||
int cacStatus = caNetConvert (
|
||||
msg.m_dataType, pPayload, pPayload, true, msg.m_count );
|
||||
msg.m_dataType, pPayload, pPayload, true, count );
|
||||
if ( cacStatus != ECA_NORMAL ) {
|
||||
pDBRDD->unreference ();
|
||||
return this->sendErrWithEpicsStatus (
|
||||
@@ -932,7 +956,7 @@ caStatus casStrmClient::monitorResponse (
|
||||
//
|
||||
// force string message size to be the true size
|
||||
//
|
||||
if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) {
|
||||
if ( msg.m_dataType == DBR_STRING && count == 1u ) {
|
||||
ca_uint32_t reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u;
|
||||
this->out.commitMsg ( reducedPayloadSize );
|
||||
}
|
||||
@@ -1842,7 +1866,7 @@ caStatus casStrmClient::privateCreateChanResponse (
|
||||
// the protocol buffer.
|
||||
//
|
||||
assert ( nativeTypeDBR <= 0xffff );
|
||||
aitIndex nativeCount = chan.getPVI().nativeCount();
|
||||
aitIndex nativeCount = chan.getMaxElem();
|
||||
assert ( nativeCount <= 0xffffffff );
|
||||
assert ( hdr.m_cid == chan.getCID() );
|
||||
status = this->out.copyInHeader ( CA_PROTO_CREATE_CHAN, 0,
|
||||
@@ -1940,7 +1964,7 @@ caStatus casStrmClient::eventAddAction (
|
||||
|
||||
casChannelI *pciu;
|
||||
{
|
||||
caStatus status = casStrmClient::verifyRequest ( pciu );
|
||||
caStatus status = casStrmClient::verifyRequest ( pciu, CA_V413 ( this->minor_version_number ) );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
if ( pciu ) {
|
||||
return this->sendErr ( guard, mp,
|
||||
@@ -2601,8 +2625,8 @@ caStatus casStrmClient::read ()
|
||||
|
||||
{
|
||||
gdd * pDD = 0;
|
||||
caStatus status = createDBRDD ( pHdr->m_dataType,
|
||||
pHdr->m_count, pDD );
|
||||
caStatus status = createDBRDD ( pHdr->m_dataType, pHdr->m_count,
|
||||
this->ctx.getChannel()->getMaxElem(), pDD );
|
||||
if ( status != S_cas_success ) {
|
||||
return status;
|
||||
}
|
||||
@@ -2749,6 +2773,7 @@ caStatus casStrmClient::sendErr ( epicsGuard <casClientMutex> &,
|
||||
else {
|
||||
stringSize = 1u + (unsigned) status;
|
||||
}
|
||||
va_end ( args );
|
||||
}
|
||||
else {
|
||||
stringSize = 0u;
|
||||
|
||||
@@ -69,7 +69,7 @@ private:
|
||||
bool responseIsPending;
|
||||
|
||||
caStatus createChannel ( const char * pName );
|
||||
caStatus verifyRequest ( casChannelI * & pChan );
|
||||
caStatus verifyRequest ( casChannelI * & pChan, bool allowdyn = false );
|
||||
typedef caStatus ( casStrmClient :: * pCASMsgHandler )
|
||||
( epicsGuard < casClientMutex > & );
|
||||
static pCASMsgHandler const msgHandlers[CA_PROTO_LAST_CMMD+1u];
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
//
|
||||
@@ -32,7 +32,7 @@ const unsigned caServerConnectPendQueueSize = 5u;
|
||||
//
|
||||
// casIntfIO::casIntfIO()
|
||||
//
|
||||
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
|
||||
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
|
||||
sock ( INVALID_SOCKET ),
|
||||
addr ( addrIn.getSockIP() )
|
||||
{
|
||||
@@ -40,80 +40,79 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
|
||||
osiSocklen_t addrSize;
|
||||
bool portChange;
|
||||
|
||||
if ( ! osiSockAttach () ) {
|
||||
throw S_cas_internal;
|
||||
}
|
||||
if ( ! osiSockAttach () ) {
|
||||
throw S_cas_internal;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the server socket
|
||||
*/
|
||||
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
if (this->sock==INVALID_SOCKET) {
|
||||
/*
|
||||
* Setup the server socket
|
||||
*/
|
||||
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
if (this->sock == INVALID_SOCKET) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
printf ( "No socket error was %s\n", sockErrBuf );
|
||||
throw S_cas_noFD;
|
||||
}
|
||||
printf ( "No socket error was %s\n", sockErrBuf );
|
||||
throw S_cas_noFD;
|
||||
}
|
||||
|
||||
epicsSocketEnableAddressReuseDuringTimeWaitState ( this->sock );
|
||||
|
||||
status = bind ( this->sock,
|
||||
reinterpret_cast <sockaddr *> (&this->addr),
|
||||
sizeof(this->addr) );
|
||||
if (status<0) {
|
||||
if (SOCKERRNO == SOCK_EADDRINUSE) {
|
||||
//
|
||||
// enable assignment of a default port
|
||||
// (so the getsockname() call below will
|
||||
// work correctly)
|
||||
//
|
||||
this->addr.sin_port = ntohs (0);
|
||||
status = bind(
|
||||
status = bind ( this->sock,
|
||||
reinterpret_cast <sockaddr *> (&this->addr),
|
||||
sizeof(this->addr) );
|
||||
if (status < 0) {
|
||||
if (SOCKERRNO == SOCK_EADDRINUSE ||
|
||||
SOCKERRNO == SOCK_EACCES) {
|
||||
//
|
||||
// enable assignment of a default port
|
||||
// (so the getsockname() call below will
|
||||
// work correctly)
|
||||
//
|
||||
this->addr.sin_port = ntohs (0);
|
||||
status = bind(
|
||||
this->sock,
|
||||
reinterpret_cast <sockaddr *> (&this->addr),
|
||||
sizeof(this->addr) );
|
||||
}
|
||||
if (status<0) {
|
||||
}
|
||||
if (status < 0) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
char buf[64];
|
||||
ipAddrToA (&this->addr, buf, sizeof(buf));
|
||||
errPrintf ( S_cas_bindFail,
|
||||
__FILE__, __LINE__,
|
||||
"- bind TCP IP addr=%s failed because %s",
|
||||
buf, sockErrBuf );
|
||||
char buf[64];
|
||||
ipAddrToA (&this->addr, buf, sizeof(buf));
|
||||
errlogPrintf ( "CAS: Socket bind TCP to %s failed with %s",
|
||||
buf, sockErrBuf );
|
||||
epicsSocketDestroy (this->sock);
|
||||
throw S_cas_bindFail;
|
||||
}
|
||||
throw S_cas_bindFail;
|
||||
}
|
||||
portChange = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
portChange = false;
|
||||
}
|
||||
|
||||
addrSize = ( osiSocklen_t ) sizeof (this->addr);
|
||||
status = getsockname (
|
||||
this->sock,
|
||||
reinterpret_cast <sockaddr *> ( &this->addr ),
|
||||
addrSize = ( osiSocklen_t ) sizeof (this->addr);
|
||||
status = getsockname (
|
||||
this->sock,
|
||||
reinterpret_cast <sockaddr *> ( &this->addr ),
|
||||
&addrSize );
|
||||
if (status) {
|
||||
if (status) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf ( "CAS: getsockname() error %s\n",
|
||||
sockErrBuf );
|
||||
errlogPrintf ( "CAS: getsockname() error %s\n",
|
||||
sockErrBuf );
|
||||
epicsSocketDestroy (this->sock);
|
||||
throw S_cas_internal;
|
||||
}
|
||||
throw S_cas_internal;
|
||||
}
|
||||
|
||||
//
|
||||
// be sure of this now so that we can fetch the IP
|
||||
// address and port number later
|
||||
//
|
||||
//
|
||||
// be sure of this now so that we can fetch the IP
|
||||
// address and port number later
|
||||
//
|
||||
assert (this->addr.sin_family == AF_INET);
|
||||
|
||||
if ( portChange ) {
|
||||
errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n");
|
||||
errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n",
|
||||
errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n",
|
||||
ntohs (this->addr.sin_port) );
|
||||
errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n");
|
||||
errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" );
|
||||
@@ -121,12 +120,12 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
|
||||
}
|
||||
|
||||
status = listen(this->sock, caServerConnectPendQueueSize);
|
||||
if(status < 0) {
|
||||
if (status < 0) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf );
|
||||
errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf );
|
||||
epicsSocketDestroy (this->sock);
|
||||
throw S_cas_internal;
|
||||
throw S_cas_internal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,17 +134,17 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
|
||||
//
|
||||
casIntfIO::~casIntfIO()
|
||||
{
|
||||
if (this->sock != INVALID_SOCKET) {
|
||||
epicsSocketDestroy (this->sock);
|
||||
}
|
||||
if (this->sock != INVALID_SOCKET) {
|
||||
epicsSocketDestroy (this->sock);
|
||||
}
|
||||
|
||||
osiSockRelease ();
|
||||
osiSockRelease ();
|
||||
}
|
||||
|
||||
//
|
||||
// newStreamIO::newStreamClient()
|
||||
//
|
||||
casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
|
||||
casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
|
||||
clientBufMemoryManager & bufMgr ) const
|
||||
{
|
||||
static bool oneMsgFlag = false;
|
||||
@@ -175,14 +174,14 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
|
||||
args.sock = newSock;
|
||||
casStreamOS * pOS = new casStreamOS ( cas, bufMgr, args );
|
||||
if ( ! pOS ) {
|
||||
errMessage ( S_cas_noMemory,
|
||||
errMessage ( S_cas_noMemory,
|
||||
"unable to create data structures for a new client" );
|
||||
epicsSocketDestroy ( newSock );
|
||||
}
|
||||
else {
|
||||
if ( cas.getDebugLevel() > 0u ) {
|
||||
char pName[64u];
|
||||
|
||||
|
||||
pOS->hostName ( pName, sizeof ( pName ) );
|
||||
errlogPrintf ( "CAS: allocated client object for \"%s\"\n", pName );
|
||||
}
|
||||
@@ -197,7 +196,7 @@ void casIntfIO::setNonBlocking()
|
||||
{
|
||||
int status;
|
||||
osiSockIoctl_t yes = true;
|
||||
|
||||
|
||||
status = socket_ioctl(this->sock, FIONBIO, &yes);
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
|
||||
Reference in New Issue
Block a user