void add_client_socket(int server_socket, int epoll) { struct sockaddr_in cliaddr; socklen_t addr_size = sizeof cliaddr; int client_socket = accept(server_socket, (struct sockaddr*) &cliaddr, &addr_size); if (client_socket < 0) { perror("accept"); return; } setnonblocking(client_socket); struct epoll_event connev; connev.data.fd = client_socket; connev.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLHUP; if (!epoll_ctl(epoll, EPOLL_CTL_ADD, client_socket, &connev) < 0) { perror("Epoll fd add"); close(client_socket); return; } }
void accept_cb(EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; int serverfd = accept(listener->fd, NULL, NULL); if (serverfd == -1) { ERROR("accept"); return; } setnonblocking(serverfd); int opt = 1; setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif struct server *server = new_server(serverfd, listener->method); server->listener = listener; ev_io_start(EV_A_ & server->recv_ctx->io); }
int pxy_start_listen() { struct sockaddr_in addr1; master->listen_fd = socket(AF_INET,SOCK_STREAM,0); if (master->listen_fd < 0) { D("create listen fd error"); return -1; } int reuse = 1; setsockopt(master->listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)); if (setnonblocking(master->listen_fd) < 0) { D("set nonblocling error"); return -1; } addr1.sin_family = AF_INET; addr1.sin_port = htons(setting.client_port); inet_aton(setting.ip, &addr1.sin_addr); if (bind(master->listen_fd, (struct sockaddr*)&addr1, sizeof(addr1)) < 0) { E("bind address %s:%d error", setting.ip, setting.client_port); return -1; } if (listen(master->listen_fd,1000) < 0) { E("listen error"); return -1; } return 0; }
int accept_agent_side( agent_t *agent, event_info_t *event_info) { socklen_t sin_size; struct sockaddr_storage their_addr; sin_size = sizeof(their_addr); int index = find_empty_agent_sock(agent); struct epoll_event event; if(index < 0) { printf("agent sock table full!!!\n"); exit(1); } if(( agent->agent_fd_pool[index] = accept(agent->listen_fds.agent_listen_sock[event_info->fd], (struct sockaddr *) &their_addr, &sin_size)) == -1) { perror(""); printf("%s %d\n", __FILE__, __LINE__); exit(1); } setnonblocking(agent->agent_fd_pool[index]); event.events = EPOLLOUT; event.data.ptr = &agent->agent_fd_pool_event[index]; agent->agent_fd_pool_event[index].type = AGENT_CONNECTED_UUID; agent->agent_fd_pool_event[index].fd = index; if( epoll_ctl(agent->event_pool, EPOLL_CTL_ADD, agent->agent_fd_pool[index], &event)) { perror(""); printf("%s %d\n", __FILE__, __LINE__); exit(1); } return EXIT_SUCCESS; }
int build_server() { struct addrinfo hints, *res; int s; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; s = getaddrinfo("0.0.0.0", setting.faddr_port, &hints, &res); if (s != 0) { perror("getaddrinfo error"); return -1; } serv_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if(serv_sock < 0) { perror("socket error"); exit(1); } int opt = 1; setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(serv_sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(serv_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif if ( bind(serv_sock, res->ai_addr, res->ai_addrlen) == -1) { perror("bind error"); exit(1); } if( listen(serv_sock, SOMAXCONN) == -1 ) { perror("listen error"); exit(1); } setnonblocking(serv_sock); }
/* Creates a new unix domain socket. */ static int create_socket(char *name) { int s; struct sockaddr_un sockun; if (strlen(name) > sizeof(sockun.sun_path) - 1) { errno = ENAMETOOLONG; return -1; } s = socket(PF_UNIX, SOCK_STREAM, 0); if (s < 0) return -1; sockun.sun_family = AF_UNIX; strcpy(sockun.sun_path, name); if (bind(s, (struct sockaddr*)&sockun, sizeof(sockun)) < 0) { close(s); return -1; } if (listen(s, 128) < 0) { close(s); return -1; } if (setnonblocking(s) < 0) { close(s); return -1; } /* chmod it to prevent any suprises */ if (chmod(name, 0600) < 0) { close(s); return -1; } return s; }
static remote_t *create_remote(listen_ctx_t *listener, struct sockaddr *addr) { struct sockaddr *remote_addr; int index = rand() % listener->remote_num; if (addr == NULL) { remote_addr = listener->remote_addr[index]; } else { remote_addr = addr; } int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); if (remotefd < 0) { ERROR("socket"); return NULL; } int opt = 1; setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif // Setup setnonblocking(remotefd); #ifdef SET_INTERFACE if (listener->iface) { setinterface(remotefd, listener->iface); } #endif remote_t *remote = new_remote(remotefd, listener->timeout); remote->addr_len = get_sockaddr_len(remote_addr); memcpy(&(remote->addr), remote_addr, remote->addr_len); remote->remote_index = index; return remote; }
void setUpServer(int argc, char *argv[]) //Sets up the server { timeout.tv_sec = TIMEOUT_SEC; timeout.tv_usec = TIMEOUT_MS; if (argc < MIN_ARGS) { fprintf(stderr,"ERROR, no port provided\n"); exit(1); } //set up the socket. we are using TCP sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) //make sure we can open the socket { error("ERROR opening socket"); } setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); //allow reuse of address setnonblocking(sockfd); //nonblocking //port stuff bzero((char *) &serv_addr, sizeof(serv_addr)); portno = atoi(argv[PORT_ARG_SERVER]); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) //check it we can bind it { error("ERROR on binding"); } listen(sockfd, LISTENING_QUEUE); //set up a listening queue clilen = sizeof(cli_addr); //set the length of the address }
int accept_host_side(agent_t *agent, client_t *new_client) { socklen_t sin_size; struct sockaddr_in their_addr; struct epoll_event event; sin_size = sizeof(their_addr); if(( new_client->host_sock = accept(agent->listen_fds.host_listen_sock, (struct sockaddr *) &their_addr, &sin_size)) == -1) { perror(""); printf("%s %d\n", __FILE__, __LINE__); exit(1); } strcpy(new_client->source_ip, inet_ntoa(their_addr.sin_addr)); new_client->source_port = htons(their_addr.sin_port); new_client->host_fd_poll = OFF; setnonblocking(new_client->host_sock); event.events = EPOLLOUT; event.data.ptr = &new_client->host_side_event_info; new_client->host_side_event_info.type = HOST_CONNECTED; new_client->host_side_event_info.client = new_client; if( epoll_ctl(agent->event_pool, EPOLL_CTL_ADD, new_client->host_sock, &event)) { perror(""); printf("%s %d\n", __FILE__, __LINE__); exit(1); } return EXIT_SUCCESS; }
CAcceptor::CAcceptor(CInetAddr& sockAddr, int backlog, int timeout) : CSock(AF_INET, SOCK_STREAM) { int res; if (setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &res, sizeof(int)) < 0) { KL_SYS_ERRORLOG("file: "__FILE__", line: %d, " \ "set SO_REUSEADDR failed, err: %s", \ __LINE__, strerror(errno)); throw errno; } if(bind(m_fd, sockAddr.getsockaddr(), sizeof(struct sockaddr)) == -1) { KL_SYS_ERRORLOG("file: "__FILE__", line: %d, " \ "call bind failed, err: %s", \ __LINE__, strerror(errno)); throw errno; } listen(m_fd, backlog); if(timeout > 0) //server option { if((res = setserveropt(timeout)) != 0) { KL_SYS_ERRORLOG("file: "__FILE__", line: %d, " \ "acceptor set server option failed, err: %s", \ __LINE__, strerror(res)); throw res; } } if((res = setnonblocking()) != 0) { KL_SYS_ERRORLOG("file: "__FILE__", line: %d, " \ "acceptor set nonblocking failed, err: %s", \ __LINE__, strerror(res)); throw res; } }
ape_socket *ape_connect(char *ip, int port, acetables *g_ape) { int sock, ret; struct sockaddr_in addr; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { ape_log(APE_ERR, __FILE__, __LINE__, g_ape, "ape_connect() - socket() : %s", strerror(errno)); return NULL; } addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); memset(&(addr.sin_zero), '\0', 8); setnonblocking(sock); if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == 0 || errno != EINPROGRESS) { return NULL; } prepare_ape_socket(sock, g_ape); g_ape->co[sock]->buffer_in.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1)); g_ape->co[sock]->buffer_in.size = DEFAULT_BUFFER_SIZE; g_ape->co[sock]->fd = sock; g_ape->co[sock]->state = STREAM_PROGRESS; g_ape->co[sock]->stream_type = STREAM_OUT; g_ape->bufout[sock].fd = sock; g_ape->bufout[sock].buf = NULL; g_ape->bufout[sock].buflen = 0; g_ape->bufout[sock].allocsize = 0; ret = events_add(g_ape->events, sock, EVENT_READ|EVENT_WRITE); return g_ape->co[sock]; }
int init_socket(int efd, uint16_t sock_type, struct sockaddr *srv, uint16_t srvlen, size_t simultaneous_connection) { struct epoll_event ev; static int optval = 1; int fd; if ((fd = socket(sock_type, SOCK_STREAM, 0)) == -1) return -1; if (!setnonblocking(fd)) goto error; memset(&ev, 0, sizeof(struct epoll_event)); ev.data.fd = fd; ev.events = EPOLLIN | EPOLLET; if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) == -1) goto error; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); int on = 1; if (srv->sa_family == AF_INET6) setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); if (bind(fd, srv, srvlen) == -1) goto error; if (listen(fd, simultaneous_connection) == -1) goto error; return fd; error: close(fd); return -1; }
static void accept_cb (EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; int serverfd = accept(listener->fd, NULL, NULL); if (serverfd == -1) { ERROR("accept"); return; } setnonblocking(serverfd); int opt = 1; setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif if (verbose) { LOGD("accept a connection."); } struct server *server = new_server(serverfd, listener); ev_io_start(EV_A_ &server->recv_ctx->io); ev_timer_start(EV_A_ &server->recv_ctx->watcher); }
/* Create the bound socket in the parent process */ static int create_main_socket() { struct addrinfo *ai, hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; const int gai_err = getaddrinfo(OPTIONS.FRONT_IP, OPTIONS.FRONT_PORT, &hints, &ai); if (gai_err != 0) { ERR("{getaddrinfo}: [%s]\n", gai_strerror(gai_err)); exit(1); } int s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); int t = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)); #ifdef SO_REUSEPORT setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &t, sizeof(int)); #endif setnonblocking(s); if (bind(s, ai->ai_addr, ai->ai_addrlen)) { fail("{bind-socket}"); } #if TCP_DEFER_ACCEPT int timeout = 1; setsockopt(s, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(int) ); #endif /* TCP_DEFER_ACCEPT */ prepare_proxy_line(ai->ai_addr); freeaddrinfo(ai); listen(s, OPTIONS.BACKLOG); return s; }
/* * 初始化网络 */ int inet_init() { socket_t s; int buf_size = 8*1024; int reuse = 1; if ((listening.s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { log_error(errno, "socket()"); exit(1); } if (setsockopt(listening.s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1 || setsockopt(listening.s, SOL_SOCKET, SO_REUSEADDR, &buf_size, sizeof(buf_size)) == -1) { log_error(errno, "setsockopt()"); exit(1); } bzero(&listening.ls_addr, sizeof(listening.ls_addr)); listening.ls_addr.sin_family = AF_INET; listening.ls_addr.sin_port = htons(LISTEN_PORT); listening.ls_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(listening.s, (struct sockaddr *)&listening.ls_addr, sizeof(listening.ls_addr)) == -1) { log_error(errno, "bind()"); exit(1); } if (listen(listening.s, LISTEN_BACKLOG) == -1) { log_error(errno, "listen()"); exit(1); } setnonblocking(listening.s); //注册一个accept()后的处理钩子 //listening.handler = http_connection_init; }
bool CLoveTcp::CreateSocket() { if((m_nSocket = socket(AF_INET,SOCK_STREAM,0))==-1) { LogErrorMsg("create socket error"); return false; } if (setnonblocking(m_nSocket) == -1) { LogErrorMsg("setnonblocking error"); } int nSock = 0; if (setsockopt(m_nSocket,SOL_SOCKET,SO_REUSEADDR,&nSock,sizeof(nSock)) < 0) { /* code */ LogErrorMsg("setsockopt failed"); } m_nEpoll = epoll_create1(EPOLL_CLOEXEC); if (EpollAdd(m_nSocket) == false) { return false; }; return true; }
int handle_accept(int fd) { struct epoll_event ev; struct echo_data* pecho_data; int newsock = 0; do{//edge-trigger newsock = accept(fd,NULL,NULL); //if( newsock <=0 ){ if( newsock == -1 ){ //error occur if( (errno == EAGAIN) || (errno == EWOULDBLOCK) ) break; else{ perror("accept error"); return -1; } } else { printf("Client accept with descriptor #%d\n" ,newsock); pecho_data = alloc_echo_data(newsock, MAX_ECHO_BUF); if( NULL == pecho_data ){ perror("malloc error"); return -1; } setnonblocking(newsock); //set nonblocking ev.data.ptr = pecho_data; ev.events = EPOLLIN|EPOLLPRI|EPOLLET; //edge-trigger if( -1 == epoll_ctl(epfd, EPOLL_CTL_ADD, newsock, &ev) ){ perror("epoll_ctl error!"); return -1; } } }while(1); return 0; }
void handle_new_connection() { int listnum; //Current item in fd int connection; // Socket file descriptor for incoming connections connection = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (connection < 0) { perror("accept"); exit(EXIT_FAILURE); } setnonblocking(connection); for (listnum = 0; (listnum < MAX_USERS) && (connection != -1); listnum ++) if (fd[listnum] == 0) { printf("\nConnection accepted: FD=%d; Slot=%d\n", connection, listnum); fd[listnum] = connection; connection = -1; } if (connection != -1) { // No room left in the queue! printf("\nNo room left for new client.\n"); } else { struct user newUser; newUser.address.sin_addr.s_addr = cli_addr.sin_addr.s_addr; //store the ip printf("USER IP: %u at %d\n", newUser.address.sin_addr.s_addr, listnum - 1); users[fd[listnum - 1]] = newUser; } }
/** * HTTTP daemon listener entry point * * @param listener The Listener DCB * @param config Configuration (ip:port) */ static int httpd_listen(DCB *listener, char *config) { struct sockaddr_in addr; char *port; int one = 1; short pnum; int rc; memcpy(&listener->func, &MyObject, sizeof(GWPROTOCOL)); port = strrchr(config, ':'); if (port) port++; else port = "6442"; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); pnum = atoi(port); addr.sin_port = htons(pnum); if ((listener->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { return 0; } /* socket options */ setsockopt(listener->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); /* set NONBLOCKING mode */ setnonblocking(listener->fd); /* bind address and port */ if (bind(listener->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { return 0; } rc = listen(listener->fd, SOMAXCONN); if (rc == 0) { fprintf(stderr, "Listening http connections at %s\n", config); } else { int eno = errno; errno = 0; fprintf(stderr, "\n* Failed to start listening http due error %d, %s\n\n", eno, strerror(eno)); return 0; } if (poll_add_dcb(listener) == -1) { return 0; } return 1; }
int main(int argc, char **argv) { srand(time(NULL)); int i, c; int pid_flags = 0; int mptcp = 0; int mtu = 0; char *user = NULL; char *local_port = NULL; char *local_addr = NULL; char *password = NULL; char *timeout = NULL; char *method = NULL; char *pid_path = NULL; char *conf_path = NULL; int remote_num = 0; ss_addr_t remote_addr[MAX_REMOTE_NUM]; char *remote_port = NULL; int option_index = 0; static struct option long_options[] = { { "mtu", required_argument, 0, 0 }, { "mptcp", no_argument, 0, 0 }, { "help", no_argument, 0, 0 }, { 0, 0, 0, 0 } }; opterr = 0; USE_TTY(); while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUvA6", long_options, &option_index)) != -1) { switch (c) { case 0: if (option_index == 0) { mtu = atoi(optarg); LOGI("set MTU to %d", mtu); } else if (option_index == 1) { mptcp = 1; LOGI("enable multipath TCP"); } else if (option_index == 2) { usage(); exit(EXIT_SUCCESS); } break; case 's': if (remote_num < MAX_REMOTE_NUM) { remote_addr[remote_num].host = optarg; remote_addr[remote_num++].port = NULL; } break; case 'p': remote_port = optarg; break; case 'l': local_port = optarg; break; case 'k': password = optarg; break; case 'f': pid_flags = 1; pid_path = optarg; break; case 't': timeout = optarg; break; case 'm': method = optarg; break; case 'c': conf_path = optarg; break; case 'b': local_addr = optarg; break; case 'a': user = optarg; break; #ifdef HAVE_SETRLIMIT case 'n': nofile = atoi(optarg); break; #endif case 'u': mode = TCP_AND_UDP; break; case 'U': mode = UDP_ONLY; break; case 'v': verbose = 1; break; case 'h': usage(); exit(EXIT_SUCCESS); case 'A': auth = 1; break; case '6': ipv6first = 1; break; case '?': // The option character is not recognized. LOGE("Unrecognized option: %s", optarg); opterr = 1; break; } } if (opterr) { usage(); exit(EXIT_FAILURE); } if (argc == 1) { if (conf_path == NULL) { conf_path = DEFAULT_CONF_PATH; } } if (conf_path != NULL) { jconf_t *conf = read_jconf(conf_path); if (remote_num == 0) { remote_num = conf->remote_num; for (i = 0; i < remote_num; i++) remote_addr[i] = conf->remote_addr[i]; } if (remote_port == NULL) { remote_port = conf->remote_port; } if (local_addr == NULL) { local_addr = conf->local_addr; } if (local_port == NULL) { local_port = conf->local_port; } if (password == NULL) { password = conf->password; } if (method == NULL) { method = conf->method; } if (timeout == NULL) { timeout = conf->timeout; } if (user == NULL) { user = conf->user; } if (auth == 0) { auth = conf->auth; } if (mtu == 0) { mtu = conf->mtu; } if (mptcp == 0) { mptcp = conf->mptcp; } #ifdef HAVE_SETRLIMIT if (nofile == 0) { nofile = conf->nofile; } #endif } if (remote_num == 0 || remote_port == NULL || local_port == NULL || password == NULL) { usage(); exit(EXIT_FAILURE); } if (method == NULL) { method = "rc4-md5"; } if (timeout == NULL) { timeout = "600"; } #ifdef HAVE_SETRLIMIT /* * no need to check the return value here since we will show * the user an error message if setrlimit(2) fails */ if (nofile > 1024) { if (verbose) { LOGI("setting NOFILE to %d", nofile); } set_nofile(nofile); } #endif if (local_addr == NULL) { local_addr = "127.0.0.1"; } if (pid_flags) { USE_SYSLOG(argv[0]); daemonize(pid_path); } if (ipv6first) { LOGI("resolving hostname to IPv6 address first"); } if (auth) { LOGI("onetime authentication enabled"); } // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGABRT, SIG_IGN); signal(SIGINT, signal_cb); signal(SIGTERM, signal_cb); // Setup keys LOGI("initializing ciphers... %s", method); int m = enc_init(password, method); // Setup proxy context listen_ctx_t listen_ctx; listen_ctx.remote_num = remote_num; listen_ctx.remote_addr = ss_malloc(sizeof(struct sockaddr *) * remote_num); for (int i = 0; i < remote_num; i++) { char *host = remote_addr[i].host; char *port = remote_addr[i].port == NULL ? remote_port : remote_addr[i].port; struct sockaddr_storage *storage = ss_malloc(sizeof(struct sockaddr_storage)); memset(storage, 0, sizeof(struct sockaddr_storage)); if (get_sockaddr(host, port, storage, 1, ipv6first) == -1) { FATAL("failed to resolve the provided hostname"); } listen_ctx.remote_addr[i] = (struct sockaddr *)storage; } listen_ctx.timeout = atoi(timeout); listen_ctx.method = m; listen_ctx.mptcp = mptcp; struct ev_loop *loop = EV_DEFAULT; if (mode != UDP_ONLY) { // Setup socket int listenfd; listenfd = create_and_bind(local_addr, local_port); if (listenfd == -1) { FATAL("bind() error"); } if (listen(listenfd, SOMAXCONN) == -1) { FATAL("listen() error"); } setnonblocking(listenfd); listen_ctx.fd = listenfd; ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ); ev_io_start(loop, &listen_ctx.io); } // Setup UDP if (mode != TCP_ONLY) { LOGI("UDP relay enabled"); init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0], get_sockaddr_len(listen_ctx.remote_addr[0]), mtu, m, auth, listen_ctx.timeout, NULL); } if (mode == UDP_ONLY) { LOGI("TCP relay disabled"); } LOGI("listening at %s:%s", local_addr, local_port); // setuid if (user != NULL && ! run_as(user)) { FATAL("failed to switch user"); } if (geteuid() == 0){ LOGI("running from root user"); } ev_run(loop, 0); return 0; }
int bsc_msc_connect(struct bsc_msc_connection *con) { struct bsc_msc_dest *dest; struct osmo_fd *fd; struct sockaddr_in sin; int on = 1, ret; if (llist_empty(con->dests)) { LOGP(DMSC, LOGL_ERROR, "No MSC(%s) connections configured.\n", con->name); connection_loss(con); return -1; } /* TODO: Why are we not using the libosmocore soecket * abstraction, or libosmo-netif? */ /* move to the next connection */ dest = (struct bsc_msc_dest *) con->dests->next; llist_del(&dest->list); llist_add_tail(&dest->list, con->dests); LOGP(DMSC, LOGL_NOTICE, "Attempting to connect MSC(%s) at %s:%d\n", con->name, dest->ip, dest->port); con->is_connected = 0; msgb_free(con->pending_msg); con->pending_msg = NULL; fd = &con->write_queue.bfd; fd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); fd->priv_nr = 1; if (fd->fd < 0) { perror("Creating TCP socket failed"); return fd->fd; } /* make it non blocking */ setnonblocking(fd); /* set the socket priority */ ret = setsockopt(fd->fd, IPPROTO_IP, IP_TOS, &dest->dscp, sizeof(dest->dscp)); if (ret != 0) LOGP(DMSC, LOGL_ERROR, "Failed to set DSCP to %d on MSC(%s). %s\n", dest->dscp, con->name, strerror(errno)); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(dest->port); inet_aton(dest->ip, &sin.sin_addr); ret = setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (ret != 0) LOGP(DMSC, LOGL_ERROR, "Failed to set SO_REUSEADDR socket option\n"); ret = connect(fd->fd, (struct sockaddr *) &sin, sizeof(sin)); if (ret == -1 && errno == EINPROGRESS) { LOGP(DMSC, LOGL_ERROR, "MSC(%s) Connection in progress\n", con->name); fd->when = BSC_FD_WRITE; fd->cb = msc_connection_connect; con->timeout_timer.cb = msc_con_timeout; con->timeout_timer.data = con; osmo_timer_schedule(&con->timeout_timer, 20, 0); } else if (ret < 0) { perror("Connection failed"); connection_loss(con); return ret; } else { fd->when = BSC_FD_READ | BSC_FD_EXCEPT; fd->cb = osmo_wqueue_bfd_cb; con->is_connected = 1; if (con->connected) con->connected(con); } ret = osmo_fd_register(fd); if (ret < 0) { perror("Registering the fd failed"); close(fd->fd); return ret; } return ret; }
int unblock_connect( const char* ip, int port, int time ) { int ret = 0; struct sockaddr_in address; bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); int sockfd = socket( PF_INET, SOCK_STREAM, 0 ); int fdopt = setnonblocking( sockfd ); ret = connect( sockfd, ( struct sockaddr* )&address, sizeof( address ) ); if ( ret == 0 ) { printf( "connect with server immediately\n" ); fcntl( sockfd, F_SETFL, fdopt ); return sockfd; } else if ( errno != EINPROGRESS ) { printf( "unblock connect not support\n" ); return -1; } fd_set readfds; fd_set writefds; struct timeval timeout; FD_ZERO( &readfds ); FD_SET( sockfd, &writefds ); timeout.tv_sec = time; timeout.tv_usec = 0; ret = select( sockfd + 1, NULL, &writefds, NULL, &timeout ); if ( ret <= 0 ) { printf( "connection time out\n" ); close( sockfd ); return -1; } if ( ! FD_ISSET( sockfd, &writefds ) ) { printf( "no events on sockfd found\n" ); close( sockfd ); return -1; } int error = 0; socklen_t length = sizeof( error ); if( getsockopt( sockfd, SOL_SOCKET, SO_ERROR, &error, &length ) < 0 ) { printf( "get socket option failed\n" ); close( sockfd ); return -1; } if( error != 0 ) { printf( "connection failed after select with the error: %d \n", error ); close( sockfd ); return -1; } printf( "connection ready after select with the socket: %d \n", sockfd ); fcntl( sockfd, F_SETFL, fdopt ); return sockfd; }
static void accept_cb(EV_P_ ev_io *w, int revents) { listen_ctx_t *listener = (listen_ctx_t *)w; struct sockaddr_storage destaddr; int err; int serverfd = accept(listener->fd, NULL, NULL); if (serverfd == -1) { ERROR("accept"); return; } err = getdestaddr(serverfd, &destaddr); if (err) { ERROR("getdestaddr"); return; } setnonblocking(serverfd); int opt = 1; setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif int index = rand() % listener->remote_num; struct sockaddr *remote_addr = listener->remote_addr[index]; int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); if (remotefd == -1) { ERROR("socket"); return; } // Set flags setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif // Enable TCP keepalive feature int keepAlive = 1; int keepIdle = 40; int keepInterval = 20; int keepCount = 5; setsockopt(remotefd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive)); setsockopt(remotefd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle)); setsockopt(remotefd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval)); setsockopt(remotefd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount)); // Set non blocking setnonblocking(remotefd); // Enable MPTCP if (listener->mptcp == 1) { int err = setsockopt(remotefd, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt)); if (err == -1) { ERROR("failed to enable multipath TCP"); } } server_t *server = new_server(serverfd, listener->method); remote_t *remote = new_remote(remotefd, listener->timeout); server->remote = remote; remote->server = server; server->destaddr = destaddr; int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); if (r == -1 && errno != CONNECT_IN_PROGRESS) { ERROR("connect"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } // listen to remote connected event ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); ev_io_start(EV_A_ & server->recv_ctx->io); }
static void server_recv_cb(EV_P_ ev_io *w, int revents) { server_ctx_t *server_ctx = (server_ctx_t *)w; struct sockaddr_storage src_addr; memset(&src_addr, 0, sizeof(struct sockaddr_storage)); buffer_t *buf = ss_malloc(sizeof(buffer_t)); balloc(buf, buf_size); socklen_t src_addr_len = sizeof(struct sockaddr_storage); unsigned int offset = 0; #ifdef MODULE_REDIR char control_buffer[64] = { 0 }; struct msghdr msg; memset(&msg, 0, sizeof(struct msghdr)); struct iovec iov[1]; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); msg.msg_name = &src_addr; msg.msg_namelen = src_addr_len; msg.msg_control = control_buffer; msg.msg_controllen = sizeof(control_buffer); iov[0].iov_base = buf->data; iov[0].iov_len = buf_size; msg.msg_iov = iov; msg.msg_iovlen = 1; buf->len = recvmsg(server_ctx->fd, &msg, 0); if (buf->len == -1) { ERROR("[udp] server_recvmsg"); goto CLEAN_UP; } else if (buf->len > packet_size) { if (verbose) { LOGI("[udp] UDP server_recv_recvmsg fragmentation"); } } if (get_dstaddr(&msg, &dst_addr)) { LOGE("[udp] unable to get dest addr"); goto CLEAN_UP; } src_addr_len = msg.msg_namelen; #else ssize_t r; r = recvfrom(server_ctx->fd, buf->data, buf_size, 0, (struct sockaddr *)&src_addr, &src_addr_len); if (r == -1) { // error on recv // simply drop that packet ERROR("[udp] server_recv_recvfrom"); goto CLEAN_UP; } else if (r > packet_size) { if (verbose) { LOGI("[udp] server_recv_recvfrom fragmentation"); } } buf->len = r; #endif if (verbose) { LOGI("[udp] server receive a packet"); } #ifdef MODULE_REMOTE tx += buf->len; int err = server_ctx->crypto->decrypt_all(buf, server_ctx->crypto->cipher, buf_size); if (err) { // drop the packet silently goto CLEAN_UP; } #endif #ifdef MODULE_LOCAL #if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) #ifdef __ANDROID__ tx += buf->len; #endif uint8_t frag = *(uint8_t *)(buf->data + 2); offset += 3; #endif #endif /* * * SOCKS5 UDP Request * +----+------+------+----------+----------+----------+ * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | * +----+------+------+----------+----------+----------+ * | 2 | 1 | 1 | Variable | 2 | Variable | * +----+------+------+----------+----------+----------+ * * SOCKS5 UDP Response * +----+------+------+----------+----------+----------+ * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | * +----+------+------+----------+----------+----------+ * | 2 | 1 | 1 | Variable | 2 | Variable | * +----+------+------+----------+----------+----------+ * * shadowsocks UDP Request (before encrypted) * +------+----------+----------+----------+ * | ATYP | DST.ADDR | DST.PORT | DATA | * +------+----------+----------+----------+ * | 1 | Variable | 2 | Variable | * +------+----------+----------+----------+ * * shadowsocks UDP Response (before encrypted) * +------+----------+----------+----------+ * | ATYP | DST.ADDR | DST.PORT | DATA | * +------+----------+----------+----------+ * | 1 | Variable | 2 | Variable | * +------+----------+----------+----------+ * * shadowsocks UDP Request and Response (after encrypted) * +-------+--------------+ * | IV | PAYLOAD | * +-------+--------------+ * | Fixed | Variable | * +-------+--------------+ * */ #ifdef MODULE_REDIR char addr_header[512] = { 0 }; int addr_header_len = construct_udprelay_header(&dst_addr, addr_header); if (addr_header_len == 0) { LOGE("[udp] failed to parse tproxy addr"); goto CLEAN_UP; } // reconstruct the buffer brealloc(buf, buf->len + addr_header_len, buf_size); memmove(buf->data + addr_header_len, buf->data, buf->len); memcpy(buf->data, addr_header, addr_header_len); buf->len += addr_header_len; #elif MODULE_TUNNEL char addr_header[512] = { 0 }; char *host = server_ctx->tunnel_addr.host; char *port = server_ctx->tunnel_addr.port; uint16_t port_num = (uint16_t)atoi(port); uint16_t port_net_num = htons(port_num); int addr_header_len = 0; struct cork_ip ip; if (cork_ip_init(&ip, host) != -1) { if (ip.version == 4) { // send as IPv4 struct in_addr host_addr; memset(&host_addr, 0, sizeof(struct in_addr)); int host_len = sizeof(struct in_addr); if (dns_pton(AF_INET, host, &host_addr) == -1) { FATAL("IP parser error"); } addr_header[addr_header_len++] = 1; memcpy(addr_header + addr_header_len, &host_addr, host_len); addr_header_len += host_len; } else if (ip.version == 6) { // send as IPv6 struct in6_addr host_addr; memset(&host_addr, 0, sizeof(struct in6_addr)); int host_len = sizeof(struct in6_addr); if (dns_pton(AF_INET6, host, &host_addr) == -1) { FATAL("IP parser error"); } addr_header[addr_header_len++] = 4; memcpy(addr_header + addr_header_len, &host_addr, host_len); addr_header_len += host_len; } else { FATAL("IP parser error"); } } else { // send as domain int host_len = strlen(host); addr_header[addr_header_len++] = 3; addr_header[addr_header_len++] = host_len; memcpy(addr_header + addr_header_len, host, host_len); addr_header_len += host_len; } memcpy(addr_header + addr_header_len, &port_net_num, 2); addr_header_len += 2; // reconstruct the buffer brealloc(buf, buf->len + addr_header_len, buf_size); memmove(buf->data + addr_header_len, buf->data, buf->len); memcpy(buf->data, addr_header, addr_header_len); buf->len += addr_header_len; #else char host[257] = { 0 }; char port[64] = { 0 }; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); int addr_header_len = parse_udprelay_header(buf->data + offset, buf->len - offset, host, port, &dst_addr); if (addr_header_len == 0) { // error in parse header goto CLEAN_UP; } char *addr_header = buf->data + offset; #endif #ifdef MODULE_LOCAL char *key = hash_key(server_ctx->remote_addr->sa_family, &src_addr); #else char *key = hash_key(dst_addr.ss_family, &src_addr); #endif struct cache *conn_cache = server_ctx->conn_cache; remote_ctx_t *remote_ctx = NULL; cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); if (remote_ctx != NULL) { if (sockaddr_cmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) { remote_ctx = NULL; } } // reset the timer if (remote_ctx != NULL) { ev_timer_again(EV_A_ & remote_ctx->watcher); } if (remote_ctx == NULL) { if (verbose) { #ifdef MODULE_REDIR char src[SS_ADDRSTRLEN]; char dst[SS_ADDRSTRLEN]; strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); LOGI("[udp] cache miss: %s <-> %s", dst, src); #else LOGI("[udp] cache miss: %s:%s <-> %s", host, port, get_addr_str((struct sockaddr *)&src_addr)); #endif } } else { if (verbose) { #ifdef MODULE_REDIR char src[SS_ADDRSTRLEN]; char dst[SS_ADDRSTRLEN]; strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); LOGI("[udp] cache hit: %s <-> %s", dst, src); #else LOGI("[udp] cache hit: %s:%s <-> %s", host, port, get_addr_str((struct sockaddr *)&src_addr)); #endif } } #ifdef MODULE_LOCAL #if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) if (frag) { LOGE("[udp] drop a message since frag is not 0, but %d", frag); goto CLEAN_UP; } #endif const struct sockaddr *remote_addr = server_ctx->remote_addr; const int remote_addr_len = server_ctx->remote_addr_len; if (remote_ctx == NULL) { // Bind to any port int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6); if (remotefd < 0) { ERROR("[udp] udprelay bind() error"); goto CLEAN_UP; } setnonblocking(remotefd); #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef IP_TOS // Set QoS flag int tos = 46; setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef SET_INTERFACE if (server_ctx->iface) { if (setinterface(remotefd, server_ctx->iface) == -1) ERROR("setinterface"); } #endif #ifdef __ANDROID__ if (vpn) { if (protect_socket(remotefd) == -1) { ERROR("protect_socket"); close(remotefd); goto CLEAN_UP; } } #endif // Init remote_ctx remote_ctx = new_remote(remotefd, server_ctx); remote_ctx->src_addr = src_addr; remote_ctx->af = remote_addr->sa_family; remote_ctx->addr_header_len = addr_header_len; memcpy(remote_ctx->addr_header, addr_header, addr_header_len); // Add to conn cache cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); // Start remote io ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } if (offset > 0) { buf->len -= offset; memmove(buf->data, buf->data + offset, buf->len); } int err = server_ctx->crypto->encrypt_all(buf, server_ctx->crypto->cipher, buf_size); if (err) { // drop the packet silently goto CLEAN_UP; } if (buf->len > packet_size) { if (verbose) { LOGI("[udp] server_recv_sendto fragmentation"); } } int s = sendto(remote_ctx->fd, buf->data, buf->len, 0, remote_addr, remote_addr_len); if (s == -1) { ERROR("[udp] server_recv_sendto"); } #else int cache_hit = 0; int need_query = 0; if (buf->len - addr_header_len > packet_size) { if (verbose) { LOGI("[udp] server_recv_sendto fragmentation"); } } if (remote_ctx != NULL) { cache_hit = 1; // detect destination mismatch if (remote_ctx->addr_header_len != addr_header_len || memcmp(addr_header, remote_ctx->addr_header, addr_header_len) != 0) { if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { need_query = 1; } } else { memcpy(&dst_addr, &remote_ctx->dst_addr, sizeof(struct sockaddr_storage)); } } else { if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) { int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6); if (remotefd != -1) { setnonblocking(remotefd); #ifdef SO_BROADCAST set_broadcast(remotefd); #endif #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef IP_TOS // Set QoS flag int tos = 46; setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef SET_INTERFACE if (server_ctx->iface) { if (setinterface(remotefd, server_ctx->iface) == -1) ERROR("setinterface"); } #endif remote_ctx = new_remote(remotefd, server_ctx); remote_ctx->src_addr = src_addr; remote_ctx->server_ctx = server_ctx; remote_ctx->addr_header_len = addr_header_len; memcpy(remote_ctx->addr_header, addr_header, addr_header_len); memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage)); } else { ERROR("[udp] bind() error"); goto CLEAN_UP; } } } if (remote_ctx != NULL && !need_query) { size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr); int s = sendto(remote_ctx->fd, buf->data + addr_header_len, buf->len - addr_header_len, 0, (struct sockaddr *)&dst_addr, addr_len); if (s == -1) { ERROR("[udp] sendto_remote"); if (!cache_hit) { close_and_free_remote(EV_A_ remote_ctx); } } else { if (!cache_hit) { // Add to conn cache remote_ctx->af = dst_addr.ss_family; char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr); cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } } } else { struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; struct query_ctx *query_ctx = new_query_ctx(buf->data + addr_header_len, buf->len - addr_header_len); query_ctx->server_ctx = server_ctx; query_ctx->addr_header_len = addr_header_len; query_ctx->src_addr = src_addr; memcpy(query_ctx->addr_header, addr_header, addr_header_len); if (need_query) { query_ctx->remote_ctx = remote_ctx; } struct ResolvQuery *query = resolv_query(host, query_resolve_cb, NULL, query_ctx, htons(atoi(port))); if (query == NULL) { ERROR("[udp] unable to create DNS query"); close_and_free_query(EV_A_ query_ctx); goto CLEAN_UP; } query_ctx->query = query; } #endif CLEAN_UP: bfree(buf); ss_free(buf); }
void *tcp_server(void *arg) { sock_t *s = (sock_t *) arg; int i,fd,try_to_read,received; struct tcp_client *clients,*client; struct pollfd *pfds = NULL; volatile nfds_t nfds; setnonblocking(s->socket); nfds = 1; pfds = mallocz_or_die(nfds * sizeof(struct pollfd)); pfds->fd = s->socket; pfds->events = POLLIN; clients = NULL; RELAY_ATOMIC_AND( RECEIVED_STATS.active_connections, 0); int rc; for (;;) { rc = poll(pfds,nfds,CONFIG.polling_interval_ms); if (rc == -1) { if (rc == EINTR) continue; WARN_ERRNO("poll"); goto out; } for (i = 0; i < nfds; i++) { if (!pfds[i].revents) continue; if (pfds[i].fd == s->socket) { fd = accept(s->socket, NULL, NULL); if (fd == -1) { WARN_ERRNO("accept"); goto out; } setnonblocking(fd); RELAY_ATOMIC_INCREMENT( RECEIVED_STATS.active_connections, 1 ); pfds = realloc_or_die(pfds, (nfds + 1) * sizeof(*pfds)); clients = realloc_or_die(clients,(nfds + 1) * sizeof(*clients)); clients[nfds].pos = 0; clients[nfds].buf = mallocz_or_die(ASYNC_BUFFER_SIZE); // WARN("[%d] CREATE %p fd: %d",i,clients[nfds].buf,fd); pfds[nfds].fd = fd; pfds[nfds].events = POLLIN; pfds[nfds].revents = 0; nfds++; } else { client = &clients[i]; try_to_read = ASYNC_BUFFER_SIZE - client->pos; // try to read as much as possible if (try_to_read <= 0) { WARN("disconnecting, try to read: %d, pos: %d", try_to_read, client->pos); goto disconnect; } received = recv(pfds[i].fd, client->buf + client->pos, try_to_read,0); if (received <= 0) { if (received == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) continue; disconnect: shutdown(pfds[i].fd,SHUT_RDWR); close(pfds[i].fd); // WARN("[%d] DESTROY %p %d %d fd: %d vs %d",i,client->buf,client->x,i,pfds[i].fd,client->fd); free(client->buf); // shft left memcpy(pfds + i,pfds + i + 1, (nfds - i - 1) * sizeof(struct pollfd)); memcpy(clients + i,clients + i + 1, (nfds - i - 1) * sizeof(struct tcp_client)); nfds--; pfds = realloc_or_die(pfds, nfds * sizeof(struct pollfd)); clients = realloc_or_die(clients, nfds * sizeof(struct tcp_client)); RELAY_ATOMIC_DECREMENT( RECEIVED_STATS.active_connections, 1 ); continue; } client->pos += received; try_to_consume_one_more: if (client->pos < EXPECTED_HEADER_SIZE) continue; if (EXPECTED(client) > MAX_CHUNK_SIZE) { WARN("received frame (%d) > MAX_CHUNK_SIZE(%d)",EXPECTED(client),MAX_CHUNK_SIZE); goto disconnect; } if (client->pos >= EXPECTED(client) + EXPECTED_HEADER_SIZE) { buf_to_blob_enqueue(client->buf,EXPECTED(client)); client->pos -= EXPECTED(client) + EXPECTED_HEADER_SIZE; if (client->pos < 0) { WARN("BAD PACKET wrong 'next' position(< 0) pos: %d expected packet size:%d header_size: %d", client->pos, EXPECTED(client),EXPECTED_HEADER_SIZE); goto disconnect; } if (client->pos > 0) { // [ h ] [ h ] [ h ] [ h ] [ D ] [ D ] [ D ] [ h ] [ h ] [ h ] [ h ] [ D ] // ^ pos(12) // after we remove the first packet + header it becomes: // [ h ] [ h ] [ h ] [ h ] [ D ] [ D ] [ D ] [ h ] [ h ] [ h ] [ h ] [ D ] // ^ pos (5) // and then we copy from header + data, to position 0, 5 bytes // // [ h ] [ h ] [ h ] [ h ] [ D ] // ^ pos (5) memmove(client->buf, client->buf + EXPECTED_HEADER_SIZE + EXPECTED(client), client->pos); if (client->pos >= EXPECTED_HEADER_SIZE) goto try_to_consume_one_more; } } } } } out: for (i = 0; i < nfds; i++) { if (pfds[i].fd != s->socket) free(clients[i].buf); shutdown(pfds[i].fd, SHUT_RDWR); close(pfds[i].fd); } free(pfds); free(clients); set_aborted(); pthread_exit(NULL); }
static void query_resolve_cb(struct sockaddr *addr, void *data) { struct query_ctx *query_ctx = (struct query_ctx *)data; struct ev_loop *loop = query_ctx->server_ctx->loop; if (verbose) { LOGI("[udp] udns resolved"); } query_ctx->query = NULL; if (addr == NULL) { LOGE("[udp] udns returned an error"); } else { remote_ctx_t *remote_ctx = query_ctx->remote_ctx; int cache_hit = 0; // Lookup in the conn cache if (remote_ctx == NULL) { char *key = hash_key(AF_UNSPEC, &query_ctx->src_addr); cache_lookup(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); } if (remote_ctx == NULL) { int remotefd = create_remote_socket(addr->sa_family == AF_INET6); if (remotefd != -1) { setnonblocking(remotefd); #ifdef SO_BROADCAST set_broadcast(remotefd); #endif #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef IP_TOS // Set QoS flag int tos = 46; setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef SET_INTERFACE if (query_ctx->server_ctx->iface) { if (setinterface(remotefd, query_ctx->server_ctx->iface) == -1) ERROR("setinterface"); } #endif remote_ctx = new_remote(remotefd, query_ctx->server_ctx); remote_ctx->src_addr = query_ctx->src_addr; remote_ctx->server_ctx = query_ctx->server_ctx; remote_ctx->addr_header_len = query_ctx->addr_header_len; memcpy(remote_ctx->addr_header, query_ctx->addr_header, query_ctx->addr_header_len); } else { ERROR("[udp] bind() error"); } } else { cache_hit = 1; } if (remote_ctx != NULL) { memcpy(&remote_ctx->dst_addr, addr, sizeof(struct sockaddr_storage)); size_t addr_len = get_sockaddr_len(addr); int s = sendto(remote_ctx->fd, query_ctx->buf->data, query_ctx->buf->len, 0, addr, addr_len); if (s == -1) { ERROR("[udp] sendto_remote"); if (!cache_hit) { close_and_free_remote(EV_A_ remote_ctx); } } else { if (!cache_hit) { // Add to conn cache char *key = hash_key(AF_UNSPEC, &remote_ctx->src_addr); cache_insert(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } } } } // clean up close_and_free_query(EV_A_ query_ctx); }
int main( int argc, char* argv[] ) { if( argc <= 2 ) { printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); return 1; } const char* ip = argv[1]; int port = atoi( argv[2] ); int ret = 0; struct sockaddr_in address; bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); listenfd = socket( PF_INET, SOCK_STREAM, 0 ); assert( listenfd >= 0 ); ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); ret = listen( listenfd, 5 ); assert( ret != -1 ); for( int i = 0; i < PROCESS_COUNT; ++i ) { ret = socketpair( PF_UNIX, SOCK_STREAM, 0, sub_process[i].pipefd ); assert( ret != -1 ); sub_process[i].pid = fork(); if( sub_process[i].pid < 0 ) { continue; } else if( sub_process[i].pid > 0 ) { close( sub_process[i].pipefd[1] ); setnonblocking( sub_process[i].pipefd[0] ); continue; } else { close( sub_process[i].pipefd[0] ); setnonblocking( sub_process[i].pipefd[1] ); run_child( i ); exit( 0 ); } } epoll_event events[ MAX_EVENT_NUMBER ]; epollfd = epoll_create( 5 ); assert( epollfd != -1 ); addfd( epollfd, listenfd ); ret = socketpair( PF_UNIX, SOCK_STREAM, 0, sig_pipefd ); assert( ret != -1 ); setnonblocking( sig_pipefd[1] ); addfd( epollfd, sig_pipefd[0] ); addsig( SIGCHLD, sig_handler ); addsig( SIGTERM, sig_handler ); addsig( SIGINT, sig_handler ); addsig( SIGPIPE, SIG_IGN ); bool stop_server = false; int sub_process_counter = 0; while( !stop_server ) { int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 ); if ( ( number < 0 ) && ( errno != EINTR ) ) { printf( "epoll failure\n" ); break; } for ( int i = 0; i < number; i++ ) { int sockfd = events[i].data.fd; if( sockfd == listenfd ) { int new_conn = 1; send( sub_process[sub_process_counter++].pipefd[0], ( char* )&new_conn, sizeof( new_conn ), 0 ); printf( "send request to child %d\n", sub_process_counter-1 ); sub_process_counter %= PROCESS_COUNT; } else if( ( sockfd == sig_pipefd[0] ) && ( events[i].events & EPOLLIN ) ) { int sig; char signals[1024]; ret = recv( sig_pipefd[0], signals, sizeof( signals ), 0 ); if( ret == -1 ) { continue; } else if( ret == 0 ) { continue; } else { for( int i = 0; i < ret; ++i ) { switch( signals[i] ) { case SIGCHLD: { pid_t pid; int stat; while ( ( pid = waitpid( -1, &stat, WNOHANG ) ) > 0 ) { for( int i = 0; i < PROCESS_COUNT; ++i ) { if( sub_process[i].pid == pid ) { close( sub_process[i].pipefd[0] ); sub_process[i].pid = -1; } } } stop_server = true; for( int i = 0; i < PROCESS_COUNT; ++i ) { if( sub_process[i].pid != -1 ) { stop_server = false; } } break; } case SIGTERM: case SIGINT: { printf( "kill all the clild now\n" ); for( int i = 0; i < PROCESS_COUNT; ++i ) { int pid = sub_process[i].pid; kill( pid, SIGTERM ); } break; } default: { break; } } } } } else { continue; } } } del_resource(); return 0; }
void test_process_events_and_timers(test_connection_t *lc) { struct epoll_event ev; int nfds; //等待epoll事件的发生 nfds=epoll_wait(epfd,event_list, nevents,500); int err = (nfds == -1) ? errno : 0; if(err){ if (err == EINTR) { if(t_event_timer_alarm){ t_event_timer_alarm=0; return; } } perror("epoll_wait() failed"); return; } if (nfds == 0) { //printf("epoll_wait() returned no events without timeout\n"); return; } //处理所发生的所有事件 for(int i=0;i<nfds;++i) { test_connection_t *c=event_list[i].data.ptr; c = (test_connection_t *) ((uintptr_t) c & (uintptr_t) ~1); if(c->fd==lc->fd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。 { struct sockaddr_in in_addr; socklen_t in_len; int connfd = accept4(lc->fd,(struct sockaddr *)&in_addr, &in_len,SOCK_NONBLOCK); if(connfd<0){ perror("connfd<0"); //exit(1); } setnonblocking(connfd); char *str = inet_ntoa(in_addr.sin_addr); printf( "%d accapt a connection from %s \n",event_list[i].events, str); //设置用于读操作的文件描述符 //设置用于注测的读操作事件 ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; test_connection_t *cnew=(test_connection_t*)calloc(1,sizeof(test_connection_t)); cnew->hand=init_hand; cnew->fd=connfd; cnew->current=0; ev.data.ptr=cnew; //注册ev epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); } else if((event_list[i].events&EPOLLIN) || (event_list[i].events&EPOLLOUT))//如果是已经连接的用户,并且收到数据,那么进行读入。 { printf("EPOLLET | EPOLLOUT: %d\n",event_list[i].events); if(28 == event_list[i].events){ perror("28"); printf("%d\n",errno); //if(errno == ECONNRESET) return;//Connection reset by peer //else printf("epoll event: 28, errno: %d\n",errno); close(c->fd); free(c); return; } c->ev=&event_list[i]; c->hand(c); } else { // 如果有数据发送 perror("unknow event: "); } } }
int main() { struct sockaddr_in server_addr; bzero(&server_addr,sizeof(server_addr)); //把一段内存区的内容全部设置为0 server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); server_addr.sin_port = htons(8000); int server_socket = socket(PF_INET,SOCK_STREAM,0); if( server_socket < 0) { printf("Create Socket Failed!"); exit(1); } int opt =1; setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))) { perror("Server Bind Port 53 Failed: "); exit(1); } if ( listen(server_socket, 5) ) { printf("Server Listen Failed!"); exit(1); } pserver_context pcontext = (pserver_context) calloc(1,sizeof(server_context)); pcontext->client_context_lt = gdsl_list_alloc("client socket",NULL,NULL); pcontext->kdpfd = epoll_create(5); pthread_attr_t attr; pthread_t threadId; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); /* 设置线程为分离属性*/ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if(pthread_create(&threadId,&attr,message_handler,(void*)pcontext)) { perror("pthread_creat error!"); exit(-1); } while(1) { struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); printf("waiting for connection...\n"); int new_client_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length); if ( new_client_socket < 0) { printf("Server Accept Failed!\n"); /*break;*/ continue; } setnonblocking(new_client_socket); pconnect_context pconnection = calloc(1,sizeof(connect_context)); if( pconnection == NULL ) { perror("calloc event fail: "); close(new_client_socket); continue; } pconnection->ev.events = EPOLLIN; pconnection->session.socket = new_client_socket; pconnection->socket = new_client_socket; pconnection->ev.data.ptr = (void*)pconnection;/*(void*)&(pconnection->session);*/ if(epoll_ctl(pcontext->kdpfd, EPOLL_CTL_ADD, new_client_socket,&(pconnection->ev))<0) { perror("epoll_ctl fail: "); close(new_client_socket); continue; } gdsl_list_insert_tail( pcontext->client_context_lt,(int*)(size_t)new_client_socket); } return 0; }
int main(int argc, char *argv[]) { char scrap[500],bindto[128]; struct hostent *myself; struct itimerval timers; struct itimerval oldtimers; struct sigaction sig; struct timeval timeout; /* Timeout for select */ int readsocks; /* Number of sockets ready for reading */ int i, i2, addr_len; int sock; int reuse_addr = 1, bind_to_other = 0; int broadcast_enable = 1; /* sort of senseless without */ long utime; /* Suck in command line options */ if (argc > 1) { /* something was passed */ for(i=1;i<argc;i++) { if (strcmp("-g", argv[i]) == 0) { sscanf(argv[i+1], "%d", &groupid); if (groupid < 1) { printf("sntsd: group must be > 0\n"); exit(1); } i++; /* so the for isn't called and the # considered a bad option */ } else if (strcmp("-a", argv[i]) == 0) { sscanf(argv[i+1], "%s", &bindto); bind_to_other=1; if (strlen(bindto)>16) { /* Just checking for too long input */ printf("sntsd: IP address is too long\n"); exit(1); } i++; } else if (strcmp("-i", argv[i]) == 0) { i++; } else { printf("sntsd: bad command line option %s.\n", argv[i]); exit(1); } } } /* this is to allow for multiple hosts on the same group. If twice the interval is reached, the host is assumed down and this host starts broadcasting */ bcast_server_interval = bcast_interval * 2; /* Get socket */ sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) { perror("socket"); exit(1); } /* So that we can re-bind to it without TIME_WAIT problems */ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)); /* Broadcast enable */ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)); /* Set socket to non-blocking with our setnonblocking routine */ setnonblocking(sock); memset((char *) &server_address, 0, sizeof(server_address)); server_address.sin_family = AF_INET; if (bind_to_other == 0) server_address.sin_addr.s_addr = htonl(INADDR_ANY); else server_address.sin_addr.s_addr = inet_addr(bindto); server_address.sin_port = htons(SNTSPORT); if (bind(sock, (struct sockaddr *) &server_address, sizeof(server_address)) < 0 ) { perror("bind"); close(sock); exit(1); } /* Daemon ourselves */ daemon(1,1); //signal(SIGALRM, timebcast); /* Linux doesn't like "signal" :( */ sig.sa_handler = &timebcast; sig.sa_flags = SA_RESTART; sigaction(SIGALRM, &sig, NULL); oldtimers.it_interval.tv_sec = bcast_interval; oldtimers.it_value.tv_sec = bcast_interval; timers.it_interval.tv_sec = bcast_interval; timers.it_value.tv_sec = bcast_interval; if(setitimer(ITIMER_REAL, &timers, NULL)) { printf("Failure setting timer (blame Linux)\n"); exit(1); } /* Get info on myself or use passed IP address */ if (bind_to_other == 0) { /* Lookup my IP */ i = gethostname(scrap, sizeof(scrap)); myself = gethostbyname(scrap); if (myself == NULL) { syslog(LOG_ERR, "Can't lookup my own IP - quiting"); exit(1); } sprintf(myip, "%s", inet_ntoa(*((struct in_addr *)myself->h_addr))); } else sprintf(myip,"%s",bindto); /* Use specified IP */ /* syslog starting message */ sprintf(scrap, "sntsd version %s proto version %s starting up", VERSION, PROTOVERSION); syslog(LOG_NOTICE, scrap); sprintf(scrap, "starting using groupid: %d", groupid); syslog(LOG_NOTICE, scrap); sprintf(scrap, "using IP: %s",myip); syslog(LOG_NOTICE, scrap); udp_socket = sock; bcast.sin_family = AF_INET; bcast.sin_addr.s_addr = inet_addr(BCAST_ADDR); bcast.sin_port = htons(SNTSPORT); time(&starttime); /* pick random sequence number */ #ifdef COMPAT_SRANDOM time(&utime); srandom(utime); #else srandomdev(); /* init using /dev/urandom on systems which have it */ #endif picknewsequence(); /* Send 'master coming up' message */ sprintf(outmessage, "snts %s %d hostup", PROTOVERSION, groupid); sendto(udp_socket, outmessage, sizeof(outmessage), 0, (struct sockaddr *)&bcast, sizeof(bcast)); while (1) { /* i=recvfrom(udp_socket, message, sizeof(message), 0, (struct sockaddr *)&their_addr, &addr_len); */ timeout.tv_sec = 10; timeout.tv_usec = 0; build_select_list(); readsocks = select(udp_socket+1, &socks, (fd_set *) 0, (fd_set *) 0, &timeout); if (readsocks == 0) { } else if (readsocks > 0) { i=recvfrom(udp_socket, message, sizeof(message), 0, (struct sockaddr *)&their_addr, &addr_len); message[i] = '\0'; process_message(); } } }