[asterisk-commits] jamesgolovich: branch jamesgolovich/chan_sip-ast_str r100263 - in /team/james...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jan 24 15:19:54 CST 2008


Author: jamesgolovich
Date: Thu Jan 24 15:19:54 2008
New Revision: 100263

URL: http://svn.digium.com/view/asterisk?view=rev&rev=100263
Log:
Change chan_sip to use ast_str for data field instead of a fixed length 
field.  Also add ast_str_dup function 



Modified:
    team/jamesgolovich/chan_sip-ast_str/channels/chan_sip.c
    team/jamesgolovich/chan_sip-ast_str/include/asterisk/strings.h

Change Statistics:
 0 files changed

Modified: team/jamesgolovich/chan_sip-ast_str/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/jamesgolovich/chan_sip-ast_str/channels/chan_sip.c?view=diff&rev=100263&r1=100262&r2=100263
==============================================================================
--- team/jamesgolovich/chan_sip-ast_str/channels/chan_sip.c (original)
+++ team/jamesgolovich/chan_sip-ast_str/channels/chan_sip.c Thu Jan 24 15:19:54 2008
@@ -818,7 +818,7 @@
 	char ignore;		/*!< if non-zero This is a re-transmit, ignore it */
 	char *header[SIP_MAX_HEADERS];
 	char *line[SIP_MAX_LINES];
-	char data[SIP_MAX_PACKET];
+	struct ast_str *data;	
 	struct sip_socket socket;	/*!< The socket used for this request */
 };
 
@@ -1366,7 +1366,7 @@
 	int timer_a;				/*!< SIP timer A, retransmission timer */
 	int timer_t1;				/*!< SIP Timer T1, estimated RTT or 500 ms */
 	int packetlen;				/*!< Length of packet */
-	char data[0];
+	struct ast_str *data;
 };	
 
 /*! \brief Structure for SIP user data. User's place calls to us */
@@ -1689,8 +1689,8 @@
 
 /*--- Transmitting responses and requests */
 static int sipsock_read(int *id, int fd, short events, void *ignore);
-static int __sip_xmit(struct sip_pvt *p, char *data, int len);
-static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *data, int len, int fatal, int sipmethod);
+static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len);
+static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, struct ast_str *data, int len, int fatal, int sipmethod);
 static int __transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
 static int retrans_pkt(const void *data);
 static int transmit_sip_request(struct sip_pvt *p, struct sip_request *req);
@@ -2165,9 +2165,11 @@
 		goto cleanup;
 
 	ast_mutex_init(req.socket.lock);
+	if (!(req.data = ast_str_create(SIP_MAX_PACKET)))
+		goto cleanup;
 
 	for (;;) {
-		memset(req.data, 0, sizeof(req.data));
+		ast_str_reset(req.data);
 		req.len = 0;
 		req.ignore = 0;
 
@@ -2186,7 +2188,7 @@
 		}
 
 		/* Read in headers one line at a time */
-		while (req.len < 4 || strncmp((char *)&req.data + req.len - 4, "\r\n\r\n", 4)) {
+		while (req.len < 4 || strncmp((char *)&req.data->str + req.len - 4, "\r\n\r\n", 4)) {
 			if (req.socket.lock) 
 				ast_mutex_lock(req.socket.lock);
 			if (!fgets(buf, sizeof(buf), ser->f))
@@ -2195,10 +2197,11 @@
 				ast_mutex_unlock(req.socket.lock);
 			if (me->stop) 
 				 goto cleanup;
-			strncat(req.data, buf, sizeof(req.data) - req.len);
-			req.len = strlen(req.data);
-		}
-		parse_copy(&reqcpy, &req);
+			ast_str_append(&req.data, 0, "%s", buf);
+			req.len = strlen(req.data->str);
+		}
+		copy_request(&reqcpy, &req);
+		parse_request(&reqcpy);
 		if (sscanf(get_header(&reqcpy, "Content-Length"), "%d", &cl)) {
 			while (cl > 0) {
 				if (req.socket.lock) 
@@ -2210,8 +2213,8 @@
 				if (me->stop)
 					goto cleanup;
 				cl -= strlen(buf);
-				strncat(req.data, buf, sizeof(req.data) - req.len);
-				req.len = strlen(req.data);
+				ast_str_append(&req.data, 0, "%s", buf);
+				req.len = strlen(req.data->str);
 			}
 		}
 		req.socket.ser = ser;
