Revert ast_str opacity in chan_sip for now, since something wasn't quite right
authorTilghman Lesher <tilghman@meg.abyt.es>
Mon, 15 Dec 2008 19:48:02 +0000 (19:48 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Mon, 15 Dec 2008 19:48:02 +0000 (19:48 +0000)
in the merge.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@164417 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
include/asterisk/strings.h

index 30d611c..834472e 100644 (file)
@@ -508,7 +508,7 @@ static int mwi_expiry = DEFAULT_MWI_EXPIRY;
 
 #define SIP_MAX_HEADERS              64               /*!< Max amount of SIP headers to read */
 #define SIP_MAX_LINES                64               /*!< Max amount of lines in SIP attachment (like SDP) */
-#define SIP_MIN_PACKET               1024             /*!< Initialize size of memory to allocate for packets */
+#define SIP_MIN_PACKET               4096             /*!< Initialize size of memory to allocate for packets */
 
 #define INITIAL_CSEQ                 101              /*!< Our initial sip sequence number */
 
@@ -2031,8 +2031,6 @@ static void temp_pvt_cleanup(void *);
 
 /*! \brief A per-thread temporary pvt structure */
 AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup);
-AST_THREADSTORAGE(transmit_state_buffer);
-AST_THREADSTORAGE(mailbox_buffer);
 
 #ifdef LOW_MEMORY
 static void ts_ast_rtp_destroy(void *);
@@ -2263,7 +2261,7 @@ static int reload_config(enum channelreloadreason reason);
 static int expire_register(const void *data);
 static void *do_monitor(void *data);
 static int restart_monitor(void);
-static char *peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer);
+static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer);
 /* static int sip_addrcmp(char *name, struct sockaddr_in *sin);        Support for peer matching */
 static int sip_refer_allocate(struct sip_pvt *p);
 static void ast_quiet_chan(struct ast_channel *chan);
@@ -2709,7 +2707,7 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi
                }
 
                /* Read in headers one line at a time */
-               while (req.len < 4 || strncmp(ast_str_buffer(req.data) + req.len - 4, "\r\n\r\n", 4)) {
+               while (req.len < 4 || strncmp((char *)&req.data->str + req.len - 4, "\r\n\r\n", 4)) {
                        ast_mutex_lock(&tcptls_session->lock);
                        if (!fgets(buf, sizeof(buf), tcptls_session->f)) {
                                ast_mutex_unlock(&tcptls_session->lock);
@@ -2718,8 +2716,8 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi
                        ast_mutex_unlock(&tcptls_session->lock);
                        if (me->stop) 
                                 goto cleanup;
-                       ast_str_append(&req.data, -1, "%s", buf);
-                       req.len = ast_str_strlen(req.data);
+                       ast_str_append(&req.data, 0, "%s", buf);
+                       req.len = req.data->used;
                }
                copy_request(&reqcpy, &req);
                parse_request(&reqcpy);
@@ -2735,8 +2733,8 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi
                                if (me->stop)
                                        goto cleanup;
                                cl -= strlen(buf);
-                               ast_str_append(&req.data, -1, "%s", buf);
-                               req.len = ast_str_strlen(req.data);
+                               ast_str_append(&req.data, 0, "%s", buf);
+                               req.len = req.data->used;
                        }
                }
                /*! \todo XXX If there's no Content-Length or if the content-length and what
@@ -3165,24 +3163,21 @@ static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len)
        int res = 0;
        const struct sockaddr_in *dst = sip_real_dst(p);
 
-       ast_debug(2, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", ast_str_buffer(data), get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port));
+       ast_debug(2, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", data->str, get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port));
 
-       if (sip_prepare_socket(p) < 0) {
+       if (sip_prepare_socket(p) < 0)
                return XMIT_ERROR;
-       }
 
-       if (p->socket.tcptls_session) {
+       if (p->socket.tcptls_session)
                ast_mutex_lock(&p->socket.tcptls_session->lock);
-       }
 
-       if (p->socket.type & SIP_TRANSPORT_UDP) {
-               res = sendto(p->socket.fd, ast_str_buffer(data), len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
-       } else {
-               if (p->socket.tcptls_session->f) {
-                       res = ast_tcptls_server_write(p->socket.tcptls_session, ast_str_buffer(data), len);
-               } else {
+       if (p->socket.type & SIP_TRANSPORT_UDP) 
+               res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+       else {
+               if (p->socket.tcptls_session->f) 
+                       res = ast_tcptls_server_write(p->socket.tcptls_session, data->str, len);
+               else
                        ast_debug(2, "No p->socket.tcptls_session->f len=%d\n", len);
-               }
        } 
 
        if (p->socket.tcptls_session)
@@ -3198,9 +3193,8 @@ static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len)
                        res = XMIT_ERROR;       /* Don't bother with trying to transmit again */
                }
        }
