/* read more from the given client, send to each appropriate driver when see * xml closure. also send all newXXX() to all other interested clients. * shut down client if any trouble. */ static void clientMsg (ClInfo *cp) { char buf[BUFSZ]; int i, nr; /* read client */ nr = read (cp->s, buf, sizeof(buf)); if (nr < 0) { fprintf (stderr, "Client %d: %s\n", cp->s, strerror(errno)); shutdownClient (cp); return; } if (nr == 0) { if (verbose) fprintf (stderr, "Client %d: read EOF\n", cp->s); shutdownClient (cp); return; } if (verbose > 2) fprintf (stderr, "Client %d: read %d:\n%.*s", cp->s, nr, nr, buf); /* process XML, sending when find closure */ for (i = 0; i < nr; i++) { char err[1024]; XMLEle *root = readXMLEle (cp->lp, buf[i], err); if (root) { char *roottag = tagXMLEle(root); if (verbose > 1) fprintf (stderr, "Client %d: read %s\n", cp->s, xmlLog(root)); /* record BLOB message locally, others go to matching drivers */ if (!strcmp (roottag, "enableBLOB")) { cp->blob = crackBLOB (pcdataXMLEle(root)); delXMLEle (root); } else { char *dev = findXMLAttValu (root, "device"); /* snag interested devices */ if (!strcmp (roottag, "getProperties")) addClDevice (cp, dev); /* send message to driver(s) responsible for dev */ send2Drivers (root, dev); /* echo new* commands back to other clients, else done */ if (!strncmp (roottag, "new", 3)) send2Clients (cp, root, dev); /* does delXMLEle */ else delXMLEle (root); } } else if (err[0]) fprintf (stderr, "Client %d: %s\n", cp->s, err); } }
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; } }
/* free Msg mp and everything it contains */ static void freeMsg (Msg *mp) { delXMLEle (mp->ep); myfree (mp); }
/* read more from the given driver, send to each interested client when see * xml closure. if driver dies, try restarting. * return 0 if ok else -1 if had to shut down anything. */ int readFromDriver (DvrInfo *dp) { char buf[MAXRBUF]; int shutany = 0; ssize_t i, nr; /* read driver */ nr = read (dp->rfd, buf, sizeof(buf)); if (nr <= 0) { if (nr < 0) fprintf (stderr, "%s: Driver %s: stdin %s\n", indi_tstamp(NULL), dp->name, strerror(errno)); else fprintf (stderr, "%s: Driver %s: stdin EOF\n", indi_tstamp(NULL), dp->name); shutdownDvr (dp, 1); return (-1); } /* process XML, sending when find closure */ for (i = 0; i < nr; i++) { char err[1024]; XMLEle *root = readXMLEle (dp->lp, buf[i], err); if (root) { char *roottag = tagXMLEle(root); const char *dev = findXMLAttValu (root, "device"); const char *name = findXMLAttValu (root, "name"); int isblob = !strcmp (tagXMLEle(root), "setBLOBVector"); Msg *mp; if (verbose > 2) { fprintf(stderr, "%s: Driver %s: read ", indi_tstamp(0),dp->name); traceMsg (root); } else if (verbose > 1) { fprintf (stderr, "%s: Driver %s: read <%s device='%s' name='%s'>\n", indi_tstamp(NULL), dp->name, tagXMLEle(root), findXMLAttValu (root, "device"), findXMLAttValu (root, "name")); } /* that's all if driver is just registering a snoop */ if (!strcmp (roottag, "getProperties")) { addSDevice (dp, dev, name); delXMLEle (root); continue; } /* that's all if driver is just registering a BLOB mode */ if (!strcmp (roottag, "enableBLOB")) { Property *sp = findSDevice (dp, dev, name); if (sp) crackBLOB (pcdataXMLEle (root), &sp->blob); delXMLEle (root); continue; } /* Found a new device? Let's add it to driver info */ if (dev[0] && isDeviceInDriver(dev, dp) == 0) { dp->dev = (char **) realloc(dp->dev, (dp->ndev+1) * sizeof(char *)); dp->dev[dp->ndev] = (char *) malloc(MAXINDIDEVICE * sizeof(char)); strncpy (dp->dev[dp->ndev], dev, MAXINDIDEVICE-1); dp->dev[dp->ndev][MAXINDIDEVICE-1] = '\0'; #ifdef OSX_EMBEDED_MODE if (!dp->ndev) fprintf(stderr, "STARTED \"%s\"\n", dp->name); fflush(stderr); #endif dp->ndev++; } /* log messages if any and wanted */ if (ldir) logDMsg (root, dev); /* build a new message -- set content iff anyone cares */ mp = newMsg(); /* send to interested clients */ if (q2Clients (NULL, isblob, dev, name, mp, root) < 0) shutany++; /* send to snooping drivers */ q2SDrivers (isblob, dev, name, mp, root); /* set message content if anyone cares else forget it */ if (mp->count > 0) setMsgXMLEle (mp, root); else freeMsg (mp); delXMLEle (root); } else if (err[0]) { char *ts = indi_tstamp(NULL); fprintf (stderr, "%s: Driver %s: XML error: %s\n", ts, dp->name, err); fprintf (stderr, "%s: Driver %s: XML read: %.*s\n", ts, dp->name, (int)nr, buf); shutdownDvr (dp, 1); return (-1); } } return (shutany ? -1 : 0); }
/* read more from the given client, send to each appropriate driver when see * xml closure. also send all newXXX() to all other interested clients. * return -1 if had to shut down anything, else 0. */ int readFromClient (ClInfo *cp) { char buf[MAXRBUF]; int shutany = 0; ssize_t i, nr; /* read client */ nr = read (cp->s, buf, sizeof(buf)); if (nr <= 0) { if (nr < 0) fprintf (stderr, "%s: Client %d: read: %s\n", indi_tstamp(NULL), cp->s, strerror(errno)); else if (verbose > 0) fprintf (stderr, "%s: Client %d: read EOF\n", indi_tstamp(NULL), cp->s); shutdownClient (cp); return (-1); } /* process XML, sending when find closure */ for (i = 0; i < nr; i++) { char err[1024]; XMLEle *root = readXMLEle (cp->lp, buf[i], err); if (root) { char *roottag = tagXMLEle(root); const char *dev = findXMLAttValu (root, "device"); const char *name = findXMLAttValu (root, "name"); int isblob = !strcmp (tagXMLEle(root), "setBLOBVector"); Msg *mp; if (verbose > 2) { fprintf (stderr, "%s: Client %d: read ",indi_tstamp(NULL),cp->s); traceMsg (root); } else if (verbose > 1) { fprintf (stderr, "%s: Client %d: read <%s device='%s' name='%s'>\n", indi_tstamp(NULL), cp->s, tagXMLEle(root), findXMLAttValu (root, "device"), findXMLAttValu (root, "name")); } /* snag interested properties. * N.B. don't open to alldevs if seen specific dev already, else * remote client connections start returning too much. */ if (dev[0]) addClDevice (cp, dev, name, isblob); else if (!strcmp (roottag, "getProperties") && !cp->nprops) cp->allprops = 1; /* snag enableBLOB -- send to remote drivers too */ if (!strcmp (roottag, "enableBLOB")) // crackBLOB (pcdataXMLEle(root), &cp->blob); crackBLOBHandling (dev, name, pcdataXMLEle(root), cp); /* build a new message -- set content iff anyone cares */ mp = newMsg(); /* send message to driver(s) responsible for dev */ q2RDrivers (dev, mp, root); /* echo new* commands back to other clients */ if (!strncmp (roottag, "new", 3)) { if (q2Clients (cp, isblob, dev, name, mp, root) < 0) shutany++; } /* set message content if anyone cares else forget it */ if (mp->count > 0) setMsgXMLEle (mp, root); else freeMsg (mp); delXMLEle (root); } else if (err[0]) { char *ts = indi_tstamp(NULL); fprintf (stderr, "%s: Client %d: XML error: %s\n", ts, cp->s, err); fprintf (stderr, "%s: Client %d: XML read: %.*s\n", ts, cp->s, (int)nr, buf); shutdownClient (cp); return (-1); } } return (shutany ? -1 : 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; } } } } }