@@ -2227,6 +2230,10 @@
 	fclose(ser->f);
 	ast_free(ser);
 	ast_free(req.socket.lock);
+	if (reqcpy.data)
+		ast_free(reqcpy.data);
+	if (req.data)
+		ast_free(req.data);
 
 	return NULL;
 }
@@ -2491,12 +2498,12 @@
 	Called by retrans_pkt, send_request, send_response and 
 	__sip_reliable_xmit
 */
-static int __sip_xmit(struct sip_pvt *p, char *data, int len)
+static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len)
 {
 	int res = 0;
 	const struct sockaddr_in *dst = sip_real_dst(p);
 
-	ast_debug(1, "Trying to put '%.10s' onto %s socket...\n", data, get_transport(p->socket.type));
+	ast_debug(1, "Trying to put '%.10s' onto %s socket...\n", data->str, get_transport(p->socket.type));
 
 	if (sip_prepare_socket(p) < 0)
 		return XMIT_ERROR;
@@ -2505,10 +2512,10 @@
 		ast_mutex_lock(p->socket.lock);
 
 	if (p->socket.type & SIP_TRANSPORT_UDP) 
-		res = sendto(p->socket.fd, data, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+		res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
 	else {
 		if (p->socket.ser->f) 
-			res = server_write(p->socket.ser, data, len);
+			res = server_write(p->socket.ser, data->str, len);
 		else
 			ast_debug(1, "No p->socket.ser->f len=%d\n", len);
 	} 
@@ -2686,10 +2693,10 @@
 			ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n",
 				pkt->retrans, sip_nat_mode(pkt->owner),
 				ast_inet_ntoa(dst->sin_addr),
-				ntohs(dst->sin_port), pkt->data);
-		}
-
-		append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data);
+				ntohs(dst->sin_port), pkt->data->str);
+		}
+
+		append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str);
 		xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
 		sip_pvt_unlock(pkt->owner);
 		if (xmitres == XMIT_ERROR)
@@ -2755,6 +2762,8 @@
 		if (cur == pkt) {
 			UNLINK(cur, pkt->owner->packets, prev);
 			sip_pvt_unlock(pkt->owner);
+			if (pkt->data)
+				ast_free(pkt->data);
 			ast_free(pkt);
 			return 0;
 		}
@@ -2768,7 +2777,7 @@
 /*! \brief Transmit packet with retransmits 
 	\return 0 on success, -1 on failure to allocate packet 
 */
-static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *data, int len, int fatal, int sipmethod)
+static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, struct ast_str *data, int len, int fatal, int sipmethod)
 {
 	struct sip_pkt *pkt = NULL;
 	int siptimer_a = DEFAULT_RETRANS;
@@ -2794,8 +2803,8 @@
 	if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1)))
 		return AST_FAILURE;
 	/* copy data, add a terminator and save length */
-	memcpy(pkt->data, data, len);
-	pkt->data[len] = '\0';
+	pkt->data = ast_str_create(len);
+	ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0");
 	pkt->packetlen = len;
 	/* copy other parameters from the caller */
 	pkt->method = sipmethod;
@@ -2821,6 +2830,8 @@
 		append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
 		ast_sched_del(sched, pkt->retransid);	/* No more retransmission */
 		pkt->retransid = -1;
+		if (pkt->data)
+			ast_free(pkt->data);
 		return AST_FAILURE;
 	} else
 		return AST_SUCCESS;
