add memory-pool based string field management for structures
authorKevin P. Fleming <kpfleming@digium.com>
Wed, 4 Jan 2006 21:54:09 +0000 (21:54 +0000)
committerKevin P. Fleming <kpfleming@digium.com>
Wed, 4 Jan 2006 21:54:09 +0000 (21:54 +0000)
convert chan_sip sip_pvt and sip_registry structures to use string fields
add 'const' qualifiers to a few API calls that don't modify their input strings
add an asprintf() wrapper to astmm

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

astmm.c
channels/chan_sip.c
include/asterisk/astmm.h
include/asterisk/pbx.h
include/asterisk/stringfields.h [new file with mode: 0644]
include/asterisk/utils.h
pbx.c
utils.c

diff --git a/astmm.c b/astmm.c
index e80219b..385128d 100644 (file)
--- a/astmm.c
+++ b/astmm.c
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 1999 - 2005, Digium, Inc.
+ * Copyright (C) 1999 - 2006, Digium, Inc.
  *
  * Mark Spencer <markster@digium.com>
  *
@@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define FUNC_STRDUP    4
 #define FUNC_STRNDUP   5
 #define FUNC_VASPRINTF 6
+#define FUNC_ASPRINTF   7
 
 /* Undefine all our macros */
 #undef malloc
@@ -56,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #undef strndup
 #undef free
 #undef vasprintf
+#undef asprintf
 
 #define FENCE_MAGIC 0xdeadbeef
 
@@ -253,6 +255,28 @@ char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const
        return ptr;
 }
 
+int __ast_asprintf(const char *file, int lineno, const char *func, char **strp, const char *fmt, ...)
+{
+       int size;
+       va_list ap, ap2;
+       char s;
+
+       *strp = NULL;
+       va_start(ap, fmt);
+       va_copy(ap2, ap);
+       size = vsnprintf(&s, 1, fmt, ap2);
+       va_end(ap2);
+       *strp = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func);
+       if (!*strp) {
+               va_end(ap);
+               return -1;
+       }
+       vsnprintf(*strp, size + 1, fmt, ap);
+       va_end(ap);
+
+       return size;
+}
+
 int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func) 
 {
        int size;
@@ -264,8 +288,10 @@ int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file,
        size = vsnprintf(&s, 1, fmt, ap2);
        va_end(ap2);
        *strp = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func);
-       if (!*strp)
+       if (!*strp) {
+               va_end(ap);
                return -1;
+       }
        vsnprintf(*strp, size + 1, fmt, ap);
 
        return size;
index 9d44d0c..55419f1 100644 (file)
@@ -86,6 +86,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/dnsmgr.h"
 #include "asterisk/devicestate.h"
 #include "asterisk/linkedlists.h"
+#include "asterisk/stringfields.h"
 
 #ifdef OSP_SUPPORT
 #include "asterisk/astosp.h"
@@ -596,8 +597,46 @@ static int global_rtautoclear = 120;
 static struct sip_pvt {
        ast_mutex_t lock;                       /*!< Channel private lock */
        int method;                             /*!< SIP method of this packet */
-       char callid[80];                        /*!< Global CallID */
-       char randdata[80];                      /*!< Random data */
+       AST_DECLARE_STRING_FIELDS(
+               AST_STRING_FIELD(callid);       /*!< Global CallID */
+               AST_STRING_FIELD(randdata);     /*!< Random data */
+               AST_STRING_FIELD(accountcode);  /*!< Account code */
+               AST_STRING_FIELD(realm);        /*!< Authorization realm */
+               AST_STRING_FIELD(nonce);        /*!< Authorization nonce */
+               AST_STRING_FIELD(opaque);       /*!< Opaque nonsense */
+               AST_STRING_FIELD(qop);          /*!< Quality of Protection, since SIP wasn't complicated enough yet. */
+               AST_STRING_FIELD(domain);       /*!< Authorization domain */
+               AST_STRING_FIELD(refer_to);     /*!< Place to store REFER-TO extension */
+               AST_STRING_FIELD(referred_by);  /*!< Place to store REFERRED-BY extension */
+               AST_STRING_FIELD(refer_contact);/*!< Place to store Contact info from a REFER extension */
+               AST_STRING_FIELD(from);         /*!< The From: header */
+               AST_STRING_FIELD(useragent);    /*!< User agent in SIP request */
+               AST_STRING_FIELD(exten);        /*!< Extension where to start */
+               AST_STRING_FIELD(context);      /*!< Context for this call */
+               AST_STRING_FIELD(subscribecontext); /*!< Subscribecontext */
+               AST_STRING_FIELD(fromdomain);   /*!< Domain to show in the from field */
+               AST_STRING_FIELD(fromuser);     /*!< User to show in the user field */
+               AST_STRING_FIELD(fromname);     /*!< Name to show in the user field */
+               AST_STRING_FIELD(tohost);       /*!< Host we should put in the "to" field */
+               AST_STRING_FIELD(language);     /*!< Default language for this call */
+               AST_STRING_FIELD(musicclass);   /*!< Music on Hold class */
+               AST_STRING_FIELD(rdnis);        /*!< Referring DNIS */
+               AST_STRING_FIELD(theirtag);     /*!< Their tag */
+               AST_STRING_FIELD(username);     /*!< [user] name */
+               AST_STRING_FIELD(peername);     /*!< [peer] name, not set if [user] */
+               AST_STRING_FIELD(authname);     /*!< Who we use for authentication */
+               AST_STRING_FIELD(uri);          /*!< Original requested URI */
+               AST_STRING_FIELD(okcontacturi); /*!< URI from the 200 OK on INVITE */
+               AST_STRING_FIELD(peersecret);   /*!< Password */
+               AST_STRING_FIELD(peermd5secret);
+               AST_STRING_FIELD(cid_num);      /*!< Caller*ID */
+               AST_STRING_FIELD(cid_name);     /*!< Caller*ID */
+               AST_STRING_FIELD(via);          /*!< Via: header */
+               AST_STRING_FIELD(fullcontact);  /*!< The Contact: that the UA registers with us */
+               AST_STRING_FIELD(our_contact);  /*!< Our contact header */
+               AST_STRING_FIELD(rpid);         /*!< Our RPID header */
+               AST_STRING_FIELD(rpid_from);    /*!< Our RPID From header */
+       );
        struct ast_codec_pref prefs;            /*!< codec prefs */
        unsigned int ocseq;                     /*!< Current outgoing seqno */
        unsigned int icseq;                     /*!< Current incoming seqno */
@@ -626,47 +665,11 @@ static struct sip_pvt {
        struct sockaddr_in recv;                /*!< Received as */
        struct in_addr ourip;                   /*!< Our IP */
        struct ast_channel *owner;              /*!< Who owns us */
-       char exten[AST_MAX_EXTENSION];          /*!< Extension where to start */
-       char refer_to[AST_MAX_EXTENSION];       /*!< Place to store REFER-TO extension */
-       char referred_by[AST_MAX_EXTENSION];    /*!< Place to store REFERRED-BY extension */
-       char refer_contact[AST_MAX_EXTENSION];  /*!< Place to store Contact info from a REFER extension */
        struct sip_pvt *refer_call;             /*!< Call we are referring */
        struct sip_route *route;                /*!< Head of linked list of routing steps (fm Record-Route) */
        int route_persistant;                   /*!< Is this the "real" route? */
-       char from[256];                         /*!< The From: header */
-       char useragent[256];                    /*!< User agent in SIP request */
-       char context[AST_MAX_CONTEXT];          /*!< Context for this call */
-       char subscribecontext[AST_MAX_CONTEXT]; /*!< Subscribecontext */
-       char fromdomain[MAXHOSTNAMELEN];        /*!< Domain to show in the from field */
-       char fromuser[AST_MAX_EXTENSION];       /*!< User to show in the user field */
-       char fromname[AST_MAX_EXTENSION];       /*!< Name to show in the user field */
-       char tohost[MAXHOSTNAMELEN];            /*!< Host we should put in the "to" field */
-       char language[MAX_LANGUAGE];            /*!< Default language for this call */
-       char musicclass[MAX_MUSICCLASS];        /*!< Music on Hold class */
-       char rdnis[256];                        /*!< Referring DNIS */
-       char theirtag[256];                     /*!< Their tag */
-       char username[256];                     /*!< [user] name */
-       char peername[256];                     /*!< [peer] name, not set if [user] */
-       char authname[256];                     /*!< Who we use for authentication */
-       char uri[256];                          /*!< Original requested URI */
-       char okcontacturi[256];                 /*!< URI from the 200 OK on INVITE */
-       char peersecret[256];                   /*!< Password */
-       char peermd5secret[256];
        struct sip_auth *peerauth;              /*!< Realm authentication */
-       char cid_num[256];                      /*!< Caller*ID */
-       char cid_name[256];                     /*!< Caller*ID */
-       char via[256];                          /*!< Via: header */
-       char fullcontact[128];                  /*!< The Contact: that the UA registers with us */
-       char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
-       char our_contact[256];                  /*!< Our contact header */
-       char *rpid;                             /*!< Our RPID header */
-       char *rpid_from;                        /*!< Our RPID From header */
-       char realm[MAXHOSTNAMELEN];             /*!< Authorization realm */
-       char nonce[256];                        /*!< Authorization nonce */
        int noncecount;                         /*!< Nonce-count */
-       char opaque[256];                       /*!< Opaque nonsense */
-       char qop[80];                           /*!< Quality of Protection, since SIP wasn't complicated enough yet. */
-       char domain[MAXHOSTNAMELEN];            /*!< Authorization domain */
        char lastmsg[256];                      /*!< Last Message sent/received */
        int amaflags;                           /*!< AMA Flags */
        int pendinginvite;                      /*!< Any pending invite */
@@ -823,14 +826,22 @@ static int sip_reloading = 0;
 /*! \brief sip_registry: Registrations with other SIP proxies */
 struct sip_registry {
        ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1);
+       AST_DECLARE_STRING_FIELDS(
+               AST_STRING_FIELD(callid);       /*!< Global Call-ID */
+               AST_STRING_FIELD(realm);        /*!< Authorization realm */
+               AST_STRING_FIELD(nonce);        /*!< Authorization nonce */
+               AST_STRING_FIELD(opaque);       /*!< Opaque nonsense */
+               AST_STRING_FIELD(qop);          /*!< Quality of Protection, since SIP wasn't complicated enough yet. */
+               AST_STRING_FIELD(domain);       /*!< Authorization domain */
+               AST_STRING_FIELD(username);     /*!< Who we are registering as */
+               AST_STRING_FIELD(authuser);     /*!< Who we *authenticate* as */
+               AST_STRING_FIELD(hostname);     /*!< Domain or host we register to */
+               AST_STRING_FIELD(secret);       /*!< Password in clear text */  
+               AST_STRING_FIELD(md5secret);    /*!< Password in md5 */
+               AST_STRING_FIELD(contact);      /*!< Contact extension */
+               AST_STRING_FIELD(random);
+       );
        int portno;                     /*!<  Optional port override */
-       char username[80];              /*!<  Who we are registering as */
-       char authuser[80];              /*!< Who we *authenticate* as */
-       char hostname[MAXHOSTNAMELEN];  /*!< Domain or host we register to */
-       char secret[80];                /*!< Password in clear text */  
-       char md5secret[80];             /*!< Password in md5 */
-       char contact[256];              /*!< Contact extension */
-       char random[80];
        int expire;                     /*!< Sched ID of expiration */
        int regattempts;                /*!< Number of attempts (since the last success) */
        int timeout;                    /*!< sched id of sip_reg_timeout */
@@ -838,19 +849,10 @@ struct sip_registry {
        struct sip_pvt *call;           /*!< create a sip_pvt structure for each outbound "registration call" in progress */
        int regstate;                   /*!< Registration state (see above) */
        int callid_valid;               /*!< 0 means we haven't chosen callid for this registry yet. */
-       char callid[80];                /*!< Global CallID for this registry */
        unsigned int ocseq;             /*!< Sequence number we got to for REGISTERs for this registry */
        struct sockaddr_in us;          /*!< Who the server thinks we are */
-       
-                                       /* Saved headers */
-       char realm[MAXHOSTNAMELEN];     /*!< Authorization realm */
-       char nonce[256];                /*!< Authorization nonce */
-       char domain[MAXHOSTNAMELEN];    /*!< Authorization domain */
-       char opaque[256];               /*!< Opaque nonsense */
-       char qop[80];                   /*!< Quality of Protection. */
        int noncecount;                 /*!< Nonce-count */
-       char lastmsg[256];              /*!< Last Message sent/received */
+       char lastmsg[256];              /*!< Last Message sent/received */
 };
 
 /*! \brief  The user list: Users and friends ---*/
@@ -891,7 +893,7 @@ static struct sip_auth *authl = NULL;          /*!< Authentication list */
 static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
 static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
 static int transmit_response_with_unsupported(struct sip_pvt *p, char *msg, struct sip_request *req, char *unsupported);
-static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *rand, int reliable, char *header, int stale);
+static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, const char *rand, int reliable, char *header, int stale);
 static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
 static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
 static int transmit_invite(struct sip_pvt *p, int sipmethod, int sendsdp, int init);
