mirror of
https://github.com/eddyem/boltwood.git
synced 2025-12-06 18:45:12 +03:00
fixed disconnect bug
This commit is contained in:
parent
0bc09f95b1
commit
e7aaa20af0
@ -30,7 +30,7 @@
|
|||||||
* here are global parameters initialisation
|
* here are global parameters initialisation
|
||||||
*/
|
*/
|
||||||
int help;
|
int help;
|
||||||
glob_pars G;
|
static glob_pars G;
|
||||||
|
|
||||||
#define DEFAULT_COMDEV "/dev/ttyUSB0"
|
#define DEFAULT_COMDEV "/dev/ttyUSB0"
|
||||||
// DEFAULTS
|
// DEFAULTS
|
||||||
|
|||||||
@ -235,6 +235,7 @@ void store_fits(char *name, datarecord *data){
|
|||||||
fits_report_error(stderr, status);
|
fits_report_error(stderr, status);
|
||||||
}
|
}
|
||||||
if(data){
|
if(data){
|
||||||
|
putlog("add boltwood's data");
|
||||||
DBG("Boltwood data");
|
DBG("Boltwood data");
|
||||||
// now the file copied -> add header from Boltwood's sensor
|
// now the file copied -> add header from Boltwood's sensor
|
||||||
while(data->varname){
|
while(data->varname){
|
||||||
@ -263,6 +264,7 @@ ret:
|
|||||||
}
|
}
|
||||||
// as cfitsio removes old file instead of trunkate it, we need to refresh inotify every time!
|
// 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
|
if(chdir(oldwd)){ // return back to BD root directory
|
||||||
|
putlog("Can't chdir");
|
||||||
ERR("Can't chdir");
|
ERR("Can't chdir");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,8 @@ void signals(int signo){
|
|||||||
exit(signo);
|
exit(signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glob_pars *G; // global - for socket.c
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
initial_setup();
|
initial_setup();
|
||||||
signal(SIGTERM, signals); // kill (-15) - quit
|
signal(SIGTERM, signals); // kill (-15) - quit
|
||||||
@ -37,10 +39,11 @@ int main(int argc, char **argv){
|
|||||||
signal(SIGINT, signals); // ctrl+C - quit
|
signal(SIGINT, signals); // ctrl+C - quit
|
||||||
signal(SIGQUIT, signals); // ctrl+\ - quit
|
signal(SIGQUIT, signals); // ctrl+\ - quit
|
||||||
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
|
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->server) ERRX(_("Please, specify server name"));
|
||||||
if(!G->filename) ERRX(_("Please, specify the name of input FITS file"));
|
if(!G->filename) ERRX(_("Please, specify the name of input FITS file"));
|
||||||
if(G->logfile) openlogfile(G->logfile);
|
if(G->logfile) openlogfile(G->logfile);
|
||||||
daemonize(G);
|
DBG("Opened, try to daemonize");
|
||||||
|
daemonize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,37 +150,43 @@ ewhile:
|
|||||||
/**
|
/**
|
||||||
* wait for answer from socket
|
* wait for answer from socket
|
||||||
* @param sock - socket fd
|
* @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){
|
static int waittoread(int sock){
|
||||||
fd_set fds;
|
fd_set fds, efds;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
int rc;
|
int rc;
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
timeout.tv_usec = 100000; // wait not more than 100ms
|
timeout.tv_usec = 100000; // wait not more than 100ms
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
|
FD_ZERO(&efds);
|
||||||
FD_SET(sock, &fds);
|
FD_SET(sock, &fds);
|
||||||
|
FD_SET(sock, &efds);
|
||||||
do{
|
do{
|
||||||
rc = select(sock+1, &fds, NULL, NULL, &timeout);
|
rc = select(sock+1, &fds, NULL, &efds, &timeout);
|
||||||
if(rc < 0){
|
if(rc < 0){
|
||||||
if(errno != EINTR){
|
if(errno != EINTR){
|
||||||
|
putlog("Server not available");
|
||||||
WARN("select()");
|
WARN("select()");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}while(1);
|
}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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open given FITS file, check it and add to inotify
|
* Open given FITS file, check it and add to inotify
|
||||||
* THREAD UNSAFE!!!
|
* THREAD UNSAFE!!!
|
||||||
* @return inotify file descriptor
|
* @return inotify file descriptor
|
||||||
*/
|
*/
|
||||||
int watch_fits(char *name){
|
int watch_fits(char *name){
|
||||||
|
FNAME();
|
||||||
static int fd = -1, wd = -1;
|
static int fd = -1, wd = -1;
|
||||||
if(fd > 0 && wd > 0){
|
if(fd > 0 && wd > 0){
|
||||||
inotify_rm_watch(fd, wd);
|
inotify_rm_watch(fd, wd);
|
||||||
@ -215,6 +221,7 @@ int watch_fits(char *name){
|
|||||||
* test if user can write something to path & make CWD
|
* test if user can write something to path & make CWD
|
||||||
*/
|
*/
|
||||||
static void test_path(char *path){
|
static void test_path(char *path){
|
||||||
|
FNAME();
|
||||||
if(path){
|
if(path){
|
||||||
if(chdir(path)){
|
if(chdir(path)){
|
||||||
putlog("Can't chdir(%s)", 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");
|
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
|
* Client daemon itself
|
||||||
|
* If sock < 0 try to reconnect after every image saving
|
||||||
* @param FITSpath - path to file watched
|
* @param FITSpath - path to file watched
|
||||||
* @param infd - inotify file descriptor
|
* @param infd - inotify file descriptor
|
||||||
* @param sock - socket's file descriptor
|
* @param sock - socket's file descriptor
|
||||||
*/
|
*/
|
||||||
static void client_(char *FITSpath, int infd, int sock){
|
static void client_(char *FITSpath, int infd, int sock){
|
||||||
if(sock < 0) return;
|
|
||||||
size_t Bufsiz = BUFLEN;
|
size_t Bufsiz = BUFLEN;
|
||||||
char *recvBuff = MALLOC(char, Bufsiz);
|
char *recvBuff = MALLOC(char, Bufsiz);
|
||||||
datarecord *last_good_msrment = NULL;
|
datarecord *last_good_msrment = NULL;
|
||||||
@ -250,6 +299,7 @@ static void client_(char *FITSpath, int infd, int sock){
|
|||||||
Bufsiz += 1024;
|
Bufsiz += 1024;
|
||||||
recvBuff = realloc(recvBuff, Bufsiz);
|
recvBuff = realloc(recvBuff, Bufsiz);
|
||||||
if(!recvBuff){
|
if(!recvBuff){
|
||||||
|
putlog("realloc() error");
|
||||||
WARN("realloc()");
|
WARN("realloc()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -265,7 +315,7 @@ static void client_(char *FITSpath, int infd, int sock){
|
|||||||
continue;
|
continue;
|
||||||
putlog("poll() error");
|
putlog("poll() error");
|
||||||
ERR("poll()");
|
ERR("poll()");
|
||||||
return;
|
return; // not reached
|
||||||
}
|
}
|
||||||
if(poll_num > 0){
|
if(poll_num > 0){
|
||||||
DBG("changed?");
|
DBG("changed?");
|
||||||
@ -292,18 +342,24 @@ static void client_(char *FITSpath, int infd, int sock){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fds.fd = watch_fits(FITSpath);
|
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;
|
size_t offset = 0;
|
||||||
do{
|
do{
|
||||||
rlc(offset);
|
rlc(offset);
|
||||||
ssize_t n = read(sock, &recvBuff[offset], Bufsiz - offset);
|
ssize_t n = read(sock, &recvBuff[offset], Bufsiz - offset);
|
||||||
if(!n){
|
if(!n){
|
||||||
putlog("socket disconnected");
|
putlog("nothing to read?");
|
||||||
|
offset = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(n < 0){
|
if(n < 0){
|
||||||
|
offset = 0;
|
||||||
putlog("read() error");
|
putlog("read() error");
|
||||||
WARN("read");
|
WARN("read");
|
||||||
break;
|
break;
|
||||||
@ -312,8 +368,8 @@ static void client_(char *FITSpath, int infd, int sock){
|
|||||||
}while(waittoread(sock));
|
}while(waittoread(sock));
|
||||||
if(!offset){
|
if(!offset){
|
||||||
putlog("socket disconnected");
|
putlog("socket disconnected");
|
||||||
WARN("Socket closed\n");
|
sock = -1;
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
rlc(offset);
|
rlc(offset);
|
||||||
recvBuff[offset] = 0;
|
recvBuff[offset] = 0;
|
||||||
@ -325,10 +381,14 @@ static void client_(char *FITSpath, int infd, int sock){
|
|||||||
/**
|
/**
|
||||||
* Connect to socket and run daemon service
|
* Connect to socket and run daemon service
|
||||||
*/
|
*/
|
||||||
void daemonize(glob_pars *G){
|
void daemonize(){
|
||||||
|
FNAME();
|
||||||
char resolved_path[PATH_MAX];
|
char resolved_path[PATH_MAX];
|
||||||
// get full path to FITS file
|
// 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
|
// open FITS file & add it to inotify
|
||||||
int fd = watch_fits(G->filename);
|
int fd = watch_fits(G->filename);
|
||||||
// CD to archive directory if user wants
|
// CD to archive directory if user wants
|
||||||
@ -336,6 +396,7 @@ void daemonize(glob_pars *G){
|
|||||||
minstoragetime = G->min_storage_time;
|
minstoragetime = G->min_storage_time;
|
||||||
// run fork before socket opening to prevent daemon's death if there's no network
|
// run fork before socket opening to prevent daemon's death if there's no network
|
||||||
#ifndef EBUG
|
#ifndef EBUG
|
||||||
|
putlog("daemonize");
|
||||||
if(daemon(1, 0)){
|
if(daemon(1, 0)){
|
||||||
putlog("daemon() error");
|
putlog("daemon() error");
|
||||||
ERR("daemon()");
|
ERR("daemon()");
|
||||||
@ -355,40 +416,8 @@ void daemonize(glob_pars *G){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
int sock = -1;
|
int sock = try_to_connect();
|
||||||
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);
|
|
||||||
client_(resolved_path, fd, sock);
|
client_(resolved_path, fd, sock);
|
||||||
close(sock);
|
if(sock > 0) close(sock);
|
||||||
signals(0);
|
signals(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,9 @@ typedef struct{
|
|||||||
bdata data; // data itself
|
bdata data; // data itself
|
||||||
} datarecord;
|
} datarecord;
|
||||||
|
|
||||||
void daemonize(glob_pars *G);
|
extern glob_pars *G; // from main.c
|
||||||
|
|
||||||
|
void daemonize();
|
||||||
int watch_fits(char *name);
|
int watch_fits(char *name);
|
||||||
|
|
||||||
#endif // __SOCKET_H__
|
#endif // __SOCKET_H__
|
||||||
|
|||||||
@ -394,6 +394,7 @@ time_t log_open_time = 0;
|
|||||||
* if failed show warning message
|
* if failed show warning message
|
||||||
*/
|
*/
|
||||||
void openlogfile(char *name){
|
void openlogfile(char *name){
|
||||||
|
FNAME();
|
||||||
if(!name){
|
if(!name){
|
||||||
WARNX(_("Need filename"));
|
WARNX(_("Need filename"));
|
||||||
return;
|
return;
|
||||||
@ -405,6 +406,7 @@ void openlogfile(char *name){
|
|||||||
}
|
}
|
||||||
log_open_time = time(NULL);
|
log_open_time = time(NULL);
|
||||||
logname = name;
|
logname = name;
|
||||||
|
DBG("log file %s opened, time: %ld", name, log_open_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user