static int timeRegister(void) { /* If TIMEZONE not defined, set it from EPICS_TIMEZONE */ if (getenv("TIMEZONE") == NULL) { const char *timezone = envGetConfigParamPtr(&EPICS_TIMEZONE); if (timezone == NULL) { printf("timeRegister: No Time Zone Information\n"); } else { epicsEnvSet("TIMEZONE", timezone); } } // Define EPICS_TS_FORCE_NTPTIME to force use of NTPTime provider bool useNTP = getenv("EPICS_TS_FORCE_NTPTIME") != NULL; if (!useNTP && (taskNameToId(sntp_sync_task) != ERROR || taskNameToId(ntp_daemon) != ERROR)) { // A VxWorks 6 SNTP/NTP sync task is running struct timespec clockNow; useNTP = clock_gettime(CLOCK_REALTIME, &clockNow) != OK || clockNow.tv_sec < BUILD_TIME; // Assumes VxWorks and the host OS have the same epoch } if (useNTP) { // Start NTP first so it can be used to sync SysTime NTPTime_Init(100); ClockTime_Init(CLOCKTIME_SYNC); } else { ClockTime_Init(CLOCKTIME_NOSYNC); } return 1; }
/* * caPutLogClientInit() */ int epicsShareAPI caPutLogClientInit (const char *addr_str) { int status; struct sockaddr_in saddr; long default_port = 7011; if (caPutLogClient!=NULL) { return caPutLogSuccess; } if (!addr_str || !addr_str[0]) { addr_str = envGetConfigParamPtr(&EPICS_CA_PUT_LOG_ADDR); } status = aToIPAddr (addr_str, default_port, &saddr); if (status<0) { fprintf (stderr, "caPutLog: bad address or host name\n"); return caPutLogError; } caPutLogClient = logClientCreate (saddr.sin_addr, ntohs(saddr.sin_port)); if (!caPutLogClient) { return caPutLogError; } else { return caPutLogSuccess; } }
string SystemConfigurationImpl::getPropertyAsString(const string &name, const string &defaultValue) { strncpy(_envParam.name,name.c_str(),name.length() + 1); const char* val = envGetConfigParamPtr(&_envParam); if(val != NULL) { return _properties->getProperty(name, string(val)); } return _properties->getProperty(name, defaultValue); }
/*+/subr********************************************************************** * NAME envPrtConfigParam - print value of a configuration parameter * * DESCRIPTION * Prints the value of a configuration parameter. * * RETURNS * 0 * * EXAMPLE * 1. Print the value for the EPICS-defined environment parameter * EPICS_TS_NTP_INET. * * #include "envDefs.h" * * envPrtConfigParam(&EPICS_TS_NTP_INET); * *-*/ long epicsShareAPI envPrtConfigParam( const ENV_PARAM *pParam) /* pointer to config param structure */ { const char *pVal; pVal = envGetConfigParamPtr(pParam); if (pVal == NULL) fprintf(stdout, "%s is undefined\n", pParam->name); else fprintf(stdout,"%s: %s\n", pParam->name, pVal); return 0; }
void osdNTPInit(void) { pserverAddr = envGetConfigParamPtr(&EPICS_TS_NTP_INET); if (!pserverAddr) { /* use the boot host */ BOOT_PARAMS bootParms; static char host_addr[BOOT_ADDR_LEN]; bootStringToStruct(sysBootLine, &bootParms); /* bootParms.had = host IP address */ strncpy(host_addr, bootParms.had, BOOT_ADDR_LEN); pserverAddr = host_addr; } }
/* * Create a command-line context */ void * epicsShareAPI epicsReadlineBegin(FILE *in) { struct readlineContext *readlineContext = calloc(1, sizeof(*readlineContext)); if (readlineContext) { readlineContext->in = in; readlineContext->line = NULL; if (!envGetConfigParamPtr(&IOCSH_HISTEDIT_DISABLE)) osdReadlineBegin(readlineContext); } return readlineContext; }
/*+/subr********************************************************************** * NAME envGetConfigParam - get value of a configuration parameter * * DESCRIPTION * Gets the value of a configuration parameter and copies it * into the caller's buffer. If the configuration parameter * isn't found in the environment, then the default value for * the parameter is copied. If no parameter is found and there * is no default, then '\0' is copied and NULL is returned. * * RETURNS * pointer to callers buffer, or * NULL if no parameter value or default value was found * * EXAMPLES * 1. Get the value for the EPICS-defined environment parameter * EPICS_TS_NTP_INET. * * #include "envDefs.h" * char temp[80]; * * printf("NTP time server is: %s\n", * envGetConfigParam(&EPICS_TS_NTP_INET, sizeof(temp), temp)); * * 2. Get the value for the DISPLAY environment parameter under UNIX. * * #include "envDefs.h" * char temp[80]; * ENV_PARAM display={"DISPLAY",""} * * if (envGetConfigParam(&display, sizeof(temp), temp) == NULL) * printf("DISPLAY isn't defined\n"); * else * printf("DISPLAY is %s\n", temp); * *-*/ char * epicsShareAPI envGetConfigParam( const ENV_PARAM *pParam,/* I pointer to config param structure */ int bufDim, /* I dimension of parameter buffer */ char *pBuf /* I pointer to parameter buffer */ ) { const char *pEnv; /* pointer to environment string */ pEnv = envGetConfigParamPtr(pParam); if (!pEnv) { return NULL; } strncpy(pBuf, pEnv, bufDim-1); pBuf[bufDim-1] = '\0'; return pBuf; }
/* * addAddrToChannelAccessAddressList () */ extern "C" void epicsShareAPI addAddrToChannelAccessAddressList ( ELLLIST *pList, const ENV_PARAM *pEnv, unsigned short port, int ignoreNonDefaultPort ) { osiSockAddrNode *pNewNode; const char *pStr; const char *pToken; struct sockaddr_in addr; char buf[32u]; /* large enough to hold an IP address */ int status; pStr = envGetConfigParamPtr (pEnv); if (!pStr) { return; } while ( ( pToken = getToken (&pStr, buf, sizeof (buf) ) ) ) { status = aToIPAddr ( pToken, port, &addr ); if (status<0) { fprintf ( stderr, "%s: Parsing '%s'\n", __FILE__, pEnv->name); fprintf ( stderr, "\tBad internet address or host name: '%s'\n", pToken); continue; } if ( ignoreNonDefaultPort && ntohs ( addr.sin_port ) != port ) { continue; } pNewNode = (osiSockAddrNode *) calloc (1, sizeof(*pNewNode)); if (pNewNode==NULL) { fprintf ( stderr, "addAddrToChannelAccessAddressList(): no memory available for configuration\n"); return; } pNewNode->addr.ia = addr; /* * LOCK applied externally */ ellAdd (pList, &pNewNode->node); } return; }
/* * * req_server() * * CA server task * * Waits for connections at the CA port and spawns a task to * handle each of them * */ static void req_server (void *pParm) { unsigned priorityOfSelf = epicsThreadGetPrioritySelf (); unsigned priorityOfBeacons; epicsThreadBooleanStatus tbs; struct sockaddr_in serverAddr; /* server's address */ osiSocklen_t addrSize; int status; SOCKET clientSock; epicsThreadId tid; int portChange; epicsSignalInstallSigPipeIgnore (); taskwdInsert ( epicsThreadGetIdSelf (), NULL, NULL ); rsrvCurrentClient = epicsThreadPrivateCreate (); if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) { ca_server_port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } else { ca_server_port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } if (IOC_sock != 0 && IOC_sock != INVALID_SOCKET) { epicsSocketDestroy ( IOC_sock ); } /* * Open the socket. Use ARPA Internet address format and stream * sockets. Format described in <sys/socket.h>. */ if ( ( IOC_sock = epicsSocketCreate (AF_INET, SOCK_STREAM, 0) ) == INVALID_SOCKET ) { errlogPrintf ("CAS: Socket creation error\n"); epicsThreadSuspendSelf (); } epicsSocketEnableAddressReuseDuringTimeWaitState ( IOC_sock ); /* Zero the sock_addr structure */ memset ( (void *) &serverAddr, 0, sizeof ( serverAddr ) ); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); serverAddr.sin_port = htons ( ca_server_port ); /* get server's Internet address */ status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); if ( status < 0 ) { if ( SOCKERRNO == SOCK_EADDRINUSE ) { /* * enable assignment of a default port * (so the getsockname() call below will * work correctly) */ serverAddr.sin_port = ntohs (0); status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); } if ( status < 0 ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "CAS: Socket bind error was \"%s\"\n", sockErrBuf ); epicsThreadSuspendSelf (); } portChange = 1; } else { portChange = 0; } addrSize = ( osiSocklen_t ) sizeof ( serverAddr ); status = getsockname ( IOC_sock, (struct sockaddr *)&serverAddr, &addrSize); if ( status ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "CAS: getsockname() error %s\n", sockErrBuf ); epicsThreadSuspendSelf (); } ca_server_port = ntohs (serverAddr.sin_port); if ( portChange ) { errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n"); errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", ca_server_port ); errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n"); errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" ); errlogPrintf ( "cas warning: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)\n" ); } /* listen and accept new connections */ if ( listen ( IOC_sock, 20 ) < 0 ) { errlogPrintf ("CAS: Listen error\n"); epicsSocketDestroy (IOC_sock); epicsThreadSuspendSelf (); } tbs = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfBeacons ); if ( tbs != epicsThreadBooleanStatusSuccess ) { priorityOfBeacons = priorityOfSelf; } beacon_startStopEvent = epicsEventMustCreate(epicsEventEmpty); beacon_ctl = ctlPause; tid = epicsThreadCreate ( "CAS-beacon", priorityOfBeacons, epicsThreadGetStackSize (epicsThreadStackSmall), rsrv_online_notify_task, 0 ); if ( tid == 0 ) { epicsPrintf ( "CAS: unable to start beacon thread\n" ); } epicsEventMustWait(beacon_startStopEvent); epicsEventSignal(castcp_startStopEvent); while (TRUE) { struct sockaddr sockAddr; osiSocklen_t addLen = sizeof(sockAddr); while (castcp_ctl == ctlPause) { epicsThreadSleep(0.1); } clientSock = epicsSocketAccept ( IOC_sock, &sockAddr, &addLen ); if ( clientSock == INVALID_SOCKET ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf("CAS: Client accept error was \"%s\"\n", sockErrBuf ); epicsThreadSleep(15.0); continue; } else { epicsThreadId id; struct client *pClient; /* socket passed in is closed if unsuccessful here */ pClient = create_tcp_client ( clientSock ); if ( ! pClient ) { epicsThreadSleep ( 15.0 ); continue; } LOCK_CLIENTQ; ellAdd ( &clientQ, &pClient->node ); UNLOCK_CLIENTQ; id = epicsThreadCreate ( "CAS-client", epicsThreadPriorityCAServerLow, epicsThreadGetStackSize ( epicsThreadStackBig ), camsgtask, pClient ); if ( id == 0 ) { LOCK_CLIENTQ; ellDelete ( &clientQ, &pClient->node ); UNLOCK_CLIENTQ; destroy_tcp_client ( pClient ); errlogPrintf ( "CAS: task creation for new client failed\n" ); epicsThreadSleep ( 15.0 ); continue; } } } }
/* * RTEMS Startup task */ rtems_task Init (rtems_task_argument ignored) { int i; char *argv[3] = { NULL, NULL, NULL }; char *cp; rtems_task_priority newpri; rtems_status_code sc; rtems_time_of_day now; /* * Explain why we're here */ logReset(); /* * Architecture-specific hooks */ if (epicsRtemsInitPreSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) delayedPanic("epicsRtemsInitPreSetBootConfigFromNVRAM"); if (rtems_bsdnet_config.bootp == NULL) { extern void setBootConfigFromNVRAM(void); setBootConfigFromNVRAM(); } if (epicsRtemsInitPostSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) delayedPanic("epicsRtemsInitPostSetBootConfigFromNVRAM"); /* * Override RTEMS configuration */ rtems_task_set_priority ( RTEMS_SELF, epicsThreadGetOssPriorityValue(epicsThreadPriorityIocsh), &newpri); /* * Create a reasonable environment */ initConsole (); putenv ("TERM=xterm"); putenv ("IOCSH_HISTSIZE=20"); /* * Display some OS information */ printf("\n***** RTEMS Version: %s *****\n", rtems_get_version_string()); /* * Start network */ if ((cp = getenv("EPICS_TS_NTP_INET")) != NULL) rtems_bsdnet_config.ntp_server[0] = cp; if (rtems_bsdnet_config.network_task_priority == 0) { unsigned int p; if (epicsThreadHighestPriorityLevelBelow(epicsThreadPriorityScanLow, &p) == epicsThreadBooleanStatusSuccess) { rtems_bsdnet_config.network_task_priority = epicsThreadGetOssPriorityValue(p); } } printf("\n***** Initializing network *****\n"); rtems_bsdnet_initialize_network(); initialize_remote_filesystem(argv, initialize_local_filesystem(argv)); /* * More environment: iocsh prompt and hostname */ { char hostname[1024]; gethostname(hostname, 1023); char *cp = mustMalloc(strlen(hostname)+3, "iocsh prompt"); sprintf(cp, "%s> ", hostname); epicsEnvSet ("IOCSH_PS1", cp); epicsEnvSet("IOC_NAME", hostname); } /* * Use BSP-supplied time of day if available otherwise supply default time. * It is very likely that other time synchronization facilities in EPICS * will soon override this value. */ if (rtems_clock_get(RTEMS_CLOCK_GET_TOD,&now) != RTEMS_SUCCESSFUL) { now.year = 2001; now.month = 1; now.day = 1; now.hour = 0; now.minute = 0; now.second = 0; now.ticks = 0; if ((sc = rtems_clock_set (&now)) != RTEMS_SUCCESSFUL) printf ("***** Can't set time: %s\n", rtems_status_text (sc)); } if (getenv("TZ") == NULL) { const char *tzp = envGetConfigParamPtr(&EPICS_TIMEZONE); if (tzp == NULL) { printf("Warning -- no timezone information available -- times will be displayed as GMT.\n"); } else { char tz[10]; int minWest, toDst = 0, fromDst = 0; if(sscanf(tzp, "%9[^:]::%d:%d:%d", tz, &minWest, &toDst, &fromDst) < 2) { printf("Warning: EPICS_TIMEZONE (%s) unrecognizable -- times will be displayed as GMT.\n", tzp); } else { char posixTzBuf[40]; char *p = posixTzBuf; p += sprintf(p, "%cST%d:%.2d", tz[0], minWest/60, minWest%60); if (toDst != fromDst) p += sprintf(p, "%cDT", tz[0]); epicsEnvSet("TZ", posixTzBuf); } } } tzset(); osdTimeRegister(); /* * Run the EPICS startup script */ printf ("***** Starting EPICS application *****\n"); iocshRegisterRTEMS (); set_directory (argv[1]); epicsEnvSet ("IOC_STARTUP_SCRIPT", argv[1]); atexit(exitHandler); i = main ((sizeof argv / sizeof argv[0]) - 1, argv); printf ("***** IOC application terminating *****\n"); epicsThreadSleep(1.0); epicsExit(0); }
/* * The body of the command interpreter */ static int iocshBody (const char *pathname, const char *commandLine) { FILE *fp = NULL; const char *filename = NULL; int icin, icout; char c; int quote, inword, backslash; const char *raw = NULL;; char *line = NULL; int lineno = 0; int argc; char **argv = NULL; int argvCapacity = 0; struct iocshRedirect *redirects = NULL; struct iocshRedirect *redirect = NULL; int sep; const char *prompt = NULL; const char *ifs = " \t(),\r"; iocshArgBuf *argBuf = NULL; int argBufCapacity = 0; struct iocshCommand *found; void *readlineContext = NULL; int wasOkToBlock; /* * See if command interpreter is interactive */ if (commandLine == NULL) { if ((pathname == NULL) || (strcmp (pathname, "<telnet>") == 0)) { if ((prompt = envGetConfigParamPtr(&IOCSH_PS1)) == NULL) prompt = "epics> "; } else { fp = fopen (pathname, "r"); if (fp == NULL) { fprintf(epicsGetStderr(), "Can't open %s: %s\n", pathname, strerror (errno)); return -1; } if ((filename = strrchr (pathname, '/')) == NULL) filename = pathname; else filename++; prompt = NULL; } /* * Create a command-line input context */ if ((readlineContext = epicsReadlineBegin(fp)) == NULL) { fprintf(epicsGetStderr(), "Can't allocate command-line object.\n"); if (fp) fclose(fp); return -1; } } /* * Set up redirection */ redirects = (struct iocshRedirect *)calloc(NREDIRECTS, sizeof *redirects); if (redirects == NULL) { fprintf(epicsGetStderr(), "Out of memory!\n"); return -1; } /* * Read commands till EOF or exit */ argc = 0; wasOkToBlock = epicsThreadIsOkToBlock(); epicsThreadSetOkToBlock(1); for (;;) { /* * Read a line */ if (commandLine) { if (raw != NULL) break; raw = commandLine; } else { if ((raw = epicsReadline(prompt, readlineContext)) == NULL) break; } lineno++; /* * Skip leading white-space */ icin = 0; while ((c = raw[icin]) && isspace(c)) { icin++; } /* * Ignore comment lines other than to echo * them if they came from a script. This * avoids macLib errors from comments. */ if (c == '#') { if ((prompt == NULL) && (commandLine == NULL)) puts(raw); continue; } /* * Expand macros */ free(line); if ((line = macEnvExpand(raw)) == NULL) continue; /* * Skip leading white-space coming from a macro */ while ((c = line[icin]) && isspace(c)) { icin++; } /* * Echo non-empty lines read from a script */ if ((prompt == NULL) && *line && (commandLine == NULL)) puts(line); /* * Ignore lines that became a comment or empty after macro expansion */ if (!c || c == '#') continue; /* * Break line into words */ icout = 0; inword = 0; argc = 0; quote = EOF; backslash = 0; redirect = NULL; for (;;) { if (argc >= argvCapacity) { char **av; argvCapacity += 50; av = (char **)realloc (argv, argvCapacity * sizeof *argv); if (av == NULL) { fprintf (epicsGetStderr(), "Out of memory!\n"); argc = -1; break; } argv = av; } c = line[icin++]; if (c == '\0') break; if ((quote == EOF) && !backslash && (strchr (ifs, c))) sep = 1; else sep = 0; if ((quote == EOF) && !backslash) { int redirectFd = 1; if (c == '\\') { backslash = 1; continue; } if (c == '<') { if (redirect != NULL) { break; } redirect = &redirects[0]; sep = 1; redirect->mode = "r"; } if ((c >= '1') && (c <= '9') && (line[icin] == '>')) { redirectFd = c - '0'; c = '>'; icin++; } if (c == '>') { if (redirect != NULL) break; if (redirectFd >= NREDIRECTS) { redirect = &redirects[1]; break; } redirect = &redirects[redirectFd]; sep = 1; if (line[icin] == '>') { icin++; redirect->mode = "a"; } else { redirect->mode = "w"; } } } if (inword) { if (c == quote) { quote = EOF; } else { if ((quote == EOF) && !backslash) { if (sep) { inword = 0; line[icout++] = '\0'; } else if ((c == '"') || (c == '\'')) { quote = c; } else { line[icout++] = c; } } else { line[icout++] = c; } } } else { if (!sep) { if (((c == '"') || (c == '\'')) && !backslash) quote = c; if (redirect != NULL) { if (redirect->name != NULL) { argc = -1; break; } redirect->name = line + icout; redirect = NULL; } else { argv[argc++] = line + icout; } if (quote == EOF) line[icout++] = c; inword = 1; } } backslash = 0; } if (redirect != NULL) { showError(filename, lineno, "Illegal redirection."); continue; } if (argc < 0) break; if (quote != EOF) { showError(filename, lineno, "Unbalanced quote."); continue; } if (backslash) { showError(filename, lineno, "Trailing backslash."); continue; } if (inword) line[icout++] = '\0'; argv[argc] = NULL; /* * Special case -- Redirected input but no command * Treat as if 'iocsh filename'. */ if ((argc == 0) && (redirects[0].name != NULL)) { const char *commandFile = redirects[0].name; redirects[0].name = NULL; if (openRedirect(filename, lineno, redirects) < 0) continue; startRedirect(filename, lineno, redirects); iocshBody(commandFile, NULL); stopRedirect(filename, lineno, redirects); continue; } /* * Special command? */ if ((argc > 0) && (strcmp(argv[0], "exit") == 0)) break; /* * Set up redirection */ if ((openRedirect(filename, lineno, redirects) == 0) && (argc > 0)) { /* * Look up command */ found = (iocshCommand *)registryFind (iocshCmdID, argv[0]); if (found) { /* * Process arguments and call function */ struct iocshFuncDef const *piocshFuncDef = found->pFuncDef; for (int iarg = 0 ; ; ) { if (iarg == piocshFuncDef->nargs) { startRedirect(filename, lineno, redirects); (*found->func)(argBuf); break; } if (iarg >= argBufCapacity) { void *np; argBufCapacity += 20; np = realloc (argBuf, argBufCapacity * sizeof *argBuf); if (np == NULL) { fprintf (epicsGetStderr(), "Out of memory!\n"); argBufCapacity -= 20; break; } argBuf = (iocshArgBuf *)np; } if (piocshFuncDef->arg[iarg]->type == iocshArgArgv) { argBuf[iarg].aval.ac = argc-iarg; argBuf[iarg].aval.av = argv+iarg; iarg = piocshFuncDef->nargs; } else { if (!cvtArg (filename, lineno, ((iarg < argc) ? argv[iarg+1] : NULL), &argBuf[iarg], piocshFuncDef->arg[iarg])) break; iarg++; } } if ((prompt != NULL) && (strcmp(argv[0], "epicsEnvSet") == 0)) { const char *newPrompt; if ((newPrompt = envGetConfigParamPtr(&IOCSH_PS1)) != NULL) prompt = newPrompt; } } else { showError(filename, lineno, "Command %s not found.", argv[0]); } } stopRedirect(filename, lineno, redirects); } if (fp && (fp != stdin)) fclose (fp); if (redirects != NULL) { stopRedirect(filename, lineno, redirects); free (redirects); } free(line); free (argv); free (argBuf); errlogFlush(); if (readlineContext) epicsReadlineEnd(readlineContext); epicsThreadSetOkToBlock( wasOkToBlock); return 0; }
bool SystemConfigurationImpl::hasProperty(const string &key) { strncpy(_envParam.name,key.c_str(),key.length() + 1); const char* val = envGetConfigParamPtr(&_envParam); return (val != NULL) || _properties->hasProperty(key); }
// // udpiiu::udpiiu () // udpiiu::udpiiu ( epicsGuard < epicsMutex > & cacGuard, epicsTimerQueueActive & timerQueue, epicsMutex & cbMutexIn, epicsMutex & cacMutexIn, cacContextNotify & ctxNotifyIn, cac & cac, unsigned port, tsDLList < SearchDest > & searchDestListIn ) : recvThread ( *this, ctxNotifyIn, cbMutexIn, "CAC-UDP", epicsThreadGetStackSize ( epicsThreadStackMedium ), cac::lowestPriorityLevelAbove ( cac::lowestPriorityLevelAbove ( cac.getInitializingThreadsPriority () ) ) ), m_repeaterTimerNotify ( *this ), repeaterSubscribeTmr ( m_repeaterTimerNotify, timerQueue, cbMutexIn, ctxNotifyIn ), govTmr ( *this, timerQueue, cacMutexIn ), maxPeriod ( maxSearchPeriodDefault ), rtteMean ( minRoundTripEstimate ), rtteMeanDev ( 0 ), cacRef ( cac ), cbMutex ( cbMutexIn ), cacMutex ( cacMutexIn ), nBytesInXmitBuf ( 0 ), nTimers ( 0 ), beaconAnomalyTimerIndex ( 0 ), sequenceNumber ( 0 ), lastReceivedSeqNo ( 0 ), sock ( 0 ), repeaterPort ( 0 ), serverPort ( port ), localPort ( 0 ), shutdownCmd ( false ), lastReceivedSeqNoIsValid ( false ) { cacGuard.assertIdenticalMutex ( cacMutex ); if ( envGetConfigParamPtr ( & EPICS_CA_MAX_SEARCH_PERIOD ) ) { long longStatus = envGetDoubleConfigParam ( & EPICS_CA_MAX_SEARCH_PERIOD, & this->maxPeriod ); if ( ! longStatus ) { if ( this->maxPeriod < maxSearchPeriodLowerLimit ) { epicsPrintf ( "\"%s\" out of range (low)\n", EPICS_CA_MAX_SEARCH_PERIOD.name ); this->maxPeriod = maxSearchPeriodLowerLimit; epicsPrintf ( "Setting \"%s\" = %f seconds\n", EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod ); } } else { epicsPrintf ( "EPICS \"%s\" wasnt a real number\n", EPICS_CA_MAX_SEARCH_PERIOD.name ); epicsPrintf ( "Setting \"%s\" = %f seconds\n", EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod ); } } double powerOfTwo = log ( this->maxPeriod / minRoundTripEstimate ) / log ( 2.0 ); this->nTimers = static_cast < unsigned > ( powerOfTwo + 1.0 ); if ( this->nTimers > channelNode::getMaxSearchTimerCount () ) { this->nTimers = channelNode::getMaxSearchTimerCount (); epicsPrintf ( "\"%s\" out of range (high)\n", EPICS_CA_MAX_SEARCH_PERIOD.name ); epicsPrintf ( "Setting \"%s\" = %f seconds\n", EPICS_CA_MAX_SEARCH_PERIOD.name, (1<<(this->nTimers-1)) * minRoundTripEstimate ); } powerOfTwo = log ( beaconAnomalySearchPeriod / minRoundTripEstimate ) / log ( 2.0 ); this->beaconAnomalyTimerIndex = static_cast < unsigned > ( powerOfTwo + 1.0 ); if ( this->beaconAnomalyTimerIndex >= this->nTimers ) { this->beaconAnomalyTimerIndex = this->nTimers - 1; } this->ppSearchTmr.reset ( new epics_auto_ptr < class searchTimer > [ this->nTimers ] ); for ( unsigned i = 0; i < this->nTimers; i++ ) { this->ppSearchTmr[i].reset ( new searchTimer ( *this, timerQueue, i, cacMutexIn, i > this->beaconAnomalyTimerIndex ) ); } this->repeaterPort = envGetInetPortConfigParam ( &EPICS_CA_REPEATER_PORT, static_cast <unsigned short> (CA_REPEATER_PORT) ); this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); if ( this->sock == INVALID_SOCKET ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ("CAC: unable to create datagram socket because = \"%s\"\n", sockErrBuf ); throwWithLocation ( noSocket () ); } int boolValue = true; int status = setsockopt ( this->sock, SOL_SOCKET, SO_BROADCAST, (char *) &boolValue, sizeof ( boolValue ) ); if ( status < 0 ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ("CAC: IP broadcasting enable failed because = \"%s\"\n", sockErrBuf ); } #if 0 { /* * some concern that vxWorks will run out of mBuf's * if this change is made joh 11-10-98 * * bump up the UDP recv buffer */ int size = 1u<<15u; status = setsockopt ( this->sock, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof (size) ); if (status<0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "CAC: unable to set socket option SO_RCVBUF because \"%s\"\n", sockErrBuf ); } } #endif // force a bind to an unconstrained address so we can obtain // the local port number below static const unsigned short PORT_ANY = 0u; osiSockAddr addr; memset ( (char *)&addr, 0 , sizeof (addr) ); addr.ia.sin_family = AF_INET; addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY ); addr.ia.sin_port = htons ( PORT_ANY ); status = bind (this->sock, &addr.sa, sizeof (addr) ); if ( status < 0 ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); epicsSocketDestroy (this->sock); errlogPrintf ( "CAC: unable to bind to an unconstrained address because = \"%s\"\n", sockErrBuf ); throwWithLocation ( noSocket () ); } { osiSockAddr tmpAddr; osiSocklen_t saddr_length = sizeof ( tmpAddr ); status = getsockname ( this->sock, &tmpAddr.sa, &saddr_length ); if ( status < 0 ) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); epicsSocketDestroy ( this->sock ); errlogPrintf ( "CAC: getsockname () error was \"%s\"\n", sockErrBuf ); throwWithLocation ( noSocket () ); } if ( tmpAddr.sa.sa_family != AF_INET) { epicsSocketDestroy ( this->sock ); errlogPrintf ( "CAC: UDP socket was not inet addr family\n" ); throwWithLocation ( noSocket () ); } this->localPort = ntohs ( tmpAddr.ia.sin_port ); } /* * load user and auto configured * broadcast address list */ ELLLIST dest; ellInit ( & dest ); configureChannelAccessAddressList ( & dest, this->sock, this->serverPort ); while ( osiSockAddrNode * pNode = reinterpret_cast < osiSockAddrNode * > ( ellGet ( & dest ) ) ) { SearchDestUDP & searchDest = * new SearchDestUDP ( pNode->addr, *this ); _searchDestList.add ( searchDest ); free ( pNode ); } /* add list of tcp name service addresses */ _searchDestList.add ( searchDestListIn ); caStartRepeaterIfNotInstalled ( this->repeaterPort ); this->pushVersionMsg (); // start timers and receive thread for ( unsigned j =0; j < this->nTimers; j++ ) { this->ppSearchTmr[j]->start ( cacGuard ); } this->govTmr.start (); this->repeaterSubscribeTmr.start (); this->recvThread.start (); }
/* * RSRV_ONLINE_NOTIFY_TASK */ void rsrv_online_notify_task(void *pParm) { unsigned priorityOfSelf = epicsThreadGetPrioritySelf (); osiSockAddrNode *pNode; double delay; double maxdelay; long longStatus; double maxPeriod; caHdr msg; int status; SOCKET sock; int intTrue = TRUE; unsigned short port; ca_uint32_t beaconCounter = 0; char * pStr; int autoBeaconAddr; ELLLIST autoAddrList; char buf[16]; unsigned priorityOfUDP; epicsThreadBooleanStatus tbs; epicsThreadId tid; taskwdInsert (epicsThreadGetIdSelf(),NULL,NULL); if ( envGetConfigParamPtr ( & EPICS_CAS_BEACON_PERIOD ) ) { longStatus = envGetDoubleConfigParam ( & EPICS_CAS_BEACON_PERIOD, & maxPeriod ); } else { longStatus = envGetDoubleConfigParam ( & EPICS_CA_BEACON_PERIOD, & maxPeriod ); } if (longStatus || maxPeriod<=0.0) { maxPeriod = 15.0; epicsPrintf ("EPICS \"%s\" float fetch failed\n", EPICS_CAS_BEACON_PERIOD.name); epicsPrintf ("Setting \"%s\" = %f\n", EPICS_CAS_BEACON_PERIOD.name, maxPeriod); } delay = 0.02; /* initial beacon period in sec */ maxdelay = maxPeriod; /* * Open the socket. * Use ARPA Internet address format and datagram socket. * Format described in <sys/socket.h>. */ if ( (sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) { errlogPrintf ("CAS: online socket creation error\n"); epicsThreadSuspendSelf (); } status = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *)&intTrue, sizeof(intTrue)); if (status<0) { errlogPrintf ("CAS: online socket set up error\n"); epicsThreadSuspendSelf (); } { /* * this connect is to supress a warning message on Linux * when we shutdown the read side of the socket. If it * fails (and it will on old ip kernels) we just ignore * the failure. */ osiSockAddr sockAddr; sockAddr.ia.sin_family = AF_UNSPEC; sockAddr.ia.sin_port = htons ( 0 ); sockAddr.ia.sin_addr.s_addr = htonl (0); connect ( sock, & sockAddr.sa, sizeof ( sockAddr.sa ) ); shutdown ( sock, SHUT_RD ); } memset((char *)&msg, 0, sizeof msg); msg.m_cmmd = htons (CA_PROTO_RSRV_IS_UP); msg.m_count = htons (ca_server_port); msg.m_dataType = htons (CA_MINOR_PROTOCOL_REVISION); ellInit ( & beaconAddrList ); ellInit ( & autoAddrList ); pStr = envGetConfigParam(&EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf); if ( ! pStr ) { pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf); } if (pStr) { if (strstr(pStr,"no")||strstr(pStr,"NO")) { autoBeaconAddr = FALSE; } else if (strstr(pStr,"yes")||strstr(pStr,"YES")) { autoBeaconAddr = TRUE; } else { fprintf(stderr, "CAS: EPICS_CA(S)_AUTO_ADDR_LIST = \"%s\"? Assuming \"YES\"\n", pStr); autoBeaconAddr = TRUE; } } else { autoBeaconAddr = TRUE; } /* * load user and auto configured * broadcast address list */ if (envGetConfigParamPtr(&EPICS_CAS_BEACON_PORT)) { port = envGetInetPortConfigParam (&EPICS_CAS_BEACON_PORT, (unsigned short) CA_REPEATER_PORT ); } else { port = envGetInetPortConfigParam (&EPICS_CA_REPEATER_PORT, (unsigned short) CA_REPEATER_PORT ); } /* * discover beacon addresses associated with this interface */ if ( autoBeaconAddr ) { osiSockAddr addr; ELLLIST tmpList; ellInit ( &tmpList ); addr.ia.sin_family = AF_UNSPEC; osiSockDiscoverBroadcastAddresses (&tmpList, sock, &addr); forcePort ( &tmpList, port ); removeDuplicateAddresses ( &autoAddrList, &tmpList, 1 ); } /* * by default use EPICS_CA_ADDR_LIST for the * beacon address list */ { const ENV_PARAM *pParam; if (envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST) || envGetConfigParamPtr(&EPICS_CAS_BEACON_ADDR_LIST)) { pParam = &EPICS_CAS_BEACON_ADDR_LIST; } else { pParam = &EPICS_CA_ADDR_LIST; } /* * add in the configured addresses */ addAddrToChannelAccessAddressList ( &autoAddrList, pParam, port, pParam == &EPICS_CA_ADDR_LIST ); } removeDuplicateAddresses ( &beaconAddrList, &autoAddrList, 0 ); if ( ellCount ( &beaconAddrList ) == 0 ) { errlogPrintf ("The CA server's beacon address list was empty after initialization?\n"); } # ifdef DEBUG printChannelAccessAddressList (&beaconAddrList); # endif tbs = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfUDP ); if ( tbs != epicsThreadBooleanStatusSuccess ) { priorityOfUDP = priorityOfSelf; } casudp_startStopEvent = epicsEventMustCreate(epicsEventEmpty); casudp_ctl = ctlPause; tid = epicsThreadCreate ( "CAS-UDP", priorityOfUDP, epicsThreadGetStackSize (epicsThreadStackMedium), cast_server, 0 ); if ( tid == 0 ) { epicsPrintf ( "CAS: unable to start UDP daemon thread\n" ); } epicsEventMustWait(casudp_startStopEvent); epicsEventSignal(beacon_startStopEvent); while (TRUE) { pNode = (osiSockAddrNode *) ellFirst (&beaconAddrList); while (pNode) { char buf[64]; status = connect (sock, &pNode->addr.sa, sizeof(pNode->addr.sa)); if (status<0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf)); errlogPrintf ( "%s: CA beacon routing (connect to \"%s\") error was \"%s\"\n", __FILE__, buf, sockErrBuf); } else { struct sockaddr_in if_addr; osiSocklen_t size = sizeof (if_addr); status = getsockname (sock, (struct sockaddr *) &if_addr, &size); if (status<0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "%s: CA beacon routing (getsockname) error was \"%s\"\n", __FILE__, sockErrBuf); } else if (if_addr.sin_family==AF_INET) { msg.m_available = if_addr.sin_addr.s_addr; msg.m_cid = htonl ( beaconCounter ); status = send (sock, (char *)&msg, sizeof(msg), 0); if (status < 0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf)); errlogPrintf ( "%s: CA beacon (send to \"%s\") error was \"%s\"\n", __FILE__, buf, sockErrBuf); } else { assert (status == sizeof(msg)); } } } pNode = (osiSockAddrNode *) pNode->node.next; } epicsThreadSleep(delay); if (delay<maxdelay) { delay *= 2.0; if (delay>maxdelay) { delay = maxdelay; } } beaconCounter++; /* expected to overflow */ while (beacon_ctl == ctlPause) { epicsThreadSleep(0.1); delay = 0.02; /* Restart beacon timing if paused */ } } }
/* * CAST_SERVER * * service UDP messages * */ void cast_server(void *pParm) { struct sockaddr_in sin; int status; int count=0; struct sockaddr_in new_recv_addr; osiSocklen_t recv_addr_size; unsigned short port; osiSockIoctl_t nchars; if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) { port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } else { port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } recv_addr_size = sizeof(new_recv_addr); if( IOC_cast_sock!=0 && IOC_cast_sock!=INVALID_SOCKET ) { epicsSocketDestroy ( IOC_cast_sock ); } /* * Open the socket. * Use ARPA Internet address format and datagram socket. */ if ( ( IOC_cast_sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0) ) == INVALID_SOCKET ) { epicsPrintf ("CAS: cast socket creation error\n"); epicsThreadSuspendSelf (); } /* * some concern that vxWorks will run out of mBuf's * if this change is made * * joh 11-10-98 */ #if 0 { /* * * this allows for faster connects by queuing * additional incomming UDP search frames * * this allocates a 32k buffer * (uses a power of two) */ int size = 1u<<15u; status = setsockopt (IOC_cast_sock, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size)); if (status<0) { epicsPrintf ("CAS: unable to set cast socket size\n"); } } #endif epicsSocketEnableAddressUseForDatagramFanout ( IOC_cast_sock ); /* Zero the sock_addr structure */ memset((char *)&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(port); /* get server's Internet address */ if( bind(IOC_cast_sock, (struct sockaddr *)&sin, sizeof (sin)) < 0){ char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); epicsPrintf ("CAS: UDP server port bind error was \"%s\"\n", sockErrBuf ); epicsSocketDestroy ( IOC_cast_sock ); epicsThreadSuspendSelf (); } /* * setup new client structure but reuse old structure if * possible * */ while ( TRUE ) { prsrv_cast_client = create_client ( IOC_cast_sock, IPPROTO_UDP ); if ( prsrv_cast_client ) { break; } epicsThreadSleep(300.0); } casAttachThreadToClient ( prsrv_cast_client ); /* * add placeholder for the first version message should it be needed */ rsrv_version_reply ( prsrv_cast_client ); epicsEventSignal(casudp_startStopEvent); while (TRUE) { status = recvfrom ( IOC_cast_sock, prsrv_cast_client->recv.buf, prsrv_cast_client->recv.maxstk, 0, (struct sockaddr *)&new_recv_addr, &recv_addr_size); if (status < 0) { if (SOCKERRNO != SOCK_EINTR) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); epicsPrintf ("CAS: UDP recv error (errno=%s)\n", sockErrBuf); epicsThreadSleep(1.0); } } else if (casudp_ctl == ctlRun) { prsrv_cast_client->recv.cnt = (unsigned) status; prsrv_cast_client->recv.stk = 0ul; epicsTimeGetCurrent(&prsrv_cast_client->time_at_last_recv); prsrv_cast_client->minor_version_number = 0; prsrv_cast_client->seqNoOfReq = 0; /* * If we are talking to a new client flush to the old one * in case we are holding UDP messages waiting to * see if the next message is for this same client. */ if (prsrv_cast_client->send.stk>sizeof(caHdr)) { status = memcmp( (void *)&prsrv_cast_client->addr, (void *)&new_recv_addr, recv_addr_size); if(status){ /* * if the address is different */ cas_send_dg_msg(prsrv_cast_client); prsrv_cast_client->addr = new_recv_addr; } } else { prsrv_cast_client->addr = new_recv_addr; } if (CASDEBUG>1) { char buf[40]; ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf)); errlogPrintf ("CAS: cast server msg of %d bytes from addr %s\n", prsrv_cast_client->recv.cnt, buf); } if (CASDEBUG>2) count = ellCount (&prsrv_cast_client->chanList); status = camessage ( prsrv_cast_client ); if(status == RSRV_OK){ if(prsrv_cast_client->recv.cnt != prsrv_cast_client->recv.stk){ char buf[40]; ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf)); epicsPrintf ("CAS: partial (damaged?) UDP msg of %d bytes from %s ?\n", prsrv_cast_client->recv.cnt-prsrv_cast_client->recv.stk, buf); } } else { char buf[40]; ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf)); epicsPrintf ("CAS: invalid (damaged?) UDP request from %s ?\n", buf); } if (CASDEBUG>2) { if ( ellCount (&prsrv_cast_client->chanList) ) { errlogPrintf ("CAS: Fnd %d name matches (%d tot)\n", ellCount(&prsrv_cast_client->chanList)-count, ellCount(&prsrv_cast_client->chanList)); } } } /* * allow messages to batch up if more are comming */ nchars = 0; /* supress purify warning */ status = socket_ioctl(IOC_cast_sock, FIONREAD, &nchars); if (status<0) { errlogPrintf ("CA cast server: Unable to fetch N characters pending\n"); cas_send_dg_msg (prsrv_cast_client); clean_addrq (); } else if (nchars == 0) { cas_send_dg_msg (prsrv_cast_client); clean_addrq (); } } }