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

BotSense proxy IP server. More...

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "rnr/rnrconfig.h"
#include "rnr/log.h"
#include "rnr/opts.h"
#include "rnr/dlistvoid.h"
#include "rnr/dliststr.h"
#include "rnr/new.h"
#include "rnr/sock.h"
#include "rnr/sockset.h"
#include "botsense/bsProxyMsgs.h"
#include "version.h"
#include "bsProxy.h"

Go to the source code of this file.

Macros

#define SERVER_LOG_ERROR(ecode, efmt, ...)
 Log Proxy Server Specific Error. More...
 
#define SERVER_LOG_SYSERROR(efmt, ...)
 Log Proxy Server Specific System Error. More...
 

Functions

static int OptsCvtArgInterface (const char *argv0, const char *sOptName, char *optarg, void *pOptVal)
 Convert command-line listen interface option string to network name/number and port number. More...
 
static int OptsCvtArgLibPath (const char *argv0, const char *sOptName, char *optarg, void *pOptVal)
 Append command-line library search path option to list of search paths. More...
 
static void ServerLock ()
 Lock server's mutual exclusion.
 
static void ServerUnlock ()
 Unlock server's mutual exclusion.
 
static bool_t ServerTryLock ()
 Try to lock global mutual exclusion. More...
 
static BsProxyClientHnd_T BsProxyClientRegister (Socket_T *pSockClient)
 Register a new client with the server. More...
 
static void BsProxyClientUnregister (BsProxyClientHnd_T hndClient)
 Unregister a client with the server. More...
 
static void BsProxyServerDelete (BsProxyServerCtl_T *pServer)
 Delete a server control block. More...
 
static BsProxyServerCtl_TBsProxyServerNew (const char *sPrefix, const char *sLocalHostName, int nPort)
 Create new server control block. More...
 
static void BsProxyDispatch (BsProxyClientHnd_T hndClient, BsProxyMsgHdr_T *pMsgHdr, byte_t bufReq[])
 Dispatch client request. More...
 
static int BsProxyServer (BsProxyServerCtl_T *pServer)
 Server mainloop. More...
 
static void MainEnv ()
 Get and set environment.
 
static void MainCfg ()
 Get configuration.
 
static void MainInit (int argc, char *argv[])
 Main initialization. More...
 
int main (int argc, char *argv[])
 bsProxy main() More...
 

Variables

const char * Argv0
 command base name
 
static char * BsOptListenIFDft = NULL
 default listen interface
 
static DListVoid_T * BsOptDListListenIF = NULL
 list of listen i/f's
 
static DListStr_T * BsOptDListLibPath = NULL
 list of lib search paths
 
static OptsPgmInfo_T BsProxyPgmInfo
 
static OptsInfo_T BsProxyOptsInfo []
 
BsProxyServerCtl_TBsServerCtl
 The server control block. More...
 

Detailed Description

BotSense proxy IP server.

LastChangedDate
2010-09-13 10:25:05 -0600 (Mon, 13 Sep 2010)
Rev
581
See also
bsProxy Man Page
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 bsProxy.c.

Macro Definition Documentation