-       if (res != len) {
+       if (res != len)
                ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno));
-       }
 
        return res;
 }
@@ -3360,10 +3354,10 @@ static int retrans_pkt(const void *data)
                        ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n",
                                pkt->retrans, sip_nat_mode(pkt->owner),
                                ast_inet_ntoa(dst->sin_addr),
-                               ntohs(dst->sin_port), ast_str_buffer(pkt->data));
+                               ntohs(dst->sin_port), pkt->data->str);
                }
 
-               append_history(pkt->owner, "ReTx", "%d %s", reschedule, ast_str_buffer(pkt->data));
+               append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str);
                xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
                sip_pvt_unlock(pkt->owner);
                if (xmitres == XMIT_ERROR)
@@ -3478,7 +3472,7 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res
                ast_free(pkt);
                return AST_FAILURE;
        }
-       ast_str_set(&pkt->data, 0, "%s", ast_str_buffer(data));
+       ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0");
        pkt->packetlen = len;
        /* copy other parameters from the caller */
        pkt->method = sipmethod;
@@ -3680,7 +3674,7 @@ static void __sip_pretend_ack(struct sip_pvt *p)
                        return;
                }
                cur = p->packets;
-               method = (cur->method) ? cur->method : find_sip_method(ast_str_buffer(cur->data));
+               method = (cur->method) ? cur->method : find_sip_method(cur->data->str);
                __sip_ack(p, cur->seqno, cur->is_resp, method);
        }
 }
@@ -3693,7 +3687,7 @@ static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod)
 
        for (cur = p->packets; cur; cur = cur->next) {
                if (cur->seqno == seqno && cur->is_resp == resp &&
-                       (cur->is_resp || method_match(sipmethod, ast_str_buffer(cur->data)))) {
+                       (cur->is_resp || method_match(sipmethod, cur->data->str))) {
                        /* this is our baby */
                        if (cur->retransid > -1) {
                                if (sipdebug)
@@ -3722,7 +3716,7 @@ static void add_blank(struct sip_request *req)
        if (!req->lines) {
                /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */
                ast_str_append(&req->data, 0, "\r\n");
-               req->len = ast_str_strlen(req->data);
+               req->len = req->data->used;
        }
 }
 
@@ -3738,12 +3732,12 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty
                ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n",
                        reliable ? "Reliably " : "", sip_nat_mode(p),
                        ast_inet_ntoa(dst->sin_addr),
-                       ntohs(dst->sin_port), ast_str_buffer(req->data));
+                       ntohs(dst->sin_port), req->data->str);
        }
        if (p->do_history) {
                struct sip_request tmp = { .rlPart1 = NULL, };
                parse_copy(&tmp, req);
-               append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"), 
+               append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), 
                        (tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? tmp.rlPart2 : sip_methods[tmp.method].text);
                ast_free(tmp.data);
        }
@@ -3771,16 +3765,15 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
 
        add_blank(req);
        if (sip_debug_test_pvt(p)) {
-               if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) {
-                       ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), ast_str_buffer(req->data));
-               } else {
-                       ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), ast_str_buffer(req->data));
-               }
+               if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE))
+                       ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data->str);
+               else
+                       ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data->str);
        }
        if (p->do_history) {
                struct sip_request tmp = { .rlPart1 = NULL, };
                parse_copy(&tmp, req);
-               append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
+               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);
        }
        res = (reliable) ?
@@ -5511,7 +5504,7 @@ static int sip_hangup(struct ast_channel *ast)
                sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 
        /* Start the process if it's not already started */
