static void done_send_request(void * args) {
    AsyncReqInfo * req = (AsyncReqInfo *) args;
    PortConnection * conn = (PortConnection *) (req)->client_data;
    int idx = conn->send_in_progress;

    port_unlock(conn);
    conn->send_in_progress = -1;
    if (conn->connected == 0) {
        port_connection_close(conn);
        return;
    }
    if (req->u.sio.rval == 0
           || (req->u.sio.rval == -1 && req->error != EINTR)) {
        /* Check if we are in auto connect mode and server has not been
         * shut down
         */
        if (conn->server->auto_connect && conn->server->sock != -1) {
            /* Client has disconnected; don't close the connection if we
             * are in auto connect mode but simply unbind the client from
             * the port.
             */
            port_connection_unbind(conn);
            
            /* Still read packets from the target even if no client is 
             * connected. This may have to be revisited.
             */
            read_packet(conn, idx);
        }
        else port_connection_close(conn);
        return;
    }

    if (conn->pending_send_req != 0) {
        int next_idx;
        int loop;

        /* Get the next packet to send. In general, it is the next buffer
         * but there are some error cases (connection lost, empty packet
         * received from TCF agent) which may break this rule.
         */
        for (loop = 0; loop < MAX_STREAM_READ; loop++) {
            next_idx = (idx + loop) % MAX_STREAM_READ;
            if (conn->pending_send_req & (1 << next_idx))
                break;
        }
        assert (loop != MAX_STREAM_READ &&
                        (conn->pending_send_req & (1 << next_idx)));
                

        conn->send_in_progress = next_idx;
        conn->pending_send_req &= ~(1 << next_idx);
        conn->send_req.u.sio.bufp = conn->read_buffer[next_idx];
        conn->send_req.u.sio.bufsz = conn->read_buffer_size[next_idx];
        port_lock(conn);
        conn->send_req.u.sio.sock = conn->fd;
        conn->send_req.u.sio.addr = &conn->server->client_addr;
        conn->send_req.u.sio.addrlen = conn->server->client_addr_len;
        async_req_post(&conn->send_req);
    }
    read_packet(conn, idx);
}
Ejemplo n.º 2
0
static void start_timer(void * args) {
    memset(&timer_req, 0, sizeof(timer_req));
    timer_req.type = AsyncReqTimer;
    async_req_post(&timer_req);
}
void channel_np_connect(PeerServer * ps, ChannelConnectCallBack callback, void * callback_args) {
    const char * host = peer_server_getprop(ps, "Host", NULL);
    const char * port = peer_server_getprop(ps, "Port", NULL);
    const char * get_url = peer_server_getprop(ps, "GetUrl", NULL);
    const char * host_name = peer_server_getprop(ps, "HostName", NULL);
#if ENABLE_WebSocket_SOCKS_V5
    const char * proxy = peer_server_getprop(ps, "Proxy", NULL);
#endif
    ChannelConnectInfo * info = NULL;
    char port_str[16];
    struct addrinfo hints;
    struct addrinfo * reslist = NULL;
    int error;

    ini_nopoll();
    if (port == NULL) {
        sprintf(port_str, "%d", DISCOVERY_TCF_PORT);
        port = port_str;
    }

    memset(&hints, 0, sizeof hints);
    hints.ai_family = PF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    error = loc_getaddrinfo(host, port, &hints, &reslist);
    if (error) error = set_gai_errno(error);
    if (!error) {
        struct addrinfo * res;
        info = (ChannelConnectInfo *)loc_alloc_zero(sizeof(ChannelConnectInfo));
        for (res = reslist; res != NULL; res = res->ai_next) {
            info->addr_len = res->ai_addrlen;
            info->addr_buf = (struct sockaddr *)loc_alloc(res->ai_addrlen);
            memcpy(info->addr_buf, res->ai_addr, res->ai_addrlen);
            error = 0;
            break;
        }
        loc_freeaddrinfo(reslist);
    }

    if (!error && info->addr_buf == NULL) error = ENOENT;
    if (error) {
        if (info != NULL) {
            loc_free(info->addr_buf);
            loc_free(info);
        }
        callback(callback_args, error, NULL);
    } else {
	noPollCtx * np_ctx_client;
	np_ctx_client = nopoll_ctx_new();
	/*nopoll_log_enable(np_ctx_client, nopoll_true);*/
#if ENABLE_WebSocket_SOCKS_V5
        if (proxy != NULL) {
            /* save global proxy values */
            char * proxy_host = socks_v5_host;
            char * proxy_port = socks_v5_port;
            if (parse_socks_v5_proxy(proxy) != 0) {
                socks_v5_host = proxy_host;
                socks_v5_port = proxy_port;
                if (info != NULL) {
                    loc_free(info->addr_buf);
                    loc_free(info);
                }
                callback(callback_args, errno, NULL);
                return;
            }
            if (socks_v5_host != NULL) nopoll_conn_set_socks_v5_proxy(np_ctx_client, socks_v5_host, socks_v5_port);
            /* Restore global proxy values */
            socks_v5_host = proxy_host;
            socks_v5_port = proxy_port;
        }
#endif

        info->callback = callback;
        info->callback_args = callback_args;
        info->is_ssl = strcmp(peer_server_getprop(ps, "TransportName", ""), "WSS") == 0;
        info->req.client_data = info;
        info->req.done = channel_np_connect_done;
        info->req.type = AsyncReqUser;
        info->req.u.user.func = np_wt_connect;
        info->req.u.user.data = info;
        info->host = loc_strdup(host == NULL ? "127.0.0.1" : host);
        info->port = loc_strdup(port);
        info->get_url = get_url;
        info->host_name = host_name;
        info->np_ctx = np_ctx_client;
        async_req_post(&info->req);
    }
}
Ejemplo n.º 4
0
static PortServer * create_server(Channel * c, PortAttribute * attrs) {
    int sock = -1;
    struct sockaddr_in addr;
    PortAttribute * attr = attrs;
#if defined(_WRS_KERNEL)
    int addrlen;
#else
    socklen_t addrlen;
#endif
    u_short port_number;
    PortServer * server = NULL;
    int is_udp = 0;           /* do we use a server UDP -or TCP- port? */
    char * port_config = NULL;
    int error = 0;
    int auto_connect = 0;
    uint64_t auto_connect_period = 0;
    unsigned int local_port = 0;

    while (attr != NULL) {
        if (strcmp(attr->name,  "Port") == 0) {
            ByteArrayInputStream buf;
            InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value));
            port_config = json_read_alloc_string(inp);
            if (strncasecmp(port_config, "udp:", strlen("udp:")) == 0) {
                is_udp = 1;
            }
        }
        else if (strcmp(attr->name, "AutoConnect") == 0) {
            ByteArrayInputStream buf;
            InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value));
            auto_connect = json_read_boolean(inp);
        }
        else if (strcmp(attr->name, "AutoConnectPeriod") == 0) {
            ByteArrayInputStream buf;
            InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value));
            auto_connect_period = json_read_ulong(inp);
        }
        else if (strcmp(attr->name, "LocalPort") == 0) {
            ByteArrayInputStream buf;
            InputStream * inp = create_byte_array_input_stream(&buf, attr->value, strlen(attr->value));
            local_port = (unsigned int) json_read_uint64(inp);
        }
        attr = attr->next;
    }
    if (port_config == NULL) {
        error = set_errno(ERR_OTHER, "No port configuration is specified");
    }
    if (error == 0) {
        loc_free(port_config);
        memset((void *) &addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        addr.sin_port = (u_short) htons(local_port);

        if (is_udp) sock = socket(AF_INET, SOCK_DGRAM, 0);
        else if ((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0) set_socket_options(sock); /* set socket options */

        if (sock == -1) error = errno;
    }

    if (error == 0) {
        if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
            error = errno;
        }
    }

    if (error == 0 && !is_udp) {
        if (listen(sock, 16) != 0) error = errno;
    }

    if (error == 0) {
        /* Get port property in case the default port could not be used or
         * the client specified a port that the system converts to a
         * dynamic port number. */
        addrlen = sizeof addr;
        if (getsockname(sock, (struct sockaddr *) &addr, &addrlen) < 0) error = errno;
    }

    if (error == 0) {
        port_number = (u_short) ntohs(addr.sin_port);

        server = (PortServer *)loc_alloc_zero(sizeof(PortServer));
        server->sock = sock;
        server->is_udp = is_udp;
#if defined(SOCK_MAXADDRLEN)
        server->addr_len = SOCK_MAXADDRLEN;
#else
        server->addr_len = 0x1000;
#endif
        server->addr_buf = (struct sockaddr *)loc_alloc(server->addr_len);
        server->local_port = port_number;

        if (!server->is_udp) {
            server->accept_in_progress = 1;
            server->auto_connect = auto_connect;

            server->accreq.done = port_server_accept_done;
            server->accreq.client_data = server;
            server->accreq.type = AsyncReqAccept;
            server->accreq.u.acc.sock = sock;
            server->accreq.u.acc.addr = server->addr_buf;
            server->accreq.u.acc.addrlen = server->addr_len;
            async_req_post(&server->accreq);
            }
        else
            {
            /* For UDP, automatically connect to the port since there is no
             * connection request we can detect.
             */
            server->auto_connect = 1;
            }
        server->auto_connect_period = auto_connect_period;

        list_add_last(&server->link, &server_list);
        channel_lock_with_msg(server->channel = c, channel_lock_svr_msg);
        snprintf (server->id, sizeof(server->id), "PS%" PRIu64, port_server_id++);
        server->attrs = attrs;
    }
    if (error == 0) return server;
    else {
        if (sock != -1) closesocket(sock);
        loc_free(server);
        return NULL ;
    }
}