static int test_strdupcat(void) { su_home_t home[1] = { SU_HOME_INIT(home) }; BEGIN(); TEST_S(su_strdup(home, "foo"), "foo"); TEST_S(su_strcat(home, "foo", "bar"), "foobar"); TEST_S(su_strndup(home, "foobar", 3), "foo"); TEST_S(su_strcat_all(home, NULL), ""); TEST_S(su_strcat_all(home, "a", "", "b", "", NULL), "ab"); su_home_deinit(home); END(); }
/** Create a http site object. * * The function nth_site_create() allocates and initializes a web site * object. A web site object can be either * - a primary http server (@a parent is NULL), * - a virtual http server (@a address contains hostpart), or * - a site within a server * (@a address does not have hostpart, only path part). * * @param parent pointer to parent site * (NULL when creating a primary server object) * @param callback pointer to callback function called when * a request is received * @param magic application context included in callback parameters * @param address absolute or relative URI specifying the address of * site * @param tag, value, ... list of tagged parameters * * @TAGS * If the @a parent is NULL, the list of tagged parameters must contain * NTHTAG_ROOT() used to create the server engine. Tags supported when @a * parent is NULL are NTHTAG_ROOT(), NTHTAG_MCLASS(), TPTAG_REUSE(), * HTTPTAG_SERVER(), and HTTPTAG_SERVER_STR(). All the tags are passed to * tport_tcreate() and tport_tbind(), too. * * @since Support for multiple sites was added to @VERSION_1_12_4 */ nth_site_t *nth_site_create(nth_site_t *parent, nth_request_f *callback, nth_site_magic_t *magic, url_string_t const *address, tag_type_t tag, tag_value_t value, ...) { nth_site_t *site = NULL, **prev = NULL; su_home_t home[SU_HOME_AUTO_SIZE(256)]; url_t *url, url0[1]; server_t *srv = NULL; ta_list ta; char *path = NULL; size_t usize; int is_host, is_path, wildcard = 0; su_home_auto(home, sizeof home); if (parent && url_is_string(address)) { char const *s = (char const *)address; size_t sep = strcspn(s, "/:"); if (parent->site_path) { /* subpath */ url_init(url0, (enum url_type_e)parent->site_url->url_type); url0->url_path = s; address = (url_string_t*)url0; } else if (s[sep] == ':') /* absolute URL with scheme */; else if (s[sep] == '\0' && strchr(s, '.') && host_is_valid(s)) { /* looks like a domain name */; url_init(url0, (enum url_type_e)parent->site_url->url_type); url0->url_host = s; address = (url_string_t*)url0; } else { /* looks like a path */ url_init(url0, (enum url_type_e)parent->site_url->url_type); url0->url_path = s; address = (url_string_t*)url0; } } url = url_hdup(home, address->us_url); if (!url || !callback) return NULL; is_host = url->url_host != NULL; is_path = url->url_path != NULL; if (is_host && is_path) { SU_DEBUG_3(("nth_site_create(): virtual host and path simultanously\n")); errno = EINVAL; goto error; } if (!parent && !is_host) { SU_DEBUG_3(("nth_site_create(): host is required\n")); errno = EINVAL; goto error; } if (parent) { if (!parent->site_isdir) { SU_DEBUG_3(("nth_site_create(): invalid parent resource \n")); errno = EINVAL; goto error; } srv = parent->site_server; assert(srv); if (is_host) { prev = site_get_host(&srv->srv_sites, url->url_host, url->url_port); if (prev == NULL) { SU_DEBUG_3(("nth_site_create(): host %s:%s already exists\n", url->url_host, url->url_port ? url->url_port : "")); errno = EEXIST; goto error; } } else { size_t i, j; path = (char *)url->url_path; while (path[0] == '/') path++; /* Remove duplicate // */ for (i = j = 0; path[i];) { while (path[i] == '/' && path[i + 1] == '/') i++; path[j++] = path[i++]; } path[j] = path[i]; url = url0, *url = *parent->site_url; if (url->url_path) { url->url_path = su_strcat(home, url->url_path, path); if (!url->url_path) goto error; path = (char *)url->url_path + strlen(parent->site_url->url_path); } else url->url_path = path; prev = site_get_rslot(parent, path, &path); if (!prev || path[0] == '\0') { SU_DEBUG_3(("nth_site_create(): directory \"%s\" already exists\n", url->url_path)); errno = EEXIST; goto error; } } } if (!parent) { if (strcmp(url->url_host, "*") == 0 || host_cmp(url->url_host, "0.0.0.0") == 0 || host_cmp(url->url_host, "::") == 0) wildcard = 1, url->url_host = "*"; } usize = sizeof(*url) + url_xtra(url); ta_start(ta, tag, value); if (!parent) { srv = server_create(url, ta_tags(ta)); prev = &srv->srv_sites; } if (srv && (site = su_zalloc(srv->srv_home, (sizeof *site) + usize))) { site->site_url = (url_t *)(site + 1); url_dup((void *)(site->site_url + 1), usize - sizeof(*url), site->site_url, url); assert(prev); if ((site->site_next = *prev)) site->site_next->site_prev = &site->site_next; *prev = site, site->site_prev = prev; site->site_server = srv; if (path) { size_t path_len; site->site_path = site->site_url->url_path + (path - url->url_path); path_len = strlen(site->site_path); assert(path_len > 0); if (path_len > 0 && site->site_path[path_len - 1] == '/') path_len--, site->site_isdir = 1; site->site_path_len = path_len; } else { site->site_isdir = is_host; site->site_path = ""; site->site_path_len = 0; } site->site_wildcard = wildcard; site->site_callback = callback; site->site_magic = magic; if (parent) site->site_auth = parent->site_auth; nth_site_set_params(site, ta_tags(ta)); } ta_end(ta); error: su_home_deinit(home); return site; }
int dig_all_srvs(struct dig *dig, char const *tport, char const *host, double weight, switch_stream_handle_t *stream) { int i, j, n; int tcount, count = 0, scount; char *domain; struct { char const *proto; sres_record_t **answers; } srvs[N_TPORT + 1] = {{ NULL }}; tcount = count_transports(dig, tport, NULL); if (!tcount) return 0; for (i = 0, n = 0; dig->tports[i].name; i++) { if (tport && !su_casematch(dig->tports[i].name, tport)) continue; if (dig->sips && !transport_is_secure(dig->tports[i].name)) continue; domain = su_strcat(NULL, dig->tports[i].srv, host); if (domain) { if (sres_blocking_query(dig->sres, sres_type_srv, domain, 0, &srvs[n].answers) >= 0) { srvs[n++].proto = dig->tports[i].name; } free(domain); } } if (n == 0) return 0; for (i = 0; i < n; i++) { unsigned priority = 0, pweight = 0, m = 0; sres_record_t **answers = srvs[i].answers; char const *tport = srvs[i].proto; for (j = 0; answers[j]; j++) { sres_srv_record_t const *srv = answers[j]->sr_srv; if (srv->srv_record->r_type != sres_type_srv) continue; if (srv->srv_record->r_status != 0) continue; if (srv->srv_priority != priority && pweight != 0) { scount = dig_srv_at(dig, tport, answers, weight / n, pweight, priority, stream); if (scount) dig->preference++; count += scount; pweight = 0, m = 0; } priority = srv->srv_priority, pweight += srv->srv_weight, m++; } if (m) { scount = dig_srv_at(dig, tport, answers, weight / n, pweight, priority, stream); if (scount) dig->preference++; count += scount; } } return count; }