-       if (!p->alreadygone && p->initreq.data && ast_str_strlen(p->initreq.data)) {
+       if (!p->alreadygone && p->initreq.data && !ast_strlen_zero(p->initreq.data->str)) {
                if (needcancel) {       /* Outgoing call, not up */
                        if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
                                /* stop retransmitting an INVITE that has not received a response */
@@ -7024,7 +7017,7 @@ static int lws2sws(char *msgbuf, int len)
 */
 static int parse_request(struct sip_request *req)
 {
-       char *c = ast_str_buffer(req->data), **dst = req->header;
+       char *c = req->data->str, **dst = req->header;
        int i = 0, lim = SIP_MAX_HEADERS - 1;
        unsigned int skipping_headers = 0;
 
@@ -7922,7 +7915,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
                /* Activate a re-invite */
                ast_queue_frame(p->owner, &ast_null_frame);
                /* Queue Manager Unhold event */
-               append_history(p, "Unhold", "%s", ast_str_buffer(req->data));
+               append_history(p, "Unhold", "%s", req->data->str);
                if (sip_cfg.callevents)
                        manager_event(EVENT_FLAG_CALL, "Hold",
                                      "Status: Off\r\n"
@@ -7944,7 +7937,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
                /* Activate a re-invite */
                ast_queue_frame(p->owner, &ast_null_frame);
                /* Queue Manager Hold event */
-               append_history(p, "Hold", "%s", ast_str_buffer(req->data));
+               append_history(p, "Hold", "%s", req->data->str);
                if (sip_cfg.callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
                        manager_event(EVENT_FLAG_CALL, "Hold",
                                      "Status: On\r\n"
@@ -7987,8 +7980,8 @@ static int add_header(struct sip_request *req, const char *var, const char *valu
                return -1;
        }
 
-       ast_str_append(&req->data, -1, "%s: %s\r\n", var, value);
-       req->header[req->headers] = ast_str_buffer(req->data) + req->len;
+       ast_str_append(&req->data, 0, "%s: %s\r\n", var, value);
+       req->header[req->headers] = req->data->str + req->len;
 
        if (sip_cfg.compactheaders)
                var = find_alias(var, var);
@@ -8014,12 +8007,16 @@ static int add_line(struct sip_request *req, const char *line)
                ast_log(LOG_WARNING, "Out of SIP line space\n");
                return -1;
        }
-       if (!req->lines) {
+       if (!req->lines)
                /* Add extra empty return */
-               req->len += ast_str_append(&req->data, -1, "\r\n");
+               req->len += ast_str_append(&req->data, 0, "\r\n");
+       if (req->len >= sizeof(req->data->str) - 4) {
+               ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
+               return -1;
        }
-       req->line[req->lines] = ast_str_buffer(req->data) + ast_str_strlen(req->data);
-       req->len += ast_str_append(&req->data, -1, "%s", line);
+       req->line[req->lines] = req->data->str + req->len;
+       ast_str_append(&req->data, 0, "%s", line);
+       req->len += strlen(req->line[req->lines]);
        req->lines++;
        return 0;       
 }
@@ -8083,7 +8080,7 @@ static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, const st
 
                        /* Find ;rport;  (empty request) */
                        rport = strstr(leftmost, ";rport");
-                       if (rport && *(rport + 6) == '=') 
+                       if (rport && *(rport+6) == '=') 
                                rport = NULL;           /* We already have a parameter to rport */
 
                        /* Check rport if NAT=yes or NAT=rfc3581 (which is the default setting)  */
@@ -8235,9 +8232,9 @@ static int init_resp(struct sip_request *resp, const char *msg)
        resp->method = SIP_RESPONSE;
        if (!(resp->data = ast_str_create(SIP_MIN_PACKET)))
                return -1;
-       ast_str_set(&resp->data, -1, "SIP/2.0 %s\r\n", msg);
-       resp->header[0] = ast_str_buffer(resp->data);
-       resp->len = ast_str_strlen(resp->data);
+       resp->header[0] = resp->data->str;
+       ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg);
+       resp->len = strlen(resp->header[0]);
        resp->headers++;
        return 0;
 }
@@ -8250,9 +8247,9 @@ static int init_req(struct sip_request *req, int sipmethod, const char *recip)
        if (!(req->data = ast_str_create(SIP_MIN_PACKET)))
                return -1;
        req->method = sipmethod;
-       ast_str_set(&req->data, -1, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip);
-       req->header[0] = ast_str_buffer(req->data);
-       req->len = ast_str_strlen(req->data);
+       req->header[0] = req->data->str;
+       ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip);
+       req->len = strlen(req->header[0]);
        req->headers++;
        return 0;
 }
@@ -8899,11 +8896,11 @@ static int add_t38_sdp(struct sip_request *resp, struct sip_pvt *p)
        ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", x);
        if (p->t38.jointcapability != T38FAX_UDP_EC_NONE)
                ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC");
-       len = ast_str_strlen(m_modem) + ast_str_strlen(a_modem);
+       len = m_modem->used + a_modem->used;
        add_header(resp, "Content-Type", "application/sdp");
        add_header_contentLength(resp, len);
-       add_line(resp, ast_str_buffer(m_modem));
-       add_line(resp, ast_str_buffer(a_modem));
+       add_line(resp, m_modem->str);
+       add_line(resp, a_modem->str);
 
        /* Update lastrtprx when we send our SDP */
        p->lastrtprx = p->lastrtptx = time(NULL);
@@ -8941,12 +8938,10 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo,
 {
        /* First, get our address */
        ast_rtp_get_us(p->rtp, sin);
-       if (p->vrtp) {
+       if (p->vrtp)
                ast_rtp_get_us(p->vrtp, vsin);
-       }
-       if (p->trtp) {
+       if (p->trtp)
                ast_rtp_get_us(p->trtp, tsin);
-       }
 
        /* Now, try to figure out where we want them to send data */
        /* Is this a re-invite to move the media out, then use the original offer from caller  */
@@ -8996,12 +8991,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
        struct sockaddr_in tdest = { 0, };
 
        /* SDP fields */
-       char *version = "v=0\r\n";                      /* Protocol version */
-       char subject[256];                              /* Subject of the session */
-       char owner[256];                                /* Session owner/creator */
-       char connection[256];                           /* Connection data */
-       char *session_time = "t=0 0\r\n";               /* Time the session is active */
-       char bandwidth[256] = "";                       /* Max bitrate */
+       char *version =         "v=0\r\n";              /* Protocol version */
+       char subject[256];                              /* Subject of the session */
+       char owner[256];                                /* Session owner/creator */
+       char connection[256];                           /* Connection data */
+       char *session_time = "t=0 0\r\n";                       /* Time the session is active */
+       char bandwidth[256] = "";                       /* Max bitrate */
        char *hold;
        struct ast_str *m_audio = ast_str_alloca(256);  /* Media declaration line for audio */
        struct ast_str *m_video = ast_str_alloca(256);  /* Media declaration line for video */
@@ -9035,12 +9030,11 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
 
        /* Set RTP Session ID and version */
        if (!p->sessionid) {
-               p->sessionid = (int) ast_random();
+               p->sessionid = (int)ast_random();
                p->sessionversion = p->sessionid;
        } else {
-               if (oldsdp == FALSE) {
+               if (oldsdp == FALSE)
                        p->sessionversion++;
-               }
        }
 
        capability = p->jointcapability;
@@ -9058,26 +9052,23 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
 #endif
 
        /* Check if we need audio */
-       if (capability & AST_FORMAT_AUDIO_MASK) {
+       if (capability & AST_FORMAT_AUDIO_MASK)
                needaudio = TRUE;
-       }
 
        /* Check if we need video in this call */
        if ((capability & AST_FORMAT_VIDEO_MASK) && !p->novideo) {
                if (p->vrtp) {
                        needvideo = TRUE;
                        ast_debug(2, "This call needs video offers!\n");
-               } else {
+               } else
                        ast_debug(2, "This call needs video offers, but there's no video support enabled!\n");
-               }
        }
 
        /* Get our media addresses */
        get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest);
                
-       if (debug) {
-               ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port));
-       }
+       if (debug) 
+               ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port)); 
 
        /* Ok, we need video. Let's add what we need for video and set codecs.
           Video is handled differently than audio since we can not transcode. */
