예제 #1
0
static struct mi_root *mi_cachestore(struct mi_root *cmd, void *param)
{
	str mc_system;
	str attr;
	str value;
	unsigned int expires = 0;
	struct mi_node* node= NULL;
	str expires_str;

	if(cmd == NULL)
	{
		LM_ERR("NULL command\n");
		return init_mi_tree(404, "NULL command", 12);
	}

	node = cmd->node.kids;
	if(node == NULL)
		return init_mi_tree(404, "Too few arguments", 17);

	mc_system = node->value;
	if(mc_system.s == NULL || mc_system.len== 0)
	{
		LM_ERR( "empty memory cache system parameter\n");
		return init_mi_tree(404, "Empty memory cache id", 21);
	}
	
	node = node->next;
	if(node == NULL)
		return init_mi_tree(404, "Too few arguments", 17);

	attr = node->value;
	if(attr.s == NULL || attr.len== 0)
	{
		LM_ERR( "empty attribute name parameter\n");
		return init_mi_tree(404, "Empty attribute name", 20);
	}
	
	node = node->next;
	if(node == NULL)
		return init_mi_tree(404, "Too few arguments", 17);

	value = node->value;
	if(value.s == NULL || value.len== 0)
	{
		LM_ERR( "empty value parameter\n");
		return init_mi_tree(404, "Empty value argument", 20);
	}

	/* expires parameter is not compulsory */
	node = node->next;
	if(node!= NULL)
	{
		expires_str = node->value;
		if(expires_str.s == NULL || expires_str.len == 0)
		{
			LM_ERR( "empty expires parameter\n");
			return init_mi_tree(404, "Empty expires argument", 22);
		}
		if(str2int(&expires_str, &expires)< 0)
		{
			LM_ERR("wrong format for expires argument- needed int\n");
			return init_mi_tree(404, "Bad format for expires argument", 31);
		}
	
		node = node->next;
		if(node!= NULL)
			return init_mi_tree(404, "Too many parameters", 19);
	}

	if(cache_store(&mc_system, &attr, &value, expires)< 0)
	{
		LM_ERR("cache_store command failed\n");
		return init_mi_tree(500, "Cache store command failed", 26);
	}
	
	return init_mi_tree(200, "OK", 2);
}
예제 #2
0
파일: host.c 프로젝트: mirror/wget
struct address_list *
lookup_host (const char *host, int flags)
{
  struct address_list *al;
  bool silent = !!(flags & LH_SILENT);
  bool use_cache;
  bool numeric_address = false;
  double timeout = opt.dns_timeout;

#ifndef ENABLE_IPV6
  /* If we're not using getaddrinfo, first check if HOST specifies a
     numeric IPv4 address.  Some implementations of gethostbyname
     (e.g. the Ultrix one and possibly Winsock) don't accept
     dotted-decimal IPv4 addresses.  */
  {
    uint32_t addr_ipv4 = (uint32_t)inet_addr (host);
    if (addr_ipv4 != (uint32_t) -1)
      {
        /* No need to cache host->addr relation, just return the
           address.  */
        char *vec[2];
        vec[0] = (char *)&addr_ipv4;
        vec[1] = NULL;
        return address_list_from_ipv4_addresses (vec);
      }
  }
#else  /* ENABLE_IPV6 */
  /* If we're using getaddrinfo, at least check whether the address is
     already numeric, in which case there is no need to print the
     "Resolving..." output.  (This comes at no additional cost since
     the is_valid_ipv*_address are already required for
     url_parse.)  */
  {
    const char *end = host + strlen (host);
    if (is_valid_ipv4_address (host, end) || is_valid_ipv6_address (host, end))
      numeric_address = true;
  }
#endif

  /* Cache is normally on, but can be turned off with --no-dns-cache.
     Don't cache passive lookups under IPv6.  */
  use_cache = opt.dns_cache;
#ifdef ENABLE_IPV6
  if ((flags & LH_BIND) || numeric_address)
    use_cache = false;
#endif

  /* Try to find the host in the cache so we don't need to talk to the
     resolver.  If LH_REFRESH is requested, remove HOST from the cache
     instead.  */
  if (use_cache)
    {
      if (!(flags & LH_REFRESH))
        {
          al = cache_query (host);
          if (al)
            return al;
        }
      else
        cache_remove (host);
    }

  /* No luck with the cache; resolve HOST. */

  if (!silent && !numeric_address)
    {
      char *str = NULL, *name;

      if (opt.enable_iri && (name = idn_decode ((char *) host)) != NULL)
        {
          str = aprintf ("%s (%s)", name, host);
          xfree (name);
        }

      logprintf (LOG_VERBOSE, _("Resolving %s... "),
                 quotearg_style (escape_quoting_style, str ? str : host));

      xfree (str);
    }

#ifdef ENABLE_IPV6
#ifdef HAVE_LIBCARES
  if (ares)
    {
      struct address_list *al4;
      struct address_list *al6;

      if (opt.ipv4_only || !opt.ipv6_only)
        ares_gethostbyname (ares, host, AF_INET, callback, &al4);
      if (opt.ipv6_only || !opt.ipv4_only)
        ares_gethostbyname (ares, host, AF_INET6, callback, &al6);

      wait_ares (ares);

      if (al4 && al6)
        al = merge_address_lists (al4, al6);
      else if (al4)
        al = al4;
      else
        al = al6;
    }
  else
#endif
    {
      int err;
      struct addrinfo hints, *res;

      xzero (hints);
      hints.ai_socktype = SOCK_STREAM;
      if (opt.ipv4_only)
        hints.ai_family = AF_INET;
      else if (opt.ipv6_only)
        hints.ai_family = AF_INET6;
      else
        /* We tried using AI_ADDRCONFIG, but removed it because: it
           misinterprets IPv6 loopbacks, it is broken on AIX 5.1, and
           it's unneeded since we sort the addresses anyway.  */
        hints.ai_family = AF_UNSPEC;

      if (flags & LH_BIND)
        hints.ai_flags |= AI_PASSIVE;

#ifdef AI_NUMERICHOST
      if (numeric_address)
        {
          /* Where available, the AI_NUMERICHOST hint can prevent costly
             access to DNS servers.  */
          hints.ai_flags |= AI_NUMERICHOST;
          timeout = 0; /* no timeout needed when "resolving"
                                   numeric hosts -- avoid setting up
                                   signal handlers and such. */
        }
#endif

      err = getaddrinfo_with_timeout (host, NULL, &hints, &res, timeout);

      if (err != 0 || res == NULL)
        {
          if (!silent)
            logprintf (LOG_VERBOSE, _ ("failed: %s.\n"),
                       err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno));
          return NULL;
        }
      al = address_list_from_addrinfo (res);
      freeaddrinfo (res);
    }

  if (!al)
    {
      logprintf (LOG_VERBOSE,
                 _ ("failed: No IPv4/IPv6 addresses for host.\n"));
      return NULL;
    }

  /* Reorder addresses so that IPv4 ones (or IPv6 ones, as per
     --prefer-family) come first.  Sorting is stable so the order of
     the addresses with the same family is undisturbed.  */
  if (al->count > 1 && opt.prefer_family != prefer_none)
    stable_sort (al->addresses, al->count, sizeof (ip_address),
                 opt.prefer_family == prefer_ipv4
                 ? cmp_prefer_ipv4 : cmp_prefer_ipv6);
