Commit 72424b26 authored by Pekka Pessi's avatar Pekka Pessi

nua: using global preferences. Added NUTAG_SHUTDOWN_EVENTS().

darcs-hash:20080206170546-65a35-d9826f24242e4916ec27516dd840a7abf389247d.gz
parent 4f7a2ef0
...@@ -77,19 +77,27 @@ su_inline int nhp_is_any_set(nua_handle_preferences_t const *nhp) ...@@ -77,19 +77,27 @@ su_inline int nhp_is_any_set(nua_handle_preferences_t const *nhp)
su_inline void nhp_or_set(nua_handle_preferences_t *a, su_inline void nhp_or_set(nua_handle_preferences_t *a,
nua_handle_preferences_t const *b) nua_handle_preferences_t const *b)
{ {
unsigned *ap = a->nhp_set_.set_unsigned;
unsigned const *bp = b->nhp_set_.set_unsigned;
size_t i;
memcpy(a, b, offsetof(nua_handle_preferences_t, nhp_set)); memcpy(a, b, offsetof(nua_handle_preferences_t, nhp_set));
/* Bitwise or of bitfields, casted to unsigned */
a->nhp_set_.set_unsigned[0] |= b->nhp_set_.set_unsigned[0];
a->nhp_set_.set_unsigned[1] |= b->nhp_set_.set_unsigned[1];
/*
unsigned *ap, const *bp;
size_t i;
ap = a->nhp_set_.set_unsigned;
bp = b->nhp_set_.set_unsigned;
for (i = 0; i < (sizeof a->nhp_set); i += (sizeof *ap)) for (i = 0; i < (sizeof a->nhp_set); i += (sizeof *ap))
*ap++ |= *bp++; *ap++ |= *bp++;
*/
} }
static int nhp_set_tags(su_home_t *home, static int nhp_set_tags(su_home_t *home,
nua_handle_preferences_t *nhp, nua_handle_preferences_t *nhp,
int global, nua_global_preferences_t *ngp,
tagi_t const *tags); tagi_t const *tags);
static int nhp_merge_lists(su_home_t *home, static int nhp_merge_lists(su_home_t *home,
...@@ -101,11 +109,11 @@ static int nhp_merge_lists(su_home_t *home, ...@@ -101,11 +109,11 @@ static int nhp_merge_lists(su_home_t *home,
int always_merge, int always_merge,
tag_value_t value); tag_value_t value);
static static int nhp_save_params(nua_handle_t *nh,
nua_handle_preferences_t *nhp_move_params(su_home_t *home, su_home_t *tmphome,
nua_handle_preferences_t *dst, nua_global_preferences_t *gsrc,
su_home_t *tmphome, nua_handle_preferences_t *src);
nua_handle_preferences_t const *src);
/* ====================================================================== */ /* ====================================================================== */
/* Magical NUTAG_USER_AGENT() - add NHP_USER_AGENT there if it is not there */ /* Magical NUTAG_USER_AGENT() - add NHP_USER_AGENT there if it is not there */
...@@ -198,20 +206,12 @@ int nua_stack_set_from(nua_t *nua, int initial, tagi_t const *tags) ...@@ -198,20 +206,12 @@ int nua_stack_set_from(nua_t *nua, int initial, tagi_t const *tags)
sip_from_t *f = NULL, f0[1]; sip_from_t *f = NULL, f0[1];
int set; int set;
char const *uicc_name = "default";
tl_gets(tags, tl_gets(tags,
/* By nua_stack_set_from() */ /* By nua_stack_set_from() */
SIPTAG_FROM_REF(from), SIPTAG_FROM_REF(from),
SIPTAG_FROM_STR_REF(str), SIPTAG_FROM_STR_REF(str),
NUTAG_UICC_REF(uicc_name),
TAG_END()); TAG_END());
#if HAVE_UICC_H
if (initial && uicc_name)
nua->nua_uicc = uicc_create(root, uicc_name);
#endif
if (!initial && from == NONE && str == NONE) if (!initial && from == NONE && str == NONE)
return 0; return 0;
...@@ -475,146 +475,124 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, ...@@ -475,146 +475,124 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
tagi_t const *tags) tagi_t const *tags)
{ {
nua_handle_t *dnh = nua->nua_dhandle; nua_handle_t *dnh = nua->nua_dhandle;
nua_handle_preferences_t tmp[1], *nhp = nh->nh_prefs;
nua_handle_preferences_t const *dnhp = dnh->nh_prefs; int status;
char const *phrase;
su_home_t tmphome[1] = { SU_HOME_INIT(tmphome) };
tagi_t const *ptags;
int error, global;
int status = 900;
char const *phrase = "Error storing parameters";
sip_supported_t const *supported = NULL;
sip_allow_t const *allow = NULL;
sip_allow_events_t const *allow_events = NULL;
sip_allow_t const *appl_method = NULL;
enter; enter;
ptags = !nh->nh_used_ptags ? nh->nh_ptags : NULL; {
su_home_t tmphome[1] = { SU_HOME_INIT(tmphome) };
*tmp = *nhp; NHP_UNSET_ALL(tmp); nua_handle_preferences_t *nhp = nh->nh_prefs;
nua_handle_preferences_t const *dnhp = dnh->nh_prefs;
/* Supported features, allowed methods and events are merged nua_handle_preferences_t tmp[1];
with previous ones */ nua_global_preferences_t gtmp[1], *ngp = NULL;
if (!NHP_ISSET(nhp, supported))
supported = tmp->nhp_supported = dnhp->nhp_supported; *tmp = *nhp; NHP_UNSET_ALL(tmp);
if (!NHP_ISSET(nhp, allow))
allow = tmp->nhp_allow = dnhp->nhp_allow; /*
if (!NHP_ISSET(nhp, allow_events)) * Supported features, allowed methods and events are merged
allow_events = tmp->nhp_allow_events = dnhp->nhp_allow_events; * with previous or default settings.
if (!NHP_ISSET(nhp, appl_method)) *
appl_method = tmp->nhp_appl_method = dnhp->nhp_appl_method; * Here we just copy pointers from default settings. However when saving
* settings we have to be extra careful so that we
error = 0; * 1) zero the pointers if the setting has not been modified
global = nh == dnh; /* save also stack-specific params */ * 2) do not free pointer if the setting has been modified
* See NHP_ZAP_OVERRIDEN() below for gorier details.
*/
if (!NHP_ISSET(nhp, supported))
tmp->nhp_supported = dnhp->nhp_supported;
if (!NHP_ISSET(nhp, allow))
tmp->nhp_allow = dnhp->nhp_allow;
if (!NHP_ISSET(nhp, allow_events))
tmp->nhp_allow_events = dnhp->nhp_allow_events;
if (!NHP_ISSET(nhp, appl_method))
tmp->nhp_appl_method = dnhp->nhp_appl_method;
/* Set and save parameters to tmp */ if (nh == dnh) /* nua_set_params() call, save stack-wide params, too */
if (nhp_set_tags(tmphome, tmp, global, ptags) < 0) ngp = gtmp, *gtmp = *nua->nua_prefs;
error = 1, phrase = "Error storing default handle parameters";
else if (nhp_set_tags(tmphome, tmp, global, tags) < 0) /* Set and save parameters to tmp */
error = 1, phrase = "Error storing parameters"; if (!nh->nh_used_ptags &&
else { nhp_set_tags(tmphome, tmp, NULL, nh->nh_ptags) < 0)
if (NHP_IS_ANY_SET(tmp)) { status = 900, phrase = "Error storing default handle parameters";
if (tmp->nhp_supported == supported) else if (nhp_set_tags(tmphome, tmp, ngp, tags) < 0)
tmp->nhp_supported = NULL; status = 900, phrase = "Error storing parameters";
else if (nhp_save_params(nh, tmphome, ngp, tmp) < 0)
if (tmp->nhp_allow == allow) status = 900, phrase = su_strerror(ENOMEM);
tmp->nhp_allow = NULL; else
status = 200, phrase = "OK", nh->nh_used_ptags = 1;
if (tmp->nhp_allow_events == allow_events)
tmp->nhp_allow_events = NULL;
if (tmp->nhp_appl_method == appl_method)
tmp->nhp_appl_method = NULL;
/* Move parameters from tmp to nhp (or allocate new nhp) */
if (nh != dnh && nhp == dnh->nh_prefs)
nhp = NULL;
nhp = nhp_move_params(nh->nh_home, nhp, tmphome, tmp);
if (nhp)
nh->nh_prefs = nhp;
else
/* Fail miserably with ENOMEM */
error = 1, status = 900, phrase = su_strerror(ENOMEM);
}
if (!error) su_home_deinit(tmphome);
nh->nh_used_ptags = 1;
} }
su_home_deinit(tmphome); if (status == 200) {
nua_handle_preferences_t const *nhp = nh->nh_prefs;
if (error) nua_handle_preferences_t const *dnhp = dnh->nh_prefs;
;
else if (!nh->nh_soa && NHP_GET(nhp, dnhp, media_enable)) { if (!nh->nh_soa && NHP_GET(nhp, dnhp, media_enable)) {
/* Create soa when needed */ /* Create soa when needed */
char const *soa_name = NHP_GET(nhp, dnhp, soa_name); char const *soa_name = NHP_GET(nhp, dnhp, soa_name);
if (dnh->nh_soa) if (dnh->nh_soa)
nh->nh_soa = soa_clone(dnh->nh_soa, nua->nua_root, nh); nh->nh_soa = soa_clone(dnh->nh_soa, nua->nua_root, nh);
else else
nh->nh_soa = soa_create(soa_name, nua->nua_root, nh); nh->nh_soa = soa_create(soa_name, nua->nua_root, nh);
ptags = nh->nh_ptags; if (!nh->nh_soa)
status = 900, phrase = "Error Creating SOA Object";
else if (soa_set_params(nh->nh_soa, TAG_NEXT(nh->nh_ptags)) < 0)
status = 900, phrase = "Error Setting SOA Parameters";
}
else if (nh->nh_soa && !NHP_GET(nhp, dnhp, media_enable)) {
/* ... destroy soa when not needed */
soa_destroy(nh->nh_soa), nh->nh_soa = NULL;
}
if (!nh->nh_soa) if (status == 200 && tags && nh->nh_soa &&
error = 1, status = 900, phrase = "Error Creating SOA Object"; soa_set_params(nh->nh_soa, TAG_NEXT(tags)) < 0)
} status = 900, phrase = "Error Setting SOA Parameters";
else if (nh->nh_soa && !NHP_GET(nhp, dnhp, media_enable)) {
/* ... destroy soa when not needed */
soa_destroy(nh->nh_soa), nh->nh_soa = NULL;
} }
if (!error && nh->nh_soa) { if (status == 200 && nh == dnh) {
if ((ptags && soa_set_params(nh->nh_soa, TAG_NEXT(ptags)) < 0) || /* Set stack-specific things below */
(tags && soa_set_params(nh->nh_soa, TAG_NEXT(tags)) < 0)) if (nua_stack_set_smime_params(nua, tags) < 0) {
error = 1, status = 900, phrase = "Error Setting SOA Parameters"; status = 900, phrase = "Error setting S/MIME parameters";
} }
else if (nua->nua_nta && nta_agent_set_params(nua->nua_nta, TAG_NEXT(tags)) < 0) {
status = 900, phrase = "Error setting NTA parameters";
}
else {
nua_stack_set_from(nua, 0, tags);
if (error || nh != dnh) { if (nua->nua_prefs->ngp_detect_network_updates)
; nua_stack_launch_network_change_detector(nua);
} }
else if (nua_stack_set_smime_params(nua, tags) < 0) {
error = 1, status = 900, phrase = "Error setting S/MIME parameters";
}
else if (!nua->nua_nta) {
}
/* Set stack-specific things below */
else if (nta_agent_set_params(nua->nua_nta, TAG_NEXT(tags)) < 0) {
status = 900, phrase = "Error setting NTA parameters";
error = 1;
}
else {
nua_stack_set_from(nua, 0, tags);
if (NHP_ISSET(nhp, detect_network_updates))
nua_stack_launch_network_change_detector(nua);
} }
if (error) { if (status != 200) {
if (e == nua_i_none) if (e == nua_i_none)
SU_DEBUG_1(("nua_set_params(): failed: %s\n", phrase)); SU_DEBUG_1(("nua_set_params(): failed: %s\n", phrase));
return UA_EVENT2(e, status, phrase), -1; return UA_EVENT2(e, status, phrase), -1;
} }
else {
if (e == nua_r_set_params) if (e == nua_r_set_params)
UA_EVENT2(e, 200, "OK"); UA_EVENT2(e, status, phrase);
return 0;
return 0; }
} }
/** Parse parameters from tags to @a nhp.
/** Parse parameters from tags to @a nhp or @a ngp.
* *
* @param home allocate new values from @a home * @param home allocate new values from @a home
* @param nhp structure to store handle preferences * @param nhp structure to store handle preferences
* @param global if true, save also global parameters * @param ngp structure to store global preferences
* @param tags list of tags to parse * @param tags list of tags to parse
*/ */
static int nhp_set_tags(su_home_t *home, static int nhp_set_tags(su_home_t *home,
nua_handle_preferences_t *nhp, nua_handle_preferences_t *nhp,
int global, nua_global_preferences_t *ngp,
tagi_t const *tags) tagi_t const *tags)
{ {
...@@ -997,7 +975,7 @@ static int nhp_set_tags(su_home_t *home, ...@@ -997,7 +975,7 @@ static int nhp_set_tags(su_home_t *home,
NHP_SET_STR(nhp, outbound, value); NHP_SET_STR(nhp, outbound, value);
} }
/* NUTAG_DETECT_NETWORK_UPDATES(detect_network_updates) */ /* NUTAG_DETECT_NETWORK_UPDATES(detect_network_updates) */
else if (global && tag == nutag_detect_network_updates) { else if (ngp && tag == nutag_detect_network_updates) {
int detector = (int)value; int detector = (int)value;
if (detector < NUA_NW_DETECT_NOTHING) if (detector < NUA_NW_DETECT_NOTHING)
...@@ -1005,7 +983,13 @@ static int nhp_set_tags(su_home_t *home, ...@@ -1005,7 +983,13 @@ static int nhp_set_tags(su_home_t *home,
else if (detector > NUA_NW_DETECT_TRY_FULL) else if (detector > NUA_NW_DETECT_TRY_FULL)
detector = NUA_NW_DETECT_TRY_FULL; detector = NUA_NW_DETECT_TRY_FULL;
NHP_SET(nhp, detect_network_updates, detector); ngp->ngp_detect_network_updates = detector;
ngp->ngp_set.ngp_detect_network_updates = 1;
}
/* NUTAG_SHUTDOWN_EVENTS() */
else if (ngp && tag == nutag_shutdown_events) {
ngp->ngp_shutdown_events = value != 0;
ngp->ngp_set.ngp_shutdown_events = 1;
} }
} }
...@@ -1078,54 +1062,70 @@ static int nhp_merge_lists(su_home_t *home, ...@@ -1078,54 +1062,70 @@ static int nhp_merge_lists(su_home_t *home,
return 1; return 1;
} }
static /** Save parameters in @a gtmp and @a tmp.
nua_handle_preferences_t *nhp_move_params(su_home_t *home, */
nua_handle_preferences_t *dst, static
su_home_t *tmphome, int nhp_save_params(nua_handle_t *nh,
nua_handle_preferences_t const *src) su_home_t *tmphome,
nua_global_preferences_t *gsrc,
nua_handle_preferences_t *src)
{ {
/* Update prefs structure */ su_home_t *home = nh->nh_home;
nua_handle_preferences_t tbf[1]; nua_t *nua = nh->nh_nua;
nua_handle_t *dnh = nua->nua_dhandle;
nua_handle_preferences_t *dst = nh->nh_prefs, old[1];
if (dst == NULL) if (gsrc) {
dst = su_zalloc(home, sizeof *dst); *nua->nua_prefs = *gsrc; /* No pointers this far */
if (dst == NULL) }
return NULL;
if (su_home_move(home, tmphome) < 0) if (!NHP_IS_ANY_SET(src))
return NULL; return 0;
if (nh == dnh || nh->nh_prefs != dnh->nh_prefs) {
dst = nh->nh_prefs, *old = *dst;
assert(dst);
}
else {
dst = su_zalloc(home, sizeof *dst), memset(old, 0, sizeof *old);
if (!dst)
return -1;
}
*tbf = *dst; /* Move allocations from tmphome to home */
su_home_move(nh->nh_home, tmphome);
/* Copy parameters that are set from src to dst */
nhp_or_set(dst, src); nhp_or_set(dst, src);
/* Handle pointer items. Free changed ones and zap unset ones. */ /* Handle pointer items. Free changed ones and zap unset ones. */
#define NHP_ZAP_OVERRIDEN(tbf, nhp, pref) \ /* Note that pointer items where !NHP_ISSET(old, pref) are not freed
(((tbf)->nhp_set.nhb_##pref \ (because they were just on loan from the default preference set) */
&& (tbf)->nhp_##pref != (nhp)->nhp_##pref \ #define NHP_ZAP_OVERRIDEN(old, dst, free, pref) \
? su_free(home, (void *)(tbf)->nhp_##pref) : (void)0), \ (((NHP_ISSET(old, pref) && \
(void)(!(nhp)->nhp_set.nhb_##pref ? (nhp)->nhp_##pref = NULL : NULL)) (old)->nhp_##pref && (old)->nhp_##pref != (dst)->nhp_##pref) \
? (free)(home, (void *)(old)->nhp_##pref) : (void)0), \
NHP_ZAP_OVERRIDEN(tbf, dst, soa_name); (void)(!(dst)->nhp_set.nhb_##pref ? (dst)->nhp_##pref = NULL : NULL))
NHP_ZAP_OVERRIDEN(tbf, dst, registrar);
NHP_ZAP_OVERRIDEN(tbf, dst, supported); NHP_ZAP_OVERRIDEN(old, dst, su_free, soa_name);
NHP_ZAP_OVERRIDEN(tbf, dst, allow); NHP_ZAP_OVERRIDEN(old, dst, su_free, registrar);
NHP_ZAP_OVERRIDEN(tbf, dst, user_agent); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, allow);
NHP_ZAP_OVERRIDEN(tbf, dst, organization); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, supported);
NHP_ZAP_OVERRIDEN(tbf, dst, instance); NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, allow_events);
NHP_ZAP_OVERRIDEN(tbf, dst, m_display); NHP_ZAP_OVERRIDEN(old, dst, su_free, user_agent);
NHP_ZAP_OVERRIDEN(tbf, dst, m_username); NHP_ZAP_OVERRIDEN(old, dst, su_free, organization);
NHP_ZAP_OVERRIDEN(tbf, dst, m_params); NHP_ZAP_OVERRIDEN(old, dst, su_free, m_display);
NHP_ZAP_OVERRIDEN(tbf, dst, m_features); NHP_ZAP_OVERRIDEN(old, dst, su_free, m_username);
NHP_ZAP_OVERRIDEN(tbf, dst, outbound); NHP_ZAP_OVERRIDEN(old, dst, su_free, m_params);
NHP_ZAP_OVERRIDEN(old, dst, su_free, m_features);
#define NHP_ZAP_OVERRIDEN_HDR(tbf, nhp, pref) \ NHP_ZAP_OVERRIDEN(old, dst, su_free, instance);
(((tbf)->nhp_set.nhb_##pref \ NHP_ZAP_OVERRIDEN(old, dst, su_free, outbound);
&& (tbf)->nhp_##pref != (nhp)->nhp_##pref \ NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, appl_method);
? msg_header_free(home, (void *)(tbf)->nhp_##pref) : (void)0), \ NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, initial_route);
(void)(!(nhp)->nhp_set.nhb_##pref ? (nhp)->nhp_##pref = NULL : NULL))
nh->nh_prefs = dst;
NHP_ZAP_OVERRIDEN_HDR(tbf, dst, initial_route);
return 0;
return dst;
} }
static int nua_handle_tags_filter(tagi_t const *f, tagi_t const *t); static int nua_handle_tags_filter(tagi_t const *f, tagi_t const *t);
...@@ -1515,6 +1515,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, ...@@ -1515,6 +1515,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
tagi_t const *tags) tagi_t const *tags)
{ {
nua_handle_t *dnh = nua->nua_dhandle; nua_handle_t *dnh = nua->nua_dhandle;
nua_global_preferences_t const *ngp = nua->nua_prefs;
nua_handle_preferences_t const *nhp = nh->nh_prefs; nua_handle_preferences_t const *nhp = nh->nh_prefs;
tagi_t *lst; tagi_t *lst;
...@@ -1539,8 +1540,6 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, ...@@ -1539,8 +1540,6 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
enter; enter;
su_home_auto(tmphome, sizeof(tmphome));
nta_agent_get_params(nua->nua_nta, nta_agent_get_params(nua->nua_nta,
NTATAG_UDP_MTU_REF(udp_mtu), NTATAG_UDP_MTU_REF(udp_mtu),
NTATAG_SIP_T1_REF(sip_t1), NTATAG_SIP_T1_REF(sip_t1),
...@@ -1588,6 +1587,8 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, ...@@ -1588,6 +1587,8 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
? sip_##pref##_make(tmphome, (char *)nhp->nhp_##pref) \ ? sip_##pref##_make(tmphome, (char *)nhp->nhp_##pref) \
: NULL)) : NULL))
su_home_auto(tmphome, sizeof(tmphome));
lst = tl_filtered_tlist lst = tl_filtered_tlist
(tmphome, tags, (tmphome, tags,
TAG_IF(has_from, SIPTAG_FROM(from)), TAG_IF(has_from, SIPTAG_FROM(from)),
...@@ -1656,11 +1657,18 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, ...@@ -1656,11 +1657,18 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
TIF(NUTAG_M_PARAMS, m_params), TIF(NUTAG_M_PARAMS, m_params),
TIF(NUTAG_M_FEATURES, m_features), TIF(NUTAG_M_FEATURES, m_features),
TIF(NUTAG_OUTBOUND, outbound), TIF(NUTAG_OUTBOUND, outbound),
TIF(NUTAG_DETECT_NETWORK_UPDATES, detect_network_updates),
/* Skip user-agent-level parameters if parameters are for handle only */ /* Skip user-agent-level parameters if parameters are for handle only */
TAG_IF(nh != dnh, TAG_NEXT(media_params)), TAG_IF(nh != dnh, TAG_NEXT(media_params)),
/* Include tag in the list returned to user
* if it has been earlier set (by user) */
#define GIF(TAG, pref) \
TAG_IF(ngp->ngp_set.ngp_##pref, TAG(ngp->ngp_##pref))
GIF(NUTAG_DETECT_NETWORK_UPDATES, detect_network_updates),
GIF(NUTAG_SHUTDOWN_EVENTS, shutdown_events),
NTATAG_CONTACT(m), NTATAG_CONTACT(m),
#if HAVE_SOFIA_SMIME #if HAVE_SOFIA_SMIME
......
...@@ -127,9 +127,6 @@ typedef struct nua_handle_preferences ...@@ -127,9 +127,6 @@ typedef struct nua_handle_preferences
/** Outbound OPTIONS */ /** Outbound OPTIONS */
char const *nhp_outbound; char const *nhp_outbound;
/** Network detection: NONE, INFORMAL, TRY_FULL */
int nhp_detect_network_updates;
sip_allow_t *nhp_appl_method; sip_allow_t *nhp_appl_method;
/** Initial route set */ /** Initial route set */
...@@ -137,6 +134,12 @@ typedef struct nua_handle_preferences ...@@ -137,6 +134,12 @@ typedef struct nua_handle_preferences
union { struct { union { struct {
/* A bit for each feature set by application */ /* A bit for each feature set by application */
/* NOTE:
Some compilers behave weird if there are bitfields
together with width > 32
So there should be a padding field (unsigned:0;)
every 32 bits.
*/
unsigned nhb_retry_count:1; unsigned nhb_retry_count:1;
unsigned nhb_max_subscriptions:1; unsigned nhb_max_subscriptions:1;
...@@ -172,7 +175,8 @@ typedef struct nua_handle_preferences ...@@ -172,7 +175,8 @@ typedef struct nua_handle_preferences
unsigned nhb_allow:1; unsigned nhb_allow:1;
unsigned nhb_supported:1; unsigned nhb_supported:1;
unsigned :0; /* at most 32 bits ... */ unsigned :0; /* at most 32 bits before this point */
unsigned nhb_allow_events:1; unsigned nhb_allow_events:1;
unsigned nhb_user_agent:1; unsigned nhb_user_agent:1;
unsigned nhb_organization:1; unsigned nhb_organization:1;
...@@ -183,7 +187,6 @@ typedef struct nua_handle_preferences ...@@ -183,7 +187,6 @@ typedef struct nua_handle_preferences
unsigned nhb_m_features:1; unsigned nhb_m_features:1;