Merged revisions 271689 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r271689 | mnicholson | 2010-06-22 07:52:27 -0500 (Tue, 22 Jun 2010) | 8 lines Modify chan_sip's packet generation api to automatically calculate the Content-Length. This is done by storing packet content in a buffer until it is actually time to send the packet, at which time the size of the packet is calculated. This change was made to ensure that the Content-Length is always correct. (closes issue #17326) Reported by: kenner Tested by: mnicholson, kenner Review: https://reviewboard.asterisk.org/r/693/ ........ This change also adds an ast_str_copy_string() function (similar to ast_copy_string), that copies one ast_str into another, properly handling embedded nulls. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@271690 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
b1e41bac90
commit
2d4eef7a4f
|
@ -1516,6 +1516,7 @@ static void *sip_tcp_worker_fn(void *);
|
|||
/*--- Constructing requests and responses */
|
||||
static void initialize_initreq(struct sip_pvt *p, struct sip_request *req);
|
||||
static int init_req(struct sip_request *req, int sipmethod, const char *recip);
|
||||
static void deinit_req(struct sip_request *req);
|
||||
static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, int seqno, int newbranch);
|
||||
static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, const char * const explicit_uri);
|
||||
static int init_resp(struct sip_request *resp, const char *msg);
|
||||
|
@ -1530,8 +1531,8 @@ static void build_callid_pvt(struct sip_pvt *pvt);
|
|||
static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain);
|
||||
static void make_our_tag(char *tagbuf, size_t len);
|
||||
static int add_header(struct sip_request *req, const char *var, const char *value);
|
||||
static int add_header_contentLength(struct sip_request *req, int len);
|
||||
static int add_line(struct sip_request *req, const char *line);
|
||||
static int add_content(struct sip_request *req, const char *line);
|
||||
static int finalize_content(struct sip_request *req);
|
||||
static int add_text(struct sip_request *req, const char *text);
|
||||
static int add_digit(struct sip_request *req, char digit, unsigned int duration, int mode);
|
||||
static int add_rpid(struct sip_request *req, struct sip_pvt *p);
|
||||
|
@ -2634,14 +2635,8 @@ cleanup:
|
|||
ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing");
|
||||
ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref");
|
||||
}
|
||||
if (reqcpy.data) {
|
||||
ast_free(reqcpy.data);
|
||||
}
|
||||
|
||||
if (req.data) {
|
||||
ast_free(req.data);
|
||||
req.data = NULL;
|
||||
}
|
||||
deinit_req(&reqcpy);
|
||||
deinit_req(&req);
|
||||
|
||||
/* if client, we own the parent session arguments and must decrement ref */
|
||||
if (ca) {
|
||||
|
@ -3804,6 +3799,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty
|
|||
{
|
||||
int res;
|
||||
|
||||
finalize_content(req);
|
||||
add_blank(req);
|
||||
if (sip_debug_test_pvt(p)) {
|
||||
const struct sockaddr_in *dst = sip_real_dst(p);
|
||||
|
@ -3818,7 +3814,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty
|
|||
parse_copy(&tmp, req);
|
||||
append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"),
|
||||
(tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? REQ_OFFSET_TO_STR(&tmp, rlPart2) : sip_methods[tmp.method].text);
|
||||
ast_free(tmp.data);
|
||||
deinit_req(&tmp);
|
||||
}
|
||||
|
||||
/* If we are sending a final response to an INVITE, stop retransmitting provisional responses */
|
||||
|
@ -3829,8 +3825,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty
|
|||
res = (reliable) ?
|
||||
__sip_reliable_xmit(p, seqno, 1, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) :
|
||||
__sip_xmit(p, req->data, req->len);
|
||||
ast_free(req->data);
|
||||
req->data = NULL;
|
||||
deinit_req(req);
|
||||
if (res > 0)
|
||||
return 0;
|
||||
return res;
|
||||
|
@ -3850,6 +3845,7 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
|
|||
p->sa = p->outboundproxy->ip;
|
||||
}
|
||||
|
||||
finalize_content(req);
|
||||
add_blank(req);
|
||||
if (sip_debug_test_pvt(p)) {
|
||||
if (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT))
|
||||
|
@ -3861,15 +3857,12 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
|
|||
struct sip_request tmp = { .rlPart1 = 0, };
|
||||
parse_copy(&tmp, req);
|
||||
append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
|
||||
ast_free(tmp.data);
|
||||
deinit_req(&tmp);
|
||||
}
|
||||
res = (reliable) ?
|
||||
__sip_reliable_xmit(p, seqno, 0, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) :
|
||||
__sip_xmit(p, req->data, req->len);
|
||||
if (req->data) {
|
||||
ast_free(req->data);
|
||||
req->data = NULL;
|
||||
}
|
||||
deinit_req(req);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -5257,8 +5250,7 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
|
|||
free_old_route(p->route);
|
||||
p->route = NULL;
|
||||
}
|
||||
if (p->initreq.data)
|
||||
ast_free(p->initreq.data);
|
||||
deinit_req(&p->initreq);
|
||||
|
||||
/* Destroy Session-Timers if allocated */
|
||||
if (p->stimer) {
|
||||
|
@ -8770,30 +8762,37 @@ static int add_header(struct sip_request *req, const char *var, const char *valu
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Add 'Content-Length' header to SIP message */
|
||||
static int add_header_contentLength(struct sip_request *req, int len)
|
||||
/*! \brief Add 'Content-Length' header and content to SIP message */
|
||||
static int finalize_content(struct sip_request *req)
|
||||
{
|
||||
char clen[10];
|
||||
|
||||
snprintf(clen, sizeof(clen), "%d", len);
|
||||
return add_header(req, "Content-Length", clen);
|
||||
if (req->lines) {
|
||||
ast_log(LOG_WARNING, "finalize_content() called on a message that has already been finalized\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(clen, sizeof(clen), "%zd", ast_str_strlen(req->content));
|
||||
add_header(req, "Content-Length", clen);
|
||||
|
||||
if (ast_str_strlen(req->content)) {
|
||||
ast_str_append(&req->data, 0, "\r\n%s", ast_str_buffer(req->content));
|
||||
req->len = ast_str_strlen(req->data);
|
||||
}
|
||||
req->lines = ast_str_strlen(req->content) ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Add content (not header) to SIP message */
|
||||
static int add_line(struct sip_request *req, const char *line)
|
||||
static int add_content(struct sip_request *req, const char *line)
|
||||
{
|
||||
if (req->lines == SIP_MAX_LINES) {
|
||||
ast_log(LOG_WARNING, "Out of SIP line space\n");
|
||||
if (req->lines) {
|
||||
ast_log(LOG_WARNING, "Can't add more content when the content has been finalized\n");
|
||||
return -1;
|
||||
}
|
||||
if (!req->lines)
|
||||
/* Add extra empty return */
|
||||
req->len += ast_str_append(&req->data, 0, "\r\n");
|
||||
req->line[req->lines] = req->len;
|
||||
ast_str_append(&req->data, 0, "%s", line);
|
||||
req->len = ast_str_strlen(req->data);
|
||||
req->lines++;
|
||||
return 0;
|
||||
|
||||
ast_str_append(&req->content, 0, "%s", line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Copy one header field from one request to another */
|
||||
|
@ -9005,12 +9004,20 @@ static int init_resp(struct sip_request *resp, const char *msg)
|
|||
memset(resp, 0, sizeof(*resp));
|
||||
resp->method = SIP_RESPONSE;
|
||||
if (!(resp->data = ast_str_create(SIP_MIN_PACKET)))
|
||||
return -1;
|
||||
goto e_return;
|
||||
if (!(resp->content = ast_str_create(SIP_MIN_PACKET)))
|
||||
goto e_free_data;
|
||||
resp->header[0] = 0;
|
||||
ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg);
|
||||
resp->len = resp->data->used;
|
||||
resp->headers++;
|
||||
return 0;
|
||||
|
||||
e_free_data:
|
||||
ast_free(resp->data);
|
||||
resp->data = NULL;
|
||||
e_return:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! \brief Initialize SIP request */
|
||||
|
@ -9019,15 +9026,37 @@ static int init_req(struct sip_request *req, int sipmethod, const char *recip)
|
|||
/* Initialize a request */
|
||||
memset(req, 0, sizeof(*req));
|
||||
if (!(req->data = ast_str_create(SIP_MIN_PACKET)))
|
||||
return -1;
|
||||
goto e_return;
|
||||
if (!(req->content = ast_str_create(SIP_MIN_PACKET)))
|
||||
goto e_free_data;
|
||||
req->method = sipmethod;
|
||||
req->header[0] = 0;
|
||||
ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip);
|
||||
req->len = ast_str_strlen(req->data);
|
||||
req->headers++;
|
||||
return 0;
|
||||
|
||||
e_free_data:
|
||||
ast_free(req->data);
|
||||
req->data = NULL;
|
||||
e_return:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! \brief Deinitialize SIP response/request */
|
||||
static void deinit_req(struct sip_request *req)
|
||||
{
|
||||
if (req->data) {
|
||||
ast_free(req->data);
|
||||
req->data = NULL;
|
||||
}
|
||||
if (req->content) {
|
||||
ast_free(req->content);
|
||||
req->content = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Test if this response needs a contact header */
|
||||
static inline int resp_needs_contact(const char *msg, enum sipmethod method) {
|
||||
/* Requirements for Contact header inclusion in responses generated
|
||||
|
@ -9309,7 +9338,6 @@ static int __transmit_response(struct sip_pvt *p, const char *msg, const struct
|
|||
add_cc_call_info_to_response(p, &resp);
|
||||
}
|
||||
|
||||
add_header_contentLength(&resp, 0);
|
||||
/* If we are cancelling an incoming invite for some reason, add information
|
||||
about the reason why we are doing this in clear text */
|
||||
if (p->method == SIP_INVITE && msg[0] != '1') {
|
||||
|
@ -9439,7 +9467,6 @@ static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg
|
|||
respprep(&resp, p, msg, req);
|
||||
append_date(&resp);
|
||||
add_header(&resp, "Unsupported", unsupported);
|
||||
add_header_contentLength(&resp, 0);
|
||||
return send_response(p, &resp, XMIT_UNRELIABLE, 0);
|
||||
}
|
||||
|
||||
|
@ -9454,8 +9481,6 @@ static int transmit_response_with_minse(struct sip_pvt *p, const char *msg, cons
|
|||
|
||||
snprintf(minse_str, sizeof(minse_str), "%d", minse_int);
|
||||
add_header(&resp, "Min-SE", minse_str);
|
||||
|
||||
add_header_contentLength(&resp, 0);
|
||||
return send_response(p, &resp, XMIT_UNRELIABLE, 0);
|
||||
}
|
||||
|
||||
|
@ -9486,7 +9511,6 @@ static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const
|
|||
struct sip_request resp;
|
||||
respprep(&resp, p, msg, req);
|
||||
append_date(&resp);
|
||||
add_header_contentLength(&resp, 0);
|
||||
return send_response(p, &resp, XMIT_UNRELIABLE, 0);
|
||||
}
|
||||
|
||||
|
@ -9496,7 +9520,6 @@ static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, cons
|
|||
struct sip_request resp;
|
||||
respprep(&resp, p, msg, req);
|
||||
add_header(&resp, "Accept", "application/sdp");
|
||||
add_header_contentLength(&resp, 0);
|
||||
return send_response(p, &resp, reliable, 0);
|
||||
}
|
||||
|
||||
|
@ -9519,7 +9542,6 @@ static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const
|
|||
snprintf(tmp, sizeof(tmp), "Digest algorithm=MD5, realm=\"%s\", nonce=\"%s\"%s", p->realm, randdata, stale ? ", stale=true" : "");
|
||||
respprep(&resp, p, msg, req);
|
||||
add_header(&resp, header, tmp);
|
||||
add_header_contentLength(&resp, 0);
|
||||
append_history(p, "AuthChal", "Auth challenge sent for %s - nc %d", p->username, p->noncecount);
|
||||
return send_response(p, &resp, reliable, seqno);
|
||||
}
|
||||
|
@ -9616,8 +9638,7 @@ static int add_text(struct sip_request *req, const char *text)
|
|||
{
|
||||
/* XXX Convert \n's to \r\n's XXX */
|
||||
add_header(req, "Content-Type", "text/plain;charset=UTF-8");
|
||||
add_header_contentLength(req, strlen(text));
|
||||
add_line(req, text);
|
||||
add_content(req, text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -9641,14 +9662,12 @@ static int add_digit(struct sip_request *req, char digit, unsigned int duration,
|
|||
event = atoi(&digit);
|
||||
snprintf(tmp, sizeof(tmp), "%d\r\n", event);
|
||||
add_header(req, "Content-Type", "application/dtmf");
|
||||
add_header_contentLength(req, strlen(tmp));
|
||||
add_line(req, tmp);
|
||||
add_content(req, tmp);
|
||||
} else {
|
||||
/* Application/dtmf-relay as documented by Cisco */
|
||||
snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration);
|
||||
add_header(req, "Content-Type", "application/dtmf-relay");
|
||||
add_header_contentLength(req, strlen(tmp));
|
||||
add_line(req, tmp);
|
||||
add_content(req, tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -9754,8 +9773,7 @@ static int add_vidupdate(struct sip_request *req)
|
|||
" </vc_primitive>\r\n"
|
||||
" </media_control>\r\n";
|
||||
add_header(req, "Content-Type", "application/media_control+xml");
|
||||
add_header_contentLength(req, strlen(xml_is_a_huge_waste_of_space));
|
||||
add_line(req, xml_is_a_huge_waste_of_space);
|
||||
add_content(req, xml_is_a_huge_waste_of_space);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -10023,7 +10041,6 @@ static void get_crypto_attrib(struct sip_srtp *srtp, const char **a_crypto)
|
|||
*/
|
||||
static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
|
||||
{
|
||||
int len = 0;
|
||||
format_t alreadysent = 0;
|
||||
|
||||
struct sockaddr_in sin = { 0, };
|
||||
|
@ -10320,72 +10337,52 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
|
|||
if (needtext)
|
||||
ast_str_append(&m_text, 0, "\r\n");
|
||||
|
||||
len = strlen(version) + strlen(subject) + strlen(owner) +
|
||||
strlen(connection) + strlen(session_time);
|
||||
if (needaudio)
|
||||
len += m_audio->used + a_audio->used + strlen(hold);
|
||||
if (needvideo) /* only if video response is appropriate */
|
||||
len += m_video->used + a_video->used + strlen(bandwidth) + strlen(hold);
|
||||
if (needtext) /* only if text response is appropriate */
|
||||
len += m_text->used + a_text->used + strlen(hold);
|
||||
if (add_t38)
|
||||
len += m_modem->used + a_modem->used;
|
||||
if (a_crypto) {
|
||||
len += strlen(a_crypto);
|
||||
}
|
||||
if (v_a_crypto) {
|
||||
len += strlen(v_a_crypto);
|
||||
}
|
||||
if (t_a_crypto) {
|
||||
len += strlen(t_a_crypto);
|
||||
}
|
||||
add_header(resp, "Content-Type", "application/sdp");
|
||||
add_header_contentLength(resp, len);
|
||||
add_line(resp, version);
|
||||
add_line(resp, owner);
|
||||
add_line(resp, subject);
|
||||
add_line(resp, connection);
|
||||
add_content(resp, version);
|
||||
add_content(resp, owner);
|
||||
add_content(resp, subject);
|
||||
add_content(resp, connection);
|
||||
if (needvideo) /* only if video response is appropriate */
|
||||
add_line(resp, bandwidth);
|
||||
add_line(resp, session_time);
|
||||
add_content(resp, bandwidth);
|
||||
add_content(resp, session_time);
|
||||
if (needaudio) {
|
||||
add_line(resp, m_audio->str);
|
||||
add_line(resp, a_audio->str);
|
||||
add_line(resp, hold);
|
||||
add_content(resp, m_audio->str);
|
||||
add_content(resp, a_audio->str);
|
||||
add_content(resp, hold);
|
||||
if (a_crypto) {
|
||||
add_line(resp, a_crypto);
|
||||
add_content(resp, a_crypto);
|
||||
}
|
||||
} else if (p->offered_media[SDP_AUDIO].offered) {
|
||||
snprintf(dummy_answer, sizeof(dummy_answer), "m=audio 0 RTP/AVP %s\r\n", p->offered_media[SDP_AUDIO].codecs);
|
||||
add_line(resp, dummy_answer);
|
||||
add_content(resp, dummy_answer);
|
||||
}
|
||||
if (needvideo) { /* only if video response is appropriate */
|
||||
add_line(resp, m_video->str);
|
||||
add_line(resp, a_video->str);
|
||||
add_line(resp, hold); /* Repeat hold for the video stream */
|
||||
add_content(resp, m_video->str);
|
||||
add_content(resp, a_video->str);
|
||||
add_content(resp, hold); /* Repeat hold for the video stream */
|
||||
if (v_a_crypto) {
|
||||
add_line(resp, v_a_crypto);
|
||||
add_content(resp, v_a_crypto);
|
||||
}
|
||||
} else if (p->offered_media[SDP_VIDEO].offered) {
|
||||
snprintf(dummy_answer, sizeof(dummy_answer), "m=video 0 RTP/AVP %s\r\n", p->offered_media[SDP_VIDEO].codecs);
|
||||
add_line(resp, dummy_answer);
|
||||
add_content(resp, dummy_answer);
|
||||
}
|
||||
if (needtext) { /* only if text response is appropriate */
|
||||
add_line(resp, m_text->str);
|
||||
add_line(resp, a_text->str);
|
||||
add_line(resp, hold); /* Repeat hold for the text stream */
|
||||
add_content(resp, m_text->str);
|
||||
add_content(resp, a_text->str);
|
||||
add_content(resp, hold); /* Repeat hold for the text stream */
|
||||
if (t_a_crypto) {
|
||||
add_line(resp, t_a_crypto);
|
||||
add_content(resp, t_a_crypto);
|
||||
}
|
||||
} else if (p->offered_media[SDP_TEXT].offered) {
|
||||
snprintf(dummy_answer, sizeof(dummy_answer), "m=text 0 RTP/AVP %s\r\n", p->offered_media[SDP_TEXT].codecs);
|
||||
add_line(resp, dummy_answer);
|
||||
add_content(resp, dummy_answer);
|
||||
}
|
||||
if (add_t38) {
|
||||
add_line(resp, m_modem->str);
|
||||
add_line(resp, a_modem->str);
|
||||
add_content(resp, m_modem->str);
|
||||
add_content(resp, a_modem->str);
|
||||
} else if (p->offered_media[SDP_IMAGE].offered) {
|
||||
add_line(resp, "m=image 0 udptl t38\r\n");
|
||||
add_content(resp, "m=image 0 udptl t38\r\n");
|
||||
}
|
||||
|
||||
/* Update lastrtprx when we send our SDP */
|
||||
|
@ -10419,25 +10416,29 @@ static int transmit_response_with_t38_sdp(struct sip_pvt *p, char *msg, struct s
|
|||
/*! \brief copy SIP request (mostly used to save request for responses) */
|
||||
static void copy_request(struct sip_request *dst, const struct sip_request *src)
|
||||
{
|
||||
struct ast_str *duplicate = dst->data;
|
||||
/* XXX this function can encounter memory allocation errors, perhaps it
|
||||
* should return a value */
|
||||
|
||||
/* First copy stuff */
|
||||
struct ast_str *duplicate = dst->data;
|
||||
struct ast_str *duplicate_content = dst->content;
|
||||
|
||||
/* copy the entire request then restore the original data and content
|
||||
* members from the dst request */
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
dst->data = duplicate;
|
||||
dst->content = duplicate_content;
|
||||
|
||||
/* All these + 1's are to account for the need to include the NULL terminator
|
||||
* Using typical string functions like ast_copy_string or ast_str_set will not
|
||||
* work in this case because the src's data string is riddled with \0's all over
|
||||
* the place and so a memcpy is the only way to accurately copy the string
|
||||
*/
|
||||
|
||||
if (!dst->data && !(dst->data = ast_str_create(src->data->used + 1)))
|
||||
/* copy the data into the dst request */
|
||||
if (!dst->data && !(dst->data = ast_str_create(ast_str_strlen(src->data) + 1)))
|
||||
return;
|
||||
else if (dst->data->len < src->data->used + 1)
|
||||
ast_str_make_space(&dst->data, src->data->used + 1);
|
||||
|
||||
memcpy(dst->data->str, src->data->str, src->data->used + 1);
|
||||
dst->data->used = src->data->used;
|
||||
ast_str_copy_string(&dst->data, src->data);
|
||||
|
||||
/* copy the content into the dst request (if it exists) */
|
||||
if (src->content) {
|
||||
if (!dst->content && !(dst->content = ast_str_create(ast_str_strlen(src->content) + 1)))
|
||||
return;
|
||||
ast_str_copy_string(&dst->content, src->content);
|
||||
}
|
||||
}
|
||||
|
||||
static void add_cc_call_info_to_response(struct sip_pvt *p, struct sip_request *resp)
|
||||
|
@ -11015,9 +11016,8 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init,
|
|||
} else if (p->notify) {
|
||||
for (var = p->notify->headers; var; var = var->next)
|
||||
add_header(&req, var->name, var->value);
|
||||
add_header_contentLength(&req, ast_str_strlen(p->notify->content));
|
||||
if (ast_str_strlen(p->notify->content))
|
||||
add_line(&req, ast_str_buffer(p->notify->content));
|
||||
add_content(&req, ast_str_buffer(p->notify->content));
|
||||
} else if (sipmethod == SIP_PUBLISH) {
|
||||
char expires[SIPBUFSIZE];
|
||||
switch (p->epa_entry->static_data->event) {
|
||||
|
@ -11030,17 +11030,12 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init,
|
|||
}
|
||||
if (!ast_strlen_zero(p->epa_entry->body)) {
|
||||
add_header(&req, "Content-Type", "application/pidf+xml");
|
||||
add_header_contentLength(&req, strlen(p->epa_entry->body));
|
||||
add_line(&req, p->epa_entry->body);
|
||||
} else {
|
||||
add_header_contentLength(&req, 0);
|
||||
add_content(&req, p->epa_entry->body);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
add_header_contentLength(&req, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!p->initreq.headers || init > 2)
|
||||
initialize_initreq(p, &req);
|
||||
|
@ -11339,11 +11334,9 @@ static int transmit_cc_notify(struct ast_cc_agent *agent, struct sip_pvt *subscr
|
|||
generate_uri(subscription, agent_pvt->notify_uri, sizeof(agent_pvt->notify_uri));
|
||||
snprintf(uri, sizeof(uri) - 1, "cc-URI: %s\r\n", agent_pvt->notify_uri);
|
||||
}
|
||||
add_header_contentLength(&req, strlen(state_str) +
|
||||
(state == CC_READY ? strlen(uri) : 0));
|
||||
add_line(&req, state_str);
|
||||
add_content(&req, state_str);
|
||||
if (state == CC_READY) {
|
||||
add_line(&req, uri);
|
||||
add_content(&req, uri);
|
||||
}
|
||||
return send_request(subscription, &req, XMIT_RELIABLE, subscription->ocseq);
|
||||
}
|
||||
|
@ -11425,8 +11418,7 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim
|
|||
break;
|
||||
}
|
||||
|
||||
add_header_contentLength(&req, tmp->used);
|
||||
add_line(&req, tmp->str);
|
||||
add_content(&req, tmp->str);
|
||||
|
||||
p->pendinginvite = p->ocseq; /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */
|
||||
|
||||
|
@ -11479,8 +11471,7 @@ static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs,
|
|||
add_header(&req, "Subscription-State", "terminated;reason=timeout");
|
||||
}
|
||||
|
||||
add_header_contentLength(&req, out->used);
|
||||
add_line(&req, out->str);
|
||||
add_content(&req, out->str);
|
||||
|
||||
if (!p->initreq.headers)
|
||||
initialize_initreq(p, &req);
|
||||
|
@ -11502,8 +11493,7 @@ static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *messa
|
|||
add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message);
|
||||
add_header_contentLength(&req, strlen(tmp));
|
||||
add_line(&req, tmp);
|
||||
add_content(&req, tmp);
|
||||
|
||||
if (!p->initreq.headers)
|
||||
initialize_initreq(p, &req);
|
||||
|
@ -11552,6 +11542,8 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
|
|||
if (ast_str_strlen(p->notify->content))
|
||||
ast_str_append(&p->notify->content, 0, "\r\n");
|
||||
ast_str_append(&p->notify->content, 0, "%s", var->value);
|
||||
} else if (!strcasecmp(var->name, "Content-Length")) {
|
||||
ast_log(LOG_WARNING, "it is not necessary to specify Content-Length, ignoring");
|
||||
} else {
|
||||
header->next = ast_variable_new(var->name, var->value, "");
|
||||
header = header->next;
|
||||
|
@ -11613,7 +11605,6 @@ static void update_connectedline(struct sip_pvt *p, const void *data, size_t dat
|
|||
reqprep(&req, p, SIP_UPDATE, 0, 1);
|
||||
add_rpid(&req, p);
|
||||
add_header(&req, "X-Asterisk-rpid-update", "Yes");
|
||||
add_header_contentLength(&req, 0);
|
||||
send_request(p, &req, XMIT_CRITICAL, p->ocseq);
|
||||
} else {
|
||||
/* We cannot send the update yet, so we have to wait until we can */
|
||||
|
@ -11971,7 +11962,6 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
|
|||
snprintf(tmp, sizeof(tmp), "%d", r->expiry);
|
||||
add_header(&req, "Expires", tmp);
|
||||
add_header(&req, "Contact", p->our_contact);
|
||||
add_header_contentLength(&req, 0);
|
||||
|
||||
initialize_initreq(p, &req);
|
||||
if (sip_debug_test_pvt(p)) {
|
||||
|
@ -12172,7 +12162,6 @@ static int transmit_request(struct sip_pvt *p, int sipmethod, int seqno, enum xm
|
|||
if (sipmethod == SIP_CANCEL && p->answered_elsewhere)
|
||||
add_header(&resp, "Reason", "SIP;cause=200;text=\"Call completed elsewhere\"");
|
||||
|
||||
add_header_contentLength(&resp, 0);
|
||||
return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
|
||||
}
|
||||
|
||||
|
@ -12224,7 +12213,6 @@ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqn
|
|||
add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
|
||||
}
|
||||
|
||||
add_header_contentLength(&resp, 0);
|
||||
return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
|
||||
}
|
||||
|
||||
|
@ -17295,6 +17283,8 @@ static char *sip_cli_notify(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
|
|||
if (ast_str_strlen(p->notify->content))
|
||||
ast_str_append(&p->notify->content, 0, "\r\n");
|
||||
ast_str_append(&p->notify->content, 0, "%s", buf);
|
||||
} else if (!strcasecmp(var->name, "Content-Length")) {
|
||||
ast_log(LOG_WARNING, "it is not necessary to specify Content-Length in sip_notify.conf, ignoring");
|
||||
} else {
|
||||
header->next = ast_variable_new(var->name, buf, "");
|
||||
header = header->next;
|
||||
|
@ -19431,8 +19421,7 @@ static void *sip_park_thread(void *stuff)
|
|||
|
||||
if (!transferee || !transferer) {
|
||||
ast_log(LOG_ERROR, "Missing channels for parking! Transferer %s Transferee %s\n", transferer ? "<available>" : "<missing>", transferee ? "<available>" : "<missing>" );
|
||||
if (d->req.data)
|
||||
ast_free(d->req.data);
|
||||
deinit_req(&d->req);
|
||||
free(d);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -19441,8 +19430,7 @@ static void *sip_park_thread(void *stuff)
|
|||
if (ast_do_masquerade(transferee)) {
|
||||
ast_log(LOG_WARNING, "Masquerade failed.\n");
|
||||
transmit_response(transferer->tech_pvt, "503 Internal error", &req);
|
||||
if (d->req.data)
|
||||
ast_free(d->req.data);
|
||||
deinit_req(&d->req);
|
||||
free(d);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -19476,8 +19464,7 @@ static void *sip_park_thread(void *stuff)
|
|||
ast_debug(1, "SIP Call parked failed \n");
|
||||
/* Do not hangup call */
|
||||
}
|
||||
if (d->req.data)
|
||||
ast_free(d->req.data);
|
||||
deinit_req(&d->req);
|
||||
free(d);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -19568,8 +19555,7 @@ static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct
|
|||
d->seqno = seqno;
|
||||
if (ast_pthread_create_detached_background(&th, NULL, sip_park_thread, d) < 0) {
|
||||
/* Could not start thread */
|
||||
if (d->req.data)
|
||||
ast_free(d->req.data);
|
||||
deinit_req(&d->req);
|
||||
ast_free(d); /* We don't need it anymore. If thread is created, d will be free'd
|
||||
by sip_park_thread() */
|
||||
return 0;
|
||||
|
@ -23347,10 +23333,7 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
|
|||
req.socket.port = bindaddr.sin_port;
|
||||
|
||||
handle_request_do(&req, &sin);
|
||||
if (req.data) {
|
||||
ast_free(req.data);
|
||||
req.data = NULL;
|
||||
}
|
||||
deinit_req(&req);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -742,6 +742,7 @@ struct sip_request {
|
|||
ptrdiff_t header[SIP_MAX_HEADERS]; /*!< Array of offsets into the request string of each SIP header*/
|
||||
ptrdiff_t line[SIP_MAX_LINES]; /*!< Array of offsets into the request string of each SDP line*/
|
||||
struct ast_str *data;
|
||||
struct ast_str *content;
|
||||
/* XXX Do we need to unref socket.ser when the request goes away? */
|
||||
struct sip_socket socket; /*!< The socket used for this request */
|
||||
AST_LIST_ENTRY(sip_request) next;
|
||||
|
|
|
@ -582,6 +582,23 @@ int ast_str_make_space(struct ast_str **buf, size_t new_len),
|
|||
)
|
||||
#endif
|
||||
|
||||
AST_INLINE_API(
|
||||
int ast_str_copy_string(struct ast_str **dst, struct ast_str *src),
|
||||
{
|
||||
|
||||
/* make sure our destination is large enough */
|
||||
if (src->__AST_STR_USED + 1 > (*dst)->__AST_STR_LEN) {
|
||||
if (ast_str_make_space(dst, src->__AST_STR_USED + 1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy((*dst)->__AST_STR_STR, src->__AST_STR_STR, src->__AST_STR_USED + 1);
|
||||
(*dst)->__AST_STR_USED = src->__AST_STR_USED;
|
||||
return 0;
|
||||
}
|
||||
)
|
||||
|
||||
#define ast_str_alloca(init_len) \
|
||||
({ \
|
||||
struct ast_str *__ast_str_buf; \
|
||||
|
|
Reference in New Issue