示例#1
0
文件: httpd.c 项目: sue602/libsthttp
int main(int argc, char *argv[]) {
  st_init();

  int sock;
  int n;
  struct sockaddr_in serv_addr;

  if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    perror("socket");
  }

  n = 1;
  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof(n)) < 0) {
    perror("setsockopt SO_REUSEADDR");
  }

  memset(&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_port = htons(8080);
  serv_addr.sin_addr.s_addr = inet_addr("0.0.0.0");

  if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
    perror("bind");
  }

  if (listen(sock, 10) < 0) {
    perror("listen");
  }

  st_netfd_t server_nfd = st_netfd_open_socket(sock);
  st_netfd_t client_nfd;
  struct sockaddr_in from;
  int fromlen = sizeof(from);

  for (;;) {
    client_nfd = st_accept(server_nfd,
      (struct sockaddr *)&from, &fromlen, ST_UTIME_NO_TIMEOUT);
    printf("accepted\n");
    if (st_thread_create(handle_connection,
      (void *)client_nfd, 0, 1024 * 1024) == NULL)
    {
      fprintf(stderr, "st_thread_create error\n");
    }
  }

  return EXIT_SUCCESS;
}
示例#2
0
文件: io.c 项目: dashaomai/CStudy
void create_listener_and_accept(void) {
  st_set_eventsys(ST_EVENTSYS_ALT);
  st_init();

  int listener_fd;
  struct addrinfo hints, *ai, *p;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = PF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  getaddrinfo("0.0.0.0", "9595", &hints, &ai);

  for (p = ai; p != NULL; p = p->ai_next) {
    listener_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
    if (listener_fd < 0) continue;

    if (bind(listener_fd, p->ai_addr, p->ai_addrlen) < 0) {
      close(listener_fd);
      continue;
    }

    break;
  }

  if (p == NULL) return;

  listen(listener_fd, 10);

  context = (struct peer_context*)calloc(5, sizeof(struct peer_context));

  context[0].rpc_fd = st_netfd_open_socket(listener_fd);

  st_netfd_t client;

  struct sockaddr from;
  int len = sizeof(from);

  while ((client = st_accept(context[0].rpc_fd, &from, &len, ST_UTIME_NO_TIMEOUT)) != NULL) {
    st_thread_create(handle_conn, client, 0, 0);
  }
}
示例#3
0
hoxResult
hoxSocketAPI::tcp_connect( const std::string&       sHost,
                           const unsigned short int nPort,
                           st_netfd_t&              nfd )
{
    int                 iResult = 0;
    struct sockaddr_in  serverAddress;
    struct hostent*     hostInfo;
    int                 sock = -1;

    nfd = NULL;   // Default: invalid socket

    // gethostbyname() takes a host name or ip address in "numbers and
    // dots" notation, and returns a pointer to a hostent structure,
    // which we'll need later.  It's not important for us what this
    // structure is actually composed of.
    hostInfo = gethostbyname( sHost.c_str() );
    if (hostInfo == NULL)
    {
        hoxLog(LOG_SYS_WARN, "%s: problem interpreting host: %s", __FUNCTION__, sHost.c_str());
        return hoxRC_ERR;
    }

    // Create a socket.  "AF_INET" means it will use the IPv4 protocol.
    // "SOCK_STREAM" means it will be a reliable connection (i.e., TCP;
    // for UDP use SOCK_DGRAM), and I'm not sure what the 0 for the last
    // parameter means, but it seems to work.
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        hoxLog(LOG_SYS_WARN, "%s: cannot create socket", __FUNCTION__);
        return hoxRC_ERR;
    }

    if ((nfd = st_netfd_open_socket(sock)) == NULL) {
        hoxLog(LOG_SYS_WARN, "%s: st_netfd_open_socket failed", __FUNCTION__);
        close(sock);
        return hoxRC_ERR;
    }

    // Connect to server.  First we have to set some fields in the
    // serverAddress structure.  The system will assign me an arbitrary
    // local port that is not in use.
    serverAddress.sin_family = hostInfo->h_addrtype;
    memcpy((char *) &serverAddress.sin_addr.s_addr,
            hostInfo->h_addr_list[0], hostInfo->h_length);
    serverAddress.sin_port = htons( nPort);

    iResult = st_connect( nfd,
                          (struct sockaddr *) &serverAddress,
                           sizeof(serverAddress),
                           ST_UTIME_NO_TIMEOUT );
    if ( iResult < 0 )
    {
        hoxLog(LOG_SYS_WARN, "%s: cannot connect", __FUNCTION__);
        st_netfd_close( nfd );
        return hoxRC_ERR;
    }

    return hoxRC_OK;
}
示例#4
0
/*
 * This program acts as a generic gateway. It listens for connections
 * to a local address ('-l' option). Upon accepting a client connection,
 * it connects to the specified remote address ('-r' option) and then
 * just pumps the data through without any modification.
 */
