Exemplo n.º 1
0
/*
 * This callback is called by SSL socket when pending accept() operation
 * has completed.
 */
static pj_bool_t on_accept_complete(pj_ssl_sock_t *ssock,
				    pj_ssl_sock_t *new_ssock,
				    const pj_sockaddr_t *src_addr,
				    int src_addr_len)
{
    struct tls_listener *listener;
    struct tls_transport *tls;
    char addr[PJ_INET6_ADDRSTRLEN+10];
    pj_status_t status;

    PJ_UNUSED_ARG(src_addr_len);

    listener = (struct tls_listener*) pj_ssl_sock_get_user_data(ssock);

    PJ_ASSERT_RETURN(new_ssock, PJ_TRUE);

    PJ_LOG(4,(listener->factory.obj_name, 
	      "TLS listener %.*s:%d: got incoming TLS connection "
	      "from %s, sock=%d",
	      (int)listener->factory.addr_name.host.slen,
	      listener->factory.addr_name.host.ptr,
	      listener->factory.addr_name.port,
	      pj_sockaddr_print(src_addr, addr, sizeof(addr), 3),
	      new_ssock));

    /* 
     * Incoming connection!
     * Create TLS transport for the new socket.
     */
    status = tls_create( listener, NULL, new_ssock, PJ_TRUE,
			 (const pj_sockaddr_in*)&listener->factory.local_addr,
			 (const pj_sockaddr_in*)src_addr, &tls);
    
    if (status == PJ_SUCCESS) {
	/* Set the "pending" SSL socket user data */
	pj_ssl_sock_set_user_data(new_ssock, tls);

	status = tls_start_read(tls);
	if (status != PJ_SUCCESS) {
	    PJ_LOG(3,(tls->base.obj_name, "New transport cancelled"));
	    tls_destroy(&tls->base, status);
	} else {
	    /* Start keep-alive timer */
	    if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) {
		pj_time_val delay = {PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0};
		pjsip_endpt_schedule_timer(listener->endpt, 
					   &tls->ka_timer, 
					   &delay);
		tls->ka_timer.id = PJ_TRUE;
		pj_gettimeofday(&tls->last_activity);
	    }
	}
    }

    return PJ_TRUE;
}
Exemplo n.º 2
0
/* 
 * Callback from ioqueue when packet is sent.
 */
static pj_bool_t on_data_sent(pj_ssl_sock_t *ssock,
			      pj_ioqueue_op_key_t *op_key,
			      pj_ssize_t bytes_sent)
{
    struct tls_transport *tls = (struct tls_transport*) 
    				pj_ssl_sock_get_user_data(ssock);
    pjsip_tx_data_op_key *tdata_op_key = (pjsip_tx_data_op_key*)op_key;

    /* Note that op_key may be the op_key from keep-alive, thus
     * it will not have tdata etc.
     */

    tdata_op_key->tdata = NULL;

    if (tdata_op_key->callback) {
	/*
	 * Notify sip_transport.c that packet has been sent.
	 */
	if (bytes_sent == 0)
	    bytes_sent = -PJ_RETURN_OS_ERROR(OSERR_ENOTCONN);

	tdata_op_key->callback(&tls->base, tdata_op_key->token, bytes_sent);

	/* Mark last activity time */
	pj_gettimeofday(&tls->last_activity);

    }

    /* Check for error/closure */
    if (bytes_sent <= 0) {
	pj_status_t status;

	PJ_LOG(5,(tls->base.obj_name, "TLS send() error, sent=%d", 
		  bytes_sent));

	status = (bytes_sent == 0) ? PJ_RETURN_OS_ERROR(OSERR_ENOTCONN) :
				     -bytes_sent;

	tls_init_shutdown(tls, status);

	return PJ_FALSE;
    }
    
    return PJ_TRUE;
}
Exemplo n.º 3
0
static pj_bool_t ssl_on_data_sent(pj_ssl_sock_t *ssock,
				  pj_ioqueue_op_key_t *op_key,
				  pj_ssize_t sent)
{
    struct test_state *st = (struct test_state*)
			     pj_ssl_sock_get_user_data(ssock);
    PJ_UNUSED_ARG(op_key);

    if (sent < 0) {
	st->err = -sent;
    } else {
	st->sent += sent;

	/* Send more if any */
	while (st->sent < st->send_str_len) {
	    pj_ssize_t size;
	    pj_status_t status;

	    size = st->send_str_len - st->sent;
	    status = pj_ssl_sock_send(ssock, (pj_ioqueue_op_key_t*)&st->send_key, 
				      st->send_str + st->sent, &size, 0);
	    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
		app_perror("...ERROR pj_ssl_sock_send()", status);
		st->err = status;
		break;
	    }

	    if (status == PJ_SUCCESS)
		st->sent += size;
	    else
		break;
	}
    }

    if (st->err != PJ_SUCCESS) {
	pj_ssl_sock_close(ssock);
	if (!st->is_server)
	    clients_num--;
	return PJ_FALSE;
    }

    return PJ_TRUE;
}
Exemplo n.º 4
0
/*
 * This callback is called by SSL socket when pending accept() operation
 * has completed.
 */