@@ -2945,6 +2956,8 @@
 			}
 			UNLINK(cur, p->packets, prev);
 			dialog_unref(cur->owner);
+			if (cur->data)
+				ast_free(cur->data);
 			ast_free(cur);
 			break;
 		}
@@ -2967,7 +2980,7 @@
 			return;
 		}
 		cur = p->packets;
-		method = (cur->method) ? cur->method : find_sip_method(cur->data);
+		method = (cur->method) ? cur->method : find_sip_method(cur->data->str);
 		__sip_ack(p, cur->seqno, cur->is_resp, method);
 	}
 }
@@ -2980,7 +2993,7 @@
 
 	for (cur = p->packets; cur; cur = cur->next) {
 		if (cur->seqno == seqno && cur->is_resp == resp &&
-			(cur->is_resp || method_match(sipmethod, cur->data))) {
+			(cur->is_resp || method_match(sipmethod, cur->data->str))) {
 			/* this is our baby */
 			if (cur->retransid > -1) {
 				if (sipdebug)
@@ -3001,8 +3014,10 @@
 static void parse_copy(struct sip_request *dst, const struct sip_request *src)
 {
 	memset(dst, 0, sizeof(*dst));
-	memcpy(dst->data, src->data, sizeof(dst->data));
+	if (!(dst->data = ast_str_create(src->len)))
+		return;
 	dst->len = src->len;
+	ast_str_set(&dst->data, 0, "%s", src->data->str);
 	parse_request(dst);
 }
 
@@ -3011,8 +3026,8 @@
 {
 	if (!req->lines) {
 		/* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */
-		ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
-		req->len += strlen(req->data + req->len);
+		ast_str_append(&req->data, 0, "\r\n");
+		req->len = req->data->used;
 	}
 }
 
@@ -3028,17 +3043,19 @@
 		ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n",
 			reliable ? "Reliably " : "", sip_nat_mode(p),
 			ast_inet_ntoa(dst->sin_addr),
-			ntohs(dst->sin_port), req->data);
+			ntohs(dst->sin_port), req->data->str);
 	}
 	if (p->do_history) {
 		struct sip_request tmp;
 		parse_copy(&tmp, req);
-		append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data, get_header(&tmp, "CSeq"), 
+		append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), 
 			(tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? tmp.rlPart2 : sip_methods[tmp.method].text);
+		ast_free(tmp.data);
 	}
 	res = (reliable) ?
 		 __sip_reliable_xmit(p, seqno, 1, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) :
 		__sip_xmit(p, req->data, req->len);
+	ast_free(req->data);
 	if (res > 0)
 		return 0;
 	return res;
@@ -3059,18 +3076,21 @@
 	add_blank(req);
 	if (sip_debug_test_pvt(p)) {
 		if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE))
-			ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data);
+			ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data->str);
 		else
-			ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data);
+			ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data->str);
 	}
 	if (p->do_history) {
 		struct sip_request tmp;
 		parse_copy(&tmp, req);
-		append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
+		append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
+		ast_free(tmp.data);
 	}
 	res = (reliable) ?
 		__sip_reliable_xmit(p, seqno, 0, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) :
 		__sip_xmit(p, req->data, req->len);
+	if (req->data)
+		ast_free(req->data);
 	return res;
 }
 
@@ -4167,6 +4187,8 @@
 			p->registry->call = NULL;
 		p->registry = registry_unref(p->registry);
 	}