int main(int argc, char *argv[])
{
  extern char *optarg;
  int opt, sock, n;
  int laddr, raddr, num_procs;
  int serialize_accept = 0;
  struct sockaddr_in lcl_addr, cli_addr;
  st_netfd_t cli_nfd, srv_nfd;

  prog = argv[0];
  num_procs = laddr = raddr = 0;

  /* Parse arguments */
  while((opt = getopt(argc, argv, "l:r:p:Sh")) != EOF) {
    switch (opt) {
    case 'l':
      read_address(optarg, &lcl_addr);
      laddr = 1;
      break;
    case 'r':
      read_address(optarg, &rmt_addr);
      if (rmt_addr.sin_addr.s_addr == INADDR_ANY) {
	fprintf(stderr, "%s: invalid remote address: %s\n", prog, optarg);
	exit(1);
      }
      raddr = 1;
      break;
    case 'p':
      num_procs = atoi(optarg);
      if (num_procs < 1) {
	fprintf(stderr, "%s: invalid number of processes: %s\n", prog, optarg);
	exit(1);
      }
      break;
    case 'S':
      /*
       * Serialization decision is tricky on some platforms. For example,
       * Solaris 2.6 and above has kernel sockets implementation, so supposedly
       * there is no need for serialization. The ST library may be compiled
       * on one OS version, but used on another, so the need for serialization
       * should be determined at run time by the application. Since it's just
       * an example, the serialization decision is left up to user.
       * Only on platforms where the serialization is never needed on any OS
       * version st_netfd_serialize_accept() is a no-op.
       */
      serialize_accept = 1;
      break;
    case 'h':
    case '?':
      fprintf(stderr, "Usage: %s -l <[host]:port> -r <host:port> "
	      "[-p <num_processes>] [-S]\n", prog);
      exit(1);
    }
  }
  if (!laddr) {
    fprintf(stderr, "%s: local address required\n", prog);
    exit(1);
  }
  if (!raddr) {
    fprintf(stderr, "%s: remote address required\n", prog);
    exit(1);
  }
  if (num_procs == 0)
    num_procs = cpu_count();

  fprintf(stderr, "%s: starting proxy daemon on %s:%d\n", prog,
	  inet_ntoa(lcl_addr.sin_addr), ntohs(lcl_addr.sin_port));

  /* Start the daemon */
  start_daemon();

  /* Initialize the ST library */
  if (st_init() < 0) {
    print_sys_error("st_init");
    exit(1);
  }

  /* Create and bind listening socket */
  if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    print_sys_error("socket");
    exit(1);
  }
  n = 1;
  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof(n)) < 0) {
    print_sys_error("setsockopt");
    exit(1);
  }
  if (bind(sock, (struct sockaddr *)&lcl_addr, sizeof(lcl_addr)) < 0) {
    print_sys_error("bind");
    exit(1);
  }
  listen(sock, 128);
  if ((srv_nfd = st_netfd_open_socket(sock)) == NULL) {
    print_sys_error("st_netfd_open");
    exit(1);
  }
  /* See the comment regarding serialization decision above */
  if (num_procs > 1 && serialize_accept && st_netfd_serialize_accept(srv_nfd)
      < 0) {
    print_sys_error("st_netfd_serialize_accept");
    exit(1);
  }

  /* Start server processes */
  set_concurrency(num_procs);

  for ( ; ; ) {
    n = sizeof(cli_addr);
    cli_nfd = st_accept(srv_nfd, (struct sockaddr *)&cli_addr, &n, -1);
    if (cli_nfd == NULL) {
      print_sys_error("st_accept");
      exit(1);
    }
    if (st_thread_create(handle_request, cli_nfd, 0, 0) == NULL) {
      print_sys_error("st_thread_create");
      exit(1);
    }
  }

  /* NOTREACHED */
  return 1;
}
示例#5
0
static void *handle_request(void *arg)
{
  struct pollfd pds[2];
  st_netfd_t cli_nfd, rmt_nfd;
  int sock, n;
  char buf[IOBUFSIZE];

  cli_nfd = (st_netfd_t) arg;
  pds[0].fd = st_netfd_fileno(cli_nfd);
  pds[0].events = POLLIN;

  /* Connect to remote host */
  if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    print_sys_error("socket");
    goto done;
  }
  if ((rmt_nfd = st_netfd_open_socket(sock)) == NULL) {
    print_sys_error("st_netfd_open_socket");
    close(sock);
    goto done;
  }
  if (st_connect(rmt_nfd, (struct sockaddr *)&rmt_addr,
		 sizeof(rmt_addr), -1) < 0) {
    print_sys_error("st_connect");
    st_netfd_close(rmt_nfd);
    goto done;
  }
  pds[1].fd = sock;
  pds[1].events = POLLIN;

  /* Now just pump the data through */
  for ( ; ; ) {
    pds[0].revents = 0;
    pds[1].revents = 0;

    if (st_poll(pds, 2, -1) <= 0) {
      print_sys_error("st_poll");
      break;
    }

    if (pds[0].revents & POLLIN) {
      if ((n = (int) st_read(cli_nfd, buf, IOBUFSIZE, -1)) <= 0)
        break;
      if (st_write(rmt_nfd, buf, n, -1) != n)
        break;
    }

    if (pds[1].revents & POLLIN) {
      if ((n = (int) st_read(rmt_nfd, buf, IOBUFSIZE, -1)) <= 0)
        break;
      if (st_write(cli_nfd, buf, n, -1) != n)
        break;
    }
  }
  st_netfd_close(rmt_nfd);

