This is Unofficial EPICS BASE Doxygen Site
caserverio.c File Reference
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include "dbDefs.h"
#include "epicsSignal.h"
#include "epicsTime.h"
#include "errlog.h"
#include "osiSock.h"
#include "caerr.h"
#include "net_convert.h"
#include "server.h"
+ Include dependency graph for caserverio.c:

Go to the source code of this file.

Macros

#define epicsExportSharedSymbols
 

Functions

void cas_send_bs_msg (struct client *pclient, int lock_needed)
 
void cas_send_dg_msg (struct client *pclient)
 
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 **ppPayload)
 
void cas_set_header_cid (struct client *pClient, ca_uint32_t cid)
 
void cas_set_header_count (struct client *pClient, ca_uint32_t count)
 
void cas_commit_msg (struct client *pClient, ca_uint32_t size)
 
ca_uint16_t rsrvGetUInt16 (struct message_buffer *recv)
 
ca_uint32_t rsrvGetUInt32 (struct message_buffer *recv)
 

Macro Definition Documentation

#define epicsExportSharedSymbols

Definition at line 33 of file caserverio.c.

Function Documentation

void cas_commit_msg ( struct client pClient,
ca_uint32_t  size 
)

Definition at line 351 of file caserverio.c.

352 {
353  caHdr * pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk];
354  size = CA_MESSAGE_ALIGN ( size );
355  if ( pMsg->m_postsize == htons ( 0xffff ) ) {
356  ca_uint32_t * pLW = ( ca_uint32_t * ) ( pMsg + 1 );
357  assert ( size <= ntohl ( *pLW ) );
358  pLW[0] = htonl ( size );
359  size += sizeof ( caHdr ) + 2 * sizeof ( *pLW );
360  }
361  else {
362  assert ( size <= ntohs ( pMsg->m_postsize ) );
363  pMsg->m_postsize = htons ( (ca_uint16_t) size );
364  size += sizeof ( caHdr );
365  }
366  pClient->send.stk += size;
367 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
unsigned int ca_uint32_t
Definition: caProto.h:76
unsigned short ca_uint16_t
Definition: caProto.h:75
unsigned stk
Definition: server.h:67
#define CA_MESSAGE_ALIGN(A)
Definition: caProto.h:154
struct message_buffer send
Definition: server.h:79
char * buf
Definition: server.h:65
ca_uint16_t m_postsize
Definition: caProto.h:162
struct ca_hdr caHdr
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 **  ppPayload 
)

Definition at line 251 of file caserverio.c.

