56 #include <sys/select.h> 59 #include "rnr/rnrconfig.h" 62 #include "rnr/netmsgs.h" 75 PRAGMA_IGNORED(sign-conversion)
85 PRAGMA_WARNING(sign-conversion)
101 if( (rc = pthread_mutex_lock(&(pClient->m_mutexTrans))) != 0 )
117 if( (rc = pthread_mutex_unlock(&(pClient->
m_mutexTrans))) != 0 )
134 return pthread_mutex_trylock(&(pClient->
m_mutexTrans)) == 0?
true:
false;
232 pInfo->
m_pBuf = uBodyLen>0? new_memdup(uBodyLen, bufRsp): NULL;
235 LOGDIAG3(
"%s: Tid=%u, MsgId=%u cached.",
272 if( (pInfo == NULL) || !pInfo->
m_bCached )
280 if( uBodyLen > sizeRsp )
283 "body_len=%zu > buf_size=%zu.", uBodyLen, sizeRsp);
293 memcpy(bufRsp, pInfo->
m_pBuf, uBodyLen);
296 LOGDIAG3(
"%s: Tid=%u, MsgId=%u loaded from cached.",
342 if( gettimeofday(pTvMark, NULL) != OK )
344 LOGSYSERROR(
"gettimeofday()");
360 struct timeval tvEnd, tvDelta;
364 if( !timerisset(pTvMark) || !timerisset(&tvEnd) )
369 tvDelta.tv_sec = tvEnd.tv_sec - pTvMark->tv_sec;
370 if( tvEnd.tv_usec < pTvMark->tv_usec )
373 tvEnd.tv_usec += 1000000;
375 tvDelta.tv_usec = tvEnd.tv_usec - pTvMark->tv_usec;
377 return (uint_t)(tvDelta.tv_sec * 1000000 + tvDelta.tv_usec);
406 return bsPackMsgHdr(pMsgHdr, buf, bufSize);
430 return bsUnpackMsgHdr(buf, bufSize, pMsgHdr);
464 struct timeval tstart;
467 struct timeval timeout;
472 LOGDIAG4CALL(_TINT(sd), _TPTR(buf), _TUINT(count), _TUINT(usec));
474 bNonBlocking = usec > 0?
true:
false;
476 while( nBytes < count )
487 timeout.tv_sec = (time_t)(usec / 1000000);
488 timeout.tv_usec = (time_t)(usec % 1000000);
490 nFd = select(sd+1, &rset, NULL, NULL, &timeout);
496 nFd = select(sd+1, &rset, NULL, NULL, NULL);
509 "select(%d,...)", sd);
517 LOGDIAG4(
"select() on read timed out.");
522 n = read(sd, buf+nBytes, count-(
size_t)nBytes);
535 "select(%d,...)", sd);
544 if( nBytes == count )
550 if( bNonBlocking && ((
size_t)nBytes < count) )
555 LOGDIAG4(
"%s() timed out.", LOGFUNCNAME);
565 LOGDIAG4(
"%s(): %d bytes read.", LOGFUNCNAME, nBytes);
601 struct timeval tstart;
604 struct timeval timeout;
609 LOGDIAG4CALL(_TINT(sd), _TPTR(buf), _TUINT(count), _TUINT(usec));
611 bNonBlocking = usec > 0?
true:
false;
613 while( nBytes < count )
624 timeout.tv_sec = (time_t)(usec / 1000000);
625 timeout.tv_usec = (time_t)(usec % 1000000);
627 nFd = select(sd+1, NULL, &wset, NULL, &timeout);
633 nFd = select(sd+1, NULL, &wset, NULL, NULL);
646 "select(%d,...)", sd);
654 LOGDIAG4(
"select() on write timed out.");
659 n = write(sd, buf+nBytes, count-(
size_t)nBytes);
672 "select(%d,...)", sd);
681 if( nBytes == count )
687 if( bNonBlocking && ((
size_t)nBytes < count) )
692 LOGDIAG4(
"%s() timed out.", LOGFUNCNAME);
702 LOGDIAG4(
"%s(): %d bytes written.", LOGFUNCNAME, nBytes);
720 sd = SocketAttrGetSd(pClient->
m_pSocket);
724 block =
sizeof(buf) >= count? count:
sizeof(buf);
748 for(nTries=0; nTries<nMaxTries; ++nTries)
751 if( (rc = bsServerReqLoopback(pClient,
"resync")) ==
BS_OK )
782 sd = SocketAttrGetSd(pClient->
m_pSocket);
800 "MsgId=%u: Failed to pack message header", uMsgId);
811 "MsgId=%u: Failed to send message", uMsgId);
813 LOGDIAG3(
"MsgId=%u: Sent %d byte request.", uMsgId, nBytes);
843 sd = SocketAttrGetSd(pClient->
m_pSocket);
854 "Failed to receive response message header, %d bytes received.", n);
861 "Received bad response message header, discarding.");
867 nBytes = BSPROXY_MSG_HDR_LEN + (int)uBodyLen;
874 "Received bad magic 0x%04x in response message header, resyncing.",
881 if( uBodyLen > bufSize )
884 "MsgId=%u: Message body_len=%zu > buf_size=%zu, discarding.",
885 uMsgId, uBodyLen, bufSize);
897 "MsgId=%u: Failed to receive response message body.", uMsgId);
900 LOGDIAG3(
"MsgId=%u: Received %d byte response.", uMsgId, nBytes);
934 if( pClient != NULL )
954 if( pClient != NULL )
972 if( pClient == NULL )
1000 if( pClient == NULL )
1023 if( pClient == NULL )
1035 else if( pClient->
m_tblVConn[index] == NULL )
1056 if( pClient == NULL )
1085 if( pClient == NULL )
1111 LOG_SET_THRESHOLD(nLevel);
1127 if( (pSocket == NULL) || !SocketStateIsOpen(pSocket) )
1129 *pConnState = noconn;
1179 static const char *sUnknown =
"unknown";
1180 const NMMsgDef_T *pMsgDef;
1187 return pMsgDef!=NULL? pMsgDef->m_sMsgName: sUnknown;
1193 else if( (pVConn =
bsGetVConn(pClient, hndVConn)) == NULL )
1197 else if( (pAppInfo = pVConn->
m_pAppInfo) == NULL )
1207 return pAppInfo->
fnGetMsgName(pClient, hndVConn, uMsgId);
1220 const char *sPreface,
1224 const char *sMsgName;
1226 fp = LOG_GET_LOGFP();
1228 if( pMsgHdr != NULL )
1234 fprintf(fp,
"%s MsgHdr = {\n", sPreface);
1235 fprintf(fp,
" Magic: 0x%04x\n", pMsgHdr->
m_hdrMagic);
1236 fprintf(fp,
" Tid: %u\n", (uint_t)(pMsgHdr->
m_hdrTid));
1237 fprintf(fp,
" VConn: %u\n", (uint_t)(pMsgHdr->
m_hdrVConn));
1238 fprintf(fp,
" MsgId: %u %s \n", pMsgHdr->
m_hdrMsgId, sMsgName);
1244 fprintf(fp,
"%s MsgHdr: (null)\n", sPreface);
1309 "MsgId=%u: Failed to send request.", uReqMsgId);
1323 "MsgId=%u: Cached response failed for request.", uReqMsgId);
1338 "MsgId=%u: Receive response failed for request.", uReqMsgId);
1364 "MsgId=%u: Failed to unpack error response message body.",
1367 n = -(int)(msgRspErr.
m_ecode);
1379 "MsgId=%u: Unexpected response message id, expected MsgId=%u.",
1423 for(i=0; i<arraysize(pClient->
m_tblVConn); ++i)
1442 if( pClient == NULL )
1447 if( SocketStateIsOpen(pClient->
m_pSocket) )
1450 "Connection still open, auto-disconnecting.");
1451 (void)bsServerDisconnect(pClient);
1526 "VConn=%d: index=%d: handle already assigned: " 1527 "Internal vconn tables corrupted.", hndVConn, i);
1531 else if( pClient->
m_tblVConn[index] == NULL )
1534 "VConn=%d: index=%d: No vConnection present: " 1535 "Internal vconn tables corrupted.", hndVConn, index);
1580 "VConn=%d: vConnection not present in table.", hndVConn);
1615 const char *sDevName,
1616 const char *sModName,
1629 "Client has the maximum=%d virtual connections.",
1644 if( index >= BSPROXY_VCONN_CLIENT_MAX )
1647 "Internal vconn tables corrupted.");
1696 if( pVConn == NULL )
1699 "index=%u: vConnection not present in table.", index);
BsVConnHnd_T m_hndVConn
virtual connection handle
const BsClientAppInfo_T * m_pAppInfo
app-specific info (optional)
int bsClientAttrGetVConnCount(BsClient_P pClient)
Get the number of active virtual connections for this client.
const char * bsClientAttrGetModName(BsClient_P pClient, BsVConnHnd_T hndVConn)
Get client virtual connection interface module name.
static uint_t timer_elapsed(struct timeval *pTvMark)
Calculate the elapsed time between the given time mark and this call.
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
#define _BS_LOG_REQ(pClient, pMsgHdr)
Log successful request recieved event.
int bsVConnNew(BsClient_T *pClient, const char *sDevName, const char *sModName, const BsClientAppInfo_T *pAppInfo, bool_t bTrace)
Reserve a new client vConnection (and proxied device) in the client's tblVConn table.
const char * m_sModName
interface module path name
#define BSCLIENT_IS_VCONN_HANDLE(hnd)
Test if the handle is in the valid client virtual connection range.
static void bsResync(BsClient_T *pClient)
Resync client with server.
const NMMsgDef_T * BsProxyLookupMsgDef(BsProxyMsgId_T eMsgId)
Look up the message definition associated with the message id.
bool_t bsClientAttrHasVConn(BsClient_P pClient, BsVConnHnd_T hndVConn)
Test if client has a virtual connection identified by the handle.
#define BSCLIENT_TRY_ECODE(pClient, ecode, efmt,...)
Check if <b><i>BotSense</i></b> return value is not an error ( < 0).
BotSense client application - bsProxy server-terminated core messages.
BsProxyMsgHdr_T * m_pMsgHdr
cached message header
static int bsClientPackMsgHdr(BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t buf[], size_t bufSize)
Pack <b><i>BotSense</i></b> client message header.
The libBotSense internal declarations.
uint_t m_uReqTimeout
client request timeout
static void bsTransForget(BsClient_T *pClient, BsTid_T uTid)
Delete any cached transaction state from the cache.
#define BS_ECODE_GEN
general, unspecified error
int bsClientTrans(BsClient_P pClient, int hndVConn, uint_t uReqMsgId, byte_t bufReq[], size_t uReqBodyLen, uint_t uRspMsgId, byte_t bufRsp[], size_t sizeRspBuf)
Execute a request - response transaction with the server.
Socket_T * m_pSocket
IP socket to server.
Client Virtual Connection Info Structure.
#define BS_ECODE_BAD_RESYNC
bad resync with server/client
#define BS_ECODE_BAD_RECV
bad receive
#define BSCLIENT_T_WRITE
5 second write timeout default
void bsClientAttrSetTimeouts(BsClient_P pClient, uint_t uReqTimeout, uint_t uRspTimeout)
Set client request (write) and response (read) timeouts.
uint_t BsTid_T
client transaction id type [0-255].
int bsVConnRemove(BsClient_T *pClient, BsVConnHnd_T hndVConn)
Remove a vConnection from the client's tblHndIndex table.
bool_t bsClientAttrGetTraceState(BsClient_P pClient, BsVConnHnd_T hndVConn)
Get client virtual connection trace state.
#define BSPROXY_VCONN_SERVER
handle for server-terminated msgs
bool_t m_bIsConnected
client is [not] connected to server
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
#define BS_ECODE_BAD_SEND
bad send
#define BSCLIENT_LOG_SYSERROR(pClient, ecode, efmt,...)
Log System Error.
#define BSPROXY_TID_MASK
transaction id mask
Cashed Transaction Information Structure.
pthread_mutex_t m_mutexTrans
client transaction mutex
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
The Client Structure Type.
uint_t m_uRspTimeout
client response timeout
#define BSCLIENT_T_FLUSH
5 second flush timeout default
static bool_t bsTransTryLock(BsClient_T *pClient)
Try to lock client's transaction mutual exclusion.
static void bsTransLock(BsClient_T *pClient)
Lock client's transaction mutual exclusion.
#define BS_OK
not an error, success
const char * m_sServerHostName
server host name
static BsTid_T bsNextTid(BsClient_T *pClient)
Atomically get the next available transaction id.
#define BS_ECODE_SYS
system (errno) error
#define BSCLIENT_LOG_WARN(pClient, ecode, wfmt,...)
Log Warning.
INLINE_IN_H int BsProxyUnpackRspErr(byte_t buf[], size_t uMsgLen, BsProxyRspErr_T *pStruct, bool_t bTrace)
Unpack a BsProxyRspErr ITV message in big-endian byte order from the input buffer.
static int bsClientUnpackMsgHdr(BsClient_T *pClient, byte_t buf[], size_t bufSize, BsProxyMsgHdr_T *pMsgHdr)
Unpack <b><i>BotSense</i></b> client message header.
#define BSPROXY_VCONN_UNDEF
undefined virtual connection handle
void bsClientAttrGetTimeouts(BsClient_P pClient, uint_t *pReqTimeout, uint_t *pRspTimeout)
Get client request (write) and response (read) timeouts.
INLINE_IN_H BsVConn_T * bsGetVConn(BsClient_T *pClient, BsVConnHnd_T hndVConn)
void bsClientLogMsgHdr(BsClient_P pClient, const char *sPreface, BsProxyMsgHdr_T *pMsgHdr)
Log [pre/un]packed message header.
int bsVConnAdd(BsClient_T *pClient, BsVConnHnd_T hndVConn, int index)
Add a created vConnection to the client's tblHndIndex table.
#define _BS_LOG_MSGHDR(pClient, sPreface, pMsgHdr)
Log [pre/un]packed message header.
void bsClientFillMsgHdr(BsClient_P pClient, int hndVConn, uint_t uMsgId, size_t uBodyLen, BsProxyMsgHdr_T *pMsgHdr)
Fill in message header.
char m_emsg[(NMFVAL_LEN_MAX_STRING)+1]
emsg
<b><i>BotSense</i></b> client library declarations.
const char * m_sDevName
device path name
uint_t m_uTidCounter
transaction id counter
BsTransInfo_T * m_tblTransCache[BSPROXY_TID_NUMOF]
transaction cache
ushort_t m_hdrBodyLen
message body length
ushort_t m_hdrMsgId
message id (vConnection unique)
#define BS_ECODE_MSG_TOO_BIG
message too big
const char *(* fnGetMsgName)(BsClient_P pClient, BsVConnHnd_T hndVConn, uint_t uMsgId)
Get the message name callback function.
<b><i>BotSense</i></b> client library information and callbacks to application-specific data...
byte_t * m_pBuf
cached packed message body buffer
#define BSCLIENT_T_READ
10 second read timeout default
static void bsFlushInput(BsClient_T *pClient, size_t count)
Flush input of count bytes.
static int bsClientWrite(BsClient_T *pClient, int sd, byte_t buf[], size_t count, uint_t usec)
Write bytes to socket.
#define _BS_LOG_RSP(pClient, pMsgHdr)
Log successful repsonse recieved event.
bool_t m_bTraceServer
do [not] trace server-ended msgs
int bsVConnDelete(BsClient_T *pClient, int index)
Delete a vConnection (and proxied device) from the client's tblVConn table.
#define BS_ECODE_MSG_BAD_HDR
bad message header
#define BS_ECODE_NO_RSRC
no resource available
void bsVConnClearAll(BsClient_T *pClient)
Remove and delete all of a client's vConnections.
const char * bsClientAttrGetName(BsClient_P pClient)
Get client name.
#define BSPROXY_MSG_MAGIC
message magic pattern
const char * m_sClientName
client name
bool_t m_bCached
this transaction is [not] cached
#define BSPROXY_MSG_HDR_LEN
message header length (bytes)
static void bsTransUnlock(BsClient_T *pClient)
Unlock client's transaction mutual exclusion.
#define BS_ECODE_BUF_TOO_SMALL
buffer too small
ushort_t m_hdrMagic
"unique" magic pattern
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
BotSense Proxy Message Header Structure.
const char * bsClientGetMsgName(BsClient_P pClient, BsVConnHnd_T hndVConn, uint_t uMsgId)
Get the message name.
#define BSPROXY_VCONN_CLIENT_MAX
max number of virtual conn/client
void bsClientAttrSetLogging(BsClient_P pClient, int nLevel)
Set client's diagnostics logging threshold.
#define BSPROXY_MSG_BODY_MAX
maximum msg body length (sans header)
#define BS_ECODE_INTERNAL
internal error (bug)
byte_t m_hdrTid
transaction id
static void bsTransCacheRsp(BsClient_T *pClient, BsTid_T uTid, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[])
Cache a transaction response.
BsClient_T * bsClientNew(const char *sClientName)
Create a new unconnected proxied client.
const char * bsClientAttrGetDevName(BsClient_P pClient, BsVConnHnd_T hndVConn)
Get client virtual connection device name.
#define BSPROXY_MSG_MAX_LEN
total message maximum length
void bsClientDelete(BsClient_P pClient)
Delete a proxied client.
static int bsClientRead(BsClient_T *pClient, int sd, byte_t buf[], size_t count, uint_t usec)
Read bytes from socket.
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
byte_t m_tblHndIndex[BSPROXY_VCONN_MOD_NUMOF]
handle to vconn index table
int m_nVConnCount
number of active v. connections
byte_t m_hdrVConn
virtual connection handle (server unique)
static int bsClientSendReq(BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t bufReq[], size_t bufSize)
Send a request message to the server.
static void bsTransMark(BsClient_T *pClient, BsTid_T uTid)
Mark the start of a client's server transaction in the transaction cache.
void bsClientAttrGetConnState(BsClient_P pClient, BsClientConnState_T *pConnState)
Get client's connection state.
static int bsTransLoadCached(BsClient_T *pClient, BsTid_T uTid, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[], size_t sizeRsp)
Load cached response from transaction cache.
bool_t m_bTrace
do [not] trace this vconn msgs
<b><i>BotSense</i></b> package top-level, unifying header declarations.
int BsVConnHnd_T
virtual connection handle type
static int bsClientRecvRsp(BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[], size_t bufSize)
Read response message from server.