diff --git a/client.c b/client.c index e701438..1cd4b37 100644 --- a/client.c +++ b/client.c @@ -32,8 +32,10 @@ #include "socket.h" static char sendbuf[BUFSIZ]; -// send any message and wait any answer +// send message and wait any answer #define SENDMSG(...) do{snprintf(sendbuf, BUFSIZ-1, __VA_ARGS__); verbose(2, "\t> %s", sendbuf); sendstrmessage(sock, sendbuf); getans(sock, NULL);}while(0) +// send message and wait answer starting with 'cmd' +#define SENDMSGW(cmd, ...) do{snprintf(sendbuf, BUFSIZ-1, cmd __VA_ARGS__); verbose(2, "\t> %s", sendbuf); sendstrmessage(sock, sendbuf); getans(sock, cmd);}while(0) // send command and wait for answer on it #define SENDCMDW(cmd) do{strncpy(sendbuf, cmd, BUFSIZ-1); verbose(2, "\t> %s", sendbuf); sendstrmessage(sock, sendbuf); getans(sock, cmd);}while(0) static volatile atomic_int expstate = CAMERA_CAPTURE; @@ -143,59 +145,63 @@ static void send_headers(int sock){ if(GP->listdevices) SENDMSG(CMD_FOCLIST); if(GP->focdevno > -1) SENDMSG(CMD_FDEVNO "=%d", GP->focdevno); if(!isnan(GP->gotopos)){ - SENDMSG(CMD_FGOTO "=%g", GP->gotopos); + SENDMSGW(CMD_FGOTO, "=%g", GP->gotopos); } // wheel - if(GP->listdevices) SENDMSG(CMD_WLIST); - if(GP->whldevno > -1) SENDMSG(CMD_WDEVNO "=%d", GP->whldevno); - if(GP->setwheel > -1) SENDMSG(CMD_WPOS "=%d", GP->setwheel); + if(GP->listdevices) SENDCMDW(CMD_WLIST); + if(GP->whldevno > -1) SENDMSGW(CMD_WDEVNO, "=%d", GP->whldevno); + if(GP->setwheel > -1) SENDMSGW(CMD_WPOS, "=%d", GP->setwheel); DBG("nxt"); // CCD/CMOS - if(GP->X0 > -1 || GP->Y0 > -1 || GP->X1 > -1 || GP->Y1 > -1){ // set format - SENDMSG(CMD_FRAMEMAX); - SENDMSG(CMD_FRAMEFORMAT); - if(GP->X0 < 0) GP->X0 = xc0; // default values + if(GP->X0 > INT_MIN || GP->Y0 > INT_MIN || GP->X1 > INT_MIN || GP->Y1 > INT_MIN){ // set format + SENDCMDW(CMD_FRAMEMAX); + SENDCMDW(CMD_FRAMEFORMAT); + // default values + if(GP->X0 == INT_MIN) GP->X0 = xc0; + if(GP->X1 == INT_MIN) GP->X1 = xc1; + if(GP->Y0 == INT_MIN) GP->Y0 = yc0; + if(GP->Y1 == INT_MIN) GP->Y1 = yc1; + // limiting values + if(GP->X0 < 0) GP->X0 = xm0; else if(GP->X0 > xm1-1) GP->X0 = xm1-1; - if(GP->Y0 < 0) GP->Y0 = yc0; + if(GP->Y0 < 0) GP->Y0 = ym0; else if(GP->Y0 > ym1-1) GP->Y0 = ym1-1; - if(GP->X1 < GP->X0+1) GP->X1 = xc1; - else if(GP->X1 > xm1) GP->X1 = xm1; - if(GP->Y1 < GP->Y0+1) GP->Y1 = yc1; - else if(GP->Y1 > ym1) GP->Y1 = ym1; + if(GP->X1 < GP->X0+1 || GP->X1 > xm1) GP->X1 = xm1; + if(GP->Y1 < GP->Y0+1 || GP->Y1 > ym1) GP->Y1 = ym1; DBG("set format: (%d,%d)x(%d,%d)", GP->X0,GP->X1,GP->Y0,GP->Y1); - SENDMSG(CMD_FRAMEFORMAT "=%d,%d,%d,%d", GP->X0, GP->Y0, GP->X1, GP->Y1); + SENDMSGW(CMD_FRAMEFORMAT, "=%d,%d,%d,%d", GP->X0, GP->Y0, GP->X1, GP->Y1); } - if(GP->cancelexpose) SENDMSG(CMD_EXPSTATE "=%d", CAMERA_IDLE); - if(GP->listdevices) SENDMSG(CMD_CAMLIST); - if(GP->camdevno > -1) SENDMSG(CMD_CAMDEVNO "=%d", GP->camdevno); - if(GP->hbin) SENDMSG(CMD_HBIN "=%d", GP->hbin); - if(GP->vbin) SENDMSG(CMD_VBIN "=%d", GP->vbin); - if(!isnan(GP->temperature)) SENDMSG(CMD_CAMTEMPER "=%g", GP->temperature); - if(GP->shtr_cmd > -1) SENDMSG(CMD_SHUTTER "=%d", GP->shtr_cmd); - if(GP->confio > -1) SENDMSG(CMD_CONFIO "=%d", GP->confio); - if(GP->setio > -1) SENDMSG(CMD_IO "=%d", GP->setio);\ - if(!isnan(GP->gain)) SENDMSG(CMD_GAIN "=%g", GP->gain); - if(!isnan(GP->brightness)) SENDMSG(CMD_BRIGHTNESS "=%g", GP->brightness); - if(GP->nflushes > 0) SENDMSG(CMD_NFLUSHES "=%d", GP->nflushes); + if(GP->cancelexpose) SENDMSGW(CMD_EXPSTATE, "=%d", CAMERA_IDLE); + if(GP->listdevices) SENDCMDW(CMD_CAMLIST); + if(GP->camdevno > -1) SENDMSGW(CMD_CAMDEVNO, "=%d", GP->camdevno); + if(GP->hbin) SENDMSGW(CMD_HBIN, "=%d", GP->hbin); + if(GP->vbin) SENDMSGW(CMD_VBIN, "=%d", GP->vbin); + if(!isnan(GP->temperature)) SENDMSGW(CMD_CAMTEMPER, "=%g", GP->temperature); + if(GP->shtr_cmd > -1) SENDMSGW(CMD_SHUTTER, "=%d", GP->shtr_cmd); + if(GP->confio > -1) SENDMSGW(CMD_CONFIO, "=%d", GP->confio); + if(GP->setio > -1) SENDMSGW(CMD_IO, "=%d", GP->setio);\ + if(!isnan(GP->gain)) SENDMSGW(CMD_GAIN, "=%g", GP->gain); + if(!isnan(GP->brightness)) SENDMSGW(CMD_BRIGHTNESS, "=%g", GP->brightness); + if(GP->nflushes > 0) SENDMSGW(CMD_NFLUSHES, "=%d", GP->nflushes); if(GP->outfile || GP->outfileprefix){ // exposition and reading control: only if start of exposition - if(GP->_8bit) SENDMSG(CMD_8BIT "=1"); - else SENDMSG(CMD_8BIT "=0"); - if(GP->fast) SENDMSG(CMD_FASTSPD "=1"); - else SENDMSG(CMD_FASTSPD "=0"); - if(GP->dark) SENDMSG(CMD_DARK "=1"); - else SENDMSG(CMD_DARK "=0"); + if(GP->_8bit) SENDMSGW(CMD_8BIT, "=1"); + else SENDMSGW(CMD_8BIT, "=0"); + if(GP->fast) SENDMSGW(CMD_FASTSPD, "=1"); + else SENDMSGW(CMD_FASTSPD, "=0"); + if(GP->dark) SENDMSGW(CMD_DARK, "=1"); + else SENDMSGW(CMD_DARK, "=0"); } if(GP->outfile){ - if(!*GP->outfile) SENDMSG(CMD_FILENAME "="); - else SENDMSG(CMD_FILENAME "=%s", makeabspath(GP->outfile, FALSE)); - if(GP->rewrite) SENDMSG(CMD_REWRITE "=1"); - else SENDMSG(CMD_REWRITE "=0"); + if(!*GP->outfile) SENDMSGW(CMD_FILENAME, "="); + else SENDMSGW(CMD_FILENAME, "=%s", makeabspath(GP->outfile, FALSE)); + if(GP->rewrite) SENDMSGW(CMD_REWRITE, "=1"); + else SENDMSGW(CMD_REWRITE, "=0"); } if(GP->outfileprefix){ - if(!*GP->outfileprefix) SENDMSG(CMD_FILENAMEPREFIX "="); - else SENDMSG(CMD_FILENAMEPREFIX "=%s", makeabspath(GP->outfileprefix, FALSE)); + if(!*GP->outfileprefix) SENDMSGW(CMD_FILENAMEPREFIX, "="); + else SENDMSGW(CMD_FILENAMEPREFIX, "=%s", makeabspath(GP->outfileprefix, FALSE)); } - if(GP->exptime > -DBL_EPSILON) SENDMSG(CMD_EXPOSITION "=%g", GP->exptime); + if(GP->exptime > -DBL_EPSILON) SENDMSGW(CMD_EXPOSITION, "=%g", GP->exptime); // FITS header keywords: #define CHKHDR(x, cmd) do{if(x) SENDMSG(cmd "=%s", x);}while(0) CHKHDR(GP->author, CMD_AUTHOR); @@ -216,13 +222,13 @@ static void send_headers(int sock){ int N = snprintf(ptr, L-1, "%s,", *sptr++); L -= N; ptr += N; } - SENDMSG(CMD_HEADERFILES "=%s", buf); + SENDMSGW(CMD_HEADERFILES, "=%s", buf); } } void client(int sock){ if(GP->restart){ - SENDMSG(CMD_RESTART); + SENDCMDW(CMD_RESTART); return; } send_headers(sock); @@ -233,7 +239,7 @@ void client(int sock){ Nremain = GP->nframes - 1; if(Nremain < 1) Nremain = 0; else GP->waitexpend = TRUE; // N>1 - wait for exp ends - SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); + SENDMSGW(CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); }else{ getans(sock, NULL); DBG("RETURN: no more data"); @@ -247,7 +253,7 @@ void client(int sock){ } while(dtime() - t0 < timeout){ if(GP->waitexpend && dtime() - tw > WAIT_TIMEOUT){ - SENDMSG(CMD_TREMAIN); // get remained time + SENDCMDW(CMD_TREMAIN); // get remained time tw = dtime(); sprintf(sendbuf, "%s", CMD_EXPSTATE); sendstrmessage(sock, sendbuf); @@ -266,7 +272,7 @@ void client(int sock){ if(GP->pause_len > 0){ double delta, time1 = dtime() + GP->pause_len; while(1){ - SENDMSG(CMD_CAMTEMPER); + SENDCMDW(CMD_CAMTEMPER); if((delta = time1 - dtime()) < __FLT_EPSILON__) break; // %d секунд до окончания паузы\n if(delta > 1.) verbose(1, _("%d seconds till pause ends\n"), (int)delta); @@ -277,7 +283,7 @@ void client(int sock){ } verbose(1, "Exposing frame %d...", ++nframe); --Nremain; - SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); + SENDMSGW(CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); }else{ GP->waitexpend = 0; timeout = WAIT_TIMEOUT; // wait for last file name @@ -301,8 +307,8 @@ static void getimage(){ FNAME(); int sock = controlfd; TIMESTAMP("Get image sizes"); - SENDMSG(CMD_IMWIDTH); - SENDMSG(CMD_IMHEIGHT); + SENDCMDW(CMD_IMWIDTH); + SENDCMDW(CMD_IMHEIGHT); int imsock = open_socket(FALSE, GP->imageport, TRUE); if(imsock < 0) ERRX("getimage(): can't open image transport socket"); if(imbufsz < imdatalen){ @@ -342,7 +348,7 @@ static void *grabnext(void _U_ *arg){ // daemon grabbing images through the net expstate = CAMERA_CAPTURE; TIMESTAMP("End of cycle, start new #%d", grabno+1); TIMEINIT(); - SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); // start capture + SENDMSGW(CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); // start capture double timeout = GP->exptime + CLIENT_TIMEOUT, t0 = dtime(); useconds_t sleept = 500000; // 0.5s if(GP->exptime < 0.5){ diff --git a/cmdlnopts.c b/cmdlnopts.c index 24a4b5f..21e704f 100644 --- a/cmdlnopts.c +++ b/cmdlnopts.c @@ -18,8 +18,8 @@ static glob_pars G = { .instrument = NULL, .exptime = -1., .nframes = 0, - .X0 = -1, .Y0 = -1, - .X1 = -1, .Y1 = -1, + .X0 = INT_MIN, .Y0 = INT_MIN, + .X1 = INT_MIN, .Y1 = INT_MIN, .focdevno = -1, .camdevno = -1, .whldevno = -1, diff --git a/locale/ru/messages.po b/locale/ru/messages.po index 4baf3f3..3648bda 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: 2023-04-11 10:00+0300\n" +"POT-Creation-Date: 2023-04-11 14:57+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -478,12 +478,12 @@ msgstr "" msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:725 server.c:236 +#: ccdfunc.c:725 server.c:251 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:737 server.c:237 +#: ccdfunc.c:737 server.c:252 msgid "Can't set given geometry" msgstr "" @@ -529,7 +529,7 @@ msgstr "" msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:783 ccdfunc.c:857 server.c:122 +#: ccdfunc.c:783 ccdfunc.c:857 server.c:137 msgid "Can't start exposition" msgstr "" @@ -546,7 +546,7 @@ msgid "Can't grab image" msgstr "" #. %d я│п╣п╨я┐п╫п╢ п╢п╬ п╬п╨п╬п╫я┤п╟п╫п╦я▐ п©п╟я┐п╥я▀\n -#: ccdfunc.c:807 client.c:272 +#: ccdfunc.c:807 client.c:278 #, c-format msgid "%d seconds till pause ends\n" msgstr "" @@ -555,15 +555,15 @@ msgstr "" msgid "Some error when capture" msgstr "" -#: server.c:170 +#: server.c:185 msgid "No camera device" msgstr "" -#: client.c:259 +#: client.c:265 msgid "Can't make exposition" msgstr "" -#: client.c:288 +#: client.c:294 msgid "Server timeout" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index 6590d3a..e7adef0 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: 2023-04-11 09:57+0300\n" + "POT-Creation-Date: 2023-04-11 14:24+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 "%.1f секунд до окончания экспозиции" #. %d я│п╣п╨я┐п╫п╢ п╢п╬ п╬п╨п╬п╫я┤п╟п╫п╦я▐ п©п╟я┐п╥я▀\n -#: ccdfunc.c:807 client.c:272 +#: ccdfunc.c:807 client.c:278 #, c-format msgid "%d seconds till pause ends\n" msgstr "%d секунд до окончания паузы\n" @@ -117,7 +117,7 @@ msgstr " msgid "Can't init mutex!" msgstr "Не могу инициализировать мьютекс!" -#: client.c:259 +#: client.c:265 msgid "Can't make exposition" msgstr "Не могу выполнить экспозицию" @@ -162,7 +162,7 @@ msgstr " msgid "Can't set active wheel number" msgstr "Не могу установить номер активного колеса" -#: ccdfunc.c:725 server.c:236 +#: ccdfunc.c:725 server.c:251 #, c-format msgid "Can't set binning %dx%d" msgstr "Не могу установить биннинг %dx%d" @@ -190,7 +190,7 @@ msgstr " msgid "Can't set gain to %g" msgstr "Не могу установить Gain в %g" -#: ccdfunc.c:737 server.c:237 +#: ccdfunc.c:737 server.c:252 msgid "Can't set given geometry" msgstr "Не могу установить геометрию" @@ -213,7 +213,7 @@ msgstr " msgid "Can't set wheel position %d" msgstr "Не могу установить положение колеса %d" -#: ccdfunc.c:783 ccdfunc.c:857 server.c:122 +#: ccdfunc.c:783 ccdfunc.c:857 server.c:137 msgid "Can't start exposition" msgstr "Не могу начать экспозицию" @@ -289,7 +289,7 @@ msgstr " msgid "N flushes before exposing (default: 1)" msgstr "N засвечиваний перед экспозицией (по умолчанию: 1)" -#: server.c:170 +#: server.c:185 msgid "No camera device" msgstr "Не указано устройство камеры" @@ -323,7 +323,7 @@ msgstr " msgid "Readout mode: %s" msgstr "Режим считывания: %s" -#: client.c:288 +#: client.c:294 msgid "Server timeout" msgstr "Таймаут сервера" diff --git a/server.c b/server.c index 865aac2..09df7a2 100644 --- a/server.c +++ b/server.c @@ -30,6 +30,8 @@ #include "server.h" #include "socket.h" +static int processData(int fd, handleritem *handlers, char *buf, int buflen); + static atomic_int camdevno = 0, wheeldevno = 0, focdevno = 0; // current devices numbers static _Atomic camera_state camstate = CAMERA_IDLE; #define FLAG_STARTCAPTURE (1<<0) @@ -37,7 +39,6 @@ static _Atomic camera_state camstate = CAMERA_IDLE; #define FLAG_RESTARTSERVER (1<<2) static atomic_int camflags = 0, camfanspd = 0, confio = 0, nflushes; static char *outfile = NULL, *lastfile = NULL; // current output file name/prefix; last name of saved file -//static pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/camera/focuser functions static frameformat frmformatmax = {0}, curformat = {0}; // maximal format static void *camdev = NULL, *focdev = NULL, *wheeldev = NULL; @@ -97,6 +98,20 @@ strpair allcommands[] = { {NULL, NULL}, }; +static pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/camera/focuser functions + +// return TRUE if `locmutex` can be locked +static int lock(){ + if(pthread_mutex_trylock(&locmutex)){ + DBG("\n\nAlready locked"); + return FALSE; + } + return TRUE; +} +static void unlock(){ + if(pthread_mutex_unlock(&locmutex)) ERR("Can't unlock mutex"); +} + static IMG ima = {0}; static void fixima(){ FNAME(); @@ -176,7 +191,7 @@ static void* processCAM(_U_ void *d){ signals(1); } usleep(100); - if(0 == pthread_mutex_trylock(&locmutex)){ + if(lock()){ // log if(dtime() - logt > TLOG_PAUSE){ logt = dtime(); @@ -206,7 +221,7 @@ static void* processCAM(_U_ void *d){ // do nothing: when `server` got this state it sends "expstate=3" to all clients and changes state to IDLE break; } - pthread_mutex_unlock(&locmutex); + unlock(); } } return NULL; @@ -354,7 +369,6 @@ static hresult nameprefixhandler(_U_ int fd, _U_ const char *key, const char *va char *path = makeabspath(val, FALSE); if(!path){ LOGERR("Can't create file '%s'", val); - //pthread_mutex_unlock(&locmutex); return RESULT_BADVAL; } FREE(outfile); @@ -676,7 +690,6 @@ static hresult FITSheaderhandler(int fd, _U_ const char *key, const char *val){ FREE(*sptr++); } FREE(list); - //pthread_mutex_unlock(&locmutex); return RESULT_BADVAL; } *lptr++ = strdup(newpath); @@ -958,8 +971,8 @@ static handleritem items[] = { {chkcc, formathandler, CMD_FRAMEMAX}, {chkcc, nflusheshandler, CMD_NFLUSHES}, {chkcam, expstatehandler, CMD_EXPSTATE}, - {NULL, imsizehandler, CMD_IMWIDTH}, - {NULL, imsizehandler, CMD_IMHEIGHT}, + {chktrue,imsizehandler, CMD_IMWIDTH}, + {chktrue,imsizehandler, CMD_IMHEIGHT}, {chkcc, nameprefixhandler, CMD_FILENAMEPREFIX}, {chkcc, rewritefilehandler, CMD_REWRITE}, {chkcc, _8bithandler, CMD_8BIT}, @@ -1125,3 +1138,77 @@ char *makeabspath(const char *path, int shouldbe){ if(unl) unlink(path); return ret; } + +// parse string of data (command or key=val) +// the CONTENT of buffer `str` WILL BE BROKEN! +// @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){ + 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 + hresult r = RESULT_OK; + int l = FALSE; + if(h->chkfunction){ + double t0 = dtime(); + do{ l = lock(); } while(!l && dtime() - t0 < BUSY_TIMEOUT); + DBG("time: %g", dtime() - t0); + if(!l){ + WARN("Can't lock mutex"); //signals(1); + 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; + } + if(l) unlock(); + if(r == RESULT_DISCONNECTED){ + DBG("handler return RESULT_DISCONNECTED"); + return FALSE; + } + return sendstrmessage(fd, hresult2str(r)); + } + } + DBG("Command not found!"); + return sendstrmessage(fd, hresult2str(RESULT_BADKEY)); +} + +/** + * @brief processData - read (if available) data from fd and run processing, sending to fd messages for each command + * @param fd - socket file descriptor + * @param handlers - NULL-terminated array of handlers + * @param buf (io) - zero-terminated buffer for storing rest of data (without newline), its content will be changed + * @param buflen - its length + * @return FALSE if client closed (nothing to read) + */ +static 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){ + //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; + if(!parsestring(fd, handlers, restofdata)) return FALSE; // client disconnected + restofdata = nl; + //DBG("rest of data: %s", restofdata); + }while(1); + if(restofdata != buf) memmove(buf, restofdata, eptr - restofdata + 1); + return TRUE; +} diff --git a/socket.c b/socket.c index 14ed413..c4da21a 100644 --- a/socket.c +++ b/socket.c @@ -38,8 +38,6 @@ double __t0 = 0.; #endif -pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/camera/focuser functions - /** * @brief open_socket - create socket and open it * @param isserver - TRUE for server, FALSE for client @@ -187,7 +185,7 @@ int sendmessage(int fd, const char *msg, int l){ buflen += 1024; tmpbuf = realloc(tmpbuf, buflen); } - //DBG("send to fd %d: %s [%d]", fd, msg, l); + DBG("send to fd %d: %s [%d]", fd, msg, l); memcpy(tmpbuf, msg, l); if(msg[l-1] != '\n') tmpbuf[l++] = '\n'; if(l != send(fd, tmpbuf, l, MSG_NOSIGNAL)){ @@ -248,79 +246,6 @@ char *get_keyval(char *keyval){ return val; } -// parse string of data (command or key=val) -// the CONTENT of buffer `str` WILL BE BROKEN! -// @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){ - 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 - hresult r = RESULT_OK; - 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; - } - if(!l) pthread_mutex_unlock(&locmutex); - if(r == RESULT_DISCONNECTED){ - DBG("handler return RESULT_DISCONNECTED"); - return FALSE; - } - return sendstrmessage(fd, hresult2str(r)); - } - } - DBG("Command not found!"); - return sendstrmessage(fd, resmessages[RESULT_BADKEY]); -} - -/** - * @brief processData - read (if available) data from fd and run processing, sending to fd messages for each command - * @param fd - socket file descriptor - * @param handlers - NULL-terminated array of handlers - * @param buf (io) - zero-terminated buffer for storing rest of data (without newline), its content will be changed - * @param buflen - its length - * @return FALSE if client closed (nothing to read) - */ -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){ - //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; - if(!parsestring(fd, handlers, restofdata)) return FALSE; // client disconnected - restofdata = nl; - //DBG("rest of data: %s", restofdata); - }while(1); - if(restofdata != buf) memmove(buf, restofdata, eptr - restofdata + 1); - return TRUE; -} - /** * check data from fd (polling function for client) * @param fd - file descriptor diff --git a/socket.h b/socket.h index 805ebaf..f0bc744 100644 --- a/socket.h +++ b/socket.h @@ -30,7 +30,7 @@ #define MAXCLIENTS (30) // wait for mutex locking -#define BUSY_TIMEOUT (0.1) +#define BUSY_TIMEOUT (1.0) // waiting for answer timeout #define ANSWER_TIMEOUT (1.0) // wait for exposition ends (between subsequent check calls) @@ -47,16 +47,14 @@ extern double __t0; #define TIMESTAMP(...) #endif -extern pthread_mutex_t locmutex; - typedef enum{ - RESULT_OK, // all OK - RESULT_BUSY, // camera busy and no setters can be done - RESULT_FAIL, // failed running command - RESULT_BADVAL, // bad key's value - RESULT_BADKEY, // bad key - RESULT_SILENCE, // send nothing to client - RESULT_DISCONNECTED,// client disconnected + RESULT_OK, // 0: all OK + RESULT_BUSY, // 1: camera busy and no setters can be done + RESULT_FAIL, // 2: failed running command + RESULT_BADVAL, // 3: bad key's value + RESULT_BADKEY, // 4: bad key + RESULT_SILENCE, // 5: send nothing to client + RESULT_DISCONNECTED,// 6: client disconnected RESULT_NUM } hresult; @@ -78,5 +76,4 @@ 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); int canberead(int fd);