Bugs fixed in this release
--------------------------
+- Fixed nua failing to refresh publication with re-PUBLISH.
+ Problem reported by Jan van den Bosch.
+- Fixed encoding of c= lines without IN address.
+ Problem reported by Saurav Sahu.
- Fixed status code sent to network and returned to the client if there was
an internal error while responding to a request.
The problem was reported by Michael Jerris and Joshua Engelbrecht.
AC_HEADER_TIME
AC_TYPE_SIZE_T
-AC_STRUCT_SIN6
AC_SYS_SA_LEN
### checks for library functions
MSG_PARSER_AWK = ${srcdir}/../msg/msg_parser.awk
-AWK_HTTP_AWK = ${AWK} -f ${MSG_PARSER_AWK} module=http
+AWK_HTTP_AWK = LC_ALL=C ${AWK} -f ${MSG_PARSER_AWK} module=http
SS_HTTP_H = ${srcdir}/sofia-sip/http.h
sofia-sip/http_protos.h: ${srcdir}/sofia-sip/http_protos.h.in
@-mkdir sofia-sip 2>/dev/null || true
- ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/$@.in ${SS_HTTP_H}
+ ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/http_protos.h.in ${SS_HTTP_H}
sofia-sip/http_tag.h: ${srcdir}/sofia-sip/http_tag.h.in
@-mkdir sofia-sip 2>/dev/null || true
- ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/$@.in ${SS_HTTP_H}
+ ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/http_tag.h.in ${SS_HTTP_H}
http_tag.c: ${srcdir}/http_tag.c.in
- ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/$@.in ${SS_HTTP_H}
+ ${AWK_HTTP_AWK} PR=$@ TEMPLATE=${srcdir}/http_tag.c.in ${SS_HTTP_H}
http_parser_table.c: ${srcdir}/http_parser_table.c.in
- ${AWK_HTTP_AWK} PT=$@ TEMPLATE=${srcdir}/$@.in \
+ ${AWK_HTTP_AWK} PT=$@ TEMPLATE=${srcdir}/http_parser_table.c.in \
MC_HASH_SIZE=127 ${SS_HTTP_H}
/**@file sofia-sip/string0.h
*
- * @brief String comparison functions accepting NULL pointers
- *
- * This module contains string comparison functions that can be called
- * with NULL pointer as argument.
+ * @brief Extra string function.
*
+ * String comparison functions accepting NULL pointers: str0cmp(),
+ * str0ncmp(), str0casecmp(), str0ncasecmp(). Also includes span functions
+ * testing at most @a n bytes: strncspn(), strnspn().
*/
#ifndef SU_CONFIG_H
MSG_PARSER_AWK = $(srcdir)/msg_parser.awk
-AWK_MSG_AWK = $(AWK) -f $(MSG_PARSER_AWK)
+AWK_MSG_AWK = LC_ALL=C $(AWK) -f $(MSG_PARSER_AWK)
${GENERATED_HC}: ${MSG_PARSER_AWK}
test_protos.h: ${srcdir}/test_protos.h.in
$(AWK_MSG_AWK) module=msg_test NO_MIDDLE=1 NO_LAST=1 \
- PR=$@ TEMPLATE=$(srcdir)/$@.in ${TEST_CLASS_H}
+ PR=$@ TEMPLATE=${srcdir}/test_protos.h.in ${TEST_CLASS_H}
test_table.c: ${srcdir}/test_table.c.in
$(AWK_MSG_AWK) module=msg_test prefix=msg \
MC_HASH_SIZE=127 multipart=msg_multipart \
- PT=$@ TEMPLATE=$(srcdir)/$@.in ${TEST_CLASS_H}
+ PT=$@ TEMPLATE=${srcdir}/test_table.c.in ${TEST_CLASS_H}
SS_MIME_H = ${srcdir}/sofia-sip/msg_mime.h
sofia-sip/msg_protos.h: ${srcdir}/sofia-sip/msg_protos.h.in
@-mkdir sofia-sip 2>/dev/null || true
$(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_MIDDLE=1 \
- PR=$@ TEMPLATE=$(srcdir)/$@.in ${SS_MIME_H}
+ PR=$@ TEMPLATE=${srcdir}/sofia-sip/msg_protos.h.in \
+ ${SS_MIME_H}
sofia-sip/msg_mime_protos.h: ${srcdir}/sofia-sip/msg_mime_protos.h.in
@-mkdir sofia-sip 2>/dev/null || true
$(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_LAST=1 \
- PR=$@ TEMPLATE=$(srcdir)/$@.in ${SS_MIME_H}
+ PR=$@ TEMPLATE=${srcdir}/sofia-sip/msg_mime_protos.h.in \
+ ${SS_MIME_H}
msg_mime_table.c: ${srcdir}/msg_mime_table.c.in
$(AWK_MSG_AWK) module=msg_multipart \
tprefix=msg prefix=mp MC_HASH_SIZE=127 \
- PT=$@ TEMPLATE=$(srcdir)/$@.in ${SS_MIME_H}
+ PT=$@ TEMPLATE=${srcdir}/msg_mime_table.c.in \
+ ${SS_MIME_H}
}
else {
# Remove line with #version#
- gsub(/\n[^\n]*#version#[^\n]*\n/, "\n", p);
+ gsub(/\n[^#\n]*#version#[^\n]*/, "", p);
}
print p > PR;
static int nua_publish_client_request(nua_client_request_t *cr,
msg_t *, sip_t *,
tagi_t const *tags);
+static int nua_publish_client_check_restart(nua_client_request_t *cr,
+ int status, char const *phrase,
+ sip_t const *sip);
static int nua_publish_client_response(nua_client_request_t *cr,
int status, char const *phrase,
sip_t const *sip);
nua_publish_client_template,
nua_publish_client_init,
nua_publish_client_request,
- /* nua_publish_client_check_restart */ NULL,
+ nua_publish_client_check_restart,
nua_publish_client_response,
/* nua_publish_client_preliminary */ NULL
};
TAG_NEXT(tags));
}
+static int nua_publish_client_check_restart(nua_client_request_t *cr,
+ int status, char const *phrase,
+ sip_t const *sip)
+{
+ char const *restarting = NULL;
+
+ if (cr->cr_terminating || !cr->cr_usage)
+ ;
+ else if (status == 412)
+ restarting = phrase;
+ else if (200 <= status && status < 300 &&
+ sip->sip_expires && sip->sip_expires->ex_delta == 0)
+ restarting = "Immediate re-PUBLISH";
+
+ if (restarting) {
+ struct publish_usage *pu = nua_dialog_usage_private(cr->cr_usage);
+
+ if (pu) {
+ pu->pu_published = 0;
+ su_free(cr->cr_owner->nh_home, pu->pu_etag), pu->pu_etag = NULL;
+ if (nua_client_restart(cr, 100, restarting))
+ return 0;
+ }
+ }
+
+ return nua_base_client_check_restart(cr, status, phrase, sip);
+}
+
static int nua_publish_client_response(nua_client_request_t *cr,
int status, char const *phrase,
sip_t const *sip)
if (pu->pu_etag)
su_free(nh->nh_home, pu->pu_etag), pu->pu_etag = NULL;
- if (status == 412) {
- if (nua_client_restart(cr, 100, phrase))
- return 0;
- }
- else if (status < 300) {
- if (ex && ex->ex_delta == 0 &&
- nua_client_restart(cr, 100, "Trying re-PUBLISH"))
- return 0;
-
+ if (status < 300) {
pu->pu_published = 1;
pu->pu_etag = sip_etag_dup(nh->nh_home, sip->sip_etag);
else
SET_STATUS1(NUA_INTERNAL_ERROR);
}
+ else
+ nua_dialog_usage_set_refresh(du, ex->ex_delta);
}
}
run_c_until(ctx, -1, save_until_final_response);
TEST_1(e = c->events->head);
TEST_E(e->data->e_event, nua_r_unregister);
+ if (e->data->e_status == 100) {
+ TEST_1(e = e->next);
+ TEST_E(e->data->e_event, nua_r_unregister);
+ }
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(!sip->sip_contact);
return 0;
}
+char const *test_etag = "tagtag";
+
int respond_with_etag(CONDITION_PARAMS)
{
msg_t *with = nua_current_request(nua);
char const *etag;
case nua_i_publish:
etag = sip->sip_if_match ? sip->sip_if_match->g_value : NULL;
- if (sip->sip_if_match && (etag == NULL || strcmp(etag, "tagtag"))) {
+ if (sip->sip_if_match && (etag == NULL || strcmp(etag, test_etag))) {
RESPOND(ep, call, nh, SIP_412_PRECONDITION_FAILED,
NUTAG_WITH(with),
TAG_END());
}
else {
- RESPOND(ep, call, nh, SIP_200_OK,
- NUTAG_WITH(with),
- SIPTAG_ETAG_STR("tagtag"),
- SIPTAG_EXPIRES_STR("3600"),
- SIPTAG_EXPIRES(sip->sip_expires), /* overrides 3600 */
- TAG_END());
+ RESPOND(ep, call, nh, SIP_200_OK,
+ NUTAG_WITH(with),
+ SIPTAG_ETAG_STR(test_etag),
+ SIPTAG_EXPIRES_STR("3600"),
+ SIPTAG_EXPIRES(sip->sip_expires), /* overrides 3600 */
+ TAG_END());
}
return 1;
default:
SIPTAG_EVENT_STR("presence"),
SIPTAG_CONTENT_TYPE_STR("text/urllist"),
SIPTAG_PAYLOAD_STR("sip:example.com\n"),
+ SIPTAG_EXPIRES_STR("5"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, respond_with_etag);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_etag);
- TEST_S(sip->sip_etag->g_string, "tagtag");
+ TEST_S(sip->sip_etag->g_string, test_etag);
TEST_1(!e->next);
/*
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+ if (!ctx->expensive && 0)
+ goto skip_republish;
+
+ run_ab_until(ctx, -1, save_until_final_response, -1, respond_with_etag);
+
+ /* Client events: nua_r_publish
+ */
+ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish);
+ TEST(e->data->e_status, 200);
+ TEST_1(sip = sip_object(e->data->e_msg));
+ TEST_1(sip->sip_etag);
+ TEST_S(sip->sip_etag->g_string, test_etag);
+ TEST_1(!e->next);
+
+ free_events_in_list(ctx, a->events);
+
+ /*
+ Server events:
+ nua_i_publish
+ */
+ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_publish);
+ TEST(e->data->e_status, 100);
+ TEST_1(sip = sip_object(e->data->e_msg));
+ TEST_1(sip = sip_object(e->data->e_msg));
+ TEST_1(sip->sip_if_match);
+ TEST_S(sip->sip_if_match->g_string, "tagtag");
+ TEST_1(!sip->sip_content_type);
+ TEST_1(!sip->sip_payload);
+ TEST_1(!e->next);
+
+ free_events_in_list(ctx, b->events);
+ nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+ skip_republish:
+
UNPUBLISH(a, a_call, a_call->nh, TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, respond_with_etag);
return;
}
- sdp_printf(p, "%s%s%s", nettype, addrtype, c->c_address);
+ if (nettype && addrtype)
+ sdp_printf(p, "%s%s%s", nettype, addrtype, c->c_address);
+ else if (nettype)
+ sdp_printf(p, "%s%s%s", nettype, c->c_address);
+ else
+ sdp_printf(p, "%s", c->c_address);
+
if (c->c_mcast || c->c_ttl) {
sdp_printf(p, "/%u", c->c_ttl);
if (c->c_groups > 1)
"o=- 2353687640 2353687640 IN IP4 128.3.4.5\r\n"
"s=marketing\r\n"
"e=john.jones.3@chinet.net\r\n"
- "c= TN RFC2543 +1-201-406-4090\r\n"
+ "c=TN RFC2543 +1-201-406-4090\r\n"
"t=2353687640 0\r\n"
"m=audio 1 voice -\r\n"
;
su_home_t *home = su_home_create();
sdp_parser_t *parser;
sdp_session_t *sdp;
+ sdp_printer_t *printer;
+ char const *m;
BEGIN();
TEST_1((parser = sdp_parse(home, pint_msg, sizeof(pint_msg) - 1, sdp_f_anynet)));
TEST_1((sdp = sdp_session(parser)));
+ TEST_1((printer = sdp_print(home, sdp, NULL, -1, 0)));
+ TEST_1((m = sdp_message(printer)));
+ TEST_S(m, pint_msg);
+ TEST(sdp_message_size(printer), sizeof(pint_msg) - 1);
+
TEST_1((parser = sdp_parse(home, pint_torture_msg, sizeof(pint_torture_msg) - 1,
sdp_f_anynet)));
TEST_1((sdp = sdp_session(parser)));
MSG_PARSER_AWK = $(srcdir)/../msg/msg_parser.awk
-AWK_SIP_AWK = $(AWK) -f $(MSG_PARSER_AWK) module=sip
+AWK_SIP_AWK = LC_ALL=C $(AWK) -f $(MSG_PARSER_AWK) module=sip
SS_SIP_H = ${srcdir}/sofia-sip/sip.h
sofia-sip/sip_hclasses.h: ${srcdir}/sofia-sip/sip_hclasses.h.in
@-mkdir sofia-sip 2>/dev/null || true
- ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/$@.in ${SS_SIP_H}
+ ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_hclasses.h.in \
+ ${SS_SIP_H}
sofia-sip/sip_protos.h: ${srcdir}/sofia-sip/sip_protos.h.in
@-mkdir sofia-sip 2>/dev/null || true
- ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/$@.in ${SS_SIP_H}
+ ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_protos.h.in \
+ ${SS_SIP_H}
sofia-sip/sip_tag.h: ${srcdir}/sofia-sip/sip_tag.h.in
@-mkdir sofia-sip 2>/dev/null || true
- ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/$@.in ${SS_SIP_H}
+ ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sofia-sip/sip_tag.h.in \
+ ${SS_SIP_H}
sip_tag.c: ${srcdir}/sip_tag.c.in ${EXTRA}
- ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/$@.in ${SS_SIP_H} ${EXTRA}
+ ${AWK_SIP_AWK} PR=$@ TEMPLATE=${srcdir}/sip_tag.c.in \
+ ${SS_SIP_H} ${EXTRA}
# Note: sip_bad_mask is used by nta to weed out bad messages
sip_parser_table.c: ${srcdir}/sip_parser_table.c.in ${EXTRA} sip_bad_mask
- ${AWK_SIP_AWK} PT=$@ TEMPLATE=${srcdir}/$@.in \
+ ${AWK_SIP_AWK} PT=$@ TEMPLATE=${srcdir}/sip_parser_table.c.in \
FLAGFILE=${srcdir}/sip_bad_mask \
MC_HASH_SIZE=127 MC_SHORT_SIZE=26 \
${SS_SIP_H} ${EXTRA}
PACKAGE_VERSION="${PACKAGE_VERSION}" \
TEMPLATE1=${srcdir}/sofia-sip/sip_hclasses.h.in \
TEMPLATE2=${srcdir}/sofia-sip/sip_protos.h.in \
- TEMPLATE=${srcdir}/$@.in ${EXTRA}
+ TEMPLATE=${srcdir}/sofia-sip/sip_extra.h.in ${EXTRA}
static int tcp_test(tp_test_t *tt)
{
+ BEGIN();
+
+#ifndef WIN32 /* Windows seems to be buffering too much */
+
msg_t *msg = NULL;
int i;
tport_t *tp, *tp0;
char ident[16];
- BEGIN();
-
/* Create a large message, just to force queueing in sending end */
TEST(new_test_msg(tt, &msg, "tcp-0", 1, 16 * 64 * 1024), 0);
test_create_md5(tt, msg);
tport_decref(&tp0);
+#endif
+
END();
}
msg = self->tp_msg;
ai = msg_addrinfo(msg);
-
- if (!ai)
- return -1;
-
from = (su_sockaddr_t *)ai->ai_addr, fromlen = (socklen_t)(ai->ai_addrlen);
n = su_vrecv(self->tp_socket, iovec, veclen, 0, from, &fromlen);
[Define to 1 if you have sa_len in struct sockaddr])
fi
-AC_REQUIRE([AC_STRUCT_SIN6])
+AC_ARG_ENABLE([ip6],
+[ --disable-ip6 disable IPv6 functionality [[enabled]]],,enable_ip6=yes)
+
+if ! test no$enable_ip6 = nono ; then
+AC_STRUCT_SIN6
case $ac_cv_sin6 in
yes) SAC_SU_DEFINE(SU_HAVE_IN6, 1, [
Define to 1 if you have struct sockaddr_in6]) ;;
no) ;;
*) AC_MSG_ERROR([Inconsistent struct sockaddr_sin6 test]) ;;
esac
+fi
AC_CHECK_HEADERS([unistd.h sys/time.h])