Commit 68804fee authored by Pekka Pessi's avatar Pekka Pessi
Browse files

Updated msg module interfaces.

Added msg_header_free(), msg_header_free_all().
Removed msg_dup_all() and msg_copy_all().

darcs-hash:20051107202157-65a35-ad6eabf68c592e4928b908fd4feea5038548158a.gz
parent 6cf78ac8
...@@ -43,7 +43,7 @@ msg_t *msg_create(msg_mclass_t const *mc, int flags); ...@@ -43,7 +43,7 @@ msg_t *msg_create(msg_mclass_t const *mc, int flags);
void msg_destroy(msg_t *); void msg_destroy(msg_t *);
msg_t *msg_copy(msg_t *); msg_t *msg_copy(msg_t *);
msg_t *msg_dup(msg_t *); msg_t *msg_dup(msg_t const *);
void msg_set_parent(msg_t *kid, msg_t *dad); void msg_set_parent(msg_t *kid, msg_t *dad);
...@@ -58,7 +58,7 @@ int msg_extract(msg_t *msg); ...@@ -58,7 +58,7 @@ int msg_extract(msg_t *msg);
unsigned msg_extract_errors(msg_t const *msg); unsigned msg_extract_errors(msg_t const *msg);
int msg_is_complete(msg_t const *msg); int msg_is_complete(msg_t const *msg);
int msg_has_error(msg_t const *msg); int msg_has_error(msg_t const *msg);
msg_header_t **msg_chain_head(msg_t *msg); msg_header_t **msg_chain_head(msg_t const *msg);
int msg_serialize(msg_t *msg, msg_pub_t *mo); int msg_serialize(msg_t *msg, msg_pub_t *mo);
int msg_prepare(msg_t *msg); int msg_prepare(msg_t *msg);
......
...@@ -52,9 +52,9 @@ msg_header_t *msg_header_alloc(su_home_t *, msg_hclass_t *hc, int extra) ...@@ -52,9 +52,9 @@ msg_header_t *msg_header_alloc(su_home_t *, msg_hclass_t *hc, int extra)
__attribute__((__malloc__)); __attribute__((__malloc__));
int msg_header_size(msg_header_t const *h); int msg_header_size(msg_header_t const *h);
msg_header_t **msg_header_offset(msg_t *, msg_pub_t *, msg_header_t const *); msg_header_t **msg_header_offset(msg_t const *, msg_pub_t const *, msg_header_t const *);
msg_header_t **msg_hclass_offset(msg_mclass_t const *, msg_header_t **msg_hclass_offset(msg_mclass_t const *,
msg_pub_t *, msg_hclass_t *); msg_pub_t const *, msg_hclass_t *);
msg_header_t *msg_header_access(msg_pub_t const *pub, msg_hclass_t *hc); msg_header_t *msg_header_access(msg_pub_t const *pub, msg_hclass_t *hc);
msg_header_t *msg_header_copy_as(su_home_t *home, msg_header_t *msg_header_copy_as(su_home_t *home,
...@@ -80,7 +80,7 @@ int msg_object_e(char b[], int size, msg_pub_t const *mo, int flags); ...@@ -80,7 +80,7 @@ int msg_object_e(char b[], int size, msg_pub_t const *mo, int flags);
int msg_header_field_e(char b[], int bsiz, msg_header_t const *h, int flags); int msg_header_field_e(char b[], int bsiz, msg_header_t const *h, int flags);
int msg_copy_all(msg_t *msg, msg_pub_t *dst, msg_pub_t const *src); int msg_copy_all(msg_t *msg, msg_pub_t *dst, msg_pub_t const *src);
int msg_dup_all(msg_t *msg, msg_pub_t *dst, msg_pub_t const *src);
int msg_header_remove(msg_t *msg, msg_pub_t *mo, msg_header_t *h); int msg_header_remove(msg_t *msg, msg_pub_t *mo, msg_header_t *h);
int msg_header_remove_all(msg_t *msg, msg_pub_t *mo, msg_header_t *h); int msg_header_remove_all(msg_t *msg, msg_pub_t *mo, msg_header_t *h);
...@@ -130,6 +130,11 @@ msg_header_t *msg_header_vformat(su_home_t *home, ...@@ -130,6 +130,11 @@ msg_header_t *msg_header_vformat(su_home_t *home,
va_list ap) va_list ap)
__attribute__((__malloc__)); __attribute__((__malloc__));
void msg_header_free(su_home_t *home, msg_header_t *h);
void msg_header_free_all(su_home_t *home, msg_header_t *h);
msg_payload_t *msg_payload_create(su_home_t *home, void const *data, int len) msg_payload_t *msg_payload_create(su_home_t *home, void const *data, int len)
__attribute__((__malloc__)); __attribute__((__malloc__));
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <su.h> #include <su.h>
#include "msg_internal.h"
#include "msg.h" #include "msg.h"
#include "msg_parser.h" #include "msg_parser.h"
#include "msg_header.h" #include "msg_header.h"
...@@ -345,3 +346,161 @@ char *msg_default_dup_one(msg_header_t *h, ...@@ -345,3 +346,161 @@ char *msg_default_dup_one(msg_header_t *h,
return b; return b;
} }
/* ====================================================================== */
/* Copying or duplicating all headers in a message */
static int msg_copy_chain(msg_t *msg, msg_t const *copied);
static int msg_dup_or_copy_all(msg_t *msg,
msg_t const *original,
msg_header_t *(*copy_one)(su_home_t *h,
msg_header_t const *));
/**Copy a message shallowly.
*
* @relates msg_s
*
* The copied message will share all the strings with the original message.
* The original message is not destroyed until all the copies have been
* destroyed.
*
* @param original message to be copied
*/
msg_t *msg_copy(msg_t *original)
{
if (original) {
msg_t *copy = msg_create(original->m_class, original->m_object->msg_flags);
if (copy) {
if (original->m_chain
? msg_copy_chain(copy, original) < 0
: msg_dup_or_copy_all(copy, original, msg_header_copy_one) < 0) {
msg_destroy(copy), copy = NULL;
}
if (copy)
msg_set_parent(copy, original);
return copy;
}
}
return NULL;
}
static
int msg_copy_chain(msg_t *msg, msg_t const *original)
{
su_home_t *home = msg_home(msg);
msg_pub_t *dst = msg->m_object;
msg_header_t **tail;
msg_header_t *dh;
msg_header_t const *sh;
msg_header_t **hh;
tail = msg->m_tail;
for (sh = original->m_chain; sh; sh = (msg_header_t const *)sh->sh_succ) {
hh = msg_hclass_offset(msg->m_class, dst, sh->sh_class);
if (!hh)
break;
while (*hh)
hh = &(*hh)->sh_next;
dh = msg_header_copy_one(home, sh);
if (!dh)
break;
dh->sh_prev = tail, *tail = dh, tail = &dh->sh_succ;
*hh = dh;
}
msg->m_tail = tail;
if (sh)
return -1;
return 0;
}
/**Deep copy a message.
*
* @relates msg_s
*
* The duplicated message does not share any (non-const) data with original.
*
* @param original message to be duplicated
*/
msg_t *msg_dup(msg_t const *original)
{
if (original) {
msg_t *dup = msg_create(original->m_class, original->m_object->msg_flags);
if (dup && msg_dup_or_copy_all(dup, original, msg_header_dup_one) < 0) {
msg_destroy(dup), dup = NULL;
}
return dup;
}
return NULL;
}
/** Copy a complete message, not keeping the header chain structure. */
static
int msg_dup_or_copy_all(msg_t *msg,
msg_t const *original,
msg_header_t *(*copy_one)(su_home_t *h,
msg_header_t const *))
{
su_home_t *home = msg_home(msg);
msg_pub_t *dst = msg->m_object;
msg_pub_t const *src = original->m_object;
msg_header_t * const *ssh;
msg_header_t * const *end;
msg_header_t const *sh;
msg_header_t **hh;
msg_header_t *h;
assert(copy_one);
end = (msg_header_t**)((char *)src + src->msg_size);
for (ssh = &src->msg_request; ssh < end; ssh++) {
sh = *ssh;
if (!sh)
continue;
hh = msg_hclass_offset(msg->m_class, dst, sh->sh_class);
if (hh == NULL)
return -1;
for (; sh; sh = sh->sh_next) {
h = copy_one(home, sh);
if (h == NULL)
return -1;
if (*hh) {
/* If there is multiple instances of single headers,
put the extra headers into the list of erroneous headers */
if (msg_is_single(h))
hh = (msg_header_t**)&dst->msg_error;
while (*hh)
hh = &(*hh)->sh_next;
}
*hh = h;
if (msg_is_list(sh))
/* Copy only first list entry */
break;
}
}
return 0;
}
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
#define MSG_INTERNAL_H #define MSG_INTERNAL_H
/**@ingroup msg /**@IFILE msg_internal.h
* @IFILE msg_internal.h
* @brief Abstract messages - internal interface * @brief Abstract messages - internal interface
* *
* @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Pekka Pessi <Pekka.Pessi@nokia.com>
...@@ -95,4 +94,31 @@ struct msg_s { ...@@ -95,4 +94,31 @@ struct msg_s {
int m_errno; /**< Errno */ int m_errno; /**< Errno */
}; };
static inline int msg_is_single(msg_header_t const *h)
{
return h->sh_class->hc_kind == msg_kind_single;
}
static inline int msg_is_prepend(msg_header_t const *h)
{
return h->sh_class->hc_kind == msg_kind_prepend;
}
static inline int msg_is_append(msg_header_t const *h)
{
return
h->sh_class->hc_kind == msg_kind_append ||
h->sh_class->hc_kind == msg_kind_apndlist;
}
static inline int msg_is_list(msg_header_t const *h)
{
return h->sh_class->hc_kind == msg_kind_list;
}
static inline int msg_is_special(msg_header_t const *h)
{
return h->sh_class->hc_hash < 0;
}
#endif /* MSG_INTERNAL_H */ #endif /* MSG_INTERNAL_H */
...@@ -47,9 +47,6 @@ ...@@ -47,9 +47,6 @@
#include <su_alloc.h> #include <su_alloc.h>
#define MSG_HDR_T union msg_mime_u
#define MSG_PUB_T struct msg_multipart_s
#include "msg_internal.h" #include "msg_internal.h"
#include "msg.h" #include "msg.h"
#include "msg_mime.h" #include "msg_mime.h"
...@@ -276,7 +273,7 @@ msg_multipart_t *msg_multipart_create(su_home_t *home, ...@@ -276,7 +273,7 @@ msg_multipart_t *msg_multipart_create(su_home_t *home,
{ {
msg_multipart_t *mp; msg_multipart_t *mp;
mp = msg_header_alloc(home, msg_multipart_class, 0)->sh_multipart; mp = (msg_multipart_t *)msg_header_alloc(home, msg_multipart_class, 0);
if (mp) { if (mp) {
if (content_type) if (content_type)
...@@ -464,7 +461,7 @@ msg_multipart_t *msg_multipart_parse(su_home_t *home, ...@@ -464,7 +461,7 @@ msg_multipart_t *msg_multipart_parse(su_home_t *home,
if (next != p && next[-1] == '\r') if (next != p && next[-1] == '\r')
next--, m++; next--, m++;
mp = msg_header_alloc(msg_home(msg), msg_multipart_class, 0)->sh_multipart; mp = (msg_multipart_t *)msg_header_alloc(msg_home(msg), msg_multipart_class, 0);
if (mp == NULL) if (mp == NULL)
break; /* error */ break; /* error */
*mmp = mp; mmp = &mp->mp_next; *mmp = mp; mmp = &mp->mp_next;
...@@ -503,7 +500,7 @@ msg_multipart_t *msg_multipart_parse(su_home_t *home, ...@@ -503,7 +500,7 @@ msg_multipart_t *msg_multipart_parse(su_home_t *home,
/* Parse each part */ /* Parse each part */
for (mp = all; mp; mp = mp->mp_next) { for (mp = all; mp; mp = mp->mp_next) {
msg->m_object = mp; p = mp->mp_data; next = p + mp->mp_len; msg->m_object = (msg_pub_t *)mp; p = mp->mp_data; next = p + mp->mp_len;
if (msg->m_tail) if (msg->m_tail)
mp->mp_common->h_prev = msg->m_tail, mp->mp_common->h_prev = msg->m_tail,
...@@ -516,20 +513,20 @@ msg_multipart_t *msg_multipart_parse(su_home_t *home, ...@@ -516,20 +513,20 @@ msg_multipart_t *msg_multipart_parse(su_home_t *home,
for (len = next - p; len > 0; len -= m, p += m) { for (len = next - p; len > 0; len -= m, p += m) {
if (IS_CRLF(p[0])) { if (IS_CRLF(p[0])) {
m = msg_extract_separator(msg, mp, p, len, 1); m = msg_extract_separator(msg, (msg_pub_t*)mp, p, len, 1);
assert(m > 0); assert(m > 0);
p += m; len -= m; p += m; len -= m;
if (len > 0) { if (len > 0) {
m = msg_extract_payload(msg, mp, NULL, len, p, len, 1); m = msg_extract_payload(msg, (msg_pub_t*)mp, NULL, len, p, len, 1);
assert(m > 0); assert(m > 0);
assert(len == m); assert(len == m);
} }
break; break;
} }
m = msg_extract_header(msg, mp, p, len, 1); m = msg_extract_header(msg, (msg_pub_t*)mp, p, len, 1);
if (m <= 0) { if (m <= 0) {
assert(m > 0); assert(m > 0);
...@@ -864,7 +861,7 @@ int msg_multipart_d(su_home_t *home, msg_header_t *h, char *s, int slen) ...@@ -864,7 +861,7 @@ int msg_multipart_d(su_home_t *home, msg_header_t *h, char *s, int slen)
msg_payload_init(pl); msg_payload_init(pl);
result = h->sh_multipart; result = (msg_multipart_t *)h;
pl->pl_data = s; pl->pl_data = s;
pl->pl_len = slen; pl->pl_len = slen;
...@@ -901,7 +898,7 @@ int msg_multipart_e(char b[], int bsiz, msg_header_t const *h, int flags) ...@@ -901,7 +898,7 @@ int msg_multipart_e(char b[], int bsiz, msg_header_t const *h, int flags)
/** Calculate extra size of a multipart */ /** Calculate extra size of a multipart */
int msg_multipart_dup_xtra(msg_header_t const *h, int offset) int msg_multipart_dup_xtra(msg_header_t const *h, int offset)
{ {
msg_multipart_t const *mp = h->sh_multipart; msg_multipart_t const *mp = (msg_multipart_t *)h;
msg_header_t const **hh; msg_header_t const **hh;
offset = msg_payload_dup_xtra(h, offset); offset = msg_payload_dup_xtra(h, offset);
...@@ -922,7 +919,7 @@ int msg_multipart_dup_xtra(msg_header_t const *h, int offset) ...@@ -922,7 +919,7 @@ int msg_multipart_dup_xtra(msg_header_t const *h, int offset)
char *msg_multipart_dup_one(msg_header_t *dst, msg_header_t const *src, char *msg_multipart_dup_one(msg_header_t *dst, msg_header_t const *src,
char *b, int xtra) char *b, int xtra)
{ {
msg_multipart_t const *mp = src->sh_multipart; msg_multipart_t const *mp = (msg_multipart_t *)src;
msg_header_t *h, **hh; msg_header_t *h, **hh;
char *end = b + xtra; char *end = b + xtra;
...@@ -1095,7 +1092,7 @@ MSG_HEADER_CLASS(msg_, accept, "Accept", "", ac_params, apndlist, msg_accept); ...@@ -1095,7 +1092,7 @@ MSG_HEADER_CLASS(msg_, accept, "Accept", "", ac_params, apndlist, msg_accept);
int msg_accept_d(su_home_t *home, msg_header_t *h, char *s, int slen) int msg_accept_d(su_home_t *home, msg_header_t *h, char *s, int slen)
{ {
msg_header_t **hh = &h->sh_succ, *h0 = h; msg_header_t **hh = &h->sh_succ, *h0 = h;
msg_accept_t *ac = h->sh_accept; msg_accept_t *ac = (msg_accept_t *)h;
assert(h); assert(sizeof(*h)); assert(h); assert(sizeof(*h));
...@@ -1107,7 +1104,7 @@ int msg_accept_d(su_home_t *home, msg_header_t *h, char *s, int slen) ...@@ -1107,7 +1104,7 @@ int msg_accept_d(su_home_t *home, msg_header_t *h, char *s, int slen)
if (!(h = msg_header_alloc(home, h0->sh_class, 0))) if (!(h = msg_header_alloc(home, h0->sh_class, 0)))
break; break;
*hh = h; h->sh_prev = hh; hh = &h->sh_succ; *hh = h; h->sh_prev = hh; hh = &h->sh_succ;
ac = ac->ac_next = h->sh_accept; ac = ac->ac_next = (msg_accept_t*)h;
} }
/* "Accept:" #(type/subtyp ; *(parameters))) */ /* "Accept:" #(type/subtyp ; *(parameters))) */
...@@ -1130,8 +1127,10 @@ int msg_accept_d(su_home_t *home, msg_header_t *h, char *s, int slen) ...@@ -1130,8 +1127,10 @@ int msg_accept_d(su_home_t *home, msg_header_t *h, char *s, int slen)
} }
/* Note: empty Accept list is not an error */ /* Note: empty Accept list is not an error */
if (h) if (h) {
h->sh_accept->ac_type = h->sh_accept->ac_subtype = ""; msg_accept_t *ac = (msg_accept_t *)h;
ac->ac_type = ac->ac_subtype = "";
}
return 0; return 0;
} }
...@@ -1139,7 +1138,7 @@ int msg_accept_d(su_home_t *home, msg_header_t *h, char *s, int slen) ...@@ -1139,7 +1138,7 @@ int msg_accept_d(su_home_t *home, msg_header_t *h, char *s, int slen)
int msg_accept_e(char b[], int bsiz, msg_header_t const *h, int flags) int msg_accept_e(char b[], int bsiz, msg_header_t const *h, int flags)
{ {
char *b0 = b, *end = b + bsiz; char *b0 = b, *end = b + bsiz;
msg_accept_t const *ac = h->sh_accept; msg_accept_t const *ac = (msg_accept_t *)h;
assert(msg_is_accept(h)); assert(msg_is_accept(h));
...@@ -1155,7 +1154,7 @@ int msg_accept_e(char b[], int bsiz, msg_header_t const *h, int flags) ...@@ -1155,7 +1154,7 @@ int msg_accept_e(char b[], int bsiz, msg_header_t const *h, int flags)
int msg_accept_dup_xtra(msg_header_t const *h, int offset) int msg_accept_dup_xtra(msg_header_t const *h, int offset)
{ {
int rv = offset; int rv = offset;
msg_accept_t const *ac = h->sh_accept; msg_accept_t const *ac = (msg_accept_t *)h;
if (ac->ac_type) { if (ac->ac_type) {
MSG_PARAMS_SIZE(rv, ac->ac_params); MSG_PARAMS_SIZE(rv, ac->ac_params);
...@@ -1169,8 +1168,8 @@ int msg_accept_dup_xtra(msg_header_t const *h, int offset) ...@@ -1169,8 +1168,8 @@ int msg_accept_dup_xtra(msg_header_t const *h, int offset)
char *msg_accept_dup_one(msg_header_t *dst, msg_header_t const *src, char *msg_accept_dup_one(msg_header_t *dst, msg_header_t const *src,
char *b, int xtra) char *b, int xtra)
{ {
msg_accept_t *ac = dst->sh_accept; msg_accept_t *ac = (msg_accept_t *)dst;
msg_accept_t const *o = src->sh_accept; msg_accept_t const *o = (msg_accept_t *)src;
char *end = b + xtra; char *end = b + xtra;
if (o->ac_type) { if (o->ac_type) {
...@@ -1179,7 +1178,7 @@ char *msg_accept_dup_one(msg_header_t *dst, msg_header_t const *src, ...@@ -1179,7 +1178,7 @@ char *msg_accept_dup_one(msg_header_t *dst, msg_header_t const *src,
if ((ac->ac_subtype = strchr(ac->ac_type, '/'))) if ((ac->ac_subtype = strchr(ac->ac_type, '/')))
ac->ac_subtype++; ac->ac_subtype++;
if (ac->ac_params) msg_accept_update(dst->sh_accept); if (ac->ac_params) msg_accept_update((msg_accept_t *)dst);
} }
assert(b <= end); assert(b <= end);
...@@ -1202,7 +1201,7 @@ int msg_accept_any_d(su_home_t *home, ...@@ -1202,7 +1201,7 @@ int msg_accept_any_d(su_home_t *home,
{ {
/** @relates msg_accept_any_s */ /** @relates msg_accept_any_s */
msg_header_t **hh = &h->sh_succ, *h0 = h; msg_header_t **hh = &h->sh_succ, *h0 = h;
msg_accept_any_t *aa = h->sh_accept_any; msg_accept_any_t *aa = (msg_accept_any_t *)h;
assert(h); assert(h->sh_class); assert(h); assert(h->sh_class);
...@@ -1215,7 +1214,7 @@ int msg_accept_any_d(su_home_t *home, ...@@ -1215,7 +1214,7 @@ int msg_accept_any_d(su_home_t *home,
break; break;
/* Append to sh_succ and aa_next */ /* Append to sh_succ and aa_next */
*hh = h, h->sh_prev = hh, hh = &h->sh_succ; *hh = h, h->sh_prev = hh, hh = &h->sh_succ;
aa = aa->aa_next = h->sh_accept_any; aa = aa->aa_next = (msg_accept_any_t *)h;
} }
/* "Accept-*:" 1#(token [; "q" = qvalue ]) */ /* "Accept-*:" 1#(token [; "q" = qvalue ]) */
...@@ -1252,7 +1251,7 @@ int msg_accept_any_e(char b[], int bsiz, msg_header_t const *h, int f) ...@@ -1252,7 +1251,7 @@ int msg_accept_any_e(char b[], int bsiz, msg_header_t const *h, int f)
{ {
/** @relates msg_accept_any_s */ /** @relates msg_accept_any_s */
char *b0 = b, *end = b + bsiz; char *b0 = b, *end = b + bsiz;
msg_accept_any_t const *aa = h->sh_accept_any; msg_accept_any_t const *aa = (msg_accept_any_t *)h;
MSG_STRING_E(b, end, aa->aa_value); MSG_STRING_E(b, end, aa->aa_value);
if (aa->aa_q) { if (aa->aa_q) {
...@@ -1269,7 +1268,7 @@ int msg_accept_any_dup_xtra(msg_header_t const *h, int offset) ...@@ -1269,7 +1268,7 @@ int msg_accept_any_dup_xtra(msg_header_t const *h, int offset)
{ {
/** @relates msg_accept_any_s */ /** @relates msg_accept_any_s */
int rv = offset; int rv = offset;
msg_accept_any_t const *aa = h->sh_accept_any; msg_accept_any_t const *aa = (msg_accept_any_t *)h;
rv += MSG_STRING_SIZE(aa->aa_value); rv += MSG_STRING_SIZE(aa->aa_value);
rv += MSG_STRING_SIZE(aa->aa_q); rv += MSG_STRING_SIZE(aa->aa_q);
...@@ -1282,8 +1281,8 @@ char *msg_accept_any_dup_one(msg_header_t *dst, msg_header_t const *src, ...@@ -1282,8 +1281,8 @@ char *msg_accept_any_dup_one(msg_header_t *dst, msg_header_t const *src,
char *b, int xtra) char *b, int xtra)
{ {
/** @relates msg_accept_any_s */ /** @relates msg_accept_any_s */
msg_accept_any_t *aa = dst->sh_accept_any; msg_accept_any_t *aa = (msg_accept_any_t *)dst;
msg_accept_any_t const *o = src->sh_accept_any; msg_accept_any_t const *o = (msg_accept_any_t *)src;
char *end = b + xtra; char *end = b + xtra;
MSG_STRING_DUP(b, aa->aa_value, o->aa_value); MSG_STRING_DUP(b, aa->aa_value, o->aa_value);
...@@ -1510,7 +1509,7 @@ static void msg_content_disposition_update(msg_content_disposition_t *cd); ...@@ -1510,7 +1509,7 @@ static void msg_content_disposition_update(msg_content_disposition_t *cd);
int msg_content_disposition_d(su_home_t *home, msg_header_t *h, char *s, int slen) int msg_content_disposition_d(su_home_t *home, msg_header_t *h, char *s, int slen)
{ {