Beispiel #1
0
static char* s_Firewall_Write(size_t reserve, const USERV_Info* u_info)
{
    const char* name = SERV_TypeStr(u_info->firewall.type);
    size_t namelen = strlen(name);
    char* str = (char*) malloc(reserve + (namelen ? namelen + 1 : 0));

    if (str)
        strcpy(str + reserve, name);
    return str;
}
static const SLBSM_Host* s_LookupHost(HEAP heap, const SERV_ITER iter,
                                      const SLBSM_Service* svc)
{
    unsigned int addr =
        svc->info.host ? svc->info.host : s_GetLocalHostAddress(heap);
    const SLBSM_Host* host = LBSM_LookupHost(heap, addr, &svc->entry);
    if (!host  ||  host->entry.good < iter->time) {
        if (svc->info.rate > 0.0) {
            char buf[40];
            if (SOCK_ntoa(addr, buf, sizeof(buf)) != 0)
                strcpy(buf, "(unknown)");
            CORE_LOGF_X(8, eLOG_Error,
                        ("Dynamic %s server `%s' on [%s] w/%s host entry",
                         SERV_TypeStr(svc->info.type),
                         (const char*) svc + svc->name,
                         buf, host ? "outdated" : "o"));
        }
        return 0;
    }
    return host;
}
Beispiel #3
0
char* SERV_Print(SERV_ITER iter, SConnNetInfo* net_info, int/*bool*/ but_last)
{
    static const char kClientRevision[] = "Client-Revision: %hu.%hu\r\n";
    static const char kAcceptedServerTypes[] = "Accepted-Server-Types:";
    static const char kUsedServerInfo[] = "Used-Server-Info: ";
    static const char kNcbiFWPorts[] = "NCBI-Firewall-Ports: ";
    static const char kServerCount[] = "Server-Count: ";
    static const char kPreference[] = "Preference: ";
    static const char kSkipInfo[] = "Skip-Info-%u: ";
    static const char kAffinity[] = "Affinity: ";
    char buffer[128], *str;
    size_t buflen, i;
    TSERV_Type t;
    BUF buf = 0;

    /* Put client version number */
    buflen = sprintf(buffer, kClientRevision,
                     SERV_CLIENT_REVISION_MAJOR, SERV_CLIENT_REVISION_MINOR);
    assert(buflen < sizeof(buffer));
    if (!BUF_Write(&buf, buffer, buflen)) {
        BUF_Destroy(buf);
        return 0;
    }
    if (iter) {
        if (net_info && !net_info->http_referer && iter->op && iter->op->name)
            s_SetDefaultReferer(iter, net_info);
        /* Accepted server types */
        buflen = sizeof(kAcceptedServerTypes) - 1;
        memcpy(buffer, kAcceptedServerTypes, buflen);
        for (t = 1;  t;  t <<= 1) {
            if (iter->type & t) {
                const char* name = SERV_TypeStr((ESERV_Type) t);
                size_t namelen = strlen(name);
                if (!namelen  ||  buflen + 1 + namelen + 2 >= sizeof(buffer))
                    break;
                buffer[buflen++] = ' ';
                memcpy(buffer + buflen, name, namelen);
                buflen += namelen;
            }
        }
        if (buffer[buflen - 1] != ':') {
            strcpy(&buffer[buflen], "\r\n");
            assert(strlen(buffer) == buflen+2  &&  buflen+2 < sizeof(buffer));
            if (!BUF_Write(&buf, buffer, buflen + 2)) {
                BUF_Destroy(buf);
                return 0;
            }
        }
        if (iter->ismask  ||  (iter->pref  &&  (iter->host | iter->port))) {
            /* FIXME: To obsolete? */
            /* How many server-infos for the dispatcher to send to us */
            if (!BUF_Write(&buf, kServerCount, sizeof(kServerCount) - 1)  ||
                !BUF_Write(&buf,
                           iter->ismask ? "10\r\n" : "ALL\r\n",
                           iter->ismask ?       4  :        5)) {
                BUF_Destroy(buf);
                return 0;
            }
        }
        if (iter->type & fSERV_Firewall) {
            /* Firewall */
            s_PrintFirewallPorts(buffer, sizeof(buffer), net_info);
            if (*buffer
                &&  (!BUF_Write(&buf, kNcbiFWPorts, sizeof(kNcbiFWPorts)-1)  ||
                     !BUF_Write(&buf, buffer, strlen(buffer))                ||
                     !BUF_Write(&buf, "\r\n", 2))) {
                BUF_Destroy(buf);
                return 0;
            }
        }
        if (iter->pref  &&  (iter->host | iter->port)) {
            /* Preference */
            buflen  = SOCK_HostPortToString(iter->host, iter->port,
                                            buffer, sizeof(buffer));
            buflen += sprintf(buffer + buflen, " %.2lf%%\r\n", iter->pref*1e2);
            if (!BUF_Write(&buf, kPreference, sizeof(kPreference) - 1)  ||
                !BUF_Write(&buf, buffer, buflen)) {
                BUF_Destroy(buf);
                return 0;
            }
        }
        if (iter->arglen) {
            /* Affinity */
            if (!BUF_Write(&buf, kAffinity, sizeof(kAffinity) - 1)           ||
                !BUF_Write(&buf, iter->arg, iter->arglen)                    ||
                (iter->val  &&  (!BUF_Write(&buf, "=", 1)                    ||
                                 !BUF_Write(&buf, iter->val, iter->vallen))) ||
                !BUF_Write(&buf, "\r\n", 2)) {
                BUF_Destroy(buf);
                return 0;
            }
        }
        /* Drop any outdated skip entries */
        iter->time = (TNCBI_Time) time(0);
        s_SkipSkip(iter);
        /* Put all the rest into rejection list */
        for (i = 0;  i < iter->n_skip;  i++) {
            /* NB: all skip infos are now kept with names (perhaps, empty) */
            const char* name    = SERV_NameOfInfo(iter->skip[i]);
            size_t      namelen = name  &&  *name ? strlen(name) : 0;
            if (!(str = SERV_WriteInfo(iter->skip[i])))
                break;
            if (but_last  &&  iter->last == iter->skip[i]) {
                buflen = sizeof(kUsedServerInfo) - 1;
                memcpy(buffer, kUsedServerInfo, buflen);
            } else
                buflen = sprintf(buffer, kSkipInfo, (unsigned) i + 1); 
            assert(buflen < sizeof(buffer) - 1);
            if (!BUF_Write(&buf, buffer, buflen)                ||
                (namelen  &&  !BUF_Write(&buf, name, namelen))  ||
                (namelen  &&  !BUF_Write(&buf, " ", 1))         ||
                !BUF_Write(&buf, str, strlen(str))              ||
                !BUF_Write(&buf, "\r\n", 2)) {
                free(str);
                break;
            }
            free(str);
        }
        if (i < iter->n_skip) {
            BUF_Destroy(buf);
            return 0;
        }
    }
    /* Ok then, we have filled the entire header, <CR><LF> terminated */
    if ((buflen = BUF_Size(buf)) != 0) {
        if ((str = (char*) malloc(buflen + 1)) != 0) {
            if (BUF_Read(buf, str, buflen) != buflen) {
                free(str);
                str = 0;
            } else
                str[buflen] = '\0';
        }
    } else
        str = 0;
    BUF_Destroy(buf);
    return str;
}
Beispiel #4
0
static int run_a_test(size_t test_idx, int live, const char *svc,
                      const char *hdr, int check_for_match, int exp_err,
                      const char *mock_body_in, int repop, int reset)
{
    const SSERV_Info    *info = NULL;
    SConnNetInfo        *net_info;
    SERV_ITER           iter;
    const char          *mock_body = NULL;
    char                *mock_body_adj = NULL;
    int                 n_matches_perfect = 0, n_matches_near = 0;
    int                 success = 0, errors = 0;
    int                 retval = -1;

    s_n_hits_got = 0;

    /* Adjust mock data for current time, if necessary. */
    adjust_mock_times(mock_body_in, &mock_body_adj);
    mock_body = mock_body_adj ? mock_body_adj : mock_body_in;

    /* Select the HTTP data source (live or mock). */
    s_results[test_idx].live = live;
    if ( ! s_results[test_idx].live  &&
        ( ! mock_body  ||  ! *mock_body))
    {
        CORE_TRACE("Mock HTTP data source unavailable.");
        s_results[test_idx].live = 1;
    }
    if (s_results[test_idx].live) {
        CORE_TRACE("Using a live HTTP data source.");
        SERV_NAMERD_SetConnectorSource(NULL); /* use live HTTP */
    } else {
        CORE_TRACE("Using a mock HTTP data source.");
        if ( ! SERV_NAMERD_SetConnectorSource(mock_body)) {
            CORE_LOG(eLOG_Error, "Unable to create mock HTTP data source.");
            retval = 1;
            goto out;
        }
    }

    /* Set up the server iterator. */
    net_info = ConnNetInfo_Create(svc);
    if (*hdr)  ConnNetInfo_SetUserHeader(net_info, hdr);
    iter = SERV_OpenP(svc, fSERV_All |
                      (strpbrk(svc, "?*") ? fSERV_Promiscuous : 0),
                      SERV_LOCALHOST, 0/*port*/, 0.0/*preference*/,
                      net_info, 0/*skip*/, 0/*n_skip*/,
                      0/*external*/, 0/*arg*/, 0/*val*/);
    ConnNetInfo_Destroy(net_info);

    /* Fetch the server hits from namerd. */
    if (iter) {
        for (; s_n_hits_got < MAX_HITS  &&  (info = SERV_GetNextInfo(iter));
             ++s_n_hits_got)
        {
            if (info->type & fSERV_Http) {
                CORE_LOGF(eLOG_Note, ("    HTTP extra (path): %s",
                                      SERV_HTTP_PATH(&info->u.http)));
            }
            strcpy(s_hits_got[s_n_hits_got].type, SERV_TypeStr(info->type));
            strcpy(s_hits_got[s_n_hits_got].xtra,
                (info->type & fSERV_Http) ? SERV_HTTP_PATH(&info->u.http) : "");
            strcpy(s_hits_got[s_n_hits_got].loc ,
                (info->site & fSERV_Local   ) ? "yes" : "no");
            strcpy(s_hits_got[s_n_hits_got].priv,
                (info->site & fSERV_Private ) ? "yes" : "no");
            strcpy(s_hits_got[s_n_hits_got].stfl,
                (info->mode & fSERV_Stateful) ? "yes" : "no");

            SOCK_ntoa(info->host, s_hits_got[s_n_hits_got].host, LEN_HOST);

            s_hits_got[s_n_hits_got].port = info->port;

            s_hits_got[s_n_hits_got].match = 0;

            char    *info_str;
            info_str = SERV_WriteInfo(info);
            CORE_LOGF(eLOG_Note, ("    Found server %d:   %s",
                                  s_n_hits_got, info_str ? info_str : "?"));
            if (info_str)
                free(info_str);
        }

        /* Make sure endpoint data can be repopulated and reset. */
        if (repop  &&  s_n_hits_got) {
            /* repopulate */
            CORE_LOG(eLOG_Trace, "Repopulating the service mapper.");
            if ( ! info  &&  ! SERV_GetNextInfo(iter)) {
                CORE_LOG(eLOG_Error, "Unable to repopulate endpoint data.");
                errors = 1;
            }
        }
        if (reset  &&  s_n_hits_got) {
            /* reset */
            CORE_LOG(eLOG_Trace, "Resetting the service mapper.");
            SERV_Reset(iter);
            if ( ! SERV_GetNextInfo(iter)) {
                CORE_LOG(eLOG_Error, "No services found after reset.");
                errors = 1;
            }
        }

        SERV_Close(iter);
    } else {
        errors = 1;
    }

    /* Search for matches unless this is a standalone run. */
    if (check_for_match) {
        /* Search for perfect matches first (order is unknown). */
        int it_exp, it_got;
        for (it_got=0; it_got < s_n_hits_got; ++it_got) {
            for (it_exp=0; it_exp < s_n_hits_exp; ++it_exp) {
                if (s_hits_exp[it_exp].match) continue;

                /*if (check_match(fMatch_Default, it_exp, it_got)) {*/
                if (check_match(fMatch_All, it_exp, it_got)) {
                    CORE_LOGF(eLOG_Note, (
                        "    Found server %d perfectly matched expected server "
                        "%d.", it_got, it_exp));
                    s_hits_exp[it_exp].match = 1;
                    s_hits_got[it_got].match = 1;
                    ++n_matches_perfect;
                    break;
                }
            }
        }
        /* If not all found, search again but exclude host:port from match. */
        for (it_got=0; it_got < s_n_hits_got; ++it_got) {
            if (s_hits_got[it_got].match) continue;
            for (it_exp=0; it_exp < s_n_hits_exp; ++it_exp) {
                if (s_hits_exp[it_exp].match) continue;

                if (check_match(fMatch_NoHostPort, it_exp, it_got)) {
                    CORE_LOGF(eLOG_Note, (
                       "    Found server %d nearly matched expected server %d.",
                        it_got, it_exp));
                    s_hits_exp[it_exp].match = 1;
                    s_hits_got[it_got].match = 1;
                    ++n_matches_near;
                    log_match_diffs(it_exp, it_got);
                    break;
                }
            }
        }
        /* List any non-matching servers. */
        for (it_exp=0; it_exp < s_n_hits_exp; ++it_exp) {
            if ( ! s_hits_exp[it_exp].match)
                CORE_LOGF(eLOG_Note, (
                    "    Expected server %d didn't match any found servers.",
                    it_exp));
        }
        for (it_got=0; it_got < s_n_hits_got; ++it_got) {
            if ( ! s_hits_got[it_got].match)
                CORE_LOGF(eLOG_Note, (
                    "    Found server %d didn't match any expected servers.",
                    it_got));
        }

        CORE_LOGF(n_matches_perfect + n_matches_near == s_n_hits_got ?
                  eLOG_Note : eLOG_Error,
                  ("Expected %d servers; found %d (%d perfect matches, %d near "
                   "matches, and %d non-matches).",
                  s_n_hits_exp, s_n_hits_got, n_matches_perfect, n_matches_near,
                  s_n_hits_got - n_matches_perfect - n_matches_near));

        if (!errors  &&
            s_n_hits_got == s_n_hits_exp  &&
            s_n_hits_got == n_matches_perfect + n_matches_near)
        {
            success = 1;
        }
        retval = (success != exp_err ? 1 : 0);
        CORE_LOGF(eLOG_Note, ("Test result:  %s.",
            retval ?
            (success ? "PASS" : "PASS (with expected error)") :
            (success ? "FAIL (success when error expected)" : "FAIL")));
    }

out:
    if (mock_body_adj)
        free(mock_body_adj);
    return retval == -1 ? (success != exp_err ? 1 : 0) : retval;
}