fixed disconnect bug

This commit is contained in:
eddyem 2017-04-25 11:02:35 +03:00
parent 0bc09f95b1
commit e7aaa20af0
6 changed files with 89 additions and 51 deletions

View File

@ -30,7 +30,7 @@
* here are global parameters initialisation
*/
int help;
glob_pars G;
static glob_pars G;
#define DEFAULT_COMDEV "/dev/ttyUSB0"
// DEFAULTS

View File

@ -235,6 +235,7 @@ void store_fits(char *name, datarecord *data){
fits_report_error(stderr, status);
}
if(data){
putlog("add boltwood's data");
DBG("Boltwood data");
// now the file copied -> add header from Boltwood's sensor
while(data->varname){
@ -263,6 +264,7 @@ ret:
}
// as cfitsio removes old file instead of trunkate it, we need to refresh inotify every time!
if(chdir(oldwd)){ // return back to BD root directory
putlog("Can't chdir");
ERR("Can't chdir");
};
}

View File

@ -30,6 +30,8 @@ void signals(int signo){
exit(signo);
}
glob_pars *G; // global - for socket.c
int main(int argc, char **argv){
initial_setup();
signal(SIGTERM, signals); // kill (-15) - quit
@ -37,10 +39,11 @@ int main(int argc, char **argv){
signal(SIGINT, signals); // ctrl+C - quit
signal(SIGQUIT, signals); // ctrl+\ - quit
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
glob_pars *G = parse_args(argc, argv);
G = parse_args(argc, argv);
if(!G->server) ERRX(_("Please, specify server name"));
if(!G->filename) ERRX(_("Please, specify the name of input FITS file"));
if(G->logfile) openlogfile(G->logfile);
daemonize(G);
DBG("Opened, try to daemonize");
daemonize();
return 0;
}

View File

@ -150,37 +150,43 @@ ewhile:
/**
* wait for answer from socket
* @param sock - socket fd
* @return 0 in case of error or timeout, 1 in case of socket ready
* @return 0 if data is absent, 1 in case of socket ready, -1 if socket closed or error occured
*/
static int waittoread(int sock){
fd_set fds;
fd_set fds, efds;
struct timeval timeout;
int rc;
timeout.tv_sec = 0;
timeout.tv_usec = 100000; // wait not more than 100ms
FD_ZERO(&fds);
FD_ZERO(&efds);
FD_SET(sock, &fds);
FD_SET(sock, &efds);
do{
rc = select(sock+1, &fds, NULL, NULL, &timeout);
rc = select(sock+1, &fds, NULL, &efds, &timeout);
if(rc < 0){
if(errno != EINTR){
putlog("Server not available");
WARN("select()");
return 0;
return -1;
}
continue;
}
break;
}while(1);
if(FD_ISSET(sock, &fds)) return 1;
if(FD_ISSET(sock, &fds)) return 1;
if(FD_ISSET(sock, &efds)) return -1; // exception - socket closed
return 0;
}
/**
* Open given FITS file, check it and add to inotify
* THREAD UNSAFE!!!
* @return inotify file descriptor
*/
int watch_fits(char *name){
FNAME();
static int fd = -1, wd = -1;
if(fd > 0 && wd > 0){
inotify_rm_watch(fd, wd);
@ -215,6 +221,7 @@ int watch_fits(char *name){
* test if user can write something to path & make CWD
*/
static void test_path(char *path){
FNAME();
if(path){
if(chdir(path)){
putlog("Can't chdir(%s)", path);
@ -228,14 +235,56 @@ static void test_path(char *path){
DBG("OK, user can write to given path");
}
/**
* try to connect to Boltwood's server
* @return file descriptor of opened socket or -1
*/
static int try_to_connect(){
int sock = -1;
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
putlog("Try to connect to %s:%s", G->server, G->port);
if(getaddrinfo(G->server, G->port, &hints, &res) != 0){
putlog("getaddrinfo()");
return -1;
}
struct sockaddr_in *ia = (struct sockaddr_in*)res->ai_addr;
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN);
DBG("canonname: %s, port: %u, addr: %s\n", res->ai_canonname, ntohs(ia->sin_port), str);
// loop through all the results and bind to the first we can
for(p = res; p != NULL; p = p->ai_next){
if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
WARN("socket");
continue;
}
if(connect(sock, p->ai_addr, p->ai_addrlen) == -1){
WARN("connect()");
close(sock);
continue;
}
break; // if we get here, we have a successfull connection
}
if(p == NULL || sock < 0){
putlog("failed to bind socket");
return -1;
}
freeaddrinfo(res);
putlog("Connection established");
return sock;
}
/**
* Client daemon itself
* If sock < 0 try to reconnect after every image saving
* @param FITSpath - path to file watched
* @param infd - inotify file descriptor
* @param sock - socket's file descriptor
*/
static void client_(char *FITSpath, int infd, int sock){
if(sock < 0) return;
size_t Bufsiz = BUFLEN;
char *recvBuff = MALLOC(char, Bufsiz);
datarecord *last_good_msrment = NULL;
@ -250,6 +299,7 @@ static void client_(char *FITSpath, int infd, int sock){
Bufsiz += 1024;
recvBuff = realloc(recvBuff, Bufsiz);
if(!recvBuff){
putlog("realloc() error");
WARN("realloc()");
return;
}
@ -265,7 +315,7 @@ static void client_(char *FITSpath, int infd, int sock){
continue;
putlog("poll() error");
ERR("poll()");
return;
return; // not reached
}
if(poll_num > 0){
DBG("changed?");
@ -292,18 +342,24 @@ static void client_(char *FITSpath, int infd, int sock){
}
}
fds.fd = watch_fits(FITSpath);
if(sock < 0) sock = try_to_connect(); // try to reconnect if disconnected
}
}
if(!waittoread(sock)) continue;
if(sock < 0) continue;
int rd = waittoread(sock);
if(rd < 0) sock = -1; // signal that socket disconnected & we need to try to connect
if(rd < 1) continue;
size_t offset = 0;
do{
rlc(offset);
ssize_t n = read(sock, &recvBuff[offset], Bufsiz - offset);
if(!n){
putlog("socket disconnected");
putlog("nothing to read?");
offset = 0;
break;
}
if(n < 0){
offset = 0;
putlog("read() error");
WARN("read");
break;
@ -312,8 +368,8 @@ static void client_(char *FITSpath, int infd, int sock){
}while(waittoread(sock));
if(!offset){
putlog("socket disconnected");
WARN("Socket closed\n");
return;
sock = -1;
continue;
}
rlc(offset);
recvBuff[offset] = 0;
@ -325,10 +381,14 @@ static void client_(char *FITSpath, int infd, int sock){
/**
* Connect to socket and run daemon service
*/
void daemonize(glob_pars *G){
void daemonize(){
FNAME();
char resolved_path[PATH_MAX];
// get full path to FITS file
if(!realpath(G->filename, resolved_path)) ERR("realpath()");
if(!realpath(G->filename, resolved_path)){
putlog("realpath() error");
ERR("realpath()");
}
// open FITS file & add it to inotify
int fd = watch_fits(G->filename);
// CD to archive directory if user wants
@ -336,6 +396,7 @@ void daemonize(glob_pars *G){
minstoragetime = G->min_storage_time;
// run fork before socket opening to prevent daemon's death if there's no network
#ifndef EBUG
putlog("daemonize");
if(daemon(1, 0)){
putlog("daemon() error");
ERR("daemon()");
@ -355,40 +416,8 @@ void daemonize(glob_pars *G){
}
}
#endif
int sock = -1;
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
DBG("connect to %s:%s", G->server, G->port);
if(getaddrinfo(G->server, G->port, &hints, &res) != 0){
ERR("getaddrinfo");
}
struct sockaddr_in *ia = (struct sockaddr_in*)res->ai_addr;
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(ia->sin_addr), str, INET_ADDRSTRLEN);
DBG("canonname: %s, port: %u, addr: %s\n", res->ai_canonname, ntohs(ia->sin_port), str);
// loop through all the results and bind to the first we can
for(p = res; p != NULL; p = p->ai_next){
if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
WARN("socket");
continue;
}
if(connect(sock, p->ai_addr, p->ai_addrlen) == -1){
WARN("connect()");
close(sock);
continue;
}
break; // if we get here, we have a successfull connection
}
if(p == NULL){
putlog("failed to bind socket");
// looped off the end of the list with no successful bind
ERRX("failed to bind socket");
}
freeaddrinfo(res);
int sock = try_to_connect();
client_(resolved_path, fd, sock);
close(sock);
if(sock > 0) close(sock);
signals(0);
}

View File

@ -45,7 +45,9 @@ typedef struct{
bdata data; // data itself
} datarecord;
void daemonize(glob_pars *G);
extern glob_pars *G; // from main.c
void daemonize();
int watch_fits(char *name);
#endif // __SOCKET_H__

View File

@ -394,6 +394,7 @@ time_t log_open_time = 0;
* if failed show warning message
*/
void openlogfile(char *name){
FNAME();
if(!name){
WARNX(_("Need filename"));
return;
@ -405,6 +406,7 @@ void openlogfile(char *name){
}
log_open_time = time(NULL);
logname = name;
DBG("log file %s opened, time: %ld", name, log_open_time);
}
/**