@@ -926,7 +928,7 @@ static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int sip_senddigit(struct ast_channel *ast, char digit);
 static int clear_realm_authentication(struct sip_auth *authlist);                            /* Clear realm authentication list (at reload) */
 static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno);   /* Add realm authentication in list */
-static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm);         /* Find authentication for a specific realm */
+static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, const char *realm);         /* Find authentication for a specific realm */
 static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */
 static void append_date(struct sip_request *req);      /* Append date to SIP packet */
 static int determine_firstline_parts(struct sip_request *req);
@@ -1084,15 +1086,15 @@ static int __sip_xmit(struct sip_pvt *p, char *data, int len)
 static void sip_destroy(struct sip_pvt *p);
 
 /*! \brief  build_via: Build a Via header for a request ---*/
-static void build_via(struct sip_pvt *p, char *buf, int len)
+static void build_via(struct sip_pvt *p)
 {
        char iabuf[INET_ADDRSTRLEN];
        /* Work around buggy UNIDEN UIP200 firmware */
-       const char *rport= ast_test_flag(p, SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
+       const char *rport = ast_test_flag(p, SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
 
        /* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
-       snprintf(buf, len, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
-               ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch, rport);
+       ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
+                              ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch, rport);
 }
 
 /*! \brief  ast_sip_ouraddrfor: NAT fix - decide which IP address to use for ASterisk server? ---*/
@@ -1857,28 +1859,31 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
                ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(r, SIP_NAT) & SIP_NAT_ROUTE));
                ast_rtp_setnat(r->vrtp, (ast_test_flag(r, SIP_NAT) & SIP_NAT_ROUTE));
        }
-       ast_copy_string(r->peername, peer->username, sizeof(r->peername));
-       ast_copy_string(r->authname, peer->username, sizeof(r->authname));
-       ast_copy_string(r->username, peer->username, sizeof(r->username));
-       ast_copy_string(r->peersecret, peer->secret, sizeof(r->peersecret));
-       ast_copy_string(r->peermd5secret, peer->md5secret, sizeof(r->peermd5secret));
-       ast_copy_string(r->tohost, peer->tohost, sizeof(r->tohost));
-       ast_copy_string(r->fullcontact, peer->fullcontact, sizeof(r->fullcontact));
+       ast_string_field_set(r, peername, peer->username);
+       ast_string_field_set(r, authname, peer->username);
+       ast_string_field_set(r, username, peer->username);
+       ast_string_field_set(r, peersecret, peer->secret);
+       ast_string_field_set(r, peermd5secret, peer->md5secret);
+       ast_string_field_set(r, tohost, peer->tohost);
+       ast_string_field_set(r, fullcontact, peer->fullcontact);
        if (!r->initreq.headers && !ast_strlen_zero(peer->fromdomain)) {
                if ((callhost = strchr(r->callid, '@'))) {
                        strncpy(callhost + 1, peer->fromdomain, sizeof(r->callid) - (callhost - r->callid) - 2);
                }
        }
        if (ast_strlen_zero(r->tohost)) {
+               char iabuf[INET_ADDRSTRLEN];
+
                if (peer->addr.sin_addr.s_addr)
-                       ast_inet_ntoa(r->tohost, sizeof(r->tohost), peer->addr.sin_addr);
+                       ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr);
                else
-                       ast_inet_ntoa(r->tohost, sizeof(r->tohost), peer->defaddr.sin_addr);
+                       ast_inet_ntoa(iabuf, sizeof(iabuf), peer->defaddr.sin_addr);
+               ast_string_field_set(r, tohost, iabuf);
        }
        if (!ast_strlen_zero(peer->fromdomain))
-               ast_copy_string(r->fromdomain, peer->fromdomain, sizeof(r->fromdomain));
+               ast_string_field_set(r, fromdomain, peer->fromdomain);
        if (!ast_strlen_zero(peer->fromuser))
-               ast_copy_string(r->fromuser, peer->fromuser, sizeof(r->fromuser));
+               ast_string_field_set(r, fromuser, peer->fromuser);
        r->maxtime = peer->maxms;
        r->callgroup = peer->callgroup;
        r->pickupgroup = peer->pickupgroup;
@@ -1889,7 +1894,7 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
                r->noncodeccapability |= AST_RTP_DTMF;
        else
                r->noncodeccapability &= ~AST_RTP_DTMF;
-       ast_copy_string(r->context, peer->context,sizeof(r->context));
+       ast_string_field_set(r, context, peer->context);
        r->rtptimeout = peer->rtptimeout;
        r->rtpholdtimeout = peer->rtpholdtimeout;
        r->rtpkeepalive = peer->rtpkeepalive;
@@ -1902,7 +1907,7 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
 /*! \brief  create_addr: create address structure from peer name
  *      Or, if peer not found, find it in the global DNS 
  *      returns TRUE (-1) on failure, FALSE on success */
-static int create_addr(struct sip_pvt *dialog, char *opeer)
+static int create_addr(struct sip_pvt *dialog, const char *opeer)
 {
        struct hostent *hp;
        struct ast_hostent ahp;
@@ -1950,7 +1955,7 @@ static int create_addr(struct sip_pvt *dialog, char *opeer)
                }
                hp = ast_gethostbyname(hostn, &ahp);
                if (hp) {
-                       ast_copy_string(dialog->tohost, peer, sizeof(dialog->tohost));
+                       ast_string_field_set(dialog, tohost, peer);
                        memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr));
                        dialog->sa.sin_port = htons(portno);
                        memcpy(&dialog->recv, &dialog->sa, sizeof(dialog->recv));
@@ -2073,6 +2078,7 @@ static void sip_registry_destroy(struct sip_registry *reg)
                ast_sched_del(sched, reg->expire);
        if (reg->timeout > -1)
                ast_sched_del(sched, reg->timeout);
+       ast_string_field_free_all(reg);
        regobjs--;
        free(reg);
        
@@ -2116,12 +2122,6 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
                ASTOBJ_UNREF(p->registry,sip_registry_destroy);
        }
 
-       if (p->rpid)
-               free(p->rpid);
-
-       if (p->rpid_from)
-               free(p->rpid_from);
-
        /* Unlink us from the owner if we have one */
        if (p->owner) {
                if (lockowner)
@@ -2173,6 +2173,9 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
                p->chanvars = NULL;
        }
        ast_mutex_destroy(&p->lock);
+
+       ast_string_field_free_all(p);
+
        free(p);
 }
 
@@ -2759,7 +2762,7 @@ static int sip_indicate(struct ast_channel *ast, int condition)
 
 /*! \brief  sip_new: Initiate a call in the SIP channel */
 /*      called from sip_request_call (calls from the pbx ) */
-static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
+static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *title)
 {
        struct ast_channel *tmp;
        struct ast_variable *v = NULL;
@@ -3036,24 +3039,46 @@ static struct ast_frame *sip_read(struct ast_channel *ast)
        return fr;
 }
 
-/*! \brief  build_callid: Build SIP CALLID header ---*/
-static void build_callid(char *callid, int len, struct in_addr ourip, char *fromdomain)
+/*! \brief  build_callid_pvt: Build SIP Call-ID value for a non-REGISTER transaction ---*/
+static void build_callid_pvt(struct sip_pvt *pvt)
 {
-       int res;
-       int val;
+       int val[4];
        int x;
        char iabuf[INET_ADDRSTRLEN];
-       for (x=0; x<4; x++) {
-               val = thread_safe_rand();
-               res = snprintf(callid, len, "%08x", val);
-               len -= res;
-               callid += res;
-       }
-       if (!ast_strlen_zero(fromdomain))
-               snprintf(callid, len, "@%s", fromdomain);
+
+       for (x=0; x<4; x++)
+               val[x] = thread_safe_rand();
+
+       if (ast_strlen_zero(pvt->fromdomain))
+               /* It's not important that we really use our right IP here... */
+               ast_string_field_build(pvt, callid, "%08x%08x%08x%08x@%s",
+                                      val[0], val[1], val[2], val[3],
+                                      ast_inet_ntoa(iabuf, sizeof(iabuf), pvt->ourip));
        else
-       /* It's not important that we really use our right IP here... */
-               snprintf(callid, len, "@%s", ast_inet_ntoa(iabuf, sizeof(iabuf), ourip));
+               ast_string_field_build(pvt, callid, "%08x%08x%08x%08x@%s",
+                                      val[0], val[1], val[2], val[3],
+                                      pvt->fromdomain);
+}
+
+/*! \brief  build_callid_registry: Build SIP Call-ID value for a REGISTER transaction ---*/
+static void build_callid_registry(struct sip_registry *reg, struct in_addr ourip, const char *fromdomain)
+{
+       int val[4];
+       int x;
+       char iabuf[INET_ADDRSTRLEN];
+
+       for (x=0; x<4; x++)
+               val[x] = thread_safe_rand();
+
+       if (ast_strlen_zero(fromdomain))
+               /* It's not important that we really use our right IP here... */
+               ast_string_field_build(reg, callid, "%08x%08x%08x%08x@%s",
+                                      val[0], val[1], val[2], val[3],
+                                      ast_inet_ntoa(iabuf, sizeof(iabuf), ourip));
+       else
+               ast_string_field_build(reg, callid, "%08x%08x%08x%08x@%s",
+                                      val[0], val[1], val[2], val[3],
+                                      fromdomain);
 }
 
 static void make_our_tag(char *tagbuf, size_t len)
