botsense  3.2.0
RoadNarrows Client-Server Proxied Services Framework
bsLibClient.c File Reference

Client base functions. More...

#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <limits.h>
#include <sys/select.h>
#include <sys/time.h>
#include "rnr/rnrconfig.h"
#include "rnr/new.h"
#include "rnr/log.h"
#include "rnr/netmsgs.h"
#include "botsense/BotSense.h"
#include "botsense/libBotSense.h"
#include "botsense/bsProxyMsgs.h"
#include "bsLibInternal.h"

Go to the source code of this file.

Functions

static void fdset_nowarn (int fd, fd_set *pset)
 FD_SET() wrapper with no annoying warnings. More...
 
static void bsTransLock (BsClient_T *pClient)
 Lock client's transaction mutual exclusion. More...
 
static void bsTransUnlock (BsClient_T *pClient)
 Unlock client's transaction mutual exclusion. More...
 
static bool_t bsTransTryLock (BsClient_T *pClient)
 Try to lock client's transaction mutual exclusion. More...
 
static void bsTransMark (BsClient_T *pClient, BsTid_T uTid)
 Mark the start of a client's server transaction in the transaction cache. More...
 
static void bsTransForget (BsClient_T *pClient, BsTid_T uTid)
 Delete any cached transaction state from the cache. More...
 
static void bsTransCacheRsp (BsClient_T *pClient, BsTid_T uTid, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[])
 Cache a transaction response. More...
 
static int bsTransLoadCached (BsClient_T *pClient, BsTid_T uTid, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[], size_t sizeRsp)
 Load cached response from transaction cache. More...
 
static BsTid_T bsNextTid (BsClient_T *pClient)
 Atomically get the next available transaction id. More...
 
static void timer_mark (struct timeval *pTvMark)
 Mark the current time. Resolution is microseconds. More...
 
static uint_t timer_elapsed (struct timeval *pTvMark)
 Calculate the elapsed time between the given time mark and this call. More...
 
static int bsClientPackMsgHdr (BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t buf[], size_t bufSize)
 Pack BotSense client message header. More...
 
static int bsClientUnpackMsgHdr (BsClient_T *pClient, byte_t buf[], size_t bufSize, BsProxyMsgHdr_T *pMsgHdr)
 Unpack BotSense client message header. More...
 
static int bsClientRead (BsClient_T *pClient, int sd, byte_t buf[], size_t count, uint_t usec)
 Read bytes from socket. More...
 
static int bsClientWrite (BsClient_T *pClient, int sd, byte_t buf[], size_t count, uint_t usec)
 Write bytes to socket. More...
 
static void bsFlushInput (BsClient_T *pClient, size_t count)
 Flush input of count bytes. More...
 
static void bsResync (BsClient_T *pClient)
 Resync client with server. More...
 
static int bsClientSendReq (BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t bufReq[], size_t bufSize)
 Send a request message to the server. More...
 
static int bsClientRecvRsp (BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[], size_t bufSize)
 Read response message from server. More...
 
const char * bsClientAttrGetName (BsClient_P pClient)
 Get client name. More...
 
void bsClientAttrGetTimeouts (BsClient_P pClient, uint_t *pReqTimeout, uint_t *pRspTimeout)
 Get client request (write) and response (read) timeouts. More...
 
void bsClientAttrSetTimeouts (BsClient_P pClient, uint_t uReqTimeout, uint_t uRspTimeout)
 Set client request (write) and response (read) timeouts. More...
 
bool_t bsClientAttrGetTraceState (BsClient_P pClient, BsVConnHnd_T hndVConn)
 Get client virtual connection trace state. More...
 
int bsClientAttrGetVConnCount (BsClient_P pClient)
 Get the number of active virtual connections for this client. More...
 
bool_t bsClientAttrHasVConn (BsClient_P pClient, BsVConnHnd_T hndVConn)
 Test if client has a virtual connection identified by the handle. More...
 
const char * bsClientAttrGetDevName (BsClient_P pClient, BsVConnHnd_T hndVConn)
 Get client virtual connection device name. More...
 
const char * bsClientAttrGetModName (BsClient_P pClient, BsVConnHnd_T hndVConn)
 Get client virtual connection interface module name. More...
 
void bsClientAttrSetLogging (BsClient_P pClient, int nLevel)
 Set client's diagnostics logging threshold. More...
 
void bsClientAttrGetConnState (BsClient_P pClient, BsClientConnState_T *pConnState)
 Get client's connection state. More...
 
void bsClientFillMsgHdr (BsClient_P pClient, int hndVConn, uint_t uMsgId, size_t uBodyLen, BsProxyMsgHdr_T *pMsgHdr)
 Fill in message header. More...
 
const char * bsClientGetMsgName (BsClient_P pClient, BsVConnHnd_T hndVConn, uint_t uMsgId)
 Get the message name. More...
 
void bsClientLogMsgHdr (BsClient_P pClient, const char *sPreface, BsProxyMsgHdr_T *pMsgHdr)
 Log [pre/un]packed message header. More...
 
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. More...
 
BsClient_TbsClientNew (const char *sClientName)
 Create a new unconnected proxied client. More...
 
void bsClientDelete (BsClient_P pClient)
 Delete a proxied client. More...
 
void bsVConnClearAll (BsClient_T *pClient)
 Remove and delete all of a client's vConnections. More...
 
int bsVConnAdd (BsClient_T *pClient, BsVConnHnd_T hndVConn, int index)
 Add a created vConnection to the client's tblHndIndex table. More...
 
int bsVConnRemove (BsClient_T *pClient, BsVConnHnd_T hndVConn)
 Remove a vConnection from the client's tblHndIndex table. More...
 
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. More...
 
int bsVConnDelete (BsClient_T *pClient, int index)
 Delete a vConnection (and proxied device) from the client's tblVConn table. More...
 

Detailed Description

Client base functions.

LastChangedDate
2012-11-25 10:42:41 -0700 (Sun, 25 Nov 2012)
Rev
2544
Author
Robin Knight (robin.nosp@m..kni.nosp@m.ght@r.nosp@m.oadn.nosp@m.arrow.nosp@m.s.co.nosp@m.m)

Definition in file bsLibClient.c.

Function Documentation

void bsClientAttrGetConnState ( BsClient_P  pClient,
BsClientConnState_T pConnState 
)

Get client's connection state.

Parameters
pClient

Definition at line 1120 of file bsLibClient.c.

References BsClientConnState_T::m_bIsConnected, _bsClientStruct::m_pSocket, and BsClientConnState_T::m_sServerHostName.

1122 {
1123  static BsClientConnState_T noconn = {false, ""};
1124 
1125  Socket_T *pSocket = pClient->m_pSocket;
1126 
1127  if( (pSocket == NULL) || !SocketStateIsOpen(pSocket) )
1128  {
1129  *pConnState = noconn;
1130  }
1131 
1132  else
1133  {
1134  pConnState->m_bIsConnected = true;
1135  pConnState->m_sServerHostName = SocketAttrGetRemoteName(pSocket);
1136  }
1137 }
Socket_T * m_pSocket
IP socket to server.
Definition: bsLibInternal.h:99
bool_t m_bIsConnected
client is [not] connected to server
Definition: libBotSense.h:115
const char * m_sServerHostName
server host name
Definition: libBotSense.h:116
const char* bsClientAttrGetDevName ( BsClient_P  pClient,
BsVConnHnd_T  hndVConn 
)

Get client virtual connection device name.

Parameters
pClient

Definition at line 1054 of file bsLibClient.c.

References bsClientAttrHasVConn(), BSPROXY_VCONN_SERVER, BsVConn_T::m_sDevName, and _bsClientStruct::m_tblVConn.

1055 {
1056  if( pClient == NULL )
1057  {
1058  return NULL;
1059  }
1060  else if( hndVConn == BSPROXY_VCONN_SERVER )
1061  {
1062  return "server";
1063  }
1064  else if( !bsClientAttrHasVConn(pClient, hndVConn) )
1065  {
1066  return NULL;
1067  }
1068  else
1069  {
1070  return pClient->m_tblVConn[hndVConn]->m_sDevName;
1071  }
1072 }
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
bool_t bsClientAttrHasVConn(BsClient_P pClient, BsVConnHnd_T hndVConn)
Test if client has a virtual connection identified by the handle.
Definition: bsLibClient.c:1019
#define BSPROXY_VCONN_SERVER
handle for server-terminated msgs
Definition: BotSense.h:140
const char * m_sDevName
device path name
Definition: bsLibInternal.h:88
const char* bsClientAttrGetModName ( BsClient_P  pClient,
BsVConnHnd_T  hndVConn 
)

Get client virtual connection interface module name.

Parameters
pClient

Definition at line 1083 of file bsLibClient.c.

References bsClientAttrHasVConn(), BSPROXY_VCONN_SERVER, BsVConn_T::m_sModName, and _bsClientStruct::m_tblVConn.

1084 {
1085  if( pClient == NULL )
1086  {
1087  return NULL;
1088  }
1089  else if( hndVConn == BSPROXY_VCONN_SERVER )
1090  {
1091  return "server";
1092  }
1093  else if( !bsClientAttrHasVConn(pClient, hndVConn) )
1094  {
1095  return NULL;
1096  }
1097  else
1098  {
1099  return pClient->m_tblVConn[hndVConn]->m_sModName;
1100  }
1101 }
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
const char * m_sModName
interface module path name
Definition: bsLibInternal.h:89
bool_t bsClientAttrHasVConn(BsClient_P pClient, BsVConnHnd_T hndVConn)
Test if client has a virtual connection identified by the handle.
Definition: bsLibClient.c:1019
#define BSPROXY_VCONN_SERVER
handle for server-terminated msgs
Definition: BotSense.h:140
const char* bsClientAttrGetName ( BsClient_P  pClient)

Get client name.

Parameters
pClient

Definition at line 918 of file bsLibClient.c.

References _bsClientStruct::m_sClientName.

Referenced by bsTransCacheRsp(), and bsTransLoadCached().

919 {
920  return pClient!=NULL? pClient->m_sClientName: NULL;
921 }
const char * m_sClientName
client name
Definition: bsLibInternal.h:98
void bsClientAttrGetTimeouts ( BsClient_P  pClient,
uint_t *  pReqTimeout,
uint_t *  pRspTimeout 
)

Get client request (write) and response (read) timeouts.

Parameters
pClient

Definition at line 930 of file bsLibClient.c.

References _bsClientStruct::m_uReqTimeout, and _bsClientStruct::m_uRspTimeout.

933 {
934  if( pClient != NULL )
935  {
936  *pReqTimeout = pClient->m_uReqTimeout / 1000000;
937  *pRspTimeout = pClient->m_uRspTimeout / 1000000;
938  }
939 }
uint_t m_uReqTimeout
client request timeout
uint_t m_uRspTimeout
client response timeout
bool_t bsClientAttrGetTraceState ( BsClient_P  pClient,
BsVConnHnd_T  hndVConn 
)