@@ -9085,36 +9076,30 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
                ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
 
                /* Build max bitrate string */
-               if (p->maxcallbitrate) {
+               if (p->maxcallbitrate)
                        snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
-               }
-               if (debug) {
-                       ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port));
-               }
+               if (debug) 
+                       ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port));        
        }
 
        /* Check if we need text in this call */
        if((capability & AST_FORMAT_TEXT_MASK) && !p->notext) {
-               if (sipdebug_text) {
+               if (sipdebug_text)
                        ast_verbose("We think we can do text\n");
-               }
                if (p->trtp) {
-                       if (sipdebug_text) {
+                       if (sipdebug_text)
                                ast_verbose("And we have a text rtp object\n");
-                       }
                        needtext = TRUE;
                        ast_debug(2, "This call needs text offers! \n");
-               } else {
+               } else
                        ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n");
-               }
        }
                
        /* Ok, we need text. Let's add what we need for text and set codecs.
           Text is handled differently than audio since we can not transcode. */
        if (needtext) {
-               if (sipdebug_text) {
+               if (sipdebug_text)
                        ast_verbose("Lets set up the text sdp\n");
-               }
                /* Determine text destination */
                if (p->tredirip.sin_addr.s_addr) {
                        tdest.sin_addr = p->tredirip.sin_addr;
@@ -9125,9 +9110,9 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
                }
                ast_str_append(&m_text, 0, "m=text %d RTP/AVP", ntohs(tdest.sin_port));
 
-               if (debug) { /* XXX should I use tdest below ? */
+               if (debug) /* XXX should I use tdest below ? */
                        ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port)); 
