⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hostip.c

📁 harvest是一个下载html网页得机器人
💻 C
📖 第 1 页 / 共 2 页
字号:
    }  }  conn->async.dns = dns;  /* The input hostent struct will be freed by ares when we return from this     function */}/* * Return name information about the given hostname and port number. If * successful, the 'hostent' is returned and the forth argument will point to * memory we need to free after use. That meory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,                                     char *hostname,                                     int port,                                     int *waitp){  int rc;  char *bufp;  struct SessionHandle *data = conn->data;  rc = ares_init(&data->state.areschannel);  *waitp = FALSE;    if(!rc) {    /* only if success */    bufp = strdup(hostname);    if(bufp) {      Curl_safefree(conn->async.hostname);      conn->async.hostname = bufp;      conn->async.port = port;      conn->async.done = FALSE; /* not done */      conn->async.status = 0;   /* clear */      conn->async.dns = NULL;   /* clear */            ares_gethostbyname(data->state.areschannel, hostname, PF_INET,                         host_callback, conn);            *waitp = TRUE; /* please wait for the response */    }    else      ares_destroy(data->state.areschannel);  }  return NULL; /* no struct yet */  }#else/* For builds without ARES, Curl_resolv() can never return wait==TRUE,   so this function will never be called. If it still gets called, we   return failure at once. */CURLcode Curl_wait_for_resolv(struct connectdata *conn,                              struct Curl_dns_entry **entry){  (void)conn;  *entry=NULL;  return CURLE_COULDNT_RESOLVE_HOST;}CURLcode Curl_multi_ares_fdset(struct connectdata *conn,                               fd_set *read_fd_set,                               fd_set *write_fd_set,                               int *max_fdp){  (void)conn;  (void)read_fd_set;  (void)write_fd_set;  (void)max_fdp;  return CURLE_OK;}CURLcode Curl_is_resolved(struct connectdata *conn,                          struct Curl_dns_entry **dns){  (void)conn;  *dns = NULL;  return CURLE_COULDNT_RESOLVE_HOST;}#endif#if defined(ENABLE_IPV6) && !defined(USE_ARES)#ifdef CURLDEBUG/* These two are strictly for memory tracing and are using the same * style as the family otherwise present in memdebug.c. I put these ones * here since they require a bunch of struct types I didn't wanna include * in memdebug.c */int curl_getaddrinfo(char *hostname, char *service,                     struct addrinfo *hints,                     struct addrinfo **result,                     int line, const char *source){  int res=(getaddrinfo)(hostname, service, hints, result);  if(0 == res) {    /* success */    if(logfile)      fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",              source, line, (void *)*result);  }  else {    if(logfile)      fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",              source, line);  }  return res;}void curl_freeaddrinfo(struct addrinfo *freethis,                       int line, const char *source){  (freeaddrinfo)(freethis);  if(logfile)    fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",            source, line, (void *)freethis);}#endif/* * Return name information about the given hostname and port number. If * successful, the 'addrinfo' is returned and the forth argument will point to * memory we need to free after use. That meory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,                                     char *hostname,                                     int port,                                     int *waitp){  struct addrinfo hints, *res;  int error;  char sbuf[NI_MAXSERV];  int s, pf;  struct SessionHandle *data = conn->data;  *waitp=0; /* don't wait, we have the response now */  /* see if we have an IPv6 stack */  s = socket(PF_INET6, SOCK_DGRAM, 0);  if (s < 0)    /* Some non-IPv6 stacks have been found to make very slow name resolves     * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if     * the stack seems to be a non-ipv6 one. */    pf = PF_INET;  else {    /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest     * possible checks. And close the socket again.     */    sclose(s);    /*     * Check if a more limited name resolve has been requested.     */    switch(data->set.ip_version) {    case CURL_IPRESOLVE_V4:      pf = PF_INET;      break;    case CURL_IPRESOLVE_V6:      pf = PF_INET6;      break;    default:      pf = PF_UNSPEC;      break;    }  }   memset(&hints, 0, sizeof(hints));  hints.ai_family = pf;  hints.ai_socktype = SOCK_STREAM;  hints.ai_flags = AI_CANONNAME;  snprintf(sbuf, sizeof(sbuf), "%d", port);  error = getaddrinfo(hostname, sbuf, &hints, &res);  if (error) {    infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);        return NULL;  }  return res;}#else /* following code is IPv4-only */#if !defined(HAVE_GETHOSTBYNAME_R) || defined(USE_ARES)static void hostcache_fixoffset(struct hostent *h, int offset);/* * Performs a "deep" copy of a hostent into a buffer (returns a pointer to the * copy). Make absolutely sure the destination buffer is big enough! */static struct hostent* pack_hostent(char** buf, struct hostent* orig){  char *bufptr;  char *newbuf;  struct hostent* copy;  int i;  char *str;  int len;  bufptr = *buf;  copy = (struct hostent*)bufptr;  bufptr += sizeof(struct hostent);  copy->h_name = bufptr;  len = strlen(orig->h_name) + 1;  strncpy(bufptr, orig->h_name, len);  bufptr += len;  /* we align on even 64bit boundaries for safety */#define MEMALIGN(x) ((x)+(8-(((unsigned long)(x))&0x7)))  /* This must be aligned properly to work on many CPU architectures! */  bufptr = MEMALIGN(bufptr);    copy->h_aliases = (char**)bufptr;  /* Figure out how many aliases there are */  for (i = 0; orig->h_aliases && orig->h_aliases[i]; ++i);  /* Reserve room for the array */  bufptr += (i + 1) * sizeof(char*);  /* Clone all known aliases */  if(orig->h_aliases) {    for(i = 0; (str = orig->h_aliases[i]); i++) {      len = strlen(str) + 1;      strncpy(bufptr, str, len);      copy->h_aliases[i] = bufptr;      bufptr += len;    }  }  /* if(!orig->h_aliases) i was already set to 0 */  /* Terminate the alias list with a NULL */  copy->h_aliases[i] = NULL;  copy->h_addrtype = orig->h_addrtype;  copy->h_length = orig->h_length;      /* align it for (at least) 32bit accesses */  bufptr = MEMALIGN(bufptr);  copy->h_addr_list = (char**)bufptr;  /* Figure out how many addresses there are */  for (i = 0; orig->h_addr_list[i] != NULL; ++i);  /* Reserve room for the array */  bufptr += (i + 1) * sizeof(char*);  i = 0;  len = orig->h_length;  str = orig->h_addr_list[i];  while (str != NULL) {    memcpy(bufptr, str, len);    copy->h_addr_list[i] = bufptr;    bufptr += len;    str = orig->h_addr_list[++i];  }  copy->h_addr_list[i] = NULL;  /* now, shrink the allocated buffer to the size we actually need, which     most often is only a fraction of the original alloc */  newbuf=(char *)realloc(*buf, (int)bufptr-(int)(*buf));  /* if the alloc moved, we need to adjust things again */  if(newbuf != *buf)    hostcache_fixoffset((struct hostent*)newbuf, (int)newbuf-(int)*buf);  /* setup the return */  *buf = newbuf;  copy = (struct hostent*)newbuf;  return copy;}#endifstatic void hostcache_fixoffset(struct hostent *h, int offset){  int i=0;  h->h_name=(char *)((long)h->h_name+offset);  if(h->h_aliases) {    /* only relocate aliases if there are any! */    h->h_aliases=(char **)((long)h->h_aliases+offset);    while(h->h_aliases[i]) {      h->h_aliases[i]=(char *)((long)h->h_aliases[i]+offset);      i++;    }  }  h->h_addr_list=(char **)((long)h->h_addr_list+offset);  i=0;  while(h->h_addr_list[i]) {    h->h_addr_list[i]=(char *)((long)h->h_addr_list[i]+offset);    i++;  }}#ifndef USE_ARESstatic char *MakeIP(unsigned long num, char *addr, int addr_len){#if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R)  struct in_addr in;  in.s_addr = htonl(num);#if defined(HAVE_INET_NTOA_R)  inet_ntoa_r(in,addr,addr_len);#else  strncpy(addr,inet_ntoa(in),addr_len);#endif#else  unsigned char *paddr;  num = htonl(num);  /* htonl() added to avoid endian probs */  paddr = (unsigned char *)&num;  sprintf(addr, "%u.%u.%u.%u", paddr[0], paddr[1], paddr[2], paddr[3]);#endif  return (addr);}/* The original code to this function was once stolen from the Dancer source   code, written by Bjorn Reese, it has since been patched and modified   considerably. */static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn,                                     char *hostname,                                     int port,                                     int *waitp){  struct hostent *h = NULL;  in_addr_t in;  int ret; /* this variable is unused on several platforms but used on some */  struct SessionHandle *data = conn->data;  (void)port; /* unused in IPv4 code */  ret = 0; /* to prevent the compiler warning */  *waitp = 0; /* don't wait, we act synchronously */  in=inet_addr(hostname);  if (in != CURL_INADDR_NONE) {    struct in_addr *addrentry;    struct namebuf {        struct hostent hostentry;        char *h_addr_list[2];        struct in_addr addrentry;        char h_name[128];    } *buf = (struct namebuf *)malloc(sizeof(struct namebuf));    if(!buf)      return NULL; /* major failure */    h = &buf->hostentry;    h->h_addr_list = &buf->h_addr_list[0];    addrentry = &buf->addrentry;    addrentry->s_addr = in;    h->h_addr_list[0] = (char*)addrentry;    h->h_addr_list[1] = NULL;    h->h_addrtype = AF_INET;    h->h_length = sizeof(*addrentry);    h->h_name = &buf->h_name[0];    MakeIP(ntohl(in), (char *)h->h_name, sizeof(buf->h_name));  }#if defined(HAVE_GETHOSTBYNAME_R)  else {    int h_errnop;    int res=ERANGE;    int step_size=200;    int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE);    if(!buf)      return NULL; /* major failure */     /* Workaround for gethostbyname_r bug in qnx nto. It is also _required_        for some of these functions. */    memset(buf, 0, CURL_NAMELOOKUP_SIZE);#ifdef HAVE_GETHOSTBYNAME_R_5    /* Solaris, IRIX and more */    (void)res; /* prevent compiler warning */    while(!h) {      h = gethostbyname_r(hostname,                          (struct hostent *)buf,                          (char *)buf + sizeof(struct hostent),                          step_size - sizeof(struct hostent),                          &h_errnop);      /* If the buffer is too small, it returns NULL and sets errno to         ERANGE. The errno is thread safe if this is compiled with         -D_REENTRANT as then the 'errno' variable is a macro defined to         get used properly for threads. */      if(h || (errno != ERANGE))        break;            step_size+=200;    }#ifdef CURLDEBUG    infof(data, "gethostbyname_r() uses %d bytes\n", step_size);#endif    if(h) {      int offset;      h=(struct hostent *)realloc(buf, step_size);      offset=(long)h-(long)buf;      hostcache_fixoffset(h, offset);      buf=(int *)h;    }    else#endif /* HAVE_GETHOSTBYNAME_R_5 */#ifdef HAVE_GETHOSTBYNAME_R_6    /* Linux */    do {      res=gethostbyname_r(hostname,			  (struct hostent *)buf,			  (char *)buf + sizeof(struct hostent),			  step_size - sizeof(struct hostent),			  &h, /* DIFFERENCE */			  &h_errnop);      /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a         sudden this function returns EAGAIN if the given buffer size is too         small. Previous versions are known to return ERANGE for the same         problem.         This wouldn't be such a big problem if older versions wouldn't         sometimes return EAGAIN on a common failure case. Alas, we can't         assume that EAGAIN *or* ERANGE means ERANGE for any given version of         glibc.         For now, we do that and thus we may call the function repeatedly and         fail for older glibc versions that return EAGAIN, until we run out         of buffer size (step_size grows beyond CURL_NAMELOOKUP_SIZE).         If anyone has a better fix, please tell us!         -------------------------------------------------------------------         On October 23rd 2003, Dan C dug up more details on the mysteries of         gethostbyname_r() in glibc:         In glibc 2.2.5 the interface is different (this has also been         discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't         explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32         (shipped/upgraded by Redhat 7.2) don't show this behavior!         In this "buggy" version, the return code is -1 on error and 'errno'         is set to the ERANGE or EAGAIN code. Note that 'errno' is not a         thread-safe variable.      */      if(((ERANGE == res) || (EAGAIN == res)) ||         ((res<0) && ((ERANGE == errno) || (EAGAIN == errno))))	step_size+=200;      else        break;    } while(step_size <= CURL_NAMELOOKUP_SIZE);    if(!h) /* failure */      res=1;    #ifdef CURLDEBUG    infof(data, "gethostbyname_r() uses %d bytes\n", step_size);#endif    if(!res) {      int offset;      h=(struct hostent *)realloc(buf, step_size);      offset=(long)h-(long)buf;      hostcache_fixoffset(h, offset);      buf=(int *)h;    }    else#endif/* HAVE_GETHOSTBYNAME_R_6 */#ifdef HAVE_GETHOSTBYNAME_R_3    /* AIX, Digital Unix, HPUX 10, more? */    /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of       the plain fact that it does not return unique full buffers on each       call, but instead several of the pointers in the hostent structs will       point to the same actual data! This have the unfortunate down-side that       our caching system breaks down horribly. Luckily for us though, AIX 4.3       and more recent versions have a completely thread-safe libc where all       the data is stored in thread-specific memory areas making calls to the       plain old gethostbyname() work fine even for multi-threaded programs.              This AIX 4.3 or later detection is all made in the configure script.       Troels Walsted Hansen helped us work this out on March 3rd, 2003. */    if(CURL_NAMELOOKUP_SIZE >=       (sizeof(struct hostent)+sizeof(struct hostent_data)))      /* August 22nd, 2000: Albert Chin-A-Young brought an updated version       * that should work! September 20: Richard Prescott worked on the buffer       * size dilemma. */      ret = gethostbyname_r(hostname,                            (struct hostent *)buf,                            (struct hostent_data *)((char *)buf +                                                    sizeof(struct hostent)));    else      ret = -1; /* failure, too smallish buffer size */        /* result expected in h */    h = (struct hostent*)buf;    h_errnop= errno; /* we don't deal with this, but set it anyway */    if(ret)#endif /* HAVE_GETHOSTBYNAME_R_3 */      {      infof(data, "gethostbyname_r(2) failed for %s\n", hostname);      h = NULL; /* set return code to NULL */      free(buf);    }#else /* HAVE_GETHOSTBYNAME_R */  else {    if ((h = gethostbyname(hostname)) == NULL ) {      infof(data, "gethostbyname(2) failed for %s\n", hostname);    }    else     {      char *buf=(char *)malloc(CURL_NAMELOOKUP_SIZE);      /* we make a copy of the hostent right now, right here, as the         static one we got a pointer to might get removed when we don't         want/expect that */      h = pack_hostent(&buf, h);    }#endif /*HAVE_GETHOSTBYNAME_R */  }  return (h);}#endif /* end of IPv4-specific code */#endif /* end of !USE_ARES */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -