void __pmConnectGetPorts(pmHostSpec *host) { PM_INIT_LOCKS(); PM_LOCK(__pmLock_libpcp); load_pmcd_ports(); if (__pmAddHostPorts(host, global_portlist, global_nports) < 0) { __pmNotifyErr(LOG_WARNING, "__pmConnectGetPorts: portlist dup failed, " "using default PMCD_PORT (%d)\n", SERVER_PORT); host->ports[0] = SERVER_PORT; host->nports = 1; } PM_UNLOCK(__pmLock_libpcp); }
/* * Parse a host specification, with optional ports and proxy host(s). * Examples: * pcp -h app1.aconex.com:44321,[email protected]:44322 * pcp -h app1.aconex.com:[email protected]:44322 * pcp -h app1.aconex.com:[email protected] * pcp -h [email protected] * pcp -h app1.aconex.com:44321 * pcp -h 192.168.122.1:44321 * pcp -h [fe80::5eff:35ff:fe07:55ca]:44321,4321@[fe80::5eff:35ff:fe07:55cc]:44322 * pcp -h [fe80::5eff:35ff:fe07:55ca]:44321 * * Basic algorithm: * look for first colon, @ or null; preceding text is hostname * if colon, look for comma, @ or null, preceding text is port * while comma, look for comma, @ or null, preceding text is next port * if @, start following host specification at the following character, * by returning to the start and repeating the above for the next chunk. * Note: * IPv6 addresses contain colons and, so, must be separated from the * rest of the spec somehow. A common notation among ipv6-enabled * applications is to enclose the address within brackets, as in * [fe80::5eff:35ff:fe07:55ca]:44321. We keep it simple, however, * and allow any host spec to be enclosed in brackets. * Note: * Currently only two hosts are useful, but ability to handle more than * one optional proxy host is there (i.e. proxy ->proxy ->... ->pmcd), * in case someone implements the pmproxy->pmproxy protocol extension. */ static int /* 0 -> ok, PM_ERR_GENERIC -> error message is set */ parseHostSpec( const char *spec, char **position, /* parse this string, return end char */ pmHostSpec **rslt, /* result allocated and returned here */ int *count, char **errmsg) /* error message */ { pmHostSpec *hsp = NULL; const char *s, *start, *next; int nhosts = 0, sts = 0; for (s = start = *position; s != NULL; s++) { /* Allow the host spec to be enclosed in brackets. */ if (s == start && *s == '[') { for (s++; *s != ']' && *s != '\0'; s++) ; if (*s != ']') { hostError(spec, s, "missing closing ']' for host spec", errmsg); sts = PM_ERR_GENERIC; goto fail; } next = s + 1; /* past the trailing ']' */ if (*next != ':' && *next != '@' && *next != '\0' && *next != '/' && *next != '?') { hostError(spec, next, "extra characters after host spec", errmsg); sts = PM_ERR_GENERIC; goto fail; } start++; /* past the initial '[' */ } else next = s; if (*next == ':' || *next == '@' || *next == '\0' || *next == '/' || *next == '?') { if (s == *position) break; else if (s == start) continue; hsp = hostAdd(hsp, &nhosts, start, s - start); if (hsp == NULL) { sts = -ENOMEM; goto fail; } s = next; if (*s == ':') { for (++s, start = s; s != NULL; s++) { if (*s == ',' || *s == '@' || *s == '\0' || *s == '/' || *s == '?') { if (s - start < 1) { hostError(spec, s, "missing port", errmsg); sts = PM_ERR_GENERIC; goto fail; } int port = atoi(start); sts = __pmAddHostPorts(&hsp[nhosts-1], &port, 1); if (sts < 0) goto fail; start = s + 1; if (*s == '@' || *s == '\0' || *s == '/' || *s == '?') break; continue; } if (isdigit((int)*s)) continue; hostError(spec, s, "non-numeric port", errmsg); sts = PM_ERR_GENERIC; goto fail; } } if (*s == '@') { start = s+1; continue; } break; } } *position = (char *)s; *count = nhosts; *rslt = hsp; return 0; fail: __pmFreeHostSpec(hsp, nhosts); *rslt = NULL; *count = 0; return sts; }