-               }
+
        }
 
        /* Start building generic SDP headers */
@@ -9139,13 +9124,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
        snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
        ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
 
-       if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) {
+       if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR)
                hold = "a=recvonly\r\n";
-       } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) {
+       else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE)
                hold = "a=inactive\r\n";
-       } else {
+       else
                hold = "a=sendrecv\r\n";
-       }
 
        /* Now, start adding audio codecs. These are added in this order:
                - First what was requested by the calling channel
@@ -9169,15 +9153,14 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
        for (x = 0; x < 32; x++) {
                int codec;
 
-               if (!(codec = ast_codec_pref_index(&p->prefs, x))) {
-                       break;
-               }
-               if (!(capability & codec)) {
+               if (!(codec = ast_codec_pref_index(&p->prefs, x)))
+                       break; 
+
+               if (!(capability & codec))
                        continue;
-               }
-               if (alreadysent & codec) {
+
+               if (alreadysent & codec)
                        continue;
-               }
 
                add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec),
                                 &m_audio, &a_audio,
@@ -9187,85 +9170,67 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
 
        /* Now send any other common audio and video codecs, and non-codec formats: */
        for (x = 1; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) {
-               if (!(capability & x)) {  /* Codec not requested */
+               if (!(capability & x))  /* Codec not requested */
                        continue;
-               }
 
-               if (alreadysent & x) {    /* Already added to SDP */
+               if (alreadysent & x)    /* Already added to SDP */
                        continue;
-               }
 
-               if (x & AST_FORMAT_AUDIO_MASK) {
+               if (x & AST_FORMAT_AUDIO_MASK)
                        add_codec_to_sdp(p, x, SDP_SAMPLE_RATE(x),
                                 &m_audio, &a_audio, debug, &min_audio_packet_size);
-               } else if (x & AST_FORMAT_VIDEO_MASK) {
+               else if (x & AST_FORMAT_VIDEO_MASK) 
                        add_vcodec_to_sdp(p, x, 90000,
                                 &m_video, &a_video, debug, &min_video_packet_size);
-               } else if (x & AST_FORMAT_TEXT_MASK) {
+               else if (x & AST_FORMAT_TEXT_MASK)
                        add_tcodec_to_sdp(p, x, 1000,
                                 &m_text, &a_text, debug, &min_text_packet_size);
-               }
        }
 
        /* Now add DTMF RFC2833 telephony-event as a codec */
        for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
-               if (!(p->jointnoncodeccapability & x)) {
+               if (!(p->jointnoncodeccapability & x))
                        continue;
-               }
 
                add_noncodec_to_sdp(p, x, 8000, &m_audio, &a_audio, debug);
        }
 
        ast_debug(3, "-- Done with adding codecs to SDP\n");
 
-       if (!p->owner || !ast_internal_timing_enabled(p->owner)) {
+       if (!p->owner || !ast_internal_timing_enabled(p->owner))
                ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n");
-       }
 
-       if (min_audio_packet_size) {
+       if (min_audio_packet_size)
                ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size);
-       }
 
        /* XXX don't think you can have ptime for video */
-       if (min_video_packet_size) {
+       if (min_video_packet_size)
                ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size);
-       }
 
        /* XXX don't think you can have ptime for text */
-       if (min_text_packet_size) {
+       if (min_text_packet_size)
                ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size);
-       }
  
-       if (    ast_str_size(m_audio) - ast_str_strlen(m_audio) < 2 ||
-                       ast_str_size(m_video) - ast_str_strlen(m_video) < 2 ||
-                       ast_str_size(m_text) - ast_str_strlen(m_text) < 2 ||
-                       ast_str_size(a_text) - ast_str_strlen(a_text) < 2 ||
-                       ast_str_size(a_audio) - ast_str_strlen(a_audio) < 2 ||
-                       ast_str_size(a_video) - ast_str_strlen(a_video) < 2) {
+       if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 ||
+                       m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 ||
+                       a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2)
                ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
-       }
 
