Flowdock
getnameinfo(p1, p2 = v2) public

No documentation

This method has no description. You can help the Ruby community by adding new notes.

Hide source
static VALUE
sock_s_getnameinfo(int argc, VALUE *argv)
{
    VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
    char *hptr, *pptr;
    char hbuf[1024], pbuf[1024];
    int fl;
    struct addrinfo hints, *res = NULL, *r;
    int error;
    struct sockaddr_storage ss;
    struct sockaddr *sap;
    char *ap;

    sa = flags = Qnil;
    rb_scan_args(argc, argv, "11", &sa, &flags);

    fl = 0;
    if (!NIL_P(flags)) {
        fl = NUM2INT(flags);
    }
    tmp = rb_check_string_type(sa);
    if (!NIL_P(tmp)) {
        sa = tmp;
        if (sizeof(ss) < RSTRING_LEN(sa)) {
            rb_raise(rb_eTypeError, "sockaddr length too big");
        }
        memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
        if (RSTRING_LEN(sa) != SA_LEN((struct sockaddr*)&ss)) {
            rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
        }
        sap = (struct sockaddr*)&ss;
        goto call_nameinfo;
    }
    tmp = rb_check_array_type(sa);
    if (!NIL_P(tmp)) {
        sa = tmp;
        MEMZERO(&hints, struct addrinfo, 1);
        if (RARRAY_LEN(sa) == 3) {
            af = RARRAY_PTR(sa)[0];
            port = RARRAY_PTR(sa)[1];
            host = RARRAY_PTR(sa)[2];
        }
        else if (RARRAY_LEN(sa) >= 4) {
            af = RARRAY_PTR(sa)[0];
            port = RARRAY_PTR(sa)[1];
            host = RARRAY_PTR(sa)[3];
            if (NIL_P(host)) {
                host = RARRAY_PTR(sa)[2];
            }
            else {
                /*
                 * 4th element holds numeric form, don't resolve.
                 * see ipaddr().
                 */
#ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
                hints.ai_flags |= AI_NUMERICHOST;
#endif
            }
        }
        else {
            rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
                     RARRAY_LEN(sa));
        }
        /* host */
        if (NIL_P(host)) {
            hptr = NULL;
        }
        else {
            strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
            hbuf[sizeof(hbuf) - 1] = '\0';
            hptr = hbuf;
        }
        /* port */
        if (NIL_P(port)) {
            strcpy(pbuf, "0");
            pptr = NULL;
        }
        else if (FIXNUM_P(port)) {
            snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
            pptr = pbuf;
        }
        else {
            strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
            pbuf[sizeof(pbuf) - 1] = '\0';
            pptr = pbuf;
        }
        hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
        /* af */
        if (NIL_P(af)) {
            hints.ai_family = PF_UNSPEC;
        }
        else if (FIXNUM_P(af)) {
            hints.ai_family = FIX2INT(af);
        }
        else if ((ap = StringValuePtr(af)) != 0) {
            if (strcmp(ap, "AF_INET") == 0) {
                hints.ai_family = PF_INET;
            }
#ifdef INET6
            else if (strcmp(ap, "AF_INET6") == 0) {
                hints.ai_family = PF_INET6;
            }
#endif
        }
        error = getaddrinfo(hptr, pptr, &hints, &res);
        if (error) goto error_exit_addr;
        sap = res->ai_addr;
    }
    else {
        rb_raise(rb_eTypeError, "expecting String or Array");
    }

  call_nameinfo:
    error = getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
                        pbuf, sizeof(pbuf), fl);
    if (error) goto error_exit_name;
    if (res) {
        for (r = res->ai_next; r; r = r->ai_next) {
            char hbuf2[1024], pbuf2[1024];

            sap = r->ai_addr;
            error = getnameinfo(sap, SA_LEN(sap), hbuf2, sizeof(hbuf2),
                                pbuf2, sizeof(pbuf2), fl);
            if (error) goto error_exit_name;
            if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
                freeaddrinfo(res);
                rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
            }
        }
        freeaddrinfo(res);
    }
    return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));

  error_exit_addr:
    if (res) freeaddrinfo(res);
    raise_socket_error("getaddrinfo", error);

  error_exit_name:
    if (res) freeaddrinfo(res);
    raise_socket_error("getnameinfo", error);
}
Register or log in to add new notes.