255 {
256  unsigned msgSize;
257  ca_uint32_t alignedPayloadSize;
258  caHdr *pMsg;
259 
260  if ( payloadSize > UINT_MAX - sizeof ( caHdr ) - 8u ) {
261  return ECA_TOLARGE;
262  }
263 
264  alignedPayloadSize = CA_MESSAGE_ALIGN ( payloadSize );
265 
266  msgSize = alignedPayloadSize + sizeof ( caHdr );
267  if ( alignedPayloadSize >= 0xffff || nElem >= 0xffff ) {
268  if ( ! CA_V49 ( pclient->minor_version_number ) ) {
269  return ECA_16KARRAYCLIENT;
270  }
271  msgSize += 2 * sizeof ( ca_uint32_t );
272  }
273 
274  if ( msgSize > pclient->send.maxstk ) {
275  casExpandSendBuffer ( pclient, msgSize );
276  if ( msgSize > pclient->send.maxstk ) {
277  return ECA_TOLARGE;
278  }
279  }
280 
281  if ( pclient->send.stk > pclient->send.maxstk - msgSize ) {
282  if ( pclient->disconnect ) {
283  pclient->send.stk = 0;
284  }
285  else{
286  if ( pclient->proto == IPPROTO_TCP) {
287  cas_send_bs_msg ( pclient, FALSE );
288  }
289  else if ( pclient->proto == IPPROTO_UDP ) {
290  cas_send_dg_msg ( pclient );
291  }
292  else {
293  return ECA_INTERNAL;
294  }
295  }
296  }
297 
298  pMsg = (caHdr *) &pclient->send.buf[pclient->send.stk];
299  pMsg->m_cmmd = htons(response);
300  pMsg->m_dataType = htons(dataType);
301  pMsg->m_cid = htonl(cid);
302  pMsg->m_available = htonl(responseSpecific);
303  if (alignedPayloadSize < 0xffff && nElem < 0xffff) {
304  pMsg->m_postsize = htons(((ca_uint16_t) alignedPayloadSize));
305  pMsg->m_count = htons(((ca_uint16_t) nElem));
306  if (ppPayload)
307  *ppPayload = (void *) (pMsg + 1);
308  }
309  else {
310  ca_uint32_t *pW32 = (ca_uint32_t *) (pMsg + 1);
311  pMsg->m_postsize = htons(0xffff);
312  pMsg->m_count = htons(0u);
313  pW32[0] = htonl(alignedPayloadSize);
314  pW32[1] = htonl(nElem);
315  if (ppPayload)
316  *ppPayload = (void *) (pW32 + 2);
317  }
318 
319  /* zero out pad bytes */
320  if ( alignedPayloadSize > payloadSize ) {
321  char *p = ( char * ) *ppPayload;
322  memset ( p + payloadSize, '\0',
323  alignedPayloadSize - payloadSize );
324  }
325 
326  return ECA_NORMAL;
327 }
#define FALSE
Definition: dbDefs.h:32
unsigned maxstk
Definition: server.h:68
#define ECA_INTERNAL
Definition: caerr.h:94
ca_uint32_t m_available
Definition: caProto.h:166
unsigned int ca_uint32_t
Definition: caProto.h:76
unsigned short ca_uint16_t
Definition: caProto.h:75
unsigned stk
Definition: server.h:67
int proto
Definition: server.h:97
#define CA_V49(MINOR)
Definition: caProto.h:40
ca_uint16_t m_cmmd
Definition: caProto.h:161
#define ECA_NORMAL
Definition: caerr.h:77
char disconnect
Definition: server.h:103
#define CA_MESSAGE_ALIGN(A)
Definition: caProto.h:154
#define ECA_TOLARGE
Definition: caerr.h:86
struct message_buffer send
Definition: server.h:79
ca_uint32_t m_cid
Definition: caProto.h:165
char * buf
Definition: server.h:65
ca_uint16_t m_postsize
Definition: caProto.h:162
void casExpandSendBuffer(struct client *pClient, ca_uint32_t size)
ca_uint16_t m_dataType
Definition: caProto.h:163
struct ca_hdr caHdr
ca_uint16_t m_count
Definition: caProto.h:164
void cas_send_dg_msg(struct client *pclient)
Definition: caserverio.c:173
unsigned minor_version_number
Definition: server.h:99
void cas_send_bs_msg(struct client *pclient, int lock_needed)
Definition: caserverio.c:44
#define ECA_16KARRAYCLIENT
Definition: caerr.h:135
void cas_send_bs_msg ( struct client pclient,
int  lock_needed 
)

Definition at line 44 of file caserverio.c.