@@ -3062,13 +3087,19 @@ static void make_our_tag(char *tagbuf, size_t len)
 }
 
 /*! \brief  sip_alloc: Allocate SIP_PVT structure and set defaults ---*/
-static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method)
+static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
+                                int useglobal_nat, const int intended_method)
 {
        struct sip_pvt *p;
 
        if (!(p = calloc(1, sizeof(*p))))
                return NULL;
 
+       if (ast_string_field_init(p)) {
+               free(p);
+               return NULL;
+       }
+
        ast_mutex_init(&p->lock);
 
        p->method = intended_method;
@@ -3129,19 +3160,19 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
        }
 
        if (p->method != SIP_REGISTER)
-               ast_copy_string(p->fromdomain, default_fromdomain, sizeof(p->fromdomain));
-       build_via(p, p->via, sizeof(p->via));
+               ast_string_field_set(p, fromdomain, default_fromdomain);
+       build_via(p);
        if (!callid)
-               build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
+               build_callid_pvt(p);
        else
-               ast_copy_string(p->callid, callid, sizeof(p->callid));
+               ast_string_field_set(p, callid, callid);
        ast_copy_flags(p, &global_flags, SIP_FLAGS_TO_COPY);
        /* Assign default music on hold class */
-       strcpy(p->musicclass, global_musicclass);
+       ast_string_field_set(p, musicclass, global_musicclass);
        p->capability = global_capability;
        if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833) || (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_AUTO))
                p->noncodeccapability |= AST_RTP_DTMF;
-       strcpy(p->context, default_context);
+       ast_string_field_set(p, context, default_context);
 
        /* Add to active dialog list */
        ast_mutex_lock(&iflock);
@@ -3274,23 +3305,28 @@ static int sip_register(char *value, int lineno)
                ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
                return -1;
        }
-       reg = malloc(sizeof(struct sip_registry));
-       if (!reg) {
+       if (!(reg = calloc(1, sizeof(*reg)))) {
                ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
                return -1;
        }
-       memset(reg, 0, sizeof(struct sip_registry));
+
+       if (ast_string_field_init(reg)) {
+               ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
+               free(reg);
+               return -1;
+       }
+
        regobjs++;
        ASTOBJ_INIT(reg);
-       ast_copy_string(reg->contact, contact, sizeof(reg->contact));
+       ast_string_field_set(reg, contact, contact);
        if (username)
-               ast_copy_string(reg->username, username, sizeof(reg->username));
+               ast_string_field_set(reg, username, username);
        if (hostname)
-               ast_copy_string(reg->hostname, hostname, sizeof(reg->hostname));
+               ast_string_field_set(reg, hostname, hostname);
        if (authuser)
-               ast_copy_string(reg->authuser, authuser, sizeof(reg->authuser));
+               ast_string_field_set(reg, authuser, authuser);
        if (secret)
-               ast_copy_string(reg->secret, secret, sizeof(reg->secret));
+               ast_string_field_set(reg, secret, secret);
        reg->expire = -1;
        reg->timeout =  -1;
        reg->refresh = default_expiry;
@@ -3993,7 +4029,7 @@ static int init_resp(struct sip_request *req, char *resp, struct sip_request *or
 }
 
 /*! \brief  init_req: Initialize SIP request ---*/
-static int init_req(struct sip_request *req, int sipmethod, char *recip)
+static int init_req(struct sip_request *req, int sipmethod, const char *recip)
 {
        /* Initialize a response */
        if (req->headers || req->len) {
@@ -4064,7 +4100,8 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in
        char stripped[80];
        char tmp[80];
        char newto[256];
-       char *c, *n;
+       const char *c;
+       char *n;
        char *ot, *of;
        int is_strict = 0;      /* Strict routing flag */
 
@@ -4079,7 +4116,7 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in
        
        if (newbranch) {
                p->branch ^= thread_safe_rand();
-               build_via(p, p->via, sizeof(p->via));
+               build_via(p);
        }
 
        /* Check for strict or loose router */
@@ -4101,8 +4138,8 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in
                c = p->uri;
        } else {
                /* We have no URI, use To: or From:  header as URI (depending on direction) */
-               c = get_header(orig, (ast_test_flag(p, SIP_OUTGOING)) ? "To" : "From");
-               ast_copy_string(stripped, c, sizeof(stripped));
+               ast_copy_string(stripped, get_header(orig, (ast_test_flag(p, SIP_OUTGOING)) ? "To" : "From"),
+                               sizeof(stripped));
                c = get_in_brackets(stripped);
                n = strchr(c, ';');
                if (n)
@@ -4237,7 +4274,7 @@ static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip
 }
 
 /* transmit_response_with_auth: Respond with authorization request */
-static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *randdata, int reliable, char *header, int stale)
+static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, const char *randdata, int reliable, char *header, int stale)
 {
        struct sip_request resp;
        char tmp[256];
@@ -4651,7 +4688,7 @@ static void extract_uri(struct sip_pvt *p, struct sip_request *req)
        if (n)
                *n = '\0';
        if (!ast_strlen_zero(c))
-               ast_copy_string(p->uri, c, sizeof(p->uri));
+               ast_string_field_set(p, uri, c);
 }
 
 /*! \brief  build_contact: Build contact header - the contact header we send out ---*/
@@ -4661,9 +4698,9 @@ static void build_contact(struct sip_pvt *p)
 
        /* Construct Contact: header */
        if (ourport != 5060)    /* Needs to be 5060, according to the RFC */
-               snprintf(p->our_contact, sizeof(p->our_contact), "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport);
+               ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport);
        else
-               snprintf(p->our_contact, sizeof(p->our_contact), "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip));
+               ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip));
 }
 
 /*! \brief  build_rpid: Build the Remote Party-ID & From using callingpres options ---*/
@@ -4739,12 +4776,11 @@ static void build_rpid(struct sip_pvt *p)
        snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain);
        if (send_pres_tags)
                snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen);
-       p->rpid = strdup(buf);
+       ast_string_field_set(p, rpid, buf);
 
-       snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>;tag=%s", clin,
-                ast_strlen_zero(p->fromuser) ? clid : p->fromuser,
-                fromdomain, p->tag);
-       p->rpid_from = strdup(buf);
+       ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin,
+                              ast_strlen_zero(p->fromuser) ? clid : p->fromuser,
+                              fromdomain, p->tag);
 }
 
 /*! \brief  initreqprep: Initiate new SIP request to peer/user ---*/
@@ -4758,7 +4794,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
        char tmp[BUFSIZ/2];
        char tmp2[BUFSIZ/2];
        char iabuf[INET_ADDRSTRLEN];
-       char *l = NULL, *n = NULL;
+       const char *l = NULL, *n = NULL;
        int x;
        char urioptions[256]="";
 
@@ -4806,13 +4842,13 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
        if (!ast_strlen_zero(p->fromuser))
                l = p->fromuser;
        else /* Save for any further attempts */
-               ast_copy_string(p->fromuser, l, sizeof(p->fromuser));
+               ast_string_field_set(p, fromuser, l);
 
        /* Allow user to be overridden */
        if (!ast_strlen_zero(p->fromname))
                n = p->fromname;
        else /* Save for any further attempts */
-               ast_copy_string(p->fromname, n, sizeof(p->fromname));
+               ast_string_field_set(p, fromname, n);
 
        if (pedanticsipchecking) {
                ast_uri_encode(n, tmp, sizeof(tmp), 0);
@@ -4850,8 +4886,8 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
        /* If custom URI options have been provided, append them */
        if (p->options && p->options->uri_options)
                ast_build_string(&invite, &invite_max, ";%s", p->options->uri_options);
-
-       ast_copy_string(p->uri, invite_buf, sizeof(p->uri));
+       
+       ast_string_field_set(p, uri, invite_buf);
 
        /* If there is a VXML URL append it to the SIP URL */
        if (p->options && p->options->vxml_url) {
@@ -4874,7 +4910,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
                add_header(req, "From", from);
        }
        add_header(req, "To", to);
-       ast_copy_string(p->exten, l, sizeof(p->exten));
+       ast_string_field_set(p, exten, l);
        build_contact(p);
        add_header(req, "Contact", p->our_contact);
        add_header(req, "Call-ID", p->callid);
@@ -4894,7 +4930,7 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
        if (init) {
                /* Bump branch even on initial requests */
                p->branch ^= thread_safe_rand();
-               build_via(p, p->via, sizeof(p->via));
+               build_via(p);
                if (init > 1)
                        initreqprep(&req, p, sipmethod);
                else
@@ -5340,7 +5376,6 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth,
        char from[256];
        char to[256];
        char tmp[80];
-       char via[80];
        char addr[80];
        struct sip_pvt *p;
 
@@ -5357,12 +5392,12 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth,
                } else {
                        p = r->call;
                        make_our_tag(p->tag, sizeof(p->tag));   /* create a new local tag for every register attempt */
-                       p->theirtag[0]='\0';    /* forget their old tag, so we don't match tags when getting response */
+                       ast_string_field_free(p, theirtag);     /* forget their old tag, so we don't match tags when getting response */
                }
        } else {
                /* Build callid for registration if we haven't registered before */
                if (!r->callid_valid) {
-                       build_callid(r->callid, sizeof(r->callid), __ourip, default_fromdomain);
+                       build_callid_registry(r, __ourip, default_fromdomain);
                        r->callid_valid = 1;
                }
                /* Allocate SIP packet for registration */
@@ -5390,32 +5425,32 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth,
                        return 0;
                }
                /* Copy back Call-ID in case create_addr changed it */
