static void port_server_accept_done(void * x) {
    AsyncReqInfo * req = (AsyncReqInfo *) x;
    PortServer * server = (PortServer *) req->client_data;

    if (server->sock < 0 || req->error) {
        /* Server closed or fatal error */
        if (server->sock >= 0 && req->error) {
            trace(LOG_ALWAYS, "Port Server accept failed for server %s: %s", server->id, errno_to_str(req->error));
        }
        server->accept_in_progress = 0;
        port_server_shutdown(server);
        return;
    }
    else {
        int fd = req->u.acc.rval;
        set_socket_options(fd); /* set socket options */
        trace (LOG_ALWAYS, "Accept done on server for server %s", server->id);

        /* In auto connect mode, we accept only a single client for the
         * port.
         */
        if (server->auto_connect == 0) {
            port_connection_open(server, fd);
        } else if (server->list == NULL || !server->list->connected || server->list->fd != -1) {
            closesocket(fd);
        } else {
            port_connection_bind(server->list, fd);
        }
    }
    server->accreq.u.acc.addrlen = server->addr_len;
    async_req_post(req);
}
Ejemplo n.º 2
0
PortServer * create_port_server(Channel * c, PortAttribute * attrs, PortConnectCallback connect_callback, PortDisconnectCallback disconnect_callback, PortRecvCallback recv_callback, void * callback_data) {
    PortServer * server;
    assert (c != NULL);
    assert (attrs != NULL);

    if (c == NULL || attrs == NULL) {
        free_port_redirection_attrs(attrs);
        errno = EINVAL;
        return NULL;
    }
    ini_portforwarding();
    server = create_server(c, attrs);
    if (server == NULL) {
        free_port_redirection_attrs(attrs);
        return NULL;
    }
    else {
        server->connect_callback = connect_callback;
        server->disconnect_callback = disconnect_callback;
        server->recv_callback = recv_callback;
        server->callback_data = callback_data;
        if (server->auto_connect) {
            /* If auto connect mode is set, immediately try to connect to the
             * port.  */
            if (server->auto_connect_period == 0) server->auto_connect_period = 3;
            port_connection_open(server, server->is_udp ? server->sock : -1);
        }
        return server;
    }
}
/*
void remove_port_redirection(PortServer * redir) {
    port_server_shutdown(redir->server);
}
*/
PortServer * create_port_redirection(PortRedirectionInfo * port) {
    PortServer * server;
    assert (port != NULL);
    assert (port->c != NULL);

    if (port == NULL || port->c == NULL) {
        free_port_redirection_info(port);
        errno = EINVAL;
        return NULL;
    }

    ini_portforwarding();

    /* We do not accept specifying a target_port (legacy) and port attributes */
    if (port->target_port != 0 && port->attrs != NULL) {
        free_port_redirection_info(port);
        errno = EINVAL;
        return NULL;
    }

    if (port->target_port != 0) {
        char port_str[16];
        PortAttribute * attr = (PortAttribute *)loc_alloc_zero(sizeof(PortAttribute));
        snprintf(port_str, 16, "%d", port->target_port);
        attr->name = loc_strdup("Port");
        attr->value = loc_strdup(port_str);
        attr->next = port->attrs;
        port->attrs = attr;
    }

    server = create_port_server(port->c, port);

    if (server == NULL) {
        free_port_redirection_info(port);
        loc_free(server);
        return NULL;
    }
    else {
        server->redir_info = port;
        port->local_port = server->local_port;
        server->auto_connect = port->auto_connect;
        server->auto_connect_period = port->auto_connect_period == 0 ? 3 : port->auto_connect_period;
        server->connect_callback = port->connect_callback;
        server->disconnect_callback = port->disconnect_callback;
        server->recv_callback = port->recv_callback;
        server->callback_data = port->callback_data;
        if (server->auto_connect) {
            /* If auto connect mode is set, immediately try to connect to the
             * port.
             */
            port_connection_open(server, server->is_udp ? server->sock : -1);
        }
        return server;
    }
}
static void port_connection_open_event(void * arg) {
    LINK * qhp = &server_list;
    LINK * qp = qhp->next;

    while (qp != qhp) {
        PortServer * server = link2server(qp);
        if (server == (PortServer *)arg) {
            port_connection_open(server, server->is_udp ? server->sock : -1);
        }
        qp = qp->next;
    }
}