Esempio n. 1
0
static gboolean angel_dispatch(liAngelConnection *acon, GError **err) {
	gint32 id = acon->parse.id, type = acon->parse.type;
	liAngelCall *call = NULL;
	liAngelCallCB cb = NULL;
	gpointer ctx = NULL;

	switch (type) {
	case ANGEL_CALL_SEND_SIMPLE:
		if (-1 != id) {
			g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
				"Invalid id: %i, should be -1 for simple call", (gint) id);
			close_fd_array(acon->parse.fds);
			return FALSE;
		}

		if (acon->parse.error->len > 0 || acon->parse.fds->len > 0) {
			g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
				"Wrong data in call");
			close_fd_array(acon->parse.fds);
			return FALSE;
		}
		acon->recv_call(acon, GSTR_LEN(acon->parse.mod), GSTR_LEN(acon->parse.action),
			id, acon->parse.data);
		break;
	case ANGEL_CALL_SEND_CALL:
		if (-1 == id) {
			g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
				"Invalid id: -1, should be >= 0 for call");
			close_fd_array(acon->parse.fds);
			return FALSE;
		}

		if (acon->parse.error->len > 0 || acon->parse.fds->len > 0) {
			g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
				"Wrong data in call");
			close_fd_array(acon->parse.fds);
			return FALSE;
		}
		acon->recv_call(acon, GSTR_LEN(acon->parse.mod), GSTR_LEN(acon->parse.action),
			id, acon->parse.data);
		break;
	case ANGEL_CALL_SEND_RESULT:
		g_mutex_lock(acon->mutex);
			if (!li_idlist_is_used(acon->call_id_list, id)) {
				g_mutex_unlock(acon->mutex);
				g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
					"Invalid id: %i", (gint) id);
				close_fd_array(acon->parse.fds);
				return FALSE;
			}
			li_idlist_put(acon->call_id_list, id);
			if (type == ANGEL_CALL_SEND_RESULT && (guint) id < acon->call_table->len) {
				call = (liAngelCall*) g_ptr_array_index(acon->call_table, id);
				g_ptr_array_index(acon->call_table, id) = NULL;
				if (call) {
					call->id = -1;
					ev_timer_stop(acon->loop, &call->timeout_watcher);
					ctx = call->context;
					if (NULL == (cb = call->callback)) {
						g_slice_free(liAngelCall, call);
					}
				}
			}
		g_mutex_unlock(acon->mutex);

		if (cb) {
			cb(call, ctx, FALSE, acon->parse.error, acon->parse.data, acon->parse.fds);
		}
		close_fd_array(acon->parse.fds);
		break;
	default:
		g_set_error(err, LI_ANGEL_CONNECTION_ERROR, LI_ANGEL_CONNECTION_INVALID_DATA,
			"Invalid type: %i", (gint) type);
		close_fd_array(acon->parse.fds);
		return FALSE;
	}

	return TRUE;
}
Esempio n. 2
0
static void mon_interval_cb(struct ev_loop* loop, ev_timer* w, int revents V_UNUSED) {
    dmn_assert(loop); dmn_assert(w); dmn_assert(revents == EV_TIMER);

    mon_t* this_mon = w->data;
    dmn_assert(!this_mon->result_pending);

    if (this_mon->cmd->max_proc > 0 && num_proc >= this_mon->cmd->max_proc) {
        // If more than max_proc processes are running, reschedule excess
        //   checks to run 0.1 seconds later. After a few passes, this will
        //   smooth the schedule out to prevent a thundering herd.
        ev_timer_stop(loop, this_mon->interval_timer);
        ev_timer_set(this_mon->interval_timer, 0.1, this_mon->cmd->interval);
        ev_timer_start(loop, this_mon->interval_timer);
        return;
    }

    // Before forking, block all signals and save the old mask
    //   to avoid a race condition where local sighandlers execute
    //   in the child between fork and exec().
    sigset_t all_sigs;
    sigfillset(&all_sigs);
    sigset_t saved_mask;
    sigemptyset(&saved_mask);
    if(pthread_sigmask(SIG_SETMASK, &all_sigs, &saved_mask))
        log_fatal("pthread_sigmask() failed");

    this_mon->cmd_pid = fork();
    if(this_mon->cmd_pid == -1)
        log_fatal("fork() failed: %s", dmn_logf_strerror(errno));

    if(!this_mon->cmd_pid) { // child
        // reset all signal handlers to default before unblocking
        struct sigaction defaultme;
        sigemptyset(&defaultme.sa_mask);
        defaultme.sa_handler = SIG_DFL;
        defaultme.sa_flags = 0;

        // we really don't care about error retvals here
        for(int i = 0; i < NSIG; i++)
            (void)sigaction(i, &defaultme, NULL);

        // unblock all
        sigset_t no_sigs;
        sigemptyset(&no_sigs);
        if(pthread_sigmask(SIG_SETMASK, &no_sigs, NULL))
            log_fatal("pthread_sigmask() failed");

        // technically, we could go ahead and close off stdout/stderr
        //   here for the "startfg" case, but why bother?  If the user
        //   is debugging via startfg they might want to see this crap anyways.
        execv(this_mon->cmd->args[0], this_mon->cmd->args);
        log_fatal("execv(%s, ...) failed: %s", this_mon->cmd->args[0], dmn_logf_strerror(errno));
    }
    num_proc++;

    // restore previous signal mask from before fork in parent
    if(pthread_sigmask(SIG_SETMASK, &saved_mask, NULL))
        log_fatal("pthread_sigmask() failed");

    this_mon->result_pending = true;
    ev_timer_set(this_mon->cmd_timeout, this_mon->cmd->timeout, 0);
    ev_timer_start(loop, this_mon->cmd_timeout);
    ev_child_set(this_mon->child_watcher, this_mon->cmd_pid, 0);
    ev_child_start(loop, this_mon->child_watcher);
}
Esempio n. 3
0
int uv_timer_stop(uv_timer_t* timer) {
  timer->flags &= ~UV_TIMER_REPEAT;
  ev_timer_stop(timer->loop->ev, &timer->timer_watcher);
  uv__handle_stop(timer);
  return 0;
}
Esempio n. 4
0
int main(int argc, char **argv)
{

    int i, c;
    int pid_flags = 0;
    char *user = NULL;
    char *password = NULL;
    char *timeout = NULL;
    char *method = NULL;
    char *pid_path = NULL;
    char *conf_path = NULL;
    char *iface = NULL;

    int server_num = 0;
    const char *server_host[MAX_REMOTE_NUM];

    char * nameservers[MAX_DNS_NUM + 1];
    int nameserver_num = 0;

    int option_index = 0;
    static struct option long_options[] =
    {
        { "fast-open",          no_argument,       0, 0 },
        { "acl",                required_argument, 0, 0 },
        { "manager-address",    required_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:i:d:a:uUv",
                            long_options, &option_index)) != -1) {
        switch (c) {
        case 0:
            if (option_index == 0) {
                fast_open = 1;
            } else if (option_index == 1) {
                LOGI("initialize acl...");
                acl = !init_acl(optarg);
            } else if (option_index == 2) {
                manager_address = optarg;
            }
            break;
        case 's':
            if (server_num < MAX_REMOTE_NUM) {
                server_host[server_num++] = optarg;
            }
            break;
        case 'p':
            server_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 'i':
            iface = optarg;
            break;
        case 'd':
            if (nameserver_num < MAX_DNS_NUM) {
                nameservers[nameserver_num++] = optarg;
            }
            break;
        case 'a':
            user = optarg;
            break;
        case 'u':
            mode = TCP_AND_UDP;
            break;
        case 'U':
            mode = UDP_ONLY;
            break;
        case 'v':
            verbose = 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 (server_num == 0) {
            server_num = conf->remote_num;
            for (i = 0; i < server_num; i++) {
                server_host[i] = conf->remote_addr[i].host;
            }
        }
        if (server_port == NULL) {
            server_port = conf->remote_port;
        }
        if (password == NULL) {
            password = conf->password;
        }
        if (method == NULL) {
            method = conf->method;
        }
        if (timeout == NULL) {
            timeout = conf->timeout;
        }
#ifdef TCP_FASTOPEN
        if (fast_open == 0) {
            fast_open = conf->fast_open;
        }
#endif
#ifdef HAVE_SETRLIMIT
        if (nofile == 0) {
            nofile = conf->nofile;
        }
        /*
         * no need to check the return value here since we will show
         * the user an error message if setrlimit(2) fails
         */
        if (nofile) {
            if (verbose) {
                LOGI("setting NOFILE to %d", nofile);
            }
            set_nofile(nofile);
        }
#endif
        if (conf->nameserver != NULL) {
            nameservers[nameserver_num++] = conf->nameserver;
        }
    }

    if (server_num == 0) {
        server_host[server_num++] = NULL;
    }

    if (server_num == 0 || server_port == NULL || password == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }

    if (method == NULL) {
        method = "table";
    }

    if (timeout == NULL) {
        timeout = "60";
    }

    if (pid_flags) {
        USE_SYSLOG(argv[0]);
        daemonize(pid_path);
    }

    if (fast_open == 1) {
#ifdef TCP_FASTOPEN
        LOGI("using tcp fast open");
#else
        LOGE("tcp fast open is not supported by this environment");
#endif
    }

#ifdef __MINGW32__
    winsock_init();
#else
    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGABRT, SIG_IGN);
#endif

    struct ev_signal sigint_watcher;
    struct ev_signal sigterm_watcher;
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    // setup keys
    LOGI("initialize ciphers... %s", method);
    int m = enc_init(password, method);

    // inilitialize ev loop
    struct ev_loop *loop = EV_DEFAULT;

    // setup udns
    if (nameserver_num == 0) {
#ifdef __MINGW32__
        nameservers[nameserver_num++] = "8.8.8.8";
        resolv_init(loop, nameservers, nameserver_num);
#else
        resolv_init(loop, NULL, 0);
#endif
    } else {
        resolv_init(loop, nameservers, nameserver_num);
    }

    for (int i = 0; i < nameserver_num; i++) {
        LOGI("using nameserver: %s", nameservers[i]);
    }

    // inilitialize listen context
    struct listen_ctx listen_ctx_list[server_num];

    // bind to each interface
    while (server_num > 0) {
        int index = --server_num;
        const char * host = server_host[index];

        if (mode != UDP_ONLY) {
            // Bind to port
            int listenfd;
            listenfd = create_and_bind(host, server_port);
            if (listenfd < 0) {
                FATAL("bind() error");
            }
            if (listen(listenfd, SSMAXCONN) == -1) {
                FATAL("listen() error");
            }
            setnonblocking(listenfd);
            struct listen_ctx *listen_ctx = &listen_ctx_list[index];

            // Setup proxy context
            listen_ctx->timeout = atoi(timeout);
            listen_ctx->fd = listenfd;
            listen_ctx->method = m;
            listen_ctx->iface = iface;
            listen_ctx->loop = loop;

            ev_io_init(&listen_ctx->io, accept_cb, listenfd, EV_READ);
            ev_io_start(loop, &listen_ctx->io);
        }

        // Setup UDP
        if (mode != TCP_ONLY) {
            init_udprelay(server_host[index], server_port, m, atoi(timeout),
                          iface);
        }

        LOGI("listening at %s:%s", host ? host : "*", server_port);

    }

    if (manager_address != NULL) {
        ev_timer_init(&stat_update_watcher, stat_update_cb, UPDATE_INTERVAL, UPDATE_INTERVAL);
        ev_timer_start(EV_DEFAULT, &stat_update_watcher);
    }

    if (mode != TCP_ONLY) {
        LOGI("UDP relay enabled");
    }

    if (mode == UDP_ONLY) {
        LOGI("TCP relay disabled");
    }

    // setuid
    if (user != NULL) {
        run_as(user);
    }

    // Init connections
    cork_dllist_init(&connections);

    // start ev loop
    ev_run(loop, 0);

    if (verbose) {
        LOGI("closed gracefully");
    }

    if (manager_address != NULL) {
        ev_timer_stop(EV_DEFAULT, &stat_update_watcher);
    }

    // Clean up
    for (int i = 0; i <= server_num; i++) {
        struct listen_ctx *listen_ctx = &listen_ctx_list[i];
        if (mode != UDP_ONLY) {
            ev_io_stop(loop, &listen_ctx->io);
            close(listen_ctx->fd);
        }
    }

    if (mode != UDP_ONLY) {
        free_connections(loop);
    }

    if (mode != TCP_ONLY) {
        free_udprelay();
    }

    resolv_shutdown(loop);