-       if (needaudio) {
+       if (needaudio)
                ast_str_append(&m_audio, 0, "\r\n");
-       }
-       if (needvideo) {
+       if (needvideo)
                ast_str_append(&m_video, 0, "\r\n");
-       }
-       if (needtext) {
+       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 += ast_str_strlen(m_audio) + ast_str_strlen(a_audio) + strlen(hold);
-       }
-       if (needvideo) { /* only if video response is appropriate */
-               len += ast_str_strlen(m_video) + ast_str_strlen(a_video) + strlen(bandwidth) + strlen(hold);
-       }
-       if (needtext) { /* only if text response is appropriate */
-               len += ast_str_strlen(m_text) + ast_str_strlen(a_text) + strlen(hold);
-       }
+       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);
 
        add_header(resp, "Content-Type", "application/sdp");
        add_header_contentLength(resp, len);
@@ -9273,23 +9238,22 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
        add_line(resp, owner);
        add_line(resp, subject);
        add_line(resp, connection);
-       if (needvideo) {                /* only if video response is appropriate */
+       if (needvideo)          /* only if video response is appropriate */
                add_line(resp, bandwidth);
-       }
        add_line(resp, session_time);
        if (needaudio) {
-               add_line(resp, ast_str_buffer(m_audio));
-               add_line(resp, ast_str_buffer(a_audio));
+               add_line(resp, m_audio->str);
+               add_line(resp, a_audio->str);
                add_line(resp, hold);
        }
        if (needvideo) { /* only if video response is appropriate */
-               add_line(resp, ast_str_buffer(m_video));
-               add_line(resp, ast_str_buffer(a_video));
+               add_line(resp, m_video->str);
+               add_line(resp, a_video->str);
                add_line(resp, hold);   /* Repeat hold for the video stream */
        }
        if (needtext) { /* only if text response is appropriate */
-               add_line(resp, ast_str_buffer(m_text));
-               add_line(resp, ast_str_buffer(a_text));
+               add_line(resp, m_text->str);
+               add_line(resp, a_text->str);
                add_line(resp, hold);   /* Repeat hold for the text stream */
        }
 
@@ -9339,13 +9303,14 @@ static void copy_request(struct sip_request *dst, const struct sip_request *src)
         * the place and so a memcpy is the only way to accurately copy the string
         */
 
-       if (!dst->data && !(dst->data = ast_str_create(ast_str_strlen(src->data) + 1)))
+       if (!dst->data && !(dst->data = ast_str_create(src->data->used + 1)))
                return;
-       else if (ast_str_size(dst->data) < ast_str_strlen(src->data) + 1)
-               ast_str_make_space(&dst->data, ast_str_strlen(src->data) + 1);
-
-       ast_str_set(&dst->data, 0, "%s", ast_str_buffer(src->data));
-       offset = ((void *)ast_str_buffer(dst->data)) - ((void *)ast_str_buffer(src->data));
+       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;
+       offset = ((void *)dst->data->str) - ((void *)src->data->str);
        /* Now fix pointer arithmetic */
        for (x = 0; x < src->headers; x++)
                dst->header[x] += offset;
@@ -9694,7 +9659,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
        /* This is the request URI, which is the next hop of the call
                which may or may not be the destination of the call
        */
-       ast_string_field_set(p, uri, ast_str_buffer(invite));
+       ast_string_field_set(p, uri, invite->str);
   
        if (!ast_strlen_zero(p->todnid)) {
                /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */
@@ -9977,8 +9942,8 @@ static int find_calling_channel(struct ast_channel *c, void *data) {
 /*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */
 static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout)
 {
-       struct ast_str *tmp = ast_str_thread_get(&transmit_state_buffer, 4000);
-       char from[256] = "", to[256] = "";
+       struct ast_str *tmp = ast_str_alloca(4000);
+       char from[256], to[256];
        char *c, *mfrom, *mto;
        struct sip_request req;
        char hint[AST_MAX_EXTENSION];
@@ -9988,6 +9953,9 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim
        char *pidfstate = "--";
        char *pidfnote= "Ready";
        
+       memset(from, 0, sizeof(from));
+       memset(to, 0, sizeof(to));
+
        switch (state) {
        case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE):
                statestring = (global_notifyringing) ? "early" : "confirmed";
@@ -10177,8 +10145,8 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim
                break;
        }
 
-       add_header_contentLength(&req, ast_str_strlen(tmp));
-       add_line(&req, ast_str_buffer(tmp));
+       add_header_contentLength(&req, tmp->used);
+       add_line(&req, tmp->str);
 
        p->pendinginvite = p->ocseq;    /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */
 
@@ -10216,8 +10184,8 @@ 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, ast_str_strlen(out));
-       add_line(&req, ast_str_buffer(out));
+       add_header_contentLength(&req, out->used);
+       add_line(&req, out->str);
 
        if (!p->initreq.headers) 
                initialize_initreq(p, &req);