-               ast_copy_string(r->callid, p->callid, sizeof(r->callid));
+               ast_string_field_set(r, callid, p->callid);
                if (r->portno)
                        p->sa.sin_port = htons(r->portno);
                ast_set_flag(p, SIP_OUTGOING);  /* Registration is outgoing call */
                r->call=p;                      /* Save pointer to SIP packet */
                p->registry=ASTOBJ_REF(r);      /* Add pointer to registry in packet */
                if (!ast_strlen_zero(r->secret))        /* Secret (password) */
-                       ast_copy_string(p->peersecret, r->secret, sizeof(p->peersecret));
+                       ast_string_field_set(p, peersecret, r->secret);
                if (!ast_strlen_zero(r->md5secret))
-                       ast_copy_string(p->peermd5secret, r->md5secret, sizeof(p->peermd5secret));
+                       ast_string_field_set(p, peermd5secret, r->md5secret);
                /* User name in this realm  
                - if authuser is set, use that, otherwise use username */
                if (!ast_strlen_zero(r->authuser)) {    
-                       ast_copy_string(p->peername, r->authuser, sizeof(p->peername));
-                       ast_copy_string(p->authname, r->authuser, sizeof(p->authname));
+                       ast_string_field_set(p, peername, r->authuser);
+                       ast_string_field_set(p, authname, r->authuser);
                } else {
                        if (!ast_strlen_zero(r->username)) {
-                               ast_copy_string(p->peername, r->username, sizeof(p->peername));
-                               ast_copy_string(p->authname, r->username, sizeof(p->authname));
-                               ast_copy_string(p->fromuser, r->username, sizeof(p->fromuser));
+                               ast_string_field_set(p, peername, r->username);
+                               ast_string_field_set(p, authname, r->username);
+                               ast_string_field_set(p, fromuser, r->username);
                        }
                }
                if (!ast_strlen_zero(r->username))
-                       ast_copy_string(p->username, r->username, sizeof(p->username));
+                       ast_string_field_set(p, username, r->username);
                /* Save extension in packet */
-               ast_copy_string(p->exten, r->contact, sizeof(p->exten));
+               ast_string_field_set(p, exten, r->contact);
 
                /*
                  check which address we should use in our contact header 
@@ -5457,7 +5492,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth,
                snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain);
        else
                snprintf(addr, sizeof(addr), "sip:%s", r->hostname);
-       ast_copy_string(p->uri, addr, sizeof(p->uri));
+       ast_string_field_set(p, uri, addr);
 
        p->branch ^= thread_safe_rand();
 
@@ -5468,8 +5503,8 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth,
        snprintf(tmp, sizeof(tmp), "%u %s", ++r->ocseq, sip_methods[sipmethod].text);
        p->ocseq = r->ocseq;
 
-       build_via(p, via, sizeof(via));
-       add_header(&req, "Via", via);
+       build_via(p);
+       add_header(&req, "Via", p->via);
        add_header(&req, "From", from);
        add_header(&req, "To", to);
        add_header(&req, "Call-ID", p->callid);
@@ -5486,11 +5521,11 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth,
                /* We have auth data to reuse, build a digest header! */
                if (sipdebug)
                        ast_log(LOG_DEBUG, "   >>> Re-using Auth data for %s@%s\n", r->username, r->hostname);
-               ast_copy_string(p->realm, r->realm, sizeof(p->realm));
-               ast_copy_string(p->nonce, r->nonce, sizeof(p->nonce));
-               ast_copy_string(p->domain, r->domain, sizeof(p->domain));
-               ast_copy_string(p->opaque, r->opaque, sizeof(p->opaque));
-               ast_copy_string(p->qop, r->qop, sizeof(p->qop));
+               ast_string_field_set(p, realm, r->realm);
+               ast_string_field_set(p, nonce, r->nonce);
+               ast_string_field_set(p, domain, r->domain);
+               ast_string_field_set(p, opaque, r->opaque);
+               ast_string_field_set(p, qop, r->qop);
                p->noncecount = r->noncecount++;
 
                memset(digest,0,sizeof(digest));
@@ -5543,7 +5578,7 @@ static int transmit_refer(struct sip_pvt *p, const char *dest)
                of = get_header(&p->initreq, "From");
        ast_copy_string(from, of, sizeof(from));
        of = get_in_brackets(from);
-       ast_copy_string(p->from,of,sizeof(p->from));
+       ast_string_field_set(p, from, of);
        if (strncmp(of, "sip:", 4)) {
                ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
        } else
@@ -5562,8 +5597,8 @@ static int transmit_refer(struct sip_pvt *p, const char *dest)
        }
 
        /* save in case we get 407 challenge */
-       ast_copy_string(p->refer_to, referto, sizeof(p->refer_to));
-       ast_copy_string(p->referred_by, p->our_contact, sizeof(p->referred_by));
+       ast_string_field_set(p, refer_to, referto);
+       ast_string_field_set(p, referred_by, p->our_contact);
 
        reqprep(&req, p, SIP_REFER, 0, 1);
        add_header(&req, "Refer-To", referto);
@@ -5608,7 +5643,7 @@ static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqn
        struct sip_request resp;
 
        reqprep(&resp, p, sipmethod, seqno, newbranch);
-       if (*p->realm) {
+       if (!ast_strlen_zero(p->realm)) {
                char digest[1024];
 
                memset(digest, 0, sizeof(digest));
@@ -5753,10 +5788,10 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
        c = get_in_brackets(contact);
 
        /* Save full contact to call pvt for later bye or re-invite */
-       ast_copy_string(pvt->fullcontact, c, sizeof(pvt->fullcontact)); 
+       ast_string_field_set(pvt, fullcontact, c);
 
        /* Save URI for later ACKs, BYE or RE-invites */
-       ast_copy_string(pvt->okcontacturi, c, sizeof(pvt->okcontacturi));
+       ast_string_field_set(pvt, okcontacturi, c);
        
        /* Make sure it's a SIP URL */
        if (strncasecmp(c, "sip:", 4)) {
@@ -5885,7 +5920,7 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
        }
        ast_copy_string(p->fullcontact, c, sizeof(p->fullcontact));
        /* For the 200 OK, we should use the received contact */
-       snprintf(pvt->our_contact, sizeof(pvt->our_contact) - 1, "<%s>", c);
+       ast_string_field_build(pvt, our_contact, "<%s>", c);
        /* Make sure it's a SIP URL */
        if (strncasecmp(c, "sip:", 4)) {
                ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", c);
@@ -6113,7 +6148,9 @@ static int check_osptoken (struct sip_pvt *p, char *token)
 /*! \brief  check_auth: Check user authorization from peer definition ---*/
 /*      Some actions, like REGISTER and INVITEs from peers require
         authentication (if peer have secret set) */
-static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata, int randlen, char *username, char *secret, char *md5secret, int sipmethod, char *uri, int reliable, int ignore)
+static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *username,
+                     const char *secret, const char *md5secret, int sipmethod,
+                     char *uri, int reliable, int ignore)
 {
        int res = -1;
        char *response = "407 Proxy Authentication Required";
@@ -6178,22 +6215,22 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
        }
 #endif 
        authtoken =  get_header(req, reqheader);        
-       if (ignore && !ast_strlen_zero(randdata) && ast_strlen_zero(authtoken)) {
+       if (ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) {
                /* This is a retransmitted invite/register/etc, don't reconstruct authentication
                   information */
-               if (!ast_strlen_zero(randdata)) {
+               if (!ast_strlen_zero(p->randdata)) {
                        if (!reliable) {
                                /* Resend message if this was NOT a reliable delivery.   Otherwise the
                                   retransmission should get it */
-                               transmit_response_with_auth(p, response, req, randdata, reliable, respheader, 0);
+                               transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
                                /* Schedule auto destroy in 15 seconds */
                                sip_scheddestroy(p, 15000);
                        }
                        res = 1;
                }
-       } else if (ast_strlen_zero(randdata) || ast_strlen_zero(authtoken)) {
-               snprintf(randdata, randlen, "%08x", thread_safe_rand());
-               transmit_response_with_auth(p, response, req, randdata, reliable, respheader, 0);
+       } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) {
+               ast_string_field_build(p, randdata, "%08x", thread_safe_rand());
+               transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
                /* Schedule auto destroy in 15 seconds */
                sip_scheddestroy(p, 15000);
                res = 1;
@@ -6214,7 +6251,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
                char *nonce = "";
                char *digestusername = "";
                int  wrongnonce = 0;
-               char *usednonce = randdata;
+               const char *usednonce = p->randdata;
 
                /* Find their response among the mess that we'r sent for comparison */
                ast_copy_string(tmp, authtoken, sizeof(tmp));
@@ -6284,7 +6321,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
                }
 
                /* Verify nonce from request matches our nonce.  If not, send 401 with new nonce */
-               if (strncasecmp(randdata, nonce, randlen)) {
+               if (strcasecmp(p->randdata, nonce)) {
                        wrongnonce = 1;
                        usednonce = nonce;
                }
@@ -6307,18 +6344,17 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
                ast_md5_hash(resp_hash, resp);
 
                if (wrongnonce) {
-
-                       snprintf(randdata, randlen, "%08x", thread_safe_rand());
+                       ast_string_field_build(p, randdata, "%08x", thread_safe_rand());
                        if (ua_hash && !strncasecmp(ua_hash, resp_hash, strlen(resp_hash))) {
                                if (sipdebug)
                                        ast_log(LOG_NOTICE, "stale nonce received from '%s'\n", get_header(req, "To"));
                                /* We got working auth token, based on stale nonce . */
-                               transmit_response_with_auth(p, response, req, randdata, reliable, respheader, 1);
+                               transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 1);
                        } else {
                                /* Everything was wrong, so give the device one more try with a new challenge */
                                if (sipdebug)
                                        ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", get_header(req, "To"));
-                               transmit_response_with_auth(p, response, req, randdata, reliable, respheader, 0);
+                               transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
                        }
 
                        /* Schedule auto destroy in 15 seconds */
@@ -6412,7 +6448,7 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
                }
        }
 
-       ast_copy_string(p->exten, name, sizeof(p->exten));
+       ast_string_field_set(p, exten, name);
        build_contact(p);
        peer = find_peer(name, NULL, 1);
        if (!(peer && ast_apply_ha(peer->ha, sin))) {
@@ -6425,7 +6461,7 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
                } else {
                        ast_copy_flags(p, peer, SIP_NAT);
                        transmit_response(p, "100 Trying", req);
-                       if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
+                       if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
                                sip_cancel_destroy(p);
                                switch (parse_register_contact(p, peer, req)) {
                                case PARSE_REGISTER_FAILED:
@@ -6531,7 +6567,7 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq)
        }
        if (sip_debug_test_pvt(p))
                ast_verbose("RDNIS is %s\n", c);
-       ast_copy_string(p->rdnis, c, sizeof(p->rdnis));
+       ast_string_field_set(p, rdnis, c);
 
        return 0;
 }