45 {
46  int status;
47 
48  if ( lock_needed ) {
49  SEND_LOCK ( pclient );
50  }
51 
52  if ( CASDEBUG > 2 && pclient->send.stk ) {
53  errlogPrintf ( "CAS: Sending a message of %d bytes\n", pclient->send.stk );
54  }
55 
56  if ( pclient->disconnect ) {
57  if ( CASDEBUG > 2 ) {
58  errlogPrintf ( "CAS: msg Discard for sock %d addr %x\n",
59  (int)pclient->sock, (unsigned) pclient->addr.sin_addr.s_addr );
60  }
61  pclient->send.stk = 0u;
62  if(lock_needed)
63  SEND_UNLOCK(pclient);
64  return;
65  }
66 
67  while ( pclient->send.stk && ! pclient->disconnect ) {
68  status = send ( pclient->sock, pclient->send.buf, pclient->send.stk, 0 );
69  if ( status >= 0 ) {
70  unsigned transferSize = (unsigned) status;
71  if ( transferSize >= pclient->send.stk ) {
72  pclient->send.stk = 0;
74  break;
75  }
76  else {
77  unsigned bytesLeft = pclient->send.stk - transferSize;
78  memmove ( pclient->send.buf, &pclient->send.buf[transferSize],
79  bytesLeft );
80  pclient->send.stk = bytesLeft;
81  }
82  }
83  else {
84  int causeWasSocketHangup = 0;
85  int anerrno = SOCKERRNO;
86  char buf[64];
87 
88  if ( pclient->disconnect ) {
89  pclient->send.stk = 0u;
90  break;
91  }
92 
93  if ( anerrno == SOCK_EINTR ) {
94  continue;
95  }
96 
97  if ( anerrno == SOCK_ENOBUFS ) {
98  errlogPrintf (
99  "CAS: Out of network buffers, retrying send in 15 seconds\n" );
100  epicsThreadSleep ( 15.0 );
101  continue;
102  }
103 
104  ipAddrToDottedIP ( &pclient->addr, buf, sizeof(buf) );
105 
106  if (
107  anerrno == SOCK_ECONNABORTED ||
108  anerrno == SOCK_ECONNRESET ||
109  anerrno == SOCK_EPIPE ||
110  anerrno == SOCK_ETIMEDOUT ) {
111  causeWasSocketHangup = 1;
112  }
113  else {
114  char sockErrBuf[64];
116  sockErrBuf, sizeof ( sockErrBuf ) );
117  errlogPrintf ( "CAS: TCP send to %s failed: %s\n",
118  buf, sockErrBuf);
119  }
120  pclient->disconnect = TRUE;
121  pclient->send.stk = 0u;
122 
123  /*
124  * wakeup the receive thread
125  */
126  if ( ! causeWasSocketHangup ) {
129  switch ( info ) {
131  if ( pclient->sock != INVALID_SOCKET ) {
132  epicsSocketDestroy ( pclient->sock );
133  pclient->sock = INVALID_SOCKET;
134  }
135  break;
137  {
138  int status = shutdown ( pclient->sock, SHUT_RDWR );
139  if ( status ) {
140  char sockErrBuf[64];
142  sockErrBuf, sizeof ( sockErrBuf ) );
143  errlogPrintf ("CAS: Socket shutdown error: %s\n",
144  sockErrBuf );
145  }
146  }
147  break;
149  epicsSignalRaiseSigAlarm ( pclient->tid );
150  break;
151  default:
152  break;
153  };
154  break;
155  }
156  }
157  }
158 
159  if ( lock_needed ) {
160  SEND_UNLOCK(pclient);
161  }
162 
163  DLOG ( 3, ( "------------------------------\n\n" ) );
164 
165  return;
166 }
LIBCOM_API void epicsStdCall epicsSocketDestroy(SOCKET s)
Definition: osdSock.c:117
GLBLTYPE int CASDEBUG
Definition: server.h:190
#define SOCK_ECONNABORTED
Definition: osdSock.h:59
#define INVALID_SOCKET
Definition: osdSock.h:32
pvd::Status status
#define SOCK_ENOBUFS
Definition: osdSock.h:52
LIBCOM_API void epicsStdCall epicsSignalRaiseSigAlarm(struct epicsThreadOSD *)
Definition: osdSignal.cpp:19
#define SOCK_ETIMEDOUT
Definition: osdSock.h:54
enum epicsSocketSystemCallInterruptMechanismQueryInfo epicsSocketSystemCallInterruptMechanismQuery()
SOCKET sock
Definition: server.h:96
unsigned stk
Definition: server.h:67
epicsSocketSystemCallInterruptMechanismQueryInfo
Definition: osiSock.h:47
struct sockaddr_in addr
Definition: server.h:89
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
#define SOCK_ECONNRESET
Definition: osdSock.h:53
#define SEND_UNLOCK(CLIENT)
Definition: server.h:221
char disconnect
Definition: server.h:103
epicsThreadId tid
Definition: server.h:98
struct message_buffer send
Definition: server.h:79
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
char * buf
Definition: server.h:65
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
#define SOCKERRNO
Definition: osdSock.h:33
#define SOCK_EPIPE
Definition: osdSock.h:65
#define DLOG(LEVEL, ARGSINPAREN)
Definition: server.h:187
#define SOCK_EINTR
Definition: osdSock.h:64
#define TRUE
Definition: dbDefs.h:27
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
Definition: osdThread.c:790
epicsTimeStamp time_at_last_send
Definition: server.h:90
#define SHUT_RDWR
Definition: osdSock.h:48
#define SEND_LOCK(CLIENT)
Definition: server.h:220
unsigned epicsStdCall ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)
Definition: osiSock.c:144
void cas_send_dg_msg ( struct client pclient)