@@ -11484,7 +11452,7 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
        if (res == AST_DYNSTR_BUILD_FAILED)
                return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */
 
-       c = ast_str_buffer(buf);
+       c = buf->str;
 
        while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */
                for (i = keys; i->key != NULL; i++) {
@@ -13975,7 +13943,7 @@ static char *sip_qualify_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 }
 
 /*! \brief list peer mailboxes to CLI */
-static char *peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer)
+static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer)
 {
        struct sip_mailbox *mailbox;
 
@@ -13986,7 +13954,6 @@ static char *peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer
                        S_OR(mailbox->context, ""),
                        AST_LIST_NEXT(mailbox, entry) ? "," : "");
        }
-       return ast_str_buffer(*mailbox_str);
 }
 
 /*! \brief Show one peer in detail (main function) */
@@ -14023,7 +13990,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
                }
        }
        if (peer && type==0 ) { /* Normal listing */
-               struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
+               struct ast_str *mailbox_str = ast_str_alloca(512);
                ast_cli(fd, "\n\n");
                ast_cli(fd, "  * Name       : %s\n", peer->name);
                if (realtimepeers) {    /* Realtime is enabled */
@@ -14052,7 +14019,8 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
                print_group(fd, peer->callgroup, 0);
                ast_cli(fd, "  Pickupgroup  : ");
                print_group(fd, peer->pickupgroup, 0);
-               ast_cli(fd, "  Mailbox      : %s\n", peer_mailboxes_to_str(&mailbox_str, peer));
+               peer_mailboxes_to_str(&mailbox_str, peer);
+               ast_cli(fd, "  Mailbox      : %s\n", mailbox_str->str);
                ast_cli(fd, "  VM Extension : %s\n", peer->vmexten);
                ast_cli(fd, "  LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff);
                ast_cli(fd, "  Call limit   : %d\n", peer->call_limit);
@@ -14138,7 +14106,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
                peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr");
        } else  if (peer && type == 1) { /* manager listing */
                char buffer[256];
-               struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
+               struct ast_str *mailbox_str = ast_str_alloca(512);
                astman_append(s, "Channeltype: SIP\r\n");
                astman_append(s, "ObjectName: %s\r\n", peer->name);
                astman_append(s, "ChanObjectType: peer\r\n");
@@ -14159,7 +14127,8 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
                astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup));
                astman_append(s, "Pickupgroup: ");
                astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup));
-               astman_append(s, "VoiceMailbox: %s\r\n", peer_mailboxes_to_str(&mailbox_str, peer));
+               peer_mailboxes_to_str(&mailbox_str, peer);
+               astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str);
                astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer));
                astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
                astman_append(s, "Call-limit: %d\r\n", peer->call_limit);
@@ -14726,7 +14695,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags)
                arg->numchans++;
        }
        if (cur->subscribed != NONE && arg->subscriptions) {
-               struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
+               struct ast_str *mailbox_str = ast_str_alloca(512);
                if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer)
                        peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer);
                ast_cli(arg->fd, FORMAT4, ast_inet_ntoa(dst->sin_addr),
@@ -14736,7 +14705,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags)
                                cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri,
                                cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), 
                                subscription_type2str(cur->subscribed),
-                               cur->subscribed == MWI_NOTIFICATION ? AS_OR(mailbox_str, "<none>") : "<none>",
+                               cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>",
                                cur->expiry
                        );
                arg->numchans++;
@@ -15822,8 +15791,9 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
        } else  if (!strcasecmp(colname, "useragent")) {
                ast_copy_string(buf, peer->useragent, len);
        } else  if (!strcasecmp(colname, "mailbox")) {
-               struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
-               ast_copy_string(buf, peer_mailboxes_to_str(&mailbox_str, peer), len);
+               struct ast_str *mailbox_str = ast_str_alloca(512);
+               peer_mailboxes_to_str(&mailbox_str, peer);
+               ast_copy_string(buf, mailbox_str->str, len);
        } else  if (!strcasecmp(colname, "context")) {
                ast_copy_string(buf, peer->context, len);
        } else  if (!strcasecmp(colname, "expire")) {
@@ -18122,12 +18092,12 @@ static int do_magic_pickup(struct ast_channel *channel, const char *extension, c
 
        ast_str_set(&str, 0, "%s@%s", extension, context);
 
-       ast_debug(2, "About to call Pickup(%s)\n", ast_str_buffer(str));
+       ast_debug(2, "About to call Pickup(%s)\n", str->str);
 
        /* There is no point in capturing the return value since pickup_exec
           doesn't return anything meaningful unless the passed data is an empty
           string (which in our case it will not be) */
-       pbx_exec(channel, pickup, ast_str_buffer(str));
+       pbx_exec(channel, pickup, str->str);
 
        return 0;
 }
@@ -20229,7 +20199,7 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
                return 1;
        }
 