+	if (p->initreq.data)
+		ast_free(p->initreq.data);
 
 	/* Destroy Session-Timers if allocated */
 	if (p->stimer) {
@@ -4217,6 +4239,8 @@
 		if (cp->retransid > -1)
 			ast_sched_del(sched, cp->retransid);
 		dialog_unref(cp->owner);
+		if (cp->data)
+			ast_free(cp->data);
 		ast_free(cp);
 	}
 	if (p->chanvars) {
@@ -4606,7 +4630,7 @@
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 
 	/* Start the process if it's not already started */
-	if (!p->alreadygone && !ast_strlen_zero(p->initreq.data)) {
+	if (!p->alreadygone && !ast_strlen_zero(p->initreq.data->str)) {
 		if (needcancel) {	/* Outgoing call, not up */
 			if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
 				/* stop retransmitting an INVITE that has not received a response */
@@ -5945,7 +5969,7 @@
 */
 static void parse_request(struct sip_request *req)
 {
-	char *c = req->data, **dst = req->header;
+	char *c = req->data->str, **dst = req->header;
 	int i = 0, lim = SIP_MAX_HEADERS - 1;
 
 	req->header[0] = c;
@@ -6732,7 +6756,7 @@
 		/* Activate a re-invite */
 		ast_queue_frame(p->owner, &ast_null_frame);
 		/* Queue Manager Unhold event */
-		append_history(p, "Unhold", "%s", req->data);
+		append_history(p, "Unhold", "%s", req->data->str);
 		if (global_callevents)
 			manager_event(EVENT_FLAG_CALL, "Hold",
 				      "Status: Off\r\n"
@@ -6754,7 +6778,7 @@
 		/* Activate a re-invite */
 		ast_queue_frame(p->owner, &ast_null_frame);
 		/* Queue Manager Hold event */
-		append_history(p, "Hold", "%s", req->data);
+		append_history(p, "Hold", "%s", req->data->str);
 		if (global_callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
 			manager_event(EVENT_FLAG_CALL, "Hold",
 				      "Status: On\r\n"
@@ -6780,8 +6804,6 @@
 /*! \brief Add header to SIP message */
 static int add_header(struct sip_request *req, const char *var, const char *value)
 {
-	int maxlen = sizeof(req->data) - 4 - req->len; /* 4 bytes are for two \r\n ? */
-
 	if (req->headers == SIP_MAX_HEADERS) {
 		ast_log(LOG_WARNING, "Out of SIP header space\n");
 		return -1;
@@ -6792,17 +6814,11 @@
 		return -1;
 	}
 
-	if (maxlen <= 0) {
-		ast_log(LOG_WARNING, "Out of space, can't add anymore (%s:%s)\n", var, value);
-		return -1;
-	}
-
-	req->header[req->headers] = req->data + req->len;
+	ast_str_append(&req->data, 0, "%s: %s\r\n", var, value);
+	req->header[req->headers] = req->data->str + req->len;
 
 	if (compactheaders)
 		var = find_alias(var, var);
-
-	snprintf(req->header[req->headers], maxlen, "%s: %s\r\n", var, value);
 	req->len += strlen(req->header[req->headers]);
 	req->headers++;
 
@@ -6825,17 +6841,15 @@
 		ast_log(LOG_WARNING, "Out of SIP line space\n");
 		return -1;
 	}
-	if (!req->lines) {
+	if (!req->lines)
 		/* Add extra empty return */
-		ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
-		req->len += strlen(req->data + req->len);
-	}
-	if (req->len >= sizeof(req->data) - 4) {
+		req->len += ast_str_append(&req->data, 0, "\r\n");
+	if (req->len >= sizeof(req->data->str) - 4) {
 		ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
 		return -1;
 	}
-	req->line[req->lines] = req->data + req->len;
-	snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
+	req->line[req->lines] = req->data->str + req->len;
+	ast_str_append(&req->data, 0, "%s", line);
 	req->len += strlen(req->line[req->lines]);
 	req->lines++;
 	return 0;	
@@ -7039,8 +7053,10 @@
 	/* Initialize a response */
 	memset(resp, 0, sizeof(*resp));
 	resp->method = SIP_RESPONSE;
-	resp->header[0] = resp->data;
-	snprintf(resp->header[0], sizeof(resp->data), "SIP/2.0 %s\r\n", msg);
+	if (!(resp->data = ast_str_create(SIP_MAX_PACKET)))
+		return -1;
+	resp->header[0] = resp->data->str;
+	ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg);
 	resp->len = strlen(resp->header[0]);
 	resp->headers++;
 	return 0;
@@ -7051,9 +7067,11 @@
 {
 	/* Initialize a request */
 	memset(req, 0, sizeof(*req));
-        req->method = sipmethod;
-	req->header[0] = req->data;
-	snprintf(req->header[0], sizeof(req->data), "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip);
+	if (!(req->data = ast_str_create(SIP_MAX_PACKET)))
+		return -1;
+	req->method = sipmethod;
+	req->header[0] = req->data->str;
+	ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip);
 	req->len = strlen(req->header[0]);
 	req->headers++;
 	return 0;
@@ -8067,16 +8085,23 @@
 {
 	long offset;
 	int x;
-	offset = ((void *)dst) - ((void *)src);
+	struct ast_str *dup = dst->data;
+
 	/* First copy stuff */
 	memcpy(dst, src, sizeof(*dst));
+	if (!(dst->data = ast_str_dup(src->data, dup)))
+		return;
+	offset = ((void *)dst->data->str) - ((void *)src->data->str);
 	/* Now fix pointer arithmetic */
 	for (x=0; x < src->headers; x++)
 		dst->header[x] += offset;
 	for (x=0; x < src->lines; x++)
 		dst->line[x] += offset;
-	dst->rlPart1 += offset;
-	dst->rlPart2 += offset;
+	/* On some occasions this function is called without parse_request being called first so lets not create an invalid pointer */
+	if (src->rlPart1)
+		dst->rlPart1 += offset;
+	if (src->rlPart2)
+		dst->rlPart2 += offset;
 }
 
 /*! \brief Used for 200 OK and 183 early media 
@@ -15275,6 +15300,8 @@
 	transferee = d->chan1;
 	transferer = d->chan2;
 	copy_request(&req, &d->req);
+	if (d->req.data)
+		ast_free(d->req.data);
 	ast_free(d);
 
 	if (!transferee || !transferer) {
@@ -15411,6 +15438,8 @@
 		d->seqno = seqno;
 		if (ast_pthread_create_detached_background(&th, NULL, sip_park_thread, d) < 0) {
 			/* Could not start thread */
+			if (d->req.data)
+				ast_free(d->req.data);
 			ast_free(d);	/* We don't need it anymore. If thread is created, d will be free'd
 					   by sip_park_thread() */
 			return 0;
@@ -17765,9 +17794,10 @@
 	struct sockaddr_in sin = { 0, };
 	int res;
 	socklen_t len = sizeof(sin);
+	static char readbuf[65535];
 
 	memset(&req, 0, sizeof(req));
-	res = recvfrom(fd, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
+	res = recvfrom(fd, readbuf, sizeof(readbuf) - 1, 0, (struct sockaddr *)&sin, &len);
 	if (res < 0) {
 #if !defined(__FreeBSD__)
 		if (errno == EAGAIN)
@@ -17778,11 +17808,15 @@
 			ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
 		return 1;
 	}
+	readbuf[res] = '\0';
+	if (!(req.data = ast_str_create(SIP_MAX_PACKET)))
+		return 1;
+	ast_str_set(&req.data, 0, "%s", readbuf);
 	if (res == sizeof(req.data)) {
 		ast_debug(1, "Received packet exceeds buffer. Data is possibly lost\n");
-		req.data[sizeof(req.data) - 1] = '\0';
-	} else
-		req.data[res] = '\0';
+		req.data->str[sizeof(req.data) - 1] = '\0';
+ 	} else
+		req.data->str[res] = '\0';
 	req.len = res;
 
 	req.socket.fd 	= sipsock;
@@ -17792,6 +17826,8 @@
 	req.socket.lock = NULL;
 
 	handle_request_do(&req, &sin);
+	if (req.data)
+		ast_free(req.data);
 
 	return 1;
 }
@@ -17806,11 +17842,11 @@
 	if (sip_debug_test_addr(sin))	/* Set the debug flag early on packet level */
 		req->debug = 1;
 	if (pedanticsipchecking)
-		req->len = lws2sws(req->data, req->len);	/* Fix multiline headers */
+		req->len = lws2sws(req->data->str, req->len);	/* Fix multiline headers */
 	if (req->debug) {
 		ast_verbose("\n<--- SIP read from %s://%s:%d --->\n%s\n<------------->\n", 
 			get_transport(req->socket.type), ast_inet_ntoa(sin->sin_addr), 
-			ntohs(sin->sin_port), req->data);
+			ntohs(sin->sin_port), req->data->str);
 	}
 
 	parse_request(req);
@@ -17819,8 +17855,10 @@
 	if (req->debug)
 		ast_verbose("--- (%d headers %d lines)%s ---\n", req->headers, req->lines, (req->headers + req->lines == 0) ? " Nat keepalive" : "");
 
-	if (req->headers < 2)	/* Must have at least two headers */
+	if (req->headers < 2) {	/* Must have at least two headers */
+		ast_free(req->data);
 		return 1;
+	}
 
 	/* Process request, with netlock held, and with usual deadlock avoidance */
 	for (lockretry = 100; lockretry > 0; lockretry--) {
@@ -17849,7 +17887,7 @@
 	p->recv = *sin;
 
 	if (p->do_history) /* This is a request or response, note what it was for */
-		append_history(p, "Rx", "%s / %s / %s", req->data, get_header(req, "CSeq"), req->rlPart2);
+		append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), req->rlPart2);
 
 	if (!lockretry) {
 		if (p->owner)

Modified: team/jamesgolovich/chan_sip-ast_str/include/asterisk/strings.h
URL: http://svn.digium.com/view/asterisk/team/jamesgolovich/chan_sip-ast_str/include/asterisk/strings.h?view=diff&rev=100263&r1=100262&r2=100263
==============================================================================
--- team/jamesgolovich/chan_sip-ast_str/include/asterisk/strings.h (original)
+++ team/jamesgolovich/chan_sip-ast_str/include/asterisk/strings.h Thu Jan 24 15:19:54 2008
@@ -301,6 +301,10 @@
  *		creates a malloc()'ed dynamic string associated to
  *		the thread-local storage key ts
  *
+ *	ds = ast_str_dup(orig, dest)
+ *		duplicates an ast_str, if dest already exists and 
+ *		is too small then it will be expanded and re-used
+ *
  * Finally, the string can be manipulated with the following:
  *
  *	ast_str_set(&buf, max_len, fmt, ...)
@@ -416,6 +420,39 @@
 }
 )
 
+/*!
+ * \brief Duplicate a malloc'ed dynamic length string
+ *
+ * \arg buf The ast_str to duplicate
+ * \arg dup The ast_str to be duplicated into, if dup already exists and
+ *		is too small then it will be expanded
+ *
+ * \return This function returns a pointer to the dynamic string length.  The
+ *         result will be NULL in the case of a memory allocation error.
+ *
+ * \note The result of this function is dynamically allocated memory, and must
+ *       be free()'d after it is no longer needed.
+ */
+AST_INLINE_API(
+struct ast_str * attribute_malloc ast_str_dup(struct ast_str *buf, struct ast_str *dup),
+{
+	if (dup) {
+		if (buf->len > dup->len) 
+			ast_str_make_space(&dup, buf->len);
+	} else
+		dup = (struct ast_str *)ast_calloc(1, sizeof(*buf) + buf->len);
+	if (dup == NULL)
+		return NULL;
+	
+	dup->len = buf->len;
+	dup->used = buf->used;
+	dup->ts = buf->ts;
+	memcpy(dup->str, buf->str, buf->len);
+
+	return dup;
+}
+)
+
 #define ast_str_alloca(init_len)			\
 	({						\
 		struct ast_str *buf;			\




More information about the asterisk-commits mailing list