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; }
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); } }
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; }
/* * 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; }
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; }
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); }
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; }
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; }
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; }