Get client virtual connection trace state.

Parameters
pClient

Definition at line 970 of file bsLibClient.c.

References bsClientAttrHasVConn(), bsGetVConn(), BSPROXY_VCONN_SERVER, BsVConn_T::m_bTrace, and _bsClientStruct::m_bTraceServer.

971 {
972  if( pClient == NULL )
973  {
974  return false;
975  }
976  else if( hndVConn == BSPROXY_VCONN_SERVER )
977  {
978  return pClient->m_bTraceServer;
979  }
980  else if( bsClientAttrHasVConn(pClient, hndVConn) )
981  {
982  return bsGetVConn(pClient, hndVConn)->m_bTrace;
983  }
984  else
985  {
986  return false;
987  }
988 }
bool_t bsClientAttrHasVConn(BsClient_P pClient, BsVConnHnd_T hndVConn)
Test if client has a virtual connection identified by the handle.
Definition: bsLibClient.c:1019
#define BSPROXY_VCONN_SERVER
handle for server-terminated msgs
Definition: BotSense.h:140
INLINE_IN_H BsVConn_T * bsGetVConn(BsClient_T *pClient, BsVConnHnd_T hndVConn)
bool_t m_bTraceServer
do [not] trace server-ended msgs
bool_t m_bTrace
do [not] trace this vconn msgs
Definition: bsLibInternal.h:87
int bsClientAttrGetVConnCount ( BsClient_P  pClient)

Get the number of active virtual connections for this client.

Parameters
pClient

Definition at line 998 of file bsLibClient.c.

References _bsClientStruct::m_nVConnCount.

Referenced by bsVConnNew().

999 {
1000  if( pClient == NULL )
1001  {
1002  return 0;
1003  }
1004  else
1005  {
1006  return pClient->m_nVConnCount;
1007  }
1008 }
int m_nVConnCount
number of active v. connections
bool_t bsClientAttrHasVConn ( BsClient_P  pClient,
BsVConnHnd_T  hndVConn 
)

Test if client has a virtual connection identified by the handle.

Parameters
pClient

Definition at line 1019 of file bsLibClient.c.

References BSCLIENT_IS_VCONN_HANDLE, BSPROXY_VCONN_UNDEF, _bsClientStruct::m_tblHndIndex, and _bsClientStruct::m_tblVConn.

Referenced by bsClientAttrGetDevName(), bsClientAttrGetModName(), bsClientAttrGetTraceState(), and bsClientGetMsgName().

1020 {
1021  int index;
1022 
1023  if( pClient == NULL )
1024  {
1025  return false;
1026  }
1027  else if( !BSCLIENT_IS_VCONN_HANDLE(hndVConn) )
1028  {
1029  return false;
1030  }
1031  else if( (index = pClient->m_tblHndIndex[hndVConn]) == BSPROXY_VCONN_UNDEF )
1032  {
1033  return false;
1034  }
1035  else if( pClient->m_tblVConn[index] == NULL )
1036  {
1037  return false;
1038  }
1039  else
1040  {
1041  return true;
1042  }
1043 }
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
#define BSCLIENT_IS_VCONN_HANDLE(hnd)
Test if the handle is in the valid client virtual connection range.
Definition: libBotSense.h:274
#define BSPROXY_VCONN_UNDEF
undefined virtual connection handle
Definition: BotSense.h:139
byte_t m_tblHndIndex[BSPROXY_VCONN_MOD_NUMOF]
handle to vconn index table
void bsClientAttrSetLogging ( BsClient_P  pClient,
int  nLevel 
)

Set client's diagnostics logging threshold.

Parameters
pClient

Definition at line 1109 of file bsLibClient.c.

1110 {
1111  LOG_SET_THRESHOLD(nLevel);
1112 }
void bsClientAttrSetTimeouts ( BsClient_P  pClient,
uint_t  uReqTimeout,
uint_t  uRspTimeout 
)

Set client request (write) and response (read) timeouts.

A timeout value of 0 means block forever until i/o operation is complete.

Parameters
pClient

Definition at line 950 of file bsLibClient.c.

References _bsClientStruct::m_uReqTimeout, and _bsClientStruct::m_uRspTimeout.

953 {
954  if( pClient != NULL )
955  {
956  pClient->m_uReqTimeout = uReqTimeout * 1000000;
957  pClient->m_uRspTimeout = uRspTimeout * 1000000;
958  }
959 }
uint_t m_uReqTimeout
client request timeout
uint_t m_uRspTimeout
client response timeout
void bsClientDelete ( BsClient_P  pClient)

Delete a proxied client.

Warning
The client should disconnect prior to deletion.
Parameters
pClient

Definition at line 1438 of file bsLibClient.c.

References BS_ECODE_GEN, BSCLIENT_LOG_WARN, bsTransForget(), bsVConnClearAll(), _bsClientStruct::m_mutexTrans, _bsClientStruct::m_pSocket, _bsClientStruct::m_sClientName, and _bsClientStruct::m_tblTransCache.

1439 {
1440  size_t i;
1441 
1442  if( pClient == NULL )
1443  {
1444  return;
1445  }
1446 
1447  if( SocketStateIsOpen(pClient->m_pSocket) )
1448  {
1450  "Connection still open, auto-disconnecting.");
1451  (void)bsServerDisconnect(pClient);
1452  }
1453 
1454  for(i=0; i<arraysize(pClient->m_tblTransCache); ++i)
1455  {
1456  bsTransForget(pClient, (BsTid_T)i);
1457  }
1458 
1459  bsVConnClearAll(pClient);
1460 
1461  pthread_mutex_destroy(&(pClient->m_mutexTrans));
1462 
1463  delete((void *)(pClient->m_sClientName));
1464 
1465  delete(pClient);
1466 }
static void bsTransForget(BsClient_T *pClient, BsTid_T uTid)
Delete any cached transaction state from the cache.
Definition: bsLibClient.c:184
#define BS_ECODE_GEN
general, unspecified error
Definition: BotSense.h:68
Socket_T * m_pSocket
IP socket to server.
Definition: bsLibInternal.h:99
uint_t BsTid_T
client transaction id type [0-255].
Definition: BotSense.h:172
pthread_mutex_t m_mutexTrans
client transaction mutex
#define BSCLIENT_LOG_WARN(pClient, ecode, wfmt,...)
Log Warning.
Definition: libBotSense.h:156
BsTransInfo_T * m_tblTransCache[BSPROXY_TID_NUMOF]
transaction cache
void bsVConnClearAll(BsClient_T *pClient)
Remove and delete all of a client&#39;s vConnections.
Definition: bsLibClient.c:1478
const char * m_sClientName
client name
Definition: bsLibInternal.h:98
void bsClientFillMsgHdr ( BsClient_P  pClient,
int  hndVConn,
uint_t  uMsgId,
size_t  uBodyLen,
BsProxyMsgHdr_T pMsgHdr 
)

Fill in message header.

Parameters
pClient

Definition at line 1148 of file bsLibClient.c.

References bsNextTid(), BSPROXY_MSG_MAGIC, BsProxyMsgHdr_T::m_hdrBodyLen, BsProxyMsgHdr_T::m_hdrMagic, BsProxyMsgHdr_T::m_hdrMsgId, BsProxyMsgHdr_T::m_hdrTid, and BsProxyMsgHdr_T::m_hdrVConn.

Referenced by bsClientTrans().

1153 {
1154  pMsgHdr->m_hdrMagic = (ushort_t)BSPROXY_MSG_MAGIC;
1155  pMsgHdr->m_hdrTid = (byte_t)bsNextTid(pClient);
1156  pMsgHdr->m_hdrVConn = (byte_t)hndVConn;
1157  pMsgHdr->m_hdrMsgId = (ushort_t)uMsgId;
1158  pMsgHdr->m_hdrBodyLen = (ushort_t)uBodyLen;
1159 }
static BsTid_T bsNextTid(BsClient_T *pClient)
Atomically get the next available transaction id.
Definition: bsLibClient.c:315
ushort_t m_hdrBodyLen
message body length
Definition: BotSense.h:284
ushort_t m_hdrMsgId
message id (vConnection unique)
Definition: BotSense.h:283
#define BSPROXY_MSG_MAGIC
message magic pattern
Definition: BotSense.h:261
ushort_t m_hdrMagic
"unique" magic pattern
Definition: BotSense.h:280
byte_t m_hdrTid
transaction id
Definition: BotSense.h:281
byte_t m_hdrVConn
virtual connection handle (server unique)
Definition: BotSense.h:282
const char* bsClientGetMsgName ( BsClient_P  pClient,
BsVConnHnd_T  hndVConn,
uint_t  uMsgId 
)

Get the message name.

For each (virtual connection, message id) 2-tuple, there can be a known name string (provided the id is valid and an application provides the information).

Parameters
pClient

Definition at line 1175 of file bsLibClient.c.

References bsClientAttrHasVConn(), bsGetVConn(), BSPROXY_VCONN_SERVER, BsProxyLookupMsgDef(), BsClientAppInfo_T::fnGetMsgName, and BsVConn_T::m_pAppInfo.

Referenced by bsClientLogMsgHdr().

1178 {
1179  static const char *sUnknown = "unknown";
1180  const NMMsgDef_T *pMsgDef;
1181  BsVConn_T *pVConn;
1182  const BsClientAppInfo_T *pAppInfo;
1183 
1184  if( hndVConn == BSPROXY_VCONN_SERVER )
1185  {
1186  pMsgDef = BsProxyLookupMsgDef((BsProxyMsgId_T)uMsgId);
1187  return pMsgDef!=NULL? pMsgDef->m_sMsgName: sUnknown;
1188  }
1189  else if( !bsClientAttrHasVConn(pClient, hndVConn) )
1190  {
1191  return sUnknown;
1192  }
1193  else if( (pVConn = bsGetVConn(pClient, hndVConn)) == NULL )
1194  {
1195  return sUnknown;
1196  }
1197  else if( (pAppInfo = pVConn->m_pAppInfo) == NULL )
1198  {
1199  return sUnknown;
1200  }
1201  else if( pAppInfo->fnGetMsgName == NULL )
1202  {
1203  return sUnknown;
1204  }
1205  else
1206  {
1207  return pAppInfo->fnGetMsgName(pClient, hndVConn, uMsgId);
1208  }
1209 }
const BsClientAppInfo_T * m_pAppInfo
app-specific info (optional)
Definition: bsLibInternal.h:90
const NMMsgDef_T * BsProxyLookupMsgDef(BsProxyMsgId_T eMsgId)
Look up the message definition associated with the message id.
Definition: bsProxyMsgs.c:874
bool_t bsClientAttrHasVConn(BsClient_P pClient, BsVConnHnd_T hndVConn)
Test if client has a virtual connection identified by the handle.
Definition: bsLibClient.c:1019
Client Virtual Connection Info Structure.
Definition: bsLibInternal.h:84
#define BSPROXY_VCONN_SERVER
handle for server-terminated msgs
Definition: BotSense.h:140
INLINE_IN_H BsVConn_T * bsGetVConn(BsClient_T *pClient, BsVConnHnd_T hndVConn)
const char *(* fnGetMsgName)(BsClient_P pClient, BsVConnHnd_T hndVConn, uint_t uMsgId)
Get the message name callback function.
Definition: libBotSense.h:105
<b><i>BotSense</i></b> client library information and callbacks to application-specific data...
Definition: libBotSense.h:86
BsProxyMsgId_T
Definition: bsProxyMsgs.h:35
void bsClientLogMsgHdr ( BsClient_P  pClient,
const char *  sPreface,
BsProxyMsgHdr_T pMsgHdr 
)