@@ -6581,7 +6617,7 @@ static int get_destination(struct sip_pvt *p, struct sip_request *oreq)
                colon = strchr(a, ':'); /* Remove :port */
                if (colon)
                        *colon = '\0';
-               ast_copy_string(p->domain, a, sizeof(p->domain));
+               ast_string_field_set(p, domain, a);
        }
        /* Skip any options */
        if ((a = strchr(uri, ';'))) {
@@ -6600,7 +6636,7 @@ static int get_destination(struct sip_pvt *p, struct sip_request *oreq)
                }
                /* If we have a context defined, overwrite the original context */
                if (!ast_strlen_zero(domain_context))
-                       ast_copy_string(p->context, domain_context, sizeof(p->context));
+                       ast_string_field_set(p, context, domain_context);
        }
 
        if (from) {
@@ -6608,9 +6644,9 @@ static int get_destination(struct sip_pvt *p, struct sip_request *oreq)
                        *a = '\0';
                if ((a = strchr(from, '@'))) {
                        *a = '\0';
-                       ast_copy_string(p->fromdomain, a + 1, sizeof(p->fromdomain));
+                       ast_string_field_set(p, fromdomain, a + 1);
                } else
-                       ast_copy_string(p->fromdomain, from, sizeof(p->fromdomain));
+                       ast_string_field_set(p, fromdomain, from);
        }
        if (sip_debug_test_pvt(p))
                ast_verbose("Looking for %s in %s (domain %s)\n", uri, p->context, p->domain);
@@ -6619,7 +6655,7 @@ static int get_destination(struct sip_pvt *p, struct sip_request *oreq)
        if (ast_exists_extension(NULL, p->context, uri, 1, from) ||
                !strcmp(uri, ast_pickup_ext())) {
                if (!oreq)
-                       ast_copy_string(p->exten, uri, sizeof(p->exten));
+                       ast_string_field_set(p, exten, uri);
                return 0;
        }
 
