seems like it works good; need tests on real star

This commit is contained in:
2025-03-14 16:42:52 +03:00
parent 6ee58edc7d
commit 7a0acd14f5
15 changed files with 678 additions and 236 deletions

View File

@@ -44,6 +44,8 @@
// Max amount of connections
#define BACKLOG (10)
static pthread_mutex_t cmd_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
TODO3: add 'FAIL error text' if not OK and instead all "wrong message"
*/
@@ -67,9 +69,9 @@ static char *stepperstatus(const char *messageid, char *buf, int buflen);
static char *getimagedata(const char *messageid, char *buf, int buflen);
static getter getterHandlers[] = {
{"help", helpmsg, "List avaiable commands"},
{"imdata", getimagedata, "Get image data (status, path, FPS, counter)"},
{"settings", listconf, "List current configuration"},
{"stpserv", stepperstatus, "Get status of steppers server"},
{"imdata", getimagedata, "Get image data (status, path, FPS, counter)"},
{NULL, NULL, NULL}
};
@@ -77,12 +79,14 @@ static char *setstepperstate(const char *state, char *buf, int buflen);
static char *setfocusstate(const char *state, char *buf, int buflen);
static char *moveU(const char *val, char *buf, int buflen);
static char *moveV(const char *val, char *buf, int buflen);
static char *addcmnt(const char *cmnt, char *buf, int buflen);
static setter setterHandlers[] = {
{"stpstate", setstepperstate, "Set given steppers' server state"},
{"comment", addcmnt, "Add comment to XY log file"},
{"focus", setfocusstate, "Move focus to given value"},
{"moveU", moveU, "Relative moving by U axe"},
{"moveV", moveV, "Relative moving by V axe"},
{"stpstate", setstepperstate, "Set given steppers' server state"},
{NULL, NULL, NULL}
};
@@ -90,6 +94,11 @@ static char *retFAIL(char *buf, int buflen){
snprintf(buf, buflen, FAIL);
return buf;
}
static char *retOK(char *buf, int buflen){
snprintf(buf, buflen, OK);
return buf;
}
/**************** functions to process commands ****************/
// getters
@@ -143,6 +152,13 @@ static char *moveV(const char *val, char *buf, int buflen){
if(theSteppers && theSteppers->moveByV) return theSteppers->moveByV(val, buf, buflen);
return retFAIL(buf, buflen);
}
static char *addcmnt(const char *cmnt, char *buf, int buflen){
if(!cmnt) return retFAIL(buf, buflen);
char *line = strdup(cmnt);
int ret = XYcomment(line);
free(line);
return ret ? retOK(buf, buflen) : retFAIL(buf, buflen) ;
}
/*
static char *rmnl(const char *msg, char *buf, int buflen){
@@ -162,14 +178,15 @@ static char *rmnl(const char *msg, char *buf, int buflen){
*/
static char *processCommand(const char msg[BUFLEN], char *ans, int anslen){
char value[BUFLEN];
char *kv = get_keyval(msg, value);
char *kv = get_keyval(msg, value); // ==NULL for getters/commands without equal sign
DBG("message: %s, value: %s, key: %s", msg, value, kv);
confparam *par;
if(kv){
DBG("got KEY '%s' with value '%s'", kv, value);
key_value result;
par = chk_keyval(kv, value, &result);
free(kv); kv = NULL;
if(par){
if(par){ // configuration parameter
DBG("found this key in conf");
switch(par->type){
case PAR_INT:
DBG("FOUND! Integer, old=%d, new=%d", *((int*)par->ptr), result.val.intval);
@@ -181,27 +198,67 @@ static char *processCommand(const char msg[BUFLEN], char *ans, int anslen){
break;
default:
snprintf(ans, anslen, FAIL);
free(kv);
return ans;
}
snprintf(ans, anslen, OK);
free(kv);
return ans;
}else{
DBG("check common setters");
setter *s = setterHandlers;
while(s->command){
int l = strlen(s->command);
if(strncasecmp(msg, s->command, l) == 0)
//int l = strlen(s->command);
//if(strncasecmp(msg, s->command, l) == 0)
DBG("check '%s' == '%s' ?", kv, s->command);
if(strcmp(kv, s->command) == 0){
free(kv);
return s->handler(value, ans, anslen);
}
++s;
}
}
free(kv);
}else{
DBG("getter?");
// first check custom getters
getter *g = getterHandlers;
while(g->command){
int l = strlen(g->command);
if(strncasecmp(msg, g->command, l) == 0)
//int l = strlen(g->command);
//if(strncasecmp(msg, g->command, l) == 0)
if(0 == strcmp(msg, g->command))
return g->handler(g->command, ans, anslen);
++g;
}
DBG("not found in getterHandlers");
// check custom setters
setter *s = setterHandlers;
while(s->command){
if(strcmp(msg, s->command) == 0){
size_t p = snprintf(ans, anslen, "%s=", msg);
s->handler(NULL, ans+p, anslen-p);
return ans;
}
++s;
}
DBG("not found in setterHandlers");
// and check configuration parameters
confparam *par = find_key(msg);
if(par){
switch(par->type){
case PAR_INT:
snprintf(ans, anslen, "%s=%d", msg, *((int*)par->ptr));
break;
case PAR_DOUBLE:
snprintf(ans, anslen, "%s=%g", msg, *((double*)par->ptr));
break;
default:
snprintf(ans, anslen, FAIL);
break;
}
return ans;
}
DBG("not found in parameters");
}
snprintf(ans, anslen, FAIL);
return ans;
@@ -215,16 +272,24 @@ static char *processCommand(const char msg[BUFLEN], char *ans, int anslen){
* @return amount of sent bytes
*/
static size_t send_data(int sock, const char *textbuf){
ssize_t Len = strlen(textbuf);
if(Len != write(sock, textbuf, Len)){
WARN("write()");
LOGERR("send_data(): write() failed");
return 0;
}else{
LOGDBG("send_data(): sent '%s'", textbuf);
size_t total = 0;
size_t len = strlen(textbuf);
const char *ptr = textbuf;
while(total < len){
ssize_t sent = write(sock, ptr + total, len - total);
if(sent < 0){
if(errno == EINTR) continue;
LOGERR("Write error: %s", strerror(errno));
return total;
}
total += sent;
}
if(textbuf[Len-1] != '\n') Len += write(sock, "\n", 1);
return (size_t)Len;
if(textbuf[len-1] != '\n'){
if(write(sock, "\n", 1) != 1){
LOGERR("Failed to write newline");
}
}
return total;
}
/**
@@ -233,7 +298,7 @@ static size_t send_data(int sock, const char *textbuf){
* @return 0 if all OK, 1 if socket closed
*/
static int handle_socket(int sock){
FNAME();
//FNAME();
char buff[BUFLEN];
char ansbuff[ANSBUFLEN];
ssize_t rd = read(sock, buff, BUFLEN-1);
@@ -243,19 +308,31 @@ static int handle_socket(int sock){
}
// add trailing zero to be on the safe side
buff[rd] = 0;
char *eol = strchr(buff, '\n');
if(eol) *eol = 0; // clear '\n'
// now we should check what do user want
// here we can process user data
DBG("user %d send '%s'", sock, buff);
LOGDBG("user %d send '%s'", sock, buff);
//pthread_mutex_lock(&mutex);
pthread_mutex_lock(&cmd_mutex);
char *ans = processCommand(buff, ansbuff, ANSBUFLEN-1); // run command parser
if(ans){
send_data(sock, ans); // send answer
}
//pthread_mutex_unlock(&mutex);
pthread_mutex_unlock(&cmd_mutex);
return 0;
}
// shutdown client and close
static void cleanup_client(int fd) {
if(fd > 0) {
shutdown(fd, SHUT_RDWR);
close(fd);
DBG("Client with fd %d closed", fd);
LOGMSG("Client %d disconnected", fd);
}
}
// main socket server
static void *server(void *asock){
DBG("server(): getpid: %d, tid: %lu",getpid(), syscall(SYS_gettid));
@@ -273,9 +350,16 @@ static void *server(void *asock){
while(1){
if(stopwork){
DBG("server() exit @ global stop");
LOGDBG("server() exit @ global stop");
return NULL;
}
poll(poll_set, nfd, 1); // poll for 1ms
int ready = poll(poll_set, nfd, 1); // 1ms timeout
if(ready < 0){
if(errno == EINTR) continue;
LOGERR("Poll error: %s", strerror(errno));
return NULL;
}
if(0 == ready) continue;
for(int fdidx = 0; fdidx < nfd; ++fdidx){ // poll opened FDs
if((poll_set[fdidx].revents & POLLIN) == 0) continue;
poll_set[fdidx].revents = 0;
@@ -284,9 +368,7 @@ static void *server(void *asock){
//int nread = 0;
//ioctl(fd, FIONREAD, &nread);
if(handle_socket(fd)){ // socket closed - remove it from list
close(fd);
DBG("Client with fd %d closed", fd);
LOGMSG("Client %d disconnected", fd);
cleanup_client(fd);
// move last to free space
poll_set[fdidx] = poll_set[nfd - 1];
--nfd;
@@ -319,6 +401,8 @@ static void *server(void *asock){
}
} // endfor
}
// disconnect all
for(int i = 1; i < nfd; ++i) cleanup_client(poll_set[i].fd);
LOGERR("server(): UNREACHABLE CODE REACHED!");
}