-       if (ast_str_set(&req.data, -1, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) {
+       if (ast_str_set(&req.data, 0, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) {
                return -1;
        }
 
@@ -20262,11 +20232,11 @@ static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin)
        if (sip_debug_test_addr(sin))   /* Set the debug flag early on packet level */
                req->debug = 1;
        if (sip_cfg.pedanticsipchecking)
-               req->len = lws2sws(ast_str_buffer(req->data), req->len);        /* Fix multiline headers */
+               req->len = lws2sws(req->data->str, req->len);   /* Fix multiline headers */
        if (req->debug) {
                ast_verbose("\n<--- SIP read from %s:%s:%d --->\n%s\n<------------->\n", 
                        get_transport(req->socket.type), ast_inet_ntoa(sin->sin_addr), 
-                       ntohs(sin->sin_port), ast_str_buffer(req->data));
+                       ntohs(sin->sin_port), req->data->str);
        }
 
        if(parse_request(req) == -1) { /* Bad packet, can't parse */
@@ -20313,7 +20283,7 @@ static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin)
        p->recv = *sin;
 
        if (p->do_history) /* This is a request or response, note what it was for */
-               append_history(p, "Rx", "%s / %s / %s", ast_str_buffer(req->data), get_header(req, "CSeq"), req->rlPart2);
+               append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), req->rlPart2);
 
        if (!lockretry) {
                if (p->owner)
@@ -20558,8 +20528,9 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *e
        } else if (cache_only) {
                return 0;
        } else { /* Fall back to manually checking the mailbox */
-               struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16);
-               ast_app_inboxcount(peer_mailboxes_to_str(&mailbox_str, peer), &newmsgs, &oldmsgs);
+               struct ast_str *mailbox_str = ast_str_alloca(512);
+               peer_mailboxes_to_str(&mailbox_str, peer);
+               ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs);
        }
        
        if (peer->mwipvt) {
@@ -22003,7 +21974,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
                        ast_copy_string(peer->name, v->value, sizeof(peer->name));
                else if (realtime && !strcasecmp(v->name, "fullcontact")) {
                        /* Reconstruct field, because realtime separates our value at the ';' */
-                       if (ast_str_strlen(fullcontact) > 0) {
+                       if (fullcontact->used > 0) {
                                ast_str_append(&fullcontact, 0, ";%s", v->value);
                        } else {
                                ast_str_set(&fullcontact, 0, "%s", v->value);
@@ -22285,8 +22256,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
                peer->socket.type = default_primary_transport;
        }
 
-       if (ast_str_strlen(fullcontact) > 0) {
-               ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
+       if (fullcontact->used > 0) {
+               ast_string_field_set(peer, fullcontact, fullcontact->str);
                peer->rt_fromcontact = TRUE;
                /* We have a hostname in the fullcontact, but if we don't have an
                 * address listed on the entry (or if it's 'dynamic'), then we need to
@@ -22295,7 +22266,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
                 * register once again). */
                /* XXX May need to revisit the final argument; does the realtime DB store whether
                 * the original contact was over TLS or not? XXX */
-               __set_address_from_contact(ast_str_buffer(fullcontact), &peer->addr, 0);
+               __set_address_from_contact(fullcontact->str, &peer->addr, 0);
        }
 
        if (srvlookup && peer->dnsmgr == NULL) {
index 0001c96..18b363b 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef _ASTERISK_STRINGS_H
 #define _ASTERISK_STRINGS_H
 
-#define DEBUG_OPAQUE
+/* #define DEBUG_OPAQUE */
 
 #include <ctype.h>
 
@@ -32,7 +32,7 @@
 
 /* You may see casts in this header that may seem useless but they ensure this file is C++ clean */
 
-#define AS_OR(a,b)     ast_str_strlen(a) ? ast_str_buffer(a) : (b)
+#define AS_OR(a,b)     (a && ast_str_strlen(a)) ? ast_str_buffer(a) : (b)
 
 #ifdef AST_DEVMODE
 #define ast_strlen_zero(foo)   _ast_strlen_zero(foo, __FILE__, __PRETTY_FUNCTION__, __LINE__)