Files
pcas/src/rsrv/server.h
Michael Abbott e87bbef75c Update rsrv to support V4.13 protocol extension.
The rsrv server is updated in this commit to deliver variable sized
waveforms in response to a zero length request, implementing an
extension to the v4 EPICS protocol tied to minor version 13.

The core of the changes are in read_reply, rsrv/camessage.c, which first
reserves packet space for the largest possible response, but then resizes
the packet according to how much data is actually returned from the
database.
2010-08-11 16:38:49 -05:00

233 lines
7.6 KiB
C

/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* 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.
\*************************************************************************/
/*
* Author: Jeffrey O. Hill
*
*/
#ifndef INCLserverh
#define INCLserverh
#ifdef epicsExportSharedSymbols
# define rsrvRestore_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif /* ifdef epicsExportSharedSymbols */
#include "epicsThread.h"
#include "epicsMutex.h"
#include "epicsEvent.h"
#include "bucketLib.h"
#include "asLib.h"
#include "dbAddr.h"
#include "dbNotify.h"
#define CA_MINOR_PROTOCOL_REVISION 13
#include "caProto.h"
#include "ellLib.h"
#include "epicsTime.h"
#include "epicsAssert.h"
#ifdef rsrvRestore_epicsExportSharedSymbols
#define epicsExportSharedSymbols
#endif
/* a modified ca header with capacity for large arrays */
typedef struct caHdrLargeArray {
ca_uint32_t m_postsize; /* size of message extension */
ca_uint32_t m_count; /* operation data count */
ca_uint32_t m_cid; /* channel identifier */
ca_uint32_t m_available; /* protocol stub dependent */
ca_uint16_t m_dataType; /* operation data type */
ca_uint16_t m_cmmd; /* operation to be performed */
} caHdrLargeArray;
/*
* !! buf must be the first item in this structure !!
* This guarantees that buf will have 8 byte natural
* alignment
*
* The terminating unsigned pad0 field is there to force the
* length of the message_buffer to be a multiple of 8 bytes.
* This is due to the sequential placing of two message_buffer
* structures (trans, rec) within the client structure.
* Eight-byte alignment is required by the Sparc 5 and other RISC
* processors.
*/
enum messageBufferType { mbtUDP, mbtSmallTCP, mbtLargeTCP };
struct message_buffer {
char *buf;
unsigned stk;
unsigned maxstk;
unsigned cnt;
enum messageBufferType type;
};
extern epicsThreadPrivateId rsrvCurrentClient;
typedef struct client {
ELLNODE node;
struct message_buffer send;
struct message_buffer recv;
epicsMutexId lock;
epicsMutexId putNotifyLock;
epicsMutexId chanListLock;
epicsMutexId eventqLock;
ELLLIST chanList;
ELLLIST chanPendingUpdateARList;
ELLLIST putNotifyQue;
struct sockaddr_in addr;
epicsTimeStamp time_at_last_send;
epicsTimeStamp time_at_last_recv;
void *evuser;
char *pUserName;
char *pHostName;
epicsEventId blockSem; /* used whenever the client blocks */
SOCKET sock;
int proto;
epicsThreadId tid;
unsigned minor_version_number;
ca_uint32_t seqNoOfReq; /* for udp */
unsigned recvBytesToDrain;
unsigned priority;
char disconnect; /* disconnect detected */
} client;
enum rsrvChanState {
rsrvCS_invalid,
rsrvCS_pendConnectResp,
rsrvCS_inService,
rsrvCS_pendConnectRespUpdatePendAR,
rsrvCS_inServiceUpdatePendAR
};
/*
* per channel structure
* (stored in chanList or chanPendingUpdateARList off of a client block)
*/
struct channel_in_use {
ELLNODE node;
ELLLIST eventq;
struct client *client;
struct rsrv_put_notify *pPutNotify; /* potential active put notify */
const unsigned cid; /* client id */
const unsigned sid; /* server id */
epicsTimeStamp time_at_creation; /* for UDP timeout */
struct dbAddr addr;
ASCLIENTPVT asClientPVT;
enum rsrvChanState state;
};
/*
* Event block extension for channel access
* some things duplicated for speed
*/
struct event_ext {
ELLNODE node;
caHdrLargeArray msg;
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 */
};
enum ctl {ctlRun, ctlPause, ctlExit};
/* NOTE: external used so they remember the state across loads */
#ifdef GLBLSOURCE
# define GLBLTYPE
# define GLBLTYPE_INIT(A)
#else
# define GLBLTYPE extern
# define GLBLTYPE_INIT(A)
#endif
/*
* for debug-level dependent messages:
*/
#ifdef DEBUG
# define DLOG(LEVEL,ARGSINPAREN) \
if (CASDEBUG > LEVEL) errlogPrintf ARGSINPAREN
#else
# define DLOG(LEVEL,ARGSINPAREN)
#endif
GLBLTYPE int CASDEBUG;
GLBLTYPE SOCKET IOC_sock;
GLBLTYPE SOCKET IOC_cast_sock;
GLBLTYPE unsigned short ca_server_port;
GLBLTYPE ELLLIST clientQ; /* locked by clientQlock */
GLBLTYPE ELLLIST beaconAddrList;
GLBLTYPE epicsMutexId clientQlock;
GLBLTYPE struct client *prsrv_cast_client;
GLBLTYPE BUCKET *pCaBucket;
GLBLTYPE void *rsrvClientFreeList;
GLBLTYPE void *rsrvChanFreeList;
GLBLTYPE void *rsrvEventFreeList;
GLBLTYPE void *rsrvSmallBufFreeListTCP;
GLBLTYPE void *rsrvLargeBufFreeListTCP;
GLBLTYPE unsigned rsrvSizeofLargeBufTCP;
GLBLTYPE void *rsrvPutNotifyFreeList;
GLBLTYPE unsigned rsrvChannelCount;
GLBLTYPE epicsEventId casudp_startStopEvent;
GLBLTYPE epicsEventId beacon_startStopEvent;
GLBLTYPE epicsEventId castcp_startStopEvent;
GLBLTYPE volatile enum ctl casudp_ctl;
GLBLTYPE volatile enum ctl beacon_ctl;
GLBLTYPE volatile enum ctl castcp_ctl;
#define CAS_HASH_TABLE_SIZE 4096
#define SEND_LOCK(CLIENT) epicsMutexMustLock((CLIENT)->lock)
#define SEND_UNLOCK(CLIENT) epicsMutexUnlock((CLIENT)->lock)
#define LOCK_CLIENTQ epicsMutexMustLock (clientQlock);
#define UNLOCK_CLIENTQ epicsMutexUnlock (clientQlock);
void camsgtask (void *client);
void cas_send_bs_msg ( struct client *pclient, int lock_needed );
void cas_send_dg_msg ( struct client *pclient );
void rsrv_online_notify_task (void *);
void cast_server (void *);
struct client *create_client ( SOCKET sock, int proto );
void destroy_client ( struct client * );
struct client *create_tcp_client ( SOCKET sock );
void destroy_tcp_client ( struct client * );
void casAttachThreadToClient ( struct client * );
int camessage ( struct client *client );
void rsrv_extra_labor ( void * pArg );
int rsrvCheckPut ( const struct channel_in_use *pciu );
int rsrv_version_reply ( struct client *client );
void rsrvFreePutNotify ( struct client *pClient,
struct rsrv_put_notify *pNotify );
void initializePutNotifyFreeList (void);
unsigned rsrvSizeOfPutNotify ( struct rsrv_put_notify *pNotify );
/*
* inclming protocol maintetnance
*/
void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size );
/*
* outgoing protocol maintenance
*/
void casExpandSendBuffer ( struct client *pClient, ca_uint32_t size );
int cas_copy_in_header (
struct client *pClient, ca_uint16_t response, ca_uint32_t payloadSize,
ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid,
ca_uint32_t responseSpecific, void **pPayload );
void cas_set_header_cid ( struct client *pClient, ca_uint32_t );
void cas_set_header_count (struct client *pClient, ca_uint32_t count);
void cas_commit_msg ( struct client *pClient, ca_uint32_t size );
#endif /*INCLserverh*/