libcyberradio  22.01.24
ClientSocket.cpp
1 /***************************************************************************
2  * \file ClientSocket.cpp
3  *
4  * \brief NDR651 client socket class.
5  *
6  * \author NH
7  * \copyright Copyright (c) 2015-2021 CyberRadio Solutions, Inc.
8  *
9  */
10 
11 #include "LibCyberRadio/Common/Pythonesque.h"
12 #include "LibCyberRadio/NDR651/ClientSocket.h"
13 
14 
15 namespace LibCyberRadio
16 {
17  namespace NDR651
18  {
19  ClientSocket::ClientSocket(const std::string& hostname, unsigned int port,
20  bool debug) {
21  // TODO Auto-generated constructor stub
22  _serverHostname = hostname;
23  _serverPort = port;
24  _debug = debug;
25  }
26 
28  // TODO Auto-generated destructor stub
29  disconnect();
30  }
31 
33  struct sockaddr_in serv_addr;
34  struct hostent *server;
35  BasicStringList cmdVec, rspVec;
36  BasicStringList::iterator cmd, rsp;
37  bool cmdRspError = false;
38 
39  //std::cout << "Client Connecting...";
40 
41  server = gethostbyname(_serverHostname.c_str());
42  _sockfd = socket(AF_INET, SOCK_STREAM, 0);
43  bzero((char *) &serv_addr, sizeof(serv_addr));
44  serv_addr.sin_family = AF_INET;
45  bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
46  serv_addr.sin_port = htons(_serverPort);
47  if (connect(_sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
48  //std::cout << "ERROR?";
49  } else {
50  //std::cout << "success!";
51  _connected = true;
52  }
53  //std::cout << std::endl;
54 
55  FD_ZERO(&set);
56  FD_SET(_sockfd, &set);
57 
58  // Commenting this out because I make one TCP connection per command --JVM
59  //cmdVec.push_back(std::string("\n"));
60  //cmdVec.push_back(std::string("*IDN?\n"));
61  //cmdVec.push_back(std::string("VER?\n"));
62  //cmdVec.push_back(std::string("HREV?\n"));
63  // for (cmd=cmdVec.begin(); cmd<cmdVec.end(); cmd++) {
64  // rspVec.clear();
65  // cmdRspError |= sendCmdAndGetRsp(*cmd, rspVec, 2000, _debug);
66  // }
67 
68  // Read radio connection greeting message (but do nothing)
69  struct timeval tout;
70  tout.tv_sec = 2;
71  tout.tv_usec = 0;
72  if (select(FD_SETSIZE, &set, NULL, NULL, &tout)>0)
73  {
74  _clearRxBuff();
75  _tcpRx();
76  }
77 
78  return isConnected();
79  }
80 
82  //std::cout << std::endl << "Client disconnecting...";
83  if (isConnected()) {
84  // shutdown(_sockfd,SHUT_WR);
85  // usleep(1000);
86  // shutdown(_sockfd,SHUT_RDWR);
87  // usleep(1000);
88  close(_sockfd);
89  _connected = false;
90  //std::cout << "success!";
91  } else {
92  //std::cout << "but we weren't connected?";
93  }
94  //std::cout << std::endl;
95 
96  return !isConnected();
97  }
98 
99  bool ClientSocket::sendCmd(const std::string& cmd) {
100  if (isConnected()) {
101  return write(_sockfd, cmd.c_str(), cmd.size())!=(int)cmd.size();
102  } else {
103  return true;
104  }
105  }
106 
107  bool ClientSocket::getRsp(BasicStringList &rsp, float timeout) {
108  struct timeval tout;
109  tout.tv_sec = (long int) timeout/1000;
110  tout.tv_usec = (long int)(1000*timeout)%1000000;
111  _clearRxBuff();
112  FD_SET(_sockfd, &set);
113  if (select(FD_SETSIZE, &set, NULL, NULL, &tout)>0) {
114  _tcpRx();
115  rsp.push_back(std::string(_rxBuff));
116  return false;
117  } else {
118  return true;
119  }
120  }
121 
122  bool ClientSocket::sendCmdAndGetRsp(const std::string& cmd, BasicStringList &rsp, float timeout) {
123  return sendCmdAndGetRsp(cmd, rsp, timeout, _debug);
124  }
125 
126  bool ClientSocket::sendCmdAndGetRsp(const std::string& cmd, BasicStringList &rsp, float timeout, bool print) {
127  _trxMutex.lock();
128  unsigned int i;
129  std::string temp;
130  bool txError=false, rxError=false;
131  struct timeval tout;
132  tout.tv_sec = (long int) timeout/1000;
133  tout.tv_usec = (long int)(1000*timeout)%1000000;
134 
135  txError = sendCmd(cmd);
136  FD_SET(_sockfd, &set);
137  while((!rxError)&&((rsp.size()==0)||((rsp.size()>0)&&(rsp.back().find("OK>")==std::string::npos)))) {
138  // txRxError = getRsp(rsp, timeout);
139  if (select(FD_SETSIZE, &set, NULL, NULL, &tout)>0) {
140  _clearRxBuff();
141  _tcpRx();
142  BasicStringList x = Pythonesque::Split(std::string(_rxBuff),"\n");
143  // std::cout << "\t** Separate strings in RSP = " << x.size() << std::endl;
144  for (i=0; i<x.size(); i++) {
145  temp = Pythonesque::Strip(x.at(i));
146  if (temp.size()>0) {
147  rsp.push_back(temp);
148  }
149  // std::cout << "\t** " << i << "(" << temp.size() << ") = '" << temp << "'" << std::endl;
150  }
151  // rsp.push_back(Pythonesque::Strip( std::string(_rxBuff) ));
152  } else {
153  rxError = true;
154  }
155  }
156  _trxMutex.unlock();
157  if (print) {
158  std::cerr << "CMD = '" << Pythonesque::Strip(cmd) << "' & RSP = '" << Pythonesque::Join(rsp, "; ") << "'" << std::endl;
159  for (BasicStringList::iterator it=rsp.begin(); it<rsp.end(); it++) {
160  std::cerr << "\tRSP = '" << *it << "'" << std::endl;
161  }
162  }
163  return txError||rxError;
164  }
165  }
166 
167 }
static std::string Strip(const std::string &str, const std::string &chars=" \\\)
Strips both leading and trailing whitespace from the given string.
Definition: Pythonesque.cpp:57
bool connectToServer(void)
Connects to the server.
bool disconnect(void)
Disconnects from the server.
bool sendCmdAndGetRsp(const std::string &cmd, BasicStringList &rsp, float timeout, bool print)
Sends a command to the server and gets the response.
bool isConnected(void)
Gets whether or not the socket is connected.
Definition: ClientSocket.h:62
static BasicStringList Split(const std::string &str, const std::string &sep, int maxsplit=INT_MAX)
Splits the given string into a list of string tokens.
Definition: Pythonesque.cpp:77
bool sendCmd(const std::string &cmd)
Sends a command to the server.
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
Definition: BasicList.h:25
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
bool getRsp(BasicStringList &rsp, float timeout)
Gets a command response from the server.
static std::string Join(const BasicStringList &vec, const std::string &sep)
Joins a list of string tokens, concatenating them into a single string.
Definition: Pythonesque.cpp:98
ClientSocket(const std::string &hostname, unsigned int port, bool debug=true)
Constructs a ClientSocket object.
virtual ~ClientSocket()
Destroys a ClientSocket object.