@@ -6755,9 +6791,9 @@ static int get_refer_info(struct sip_pvt *sip_pvt, struct sip_request *outgoing_
                /* This is a supervised transfer */
                ast_log(LOG_DEBUG,"Assigning Replace-Call-ID Info %s to REPLACE_CALL_ID\n",replace_callid);
                
-               ast_copy_string(sip_pvt->refer_to, "", sizeof(sip_pvt->refer_to));
-               ast_copy_string(sip_pvt->referred_by, "", sizeof(sip_pvt->referred_by));
-               ast_copy_string(sip_pvt->refer_contact, "", sizeof(sip_pvt->refer_contact));
+               ast_string_field_free(sip_pvt, refer_to);
+               ast_string_field_free(sip_pvt, referred_by);
+               ast_string_field_free(sip_pvt, refer_contact);
                sip_pvt->refer_call = NULL;
                if ((sip_pvt_ptr = get_sip_pvt_byid_locked(replace_callid))) {
                        sip_pvt->refer_call = sip_pvt_ptr;
@@ -6779,11 +6815,11 @@ static int get_refer_info(struct sip_pvt *sip_pvt, struct sip_request *outgoing_
                if (referred_by)
                        ast_log(LOG_DEBUG,"Transferred by  (Referred-by: ) %s \n", referred_by);
                ast_log(LOG_DEBUG,"Transfer Contact Info %s (REFER_CONTACT)\n", h_contact);
-               ast_copy_string(sip_pvt->refer_to, refer_to, sizeof(sip_pvt->refer_to));
+               ast_string_field_set(sip_pvt, refer_to, refer_to);
                if (referred_by)
-                       ast_copy_string(sip_pvt->referred_by, referred_by, sizeof(sip_pvt->referred_by));
+                       ast_string_field_set(sip_pvt, referred_by, referred_by);
                if (h_contact) {
-                       ast_copy_string(sip_pvt->refer_contact, h_contact, sizeof(sip_pvt->refer_contact));
+                       ast_string_field_set(sip_pvt, refer_contact, h_contact);
                }
                sip_pvt->refer_call = NULL;
                if ((chan = sip_pvt->owner) && (peer = ast_bridged_channel(sip_pvt->owner))) {
@@ -6828,9 +6864,9 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
        if (ast_exists_extension(NULL, p->context, c, 1, NULL)) {
                /* This is an unsupervised transfer */
                ast_log(LOG_DEBUG,"Assigning Extension %s to REFER-TO\n", c);
-               ast_copy_string(p->refer_to, c, sizeof(p->refer_to));
-               ast_copy_string(p->referred_by, "", sizeof(p->referred_by));
-               ast_copy_string(p->refer_contact, "", sizeof(p->refer_contact));
+               ast_string_field_set(p, refer_to, c);
+               ast_string_field_free(p, referred_by);
+               ast_string_field_free(p, refer_contact);
                p->refer_call = NULL;
                return 0;
        } else if (ast_canmatch_extension(NULL, p->context, c, 1, NULL)) {
@@ -6992,7 +7028,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
        memset(calleridname, 0, sizeof(calleridname));
        get_calleridname(from, calleridname, sizeof(calleridname));
        if (calleridname[0])
-               ast_copy_string(p->cid_name, calleridname, sizeof(p->cid_name));
+               ast_string_field_set(p, cid_name, calleridname);
 
        rpid = get_header(req, "Remote-Party-ID");
        memset(rpid_num, 0, sizeof(rpid_num));
@@ -7004,7 +7040,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                t = uri;
                if (!strncmp(t, "sip:", 4))
                        t+= 4;
-               ast_copy_string(p->exten, t, sizeof(p->exten));
+               ast_string_field_set(p, exten, t);
                t = strchr(p->exten, '@');
                if (t)
                        *t = '\0';
@@ -7012,7 +7048,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                        build_contact(p);
        }
        /* save the URI part of the From header */
-       ast_copy_string(p->from, of, sizeof(p->from));
+       ast_string_field_set(p, from, of);
        if (strncmp(of, "sip:", 4)) {
                ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
        } else
@@ -7022,8 +7058,8 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                *c = '\0';
                if ((c = strchr(of, ':')))
                        *c = '\0';
-               ast_copy_string(p->cid_num, of, sizeof(p->cid_num));
-               ast_shrink_phone_number(p->cid_num);
+               ast_string_field_set(p, cid_num, of);
+               ast_shrink_phone_number((char *) p->cid_num);
        }
        if (ast_strlen_zero(of))
                return 0;
@@ -7045,9 +7081,9 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                /* replace callerid if rpid found, and not restricted */
                if (!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
                        if (*calleridname)
-                               ast_copy_string(p->cid_name, calleridname, sizeof(p->cid_name));
-                       ast_copy_string(p->cid_num, rpid_num, sizeof(p->cid_num));
-                       ast_shrink_phone_number(p->cid_num);
+                               ast_string_field_set(p, cid_name, calleridname);
+                       ast_string_field_set(p, cid_num, rpid_num);
+                       ast_shrink_phone_number((char *) p->cid_num);
                }
 
                if (p->rtp) {
@@ -7060,7 +7096,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                                ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
                        ast_rtp_setnat(p->vrtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
                }
-               if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, user->md5secret, sipmethod, uri, reliable, ignore))) {
+               if (!(res = check_auth(p, req, user->name, user->secret, user->md5secret, sipmethod, uri, reliable, ignore))) {
                        sip_cancel_destroy(p);
                        ast_copy_flags(p, user, SIP_FLAGS_TO_COPY);
                        /* Copy SIP extensions profile from INVITE */
@@ -7071,20 +7107,20 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                        if (user->call_limit)
                                ast_set_flag(p, SIP_CALL_LIMIT);
                        if (!ast_strlen_zero(user->context))
-                               ast_copy_string(p->context, user->context, sizeof(p->context));
-                       if (!ast_strlen_zero(user->cid_num) && !ast_strlen_zero(p->cid_num))  {
-                               ast_copy_string(p->cid_num, user->cid_num, sizeof(p->cid_num));
-                               ast_shrink_phone_number(p->cid_num);
+                               ast_string_field_set(p, context, user->context);
+                       if (!ast_strlen_zero(user->cid_num) && !ast_strlen_zero(p->cid_num)) {
+                               ast_string_field_set(p, cid_num, user->cid_num);
+                               ast_shrink_phone_number((char *) p->cid_num);
                        }
-                       if (!ast_strlen_zero(user->cid_name) && !ast_strlen_zero(p->cid_num)) 
-                               ast_copy_string(p->cid_name, user->cid_name, sizeof(p->cid_name));
-                       ast_copy_string(p->username, user->name, sizeof(p->username));
-                       ast_copy_string(p->peersecret, user->secret, sizeof(p->peersecret));
-                       ast_copy_string(p->subscribecontext, user->subscribecontext, sizeof(p->subscribecontext));
-                       ast_copy_string(p->peermd5secret, user->md5secret, sizeof(p->peermd5secret));
-                       ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
-                       ast_copy_string(p->language, user->language, sizeof(p->language));
-                       ast_copy_string(p->musicclass, user->musicclass, sizeof(p->musicclass));
+                       if (!ast_strlen_zero(user->cid_name) && !ast_strlen_zero(p->cid_num))
+                               ast_string_field_set(p, cid_name, user->cid_name);
+                       ast_string_field_set(p, username, user->name);
+                       ast_string_field_set(p, peersecret, user->secret);
+                       ast_string_field_set(p, peermd5secret, user->md5secret);
+                       ast_string_field_set(p, subscribecontext, user->subscribecontext);
+                       ast_string_field_set(p, accountcode, user->accountcode);
+                       ast_string_field_set(p, language, user->language);
+                       ast_string_field_set(p, musicclass, user->musicclass);
                        p->amaflags = user->amaflags;
                        p->callgroup = user->callgroup;
                        p->pickupgroup = user->pickupgroup;
@@ -7134,9 +7170,9 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                        /* replace callerid if rpid found, and not restricted */
                        if (!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
                                if (*calleridname)
-                                       ast_copy_string(p->cid_name, calleridname, sizeof(p->cid_name));
-                               ast_copy_string(p->cid_num, rpid_num, sizeof(p->cid_num));
-                               ast_shrink_phone_number(p->cid_num);
+                                       ast_string_field_set(p, cid_name, calleridname);
+                               ast_string_field_set(p, cid_num, rpid_num);
+                               ast_shrink_phone_number((char *) p->cid_num);
                        }
                        if (p->rtp) {
                                ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
@@ -7146,26 +7182,25 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                                ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
                                ast_rtp_setnat(p->vrtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
                        }
-                       ast_copy_string(p->peersecret, peer->secret, sizeof(p->peersecret));
-                       p->peersecret[sizeof(p->peersecret)-1] = '\0';
-                       ast_copy_string(p->subscribecontext, peer->subscribecontext, sizeof(p->subscribecontext));
-                       ast_copy_string(p->peermd5secret, peer->md5secret, sizeof(p->peermd5secret));
-                       p->peermd5secret[sizeof(p->peermd5secret)-1] = '\0';
+                       ast_string_field_set(p, peersecret, peer->secret);
+                       ast_string_field_set(p, peermd5secret, peer->md5secret);
+                       ast_string_field_set(p, subscribecontext, peer->subscribecontext);
                        p->callingpres = peer->callingpres;
                        if (peer->maxms && peer->lastms)
                                p->timer_t1 = peer->lastms;
                        if (ast_test_flag(peer, SIP_INSECURE_INVITE)) {
                                /* Pretend there is no required authentication */
-                               p->peersecret[0] = '\0';
-                               p->peermd5secret[0] = '\0';
+                               ast_string_field_free(p, peersecret);
+                               ast_string_field_free(p, peermd5secret);
                        }
-                       if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, p->peersecret, p->peermd5secret, sipmethod, uri, reliable, ignore))) {
+                       if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri, reliable, ignore))) {
                                ast_copy_flags(p, peer, SIP_FLAGS_TO_COPY);
                                /* If we have a call limit, set flag */
                                if (peer->call_limit)
                                        ast_set_flag(p, SIP_CALL_LIMIT);
-                               ast_copy_string(p->peername, peer->name, sizeof(p->peername));
-                               ast_copy_string(p->authname, peer->name, sizeof(p->authname));
+                               ast_string_field_set(p, peername, peer->name);
+                               ast_string_field_set(p, authname, peer->name);
+
                                /* copy channel vars */
                                for (v = peer->chanvars ; v ; v = v->next) {
                                        if ((tmpvar = ast_variable_new(v->name, v->value))) {
@@ -7176,23 +7211,23 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
                                if (mailbox)
                                        snprintf(mailbox, mailboxlen, ",%s,", peer->mailbox);
                                if (!ast_strlen_zero(peer->username)) {
-                                       ast_copy_string(p->username, peer->username, sizeof(p->username));
+                                       ast_string_field_set(p, username, peer->username);
                                        /* Use the default username for authentication on outbound calls */
-                                       ast_copy_string(p->authname, peer->username, sizeof(p->authname));
+                                       ast_string_field_set(p, authname, peer->username);
                                }
-                               if (!ast_strlen_zero(peer->cid_num) && !ast_strlen_zero(p->cid_num))  {
-                                       ast_copy_string(p->cid_num, peer->cid_num, sizeof(p->cid_num));
-                                       ast_shrink_phone_number(p->cid_num);
+                               if (!ast_strlen_zero(peer->cid_num) && !ast_strlen_zero(p->cid_num)) {
+                                       ast_string_field_set(p, cid_num, peer->cid_num);
+                                       ast_shrink_phone_number((char *) p->cid_num);
                                }
                                if (!ast_strlen_zero(peer->cid_name) && !ast_strlen_zero(p->cid_name)) 
-                                       ast_copy_string(p->cid_name, peer->cid_name, sizeof(p->cid_name));
-                               ast_copy_string(p->fullcontact, peer->fullcontact, sizeof(p->fullcontact));
+                                       ast_string_field_set(p, cid_name, peer->cid_name);
+                               ast_string_field_set(p, fullcontact, peer->fullcontact);
                                if (!ast_strlen_zero(peer->context))
-                                       ast_copy_string(p->context, peer->context, sizeof(p->context));
-                               ast_copy_string(p->peersecret, peer->secret, sizeof(p->peersecret));
-                               ast_copy_string(p->peermd5secret, peer->md5secret, sizeof(p->peermd5secret));
-                               ast_copy_string(p->language, peer->language, sizeof(p->language));
-                               ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode));
+                                       ast_string_field_set(p, context, peer->context);
+                               ast_string_field_set(p, peersecret, peer->secret);
+                               ast_string_field_set(p, peermd5secret, peer->md5secret);
+                               ast_string_field_set(p, language, peer->language);
+                               ast_string_field_set(p, accountcode, peer->accountcode);
                                p->amaflags = peer->amaflags;
                                p->callgroup = peer->callgroup;
                                p->pickupgroup = peer->pickupgroup;
@@ -7217,7 +7252,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
 #ifdef OSP_SUPPORT                     
                        else if (global_allowguest == 2) {
                                ast_copy_flags(p, &global_flags, SIP_OSPAUTH);
-                               res = check_auth(p, req, p->randdata, sizeof(p->randdata), "", "", "", sipmethod, uri, reliable, ignore); 
+                               res = check_auth(p, req, "", "", "", sipmethod, uri, reliable, ignore); 
                        }
 #endif
                }
@@ -8823,8 +8858,8 @@ static int sip_notify(int fd, int argc, char *argv[])
                /* Recalculate our side, and recalculate Call ID */
                if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
                        memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
-               build_via(p, p->via, sizeof(p->via));
-               build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
+               build_via(p);
+               build_callid_pvt(p);
                ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
                transmit_sip_request(p, &req);
                sip_scheddestroy(p, 15000);
@@ -8929,15 +8964,14 @@ static int reply_digest(struct sip_pvt *p, struct sip_request *req,
        /* table of recognised keywords, and places where they should be copied */
        const struct x {
                const char *key;
-               char *dst;
-               int dstlen;
+               int field_index;
        } *i, keys[] = {
-               { "realm=", p->realm, sizeof(p->realm) },
-               { "nonce=", p->nonce, sizeof(p->nonce) },
-               { "opaque=", p->opaque, sizeof(p->opaque) },
-               { "qop=", p->qop, sizeof(p->qop) },
-               { "domain=", p->domain, sizeof(p->domain) },
-               { NULL, NULL, 0 },
+               { "realm=", ast_string_field_index(p, realm) },
+               { "nonce=", ast_string_field_index(p, nonce) },
+               { "opaque=", ast_string_field_index(p, opaque) },
+               { "qop=", ast_string_field_index(p, qop) },
+               { "domain=", ast_string_field_index(p, domain) },
+               { NULL, 0 },
        };
 
        ast_copy_string(tmp, get_header(req, header), sizeof(tmp));
@@ -8948,8 +8982,6 @@ static int reply_digest(struct sip_pvt *p, struct sip_request *req,
                return -1;
        }
        c = tmp + strlen("Digest ");
-       for (i = keys; i->key != NULL; i++)
-               i->dst[0] = '\0';       /* init all to empty strings */
        ast_copy_string(oldnonce, p->nonce, sizeof(oldnonce));
        while (c && *(c = ast_skip_blanks(c))) {        /* lookup for keys */
                for (i = keys; i->key != NULL; i++) {
@@ -8966,7 +8998,7 @@ static int reply_digest(struct sip_pvt *p, struct sip_request *req,
                                separator = ",";
                        }
                        strsep(&c, separator); /* clear separator and move ptr */
-                       ast_copy_string(i->dst, src, i->dstlen);
+                       ast_string_field_index_set(p, i->field_index, src);
                        break;
                }
                if (i->key == NULL) /* not found, try ',' */
@@ -8981,11 +9013,11 @@ static int reply_digest(struct sip_pvt *p, struct sip_request *req,
                struct sip_registry *r = p->registry;
 
                if (strcmp(r->nonce, p->nonce)) {
-                       ast_copy_string(r->realm, p->realm, sizeof(r->realm));
-                       ast_copy_string(r->nonce, p->nonce, sizeof(r->nonce));
-                       ast_copy_string(r->domain, p->domain, sizeof(r->domain));
-                       ast_copy_string(r->opaque, p->opaque, sizeof(r->opaque));
-                       ast_copy_string(r->qop, p->qop, sizeof(r->qop));
+                       ast_string_field_set(r, realm, p->realm);
+                       ast_string_field_set(r, nonce, p->nonce);
+                       ast_string_field_set(r, domain, p->domain);
+                       ast_string_field_set(r, opaque, p->opaque);
+                       ast_string_field_set(r, qop, p->qop);
                        r->noncecount = 0;
                }
        }
@@ -9007,9 +9039,9 @@ static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int d
        char uri[256];
        char cnonce[80];
        char iabuf[INET_ADDRSTRLEN];
-       char *username;
-       char *secret;
-       char *md5secret;
+       const char *username;
+       const char *secret;
+       const char *md5secret;
        struct sip_auth *auth = (struct sip_auth *) NULL;       /* Realm authentication */
 
        if (!ast_strlen_zero(p->domain))
@@ -9541,7 +9573,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
                        p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH);
 
                /* Then we AUTH */
-               p->theirtag[0]='\0';    /* forget their old tag, so we don't match tags when getting response */
+               ast_string_field_free(p, theirtag);     /* forget their old tag, so we don't match tags when getting response */
                if (!ignore) {
                        char *authenticate = (resp == 401 ? "WWW-Authenticate" : "Proxy-Authenticate");
                        char *authorization = (resp == 401 ? "Authorization" : "Proxy-Authorization");
@@ -9787,7 +9819,10 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
 
        /* Get their tag if we haven't already */
        if (ast_strlen_zero(p->theirtag) || (resp >= 200)) {
-               gettag(req, "To", p->theirtag, sizeof(p->theirtag));
+               char tag[128];
+
+               gettag(req, "To", tag, sizeof(tag));
+               ast_string_field_set(p, theirtag, tag);
        }
        if (p->peerpoke) {
                /* We don't really care what the response is, just that it replied back. 
@@ -9973,7 +10008,10 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
                if (resp == 200) {
                        /* Tags in early session is replaced by the tag in 200 OK, which is 
                        the final reply to our INVITE */
-                       gettag(req, "To", p->theirtag, sizeof(p->theirtag));
+                       char tag[128];
+
+                       gettag(req, "To", tag, sizeof(tag));
+                       ast_string_field_set(p, theirtag, tag);
                }
 
                switch(resp) {
@@ -10208,9 +10246,7 @@ static int attempt_transfer(struct sip_pvt *p1, struct sip_pvt *p2)
 /*! \brief  gettag: Get tag from packet */
 static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize) 
 {
-
        char *thetag, *sep;
-       
 
        if (!tagbuf)
                return NULL;
@@ -10236,7 +10272,7 @@ static int handle_request_options(struct sip_pvt *p, struct sip_request *req, in
        build_contact(p);
        /* XXX Should we authenticate OPTIONS? XXX */
        if (ast_strlen_zero(p->context))
-               strcpy(p->context, default_context);
+               ast_string_field_set(p, context, default_context);
        if (res < 0)
                transmit_response_with_allow(p, "404 Not Found", req, 0);
        else if (res > 0)
@@ -10329,8 +10365,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                        transmit_response(p, "403 Forbidden", req);
                                else
                                        transmit_response_reliable(p, "403 Forbidden", req, 1);
-                               ast_set_flag(p, SIP_NEEDDESTROY);       
-                               p->theirtag[0] = '\0'; /* Forget their to-tag, we'll get a new one */
+                               ast_set_flag(p, SIP_NEEDDESTROY);
+                               ast_string_field_free(p, theirtag);
                        }
                        return 0;
                }
@@ -10350,7 +10386,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                        ast_queue_frame(p->owner, &af);
                /* Initialize the context if it hasn't been already */
                if (ast_strlen_zero(p->context))
-                       strcpy(p->context, default_context);
+                       ast_string_field_set(p, context, default_context);
                /* Check number of concurrent calls -vs- incoming limit HERE */
                ast_log(LOG_DEBUG, "Checking SIP call limits for device %s\n", p->username);
                res = update_call_counter(p, INC_CALL_LIMIT);
@@ -10390,11 +10426,11 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                } else {
                        /* If no extension was specified, use the s one */
                        if (ast_strlen_zero(p->exten))
-                               ast_copy_string(p->exten, "s", sizeof(p->exten));
+                               ast_string_field_set(p, exten, "s");
                        /* Initialize tag */    
                        make_our_tag(p->tag, sizeof(p->tag));
                        /* First invitation */
-                       c = sip_new(p, AST_STATE_DOWN, ast_strlen_zero(p->username) ? NULL : p->username );
+                       c = sip_new(p, AST_STATE_DOWN, ast_strlen_zero(p->username) ? NULL : p->username);
                        *recount = 1;
                        /* Save Record-Route for any later requests we make on this dialogue */
                        build_route(p, req, 0);
@@ -10520,7 +10556,7 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int
        if (option_debug > 2)
                ast_log(LOG_DEBUG, "SIP call transfer received for call %s (REFER)!\n", p->callid);
        if (ast_strlen_zero(p->context))
-               strcpy(p->context, default_context);
+               ast_string_field_set(p, context, default_context);
        res = get_refer_info(p, req);
        if (res < 0)
                transmit_response_with_allow(p, "404 Not Found", req, 1);
@@ -10632,7 +10668,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req, int de
                ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method.  Ask vendor to support REFER instead\n",
                        ast_inet_ntoa(iabuf, sizeof(iabuf), p->recv.sin_addr));
                if (ast_strlen_zero(p->context))
-                       strcpy(p->context, default_context);
+                       ast_string_field_set(p, context, default_context);
                res = get_also_info(p, req);
                if (!res) {
                        c = p->owner;
@@ -10726,9 +10762,9 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
                }
                /* Initialize the context if it hasn't been already */
                if (!ast_strlen_zero(p->subscribecontext))
-                       ast_copy_string(p->context, p->subscribecontext, sizeof(p->context));
+                       ast_string_field_set(p, context, p->subscribecontext);
                else if (ast_strlen_zero(p->context))
-                       strcpy(p->context, default_context);
+                       ast_string_field_set(p, context, default_context);
                /* Get destination right away */
                gotdest = get_destination(p, NULL);
                build_contact(p);
@@ -10935,7 +10971,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
        /* Save useragent of the client */
        useragent = get_header(req, "User-Agent");
        if (!ast_strlen_zero(useragent))
-               ast_copy_string(p->useragent, useragent, sizeof(p->useragent));
+               ast_string_field_set(p, useragent, useragent);
 
        /* Find out SIP method for incoming request */
        if (req->method == SIP_RESPONSE) {      /* Response to our request */
@@ -10994,7 +11030,10 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
 
        /* Find their tag if we haven't got it */
        if (ast_strlen_zero(p->theirtag)) {
-               gettag(req, "From", p->theirtag, sizeof(p->theirtag));
+               char tag[128];
+
+               gettag(req, "From", tag, sizeof(tag));
+               ast_string_field_set(p, theirtag, tag);
        }
        snprintf(p->lastmsg, sizeof(p->lastmsg), "Rx: %s", cmd);
 
@@ -11202,8 +11241,8 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer)
        /* Recalculate our side, and recalculate Call ID */
        if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
                memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
-       build_via(p, p->via, sizeof(p->via));
-       build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
+       build_via(p);
+       build_callid_pvt(p);
        /* Send MWI */
        ast_set_flag(p, SIP_OUTGOING);
        transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten);
@@ -11425,20 +11464,23 @@ static int sip_poke_peer(struct sip_peer *peer)
        memcpy(&p->recv, &peer->addr, sizeof(p->sa));
 
        /* Send options to peer's fullcontact */
-       if (!ast_strlen_zero(peer->fullcontact)) {
-               ast_copy_string (p->fullcontact, peer->fullcontact, sizeof(p->fullcontact));
-       }
+       if (!ast_strlen_zero(peer->fullcontact))
+               ast_string_field_set(p, fullcontact, peer->fullcontact);
 
        if (!ast_strlen_zero(peer->tohost))
-               ast_copy_string(p->tohost, peer->tohost, sizeof(p->tohost));
-       else
-               ast_inet_ntoa(p->tohost, sizeof(p->tohost), peer->addr.sin_addr);
+               ast_string_field_set(p, tohost, peer->tohost);
+       else {
+               char iabuf[INET_ADDRSTRLEN];
+
+               ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr);
+               ast_string_field_set(p, tohost, iabuf);
+       }
 
        /* Recalculate our side, and recalculate Call ID */
        if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
                memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