Definition at line 173 of file caserverio.c.

174 {
175  int status;
176  int sizeDG;
177  char * pDG;
178  caHdr * pMsg;
179 
180  if ( CASDEBUG > 2 && pclient->send.stk ) {
181  errlogPrintf ( "CAS: Sending a udp message of %d bytes\n", pclient->send.stk );
182  }
183 
184  SEND_LOCK ( pclient );
185 
186  if ( pclient->send.stk <= sizeof (caHdr) ) {
187  SEND_UNLOCK(pclient);
188  return;
189  }
190 
191  pDG = pclient->send.buf;
192  pMsg = ( caHdr * ) pDG;
193  sizeDG = pclient->send.stk;
194  assert ( ntohs ( pMsg->m_cmmd ) == CA_PROTO_VERSION );
195  if ( CA_V411 ( pclient->minor_version_number ) ) {
196  pMsg->m_cid = htonl ( pclient->seqNoOfReq );
197  pMsg->m_dataType = htons ( sequenceNoIsValid );
198  }
199  else {
200  pDG += sizeof (caHdr);
201  sizeDG -= sizeof (caHdr);
202  }
203 
204  status = sendto ( pclient->sock, pDG, sizeDG, 0,
205  (struct sockaddr *)&pclient->addr, sizeof(pclient->addr) );
206  if ( status >= 0 ) {
207  if ( status >= sizeDG ) {
209  }
210  else {
211  errlogPrintf (
212  "CAS: System failed to send entire udp frame?\n" );
213  }
214  }
215  else {
216  char sockErrBuf[64];
217  char buf[128];
219  sockErrBuf, sizeof ( sockErrBuf ) );
220  ipAddrToDottedIP ( &pclient->addr, buf, sizeof(buf) );
221  errlogPrintf( "CAS: UDP send to %s failed: %s\n",
222  buf, sockErrBuf);
223  }
224 
225  pclient->send.stk = 0u;
226 
227  /*
228  * add placeholder for the first version message should it be needed
229  */
230  rsrv_version_reply ( pclient );
231 
232  SEND_UNLOCK(pclient);
233 
234  DLOG ( 3, ( "------------------------------\n\n" ) );
235 
236  return;
237 }
GLBLTYPE int CASDEBUG
Definition: server.h:190
int rsrv_version_reply(struct client *client)
Definition: camessage.c:2141
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
pvd::Status status
#define CA_PROTO_VERSION
Definition: caProto.h:83
#define CA_V411(MINOR)
Definition: caProto.h:42
SOCKET sock
Definition: server.h:96
unsigned stk
Definition: server.h:67
struct sockaddr_in addr
Definition: server.h:89
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
ca_uint16_t m_cmmd
Definition: caProto.h:161
#define SEND_UNLOCK(CLIENT)
Definition: server.h:221
struct message_buffer send
Definition: server.h:79
ca_uint32_t m_cid
Definition: caProto.h:165
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
char * buf
Definition: server.h:65
#define sequenceNoIsValid
Definition: caProto.h:124
ca_uint16_t m_dataType
Definition: caProto.h:163
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
struct ca_hdr caHdr
#define DLOG(LEVEL, ARGSINPAREN)
Definition: server.h:187
unsigned minor_version_number
Definition: server.h:99
epicsTimeStamp time_at_last_send
Definition: server.h:90
ca_uint32_t seqNoOfReq
Definition: server.h:100
#define SEND_LOCK(CLIENT)
Definition: server.h:220
unsigned epicsStdCall ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)
Definition: osiSock.c:144
void cas_set_header_cid ( struct client pClient,
ca_uint32_t  cid 
)

