Maintenance: fgfsclient
Ensure we don't throw during dtor. Update Whitespace.
This commit is contained in:
parent
cc2336c5fa
commit
02a299ed34
1 changed files with 126 additions and 118 deletions
|
@ -10,184 +10,192 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
const char *HOST = "localhost";
|
||||
const char* HOST = "localhost";
|
||||
const unsigned PORT = 5501;
|
||||
const int BUFLEN = 256;
|
||||
|
||||
|
||||
class FGFSSocket {
|
||||
class FGFSSocket
|
||||
{
|
||||
public:
|
||||
FGFSSocket(const char *name, unsigned port);
|
||||
~FGFSSocket();
|
||||
FGFSSocket(const char* name, unsigned port);
|
||||
~FGFSSocket();
|
||||
|
||||
int write(const char *msg, ...);
|
||||
const char *read(void);
|
||||
inline void flush(void);
|
||||
void settimeout(unsigned t) { _timeout = t; }
|
||||
int write(const char* msg, ...);
|
||||
const char* read(void);
|
||||
inline void flush(void);
|
||||
void settimeout(unsigned t) { _timeout = t; }
|
||||
|
||||
private:
|
||||
int close(void);
|
||||
int close(void);
|
||||
|
||||
int _sock;
|
||||
bool _connected;
|
||||
unsigned _timeout;
|
||||
char _buffer[BUFLEN];
|
||||
int _sock;
|
||||
bool _connected;
|
||||
unsigned _timeout;
|
||||
char _buffer[BUFLEN];
|
||||
bool _isShutdown = false;
|
||||
};
|
||||
|
||||
|
||||
FGFSSocket::FGFSSocket(const char *hostname = HOST, unsigned port = PORT) :
|
||||
_sock(-1),
|
||||
_connected(false),
|
||||
_timeout(1)
|
||||
FGFSSocket::FGFSSocket(const char* hostname = HOST, unsigned port = PORT) : _sock(-1),
|
||||
_connected(false),
|
||||
_timeout(1)
|
||||
{
|
||||
_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (_sock < 0)
|
||||
throw("FGFSSocket/socket");
|
||||
_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (_sock < 0)
|
||||
throw("FGFSSocket/socket");
|
||||
|
||||
struct hostent *hostinfo;
|
||||
hostinfo = gethostbyname(hostname);
|
||||
if (!hostinfo) {
|
||||
close();
|
||||
throw("FGFSSocket/gethostbyname: unknown host");
|
||||
}
|
||||
struct hostent* hostinfo;
|
||||
hostinfo = gethostbyname(hostname);
|
||||
if (!hostinfo) {
|
||||
close();
|
||||
throw("FGFSSocket/gethostbyname: unknown host");
|
||||
}
|
||||
|
||||
struct sockaddr_in serv_addr;
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(port);
|
||||
serv_addr.sin_addr = *(struct in_addr *)hostinfo->h_addr;
|
||||
struct sockaddr_in serv_addr;
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(port);
|
||||
serv_addr.sin_addr = *(struct in_addr*)hostinfo->h_addr;
|
||||
|
||||
if (connect(_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
|
||||
close();
|
||||
throw("FGFSSocket/connect");
|
||||
}
|
||||
_connected = true;
|
||||
try {
|
||||
write("data");
|
||||
} catch (...) {
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
if (connect(_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
|
||||
close();
|
||||
throw("FGFSSocket/connect");
|
||||
}
|
||||
_connected = true;
|
||||
try {
|
||||
write("data");
|
||||
} catch (...) {
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FGFSSocket::~FGFSSocket()
|
||||
{
|
||||
close();
|
||||
_isShutdown = true;
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
int FGFSSocket::close(void)
|
||||
{
|
||||
if (_connected)
|
||||
write("quit");
|
||||
if (_sock < 0)
|
||||
return 0;
|
||||
int ret = ::close(_sock);
|
||||
_sock = -1;
|
||||
return ret;
|
||||
if (_connected)
|
||||
write("quit");
|
||||
if (_sock < 0)
|
||||
return 0;
|
||||
int ret = ::close(_sock);
|
||||
_sock = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int FGFSSocket::write(const char *msg, ...)
|
||||
int FGFSSocket::write(const char* msg, ...)
|
||||
{
|
||||
va_list va;
|
||||
ssize_t len;
|
||||
char buf[BUFLEN];
|
||||
fd_set fd;
|
||||
struct timeval tv;
|
||||
va_list va;
|
||||
ssize_t len;
|
||||
char buf[BUFLEN];
|
||||
fd_set fd;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&fd);
|
||||
FD_SET(_sock, &fd);
|
||||
tv.tv_sec = _timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (!select(FD_SETSIZE, 0, &fd, 0, &tv))
|
||||
throw("FGFSSocket::write/select: timeout exceeded");
|
||||
FD_ZERO(&fd);
|
||||
FD_SET(_sock, &fd);
|
||||
tv.tv_sec = _timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (!select(FD_SETSIZE, 0, &fd, 0, &tv))
|
||||
if (_isShutdown) // don't throw during dtor
|
||||
std::cout << "FGFSSocket::write/select: timeout exceeded" << std::endl;
|
||||
else
|
||||
throw("FGFSSocket::write/select: timeout exceeded");
|
||||
|
||||
va_start(va, msg);
|
||||
vsnprintf(buf, BUFLEN - 2, msg, va);
|
||||
va_end(va);
|
||||
std::cout << "SEND: " << buf << std::endl;
|
||||
strcat(buf, "\015\012");
|
||||
va_start(va, msg);
|
||||
vsnprintf(buf, BUFLEN - 2, msg, va);
|
||||
va_end(va);
|
||||
std::cout << "SEND: " << buf << std::endl;
|
||||
strcat(buf, "\015\012");
|
||||
|
||||
len = ::write(_sock, buf, strlen(buf));
|
||||
if (len < 0)
|
||||
throw("FGFSSocket::write");
|
||||
return len;
|
||||
len = ::write(_sock, buf, strlen(buf));
|
||||
if (len < 0)
|
||||
if (_isShutdown) // don't throw during dtor
|
||||
std::cout << "FGFSSocket::write error" << std::endl;
|
||||
else
|
||||
throw("FGFSSocket::write");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
const char *FGFSSocket::read(void)
|
||||
const char* FGFSSocket::read(void)
|
||||
{
|
||||
char *p;
|
||||
fd_set fd;
|
||||
struct timeval tv;
|
||||
ssize_t len;
|
||||
char* p;
|
||||
fd_set fd;
|
||||
struct timeval tv;
|
||||
ssize_t len;
|
||||
|
||||
FD_ZERO(&fd);
|
||||
FD_SET(_sock, &fd);
|
||||
tv.tv_sec = _timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (!select(FD_SETSIZE, &fd, 0, 0, &tv)) {
|
||||
if (_timeout == 0)
|
||||
return 0;
|
||||
else
|
||||
throw("FGFSSocket::read/select: timeout exceeded");
|
||||
}
|
||||
FD_ZERO(&fd);
|
||||
FD_SET(_sock, &fd);
|
||||
tv.tv_sec = _timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (!select(FD_SETSIZE, &fd, 0, 0, &tv)) {
|
||||
if (_timeout == 0)
|
||||
return 0;
|
||||
else
|
||||
throw("FGFSSocket::read/select: timeout exceeded");
|
||||
}
|
||||
|
||||
len = ::read(_sock, _buffer, BUFLEN - 1);
|
||||
if (len < 0)
|
||||
throw("FGFSSocket::read/read");
|
||||
if (len == 0)
|
||||
return 0;
|
||||
len = ::read(_sock, _buffer, BUFLEN - 1);
|
||||
if (len < 0)
|
||||
throw("FGFSSocket::read/read");
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
for (p = &_buffer[len - 1]; p >= _buffer; p--)
|
||||
if (*p != '\015' && *p != '\012')
|
||||
break;
|
||||
*++p = '\0';
|
||||
return strlen(_buffer) ? _buffer : 0;
|
||||
for (p = &_buffer[len - 1]; p >= _buffer; p--)
|
||||
if (*p != '\015' && *p != '\012')
|
||||
break;
|
||||
*++p = '\0';
|
||||
return strlen(_buffer) ? _buffer : 0;
|
||||
}
|
||||
|
||||
|
||||
inline void FGFSSocket::flush(void)
|
||||
{
|
||||
int i = _timeout;
|
||||
_timeout = 0;
|
||||
while (read())
|
||||
;
|
||||
_timeout = i;
|
||||
int i = _timeout;
|
||||
_timeout = 0;
|
||||
while (read())
|
||||
;
|
||||
_timeout = i;
|
||||
}
|
||||
|
||||
|
||||
int main(const int argc, const char *argv[])
|
||||
int main(const int argc, const char* argv[])
|
||||
try {
|
||||
const char *hostname = argc > 1 ? argv[1] : "localhost";
|
||||
int port = argc > 2 ? atoi(argv[2]) : 5501;
|
||||
const char* hostname = argc > 1 ? argv[1] : "localhost";
|
||||
int port = argc > 2 ? atoi(argv[2]) : 5501;
|
||||
|
||||
FGFSSocket f(hostname, port);
|
||||
f.flush();
|
||||
f.write("set /controls/engines/engine[%d]/throttle %lg", 0, 1.0);
|
||||
f.write("set /controls/engines/engine[%d]/throttle %lg", 1, 1.0);
|
||||
f.write("get /sim/aircraft");
|
||||
const char *p = f.read();
|
||||
if (p)
|
||||
std::cout << "RECV: " << p << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
FGFSSocket f(hostname, port);
|
||||
f.flush();
|
||||
f.write("set /controls/engines/engine[%d]/throttle %lg", 0, 1.0);
|
||||
f.write("set /controls/engines/engine[%d]/throttle %lg", 1, 1.0);
|
||||
f.write("get /sim/aircraft");
|
||||
const char* p = f.read();
|
||||
if (p)
|
||||
std::cout << "RECV: " << p << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
} catch (const char s[]) {
|
||||
std::cerr << "Error: " << s << ": " << strerror(errno) << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
std::cerr << "Error: " << s << ": " << strerror(errno) << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
|
||||
} catch (...) {
|
||||
std::cerr << "Error: unknown exception" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
std::cerr << "Error: unknown exception" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// vim:cindent
|
||||
|
|
Loading…
Reference in a new issue