#else  /* not ENABLE_IPV6 */
#ifdef HAVE_LIBCARES
  if (ares)
    {
      ares_gethostbyname (ares, host, AF_INET, callback, &al);
      wait_ares (ares);
    }
  else
#endif
    {
      struct hostent *hptr = gethostbyname_with_timeout (host, timeout);
      if (!hptr)
        {
          if (!silent)
            {
              if (errno != ETIMEDOUT)
                logprintf (LOG_VERBOSE, _ ("failed: %s.\n"),
                           host_errstr (h_errno));
              else
                logputs (LOG_VERBOSE, _ ("failed: timed out.\n"));
            }
          return NULL;
        }
      /* Do older systems have h_addr_list?  */
      al = address_list_from_ipv4_addresses (hptr->h_addr_list);
    }
#endif /* not ENABLE_IPV6 */

  /* Print the addresses determined by DNS lookup, but no more than
     three if show_all_dns_entries is not specified.  */
  if (!silent && !numeric_address)
    {
      int i;
      int printmax = al->count;

      if (!opt.show_all_dns_entries && printmax > 3)
          printmax = 3;

      for (i = 0; i < printmax; i++)
        {
          logputs (LOG_VERBOSE, print_address (al->addresses + i));
          if (i < printmax - 1)
            logputs (LOG_VERBOSE, ", ");
        }
      if (printmax != al->count)
        logputs (LOG_VERBOSE, ", ...");
      logputs (LOG_VERBOSE, "\n");
    }

  /* Cache the lookup information. */
  if (use_cache)
    cache_store (host, al);

  return al;
}
예제 #3
0
파일: network.c 프로젝트: thesjg/ecached
void
network_main(ecached_settings_t settings)
{
    struct sockaddr_in sa_local;
    int fd_listen, maxfiles, i;
    uint32_t bufsize;
    socklen_t optval, optlen = sizeof(socklen_t);

    if ((fd_listen = socket(PF_INET, SOCK_STREAM, 0)) == -1)
        ecached_err(EX_OSERR, "socket(2) failure");

    optval = 1;
    if (setsockopt(fd_listen, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, optlen) == -1)
        ecached_err(EX_OSERR, "setsockopt(2) failure");

    /* Make socket non-blocking */
    if ((i = fcntl(fd_listen, F_GETFL)) == -1)
        i = 0;
    if (fcntl(fd_listen, F_SETFL, i | O_NONBLOCK) == -1)
        ecached_err(EX_OSERR, "fcntl(2) failure");

    /* */
    sa_local.sin_family = AF_INET;
    sa_local.sin_port = htons(settings->port);
    sa_local.sin_addr.s_addr = htonl(INADDR_ANY); /* XXX: Addr via getopt() */
    memset(&(sa_local.sin_zero), 0, sizeof(sa_local.sin_zero));

    if (bind(fd_listen, (struct sockaddr *)&sa_local, sizeof(struct sockaddr)) == -1)
        ecached_err(EX_OSERR, "bind(2) failure");

    /* Attempt to ensure listen backlog is at least 128 long */
    if ((i = listen(fd_listen, -1)) < 128)
        i = 128;

    if (listen(fd_listen, i) == -1)
        ecached_err(EX_OSERR, "listen(2) failure");

    (void)set_sockbuf_sendsize(fd_listen, MEMORY_ZONE_MAX);

    /*
     * TODO: Make this a #define
     */
    bufsize = set_sockbuf_recvsize(fd_listen, (MEMORY_ZONE_MAX >> 2));

    maxfiles = get_maxfiles(); /* XXX: From getopt() */

    /**
     *
     * Begin main loop
     *
     */
    do {
        struct kevent changes[maxfiles], events[maxfiles];
        struct network_connection connections[maxfiles];
        struct sockaddr_in sa_remote;
        socklen_t remote_size = sizeof(sa_remote);
        int kq, nchanges, nevents;

        if ((kq = kqueue()) == -1)
            ecached_err(EX_OSERR, "kqueue(2) failure");

        memset(&changes, 0, sizeof(changes));
        memset(&events, 0, sizeof(events));
        memset(&connections, 0, sizeof(connections));

        EV_SET(&changes[0], fd_listen, EVFILT_READ, EV_ADD, 0, 0, 0);
        nchanges = 1;

        while (true) {

            nevents = kevent(kq, (struct kevent *)&changes, nchanges,
                             (struct kevent *)&events, maxfiles, NULL);
            nchanges = 0;

            for (i = 0; i < nevents; ++i) {
                int fd = events[i].ident;

                /* New connection */
                if (fd == fd_listen) {
                    int fd_new = accept(fd_listen, (struct sockaddr *)&sa_remote, &remote_size);
                    if (fd_new == -1) {
                        /* XXX: Could not accept */
                    } else {
                        connections[fd_new].state = CONNECTION_ACCEPTED;
                        connections[fd_new].buffer = NULL;

                        EV_SET(&changes[nchanges], fd_new, EVFILT_READ, EV_ADD, 0, 0, 0);
                        ++nchanges;
                    }

                /* Existing connection */
                } else {
printf("New event, existing connection\n");
                    if (events[i].filter == EVFILT_READ) {
                        network_buffer_t buf;
                        network_connection_t conn = &connections[fd];

                        if (conn->buffer == NULL) {
                            /* Assume malloc(3) will be caching bufsize sized objects */
                            if ((conn->buffer = network_buffer_allocate(bufsize)) == NULL)
                            {
                                (void)close(fd);
                                continue;
                            }

memset(conn->buffer+10, '\0', bufsize);

                            conn->state = CONNECTION_PARSING_COMMAND;
                            buf = conn->buffer;

                            command_init(conn);
                        } else {
                            buf = conn->buffer;
                        }

                        /* XXX: will go to 0 */
                        ssize_t rb = recv(fd, &buf->buffer[buf->used],
                                          buf->size - buf->used, 0);
                        if (rb == 0) {
                            if (conn->buffer != NULL) {
                                (void)free(conn->buffer);
                                conn->buffer = NULL;
                            }
                            (void)close(fd);

                            /*
                             * kevent(2) does this for us on close(2)
                             *
                             * EV_SET(&changes[nchanges], events[i].ident, 0, EV_DELETE, 0, 0, 0);
                             * ++nchanges;
                             */
                        } else {
                            buf->used += rb;
                            if (connections[fd].state == CONNECTION_PARSING_COMMAND) {
                                if (command_parse(conn) == true)
                                    connections[fd].state = CONNECTION_PARSED_COMMAND;
                            }

                            if (connections[fd].state == CONNECTION_PARSED_COMMAND) {
                                cache_object_t co;

                                switch (conn->action.command_type) {
                                case COMMAND_TYPE_STORE:
printf("DOING CACHE_STORE()\n");
                                    if (cache_store(&conn->action, buf) == true) {
                                    }
                                    break;
                                case COMMAND_TYPE_RETRIEVE:
printf("DOING CACHE_RETRIEVE()\n");
                                    if ((co = cache_retrieve(&conn->action)) != NULL) {
                                        printf("Retrieved item from cache!\n");
                                        printf("LEN IS: %d\n", co->size);
                                    }
                                    break;
                                case COMMAND_TYPE_EXPIRE:
                                    break;
                                case COMMAND_TYPE_MODIFY:
                                    break;
                                }
                            }

                            print_buffer(buf);
                        }

                    /* EVFILT_WRITE */
                    } else {
                    }
                }

            }
        }
    } while (false);
}