#define SERVER_LOG_ERROR (   ecode,
  efmt,
  ... 
)
Value:
LOGERROR("Server %s:%s(ecode=%d): " efmt, \
bsStrError(ecode), (ecode>=0? ecode: -ecode), \
##__VA_ARGS__)
INLINE_IN_H const char * ServerHasName()
Get the <b><i>BotSense</i></b> server&#39;s official name.
Definition: bsProxy.h:485

Log Proxy Server Specific Error.

Parameters
ecode

Definition at line 159 of file bsProxy.c.

Referenced by BsProxyServer().

#define SERVER_LOG_SYSERROR (   efmt,
  ... 
)
Value:
LOGERROR("Server %s: %s(ecode=%d): %s(errno=%d)" efmt, \
bsStrError(BS_ECODE_SYS), BS_ECODE_SYS, \
strerror(errno), errno, ##__VA_ARGS__)
INLINE_IN_H const char * ServerHasName()
Get the <b><i>BotSense</i></b> server&#39;s official name.
Definition: bsProxy.h:485
#define BS_ECODE_SYS
system (errno) error
Definition: BotSense.h:92

Log Proxy Server Specific System Error.

Parameters
efmtError output format string litteral.
...Error variable arguments.

Definition at line 171 of file bsProxy.c.

Referenced by ServerLock(), and ServerUnlock().

Function Documentation

static BsProxyClientHnd_T BsProxyClientRegister ( Socket_T *  pSockClient)
static

Register a new client with the server.

Parameters
pSockClientAccecpted client socket.
Returns
Returns client handle.

Definition at line 224 of file bsProxy.c.

References ClientNew(), BsProxyClientCtl_T::m_pClientSock, BsProxyServerCtl_T::m_pServerRegClient, BsProxyServerCtl_T::m_pServerSockSet, BsProxyServerCtl_T::m_uServerRegClientCount, ServerClientSd2Hnd(), and ServerGet().

Referenced by BsProxyServer().

225 {
226  BsProxyServerCtl_T *pServer;
227  BsProxyClientCtl_T *pClient;
228  int sd;
229 
230  pClient = ClientNew(pSockClient);
231 
232  // get the server instance
233  pServer = ServerGet();
234 
235  //
236  // The client handle is also the opened socket descriptor.
237  //
238  sd = SocketAttrGetSd(pSockClient);
239 
240  //
241  // Add client socket to server's socket set. The client socket is added
242  // only to the active read set, not the write set.
243  //
244  SockSetAdd(pServer->m_pServerSockSet, pClient->m_pClientSock, true, false);
245 
246  pServer->m_pServerRegClient[sd] = pClient;
247  pServer->m_uServerRegClientCount++;
248 
249  return ServerClientSd2Hnd(sd);
250 }
BsProxyClientCtl_T * m_pServerRegClient[256]
registered clients
Definition: bsProxy.h:212
uint_t m_uServerRegClientCount
num of reg. clients
Definition: bsProxy.h:211
Socket_T * m_pClientSock
client opened TCP socket
Definition: bsProxy.h:196
INLINE_IN_H BsProxyServerCtl_T * ServerGet()
Get the <b><i>BotSense</i></b> server.
Definition: bsProxy.h:475
INLINE_IN_H BsProxyClientHnd_T ServerClientSd2Hnd(int sd)
Convert the <b><i>BotSense</i></b> server client socket descriptor to client handle.
Definition: bsProxy.h:537
SockSet_T * m_pServerSockSet
server socket set
Definition: bsProxy.h:209
BsProxyClientCtl_T * ClientNew(Socket_T *pSockClient)
Create new client control structure.
static void BsProxyClientUnregister ( BsProxyClientHnd_T  hndClient)
static

Unregister a client with the server.

Okay, this is messy. A client may disconnect from the server at any time, leaving many virtual connections open. The server thread could be processing open and close requests on this zombie client while device threads could be sending responses on the same client. Hopefully, all will work out with only a few diagnotics messages printed.

Execution Context:
Server thread (main)
Parameters
hndClient

Definition at line 266 of file bsProxy.c.

References BSPROXY_VCONN_MOD_MAX, BSPROXY_VCONN_MOD_MIN, BsProxyClientStateZombie, ClientAcquire(), ClientDelete(), ClientSetState(), BsProxyVConn_T::m_hndClient, BsProxyClientCtl_T::m_pClientSock, BsProxyServerCtl_T::m_pServerRegClient, BsProxyServerCtl_T::m_pServerSockSet, BsProxyClientCtl_T::m_uRefCnt, BsProxyServerCtl_T::m_uServerRegClientCount, ServerClientHnd2Sd(), ServerGet(), VConnClose(), and VConnGet().

Referenced by BsProxyServer(), and BsProxyServerDelete().

267 {
268  BsProxyServerCtl_T *pServer;
269  BsProxyClientCtl_T *pClient;
270  BsVConnHnd_T hndVConn;
271  BsProxyVConn_T *pVConn;
272 
273  //
274  // Lock the client.
275  //
276  if( (pClient = ClientAcquire(hndClient)) == NULL )
277  {
278  return;
279  }
280 
281  // mark client zombie state (stop thread actions on this client)
283 
284  // get the server instance
285  pServer = ServerGet();
286 
287  //
288  // Loop through the device virtual connections, closing all opened connections
289  // associated with this client.
290  //
291  for(hndVConn=BSPROXY_VCONN_MOD_MIN;
292  hndVConn<=BSPROXY_VCONN_MOD_MAX;
293  ++hndVConn)
294  {
295  if( (pVConn = VConnGet(hndVConn)) != NULL )
296  {
297  // pointers point to the same client allocated object
298  if( pVConn->m_hndClient == hndClient )
299  {
300  VConnClose(hndClient, hndVConn);
301  pClient->m_uRefCnt--;
302  }
303  }
304  }
305 
306  //
307  // Remove the client from server reqistered set.
308  //
309  SockSetRemove(pServer->m_pServerSockSet, pClient->m_pClientSock);
310  pServer->m_pServerRegClient[ServerClientHnd2Sd(hndClient)] = NULL;
311  pServer->m_uServerRegClientCount--;
312 
313  //
314  // Now delete the client (don't need to release since the client no longer
315  // exists).
316  //
317  ClientDelete(pClient);
318 }
BsProxyClientCtl_T * ClientAcquire(BsProxyClientHnd_T hndClient)
Acquire client, locking it from other threads.
BsProxyClientCtl_T * m_pServerRegClient[256]
registered clients
Definition: bsProxy.h:212
uint_t m_uServerRegClientCount
num of reg. clients
Definition: bsProxy.h:211
Socket_T * m_pClientSock
client opened TCP socket
Definition: bsProxy.h:196
#define BSPROXY_VCONN_MOD_MIN
minimum module-specific handle value
Definition: BotSense.h:141
INLINE_IN_H BsProxyServerCtl_T * ServerGet()
Get the <b><i>BotSense</i></b> server.
Definition: bsProxy.h:475
#define BSPROXY_VCONN_MOD_MAX
maximum module-specific handle value
Definition: BotSense.h:142
int VConnClose(BsProxyClientHnd_T hndClient, BsVConnHnd_T hndVConn)
Close the virtual connection.
Definition: bsProxyVConn.c:478
INLINE_IN_H int ServerClientHnd2Sd(BsProxyClientHnd_T hndClient)
Convert the <b><i>BotSense</i></b> server client handle to client socket descriptor.
Definition: bsProxy.h:521
disconnected or fatal, not deleted
Definition: bsProxy.h:186
SockSet_T * m_pServerSockSet
server socket set
Definition: bsProxy.h:209
BsProxyClientHnd_T m_hndClient
proxied client handle
Definition: bsProxy.h:224
uint_t m_uRefCnt
vconn ref count for this client
Definition: bsProxy.h:198
BsProxyVConn_T * VConnGet(BsVConnHnd_T hndVConn)
Get the virtual connection entry associated with the handle.
Definition: bsProxyVConn.c:248
void ClientSetState(BsProxyClientCtl_T *pClient, BsProxyClientState_T eNewState)
Set client&#39;s state.
void ClientDelete(BsProxyClientCtl_T *pClient)
Delete a client with the server.
int BsVConnHnd_T
virtual connection handle type
Definition: BotSense.h:151
static void BsProxyDispatch ( BsProxyClientHnd_T  hndClient,
BsProxyMsgHdr_T pMsgHdr,
byte_t  bufReq[] 
)
static

Dispatch client request.

The client request is queued in the appropriate service thread.

Note
This dispatcher owns the allocated message buffer until it is successfully queue.
Parameters
hndClient

Definition at line 423 of file bsProxy.c.

References BS_ECODE_BAD_VCONN_HND, BS_ECODE_NO_RSRC, BS_ECODE_NO_VCONN, BSPROXY_CHK_VCONN_HND, BSPROXY_SEND_ERROR_RSP, BsProxyMsgHdr_T::m_hdrBodyLen, BsProxyMsgHdr_T::m_hdrMsgId, BsProxyMsgHdr_T::m_hdrTid, BsProxyMsgHdr_T::m_hdrVConn, BsProxyVConn_T::m_pThCtl, ThQueue(), VConnAcquire(), and VConnRelease().

Referenced by BsProxyServer().

426 {
427  BsProxyVConn_T *pVConn;
428  BsVConnHnd_T hndVConn;
429  BsTid_T uTid;
430  BsMsgId_T uMsgId;
431  int rc;
432 
433  hndVConn= (BsVConnHnd_T)pMsgHdr->m_hdrVConn;
434  uTid = (BsTid_T)pMsgHdr->m_hdrTid;
435  uMsgId = (BsMsgId_T)pMsgHdr->m_hdrMsgId;
436 
437  //
438  // Check if handle is valid.
439  //
440  if( !BSPROXY_CHK_VCONN_HND(hndVConn) )
441  {
442  delete(bufReq);
443  BSPROXY_SEND_ERROR_RSP(hndClient, hndVConn, uTid,
444  BS_ECODE_BAD_VCONN_HND, "VConn=%d", hndVConn);
445  return;
446  }
447 
448  //
449  // Lock the virtual connection.
450  //
451  else if( (pVConn = VConnAcquire(hndVConn)) == NULL )
452  {
453  delete(bufReq);
454  BSPROXY_SEND_ERROR_RSP(hndClient, hndVConn, uTid,
455  BS_ECODE_NO_VCONN, "VConn=%d", hndVConn);
456  return;
457  }
458 
459  //
460  // Queue the request
461  //
462  else
463  {
464  rc = ThQueue(pVConn->m_pThCtl,
465  hndClient, hndVConn, uTid, uMsgId,
466  bufReq, (size_t)pMsgHdr->m_hdrBodyLen);
467 
468  // release the virtual connection
469  VConnRelease(hndVConn);
470 
471  if( rc < 0 )
472  {
473  delete(bufReq);
474  BSPROXY_SEND_ERROR_RSP(hndClient, hndVConn, uTid,
475  BS_ECODE_NO_RSRC, "MsgId=%u", uMsgId);
476  }
477  }
478 }
uint_t BsMsgId_T
client message id type [0-64k].
Definition: BotSense.h:188
void VConnRelease(BsVConnHnd_T hndVConn)
Release the locked virtual client.
Definition: bsProxyVConn.c:585
uint_t BsTid_T
client transaction id type [0-255].
Definition: BotSense.h:172
BsProxyThCtl_T * m_pThCtl
service thread
Definition: bsProxy.h:225
#define BS_ECODE_BAD_VCONN_HND
bad virtual connection handle
Definition: BotSense.h:79
BsProxyVConn_T * VConnAcquire(BsVConnHnd_T hndVConn)
Acquire virtual connection, locking it from other threads.
Definition: bsProxyVConn.c:552
ushort_t m_hdrBodyLen
message body length
Definition: BotSense.h:284
#define BSPROXY_SEND_ERROR_RSP(hndClient, hndVConn, uTid, ecode, efmt,...)
Log <b><i>BotSense</i></b> Error and Send Error Response.
Definition: bsProxy.h:330
ushort_t m_hdrMsgId
message id (vConnection unique)
Definition: BotSense.h:283
#define BS_ECODE_NO_RSRC
no resource available
Definition: BotSense.h:85
#define BSPROXY_CHK_VCONN_HND(hndVConn)
Definition: bsProxy.h:428
int ThQueue(BsProxyThCtl_T *pThCtl, BsProxyClientHnd_T hndClient, BsVConnHnd_T hndVConn, BsTid_T uTid, BsMsgId_T uMsgId, byte_t bufReq[], size_t uReqLen)
Queue a request for the given service thread.
byte_t m_hdrTid
transaction id
Definition: BotSense.h:281
#define BS_ECODE_NO_VCONN
virtual connection not found
Definition: BotSense.h:80
byte_t m_hdrVConn
virtual connection handle (server unique)
Definition: BotSense.h:282
int BsVConnHnd_T
virtual connection handle type
Definition: BotSense.h:151
static int BsProxyServer ( BsProxyServerCtl_T pServer)
static

Server mainloop.

Processes all client registrations, requests, and unregistrations.

Parameters
pServer

Definition at line 489 of file bsProxy.c.

References BS_ECODE_GEN, BS_ECODE_INTERNAL, BS_ECODE_SERVER_BAD_CLIENT, BS_ECODE_SERVER_CONN_DENY, BS_OK, BSPROXY_FD_SETSIZE, BSPROXY_REG_CLIENT_MAX, BSPROXY_TUNE_T_SELECT, BsProxyClientRegister(), BsProxyClientUnregister(), BsProxyDispatch(), ClientHasName(), ClientRecvReq(), BsProxyServerCtl_T::m_pServerSockListener, BsProxyServerCtl_T::m_pServerSockSet, BsProxyServerCtl_T::m_uServerRegClientCount, SERVER_LOG_ERROR, ServerClientSd2Hnd(), ServerGetClient(), ServerHasName(), and ServerHasPort().

Referenced by main().

490 {
491  struct timeval tvSelect; // select() timeout
492  Socket_T *pSockClient; // new client socket
493  BsProxyClientCtl_T *pClient; // client
494  Socket_T *pSock; // working socket
495  SockSetIter_T iterSockSet; // socket set iterator
496  int nCntSd; // number of active sockets
497  int sdListener; // socket descriptor
498  int sd; // socket descriptor
499  BsProxyClientHnd_T hndClient; // client handle
500  int nMsgLen; // message length/return code
501  BsProxyMsgHdr_T msgHdr; // request message header
502  byte_t *pBuf; // allocated message body
503 
504  LOGDIAG1("%s: Listening on interface %d", ServerHasName(), ServerHasPort());
505 
506  sdListener = SocketAttrGetSd(pServer->m_pServerSockListener);
507 
508  tvSelect.tv_sec = BSPROXY_TUNE_T_SELECT / 1000000;
509  tvSelect.tv_usec = BSPROXY_TUNE_T_SELECT % 1000000;
510 
511  //
512  // Loop forever for client events.
513  //
514  while( true )
515  {
516  // block w/o timout on select() with active sockets
517  nCntSd = SockSetSelect(pServer->m_pServerSockSet, &tvSelect);
518 
519  //
520  // One or more clients I/O operations are available.
521  //
522  if( nCntSd > 0 )
523  {
524  //
525  // Iterate through read events.
526  //
527  for(pSock=SockSetIterFirst(pServer->m_pServerSockSet,
528  SOCK_SET_SELECTED, SOCK_IO_READ,
529  &iterSockSet);
530  pSock!=NULL;
531  pSock=SockSetIterNext(&iterSockSet))
532  {
533  // socket descriptor
534  sd = SocketAttrGetSd(pSock);
535 
536  //
537  // New bsProxy client.
538  //
539  if( sd == sdListener )
540  {
541  // accept new, non-blocking connection
542  pSockClient = SocketAccept(pServer->m_pServerSockListener, true);
543 
544  if( pSockClient == NULL )
545  {
546  SERVER_LOG_ERROR(BS_ECODE_GEN, "accept() failed.");
547  return -BS_ECODE_GEN;
548  }
549 
550  // maximum number of clients exceeded
552  (sd >= BSPROXY_FD_SETSIZE) )
553  {
555  "%s: Connection denied, maximum %d clients are "
556  "already registered.",
557  SocketAttrGetRemoteName(pSockClient), BSPROXY_REG_CLIENT_MAX);
558  SocketClose(pSockClient);
559  SocketDelete(pSockClient);
560  }
561 
562  // register accepted client with this server
563  else
564  {
565  hndClient = BsProxyClientRegister(pSockClient);
566  LOGDIAG1("%s: %s: Connection accepted, client registered.",
567  ServerHasName(), ClientHasName(hndClient));
568  LOGDIAG2("%s: %u registered clients.",
570  }
571  }
572 
573  //
574  // A registered bsProxy client sent a request.
575  //
576  else
577  {
578  // map socket descriptor to handle
579  hndClient = ServerClientSd2Hnd(sd);
580 
581  // get the (unlocked) client
582  pClient = ServerGetClient(hndClient);
583 
584  if( pClient == NULL )
585  {
587  "%d: No registered client for select().", sd);
588  close(sd);
589  continue;
590  }
591 
592  // receive client request
593  nMsgLen = ClientRecvReq(sd, &msgHdr, &pBuf);
594 
595  // unrecoverable connection error or client has disconnected
596  if( nMsgLen <= 0 )
597  {
598  LOGDIAG1("%s: %s: Connnection closed, client unregistered.",
599  ServerHasName(), ClientHasName(hndClient));
600  BsProxyClientUnregister(hndClient);
601  delete(pBuf);
602  LOGDIAG2("%s: %u registered clients.",
604  }
605 
606  // dispatch the client request
607  else if( nMsgLen > 0 )
608  {
609  BsProxyDispatch(hndClient, &msgHdr, pBuf);
610  }
611  }
612  }
613 
614  //
615  // Clear any write events. For now, nothing to do.
616  //
617  for(pSock=SockSetIterFirst(pServer->m_pServerSockSet,
618  SOCK_SET_SELECTED, SOCK_IO_WRITE,
619  &iterSockSet);
620  pSock!=NULL;
621  pSock=SockSetIterNext(&iterSockSet))
622  {
623  sd = SocketAttrGetSd(pSock);
624  }
625  }
626 
627  //
628  // Timed out. Check client connections.
629  //
630  // Note: This is a sanity check. When a client disconnects, typically a
631  // read event with zero bytes will occur. The select() will detect
632  // this event and will be processed in the above code.
633  //
634  else if( nCntSd == 0 )
635  {
636  for(pSock=SockSetIterFirst(pServer->m_pServerSockSet,
637  SOCK_SET_ACTIVE, SOCK_IO_READ,
638  &iterSockSet);
639  pSock!=NULL;
640  pSock=SockSetIterNext(&iterSockSet))
641  {
642  // socket descriptor
643  sd = SocketAttrGetSd(pSock);
644 
645  if( (sd != sdListener) && SocketStateIsErrored(pSock) )
646  {
647  hndClient = ServerClientSd2Hnd(sd);
648  LOGDIAG1("%s: %s: Connnection closed, client unregistered.",
649  ServerHasName(), ClientHasName(hndClient));
650  BsProxyClientUnregister(hndClient);
651  LOGDIAG2("%s: %u registered clients.",
653  }
654  }
655  }
656 
657  //
658  // Internal error.
659  //
660  else
661  {
662  SERVER_LOG_ERROR(BS_ECODE_INTERNAL, "select() failed.");
663  return -BS_ECODE_INTERNAL;
664  }
665  }
666 
667  return BS_OK;
668 }
int ClientRecvReq(BsProxyClientHnd_T hndClient, BsProxyMsgHdr_T *pMsgHdr, byte_t **addrBuf)
Receive a request message from client.
Socket_T * m_pServerSockListener
server listener socket
Definition: bsProxy.h:210
#define BS_ECODE_GEN
general, unspecified error
Definition: BotSense.h:68
static BsProxyClientHnd_T BsProxyClientRegister(Socket_T *pSockClient)
Register a new client with the server.
Definition: bsProxy.c:224
uint_t m_uServerRegClientCount
num of reg. clients
Definition: bsProxy.h:211
static void BsProxyDispatch(BsProxyClientHnd_T hndClient, BsProxyMsgHdr_T *pMsgHdr, byte_t bufReq[])
Dispatch client request.
Definition: bsProxy.c:423
static void BsProxyClientUnregister(BsProxyClientHnd_T hndClient)
Unregister a client with the server.
Definition: bsProxy.c:266
INLINE_IN_H int ServerHasPort()
Get the <b><i>BotSense</i></b> server&#39;s listening port.
Definition: bsProxy.h:505
#define BSPROXY_FD_SETSIZE
server socket set size
Definition: bsProxy.h:103
INLINE_IN_H const char * ServerHasName()
Get the <b><i>BotSense</i></b> server&#39;s official name.
Definition: bsProxy.h:485
#define BS_OK
not an error, success
Definition: BotSense.h:66
int BsProxyClientHnd_T
bsProxy server client handle
Definition: bsProxy.h:114
INLINE_IN_H BsProxyClientHnd_T ServerClientSd2Hnd(int sd)
Convert the <b><i>BotSense</i></b> server client socket descriptor to client handle.
Definition: bsProxy.h:537
#define BSPROXY_REG_CLIENT_MAX
max number of simultaneous clients
Definition: BotSense.h:121
#define BSPROXY_TUNE_T_SELECT
5.0s send select time out
Definition: bsProxy.h:96
SockSet_T * m_pServerSockSet
server socket set
Definition: bsProxy.h:209
#define SERVER_LOG_ERROR(ecode, efmt,...)
Log Proxy Server Specific Error.
Definition: bsProxy.c:159
INLINE_IN_H BsProxyClientCtl_T * ServerGetClient(BsProxyClientHnd_T hndClient)
Get the <b><i>BotSense</i></b> server client.
Definition: bsProxy.h:551
BotSense Proxy Message Header Structure.
Definition: BotSense.h:278
#define BS_ECODE_SERVER_BAD_CLIENT
server detected bad client
Definition: BotSense.h:91
#define BS_ECODE_INTERNAL
internal error (bug)
Definition: BotSense.h:93
#define BS_ECODE_SERVER_CONN_DENY
server denied connection
Definition: BotSense.h:90
INLINE_IN_H const char * ClientHasName(BsProxyClientHnd_T hndClient)
Get the <b><i>BotSense</i></b> client official name.
Definition: bsProxy.h:588
static void BsProxyServerDelete ( BsProxyServerCtl_T pServer)
static

Delete a server control block.

Parameters
pServer

Definition at line 325 of file bsProxy.c.

References BSPROXY_FD_SETSIZE, BsProxyClientUnregister(), BsProxyServerCtl_T::m_mutex, BsProxyServerCtl_T::m_pServerRegClient, BsProxyServerCtl_T::m_pServerSockListener, BsProxyServerCtl_T::m_pServerSockSet, BsProxyServerCtl_T::m_sServerName, and ServerClientHnd2Sd().

Referenced by BsProxyServerNew().

326 {
327  BsProxyClientHnd_T hndClient;
328 
329  if( pServer != NULL )
330  {
331  for(hndClient=0; hndClient<BSPROXY_FD_SETSIZE; ++hndClient)
332  {
333  if( pServer->m_pServerRegClient[ServerClientHnd2Sd(hndClient)] != NULL )
334  {
335  BsProxyClientUnregister(hndClient);
336  }
337  }
338  SocketDelete(pServer->m_pServerSockListener);
339  SockSetDelete(pServer->m_pServerSockSet);
340  delete((char *)pServer->m_sServerName);
341  pthread_mutex_destroy(&pServer->m_mutex);
342  delete(pServer);
343  }
344 }
Socket_T * m_pServerSockListener
server listener socket
Definition: bsProxy.h:210
BsProxyClientCtl_T * m_pServerRegClient[256]
registered clients
Definition: bsProxy.h:212
static void BsProxyClientUnregister(BsProxyClientHnd_T hndClient)
Unregister a client with the server.
Definition: bsProxy.c:266
#define BSPROXY_FD_SETSIZE
server socket set size
Definition: bsProxy.h:103
int BsProxyClientHnd_T
bsProxy server client handle
Definition: bsProxy.h:114
INLINE_IN_H int ServerClientHnd2Sd(BsProxyClientHnd_T hndClient)
Convert the <b><i>BotSense</i></b> server client handle to client socket descriptor.
Definition: bsProxy.h:521
const char * m_sServerName
server&#39;s name
Definition: bsProxy.h:207
pthread_mutex_t m_mutex
server mutex lock
Definition: bsProxy.h:214
SockSet_T * m_pServerSockSet
server socket set
Definition: bsProxy.h:209
static BsProxyServerCtl_T* BsProxyServerNew ( const char *  sPrefix,
const char *  sLocalHostName,
int  nPort 
)
static

Create new server control block.

Parameters
sPrefixServer name prefix.
sLocalHostNameLocal host interface to bind to.
nPortServer listener TCP port number.
Returns
Returns a newly allocated and intialized server control block.

Definition at line 355 of file bsProxy.c.

References BS_ECODE_INTERNAL, BS_ECODE_SYS, BS_OK, BsProxyServerDelete(), BsProxyServerCtl_T::m_mutex, BsProxyServerCtl_T::m_nServerPort, BsProxyServerCtl_T::m_pServerSockListener, BsProxyServerCtl_T::m_pServerSockSet, BsProxyServerCtl_T::m_sServerName, and BsProxyServerCtl_T::m_uServerRegClientCount.

Referenced by main().

358 {
359  BsProxyServerCtl_T *pServer;
360  char *bufName;
361  int rc = BS_OK;
362 
363  bufName = NEWSTR(strlen(sPrefix)+16);
364  sprintf(bufName, "%s_%d", sPrefix, nPort);
365 
366  pServer = NEW(BsProxyServerCtl_T);
367  pServer->m_sServerName = bufName;
368  pServer->m_nServerPort = nPort;
369  pServer->m_pServerSockSet = SockSetNew();
370  pServer->m_pServerSockListener = SocketOpenTcpListener(nPort,
371  sLocalHostName);
372  pServer->m_uServerRegClientCount = 0;
373 
374  // create server mutex
375  pthread_mutex_init(&pServer->m_mutex, NULL);
376 
377  if( pServer->m_pServerSockListener == NULL )
378  {
379  LOGERROR("%s: Failed to open server listener socket.",
380  pServer->m_sServerName);
381  rc = -BS_ECODE_SYS;
382  }
383 
384  else
385  {
386  rc = SockSetAdd(pServer->m_pServerSockSet, // server client socket set
387  pServer->m_pServerSockListener, // server listener socket
388  true, // add listener to active read
389  true); // add listener to active write
390 
391  if( rc < 0 )
392  {
393  LOGERROR("%s: Failed to add server listener socket to set.",
394  pServer->m_sServerName);
395  rc = -BS_ECODE_INTERNAL;
396  }
397  }
398 
399  //
400  // Error clean up.
401  //
402  if( rc < 0 )
403  {
404  BsProxyServerDelete(pServer);
405  pServer = NULL;
406  }
407 
408  return pServer;
409 }
Socket_T * m_pServerSockListener
server listener socket
Definition: bsProxy.h:210
uint_t m_uServerRegClientCount
num of reg. clients
Definition: bsProxy.h:211
static void BsProxyServerDelete(BsProxyServerCtl_T *pServer)
Delete a server control block.
Definition: bsProxy.c:325
#define BS_OK
not an error, success
Definition: BotSense.h:66
#define BS_ECODE_SYS
system (errno) error
Definition: BotSense.h:92
const char * m_sServerName
server&#39;s name
Definition: bsProxy.h:207
pthread_mutex_t m_mutex
server mutex lock
Definition: bsProxy.h:214
SockSet_T * m_pServerSockSet
server socket set
Definition: bsProxy.h:209
#define BS_ECODE_INTERNAL
internal error (bug)
Definition: BotSense.h:93
int m_nServerPort
server&#39;s listener port
Definition: bsProxy.h:208
int main ( int  argc,
char *  argv[] 
)

bsProxy main()

Parameters
argcCount of command-line options and arguments.
argvArray of command-line options and arguments.
Returns
Exit value.

Definition at line 841 of file bsProxy.c.

References Argv0, BS_OK, BsOptDListLibPath, BsOptDListListenIF, BsProxyServer(), BsProxyServerNew(), ClientOneTimeInit(), BsProxyListenIF_T::m_nPort, BsProxyListenIF_T::m_sAddr, MainInit(), ModOneTimeInit(), PkgInfo, ServerHasName(), ThOneTimeInit(), VConnOneTimeInit(), and VConnOpenServer().

842 {
843  BsProxyListenIF_T *pIF;
844  int rc;
845 
846  // Process command-line, environment, and configuration file data.
847  MainInit(argc, argv);
848 
849  LOGDIAG1("%s v%s %s", Argv0, PkgInfo.m_sPkgVersion, PkgInfo.m_sPkgTimeStamp);
850 
851  // Interface module control one-time initialization.
853 
854  // Service thread control one-time initialization.
855  ThOneTimeInit();
856 
857  // Client control one-time initialization.
859 
860  // Virtual connection control one-time initialization.
862 
863  //
864  // FUTURE: If multiple listen interfaces are specified, then fork extra
865  // copies of bsProxy here.
866  //
867 
868  //
869  // Create a server control block to listen on the first interface.
870  //
871  pIF = (BsProxyListenIF_T *)DListStrGetDataAt(BsOptDListListenIF, 0);
873 
874  if( BsServerCtl == NULL )
875  {
876  return EC_ERROR;
877  }
878 
879  //
880  // Open the server-terminated virtual connection. The server service thread
881  // is started.
882  //
883  if( (rc = VConnOpenServer()) < 0 )
884  {
885  return EC_ERROR;
886  }
887 
888  LOGDIAG1("BotSense IP Proxy Server %s started", ServerHasName());
889 
890  // Run.
892 
893  return rc == BS_OK? 0: EC_ERROR;
894 }
static BsProxyServerCtl_T * BsProxyServerNew(const char *sPrefix, const char *sLocalHostName, int nPort)
Create new server control block.
Definition: bsProxy.c:355
static int BsProxyServer(BsProxyServerCtl_T *pServer)
Server mainloop.
Definition: bsProxy.c:489
int VConnOpenServer()
Open special server virtual connection.
Definition: bsProxyVConn.c:265
INLINE_IN_H const char * ServerHasName()
Get the <b><i>BotSense</i></b> server&#39;s official name.
Definition: bsProxy.h:485
#define BS_OK
not an error, success
Definition: BotSense.h:66
static DListStr_T * BsOptDListLibPath
list of lib search paths
Definition: bsProxy.c:86
void VConnOneTimeInit()
The bsProxy virtual connections one-time initialization.
Definition: bsProxyVConn.c:165
static const PkgInfo_T PkgInfo
Definition: version.h:45
static void MainInit(int argc, char *argv[])
Main initialization.
Definition: bsProxy.c:779
static DListVoid_T * BsOptDListListenIF
list of listen i/f&#39;s
Definition: bsProxy.c:85
void ClientOneTimeInit()
The <b><i>BotSense</i></b> bsProxy server one-time client control initialization.
const char * Argv0
command base name
Definition: bsProxy.c:79
BsProxyServerCtl_T * BsServerCtl
The server control block.
Definition: bsProxy.c:831
int m_nPort
listen port number
Definition: bsProxy.h:249
void ThOneTimeInit()
The service thread one-time global initialization.
void ModOneTimeInit(DListStr_T *pDListLibPath)
The bsProxy interface module handling one-time initialization.
Definition: bsProxyMod.c:1013
char * m_sAddr
listen local address or hostname
Definition: bsProxy.h:248
static void MainInit ( int  argc,
char *  argv[] 
)
static

Main initialization.

Parses command-line options and arguments and environment variables to configure the BotsSense Proxy server.

Parameters
argcCount of command-line options and arguments.
argvArray of command-line options and arguments.

Definition at line 779 of file bsProxy.c.

References Argv0, BsOptDListLibPath, BsOptDListListenIF, BsOptListenIFDft, BSPROXY_LISTEN_PORT_DFT, BsProxyOptsInfo, BsProxyPgmInfo, BsProxyListenIF_T::m_nPort, BsProxyListenIF_T::m_sAddr, MainCfg(), MainEnv(), and PkgInfo.

Referenced by main().

780 {
781  BsProxyListenIF_T *pIF;
782  char buf[32];
783 
784  Argv0 = basename(argv[0]);
785 
786  sprintf_s(buf, sizeof(buf), ":%d", BSPROXY_LISTEN_PORT_DFT);
787  BsOptListenIFDft = new_strdup(buf);
788  BsOptDListListenIF = DListVoidNew(NULL, NULL);
789  BsOptDListLibPath = DListStrNew(NULL, NULL);
790 
791  // Parse input options
792  argv = OptsGet(Argv0, &PkgInfo, &BsProxyPgmInfo,
793  BsProxyOptsInfo, true, &argc, argv);
794 
795  // The environment
796  MainEnv();
797 
798  // The configuration file(s)
799  MainCfg();
800 
801  //
802  // Final checks and tweaks.
803  //
804  if( DListVoidCount(BsOptDListListenIF) == 0 )
805  {
806  pIF = NEW(BsProxyListenIF_T);
807  pIF->m_sAddr = NULL;
809  DListVoidAppend(BsOptDListListenIF, pIF);
810  }
811 
812  if( DListVoidCount(BsOptDListListenIF) > 1 )
813  {
814  LOGDIAG2("Warning: Currently only one listen interface is supported. "
815  "First I/F will be used.");
816  }
817 }
#define BSPROXY_LISTEN_PORT_DFT
default bsProxy passive socket
Definition: BotSense.h:120
static void MainEnv()
Get and set environment.
Definition: bsProxy.c:673
static DListStr_T * BsOptDListLibPath
list of lib search paths
Definition: bsProxy.c:86
static void MainCfg()
Get configuration.
Definition: bsProxy.c:680
static const PkgInfo_T PkgInfo
Definition: version.h:45
static OptsInfo_T BsProxyOptsInfo[]
Definition: bsProxy.c:118
static DListVoid_T * BsOptDListListenIF
list of listen i/f&#39;s
Definition: bsProxy.c:85
const char * Argv0
command base name
Definition: bsProxy.c:79
int m_nPort
listen port number
Definition: bsProxy.h:249
static char * BsOptListenIFDft
default listen interface
Definition: bsProxy.c:84
static OptsPgmInfo_T BsProxyPgmInfo
Definition: bsProxy.c:99
char * m_sAddr
listen local address or hostname
Definition: bsProxy.h:248
static int OptsCvtArgInterface ( const char *  argv0,
const char *  sOptName,
char *  optarg,
void *  pOptVal 
)
static

Convert command-line listen interface option string to network name/number and port number.

Option Argument Syntax:
[addr][:port]
Parameters
argv0Command name.
sOptNameOption name.
optargParsed option argument to convert (optional).
[out]pOptValPointer to converted option value (not used).
Exceptions
OptsInvalid()
Returns
If returns, then returns BS_OK.

Definition at line 700 of file bsProxy.c.

References Argv0, BS_OK, BsOptDListListenIF, BSPROXY_LISTEN_PORT_DFT, BsProxyListenIF_T::m_nPort, and BsProxyListenIF_T::m_sAddr.

704 {
705  char *sInet;
706  char *sSepField;
707  char *sPort;
708  int nPort;
709  BsProxyListenIF_T *pIF;
710 
711  sInet = new_strdup(optarg);
712 
713  sSepField = strchr(sInet, ':');
714 
715  if( sSepField )
716  {
717  *sSepField = 0;
718  sPort = sSepField+1;
719  nPort = (int)atol(sPort);
720  if( (nPort <= 0) || (nPort > 0xffff) )
721  {
722  OptsInvalid(Argv0, "'%s': Invalid '%s' argument port value.",
723  optarg, sOptName);
724  }
725  }
726  else
727  {
728  nPort = BSPROXY_LISTEN_PORT_DFT;
729  }
730 
731  if( *sInet == 0 )
732  {
733  delete(sInet);
734  sInet = NULL;
735  }
736 
737  pIF = NEW(BsProxyListenIF_T);
738  pIF->m_sAddr = sInet;
739  pIF->m_nPort = nPort;
740  DListVoidAppend(BsOptDListListenIF, pIF);
741 
742  return BS_OK;
743 }
#define BSPROXY_LISTEN_PORT_DFT
default bsProxy passive socket
Definition: BotSense.h:120
#define BS_OK
not an error, success
Definition: BotSense.h:66
static DListVoid_T * BsOptDListListenIF
list of listen i/f&#39;s
Definition: bsProxy.c:85
const char * Argv0
command base name
Definition: bsProxy.c:79
int m_nPort
listen port number
Definition: bsProxy.h:249
char * m_sAddr
listen local address or hostname
Definition: bsProxy.h:248
static int OptsCvtArgLibPath ( const char *  argv0,
const char *  sOptName,
char *  optarg,
void *  pOptVal 
)
static

Append command-line library search path option to list of search paths.

Option Argument Syntax:
dir
Parameters
argv0Command name.
sOptNameOption name.
optargParsed option argument to convert (optional).
[out]pOptValPointer to converted option value (not used).
Exceptions
OptsInvalid()
Returns
If returns, then returns BS_OK.

Definition at line 761 of file bsProxy.c.

References BS_OK, and BsOptDListLibPath.

765 {
766  DListVoidAppend(BsOptDListLibPath, optarg);
767  return BS_OK;
768 }
#define BS_OK
not an error, success
Definition: BotSense.h:66
static DListStr_T * BsOptDListLibPath
list of lib search paths
Definition: bsProxy.c:86
static bool_t ServerTryLock ( )
inlinestatic

Try to lock global mutual exclusion.

Returns
Returns true if lock is acquired. Otherwise returns false if mutex already locked.

Definition at line 212 of file bsProxy.c.

References BsServerCtl, and BsProxyServerCtl_T::m_mutex.

213 {
214  return pthread_mutex_trylock(&BsServerCtl->m_mutex) == 0? true: false;
215 }
pthread_mutex_t m_mutex
server mutex lock
Definition: bsProxy.h:214
BsProxyServerCtl_T * BsServerCtl
The server control block.
Definition: bsProxy.c:831

Variable Documentation

OptsInfo_T BsProxyOptsInfo[]
static

Command Line Options Information.

Definition at line 118 of file bsProxy.c.

Referenced by MainInit().

OptsPgmInfo_T BsProxyPgmInfo
static
Initial value:
=
{
.synopsis = "BotSense IP Proxy Server.",
.long_desc =
"The BotSense Proxy Server (%P) provides an IP interace to any proxied "
"(pseudo) device. %P is multi-threaded by device to optimize client "
"responsiveness. For each (pseudo) device, there must exist a dynamically "
"linked library that %P will load as needed, plus a client side library. "
"The two libraries typically communicate through a defined set of NetMsgs "
"network messages. The Message Exchange Patterns (MEP) support by %P "
"are client request - server response and server output streaming "
"(e.g. video).\n"
"\n"
"A wide range of RoadNarrows support robots use %P."
}

Program Information

Definition at line 99 of file bsProxy.c.

Referenced by MainInit().

BsProxyServerCtl_T* BsServerCtl

The server control block.

Note
In a future bsProxy implementation, multiple server instance threads could be running in the same application. But currently there is only one server per application instance.

Definition at line 831 of file bsProxy.c.

Referenced by ServerGet(), ServerLock(), ServerTryLock(), and ServerUnlock().