-       build_via(p, p->via, sizeof(p->via));
-       build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
+       build_via(p);
+       build_callid_pvt(p);
 
        if (peer->pokeexpire > -1)
                ast_sched_del(sched, peer->pokeexpire);
@@ -11574,20 +11616,20 @@ static struct ast_channel *sip_request_call(const char *type, int format, void *
                return NULL;
        }
        if (ast_strlen_zero(p->peername) && ext)
-               ast_copy_string(p->peername, ext, sizeof(p->peername));
+               ast_string_field_set(p, peername, ext);
        /* Recalculate our side, and recalculate Call ID */
        if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
                memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
-       build_via(p, p->via, sizeof(p->via));
-       build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
+       build_via(p);
+       build_callid_pvt(p);
        
        /* We have an extension to call, don't use the full contact here */
-       /* This to enable dialling registered peers with extension dialling,
+       /* This to enable dialing registered peers with extension dialling,
           like SIP/peername/extension  
           SIP/peername will still use the full contact */
        if (ext) {
-               ast_copy_string(p->username, ext, sizeof(p->username));
-               p->fullcontact[0] = 0;  
+               ast_string_field_set(p, username, ext);
+               ast_string_field_free(p, fullcontact);
        }
 #if 0
        printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host);
@@ -11862,7 +11904,7 @@ static int clear_realm_authentication(struct sip_auth *authlist)
 }
 
 /*! \brief  find_realm_authentication: Find authentication for a specific realm ---*/
-static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm)
+static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, const char *realm)
 {
        struct sip_auth *a;
 
@@ -12966,7 +13008,7 @@ static int sip_sipredirect(struct sip_pvt *p, const char *dest)
                }
        }
 
-       snprintf(p->our_contact, sizeof(p->our_contact), "Transfer <sip:%s@%s%s%s>", extension, host, port ? ":" : "", port ? port : "");
+       ast_string_field_build(p, our_contact, "Transfer <sip:%s@%s%s%s>", extension, host, port ? ":" : "", port ? port : "");
        transmit_response_reliable(p, "302 Moved Temporarily", &p->initreq, 1);
 
        /* this is all that we want to send to that SIP device */
index 9e70366..9be9ef9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 1999 - 2005, Digium, Inc.
+ * Copyright (C) 1999 - 2006, Digium, Inc.
  *
  * Mark Spencer <markster@digium.com>
  *
@@ -38,6 +38,7 @@
 #undef realloc
 #undef strdup
 #undef strndup
+#undef asprintf
 #undef vasprintf
 
 void *__ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func);
@@ -46,6 +47,7 @@ void __ast_free(void *ptr, const char *file, int lineno, const char *func);
 void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func);
 char *__ast_strdup(const char *s, const char *file, int lineno, const char *func);
 char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func);
+int __ast_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...);
 int __ast_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func);
 
 void __ast_mm_init(void);
@@ -70,6 +72,9 @@ void __ast_mm_init(void);
 #define strndup(a,b) \
        __ast_strndup(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
 
+#define asprintf(a, b, c...) \
+       __ast_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, b, c)
+
 #define vasprintf(a,b,c) \
        __ast_vasprintf(a,b,c,__FILE__, __LINE__, __PRETTY_FUNCTION__)
 
index 82df57a..19d9284 100644 (file)
@@ -287,7 +287,7 @@ int ast_unregister_application(const char *app);
  * \param exten which extension to get state
  * Returns extension state !! = AST_EXTENSION_???
  */
