From 684a0616a4a112d972062232a89e7b5d287a27ba Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 24 Mar 2022 17:06:29 +0300 Subject: [PATCH] fixed bug with SIGPIPE @write, fixed some other big bugs --- CMakeLists.txt | 2 +- Dummy_cameras/CMakeLists.txt | 2 +- FLI_cameras/CMakeLists.txt | 2 +- FLI_cameras/flifunc.c | 36 +++- ZWO_cameras/CMakeLists.txt | 2 +- ZWO_cameras/zwofunc.c | 13 +- client.c | 29 ++- client.h | 7 - locale/ru/messages.po | 16 +- locale/ru/ru.po | 16 +- main.c | 2 +- server.c | 335 +++++++++++++++-------------------- socket.c | 92 ++++++---- socket.h | 18 +- 14 files changed, 296 insertions(+), 276 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f7c528..eee70dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,7 +107,7 @@ set(RU_FILE ${LCPATH}/ru.po) # exe file add_executable(${PROJ} ${SOURCES} ${PO_FILE} ${MO_FILE}) -target_link_libraries(${PROJ} ${CFITSIO_LIBRARIES} ${X11_LIBRARIES} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${${PROJ}_LIBRARIES} -lm) +target_link_libraries(${PROJ} ${CFITSIO_LIBRARIES} ${X11_LIBRARIES} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${${PROJ}_LIBRARIES} -lm ${CMAKE_DL_LIBS}) include_directories(${${PROJ}_INCLUDE_DIRS} .) link_directories(${${PROJ}_LIBRARY_DIRS} ) diff --git a/Dummy_cameras/CMakeLists.txt b/Dummy_cameras/CMakeLists.txt index 700289e..04377ef 100644 --- a/Dummy_cameras/CMakeLists.txt +++ b/Dummy_cameras/CMakeLists.txt @@ -9,4 +9,4 @@ include_directories(${${CCDLIB}_INCLUDE_DIRS} ..) link_directories(${${CCDLIB}_LIBRARY_DIRS}) add_library(${CCDLIB} SHARED ${SRC}) -target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES}) +target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES} -fPIC) diff --git a/FLI_cameras/CMakeLists.txt b/FLI_cameras/CMakeLists.txt index b667ae7..edbe116 100644 --- a/FLI_cameras/CMakeLists.txt +++ b/FLI_cameras/CMakeLists.txt @@ -9,4 +9,4 @@ include_directories(${${CCDLIB}_INCLUDE_DIRS} ..) link_directories(${${CCDLIB}_LIBRARY_DIRS}) add_library(${CCDLIB} SHARED ${SRC}) -target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES}) +target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES} -fPIC) diff --git a/FLI_cameras/flifunc.c b/FLI_cameras/flifunc.c index be114c2..21dc1c2 100644 --- a/FLI_cameras/flifunc.c +++ b/FLI_cameras/flifunc.c @@ -49,7 +49,7 @@ extern Wheel wheel; #define FOCSCALE (10000.) #define TRYFUNC(f, ...) \ -do{ if((fli_err = f(__VA_ARGS__))) \ +do{fli_err = 0; if((fli_err = f(__VA_ARGS__))) \ WARNX(#f "() failed"); \ }while(0) @@ -62,7 +62,7 @@ typedef struct{ static char camname[BUFSIZ] = {0}, whlname[BUFSIZ], focname[BUFSIZ]; static long fli_err, tmpl; static cam_t *camz = NULL, *whlz = NULL, *focz = NULL; -static flidev_t camdev, whldev, focdev; +static flidev_t camdev = -1, whldev = -1, focdev = -1; static capture_status capStatus = CAPTURE_NO; static int curhbin = 1, curvbin = 1; static long filterpos = -1, filtermax = -1; // filter position @@ -140,15 +140,20 @@ static int fli_findCCD(){ return TRUE; } static int fli_setActiceCam(int n){ + DBG("SET ACTUIVE #%d", n); if(!camz && !fli_findCCD()) return FALSE; if(n >= camera.Ndevices){ return FALSE; } - FLIClose(camdev); + if(camdev > -1){ + FLIClose(camdev); + camdev = -1; + } TRYFUNC(FLIOpen, &camdev, camz[n].name, camz[n].domain); if(fli_err){ return FALSE; } + DBG("camera fdno: %ld", camdev); TRYFUNC(FLIGetModel, camdev, camname, BUFSIZ); #ifdef EBUG if(!fli_err) DBG("Model: %s", camname); @@ -205,12 +210,16 @@ static int fli_findFocuser(){ static int fli_setActiceFocuser(int n){ if(!focz && !fli_findFocuser()) return FALSE; if(n >= focuser.Ndevices) return FALSE; - FLIClose(focdev); + if(focdev > -1){ + FLIClose(focdev); + focdev = -1; + } int OK = FALSE; for(int i = 0; i < focuser.Ndevices; ++i){ DBG("Try %s", focz[i].name); TRYFUNC(FLIOpen, &focdev, focz[i].name, focz[i].domain); if(fli_err) continue; + DBG("focuser fdno: %ld", focdev); TRYFUNC(FLIGetModel, focdev, focname, BUFSIZ); DBG("MODEL '%s'", focname); if(fli_err) continue; @@ -315,12 +324,16 @@ static int fli_wgetpos(int *p); static int fli_setActiceWheel(int n){ if(!whlz && !fli_findWheel()) return FALSE; if(n >= wheel.Ndevices) return FALSE; - FLIClose(whldev); + if(whldev > -1){ + FLIClose(whldev); + whldev = -1; + } int OK = FALSE; - for(int i = 0; i < focuser.Ndevices; ++i){ + for(int i = 0; i < wheel.Ndevices; ++i){ DBG("Try %s", whlz[i].name); TRYFUNC(FLIOpen, &whldev, whlz[i].name, whlz[i].domain); if(fli_err) continue; + DBG("wheel fdno: %ld", whldev); TRYFUNC(FLIGetFilterCount, whldev, &filtermax); if(fli_err || filtermax < 2){ // not a wheel DBG("Not a wheel"); @@ -351,6 +364,7 @@ static int fli_setActiceWheel(int n){ } static int fli_wgetname(char *x, int n){ + if(!x) return FALSE; strncpy(x, whlname, n); return TRUE; } @@ -381,7 +395,9 @@ static int fli_wgetpos(int *p){ static int fli_wsetpos(int p){ if(p == filterpos) return TRUE; if(p > filtermax || p < 0) return FALSE; + DBG("RUN FLISetFilterPos"); TRYFUNC(FLISetFilterPos, whldev, (long)p); + DBG("end"); if(fli_err) return FALSE; return TRUE; } @@ -427,7 +443,7 @@ static int fli_pollcapt(capture_status *st, float *remain){ goto retn; } if(remain) *remain = tmpl/1000.; - DBG("remained: %g", tmpl/1000.); + //DBG("remained: %g", tmpl/1000.); if(tmpl == 0){ if(st) *st = CAPTURE_READY; capStatus = CAPTURE_NO; @@ -506,15 +522,19 @@ typedef enum{ } temptype; static int fli_gettemp(temptype type, float *t){ + if(!t) return FALSE; double d; switch(type){ case T_COLD: + DBG("read T_COLD"); TRYFUNC(FLIGetTemperature, camdev, &d); break; case T_BODY: + DBG("read T_BODY"); TRYFUNC(FLIReadTemperature, camdev, FLI_TEMPERATURE_EXTERNAL, &d); break; default: + DBG("read T_HOT"); TRYFUNC(FLIReadTemperature, camdev, FLI_TEMPERATURE_INTERNAL, &d); } if(fli_err) return FALSE; @@ -581,8 +601,10 @@ static int fli_setio(int io){ static int fli_setexp(float t){ long e = (long)(t*1000.); // milliseconds! + DBG("Try to set exp to %ldms", e); TRYFUNC(FLISetExposureTime, camdev, e); if(fli_err) return FALSE; + DBG("OK"); return TRUE; } diff --git a/ZWO_cameras/CMakeLists.txt b/ZWO_cameras/CMakeLists.txt index 6cb099c..a55e4a3 100644 --- a/ZWO_cameras/CMakeLists.txt +++ b/ZWO_cameras/CMakeLists.txt @@ -9,4 +9,4 @@ include_directories(${${CCDLIB}_INCLUDE_DIRS} ..) link_directories(${${CCDLIB}_LIBRARY_DIRS}) add_library(${CCDLIB} SHARED ${SRC}) -target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES} -lASICamera2) +target_link_libraries(${CCDLIB} ${${CCDLIB}_LIBRARIES} -lASICamera2 -fPIC) diff --git a/ZWO_cameras/zwofunc.c b/ZWO_cameras/zwofunc.c index 1493c2a..924f5a5 100644 --- a/ZWO_cameras/zwofunc.c +++ b/ZWO_cameras/zwofunc.c @@ -85,18 +85,25 @@ static int asi_checkcam(){ static int campoll(capture_status *st, float *remain){ if(!st) return FALSE; ASI_EXPOSURE_STATUS s; - if(ASI_SUCCESS != ASIGetExpStatus(caminfo.CameraID, &s)) return FALSE; + if(ASI_SUCCESS != ASIGetExpStatus(caminfo.CameraID, &s)){ + DBG("Can't get exp status"); + return FALSE; + } switch(s){ case ASI_EXP_IDLE: + DBG("No capture"); *st = CAPTURE_NO; break; case ASI_EXP_WORKING: + DBG("Capture in progress"); *st = CAPTURE_PROCESS; break; case ASI_EXP_SUCCESS: + DBG("Capture ready"); *st = CAPTURE_READY; break; default: // failed + DBG("Failed: %d", s); *st = CAPTURE_ABORTED; } if(remain){ @@ -309,8 +316,8 @@ static int gett(_U_ float *t){ static int camsetbin(int h, int v){ DBG("set bin %dx%d", h, v); if(h != v){ - WARNX(_("BinX and BinY should be equal")); - return FALSE; + WARNX(_("BinX and BinY should be equal, take h")); + //return FALSE; } if(h > extrvalues.maxbin){ WARNX(_("Maximal binning value is %d"), extrvalues.maxbin); diff --git a/client.c b/client.c index a8ad8fc..afe78fd 100644 --- a/client.c +++ b/client.c @@ -30,7 +30,7 @@ static char sendbuf[BUFSIZ]; #define SENDMSG(...) do{snprintf(sendbuf, BUFSIZ-1, __VA_ARGS__); verbose(2, "\t> %s", sendbuf); sendstrmessage(sock, sendbuf); getans(sock);}while(0) -static int expstate = 0; +static int expstate = CAMERA_CAPTURE; /** * check data from fd (polling function for client) @@ -77,7 +77,7 @@ static char *readmsg(int fd){ curlen += rd; buf[curlen] = 0; if(curlen == 0) return NULL; - DBG("cur buffer: ----%s----", buf); + //DBG("cur buffer: ----%s----", buf); char *nl = strchr(buf, '\n'); if(!nl) return NULL; *nl++ = 0; @@ -91,11 +91,15 @@ static char *readmsg(int fd){ // parser of CCD server messages; return TRUE to exit from polling cycle of `getans` (if receive 'FAIL', 'OK' or 'BUSY') static int parseans(char *ans){ if(!ans) return FALSE; + //DBG("Parsing of '%s'", ans); if(0 == strcmp(hresult2str(RESULT_BUSY), ans)) ERRX("Server busy"); if(0 == strcmp(hresult2str(RESULT_FAIL), ans)) return TRUE; if(0 == strcmp(hresult2str(RESULT_OK), ans)) return TRUE; char *val = get_keyval(ans); // now `ans` is a key and `val` its value - if(0 == strcmp(CMD_EXPSTATE, ans)) expstate = atoi(val); + if(0 == strcmp(CMD_EXPSTATE, ans)){ + expstate = atoi(val); + DBG("Exposition state: %d", expstate); + } return FALSE; } @@ -109,11 +113,13 @@ static int getans(int sock){ if(ans) return TRUE; else continue; } + t0 = dtime(); ans = s; DBG("Got from server: %s", ans); verbose(1, "\t%s", ans); if(parseans(ans)) break; } + DBG("GETANS: timeout, ans: %s", ans); return ((ans) ? TRUE : FALSE); } @@ -121,6 +127,8 @@ static int getans(int sock){ * @brief processData - process here some actions and make messages for server */ static void process_data(int sock){ + // common information + SENDMSG(CMD_INFO); // focuser if(GP->listdevices) SENDMSG(CMD_FOCLIST); if(GP->focdevno > -1) SENDMSG(CMD_FDEVNO "=%d", GP->focdevno); @@ -181,8 +189,6 @@ static void process_data(int sock){ } SENDMSG(CMD_HEADERFILES "=%s", buf); } - // common information - SENDMSG(CMD_INFO); } void client(int sock){ @@ -200,12 +206,16 @@ void client(int sock){ else GP->waitexpend = TRUE; // N>1 - wait for exp ends SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); } else { - getans(sock); + while(getans(sock)); + DBG("RETURN: no more data"); return; } - double timeout = GP->waitexpend ? CLIENT_TIMEOUT : 0.1; + double timeout = GP->waitexpend ? CLIENT_TIMEOUT : WAIT_TIMEOUT; verbose(1, "Exposing frame 1..."); - if(GP->waitexpend) verbose(2, "Wait for exposition end"); + if(GP->waitexpend){ + expstate = CAMERA_CAPTURE; // could be changed earlier + verbose(2, "Wait for exposition end"); + } while(dtime() - t0 < timeout){ if(GP->waitexpend && dtime() - tw > WAIT_TIMEOUT){ SENDMSG(CMD_TREMAIN); // get remained time @@ -214,6 +224,7 @@ void client(int sock){ sendstrmessage(sock, sendbuf); } if(getans(sock)){ // got next portion of data + DBG("server message"); t0 = dtime(); if(expstate == CAMERA_ERROR){ WARNX(_("Can't make exposition")); @@ -240,7 +251,7 @@ void client(int sock){ SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); }else{ GP->waitexpend = 0; - timeout = 0.2; // wait for last file name + timeout = WAIT_TIMEOUT; // wait for last file name } } } diff --git a/client.h b/client.h index 87cfe2b..97d9c47 100644 --- a/client.h +++ b/client.h @@ -20,13 +20,6 @@ #ifndef CLIENT_H__ #define CLIENT_H__ -// waiting for answer timeout -#define ANSWER_TIMEOUT 1.0 -// wait for exposition ends (between subsequent check calls) -#define WAIT_TIMEOUT 2.0 -// client will disconnect after this time from last server message -#define CLIENT_TIMEOUT 10.0 - // client-side functions void client(int fd); diff --git a/locale/ru/messages.po b/locale/ru/messages.po index fc50e3d..7ed5184 100644 --- a/locale/ru/messages.po +++ b/locale/ru/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-03-22 17:17+0300\n" +"POT-Creation-Date: 2022-03-24 11:43+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -473,12 +473,12 @@ msgstr "" msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:703 server.c:219 +#: ccdfunc.c:703 server.c:225 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:713 server.c:220 +#: ccdfunc.c:713 server.c:226 msgid "Can't set given geometry" msgstr "" @@ -528,7 +528,7 @@ msgstr "" msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:756 server.c:120 +#: ccdfunc.c:756 server.c:121 msgid "Can't start exposition" msgstr "" @@ -545,20 +545,20 @@ msgid "Can't grab image" msgstr "" #. %d секунд до окончания паузы\n -#: ccdfunc.c:803 client.c:232 +#: ccdfunc.c:803 client.c:236 #, c-format msgid "%d seconds till pause ends\n" msgstr "" -#: server.c:161 +#: server.c:163 msgid "No camera device" msgstr "" -#: client.c:219 +#: client.c:223 msgid "Can't make exposition" msgstr "" -#: client.c:248 +#: client.c:252 msgid "Server timeout" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index d7e8449..d79af04 100644 --- a/locale/ru/ru.po +++ b/locale/ru/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" - "POT-Creation-Date: 2022-03-22 17:17+0300\n" + "POT-Creation-Date: 2022-03-24 11:10+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -22,7 +22,7 @@ msgid "%.1f seconds till exposition ends" msgstr "" #. %d секунд до окончания паузы\n -#: ccdfunc.c:803 client.c:232 +#: ccdfunc.c:803 client.c:236 #, c-format msgid "%d seconds till pause ends\n" msgstr "" @@ -117,7 +117,7 @@ msgstr "" msgid "Can't init mutex!" msgstr "" -#: client.c:219 +#: client.c:223 msgid "Can't make exposition" msgstr "" @@ -162,7 +162,7 @@ msgstr "" msgid "Can't set active wheel number" msgstr "" -#: ccdfunc.c:703 server.c:219 +#: ccdfunc.c:703 server.c:225 #, c-format msgid "Can't set binning %dx%d" msgstr "" @@ -190,7 +190,7 @@ msgstr "" msgid "Can't set gain to %g" msgstr "" -#: ccdfunc.c:713 server.c:220 +#: ccdfunc.c:713 server.c:226 msgid "Can't set given geometry" msgstr "" @@ -213,7 +213,7 @@ msgstr "" msgid "Can't set wheel position %d" msgstr "" -#: ccdfunc.c:756 server.c:120 +#: ccdfunc.c:756 server.c:121 msgid "Can't start exposition" msgstr "" @@ -288,7 +288,7 @@ msgstr "" msgid "Neither filename nor filename prefix pointed!" msgstr "" -#: server.c:161 +#: server.c:163 msgid "No camera device" msgstr "" @@ -326,7 +326,7 @@ msgstr "" msgid "Readout mode: %s" msgstr "" -#: client.c:248 +#: client.c:252 msgid "Server timeout" msgstr "" diff --git a/main.c b/main.c index 1aaf02a..1c39ad1 100644 --- a/main.c +++ b/main.c @@ -47,7 +47,7 @@ void signals(int signo){ signal(signo, signals); return; } - DBG("Master killed with sig=%d", signo); + WARNX("Master killed with sig=%d", signo); LOGERR("Master killed with sig=%d", signo); if(!GP->client){ DBG("Unlink pid file"); diff --git a/server.c b/server.c index 442c32d..8534959 100644 --- a/server.c +++ b/server.c @@ -52,58 +52,59 @@ typedef struct{ // cat | awk '{print "{ " $3 ", \"\" }," }' | sort strpair allcommands[] = { - { "8bit", "run in 8 bit mode instead of 16 bit" }, - { "author", "FITS 'AUTHOR' field" }, - { "brightness", "camera brightness" }, - { "camdevno", "camera device number" }, - { "camlist", "list all connected cameras" }, - { "ccdfanspeed", "fan speed of camera" }, - { "confio", "camera IO configuration" }, - { "dark", "don't open shutter @ exposure" }, - { "expstate", "get exposition state" }, - { "exptime", "exposition time" }, - { "fastspeed", "fast readout speed" }, - { "filename", "save file with this name, like file.fits" }, - { "filenameprefix", "prefix of files, like ex (will be saved as exXXXX.fits)" }, - { "focdevno", "focuser device number" }, - { "foclist", "list all connected focusers" }, - { "focpos", "focuser position" }, - { "format", "camera frame format (X0,Y0,X1,Y1)" }, - { "gain", "camera gain" }, - { "hbin", "horizontal binning" }, - { "headerfiles", "add FITS records from these files (comma-separated list)" }, - { "help", "show this help" }, - { "info", "connected devices state" }, - { "instrument", "FITS 'INSTRUME' field" }, - { "io", "get/set camera IO" }, - { "lastfilename", "path to last saved file"}, - { "maxformat", "camera maximal available format" }, - { "nflushes", "camera number of preflushes" }, - { "object", "FITS 'OBJECT' field" }, - { "objtype", "FITS 'IMAGETYP' field" }, - { "observer", "FITS 'OBSERVER' field" }, - { "program", "FITS 'PROG-ID' field" }, - { "rewrite", "rewrite file (if give `filename`, not `filenameprefix`" }, - { "shutter", "camera shutter's operations" }, - { "tcold", "camera chip temperature" }, - { "tremain", "time (in seconds) of exposition remained" }, - { "vbin", "vertical binning" }, - { "wdevno", "wheel device number" }, - { "wlist", "list all connected wheels" }, - { "wpos", "wheel position" }, + { CMD_8BIT, "run in 8 bit mode instead of 16 bit" }, + { CMD_AUTHOR, "FITS 'AUTHOR' field" }, + { CMD_BRIGHTNESS, "camera brightness" }, + { CMD_CAMDEVNO, "camera device number" }, + { CMD_CAMLIST, "list all connected cameras" }, + { CMD_CAMFANSPD, "fan speed of camera" }, + { CMD_CONFIO, "camera IO configuration" }, + { CMD_DARK, "don't open shutter @ exposure" }, + { CMD_EXPSTATE, "get exposition state" }, + { CMD_EXPOSITION, "exposition time" }, + { CMD_FASTSPD, "fast readout speed" }, + { CMD_FILENAME, "save file with this name, like file.fits" }, + { CMD_FILENAMEPREFIX,"prefix of files, like ex (will be saved as exXXXX.fits)" }, + { CMD_FDEVNO, "focuser device number" }, + { CMD_FOCLIST, "list all connected focusers" }, + { CMD_FGOTO, "focuser position" }, + { CMD_FRAMEFORMAT, "camera frame format (X0,Y0,X1,Y1)" }, + { CMD_GAIN, "camera gain" }, + { CMD_HBIN, "horizontal binning" }, + { CMD_HEADERFILES, "add FITS records from these files (comma-separated list)" }, + { CMD_HELP, "show this help" }, + { CMD_INFO, "connected devices state" }, + { CMD_INSTRUMENT, "FITS 'INSTRUME' field" }, + { CMD_IO, "get/set camera IO" }, + { CMD_LASTFNAME, "path to last saved file"}, + { CMD_FRAMEMAX, "camera maximal available format" }, + { CMD_NFLUSHES, "camera number of preflushes" }, + { CMD_OBJECT, "FITS 'OBJECT' field" }, + { CMD_OBJTYPE, "FITS 'IMAGETYP' field" }, + { CMD_OBSERVER, "FITS 'OBSERVER' field" }, + { CMD_PROGRAM, "FITS 'PROG-ID' field" }, + { CMD_RESTART, "restart server" }, + { CMD_REWRITE, "rewrite file (if give `filename`, not `filenameprefix`" }, + { CMD_SHUTTER, "camera shutter's operations" }, + { CMD_CAMTEMPER, "camera chip temperature" }, + { CMD_TREMAIN, "time (in seconds) of exposition remained" }, + { CMD_VBIN, "vertical binning" }, + { CMD_WDEVNO, "wheel device number" }, + { CMD_WLIST, "list all connected wheels" }, + { CMD_WPOS, "wheel position" }, {NULL, NULL}, }; static IMG ima = {0}; static void fixima(){ FNAME(); + if(!camera) return; int raw_width = curformat.w / GP->hbin, raw_height = curformat.h / GP->vbin; + if(!ima.data) ima.data = MALLOC(uint16_t, camera->array.h * camera->array.w); if(ima.data && raw_width == ima.w && raw_height == ima.h) return; // all OK - FREE(ima.data); DBG("curformat: %dx%d", curformat.w, curformat.h); ima.h = raw_height; ima.w = raw_width; - ima.data = MALLOC(uint16_t, raw_width * raw_height); DBG("new image: %dx%d", raw_width, raw_height); } @@ -126,6 +127,7 @@ static inline void cameraidlestate(){ // idle - wait for capture commands static inline void cameracapturestate(){ // capturing - wait for exposition ends if(camflags & FLAG_CANCEL){ // cancel all expositions DBG("Cancel exposition"); + LOGMSG("User canceled exposition"); camflags &= ~(FLAG_STARTCAPTURE | FLAG_CANCEL); camera->cancel(); camstate = CAMERA_IDLE; @@ -166,34 +168,38 @@ static void* processCAM(_U_ void *d){ LOGERR("User asks to restart"); signals(1); } - // log - if(dtime() - logt > TLOG_PAUSE){ - logt = dtime(); - float t; - if(camera->getTcold(&t)){ - LOGMSG("CCDTEMP=%f", t); + usleep(100); + if(0 == pthread_mutex_trylock(&locmutex)){ + // log + if(dtime() - logt > TLOG_PAUSE){ + logt = dtime(); + float t; + if(camera->getTcold(&t)){ + LOGMSG("CCDTEMP=%.1f", t); + } + if(camera->getThot(&t)){ + LOGMSG("HOTTEMP=%.1f", t); + } + if(camera->getTbody(&t)){ + LOGMSG("BODYTEMP=%.1f", t); + } } - if(camera->getThot(&t)){ - LOGMSG("HOTTEMP=%f", t); + camera_state curstate = camstate; + switch(curstate){ + case CAMERA_IDLE: + cameraidlestate(); + break; + case CAMERA_CAPTURE: + cameracapturestate(); + break; + case CAMERA_FRAMERDY: + // do nothing: when `server` got this state it sends "expstate=2" to all clients and changes state to IDLE + break; + case CAMERA_ERROR: + // do nothing: when `server` got this state it sends "expstate=3" to all clients and changes state to IDLE + break; } - if(camera->getTbody(&t)){ - LOGMSG("BODYTEMP=%f", t); - } - } - camera_state curstate = camstate; - switch(curstate){ - case CAMERA_IDLE: - cameraidlestate(); - break; - case CAMERA_CAPTURE: - cameracapturestate(); - break; - case CAMERA_FRAMERDY: -// do nothing: when `server` got this state it sends "expstate=2" to all clients and changes state to IDLE - break; - case CAMERA_ERROR: -// do nothing: when `server` got this state it sends "expstate=3" to all clients and changes state to IDLE - break; + pthread_mutex_unlock(&locmutex); } } return NULL; @@ -202,10 +208,8 @@ static void* processCAM(_U_ void *d){ // functions running @ each devno change static int camdevini(int n){ if(!camera) return FALSE; - //pthread_mutex_lock(&locmutex); if(!camera->setDevNo(n)){ LOGERR("Can't set active camera number"); - //pthread_mutex_unlock(&locmutex); return FALSE; } camdevno = n; @@ -218,36 +222,29 @@ static int camdevini(int n){ fixima(); if(!camera->setbin(GP->hbin, GP->vbin)) WARNX(_("Can't set binning %dx%d"), GP->hbin, GP->vbin); if(!camera->setgeometry(&curformat)) WARNX(_("Can't set given geometry")); - //pthread_mutex_unlock(&locmutex); return TRUE; } static int focdevini(int n){ if(!focuser) return FALSE; - //pthread_mutex_lock(&locmutex); if(!focuser->setDevNo(n)){ LOGERR("Can't set active focuser number"); - //pthread_mutex_unlock(&locmutex); return FALSE; } focdevno = n; LOGMSG("Set focuser device number to %d", focdevno); focuser->getMaxPos(&focmaxpos); focuser->getMinPos(&focminpos); - //pthread_mutex_unlock(&locmutex); return TRUE; } static int wheeldevini(int n){ if(!wheel) return FALSE; - //pthread_mutex_unlock(&locmutex); if(!wheel->setDevNo(n)){ LOGERR("Can't set active wheel number"); - //pthread_mutex_unlock(&locmutex); return FALSE; } wheeldevno = n; LOGMSG("Set wheel device number to %d", wheeldevno); wheel->getMaxPos(&wmaxpos); - //pthread_mutex_unlock(&locmutex); return TRUE; } @@ -264,15 +261,13 @@ static hresult restarthandler(_U_ int fd, _U_ const char *key, _U_ const char *v ******************************************************************************/ static hresult camlisthandler(int fd, _U_ const char *key, _U_ const char *val){ char buf[BUFSIZ], modname[256]; - //pthread_mutex_lock(&locmutex); for(int i = 0; i < camera->Ndevices; ++i){ if(!camera->setDevNo(i)) continue; camera->getModelName(modname, 255); snprintf(buf, BUFSIZ-1, CMD_CAMLIST "='%s'", modname); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } if(camdevno > -1) camera->setDevNo(camdevno); - //pthread_mutex_unlock(&locmutex); return RESULT_SILENCE; } static hresult camsetNhandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ @@ -285,61 +280,55 @@ static hresult camsetNhandler(_U_ int fd, _U_ const char *key, _U_ const char *v if(!camdevini(num)) return RESULT_FAIL; } snprintf(buf, 63, CMD_CAMDEVNO "=%d", camdevno); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } // exposition time setter/getter static hresult exphandler(int fd, _U_ const char *key, const char *val){ char buf[64]; if(val){ + DBG("setexp to %s", val); double v = atof(val); if(v < DBL_EPSILON) return RESULT_BADVAL; - //pthread_mutex_lock(&locmutex); if(camera->setexp(v)){ GP->exptime = v; }else LOGWARN("Can't set exptime to %g", v); - //pthread_mutex_unlock(&locmutex); } + DBG("expt: %g", GP->exptime); snprintf(buf, 63, CMD_EXPOSITION "=%g", GP->exptime); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } // show last filename of saved FITS static hresult lastfnamehandler(int fd, _U_ const char *key, _U_ const char *val){ char buf[PATH_MAX+32]; - //pthread_mutex_lock(&locmutex); snprintf(buf, PATH_MAX+31, CMD_LASTFNAME "=%s", lastfile); - sendstrmessage(fd, buf); - //pthread_mutex_unlock(&locmutex); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } // filename setter/getter static hresult namehandler(int fd, _U_ const char *key, const char *val){ char buf[PATH_MAX+32]; if(val){ - //pthread_mutex_lock(&locmutex); char *path = makeabspath(val, FALSE); if(!path){ LOGERR("Can't create file '%s'", val); - //pthread_mutex_unlock(&locmutex); return RESULT_BADVAL; } FREE(outfile); outfile = strdup(path); GP->outfile = outfile; GP->outfileprefix = NULL; - //pthread_mutex_unlock(&locmutex); } if(!GP->outfile) return RESULT_FAIL; snprintf(buf, PATH_MAX+31, CMD_FILENAME "=%s", GP->outfile); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } // filename prefix static hresult nameprefixhandler(_U_ int fd, _U_ const char *key, const char *val){ char buf[PATH_MAX+32]; if(val){ - //pthread_mutex_lock(&locmutex); char *path = makeabspath(val, FALSE); if(!path){ LOGERR("Can't create file '%s'", val); @@ -350,11 +339,10 @@ static hresult nameprefixhandler(_U_ int fd, _U_ const char *key, const char *va outfile = strdup(path); GP->outfileprefix = outfile; GP->outfile = NULL; - //pthread_mutex_unlock(&locmutex); } if(!GP->outfileprefix) return RESULT_FAIL; snprintf(buf, PATH_MAX+31, CMD_FILENAMEPREFIX "=%s", GP->outfileprefix); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } // rewrite @@ -363,12 +351,10 @@ static hresult rewritefilehandler(_U_ int fd, _U_ const char *key, const char *v if(val){ int n = atoi(val); if(n < 0 || n > 1) return RESULT_BADVAL; - //pthread_mutex_lock(&locmutex); GP->rewrite = n; - //pthread_mutex_unlock(&locmutex); } snprintf(buf, 63, CMD_REWRITE "=%d", GP->rewrite); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult binhandler(_U_ int fd, const char *key, const char *val){ @@ -378,21 +364,16 @@ static hresult binhandler(_U_ int fd, const char *key, const char *val){ if(b < 1) return RESULT_BADVAL; if(0 == strcmp(key, CMD_HBIN)) GP->hbin = b; else GP->vbin = b; - //pthread_mutex_lock(&locmutex); if(!camera->setbin(GP->hbin, GP->vbin)){ - //pthread_mutex_unlock(&locmutex); return RESULT_BADVAL; } - fixima(); - //pthread_mutex_unlock(&locmutex); } - //pthread_mutex_lock(&locmutex); int r = camera->getbin(&GP->hbin, &GP->vbin); - //pthread_mutex_unlock(&locmutex); if(r){ if(0 == strcmp(key, CMD_HBIN)) snprintf(buf, 63, "%s=%d", key, GP->hbin); else snprintf(buf, 63, "%s=%d", key, GP->vbin); - sendstrmessage(fd, buf); + if(val) fixima(); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } return RESULT_FAIL; @@ -403,34 +384,26 @@ static hresult temphandler(_U_ int fd, _U_ const char *key, const char *val){ int r; if(val){ f = atof(val); - //pthread_mutex_lock(&locmutex); r = camera->setT((float)f); - //pthread_mutex_unlock(&locmutex); if(!r){ LOGWARN("Can't set camera T to %.1f", f); return RESULT_FAIL; } LOGMSG("Set camera T to %.1f", f); } - //pthread_mutex_lock(&locmutex); r = camera->getTcold(&f); - //pthread_mutex_unlock(&locmutex); if(r){ snprintf(buf, 63, CMD_CAMTEMPER "=%.1f", f); - sendstrmessage(fd, buf); - //pthread_mutex_lock(&locmutex); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; r = camera->getTbody(&f); - //pthread_mutex_unlock(&locmutex); if(r){ snprintf(buf, 63, "tbody=%.1f", f); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } - //pthread_mutex_lock(&locmutex); r = camera->getThot(&f); - //pthread_mutex_unlock(&locmutex); if(r){ snprintf(buf, 63, "thot=%.1f", f); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } return RESULT_SILENCE; }else return RESULT_FAIL; @@ -441,14 +414,12 @@ static hresult camfanhandler(_U_ int fd, _U_ const char *key, _U_ const char *va int spd = atoi(val); if(spd < 0) return RESULT_BADVAL; if(spd > FAN_HIGH) spd = FAN_HIGH; - //pthread_mutex_lock(&locmutex); int r = camera->setfanspeed((fan_speed)spd); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; camfanspd = spd; } snprintf(buf, 63, CMD_CAMFANSPD "=%d", camfanspd); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } const char *shutterstr[] = {"open", "close", "expose @high", "expose @low"}; @@ -456,9 +427,7 @@ static hresult shutterhandler(_U_ int fd, _U_ const char *key, const char *val){ if(val){ int x = atoi(val); if(x < 0 || x >= SHUTTER_AMOUNT) return RESULT_BADVAL; - //pthread_mutex_lock(&locmutex); int r = camera->shuttercmd((shutter_op)x); - //pthread_mutex_unlock(&locmutex); if(r){ LOGMSG("Shutter command '%s'", shutterstr[x]); }else{ @@ -472,14 +441,12 @@ static hresult confiohandler(_U_ int fd, _U_ const char *key, _U_ const char *va char buf[64]; if(val){ int io = atoi(val); - //pthread_mutex_lock(&locmutex); int r = camera->confio(io); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; confio = io; } snprintf(buf, 63, CMD_CONFIO "=%d", confio); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult iohandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ @@ -487,17 +454,13 @@ static hresult iohandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ int io; if(val){ io = atoi(val); - //pthread_mutex_lock(&locmutex); int r = camera->setio(io); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; } - //pthread_mutex_lock(&locmutex); int r = camera->getio(&io); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; snprintf(buf, 63, CMD_IO "=%d", io); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult gainhandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ @@ -505,17 +468,13 @@ static hresult gainhandler(_U_ int fd, _U_ const char *key, _U_ const char *val) float f; if(val){ f = atof(val); - //pthread_mutex_lock(&locmutex); int r = camera->setgain(f); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; } - //pthread_mutex_lock(&locmutex); int r = camera->getgain(&f); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; snprintf(buf, 63, CMD_GAIN "=%.1f", f); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult brightnesshandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ @@ -523,17 +482,13 @@ static hresult brightnesshandler(_U_ int fd, _U_ const char *key, _U_ const char float b; if(val){ b = atof(val); - //pthread_mutex_lock(&locmutex); int r = camera->setbrightness(b); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; } - //pthread_mutex_lock(&locmutex); int r = camera->getbrightness(&b); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; snprintf(buf, 63, CMD_BRIGHTNESS "=%.1f", b); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } // set format: `format=X0,X1,Y0,Y1` @@ -545,9 +500,7 @@ static hresult formathandler(int fd, const char *key, const char *val){ if(strcmp(key, CMD_FRAMEFORMAT)) return RESULT_BADKEY; // can't set maxformat if(4 != sscanf(val, "%d,%d,%d,%d", &fmt.xoff, &fmt.yoff, &fmt.w, &fmt.h)) return RESULT_BADVAL; fmt.w -= fmt.xoff; fmt.h -= fmt.yoff; - //pthread_mutex_lock(&locmutex); int r = camera->setgeometry(&fmt); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; curformat = fmt; fixima(); @@ -556,7 +509,7 @@ static hresult formathandler(int fd, const char *key, const char *val){ frmformatmax.xoff, frmformatmax.yoff, frmformatmax.xoff+frmformatmax.w, frmformatmax.yoff+frmformatmax.h); else snprintf(buf, 63, CMD_FRAMEFORMAT "=%d,%d,%d,%d", camera->geometry.xoff, camera->geometry.yoff, camera->geometry.xoff+camera->geometry.w, camera->geometry.yoff+camera->geometry.h); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult nflusheshandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ @@ -564,16 +517,13 @@ static hresult nflusheshandler(_U_ int fd, _U_ const char *key, _U_ const char * if(val){ int n = atoi(val); if(n < 1) return RESULT_BADVAL; - //pthread_mutex_lock(&locmutex); if(!camera->setnflushes(n)){ - //pthread_mutex_unlock(&locmutex); return RESULT_FAIL; } nflushes = n; - //pthread_mutex_unlock(&locmutex); } snprintf(buf, 63, CMD_NFLUSHES "=%d", nflushes); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult expstatehandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ @@ -591,15 +541,15 @@ static hresult expstatehandler(_U_ int fd, _U_ const char *key, _U_ const char * else return RESULT_BADVAL; } snprintf(buf, 63, CMD_EXPSTATE "=%d", camstate); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; snprintf(buf, 63, "camflags=%d", camflags); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult tremainhandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ char buf[64]; snprintf(buf, 63, CMD_TREMAIN "=%g", tremain); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult _8bithandler(int fd, _U_ const char *key, const char *val){ @@ -612,7 +562,7 @@ static hresult _8bithandler(int fd, _U_ const char *key, const char *val){ if(!camera->setbitdepth(s)) return RESULT_FAIL; } snprintf(buf, 63, CMD_8BIT "=%d", GP->_8bit); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult fastspdhandler(int fd, _U_ const char *key, const char *val){ @@ -624,7 +574,7 @@ static hresult fastspdhandler(int fd, _U_ const char *key, const char *val){ if(!camera->setfastspeed(b)) return RESULT_FAIL; } snprintf(buf, 63, CMD_FASTSPD "=%d", GP->fast); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult darkhandler(int fd, _U_ const char *key, const char *val){ @@ -637,7 +587,7 @@ static hresult darkhandler(int fd, _U_ const char *key, const char *val){ if(!camera->setframetype(d)) return RESULT_FAIL; } snprintf(buf, 63, CMD_DARK "=%d", GP->dark); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult FITSparhandler(int fd, const char *key, const char *val){ @@ -660,7 +610,7 @@ static hresult FITSparhandler(int fd, const char *key, const char *val){ *fitskey = strdup(val); } snprintf(buf, 255, "%s=%s", key, *fitskey); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult FITSheaderhandler(int fd, _U_ const char *key, const char *val){ @@ -669,7 +619,6 @@ static hresult FITSheaderhandler(int fd, _U_ const char *key, const char *val){ static int firstrun = 1; if(val){ int sz = 10, amount = 0; - //pthread_mutex_lock(&locmutex); // first we should check `val` char b2[BUFSIZ], *bptr = buf; snprintf(b2, BUFSIZ-1, "%s", val); @@ -715,9 +664,8 @@ static hresult FITSheaderhandler(int fd, _U_ const char *key, const char *val){ } GP->addhdr = list; FREE(curhdr); - if(*val && *val != ',') curhdr = strdup(buf); + if(*val && *val != ',') curhdr = strdup(buf); // command with empty arg will clear curhdr DBG("curhdr now: %s", curhdr); - //pthread_mutex_unlock(&locmutex); } if(!curhdr && firstrun){ firstrun = 0; @@ -734,7 +682,7 @@ static hresult FITSheaderhandler(int fd, _U_ const char *key, const char *val){ } } snprintf(buf, BUFSIZ-1, CMD_HEADERFILES "=%s", curhdr); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } /* @@ -748,16 +696,14 @@ static hresult handler(_U_ int fd, _U_ const char *key, _U_ const char *val){ ******************************************************************************/ static hresult wlisthandler(int fd, _U_ const char *key, _U_ const char *val){ if(wheel->Ndevices < 1) return RESULT_FAIL; - //pthread_mutex_lock(&locmutex); for(int i = 0; i < wheel->Ndevices; ++i){ if(!wheel->setDevNo(i)) continue; char modname[256], buf[BUFSIZ]; wheel->getModelName(modname, 255); snprintf(buf, BUFSIZ-1, CMD_WLIST "='%s'", modname); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } if(wheeldevno > -1) wheel->setDevNo(wheeldevno); - //pthread_mutex_unlock(&locmutex); return RESULT_SILENCE; } static hresult wsetNhandler(int fd, _U_ const char *key, const char *val){ @@ -770,7 +716,7 @@ static hresult wsetNhandler(int fd, _U_ const char *key, const char *val){ if(!wheeldevini(num)) return RESULT_FAIL; } snprintf(buf, 63, CMD_WDEVNO "=%d", wheeldevno); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } @@ -779,17 +725,15 @@ static hresult wgotohandler(_U_ int fd, _U_ const char *key, _U_ const char *val int pos; if(val){ pos = atoi(val); - //pthread_mutex_lock(&locmutex); + DBG("USER wants to %d", pos); int r = wheel->setPos(pos); - //pthread_mutex_unlock(&locmutex); + DBG("wheel->setPos(%d)", pos); if(!r) return RESULT_BADVAL; } - //pthread_mutex_lock(&locmutex); int r = wheel->getPos(&pos); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; snprintf(buf, 63, CMD_WPOS "=%d", pos); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } @@ -799,16 +743,14 @@ static hresult wgotohandler(_U_ int fd, _U_ const char *key, _U_ const char *val static hresult foclisthandler(int fd, _U_ const char *key, _U_ const char *val){ if(focuser->Ndevices < 1) return RESULT_FAIL; - //pthread_mutex_lock(&locmutex); for(int i = 0; i < focuser->Ndevices; ++i){ char modname[256], buf[BUFSIZ]; if(!focuser->setDevNo(i)) continue; focuser->getModelName(modname, 255); snprintf(buf, BUFSIZ-1, CMD_FOCLIST "='%s'", modname); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } if(focdevno > -1) focuser->setDevNo(focdevno); - //pthread_mutex_unlock(&locmutex); return RESULT_SILENCE; } static hresult fsetNhandler(int fd, _U_ const char *key, const char *val){ @@ -821,7 +763,7 @@ static hresult fsetNhandler(int fd, _U_ const char *key, const char *val){ if(!focdevini(num)) return RESULT_FAIL; } snprintf(buf, 63, CMD_FDEVNO "=%d", focdevno); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } static hresult fgotohandler(int fd, _U_ const char *key, const char *val){ @@ -831,21 +773,17 @@ static hresult fgotohandler(int fd, _U_ const char *key, const char *val){ if(val){ f = atof(val); if(f < focminpos || f > focmaxpos) return RESULT_BADVAL; - //pthread_mutex_lock(&locmutex); if(f - focminpos < __FLT_EPSILON__){ r = focuser->home(1); }else{ r = focuser->setAbsPos(1, f); } - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; } - //pthread_mutex_lock(&locmutex); r = focuser->getPos(&f); - //pthread_mutex_unlock(&locmutex); if(!r) return RESULT_FAIL; snprintf(buf, 63, CMD_FGOTO "=%g", f); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } @@ -861,48 +799,52 @@ static hresult infohandler(int fd, _U_ const char *key, _U_ const char *val){ if(camera){ if(camera->getModelName(buf1, 255)){ snprintf(buf, BUFSIZ-1, CMD_CAMLIST "='%s'", buf1); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } - namehandler(fd, CMD_FILENAME, NULL); - binhandler(fd, CMD_HBIN, NULL); - binhandler(fd, CMD_VBIN, NULL); - temphandler(fd, CMD_CAMTEMPER, NULL); - exphandler(fd, CMD_EXPOSITION, NULL); - lastfnamehandler(fd, CMD_LASTFNAME, NULL); - expstatehandler(fd, CMD_EXPSTATE, NULL); +#define RUN(f, arg) do{if(RESULT_DISCONNECTED == f(fd, arg, NULL)) return RESULT_DISCONNECTED;}while(0) + RUN(namehandler, CMD_FILENAME); + RUN(binhandler, CMD_HBIN); + RUN(binhandler, CMD_VBIN); + RUN(temphandler, CMD_CAMTEMPER); + RUN(exphandler, CMD_EXPOSITION); + RUN(lastfnamehandler, CMD_LASTFNAME); + RUN(expstatehandler, CMD_EXPSTATE); +#undef RUN } + DBG("chk wheel"); if(wheel){ + DBG("Wname"); if(wheel->getModelName(buf1, 255)){ snprintf(buf, BUFSIZ-1, CMD_WLIST "='%s'", buf1); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } if(wheel->getTbody(&f)){ snprintf(buf, BUFSIZ-1, "wtemp=%.1f", f); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } if(wheel->getPos(&i)){ snprintf(buf, BUFSIZ-1, CMD_WPOS "=%d", i); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } snprintf(buf, BUFSIZ-1, "wmaxpos=%d", wmaxpos); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } if(focuser){ if(focuser->getModelName(buf1, 255)){ snprintf(buf, BUFSIZ-1, CMD_FOCLIST "='%s'", buf1); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } if(focuser->getTbody(&f)){ snprintf(buf, BUFSIZ-1, "foctemp=%.1f", f); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } snprintf(buf, BUFSIZ-1, "focminpos=%g", focminpos); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; snprintf(buf, BUFSIZ-1, "focmaxpos=%g", focmaxpos); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; if(focuser->getPos(&f)){ snprintf(buf, BUFSIZ-1, CMD_FGOTO "=%g", f); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; } } return RESULT_SILENCE; @@ -913,7 +855,7 @@ static hresult helphandler(int fd, _U_ const char *key, _U_ const char *val){ strpair *ptr = allcommands; while(ptr->key){ snprintf(buf, 255, "%s - %s", ptr->key, ptr->help); - sendstrmessage(fd, buf); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; ++ptr; } return RESULT_SILENCE; @@ -927,7 +869,10 @@ static int CAMbusy(){ } return FALSE; } - +// check funtions +static hresult chktrue(_U_ char *val){ // dummy check for `infohandler` (need to lock mutex anymore) + return RESULT_OK; +} static hresult chkcam(char *val){ if(val && CAMbusy()) return RESULT_BUSY; if(camera) return RESULT_OK; @@ -944,7 +889,7 @@ static hresult chkfoc(char *val){ return RESULT_FAIL; } static handleritem items[] = { - {NULL, infohandler, CMD_INFO}, + {chktrue,infohandler, CMD_INFO}, {NULL, helphandler, CMD_HELP}, {NULL, restarthandler, CMD_RESTART}, {chkcam, camlisthandler, CMD_CAMLIST}, @@ -991,12 +936,12 @@ static handleritem items[] = { void server(int sock){ // init everything - startCCD(&camdev); - camdevini(0); startFocuser(&focdev); focdevini(0); startWheel(&wheeldev); wheeldevini(0); + startCCD(&camdev); + camdevini(0); if(listen(sock, MAXCLIENTS) == -1){ WARN("listen"); LOGWARN("listen"); diff --git a/socket.c b/socket.c index 170542e..833ca65 100644 --- a/socket.c +++ b/socket.c @@ -18,7 +18,6 @@ #include // isspace #include -#include #include #include #include @@ -30,7 +29,7 @@ #include "server.h" #include "socket.h" -static pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/camera/focuser functions +pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/camera/focuser functions /** * @brief start_socket - create socket and run client or server @@ -82,26 +81,28 @@ int start_socket(int isserver, char *path, int isnet){ if(isserver){ int reuseaddr = 1; if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){ - LOGWARN("setsockopt()"); WARN("setsockopt()"); + LOGWARN("setsockopt()"); close(sock); sock = -1; continue; } if(bind(sock, p->ai_addr, p->ai_addrlen) == -1){ - LOGWARN("bind()"); WARN("bind()"); + LOGWARN("bind()"); close(sock); sock = -1; continue; } + /* int enable = 1; if(ioctl(sock, FIONBIO, (void *)&enable) < 0){ // make socket nonblocking - LOGERR("Can't make socket nonblocking"); - ERRX("ioctl()"); + WARN("ioctl()"); + LOGWARN("Can't make socket nonblocking"); } + */ }else{ if(connect(sock, p->ai_addr, p->ai_addrlen) == -1){ - LOGWARN("connect()"); WARN("connect()"); + LOGWARN("connect()"); close(sock); sock = -1; } } @@ -121,27 +122,34 @@ int start_socket(int isserver, char *path, int isnet){ } // simple wrapper over write: add missed newline and log data -void sendmessage(int fd, const char *msg, int l){ - if(fd < 1 || !msg || l < 1) return; +int sendmessage(int fd, const char *msg, int l){ + if(fd < 1 || !msg || l < 1) return TRUE; // empty message + static char *tmpbuf = NULL; + static int buflen = 0; + if(l + 1 > buflen){ + buflen += 1024; + tmpbuf = realloc(tmpbuf, buflen); + } DBG("send to fd %d: %s [%d]", fd, msg, l); - char *tmpbuf = MALLOC(char, l+1); memcpy(tmpbuf, msg, l); if(msg[l-1] != '\n') tmpbuf[l++] = '\n'; - if(l != write(fd, tmpbuf, l)){ - LOGWARN("write()"); + if(l != send(fd, tmpbuf, l, MSG_NOSIGNAL)){ WARN("write()"); + LOGWARN("write()"); + return FALSE; }else{ + DBG("success"); if(globlog){ // logging turned ON tmpbuf[l-1] = 0; // remove trailing '\n' for logging LOGDBG("SEND '%s'", tmpbuf); } } - FREE(tmpbuf); + return TRUE; } -void sendstrmessage(int fd, const char *msg){ - if(fd < 1 || !msg) return; +int sendstrmessage(int fd, const char *msg){ + if(fd < 1 || !msg) return FALSE; int l = strlen(msg); - sendmessage(fd, msg, l); + return sendmessage(fd, msg, l); } // text messages for `hresult` @@ -165,7 +173,7 @@ const char *hresult2str(hresult r){ * @return `val` */ char *get_keyval(char *keyval){ - DBG("Got string %s", keyval); + //DBG("Got string %s", keyval); // remove starting spaces in key while(isspace(*keyval)) ++keyval; char *val = strchr(keyval, '='); @@ -178,32 +186,49 @@ char *get_keyval(char *keyval){ while(isspace(*e) && e > keyval) --e; e[1] = 0; // now we have key (`str`) and val (or NULL) - DBG("key=%s, val=%s", keyval, val); + //DBG("key=%s, val=%s", keyval, val); return val; } // parse string of data (command or key=val) // the CONTENT of buffer `str` WILL BE BROKEN! -static void parsestring(int fd, handleritem *handlers, char *str){ - if(fd < 1 || !handlers || !handlers->key || !str || !*str) return; +// @return FALSE if client closed (nothing to read) +static int parsestring(int fd, handleritem *handlers, char *str){ + if(fd < 1 || !handlers || !handlers->key || !str || !*str) return FALSE; char *val = get_keyval(str); - if(val) LOGDBG("RECEIVE '%s=%s'", str, val); - else LOGDBG("RECEIVE '%s'", str); + if(val){ + DBG("RECEIVE '%s=%s'", str, val); + LOGDBG("RECEIVE '%s=%s'", str, val); + }else{ + DBG("RECEIVE '%s'", str); + LOGDBG("RECEIVE '%s'", str); + } for(handleritem *h = handlers; h->key; ++h){ if(strcmp(str, h->key) == 0){ // found command - pthread_mutex_lock(&locmutex); hresult r = RESULT_OK; - if(h->chkfunction) r = h->chkfunction(val); + int l = 1; + if(h->chkfunction){ + double t0 = dtime(); + do{ l = pthread_mutex_trylock(&locmutex); }while(l && dtime() - t0 > BUSY_TIMEOUT); + if(l){ + DBG("Can't lock mutex"); + return RESULT_BUSY; // long blocking work + } + r = h->chkfunction(val); + } // else NULL instead of chkfuntion -> don't check and don't lock mutex if(r == RESULT_OK){ // no test function or it returns TRUE if(h->handler) r = h->handler(fd, str, val); else r = RESULT_FAIL; } - pthread_mutex_unlock(&locmutex); - sendstrmessage(fd, hresult2str(r)); - return; + if(!l) pthread_mutex_unlock(&locmutex); + if(r == RESULT_DISCONNECTED){ + DBG("handler return RESULT_DISCONNECTED"); + return FALSE; + } + return sendstrmessage(fd, hresult2str(r)); } } - sendstrmessage(fd, resmessages[RESULT_BADKEY]); + return sendstrmessage(fd, resmessages[RESULT_BADKEY]); } /** @@ -218,17 +243,20 @@ int processData(int fd, handleritem *handlers, char *buf, int buflen){ int curlen = strlen(buf); if(curlen == buflen-1) curlen = 0; // buffer overflow - clear old content ssize_t rd = read(fd, buf + curlen, buflen-1 - curlen); - if(rd <= 0) return FALSE; - DBG("got %s[%zd] from %d", buf, rd, fd); + if(rd <= 0){ + //DBG("read %zd bytes from client", rd); + return FALSE; + } + //DBG("got %s[%zd] from %d", buf, rd, fd); char *restofdata = buf, *eptr = buf + curlen + rd; *eptr = 0; do{ char *nl = strchr(restofdata, '\n'); if(!nl) break; *nl++ = 0; - parsestring(fd, handlers, restofdata); + if(!parsestring(fd, handlers, restofdata)) return FALSE; // client disconnected restofdata = nl; - DBG("rest of data: %s", restofdata); + //DBG("rest of data: %s", restofdata); }while(1); if(restofdata != buf) memmove(buf, restofdata, eptr - restofdata + 1); return TRUE; diff --git a/socket.h b/socket.h index 5212aee..51e0201 100644 --- a/socket.h +++ b/socket.h @@ -20,6 +20,8 @@ #ifndef SERSOCK_H__ #define SERSOCK_H__ +#include + // max & min TCP socket port number #define PORTN_MAX (65535) #define PORTN_MIN (1024) @@ -28,6 +30,17 @@ // Max amount of connections #define MAXCLIENTS (30) +// wait for mutex locking +#define BUSY_TIMEOUT (0.3) +// waiting for answer timeout +#define ANSWER_TIMEOUT (1.0) +// wait for exposition ends (between subsequent check calls) +#define WAIT_TIMEOUT (2.0) +// client will disconnect after this time from last server message +#define CLIENT_TIMEOUT (10.0) + +extern pthread_mutex_t locmutex; + typedef enum{ RESULT_OK, // all OK RESULT_BUSY, // camera busy and no setters can be done @@ -35,6 +48,7 @@ typedef enum{ RESULT_BADVAL, // bad key's value RESULT_BADKEY, // bad key RESULT_SILENCE, // send nothing to client + RESULT_DISCONNECTED,// client disconnected RESULT_NUM } hresult; @@ -50,8 +64,8 @@ typedef struct{ } handleritem; int start_socket(int server, char *path, int isnet); -void sendmessage(int fd, const char *msg, int l); -void sendstrmessage(int fd, const char *msg); +int sendmessage(int fd, const char *msg, int l); +int sendstrmessage(int fd, const char *msg); char *get_keyval(char *keyval); int processData(int fd, handleritem *handlers, char *buf, int buflen);