#ifdef __MINGW32__
    winsock_cleanup();
#endif

    ev_signal_stop(EV_DEFAULT, &sigint_watcher);
    ev_signal_stop(EV_DEFAULT, &sigterm_watcher);

    return 0;
}
Esempio n. 5
0
static void server_recv_cb(EV_P_ ev_io *w, int revents)
{
    struct server_ctx *server_recv_ctx = (struct server_ctx *)w;
    struct server *server = server_recv_ctx->server;
    struct remote *remote = server->remote;
    char *buf;

    if (remote == NULL) {
        buf = server->buf;
    } else {
        buf = remote->buf;
    }

    ssize_t r = recv(server->fd, buf, BUF_SIZE, 0);

    if (r == 0) {
        // connection closed
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    } else if (r < 0) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            // no data
            // continue to wait for recv
            return;
        } else {
            ERROR("server_recv_cb_recv");
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    while (1) {
        // local socks5 server
        if (server->stage == 5) {
            if (remote == NULL) {
                LOGE("invalid remote.");
                close_and_free_server(EV_A_ server);
                return;
            }

            // insert shadowsocks header
            if (!remote->direct) {
                remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r,
                                         server->e_ctx);

                if (remote->buf == NULL) {
                    LOGE("invalid password or cipher");
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }
            }

            if (!remote->send_ctx->connected) {
                remote->buf_idx = 0;
                remote->buf_len = r;

                if (!fast_open || remote->direct) {
                    // connecting, wait until connected
                    connect(remote->fd, remote->addr_info->ai_addr,
                            remote->addr_info->ai_addrlen);

                    // wait on remote connected event
                    ev_io_stop(EV_A_ & server_recv_ctx->io);
                    ev_io_start(EV_A_ & remote->send_ctx->io);
                    ev_timer_start(EV_A_ & remote->send_ctx->watcher);
                } else {
#ifdef TCP_FASTOPEN
                    int s = sendto(remote->fd, remote->buf, r, MSG_FASTOPEN,
                                   remote->addr_info->ai_addr,
                                   remote->addr_info->ai_addrlen);
                    if (s == -1) {
                        if (errno == EINPROGRESS) {
                            // in progress, wait until connected
                            remote->buf_idx = 0;
                            remote->buf_len = r;
                            ev_io_stop(EV_A_ & server_recv_ctx->io);
                            ev_io_start(EV_A_ & remote->send_ctx->io);
                            return;
                        } else {
                            ERROR("sendto");
                            if (errno == ENOTCONN) {
                                LOGE(
                                    "fast open is not supported on this platform");
                                // just turn it off
                                fast_open = 0;
                            }
                            close_and_free_remote(EV_A_ remote);
                            close_and_free_server(EV_A_ server);
                            return;
                        }
                    } else if (s < r) {
                        remote->buf_len = r - s;
                        remote->buf_idx = s;
                    }

                    // Just connected
                    remote->send_ctx->connected = 1;
                    ev_timer_stop(EV_A_ & remote->send_ctx->watcher);
                    ev_io_start(EV_A_ & remote->recv_ctx->io);
#else
                    // if TCP_FASTOPEN is not defined, fast_open will always be 0
                    LOGE("can't come here");
                    exit(1);
#endif
                }
            } else {
                int s = send(remote->fd, remote->buf, r, 0);
                if (s == -1) {
                    if (errno == EAGAIN || errno == EWOULDBLOCK) {
                        // no data, wait for send
                        remote->buf_idx = 0;
                        remote->buf_len = r;
                        ev_io_stop(EV_A_ & server_recv_ctx->io);
                        ev_io_start(EV_A_ & remote->send_ctx->io);
                        return;
                    } else {
                        ERROR("server_recv_cb_send");
                        close_and_free_remote(EV_A_ remote);
                        close_and_free_server(EV_A_ server);
                        return;
                    }
                } else if (s < r) {
                    remote->buf_len = r - s;
                    remote->buf_idx = s;
                    ev_io_stop(EV_A_ & server_recv_ctx->io);
                    ev_io_start(EV_A_ & remote->send_ctx->io);
                    return;
                }
            }

            // all processed
            return;
        } else if (server->stage == 0) {
            struct method_select_response response;
            response.ver = SVERSION;
            response.method = 0;
            char *send_buf = (char *)&response;
            send(server->fd, send_buf, sizeof(response), 0);
            server->stage = 1;
            return;
        } else if (server->stage == 1) {
            struct socks5_request *request = (struct socks5_request *)buf;

            struct sockaddr_in sock_addr;
            memset(&sock_addr, 0, sizeof(sock_addr));

            int udp_assc = 0;

            if (udprelay && request->cmd == 3) {
                udp_assc = 1;
                socklen_t addr_len = sizeof(sock_addr);
                getsockname(server->fd, (struct sockaddr *)&sock_addr,
                            &addr_len);
                if (verbose) {
                    LOGD("udp assc request accepted.");
                }
            } else if (request->cmd != 1) {
                LOGE("unsupported cmd: %d", request->cmd);
                struct socks5_response response;
                response.ver = SVERSION;
                response.rep = CMD_NOT_SUPPORTED;
                response.rsv = 0;
                response.atyp = 1;
                char *send_buf = (char *)&response;
                send(server->fd, send_buf, 4, 0);
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            } else {
                char *ss_addr_to_send = malloc(BUF_SIZE);
                ssize_t addr_len = 0;
                ss_addr_to_send[addr_len++] = request->atyp;
                char host[256], port[16];

                // get remote addr and port
                if (request->atyp == 1) {
                    // IP V4
                    size_t in_addr_len = sizeof(struct in_addr);
                    memcpy(ss_addr_to_send + addr_len, buf + 4, in_addr_len +
                           2);
                    addr_len += in_addr_len + 2;

                    if (acl || verbose) {
                        uint16_t p =
                            ntohs(*(uint16_t *)(buf + 4 + in_addr_len));
                        inet_ntop(AF_INET, (const void *)(buf + 4),
                                  host, INET_ADDRSTRLEN);
                        sprintf(port, "%d", p);
                    }
                } else if (request->atyp == 3) {
                    // Domain name
                    uint8_t name_len = *(uint8_t *)(buf + 4);
                    ss_addr_to_send[addr_len++] = name_len;
                    memcpy(ss_addr_to_send + addr_len, buf + 4 + 1, name_len +
                           2);
                    addr_len += name_len + 2;

                    if (acl || verbose) {
                        uint16_t p =
                            ntohs(*(uint16_t *)(buf + 4 + 1 + name_len));
                        memcpy(host, buf + 4 + 1, name_len);
                        host[name_len] = '\0';
                        sprintf(port, "%d", p);
                    }
                } else if (request->atyp == 4) {
                    // IP V6
                    size_t in6_addr_len = sizeof(struct in6_addr);
                    memcpy(ss_addr_to_send + addr_len, buf + 4, in6_addr_len +
                           2);
                    addr_len += in6_addr_len + 2;

                    if (acl || verbose) {
                        uint16_t p =
                            ntohs(*(uint16_t *)(buf + 4 + in6_addr_len));
                        inet_ntop(AF_INET6, (const void *)(buf + 4),
                                  host, INET6_ADDRSTRLEN);
                        sprintf(port, "%d", p);
                    }
                } else {
                    LOGE("unsupported addrtype: %d", request->atyp);
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }

                server->stage = 5;

                r -= (3 + addr_len);
                buf += (3 + addr_len);

                if (verbose) {
                    LOGD("connect to %s:%s", host, port);
                }

                if ((acl && request->atyp == 1 && acl_contains_ip(host))
                    || (acl && request->atyp == 3 &&
                        acl_contains_domain(host))) {
                    remote = connect_to_remote(server->listener, host, port);
                    remote->direct = 1;
                    if (verbose) {
                        LOGD("bypass %s:%s", host, port);
                    }
                } else {
                    remote = connect_to_remote(server->listener, NULL, NULL);
                }

                if (remote == NULL) {
                    LOGE("invalid remote addr.");
                    close_and_free_server(EV_A_ server);
                    return;
                }

                if (!remote->direct) {
                    memcpy(remote->buf, ss_addr_to_send, addr_len);
                    if (r > 0) {
                        memcpy(remote->buf + addr_len, buf, r);
                    }
                    r += addr_len;
                } else {
                    if (r > 0) {
                        memcpy(remote->buf, buf, r);
                    }
                }

                server->remote = remote;
                remote->server = server;
            }

            // Fake reply
            struct socks5_response response;
            response.ver = SVERSION;
            response.rep = 0;
            response.rsv = 0;
            response.atyp = 1;

            memcpy(server->buf, &response, sizeof(struct socks5_response));
            memcpy(server->buf + sizeof(struct socks5_response),
                   &sock_addr.sin_addr, sizeof(sock_addr.sin_addr));
            memcpy(server->buf + sizeof(struct socks5_response) +
                   sizeof(sock_addr.sin_addr),
                   &sock_addr.sin_port, sizeof(sock_addr.sin_port));

            int reply_size = sizeof(struct socks5_response) +
                             sizeof(sock_addr.sin_addr) +
                             sizeof(sock_addr.sin_port);
            int s = send(server->fd, server->buf, reply_size, 0);
            if (s < reply_size) {
                LOGE("failed to send fake reply.");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            if (udp_assc) {
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }
        }
    }
}
Esempio n. 6
0
static void ev_bomb(EV_P_ ev_timer * w,int revents)
{
    lwqq_puts("boom!!");
    ev_timer_stop(loop,w);
    ev_break(loop,EVBREAK_ALL);
}
Esempio n. 7
0
F_NONNULL
static void mon_write_cb(struct ev_loop* loop, struct ev_io* io, const int revents V_UNUSED) {
    dmn_assert(loop); dmn_assert(io);
    dmn_assert(revents == EV_WRITE);

    http_events_t* md = (http_events_t*)io->data;

    dmn_assert(md);
    dmn_assert(md->hstate == HTTP_STATE_WRITING);
    dmn_assert(!ev_is_active(md->read_watcher));
    dmn_assert(ev_is_active(md->write_watcher));
    dmn_assert(ev_is_active(md->timeout_watcher));
    dmn_assert(md->sock > -1);

    int sock = md->sock;
    if(likely(!md->already_connected)) {
        // nonblocking connect() just finished, need to check status
        int so_error = 0;
        unsigned int so_error_len = sizeof(so_error);
        (void)getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &so_error_len);
        if(unlikely(so_error)) {
            switch(so_error) {
                case EPIPE:
                case ECONNREFUSED:
                case ETIMEDOUT:
                case EHOSTUNREACH:
                case EHOSTDOWN:
                case ENETUNREACH:
                    break;
                default:
                    log_err("plugin_http_status: Failed to connect() monitoring socket to remote server, possible local problem: %s", logf_errnum(so_error));
            }

            log_debug("plugin_http_status: State poll of %s failed quickly: %s", md->smgr->desc, logf_errnum(so_error));
            close(sock); md->sock = -1;
            ev_io_stop(loop, md->write_watcher);
            ev_timer_stop(loop, md->timeout_watcher);
            md->hstate = HTTP_STATE_WAITING;
            gdnsd_mon_state_updater(md->smgr, false);
            return;
        }
        md->already_connected = true;
    }

    const unsigned to_send = md->http_svc->req_data_len - md->done;
    const int sent = send(sock, md->http_svc->req_data + md->done, md->http_svc->req_data_len, 0);
    if(unlikely(sent == -1)) {
        switch(errno) {
            case EAGAIN:
            case EINTR:
                return;
            case ENOTCONN:
            case ECONNRESET:
            case ETIMEDOUT:
            case EHOSTUNREACH:
            case ENETUNREACH:
            case EPIPE:
                break;
            default:
                log_err("plugin_http_status: write() to monitoring socket failed, possible local problem: %s", logf_errno());
        }
        shutdown(sock, SHUT_RDWR);
        close(sock);
        md->sock = -1;
        ev_io_stop(loop, md->write_watcher);
        ev_timer_stop(loop, md->timeout_watcher);
        md->hstate = HTTP_STATE_WAITING;
        gdnsd_mon_state_updater(md->smgr, false);
    }
    if(unlikely(sent != (signed)to_send)) {
        md->done += sent;
        return;
    }

    md->done = 0;
    md->hstate = HTTP_STATE_READING;
    ev_io_stop(loop, md->write_watcher);
    ev_io_set(md->read_watcher, sock, EV_READ);
    ev_io_start(loop, md->read_watcher);
}
Esempio n. 8
0
static void remote_send_cb(EV_P_ ev_io *w, int revents)
{
    struct remote_ctx *remote_send_ctx = (struct remote_ctx *)w;
    struct remote *remote = remote_send_ctx->remote;
    struct server *server = remote->server;

    if (!remote_send_ctx->connected) {

        struct sockaddr_storage addr;
        socklen_t len = sizeof addr;
        int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
        if (r == 0) {
            remote_send_ctx->connected = 1;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_timer_stop(EV_A_ & remote_send_ctx->watcher);

            // send destaddr
            char *ss_addr_to_send = malloc(BUF_SIZE);
            ssize_t addr_len = 0;
            if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                ss_addr_to_send[addr_len++] = 4;          //Type 4 is IPv6 address

                size_t in_addr_len = sizeof(struct in6_addr);
                memcpy(ss_addr_to_send + addr_len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_addr),
                       in_addr_len);
                addr_len += in_addr_len;
                memcpy(ss_addr_to_send + addr_len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_port),
                       2);
            } else {                             //IPv4
                ss_addr_to_send[addr_len++] = 1; //Type 1 is IPv4 address

                size_t in_addr_len = sizeof(struct in_addr);
                memcpy(ss_addr_to_send + addr_len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_addr,
                       in_addr_len);
                addr_len += in_addr_len;
                memcpy(ss_addr_to_send + addr_len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_port,
                       2);
            }
            addr_len += 2;
            ss_addr_to_send = ss_encrypt(BUF_SIZE, ss_addr_to_send, &addr_len,
                                         server->e_ctx);
            if (ss_addr_to_send == NULL) {
                LOGE("invalid password or cipher");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            int s = send(remote->fd, ss_addr_to_send, addr_len, 0);
            free(ss_addr_to_send);

            if (s < addr_len) {
                LOGE("failed to send remote addr.");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
            }

            ev_io_start(EV_A_ & server->recv_ctx->io);
            ev_io_start(EV_A_ & remote->recv_ctx->io);

            return;
        } else {
            ERROR("getpeername");
            // not connected
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    } else {
        if (remote->buf_len == 0) {
            // close and free
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        } else {
            // has data to send
            ssize_t s = send(remote->fd, remote->buf + remote->buf_idx,
                             remote->buf_len, 0);
            if (s < 0) {
                if (errno != EAGAIN && errno != EWOULDBLOCK) {
                    ERROR("send");
                    // close and free
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                }
                return;
            } else if (s < remote->buf_len) {
                // partly sent, move memory, wait for the next time to send
                remote->buf_len -= s;
                remote->buf_idx += s;
                return;
            } else {
                // all sent out, wait for reading
                remote->buf_len = 0;
                remote->buf_idx = 0;
                ev_io_stop(EV_A_ & remote_send_ctx->io);
                if (server != NULL) {
                    ev_io_start(EV_A_ & server->recv_ctx->io);
                } else {
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }
            }
        }

    }
}
Esempio n. 9
0
static void server_recv_cb (EV_P_ ev_io *w, int revents)
{
    struct server_ctx *server_recv_ctx = (struct server_ctx *)w;
    struct server *server = server_recv_ctx->server;
    struct remote *remote = server->remote;

    if (remote == NULL)
    {
        close_and_free_server(EV_A_ server);
        return;
    }

    ssize_t r = recv(server->fd, remote->buf, BUF_SIZE, 0);

    if (r == 0)
    {
        // connection closed
        remote->buf_len = 0;
        remote->buf_idx = 0;
        close_and_free_server(EV_A_ server);
        if (remote != NULL)
        {
            ev_io_start(EV_A_ &remote->send_ctx->io);
        }
        return;
    }
    else if(r < 0)
    {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
        {
            // no data
            // continue to wait for recv
            return;
        }
        else
        {
            ERROR("server recv");
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    // local socks5 server
    if (server->stage == 5)
    {
        if (fast_open && !remote->send_ctx->connected)
        {
            char *buf = malloc(r + server->addr_len);
            memcpy(buf, server->addr_to_send, server->addr_len);
            memcpy(buf + server->addr_len, remote->buf, r);
            r += server->addr_len;
            free(remote->buf);
            remote->buf = buf;
        }
        remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r, server->e_ctx);
        if (remote->buf == NULL)
        {
            LOGE("invalid password or cipher");
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
        int s;
        if (fast_open && !remote->send_ctx->connected)
        {
#ifdef TCP_FASTOPEN
            s = sendto(remote->fd, remote->buf, r, MSG_FASTOPEN,
                       remote_res->ai_addr, remote_res->ai_addrlen);
            if (s == -1)
            {
                if (errno == EINPROGRESS)
                {
                    // in progress, wait until connected
                    remote->buf_len = r;
                    remote->buf_idx = 0;
                    ev_io_stop(EV_A_ &server_recv_ctx->io);
                    ev_io_start(EV_A_ &remote->send_ctx->io);
                    return;
                }
                else
                {
                    ERROR("sendto");
                    if (errno == ENOTCONN)
                    {
                        LOGE("fast open is not supported on this platform");
                        // just turn it off
                        fast_open = 0;
                    }
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }
            }
            remote->send_ctx->connected = 1;
            ev_timer_stop(EV_A_ &remote->send_ctx->watcher);
            ev_io_start(EV_A_ &remote->recv_ctx->io);
#else
            // if TCP_FASTOPEN is not defined, fast_open will always be 0
            LOGE("can't come here");
            exit(1);
#endif
        }
        else
        {
            s = send(remote->fd, remote->buf, r, 0);
        }
        if(s == -1)
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
                // no data, wait for send
                remote->buf_len = r;
                remote->buf_idx = 0;
                ev_io_stop(EV_A_ &server_recv_ctx->io);
                ev_io_start(EV_A_ &remote->send_ctx->io);
                return;
            }
            else
            {
                ERROR("send");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }
        }
        else if(s < r)
        {
            remote->buf_len = r - s;
            remote->buf_idx = s;
            ev_io_stop(EV_A_ &server_recv_ctx->io);
            ev_io_start(EV_A_ &remote->send_ctx->io);
            return;
        }
    }
    else if (server->stage == 0)
    {
        struct method_select_response response;
        response.ver = SVERSION;
        response.method = 0;
        char *send_buf = (char *)&response;
        send(server->fd, send_buf, sizeof(response), 0);
        server->stage = 1;
        return;
    }
    else if (server->stage == 1)
    {
        struct socks5_request *request = (struct socks5_request *)remote->buf;

        struct sockaddr_in sock_addr;
        memset(&sock_addr, 0, sizeof(sock_addr));

        if (udprelay && request->cmd == 3)
        {
            socklen_t addr_len = sizeof(sock_addr);
            getsockname(server->fd, (struct sockaddr *)&sock_addr,
                        &addr_len);
            if (verbose)
            {
                LOGD("udp assc request accepted.");
            }
        }
        else if (request->cmd != 1)
        {
            LOGE("unsupported cmd: %d", request->cmd);
            struct socks5_response response;
            response.ver = SVERSION;
            response.rep = CMD_NOT_SUPPORTED;
            response.rsv = 0;
            response.atyp = 1;
            char *send_buf = (char *)&response;
            send(server->fd, send_buf, 4, 0);
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
        else
        {
            char *ss_addr_to_send = malloc(BUF_SIZE);
            ssize_t addr_len = 0;
            ss_addr_to_send[addr_len++] = request->atyp;

            // get remote addr and port
            if (request->atyp == 1)
            {
                // IP V4
                size_t in_addr_len = sizeof(struct in_addr);
                memcpy(ss_addr_to_send + addr_len, remote->buf + 4, in_addr_len + 2);
                addr_len += in_addr_len + 2;

                if (verbose)
                {
                    char host[INET_ADDRSTRLEN];
                    uint16_t port = ntohs(*(uint16_t *)(remote->buf + 4 + in_addr_len));
                    inet_ntop(AF_INET, (const void *)(remote->buf + 4),
                              host, INET_ADDRSTRLEN);
                    LOGD("connect to %s:%d", host, port);
                }

            }
            else if (request->atyp == 3)
            {
                // Domain name
                uint8_t name_len = *(uint8_t *)(remote->buf + 4);
                ss_addr_to_send[addr_len++] = name_len;
                memcpy(ss_addr_to_send + addr_len, remote->buf + 4 + 1, name_len + 2);
                addr_len += name_len + 2;

                if (verbose)
                {
                    char host[256];
                    uint16_t port = ntohs(*(uint16_t *)(remote->buf + 4 + 1 + name_len));
                    memcpy(host, remote->buf + 4 + 1, name_len);
                    host[name_len] = '\0';
                    LOGD("connect to %s:%d", host, port);
                }

            }
            else if (request->atyp == 4)
            {
                // IP V6
                size_t in6_addr_len = sizeof(struct in6_addr);
                memcpy(ss_addr_to_send + addr_len, remote->buf + 4, in6_addr_len + 2);
                addr_len += in6_addr_len + 2;

                if (verbose)
                {
                    char host[INET6_ADDRSTRLEN];
                    uint16_t port = ntohs(*(uint16_t *)(remote->buf + 4 + in6_addr_len));
                    inet_ntop(AF_INET6, (const void *)(remote->buf + 4),
                              host, INET6_ADDRSTRLEN);
                    LOGD("connect to %s:%d", host, port);
                }

            }
            else
            {
                LOGE("unsupported addrtype: %d", request->atyp);
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            if (!fast_open)
            {
                ss_addr_to_send = ss_encrypt(BUF_SIZE, ss_addr_to_send, &addr_len, server->e_ctx);
                if (ss_addr_to_send == NULL)
                {
                    LOGE("invalid password or cipher");
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }
                int s = send(remote->fd, ss_addr_to_send, addr_len, 0);
                free(ss_addr_to_send);

                if (s < addr_len)
                {
                    LOGE("failed to send remote addr.");
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }
                ev_io_start(EV_A_ &remote->recv_ctx->io);
            }
            else
            {
                if (addr_len > BUF_SIZE)
                {
                    LOGE("addr_len is too large");
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }
                server->addr_to_send = ss_addr_to_send;
                server->addr_len = addr_len;
            }

            server->stage = 5;
        }

        // Fake reply
        struct socks5_response response;
        response.ver = SVERSION;
        response.rep = 0;
        response.rsv = 0;
        response.atyp = 1;

        memcpy(server->buf, &response, sizeof(struct socks5_response));
        memcpy(server->buf + sizeof(struct socks5_response), &sock_addr.sin_addr, sizeof(sock_addr.sin_addr));
        memcpy(server->buf + sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr),
               &sock_addr.sin_port, sizeof(sock_addr.sin_port));

        int reply_size = sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port);
        int s = send(server->fd, server->buf, reply_size, 0);
        if (s < reply_size)
        {
            LOGE("failed to send fake reply.");
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }

        if (request->cmd == 3)
        {
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }
}
Esempio n. 10
0
static void
recv_handler(struct ev_loop *loop, struct ev_io *watcher, int events) {
    //debug("recv_handler");

    size_t i;

    domain_t *domain = (domain_t *) watcher;
    ev_io_stop(loop, &domain->io);
    ev_timer_stop(loop, &domain->tw);


    //debug("recv_header %s -- data buffer:%p; data len: %d", domain->domain, domain->data.buffer + domain->data.len, domain->data.len);


    ssize_t len = readn(domain->io.fd, domain->data.buffer + domain->data.len, sizeof (domain->data.buffer) - domain->data.len);

    if (len <= 0) {
        if (EAGAIN == errno) { // сокет занят буфер кончился и прочее
            //err_ret("error read socket %s: ", domain->domain);
            ev_io_start(loop, &domain->io);
            ev_timer_start(loop, &domain->tw);
            return;
        } else { // жесткая ошибка
            err_ret("error read socket %s: ", domain->domain);
            free_domain(domain);
            return;
        }
    } else {

        domain->data.len += len;

        int pret = parse_response(domain);

        debug("parse_response %s:%d", domain->domain, pret);

        if (pret > 0) {

            switch (domain->http.status) {
                case 301:
                case 302:
                {

                    for (i = 0; i != domain->http.num_headers; ++i) {
                        if (NULL != memmem(domain->http.headers[i].name, domain->http.headers[i].name_len, "Location", 8)) {
                            follow_location(domain, domain->http.headers[i].value, domain->http.headers[i].value_len);
                            return;
                            //break;
                        }
                    }
                    break;
                }

                case 200:
                {
                    if (true == parse_body(&domain->data.buffer[pret], domain->data.len - pret)) {
                        success_checked(domain);
                    } else {

                        if (++domain->index_search < (sizeof (search_path) / sizeof (search_path[0]))) {
                            //ares_gethostbyname(domain->options->ares.channel, domain->domain, AF_INET, ev_ares_dns_callback, (void *) domain);
                            http_request(domain);
                            return;
                        }
                    }
                    break;
                }


            }
        } else {
            error_parse(domain);
        }
    }


    debug("-- %s %d checked", domain->domain, domain->http.status);
    free_domain(domain);
}
Esempio n. 11
0
/** Callback function to remove worker from application */
void wr_app_wrk_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
  LOG_FUNCTION
  wr_app_t* app = (wr_app_t*) w->data;
  wr_wkr_t* worker;

  ev_timer_stop(loop, &app->t_remove);

  // Following variable helps in removing unncecessary call to wr_app_wrk_remove_cb
  int forecasted_count=app->wkr_que->q_count;
  // Its a known bug - At any time app->active_worker should equals to app->wkr_que->q_count
  // Scenario: We are forking new worker due to high load and also increasing active worker count.
  // It took some time to get register with Head, and actual queue count incremented after Head
  // register the newly created worker. Now, mean while load goes down, and we are ready to remove the
  // worker.
  // Now there could be two things,
  // First, newly created worker failed to successful registration.
  // Second, newly created worker took little extra time for successful registration.
  // In both case active worker indicate wrong number and we try to remove the worker which does not exists for Head.
  // To overcome this, we would adjust high load ratio when new worker is added, adjust low load ratio
  // when new worker is actually get registered with Head also, we reset active worker with
  // application worker queue count, whenever worker is actually removed.
  // TODO: Handle above bug properly.
  LOG_DEBUG(DEBUG,"Pending_wkr = %d, app->wkr_que->q_count = %d",
            app->pending_wkr, app->wkr_que->q_count);
  if(app->wkr_que->q_count > app->conf->min_worker) {
    char cmd[WR_LONG_LONG_STR_LEN];
    char pid_list[WR_LONG_LONG_STR_LEN], pid_c[WR_SHORT_STR_LEN];
    int i,index;
    i = 0;
    index = (app->wkr_que->q_front + i) % app->wkr_que->q_max_size;
    wr_wkr_t *tmp_worker = (wr_wkr_t*)app->wkr_que->q_elements[index];
    
    
    // Get pid of the worker consuming more resident memory
#ifdef __APPLE__
    //sprintf(cmd,"ps -o pid -m -p %s | head -n2 | tail -n1 | cut -c-6 > %s",pid_list, WR_HIGH_RSS_PID_FILE);
	/* TODO: when any shell command is executed using system(), process goes into wait state. It is 
	 observed on only Mac. When tried calling syste() at various interval like after port binding,
	 controller initialization, forking required worker, daemonizing, activating event loop etc, in all 
	 cases it was working fine. But after dynamically created worker added into service, call to system()
	 goes into infinite wait.	   
	 In this case we would simply pick the first worker from queue and remove it.
	 */
    FILE *wfp = fopen(WR_HIGH_RSS_PID_FILE, "w");
    if(wfp) {
      fprintf(wfp,"%d", tmp_worker->pid); 
      fclose(wfp);
	}
#else
    sprintf(pid_c,"%d",tmp_worker->pid);
    strcpy(pid_list, pid_c);
    i++;
    for(;i < app->wkr_que->q_count ; i++) {
      index = (app->wkr_que->q_front + i) % app->wkr_que->q_max_size;
      tmp_worker = (wr_wkr_t*)app->wkr_que->q_elements[index];
      sprintf(pid_c,",%d", tmp_worker->pid);
      strcat(pid_list, pid_c);
    }
    sprintf(cmd,"ps -o pid --sort=rss -p %s | tail -n1 | cut -c-6 > %s",pid_list, WR_HIGH_RSS_PID_FILE);
    LOG_DEBUG(DEBUG,"Formed command to remove worker is %s",cmd);
    system(cmd);
#endif
	
    // Read pid from file
    FILE *fp = fopen(WR_HIGH_RSS_PID_FILE, "r");
    if(fp) {
      unsigned pid = 0;
      fscanf(fp, "%u", &pid);
      fclose(fp);
      remove(WR_HIGH_RSS_PID_FILE);
      int flag = 1;

      // Check for worker in list of free workers. If found remove it.
      if(app->free_wkr_que->q_count > 0) {
        LOG_DEBUG(DEBUG,", pid = %d find in free worker", pid);
        //int i, index;
        for( i = 0; i < app->free_wkr_que->q_count ; i++) {
          index = (app->free_wkr_que->q_front + i) % app->free_wkr_que->q_max_size;
          tmp_worker = (wr_wkr_t*)app->free_wkr_que->q_elements[index];
          if(tmp_worker->pid == pid) {
            LOG_DEBUG(DEBUG,"Removing from free worker id=%d", tmp_worker->id);
            forecasted_count--;
            wr_wkr_remove(tmp_worker, 1);
            LOG_DEBUG(DEBUG,"Worker removed from free worker.");
            flag = 0;
            break;
          }
        }
      }

      // Check for worker in the list of all the worker. If found mark it as in-active.
      // In-active worker will be removed once current request is processed.
      if(flag && app->wkr_que->q_count > 0) {
        LOG_DEBUG(DEBUG,"pid = %d find in active worker", pid);
        //int i, index;
        for( i = 0; i < app->wkr_que->q_count ; i++) {
          index = (app->wkr_que->q_front + i) % app->wkr_que->q_max_size;
          tmp_worker = (wr_wkr_t*)app->wkr_que->q_elements[index];
          if(tmp_worker->pid == pid) {
            forecasted_count--;
            LOG_DEBUG(DEBUG,"Remove active status id = %d", tmp_worker->id);
            if(tmp_worker->state & WR_WKR_ACTIVE)
              tmp_worker->state -= WR_WKR_ACTIVE;
            break;
          }
        }
      }
    }
  }

  if(forecasted_count > app->conf->min_worker) {
    ev_timer_again(loop, &app->t_remove);
  }
}
Esempio n. 12
0
static void
remote_send_cb(EV_P_ ev_io *w, int revents)
{
    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;
    remote_t *remote              = remote_send_ctx->remote;
    server_t *server              = remote->server;

    if (!remote_send_ctx->connected) {
        struct sockaddr_storage addr;
        socklen_t len = sizeof addr;

        int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
        if (r == 0) {
            remote_send_ctx->connected = 1;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_timer_stop(EV_A_ & remote_send_ctx->watcher);

            buffer_t ss_addr_to_send;
            buffer_t *abuf = &ss_addr_to_send;
            balloc(abuf, BUF_SIZE);

            ss_addr_t *sa = &server->destaddr;
            struct cork_ip ip;
            if (cork_ip_init(&ip, sa->host) != -1) {
                if (ip.version == 4) {
                    // send as IPv4
                    struct in_addr host;
                    int host_len = sizeof(struct in_addr);

                    if (dns_pton(AF_INET, sa->host, &host) == -1) {
                        FATAL("IP parser error");
                    }
                    abuf->array[abuf->len++] = 1;
                    memcpy(abuf->array + abuf->len, &host, host_len);
                    abuf->len += host_len;
                } else if (ip.version == 6) {
                    // send as IPv6
                    struct in6_addr host;
                    int host_len = sizeof(struct in6_addr);

                    if (dns_pton(AF_INET6, sa->host, &host) == -1) {
                        FATAL("IP parser error");
                    }
                    abuf->array[abuf->len++] = 4;
                    memcpy(abuf->array + abuf->len, &host, host_len);
                    abuf->len += host_len;
                } else {
                    FATAL("IP parser error");
                }
            } else {
                // send as domain
                int host_len = strlen(sa->host);

                abuf->array[abuf->len++] = 3;
                abuf->array[abuf->len++] = host_len;
                memcpy(abuf->array + abuf->len, sa->host, host_len);
                abuf->len += host_len;
            }

            uint16_t port = htons(atoi(sa->port));
            memcpy(abuf->array + abuf->len, &port, 2);
            abuf->len += 2;

            if (auth) {
                abuf->array[0] |= ONETIMEAUTH_FLAG;
                ss_onetimeauth(abuf, server->e_ctx->evp.iv, BUF_SIZE);
            }

            int err = ss_encrypt(abuf, server->e_ctx, BUF_SIZE);
            if (err) {
                bfree(abuf);
                LOGE("invalid password or cipher");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            int s = send(remote->fd, abuf->array, abuf->len, 0);

            bfree(abuf);

            if (s < abuf->len) {
                LOGE("failed to send addr");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            ev_io_start(EV_A_ & remote->recv_ctx->io);
            ev_io_start(EV_A_ & server->recv_ctx->io);

            return;
        } else {
            ERROR("getpeername");
            // not connected
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    } else {
        if (remote->buf->len == 0) {
            // close and free
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        } else {
            // has data to send
            ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx,
                             remote->buf->len, 0);
            if (s == -1) {
                if (errno != EAGAIN && errno != EWOULDBLOCK) {
                    ERROR("send");
                    // close and free
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                }
                return;
            } else if (s < remote->buf->len) {
                // partly sent, move memory, wait for the next time to send
                remote->buf->len -= s;
                remote->buf->idx += s;
                return;
            } else {
                // all sent out, wait for reading
                remote->buf->len = 0;
                remote->buf->idx = 0;
                ev_io_stop(EV_A_ & remote_send_ctx->io);
                ev_io_start(EV_A_ & server->recv_ctx->io);
            }
        }
    }
}
Esempio n. 13
0
static int NIO_Selector_run(struct NIO_Selector *selector, VALUE timeout)
{
    int result;
    selector->selecting = 1;

#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) || defined(HAVE_RB_THREAD_ALONE)
    /* Implement the optional timeout (if any) as a ev_timer */
    if(timeout != Qnil) {
        /* It seems libev is not a fan of timers being zero, so fudge a little */
        selector->timer.repeat = NUM2DBL(timeout) + 0.0001;
        ev_timer_again(selector->ev_loop, &selector->timer);
    } else {
        ev_timer_stop(selector->ev_loop, &selector->timer);
    }
#else
    /* Store when we started the loop so we can calculate the timeout */
    ev_tstamp started_at = ev_now(selector->ev_loop);
#endif

#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
    /* libev is patched to release the GIL when it makes its system call */
    ev_loop(selector->ev_loop, EVLOOP_ONESHOT);
#elif defined(HAVE_RB_THREAD_ALONE)
    /* If we're the only thread we can make a blocking system call */
    if(rb_thread_alone()) {
#else
    /* If we don't have rb_thread_alone() we can't block */
    if(0) {
#endif /* defined(HAVE_RB_THREAD_BLOCKING_REGION) */

#if !defined(HAVE_RB_THREAD_BLOCKING_REGION) && !defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
        TRAP_BEG;
        ev_loop(selector->ev_loop, EVLOOP_ONESHOT);
        TRAP_END;
    } else {
        /* We need to busy wait as not to stall the green thread scheduler
           Ruby 1.8: just say no! :( */
        ev_timer_init(&selector->timer, NIO_Selector_timeout_callback, BUSYWAIT_INTERVAL, BUSYWAIT_INTERVAL);
        ev_timer_start(selector->ev_loop, &selector->timer);

        /* Loop until we receive events */
        while(selector->selecting && !selector->ready_count) {
            TRAP_BEG;
            ev_loop(selector->ev_loop, EVLOOP_ONESHOT);
            TRAP_END;

            /* Run the next green thread */
            rb_thread_schedule();

            /* Break if the timeout has elapsed */
            if(timeout != Qnil && ev_now(selector->ev_loop) - started_at >= NUM2DBL(timeout))
                break;
        }

        ev_timer_stop(selector->ev_loop, &selector->timer);
    }
#endif /* defined(HAVE_RB_THREAD_BLOCKING_REGION) */

    result = selector->ready_count;
    selector->selecting = selector->ready_count = 0;

    return result;
}

/* Wake the selector up from another thread */
static VALUE NIO_Selector_wakeup(VALUE self)
{
    struct NIO_Selector *selector;
    Data_Get_Struct(self, struct NIO_Selector, selector);

    if(selector->closed) {
        rb_raise(rb_eIOError, "selector is closed");
    }

    write(selector->wakeup_writer, "\0", 1);
    return Qnil;
}

/* Close the selector and free system resources */
static VALUE NIO_Selector_close(VALUE self)
{
    VALUE args[1] = {self};
    return NIO_Selector_synchronize(self, NIO_Selector_close_synchronized, args);
}
Esempio n. 14
0
void pc__channel_cleanup(pc_context_t *ctx)
{
    ev_timer_stop(ctx->cctx->loop, &ctx->cctx->timeout);
    pc_pool_destroy(ctx->cctx->pool);
    ctx->cctx = NULL;
}
Esempio n. 15
0
/******************************************************************************
 **函数名称: lws_libev_timer_stop
 **功    能: 停止计时器
 **输入参数:
 **     context: lws上下文
 **     timer: 计时器
 **输出参数: NONE
 **返    回: VOID
 **实现描述: 将计时器从libev loop中删除
 **注意事项:
 **作    者: # Qifeng.zou # 2015.12.10 #
 ******************************************************************************/
LWS_VISIBLE void lws_libev_timer_stop(struct lws_context *context, ev_timer *timer)
{
    ev_timer_stop(context->io_loop, timer);
}
Esempio n. 16
0
static void server_recv_cb(EV_P_ ev_io *w, int revents)
{
    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;
    server_t *server              = server_recv_ctx->server;
    remote_t *remote              = server->remote;
    buffer_t *buf;

    if (remote == NULL) {
        buf = server->buf;
    } else {
        buf = remote->buf;
    }

    ssize_t r;

    r = recv(server->fd, buf->array, BUF_SIZE, 0);

    if (r == 0) {
        // connection closed
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    } else if (r < 0) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            // no data
            // continue to wait for recv
            return;
        } else {
            ERROR("server_recv_cb_recv");
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    buf->len = r;

    while (1) {
        // local socks5 server
        if (server->stage == 5) {
            if (remote == NULL) {
                LOGE("invalid remote");
                close_and_free_server(EV_A_ server);
                return;
            }

            if (!remote->direct && remote->send_ctx->connected && auth) {
                ss_gen_hash(remote->buf, &remote->counter, server->e_ctx);
            }

            // insert shadowsocks header
            if (!remote->direct) {
                // SSR beg
                if (server->protocol_plugin) {
                    obfs_class *protocol_plugin = server->protocol_plugin;
                    if (protocol_plugin->client_pre_encrypt) {
                        remote->buf->len = protocol_plugin->client_pre_encrypt(server->protocol, &remote->buf->array, remote->buf->len, &remote->buf->capacity);
                    }
                }
                int err = ss_encrypt(remote->buf, server->e_ctx);

                if (err) {
                    LOGE("server invalid password or cipher");
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }

                if (server->obfs_plugin) {
                    obfs_class *obfs_plugin = server->obfs_plugin;
                    if (obfs_plugin->client_encode) {
                        remote->buf->len = obfs_plugin->client_encode(server->obfs, &remote->buf->array, remote->buf->len, &remote->buf->capacity);
                    }
                }
                // SSR end
#ifdef ANDROID
                tx += r;
#endif
            }

            if (!remote->send_ctx->connected) {
#ifdef ANDROID
                if (vpn) {
                    if (protect_socket(remote->fd) == -1) {
                        ERROR("protect_socket");
                        close_and_free_remote(EV_A_ remote);
                        close_and_free_server(EV_A_ server);
                        return;
                    }
                }
#endif

                remote->buf->idx = 0;

                if (!fast_open || remote->direct) {
                    // connecting, wait until connected
                    connect(remote->fd, (struct sockaddr *)&(remote->addr), remote->addr_len);

                    // wait on remote connected event
                    ev_io_stop(EV_A_ & server_recv_ctx->io);
                    ev_io_start(EV_A_ & remote->send_ctx->io);
                    ev_timer_start(EV_A_ & remote->send_ctx->watcher);
                } else {
#ifdef TCP_FASTOPEN
#ifdef __APPLE__
                    ((struct sockaddr_in*)&(remote->addr))->sin_len = sizeof(struct sockaddr_in);
                    sa_endpoints_t endpoints;
                    bzero((char*)&endpoints, sizeof(endpoints));
                    endpoints.sae_dstaddr = (struct sockaddr*)&(remote->addr);
                    endpoints.sae_dstaddrlen = remote->addr_len;

                    int s = connectx(remote->fd, &endpoints, SAE_ASSOCID_ANY,
                            CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
                            NULL, 0, NULL, NULL);
                    if (s == 0) {
                        s = send(remote->fd, remote->buf->array, remote->buf->len, 0);
                    }
#else
                    int s = sendto(remote->fd, remote->buf->array, remote->buf->len, MSG_FASTOPEN,
                                   (struct sockaddr *)&(remote->addr), remote->addr_len);
#endif
                    if (s == -1) {
                        if (errno == EINPROGRESS) {
                            // in progress, wait until connected
                            remote->buf->idx = 0;
                            ev_io_stop(EV_A_ & server_recv_ctx->io);
                            ev_io_start(EV_A_ & remote->send_ctx->io);
                            return;
                        } else {
                            ERROR("sendto");
                            if (errno == ENOTCONN) {
                                LOGE( "fast open is not supported on this platform");
                                // just turn it off
                                fast_open = 0;
                            }
                            close_and_free_remote(EV_A_ remote);
                            close_and_free_server(EV_A_ server);
                            return;
                        }
                    } else if (s <= remote->buf->len) {
                        remote->buf->len -= s;
                        remote->buf->idx  = s;
                    }

                    // Just connected
                    remote->send_ctx->connected = 1;
                    ev_timer_stop(EV_A_ & remote->send_ctx->watcher);
                    ev_io_start(EV_A_ & remote->recv_ctx->io);
#else
                    // if TCP_FASTOPEN is not defined, fast_open will always be 0
                    LOGE("can't come here");
                    exit(1);
#endif
                }
            } else {
                int s = send(remote->fd, remote->buf->array, remote->buf->len, 0);
                if (s == -1) {
                    if (errno == EAGAIN || errno == EWOULDBLOCK) {
                        // no data, wait for send
                        remote->buf->idx = 0;
                        ev_io_stop(EV_A_ & server_recv_ctx->io);
                        ev_io_start(EV_A_ & remote->send_ctx->io);
                        return;
                    } else {
                        ERROR("server_recv_cb_send");
                        close_and_free_remote(EV_A_ remote);
                        close_and_free_server(EV_A_ server);
                        return;
                    }
                } else if (s < remote->buf->len) {
                    remote->buf->len -= s;
                    remote->buf->idx  = s;
                    ev_io_stop(EV_A_ & server_recv_ctx->io);
                    ev_io_start(EV_A_ & remote->send_ctx->io);
                    return;
                }
            }

            // all processed
            return;
        } else if (server->stage == 0) {
            struct method_select_response response;
            response.ver    = SVERSION;
            response.method = 0;
            char *send_buf = (char *)&response;
            send(server->fd, send_buf, sizeof(response), 0);
            server->stage = 1;

            int off = (buf->array[1] & 0xff) + 2;
            if (buf->array[0] == 0x05 && off < buf->len) {
                memmove(buf->array, buf->array + off, buf->len - off);
                buf->len -= off;
                continue;
            }

            return;
        } else if (server->stage == 1) {
            struct socks5_request *request = (struct socks5_request *)buf->array;

            struct sockaddr_in sock_addr;
            memset(&sock_addr, 0, sizeof(sock_addr));

            int udp_assc = 0;

            if (mode != TCP_ONLY && request->cmd == 3) {
                udp_assc = 1;
                socklen_t addr_len = sizeof(sock_addr);
                getsockname(server->fd, (struct sockaddr *)&sock_addr,
                            &addr_len);
                if (verbose) {
                    LOGI("udp assc request accepted");
                }
            } else if (request->cmd != 1) {
                LOGE("unsupported cmd: %d", request->cmd);
                struct socks5_response response;
                response.ver  = SVERSION;
                response.rep  = CMD_NOT_SUPPORTED;
                response.rsv  = 0;
                response.atyp = 1;
                char *send_buf = (char *)&response;
                send(server->fd, send_buf, 4, 0);
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            } else {
                char host[256], port[16];

                buffer_t ss_addr_to_send;
                buffer_t *abuf = &ss_addr_to_send;
                balloc(abuf, BUF_SIZE);

                abuf->array[abuf->len++] = request->atyp;

                // get remote addr and port
                if (request->atyp == 1) {
                    // IP V4
                    size_t in_addr_len = sizeof(struct in_addr);
                    memcpy(abuf->array + abuf->len, buf->array + 4, in_addr_len + 2);
                    abuf->len += in_addr_len + 2;

                    if (acl || verbose) {
                        uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in_addr_len));
                        dns_ntop(AF_INET, (const void *)(buf->array + 4),
                                 host, INET_ADDRSTRLEN);
                        sprintf(port, "%d", p);
                    }
                } else if (request->atyp == 3) {
                    // Domain name
                    uint8_t name_len = *(uint8_t *)(buf->array + 4);
                    abuf->array[abuf->len++] = name_len;
                    memcpy(abuf->array + abuf->len, buf->array + 4 + 1, name_len + 2);
                    abuf->len += name_len + 2;

                    if (acl || verbose) {
                        uint16_t p =
                            ntohs(*(uint16_t *)(buf->array + 4 + 1 + name_len));
                        memcpy(host, buf->array + 4 + 1, name_len);
                        host[name_len] = '\0';
                        sprintf(port, "%d", p);
                    }
                } else if (request->atyp == 4) {
                    // IP V6
                    size_t in6_addr_len = sizeof(struct in6_addr);
                    memcpy(abuf->array + abuf->len, buf->array + 4, in6_addr_len + 2);
                    abuf->len += in6_addr_len + 2;

                    if (acl || verbose) {
                        uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in6_addr_len));
                        dns_ntop(AF_INET6, (const void *)(buf->array + 4),
                                 host, INET6_ADDRSTRLEN);
                        sprintf(port, "%d", p);
                    }
                } else {
                    bfree(abuf);
                    LOGE("unsupported addrtype: %d", request->atyp);
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                    return;
                }

                server->stage = 5;

                buf->len -= (3 + abuf->len);
                if (buf->len > 0) {
                    memmove(buf->array, buf->array + 3 + abuf->len, buf->len);
                }

                if (verbose) {
                    LOGI("connect to %s:%s", host, port);
                }

                if ((acl && (request->atyp == 1 || request->atyp == 4) && acl_match_ip(host))) {
                    if (verbose) {
                        LOGI("bypass %s:%s", host, port);
                    }
                    struct sockaddr_storage storage;
                    memset(&storage, 0, sizeof(struct sockaddr_storage));
                    if (get_sockaddr(host, port, &storage, 0) != -1) {
                        remote         = create_remote(server->listener, (struct sockaddr *)&storage);
                        remote->direct = 1;
                    }
                } else {
                    remote = create_remote(server->listener, NULL);
                }

                if (remote == NULL) {
                    bfree(abuf);
                    LOGE("invalid remote addr");
                    close_and_free_server(EV_A_ server);
                    return;
                }

                // SSR beg
                if (server->listener->list_obfs_global[remote->remote_index] == NULL && server->obfs_plugin) {
                    server->listener->list_obfs_global[remote->remote_index] = server->obfs_plugin->init_data();
                }
                if (server->listener->list_protocol_global[remote->remote_index] == NULL && server->protocol_plugin) {
                    server->listener->list_protocol_global[remote->remote_index] = server->protocol_plugin->init_data();
                }

                server_info _server_info;
                memset(&_server_info, 0, sizeof(server_info));
                strcpy(_server_info.host, inet_ntoa(((struct sockaddr_in*)&remote->addr)->sin_addr));
                _server_info.port = ((struct sockaddr_in*)&remote->addr)->sin_port;
                _server_info.port = _server_info.port >> 8 | _server_info.port << 8;
                _server_info.param = server->listener->obfs_param;
                _server_info.g_data = server->listener->list_obfs_global[remote->remote_index];
                _server_info.head_len = get_head_size(ss_addr_to_send.array, 320, 30);
                _server_info.iv = server->e_ctx->evp.iv;
                _server_info.iv_len = enc_get_iv_len();
                _server_info.key = enc_get_key();
                _server_info.key_len = enc_get_key_len();
                _server_info.tcp_mss = 1440;

                if (server->obfs_plugin)
                    server->obfs_plugin->set_server_info(server->obfs, &_server_info);

                _server_info.param = NULL;
                _server_info.g_data = server->listener->list_protocol_global[remote->remote_index];

                if (server->protocol_plugin)
                    server->protocol_plugin->set_server_info(server->protocol, &_server_info);
                // SSR end

                if (!remote->direct) {
                    if (auth) {
                        abuf->array[0] |= ONETIMEAUTH_FLAG;
                        ss_onetimeauth(abuf, server->e_ctx->evp.iv);
                    }

                    brealloc(remote->buf, buf->len + abuf->len, BUF_SIZE);
                    memcpy(remote->buf->array, abuf->array, abuf->len);
                    remote->buf->len = buf->len + abuf->len;

                    if (buf->len > 0) {
                        if (auth) {
                            ss_gen_hash(buf, &remote->counter, server->e_ctx);
                        }
                        memcpy(remote->buf->array + abuf->len, buf->array, buf->len);
                    }
                } else {
                    if (buf->len > 0) {
                        memcpy(remote->buf->array, buf->array, buf->len);
                        remote->buf->len = buf->len;
                    }
                }

                server->remote = remote;
                remote->server = server;

                bfree(abuf);
            }

            // Fake reply
            struct socks5_response response;
            response.ver  = SVERSION;
            response.rep  = 0;
            response.rsv  = 0;
            response.atyp = 1;

            memcpy(server->buf->array, &response, sizeof(struct socks5_response));
            memcpy(server->buf->array + sizeof(struct socks5_response),
                   &sock_addr.sin_addr, sizeof(sock_addr.sin_addr));
            memcpy(server->buf->array + sizeof(struct socks5_response) +
                   sizeof(sock_addr.sin_addr),
                   &sock_addr.sin_port, sizeof(sock_addr.sin_port));

            int reply_size = sizeof(struct socks5_response) +
                             sizeof(sock_addr.sin_addr) +
                             sizeof(sock_addr.sin_port);
            int s = send(server->fd, server->buf->array, reply_size, 0);
            if (s < reply_size) {
                LOGE("failed to send fake reply");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            if (udp_assc) {
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }
        }
    }
}
Esempio n. 17
0
void lwqq_async_timer_stop(LwqqAsyncTimerHandle timer)
{
    ev_timer_stop(ev_default, &timer->h);
}
Esempio n. 18
0
template<> void event_watcher<ev_timer>::stop() {
    /* TODO event shall be removed from timer_watchers */
    ev_timer_stop(this->self->loop, &this->watcher);
}
Esempio n. 19
0
/** Reads the response from worker, deserialize it, render it to the Request. */
static void wr_resp_len_read_cb(struct ev_loop *loop, struct ev_io *w, int revents) {
  LOG_FUNCTION
  wr_req_t* req = (wr_req_t*) w->data;
  wr_wkr_t *worker = req->wkr;
  ssize_t read;

  LOG_DEBUG(DEBUG,"Request %d",req->id);

  if(!(revents & EV_READ))
    return;

  read = recv(w->fd,
              req->resp_buf + req->bytes_received,
              WR_RESP_BUF_SIZE - req->bytes_received,
              0);

  if(read <= 0) {
    ev_io_stop(loop,w);
    LOG_ERROR(WARN,"Error reading response:%s",strerror(errno));
    worker->state += (WR_WKR_ERROR + WR_WKR_HANG);
    wr_ctl_free(worker->ctl);
    return;
  }

  req->bytes_received =+ read;
  //worker responding
  LOG_DEBUG(DEBUG,"Idle watcher reset for worker %d", worker->id);
  LOG_DEBUG(DEBUG,"bytes read = %d", req->bytes_received);

  scgi_t* scgi = scgi_parse(req->resp_buf, req->bytes_received);

  if(scgi) {
    ev_io_stop(loop,w);
    const char *value = scgi_header_value_get(scgi, SCGI_CONTENT_LENGTH);
    // Set response length
    if(value)
      req->resp_buf_len = atoi(value);
    else
      req->resp_buf_len = 0;
    
    // Set rsponse code
    value = scgi_header_value_get(scgi, RESP_CODE);
    if(value)
      req->resp_code = atoi(value);
    else
      req->resp_code = 0;
    
    // Set content length
    value = scgi_header_value_get(scgi, RESP_CONTENT_LENGTH);
    if(value)
      req->resp_body_len = atoi(value);
    else
      req->resp_body_len = 0;
    
    LOG_DEBUG(DEBUG,"resp_code = %d, content len = %d, resp len = %d",
              req->resp_code,
              req->resp_body_len,
              req->resp_buf_len);
    // Response length should be greater than 0
    if(req->resp_buf_len == 0) {
      //TODO: Render 500 Internal Error, close Request, allocate worker to next Request
      LOG_ERROR(WARN,"Got response len 0");
      ev_io_stop(loop,w);
      worker->state += (WR_WKR_ERROR + WR_WKR_HANG);
      wr_ctl_free(worker->ctl);
      return;
    }

    if(!req->conn_err && req->app && req->app->svr->conf->server->flag & WR_SVR_ACCESS_LOG) {
      wr_access_log(req);
    }

    scgi_free(req->scgi);
    req->scgi = NULL;

    req->bytes_received = scgi->body_length;
    LOG_DEBUG(DEBUG,"wr_resp_len_read_cb() bytes read = %d", req->bytes_received);
    if(req->bytes_received > 0 && !req->conn_err) {
      wr_conn_resp_body_add(req->conn, scgi->body, scgi->body_length);
    }

    scgi_free(scgi);

    // Check for response length
    if(req->resp_buf_len == req->bytes_received) {
      LOG_DEBUG(DEBUG,"Idle watcher stopped for worker %d", worker->id);
      // worker is done with current Request
      worker->req = NULL;
      req->using_wkr = FALSE;
      worker->state &= (~224);
      ev_timer_stop(worker->loop,&worker->t_wait);
      // Close Request once complete response read
      wr_wkr_release(req);
    } else {
      LOG_DEBUG(DEBUG,"wr_resp_len_read_cb() Request %d, read %d/%d",
                req->id,
                req->bytes_received,
                req->resp_buf_len);
      ev_io_init(w,wr_resp_read_cb, w->fd,EV_READ);
      ev_io_start(loop,w);
      wr_wait_watcher_start(worker);
    }
  }
}
Esempio n. 20
0
static void
server_recv_cb(EV_P_ ev_io *w, int revents)
{
    server_ctx_t *server_recv_ctx = (server_ctx_t *)w;
    server_t *server              = server_recv_ctx->server;
    remote_t *remote              = server->remote;

    ev_timer_stop(EV_A_ & server->delayed_connect_watcher);

    ssize_t r = recv(server->fd, remote->buf->data + remote->buf->len,
                     BUF_SIZE - remote->buf->len, 0);

    if (r == 0) {
        // connection closed
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    } else if (r == -1) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            // no data
            // continue to wait for recv
            return;
        } else {
            ERROR("server recv");
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    remote->buf->len += r;

    if (verbose) {
        uint16_t port = 0;
        char ipstr[INET6_ADDRSTRLEN];
        memset(&ipstr, 0, INET6_ADDRSTRLEN);

        if (AF_INET == server->destaddr.ss_family) {
            struct sockaddr_in *sa = (struct sockaddr_in *)&(server->destaddr);
            inet_ntop(AF_INET, &(sa->sin_addr), ipstr, INET_ADDRSTRLEN);
            port = ntohs(sa->sin_port);
        } else {
            struct sockaddr_in6 *sa = (struct sockaddr_in6 *)&(server->destaddr);
            inet_ntop(AF_INET6, &(sa->sin6_addr), ipstr, INET6_ADDRSTRLEN);
            port = ntohs(sa->sin6_port);
        }

        LOGI("redir to %s:%d, len=%zu, recv=%zd", ipstr, port, remote->buf->len, r);
    }

    if (!remote->send_ctx->connected) {
        if (!disable_sni) {
            // SNI
            int ret       = 0;
            uint16_t port = 0;
            if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                port = ntohs(((struct sockaddr_in6 *)&(server->destaddr))->sin6_port);
            } else {                             // IPv4
                port = ntohs(((struct sockaddr_in *)&(server->destaddr))->sin_port);
            }
            if (port == http_protocol->default_port)
                ret = http_protocol->parse_packet(remote->buf->data,
                                                  remote->buf->len, &server->hostname);
            else if (port == tls_protocol->default_port)
                ret = tls_protocol->parse_packet(remote->buf->data,
                                                 remote->buf->len, &server->hostname);
            if (ret > 0) {
                server->hostname_len = ret;
            }
        }

        ev_io_stop(EV_A_ & server_recv_ctx->io);
        ev_io_start(EV_A_ & remote->send_ctx->io);
        return;
    }

    int err = crypto->encrypt(remote->buf, server->e_ctx, BUF_SIZE);

    if (err) {
        LOGE("invalid password or cipher");
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    }

    int s = send(remote->fd, remote->buf->data, remote->buf->len, 0);

    if (s == -1) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            // no data, wait for send
            remote->buf->idx = 0;
            ev_io_stop(EV_A_ & server_recv_ctx->io);
            ev_io_start(EV_A_ & remote->send_ctx->io);
            return;
        } else {
            ERROR("send");
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    } else if (s < remote->buf->len) {
        remote->buf->len -= s;
        remote->buf->idx  = s;
        ev_io_stop(EV_A_ & server_recv_ctx->io);
        ev_io_start(EV_A_ & remote->send_ctx->io);
        return;
    } else {
        remote->buf->idx = 0;
        remote->buf->len = 0;
    }
}
Esempio n. 21
0
static void query_resolve_cb(EV_P_ ev_timer *watcher, int revents)
{
    int err;
    struct addrinfo *result, *rp;
    struct query_ctx *query_ctx = (struct query_ctx *)((void*)watcher);
    asyncns_t *asyncns = query_ctx->server_ctx->asyncns;
    asyncns_query_t *query = query_ctx->query;

    if (asyncns == NULL || query == NULL)
    {
        LOGE("invalid dns query.");
        close_and_free_query(EV_A_ query_ctx);
        return;
    }

    if (asyncns_wait(asyncns, 0) == -1)
    {
        // asyncns error
        FATAL("asyncns exit unexpectedly.");
    }

    if (!asyncns_isdone(asyncns, query))
    {
        // wait reolver
        return;
    }

    if (verbose)
    {
        LOGD("[udp] asyncns resolved.");
    }

    ev_timer_stop(EV_A_ watcher);

    err = asyncns_getaddrinfo_done(asyncns, query, &result);

    if (err)
    {
        ERROR("getaddrinfo");
    }
    else
    {
        // Use IPV4 address if possible
        for (rp = result; rp != NULL; rp = rp->ai_next)
        {
            if (rp->ai_family == AF_INET) break;
        }

        if (rp == NULL)
        {
            rp = result;
        }

        int remotefd = create_remote_socket(rp->ai_family == AF_INET6);
        if (remotefd != -1)
        {
            setnonblocking(remotefd);
#ifdef SO_NOSIGPIPE
            int opt = 1;
            setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
#ifdef SET_INTERFACE
            if (query_ctx->server_ctx->iface)
                setinterface(remotefd, query_ctx->server_ctx->iface);
#endif

            struct remote_ctx *remote_ctx = new_remote(remotefd, query_ctx->server_ctx);
            remote_ctx->src_addr = query_ctx->src_addr;
            remote_ctx->dst_addr = *rp->ai_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);

            // Add to conn cache
            char *key = hash_key(remote_ctx->addr_header,
                                 remote_ctx->addr_header_len, &remote_ctx->src_addr);
            cache_insert(query_ctx->server_ctx->conn_cache, key, (void *)remote_ctx);

            ev_io_start(EV_A_ &remote_ctx->io);

            int s = sendto(remote_ctx->fd, query_ctx->buf, query_ctx->buf_len, 0, &remote_ctx->dst_addr, sizeof(remote_ctx->dst_addr));

            if (s == -1)
            {
                ERROR("udprelay_sendto_remote");
                close_and_free_remote(EV_A_ remote_ctx);
            }

        }
        else
        {
            ERROR("udprelay bind() error..");
        }
    }

    // clean up
    asyncns_freeaddrinfo(result);
    close_and_free_query(EV_A_ query_ctx);
}
Esempio n. 22
0
static void
remote_send_cb(EV_P_ ev_io *w, int revents)
{
    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;
    remote_t *remote              = remote_send_ctx->remote;
    server_t *server              = remote->server;

    ev_timer_stop(EV_A_ & remote_send_ctx->watcher);

    if (!remote_send_ctx->connected) {
        int r = 0;
        if (remote->addr == NULL) {
            struct sockaddr_storage addr;
            memset(&addr, 0, sizeof(struct sockaddr_storage));
            socklen_t len = sizeof addr;
            r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
        }
        if (r == 0) {
            remote_send_ctx->connected = 1;

            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_stop(EV_A_ & server->recv_ctx->io);
            ev_io_start(EV_A_ & remote->recv_ctx->io);
            ev_timer_start(EV_A_ & remote->recv_ctx->watcher);

            // send destaddr
            buffer_t ss_addr_to_send;
            buffer_t *abuf = &ss_addr_to_send;
            balloc(abuf, BUF_SIZE);

            if (server->hostname_len > 0
                    && validate_hostname(server->hostname, server->hostname_len)) { // HTTP/SNI
                uint16_t port;
                if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                    port = (((struct sockaddr_in6 *)&(server->destaddr))->sin6_port);
                } else {                             // IPv4
                    port = (((struct sockaddr_in *)&(server->destaddr))->sin_port);
                }

                abuf->data[abuf->len++] = 3;          // Type 3 is hostname
                abuf->data[abuf->len++] = server->hostname_len;
                memcpy(abuf->data + abuf->len, server->hostname, server->hostname_len);
                abuf->len += server->hostname_len;
                memcpy(abuf->data + abuf->len, &port, 2);
            } else if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                abuf->data[abuf->len++] = 4;          // Type 4 is IPv6 address

                size_t in6_addr_len = sizeof(struct in6_addr);
                memcpy(abuf->data + abuf->len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_addr),
                       in6_addr_len);
                abuf->len += in6_addr_len;
                memcpy(abuf->data + abuf->len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_port),
                       2);
            } else {                             // IPv4
                abuf->data[abuf->len++] = 1; // Type 1 is IPv4 address

                size_t in_addr_len = sizeof(struct in_addr);
                memcpy(abuf->data + abuf->len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_addr, in_addr_len);
                abuf->len += in_addr_len;
                memcpy(abuf->data + abuf->len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_port, 2);
            }

            abuf->len += 2;

            int err = crypto->encrypt(abuf, server->e_ctx, BUF_SIZE);
            if (err) {
                LOGE("invalid password or cipher");
                bfree(abuf);
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            err = crypto->encrypt(remote->buf, server->e_ctx, BUF_SIZE);
            if (err) {
                LOGE("invalid password or cipher");
                bfree(abuf);
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            bprepend(remote->buf, abuf, BUF_SIZE);
            bfree(abuf);
        } else {
            ERROR("getpeername");
            // not connected
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    if (remote->buf->len == 0) {
        // close and free
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    } else {
        // has data to send
        ssize_t s;
        if (remote->addr != NULL) {
            s = sendto(remote->fd, remote->buf->data + remote->buf->idx,
                       remote->buf->len, MSG_FASTOPEN, remote->addr,
                       get_sockaddr_len(remote->addr));

            if (s == -1 && (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT ||
                errno == ENOPROTOOPT)) {
                fast_open = 0;
                LOGE("fast open is not supported on this platform");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            remote->addr = NULL;

            if (s == -1) {
                if (errno == CONNECT_IN_PROGRESS || errno == EAGAIN
                    || errno == EWOULDBLOCK) {
                    ev_io_start(EV_A_ & remote_send_ctx->io);
                    ev_timer_start(EV_A_ & remote_send_ctx->watcher);
                } else {
                    ERROR("connect");
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                }
                return;
            }
        } else {
            s = send(remote->fd, remote->buf->data + remote->buf->idx,
                     remote->buf->len, 0);
        }

        if (s == -1) {
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
                ERROR("send");
                // close and free
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
            }
            return;
        } else if (s < remote->buf->len) {
            // partly sent, move memory, wait for the next time to send
            remote->buf->len -= s;
            remote->buf->idx += s;
            ev_io_start(EV_A_ & remote_send_ctx->io);
            return;
        } else {
            // all sent out, wait for reading
            remote->buf->len = 0;
            remote->buf->idx = 0;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_start(EV_A_ & server->recv_ctx->io);
        }
    }
}
Esempio n. 23
0
}
LWRESULT Cx_WatcherTimer::WatcherStop()
{
	ev_timer_stop(mLoop, &mWatcher);
	return LWDP_OK;
Esempio n. 24
0
void lwqq_async_timer_stop(LwqqAsyncTimerHandle timer)
{
    ev_timer_stop(EV_DEFAULT,timer);
    s_free(timer->data);
}
Esempio n. 25
0
static void remote_send_cb(EV_P_ ev_io *w, int revents)
{
    struct remote_ctx *remote_send_ctx = (struct remote_ctx *)w;
    struct remote *remote = remote_send_ctx->remote;
    struct server *server = remote->server;

    if (!remote_send_ctx->connected) {
        struct sockaddr_storage addr;
        socklen_t len = sizeof addr;
        int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
        if (r == 0) {
            remote_send_ctx->connected = 1;
            ev_timer_stop(EV_A_ & remote_send_ctx->watcher);
            ev_timer_start(EV_A_ & remote->recv_ctx->watcher);
            ev_io_start(EV_A_ & remote->recv_ctx->io);

            // no need to send any data
            if (remote->buf_len == 0) {
                ev_io_stop(EV_A_ & remote_send_ctx->io);
                ev_io_start(EV_A_ & server->recv_ctx->io);
                return;
            }
        } else {
            // not connected
            ERROR("getpeername");
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    if (remote->buf_len == 0) {
        // close and free
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    } else {
        // has data to send
        ssize_t s = send(remote->fd, remote->buf + remote->buf_idx,
                         remote->buf_len, 0);
        if (s < 0) {
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
                ERROR("remote_send_cb_send");
                // close and free
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
            }
            return;
        } else if (s < remote->buf_len) {
            // partly sent, move memory, wait for the next time to send
            remote->buf_len -= s;
            remote->buf_idx += s;
            return;
        } else {
            // all sent out, wait for reading
            remote->buf_len = 0;
            remote->buf_idx = 0;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_start(EV_A_ & server->recv_ctx->io);
        }
    }
}
Esempio n. 26
0
static void remote_send_cb(EV_P_ ev_io *w, int revents)
{
    struct remote_ctx *remote_send_ctx = (struct remote_ctx *)w;
    struct remote *remote = remote_send_ctx->remote;
    struct server *server = remote->server;

    if (!remote_send_ctx->connected) {
        struct sockaddr_storage addr;
        socklen_t len = sizeof addr;

        int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
        if (r == 0) {
            remote_send_ctx->connected = 1;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_timer_stop(EV_A_ & remote_send_ctx->watcher);
            char *ss_addr_to_send = malloc(BUF_SIZE);
            ssize_t addr_len = 0;

            ss_addr_t *sa = &server->destaddr;
            struct cork_ip ip;
            if (cork_ip_init(&ip, sa->host) != -1) {
                if (ip.version == 4) {
                    // send as IPv4
                    struct in_addr host;
                    int host_len = sizeof(struct in_addr);

                    if (dns_pton(AF_INET, sa->host, &host) == -1) {
                        FATAL("IP parser error");
                    }
                    ss_addr_to_send[addr_len++] = 1;
                    memcpy(ss_addr_to_send + addr_len, &host, host_len);
                    addr_len += host_len;
                } else if (ip.version == 6) {
                    // send as IPv6
                    struct in6_addr host;
                    int host_len = sizeof(struct in6_addr);

                    if (dns_pton(AF_INET6, sa->host, &host) == -1) {
                        FATAL("IP parser error");
                    }
                    ss_addr_to_send[addr_len++] = 4;
                    memcpy(ss_addr_to_send + addr_len, &host, host_len);
                    addr_len += host_len;
                } else {
                    FATAL("IP parser error");
                }
            } else {
                // send as domain
                int host_len = strlen(sa->host);

                ss_addr_to_send[addr_len++] = 3;
                ss_addr_to_send[addr_len++] = host_len;
                memcpy(ss_addr_to_send + addr_len, sa->host, host_len);
                addr_len += host_len;
            }

            uint16_t port = htons(atoi(sa->port));
            memcpy(ss_addr_to_send + addr_len, &port, 2);
            addr_len += 2;

            ss_addr_to_send = ss_encrypt(BUF_SIZE, ss_addr_to_send, &addr_len,
                                         server->e_ctx);
            if (ss_addr_to_send == NULL) {
                LOGE("invalid password or cipher");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            int s = send(remote->fd, ss_addr_to_send, addr_len, 0);
            free(ss_addr_to_send);

            if (s < addr_len) {
                LOGE("failed to send addr");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            ev_io_start(EV_A_ & remote->recv_ctx->io);
            ev_io_start(EV_A_ & server->recv_ctx->io);

            return;
        } else {
            ERROR("getpeername");
            // not connected
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    } else {
        if (remote->buf_len == 0) {
            // close and free
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        } else {
            // has data to send
            ssize_t s = send(remote->fd, remote->buf + remote->buf_idx,
                             remote->buf_len, 0);
            if (s < 0) {
                if (errno != EAGAIN && errno != EWOULDBLOCK) {
                    ERROR("send");
                    // close and free
                    close_and_free_remote(EV_A_ remote);
                    close_and_free_server(EV_A_ server);
                }
                return;
            } else if (s < remote->buf_len) {
                // partly sent, move memory, wait for the next time to send
                remote->buf_len -= s;
                remote->buf_idx += s;
                return;
            } else {
                // all sent out, wait for reading
                remote->buf_len = 0;
                remote->buf_idx = 0;
                ev_io_stop(EV_A_ & remote_send_ctx->io);
                ev_io_start(EV_A_ & server->recv_ctx->io);
            }
        }

    }
}
Esempio n. 27
0
File: core.c Progetto: dshaw/libuv
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
  uv_udp_t* udp;
  uv_async_t* async;
  uv_timer_t* timer;
  uv_stream_t* stream;
  uv_process_t* process;

  handle->close_cb = close_cb;

  switch (handle->type) {
    case UV_NAMED_PIPE:
      uv_pipe_cleanup((uv_pipe_t*)handle);
      /* Fall through. */

    case UV_TTY:
    case UV_TCP:
      stream = (uv_stream_t*)handle;

      uv_read_stop(stream);
      ev_io_stop(stream->loop->ev, &stream->write_watcher);

      uv__close(stream->fd);
      stream->fd = -1;

      if (stream->accepted_fd >= 0) {
        uv__close(stream->accepted_fd);
        stream->accepted_fd = -1;
      }

      assert(!ev_is_active(&stream->read_watcher));
      assert(!ev_is_active(&stream->write_watcher));
      break;

    case UV_UDP:
      udp = (uv_udp_t*)handle;
      uv__udp_watcher_stop(udp, &udp->read_watcher);
      uv__udp_watcher_stop(udp, &udp->write_watcher);
      uv__close(udp->fd);
      udp->fd = -1;
      break;

    case UV_PREPARE:
      uv_prepare_stop((uv_prepare_t*) handle);
      break;

    case UV_CHECK:
      uv_check_stop((uv_check_t*) handle);
      break;

    case UV_IDLE:
      uv_idle_stop((uv_idle_t*) handle);
      break;

    case UV_ASYNC:
      async = (uv_async_t*)handle;
      ev_async_stop(async->loop->ev, &async->async_watcher);
      ev_ref(async->loop->ev);
      break;

    case UV_TIMER:
      timer = (uv_timer_t*)handle;
      if (ev_is_active(&timer->timer_watcher)) {
        ev_ref(timer->loop->ev);
      }
      ev_timer_stop(timer->loop->ev, &timer->timer_watcher);
      break;

    case UV_PROCESS:
      process = (uv_process_t*)handle;
      ev_child_stop(process->loop->ev, &process->child_watcher);
      break;

    case UV_FS_EVENT:
      uv__fs_event_destroy((uv_fs_event_t*)handle);
      break;

    default:
      assert(0);
  }

  handle->flags |= UV_CLOSING;

  /* This is used to call the on_close callback in the next loop. */
  ev_idle_start(handle->loop->ev, &handle->next_watcher);
  ev_feed_event(handle->loop->ev, &handle->next_watcher, EV_IDLE);
  assert(ev_is_pending(&handle->next_watcher));
}
Esempio n. 28
0
void server_generic_remove_client(server_generic_t *server, server_generic_client_t *client)
{
        ev_io_stop(manager_event_loop, &client->evio);
        ev_timer_stop(manager_event_loop, &client->evtimer);
}
Esempio n. 29
0
static void
remote_send_cb(EV_P_ ev_io *w, int revents)
{
    remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w;
    remote_t *remote              = remote_send_ctx->remote;
    server_t *server              = remote->server;

    if (!remote_send_ctx->connected) {
        struct sockaddr_storage addr;
        socklen_t len = sizeof addr;
        int r         = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
        if (r == 0) {
            remote_send_ctx->connected = 1;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_stop(EV_A_ & server->recv_ctx->io);
            ev_timer_stop(EV_A_ & remote_send_ctx->watcher);
            ev_timer_start(EV_A_ & remote->recv_ctx->watcher);

            // send destaddr
            buffer_t ss_addr_to_send;
            buffer_t *abuf = &ss_addr_to_send;
            balloc(abuf, BUF_SIZE);

            if (server->hostname_len > 0) { // HTTP/SNI
                uint16_t port;
                if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                    port = (((struct sockaddr_in6 *)&(server->destaddr))->sin6_port);
                } else {                             // IPv4
                    port = (((struct sockaddr_in *)&(server->destaddr))->sin_port);
                }

                abuf->array[abuf->len++] = 3;          // Type 3 is hostname
                abuf->array[abuf->len++] = server->hostname_len;
                memcpy(abuf->array + abuf->len, server->hostname, server->hostname_len);
                abuf->len += server->hostname_len;
                memcpy(abuf->array + abuf->len, &port, 2);
            } else if (AF_INET6 == server->destaddr.ss_family) { // IPv6
                abuf->array[abuf->len++] = 4;          // Type 4 is IPv6 address

                size_t in6_addr_len = sizeof(struct in6_addr);
                memcpy(abuf->array + abuf->len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_addr),
                       in6_addr_len);
                abuf->len += in6_addr_len;
                memcpy(abuf->array + abuf->len,
                       &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_port),
                       2);
            } else {                             // IPv4
                abuf->array[abuf->len++] = 1; // Type 1 is IPv4 address

                size_t in_addr_len = sizeof(struct in_addr);
                memcpy(abuf->array + abuf->len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_addr, in_addr_len);
                abuf->len += in_addr_len;
                memcpy(abuf->array + abuf->len,
                       &((struct sockaddr_in *)&(server->destaddr))->sin_port, 2);
            }

            abuf->len += 2;

            if (auth) {
                abuf->array[0] |= ONETIMEAUTH_FLAG;
                ss_onetimeauth(abuf, server->e_ctx->evp.iv, BUF_SIZE);
            }

            brealloc(remote->buf, remote->buf->len + abuf->len, BUF_SIZE);
            memmove(remote->buf->array + abuf->len, remote->buf->array, remote->buf->len);
            memcpy(remote->buf->array, abuf->array, abuf->len);
            remote->buf->len += abuf->len;
            bfree(abuf);

            int err = ss_encrypt(remote->buf, server->e_ctx, BUF_SIZE);
            if (err) {
                LOGE("invalid password or cipher");
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
                return;
            }

            ev_io_start(EV_A_ & remote->recv_ctx->io);
        } else {
            ERROR("getpeername");
            // not connected
            close_and_free_remote(EV_A_ remote);
            close_and_free_server(EV_A_ server);
            return;
        }
    }

    if (remote->buf->len == 0) {
        // close and free
        close_and_free_remote(EV_A_ remote);
        close_and_free_server(EV_A_ server);
        return;
    } else {
        // has data to send
        ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx,
                         remote->buf->len, 0);
        if (s == -1) {
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
                ERROR("send");
                // close and free
                close_and_free_remote(EV_A_ remote);
                close_and_free_server(EV_A_ server);
            }
            return;
        } else if (s < remote->buf->len) {
            // partly sent, move memory, wait for the next time to send
            remote->buf->len -= s;
            remote->buf->idx += s;
            return;
        } else {
            // all sent out, wait for reading
            remote->buf->len = 0;
            remote->buf->idx = 0;
            ev_io_stop(EV_A_ & remote_send_ctx->io);
            ev_io_start(EV_A_ & server->recv_ctx->io);
        }
    }
}
Esempio n. 30
0
// libev write callback
static void 
zc_asynio_ev_write(struct ev_loop *loop, ev_io *w, int events)
{
    //ZCINFO("ok, write event\n");
    zcAsynIO *conn = (zcAsynIO*)w->data; 

    char addr[32];
    sprintf(addr, "%s:%d ", conn->sock->remote.ip, conn->sock->remote.port);
    zc_log_set_prefix(_zc_log, addr);

    // stop write timeout
    ev_timer_stop(loop, &conn->wtimer);
    int ret;
    zcBuffer *wbuf = conn->wbuf;
    // udp
    if (conn->sock->type == SOCK_DGRAM) {
        ret = zc_socket_sendto_self(conn->sock, zc_buffer_data(wbuf), zc_buffer_used(wbuf), 0);
        if (ret != zc_buffer_used(wbuf)) {
            ZCWARN("sendto error:%d, wbuf:%d, close conn", ret, zc_buffer_used(wbuf));
            conn->p.handle_close(conn);
            //zc_asynio_safedel(conn);
            zc_asynio_delete_delay(conn);
            return;
        }
        ZCINFO("udp write:%d", ret);
        conn->p.handle_wrote(conn);
        zc_buffer_reset(wbuf);

        if (zc_buffer_used(conn->wbuf) == 0) {
            zc_asynio_write_stop(conn);
        }
        return;
    }

    // tcp
    // optimize?
    ret = zc_socket_peek(conn->sock);
    if (ret <= 0 && ret != -EAGAIN) {
        if (zc_socket_conn_lost(-1*ret)) {
            conn->p.handle_error(conn, ret);
        }
        ZCWARN("peek error:%d\n", ret);
        conn->p.handle_close(conn); 
        //zc_socket_delete(conn->sock);
        //zc_asynio_safedel(conn);
        zc_asynio_delete_delay(conn);
        return;
    }

    while (zc_buffer_used(wbuf) > 0) {
        //ZCINFO("write len:%d, pos:%d\n", zc_buffer_used(wbuf), wbuf->pos);
        ret = zc_socket_send(conn->sock, wbuf->data+wbuf->pos, zc_buffer_used(wbuf)); 
        if (ret < 0) {
            ZCWARN("send error:%d\n", ret);
            if (ret == -EAGAIN || ret == -EWOULDBLOCK) {
                ZCWARN("write EAGAIN, break");
                break;
            }
            conn->p.handle_close(conn);
            //zc_socket_delete(conn->sock);
            //zc_asynio_safedel(conn);
            zc_asynio_delete_delay(conn);
            return;
        }
        wbuf->pos += ret;
    }
    ZCINFO("after send, wbuf:%d", zc_buffer_used(conn->wbuf));
    if (zc_buffer_used(conn->wbuf) == 0) {
        if (conn->wbuf->next == NULL) {
            zc_buffer_reset(conn->wbuf);
            if (conn->p.handle_wrote(conn) == 0) { // handle_wrote return 0 means no new data, >0 have new data, not stop write
                zc_asynio_write_stop(conn);
            }
        }else{
            zcBuffer *mybuf = conn->wbuf;
            conn->wbuf = conn->wbuf->next;
            zc_buffer_delete(mybuf);
        }
    }
    //ZCINFO("write event end");
    return;
}