/* * Check basic authentication. Return zero if authenticated. * Return -1 if failed authentication. * Return 1 if authentication not attempted. */ int basicauth_check (XML *xml, char *path, char *req) { int i, n; char *uid, *pw; char buf[DBUFSZ]; debug ("request: %s\n", req); /* is basic auth required? */ if ((n = xml_count (xml, path)) < 1) return (0); /* get authentication header */ uid = strstr (req, "Authorization: Basic "); if (uid == NULL) return (1); uid += 21; /* limit b64 decoding */ if ((pw = strchr (uid, '\n')) != NULL) *pw = 0; b64_decode (buf, uid); if (pw != NULL) /* restore if limited */ *pw = '\n'; uid = buf; if ((pw = strchr (uid, ':')) == NULL) return (1); *pw++ = 0; for (i = 0; i < n; i++) /* check against users */ { if ((strcmp (uid, xml_getf (xml, "%s%c%d%cUserID", path, xml->indx_sep, i, xml->path_sep)) == 0) && (strcmp (pw, xml_getf (xml, "%s%c%d%cPassword", path, xml->indx_sep, i, xml->path_sep)) == 0)) return (0); } return (-1); }
/* * find the index for a repeated configuration item */ cfg_index (XML *xml, char *path, char *name) { int i, n; char *ch; n = xml_count (xml, path); for (i = 0; i < n; i++) { if (!strcmp (name, xml_getf (xml, "%s[%d].Name", path, i))) return (i); } error ("Can't find name matching %s for %s\n", name, path); return (-1); }
/* * Poll all queues... * a thread, expected to be started from the TASKQ. Note you must * re-register processors once this task exits. * * Note we expect sender_xml to have QueueInfo embedded! */ int qpoller_task (void *parm) { int i, poll_interval, num_queues; QPOLLER *p; QPOLLERJOB *j; TASKQ *q; XML *xml = (XML *) parm; info ("Queue Poller starting\n"); num_queues = xml_count (xml, QP_QUEUE); if ((poll_interval = xml_get_int (xml, QP_INFO".PollInterval")) < 1) poll_interval = 5; poll_interval *= 1000; if ((i = xml_get_int (xml, QP_INFO".MaxThreads")) < 1) i = 1; q = task_allocq (i, poll_interval); debug ("%d queues %d interval\n", num_queues, poll_interval); while (phineas_running ()) { for (i = 0; i < num_queues; i++) { qpoller_poll (xml, i, q); } sleep (poll_interval); } debug ("Queue Poller shutting down...\n"); task_stop (q); task_freeq (q); while ((j = QpollerJobs) != NULL) { QpollerJobs = j->next; free (j); } while ((p = Qpoller) != NULL) { Qpoller = p->next; free (p); } info ("Queue Poller exiting\n"); return (0); }
// Return the data for all the names[], start .. end etc. // as get_values() is supposed to return them. // // Returns raw values if interpol <= 0.0. // Returns 0 on error. xmlrpc_value *get_sheet_data(xmlrpc_env *env, int key, const stdVector<stdString> names, const epicsTime &start, const epicsTime &end, long count, ReaderFactory::How how, double delta) { try { #ifdef LOGFILE stdString txt; LOG_MSG("get_sheet_data\n"); LOG_MSG("Start : %s\n", epicsTimeTxt(start, txt)); LOG_MSG("End : %s\n", epicsTimeTxt(end, txt)); LOG_MSG("Method: %s\n", ReaderFactory::toString(how, delta)); #endif AutoPtr<Index> index(open_index(env, key)); if (env->fault_occurred) return 0; AutoPtr<SpreadsheetReader> sheet(new SpreadsheetReader(*index, how, delta)); AutoXmlRpcValue results(xmlrpc_build_value(env, "()")); if (env->fault_occurred) return 0; long name_count = names.size(); AutoArrayPtr<AutoXmlRpcValue> meta (new AutoXmlRpcValue[name_count]); AutoArrayPtr<AutoXmlRpcValue> values (new AutoXmlRpcValue[name_count]); AutoArrayPtr<xmlrpc_int32> xml_type (new xmlrpc_int32[name_count]); AutoArrayPtr<xmlrpc_int32> xml_count(new xmlrpc_int32[name_count]); AutoArrayPtr<size_t> ch_vals (new size_t[name_count]); bool ok = sheet->find(names, &start); long i; // Per-channel meta-info. for (i=0; i<name_count; ++i) { #ifdef LOGFILE LOG_MSG("Handling '%s'\n", names[i].c_str()); #endif ch_vals[i] = 0; values[i] = xmlrpc_build_value(env, "()"); if (env->fault_occurred) return 0; if (sheet->found(i)) { // Fix meta/type/count based on first value meta[i] = encode_ctrl_info(env, &sheet->getInfo(i)); dbr_type_to_xml_type(sheet->getType(i), sheet->getCount(i), xml_type[i], xml_count[i]); #if 0 LOG_MSG("Ch %lu: type, count = %d, %d\n", i, (int)xml_type[i], (int)xml_count[i]); #endif } else { // Channel exists, but has no data meta[i] = encode_ctrl_info(env, 0); xml_type[i] = XML_ENUM; xml_count[i] = 1; } } // Collect values long num_vals = 0; while (ok && num_vals < count && sheet->getTime() < end) { for (i=0; i<name_count; ++i) { if (sheet->get(i)) { ++ch_vals[i]; encode_value(env, sheet->getType(i), sheet->getCount(i), sheet->getTime(), sheet->get(i), xml_type[i], xml_count[i], values[i]); } else { // Encode as no value, but one of them ;-) // to avoid confusion w/ viewers that like to see some data in any case. encode_value(env, 0, 1, sheet->getTime(), 0, xml_type[i], xml_count[i], values[i]); } } ++num_vals; ok = sheet->next(); } // Assemble result = { name, meta, type, count, values } for (i=0; i<name_count; ++i) { AutoXmlRpcValue result( xmlrpc_build_value(env, "{s:s,s:V,s:i,s:i,s:V}", "name", names[i].c_str(), "meta", meta[i].get(), "type", xml_type[i], "count", xml_count[i], "values", values[i].get())); // Add to result array xmlrpc_array_append_item(env, results, result); #ifdef LOGFILE LOG_MSG("Ch %lu: %zu values\n", i, ch_vals[i]); #endif } #ifdef LOGFILE LOG_MSG("%ld values total\n", num_vals); #endif return results.release(); } catch (GenericException &e) { #ifdef LOGFILE LOG_MSG("Error:\n%s\n", e.what()); #endif xmlrpc_env_set_fault_formatted(env, ARCH_DAT_DATA_ERROR, "%s", e.what()); } return 0; }