done:

  st_netfd_close(cli_nfd);

  return NULL;
}
示例#6
0
文件: res.c 项目: 12307/state-threads
int dns_getaddr(const char *host, struct in_addr *addr, st_utime_t timeout)
{
  char name[MAXDNAME], **domain;
  const char *cp;
  int s, n, maxlen, dots;
  int trailing_dot, tried_as_is;
  st_netfd_t nfd;

  if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    h_errno = NETDB_INTERNAL;
    return -1;
  }
  if (_res.options & RES_USEVC) {
    h_errno = NETDB_INTERNAL;
    errno = ENOSYS;
    return -1;
  }
  if (!host || *host == '\0') {
    h_errno = HOST_NOT_FOUND;
    return -1;
  }

  /* Create UDP socket */
  if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
    h_errno = NETDB_INTERNAL;
    return -1;
  }
  if ((nfd = st_netfd_open_socket(s)) == NULL) {
    h_errno = NETDB_INTERNAL;
    n = errno;
    close(s);
    errno = n;
    return -1;
  }

  maxlen = sizeof(name) - 1;
  n = 0;
  dots = 0;
  trailing_dot = 0;
  tried_as_is = 0;

  for (cp = host; *cp && n < maxlen; cp++) {
    dots += (*cp == '.');
    name[n++] = *cp;
  }
  if (name[n - 1] == '.')
    trailing_dot = 1;

  /*
   * If there are dots in the name already, let's just give it a try
   * 'as is'.  The threshold can be set with the "ndots" option.
   */
  if (dots >= _res.ndots) {
    if (query_domain(nfd, host, addr, timeout) == 0)
      CLOSE_AND_RETURN(0);
    if (h_errno == NETDB_INTERNAL && errno == EINTR)
      CLOSE_AND_RETURN(-1);
    tried_as_is = 1;
  }

  /*
   * We do at least one level of search if
   *     - there is no dot and RES_DEFNAME is set, or
   *     - there is at least one dot, there is no trailing dot,
   *       and RES_DNSRCH is set.
   */
  if ((!dots && (_res.options & RES_DEFNAMES)) ||
      (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
    name[n++] = '.';
    for (domain = _res.dnsrch; *domain; domain++) {
      strncpy(name + n, *domain, maxlen - n);
      if (query_domain(nfd, name, addr, timeout) == 0)
	CLOSE_AND_RETURN(0);
      if (h_errno == NETDB_INTERNAL && errno == EINTR)
	CLOSE_AND_RETURN(-1);
      if (!(_res.options & RES_DNSRCH))
	break;
    }
  }

  /*
   * If we have not already tried the name "as is", do that now.
   * note that we do this regardless of how many dots were in the
   * name or whether it ends with a dot.
   */
  if (!tried_as_is) {
    if (query_domain(nfd, host, addr, timeout) == 0)
      CLOSE_AND_RETURN(0);
  }

  CLOSE_AND_RETURN(-1);
}
示例#7
0
int _peer_listen(const peer_index_t index) {
  // 现在开始创建 rpc_fd
  int listen_fd;
  struct addrinfo hints, *ai, *p;
  int reuseaddr = 1;
  int rv;
  struct peer_info *peer_info;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = PF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  peer_info = &peer_list[index];

  LOG("[%d] 准备从以下地址获取 IP 信息:%s:%s\n", self_index, peer_info->host, peer_info->port);

  if ((rv = getaddrinfo(peer_info->host, peer_info->port, &hints, &ai)) != 0) {
    ERR("[%d] getaddrinfo 时出现错误:%s\n", self_index, strerror(errno));
    return -1;
  }

  for (p = ai; p != NULL; p = p->ai_next) {
    if ((listen_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
      ERR("[%d] socket: %s\n", self_index, strerror(errno));
      continue;
    }

    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int));

    if (bind(listen_fd, p->ai_addr, p->ai_addrlen) < 0) {
      close(listen_fd);
      ERR("[%d] bind: %s\n", self_index, strerror(errno));
      continue;
    }

    LOG("[%d] success to bind.\n", self_index);
    break;
  }

  if (p == NULL) {
    ERR("[%d] failed to bind at %s.\n", self_index, peer_info->host);
    return -1;
  }

  freeaddrinfo(ai);
  ai = NULL;
  p = NULL;

  if (listen(listen_fd, 10) == -1) {
    ERR("[%d] failed to listen in %d\n", self_index, peer_info->port);
    goto close_fd_and_quit;
  }

  // 初始化 state-threads 系统
  if (st_set_eventsys(ST_EVENTSYS_ALT) == -1)
    ERR("[%d] Can't set event system to alt: %s\n", self_index, strerror(errno));

  if (st_init() < 0) {
    ERR("[%d] st_init \n", self_index);
    goto close_fd_and_quit;
  }

  LOG("[%d] The event system of state-threads is: %s\n", self_index, st_get_eventsys_name());

  // 转换 fd
  if ((peer_list[self_index].rpc_fd = st_netfd_open_socket(listen_fd)) == NULL) {
    ERR("[%d] st_netfd_open: %s\n", self_index, strerror(errno));
    goto close_fd_and_quit;
  }

  return 0;

