/* prepare for new client arriving on lsocket. * exit if trouble. */ static void newClient() { ClInfo *cp = NULL; int s, cli; /* assign new socket */ s = newClSocket (); /* try to reuse a clinfo slot, else add one */ for (cli = 0; cli < nclinfo; cli++) if (!(cp = &clinfo[cli])->active) break; if (cli == nclinfo) { /* grow clinfo, lock while moving */ pthread_mutex_lock (&client_m); clinfo = (ClInfo *) myrealloc (clinfo, (nclinfo+1)*sizeof(ClInfo)); if (!clinfo) { fprintf (stderr, "%s: no memory for new client\n", me); exit(1); } cp = &clinfo[nclinfo++]; pthread_mutex_unlock (&client_m); } /* rig up new clinfo entry */ memset (cp, 0, sizeof(*cp)); cp->active = 1; cp->s = s; cp->lp = newLilXML(); cp->msgq = newFQ(1); cp->devs = mymalloc (1); /* N.B. beware implied use of malloc */ pthread_mutex_lock (&malloc_m); cp->wfp = fdopen (cp->s, "a"); setbuf (cp->wfp, NULL); pthread_mutex_unlock (&malloc_m); if (verbose > 0) fprintf (stderr, "Client %d: new arrival - welcome!\n", cp->s); /* start the writer thread */ s = pthread_create (&cp->wtid, NULL, clientWThread, (void*)(cp-clinfo)); if (s) { fprintf (stderr, "Thread create error: %s\n", strerror(s)); exit (1); } }
/* start the given remote INDI driver connection. * exit if trouble. */ void startRemoteDvr (DvrInfo *dp) { Msg *mp; char dev[1024]; char host[1024]; char buf[1024]; int indi_port, sockfd; /* extract host and port */ indi_port = INDIPORT; if (sscanf (dp->name, "%[^@]@%[^:]:%d", dev, host, &indi_port) < 2) { fprintf (stderr, "Bad remote device syntax: %s\n", dp->name); Bye(); } /* connect */ sockfd = openINDIServer (host, indi_port); /* record flag pid, io channels, init lp and snoop list */ dp->pid = REMOTEDVR; dp->rfd = sockfd; dp->wfd = sockfd; dp->lp = newLilXML(); dp->msgq = newFQ(1); dp->sprops = (Property*) malloc (1); /* seed for realloc */ dp->nsprops = 0; dp->nsent = 0; dp->active = 1; dp->ndev = 1; dp->dev = (char **) malloc(sizeof(char *)); /* N.B. storing name now is key to limiting outbound traffic to this * dev. */ dp->dev[0] = (char *) malloc(MAXINDIDEVICE * sizeof(char)); strncpy (dp->dev[0], dev, MAXINDIDEVICE-1); dp->dev[0][MAXINDIDEVICE-1] = '\0'; /* Sending getProperties with device lets remote server limit its * outbound (and our inbound) traffic on this socket to this device. */ mp = newMsg(); pushFQ (dp->msgq, mp); sprintf (buf, "<getProperties device='%s' version='%g'/>\n", dp->dev[0], INDIV); setMsgStr (mp, buf); mp->count++; if (verbose > 0) fprintf (stderr, "%s: Driver %s: socket=%d\n", indi_tstamp(NULL), dp->name, sockfd); }
/* prepare for new client arriving on lsocket. * exit if trouble. */ void newClient() { ClInfo *cp = NULL; int s, cli; /* assign new socket */ s = newClSocket (); /* try to reuse a clinfo slot, else add one */ for (cli = 0; cli < nclinfo; cli++) if (!(cp = &clinfo[cli])->active) break; if (cli == nclinfo) { /* grow clinfo */ clinfo = (ClInfo *) realloc (clinfo, (nclinfo+1)*sizeof(ClInfo)); if (!clinfo) { fprintf (stderr, "no memory for new client\n"); Bye(); } cp = &clinfo[nclinfo++]; } /* rig up new clinfo entry */ memset (cp, 0, sizeof(*cp)); cp->active = 1; cp->s = s; cp->lp = newLilXML(); cp->msgq = newFQ(1); cp->props = malloc (1); cp->nsent = 0; if (verbose > 0) { struct sockaddr_in addr; socklen_t len = sizeof(addr); getpeername(s, (struct sockaddr*)&addr, &len); fprintf(stderr,"%s: Client %d: new arrival from %s:%d - welcome!\n", indi_tstamp(NULL), cp->s, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); } #ifdef OSX_EMBEDED_MODE int active = 0; for (int i = 0; i < nclinfo; i++) if (clinfo[i].active) active++; fprintf(stderr, "CLIENTS %d\n", active); fflush(stderr); #endif }
/* start the given local INDI driver process. * exit if trouble. */ void startLocalDvr (DvrInfo *dp) { Msg *mp; char buf[32]; int rp[2], wp[2], ep[2]; int pid; #ifdef OSX_EMBEDED_MODE fprintf(stderr, "STARTING \"%s\"\n", dp->name); fflush(stderr); #endif /* build three pipes: r, w and error*/ if (pipe (rp) < 0) { fprintf (stderr, "%s: read pipe: %s\n", indi_tstamp(NULL), strerror(errno)); Bye(); } if (pipe (wp) < 0) { fprintf (stderr, "%s: write pipe: %s\n", indi_tstamp(NULL), strerror(errno)); Bye(); } if (pipe (ep) < 0) { fprintf (stderr, "%s: stderr pipe: %s\n", indi_tstamp(NULL), strerror(errno)); Bye(); } /* fork&exec new process */ pid = fork(); if (pid < 0) { fprintf (stderr, "%s: fork: %s\n", indi_tstamp(NULL), strerror(errno)); Bye(); } if (pid == 0) { /* child: exec name */ int fd; /* rig up pipes */ dup2 (wp[0], 0); /* driver stdin reads from wp[0] */ dup2 (rp[1], 1); /* driver stdout writes to rp[1] */ dup2 (ep[1], 2); /* driver stderr writes to e[]1] */ for (fd = 3; fd < 100; fd++) (void) close (fd); if (*dp->envDev) setenv("INDIDEV", dp->envDev, 1); /* Only reset environment variable in case of FIFO */ else if (fifo.fd > 0) unsetenv("INDIDEV"); if (*dp->envConfig) setenv("INDICONFIG", dp->envConfig, 1); else if (fifo.fd > 0) unsetenv("INDICONFIG"); if (*dp->envSkel) setenv("INDISKEL", dp->envSkel, 1); else if (fifo.fd > 0) unsetenv("INDISKEL"); char executable[MAXSBUF]; if (*dp->envPrefix) { setenv("INDIPREFIX", dp->envPrefix, 1); #ifdef OSX_EMBEDED_MODE snprintf(executable, MAXSBUF, "%s/Contents/MacOS/%s", dp->envPrefix, dp->name); #else snprintf(executable, MAXSBUF, "%s/bin/%s", dp->envPrefix, dp->name); #endif fprintf(stderr, "%s\n", executable); execlp (executable, dp->name, NULL); } else { if (fifo.fd > 0) unsetenv("INDIPREFIX"); execlp (dp->name, dp->name, NULL); } #ifdef OSX_EMBEDED_MODE fprintf(stderr, "FAILED \"%s\"\n", dp->name); fflush(stderr); #endif fprintf (stderr, "%s: Driver %s: execlp: %s\n", indi_tstamp(NULL), dp->name, strerror(errno)); _exit (1); /* parent will notice EOF shortly */ } /* don't need child's side of pipes */ close (wp[0]); close (rp[1]); close (ep[1]); /* record pid, io channels, init lp and snoop list */ dp->pid = pid; dp->rfd = rp[0]; dp->wfd = wp[1]; dp->efd = ep[0]; dp->lp = newLilXML(); dp->msgq = newFQ(1); dp->sprops = (Property*) malloc (1); /* seed for realloc */ dp->nsprops = 0; dp->nsent = 0; dp->active = 1; dp->ndev = 0; dp->dev = (char **) malloc(sizeof(char *)); /* first message primes driver to report its properties -- dev known * if restarting */ mp = newMsg(); pushFQ (dp->msgq, mp); sprintf (buf, "<getProperties version='%g'/>\n", INDIV); setMsgStr (mp, buf); mp->count++; if (verbose > 0) fprintf (stderr, "%s: Driver %s: pid=%d rfd=%d wfd=%d efd=%d\n", indi_tstamp(NULL), dp->name, dp->pid, dp->rfd, dp->wfd, dp->efd); }