void INDI::BaseClientQt::listenINDI() { char buffer[MAXINDIBUF]; char errorMsg[MAXRBUF]; int err_code=0; XMLEle ** nodes; XMLEle * root; int inode=0; if (sConnected == false) return; while (client_socket.bytesAvailable() > 0) { qint64 readBytes = client_socket.read(buffer, MAXINDIBUF - 1); if ( readBytes > 0 ) buffer[ readBytes ] = '\0'; nodes=parseXMLChunk(lillp, buffer, readBytes, errorMsg); if (!nodes) { if (errorMsg[0]) { fprintf (stderr, "Bad XML from %s/%d: %s\n%s\n", cServer.c_str(), cPort, errorMsg, buffer); return; } return; } root=nodes[inode]; while (root) { if (verbose) prXMLEle(stderr, root, 0); if ( (err_code = dispatchCommand(root, errorMsg)) < 0) { // Silenty ignore property duplication errors if (err_code != INDI_PROPERTY_DUPLICATED) { IDLog("Dispatch command error(%d): %s\n", err_code, errorMsg); prXMLEle (stderr, root, 0); } } delXMLEle (root); // not yet, delete and continue inode++; root=nodes[inode]; } free(nodes); inode=0; } }
/* send the xml command to each driver supporting device dev, or all if unknown. * restart if write fails. */ static void send2Drivers (XMLEle *root, char *dev) { int i; for (i = 0; i < ndvrinfo; i++) { DvrInfo *dp = &dvrinfo[i]; if (dev[0] && dp->dev[0] && strcmp (dev, dp->dev)) continue; prXMLEle (dp->wfp, root, 0); if (ferror(dp->wfp)) { fprintf (stderr, "Driver %s: %s\n", dp->name, strerror(errno)); restartDvr (dp); } else if (verbose > 2) { fprintf (stderr, "Driver %s: send:\n", dp->name); prXMLEle (stderr, root, 0); } else if (verbose > 1) fprintf(stderr,"Driver %s: send %s\n", dp->name, xmlLog(root)); } }
/* monitor server and return the next complete XML message. * exit(2) if time out. * N.B. caller must call delXMLEle() */ static XMLEle * nxtEle (FILE *fp) { char msg[1024]; /* read from server, exit if trouble or see malformed XML */ while(1) { XMLEle *root = readXMLEle (lillp, readServerChar(fp), msg); if (root) { /* found a complete XML element */ if (verbose > 1) prXMLEle (stderr, root, 0); return (root); } else if (msg[0]) { fprintf (stderr, "Bad XML from %s/%d: %s\n", host, port, msg); exit(2); } } }
/* this function is the thread to perform all writes to client carg. * return with client closed when we have problems or when shutdown flag is set. * N.B. coordinate all access to clinfo via client_m/c. * N.B. clinfo can move (be realloced) when unlocked so beware pointers thereto. */ static void * clientWThread(void *carg) { int c = (int)carg; ClInfo *cp; Msg *mp; /* start off wanting exclusive access to client info */ pthread_mutex_lock (&client_m); /* loop until told to shut down or get write error */ while (1) { /* check for message or shutdown, unlock while waiting */ while (nFQ(clinfo[c].msgq) == 0 && !clinfo[c].shutdown) { if (verbose > 2) fprintf (stderr,"Client %d: thread sleeping\n",clinfo[c].s); pthread_cond_wait (&client_c, &client_m); if (verbose > 2) fprintf (stderr, "Client %d: thread awake\n", clinfo[c].s); } if (clinfo[c].shutdown) break; /* get next message for this client */ mp = popFQ (clinfo[c].msgq); /* unlock client info while writing */ pthread_mutex_unlock (&client_m); prXMLEle (clinfo[c].wfp, mp->ep, 0); pthread_mutex_lock (&client_m); /* trace */ cp = &clinfo[c]; /* ok to use pointer while locked */ if (verbose > 2) { fprintf (stderr, "Client %d: send:\n", cp->s); prXMLEle (stderr, mp->ep, 0); } else if (verbose > 1) fprintf (stderr, "Client %d: send %s\n", cp->s, xmlLog(mp->ep)); /* update message usage count, free if goes to 0 */ if (--mp->count == 0) freeMsg (mp); /* exit this thread if encountered write errors */ if (ferror(cp->wfp)) { fprintf (stderr, "Client %d: %s\n", cp->s, strerror(errno)); break; } } /* close down this client */ cp = &clinfo[c]; /* ok to use pointer while locked */ fclose (cp->wfp); /* also closes cp->s */ delLilXML (cp->lp); myfree (cp->devs); /* decrement and possibly free any unsent messages for this client */ while ((mp = (Msg*) popFQ(cp->msgq)) != NULL) if (--mp->count == 0) freeMsg (mp); delFQ (cp->msgq); /* this thread is now finished with client info */ pthread_mutex_unlock (&client_m); /* exit thread */ return (0); }
/* Read commands from FIFO and process them. Start/stop drivers accordingly */ void newFIFO(void) { //char line[MAXRBUF], tDriver[MAXRBUF], tConfig[MAXRBUF], tDev[MAXRBUF], tSkel[MAXRBUF], envDev[MAXRBUF], envConfig[MAXRBUF], envSkel[MAXR]; char line[MAXRBUF]; DvrInfo *dp = NULL; int startCmd=0, i=0; while (i < MAXRBUF) { if (read(fifo.fd, line+i, 1) <= 0) { // Reset FIFO now, otherwise select will always return with no data from FIFO. indiFIFO(); return; } if (line[i] == '\n') { line[i] = '\0'; i=0; } else { i++; continue; } if (verbose) fprintf(stderr, "FIFO: %s\n", line); char cmd[MAXSBUF], arg[4][1], var[4][MAXSBUF], tDriver[MAXSBUF], tName[MAXSBUF], envDev[MAXSBUF], envConfig[MAXSBUF], envSkel[MAXSBUF], envPrefix[MAXSBUF]; memset(&tDriver[0], 0, sizeof(MAXSBUF)); memset(&tName[0], 0, sizeof(MAXSBUF)); memset(&envDev[0], 0, sizeof(MAXSBUF)); memset(&envConfig[0], 0, sizeof(MAXSBUF)); memset(&envSkel[0], 0, sizeof(MAXSBUF)); memset(&envPrefix[0], 0, sizeof(MAXSBUF)); int n = sscanf(line, "%s %s -%1c \"%512[^\"]\" -%1c \"%512[^\"]\" -%1c \"%512[^\"]\" -%1c \"%512[^\"]\"", cmd, tDriver, arg[0], var[0], arg[1], var[1] , arg[2], var[2], arg[3], var[3]); int n_args = (n - 2)/2; int j=0; for (j=0; j < n_args; j++) { //fprintf(stderr, "arg[%d]: %c\n", i, arg[j][0]); //fprintf(stderr, "var[%d]: %s\n", i, var[j]); if (arg[j][0] == 'n') { strncpy(tName, var[j], MAXSBUF-1); tName[MAXSBUF-1] = '\0'; if (verbose) fprintf(stderr, "With name: %s\n", envDev); } else if (arg[j][0] == 'c') { strncpy(envConfig, var[j], MAXSBUF-1); envConfig[MAXSBUF-1] = '\0'; if (verbose) fprintf(stderr, "With config: %s\n", envConfig); } else if (arg[j][0] == 's') { strncpy(envSkel, var[j], MAXSBUF-1); envSkel[MAXSBUF-1] = '\0'; if (verbose) fprintf(stderr, "With skeketon: %s\n", envSkel); } else if (arg[j][0] == 'p') { strncpy(envPrefix, var[j], MAXSBUF-1); envPrefix[MAXSBUF-1] = '\0'; if (verbose) fprintf(stderr, "With prefix: %s\n", envPrefix); } } if (!strcmp(cmd, "start")) startCmd = 1; else startCmd = 0; if (startCmd) { if (verbose) fprintf(stderr, "FIFO: Starting driver %s with name (%s)\n", tDriver, tName); dp = allocDvr(); strncpy(dp->name, tDriver, MAXINDIDEVICE); //strncpy(dp->dev, tName, MAXINDIDEVICE); strncpy(dp->envDev, tName, MAXSBUF); strncpy(dp->envConfig, envConfig, MAXSBUF); strncpy(dp->envSkel, envSkel, MAXSBUF); strncpy(dp->envPrefix, envPrefix, MAXSBUF); startDvr (dp); } else { for (dp = dvrinfo; dp < &dvrinfo[ndvrinfo]; dp++) { fprintf(stderr, "dp->name: %s - tDriver: %s\n", dp->name, tDriver); if (!strcmp(dp->name, tDriver) && dp->active==1) { fprintf(stderr, "name: %s - dp->dev[0]: %s\n", tName, dp->dev[0]); /* If device name is given, check against it before shutting down */ //if (tName[0] && strcmp(dp->dev[0], tName)) if (tName[0] && isDeviceInDriver(tName, dp) == 0) continue; if (verbose) fprintf(stderr, "FIFO: Shutting down driver: %s\n", tDriver); for (i=0; i < dp->ndev; i++) { /* Inform clients that this driver is dead */ XMLEle *root = addXMLEle (NULL, "delProperty"); addXMLAtt(root, "device", dp->dev[i]); prXMLEle(stderr, root, 0); Msg * mp = newMsg(); q2Clients(NULL, 0, dp->dev[i], NULL, mp, root); if (mp->count > 0) setMsgXMLEle (mp, root); else freeMsg (mp); delXMLEle (root); } shutdownDvr(dp, 0); break; } } } } }