Log [pre/un]packed message header.

Parameters
pClient

Definition at line 1219 of file bsLibClient.c.

References bsClientGetMsgName(), BsProxyMsgHdr_T::m_hdrBodyLen, BsProxyMsgHdr_T::m_hdrMagic, BsProxyMsgHdr_T::m_hdrMsgId, BsProxyMsgHdr_T::m_hdrTid, and BsProxyMsgHdr_T::m_hdrVConn.

1222 {
1223  FILE *fp;
1224  const char *sMsgName;
1225 
1226  fp = LOG_GET_LOGFP();
1227 
1228  if( pMsgHdr != NULL )
1229  {
1230  sMsgName = bsClientGetMsgName(pClient,
1231  (BsVConnHnd_T)pMsgHdr->m_hdrVConn,
1232  (uint_t)pMsgHdr->m_hdrMsgId);
1233 
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);
1239  fprintf(fp, " BodyLen: %u\n", pMsgHdr->m_hdrBodyLen);
1240  fprintf(fp, "}\n");
1241  }
1242  else
1243  {
1244  fprintf(fp, "%s MsgHdr: (null)\n", sPreface);
1245  }
1246 }
ushort_t m_hdrBodyLen
message body length
Definition: BotSense.h:284
ushort_t m_hdrMsgId
message id (vConnection unique)
Definition: BotSense.h:283
ushort_t m_hdrMagic
"unique" magic pattern
Definition: BotSense.h:280
const char * bsClientGetMsgName(BsClient_P pClient, BsVConnHnd_T hndVConn, uint_t uMsgId)
Get the message name.
Definition: bsLibClient.c:1175
byte_t m_hdrTid
transaction id
Definition: BotSense.h:281
byte_t m_hdrVConn
virtual connection handle (server unique)
Definition: BotSense.h:282
int BsVConnHnd_T
virtual connection handle type
Definition: BotSense.h:151
BsClient_T* bsClientNew ( const char *  sClientName)

Create a new unconnected proxied client.

Parameters
sClientNameProxied client (robot)'s name.
Returns
Returns pointer to new client on success. Else returns NULL.

Definition at line 1396 of file bsLibClient.c.

References BSCLIENT_T_READ, BSCLIENT_T_WRITE, BSPROXY_VCONN_UNDEF, _bsClientStruct::m_bTraceServer, _bsClientStruct::m_mutexTrans, _bsClientStruct::m_nVConnCount, _bsClientStruct::m_pSocket, _bsClientStruct::m_sClientName, _bsClientStruct::m_tblHndIndex, _bsClientStruct::m_tblTransCache, _bsClientStruct::m_tblVConn, _bsClientStruct::m_uReqTimeout, _bsClientStruct::m_uRspTimeout, and _bsClientStruct::m_uTidCounter.

1397 {
1398  BsClient_T *pClient = NEW(BsClient_T);
1399  size_t i;
1400 
1401  pClient->m_sClientName = new_strdup(sClientName);
1402  pClient->m_pSocket = NULL;
1403 
1404  pthread_mutex_init(&(pClient->m_mutexTrans), NULL);
1405 
1406  pClient->m_uReqTimeout = BSCLIENT_T_WRITE;
1407  pClient->m_uRspTimeout = BSCLIENT_T_READ;
1408  pClient->m_uTidCounter = 0;
1409  pClient->m_bTraceServer = false;
1410 
1411  for(i=0; i<arraysize(pClient->m_tblTransCache); ++i)
1412  {
1413  pClient->m_tblTransCache[i] = NULL;
1414  }
1415 
1416  pClient->m_nVConnCount = 0;
1417 
1418  for(i=0; i<arraysize(pClient->m_tblHndIndex); ++i)
1419  {
1420  pClient->m_tblHndIndex[i] = BSPROXY_VCONN_UNDEF;
1421  }
1422 
1423  for(i=0; i<arraysize(pClient->m_tblVConn); ++i)
1424  {
1425  pClient->m_tblVConn[i] = NULL;
1426  }
1427 
1428  return pClient;
1429 }
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
uint_t m_uReqTimeout
client request timeout
Socket_T * m_pSocket
IP socket to server.
Definition: bsLibInternal.h:99
#define BSCLIENT_T_WRITE
5 second write timeout default
Definition: bsLibInternal.h:67
pthread_mutex_t m_mutexTrans
client transaction mutex
The Client Structure Type.
Definition: bsLibInternal.h:96
uint_t m_uRspTimeout
client response timeout
#define BSPROXY_VCONN_UNDEF
undefined virtual connection handle
Definition: BotSense.h:139
uint_t m_uTidCounter
transaction id counter
BsTransInfo_T * m_tblTransCache[BSPROXY_TID_NUMOF]
transaction cache
#define BSCLIENT_T_READ
10 second read timeout default
Definition: bsLibInternal.h:66
bool_t m_bTraceServer
do [not] trace server-ended msgs
const char * m_sClientName
client name
Definition: bsLibInternal.h:98
byte_t m_tblHndIndex[BSPROXY_VCONN_MOD_NUMOF]
handle to vconn index table
int m_nVConnCount
number of active v. connections
static int bsClientPackMsgHdr ( BsClient_T pClient,
BsProxyMsgHdr_T pMsgHdr,
byte_t  buf[],
size_t  bufSize 
)
inlinestatic

Pack BotSense client message header.

Parameters
pClient

Definition at line 397 of file bsLibClient.c.

References BS_ECODE_BUF_TOO_SMALL, BSCLIENT_TRY_EXPR, and BSPROXY_MSG_HDR_LEN.

Referenced by bsClientSendReq().

401 {
402  BSCLIENT_TRY_EXPR(pClient, (bufSize >= BSPROXY_MSG_HDR_LEN),
403  BS_ECODE_BUF_TOO_SMALL, "bufSize=%zu < %u",
404  bufSize, BSPROXY_MSG_HDR_LEN);
405 
406  return bsPackMsgHdr(pMsgHdr, buf, bufSize);
407 }
#define BSPROXY_MSG_HDR_LEN
message header length (bytes)
Definition: BotSense.h:258
#define BS_ECODE_BUF_TOO_SMALL
buffer too small
Definition: BotSense.h:75
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
static int bsClientRead ( BsClient_T pClient,
int  sd,
byte_t  buf[],
size_t  count,
uint_t  usec 
)
static

Read bytes from socket.

Read up to count bytes into buf from the socket. This call is non-blocking if the timeout value usec is greater than zero. Otherwise the read can block indefinitely.

Note that on return the bytes read can be less than count.

Parameters
pClient

Definition at line 457 of file bsLibClient.c.

References BS_ECODE_BAD_RECV, BSCLIENT_LOG_SYSERROR, fdset_nowarn(), timer_elapsed(), and timer_mark().

Referenced by bsClientRecvRsp(), and bsFlushInput().

462 {
463  bool_t bNonBlocking;
464  struct timeval tstart;
465  uint_t tdelta;
466  fd_set rset;
467  struct timeval timeout;
468  int nFd;
469  ssize_t n;
470  int nBytes = 0;
471 
472  LOGDIAG4CALL(_TINT(sd), _TPTR(buf), _TUINT(count), _TUINT(usec));
473 
474  bNonBlocking = usec > 0? true: false;
475 
476  while( nBytes < count )
477  {
478  FD_ZERO(&rset);
479  fdset_nowarn(sd, &rset);
480 
481  // wait for input with timeout
482  if( bNonBlocking )
483  {
484  timer_mark(&tstart);
485 
486  // (re)load timeout (gets munged after each select())
487  timeout.tv_sec = (time_t)(usec / 1000000);
488  timeout.tv_usec = (time_t)(usec % 1000000);
489 
490  nFd = select(sd+1, &rset, NULL, NULL, &timeout);
491  }
492 
493  // block indefinitely for input
494  else
495  {
496  nFd = select(sd+1, &rset, NULL, NULL, NULL);
497  }
498 
499  // system error occurred on select - interpret
500  if( nFd < 0 )
501  {
502  switch(errno)
503  {
504  case EAGAIN: // non-blocking timeout
505  case EINTR: // read was interrupted
506  break;
507  default:
509  "select(%d,...)", sd);
510  return -BS_ECODE_BAD_RECV;
511  }
512  }
513 
514  // select() timeout occurred
515  else if( nFd == 0 )
516  {
517  LOGDIAG4("select() on read timed out.");
518  break;
519  }
520 
521  // data available from serial device
522  n = read(sd, buf+nBytes, count-(size_t)nBytes);
523 
524  // system error occurred on read - interpret
525  if( n < 0 )
526  {
527  switch(errno)
528  {
529  case EAGAIN: // non-blocking timeout
530  case EINTR: // read was interrupted
531  n = 0;
532  break;
533  default:
535  "select(%d,...)", sd);
536  return -BS_ECODE_BAD_RECV;
537  }
538  }
539 
540  // got some data
541  nBytes += (int)n;
542 
543  // all of the requested bytes have been read
544  if( nBytes == count )
545  {
546  break;
547  }
548 
549  // determine time left for non-blocking read timeout
550  if( bNonBlocking && ((size_t)nBytes < count) )
551  {
552  tdelta = timer_elapsed(&tstart);
553  if( tdelta >= usec )
554  {
555  LOGDIAG4("%s() timed out.", LOGFUNCNAME);
556  break;
557  }
558  else
559  {
560  usec -= tdelta;
561  }
562  }
563  }
564 
565  LOGDIAG4("%s(): %d bytes read.", LOGFUNCNAME, nBytes);
566 
567  return nBytes;
568 }
static uint_t timer_elapsed(struct timeval *pTvMark)
Calculate the elapsed time between the given time mark and this call.
Definition: bsLibClient.c:358
#define BS_ECODE_BAD_RECV
bad receive
Definition: BotSense.h:69
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
Definition: bsLibClient.c:81
#define BSCLIENT_LOG_SYSERROR(pClient, ecode, efmt,...)
Log System Error.
Definition: libBotSense.h:196
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
Definition: bsLibClient.c:340
static int bsClientRecvRsp ( BsClient_T pClient,
BsProxyMsgHdr_T pMsgHdr,
byte_t  bufRsp[],
size_t  bufSize 
)
static

Read response message from server.

Parameters
pClient

Definition at line 829 of file bsLibClient.c.

References _BS_LOG_MSGHDR, BS_ECODE_BAD_RECV, BS_ECODE_MSG_BAD_HDR, BS_ECODE_MSG_TOO_BIG, BSCLIENT_LOG_ERROR, BSCLIENT_TRY_ECODE, BSCLIENT_TRY_EXPR, bsClientRead(), bsClientUnpackMsgHdr(), bsFlushInput(), BSPROXY_MSG_HDR_LEN, BSPROXY_MSG_MAGIC, bsResync(), bsTransLock(), bsTransUnlock(), BsProxyMsgHdr_T::m_hdrBodyLen, BsProxyMsgHdr_T::m_hdrMagic, BsProxyMsgHdr_T::m_hdrMsgId, _bsClientStruct::m_pSocket, and _bsClientStruct::m_uRspTimeout.

Referenced by bsClientTrans().

834 {
835  int sd;
836  size_t uBodyLen;
837  uint_t uMsgId;
838  int nBytes;
839  byte_t bufHdr[BSPROXY_MSG_HDR_LEN];
840  int n;
841 
842  // socket file descriptor
843  sd = SocketAttrGetSd(pClient->m_pSocket);
844 
845  bsTransLock(pClient);
846 
847  // read response header
848  n = bsClientRead(pClient, sd, bufHdr, BSPROXY_MSG_HDR_LEN,
849  pClient->m_uRspTimeout);
850 
851  bsTransUnlock(pClient);
852 
854  "Failed to receive response message header, %d bytes received.", n);
855 
856  // unpack message header
857  n = bsClientUnpackMsgHdr(pClient, bufHdr, (size_t)BSPROXY_MSG_HDR_LEN,
858  pMsgHdr);
859 
860  BSCLIENT_TRY_ECODE(pClient, n,
861  "Received bad response message header, discarding.");
862 
863  _BS_LOG_MSGHDR(pClient, "Rx Rsp", pMsgHdr);
864 
865  uBodyLen = (size_t)(pMsgHdr->m_hdrBodyLen);
866  uMsgId = pMsgHdr->m_hdrMsgId;
867  nBytes = BSPROXY_MSG_HDR_LEN + (int)uBodyLen;
868 
869  // validate magic
870  if( pMsgHdr->m_hdrMagic != BSPROXY_MSG_MAGIC )
871  {
873  "MsgId=%u: "
874  "Received bad magic 0x%04x in response message header, resyncing.",
875  uMsgId, pMsgHdr->m_hdrMagic);
876  bsResync(pClient);
877  return -BS_ECODE_MSG_BAD_HDR;
878  }
879 
880  // message too long
881  if( uBodyLen > bufSize )
882  {
884  "MsgId=%u: Message body_len=%zu > buf_size=%zu, discarding.",
885  uMsgId, uBodyLen, bufSize);
886  bsFlushInput(pClient, uBodyLen);
887  return -BS_ECODE_MSG_TOO_BIG;
888  }
889 
890  // read response body
891  if( uBodyLen > 0 )
892  {
893  // read response body
894  n = bsClientRead(pClient, sd, bufRsp, uBodyLen, pClient->m_uRspTimeout);
895 
896  BSCLIENT_TRY_EXPR(pClient, (n == (int)uBodyLen), BS_ECODE_BAD_RECV,
897  "MsgId=%u: Failed to receive response message body.", uMsgId);
898  }
899 
900  LOGDIAG3("MsgId=%u: Received %d byte response.", uMsgId, nBytes);
901 
902  return nBytes;
903 }
static void bsResync(BsClient_T *pClient)
Resync client with server.
Definition: bsLibClient.c:742
#define BSCLIENT_TRY_ECODE(pClient, ecode, efmt,...)
Check if <b><i>BotSense</i></b> return value is not an error ( &lt; 0).
Definition: libBotSense.h:214
Socket_T * m_pSocket
IP socket to server.
Definition: bsLibInternal.h:99
#define BS_ECODE_BAD_RECV
bad receive
Definition: BotSense.h:69
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
Definition: libBotSense.h:170
uint_t m_uRspTimeout
client response timeout
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
static int bsClientUnpackMsgHdr(BsClient_T *pClient, byte_t buf[], size_t bufSize, BsProxyMsgHdr_T *pMsgHdr)
Unpack <b><i>BotSense</i></b> client message header.
Definition: bsLibClient.c:421
#define _BS_LOG_MSGHDR(pClient, sPreface, pMsgHdr)
Log [pre/un]packed message header.
ushort_t m_hdrBodyLen
message body length
Definition: BotSense.h:284
ushort_t m_hdrMsgId
message id (vConnection unique)
Definition: BotSense.h:283
#define BS_ECODE_MSG_TOO_BIG
message too big
Definition: BotSense.h:74
static void bsFlushInput(BsClient_T *pClient, size_t count)
Flush input of count bytes.
Definition: bsLibClient.c:713
#define BS_ECODE_MSG_BAD_HDR
bad message header
Definition: BotSense.h:72
#define BSPROXY_MSG_MAGIC
message magic pattern
Definition: BotSense.h:261
#define BSPROXY_MSG_HDR_LEN
message header length (bytes)
Definition: BotSense.h:258
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
ushort_t m_hdrMagic
"unique" magic pattern
Definition: BotSense.h:280
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
static int bsClientRead(BsClient_T *pClient, int sd, byte_t buf[], size_t count, uint_t usec)
Read bytes from socket.
Definition: bsLibClient.c:457
static int bsClientSendReq ( BsClient_T pClient,
BsProxyMsgHdr_T pMsgHdr,
byte_t  bufReq[],
size_t  bufSize 
)
static

Send a request message to the server.

Parameters
pClient

Definition at line 771 of file bsLibClient.c.

References _BS_LOG_MSGHDR, BS_ECODE_BAD_SEND, BS_ECODE_BUF_TOO_SMALL, BS_ECODE_MSG_TOO_BIG, BSCLIENT_TRY_ECODE, BSCLIENT_TRY_EXPR, bsClientPackMsgHdr(), bsClientWrite(), BSPROXY_MSG_BODY_MAX, BSPROXY_MSG_HDR_LEN, bsTransLock(), bsTransUnlock(), BsProxyMsgHdr_T::m_hdrBodyLen, BsProxyMsgHdr_T::m_hdrMsgId, _bsClientStruct::m_pSocket, and _bsClientStruct::m_uReqTimeout.

Referenced by bsClientTrans().

775 {
776  int sd;
777  size_t uBodyLen;
778  uint_t uMsgId;
779  int nBytes;
780  int n;
781 
782  sd = SocketAttrGetSd(pClient->m_pSocket);
783  uMsgId = pMsgHdr->m_hdrMsgId;
784  uBodyLen = (size_t)(pMsgHdr->m_hdrBodyLen);
785  nBytes = BSPROXY_MSG_HDR_LEN + (int)uBodyLen;
786 
787  _BS_LOG_MSGHDR(pClient, "Tx Req", pMsgHdr);
788 
789  BSCLIENT_TRY_EXPR(pClient, (bufSize >= BSPROXY_MSG_HDR_LEN),
790  BS_ECODE_BUF_TOO_SMALL, "MsgId=%u: buf_size=%zu", bufSize);
791 
792  BSCLIENT_TRY_EXPR(pClient, (uBodyLen <= BSPROXY_MSG_BODY_MAX),
793  BS_ECODE_MSG_TOO_BIG, "MsgId=%u: Message body_len=%zu > max=%zu",
794  uMsgId, uBodyLen, BSPROXY_MSG_BODY_MAX);
795 
796  // prepend header to request buffer
797  n = bsClientPackMsgHdr(pClient, pMsgHdr, bufReq, BSPROXY_MSG_HDR_LEN);
798 
799  BSCLIENT_TRY_ECODE(pClient, n,
800  "MsgId=%u: Failed to pack message header", uMsgId);
801 
802  bsTransLock(pClient);
803 
804  // send the message to the server
805  n = bsClientWrite(pClient, sd, bufReq, (size_t)nBytes,
806  pClient->m_uReqTimeout);
807 
808  bsTransUnlock(pClient);
809 
810  BSCLIENT_TRY_EXPR(pClient, (n == nBytes), BS_ECODE_BAD_SEND,
811  "MsgId=%u: Failed to send message", uMsgId);
812 
813  LOGDIAG3("MsgId=%u: Sent %d byte request.", uMsgId, nBytes);
814 
815  return nBytes;
816 }
#define BSCLIENT_TRY_ECODE(pClient, ecode, efmt,...)
Check if <b><i>BotSense</i></b> return value is not an error ( &lt; 0).
Definition: libBotSense.h:214
static int bsClientPackMsgHdr(BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t buf[], size_t bufSize)
Pack <b><i>BotSense</i></b> client message header.
Definition: bsLibClient.c:397
uint_t m_uReqTimeout
client request timeout
Socket_T * m_pSocket
IP socket to server.
Definition: bsLibInternal.h:99
#define BS_ECODE_BAD_SEND
bad send
Definition: BotSense.h:70
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
#define _BS_LOG_MSGHDR(pClient, sPreface, pMsgHdr)
Log [pre/un]packed message header.
ushort_t m_hdrBodyLen
message body length
Definition: BotSense.h:284
ushort_t m_hdrMsgId
message id (vConnection unique)
Definition: BotSense.h:283
#define BS_ECODE_MSG_TOO_BIG
message too big
Definition: BotSense.h:74
static int bsClientWrite(BsClient_T *pClient, int sd, byte_t buf[], size_t count, uint_t usec)
Write bytes to socket.
Definition: bsLibClient.c:594
#define BSPROXY_MSG_HDR_LEN
message header length (bytes)
Definition: BotSense.h:258
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
#define BS_ECODE_BUF_TOO_SMALL
buffer too small
Definition: BotSense.h:75
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
#define BSPROXY_MSG_BODY_MAX
maximum msg body length (sans header)
Definition: BotSense.h:123
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.

Note
The request and response buffer can be the same buffer if packed request contents does not need to be preserved.
Warning
There must be exactly BSPROXY_MSG_HDR_LEN bytes at the front of the request buffer available to pack the BotSense header. (Reduces the number of buffer copies.)
Request Format:
msghdr msgbody
Response Format:
msghdr msgbody
Parameters
pClient

Definition at line 1279 of file bsLibClient.c.

