Example #1
0
/*
 * Create a request
 */
char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog,
		int branch, struct cell *t, int* len, struct dest_info* dst)
{
	char* buf, *w, *p;
	str content_length, cseq, via;
	unsigned int maxfwd_len;
	int tbracket, fbracket;
	str fromtag = STR_NULL;
	str loc_tag = STR_NULL;

	if (!method || !dialog) {
		LM_ERR("invalid parameter value\n");
		return 0;
	}

	if (dialog->id.loc_tag.len<=0) {
		/* From Tag is mandatory in RFC3261 - generate one if not provided */
		generate_fromtag(&fromtag, &dialog->id.call_id);
		loc_tag = dialog->id.loc_tag;
		dialog->id.loc_tag = fromtag;
	}
	if (print_content_length(&content_length, body) < 0) {
		LM_ERR("error while printing content-length\n");
		return 0;
	}
	if (print_cseq_num(&cseq, dialog) < 0) {
		LM_ERR("error while printing CSeq number\n");
		return 0;
	}

	if(headers==NULL || headers->len<15
			|| _strnstr(headers->s, "Max-Forwards:", headers->len)==NULL) {
		maxfwd_len = MAXFWD_HEADER_LEN;
	} else {
		maxfwd_len = 0;
	}

	*len = method->len + 1 + dialog->hooks.request_uri->len + 1
		+ SIP_VERSION_LEN + CRLF_LEN;

	if (assemble_via(&via, t, dst, branch) < 0) {
		LM_ERR("error while assembling Via\n");
		return 0;
	}
	*len += via.len;

	if((p=q_memrchr(dialog->rem_uri.s, '>', dialog->rem_uri.len))!=NULL) {
		if((p==dialog->rem_uri.s + dialog->rem_uri.len - 1)
				|| *(p+1)==';') {
			tbracket = 0;
		} else {
			tbracket = 1;
		}
	} else {
		tbracket = 1;
	}
	if((p=q_memrchr(dialog->loc_uri.s, '>', dialog->loc_uri.len))!=NULL) {
		if((p==dialog->loc_uri.s + dialog->loc_uri.len - 1)
				|| *(p+1)==';') {
			fbracket = 0;
		} else {
			fbracket = 1;
		}
	} else {
		fbracket = 1;
	}

	*len += TO_LEN + dialog->rem_uri.len
		+ (dialog->id.rem_tag.len ? (TOTAG_LEN + dialog->id.rem_tag.len) : 0)
		+ CRLF_LEN;    /* To */
	if(tbracket) *len += 2; /* To-URI < > */
	*len += FROM_LEN + dialog->loc_uri.len
		+ (dialog->id.loc_tag.len ? (FROMTAG_LEN + dialog->id.loc_tag.len) : 0)
		+ CRLF_LEN;  /* From */
	if(fbracket) *len += 2; /* From-URI < > */
	*len += CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;   /* Call-ID */
	*len += CSEQ_LEN + cseq.len + 1 + method->len + CRLF_LEN; /* CSeq */
	*len += calculate_routeset_length(dialog);                /* Route set */
	*len += maxfwd_len;                                       /* Max-forwards */
	*len += CONTENT_LENGTH_LEN + content_length.len
											+ CRLF_LEN; /* Content-Length */
	*len += ((server_signature && user_agent_hdr.len>0)
						? (user_agent_hdr.len + CRLF_LEN) : 0);	/* Signature */
	if(headers && headers->len>2) {
		/* Additional headers */
		*len += headers->len;
		/* End of header if missing */
		if(headers->s[headers->len - 1] != '\n')
			*len += CRLF_LEN;
	}
	*len += (body ? body->len : 0);                         /* Message body */
	*len += CRLF_LEN;                                       /* End of Header */

	buf = shm_malloc(*len + 1);
	if (!buf) {
		LM_ERR("no more shared memory (%d)\n", *len);
		goto error;
	}

	w = buf;

	w = print_request_uri(w, method, dialog, t, branch);  /* Request-URI */
	memapp(w, via.s, via.len);                            /* Top-most Via */
	w = print_to(w, dialog, t, tbracket);                 /* To */
	w = print_from(w, dialog, t, fbracket);               /* From */
	if(fromtag.len>0) {
		dialog->id.loc_tag = loc_tag;
	}
	w = print_cseq(w, &cseq, method, t);                  /* CSeq */
	w = print_callid(w, dialog, t);                       /* Call-ID */
	w = print_routeset(w, dialog);                        /* Route set */

	if(maxfwd_len>0)
		memapp(w, MAXFWD_HEADER, MAXFWD_HEADER_LEN);      /* Max-forwards */

	/* Content-Length */
	memapp(w, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
	memapp(w, content_length.s, content_length.len);
	memapp(w, CRLF, CRLF_LEN);

	/* Server signature */
	if (server_signature && user_agent_hdr.len>0) {
		memapp(w, user_agent_hdr.s, user_agent_hdr.len);
		memapp(w, CRLF, CRLF_LEN);
	}
	if(headers && headers->len>2) {
		memapp(w, headers->s, headers->len);
		if(headers->s[headers->len - 1] != '\n')
			memapp(w, CRLF, CRLF_LEN);
	}
	memapp(w, CRLF, CRLF_LEN);
	if (body) memapp(w, body->s, body->len);

#ifdef EXTRA_DEBUG
	assert(w-buf == *len);
#endif

	memapp(w, "\0", 1);

	pkg_free(via.s);
	return buf;

error:
	pkg_free(via.s);
	return 0;
}
Example #2
0
/*
 * Create a request
 */
char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog, 
										int branch, struct cell *t, int* len)
{
	char* buf, *w;
	str content_length, cseq, via;

	if (!method || !dialog) {
		LM_ERR("inalid parameter value\n");
		return 0;
	}
	if (print_content_length(&content_length, body) < 0) {
		LM_ERR("failed to print content-length\n");
		return 0;
	}
	if (print_cseq_num(&cseq, dialog) < 0) {
		LM_ERR("failed to print CSeq number\n");
		return 0;
	}
	*len = method->len + 1 + dialog->hooks.request_uri->len + 1 + 
		SIP_VERSION_LEN + CRLF_LEN;

	if (assemble_via(&via, t, dialog->send_sock, branch) < 0) {
		LM_ERR("failed to assemble Via\n");
		return 0;
	}
	*len += via.len;

	/* To */
	*len += TO_LEN 
		+ (dialog->rem_dname.len ? dialog->rem_dname.len+1 : 0)
		+ dialog->rem_uri.len
		+ (dialog->id.rem_tag.len ? TOTAG_LEN + dialog->id.rem_tag.len : 0)
		+ (dialog->rem_dname.len || dialog->id.rem_tag.len ? 2 : 0)
		+ CRLF_LEN;
	/* From */
	*len += FROM_LEN 
		+ (dialog->loc_dname.len ? dialog->loc_dname.len+1 : 0)
		+ dialog->loc_uri.len
		+ (dialog->id.loc_tag.len ? FROMTAG_LEN + dialog->id.loc_tag.len : 0)
		+ (dialog->loc_dname.len || dialog->id.loc_tag.len ? 2 : 0)
		+ CRLF_LEN;
	/* Call-ID */
	*len += CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;
	/* CSeq */
	*len += CSEQ_LEN + cseq.len + 1 + method->len + CRLF_LEN;
	/* Route set */
	*len += calculate_routeset_length(dialog);
	/* Content-Length */
	*len += CONTENT_LENGTH_LEN + content_length.len + CRLF_LEN;
	/* Signature */
	*len += (server_signature ? (user_agent_header.len + CRLF_LEN) : 0);
	/* Additional headers */
	*len += (headers ? headers->len : 0);
	/* Message body */
	*len += (body ? body->len : 0);
	/* End of Header */
	*len += CRLF_LEN;

	buf = shm_malloc(*len + 1);
	if (!buf) {
		LM_ERR("no more share memory\n");
		goto error;
	}
	
	w = buf;

	w = print_request_uri(w, method, dialog, t, branch);  /* Request-URI */
	append_string(w, via.s, via.len);                     /* Top-most Via */
	w = print_to(w, dialog, t);                           /* To */
	w = print_from(w, dialog, t);                         /* From */
	w = print_cseq(w, &cseq, method, t);                  /* CSeq */
	w = print_callid(w, dialog, t);                       /* Call-ID */
	w = print_routeset(w, dialog);                        /* Route set */

	/* Content-Length */
	append_string(w, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
	append_string(w, content_length.s, content_length.len);
	append_string(w, CRLF, CRLF_LEN);

	/* Server signature */
	if (server_signature) {
		append_string(w, user_agent_header.s, user_agent_header.len);
		append_string(w, CRLF, CRLF_LEN);
	}
	if (headers) {
		t->uac[branch].extra_headers.s = w;
		t->uac[branch].extra_headers.len = headers->len;
		append_string(w, headers->s, headers->len);
	}
	append_string(w, CRLF, CRLF_LEN);
	if (body) {
		t->uac[branch].body.s = w;
		t->uac[branch].body.len = body->len;
		append_string(w, body->s, body->len);
	}

#ifdef EXTRA_DEBUG
	if (w-buf != *len ) abort();
#endif

	pkg_free(via.s);
	return buf;

 error:
	pkg_free(via.s);
	return 0;
}