示例#1
0
/* Set the socket handle of the transport */
static void udp_set_socket(struct udp_transport *tp,
                           pj_sock_t sock,
                           const pjsip_host_port *a_name)
{
    long sobuf_size;
    pj_status_t status;

    /* Adjust socket rcvbuf size */
    sobuf_size = PJSIP_UDP_SO_RCVBUF_SIZE;
    status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_RCVBUF(),
                                &sobuf_size, sizeof(sobuf_size));
    if (status != PJ_SUCCESS) {
        char errmsg[PJ_ERR_MSG_SIZE];
        pj_strerror(status, errmsg, sizeof(errmsg));
        PJ_LOG(4,(THIS_FILE, "Error setting SO_RCVBUF: %s [%d]", errmsg,
                  status));
    }

    /* Adjust socket sndbuf size */
    sobuf_size = PJSIP_UDP_SO_SNDBUF_SIZE;
    status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_SNDBUF(),
                                &sobuf_size, sizeof(sobuf_size));
    if (status != PJ_SUCCESS) {
        char errmsg[PJ_ERR_MSG_SIZE];
        pj_strerror(status, errmsg, sizeof(errmsg));
        PJ_LOG(4,(THIS_FILE, "Error setting SO_SNDBUF: %s [%d]", errmsg,
                  status));
    }

    /* Set the socket. */
    tp->sock = sock;

    /* Init address name (published address) */
    udp_set_pub_name(tp, a_name);
}
示例#2
0
/*
 * Restart transport.
 *
 * If option is KEEP_SOCKET, just re-activate ioqueue operation.
 *
 * If option is DESTROY_SOCKET:
 *  - if socket is specified, replace.
 *  - if socket is not specified, create and replace.
 */
PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
					        unsigned option,
						pj_sock_t sock,
						const pj_sockaddr_in *local,
						const pjsip_host_port *a_name)
{
    struct udp_transport *tp;
    pj_status_t status;

    PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL);
    /* Flag must be specified */
    PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL);

    tp = (struct udp_transport*) transport;

    if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
	char addr_buf[PJ_INET6_ADDRSTRLEN];
	pjsip_host_port bound_name;

	/* Request to recreate transport */

	/* Destroy existing socket, if any. */
	if (tp->key) {
	    /* This implicitly closes the socket */
	    pj_ioqueue_unregister(tp->key);
	    tp->key = NULL;
	} else {
	    /* Close socket. */
	    if (tp->sock && tp->sock != PJ_INVALID_SOCKET) {
		pj_sock_close(tp->sock);
		tp->sock = PJ_INVALID_SOCKET;
	    }
	}
	tp->sock = PJ_INVALID_SOCKET;

	/* Create the socket if it's not specified */
	if (sock == PJ_INVALID_SOCKET) {
	    status = create_socket(pj_AF_INET(), local, 
				   sizeof(pj_sockaddr_in), &sock);
	    if (status != PJ_SUCCESS)
		return status;
	}

	/* If transport published name is not specified, calculate it
	 * from the bound address.
	 */
	if (a_name == NULL) {
	    status = get_published_name(sock, addr_buf, sizeof(addr_buf),
					&bound_name);
	    if (status != PJ_SUCCESS) {
		pj_sock_close(sock);
		return status;
	    }

	    a_name = &bound_name;
	}

        /* Init local address. */
        status = pj_sock_getsockname(sock, &tp->base.local_addr, 
				     &tp->base.addr_len);
        if (status != PJ_SUCCESS) {
            pj_sock_close(sock);
            return status;
        }

	/* Assign the socket and published address to transport. */
	udp_set_socket(tp, sock, a_name);

    } else {

	/* For KEEP_SOCKET, transport must have been paused before */
	PJ_ASSERT_RETURN(tp->is_paused, PJ_EINVALIDOP);

	/* If address name is specified, update it */
	if (a_name != NULL)
	    udp_set_pub_name(tp, a_name);
    }

    /* Re-register new or existing socket to ioqueue. */
    status = register_to_ioqueue(tp);
    if (status != PJ_SUCCESS) {
	return status;
    }

    /* Restart async read operation. */
    status = start_async_read(tp);
    if (status != PJ_SUCCESS)
	return status;

    /* Everything has been set up */
    tp->is_paused = PJ_FALSE;

    PJ_LOG(4,(tp->base.obj_name, 
	      "SIP UDP transport restarted, published address is %.*s:%d",
	      (int)tp->base.local_name.host.slen,
	      tp->base.local_name.host.ptr,
	      tp->base.local_name.port));

    return PJ_SUCCESS;
}
示例#3
0
PJ_DEF(pj_status_t) pjsip_udp_transport_restart2(pjsip_transport *transport,
					         unsigned option,
					         pj_sock_t sock,
					         const pj_sockaddr *local,
					         const pjsip_host_port *a_name)
{
    struct udp_transport *tp;
    pj_status_t status;
    char addr[PJ_INET6_ADDRSTRLEN+10];
    int i;

    PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL);
    /* Flag must be specified */
    PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL);

    tp = (struct udp_transport*) transport;

    /* Pause the transport first, so that any active read loop spin will
     * quit as soon as possible.
     */
    tp->is_paused = PJ_TRUE;
    
    if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
	char addr_buf[PJ_INET6_ADDRSTRLEN];
	pjsip_host_port bound_name;

	/* Request to recreate transport */

	/* Destroy existing socket, if any. */
	if (tp->key) {
	    /* This implicitly closes the socket */
	    pj_ioqueue_unregister(tp->key);
	    tp->key = NULL;
	} else {
	    /* Close socket. */
	    if (tp->sock && tp->sock != PJ_INVALID_SOCKET) {
		pj_sock_close(tp->sock);
		tp->sock = PJ_INVALID_SOCKET;
	    }
	}
	tp->sock = PJ_INVALID_SOCKET;

	/* Create the socket if it's not specified */
	if (sock == PJ_INVALID_SOCKET) {
	    status = create_socket(local?local->addr.sa_family:pj_AF_UNSPEC(), 
				   local, local?pj_sockaddr_get_len(local):0, 
				   &sock);
	    if (status != PJ_SUCCESS)
		return status;
	}

	/* If transport published name is not specified, calculate it
	 * from the bound address.
	 */
	if (a_name == NULL) {
	    status = get_published_name(sock, addr_buf, sizeof(addr_buf),
					&bound_name);
	    if (status != PJ_SUCCESS) {
		pj_sock_close(sock);
		return status;
	    }

	    a_name = &bound_name;
	}

        /* Init local address. */
        status = pj_sock_getsockname(sock, &tp->base.local_addr, 
				     &tp->base.addr_len);
        if (status != PJ_SUCCESS) {
            pj_sock_close(sock);
            return status;
        }

	/* Assign the socket and published address to transport. */
	udp_set_socket(tp, sock, a_name);

    } else {

	/* For KEEP_SOCKET, transport must have been paused before */
	PJ_ASSERT_RETURN(tp->is_paused, PJ_EINVALIDOP);

	/* If address name is specified, update it */
	if (a_name != NULL)
	    udp_set_pub_name(tp, a_name);
    }

    /* Make sure all udp_on_read_complete() loop spin are stopped */
    do {
	pj_thread_sleep(1);
    } while (tp->read_loop_spin);

    /* Re-register new or existing socket to ioqueue. */
    status = register_to_ioqueue(tp);
    if (status != PJ_SUCCESS) {
	return status;
    }

    /* Re-init op_key. */
    for (i = 0; i < tp->rdata_cnt; ++i) {
	pj_ioqueue_op_key_init(&tp->rdata[i]->tp_info.op_key.op_key,
			       sizeof(pj_ioqueue_op_key_t));
    }

    /* Restart async read operation. */
    status = start_async_read(tp);
    if (status != PJ_SUCCESS)
	return status;

    /* Everything has been set up */
    tp->is_paused = PJ_FALSE;

    PJ_LOG(4, (tp->base.obj_name,
	       "SIP UDP transport restarted, published address is %s",
	       pj_addr_str_print(&tp->base.local_name.host,
				 tp->base.local_name.port,
				 addr, sizeof(addr), 1)));

    return PJ_SUCCESS;
}