References _BS_LOG_REQ, _BS_LOG_RSP, BS_ECODE_MSG_BAD_HDR, BSCLIENT_LOG_ERROR, BSCLIENT_TRY_ECODE, BSCLIENT_TRY_EXPR, bsClientFillMsgHdr(), bsClientRecvRsp(), bsClientSendReq(), BSPROXY_MSG_HDR_LEN, BSPROXY_VCONN_SERVER, BsProxyMsgIdRspErr, BsProxyUnpackRspErr(), bsTransCacheRsp(), bsTransForget(), bsTransLoadCached(), bsTransMark(), BsProxyRspErr_T::m_ecode, BsProxyRspErr_T::m_emsg, BsProxyMsgHdr_T::m_hdrBodyLen, BsProxyMsgHdr_T::m_hdrMsgId, BsProxyMsgHdr_T::m_hdrTid, and BsProxyMsgHdr_T::m_hdrVConn.

1287 {
1288  BsProxyMsgHdr_T hdrReq; // request message header
1289  BsProxyMsgHdr_T hdrRsp; // response message header
1290  BsTid_T tidReq; // request transaction id
1291  BsProxyRspErr_T msgRspErr; // common error response message
1292  bool_t bPending; // resposne is [not] pending
1293  int n; // number of bytes/return code
1294 
1295  // fill request header
1296  bsClientFillMsgHdr(pClient, hndVConn, uReqMsgId, uReqBodyLen, &hdrReq);
1297 
1298  // this request's transaction id
1299  tidReq = hdrReq.m_hdrTid;
1300 
1301  // mark request for tracking
1302  bsTransMark(pClient, tidReq);
1303 
1304  // send request
1305  n = bsClientSendReq(pClient, &hdrReq, bufReq,
1306  BSPROXY_MSG_HDR_LEN+uReqBodyLen);
1307 
1308  BSCLIENT_TRY_ECODE(pClient, n,
1309  "MsgId=%u: Failed to send request.", uReqMsgId);
1310 
1311  // log successful request sent event
1312  _BS_LOG_REQ(pClient, &hdrReq);
1313 
1314  bPending = true;
1315 
1316  // receive response
1317  while( bPending )
1318  {
1319  // check transaction cache for any cached response.
1320  n = bsTransLoadCached(pClient, tidReq, &hdrRsp, bufRsp, sizeRspBuf);
1321 
1322  BSCLIENT_TRY_ECODE(pClient, n,
1323  "MsgId=%u: Cached response failed for request.", uReqMsgId);
1324 
1325  // found a good, cached response
1326  if( n > 0 )
1327  {
1328  bsTransForget(pClient, tidReq);
1329  bPending = false;
1330  }
1331 
1332  // receive a response
1333  else
1334  {
1335  n = (int)bsClientRecvRsp(pClient, &hdrRsp, bufRsp, sizeRspBuf);
1336 
1337  BSCLIENT_TRY_ECODE(pClient, n,
1338  "MsgId=%u: Receive response failed for request.", uReqMsgId);
1339 
1340  // response was for this request
1341  if( tidReq == hdrRsp.m_hdrTid )
1342  {
1343  bsTransForget(pClient, tidReq);
1344  bPending = false;
1345  }
1346 
1347  // response is for another thread - cache it
1348  else
1349  {
1350  bsTransCacheRsp(pClient, tidReq, &hdrRsp, bufRsp);
1351  }
1352  }
1353  }
1354 
1355  n = (int)hdrRsp.m_hdrBodyLen;
1356 
1357  // received common error response
1358  if( (hdrRsp.m_hdrVConn == BSPROXY_VCONN_SERVER) &&
1359  (hdrRsp.m_hdrMsgId == BsProxyMsgIdRspErr) )
1360  {
1361  n = BsProxyUnpackRspErr(bufRsp, (size_t)n, &msgRspErr, false);
1362 
1363  BSCLIENT_TRY_ECODE(pClient, n,
1364  "MsgId=%u: Failed to unpack error response message body.",
1365  hdrRsp.m_hdrMsgId);
1366 
1367  n = -(int)(msgRspErr.m_ecode);
1368 
1369  BSCLIENT_LOG_ERROR(pClient, n, "%s", msgRspErr.m_emsg);
1370 
1371  return n;
1372  }
1373 
1374  // received application-specific response
1375  else
1376  {
1377  BSCLIENT_TRY_EXPR(pClient, (hdrRsp.m_hdrMsgId == uRspMsgId),
1379  "MsgId=%u: Unexpected response message id, expected MsgId=%u.",
1380  hdrRsp.m_hdrMsgId, uRspMsgId);
1381  }
1382 
1383  // log response received event
1384  _BS_LOG_RSP(pClient, &hdrRsp);
1385 
1386  return n;
1387 }
#define _BS_LOG_REQ(pClient, pMsgHdr)
Log successful request recieved event.
#define BSCLIENT_TRY_ECODE(pClient, ecode, efmt,...)
Check if <b><i>BotSense</i></b> return value is not an error ( &lt; 0).
Definition: libBotSense.h:214
static void bsTransForget(BsClient_T *pClient, BsTid_T uTid)
Delete any cached transaction state from the cache.
Definition: bsLibClient.c:184
uint_t BsTid_T
client transaction id type [0-255].
Definition: BotSense.h:172
#define BSPROXY_VCONN_SERVER
handle for server-terminated msgs
Definition: BotSense.h:140
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
Definition: libBotSense.h:170
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.
Definition: bsProxyMsgs.h:366
void bsClientFillMsgHdr(BsClient_P pClient, int hndVConn, uint_t uMsgId, size_t uBodyLen, BsProxyMsgHdr_T *pMsgHdr)
Fill in message header.
Definition: bsLibClient.c:1148
char m_emsg[(NMFVAL_LEN_MAX_STRING)+1]
emsg
Definition: bsProxyMsgs.h:75
ushort_t m_hdrBodyLen
message body length
Definition: BotSense.h:284
ushort_t m_hdrMsgId
message id (vConnection unique)
Definition: BotSense.h:283
#define _BS_LOG_RSP(pClient, pMsgHdr)
Log successful repsonse recieved event.
#define BS_ECODE_MSG_BAD_HDR
bad message header
Definition: BotSense.h:72
#define BSPROXY_MSG_HDR_LEN
message header length (bytes)
Definition: BotSense.h:258
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
BotSense Proxy Message Header Structure.
Definition: BotSense.h:278
byte_t m_ecode
ecode
Definition: bsProxyMsgs.h:74
byte_t m_hdrTid
transaction id
Definition: BotSense.h:281
static void bsTransCacheRsp(BsClient_T *pClient, BsTid_T uTid, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[])
Cache a transaction response.
Definition: bsLibClient.c:214
byte_t m_hdrVConn
virtual connection handle (server unique)
Definition: BotSense.h:282
static int bsClientSendReq(BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t bufReq[], size_t bufSize)
Send a request message to the server.
Definition: bsLibClient.c:771
static void bsTransMark(BsClient_T *pClient, BsTid_T uTid)
Mark the start of a client&#39;s server transaction in the transaction cache.
Definition: bsLibClient.c:152
static int bsTransLoadCached(BsClient_T *pClient, BsTid_T uTid, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[], size_t sizeRsp)
Load cached response from transaction cache.
Definition: bsLibClient.c:258
static int bsClientRecvRsp(BsClient_T *pClient, BsProxyMsgHdr_T *pMsgHdr, byte_t bufRsp[], size_t bufSize)
Read response message from server.
Definition: bsLibClient.c:829
static int bsClientUnpackMsgHdr ( BsClient_T pClient,
byte_t  buf[],
size_t  bufSize,
BsProxyMsgHdr_T pMsgHdr 
)
inlinestatic

Unpack BotSense client message header.

Parameters
pClient

Definition at line 421 of file bsLibClient.c.

References BS_ECODE_BUF_TOO_SMALL, BSCLIENT_TRY_EXPR, and BSPROXY_MSG_HDR_LEN.

Referenced by bsClientRecvRsp().

425 {
426  BSCLIENT_TRY_EXPR(pClient, (bufSize >= BSPROXY_MSG_HDR_LEN),
427  BS_ECODE_BUF_TOO_SMALL, "bufSize=%zu < %u",
428  bufSize, BSPROXY_MSG_HDR_LEN);
429 
430  return bsUnpackMsgHdr(buf, bufSize, pMsgHdr);
431 }
#define BSPROXY_MSG_HDR_LEN
message header length (bytes)
Definition: BotSense.h:258
#define BS_ECODE_BUF_TOO_SMALL
buffer too small
Definition: BotSense.h:75
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
static int bsClientWrite ( BsClient_T pClient,
int  sd,
byte_t  buf[],
size_t  count,
uint_t  usec 
)
static

Write bytes to socket.

Write up to count bytes from buf to the socket. This call is non-blocking if the timeout value usec is greater than zero. Otherwise the read can block indefinitely.

Note that the number of bytes written can be less than the count.

Parameters
pClient

Definition at line 594 of file bsLibClient.c.

References BS_ECODE_BAD_RECV, BS_ECODE_BAD_SEND, BSCLIENT_LOG_SYSERROR, fdset_nowarn(), timer_elapsed(), and timer_mark().

Referenced by bsClientSendReq().

599 {
600  bool_t bNonBlocking;
601  struct timeval tstart;
602  uint_t tdelta;
603  fd_set wset;
604  struct timeval timeout;
605  int nFd;
606  ssize_t n;
607  int nBytes = 0;
608 
609  LOGDIAG4CALL(_TINT(sd), _TPTR(buf), _TUINT(count), _TUINT(usec));
610 
611  bNonBlocking = usec > 0? true: false;
612 
613  while( nBytes < count )
614  {
615  FD_ZERO(&wset);
616  fdset_nowarn(sd, &wset);
617 
618  // wait for input with timeout
619  if( bNonBlocking )
620  {
621  timer_mark(&tstart);
622 
623  // (re)load timeout (gets munged after each select())
624  timeout.tv_sec = (time_t)(usec / 1000000);
625  timeout.tv_usec = (time_t)(usec % 1000000);
626 
627  nFd = select(sd+1, NULL, &wset, NULL, &timeout);
628  }
629 
630  // block indefinitely for input
631  else
632  {
633  nFd = select(sd+1, NULL, &wset, NULL, NULL);
634  }
635 
636  // system error occurred on select - interpret
637  if( nFd < 0 )
638  {
639  switch(errno)
640  {
641  case EAGAIN: // non-blocking timeout
642  case EINTR: // write was interrupted
643  break;
644  default:
646  "select(%d,...)", sd);
647  return -BS_ECODE_BAD_RECV;
648  }
649  }
650 
651  // select() timeout occurred
652  else if( nFd == 0 )
653  {
654  LOGDIAG4("select() on write timed out.");
655  break;
656  }
657 
658  // data available from serial device
659  n = write(sd, buf+nBytes, count-(size_t)nBytes);
660 
661  // system error occurred on write - interpret
662  if( n < 0 )
663  {
664  switch(errno)
665  {
666  case EAGAIN: // non-blocking timeout
667  case EINTR: // write was interrupted
668  n = 0;
669  break;
670  default:
672  "select(%d,...)", sd);
673  return -BS_ECODE_BAD_RECV;
674  }
675  }
676 
677  // sent some data
678  nBytes += (int)n;
679 
680  // all of the requested bytes have been written
681  if( nBytes == count )
682  {
683  break;
684  }
685 
686  // determine time left for non-blocking write timeout
687  if( bNonBlocking && ((size_t)nBytes < count) )
688  {
689  tdelta = timer_elapsed(&tstart);
690  if( tdelta >= usec )
691  {
692  LOGDIAG4("%s() timed out.", LOGFUNCNAME);
693  break;
694  }
695  else
696  {
697  usec -= tdelta;
698  }
699  }
700  }
701 
702  LOGDIAG4("%s(): %d bytes written.", LOGFUNCNAME, nBytes);
703 
704  return nBytes;
705 }
static uint_t timer_elapsed(struct timeval *pTvMark)
Calculate the elapsed time between the given time mark and this call.
Definition: bsLibClient.c:358
#define BS_ECODE_BAD_RECV
bad receive
Definition: BotSense.h:69
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
Definition: bsLibClient.c:81
#define BS_ECODE_BAD_SEND
bad send
Definition: BotSense.h:70
#define BSCLIENT_LOG_SYSERROR(pClient, ecode, efmt,...)
Log System Error.
Definition: libBotSense.h:196
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
Definition: bsLibClient.c:340
static void bsFlushInput ( BsClient_T pClient,
size_t  count 
)
static

