示例#1
0
/*== Add new socket ==*/
int addSocket(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transport, tsk_bool_t take_ownership, tsk_bool_t is_client)
{
	transport_context_t *context = transport?transport->context:0;
	if(context){
		transport_socket_xt *sock = tsk_calloc(1, sizeof(transport_socket_xt));
		sock->fd = fd;
		sock->type = type;
		sock->owner = take_ownership;

		if((TNET_SOCKET_TYPE_IS_TLS(sock->type) || TNET_SOCKET_TYPE_IS_WSS(sock->type)) && transport->tls.enabled){
#if HAVE_OPENSSL
			sock->tlshandle = tnet_tls_socket_create(sock->fd, is_client ? transport->tls.ctx_client : transport->tls.ctx_server);       
#endif
		}
		
		tsk_safeobj_lock(context);
		
		context->ufds[context->count].fd = fd;
		context->ufds[context->count].events = (fd == context->pipeR) ? TNET_POLLIN : context->events;
		context->ufds[context->count].revents = 0;
		context->sockets[context->count] = sock;
		
		context->count++;
		
		tsk_safeobj_unlock(context);
		
		TSK_DEBUG_INFO("Socket added: fd=%d, tail.count=%d", fd, context->count);
		
		return 0;
	}
	else{
		TSK_DEBUG_ERROR("Context is Null.");
		return -1;
	}
}
示例#2
0
static int _tnet_transport_ssl_init(tnet_transport_t* transport)
{
	if(!transport){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}
#if HAVE_OPENSSL
	{
		tnet_socket_type_t type = tnet_transport_get_type(transport);
		tsk_bool_t is_tls = (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type));
		tsk_bool_t is_dtls = TNET_SOCKET_TYPE_IS_DTLS(type);
		if(is_dtls && !tnet_dtls_is_supported()){
			TSK_DEBUG_ERROR("Requesting to create DTLS transport but source code not built with support for this feature");
			return -1;
		}
		if(is_tls && !tnet_tls_is_supported()){
			TSK_DEBUG_ERROR("Requesting to create TLS transport but source code not built with support for this feature");
			return -1;
		}
		if((transport->tls.enabled = is_tls)){
			if(!transport->tls.ctx_client && !(transport->tls.ctx_client = SSL_CTX_new(SSLv23_client_method()))){
				TSK_DEBUG_ERROR("Failed to create SSL client context");
				return -2;
			}
			if(!transport->tls.ctx_server && !(transport->tls.ctx_server = SSL_CTX_new(SSLv23_server_method()))){
				TSK_DEBUG_ERROR("Failed to create SSL server context");
				return -3;
			}
			SSL_CTX_set_mode(transport->tls.ctx_client, SSL_MODE_AUTO_RETRY);
			SSL_CTX_set_mode(transport->tls.ctx_server, SSL_MODE_AUTO_RETRY);
			SSL_CTX_set_verify(transport->tls.ctx_server, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs()
			SSL_CTX_set_verify(transport->tls.ctx_client, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs()
			if(SSL_CTX_set_cipher_list(transport->tls.ctx_client, TNET_CIPHER_LIST) <= 0 || SSL_CTX_set_cipher_list(transport->tls.ctx_server, TNET_CIPHER_LIST) <= 0){
				TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
				return -4;
			}
		}
#if HAVE_OPENSSL_DTLS
		if((transport->dtls.enabled = is_dtls)){
			if(!transport->dtls.ctx && !(transport->dtls.ctx = SSL_CTX_new(DTLSv1_method()))){
				TSK_DEBUG_ERROR("Failed to create DTLSv1 context");
				TSK_OBJECT_SAFE_FREE(transport);
				return -5;
			}
			SSL_CTX_set_read_ahead(transport->dtls.ctx, 1);
			// SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_ALL);
			// SSL_CTX_set_mode(transport->dtls.ctx, SSL_MODE_AUTO_RETRY);
			SSL_CTX_set_verify(transport->dtls.ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, tsk_null); // to be updated by tnet_transport_tls_set_certs()
			if(SSL_CTX_set_cipher_list(transport->dtls.ctx, TNET_CIPHER_LIST) <= 0){
				TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
				return -6;
			}
			transport->dtls.activated = tsk_true;
		}
#endif /* HAVE_OPENSSL_DTLS */
	}
#endif /* HAVE_OPENSSL */

	return 0;
}
/*== Add new socket ==*/
static int addSocket(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transport, tsk_bool_t take_ownership, tsk_bool_t is_client, tnet_tls_socket_handle_t* tlsHandle)
{
    transport_context_t *context;

    if (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) {
#if !HAVE_OPENSSL
        TSK_DEBUG_ERROR("Cannot create TLS socket: OpenSSL missing");
        return -2;
#endif
    }

    if ((context = transport ? transport->context : tsk_null)) {
        transport_socket_xt *sock = tsk_calloc(1, sizeof(transport_socket_xt));
        sock->fd = fd;
        sock->type = type;
        sock->owner = take_ownership ? 1 : 0;

        if ((TNET_SOCKET_TYPE_IS_TLS(sock->type) || TNET_SOCKET_TYPE_IS_WSS(sock->type)) && transport->tls.enabled) {
            if (tlsHandle) {
                sock->tlshandle = tsk_object_ref(tlsHandle);
            }
            else {
#if HAVE_OPENSSL
                sock->tlshandle = tnet_tls_socket_create(sock->fd, is_client ? transport->tls.ctx_client : transport->tls.ctx_server);
#endif
            }
        }

        tsk_safeobj_lock(context);
        context->events[context->count] = WSACreateEvent();
        context->sockets[context->count] = sock;

        context->count++;

        TSK_DEBUG_INFO("Transport[%s] sockets count = %u", transport->description, context->count);

        tsk_safeobj_unlock(context);

        return 0;
    }
    else {
        TSK_DEBUG_ERROR("Context is Null.");
        return -1;
    }
}
示例#4
0
/**@ingroup tnet_socket_group
* Returns the number of bytes sent (or negative value on error)
*/
int tnet_socket_send_stream(tnet_socket_t* self, const void* data, tsk_size_t size)
{
	if (!self || self->fd == TNET_INVALID_FD || !data || !size || !TNET_SOCKET_TYPE_IS_STREAM(self->type)) {
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}
	if (self->tlshandle && (TNET_SOCKET_TYPE_IS_TLS(self->type) || TNET_SOCKET_TYPE_IS_WSS(self->type))) {
		return tnet_tls_socket_send(self->tlshandle, data, size) == 0 ? (int)size : -1; // returns zero on success
	}

	return (int)tnet_sockfd_send(self->fd, data, size, 0);
}
/*== Add new socket ==*/
int addSocket(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transport, tsk_bool_t take_ownership, tsk_bool_t is_client, tnet_tls_socket_handle_t* tlsHandle)
{
    transport_context_t *context = transport?transport->context:0;
    if(context) {
        transport_socket_xt *sock = tsk_calloc(1, sizeof(transport_socket_xt));
        sock->fd = fd;
        sock->type = type;
        sock->owner = take_ownership;

        if((TNET_SOCKET_TYPE_IS_TLS(sock->type) || TNET_SOCKET_TYPE_IS_WSS(sock->type)) && transport->tls.enabled) {
            if(tlsHandle) {
                sock->tlshandle = tsk_object_ref(tlsHandle);
            }
            else {
#if HAVE_OPENSSL
                sock->tlshandle = tnet_tls_socket_create(sock->fd, is_client ? transport->tls.ctx_client : transport->tls.ctx_server);
#endif
            }
        }

        tsk_safeobj_lock(context);

        context->ufds[context->count].fd = fd;
        context->ufds[context->count].events = (fd == context->pipeR) ? TNET_POLLIN : (TNET_POLLIN | TNET_POLLNVAL | TNET_POLLERR);
        if(TNET_SOCKET_TYPE_IS_STREAM(sock->type) && fd != context->pipeR) {
            context->ufds[context->count].events |= TNET_POLLOUT; // emulate WinSock2 FD_CONNECT event
        }
        context->ufds[context->count].revents = 0;
        context->sockets[context->count] = sock;

        context->count++;

        tsk_safeobj_unlock(context);

        TSK_DEBUG_INFO("Socket added[%s]: fd=%d, tail.count=%d", transport->description, fd, (int)context->count);

        return 0;
    }
    else {
        TSK_DEBUG_ERROR("Context is Null.");
        return -1;
    }
}
int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_socket_type_t type, tsk_bool_t take_ownership, tsk_bool_t isClient, tnet_tls_socket_handle_t* tlsHandle)
{
    tnet_transport_t *transport = (tnet_transport_t*)handle;
    transport_context_t* context;
    static char c = '\0';
    int ret = -1;

    if(!transport) {
        TSK_DEBUG_ERROR("Invalid server handle.");
        return ret;
    }

    if(!(context = (transport_context_t*)transport->context)) {
        TSK_DEBUG_ERROR("Invalid context.");
        return -2;
    }

    if(TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) {
        transport->tls.enabled = 1;
    }

    if((ret = addSocket(fd, type, transport, take_ownership, isClient, tlsHandle))) {
        TSK_DEBUG_ERROR("Failed to add new Socket.");
        return ret;
    }

    // signal
    if(context->pipeW && (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started)) {
        if((ret = write(context->pipeW, &c, 1)) > 0) {
            TSK_DEBUG_INFO("Socket added (external call) %d", fd);
            return 0;
        }
        else {
            TSK_DEBUG_ERROR("Failed to add new Socket.");
            return ret;
        }
    }
    else {
        TSK_DEBUG_INFO("pipeW (write site) not initialized yet.");
        return 0; //Will be taken when mainthead start
    }
}
/*
* Add new socket to the watcher.
*/
int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_socket_type_t type, tsk_bool_t take_ownership, tsk_bool_t isClient, tnet_tls_socket_handle_t* tlsHandle)
{
    tnet_transport_t *transport = (tnet_transport_t*)handle;
    transport_context_t* context;
    int ret = -1;

    if (!transport) {
        TSK_DEBUG_ERROR("Invalid server handle.");
        return ret;
    }

    if (!(context = (transport_context_t*)transport->context)) {
        TSK_DEBUG_ERROR("Invalid context.");
        return -2;
    }

    if (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) {
        transport->tls.enabled = tsk_true;
    }

    addSocket(fd, type, transport, take_ownership, isClient, tlsHandle);

    if (WSAEventSelect(fd, context->events[context->count - 1], FD_ALL_EVENTS) == SOCKET_ERROR) {
        removeSocket((int)(context->count - 1), context);
        TNET_PRINT_LAST_ERROR("WSAEventSelect have failed.");
        return -1;
    }

    /* Signal if transport is running */
    if (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) {
        if (WSASetEvent(context->events[0])) {
            TSK_DEBUG_INFO("New socket added to the network transport.");
            return 0;
        }
        TSK_DEBUG_ERROR("Transport not started yet");
        return -1;
    }

    TSK_DEBUG_INFO("Adding socket delayed");
    return 0;
}
示例#8
0
static int tsip_transac_dst_deliver(struct tsip_transac_dst_s* self, tsip_dialog_event_type_t event_type, const tsip_message_t *msg)
{
	if(!self){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	switch(self->type){
		case tsip_transac_dst_type_dialog:
			{
				return self->dialog.dlg->callback(
					self->dialog.dlg, 
					event_type, 
					msg
				);
			}
		case tsip_transac_dst_type_net:
			{
				if(!msg){
					TSK_DEBUG_ERROR("Message is null");
					return -1;
				}
				
				// all messages coming from WebSocket transport have to be updated (AoR, Via...) before network delivering
				// all other messages MUST not unless specified from the dialog layer
				TSIP_MESSAGE(msg)->update |= (TNET_SOCKET_TYPE_IS_WS(msg->src_net_type) || TNET_SOCKET_TYPE_IS_WSS(msg->src_net_type));

				return tsip_transport_layer_send(
					self->stack->layer_transport, 
					msg->firstVia ? msg->firstVia->branch : tsk_null, 
					TSIP_MESSAGE(msg)
				);
			}
		default:
			{
				TSK_DEBUG_ERROR("Unexpected code called");
				return -2;
			}
	}
}
示例#9
0
/**
* Connects a socket.
* @param handle The transport to use to connect() the socket. The new socket will be managed by this transport.
* @param host The remote @a host to connect() to.
* @param port The remote @a port to connect() to.
* @param type The type of the socket to use to connect() to the remote @a host.
* @retval The newly connected socket. For non-blocking sockets you should use @ref tnet_sockfd_waitUntilWritable to check
* the socket for writability.
* @sa tnet_sockfd_waitUntilWritable.
*/
tnet_fd_t tnet_transport_connectto(const tnet_transport_handle_t *handle, const char* host, tnet_port_t port, tnet_socket_type_t type)
{
	tnet_transport_t *transport = (tnet_transport_t*)handle;
	struct sockaddr_storage to;
	int status = -1;
	tnet_fd_t fd = TNET_INVALID_FD;
	tnet_tls_socket_handle_t* tls_handle = tsk_null;
	
	if(!transport || !transport->master){
		TSK_DEBUG_ERROR("Invalid transport handle");
		goto bail;
	}
	
	if((TNET_SOCKET_TYPE_IS_STREAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_STREAM(type)) ||
		(TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_DGRAM(type))){
		TSK_DEBUG_ERROR("Master/destination types mismatch [%u/%u]", transport->master->type, type);
		goto bail;
	}

	/* Init destination sockaddr fields */
	if((status = tnet_sockaddr_init(host, port, type, &to))){
		TSK_DEBUG_ERROR("Invalid HOST/PORT [%s/%u]", host, port);
		goto bail;
	}
	else if(TNET_SOCKET_TYPE_IS_IPV46(type)){
		/* Update the type (unambiguously) */
		if(to.ss_family == AF_INET6){
			TNET_SOCKET_TYPE_SET_IPV6Only(type);
		}
		else{
			TNET_SOCKET_TYPE_SET_IPV4Only(type);
		}
	}
	
	/*
	* STREAM ==> create new socket and connect it to the remote host.
	* DGRAM ==> connect the master to the remote host.
	*/
	if(TNET_SOCKET_TYPE_IS_STREAM(type)){		
		/* Create client socket descriptor. */
		if((status = tnet_sockfd_init(transport->local_host, TNET_SOCKET_PORT_ANY, type, &fd))){
			TSK_DEBUG_ERROR("Failed to create new sockfd.");
			goto bail;
		}
	}
	else{
		fd = transport->master->fd;
	}
	
	if((status = tnet_sockfd_connectto(fd, (const struct sockaddr_storage *)&to))){
		if(fd != transport->master->fd){
			tnet_sockfd_close(&fd);
		}
		goto bail;
	}
	else{
        static const tsk_bool_t __isClient = tsk_true;
        static const tsk_bool_t __takeOwnership = tsk_true;
		if(TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)){
#if HAVE_OPENSSL
			tls_handle = tnet_tls_socket_create(fd, transport->tls.ctx_client);     
			if((status = tnet_tls_socket_connect(tls_handle))){
				tnet_sockfd_close(&fd);
				goto bail;
			}
#endif
		}
        /* Add the socket */
        // socket must be added after connect() otherwise many Linux systems when return POLLHUP as the fd is not active yet
        if((status = tnet_transport_add_socket(handle, fd, type, __takeOwnership, __isClient, tls_handle))){
            TNET_PRINT_LAST_ERROR("Failed to add new socket");
            tnet_sockfd_close(&fd);
            goto bail;
        }
	}
	
bail:
	TSK_OBJECT_SAFE_FREE(tls_handle);
	return fd;
}
示例#10
0
tnet_fd_t tnet_transport_connectto_3(const tnet_transport_handle_t *handle, struct tnet_socket_s* socket, const char* host, tnet_port_t port, tnet_socket_type_t type)
{
    tnet_transport_t *transport = (tnet_transport_t*)handle;
    struct sockaddr_storage to;
    int status = -1;
    tnet_fd_t fd = socket ? socket->fd : TNET_INVALID_FD;
    tnet_tls_socket_handle_t* tls_handle = tsk_null;
    tsk_bool_t owe_socket = socket ? tsk_false : tsk_true;
    tsk_bool_t use_proxy = TNET_SOCKET_TYPE_IS_STREAM(type);
    const char* to_host = host;
    tnet_port_t to_port = port;
    tnet_socket_type_t to_type = type;
    tnet_proxyinfo_t* proxy_info = tsk_null;
    
    if (!transport || !transport->master) {
        TSK_DEBUG_ERROR("Invalid transport handle");
        goto bail;
    }
    
    if ((TNET_SOCKET_TYPE_IS_STREAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_STREAM(type)) ||
        (TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_DGRAM(type))) {
        TSK_DEBUG_ERROR("Master/destination types mismatch [%u/%u]", transport->master->type, type);
        goto bail;
    }
    
    if (use_proxy) {
        // auto-detect the proxy
        if (transport->proxy.auto_detect) {
            char* url = tsk_null;
            // The proxy detection implementations are designed for a browser and expect a "http://" or "https://" schemes (will work with socks).
            tsk_sprintf(&url, "%s://%s:%d", TNET_SOCKET_TYPE_IS_TLS(to_type) ? "https" : "http", to_host, to_port);
            proxy_info = tnet_proxydetect_get_info_fast(url, to_type);
            TSK_FREE(url);
        }
        // fall-back to the hard proxy if auto-detection failed
        if (!tnet_proxyinfo_is_valid(proxy_info) && tnet_proxyinfo_is_valid(transport->proxy.info)) {
            proxy_info = tsk_object_ref(transport->proxy.info);
        }
    }
    
    use_proxy &= tnet_proxyinfo_is_valid(proxy_info);
    if (use_proxy) {
        if (tnet_proxy_node_is_nettransport_supported(proxy_info->type, type)) {
            to_host = proxy_info->hostname;
            to_port = proxy_info->port;
            // SOCKS still doesn't define RFC for SSL security (https://tools.ietf.org/html/draft-ietf-aft-socks-ssl-00) but Kerberos6 authentication is supported
            if (proxy_info->type == tnet_proxy_type_http || proxy_info->type == tnet_proxy_type_socks4 || proxy_info->type == tnet_proxy_type_socks4a || proxy_info->type == tnet_proxy_type_socks5) {
                // Send CONNET to the proxy using unsecure connection then begin SSL handshaking if needed
                TNET_SOCKET_TYPE_UNSET(to_type, TLS); // Make the type unsecure (will keep other flags-e.g. IP version-)
                TNET_SOCKET_TYPE_SET(to_type, TCP); // Use plain TCP
            }
        }
        else {
            // Not an error.
            TSK_DEBUG_INFO("No proxy plugin to handle network transport type = %d", type);
            use_proxy = tsk_false;
        }
    }
    
    TSK_DEBUG_INFO("tnet_transport_connectto_3(host=%s, port=%d, type=%d, fd=%d, use_proxy=%d, to_host=%s, to_port=%d, to_type=%d, proxy_type=%d)" , host, port, type, fd, use_proxy, to_host, to_port, to_type, proxy_info ? proxy_info->type : 0);
    
    /* Init destination sockaddr fields */
    if ((status = tnet_sockaddr_init(to_host, to_port, to_type, &to))) {
        TSK_DEBUG_ERROR("Invalid HOST/PORT [%s/%u]", host, port);
        goto bail;
    }
    if (TNET_SOCKET_TYPE_IS_IPV46(type)) {
        /* Update the type (unambiguously) */
        if (to.ss_family == AF_INET6) {
            TNET_SOCKET_TYPE_SET_IPV6Only(type);
        }
        else {
            TNET_SOCKET_TYPE_SET_IPV4Only(type);
        }
    }
    
    /*
     * STREAM ==> create new socket and connect it to the remote host.
     * DGRAM ==> connect the master to the remote host.
     */
    if (fd == TNET_INVALID_FD) {
        // Create client socket descriptor.
        if ((status = tnet_sockfd_init(transport->local_host, TNET_SOCKET_PORT_ANY, to_type, &fd))) {
            TSK_DEBUG_ERROR("Failed to create new sockfd.");
            goto bail;
        }
    }
    
    if ((status = tnet_sockfd_connectto(fd, (const struct sockaddr_storage *)&to))) {
        if (fd != transport->master->fd) {
            tnet_sockfd_close(&fd);
        }
        goto bail;
    }
    else {
        static const tsk_bool_t __isClient = tsk_true;
        if (TNET_SOCKET_TYPE_IS_TLS(to_type) || TNET_SOCKET_TYPE_IS_WSS(to_type)) {
#if HAVE_OPENSSL
            tls_handle = tnet_tls_socket_create(fd, transport->tls.ctx_client);
            if (socket) {
                TSK_OBJECT_SAFE_FREE(socket->tlshandle);
                socket->tlshandle = tsk_object_ref(tls_handle);
            }
            if ((status = tnet_tls_socket_connect(tls_handle))) {
                tnet_sockfd_close(&fd);
                goto bail;
            }
#endif
        }
        /* Add the socket */
        // socket must be added after connect() otherwise many Linux systems will return POLLHUP as the fd is not active yet
        if ((status = tnet_transport_add_socket_2(handle, fd, to_type, owe_socket, __isClient, tls_handle, host, port, proxy_info))) {
            TNET_PRINT_LAST_ERROR("Failed to add new socket");
            tnet_sockfd_close(&fd);
            goto bail;
        }
    }
    
bail:
    TSK_OBJECT_SAFE_FREE(tls_handle);
    TSK_OBJECT_SAFE_FREE(proxy_info);
    return status == 0 ? fd : TNET_INVALID_FD;
}