示例#1
0
/*
 * Create new allocation.
 */
PJ_DEF(pj_status_t) pj_turn_allocation_create(pj_turn_transport *transport,
					      const pj_sockaddr_t *src_addr,
					      unsigned src_addr_len,
					      const pj_stun_rx_data *rdata,
					      pj_stun_session *srv_sess,
					      pj_turn_allocation **p_alloc)
{
    pj_turn_srv *srv = transport->listener->server;
    const pj_stun_msg *msg = rdata->msg;
    pj_pool_t *pool;
    alloc_request req;
    pj_turn_allocation *alloc;
    pj_stun_session_cb sess_cb;
    char str_tmp[80];
    pj_status_t status;

    /* Parse ALLOCATE request */
    status = parse_allocate_req(&req, srv_sess, rdata, src_addr, src_addr_len);
    if (status != PJ_SUCCESS)
	return status;

    pool = pj_pool_create(srv->core.pf, "alloc%p", 1000, 1000, NULL);

    /* Init allocation structure */
    alloc = PJ_POOL_ZALLOC_T(pool, pj_turn_allocation);
    alloc->pool = pool;
    alloc->obj_name = pool->obj_name;
    alloc->relay.tp.sock = PJ_INVALID_SOCKET;
    alloc->server = transport->listener->server;

    alloc->bandwidth = req.bandwidth;

    /* Set transport */
    alloc->transport = transport;
    pj_turn_transport_add_ref(transport, alloc);

    alloc->hkey.tp_type = transport->listener->tp_type;
    pj_memcpy(&alloc->hkey.clt_addr, src_addr, src_addr_len);

    status = pj_lock_create_recursive_mutex(pool, alloc->obj_name,
					    &alloc->lock);
    if (status != PJ_SUCCESS) {
	goto on_error;
    }

    /* Create peer hash table */
    alloc->peer_table = pj_hash_create(pool, PEER_TABLE_SIZE);

    /* Create channel hash table */
    alloc->ch_table = pj_hash_create(pool, PEER_TABLE_SIZE);

    /* Print info */
    pj_ansi_strcpy(alloc->info,
		   pj_turn_tp_type_name(transport->listener->tp_type));
    alloc->info[3] = ':';
    pj_sockaddr_print(src_addr, alloc->info+4, sizeof(alloc->info)-4, 3);

    /* Create STUN session to handle STUN communication with client */
    pj_bzero(&sess_cb, sizeof(sess_cb));
    sess_cb.on_send_msg = &stun_on_send_msg;
    sess_cb.on_rx_request = &stun_on_rx_request;
    sess_cb.on_rx_indication = &stun_on_rx_indication;
    status = pj_stun_session_create(&srv->core.stun_cfg, alloc->obj_name,
				    &sess_cb, PJ_FALSE, NULL, &alloc->sess);
    if (status != PJ_SUCCESS) {
	goto on_error;
    }

    /* Attach to STUN session */
    pj_stun_session_set_user_data(alloc->sess, alloc);

    /* Init authentication credential */
    status = init_cred(alloc, msg);
    if (status != PJ_SUCCESS) {
	goto on_error;
    }

    /* Attach authentication credential to STUN session */
    pj_stun_session_set_credential(alloc->sess, PJ_STUN_AUTH_LONG_TERM,
				   &alloc->cred);

    /* Create the relay resource */
    status = create_relay(srv, alloc, msg, &req, &alloc->relay);
    if (status != PJ_SUCCESS) {
	goto on_error;
    }

    /* Register this allocation */
    pj_turn_srv_register_allocation(srv, alloc);

    /* Respond to ALLOCATE request */
    status = send_allocate_response(alloc, srv_sess, transport, rdata);
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Done */
    pj_sockaddr_print(&alloc->relay.hkey.addr, str_tmp,
		      sizeof(str_tmp), 3);
    PJ_LOG(4,(alloc->obj_name, "Client %s created, relay addr=%s:%s",
	      alloc->info, pj_turn_tp_type_name(req.tp_type), str_tmp));

    /* Success */
    *p_alloc = alloc;
    return PJ_SUCCESS;

on_error:
    /* Send reply to the ALLOCATE request */
    pj_strerror(status, str_tmp, sizeof(str_tmp));
    pj_stun_session_respond(srv_sess, rdata, PJ_STUN_SC_BAD_REQUEST, str_tmp,
			    transport, PJ_TRUE, src_addr, src_addr_len);

    /* Cleanup */
    destroy_allocation(alloc);
    return status;
}
static void console_main(void)
{
    while (!g.quit) {
	char input[32];
	struct peer *peer;
	pj_status_t status;

	menu();

	if (fgets(input, sizeof(input), stdin) == NULL)
	    break;
	
	switch (input[0]) {
	case 'a':
	    create_relay();
	    break;
	case 'd':
	    pj_pool_factory_dump(&g.cp.factory, PJ_TRUE);
	    break;
	case 's':
	    if (g.relay == NULL) {
		puts("Error: no relay");
		continue;
	    }
	    if (input[1]!='s')
		peer = &g.peer[0];
	    else
		peer = &g.peer[1];

	    strcpy(input, "Hello from client");
	    status = pj_turn_sock_sendto(g.relay, (const pj_uint8_t*)input, 
					strlen(input)+1, 
					&peer->mapped_addr, 
					pj_sockaddr_get_len(&peer->mapped_addr));
	    if (status != PJ_SUCCESS)
		my_perror("turn_udp_sendto() failed", status);
	    break;
	case 'b':
	    if (g.relay == NULL) {
		puts("Error: no relay");
		continue;
	    }
	    if (input[1]!='b')
		peer = &g.peer[0];
	    else
		peer = &g.peer[1];

	    status = pj_turn_sock_bind_channel(g.relay, &peer->mapped_addr,
					      pj_sockaddr_get_len(&peer->mapped_addr));
	    if (status != PJ_SUCCESS)
		my_perror("turn_udp_bind_channel() failed", status);
	    break;
	case 'p':
	    if (g.relay == NULL) {
		puts("Error: no relay");
		continue;
	    }
	    if (input[1]!='p')
		peer = &g.peer[0];
	    else
		peer = &g.peer[1];

	    status = pj_turn_sock_set_perm(g.relay, 1, &peer->mapped_addr, 1);
	    if (status != PJ_SUCCESS)
		my_perror("pj_turn_sock_set_perm() failed", status);
	    break;
	case 'x':
	    if (g.relay == NULL) {
		puts("Error: no relay");
		continue;
	    }
	    destroy_relay();
	    break;
	case '0':
	case '1':
	    if (g.relay == NULL) {
		puts("No relay");
		break;
	    }
	    peer = &g.peer[input[0]-'0'];
	    sprintf(input, "Hello from peer%d", input[0]-'0');
	    pj_stun_sock_sendto(peer->stun_sock, NULL, input, strlen(input)+1, 0,
				&g.relay_addr, pj_sockaddr_get_len(&g.relay_addr));
	    break;
	case 'q':
	    g.quit = PJ_TRUE;
	    break;
	}
    }
}