xvc_server: don't stop when connection close, rework read to return code for error and for disconnect

This commit is contained in:
Gwenhael Goavec-Merou 2023-01-02 18:02:28 +01:00
parent c28e955bb9
commit 2182a8ff7f
2 changed files with 94 additions and 81 deletions

View File

@ -6,6 +6,7 @@
#include "xvc_server.hpp" #include "xvc_server.hpp"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <unistd.h> #include <unistd.h>
@ -43,12 +44,12 @@ XVC_server::XVC_server(int port, const cable_t & cable,
if (pin_conf == NULL) if (pin_conf == NULL)
throw std::exception(); throw std::exception();
_jtag = _jtag =
new FtdiJtagBitBang(cable.config, pin_conf, dev, serial, new FtdiJtagBitBang(cable.config, pin_conf, dev, serial,
clkHZ, _verbose); clkHZ, _verbose);
break; break;
case MODE_CH552_JTAG: case MODE_CH552_JTAG:
_jtag = _jtag =
new CH552_jtag(cable.config, dev, serial, clkHZ, _verbose); new CH552_jtag(cable.config, dev, serial, clkHZ, _verbose);
break; break;
case MODE_DIRTYJTAG: case MODE_DIRTYJTAG:
_jtag = new DirtyJtag(clkHZ, _verbose); _jtag = new DirtyJtag(clkHZ, _verbose);
@ -58,12 +59,12 @@ XVC_server::XVC_server(int port, const cable_t & cable,
break; break;
case MODE_USBBLASTER: case MODE_USBBLASTER:
_jtag = new UsbBlaster(cable.config.vid, cable.config.pid, _jtag = new UsbBlaster(cable.config.vid, cable.config.pid,
firmware_path, _verbose); firmware_path, _verbose);
break; break;
#ifdef ENABLE_CMSISDAP #ifdef ENABLE_CMSISDAP
case MODE_CMSISDAP: case MODE_CMSISDAP:
_jtag = _jtag =
new CmsisDAP(cable.config.vid, cable.config.pid, _verbose); new CmsisDAP(cable.config.vid, cable.config.pid, _verbose);
break; break;
#endif #endif
#endif #endif
@ -139,67 +140,69 @@ bool XVC_server::close_connection()
void XVC_server::thread_listen() void XVC_server::thread_listen()
{ {
fd_set conn; fd_set conn;
int maxfd = 0; int maxfd = 0;
FD_ZERO(&conn); FD_ZERO(&conn);
FD_SET(_sock, &conn); FD_SET(_sock, &conn);
maxfd = _sock; maxfd = _sock;
while (!_must_stop) { while (!_must_stop) {
fd_set read = conn, except = conn; fd_set read = conn, except = conn;
int fd; int fd;
struct timeval tv; struct timeval tv;
tv.tv_sec = 1; tv.tv_sec = 1;
tv.tv_usec = 0; tv.tv_usec = 0;
if (select(maxfd + 1, &read, 0, &except, &tv) < 0) { if (select(maxfd + 1, &read, 0, &except, &tv) < 0) {
printError("select"); printError("select");
break; break;
} }
for (fd = 0; fd <= maxfd; ++fd) { for (fd = 0; fd <= maxfd; ++fd) {
if (FD_ISSET(fd, &read)) { if (FD_ISSET(fd, &read)) {
if (fd == _sock) { if (fd == _sock) {
int newfd; int newfd;
socklen_t nsize = sizeof(_sock_addr); socklen_t nsize = sizeof(_sock_addr);
newfd = accept(_sock, (struct sockaddr*) &_sock_addr, newfd = accept(_sock, (struct sockaddr*) &_sock_addr,
&nsize); &nsize);
printf("connection accepted - fd %d\n", newfd); printf("connection accepted - fd %d\n", newfd);
if (newfd < 0) { if (newfd < 0) {
throw std::runtime_error("accept"); throw std::runtime_error("accept");
} else { } else {
printInfo("setting TCP_NODELAY to 1\n"); printInfo("setting TCP_NODELAY to 1\n");
int flag = 1; int flag = 1;
int optResult = setsockopt(newfd, IPPROTO_TCP, int optResult = setsockopt(newfd, IPPROTO_TCP,
TCP_NODELAY, (char *)&flag, sizeof(int)); TCP_NODELAY, (char *)&flag, sizeof(int));
if (optResult < 0) if (optResult < 0)
throw std::runtime_error("TCP_NODELAY error"); throw std::runtime_error("TCP_NODELAY error");
if (newfd > maxfd) { if (newfd > maxfd) {
maxfd = newfd; maxfd = newfd;
} }
FD_SET(newfd, &conn); FD_SET(newfd, &conn);
} }
} else { } else {
int ret = handle_data(fd); int ret = handle_data(fd);
printInfo("connection closed - fd " + std::to_string(fd)); if (ret != 0) {
close(fd); printInfo("connection closed - fd " + std::to_string(fd));
FD_CLR(fd, &conn); close(fd);
if (ret == 1) FD_CLR(fd, &conn);
throw std::runtime_error("communication failure"); if (ret == 3)
throw std::runtime_error("communication failure");
}
} }
} else if (FD_ISSET(fd, &except)) { } else if (FD_ISSET(fd, &except)) {
printWarn("connection aborted - fd " + std::to_string(fd)); printWarn("connection aborted - fd " + std::to_string(fd));
close(fd); close(fd);
FD_CLR(fd, &conn); FD_CLR(fd, &conn);
if (fd == _sock) if (fd == _sock)
break; break;
} }
} }
} }
_is_stopped = true; _is_stopped = true;
} }
@ -220,37 +223,46 @@ bool XVC_server::listen_loop()
int XVC_server::sread(int fd, void *target, int len) int XVC_server::sread(int fd, void *target, int len)
{ {
unsigned char *t = (unsigned char *)target; unsigned char *t = (unsigned char *)target;
while (len) { while (len) {
int r = read(fd, t, len); int r = read(fd, t, len);
if (r <= 0) if (r == 0) // connection closed
return r; return 2;
t += r; else if (r < 0) {
len -= r; char err[256];
} snprintf(err, 256, "Read error (%d) %d %s\n", r,
return 1; errno, strerror(errno));
} printError(err);
return 3;
}
t += r;
len -= r;
}
return 1;
}
int XVC_server::handle_data(int fd) int XVC_server::handle_data(int fd)
{ {
char xvcInfo[32]; char xvcInfo[32];
int ret;
do { do {
char cmd[16]; char cmd[16];
memset(cmd, 0, 16); memset(cmd, 0, 16);
if (sread(fd, cmd, 2) != 1) if ((ret = sread(fd, cmd, 2)) != 1) {
return 1; return ret;
}
/* getinfo */ /* getinfo */
if (memcmp(cmd, "ge", 2) == 0) { if (memcmp(cmd, "ge", 2) == 0) {
if (sread(fd, cmd, 6) != 1) if ((ret = sread(fd, cmd, 6)) != 1)
return 1; return ret;
snprintf(xvcInfo, sizeof(xvcInfo), snprintf(xvcInfo, sizeof(xvcInfo),
"xvcServer_v1.0:%u\n", _buffer_size); "xvcServer_v1.0:%u\n", _buffer_size);
if (send(fd, xvcInfo, strlen(xvcInfo), 0) != if (send(fd, xvcInfo, strlen(xvcInfo), 0) !=
(ssize_t) strlen(xvcInfo)) { (ssize_t) strlen(xvcInfo)) {
perror("write"); perror("write");
return 1; return 1;
} }
@ -262,8 +274,8 @@ int XVC_server::handle_data(int fd)
break; break;
/* settck */ /* settck */
} else if (memcmp(cmd, "se", 2) == 0) { } else if (memcmp(cmd, "se", 2) == 0) {
if (sread(fd, cmd, 9) != 1) if ((ret = sread(fd, cmd, 9)) != 1)
return 1; return ret;
memcpy(_result, cmd + 5, 4); memcpy(_result, cmd + 5, 4);
if (write(fd, _result, 4) != 4) { if (write(fd, _result, 4) != 4) {
printError("write"); printError("write");
@ -281,24 +293,24 @@ int XVC_server::handle_data(int fd)
printInfo(std::to_string((int)time(NULL)) + printInfo(std::to_string((int)time(NULL)) +
" : Received command: 'settck'"); " : Received command: 'settck'");
printf("\t Replied with '%.*s'\n\n", 4, printf("\t Replied with '%.*s'\n\n", 4,
cmd + 5); cmd + 5);
} }
break; break;
} else if (memcmp(cmd, "de", 2) == 0) { // DEBUG CODE } else if (memcmp(cmd, "de", 2) == 0) { // DEBUG CODE
if (sread(fd, cmd, 3) != 1) if ((ret = sread(fd, cmd, 3)) != 1)
return 1; return ret;
printf("%u : Received command: 'debug'\n", printf("%u : Received command: 'debug'\n",
(int)time(NULL)); (int)time(NULL));
break; break;
} else if (memcmp(cmd, "of", 2) == 0) { // DEBUG CODE } else if (memcmp(cmd, "of", 2) == 0) { // DEBUG CODE
if (sread(fd, cmd, 1) != 1) if ((ret = sread(fd, cmd, 1)) != 1)
return 1; return ret;
printf("%u : Received command: 'off'\n", printf("%u : Received command: 'off'\n",
(int)time(NULL)); (int)time(NULL));
break; break;
} else if (memcmp(cmd, "sh", 2) == 0) { } else if (memcmp(cmd, "sh", 2) == 0) {
if (sread(fd, cmd, 4) != 1) if ((ret = sread(fd, cmd, 4)) != 1)
return 1; return ret;
if (_verbose) { if (_verbose) {
printInfo(std::to_string((int)time(NULL)) + printInfo(std::to_string((int)time(NULL)) +
" : Received command: 'shift'"); " : Received command: 'shift'");
@ -311,9 +323,9 @@ int XVC_server::handle_data(int fd)
/* Handling for -> "shift:<num bits><tms vector><tdi vector>" */ /* Handling for -> "shift:<num bits><tms vector><tdi vector>" */
uint32_t len, nr_bytes; uint32_t len, nr_bytes;
/* 1. len */ /* 1. len */
if (sread(fd, &len, 4) != 1) { if ((ret = sread(fd, &len, 4)) != 1) {
printError("reading length failed"); printError("reading length failed");
return 1; return ret;
} }
/* 2. convert len (in bits) to nr_bytes (in bytes) */ /* 2. convert len (in bits) to nr_bytes (in bytes) */
@ -326,9 +338,9 @@ int XVC_server::handle_data(int fd)
/* 3. receive 2 x nr_bytes (TMS + TDI) */ /* 3. receive 2 x nr_bytes (TMS + TDI) */
memset(_tmstdi, 0, _buffer_size); memset(_tmstdi, 0, _buffer_size);
if (sread(fd, _tmstdi, nr_bytes * 2) != 1) { if ((ret = sread(fd, _tmstdi, nr_bytes * 2)) != 1) {
printError("reading data failed"); printError("reading data failed");
return 1; return ret;
} }
memset(_result, 0, _buffer_size/2); memset(_result, 0, _buffer_size/2);

View File

@ -50,7 +50,8 @@ class XVC_server {
void thread_listen(); void thread_listen();
/*! /*!
* \brief parser and dispatcher for XVC transactions * \brief parser and dispatcher for XVC transactions
* \return 1 when transactions fails, 0 otherwise * \return 2 when connection is closed, 1 when transactions fails,
* 0 otherwise
*/ */
int handle_data(int fd); int handle_data(int fd);
/*! /*!
@ -58,7 +59,7 @@ class XVC_server {
* \param fd: socket descriptor * \param fd: socket descriptor
* \param target: buffer * \param target: buffer
* \param len: number of bytes to read * \param len: number of bytes to read
* \return <= 0 when failure, 1 otherwise * \return 3 when failure, 2 when connection closed, 1 otherwise
*/ */
int sread(int fd, void *target, int len); int sread(int fd, void *target, int len);
int _verbose; /*!< verbose level */ int _verbose; /*!< verbose level */