39 #define epicsExportSharedSymbols 40 #include "dbChannel.h" 43 #include "db_field_log.h" 62 static void req_server (
void *pParm)
84 sockAddr.
sa.sa_family != AF_INET ||
85 addLen <
sizeof(sockAddr.
ia) ) {
88 sockErrBuf,
sizeof ( sockErrBuf ) );
90 sockErrBuf, (
int)addLen );
117 errlogPrintf (
"CAS: task creation for new client failed\n" );
128 if(bind(
sock, (
struct sockaddr *) &addr->
sa,
sizeof(*addr))<0) {
133 sockErrBuf,
sizeof ( sockErrBuf ) );
150 SOCKET* rsrv_grab_tcp(
unsigned short *port)
161 memset(&scratch, 0,
sizeof(scratch));
162 scratch.
ia.sin_family = AF_INET;
163 scratch.
ia.sin_port = htons(*port);
182 scratch.
ia.sin_addr = ifaceAddr.
ia.sin_addr;
186 cantProceed(
"rsrv ran out of sockets during initialization");
190 if(bind(tcpsock, &scratch.
sa,
sizeof(scratch))==0 && listen(tcpsock, 20)==0) {
191 if(scratch.
ia.sin_port==0) {
195 if(getsockname(tcpsock, &ifaceAddr.
sa, &alen)) {
198 sockErrBuf,
sizeof ( sockErrBuf ) );
205 scratch.
ia.sin_port = ifaceAddr.
ia.sin_port;
216 printf(
"Skipping %s which is not an interface address\n", name);
218 for(j=0; j<=
i; j++) {
236 sockErrBuf,
sizeof ( sockErrBuf ) );
248 *port = ntohs(scratch.
ia.sin_port);
261 scratch.
ia.sin_port=0;
266 cantProceed(
"Error: RSRV has empty interface list\n" 267 "The CA server can't function without binding to" 268 " at least one network interface.\n");
274 void rsrv_build_addr_lists(
void)
276 int autobeaconlist = 1;
294 cantProceed(
"socket allocation failed during address list expansion");
299 (
char *)&intTrue,
sizeof(intTrue))<0) {
302 #ifdef IP_ADD_MEMBERSHIP 305 if (setsockopt(
beaconSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
306 (
char *)&flag,
sizeof(flag))<0) {
309 sockErrBuf,
sizeof ( sockErrBuf ) );
316 #ifdef IP_MULTICAST_TTL 323 if ( setsockopt(
beaconSocket, IPPROTO_IP, IP_MULTICAST_TTL, (
char*)&ttl,
sizeof(ttl))) {
326 sockErrBuf,
sizeof ( sockErrBuf ) );
327 errlogPrintf(
"rsrv: failed to set mcast ttl %d\n", (
int)ttl);
347 int foundWildcard = 0, doautobeacon = autobeaconlist;
359 if(pNode->
addr.
ia.sin_family==AF_INET && pNode->
addr.
ia.sin_addr.s_addr==htonl(INADDR_ANY))
363 }
else if(pNode->
addr.
ia.sin_family==AF_INET && top>=224 && top<=239) {
378 memset(&match, 0,
sizeof(match));
379 match.
ia.sin_family = AF_INET;
380 match.
ia.sin_addr.s_addr = pNode->
addr.
ia.sin_addr.s_addr;
387 cantProceed(
"CAS interface address list can not contain 0.0.0.0 and other interface addresses.\n");
394 pNode->
addr.
ia.sin_family = AF_INET;
395 pNode->
addr.
ia.sin_addr.s_addr = htonl ( INADDR_ANY );
396 pNode->
addr.
ia.sin_port = 0;
411 if (autobeaconlist) {
417 memset(&match, 0,
sizeof(match));
418 match.
ia.sin_family = AF_INET;
419 match.
ia.sin_addr.s_addr = htonl(INADDR_ANY);
430 if(pNode->
addr.
ia.sin_port==0)
438 fprintf(
stderr,
"Warning: RSRV has empty beacon address list\n");
468 void rsrv_init (
void)
470 long maxBytesAsALong;
507 if ( status || maxBytesAsALong < 0 ) {
508 errlogPrintf (
"CAS: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" );
513 static const unsigned headerSize =
sizeof (
caHdr ) + 2 *
sizeof (
ca_uint32_t );
514 ca_uint32_t maxBytes = ( unsigned ) maxBytesAsALong;
515 if ( maxBytes < 0xffffffff - headerSize ) {
516 maxBytes += headerSize;
519 maxBytes = 0xffffffff;
539 cantProceed(
"RSRV failed to allocate ID lookup table\n");
541 rsrv_build_addr_lists();
575 socks = rsrv_grab_tcp(&sport);
579 errlogPrintf (
"cas warning: Configured TCP port was unavailable.\n");
580 errlogPrintf (
"cas warning: Using dynamically assigned TCP port %hu,\n",
582 errlogPrintf (
"cas warning: but now two or more servers share the same UDP port.\n");
583 errlogPrintf (
"cas warning: Depending on your IP kernel this server may not be\n" );
584 errlogPrintf (
"cas warning: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)\n" );
604 conf->
tcp = socks[
i];
622 if(tryBind(conf->
udp, &conf->
udpAddr,
"UDP unicast socket"))
625 #ifdef IP_ADD_MEMBERSHIP 636 memset(&mreq, 0,
sizeof(mreq));
637 mreq.imr_multiaddr = pNode->
addr.
ia.sin_addr;
638 mreq.imr_interface.s_addr = conf->
udpAddr.
ia.sin_addr.s_addr;
640 if (setsockopt(conf->
udp, IPPROTO_IP, IP_ADD_MEMBERSHIP,
641 (
char *) &mreq,
sizeof(mreq))!=0) {
642 struct sockaddr_in temp;
645 temp.sin_family = AF_INET;
646 temp.sin_addr = mreq.imr_multiaddr;
647 temp.sin_port = conf->
udpAddr.
ia.sin_port;
649 sockErrBuf,
sizeof ( sockErrBuf ) );
651 errlogPrintf(
"CAS: Socket mcast join %s to %s failed: %s\n",
652 ifaceName, name, sockErrBuf );
658 fprintf(
stderr,
"IPv4 Multicast name lookup not supported by this target\n");
662 #if !(defined(_WIN32) || defined(__CYGWIN__)) 669 if(conf->
udpAddr.
ia.sin_addr.s_addr!=htonl(INADDR_ANY)) {
678 fprintf(
stderr,
"Warning: Can't find broadcast address of interface %s\n" 679 " Name lookup may not work on this interface\n", ifaceName);
681 if(
ellCount(&bcastList)>1 && conf->
udpAddr.
ia.sin_addr.s_addr!=htonl(INADDR_ANY))
682 printf(
"Interface %s has more than one broadcast address?\n", ifaceName);
688 cantProceed(
"rsrv_init ran out of udp sockets for bcast");
720 #if !(defined(_WIN32) || defined(__CYGWIN__)) 765 void rsrv_pause (
void)
772 static unsigned countChanListBytes (
776 unsigned bytes_reserved = 0;
788 return bytes_reserved;
791 static void showChanList (
792 struct client * client,
unsigned level,
ELLLIST * pList )
798 dbChannelShow ( pciu->
dbch, level, 8 );
800 printf(
"%12s# on eventq=%d, access=%c%c\n",
"",
812 static void log_one_client (
struct client *client,
unsigned level)
819 if ( client->
proto == IPPROTO_UDP ) {
820 printf (
"\tLast name requested by %s:\n",
823 else if ( client->
proto == IPPROTO_TCP ) {
824 printf (
" TCP client at %s '%s':\n",
829 printf (
" Unknown client at %s '%s':\n",
835 printf (
"\tUser '%s', V%u.%u, Priority = %u, %d Channel%s\n",
840 n, n == 1 ?
"" :
"s" );
845 char *
state[] = {
"up",
"down"};
852 printf (
"\tTask Id = %p, Socket FD = %d\n",
853 (
void *) client->
tid, (
int)client->
sock);
855 "\t%.2f secs since last send, %.2f secs since last receive\n",
856 send_delay, recv_delay);
858 "\tUnprocessed request bytes = %u, Undelivered response bytes = %u\n",
862 "\tState = %s%s%s\n",
869 showChanList ( client, level - 1u, & client->
chanList );
874 unsigned bytes_reserved =
sizeof(
struct client);
876 bytes_reserved += countChanListBytes (
878 bytes_reserved += countChanListBytes (
880 printf(
"\t%d bytes allocated\n", bytes_reserved);
881 printf(
"\tSend Lock:\n\t ");
883 printf(
"\tPut Notify Lock:\n\t ");
885 printf(
"\tAddress Queue Lock:\n\t ");
887 printf(
"\tEvent Queue Lock:\n\t ");
889 printf(
"\tBlock Semaphore:\n\t ");
899 size_t bytes_reserved;
906 printf (
"Channel Access Server V%s\n",
912 printf(
"No clients connected.\n");
914 else if (level == 0) {
915 printf(
"%d client%s connected.\n",
916 n, n == 1 ?
"" :
"s" );
919 struct client *client = (
struct client *)
ellFirst ( &clientQ );
921 printf(
"%d client%s connected:\n",
922 n, n == 1 ?
"" :
"s" );
924 log_one_client(client, level - 1);
936 printf(
"CAS-TCP server on %s with\n", buf);
940 printf(
" CAS-UDP name server on %s\n", buf);
942 log_one_client(iface->
client, level - 2);
945 printf(
" CAS-UDP name server on %s\n", buf);
947 log_one_client(iface->
client, level - 2);
950 printf(
" CAS-UDP unicast name server on %s\n", buf);
952 log_one_client(iface->
client, level - 2);
954 printf(
" CAS-UDP broadcast name server on %s\n", buf);
956 log_one_client(iface->
bclient, level - 2);
970 printf(
"Monitoring %d multicast address%s:\n",
971 n, n == 1 ?
"" :
"es");
982 printf(
"Sending CAS-beacons to %d address%s:\n",
983 n, n == 1 ?
"" :
"es");
994 printf(
"Ignoring UDP messages from address%s\n",
998 struct sockaddr_in addr;
999 memset(&addr, 0,
sizeof(addr));
1000 addr.sin_family = AF_INET;
1010 bytes_reserved = 0u;
1011 bytes_reserved +=
sizeof (
struct client) *
1015 bytes_reserved +=
sizeof(
struct event_ext) *
1025 printf(
"Free-lists total %u bytes, comprising\n",
1026 (
unsigned int) bytes_reserved);
1027 printf(
" %u client(s), %u channel(s), %u monitor event(s), %u putNotify(s)\n",
1032 printf(
" %u small (%u byte) buffers, %u jumbo (%u byte) buffers\n",
1037 printf(
"Server resource id table:\n");
1053 if ( client->
tid != 0 ) {
1061 if ( client->
proto == IPPROTO_TCP ) {
1073 errlogPrintf (
"CAS: Corrupt send buffer free list type code=%u during client cleanup?\n",
1088 errlogPrintf (
"CAS: Corrupt recv buffer free list type code=%u during client cleanup?\n",
1093 else if ( client->
proto == IPPROTO_UDP ) {
1114 if ( client->
lock ) {
1133 static void destroyAllChannels (
1134 struct client * client,
ELLLIST * pList )
1166 if ( pevext->
pdbev ) {
1167 db_cancel_event (pevext->
pdbev);
1178 "Bad id=%d at close", pciu->
sid);
1182 printf (
"bad asRemoveClient() status was %x \n", status );
1183 errPrintf ( status, __FILE__, __LINE__,
"asRemoveClient" );
1186 dbChannelDelete(pciu->
dbch);
1203 status = db_add_extra_labor_event ( client->
evuser,
NULL,
NULL );
1209 db_flush_extra_labor_event ( client->
evuser );
1212 destroyAllChannels ( client, & client->
chanList );
1216 db_close_events (client->
evuser);
1228 int spaceAvailOnFreeList;
1236 spaceNeeded =
sizeof (
struct client) + MAX_TCP;
1239 epicsPrintf (
"CAS: no space in pool for a new client (below max block thresh)\n");
1246 epicsPrintf (
"CAS: no space in pool for a new client (alloc failed)\n");
1269 memset ( (
char *)&client->
addr, 0, sizeof (client->
addr) );
1272 if ( proto == IPPROTO_TCP ) {
1280 else if ( proto == IPPROTO_UDP ) {
1319 char *newbuf =
NULL;
1325 if ( size <= buf->maxstk || buf->
type ==
mbtUDP )
return;
1333 size = ((size-1)|0xfff)+1;
1336 newbuf = realloc (buf->
buf, size);
1340 newbuf = malloc (size);
1358 memcpy ( newbuf, buf->
buf, buf->
stk );
1364 used = buf->
cnt - buf->
stk;
1367 memmove ( newbuf, &buf->
buf[buf->
stk], used );
1384 buf->
type = newtype;
1391 casExpandBuffer (&pClient->
send, size, 1);
1396 casExpandBuffer (&pClient->
recv, size, 0);
1407 unsigned priorityOfEvents;
1415 client->
addr = peerAddr->
ia;
1435 status = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY,
1436 (
char *) &intTrue,
sizeof (intTrue) );
1438 errlogPrintf (
"CAS: TCP_NODELAY option set failed\n" );
1447 status = setsockopt ( sock, SOL_SOCKET, SO_KEEPALIVE,
1448 (
char *) &intTrue,
sizeof (intTrue) );
1450 errlogPrintf (
"CAS: SO_KEEPALIVE option set failed\n" );
1467 status = setsockopt ( sock, SOL_SOCKET, SO_SNDBUF, (
char *) &
i,
sizeof (
i) );
1474 status = setsockopt ( sock, SOL_SOCKET, SO_RCVBUF, (
char *) &
i,
sizeof (
i) );
1482 client->
evuser = (
struct event_user *) db_init_events ();
1483 if ( ! client->
evuser ) {
1484 errlogPrintf (
"CAS: unable to init the event facility\n");
1490 if (status != DB_EVENT_OK) {
1491 errlogPrintf(
"CAS: unable to setup the event facility\n");
1505 status = db_start_events ( client->
evuser,
"CAS-event",
1507 if ( status != DB_EVENT_OK ) {
1508 errlogPrintf (
"CAS: unable to start the event facility\n" );
1531 int circuitCount =
ellCount ( &clientQ );
1532 if ( circuitCount < 0 ) {
1536 *pCircuitCount = (unsigned) circuitCount;
1544 static dbServer rsrv_server = {
1557 dbRegisterServer(&rsrv_server);
LIBCOM_API void epicsStdCall osiSockDiscoverBroadcastAddresses(ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
LIBCA_API void epicsStdCall removeDuplicateAddresses(struct ELLLIST *pDestList, ELLLIST *pSrcList, int silent)
LIBCOM_API void epicsStdCall epicsSocketDestroy(SOCKET s)
LIBCOM_API void *epicsStdCall freeListCalloc(void *pvt)
void casAttachThreadToClient(struct client *pClient)
epicsThreadId epicsStdCall epicsThreadMustCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
#define SOCK_EADDRNOTAVAIL
void taskwdInsert(epicsThreadId tid, TASKWDFUNC callback, void *usr)
void rsrvFreePutNotify(client *pClient, struct rsrv_put_notify *pNotify)
struct message_buffer recv
int rsrv_version_reply(struct client *client)
#define assert(exp)
Declare that a condition should be true.
LIBCOM_API int asCheckClientIP
#define ellCount(PLIST)
Report the number of nodes in a list.
LIBCOM_API void epicsStdCall epicsSignalInstallSigPipeIgnore(void)
void destroy_tcp_client(struct client *client)
#define CA_MAJOR_PROTOCOL_REVISION
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
Destroy an epicsMutex semaphore.
GLBLTYPE unsigned int threadPrios[5]
#define asCheckGet(asClientPvt)
LIBCOM_API const char *epicsStdCall envGetConfigParamPtr(const ENV_PARAM *pParam)
Get a configuration parameter's value or default string.
int rsrvCheckPut(const struct channel_in_use *pciu)
GLBLTYPE SOCKET beaconSocket
struct rsrv_put_notify * pPutNotify
LIBCA_API int epicsStdCall addAddrToChannelAccessAddressList(struct ELLLIST *pList, const ENV_PARAM *pEnv, unsigned short port, int ignoreNonDefaultPort)
GLBLTYPE ELLLIST casMCastAddrList
LIBCOM_API int epicsStdCall bucketShow(BUCKET *pb)
Display information about a hash table.
void rsrv_online_notify_task(void *pParm)
void cast_server(void *pParm)
void casExpandRecvBuffer(struct client *pClient, ca_uint32_t size)
epicsThreadPrivateId rsrvCurrentClient
GLBLTYPE void * rsrvSmallBufFreeListTCP
GLBLTYPE epicsMutexId clientQlock
ELLNODE * ellGet(ELLLIST *pList)
Deletes and returns the first node from a list.
LIBCOM_API const ENV_PARAM EPICS_CA_MAX_ARRAY_BYTES
#define CA_UKN_MINOR_VERSION
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
void epicsStdCall epicsSocketEnableAddressUseForDatagramFanout(SOCKET s)
Functions to check the state of the system memory pool.
LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int nmalloc)
LIBCOM_API int epicsStdCall osiSufficentSpaceInPool(size_t contiguousBlockSize)
Checks if a memory block of a specific size can be safely allocated.
#define ELLLIST_INIT
Value of an empty list.
void casr(unsigned level)
void initializePutNotifyFreeList(void)
int osiSockOptMcastLoop_t
LIBCOM_API epicsEventId epicsEventMustCreate(epicsEventInitialState initialState)
Create an epicsEvent for use from C code.
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
#define CA_VERSION_STRING(MINOR_REVISION)
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass size)
LIBCOM_API void epicsEventMustWait(epicsEventId id)
Wait for an event (see epicsEventWait()).
epicsThreadId epicsStdCall epicsThreadCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
#define CA_MINOR_PROTOCOL_REVISION
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
void destroy_client(struct client *client)
GLBLTYPE ELLLIST casIntfAddrList
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
GLBLTYPE ELLLIST beaconAddrList
LIBCOM_API SOCKET epicsStdCall epicsSocketCreate(int domain, int type, int protocol)
LIBCOM_API const ENV_PARAM EPICS_CAS_SERVER_PORT
#define ellNext(PNODE)
Find the next node in list.
#define ellFree(PLIST)
Free up the list.
LIBCOM_API const ENV_PARAM EPICS_CA_SERVER_PORT
LIBCOM_API const ENV_PARAM EPICS_CAS_INTF_ADDR_LIST
GLBLTYPE void * rsrvClientFreeList
LIBCOM_API void epicsStdCall epicsThreadSuspendSelf(void)
epicsMutexId chanListLock
void errPrintf(long status, const char *pFileName, int lineno, const char *pformat,...)
#define epicsEventSignal(ID)
A synonym for epicsEventTrigger().
LIBCOM_API long epicsStdCall envGetBoolConfigParam(const ENV_PARAM *pParam, int *pBool)
Get value of a boolean configuration parameter.
LIBCOM_API const ENV_PARAM EPICS_CAS_AUTO_BEACON_ADDR_LIST
struct message_buffer send
epicsTimeStamp time_at_last_recv
APIs for the epicsMutex mutual exclusion semaphore.
LIBCOM_API const ENV_PARAM EPICS_CA_REPEATER_PORT
unsigned recvBytesToDrain
LIBCOM_API void epicsStdCall epicsSocketEnableAddressReuseDuringTimeWaitState(SOCKET s)
LIBCOM_API void epicsStdCall freeListFree(void *pvt, void *pmem)
LIBCOM_API void epicsStdCall epicsThreadPrivateSet(epicsThreadPrivateId, void *)
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
LIBCOM_API int epicsStdCall epicsSocketAccept(int sock, struct sockaddr *pAddr, osiSocklen_t *addrlen)
GLBLTYPE void * rsrvLargeBufFreeListTCP
#define CA_PROTO_PRIORITY_MIN
LIBCOM_API size_t epicsStdCall freeListItemsAvail(void *pvt)
LIBCOM_API unsigned short epicsStdCall envGetInetPortConfigParam(const ENV_PARAM *pEnv, unsigned short defaultPort)
Get value of a port number configuration parameter.
void rsrv_register_server(void)
LIBCOM_API int epicsStdCall bucketRemoveItemUnsignedId(BUCKET *prb, const unsigned *pId)
Remove an item identified by a string from the table.
LIBCOM_API long epicsStdCall asRemoveClient(ASCLIENTPVT *asClientPvt)
LIBCOM_API void epicsEventDestroy(epicsEventId id)
Destroy an epicsEvent and any resources it holds.
void casExpandSendBuffer(struct client *pClient, ca_uint32_t size)
GLBLTYPE BUCKET * pCaBucket
LIBCOM_API void * callocMustSucceed(size_t count, size_t size, const char *msg)
A calloc() that never returns NULL.
LIBCOM_API void epicsStdCall epicsSignalInstallSigAlarmIgnore(void)
LIBCOM_API const ENV_PARAM EPICS_CAS_IGNORE_ADDR_LIST
int errlogPrintf(const char *pFormat,...)
struct client * create_client(SOCKET sock, int proto)
LIBCOM_API const ENV_PARAM EPICS_CAS_BEACON_ADDR_LIST
GLBLTYPE enum ctl castcp_ctl
GLBLTYPE epicsEventId casudp_startStopEvent
APIs for the epicsEvent binary semaphore.
GLBLTYPE void * rsrvChanFreeList
GLBLTYPE unsigned short ca_beacon_port
GLBLTYPE unsigned rsrvSizeofLargeBufTCP
GLBLTYPE void * rsrvEventFreeList
LIBCOM_API epicsThreadBooleanStatus epicsStdCall epicsThreadHighestPriorityLevelBelow(unsigned int priority, unsigned *pPriorityJustBelow)
#define epicsThreadPriorityCAServerLow
void casStatsFetch(unsigned *pChanCount, unsigned *pCircuitCount)
GLBLTYPE epicsEventId castcp_startStopEvent
void camsgtask(void *pParm)
struct ELLNODE * next
Pointer to next node in list.
ELLLIST chanPendingUpdateARList
LIBCOM_API void * mallocMustSucceed(size_t size, const char *msg)
A malloc() that never returns NULL.
void taskwdRemove(epicsThreadId tid)
GLBLTYPE epicsUInt32 * casIgnoreAddrs
EPICS time stamp, for use from C code.
GLBLTYPE enum ctl beacon_ctl
LIBCOM_API long epicsStdCall envGetLongConfigParam(const ENV_PARAM *pParam, long *pLong)
Get value of a long configuration parameter.
#define ellInit(PLIST)
Initialize a list type.
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
LIBCOM_API BUCKET *epicsStdCall bucketCreate(unsigned nHashTableEntries)
Creates a new hash table.
GLBLTYPE unsigned short ca_server_port
#define epicsMutexCreate()
Create an epicsMutex semaphore for use from C code.
LIBCOM_API void cantProceed(const char *msg,...)
GLBLTYPE epicsEventId beacon_startStopEvent
void epicsStdCall epicsMutexShow(epicsMutexId pmutexNode, unsigned int level)
Display information about the semaphore.
LIBCOM_API const ENV_PARAM EPICS_CA_MCAST_TTL
LIBCOM_API double epicsStdCall epicsTimeDiffInSeconds(const epicsTimeStamp *pLeft, const epicsTimeStamp *pRight)
Time difference between left and right in seconds.
void ellConcat(ELLLIST *pDstList, ELLLIST *pAddList)
Concatenates a list to the end of another list. The list to be added is left empty. Either list (or both) can be empty at the beginning of the operation.
Routines for code that can't continue or return after an error.
unsigned minor_version_number
OS-independent routines for ignoring Posix signals.
EPICS time-stamps (epicsTimeStamp), epicsTime C++ class and C functions for handling wall-clock times...
epicsMutexId putNotifyLock
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
void rsrv_extra_labor(void *pArg)
struct event_block * pdbev
LIBCOM_API epicsThreadPrivateId epicsStdCall epicsThreadPrivateCreate(void)
ELLNODE node
Pointers to the first and last nodes on list.
epicsTimeStamp time_at_last_send
#define S_bucket_success
Success, must be 0.
GLBLTYPE unsigned rsrvChannelCount
LIBCOM_API const ENV_PARAM EPICS_CA_AUTO_ARRAY_BYTES
#define ELLNODE_INIT
Value of a terminal node.
GLBLTYPE unsigned short ca_udp_port
LIBCOM_API epicsEventId epicsEventCreate(epicsEventInitialState initialState)
Create an epicsEvent for use from C code, or return NULL.
struct client * create_tcp_client(SOCKET sock, const osiSockAddr *peerAddr)
int casClientInitiatingCurrentThread(char *pBuf, size_t bufSize)
#define S_asLib_asNotActive
GLBLTYPE enum ctl casudp_ctl
unsigned rsrvSizeOfPutNotify(struct rsrv_put_notify *pNotify)
LIBCOM_API int epicsStdCall epicsSnprintf(char *str, size_t size, const char *format,...) EPICS_PRINTF_STYLE(3
GLBLTYPE void * rsrvPutNotifyFreeList
#define CAS_HASH_TABLE_SIZE
LIBCOM_API const ENV_PARAM EPICS_CAS_BEACON_PORT
unsigned epicsStdCall ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)
enum messageBufferType type
LIBCOM_API void epicsEventShow(epicsEventId id, unsigned int level)
Display information about the semaphore.
#define ellFirst(PLIST)
Find the first node in list.
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)