static pj_bool_t on_accept_complete(pj_ssl_sock_t *ssock,
				    pj_ssl_sock_t *new_ssock,
				    const pj_sockaddr_t *src_addr,
				    int src_addr_len)
{
    struct tls_listener *listener;
    struct tls_transport *tls;
    pj_ssl_sock_info ssl_info;
    char addr[PJ_INET6_ADDRSTRLEN+10];
    pjsip_tp_state_callback state_cb;
    pj_bool_t is_shutdown;
    pj_status_t status;

    PJ_UNUSED_ARG(src_addr_len);

    listener = (struct tls_listener*) pj_ssl_sock_get_user_data(ssock);

    PJ_ASSERT_RETURN(new_ssock, PJ_TRUE);

    PJ_LOG(4,(listener->factory.obj_name, 
	      "TLS listener %.*s:%d: got incoming TLS connection "
	      "from %s, sock=%d",
	      (int)listener->factory.addr_name.host.slen,
	      listener->factory.addr_name.host.ptr,
	      listener->factory.addr_name.port,
	      pj_sockaddr_print(src_addr, addr, sizeof(addr), 3),
	      new_ssock));

    /* Retrieve SSL socket info, close the socket if this is failed
     * as the SSL socket info availability is rather critical here.
     */
    status = pj_ssl_sock_get_info(new_ssock, &ssl_info);
    if (status != PJ_SUCCESS) {
	pj_ssl_sock_close(new_ssock);
	return PJ_TRUE;
    }

    /* 
     * Incoming connection!
     * Create TLS transport for the new socket.
     */
    status = tls_create( listener, NULL, new_ssock, PJ_TRUE,
			 (const pj_sockaddr_in*)&listener->factory.local_addr,
			 (const pj_sockaddr_in*)src_addr, NULL, &tls);
    
    if (status != PJ_SUCCESS)
	return PJ_TRUE;

    /* Set the "pending" SSL socket user data */
    pj_ssl_sock_set_user_data(new_ssock, tls);

    /* Prevent immediate transport destroy as application may access it 
     * (getting info, etc) in transport state notification callback.
     */
    pjsip_transport_add_ref(&tls->base);

    /* If there is verification error and verification is mandatory, shutdown
     * and destroy the transport.
     */
    if (ssl_info.verify_status && listener->tls_setting.verify_client) {
	if (tls->close_reason == PJ_SUCCESS) 
	    tls->close_reason = PJSIP_TLS_ECERTVERIF;
	pjsip_transport_shutdown(&tls->base);
    }

    /* Notify transport state to application */
    state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr);
    if (state_cb) {
	pjsip_transport_state_info state_info;
	pjsip_tls_state_info tls_info;
	pjsip_transport_state tp_state;

	/* Init transport state info */
	pj_bzero(&tls_info, sizeof(tls_info));
	pj_bzero(&state_info, sizeof(state_info));
	tls_info.ssl_sock_info = &ssl_info;
	state_info.ext_info = &tls_info;

	/* Set transport state based on verification status */
	if (ssl_info.verify_status && listener->tls_setting.verify_client)
	{
	    tp_state = PJSIP_TP_STATE_DISCONNECTED;
	    state_info.status = PJSIP_TLS_ECERTVERIF;
	} else {
	    tp_state = PJSIP_TP_STATE_CONNECTED;
	    state_info.status = PJ_SUCCESS;
	}

	(*state_cb)(&tls->base, tp_state, &state_info);
    }

    /* Release transport reference. If transport is shutting down, it may
     * get destroyed here.
     */
    is_shutdown = tls->base.is_shutdown;
    pjsip_transport_dec_ref(&tls->base);
    if (is_shutdown)
	return PJ_TRUE;


    status = tls_start_read(tls);
    if (status != PJ_SUCCESS) {
	PJ_LOG(3,(tls->base.obj_name, "New transport cancelled"));
	tls_init_shutdown(tls, status);
	tls_destroy(&tls->base, status);
    } else {
	/* Start keep-alive timer */
	if (PJSIP_TLS_KEEP_ALIVE_INTERVAL) {
	    pj_time_val delay = {PJSIP_TLS_KEEP_ALIVE_INTERVAL, 0};
	    pjsip_endpt_schedule_timer(listener->endpt, 
				       &tls->ka_timer, 
				       &delay);
	    tls->ka_timer.id = PJ_TRUE;
	    pj_gettimeofday(&tls->last_activity);
	}
    }

    return PJ_TRUE;
}
Exemplo n.º 5
0
static pj_bool_t ssl_on_data_read(pj_ssl_sock_t *ssock,
				  void *data,
				  pj_size_t size,
				  pj_status_t status,
				  pj_size_t *remainder)
{
    struct test_state *st = (struct test_state*) 
			     pj_ssl_sock_get_user_data(ssock);

    PJ_UNUSED_ARG(remainder);
    PJ_UNUSED_ARG(data);

    if (size > 0) {
	pj_size_t consumed;

	/* Set random remainder */
	*remainder = pj_rand() % 100;

	/* Apply zero remainder if:
	 * - remainder is less than size, or
	 * - connection closed/error
	 * - echo/check_eco set
	 */
	if (*remainder > size || status != PJ_SUCCESS || st->echo || st->check_echo)
	    *remainder = 0;

	consumed = size - *remainder;
	st->recv += consumed;

	//printf("%.*s", consumed, (char*)data);

	pj_memmove(data, (char*)data + consumed, *remainder);

	/* Echo data when specified to */
	if (st->echo) {
	    pj_ssize_t size_ = consumed;
	    status = pj_ssl_sock_send(ssock, (pj_ioqueue_op_key_t*)&st->send_key, data, &size_, 0);
	    if (status != PJ_SUCCESS && status != PJ_EPENDING) {
		app_perror("...ERROR pj_ssl_sock_send()", status);
		goto on_return;
	    }

	    if (status == PJ_SUCCESS)
		st->sent += size_;
	}

	/* Verify echoed data when specified to */
	if (st->check_echo) {
	    if (!st->check_echo_ptr)
		st->check_echo_ptr = st->send_str;

	    if (pj_memcmp(st->check_echo_ptr, data, consumed)) {
		status = PJ_EINVAL;
		app_perror("...ERROR echoed data not exact", status);
		goto on_return;
	    }
	    st->check_echo_ptr += consumed;

	    /* Echo received completely */
	    if (st->send_str_len == st->recv) {
		pj_ssl_sock_info info;
		char buf[64];

		status = pj_ssl_sock_get_info(ssock, &info);
		if (status != PJ_SUCCESS) {
		    app_perror("...ERROR pj_ssl_sock_get_info()", status);
		    goto on_return;
		}

		pj_sockaddr_print((pj_sockaddr_t*)&info.local_addr, buf, sizeof(buf), 1);
		PJ_LOG(3, ("", "...%s successfully recv %d bytes echo", buf, st->recv));
		st->done = PJ_TRUE;
	    }
	}
    }

    if (status != PJ_SUCCESS) {
	if (status == PJ_EEOF) {
	    status = PJ_SUCCESS;
	    st->done = PJ_TRUE;
	} else {
	    app_perror("...ERROR ssl_on_data_read()", status);
	}
    }

on_return:
    st->err = status;

    if (st->err != PJ_SUCCESS || st->done) {
	pj_ssl_sock_close(ssock);
	if (!st->is_server)
	    clients_num--;
	return PJ_FALSE;
    }

    return PJ_TRUE;
}
Exemplo n.º 6
0
static pj_bool_t ssl_on_accept_complete(pj_ssl_sock_t *ssock,
					pj_ssl_sock_t *newsock,
					const pj_sockaddr_t *src_addr,
					int src_addr_len)
{
    struct test_state *parent_st = (struct test_state*) 
				   pj_ssl_sock_get_user_data(ssock);
    struct test_state *st;
    void *read_buf[1];
    pj_ssl_sock_info info;
    char buf[64];
    pj_status_t status;

    PJ_UNUSED_ARG(src_addr_len);

    /* Duplicate parent test state to newly accepted test state */
    st = pj_pool_zalloc(parent_st->pool, sizeof(struct test_state));
    *st = *parent_st;
    pj_ssl_sock_set_user_data(newsock, st);

    status = pj_ssl_sock_get_info(newsock, &info);
    if (status != PJ_SUCCESS) {
	app_perror("...ERROR pj_ssl_sock_get_info()", status);
	goto on_return;
    }

    pj_sockaddr_print(src_addr, buf, sizeof(buf), 1);
    PJ_LOG(3, ("", "...Accepted connection from %s", buf));

    if (st->is_verbose)
	dump_ssl_info(&info);

    /* Start reading data */
    read_buf[0] = st->read_buf;
    status = pj_ssl_sock_start_read2(newsock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0);
    if (status != PJ_SUCCESS) {
	app_perror("...ERROR pj_ssl_sock_start_read2()", status);
	goto on_return;
    }

    /* Start sending data */
    while (st->sent < st->send_str_len) {
	pj_ssize_t size;

	size = st->send_str_len - st->sent;
	status = pj_ssl_sock_send(newsock, (pj_ioqueue_op_key_t*)&st->send_key, 
				  st->send_str + st->sent, &size, 0);
	if (status != PJ_SUCCESS && status != PJ_EPENDING) {
	    app_perror("...ERROR pj_ssl_sock_send()", status);
	    goto on_return;
	}

	if (status == PJ_SUCCESS)
	    st->sent += size;
	else
	    break;
    }

on_return:
    st->err = status;

    if (st->err != PJ_SUCCESS) {
	pj_ssl_sock_close(newsock);
	return PJ_FALSE;
    }

    return PJ_TRUE;
}
Exemplo n.º 7
0
static pj_bool_t ssl_on_connect_complete(pj_ssl_sock_t *ssock,
					 pj_status_t status)
{
    struct test_state *st = (struct test_state*) 
		    	    pj_ssl_sock_get_user_data(ssock);
    void *read_buf[1];
    pj_ssl_sock_info info;
    char buf1[64], buf2[64];

    if (status != PJ_SUCCESS) {
	app_perror("...ERROR ssl_on_connect_complete()", status);
	goto on_return;
    }

    status = pj_ssl_sock_get_info(ssock, &info);
    if (status != PJ_SUCCESS) {
	app_perror("...ERROR pj_ssl_sock_get_info()", status);
	goto on_return;
    }

    pj_sockaddr_print((pj_sockaddr_t*)&info.local_addr, buf1, sizeof(buf1), 1);
    pj_sockaddr_print((pj_sockaddr_t*)&info.remote_addr, buf2, sizeof(buf2), 1);
    PJ_LOG(3, ("", "...Connected %s -> %s!", buf1, buf2));

    if (st->is_verbose)
	dump_ssl_info(&info);

    /* Start reading data */
    read_buf[0] = st->read_buf;
    status = pj_ssl_sock_start_read2(ssock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0);
    if (status != PJ_SUCCESS) {
	app_perror("...ERROR pj_ssl_sock_start_read2()", status);
	goto on_return;
    }

    /* Start sending data */
    while (st->sent < st->send_str_len) {
	pj_ssize_t size;

	size = st->send_str_len - st->sent;
	status = pj_ssl_sock_send(ssock, (pj_ioqueue_op_key_t*)&st->send_key, 
				  st->send_str + st->sent, &size, 0);
	if (status != PJ_SUCCESS && status != PJ_EPENDING) {
	    app_perror("...ERROR pj_ssl_sock_send()", status);
	    goto on_return;
	}

	if (status == PJ_SUCCESS)
	    st->sent += size;
	else
	    break;
    }

on_return:
    st->err = status;

    if (st->err != PJ_SUCCESS) {
	pj_ssl_sock_close(ssock);
	clients_num--;
	return PJ_FALSE;
    }

    return PJ_TRUE;
}