Definition at line 329 of file caserverio.c.

330 {
331  caHdr *pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk];
332  pMsg->m_cid = htonl ( cid );
333 }
unsigned stk
Definition: server.h:67
struct message_buffer send
Definition: server.h:79
ca_uint32_t m_cid
Definition: caProto.h:165
char * buf
Definition: server.h:65
void cas_set_header_count ( struct client pClient,
ca_uint32_t  count 
)

Definition at line 335 of file caserverio.c.

336 {
337  caHdr *pMsg = (caHdr *) &pClient->send.buf[pClient->send.stk];
338  if (pMsg->m_postsize == htons(0xffff)) {
339  ca_uint32_t *pLW;
340 
341  assert(pMsg->m_count == 0);
342  pLW = (ca_uint32_t *) (pMsg + 1);
343  pLW[1] = htonl(count);
344  }
345  else {
346  assert(count < 65536);
347  pMsg->m_count = htons((ca_uint16_t) count);
348  }
349 }
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
unsigned int ca_uint32_t
Definition: caProto.h:76
unsigned short ca_uint16_t
Definition: caProto.h:75
unsigned stk
Definition: server.h:67
struct message_buffer send
Definition: server.h:79
char * buf
Definition: server.h:65
ca_uint16_t m_postsize
Definition: caProto.h:162
ca_uint16_t m_count
Definition: caProto.h:164
if(yy_init)
Definition: scan.c:972
ca_uint16_t rsrvGetUInt16 ( struct message_buffer recv)

Definition at line 373 of file caserverio.c.

374 {
375  ca_uint8_t *pBuf = ( ca_uint8_t * ) recv->buf;
377  /*
378  * this assumes that we have already checked to see
379  * if sufficent bytes are available
380  */
381  assert ( recv->cnt - recv->stk >= 2u );
382  result = pBuf[recv->stk++] << 8u;
383  result |= pBuf[recv->stk++] << 0u;
384  return result;
385 }
pvac::PutEvent result
Definition: clientSync.cpp:117
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
unsigned cnt
Definition: server.h:70
unsigned short ca_uint16_t
Definition: caProto.h:75
unsigned stk
Definition: server.h:67
char * buf
Definition: server.h:65
unsigned char ca_uint8_t
Definition: caProto.h:74
ca_uint32_t rsrvGetUInt32 ( struct message_buffer recv)

Definition at line 391 of file caserverio.c.

392 {
393  ca_uint8_t *pBuf = ( ca_uint8_t * ) recv->buf;
395  /*
396  * this assumes that we have already checked to see
397  * if sufficent bytes are available
398  */
399  assert ( recv->cnt - recv->stk >= 4u );
400  result = pBuf[recv->stk++] << 24u;
401  result |= pBuf[recv->stk++] << 16u;
402  result |= pBuf[recv->stk++] << 8u;
403  result |= pBuf[recv->stk++] << 0u;
404  return result;
405 }
pvac::PutEvent result
Definition: clientSync.cpp:117
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
unsigned cnt
Definition: server.h:70
unsigned int ca_uint32_t
Definition: caProto.h:76
unsigned stk
Definition: server.h:67
char * buf
Definition: server.h:65
unsigned char ca_uint8_t
Definition: caProto.h:74