示例#1
0
/** read from a mbuf.
 * (internal openssl use via the tls_mbuf method)
 * @return bytes read on success (0< ret <=dst_len), -1 on empty buffer & sets
 *  should_retry_read, -1 on some other errors (w/o should_retry_read set).
 */
static int tls_bio_mbuf_read(BIO* b, char* dst, int dst_len)
{
	struct tls_bio_mbuf_data* d;
	struct tls_mbuf* rd;
	int ret;

	ret = 0;
	if (likely(dst)) {
#if OPENSSL_VERSION_NUMBER < 0x010100000L
		d = b->ptr;
#else
		d = BIO_get_data(b);
#endif
		BIO_clear_retry_flags(b);
		if (unlikely(d == 0 || d->rd->buf == 0)) {
			if (d == 0)
				BUG("tls_BIO_mbuf %p: read called with null b->ptr\n", b);
			else {
				/* this form of calling read with a null buffer is used
				   as a shortcut when no data is available =>
				   simulate EAGIAN/WANT_READ */
				TLS_BIO_DBG("read (%p, %p, %d) called with null read buffer"
						"(%p->%p) => simulating EAGAIN/WANT_READ\n",
						b, dst, dst_len, d, d->rd);
				BIO_set_retry_read(b);
			}
			return -1;
		}
		rd = d->rd;
		if (unlikely(rd->used == rd->pos && dst_len)) {
			/* mimic non-blocking read behaviour */
			TLS_BIO_DBG("read (%p, %p, %d) called with full rd (%d)"
						" => simulating EAGAIN/WANT_READ\n",
						b, dst, dst_len, rd->used);
			BIO_set_retry_read(b);
			return -1;
		}
		ret = MIN_int(rd->used - rd->pos, dst_len);
		/* copy data from rd.buf into dst */
		memcpy(dst, rd->buf+rd->pos, ret);
		TLS_BIO_DBG("read(%p, %p, %d) called with rd=%p pos=%d => %d bytes\n",
						b, dst, dst_len, rd->buf, rd->pos, ret);
		rd->pos += ret;
/*		if (unlikely(rd->pos < rd->used))
			BIO_set_retry_read(b);
*/
	}
	return ret;
}
示例#2
0
/** write to a mbuf.
 * (internal openssl use via the tls_mbuf method)
 * @return bytes written on success (0<= ret <=src_len), -1 on error or buffer
 * full (in this case sets should_retry_write).
 */