Flush input of count bytes.

Parameters
pClient

Definition at line 713 of file bsLibClient.c.

References BSCLIENT_T_FLUSH, bsClientRead(), and _bsClientStruct::m_pSocket.

Referenced by bsClientRecvRsp(), and bsResync().

714 {
715  int sd;
716  byte_t buf[1024];
717  size_t block;
718  int n;
719 
720  sd = SocketAttrGetSd(pClient->m_pSocket);
721 
722  while( count > 0 )
723  {
724  block = sizeof(buf) >= count? count: sizeof(buf);
725  n = bsClientRead(pClient, sd, buf, block, BSCLIENT_T_FLUSH);
726  if( n <= 0 )
727  {
728  return;
729  }
730  count -= (size_t)n;
731  }
732 }
Socket_T * m_pSocket
IP socket to server.
Definition: bsLibInternal.h:99
#define BSCLIENT_T_FLUSH
5 second flush timeout default
Definition: bsLibInternal.h:68
static int bsClientRead(BsClient_T *pClient, int sd, byte_t buf[], size_t count, uint_t usec)
Read bytes from socket.
Definition: bsLibClient.c:457
static BsTid_T bsNextTid ( BsClient_T pClient)
static

Atomically get the next available transaction id.

Parameters
pClient

Definition at line 315 of file bsLibClient.c.

References BSPROXY_TID_MASK, bsTransLock(), bsTransUnlock(), and _bsClientStruct::m_uTidCounter.

Referenced by bsClientFillMsgHdr().

316 {
317  BsTid_T uTid;
318 
319  bsTransLock(pClient);
320 
321  uTid = pClient->m_uTidCounter;
322  pClient->m_uTidCounter = (uTid + 1) & BSPROXY_TID_MASK;
323 
324  bsTransUnlock(pClient);
325 
326  return uTid;
327 }
uint_t BsTid_T
client transaction id type [0-255].
Definition: BotSense.h:172
#define BSPROXY_TID_MASK
transaction id mask
Definition: BotSense.h:170
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
uint_t m_uTidCounter
transaction id counter
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
static void bsResync ( BsClient_T pClient)
static

Resync client with server.

Lost message alignment with the server (if this is possible). Perfomr a series of flush-request cycles to try to get back in sync.

Parameters
pClient

Definition at line 742 of file bsLibClient.c.

References BS_ECODE_BAD_RESYNC, BS_OK, BSCLIENT_LOG_ERROR, bsFlushInput(), and BSPROXY_MSG_MAX_LEN.

Referenced by bsClientRecvRsp().

743 {
744  int nMaxTries = 5;
745  int nTries;
746  int rc;
747 
748  for(nTries=0; nTries<nMaxTries; ++nTries)
749  {
751  if( (rc = bsServerReqLoopback(pClient, "resync")) == BS_OK )
752  {
753  return;
754  }
755  }
757 }
#define BS_ECODE_BAD_RESYNC
bad resync with server/client
Definition: BotSense.h:71
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
Definition: libBotSense.h:170
#define BS_OK
not an error, success
Definition: BotSense.h:66
static void bsFlushInput(BsClient_T *pClient, size_t count)
Flush input of count bytes.
Definition: bsLibClient.c:713
#define BSPROXY_MSG_MAX_LEN
total message maximum length
Definition: BotSense.h:259
static void bsTransCacheRsp ( BsClient_T pClient,
BsTid_T  uTid,
BsProxyMsgHdr_T pMsgHdr,
byte_t  bufRsp[] 
)
static

Cache a transaction response.

Cashing a response occurs when this client thread receives a response fo another client thread.

Parameters
pClient

Definition at line 214 of file bsLibClient.c.

References bsClientAttrGetName(), BSPROXY_TID_MASK, bsTransLock(), bsTransUnlock(), BsTransInfo_T::m_bCached, BsProxyMsgHdr_T::m_hdrBodyLen, BsProxyMsgHdr_T::m_hdrMsgId, BsTransInfo_T::m_pBuf, BsTransInfo_T::m_pMsgHdr, and _bsClientStruct::m_tblTransCache.

Referenced by bsClientTrans().

218 {
219  BsTransInfo_T *pInfo;
220  size_t uBodyLen;
221 
222  bsTransLock(pClient);
223 
224  pInfo = pClient->m_tblTransCache[uTid & BSPROXY_TID_MASK];
225 
226  delete(pInfo->m_pMsgHdr);
227  delete(pInfo->m_pBuf);
228 
229  uBodyLen = (size_t)(pMsgHdr->m_hdrBodyLen);
230 
231  pInfo->m_pMsgHdr = new_memdup(sizeof(BsProxyMsgHdr_T), pMsgHdr);
232  pInfo->m_pBuf = uBodyLen>0? new_memdup(uBodyLen, bufRsp): NULL;
233  pInfo->m_bCached = true;
234 
235  LOGDIAG3("%s: Tid=%u, MsgId=%u cached.",
236  bsClientAttrGetName(pClient), uTid, pMsgHdr->m_hdrMsgId);
237 
238  bsTransUnlock(pClient);
239 }
BsProxyMsgHdr_T * m_pMsgHdr
cached message header
Definition: bsLibInternal.h:77
#define BSPROXY_TID_MASK
transaction id mask
Definition: BotSense.h:170
Cashed Transaction Information Structure.
Definition: bsLibInternal.h:74
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
BsTransInfo_T * m_tblTransCache[BSPROXY_TID_NUMOF]
transaction cache
ushort_t m_hdrBodyLen
message body length
Definition: BotSense.h:284
ushort_t m_hdrMsgId
message id (vConnection unique)
Definition: BotSense.h:283
byte_t * m_pBuf
cached packed message body buffer
Definition: bsLibInternal.h:78
const char * bsClientAttrGetName(BsClient_P pClient)
Get client name.
Definition: bsLibClient.c:918
bool_t m_bCached
this transaction is [not] cached
Definition: bsLibInternal.h:76
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
BotSense Proxy Message Header Structure.
Definition: BotSense.h:278
static void bsTransForget ( BsClient_T pClient,
BsTid_T  uTid 
)
static

Delete any cached transaction state from the cache.

Parameters
pClient

Definition at line 184 of file bsLibClient.c.

References BSPROXY_TID_MASK, bsTransLock(), bsTransUnlock(), BsTransInfo_T::m_pBuf, BsTransInfo_T::m_pMsgHdr, and _bsClientStruct::m_tblTransCache.

Referenced by bsClientDelete(), and bsClientTrans().

185 {
186  BsTransInfo_T *pInfo;
187 
188  bsTransLock(pClient);
189 
190  pInfo = pClient->m_tblTransCache[uTid & BSPROXY_TID_MASK];
191 
192  if( pInfo != NULL )
193  {
194  delete(pInfo->m_pMsgHdr);
195  delete(pInfo->m_pBuf);
196  delete(pInfo);
197  pClient->m_tblTransCache[uTid & BSPROXY_TID_MASK] = NULL;
198  }
199 
200  bsTransUnlock(pClient);
201 }
BsProxyMsgHdr_T * m_pMsgHdr
cached message header
Definition: bsLibInternal.h:77
#define BSPROXY_TID_MASK
transaction id mask
Definition: BotSense.h:170
Cashed Transaction Information Structure.
Definition: bsLibInternal.h:74
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
BsTransInfo_T * m_tblTransCache[BSPROXY_TID_NUMOF]
transaction cache
byte_t * m_pBuf
cached packed message body buffer
Definition: bsLibInternal.h:78
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
static int bsTransLoadCached ( BsClient_T pClient,
BsTid_T  uTid,
BsProxyMsgHdr_T pMsgHdr,
byte_t  bufRsp[],
size_t  sizeRsp 
)
static

Load cached response from transaction cache.

Cashing a response occurs when this client thread receives a response fo another client thread.

Parameters
pClient

Definition at line 258 of file bsLibClient.c.

References BS_ECODE_MSG_TOO_BIG, BSCLIENT_LOG_ERROR, bsClientAttrGetName(), BSPROXY_TID_MASK, bsTransLock(), bsTransUnlock(), BsTransInfo_T::m_bCached, BsProxyMsgHdr_T::m_hdrBodyLen, BsProxyMsgHdr_T::m_hdrMsgId, BsTransInfo_T::m_pBuf, BsTransInfo_T::m_pMsgHdr, and _bsClientStruct::m_tblTransCache.

Referenced by bsClientTrans().

263 {
264  BsTransInfo_T *pInfo;
265  size_t uBodyLen;
266  int rc = 0;
267 
268  bsTransLock(pClient);
269 
270  pInfo = pClient->m_tblTransCache[uTid & BSPROXY_TID_MASK];
271 
272  if( (pInfo == NULL) || !pInfo->m_bCached )
273  {
274  rc = 0;
275  }
276 
277  else
278  {
279  uBodyLen = (size_t)(pMsgHdr->m_hdrBodyLen);
280  if( uBodyLen > sizeRsp )
281  {
283  "body_len=%zu > buf_size=%zu.", uBodyLen, sizeRsp);
284  rc = -BS_ECODE_MSG_TOO_BIG;
285  }
286 
287  // load from cache
288  else
289  {
290  *pMsgHdr = *(pInfo->m_pMsgHdr);
291  if( uBodyLen > 0 )
292  {
293  memcpy(bufRsp, pInfo->m_pBuf, uBodyLen);
294  }
295 
296  LOGDIAG3("%s: Tid=%u, MsgId=%u loaded from cached.",
297  bsClientAttrGetName(pClient), uTid, pMsgHdr->m_hdrMsgId);
298 
299  rc = 1;
300  }
301  }
302 
303  bsTransUnlock(pClient);
304 
305  return rc;
306 }
BsProxyMsgHdr_T * m_pMsgHdr
cached message header
Definition: bsLibInternal.h:77
#define BSPROXY_TID_MASK
transaction id mask
Definition: BotSense.h:170
Cashed Transaction Information Structure.
Definition: bsLibInternal.h:74
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
Definition: libBotSense.h:170
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
BsTransInfo_T * m_tblTransCache[BSPROXY_TID_NUMOF]
transaction cache
ushort_t m_hdrBodyLen
message body length
Definition: BotSense.h:284
ushort_t m_hdrMsgId
message id (vConnection unique)
Definition: BotSense.h:283
#define BS_ECODE_MSG_TOO_BIG
message too big
Definition: BotSense.h:74
byte_t * m_pBuf
cached packed message body buffer
Definition: bsLibInternal.h:78
const char * bsClientAttrGetName(BsClient_P pClient)
Get client name.
Definition: bsLibClient.c:918
bool_t m_bCached
this transaction is [not] cached
Definition: bsLibInternal.h:76
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
static void bsTransLock ( BsClient_T pClient)
inlinestatic

