Beispiel #1
0
/**
 * Add TURN Permission for a peer
 *
 * @param turnc TURN Client
 * @param peer  Peer IP-address
 * @param ph    Permission handler
 * @param arg   Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int turnc_add_perm(struct turnc *turnc, const struct sa *peer,
		   turnc_perm_h *ph, void *arg)
{
	struct perm *perm;
	int err;

	if (!turnc || !peer)
		return EINVAL;

	if (perm_find(turnc, peer))
		return 0;

	perm = mem_zalloc(sizeof(*perm), destructor);
	if (!perm)
		return ENOMEM;

	hash_append(turnc->perms, sa_hash(peer, SA_ADDR), &perm->he, perm);
	tmr_init(&perm->tmr);
	perm->peer = *peer;
	perm->turnc = turnc;
	perm->ph = ph;
	perm->arg = arg;

	err = createperm_request(perm, true);
	if (err)
		mem_deref(perm);

	return err;
}
Beispiel #2
0
static void timeout(void *arg)
{
	struct perm *perm = arg;
	int err;

	err = createperm_request(perm, true);
	if (err)
		perm->turnc->th(err, 0, NULL, NULL, NULL, NULL,
				perm->turnc->arg);
}
Beispiel #3
0
static void createperm_resp_handler(int err, uint16_t scode,
				    const char *reason,
				    const struct stun_msg *msg, void *arg)
{
	struct perm *perm = arg;

	if (err || turnc_request_loops(&perm->ls, scode))
		goto out;

	switch (scode) {

	case 0:
		tmr_start(&perm->tmr, PERM_REFRESH * 1000, timeout, perm);
		if (perm->ph) {
			perm->ph(perm->arg);
			perm->ph  = NULL;
			perm->arg = NULL;
		}
		return;

	case 401:
	case 438:
		err = turnc_keygen(perm->turnc, msg);
		if (err)
			break;

		err = createperm_request(perm, false);
		if (err)
			break;

		return;

	default:
		break;
	}

 out:
	perm->turnc->th(err, scode, reason, NULL, NULL, msg, perm->turnc->arg);
}
Beispiel #4
0
static bool request_handler(struct restund_msgctx *ctx, int proto, void *sock,
			    const struct sa *src, const struct sa *dst,
			    const struct stun_msg *msg)
{
	const uint16_t met = stun_msg_method(msg);
	struct allocation *al;
	int err = 0;

	switch (met) {

	case STUN_METHOD_ALLOCATE:
	case STUN_METHOD_REFRESH:
	case STUN_METHOD_CREATEPERM:
	case STUN_METHOD_CHANBIND:
		break;

	default:
		return false;
	}

	if (ctx->ua.typec > 0) {
		err = stun_ereply(proto, sock, src, 0, msg,
				  420, "Unknown Attribute",
				  ctx->key, ctx->keylen, ctx->fp, 2,
				  STUN_ATTR_UNKNOWN_ATTR, &ctx->ua,
				  STUN_ATTR_SOFTWARE, restund_software);
		goto out;
	}

	al = allocation_find(proto, src, dst);

	if (!al && met != STUN_METHOD_ALLOCATE) {
		restund_debug("turn: allocation does not exist\n");
		err = stun_ereply(proto, sock, src, 0, msg,
				  437, "Allocation Mismatch",
				  ctx->key, ctx->keylen, ctx->fp, 1,
				  STUN_ATTR_SOFTWARE, restund_software);
		goto out;
	}

	if (al && al->username && ctx->key) {

		struct stun_attr *usr = stun_msg_attr(msg, STUN_ATTR_USERNAME);

		if (!usr || strcmp(usr->v.username, al->username)) {
			restund_debug("turn: wrong credetials\n");
			err = stun_ereply(proto, sock, src, 0, msg,
					  441, "Wrong Credentials",
					  ctx->key, ctx->keylen, ctx->fp, 1,
					  STUN_ATTR_SOFTWARE,restund_software);
			goto out;
		}
	}

	switch (met) {

	case STUN_METHOD_ALLOCATE:
		allocate_request(&turnd, al, ctx, proto, sock, src, dst, msg);
		break;

	case STUN_METHOD_REFRESH:
		refresh_request(&turnd, al, ctx, proto, sock, src, msg);
		break;

	case STUN_METHOD_CREATEPERM:
		createperm_request(al, ctx, proto, sock, src, msg);
		break;

	case STUN_METHOD_CHANBIND:
		chanbind_request(al, ctx, proto, sock, src, msg);
		break;
	}

 out:
	if (err) {
		restund_warning("turn reply error: %m\n", err);
	}

	return true;
}