-int ast_extension_state(struct ast_channel *c, char *context, char *exten);
+int ast_extension_state(struct ast_channel *c, const char *context, const char *exten);
 
 /*! Return string of the state of an extension */
 /*!
diff --git a/include/asterisk/stringfields.h b/include/asterisk/stringfields.h
new file mode 100644 (file)
index 0000000..02811a6
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2006, Digium, Inc.
+ *
+ * Kevin P. Fleming <kpfleming@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+  \brief String fields in structures
+
+  This file contains objects and macros used to manage string
+  fields in structures without requiring them to be allocated
+  as fixed-size buffers or requiring individual allocations for
+  for each field.
+  
+  Using this functionality is quite simple... an example structure
+  with three fields is defined like this:
+  
+  \code
+  struct sample_fields {
+         int x1;
+         AST_DECLARE_STRING_FIELDS(
+                 AST_STRING_FIELD(name);
+                 AST_STRING_FIELD(address);
+                 AST_STRING_FIELD(password);
+         );
+         long x2;
+  };
+  \endcode
+  
+  When an instance of this structure is allocated, the fields
+  (and the pool of storage for them) must be initialized:
+  
+  \code
+  struct sample_fields *sample;
+  
+  sample = calloc(1, sizeof(*sample));
+  if (sample) {
+         if (!ast_string_field_init(sample)) {
+                 free(sample);
+                 sample = NULL;
+         }
+  }
+  
+  if (!sample) {
+  ...
+  }
+  \endcode
+  
+  Fields will default to pointing to an empty string, and will
+  revert to that when ast_string_field_free() is called. This means
+  that a string field will \b never contain NULL.
+  
+  Using the fields is much like using regular 'char *' fields
+  in the structure, except that writing into them must be done
+  using wrapper macros defined in this file.
+  
+  Storing simple values into fields can be done using ast_string_field_set();
+  more complex values (using printf-style format strings) can be stored
+  using ast_string_field_build().
+  
+  When the structure instance is no longer needed, the fields
+  and their storage pool must be freed:
+  
+  \code
+  ast_string_field_free_all(sample);
+  free(sample);
+  \endcode
+*/
+
+#ifndef _ASTERISK_STRINGFIELDS_H
+#define _ASTERISK_STRINGFIELDS_H
+
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "asterisk/inline_api.h"
+#include "asterisk/compiler.h"
+#include "asterisk/compat.h"
+
+/*!
+  \internal
+  \brief An opaque type for managed string fields in structures
+
+  Don't declare instances of this type directly; use the AST_STRING_FIELD()
+  macro instead.
+*/
+typedef const char * ast_string_field;
+
+/*!
+  \internal
+  \brief A constant empty string used for fields that have no other value
+*/
+extern const char *__ast_string_field_empty;
+
+/*!
+  \internal
+  \brief Structure used to manage the storage for a field pool
+*/
+struct ast_string_field_pool {
+       char *base;     /*!< the address of the pool's base in memory */
+       size_t size;    /*!< the total size of the pool */
+       size_t space;   /*!< the space available in the pool */
+       size_t used;    /*!< the space used in the pool */
+};
+
+/*!
+  \internal
+  \brief Initialize a field pool and fields
+  \param pool Pointer to the pool structure
+  \param size Amount of storage to allocate
+  \param fields Pointer to the first entry of the field array
+  \param num_fields Number of fields in the array
+  \return 0 on failure, non-zero on success
+*/
+int __ast_string_field_init(struct ast_string_field_pool *pool, size_t size,
+                           ast_string_field *fields, int num_fields);
+
+/*!
+  \internal
+  \brief Allocate space for field in the pool
+  \param pool Pointer to the pool structure
+  \param needed Amount of space needed for this field
+  \param fields Pointer to the first entry of the field array
+  \param num_fields Number of fields in the array
+  \return NULL on failure, an address for the field on success
+
+  This function will allocate the requested amount of space from
+  the field pool. If the requested amount of space is not available,
+  the pool will be expanded until enough space becomes available,
+  and the existing fields stored there will be updated to point
+  into the new pool.
+*/
+char *__ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t needed,
+                                    ast_string_field *fields, int num_fields);
+
+/*!
+  The default amount of storage to be allocated for a field pool.
+*/
+#define AST_STRING_FIELD_DEFAULT_POOL 512
+
+/*!
+  \brief Declare a string field
+  \param name The field name
+*/
+#define AST_STRING_FIELD(name) const ast_string_field name;
+
+/*!
+  \brief Declare the fields needed in a structure
+  \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one
+*/
+#define AST_DECLARE_STRING_FIELDS(field_list) \
+       ast_string_field __begin_field[0]; \
+       field_list \
+       ast_string_field __end_field[0]; \
+       struct ast_string_field_pool __field_pool;
+
+/*!
+  \brief Get the number of string fields in a structure
+  \param x Pointer to a structure containing fields
+  \return the number of fields in the structure's definition
+*/
+#define ast_string_field_count(x) \
+       (offsetof(typeof(*x), __end_field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
+
+/*!
+  \brief Get the index of a field in a structure
+  \param x Pointer to a structure containing fields
+  \param field Name of the field to locate
+  \return the position (index) of the field within the structure's
+  array of fields
+*/
+#define ast_string_field_index(x, field) \
+       (offsetof(typeof(*x), field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
+
+/*!
+  \brief Initialize a field pool and fields
+  \param x Pointer to a structure containing fields
+  \return 0 on failure, non-zero on success
+*/
+#define ast_string_field_init(x) \
+       __ast_string_field_init(&x->__field_pool, AST_STRING_FIELD_DEFAULT_POOL, &x->__begin_field[0], ast_string_field_count(x))
+
+/*!
+  \brief Set a field to a simple string value
+  \param x Pointer to a structure containing fields
+  \param index Index position of the field within the structure
+  \param data String value to be copied into the field
+  \return nothing
+*/
+#define ast_string_field_index_set(x, index, data) do { \
+       if ((x->__begin_field[index] = __ast_string_field_alloc_space(&x->__field_pool, strlen(data) + 1, &x->__begin_field[0], ast_string_field_count(x)))) \
+               strcpy((char *) x->__begin_field[index], data); \
+       } while (0)
+
+/*!
+  \brief Set a field to a simple string value
+  \param x Pointer to a structure containing fields
+  \param field Name of the field to set
+  \param data String value to be copied into the field
+  \return nothing
+*/
+#define ast_string_field_set(x, field, data) \
+       ast_string_field_index_set(x, ast_string_field_index(x, field), data)
+
+/*!
+  \brief Set a field to a simple complex (built) value
+  \param x Pointer to a structure containing fields
+  \param index Index position of the field within the structure
+  \param fmt printf-style format string
+  \param args Arguments for format string
+  \return nothing
+*/
+#define ast_string_field_index_build(x, index, fmt, args...) do { \
+       char s; \
+       size_t needed; \
+       needed = snprintf(&s, 1, fmt, args) + 1; \
+       if ((x->__begin_field[index] = __ast_string_field_alloc_space(&x->__field_pool, needed, &x->__begin_field[0], ast_string_field_count(x)))) \
+               sprintf((char *) x->__begin_field[index], fmt, args); \
+       } while (0)
+
+/*!
+  \brief Set a field to a simple complex (built) value
+  \param x Pointer to a structure containing fields
+  \param field Name of the field to set
+  \param fmt printf-style format string
+  \param args Arguments for format string
+  \return nothing
+*/
+#define ast_string_field_build(x, field, fmt, args...) \
+       ast_string_field_index_build(x, ast_string_field_index(x, field), fmt, args)
+
+/*!
+  \brief Free a field's value.
+  \param x Pointer to a structure containing fields
+  \param index Index position of the field within the structure
+  \return nothing
+
+  \note Because of the storage pool used, the memory
+  occupied by the field's value is \b not recovered; the field
+  pointer is just changed to point to an empty string.
+*/
+#define ast_string_field_index_free(x, index) do { \
+       x->__begin_field[index] = __ast_string_field_empty; \
+       } while(0)
+
+/*!
+  \brief Free a field's value.
+  \param x Pointer to a structure containing fields
+  \param field Name of the field to free
+  \return nothing
+
+  \note Because of the storage pool used, the memory
+  occupied by the field's value is \b not recovered; the field
+  pointer is just changed to point to an empty string.
+*/
+#define ast_string_field_free(x, field) \
+       ast_string_field_index_free(x, ast_string_field_index(x, field))
+
+/*!
+  \brief Free all fields (and the storage pool) in a structure
+  \param x Pointer to a structure containing fields
+  \return nothing
+
+  After calling this macro, fields can no longer be accessed in
+  structure; it should only be called immediately before freeing
+  the structure itself.
+*/
+#define ast_string_field_free_all(x) do { \
+       int index; \
+       for (index = 0; index < ast_string_field_count(x); index ++) \
+               ast_string_field_index_free(x, index); \
+       free(x->__field_pool.base); \
+       } while(0)
+
+#endif /* _ASTERISK_STRINGFIELDS_H */
index b6b85df..8e1c5a9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 1999 - 2005, Digium, Inc.
+ * Copyright (C) 1999 - 2006, Digium, Inc.
  *
  * Mark Spencer <markster@digium.com>
  *
@@ -162,7 +162,7 @@ int ast_base64decode(unsigned char *dst, const char *src, int max);
        \param doreserved       Convert reserved characters
 */
 
-char *ast_uri_encode(char *string, char *outbuf, int buflen, int doreserved);
+char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved);
 
 /*!    \brief Decode URI, URN, URL (overwrite string)
        \param s        String to be decoded 
diff --git a/pbx.c b/pbx.c
index 0e689e5..c08bdc2 100644 (file)
--- a/pbx.c
+++ b/pbx.c
@@ -1849,7 +1849,7 @@ const char *ast_extension_state2str(int extension_state)
 }
 
 /*! \brief  ast_extension_state: Check extension state for an extension by using hint */
-int ast_extension_state(struct ast_channel *c, char *context, char *exten)
+int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
 {
        struct ast_exten *e;
 
diff --git a/utils.c b/utils.c
index 2432c97..df2e393 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 1999 - 2005, Digium, Inc.
+ * Copyright (C) 1999 - 2006, Digium, Inc.
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
@@ -53,6 +53,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/time.h"
 
 #define AST_API_MODULE         /* ensure that inlinable API functions will be built in this module if required */
+#include "asterisk/stringfields.h"
+
+#define AST_API_MODULE         /* ensure that inlinable API functions will be built in this module if required */
 #include "asterisk/utils.h"
 
 static char base64[64];
@@ -421,11 +424,11 @@ static void base64_init(void)
        Note: The doreserved option is needed for replaces header in
        SIP transfers.
 */
-char *ast_uri_encode(char *string, char *outbuf, int buflen, int doreserved) 
+char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved) 
 {
        char *reserved = ";/?:@&=+$, "; /* Reserved chars */
 
-       char *ptr  = string;    /* Start with the string */
+       const char *ptr  = string;      /* Start with the string */
        char *out = NULL;
        char *buf = NULL;
 
@@ -922,3 +925,52 @@ void ast_join(char *s, size_t len, char * const w[])
                ofs--;
        s[ofs] = '\0';
 }
+
+const char const *__ast_string_field_empty = "";
+
+int __ast_string_field_init(struct ast_string_field_pool *pool, size_t size,
+                           ast_string_field *fields, int num_fields)
+{
+       int index;
+
+       pool->base = calloc(1, size);
+       if (pool->base) {
+               pool->size = size;
+               pool->space = size;
+               for (index = 0; index < num_fields; index++)
+                       fields[index] = __ast_string_field_empty;
+       }
+       return pool->base ? 0 : -1;
+}
+
+char *__ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t needed,
+                                    ast_string_field *fields, int num_fields)
+{
+       char *result = NULL;
+
+       if (__builtin_expect(needed > pool->space, 0)) {
+               int index;
+               char *new_base;
+               size_t new_size = pool->size * 2;
+
+               while (new_size < (pool->used + needed))
+                       new_size *= 2;
+
+               if (!(new_base = realloc(pool->base, new_size)))
+                       return NULL;
+
+               for (index = 0; index < num_fields; index++) {
+                       if (fields[index] != __ast_string_field_empty)
+                               fields[index] = new_base + (fields[index] - pool->base);
+               }
+
+               pool->base = new_base;
+               pool->space += new_size - pool->size;
+               pool->size = new_size;
+       }
+
+       result = pool->base + pool->used;
+       pool->used += needed;
+       pool->space -= needed;
+       return result;
+}