Lock client's transaction mutual exclusion.

Parameters
pClient

Definition at line 97 of file bsLibClient.c.

References BS_ECODE_SYS, and BSCLIENT_LOG_SYSERROR.

Referenced by bsClientRecvRsp(), bsClientSendReq(), bsNextTid(), bsTransCacheRsp(), bsTransForget(), bsTransLoadCached(), bsTransMark(), bsVConnAdd(), bsVConnDelete(), bsVConnNew(), and bsVConnRemove().

98 {
99  int rc;
100 
101  if( (rc = pthread_mutex_lock(&(pClient->m_mutexTrans))) != 0 )
102  {
103  errno = rc;
104  BSCLIENT_LOG_SYSERROR(pClient, BS_ECODE_SYS, "pthread_mutex_lock()");
105  }
106 }
#define BSCLIENT_LOG_SYSERROR(pClient, ecode, efmt,...)
Log System Error.
Definition: libBotSense.h:196
pthread_mutex_t m_mutexTrans
client transaction mutex
#define BS_ECODE_SYS
system (errno) error
Definition: BotSense.h:92
static void bsTransMark ( BsClient_T pClient,
BsTid_T  uTid 
)
static

Mark the start of a client's server transaction in the transaction cache.

A client can be multi-threaded, and so the responses from the server may come out of order with respect to the client thread.

Parameters
pClient

Definition at line 152 of file bsLibClient.c.

References BSPROXY_TID_MASK, bsTransLock(), bsTransUnlock(), BsTransInfo_T::m_bCached, BsTransInfo_T::m_pBuf, BsTransInfo_T::m_pMsgHdr, and _bsClientStruct::m_tblTransCache.

Referenced by bsClientTrans().

153 {
154  BsTransInfo_T *pInfo;
155 
156  bsTransLock(pClient);
157 
158  pInfo = pClient->m_tblTransCache[uTid & BSPROXY_TID_MASK];
159 
160  if( pInfo != NULL )
161  {
162  delete(pInfo->m_pMsgHdr);
163  delete(pInfo->m_pBuf);
164  delete(pInfo);
165  }
166 
167  pInfo = NEW(BsTransInfo_T);
168 
169  pInfo->m_pMsgHdr = NULL;
170  pInfo->m_pBuf = NULL;
171  pInfo->m_bCached = false;
172 
173  pClient->m_tblTransCache[uTid & BSPROXY_TID_MASK] = pInfo;
174 
175  bsTransUnlock(pClient);
176 }
BsProxyMsgHdr_T * m_pMsgHdr
cached message header
Definition: bsLibInternal.h:77
#define BSPROXY_TID_MASK
transaction id mask
Definition: BotSense.h:170
Cashed Transaction Information Structure.
Definition: bsLibInternal.h:74
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
BsTransInfo_T * m_tblTransCache[BSPROXY_TID_NUMOF]
transaction cache
byte_t * m_pBuf
cached packed message body buffer
Definition: bsLibInternal.h:78
bool_t m_bCached
this transaction is [not] cached
Definition: bsLibInternal.h:76
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
static bool_t bsTransTryLock ( BsClient_T pClient)
inlinestatic

Try to lock client's transaction mutual exclusion.

Parameters
pClient

Definition at line 132 of file bsLibClient.c.

References _bsClientStruct::m_mutexTrans.

133 {
134  return pthread_mutex_trylock(&(pClient->m_mutexTrans)) == 0? true: false;
135 }
pthread_mutex_t m_mutexTrans
client transaction mutex
static void bsTransUnlock ( BsClient_T pClient)
inlinestatic

Unlock client's transaction mutual exclusion.

Parameters
pClient

Definition at line 113 of file bsLibClient.c.

References BS_ECODE_SYS, BSCLIENT_LOG_SYSERROR, and _bsClientStruct::m_mutexTrans.

Referenced by bsClientRecvRsp(), bsClientSendReq(), bsNextTid(), bsTransCacheRsp(), bsTransForget(), bsTransLoadCached(), bsTransMark(), bsVConnAdd(), bsVConnDelete(), bsVConnNew(), and bsVConnRemove().

114 {
115  int rc;
116 
117  if( (rc = pthread_mutex_unlock(&(pClient->m_mutexTrans))) != 0 )
118  {
119  errno = rc;
120  BSCLIENT_LOG_SYSERROR(pClient, BS_ECODE_SYS, "pthread_mutex_unlock()");
121  }
122 }
#define BSCLIENT_LOG_SYSERROR(pClient, ecode, efmt,...)
Log System Error.
Definition: libBotSense.h:196
pthread_mutex_t m_mutexTrans
client transaction mutex
#define BS_ECODE_SYS
system (errno) error
Definition: BotSense.h:92
int bsVConnAdd ( BsClient_T pClient,
BsVConnHnd_T  hndVConn,
int  index 
)

Add a created vConnection to the client's tblHndIndex table.

Note
The new vConnection should have been created and reserved prior to adding.
Parameters
pClient

Definition at line 1506 of file bsLibClient.c.

References BS_ECODE_INTERNAL, BS_OK, BSCLIENT_IS_VCONN_HANDLE, BSCLIENT_LOG_ERROR, BSCLIENT_TRY_EXPR, BSPROXY_VCONN_CLIENT_MAX, BSPROXY_VCONN_UNDEF, bsTransLock(), bsTransUnlock(), BsVConn_T::m_hndVConn, _bsClientStruct::m_nVConnCount, _bsClientStruct::m_tblHndIndex, and _bsClientStruct::m_tblVConn.

Referenced by bsGetVConn(), and bsServerReqOpenDev().

1509 {
1510  int i;
1511  int rc;
1512 
1513  BSCLIENT_TRY_EXPR(pClient, BSCLIENT_IS_VCONN_HANDLE(hndVConn),
1514  BS_ECODE_INTERNAL, "VConn=%d: out-of-range.", hndVConn);
1515 
1516  BSCLIENT_TRY_EXPR(pClient, (index < BSPROXY_VCONN_CLIENT_MAX),
1517  BS_ECODE_INTERNAL, "index=%d: out-of-range.", index);
1518 
1519  bsTransLock(pClient);
1520 
1521  i = (int)pClient->m_tblHndIndex[hndVConn];
1522 
1523  if( i != BSPROXY_VCONN_UNDEF )
1524  {
1526  "VConn=%d: index=%d: handle already assigned: "
1527  "Internal vconn tables corrupted.", hndVConn, i);
1528  rc = -BS_ECODE_INTERNAL;
1529  }
1530 
1531  else if( pClient->m_tblVConn[index] == NULL )
1532  {
1534  "VConn=%d: index=%d: No vConnection present: "
1535  "Internal vconn tables corrupted.", hndVConn, index);
1536  rc = -BS_ECODE_INTERNAL;
1537  }
1538 
1539  else
1540  {
1541  pClient->m_tblVConn[index]->m_hndVConn = hndVConn;
1542  pClient->m_tblHndIndex[hndVConn] = (byte_t)index;
1543  pClient->m_nVConnCount++;
1544  rc = BS_OK;
1545  }
1546 
1547  bsTransUnlock(pClient);
1548 
1549  return rc;
1550 }
BsVConnHnd_T m_hndVConn
virtual connection handle
Definition: bsLibInternal.h:86
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
#define BSCLIENT_IS_VCONN_HANDLE(hnd)
Test if the handle is in the valid client virtual connection range.
Definition: libBotSense.h:274
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
Definition: libBotSense.h:170
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
#define BS_OK
not an error, success
Definition: BotSense.h:66
#define BSPROXY_VCONN_UNDEF
undefined virtual connection handle
Definition: BotSense.h:139
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
#define BSPROXY_VCONN_CLIENT_MAX
max number of virtual conn/client
Definition: BotSense.h:122
#define BS_ECODE_INTERNAL
internal error (bug)
Definition: BotSense.h:93
byte_t m_tblHndIndex[BSPROXY_VCONN_MOD_NUMOF]
handle to vconn index table
int m_nVConnCount
number of active v. connections
void bsVConnClearAll ( BsClient_T pClient)

Remove and delete all of a client's vConnections.

Parameters
pClient

Definition at line 1478 of file bsLibClient.c.

References BSPROXY_VCONN_UNDEF, bsVConnDelete(), bsVConnRemove(), and _bsClientStruct::m_tblHndIndex.

Referenced by bsClientDelete(), bsGetVConn(), and bsServerDisconnect().

1479 {
1480  size_t nHnd;
1481  int index;
1482 
1483  for(nHnd=0; nHnd<arraysize(pClient->m_tblHndIndex); ++nHnd)
1484  {
1485  index = (int)pClient->m_tblHndIndex[nHnd];
1486  if( index != BSPROXY_VCONN_UNDEF )
1487  {
1488  bsVConnRemove(pClient, (BsVConnHnd_T)nHnd);
1489  bsVConnDelete(pClient, index);
1490  }
1491  }
1492 }
int bsVConnRemove(BsClient_T *pClient, BsVConnHnd_T hndVConn)
Remove a vConnection from the client&#39;s tblHndIndex table.
Definition: bsLibClient.c:1565
#define BSPROXY_VCONN_UNDEF
undefined virtual connection handle
Definition: BotSense.h:139
int bsVConnDelete(BsClient_T *pClient, int index)
Delete a vConnection (and proxied device) from the client&#39;s tblVConn table.
Definition: bsLibClient.c:1684
byte_t m_tblHndIndex[BSPROXY_VCONN_MOD_NUMOF]
handle to vconn index table
int BsVConnHnd_T
virtual connection handle type
Definition: BotSense.h:151
int bsVConnDelete ( BsClient_T pClient,
int  index 
)

Delete a vConnection (and proxied device) from the client's tblVConn table.

Note
The vConnection should be removed first prior to deletion.
Parameters
pClient