static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
{
	struct tls_bio_mbuf_data* d;
	struct tls_mbuf* wr;
	int ret;

	ret = 0;
#if OPENSSL_VERSION_NUMBER < 0x010100000L
	d = b->ptr;
#else
	d = BIO_get_data(b);
#endif
	BIO_clear_retry_flags(b);
	if (unlikely(d == 0 || d->wr->buf == 0)) {
		if (d == 0)
			BUG("tls_BIO_mbuf %p: write called with null b->ptr\n", b);
		else {
			/* this form of calling write with a null buffer is used
			   as a shortcut when no data is available =>
			   simulate EAGAIN/WANT_WRITE */
			TLS_BIO_DBG("write (%p, %p, %d) called with null buffer"
					" => simulating WANT_WRITE\n", b, src, src_len);
			BIO_set_retry_write(b);
		}
		return -1;
	}
	wr = d->wr;
	if (unlikely(wr->size == wr->used && src_len)) {
		/* mimic non-blocking socket behaviour */
		TLS_BIO_DBG("write (%p, %p, %d) called with full wr buffer (%d)"
					" => simulating WANT_WRITE\n", b, src, src_len, wr->used);
		BIO_set_retry_write(b);
		return -1;
	}
	ret = MIN_int(wr->size - wr->used, src_len);
	memcpy(wr->buf + wr->used, src, ret);
	wr->used += ret;
/*	if (unlikely(ret < src_len))
		BIO_set_retry_write();
*/
	TLS_BIO_DBG("write called (%p, %p, %d) => %d\n", b, src, src_len, ret);
	return ret;
}
示例#3
0
int t_append_branches(void) {
	struct cell *t = NULL;
	struct sip_msg *orig_msg = NULL;
	short outgoings;

	int success_branch;

	str current_uri;
	str dst_uri, path, instance, ruid, location_ua;
	struct socket_info* si;
	int q, i, found;
	flag_t backup_bflags = 0;
	flag_t bflags = 0;
	int new_branch, branch_ret, lowest_ret;
	branch_bm_t	added_branches;
	int replies_locked = 0;

	t = get_t();
	if(t == NULL)
	{
		LM_ERR("cannot get transaction\n");
		return -1;
	}

	LM_DBG("transaction %u:%u in status %d\n", t->hash_index, t->label, t->uas.status);

	/* test if transaction has already been canceled */
	if (t->flags & T_CANCELED) {
		ser_error=E_CANCELED;
		return -1;
	}

	if ((t->uas.status >= 200 && t->uas.status<=399)
			|| ((t->uas.status >= 600 && t->uas.status)
				&& !(t->flags & (T_6xx | T_DISABLE_6xx))) ) {
		LM_DBG("transaction %u:%u in status %d: cannot append new branch\n",
				t->hash_index, t->label, t->uas.status);
		return -1;
	}

	/* set the lock on the transaction here */
	LOCK_REPLIES(t);
	replies_locked = 1;
	outgoings = t->nr_of_outgoings;
	orig_msg = t->uas.request;

	LM_DBG("Call %.*s: %d (%d) outgoing branches\n",orig_msg->callid->body.len,
			orig_msg->callid->body.s,outgoings, nr_branches);

	lowest_ret=E_UNSPEC;
	added_branches=0;

	/* it's a "late" branch so the on_branch variable has already been
	reset by previous execution of t_forward_nonack: we use the saved
	   value  */
	if (t->on_branch_delayed) {
		/* tell add_uac that it should run branch route actions */
		set_branch_route(t->on_branch_delayed);
	}

	outgoings = t->nr_of_outgoings;

	/* not really sure that the following is needed */

	set_branch_iterator(nr_branches-1);
	found = 0;
	while((current_uri.s=next_branch( &current_uri.len, &q, &dst_uri, &path,
										&bflags, &si, &ruid, &instance, &location_ua))) {
		LM_DBG("Current uri %.*s\n",current_uri.len, current_uri.s);

		for (i=0; i<nr_branches; i++) {
			if (t->uac[i].ruid.len == ruid.len
					&& !memcmp(t->uac[i].ruid.s, ruid.s, ruid.len)) {
				LM_DBG("branch already added [%.*s]\n", ruid.len, ruid.s);
				found = 1;
				break;
			}
		}
		if (found)
			continue;

		setbflagsval(0, bflags);
		new_branch=add_uac( t, orig_msg, &current_uri,
					(dst_uri.len) ? (&dst_uri) : &current_uri,
					&path, 0, si, orig_msg->fwd_send_flags,
					orig_msg->rcv.proto, (dst_uri.len)?-1:UAC_SKIP_BR_DST_F, &instance,
					&ruid, &location_ua);

		/* test if cancel was received meanwhile */
		if (t->flags & T_CANCELED) goto canceled;

		if (new_branch>=0)
			added_branches |= 1<<new_branch;
		else
			lowest_ret=MIN_int(lowest_ret, new_branch);
	}

	clear_branches();

	LM_DBG("Call %.*s: %d (%d) outgoing branches after clear_branches()\n",
			orig_msg->callid->body.len, orig_msg->callid->body.s,outgoings, nr_branches);
	setbflagsval(0, backup_bflags);

	/* update message flags, if changed in branch route */
	t->uas.request->flags = orig_msg->flags;

	if (added_branches==0) {
		if(lowest_ret!=E_CFG)
			LOG(L_ERR, "ERROR: t_append_branch: failure to add branches\n");
		ser_error=lowest_ret;
		replies_locked = 0;
		UNLOCK_REPLIES(t);
		return lowest_ret;
	}

	ser_error=0; /* clear branch adding errors */
	/* send them out now */
	success_branch=0;
	/* since t_append_branch can only be called from REQUEST_ROUTE, always lock replies */

	for (i=outgoings; i<t->nr_of_outgoings; i++) {
		if (added_branches & (1<<i)) {
			branch_ret=t_send_branch(t, i, orig_msg , 0, 0 /* replies are already locked */ );
			if (branch_ret>=0){ /* some kind of success */
				if (branch_ret==i) { /* success */
					success_branch++;
					if (unlikely(has_tran_tmcbs(t, TMCB_REQUEST_OUT)))
						run_trans_callbacks_with_buf( TMCB_REQUEST_OUT,
								&t->uac[nr_branches].request,
								orig_msg, 0, -orig_msg->REQ_METHOD);
				}
				else /* new branch added */
					added_branches |= 1<<branch_ret;
			}
		}
	}
	if (success_branch<=0) {
		/* return always E_SEND for now
		 * (the real reason could be: denied by onsend routes, blacklisted,
		 *  send failed or any of the errors listed before + dns failed
		 *  when attempting dns failover) */
		ser_error=E_SEND;
		/* else return the last error (?) */
		/* the caller should take care and delete the transaction */
		replies_locked = 0;
		UNLOCK_REPLIES(t);
		return -1;
	}

	ser_error=0; /* clear branch send errors, we have overall success */
	set_kr(REQ_FWDED);
	replies_locked = 0;
	UNLOCK_REPLIES(t);
	return 1;

canceled:
	DBG("t_append_branches: cannot append branches to a canceled transaction\n");
	/* reset processed branches */
	clear_branches();
	/* restore backup flags from initial env */
	setbflagsval(0, backup_bflags);
	/* update message flags, if changed in branch route */
	t->uas.request->flags = orig_msg->flags;
	/* if needed unlock transaction's replies */
	if (likely(replies_locked)) {
		/* restore the number of outgoing branches
		 * since new branches have not been completed */
		t->nr_of_outgoings = outgoings;
		replies_locked = 0;
		UNLOCK_REPLIES(t);
	}
	ser_error=E_CANCELED;
	return -1;
}