close_fd_and_quit:
  close(listen_fd);
  return -1;
}
int SrsEdgeForwarder::connect_server()
{
    int ret = ERROR_SUCCESS;
    
    // reopen
    close_underlayer_socket();
    
    SrsConfDirective* conf = _srs_config->get_vhost_edge_origin(_req->vhost);
    srs_assert(conf);
    
    // select the origin.
    std::string server = conf->args.at(origin_index % conf->args.size());
    origin_index = (origin_index + 1) % conf->args.size();
    
    std::string s_port = RTMP_DEFAULT_PORT;
    int port = ::atoi(RTMP_DEFAULT_PORT);
    size_t pos = server.find(":");
    if (pos != std::string::npos) {
        s_port = server.substr(pos + 1);
        server = server.substr(0, pos);
        port = ::atoi(s_port.c_str());
    }
    
    // open socket.
    srs_trace("connect edge stream=%s, tcUrl=%s to server=%s, port=%d",
        _req->stream.c_str(), _req->tcUrl.c_str(), server.c_str(), port);

    // TODO: FIXME: extract utility method
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock == -1){
        ret = ERROR_SOCKET_CREATE;
        srs_error("create socket error. ret=%d", ret);
        return ret;
    }
    
    srs_assert(!stfd);
    stfd = st_netfd_open_socket(sock);
    if(stfd == NULL){
        ret = ERROR_ST_OPEN_SOCKET;
        srs_error("st_netfd_open_socket failed. ret=%d", ret);
        return ret;
    }
    
    srs_freep(client);
    srs_freep(io);
    
    io = new SrsSocket(stfd);
    client = new SrsRtmpClient(io);
    kbps->set_io(io, io);
    
    // connect to server.
    std::string ip = srs_dns_resolve(server);
    if (ip.empty()) {
        ret = ERROR_SYSTEM_IP_INVALID;
        srs_error("dns resolve server error, ip empty. ret=%d", ret);
        return ret;
    }
    
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    
    if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), SRS_EDGE_FORWARDER_TIMEOUT_US) == -1){
        ret = ERROR_ST_CONNECT;
        srs_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret);
        return ret;
    }
    srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
    
    return ret;
}
示例#9
0
文件: res.c 项目: commshare/testST
int dns_getaddr(const char *hosttest, struct in_addr *addr, st_utime_t timeout)
{
	//return 0;
//	host="www.baidu.com";
#if 0
char *host=malloc(128);
memset(host,0,128);
strcpy(host,hosttest);
#endif
char host[128];
memset(host,0,128);
strcpy(host,hosttest);
LOGD("hosttest [%s] host[%s]",hosttest,host);

  char name[MAXDNAME], **domain;
  const char *cp;
  int s, n, maxlen, dots;
  int trailing_dot, tried_as_is;
  st_netfd_t nfd;

  if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    h_errno = NETDB_INTERNAL;
    return -1;
  }
  if (_res.options & RES_USEVC) {
    h_errno = NETDB_INTERNAL;
    errno = ENOSYS;
    return -1;
  }
  if (!host || *host == '\0') {
    h_errno = HOST_NOT_FOUND;
    return -1;
  }

  /* Create UDP socket */
  if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
    h_errno = NETDB_INTERNAL;
    return -1;
  }
  if ((nfd = st_netfd_open_socket(s)) == NULL) {
    h_errno = NETDB_INTERNAL;
    n = errno; //n用来记录错误号
    close(s);
    errno = n;
    return -1;
  }
  //可以走到这里
  maxlen = sizeof(name) - 1;
  LOGD("maxlen[%d]",maxlen);
  n = 0; //此时n是计数器
  dots = 0;
  trailing_dot = 0;
  tried_as_is = 0;

  for (cp = host; *cp && n < maxlen; cp++) {
  	//dots记录host中有几个.
    dots += (*cp == '.'); //走这里
    name[n++] = *cp; //看起来好像是复制host到name中
  }
  //n是后加,所以n-1,此时n-1对应的是最后一个字符
  if (name[n - 1] == '.')
    trailing_dot = 1;
  LOGD("========AAA===name[%s]=========",name);
  /*
   * If there are dots in the name already, let's just give it a try
   * 'as is'.  The threshold can be set with the "ndots" option.
   */



  if (dots >= _res.ndots) {
    if (query_domain(nfd, host, addr, timeout) == 0)
    {
		/*貌似我的query域名就是返回0,只好关闭并且退出了*/
	//	LOGD("query_domain return 0");
     /*不管我是否注释掉这句话都有段错误*/

		return 0;
#if 0
		CLOSE_AND_RETURN(0);
#else
     int ret=0;
     LOGD("===BB==========");
    // LOGD("%-40s %s", (char *)host, inet_ntoa(addr));
    // LOGD("DO RETURN ret[%d]",ret);

  	//LOGD(" errno[%d]",errno);
   // n = errno;
   // st_netfd_close(nfd);
  //  errno = n;
    return -1;
//  goto ZBTEST;
#endif
		//下面这句话不被执行,上面的return直接退出了这个函数
		slogi("query_domain WILL NOT HERE");
    }
    if (h_errno == NETDB_INTERNAL && errno == EINTR)
      CLOSE_AND_RETURN(-1);
    tried_as_is = 1;
  }

  /*
   * We do at least one level of search if
   *     - there is no dot and RES_DEFNAME is set, or
   *     - there is at least one dot, there is no trailing dot,
   *       and RES_DNSRCH is set.
   */
  if ((!dots && (_res.options & RES_DEFNAMES)) ||
      (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
    name[n++] = '.';
    for (domain = _res.dnsrch; *domain; domain++) {
      strncpy(name + n, *domain, maxlen - n);
      if (query_domain(nfd, name, addr, timeout) == 0)
	CLOSE_AND_RETURN(0);
      if (h_errno == NETDB_INTERNAL && errno == EINTR)
	CLOSE_AND_RETURN(-1);
      if (!(_res.options & RES_DNSRCH))
	break;
    }
  }

  /*
   * If we have not already tried the name "as is", do that now.
   * note that we do this regardless of how many dots were in the
   * name or whether it ends with a dot.
   */
  if (!tried_as_is) {
    if (query_domain(nfd, host, addr, timeout) == 0)
    {
		//LOGD("===HERE=query_domain");
		LOGD("----1----query_domain------");
     	CLOSE_AND_RETURN(0);
    }
  }
  CLOSE_AND_RETURN(-1);
//  ZBTEST:
	//  	LOGD("ZBTEST");
  //	return 0;
}
示例#10
0
void *push(void *data)
{
  int sock;
  struct hostent *hp;
  struct sockaddr_in server;
  st_netfd_t rmt_nfd;
  struct thr_data *td = (struct thr_data *)data;
  struct q_info *q = td->q;

  if (HAVE_OPT(DIALSCRIPT) && !online) {
    int status;

    status = system(OPT_ARG(DIALSCRIPT));
    if (WIFEXITED(status)) {
      if (WEXITSTATUS(status) != 0) {
        LOG(LOG_WARNING, "%s: error %d", OPT_ARG(DIALSCRIPT), WEXITSTATUS(status));
        goto quit;
      }
    } else {
      LOG(LOG_ERR, "%s exited abnormally", OPT_ARG(DIALSCRIPT));
      goto quit;
    }
    online = TRUE;
  }

  if ((hp = gethostbyname(q->host)) == (struct hostent *) 0) {
    LOG(LOG_ERR, "can't resolve %s: %s", q->host, strerror(h_errno));
    q->fatal = 1;
    goto quit;
  } 

  memset(&server, 0, sizeof(server));
  server.sin_family = AF_INET;
  memcpy((char *) &server.sin_addr, (char *) hp->h_addr, hp->h_length);
  server.sin_port = htons(q->port);

  sock = socket( AF_INET, SOCK_STREAM, 0 );
  if (sock == -1) {
    LOG(LOG_ERR, "socket: %m");
    q->fatal = 1;
    goto quit;
  }
  uw_setproctitle("connecting to %s:%d", q->host, q->port);
#ifdef USE_ST
  if ((rmt_nfd = st_netfd_open_socket(sock)) == NULL) {
    LOG(LOG_ERR, "st_netfd_open_socket: %m", strerror(errno));
    close(sock);
    q->fatal = 1;
    goto quit;
  } 

  if (st_connect(rmt_nfd, (struct sockaddr *)&server, sizeof(server), TIMEOUT) < 0) {
    LOG(LOG_ERR, "%s:%d: %m", q->host, q->port, strerror(errno));
    st_netfd_close(rmt_nfd);
    q->fatal = 1;
    goto quit;
  }
#else
  rmt_nfd = sock;
  if (connect(rmt_nfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
    LOG(LOG_ERR, "%s:%d: %m", q->host, q->port, strerror(errno));
    close(rmt_nfd);
    q->fatal = 1;
    goto quit;
  }
#endif

  if (pushto(rmt_nfd, td)) {
    LOG(LOG_INFO, "uploaded %s", td->filename); 
    unlink(td->filename);
  }
#ifdef USE_ST
  st_netfd_close(rmt_nfd);
#else
  close(rmt_nfd);
#endif

quit:
  free(td->filename);
  free(td);
#ifdef USE_ST
  q->thread_count--;
  thread_count--;
#endif
  return NULL;
}