Definition at line 1684 of file bsLibClient.c.

References BS_ECODE_INTERNAL, BS_OK, BSCLIENT_LOG_ERROR, BSCLIENT_TRY_EXPR, BSPROXY_VCONN_CLIENT_MAX, bsTransLock(), bsTransUnlock(), BsVConn_T::m_sDevName, BsVConn_T::m_sModName, and _bsClientStruct::m_tblVConn.

Referenced by bsGetVConn(), bsServerReqCloseDev(), bsServerReqOpenDev(), and bsVConnClearAll().

1685 {
1686  BsVConn_T *pVConn;
1687  int rc;
1688 
1689  BSCLIENT_TRY_EXPR(pClient, (index < BSPROXY_VCONN_CLIENT_MAX),
1690  BS_ECODE_INTERNAL, "index=%d: out-of-range.", index);
1691 
1692  bsTransLock(pClient);
1693 
1694  pVConn = pClient->m_tblVConn[index];
1695 
1696  if( pVConn == NULL )
1697  {
1699  "index=%u: vConnection not present in table.", index);
1700  rc = -BS_ECODE_INTERNAL;
1701  }
1702 
1703  else
1704  {
1705  delete((char *)(pVConn->m_sDevName));
1706  delete((char *)(pVConn->m_sModName));
1707  delete(pVConn);
1708 
1709  // free slot
1710  pClient->m_tblVConn[index] = NULL;
1711 
1712  rc = BS_OK;
1713  }
1714 
1715  bsTransUnlock(pClient);
1716 
1717  return rc;
1718 }
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
const char * m_sModName
interface module path name
Definition: bsLibInternal.h:89
Client Virtual Connection Info Structure.
Definition: bsLibInternal.h:84
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
Definition: libBotSense.h:170
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
#define BS_OK
not an error, success
Definition: BotSense.h:66
const char * m_sDevName
device path name
Definition: bsLibInternal.h:88
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
#define BSPROXY_VCONN_CLIENT_MAX
max number of virtual conn/client
Definition: BotSense.h:122
#define BS_ECODE_INTERNAL
internal error (bug)
Definition: BotSense.h:93
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.

Note
The new vConnection still needs to be added.
Parameters
pClient

Definition at line 1614 of file bsLibClient.c.

References BS_ECODE_INTERNAL, BS_ECODE_NO_RSRC, BS_OK, BSCLIENT_LOG_ERROR, bsClientAttrGetVConnCount(), BSPROXY_VCONN_CLIENT_MAX, BSPROXY_VCONN_UNDEF, bsTransLock(), bsTransUnlock(), BsVConn_T::m_bTrace, BsVConn_T::m_hndVConn, BsVConn_T::m_pAppInfo, BsVConn_T::m_sDevName, BsVConn_T::m_sModName, and _bsClientStruct::m_tblVConn.

Referenced by bsGetVConn(), and bsServerReqOpenDev().

1619 {
1620  int index;
1621  BsVConn_T *pVConn;
1622  int rc = BS_OK;
1623 
1624  bsTransLock(pClient);
1625 
1627  {
1629  "Client has the maximum=%d virtual connections.",
1631  rc = -BS_ECODE_NO_RSRC;
1632  }
1633 
1634  else
1635  {
1636  for(index=0; index<BSPROXY_VCONN_CLIENT_MAX; ++index)
1637  {
1638  if( pClient->m_tblVConn[index] == NULL )
1639  {
1640  break;
1641  }
1642  }
1643 
1644  if( index >= BSPROXY_VCONN_CLIENT_MAX )
1645  {
1647  "Internal vconn tables corrupted.");
1648  rc = -BS_ECODE_INTERNAL;
1649  }
1650  }
1651 
1652  if( rc == BS_OK )
1653  {
1654  pVConn = NEW(BsVConn_T);
1655 
1656  pVConn->m_hndVConn = BSPROXY_VCONN_UNDEF;
1657  pVConn->m_bTrace = bTrace;
1658  pVConn->m_sDevName = new_strdup(sDevName);
1659  pVConn->m_sModName = new_strdup(sModName);
1660  pVConn->m_pAppInfo = pAppInfo;
1661 
1662  // reserve slot
1663  pClient->m_tblVConn[index] = pVConn;
1664 
1665  rc = index;
1666  }
1667 
1668  bsTransUnlock(pClient);
1669 
1670  return rc;
1671 }
BsVConnHnd_T m_hndVConn
virtual connection handle
Definition: bsLibInternal.h:86
const BsClientAppInfo_T * m_pAppInfo
app-specific info (optional)
Definition: bsLibInternal.h:90
int bsClientAttrGetVConnCount(BsClient_P pClient)
Get the number of active virtual connections for this client.
Definition: bsLibClient.c:998
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
const char * m_sModName
interface module path name
Definition: bsLibInternal.h:89
Client Virtual Connection Info Structure.
Definition: bsLibInternal.h:84
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
Definition: libBotSense.h:170
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
#define BS_OK
not an error, success
Definition: BotSense.h:66
#define BSPROXY_VCONN_UNDEF
undefined virtual connection handle
Definition: BotSense.h:139
const char * m_sDevName
device path name
Definition: bsLibInternal.h:88
#define BS_ECODE_NO_RSRC
no resource available
Definition: BotSense.h:85
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
#define BSPROXY_VCONN_CLIENT_MAX
max number of virtual conn/client
Definition: BotSense.h:122
#define BS_ECODE_INTERNAL
internal error (bug)
Definition: BotSense.h:93
bool_t m_bTrace
do [not] trace this vconn msgs
Definition: bsLibInternal.h:87
int bsVConnRemove ( BsClient_T pClient,
BsVConnHnd_T  hndVConn 
)

Remove a vConnection from the client's tblHndIndex table.

Note
The vConnection stills needs to be deleted.
Parameters
pClient

Definition at line 1565 of file bsLibClient.c.

References BS_ECODE_INTERNAL, BSCLIENT_IS_VCONN_HANDLE, BSCLIENT_LOG_ERROR, BSCLIENT_TRY_EXPR, BSPROXY_VCONN_UNDEF, bsTransLock(), bsTransUnlock(), BsVConn_T::m_hndVConn, _bsClientStruct::m_nVConnCount, _bsClientStruct::m_tblHndIndex, and _bsClientStruct::m_tblVConn.

Referenced by bsGetVConn(), bsServerReqCloseDev(), and bsVConnClearAll().

1566 {
1567  int index;
1568  int rc;
1569 
1570  BSCLIENT_TRY_EXPR(pClient, BSCLIENT_IS_VCONN_HANDLE(hndVConn),
1571  BS_ECODE_INTERNAL, "VConn=%d: out-of-range.", hndVConn);
1572 
1573  bsTransLock(pClient);
1574 
1575  index = pClient->m_tblHndIndex[hndVConn];
1576 
1577  if( index == BSPROXY_VCONN_UNDEF )
1578  {
1580  "VConn=%d: vConnection not present in table.", hndVConn);
1581  rc = -BS_ECODE_INTERNAL;
1582  }
1583 
1584  else
1585  {
1586  pClient->m_tblVConn[index]->m_hndVConn = BSPROXY_VCONN_UNDEF;
1587  pClient->m_tblHndIndex[hndVConn] = BSPROXY_VCONN_UNDEF;
1588  pClient->m_nVConnCount--;
1589 
1590  rc = index;
1591  }
1592 
1593  bsTransUnlock(pClient);
1594 
1595  return rc;
1596 }
BsVConnHnd_T m_hndVConn
virtual connection handle
Definition: bsLibInternal.h:86
BsVConn_T * m_tblVConn[BSPROXY_VCONN_CLIENT_MAX]
table of virtual connections
#define BSCLIENT_IS_VCONN_HANDLE(hnd)
Test if the handle is in the valid client virtual connection range.
Definition: libBotSense.h:274
#define BSCLIENT_LOG_ERROR(pClient, ecode, efmt,...)
Log Error.
Definition: libBotSense.h:170
static void bsTransLock(BsClient_T *pClient)
Lock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:97
#define BSPROXY_VCONN_UNDEF
undefined virtual connection handle
Definition: BotSense.h:139
static void bsTransUnlock(BsClient_T *pClient)
Unlock client&#39;s transaction mutual exclusion.
Definition: bsLibClient.c:113
#define BSCLIENT_TRY_EXPR(pClient, expr, ecode, efmt,...)
Check if expression evaluates to true.
Definition: libBotSense.h:259
#define BS_ECODE_INTERNAL
internal error (bug)
Definition: BotSense.h:93
byte_t m_tblHndIndex[BSPROXY_VCONN_MOD_NUMOF]
handle to vconn index table
int m_nVConnCount
number of active v. connections
static void fdset_nowarn ( int  fd,
fd_set *  pset 
)
inlinestatic

FD_SET() wrapper with no annoying warnings.

Parameters
fdFile descriptor to add to set.
psetPointer to fd set.

Definition at line 81 of file bsLibClient.c.

Referenced by bsClientRead(), and bsClientWrite().

82 {
83  FD_SET(fd, pset);
84 }
static uint_t timer_elapsed ( struct timeval *  pTvMark)
static

Calculate the elapsed time between the given time mark and this call.

Parameters
pTvMarkPointer to timeval holding time mark.
Returns
Number of microseconds elasped. If the marked time is invalid or the current time cannot be ascertained, UINT_MAX is returned.

Definition at line 358 of file bsLibClient.c.

References timer_mark().

Referenced by bsClientRead(), bsClientWrite(), ClientRead(), and ClientWrite().

359 {
360  struct timeval tvEnd, tvDelta;
361 
362  timer_mark(&tvEnd);
363 
364  if( !timerisset(pTvMark) || !timerisset(&tvEnd) )
365  {
366  return UINT_MAX;
367  }
368 
369  tvDelta.tv_sec = tvEnd.tv_sec - pTvMark->tv_sec;
370  if( tvEnd.tv_usec < pTvMark->tv_usec )
371  {
372  tvDelta.tv_sec--;
373  tvEnd.tv_usec += 1000000;
374  }
375  tvDelta.tv_usec = tvEnd.tv_usec - pTvMark->tv_usec;
376 
377  return (uint_t)(tvDelta.tv_sec * 1000000 + tvDelta.tv_usec);
378 }
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
Definition: bsLibClient.c:340
static void timer_mark ( struct timeval *  pTvMark)
inlinestatic

Mark the current time. Resolution is microseconds.

Parameters
pTvMarkPointer to timeval structure to be populated with the current system time in seconds and useconds.

Definition at line 340 of file bsLibClient.c.

Referenced by bsClientRead(), bsClientWrite(), ClientRead(), ClientWrite(), and timer_elapsed().

341 {
342  if( gettimeofday(pTvMark, NULL) != OK )
343  {
344  LOGSYSERROR("gettimeofday()");
345  timerclear(pTvMark);
346  }
347 }