sync back up again with sofia tree prior to their release

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4177 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris committed 2007-02-09 17:32:17 +00:00
1 parent f359f847f7
commit 666bd3bec3
55 files changed
+1807 -2097

No files matched your search

+8
View File
@@ -1,3 +1,11 @@
2007-02-09 Kai Vehmanen <kai.vehmanen@nokia.com>
* libsofia-sip-ua interface v4 frozen (4:0:4) for the 1.12.5 release
2006-10-12 Kai Vehmanen <kai.vehmanen@nokia.com>
* libsofia-sip-ua interface v3 frozen (3:0:3) for the 1.12.3 release
2006-09-26 Kai Vehmanen <kai.vehmanen@nokia.com>
* libsofia-sip-ua interface v2 frozen (2:0:2) for the 1.12.2 release
@@ -61,9 +61,9 @@ char const http_version_1_0[] = "HTTP/1.0";
/** HTTP version 0.9 is an empty string. */
char const http_version_0_9[] = "";
msg_mclass_t *http_default_mclass(void)
msg_mclass_t const *http_default_mclass(void)
{
extern msg_mclass_t http_mclass[];
extern msg_mclass_t const http_mclass[];
return http_mclass;
}
@@ -95,7 +95,7 @@ SOFIAPUBVAR char const http_version_1_1[];
*/
/** HTTP parser description. */
SOFIAPUBFUN msg_mclass_t *http_default_mclass(void);
SOFIAPUBFUN msg_mclass_t const *http_default_mclass(void);
/** Complete a HTTP request. */
SOFIAPUBFUN int http_request_complete(msg_t *msg);
@@ -76,7 +76,7 @@ static int http_tag_test(void);
static int test_query_parser(void);
static msg_t *read_message(char const string[]);
msg_mclass_t *test_mclass = NULL;
msg_mclass_t const *test_mclass = NULL;
void usage(void)
{
+35 -20
View File
@@ -890,7 +890,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
unsigned threadpool = agent->sa_tport_threadpool;
char const *sigcomp = agent->sa_sigcomp_options;
char const *algorithm = NONE;
msg_mclass_t *mclass = NONE;
msg_mclass_t const *mclass = NONE;
sip_contact_t const *aliases = NONE;
url_string_t const *proxy = NONE;
tport_t *tport;
@@ -4983,15 +4983,16 @@ static inline
nta_incoming_t *incoming_find(nta_agent_t const *agent,
sip_t const *sip,
sip_via_t const *v,
nta_incoming_t **merge,
nta_incoming_t **ack)
nta_incoming_t **return_merge,
nta_incoming_t **return_ack)
{
sip_cseq_t const *cseq = sip->sip_cseq;
sip_call_id_t const *i = sip->sip_call_id;
sip_to_t const *to = sip->sip_to;
sip_from_t const *from = sip->sip_from;
sip_request_t *rq = sip->sip_request;
int is_uas_ack = ack && agent->sa_is_a_uas && rq->rq_method == sip_method_ack;
int is_uas_ack = return_ack &&
agent->sa_is_a_uas && rq->rq_method == sip_method_ack;
incoming_htable_t const *iht = agent->sa_incoming;
hash_value_t hash = NTA_HASH(i, cseq->cs_seq);
@@ -5008,6 +5009,30 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
continue;
if (str0casecmp(irq->irq_from->a_tag, from->a_tag))
continue;
if (str0casecmp(irq->irq_via->v_branch, v->v_branch) != 0 ||
strcasecmp(irq->irq_via->v_host, v->v_host) != 0) {
if (!agent->sa_is_a_uas)
continue;
if (is_uas_ack &&
irq->irq_method == sip_method_invite &&
200 <= irq->irq_status && irq->irq_status < 300 &&
addr_match(irq->irq_to, to))
*return_ack = irq;
/* RFC3261 - section 8.2.2.2 Merged Requests */
else if (return_merge && agent->sa_merge_482 &&
irq->irq_cseq->cs_method == cseq->cs_method &&
(irq->irq_cseq->cs_method != sip_method_unknown ||
strcmp(irq->irq_cseq->cs_method_name,
cseq->cs_method_name) == 0)) {
*return_merge = irq;
continue;
}
else
continue;
}
if (is_uas_ack) {
if (!addr_match(irq->irq_to, to))
continue;
@@ -5020,16 +5045,6 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
else if (str0casecmp(irq->irq_to->a_tag, to->a_tag))
continue;
if (str0casecmp(irq->irq_via->v_branch, v->v_branch) != 0) {
if (!agent->sa_is_a_uas)
continue;
if (is_uas_ack && irq->irq_status >= 200 && irq->irq_status < 300)
*ack = irq;
/* RFC3261 - section 8.2.2.2 Merged Requests */
else if (merge && !to->a_tag && agent->sa_merge_482)
*merge = irq;
continue;
}
if (!is_uas_ack && url_cmp(irq->irq_rq->rq_url, rq->rq_url))
continue;
@@ -5041,18 +5056,18 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
if (irq->irq_method == rq->rq_method)
break; /* found */
if (ack && rq->rq_method == sip_method_cancel)
*ack = irq;
else if (ack && rq->rq_method == sip_method_ack &&
if (return_ack && rq->rq_method == sip_method_cancel)
*return_ack = irq;
else if (return_ack && rq->rq_method == sip_method_ack &&
irq->irq_method == sip_method_invite)
*ack = irq;
*return_ack = irq;
}
if (irq)
return irq;
/* Check PRACKed requests */
if (ack && rq->rq_method == sip_method_prack && sip->sip_rack) {
if (return_ack && rq->rq_method == sip_method_prack && sip->sip_rack) {
sip_rack_t const *rack = sip->sip_rack;
hash = NTA_HASH(i, rack->ra_cseq);
@@ -5072,7 +5087,7 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
continue;
if (!irq->irq_from->a_tag != !from->a_tag)
continue;
*ack = irq;
*return_ack = irq;
return NULL;
}
@@ -108,7 +108,7 @@ struct nta_agent_s
uint32_t sa_nw_updates; /* Shall we enable network detector? */
uint32_t sa_flags; /**< Message flags */
msg_mclass_t *sa_mclass;
msg_mclass_t const *sa_mclass;
sip_contact_t *sa_contact;
sip_via_t *sa_vias; /**< @Via headers for all transports */
+32 -32
View File
@@ -110,38 +110,38 @@ tag_typedef_t ntatag_rseq = UINTTAG_TYPEDEF(rseq);
/* Status */
tag_typedef_t ntatag_s_irq_hash = UINTTAG_TYPEDEF(s_irq_hash);
tag_typedef_t ntatag_s_orq_hash = UINTTAG_TYPEDEF(s_orq_hash);
tag_typedef_t ntatag_s_leg_hash = UINTTAG_TYPEDEF(s_leg_hash);
tag_typedef_t ntatag_s_irq_hash_used = UINTTAG_TYPEDEF(s_irq_hash_used);
tag_typedef_t ntatag_s_orq_hash_used = UINTTAG_TYPEDEF(s_orq_hash_used);
tag_typedef_t ntatag_s_leg_hash_used = UINTTAG_TYPEDEF(s_leg_hash_used);
tag_typedef_t ntatag_s_recv_msg = UINTTAG_TYPEDEF(s_recv_msg);
tag_typedef_t ntatag_s_recv_request = UINTTAG_TYPEDEF(s_recv_request);
tag_typedef_t ntatag_s_recv_response = UINTTAG_TYPEDEF(s_recv_response);
tag_typedef_t ntatag_s_bad_message = UINTTAG_TYPEDEF(s_bad_message);
tag_typedef_t ntatag_s_bad_request = UINTTAG_TYPEDEF(s_bad_request);
tag_typedef_t ntatag_s_bad_response = UINTTAG_TYPEDEF(s_bad_response);
tag_typedef_t ntatag_s_drop_request = UINTTAG_TYPEDEF(s_drop_request);
tag_typedef_t ntatag_s_drop_response = UINTTAG_TYPEDEF(s_drop_response);
tag_typedef_t ntatag_s_client_tr = UINTTAG_TYPEDEF(s_client_tr);
tag_typedef_t ntatag_s_server_tr = UINTTAG_TYPEDEF(s_server_tr);
tag_typedef_t ntatag_s_dialog_tr = UINTTAG_TYPEDEF(s_dialog_tr);
tag_typedef_t ntatag_s_acked_tr = UINTTAG_TYPEDEF(s_acked_tr);
tag_typedef_t ntatag_s_canceled_tr = UINTTAG_TYPEDEF(s_canceled_tr);
tag_typedef_t ntatag_s_trless_request = UINTTAG_TYPEDEF(s_trless_request);
tag_typedef_t ntatag_s_trless_to_tr = UINTTAG_TYPEDEF(s_trless_to_tr);
tag_typedef_t ntatag_s_trless_response = UINTTAG_TYPEDEF(s_trless_response);
tag_typedef_t ntatag_s_trless_200 = UINTTAG_TYPEDEF(s_trless_200);
tag_typedef_t ntatag_s_merged_request = UINTTAG_TYPEDEF(s_merged_request);
tag_typedef_t ntatag_s_sent_msg = UINTTAG_TYPEDEF(s_sent_msg);
tag_typedef_t ntatag_s_sent_request = UINTTAG_TYPEDEF(s_sent_request);
tag_typedef_t ntatag_s_sent_response = UINTTAG_TYPEDEF(s_sent_response);
tag_typedef_t ntatag_s_retry_request = UINTTAG_TYPEDEF(s_retry_request);
tag_typedef_t ntatag_s_retry_response = UINTTAG_TYPEDEF(s_retry_response);
tag_typedef_t ntatag_s_recv_retry = UINTTAG_TYPEDEF(s_recv_retry);
tag_typedef_t ntatag_s_tout_request = UINTTAG_TYPEDEF(s_tout_request);
tag_typedef_t ntatag_s_tout_response = UINTTAG_TYPEDEF(s_tout_response);
tag_typedef_t ntatag_s_irq_hash = USIZETAG_TYPEDEF(s_irq_hash);
tag_typedef_t ntatag_s_orq_hash = USIZETAG_TYPEDEF(s_orq_hash);
tag_typedef_t ntatag_s_leg_hash = USIZETAG_TYPEDEF(s_leg_hash);
tag_typedef_t ntatag_s_irq_hash_used = USIZETAG_TYPEDEF(s_irq_hash_used);
tag_typedef_t ntatag_s_orq_hash_used = USIZETAG_TYPEDEF(s_orq_hash_used);
tag_typedef_t ntatag_s_leg_hash_used = USIZETAG_TYPEDEF(s_leg_hash_used);
tag_typedef_t ntatag_s_recv_msg = USIZETAG_TYPEDEF(s_recv_msg);
tag_typedef_t ntatag_s_recv_request = USIZETAG_TYPEDEF(s_recv_request);
tag_typedef_t ntatag_s_recv_response = USIZETAG_TYPEDEF(s_recv_response);
tag_typedef_t ntatag_s_bad_message = USIZETAG_TYPEDEF(s_bad_message);
tag_typedef_t ntatag_s_bad_request = USIZETAG_TYPEDEF(s_bad_request);
tag_typedef_t ntatag_s_bad_response = USIZETAG_TYPEDEF(s_bad_response);
tag_typedef_t ntatag_s_drop_request = USIZETAG_TYPEDEF(s_drop_request);
tag_typedef_t ntatag_s_drop_response = USIZETAG_TYPEDEF(s_drop_response);
tag_typedef_t ntatag_s_client_tr = USIZETAG_TYPEDEF(s_client_tr);
tag_typedef_t ntatag_s_server_tr = USIZETAG_TYPEDEF(s_server_tr);
tag_typedef_t ntatag_s_dialog_tr = USIZETAG_TYPEDEF(s_dialog_tr);
tag_typedef_t ntatag_s_acked_tr = USIZETAG_TYPEDEF(s_acked_tr);
tag_typedef_t ntatag_s_canceled_tr = USIZETAG_TYPEDEF(s_canceled_tr);
tag_typedef_t ntatag_s_trless_request = USIZETAG_TYPEDEF(s_trless_request);
tag_typedef_t ntatag_s_trless_to_tr = USIZETAG_TYPEDEF(s_trless_to_tr);
tag_typedef_t ntatag_s_trless_response = USIZETAG_TYPEDEF(s_trless_response);
tag_typedef_t ntatag_s_trless_200 = USIZETAG_TYPEDEF(s_trless_200);
tag_typedef_t ntatag_s_merged_request = USIZETAG_TYPEDEF(s_merged_request);
tag_typedef_t ntatag_s_sent_msg = USIZETAG_TYPEDEF(s_sent_msg);
tag_typedef_t ntatag_s_sent_request = USIZETAG_TYPEDEF(s_sent_request);
tag_typedef_t ntatag_s_sent_response = USIZETAG_TYPEDEF(s_sent_response);
tag_typedef_t ntatag_s_retry_request = USIZETAG_TYPEDEF(s_retry_request);
tag_typedef_t ntatag_s_retry_response = USIZETAG_TYPEDEF(s_retry_response);
tag_typedef_t ntatag_s_recv_retry = USIZETAG_TYPEDEF(s_recv_retry);
tag_typedef_t ntatag_s_tout_request = USIZETAG_TYPEDEF(s_tout_request);
tag_typedef_t ntatag_s_tout_response = USIZETAG_TYPEDEF(s_tout_response);
/* Internal */
tag_typedef_t ntatag_delay_sending = BOOLTAG_TYPEDEF(delay_sending);
@@ -59,10 +59,10 @@ NTA_DLL extern tag_typedef_t ntatag_any;
NTA_DLL extern tag_typedef_t ntatag_mclass;
/** Message class used by NTA. @HI */
#define NTATAG_MCLASS(x) ntatag_mclass, tag_ptr_v((x))
#define NTATAG_MCLASS(x) ntatag_mclass, tag_cptr_v((x))
NTA_DLL extern tag_typedef_t ntatag_mclass_ref;
#define NTATAG_MCLASS_REF(x) ntatag_mclass_ref, tag_ptr_vr(&(x), (x))
#define NTATAG_MCLASS_REF(x) ntatag_mclass_ref, tag_cptr_vr(&(x), (x))
NTA_DLL extern tag_typedef_t ntatag_bad_req_mask;
/** Mask for bad request messages.
@@ -503,184 +503,184 @@ NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_used_ref;
ntatag_s_leg_hash_used_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_recv_msg;
#define NTATAG_S_RECV_MSG(x) ntatag_s_recv_msg, tag_uint_v(x)
#define NTATAG_S_RECV_MSG(x) ntatag_s_recv_msg, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_recv_msg_ref;
#define NTATAG_S_RECV_MSG_REF(x) ntatag_s_recv_msg_ref, tag_uint_vr(&(x))
#define NTATAG_S_RECV_MSG_REF(x) ntatag_s_recv_msg_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_recv_request;
#define NTATAG_S_RECV_REQUEST(x) ntatag_s_recv_request, tag_uint_v(x)
#define NTATAG_S_RECV_REQUEST(x) ntatag_s_recv_request, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_recv_request_ref;
#define NTATAG_S_RECV_REQUEST_REF(x)\
ntatag_s_recv_request_ref, tag_uint_vr(&(x))
ntatag_s_recv_request_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_recv_response;
#define NTATAG_S_RECV_RESPONSE(x) ntatag_s_recv_response, tag_uint_v(x)
#define NTATAG_S_RECV_RESPONSE(x) ntatag_s_recv_response, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_recv_response_ref;
#define NTATAG_S_RECV_RESPONSE_REF(x)\
ntatag_s_recv_response_ref, tag_uint_vr(&(x))
ntatag_s_recv_response_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_bad_message;
#define NTATAG_S_BAD_MESSAGE(x) ntatag_s_bad_message, tag_uint_v(x)
#define NTATAG_S_BAD_MESSAGE(x) ntatag_s_bad_message, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_bad_message_ref;
#define NTATAG_S_BAD_MESSAGE_REF(x)\
ntatag_s_bad_message_ref, tag_uint_vr(&(x))
ntatag_s_bad_message_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_bad_request;
#define NTATAG_S_BAD_REQUEST(x) ntatag_s_bad_request, tag_uint_v(x)
#define NTATAG_S_BAD_REQUEST(x) ntatag_s_bad_request, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_bad_request_ref;
#define NTATAG_S_BAD_REQUEST_REF(x)\
ntatag_s_bad_request_ref, tag_uint_vr(&(x))
ntatag_s_bad_request_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_bad_response;
#define NTATAG_S_BAD_RESPONSE(x) ntatag_s_bad_response, tag_uint_v(x)
#define NTATAG_S_BAD_RESPONSE(x) ntatag_s_bad_response, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_bad_response_ref;
#define NTATAG_S_BAD_RESPONSE_REF(x)\
ntatag_s_bad_response_ref, tag_uint_vr(&(x))
ntatag_s_bad_response_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_drop_request;
#define NTATAG_S_DROP_REQUEST(x) ntatag_s_drop_request, tag_uint_v(x)
#define NTATAG_S_DROP_REQUEST(x) ntatag_s_drop_request, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_drop_request_ref;
#define NTATAG_S_DROP_REQUEST_REF(x)\
ntatag_s_drop_request_ref, tag_uint_vr(&(x))
ntatag_s_drop_request_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_drop_response;
#define NTATAG_S_DROP_RESPONSE(x) ntatag_s_drop_response, tag_uint_v(x)
#define NTATAG_S_DROP_RESPONSE(x) ntatag_s_drop_response, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_drop_response_ref;
#define NTATAG_S_DROP_RESPONSE_REF(x)\
ntatag_s_drop_response_ref, tag_uint_vr(&(x))
ntatag_s_drop_response_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_client_tr;
#define NTATAG_S_CLIENT_TR(x) ntatag_s_client_tr, tag_uint_v(x)
#define NTATAG_S_CLIENT_TR(x) ntatag_s_client_tr, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_client_tr_ref;
#define NTATAG_S_CLIENT_TR_REF(x)\
ntatag_s_client_tr_ref, tag_uint_vr(&(x))
ntatag_s_client_tr_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_server_tr;
#define NTATAG_S_SERVER_TR(x) ntatag_s_server_tr, tag_uint_v(x)
#define NTATAG_S_SERVER_TR(x) ntatag_s_server_tr, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_server_tr_ref;
#define NTATAG_S_SERVER_TR_REF(x)\
ntatag_s_server_tr_ref, tag_uint_vr(&(x))
ntatag_s_server_tr_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_dialog_tr;
#define NTATAG_S_DIALOG_TR(x) ntatag_s_dialog_tr, tag_uint_v(x)
#define NTATAG_S_DIALOG_TR(x) ntatag_s_dialog_tr, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_dialog_tr_ref;
#define NTATAG_S_DIALOG_TR_REF(x)\
ntatag_s_dialog_tr_ref, tag_uint_vr(&(x))
ntatag_s_dialog_tr_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_acked_tr;
#define NTATAG_S_ACKED_TR(x) ntatag_s_acked_tr, tag_uint_v(x)
#define NTATAG_S_ACKED_TR(x) ntatag_s_acked_tr, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_acked_tr_ref;
#define NTATAG_S_ACKED_TR_REF(x) ntatag_s_acked_tr_ref, tag_uint_vr(&(x))
#define NTATAG_S_ACKED_TR_REF(x) ntatag_s_acked_tr_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_canceled_tr;
#define NTATAG_S_CANCELED_TR(x) ntatag_s_canceled_tr, tag_uint_v(x)
#define NTATAG_S_CANCELED_TR(x) ntatag_s_canceled_tr, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_canceled_tr_ref;
#define NTATAG_S_CANCELED_TR_REF(x) \
ntatag_s_canceled_tr_ref, tag_uint_vr(&(x))
ntatag_s_canceled_tr_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_trless_request;
#define NTATAG_S_TRLESS_REQUEST(x) ntatag_s_trless_request, tag_uint_v(x)
#define NTATAG_S_TRLESS_REQUEST(x) ntatag_s_trless_request, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_trless_request_ref;
#define NTATAG_S_TRLESS_REQUEST_REF(x)\
ntatag_s_trless_request_ref, tag_uint_vr(&(x))
ntatag_s_trless_request_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_trless_to_tr;
#define NTATAG_S_TRLESS_TO_TR(x) ntatag_s_trless_to_tr, tag_uint_v(x)
#define NTATAG_S_TRLESS_TO_TR(x) ntatag_s_trless_to_tr, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_trless_to_tr_ref;
#define NTATAG_S_TRLESS_TO_TR_REF(x)\
ntatag_s_trless_to_tr_ref, tag_uint_vr(&(x))
ntatag_s_trless_to_tr_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_trless_response;
#define NTATAG_S_TRLESS_RESPONSE(x) ntatag_s_trless_response, tag_uint_v(x)
#define NTATAG_S_TRLESS_RESPONSE(x) ntatag_s_trless_response, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_trless_response_ref;
#define NTATAG_S_TRLESS_RESPONSE_REF(x)\
ntatag_s_trless_response_ref, tag_uint_vr(&(x))
ntatag_s_trless_response_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_trless_200;
#define NTATAG_S_TRLESS_200(x) ntatag_s_trless_200, tag_uint_v(x)
#define NTATAG_S_TRLESS_200(x) ntatag_s_trless_200, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_trless_200_ref;
#define NTATAG_S_TRLESS_200_REF(x)\
ntatag_s_trless_200_ref, tag_uint_vr(&(x))
ntatag_s_trless_200_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_merged_request;
#define NTATAG_S_MERGED_REQUEST(x) ntatag_s_merged_request, tag_uint_v(x)
#define NTATAG_S_MERGED_REQUEST(x) ntatag_s_merged_request, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_merged_request_ref;
#define NTATAG_S_MERGED_REQUEST_REF(x)\
ntatag_s_merged_request_ref, tag_uint_vr(&(x))
ntatag_s_merged_request_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_sent_msg;
#define NTATAG_S_SENT_MSG(x) ntatag_s_sent_msg, tag_uint_v(x)
#define NTATAG_S_SENT_MSG(x) ntatag_s_sent_msg, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_sent_msg_ref;
#define NTATAG_S_SENT_MSG_REF(x)\
ntatag_s_sent_msg_ref, tag_uint_vr(&(x))
ntatag_s_sent_msg_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_sent_request;
#define NTATAG_S_SENT_REQUEST(x) ntatag_s_sent_request, tag_uint_v(x)
#define NTATAG_S_SENT_REQUEST(x) ntatag_s_sent_request, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_sent_request_ref;
#define NTATAG_S_SENT_REQUEST_REF(x)\
ntatag_s_sent_request_ref, tag_uint_vr(&(x))
ntatag_s_sent_request_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_sent_response;
#define NTATAG_S_SENT_RESPONSE(x) ntatag_s_sent_response, tag_uint_v(x)
#define NTATAG_S_SENT_RESPONSE(x) ntatag_s_sent_response, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_sent_response_ref;
#define NTATAG_S_SENT_RESPONSE_REF(x)\
ntatag_s_sent_response_ref, tag_uint_vr(&(x))
ntatag_s_sent_response_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_retry_request;
#define NTATAG_S_RETRY_REQUEST(x) ntatag_s_retry_request, tag_uint_v(x)
#define NTATAG_S_RETRY_REQUEST(x) ntatag_s_retry_request, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_retry_request_ref;
#define NTATAG_S_RETRY_REQUEST_REF(x)\
ntatag_s_retry_request_ref, tag_uint_vr(&(x))
ntatag_s_retry_request_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_retry_response;
#define NTATAG_S_RETRY_RESPONSE(x) ntatag_s_retry_response, tag_uint_v(x)
#define NTATAG_S_RETRY_RESPONSE(x) ntatag_s_retry_response, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_retry_response_ref;
#define NTATAG_S_RETRY_RESPONSE_REF(x)\
ntatag_s_retry_response_ref, tag_uint_vr(&(x))
ntatag_s_retry_response_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_recv_retry;
#define NTATAG_S_RECV_RETRY(x) ntatag_s_recv_retry, tag_uint_v(x)
#define NTATAG_S_RECV_RETRY(x) ntatag_s_recv_retry, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_recv_retry_ref;
#define NTATAG_S_RECV_RETRY_REF(x)\
ntatag_s_recv_retry_ref, tag_uint_vr(&(x))
ntatag_s_recv_retry_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_tout_request;
#define NTATAG_S_TOUT_REQUEST(x) ntatag_s_tout_request, tag_uint_v(x)
#define NTATAG_S_TOUT_REQUEST(x) ntatag_s_tout_request, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_tout_request_ref;
#define NTATAG_S_TOUT_REQUEST_REF(x)\
ntatag_s_tout_request_ref, tag_uint_vr(&(x))
ntatag_s_tout_request_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_tout_response;
#define NTATAG_S_TOUT_RESPONSE(x) ntatag_s_tout_response, tag_uint_v(x)
#define NTATAG_S_TOUT_RESPONSE(x) ntatag_s_tout_response, tag_usize_v(x)
NTA_DLL extern tag_typedef_t ntatag_s_tout_response_ref;
#define NTATAG_S_TOUT_RESPONSE_REF(x)\
ntatag_s_tout_response_ref, tag_uint_vr(&(x))
ntatag_s_tout_response_ref, tag_usize_vr(&(x))
SOFIA_END_DECLS
@@ -559,18 +559,18 @@ int api_test_stats(agent_t *ag)
nta_agent_t *nta;
uint32_t irq_hash = -1, orq_hash = -1, leg_hash = -1;
uint32_t recv_msg = -1, sent_msg = -1;
uint32_t recv_request = -1, recv_response = -1;
uint32_t bad_message = -1, bad_request = -1, bad_response = -1;
uint32_t drop_request = -1, drop_response = -1;
uint32_t client_tr = -1, server_tr = -1, dialog_tr = -1;
uint32_t acked_tr = -1, canceled_tr = -1;
uint32_t trless_request = -1, trless_to_tr = -1, trless_response = -1;
uint32_t trless_200 = -1, merged_request = -1;
uint32_t sent_request = -1, sent_response = -1;
uint32_t retry_request = -1, retry_response = -1, recv_retry = -1;
uint32_t tout_request = -1, tout_response = -1;
usize_t irq_hash = -1, orq_hash = -1, leg_hash = -1;
usize_t recv_msg = -1, sent_msg = -1;
usize_t recv_request = -1, recv_response = -1;
usize_t bad_message = -1, bad_request = -1, bad_response = -1;
usize_t drop_request = -1, drop_response = -1;
usize_t client_tr = -1, server_tr = -1, dialog_tr = -1;
usize_t acked_tr = -1, canceled_tr = -1;
usize_t trless_request = -1, trless_to_tr = -1, trless_response = -1;
usize_t trless_200 = -1, merged_request = -1;
usize_t sent_request = -1, sent_response = -1;
usize_t retry_request = -1, retry_response = -1, recv_retry = -1;
usize_t tout_request = -1, tout_response = -1;
TEST_1(nta = nta_agent_create(ag->ag_root, (url_string_t *)"sip:*:*",
NULL, NULL, TAG_END()));
@@ -1301,10 +1301,10 @@ int main(int argc, char *argv[])
}
if (o_attach) {
char line[10];
char *response, line[10];
printf("nua_test: pid %lu\n", (unsigned long)getpid());
printf("<Press RETURN to continue>\n");
fgets(line, sizeof line, stdin);
response = fgets(line, sizeof line, stdin);
}
#if HAVE_ALARM
else if (o_alarm) {
@@ -704,7 +704,7 @@ server_t *server_create(url_t const *url,
tag_type_t tag, tag_value_t value, ...)
{
server_t *srv;
msg_mclass_t *mclass = NULL;
msg_mclass_t const *mclass = NULL;
tp_name_t tpn[1] = {{ NULL }};
su_root_t *root = NULL;
http_server_t const *server = NULL;
@@ -378,11 +378,9 @@ void nua_dialog_usage_remove_at(nua_owner_t *own,
su_free(own, du);
}
/* Zap dialog if there is no more usages */
/* Zap dialog if there are no more usages */
if (ds->ds_usage == NULL) {
nta_leg_destroy(ds->ds_leg), ds->ds_leg = NULL;
su_free(own, (void *)ds->ds_remote_tag), ds->ds_remote_tag = NULL;
ds->ds_route = 0;
nua_dialog_remove(own, ds, NULL);
ds->ds_has_events = 0;
ds->ds_terminated = 0;
return;
+133 -119
View File
@@ -119,8 +119,11 @@ struct register_usage {
nua_registration_t *nr_next, **nr_prev, **nr_list; /* Doubly linked list and its head */
sip_from_t *nr_aor; /**< AoR for this registration, NULL if none */
sip_contact_t *nr_contact; /**< Our Contact */
sip_contact_t nr_dcontact[1]; /**< Contact in dialog */
sip_via_t *nr_via; /**< Corresponding Via headers */
unsigned long nr_min_expires; /**< Value from 423 negotiation */
/** Status of registration */
unsigned nr_ready:1;
/** Kind of registration.
@@ -222,14 +225,13 @@ static void nua_register_usage_peer_info(nua_dialog_usage_t *du,
/* Interface towards outbound_t */
sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
su_home_t *home,
int in_dialog,
char const *extra_username,
sip_via_t const *v,
char const *transport,
char const *m_param,
...);
static int nua_stack_outbound_features(nua_handle_t *nh, outbound_t *ob);
static int nua_stack_outbound_refresh(nua_handle_t *,
outbound_t *ob);
@@ -431,6 +433,11 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
* the desired transport-layer keepalive interval for stream-based
* transports like TLS and TCP.
*
* As alternative to OPTIONS/STUN keepalives, the client can propose
* a more frequent registration refresh interval with
* NUTAG_M_FEATURES() (e.g. NUTAG_M_FEATURES("expires=120") given as
* parameter to nua_register()).
*
* @sa #nua_r_register, nua_unregister(), #nua_r_unregister,
* #nua_i_register,
* @RFC3261 section 10,
@@ -659,7 +666,6 @@ static int nua_register_client_init(nua_client_request_t *cr,
NH_PISSET(nh, keepalive_stream)
? NH_PGET(nh, keepalive_stream)
: NH_PGET(nh, keepalive));
nua_stack_outbound_features(nh, ob);
if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0)
return nua_client_return(cr, 900, "Cannot set outbound contact", msg);
@@ -676,7 +682,8 @@ int nua_register_client_request(nua_client_request_t *cr,
nua_handle_t *nh = cr->cr_owner;
nua_dialog_usage_t *du = cr->cr_usage;
nua_registration_t *nr;
sip_contact_t *m = NULL, *contacts = sip->sip_contact, *previous = NULL;
sip_contact_t *m, *contacts = sip->sip_contact;
char const *min_expires = NULL;
int unreg;
(void)nh;
@@ -698,48 +705,58 @@ int nua_register_client_request(nua_client_request_t *cr,
if (m == NULL)
nua_client_terminating(cr);
}
if (cr->cr_terminating) {
/* Remove the expire parameters from contacts */
for (m = sip->sip_contact; m; m = m->m_next) {
if (m->m_url->url_type == url_any) {
/* If there is a '*' in contact list, remove everything else */
while (m != sip->sip_contact)
sip_header_remove(msg, sip, (sip_header_t *)sip->sip_contact);
while (m->m_next)
sip_header_remove(msg, sip, (sip_header_t *)m->m_next);
contacts = m;
break;
}
msg_header_remove_param(m->m_common, "expires");
}
}
}
unreg = cr->cr_terminating;
if (du) {
nr = nua_dialog_usage_private(du);
nr = nua_dialog_usage_private(du);
if (nr) {
if (nr->nr_ob) {
outbound_stop_keepalive(nr->nr_ob);
outbound_start_registering(nr->nr_ob);
}
if (nr->nr_by_stack) {
m = nr->nr_contact;
sip_contact_t *m = nr->nr_contact, *previous = NULL;
outbound_get_contacts(nr->nr_ob, &m, &previous);
sip_add_dup(msg, sip, (sip_header_t *)m);
/* previous is an outdated contact generated by stack
* and it is now unregistered */
if (previous)
sip_add_dup(msg, sip, (sip_header_t *)previous);
}
}
for (m = sip->sip_contact; m; m = m->m_next) {
if (m->m_url->url_type == url_any) {
/* If there is a '*' in contact list, remove everything else */
while (m != sip->sip_contact)
sip_header_remove(msg, sip, (sip_header_t *)sip->sip_contact);
while (m->m_next)
sip_header_remove(msg, sip, (sip_header_t *)m->m_next);
contacts = m;
break;
}
if (!m->m_expires)
continue;
if (unreg) {
/* Remove the expire parameters from contacts */
msg_header_remove_param(m->m_common, "expires");
}
else if (nr && nr->nr_min_expires &&
strtoul(m->m_expires, 0, 10) < nr->nr_min_expires) {
if (min_expires == NULL)
min_expires = su_sprintf(msg_home(msg), "expires=%lu",
nr->nr_min_expires);
msg_header_replace_param(msg_home(msg), m->m_common, min_expires);
}
}
return nua_base_client_trequest(cr, msg, sip,
/* m is stack-generated contact */
SIPTAG_CONTACT(m),
/*
* previous is outdated stack-generated contact
* which is now unregistered
*/
SIPTAG_CONTACT(previous),
TAG_IF(unreg, SIPTAG_EXPIRES_STR("0")),
#if 0
TAG_IF(unreg, NTATAG_SIGCOMP_CLOSE(1)),
@@ -772,6 +789,11 @@ static int nua_register_client_check_restart(nua_client_request_t *cr,
/* XXX - report an error? */;
}
if (nr && status == 423) {
if (sip->sip_min_expires)
nr->nr_min_expires = sip->sip_min_expires->me_delta;
}
/* Check for status-specific reasons to retry */
if (nua_base_client_check_restart(cr, status, phrase, sip))
return 1;
@@ -1262,11 +1284,8 @@ int nua_registration_from_via(nua_registration_t **list,
v2[1].v_next = NULL;
#if 1
contact = nua_handle_contact_by_via(nh, home, NULL, v2, protocol, NULL);
#else
contact = sip_contact_create_from_via_with_transport(home, v2, NULL, protocol);
#endif
contact = nua_handle_contact_by_via(nh, home, 0, NULL, v2, protocol, NULL);
v = sip_via_dup(home, v2);
if (!contact || !v) {
@@ -1277,6 +1296,7 @@ int nua_registration_from_via(nua_registration_t **list,
nr->nr_ready = 1, nr->nr_default = 1, nr->nr_public = public;
nr->nr_secure = contact->m_url->url_type == url_sips;
nr->nr_contact = contact;
*nr->nr_dcontact = *contact, nr->nr_dcontact->m_params = NULL;
nr->nr_via = v;
nr->nr_ip4 = host_is_ip4_address(contact->m_url->url_host);
nr->nr_ip6 = !nr->nr_ip4 && host_is_ip6_reference(contact->m_url->url_host);
@@ -1446,7 +1466,10 @@ sip_contact_t const *nua_registration_contact(nua_registration_t const *nr)
return m;
}
return nr->nr_contact;
if (nr->nr_contact)
return nr->nr_dcontact;
else
return NULL;
}
/** Return initial route. */
@@ -1458,7 +1481,7 @@ sip_route_t const *nua_registration_route(nua_registration_t const *nr)
sip_contact_t const *nua_stack_get_contact(nua_registration_t const *nr)
{
nr = nua_registration_by_aor(nr, NULL, NULL, 1);
return nr ? nr->nr_contact : NULL;
return nr && nr->nr_contact ? nr->nr_dcontact : NULL;
}
/** Add a Contact (and Route) header to request */
@@ -1531,23 +1554,51 @@ int nua_registration_add_contact_and_route(nua_handle_t *nh,
return -1;
if (add_contact) {
sip_contact_t const *m = nua_registration_contact(nr);
sip_contact_t const *m = NULL;
char const *m_display;
char const *m_username;
char const *m_params;
url_t const *u;
char const *m_display = NH_PGET(nh, m_display);
char const *m_username = NH_PGET(nh, m_username);
char const *m_params = NH_PGET(nh, m_params);
url_t const *u = m->m_url;
if (nr->nr_by_stack && nr->nr_ob) {
m = outbound_dialog_gruu(nr->nr_ob);
if (m)
return msg_header_add_dup(msg, (msg_pub_t *)sip, (void const *)m);
m = outbound_dialog_contact(nr->nr_ob);
}
if (m == NULL)
m = nr->nr_contact;
if (!m)
return -1;
if (str0cmp(m_params, u->url_params) == 0)
u = m->m_url;
if (NH_PISSET(nh, m_display))
m_display = NH_PGET(nh, m_display);
else
m_display = m->m_display;
if (NH_PISSET(nh, m_username))
m_username = NH_PGET(nh, m_username);
else
m_username = m->m_url->url_user;
if (NH_PISSET(nh, m_params)) {
m_params = NH_PGET(nh, m_params);
if (u->url_params && m_params && strstr(u->url_params, m_params) == 0)
m_params = NULL;
}
else
m_params = NULL;
m = sip_contact_format(msg_home(msg),
"%s<%s:%s%s%s%s%s%s%s%s%s>",
m_display ? m_display :
m->m_display ? m->m_display : "",
m_display ? m_display : "",
u->url_scheme,
m_username ? m_username : "",
m_username ? "@" : "",
@@ -1648,7 +1699,7 @@ int nua_registration_set_contact(nua_handle_t *nh,
if (nr0 && nr0->nr_via) {
char const *tport = nr0->nr_via->v_next ? NULL : nr0->nr_via->v_protocol;
m = nua_handle_contact_by_via(nh, nh->nh_home,
m = nua_handle_contact_by_via(nh, nh->nh_home, 0,
NULL, nr0->nr_via, tport, NULL);
}
}
@@ -1657,6 +1708,7 @@ int nua_registration_set_contact(nua_handle_t *nh,
return -1;
nr->nr_contact = m;
*nr->nr_dcontact = *m, nr->nr_dcontact->m_params = NULL;
nr->nr_ip4 = host_is_ip4_address(m->m_url->url_host);
nr->nr_ip6 = !nr->nr_ip4 && host_is_ip6_reference(m->m_url->url_host);
nr->nr_by_stack = !application_contact;
@@ -1785,6 +1837,7 @@ static int nua_stack_outbound_credentials(nua_handle_t *nh,
/** @internal Generate a @Contact header. */
sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
su_home_t *home,
int in_dialog,
char const *extra_username,
sip_via_t const *v,
char const *transport,
@@ -1868,7 +1921,7 @@ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
su_strlst_append(l, ";comp="), su_strlst_append(l, comp);
s = NH_PGET(nh, m_params);
if (s)
su_strlst_append(l, s[0] == ';' ? "" : ";"), su_strlst_append(l, s);
s[0] == ';' ? "" : su_strlst_append(l, ";"), su_strlst_append(l, s);
su_strlst_append(l, ">");
va_start(va, m_param);
@@ -1882,81 +1935,42 @@ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
va_end(va);
if (!in_dialog) {
s = NH_PGET(nh, m_features);
if (s)
s[0] == ';' ? "" : su_strlst_append(l, ";"), su_strlst_append(l, s);
if (NH_PGET(nh, callee_caps)) {
sip_allow_t const *allow = NH_PGET(nh, allow);
if (allow) {
su_strlst_append(l, ";methods=\"");
if (allow->k_items) {
size_t i;
for (i = 0; allow->k_items[i]; i++) {
su_strlst_append(l, allow->k_items[i]);
if (allow->k_items[i + 1])
su_strlst_append(l, ",");
}
}
su_strlst_append(l, "\"");
}
if (nh->nh_soa) {
char **media = soa_media_features(nh->nh_soa, 0, home);
while (*media) {
if (su_strlst_len(l))
su_strlst_append(l, ";");
su_strlst_append(l, *media++);
}
}
}
}
m = sip_contact_make(home, su_strlst_join(l, su_strlst_home(l), ""));
su_strlst_destroy(l);
return m;
}
/** @internal Return a string describing our features. */
static char *nua_handle_features(nua_handle_t *nh)
{
char *retval = NULL;
su_strlst_t *l = su_strlst_create(NULL);
su_home_t *home = su_strlst_home(l);
if (!l)
return NULL;
if (NH_PGET(nh, m_features)) {
char const *m_features = NH_PGET(nh, m_features);
if (m_features[0] != ';')
su_strlst_append(l, ";");
su_strlst_append(l, m_features);
}
if (NH_PGET(nh, callee_caps)) {
sip_allow_t const *allow = NH_PGET(nh, allow);
if (allow) {
/* Skip ";" if this is first one */
su_strlst_append(l, ";methods=\"" + (su_strlst_len(l) == 0));
if (allow->k_items) {
size_t i;
for (i = 0; allow->k_items[i]; i++) {
su_strlst_append(l, allow->k_items[i]);
if (allow->k_items[i + 1])
su_strlst_append(l, ",");
}
}
su_strlst_append(l, "\"");
}
if (nh->nh_soa) {
char **media = soa_media_features(nh->nh_soa, 0, home);
while (*media) {
if (su_strlst_len(l))
su_strlst_append(l, ";");
su_strlst_append(l, *media++);
}
}
}
if (su_strlst_len(l))
retval = su_strlst_join(l, nh->nh_home, "");
su_strlst_destroy(l);
return retval;
}
static int nua_stack_outbound_features(nua_handle_t *nh, outbound_t *ob)
{
char *features;
int retval;
if (!nh)
return -1;
if (!ob)
return 0;
features = nua_handle_features(nh);
retval = outbound_set_features(ob, features);
su_free(nh->nh_home, features);
return retval;
}
@@ -299,10 +299,7 @@ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg,
if (tags) {
tagi_t *t = e->e_tags, *t_end = (tagi_t *)((char *)t + len);
void *b = t_end;
#ifndef NDEBUG
void *end = (char *)b + xtra;
#endif
void *b = t_end, *end = (char *)b + xtra;
t = tl_dup(t, tags, &b); p = b;
assert(t == t_end); assert(b == end); (void)end;
+30 -60
View File
@@ -117,7 +117,6 @@ struct outbound {
char const *ob_instance; /**< Our instance ID */
int32_t ob_reg_id; /**< Flow-id */
char const *ob_features; /**< Feature parameters for rcontact */
sip_contact_t *ob_rcontact; /**< Our contact */
sip_contact_t *ob_dcontact; /**< Contact for dialogs */
sip_contact_t *ob_previous; /**< Stale contact */
@@ -327,20 +326,6 @@ int outbound_set_options(outbound_t *ob,
return 0;
}
/** Set the feature string (added to the Contact header when registering). */
int outbound_set_features(outbound_t *ob, char *features)
{
char *old_features = (char *)ob->ob_features;
char *new_features = su_strdup(ob->ob_home, features);
if (features && !new_features)
return -1;
ob->ob_features = new_features;
su_free(ob->ob_home, old_features);
return 0;
}
/* ---------------------------------------------------------------------- */
/** Obtain contacts for REGISTER */
@@ -698,21 +683,32 @@ static int create_keepalive_message(outbound_t *ob, sip_t const *regsip)
{
msg_t *msg = nta_msg_create(ob->ob_nta, MSG_FLG_COMPACT), *previous;
sip_t *osip = sip_object(msg);
sip_accept_contact_t *ac;
char const *p1 = ob->ob_instance;
char const *p2 = ob->ob_features;
sip_contact_t *m = ob->ob_rcontact;
unsigned d = ob->ob_keepalive.interval;
assert(regsip); assert(regsip->sip_request);
if (p1 || p2) {
ac = sip_accept_contact_format(msg_home(msg), "*;require;explicit;%s%s%s",
p1 ? p1 : "",
p2 && p2 ? ";" : "",
p2 ? p2 : "");
msg_header_insert(msg, NULL, (void *)ac);
if (m && m->m_params) {
sip_accept_contact_t *ac;
size_t i;
int features = 0;
ac = sip_accept_contact_make(msg_home(msg), "*;require;explicit");
for (i = 0; m->m_params[i]; i++) {
char const *s = m->m_params[i];
if (!sip_is_callerpref(s))
continue;
features++;
s = su_strdup(msg_home(msg), s);
msg_header_add_param(msg_home(msg), ac->cp_common, s);
}
if (features)
msg_header_insert(msg, NULL, (void *)ac);
else
msg_header_free(msg_home(msg), (void *)ac);
}
if (0 >
@@ -1008,46 +1004,16 @@ int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via)
v = v0; *v0 = *via; v0->v_next = NULL;
dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1,
NULL, v, v->v_protocol, NULL);
if (ob->ob_instance && ob->ob_reg_id != 0)
snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);
rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0,
NULL, v, v->v_protocol,
ob->ob_features ? ob->ob_features : "",
ob->ob_instance, reg_id_param, NULL);
#if 0
char *uri;
/* uri contains < > */
uri = sip_contact_string_from_via(NULL, via, NULL, v->v_protocol);
dcontact = sip_contact_make(home, uri);
if (ob->ob_instance) {
char reg_id[20];
if (ob->ob_instance && ob->ob_reg_id)
snprintf(reg_id, sizeof reg_id, ";reg-id=%u", ob->ob_reg_id);
else
strcpy(reg_id, "");
rcontact = sip_contact_format(home, "%s;%s%s%s%s",
uri, ob->ob_instance, reg_id,
ob->ob_features ? ";" : "",
ob->ob_features ? ob->ob_features : "");
}
else if (ob->ob_features)
rcontact = sip_contact_format(home, "%s;%s", uri, ob->ob_features);
else
rcontact = dcontact;
free(uri);
#endif
v = sip_via_dup(home, v);
if (!rcontact || !dcontact || !v) {
@@ -1139,7 +1105,7 @@ int outbound_set_contact(outbound_t *ob,
char const *tport = !v->v_next ? v->v_protocol : NULL;
char reg_id_param[20];
dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1,
NULL, v, tport, NULL);
if (!dcontact)
return -1;
@@ -1147,9 +1113,8 @@ int outbound_set_contact(outbound_t *ob,
if (ob->ob_instance && ob->ob_reg_id != 0)
snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);
rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0,
NULL, v, v->v_protocol,
ob->ob_features ? ob->ob_features : "",
ob->ob_instance, reg_id_param, NULL);
if (!rcontact)
return -1;
@@ -1195,6 +1160,11 @@ sip_contact_t const *outbound_dialog_contact(outbound_t const *ob)
return ob->ob_dcontact;
}
sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob)
{
return ob ? ob->ob_gruu : NULL;
}
/* ---------------------------------------------------------------------- */
@@ -70,8 +70,6 @@ int outbound_set_options(outbound_t *ob,
unsigned dgram_interval,
unsigned stream_interval);
int outbound_set_features(outbound_t *ob, char *features);
int outbound_get_contacts(outbound_t *ob,
sip_contact_t **return_current_contact,
sip_contact_t **return_previous_contact);
@@ -98,6 +96,8 @@ int outbound_set_contact(outbound_t *ob,
sip_contact_t const *outbound_dialog_contact(outbound_t const *ob);
sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob);
int outbound_gruuize(outbound_t *ob, sip_t const *sip);
void outbound_start_keepalive(outbound_t *ob,
@@ -118,6 +118,7 @@ struct outbound_owner_vtable
int oo_size;
sip_contact_t *(*oo_contact)(outbound_owner_t *,
su_home_t *home,
int used_in_dialog,
char const *extra_username,
sip_via_t const *v,
char const *transport,
@@ -1074,7 +1074,7 @@ SOFIAPUBVAR tag_typedef_t nutag_registrar_ref;
*
* The outbound option string can specify how the NAT traversal is handled.
* The option tokens are as follows:
* - "gruuize": try to generate a GRUU
* - "gruuize": try to generate a GRUU contact from REGISTER response
* - "outbound": use SIP outbound extension (off by default)
* - "validate": validate registration behind a NAT by sending OPTIONS to self
* - "natify": try to traverse NAT
@@ -1084,6 +1084,10 @@ SOFIAPUBVAR tag_typedef_t nutag_registrar_ref;
* An option token with "no-" or "not-" prefix turns the option off. For
* example, if you want to try to traverse NATs but not to use OPTIONS
* keepalive, use NUTAG_OUTBOUND("natify no-options-keepalive").
*
* An empty string can be passed to let the stack choose the
* default values for outbound usage (in the 1.12.5 release, the
* defaults are: "gruuize no-outbound validate use-port options-keepalive").
*
* @note
* Options string is used so that no new tags need to be added when the
@@ -1207,7 +1211,7 @@ SOFIAPUBVAR tag_typedef_t nutag_outbound_set4_ref;
* nua_create()
*
* @par Parameter type
* msg_mclass_t *
* msg_mclass_t const *
*
* @par Values
* Pointer to an extended SIP parser.
@@ -1243,6 +1247,9 @@ SOFIAPUBVAR tag_typedef_t nutag_auth;
SOFIAPUBVAR tag_typedef_t nutag_auth_ref;
/** Keepalive interval in milliseconds.
*
* This setting applies to OPTIONS/STUN keepalives. See documentation
* for nua_register() for more detailed information.
*
* @par Used with
* nua_register() \n
@@ -1268,6 +1275,8 @@ SOFIAPUBVAR tag_typedef_t nutag_keepalive;
SOFIAPUBVAR tag_typedef_t nutag_keepalive_ref;
/** Transport-level keepalive interval for streams.
*
* See documentation for nua_register() for more detailed information.
*
* @par Used with
* nua_register() \n
@@ -478,6 +478,47 @@ int test_basic_call_2(struct context *ctx)
TEST_1(nua_handle_has_active_call(b_call->nh));
TEST_1(!nua_handle_has_call_on_hold(b_call->nh));
/* Send a NOTIFY from B to A */
if (print_headings)
printf("TEST NUA-3.2.2: send a NOTIFY within a dialog\n");
/* Make A to accept NOTIFY */
nua_set_params(a->nua, NUTAG_APPL_METHOD("NOTIFY"), TAG_END());
run_a_until(ctx, nua_r_set_params, until_final_response);
NOTIFY(b, b_call, b_call->nh,
NUTAG_NEWSUB(1),
SIPTAG_SUBJECT_STR("NUA-3.2.2"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: no"),
TAG_END());
run_ab_until(ctx, -1, accept_notify, -1, save_until_final_response);
/* Notifier events: nua_r_notify */
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
TEST_1(tl_find(e->data->e_tags, nutag_substate));
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value,
nua_substate_terminated);
/* watcher events: nua_i_notify */
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
TEST_1(tl_find(e->data->e_tags, nutag_substate));
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value,
nua_substate_terminated);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-3.2.2: PASSED\n");
INFO(b, b_call, b_call->nh, TAG_END());
BYE(b, b_call, b_call->nh, TAG_END());
INFO(b, b_call, b_call->nh, TAG_END());
@@ -92,6 +92,9 @@ static char const options_usage[] =
" --no-alarm don't ask for guard ALARM\n"
" -p uri specify uri of outbound proxy (implies --no-proxy)\n"
" --proxy-tests run tests involving proxy, too\n"
#if SU_HAVE_OSX_CF_API /* If compiled with CoreFoundation events */
" --osx-runloop use OSX CoreFoundation runloop instead of poll() loop\n"
#endif
" -k do not exit after first error\n"
;
@@ -216,6 +216,8 @@ int until_terminated(CONDITION_PARAMS);
int until_ready(CONDITION_PARAMS);
int accept_call(CONDITION_PARAMS);
int accept_notify(CONDITION_PARAMS);
void a_callback(nua_event_t event,
int status, char const *phrase,
nua_t *nua, struct context *ctx,
@@ -133,6 +133,8 @@ int test_register_to_proxy(struct context *ctx)
NUTAG_KEEPALIVE(1000),
NUTAG_M_DISPLAY("A&A"),
NUTAG_M_USERNAME("a"),
NUTAG_M_PARAMS("foo=bar"),
NUTAG_M_FEATURES("q=0.9"),
SIPTAG_CSEQ(cseq),
TAG_END());
run_a_until(ctx, -1, save_until_final_response);
@@ -161,6 +163,8 @@ int test_register_to_proxy(struct context *ctx)
/* VC does not dig \" with TEST_S() */
TEST_S(sip->sip_contact->m_display, expect_m_display); }
TEST_S(sip->sip_contact->m_url->url_user, "a");
TEST_1(strstr(sip->sip_contact->m_url->url_params, "foo=bar"));
TEST_S(sip->sip_contact->m_q, "0.9");
TEST(sip->sip_cseq->cs_seq, 14);
if (ctx->nat) {
@@ -222,8 +226,12 @@ int test_register_to_proxy(struct context *ctx)
TEST_1(c_reg->nh = nua_handle(c->nua, c_reg, TAG_END()));
REGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to),
NUTAG_OUTBOUND(NULL),
NUTAG_M_DISPLAY("C"),
NUTAG_M_USERNAME("c"),
NUTAG_M_PARAMS("c=1"),
NUTAG_M_FEATURES("q=0.987;expires=5"),
NUTAG_CALLEE_CAPS(1),
SIPTAG_EXPIRES_STR("5"), /* Test 423 negotiation */
TAG_END());
run_abc_until(ctx, -1, save_events, -1, save_events,
@@ -254,6 +262,9 @@ int test_register_to_proxy(struct context *ctx)
TEST_1(sip->sip_contact);
TEST_S(sip->sip_contact->m_display, "C");
TEST_S(sip->sip_contact->m_url->url_user, "c");
TEST_1(strstr(sip->sip_contact->m_url->url_params, "c=1"));
TEST_S(sip->sip_contact->m_q, "0.987");
TEST_1(msg_header_find_param(sip->sip_contact->m_common, "methods="));
TEST_1(!e->next);
free_events_in_list(ctx, c->events);
@@ -688,6 +699,7 @@ int test_unregister(struct context *ctx)
UNREGISTER(c, c->call, c->call->nh, SIPTAG_TO(c->to),
NUTAG_M_DISPLAY("C"),
NUTAG_M_USERNAME("c"),
NUTAG_M_PARAMS("c=1"),
TAG_END());
run_c_until(ctx, -1, save_until_final_response);
@@ -899,7 +899,7 @@ sip_addr_make_url(su_home_t *home, msg_hclass_t *hc, url_string_t const *us)
sip_header_t *h;
n = url_xtra(us->us_url);
h = sip_header_alloc(home, sip_to_class, n);
h = sip_header_alloc(home, hc, n);
if (h) {
sip_addr_t *a = h->sh_to;
@@ -60,9 +60,9 @@ char const sip_parser_version[] = VERSION;
char const sip_version_2_0[] = "SIP/2.0";
/** Default message class */
extern msg_mclass_t sip_mclass[];
extern msg_mclass_t const sip_mclass[];
msg_mclass_t *sip_default_mclass(void)
msg_mclass_t const *sip_default_mclass(void)
{
return sip_mclass;
}
@@ -58,7 +58,7 @@
SOFIA_BEGIN_DECLS
/** Return built-in SIP parser object. */
SOFIAPUBFUN msg_mclass_t *sip_default_mclass(void);
SOFIAPUBFUN msg_mclass_t const *sip_default_mclass(void);
/** Check that sip_t is a SIP structure (not RTSP or HTTP). @HIDE */
#define sip_is_sip(sip) ((sip) && (sip)->sip_ident == SIP_PROTOCOL_TAG)
@@ -65,7 +65,7 @@ int diff(const char *olds, const char *news, int *linep, int *pos)
return *o != *n;
}
int test_msg_class(msg_mclass_t *mc)
int test_msg_class(msg_mclass_t const *mc)
{
int i, j, N;
@@ -159,7 +159,7 @@ int main(int argc, char *argv[])
int m, tcp;
sip_t *sip;
int exitcode = 0;
msg_mclass_t *sip_mclass = sip_default_mclass();
msg_mclass_t const *sip_mclass = sip_default_mclass();
msg_t *msg = msg_create(sip_mclass, MSG_FLG_EXTRACT_COPY);
msg_iovec_t iovec[1];
@@ -412,7 +412,12 @@ int test_basic(void)
TEST_1(sip_from_tag(home, f, "tag=jxahudsf") == 0);
su_free(home, f);
TEST_1(f = sip_from_create(home, (void *)"<sip:joe@bar;tag=bar> (joe)"));
TEST_1(sip_is_from((sip_header_t*)f));
su_free(home, f);
TEST_1(t = sip_to_create(home, (void *)"<sip:joe@bar;tag=bar> (joe)"));
TEST_1(sip_is_to((sip_header_t*)f));
TEST_1(sip_to_tag(home, t, "tag=jxahudsf") == 0);
TEST_S(t->a_tag, "jxahudsf");
TEST(msg_header_replace_param(home, t->a_common, "tag=bar"), 1);
@@ -180,7 +180,7 @@ char *lastpart(char *path)
return path;
}
msg_mclass_t *mclass = NULL;
msg_mclass_t const *mclass = NULL;
int validate_file(int fd, char const *name, context_t *ctx);
int validate_dump(char *, off_t, context_t *ctx);
@@ -55,9 +55,11 @@ if netstat --ip >/dev/null 2>&1 ; then
done
fi
# No named, no fun
type -p named >/dev/null || {
echo test_sresolv: there is no BIND named installed, skipping
# No BIND 9, no fun
{ type -p named >/dev/null &&
named -v | grep -q BIND.*9
} || {
echo test_sresolv: there is no BIND 9 named in you path, skipping
exit 77
}
@@ -64,7 +64,6 @@ typedef unsigned _int32 uint32_t;
#include <sofia-resolv/sres_async.h>
#include <sofia-resolv/sres_record.h>
#include <sofia-sip/su.h>
#include <sofia-sip/su_alloc.h>
#include <assert.h>
@@ -120,6 +119,84 @@ static void test_answer_multi(sres_context_t *ctx, sres_query_t *query,
static int tstflags = 0;
#if HAVE_WINSOCK2_H
/* Posix send() */
static inline
ssize_t sres_send(sres_socket_t s, void *b, size_t length, int flags)
{
if (length > INT_MAX)
length = INT_MAX;
return (ssize_t)send(s, b, (int)length, flags);
}
static inline
ssize_t sres_sendto(sres_socket_t s, void *b, size_t length, int flags,
struct sockaddr const *sa, socklen_t salen)
{
if (length > INT_MAX)
length = INT_MAX;
return (ssize_t)sendto(s, b, (int)length, flags, (void *)sa, (int)salen);
}
/* Posix recvfrom() */
static inline
ssize_t sres_recvfrom(sres_socket_t s, void *buffer, size_t length, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
int retval, ilen;
if (fromlen)
ilen = *fromlen;
if (length > INT_MAX)
length = INT_MAX;
retval = recvfrom(s, buffer, (int)length, flags,
(void *)from, fromlen ? &ilen : NULL);
if (fromlen)
*fromlen = ilen;
return (ssize_t)retval;
}
static sres_socket_t sres_socket(int af, int socktype, int protocol)
{
return socket(af, socktype, protocol);
}
static inline
int sres_close(sres_socket_t s)
{
return closesocket(s);
}
#if !defined(IPPROTO_IPV6)
#if HAVE_SIN6
#include <tpipv6.h>
#else
#if !defined(__MINGW32__)
struct sockaddr_storage {
short ss_family;
char ss_pad[126];
};
#endif
#endif
#endif
#else
#define sres_send(s,b,len,flags) send((s),(b),(len),(flags))
#define sres_sendto(s,b,len,flags,a,alen) \
sendto((s),(b),(len),(flags),(a),(alen))
#define sres_recvfrom(s,b,len,flags,a,alen) \
recvfrom((s),(b),(len),(flags),(a),(alen))
#define sres_close(s) close((s))
#define SOCKET_ERROR (-1)
#define INVALID_SOCKET ((sres_socket_t)-1)
#define sres_socket(x,y,z) socket((x),(y),(z))
#endif
#if 1
#if HAVE_POLL && 0
@@ -145,7 +222,7 @@ static
int test_socket(sres_context_t *ctx)
{
int af;
su_sockeet_t s1, s2, s3, s4;
sres_socket_t s1, s2, s3, s4;
struct sockaddr_storage a[1];
struct sockaddr_storage a1[1], a2[1], a3[1], a4[1];
struct sockaddr_in *sin = (void *)a;
@@ -160,10 +237,10 @@ int test_socket(sres_context_t *ctx)
af = AF_INET;
for (;;) {
TEST_1((s1 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s2 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s3 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s4 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s1 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s2 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s3 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s4 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1(setblocking(s1, 0) == 0);
TEST_1(setblocking(s2, 0) == 0);
@@ -212,13 +289,13 @@ int test_socket(sres_context_t *ctx)
TEST(connect(s2, sa4, a4len), 0);
TEST(getsockname(s2, (struct sockaddr *)a2, &a2len), 0);
TEST(sendto(s1, "foo", 3, 0, sa4, a4len), 3);
TEST(recvfrom(s4, buf, sizeof buf, 0, sa, &alen), 3);
TEST(sendto(s4, "bar", 3, 0, sa, alen), 3);
TEST(recvfrom(s2, buf, sizeof buf, 0, sa, &alen), -1);
TEST(recvfrom(s1, buf, sizeof buf, 0, sa, &alen), 3);
TEST(sres_sendto(s1, "foo", 3, 0, sa4, a4len), 3);
TEST(sres_recvfrom(s4, buf, sizeof buf, 0, sa, &alen), 3);
TEST(sres_sendto(s4, "bar", 3, 0, sa, alen), 3);
TEST(sres_recvfrom(s2, buf, sizeof buf, 0, sa, &alen), -1);
TEST(sres_recvfrom(s1, buf, sizeof buf, 0, sa, &alen), 3);
su_close(s1), su_close(s2), su_close(s3), su_close(s4);
sres_close(s1), sres_close(s2), sres_close(s3), sres_close(s4);
break;
}
@@ -1428,7 +1505,7 @@ int sink_deinit(sres_context_t *ctx)
if (ctx->sinkidx)
su_root_deregister(ctx->root, ctx->sinkidx);
ctx->sinkidx = 0;
su_close(ctx->sink), ctx->sink = INVALID_SOCKET;
sres_close(ctx->sink), ctx->sink = INVALID_SOCKET;
END();
}
@@ -1453,7 +1530,7 @@ int test_timeout(sres_context_t *ctx)
result = sres_cached_answers(res, sres_type_a, domain);
#if 0
#if 0 /* Currently, we do not create error records */
TEST_1(result); TEST_1(result[0] != NULL);
rr_soa = result[0]->sr_soa;
@@ -1464,7 +1541,6 @@ int test_timeout(sres_context_t *ctx)
sres_free_answers(res, result);
#else
/* Currently, we do not create error records */
TEST_1(result == NULL);
#endif
@@ -1625,7 +1701,8 @@ int test_net(sres_context_t *ctx)
struct sockaddr *sa = (void *)ss;
socklen_t salen = sizeof ss;
char *bin;
size_t i, n, binlen;
size_t i, binlen;
ssize_t n;
char const *domain = "example.com";
char query[512];
@@ -1647,14 +1724,14 @@ int test_net(sres_context_t *ctx)
/* We got an error => make new query */
TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */
sres_type_naptr, domain));
TEST_1((n = recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1);
TEST_1((n = sres_recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1);
memcpy(bin, query, 2); /* Copy ID */
}
if (i != 1)
bin[i] ^= 0xff;
else
bin[3] ^= SRES_FORMAT_ERR; /* format error -> EDNS0 failure */
n = su_sendto(c, bin, binlen, 0, sa, salen);
n = sres_sendto(c, bin, binlen, 0, sa, salen);
if (i != 1)
bin[i] ^= 0xff;
else
@@ -1675,10 +1752,10 @@ int test_net(sres_context_t *ctx)
/* We got an error => make new query */
TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */
sres_type_naptr, domain));
TEST_1((n = su_recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1);
TEST_1((n = sres_recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1);
memcpy(bin, query, 2); /* Copy ID */
}
n = su_sendto(c, bin, i, 0, sa, salen);
n = sres_sendto(c, bin, i, 0, sa, salen);
if (n == -1)
perror("sendto");
while (!poll_sockets(ctx))
@@ -79,7 +79,7 @@ libsu_la_SOURCES = \
su_time.c su_time0.c \
su_wait.c su_root.c su_timer.c \
su_port.c su_port.h \
su_base_port.c su_pthread_port.c \
su_base_port.c su_pthread_port.c su_socket_port.c \
su_poll_port.c su_epoll_port.c su_select_port.c \
su_localinfo.c \
su_os_nw.c \
@@ -94,6 +94,7 @@ EXTRA_libsu_la_SOURCES = \
inet_ntop.c inet_pton.c poll.c getopt.c \
su_tag_ref.c su_win32_port.c
libsu_la_CFLAGS = $(AM_CFLAGS) $(SOFIA_CFLAGS)
libsu_la_LIBADD = $(REPLACE_LIBADD)
libsu_la_DEPENDENCIES = $(REPLACE_LIBADD)
+166 -171
View File
@@ -1,13 +1,20 @@
/* Copyright (C) 1994,1996,1997,1998,1999,2001,2002
Free Software Foundation, Inc.
This file is part of the GNU C Library.
/* This file is part of the Sofia-SIP package.
The GNU C Library is free software; you can redistribute it and/or
Copyright (C) 2005 Nokia Corporation.
Contact: Pekka Pessi <pekka.pessi@nokia.com>
This file is originally from GNU C library.
Copyright (C) 1994,1996,1997,1998,1999,2001,2002
Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
@@ -19,237 +26,225 @@
#include "config.h"
#if !HAVE_POLL && HAVE_SELECT && HAVE_POLL_PORT
#if HAVE_SELECT
#include "sofia-sip/su.h"
//extern __typeof(poll) __libc_poll;
#if 1
#include <alloca.h>
#include <string.h>
#include "sofia-sip/su_wait.h"
#ifndef __NFDBITS
#define NBBY 8 /* bits in a byte */
#define __NFDBITS (sizeof(__int32_t) * NBBY) /* bits per mask */
#endif
#undef NBBY
#undef NFDBITS
#undef FDSETSIZE
#undef roundup
#define NBBY 8 /* bits in a byte */
#define NFDBITS (sizeof(long) * NBBY) /* bits per mask */
#undef howmany
#define FDSETSIZE(n) (((n) + NFDBITS - 1) / NFDBITS * (NFDBITS / NBBY))
#define roundup(n, x) (((n) + (x) - 1) / (x) * (x))
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y)) * sizeof(uint32_t)
#endif
/* Emulated poll() using select().
//libc_hidden_proto(memcpy)
//libc_hidden_proto(memset)
//libc_hidden_proto(getdtablesize)
//libc_hidden_proto(select)
This is used by su_wait().
/* uClinux 2.0 doesn't have poll, emulate it using select */
/* Poll the file descriptors described by the NFDS structures starting at
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
an event to occur; if TIMEOUT is -1, block until an event occurs.
Returns the number of file descriptors with events, zero if timed out,
or -1 for errors. */
Poll the file descriptors described by the NFDS structures starting at
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
an event to occur; if TIMEOUT is -1, block until an event occurs.
Returns the number of file descriptors with events, zero if timed out,
or -1 for errors. */
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
struct timeval tv;
#if HAVE_ALLOCA_H
static int max_fd_size;
int bytes;
fd_set *rset, *wset, *xset;
#else
fd_set rset[1], wset[1], xset[1];
#endif
struct pollfd *f;
int ready;
int maxfd = 0;
struct timeval tv;
struct pollfd *f;
int ready;
int maxfd = 0;
#if HAVE_ALLOCA_H
if (!max_fd_size)
max_fd_size = getdtablesize ();
static int max_fd_size;
int bytes;
fd_set *rset, *wset, *xset;
bytes = howmany (max_fd_size, __NFDBITS);
if (!max_fd_size)
max_fd_size = getdtablesize ();
rset = alloca (bytes);
wset = alloca (bytes);
xset = alloca (bytes);
bytes = FDSETSIZE (max_fd_size);
/* We can't call FD_ZERO, since FD_ZERO only works with sets
of exactly __FD_SETSIZE size. */
memset (rset, 0, bytes);
memset (wset, 0, bytes);
memset (xset, 0, bytes);
rset = alloca (bytes);
wset = alloca (bytes);
xset = alloca (bytes);
/* We can't call FD_ZERO, since FD_ZERO only works with sets
of exactly __FD_SETSIZE size. */
memset (rset, 0, bytes);
memset (wset, 0, bytes);
memset (xset, 0, bytes);
#else
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
fd_set rset[1], wset[1], xset[1];
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
#endif
for (f = fds; f < &fds[nfds]; ++f)
for (f = fds; f < &fds[nfds]; ++f)
{
f->revents = 0;
if (f->fd >= 0)
f->revents = 0;
if (f->fd >= 0)
{
#if HAVE_ALLOCA_H
if (f->fd >= max_fd_size)
if (f->fd >= max_fd_size)
{
/* The user provides a file descriptor number which is higher
than the maximum we got from the `getdtablesize' call.
Maybe this is ok so enlarge the arrays. */
fd_set *nrset, *nwset, *nxset;
int nbytes;
/* The user provides a file descriptor number which is higher
than the maximum we got from the `getdtablesize' call.
Maybe this is ok so enlarge the arrays. */
fd_set *nrset, *nwset, *nxset;
int nbytes;
max_fd_size = roundup (f->fd, __NFDBITS);
nbytes = howmany (max_fd_size, __NFDBITS);
max_fd_size = roundup (f->fd, NFDBITS);
nbytes = FDSETSIZE (max_fd_size);
nrset = alloca (nbytes);
nwset = alloca (nbytes);
nxset = alloca (nbytes);
nrset = alloca (nbytes);
nwset = alloca (nbytes);
nxset = alloca (nbytes);
memset ((char *) nrset + bytes, 0, nbytes - bytes);
memset ((char *) nwset + bytes, 0, nbytes - bytes);
memset ((char *) nxset + bytes, 0, nbytes - bytes);
memset ((char *) nrset + bytes, 0, nbytes - bytes);
memset ((char *) nwset + bytes, 0, nbytes - bytes);
memset ((char *) nxset + bytes, 0, nbytes - bytes);
rset = memcpy (nrset, rset, bytes);
wset = memcpy (nwset, wset, bytes);
xset = memcpy (nxset, xset, bytes);
rset = memcpy (nrset, rset, bytes);
wset = memcpy (nwset, wset, bytes);
xset = memcpy (nxset, xset, bytes);
bytes = nbytes;
bytes = nbytes;
}
#else
if (f->fd >= FD_SETSIZE) {
errno = EBADF;
return -1;
}
if (f->fd >= FD_SETSIZE) {
errno = EBADF;
return -1;
}
#endif /* HAVE_ALLOCA_H */
if (f->events & POLLIN)
FD_SET (f->fd, rset);
if (f->events & POLLOUT)
FD_SET (f->fd, wset);
if (f->events & POLLPRI)
FD_SET (f->fd, xset);
if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
maxfd = f->fd;
if (f->events & POLLIN)
FD_SET (f->fd, rset);
if (f->events & POLLOUT)
FD_SET (f->fd, wset);
if (f->events & POLLPRI)
FD_SET (f->fd, xset);
if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
maxfd = f->fd;
}
}
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
while (1)
while (1)
{
ready = select (maxfd + 1, rset, wset, xset,
timeout == -1 ? NULL : &tv);
ready = select (maxfd + 1, rset, wset, xset,
timeout == -1 ? NULL : &tv);
/* It might be that one or more of the file descriptors is invalid.
We now try to find and mark them and then try again. */
if (ready == -1 && errno == EBADF)
/* It might be that one or more of the file descriptors is invalid.
We now try to find and mark them and then try again. */
if (ready == -1 && errno == EBADF)
{
struct timeval sngl_tv;
struct timeval sngl_tv;
#if HAVE_ALLOCA_H
fd_set *sngl_rset = alloca (bytes);
fd_set *sngl_wset = alloca (bytes);
fd_set *sngl_xset = alloca (bytes);
fd_set *sngl_rset = alloca (bytes);
fd_set *sngl_wset = alloca (bytes);
fd_set *sngl_xset = alloca (bytes);
/* Clear the original set. */
memset (rset, 0, bytes);
memset (wset, 0, bytes);
memset (xset, 0, bytes);
/* Clear the original set. */
memset (rset, 0, bytes);
memset (wset, 0, bytes);
memset (xset, 0, bytes);
#else
fd_set sngl_rset[1];
fd_set sngl_wset[1];
fd_set sngl_xset[1];
fd_set sngl_rset[1];
fd_set sngl_wset[1];
fd_set sngl_xset[1];
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
#endif
/* This means we don't wait for input. */
sngl_tv.tv_sec = 0;
sngl_tv.tv_usec = 0;
/* This means we don't wait for input. */
sngl_tv.tv_sec = 0;
sngl_tv.tv_usec = 0;
maxfd = -1;
maxfd = -1;
/* Reset the return value. */
ready = 0;
/* Reset the return value. */
ready = 0;
for (f = fds; f < &fds[nfds]; ++f)
if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
&& (f->revents & POLLNVAL) == 0)
{
int n;
for (f = fds; f < &fds[nfds]; ++f)
if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
&& (f->revents & POLLNVAL) == 0)
{
int n;
#if HAVE_ALLOCA_H
memset (sngl_rset, 0, bytes);
memset (sngl_wset, 0, bytes);
memset (sngl_xset, 0, bytes);
memset (sngl_rset, 0, bytes);
memset (sngl_wset, 0, bytes);
memset (sngl_xset, 0, bytes);
#else
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
#endif
if (f->events & POLLIN)
FD_SET (f->fd, sngl_rset);
if (f->events & POLLOUT)
FD_SET (f->fd, sngl_wset);
if (f->events & POLLPRI)
FD_SET (f->fd, sngl_xset);
if (f->events & POLLIN)
FD_SET (f->fd, sngl_rset);
if (f->events & POLLOUT)
FD_SET (f->fd, sngl_wset);
if (f->events & POLLPRI)
FD_SET (f->fd, sngl_xset);
n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
&sngl_tv);
if (n != -1)
{
/* This descriptor is ok. */
if (f->events & POLLIN)
FD_SET (f->fd, rset);
if (f->events & POLLOUT)
FD_SET (f->fd, wset);
if (f->events & POLLPRI)
FD_SET (f->fd, xset);
if (f->fd > maxfd)
maxfd = f->fd;
if (n > 0)
/* Count it as being available. */
++ready;
}
else if (errno == EBADF)
f->revents |= POLLNVAL;
}
/* Try again. */
continue;
if (n != -1)
{
/* This descriptor is ok. */
if (f->events & POLLIN)
FD_SET (f->fd, rset);
if (f->events & POLLOUT)
FD_SET (f->fd, wset);
if (f->events & POLLPRI)
FD_SET (f->fd, xset);
if (f->fd > maxfd)
maxfd = f->fd;
if (n > 0)
/* Count it as being available. */
++ready;
}
else if (errno == EBADF)
f->revents |= POLLNVAL;
}
/* Try again. */
continue;
}
break;
break;
}
if (ready > 0)
for (f = fds; f < &fds[nfds]; ++f)
{
if (f->fd >= 0)
{
if (FD_ISSET (f->fd, rset))
f->revents |= POLLIN;
if (FD_ISSET (f->fd, wset))
f->revents |= POLLOUT;
if (FD_ISSET (f->fd, xset))
f->revents |= POLLPRI;
}
}
if (ready > 0)
for (f = fds; f < &fds[nfds]; ++f)
{
if (f->fd >= 0)
{
if (FD_ISSET (f->fd, rset))
f->revents |= POLLIN;
if (FD_ISSET (f->fd, wset))
f->revents |= POLLOUT;
if (FD_ISSET (f->fd, xset))
f->revents |= POLLPRI;
}
}
return ready;
return ready;
}
#endif
#endif
+19 -4
View File
@@ -2,18 +2,33 @@
rc=0
run=no
for SU_PORT in select epoll poll ; do
export SU_PORT
grep -q -i '^#define have_'$SU_PORT ../../config.h ||
continue
run=yes
if $VALGRIND ./test_su ; then
echo PASS: multithread test_su
echo PASS: multithread test_su with $SU_PORT
else
echo FAIL: multithread test_su failed
echo FAIL: multithread test_su with $SU_PORT failed
rc=1
fi
if $VALGRIND ./test_su -s ; then
echo PASS: singlethread test_su
echo PASS: singlethread test_su with $SU_PORT
else
echo FAIL: singlethread test_su failed
echo FAIL: singlethread test_su with $SU_PORT failed
rc=1
fi
done
test $run = no && exit 77
exit $rc
@@ -512,6 +512,31 @@ SOFIAPUBFUN void su_clone_wait(su_root_t *root, su_clone_r clone);
SOFIAPUBFUN int su_clone_pause(su_clone_r);
SOFIAPUBFUN int su_clone_resume(su_clone_r);
/* ---------------------------------------------------------------------- */
/* Different su_root_t implementations */
typedef su_port_t *su_port_create_f(void);
typedef int su_clone_start_f(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit);
SOFIAPUBFUN void su_port_prefer(su_port_create_f *f, su_clone_start_f *);
SOFIAPUBFUN su_port_create_f su_default_port_create;
SOFIAPUBFUN su_port_create_f su_epoll_port_create;
SOFIAPUBFUN su_port_create_f su_poll_port_create;
SOFIAPUBFUN su_port_create_f su_wsaevent_port_create;
SOFIAPUBFUN su_port_create_f su_select_port_create;
SOFIAPUBFUN su_clone_start_f su_default_clone_start;
SOFIAPUBFUN su_clone_start_f su_epoll_clone_start;
SOFIAPUBFUN su_clone_start_f su_poll_clone_start;
SOFIAPUBFUN su_clone_start_f su_wsaevent_clone_start;
SOFIAPUBFUN su_clone_start_f su_select_clone_start;
SOFIA_END_DECLS
#endif /* SU_WAIT_H */
@@ -1,7 +1,7 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 Nokia Corporation.
* Copyright (C) 2005, 2006, 2007 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
@@ -23,18 +23,28 @@
*/
/**@ingroup su_wait
* @CFILE su_poll_port.c
* @CFILE su_epoll_port.c
*
* Port implementation using poll()
* Port implementation using epoll(7)
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Tue Sep 14 15:51:04 1999 ppessi
* @date Created: Fri Jan 26 20:44:14 2007 ppessi
* @date Original: Tue Sep 14 15:51:04 1999 ppessi
*/
#include "config.h"
#define su_port_s su_epoll_port_s
#include "su_port.h"
#if HAVE_EPOLL
#include "sofia-sip/su.h"
#include "sofia-sip/su_alloc.h"
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
@@ -43,14 +53,6 @@
#include <limits.h>
#include <errno.h>
#define su_port_s su_poll_port_s
#include "sofia-sip/su.h"
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
#if HAVE_EPOLL
#include <sys/epoll.h>
#define POLL2EPOLL_NEEDED \
@@ -62,8 +64,8 @@
/** Port based on epoll(). */
struct su_poll_port_s {
su_pthread_port_t sup_base[1];
struct su_epoll_port_s {
su_socket_port_t sup_base[1];
/** epoll fd */
int sup_epoll;
@@ -88,7 +90,9 @@ struct su_poll_port_s {
} **sup_indices;
};
static void su_epoll_port_decref(su_port_t *self, int blocking, char const *who);
static void su_epoll_port_decref(su_port_t *self,
int blocking,
char const *who);
static int su_epoll_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
@@ -118,7 +122,7 @@ su_port_vtable_t const su_epoll_port_vtable[1] =
su_base_port_incref,
su_epoll_port_decref,
su_base_port_gsource,
su_pthread_port_send,
su_socket_port_send,
su_epoll_port_register,
su_epoll_port_unregister,
su_epoll_port_deregister,
@@ -159,7 +163,7 @@ static void su_epoll_port_deinit(void *arg)
SU_DEBUG_9(("%s(%p) called\n", "su_epoll_port_deinit", (void* )self));
su_pthread_port_deinit(self);
su_socket_port_deinit(self->sup_base);
close(self->sup_epoll), self->sup_epoll = -1;
}
@@ -434,9 +438,9 @@ int su_epoll_port_eventmask(su_port_t *self, int index, int socket, int events)
ev.data.u64 = (uint64_t)0;
ev.data.u32 = (uint32_t)index;
if (epoll_ctl(self->sup_epoll, EPOLL_CTL_MOD, ser->ser_wait->fd, &ev) == -1) {
if (epoll_ctl(self->sup_epoll, EPOLL_CTL_MOD, socket, &ev) == -1) {
SU_DEBUG_1(("su_port(%p): EPOLL_CTL_MOD(%u): %s\n", (void *)self,
ser->ser_wait->fd, su_strerror(su_errno())));
socket, su_strerror(su_errno())));
return -1;
}
@@ -449,7 +453,7 @@ int su_epoll_port_eventmask(su_port_t *self, int index, int socket, int events)
* multishot mode determines how the events are scheduled by port. If
* multishot mode is enabled, port serves all the sockets that have received
* network events. If it is disabled, only first socket event is served.
p *
*
* @param self pointer to port object
* @param multishot multishot mode (0 => disables, 1 => enables, -1 => query)
*
@@ -547,7 +551,7 @@ su_port_t *su_epoll_port_create(void)
self->sup_epoll = epoll;
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
if (su_pthread_port_init(self, su_epoll_port_vtable) < 0)
if (su_socket_port_init(self->sup_base, su_epoll_port_vtable) < 0)
return su_home_unref(su_port_home(self)), NULL;
return self;
@@ -562,22 +566,21 @@ int su_epoll_clone_start(su_root_t *parent,
return su_pthreaded_port_start(su_epoll_port_create,
parent, return_clone, magic, init, deinit);
}
#else
su_port_t *su_epoll_port_create(void)
{
return su_poll_port_create();
return su_default_port_create();
}
int su_epoll_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_pthreaded_port_start(su_poll_port_create,
parent, return_clone, magic, init, deinit);
return su_default_clone_start(parent, return_clone, magic, init, deinit);
}
#endif /* HAVE_EPOLL */
@@ -1199,7 +1199,7 @@ static
int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
{
/* This is Windows XP code, for both IPv6 and IPv4. */
size_t iaa_size = 2048;
ULONG iaa_size = 2048;
IP_ADAPTER_ADDRESSES *iaa0, *iaa;
int error, loopback_seen = 0;
int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
@@ -1208,7 +1208,7 @@ int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
int flags = GAA_FLAG_SKIP_MULTICAST;
*rresult = NULL; next = rresult;
iaa0 = malloc(iaa_size);
iaa0 = malloc((size_t)iaa_size);
if (!iaa0) {
SU_DEBUG_1(("su_localinfo: memory exhausted\n"));
error = ELI_MEMORY;
@@ -1229,7 +1229,7 @@ int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
IP_ADAPTER_UNICAST_ADDRESS *ua;
IP_ADAPTER_UNICAST_ADDRESS lua[1];
int if_index = iaa->IfIndex;
int ifnamelen = 0;
size_t ifnamelen = 0;
char ifname[16];
for (ua = iaa->FirstUnicastAddress; ;ua = ua->Next) {
File diff suppressed because it is too large. Load diff
@@ -30,12 +30,19 @@
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Tue Sep 14 15:51:04 1999 ppessi
* @date Create: Fri Jan 26 20:44:14 2007 ppessi
* @date Original: Tue Sep 14 15:51:04 1999 ppessi
*/
#include "config.h"
#if HAVE_POLL || HAVE_SELECT
#define su_port_s su_poll_port_s
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
#include "sofia-sip/su.h"
#if HAVE_POLL_PORT
#include <stdlib.h>
#include <assert.h>
@@ -45,18 +52,12 @@
#include <limits.h>
#include <errno.h>
#define su_port_s su_poll_port_s
#include "sofia-sip/su.h"
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
/** Port based on poll(). */
struct su_poll_port_s {
su_pthread_port_t sup_base[1];
su_socket_port_t sup_base[1];
#define sup_home sup_base->sup_base->sup_home
#define sup_home sup_base->sup_base->sup_base->sup_home
unsigned sup_multishot; /**< Multishot operation? */
@@ -69,12 +70,7 @@ struct su_poll_port_s {
int sup_size_waits; /**< Size of allocated su_waits */
int sup_pri_offset; /**< Offset to prioritized waits */
#if !SU_HAVE_WINSOCK
#define INDEX_MAX (0x7fffffff)
#else
/* We use WSAWaitForMultipleEvents() */
#define INDEX_MAX (64)
#endif
/** Indices from index returned by su_root_register() to tables below.
*
@@ -124,7 +120,7 @@ su_port_vtable_t const su_poll_port_vtable[1] =
su_base_port_incref,
su_poll_port_decref,
su_base_port_gsource,
su_pthread_port_send,
su_socket_port_send,
su_poll_port_register,
su_poll_port_unregister,
su_poll_port_deregister,
@@ -160,7 +156,7 @@ static void su_poll_port_deinit(void *arg)
SU_DEBUG_9(("%s(%p) called\n", "su_poll_port_deinit", (void *)self));
su_pthread_port_deinit(self);
su_socket_port_deinit(self->sup_base);
}
static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
@@ -516,8 +512,8 @@ int su_poll_port_unregister_all(su_port_t *self,
/**Set mask for a registered event. @internal
*
* The function su_poll_port_eventmask() sets the mask describing events that can
* signal the registered callback.
* The function su_poll_port_eventmask() sets the mask describing events
* that can signal the registered callback.
*
* @param port pointer to port object
* @param index registration index
@@ -663,7 +659,7 @@ su_port_t *su_poll_port_create(void)
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
if (su_pthread_port_init(self, su_poll_port_vtable) < 0)
if (su_socket_port_init(self->sup_base, su_poll_port_vtable) < 0)
return su_home_unref(su_port_home(self)), NULL;
return self;
@@ -675,8 +671,25 @@ int su_poll_clone_start(su_root_t *parent,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_pthreaded_port_start(su_poll_port_create,
return su_pthreaded_port_start(su_default_port_create,
parent, return_clone, magic, init, deinit);
}
#endif /* HAVE_POLL || HAVE_SELECT */
#else
su_port_t *su_poll_port_create(void)
{
return su_default_port_create();
}
int su_poll_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_default_clone_start(parent, return_clone, magic, init, deinit);
}
#endif /* HAVE_POLL_PORT */
+58 -28
View File
@@ -48,7 +48,43 @@
#include <string.h>
#include <stdlib.h>
static su_port_create_f *preferred_su_port_create;
/** Create the default su_port_t implementation. */
su_port_t *su_default_port_create(void)
{
#if HAVE_EPOLL
return su_epoll_port_create();
#elif HAVE_POLL_PORT
return su_poll_port_create();
#elif HAVE_WIN32
return su_wsaevent_port_create();
#elif HAVE_SELECT
return su_select_port_create();
#else
return NULL;
#endif
}
int su_default_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
#if HAVE_EPOLL
return su_epoll_clone_start(parent, return_clone, magic, init, deinit);;
#elif HAVE_POLL_PORT
return su_poll_clone_start(parent, return_clone, magic, init, deinit);;
#elif HAVE_WIN32
return su_wsaevent_clone_start(parent, return_clone, magic, init, deinit);;
#elif HAVE_SELECT
return su_select_clone_start(parent, return_clone, magic, init, deinit);;
#else
errno = ENOSYS;
return -1;
#endif
}
static su_port_create_f *preferred_su_port_create = su_default_port_create;
static su_clone_start_f *preferred_su_clone_start;
/** Explicitly set the preferred su_port_t implementation.
@@ -69,45 +105,44 @@ void su_port_set_system_preferences(char const *name)
if (name == NULL)
;
#if HAVE_POLL_PORT
#if HAVE_EPOLL
else if (strcmp(name, "epoll") == 0) {
create = su_epoll_port_create;
start = su_epoll_clone_start;
}
#endif
#if HAVE_POLL_PORT
else if (strcmp(name, "poll") == 0) {
create = su_poll_port_create;
start = su_poll_clone_start;
}
#else
/* select port does not work yet */
#error no poll!
#endif
#if HAVE_SELECT
#if HAVE_WIN32
else if (strcasecmp(name, "wsaevent") == 0) {
create = su_wsaevent_port_create;
start = su_wsaevent_clone_start;
}
#endif
#if HAVE_SELECT && !HAVE_WIN32
else if (strcmp(name, "select") == 0) {
create = su_select_port_create;
start = su_select_clone_start;
}
#endif
#if HAVE_POLL_PORT
#if HAVE_EPOLL
if (create == NULL) create = su_epoll_port_create;
if (start == NULL) start = su_epoll_clone_start;
#else
if (create == NULL) create = su_poll_port_create;
if (start == NULL) start = su_poll_clone_start;
#endif
#else
#if HAVE_SELECT
if (create == NULL) create = su_select_port_create;
if (start == NULL) start = su_select_clone_start;
#endif
#endif
if (create == NULL)
create = su_default_port_create;
if (preferred_su_port_create == NULL) preferred_su_port_create = create;
if (preferred_su_clone_start == NULL) preferred_su_clone_start = start;
if (!preferred_su_port_create ||
preferred_su_port_create == su_default_port_create)
preferred_su_port_create = create;
if (start == NULL)
start = su_default_clone_start;
if (!preferred_su_clone_start ||
preferred_su_clone_start == su_default_clone_start)
preferred_su_clone_start = start;
}
/** Create the preferred su_port_t implementation. */
@@ -116,10 +151,7 @@ su_port_t *su_port_create(void)
if (preferred_su_port_create == NULL)
su_port_set_system_preferences(getenv("SU_PORT"));
if (preferred_su_port_create)
return preferred_su_port_create();
return NULL;
return preferred_su_port_create();
}
/* ========================================================================
@@ -244,8 +276,6 @@ int su_clone_start(su_root_t *parent,
if (parent == NULL || parent->sur_threading) {
if (preferred_su_clone_start == NULL)
su_port_set_system_preferences(getenv("SU_PORT"));
if (preferred_su_clone_start == NULL)
return -1;
return preferred_su_clone_start(parent, return_clone, magic, init, deinit);
}
+18 -27
View File
@@ -152,26 +152,6 @@ SOFIAPUBFUN su_port_t *su_port_create(void)
/* Extension from >= 1.12.5 */
typedef su_port_t *su_port_create_f(void);
typedef int su_clone_start_f(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit);
SOFIAPUBFUN void su_port_prefer(su_port_create_f *f, su_clone_start_f *);
SOFIAPUBFUN su_port_t *su_epoll_port_create(void)
__attribute__((__malloc__));
SOFIAPUBFUN su_port_t *su_poll_port_create(void)
__attribute__((__malloc__));
SOFIAPUBFUN su_port_t *su_select_port_create(void)
__attribute__((__malloc__));
SOFIAPUBFUN su_clone_start_f su_epoll_clone_start;
SOFIAPUBFUN su_clone_start_f su_poll_clone_start;
SOFIAPUBFUN su_clone_start_f su_select_clone_start;
SOFIAPUBFUN void su_msg_delivery_report(su_msg_r msg);
SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_t const * t,
su_time_t now);
@@ -518,22 +498,18 @@ SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone);
#include <pthread.h>
#define SU_MBOX_SIZE 2
/** Pthread port object */
typedef struct su_pthread_port_s {
su_base_port_t sup_base[1];
struct su_pthread_port_waiting_parent
*sup_waiting_parent;
pthread_t sup_tid;
pthread_mutex_t sup_runlock[1];
#if 0
pthread_mutex_t sup_runlock[1];
pthread_cond_t sup_resume[1];
short sup_paused; /**< True if thread is paused */
#endif
short sup_thread; /**< True if thread is active */
short sup_mbox_index;
su_socket_t sup_mbox[SU_MBOX_SIZE];
} su_pthread_port_t;
/* Pthread methods */
@@ -546,9 +522,9 @@ SOFIAPUBFUN void su_pthread_port_unlock(su_port_t *self, char const *who);
SOFIAPUBFUN int su_pthread_port_own_thread(su_port_t const *self);
#if 0 /* not yet */
SOFIAPUBFUN int su_pthread_port_send(su_port_t *self, su_msg_r rmsg);
#if 0 /* not yet */
SOFIAPUBFUN su_port_t *su_pthread_port_create(void);
SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent,
su_clone_r return_clone,
@@ -584,12 +560,27 @@ typedef su_base_port_t su_pthread_port_t;
#define su_pthread_port_lock su_base_port_lock
#define su_pthread_port_unlock su_base_port_unlock
#define su_pthread_port_own_thread su_base_port_own_thread
#define su_pthread_port_send su_base_port_send
#define su_pthread_port_wait su_base_port_wait
#define su_pthread_port_execute su_base_port_execute
#endif
/* ====================================================================== */
/* Mailbox port using sockets */
#define SU_MBOX_SIZE 2
typedef struct su_socket_port_s {
su_pthread_port_t sup_base[1];
int sup_mbox_index;
su_socket_t sup_mbox[SU_MBOX_SIZE];
} su_socket_port_t;
SOFIAPUBFUN int su_socket_port_init(su_socket_port_t *,
su_port_vtable_t const *);
SOFIAPUBFUN void su_socket_port_deinit(su_socket_port_t *self);
SOFIAPUBFUN int su_socket_port_send(su_port_t *self, su_msg_r rmsg);
SOFIA_END_DECLS
#endif /* SU_PORT_H */
@@ -61,24 +61,6 @@
#define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \
(s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0)
#if HAVE_SOCKETPAIR
#define SU_MBOX_SEND 1
#else
#define SU_MBOX_SEND 0
#endif
/** @internal Message box wakeup function. */
static int su_mbox_port_wakeup(su_root_magic_t *magic, /* NULL */
su_wait_t *w,
su_wakeup_arg_t *arg)
{
char buf[32];
su_socket_t socket = *(su_socket_t*)arg;
su_wait_events(w, socket);
recv(socket, buf, sizeof(buf), 0);
return 0;
}
/**@internal
*
* Initializes a message port. It creates a mailbox used to wake up the
@@ -90,93 +72,14 @@ int su_pthread_port_init(su_port_t *self, su_port_vtable_t const *vtable)
SU_DEBUG_9(("su_pthread_port_init(%p, %p) called\n",
(void *)self, (void *)vtable));
self->sup_tid = pthread_self();
if (su_base_port_init(self, vtable) == 0 &&
su_base_port_threadsafe(self) == 0) {
int af;
su_socket_t mb = INVALID_SOCKET;
su_wait_t wait[1] = { SU_WAIT_INIT };
char const *why;
self->sup_tid = pthread_self();
#if 0
pthread_mutex_init(self->sup_runlock, NULL);
pthread_mutex_lock(self->sup_runlock);
pthread_cond_init(self->sup_resume, NULL);
#endif
#if HAVE_SOCKETPAIR
#if defined(AF_LOCAL)
af = AF_LOCAL;
#else
af = AF_UNIX;
#endif
if (socketpair(af, SOCK_STREAM, 0, self->sup_mbox) == -1) {
why = "socketpair"; goto error;
}
mb = self->sup_mbox[0];
su_setblocking(self->sup_mbox[1], 0);
#else
{
struct sockaddr_in sin = { sizeof(struct sockaddr_in), 0 };
socklen_t sinsize = sizeof sin;
struct sockaddr *sa = (struct sockaddr *)&sin;
af = PF_INET;
self->sup_mbox[0] = mb = su_socket(af, SOCK_DGRAM, IPPROTO_UDP);
if (mb == INVALID_SOCKET) {
why = "socket"; goto error;
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* 127.1 */
/* Get a port for us */
if (bind(mb, sa, sizeof sin) == -1) {
why = "bind"; goto error;
}
if (getsockname(mb, sa, &sinsize) == -1) {
why = "getsockname"; goto error;
}
if (connect(mb, sa, sinsize) == -1) {
why = "connect"; goto error;
}
}
#endif
su_setblocking(mb, 0);
if (su_wait_create(wait, mb, SU_WAIT_IN) == -1) {
why = "su_wait_create";
goto error;
}
self->sup_mbox_index = su_port_register(self, NULL, wait,
su_mbox_port_wakeup,
(void *)self->sup_mbox, 0);
if (self->sup_mbox_index <= 0) {
why = "su_port_register";
su_wait_destroy(wait);
goto error;
}
SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", 0));
return 0;
error:
su_log("%s: %s: %s\n",
"su_pthread_port_init", why, su_strerror(su_errno()));
su_pthread_port_deinit(self);
}
SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", -1));
else
su_base_port_deinit(self);
return -1;
}
@@ -187,17 +90,6 @@ void su_pthread_port_deinit(su_port_t *self)
{
assert(self);
if (self->sup_mbox_index > 0)
su_port_deregister(self, self->sup_mbox_index);
self->sup_mbox_index = 0;
if (self->sup_mbox[0] && self->sup_mbox[0] != INVALID_SOCKET)
su_close(self->sup_mbox[0]); self->sup_mbox[0] = INVALID_SOCKET;
#if HAVE_SOCKETPAIR
if (self->sup_mbox[1] && self->sup_mbox[1] != INVALID_SOCKET)
su_close(self->sup_mbox[1]); self->sup_mbox[1] = INVALID_SOCKET;
#endif
#if 0
pthread_mutex_destroy(self->sup_runlock);
pthread_cond_destroy(self->sup_resume);
@@ -225,27 +117,6 @@ void su_pthread_port_unlock(su_port_t *self, char const *who)
(void *)pthread_self(), who, self));
}
/** @internal Send a message to the port. */
int su_pthread_port_send(su_port_t *self, su_msg_r rmsg)
{
int wakeup = su_base_port_send(self, rmsg);
if (wakeup < 0)
return -1;
if (wakeup == 0)
return 0;
assert(self->sup_mbox[SU_MBOX_SEND] != INVALID_SOCKET);
if (send(self->sup_mbox[SU_MBOX_SEND], "X", 1, 0) == -1) {
#if HAVE_SOCKETPAIR
if (su_errno() != EWOULDBLOCK)
#endif
su_perror("su_msg_send: send()");
}
return 0;
}
/** @internal
* Checks if the calling thread owns the port object.
*
+334 -344
View File
@@ -25,12 +25,12 @@
/**@ingroup su_wait
* @CFILE su_select_port.c
*
* Port implementation using select(). NOT IMPLEMENTED YET!
* Port implementation using select().
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Tue Sep 14 15:51:04 1999 ppessi
* @date Created: Fri Jan 26 17:56:34 2007 ppessi
*/
#include "config.h"
@@ -51,63 +51,82 @@
#include <limits.h>
#include <errno.h>
#if HAVE_WIN32
#error winsock select() not supported yet
#else
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#elif HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#ifndef __NFDBITS
#define __NFDBITS (8 * sizeof (long int))
#endif
#undef FDSETSIZE
/* Size of fd set in bytes */
#define FDSETSIZE(n) (((n) + __NFDBITS - 1) / __NFDBITS * (__NFDBITS / 8))
#endif
/** Port based on select(). */
struct su_select_port_s {
su_pthread_port_t sup_base[1];
su_socket_port_t sup_base[1];
#define sup_home sup_base->sup_base->sup_base->sup_home
/** epoll fd */
int sup_epoll;
unsigned sup_multishot; /**< Multishot operation? */
unsigned sup_registers; /** Counter incremented by
su_port_register() or
su_port_unregister()
*/
int sup_n_registrations;
int sup_max_index; /**< Indexes are equal or smaller than this */
int sup_size_indices; /**< Size of allocated index table */
int sup_n_waits; /**< Active su_wait_t in su_waits */
int sup_size_waits; /**< Size of allocated su_waits */
int sup_pri_offset; /**< Offset to prioritized waits */
/** Structure containing registration data */
struct su_select_register {
struct su_select_register *ser_next; /* Next in free list */
su_wakeup_f ser_cb;
su_wakeup_arg_t*ser_arg;
su_root_t *ser_root;
int ser_id; /** registration identifier */
su_wait_t ser_wait[1];
} **sup_indices;
/** Indices from index returned by su_root_register() to tables below.
*
* Free elements are negative. Free elements form a list, value of free
* element is (0 - index of next free element).
*
* First element sup_indices[0] points to first free element.
*/
int *sup_indices;
int *sup_reverses; /** Reverse index */
su_wakeup_f *sup_wait_cbs;
su_wakeup_arg_t**sup_wait_args;
su_root_t **sup_wait_roots;
su_wait_t *sup_waits;
int sup_maxfd, sup_allocfd;
fd_set *sup_readfds, *sup_readfds2;
fd_set *sup_writefds, *sup_writefds2;
};
static void su_select_port_decref(su_port_t *, int blocking, char const *who);
static void su_select_port_decref(su_port_t *self,
int blocking,
char const *who);
static int su_select_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority);
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority);
static int su_select_port_unregister(su_port_t *port,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg);
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg);
static int su_select_port_deregister(su_port_t *self, int i);
static int su_select_port_unregister_all(su_port_t *self, su_root_t *root);
static int su_select_port_eventmask(su_port_t *self,
int index,
int socket,
int events);
int index,
int socket,
int events);
static int su_select_port_multishot(su_port_t *self, int multishot);
static int su_select_port_wait_events(su_port_t *self, su_duration_t tout);
static char const *su_select_port_name(su_port_t const *self);
@@ -120,7 +139,7 @@ su_port_vtable_t const su_select_port_vtable[1] =
su_base_port_incref,
su_select_port_decref,
su_base_port_gsource,
su_pthread_port_send,
su_socket_port_send,
su_select_port_register,
su_select_port_unregister,
su_select_port_deregister,
@@ -142,7 +161,7 @@ su_port_vtable_t const su_select_port_vtable[1] =
su_select_port_name,
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute
su_pthread_port_execute,
}};
static char const *su_select_port_name(su_port_t const *self)
@@ -150,39 +169,23 @@ static char const *su_select_port_name(su_port_t const *self)
return "select";
}
static void su_select_port_decref(su_port_t *self, int blocking, char const *who)
{
(void)su_base_port_decref(self, blocking, who);
}
static void su_select_port_deinit(void *arg)
{
su_port_t *self = arg;
SU_DEBUG_9(("%s(%p) called\n", "su_select_port_deinit", (void *)self));
su_pthread_port_deinit(self);
if (self->sup_waits)
free(self->sup_waits), self->sup_waits = NULL;
if (self->sup_wait_cbs)
free(self->sup_wait_cbs), self->sup_wait_cbs = NULL;
if (self->sup_wait_args)
free(self->sup_wait_args), self->sup_wait_args = NULL;
if (self->sup_wait_roots)
free(self->sup_wait_roots), self->sup_wait_roots = NULL;
if (self->sup_reverses)
free(self->sup_reverses), self->sup_reverses = NULL;
if (self->sup_indices)
free(self->sup_indices), self->sup_indices = NULL;
SU_DEBUG_9(("%s(%p) freed registrations\n",
"su_select_port_deinit", (void *)self));
}
static void su_select_port_decref(su_port_t *self, int blocking, char const *who)
{
su_base_port_decref(self, blocking, who);
su_socket_port_deinit(self->sup_base);
}
/** @internal
*
* Register a @c su_wait_t object. The wait object, a callback function and
* Register a #su_wait_t object. The wait object, a callback function and
* an argument pointer is stored in the port object. The callback function
* will be called when the wait object is signaled.
*
@@ -202,179 +205,154 @@ static void su_select_port_decref(su_port_t *self, int blocking, char const *who
* or -1 upon an error.
*/
int su_select_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority)
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority)
{
int i, j, n;
struct su_select_register *ser;
struct su_select_register **indices = self->sup_indices;
int allocfd = self->sup_allocfd;
fd_set *readfds = self->sup_readfds, *readfds2 = self->sup_readfds2;
fd_set *writefds = self->sup_writefds, *writefds2 = self->sup_writefds2;
assert(su_port_own_thread(self));
n = self->sup_n_waits;
n = self->sup_size_indices;
if (n >= SU_WAIT_MAX)
return su_seterrno(ENOMEM);
if (n >= self->sup_size_waits) {
/* Reallocate size arrays */
int size;
int *indices;
int *reverses;
su_wait_t *waits;
su_wakeup_f *wait_cbs;
su_wakeup_arg_t **wait_args;
su_root_t **wait_tasks;
if (self->sup_size_waits == 0)
size = su_root_size_hint;
else
size = 2 * self->sup_size_waits;
if (size < SU_WAIT_MIN)
size = SU_WAIT_MIN;
/* Too large */
if (-3 - size > 0)
return (errno = ENOMEM), -1;
indices = realloc(self->sup_indices, (size + 1) * sizeof(*indices));
if (indices) {
self->sup_indices = indices;
if (self->sup_size_waits == 0)
indices[0] = -1;
for (i = self->sup_size_waits + 1; i <= size; i++)
indices[i] = -1 - i;
}
reverses = realloc(self->sup_reverses, size * sizeof(*waits));
if (reverses) {
for (i = self->sup_size_waits; i < size; i++)
reverses[i] = -1;
self->sup_reverses = reverses;
}
waits = realloc(self->sup_waits, size * sizeof(*waits));
if (waits)
self->sup_waits = waits;
wait_cbs = realloc(self->sup_wait_cbs, size * sizeof(*wait_cbs));
if (wait_cbs)
self->sup_wait_cbs = wait_cbs;
wait_args = realloc(self->sup_wait_args, size * sizeof(*wait_args));
if (wait_args)
self->sup_wait_args = wait_args;
/* Add sup_wait_roots array, if needed */
wait_tasks = realloc(self->sup_wait_roots, size * sizeof(*wait_tasks));
if (wait_tasks)
self->sup_wait_roots = wait_tasks;
if (!(indices &&
reverses && waits && wait_cbs && wait_args && wait_tasks)) {
return -1;
}
self->sup_size_waits = size;
}
i = -self->sup_indices[0]; assert(i <= self->sup_size_waits);
if (priority > 0) {
/* Insert */
for (n = self->sup_n_waits; n > 0; n--) {
j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1);
self->sup_indices[j] = n;
self->sup_reverses[n] = j;
self->sup_waits[n] = self->sup_waits[n-1];
self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1];
self->sup_wait_args[n] = self->sup_wait_args[n-1];
self->sup_wait_roots[n] = self->sup_wait_roots[n-1];
}
self->sup_pri_offset++;
}
else {
/* Append - no need to move anything */
n = self->sup_n_waits;
}
self->sup_n_waits++;
self->sup_indices[0] = self->sup_indices[i]; /* Free index */
self->sup_indices[i] = n;
self->sup_reverses[n] = i;
self->sup_waits[n] = *wait;
self->sup_wait_cbs[n] = callback;
self->sup_wait_args[n] = arg;
self->sup_wait_roots[n] = root;
self->sup_registers++;
/* We return -1 or positive integer */
if (wait->fd >= allocfd)
allocfd += __NFDBITS; /* long at a time */
return i;
if (allocfd >= self->sup_allocfd) {
size_t bytes = FDSETSIZE(allocfd);
size_t bytes0 = FDSETSIZE(self->sup_allocfd);
/* (Re)allocate fd_sets */
readfds = su_realloc(self->sup_home, readfds, bytes);
if (readfds) self->sup_readfds = readfds;
readfds2 = su_realloc(self->sup_home, readfds2, bytes);
if (readfds2) self->sup_readfds2 = readfds2;
if (!readfds || !readfds2)
return -1;
writefds = su_realloc(self->sup_home, writefds, bytes);
if (writefds) self->sup_writefds = writefds;
writefds2 = su_realloc(self->sup_home, writefds2, bytes);
if (writefds2) self->sup_writefds2 = writefds2;
if (!writefds || !writefds2)
return -1;
memset((char *)readfds + bytes0, 0, bytes - bytes0);
memset((char *)writefds + bytes0, 0, bytes - bytes0);
self->sup_allocfd = allocfd;
}
ser = indices[0];
if (!ser) {
su_home_t *h = su_port_home(self);
i = self->sup_max_index, j = i == 0 ? 15 : i + 16;
if (j >= self->sup_size_indices) {
/* Reallocate index table */
n = n < 1024 ? 2 * n : n + 1024;
indices = su_realloc(h, indices, n * sizeof(indices[0]));
if (!indices)
return -1;
self->sup_indices = indices;
self->sup_size_indices = n;
}
/* Allocate registrations */
ser = su_zalloc(h, (j - i) * (sizeof *ser));
if (!ser)
return -1;
indices[0] = ser;
for (i++; i <= j; i++) {
ser->ser_id = i;
ser->ser_next = i < j ? ser + 1 : NULL;
indices[i] = ser++;
}
self->sup_max_index = j;
ser = indices[0];
}
i = ser->ser_id;
indices[0] = ser->ser_next;
ser->ser_next = NULL;
*ser->ser_wait = *wait;
ser->ser_cb = callback;
ser->ser_arg = arg;
ser->ser_root = root;
if (wait->events & SU_WAIT_IN)
FD_SET(wait->fd, readfds);
if (wait->events & SU_WAIT_OUT)
FD_SET(wait->fd, writefds);
if (wait->fd >= self->sup_maxfd)
self->sup_maxfd = wait->fd + 1;
self->sup_n_registrations++;
return i; /* return index */
}
static void su_select_port_update_maxfd(su_port_t *self)
{
int i;
su_socket_t maxfd = 0;
for (i = 1; i <= self->sup_max_index; i++) {
if (!self->sup_indices[i]->ser_cb)
continue;
if (maxfd <= self->sup_indices[i]->ser_wait->fd)
maxfd = self->sup_indices[i]->ser_wait->fd + 1;
}
self->sup_maxfd = maxfd;
}
/** Deregister a su_wait_t object. */
static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
{
int n, N, *indices, *reverses;
struct su_select_register **indices = self->sup_indices;
struct su_select_register *ser;
indices = self->sup_indices;
reverses = self->sup_reverses;
n = indices[i]; assert(n >= 0);
if (destroy_wait)
su_wait_destroy(&self->sup_waits[n]);
N = --self->sup_n_waits;
if (n < self->sup_pri_offset) {
int j = --self->sup_pri_offset;
if (n != j) {
assert(reverses[j] > 0);
assert(indices[reverses[j]] == j);
indices[reverses[j]] = n;
reverses[n] = reverses[j];
self->sup_waits[n] = self->sup_waits[j];
self->sup_wait_cbs[n] = self->sup_wait_cbs[j];
self->sup_wait_args[n] = self->sup_wait_args[j];
self->sup_wait_roots[n] = self->sup_wait_roots[j];
n = j;
}
ser = self->sup_indices[i];
if (ser == NULL || ser->ser_cb == NULL) {
su_seterrno(ENOENT);
return -1;
}
if (n < N) {
assert(reverses[N] > 0);
assert(indices[reverses[N]] == N);
assert(ser->ser_id == i);
indices[reverses[N]] = n;
reverses[n] = reverses[N];
FD_CLR(ser->ser_wait->fd, self->sup_readfds);
FD_CLR(ser->ser_wait->fd, self->sup_writefds);
self->sup_waits[n] = self->sup_waits[N];
self->sup_wait_cbs[n] = self->sup_wait_cbs[N];
self->sup_wait_args[n] = self->sup_wait_args[N];
self->sup_wait_roots[n] = self->sup_wait_roots[N];
n = N;
}
if (ser->ser_wait->fd + 1 >= self->sup_maxfd)
self->sup_maxfd = 0;
reverses[n] = -1;
memset(&self->sup_waits[n], 0, sizeof self->sup_waits[n]);
self->sup_wait_cbs[n] = NULL;
self->sup_wait_args[n] = NULL;
self->sup_wait_roots[n] = NULL;
indices[i] = indices[0];
indices[0] = -i;
memset(ser, 0, sizeof *ser);
ser->ser_id = i;
ser->ser_next = indices[0], indices[0] = ser;
self->sup_n_registrations--;
self->sup_registers++;
return i;
@@ -383,9 +361,9 @@ static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
/** Unregister a su_wait_t object.
*
* The function su_select_port_unregister() unregisters a su_wait_t object. The
* wait object, a callback function and a argument are removed from the
* port object.
* The function su_select_port_unregister() unregisters a su_wait_t object.
* The registration defined by the wait object, the callback function and
* the argument pointer are removed from the port object.
*
* @param self - pointer to port object
* @param root - pointer to root object
@@ -399,22 +377,27 @@ static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
* @return Nonzero index of the wait object, or -1 upon an error.
*/
int su_select_port_unregister(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback, /* XXX - ignored */
su_wakeup_arg_t *arg)
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback, /* XXX - ignored */
su_wakeup_arg_t *arg)
{
int n, N;
int i, I;
struct su_select_register *ser;
assert(self);
assert(su_port_own_thread(self));
N = self->sup_n_waits;
I = self->sup_max_index;
for (n = 0; n < N; n++) {
if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) {
return su_select_port_deregister0(self, self->sup_reverses[n], 0);
}
for (i = 1; i <= I; i++) {
ser = self->sup_indices[i];
if (ser->ser_cb &&
arg == ser->ser_arg &&
SU_WAIT_CMP(wait[0], ser->ser_wait[0]) == 0)
return su_select_port_deregister0(self, ser->ser_id, 0);
}
su_seterrno(ENOENT);
@@ -435,100 +418,56 @@ int su_select_port_unregister(su_port_t *self,
*/
int su_select_port_deregister(su_port_t *self, int i)
{
su_wait_t wait[1] = { SU_WAIT_INIT };
int retval;
struct su_select_register *ser;
assert(self);
assert(su_port_own_thread(self));
if (i <= 0 || i > self->sup_size_waits)
if (i <= 0 || i > self->sup_max_index)
return su_seterrno(EBADF);
if (self->sup_indices[i] < 0)
ser = self->sup_indices[i];
if (!ser->ser_cb)
return su_seterrno(EBADF);
retval = su_select_port_deregister0(self, i, 1);
su_wait_destroy(wait);
return retval;
return su_select_port_deregister0(self, i, 1);
}
/** @internal
* Unregister all su_wait_t objects.
* Unregister all su_wait_t objects of given su_root_t instance.
*
* The function su_select_port_unregister_all() unregisters all su_wait_t objects
* and destroys all queued timers associated with given root object.
* The function su_select_port_unregister_all() unregisters all su_wait_t
* objects associated with given root object.
*
* @param self - pointer to port object
* @param root - pointer to root object
*
* @return Number of wait objects removed.
*/
int su_select_port_unregister_all(su_port_t *self,
su_root_t *root)
int su_select_port_unregister_all(su_port_t *self, su_root_t *root)
{
int i, j, index, N;
int *indices, *reverses;
su_wait_t *waits;
su_wakeup_f *wait_cbs;
su_wakeup_arg_t**wait_args;
su_root_t **wait_roots;
int i, I, n;
struct su_select_register *ser;
assert(self); assert(root);
assert(su_port_own_thread(self));
N = self->sup_n_waits;
indices = self->sup_indices;
reverses = self->sup_reverses;
waits = self->sup_waits;
wait_cbs = self->sup_wait_cbs;
wait_args = self->sup_wait_args;
wait_roots = self->sup_wait_roots;
for (i = j = 0; i < N; i++) {
index = reverses[i]; assert(index > 0 && indices[index] == i);
I = self->sup_max_index;
if (wait_roots[i] == root) {
/* XXX - we should free all resources associated with this, too */
if (i < self->sup_pri_offset)
self->sup_pri_offset--;
indices[index] = indices[0];
indices[0] = -index;
for (i = 1, n = 0; i <= I; i++) {
ser = self->sup_indices[i];
if (ser->ser_root != root)
continue;
}
if (i != j) {
indices[index] = j;
reverses[j] = reverses[i];
waits[j] = waits[i];
wait_cbs[j] = wait_cbs[i];
wait_args[j] = wait_args[i];
wait_roots[j] = wait_roots[i];
}
j++;
su_select_port_deregister0(self, ser->ser_id, 0);
n++;
}
for (i = j; i < N; i++) {
reverses[i] = -1;
wait_cbs[i] = NULL;
wait_args[i] = NULL;
wait_roots[i] = NULL;
}
memset(&waits[j], 0, (char *)&waits[N] - (char *)&waits[j]);
self->sup_n_waits = j;
self->sup_registers++;
return N - j;
return n;
}
/**Set mask for a registered event. @internal
*
* The function su_select_port_eventmask() sets the mask describing events that can
* signal the registered callback.
* The function su_select_port_eventmask() sets the mask describing events
* that can signal the registered callback.
*
* @param port pointer to port object
* @param index registration index
@@ -538,19 +477,41 @@ int su_select_port_unregister_all(su_port_t *self,
* @retval 0 when successful,
* @retval -1 upon an error.
*/
int su_select_port_eventmask(su_port_t *self, int index, int socket, int events)
int su_select_port_eventmask(su_port_t *self,
int index,
int socket, int events)
{
int n;
assert(self);
assert(su_port_own_thread(self));
struct su_select_register *ser;
if (index <= 0 || index > self->sup_size_waits)
return su_seterrno(EBADF);
n = self->sup_indices[index];
if (n < 0)
if (index <= 0 || index > self->sup_max_index)
return su_seterrno(EBADF);
return su_wait_mask(&self->sup_waits[n], socket, events);
ser = self->sup_indices[index];
if (!ser->ser_cb)
return su_seterrno(EBADF);
if (self->sup_maxfd == 0)
su_select_port_update_maxfd(self);
if (socket >= self->sup_maxfd)
return su_seterrno(EBADF);
if (su_wait_mask(ser->ser_wait, socket, events) < 0)
return -1;
assert(socket < self->sup_maxfd);
if (events & SU_WAIT_IN)
FD_SET(socket, self->sup_readfds);
else
FD_CLR(socket, self->sup_readfds);
if (events & SU_WAIT_OUT)
FD_SET(socket, self->sup_writefds);
else
FD_CLR(socket, self->sup_writefds);
return 0;
}
/** @internal Enable multishot mode.
@@ -580,7 +541,7 @@ int su_select_port_multishot(su_port_t *self, int multishot)
/** @internal
* Wait (select()) for wait objects in port.
* Wait (poll()) for wait objects in port.
*
* @param self pointer to port
* @param tout timeout in milliseconds
@@ -590,78 +551,107 @@ int su_select_port_multishot(su_port_t *self, int multishot)
static
int su_select_port_wait_events(su_port_t *self, su_duration_t tout)
{
/* NOT IMPLEMENTED */
(void)su_select_port_deinit;
int j, n, events = 0;
unsigned version = self->sup_registers;
size_t bytes;
struct timeval tv;
fd_set *rset = NULL, *wset = NULL;
return -1;
}
if (self->sup_maxfd == 0)
su_select_port_update_maxfd(self);
#if 0
/** @internal
* Prints out the contents of the port.
*
* @param self pointer to a port
* @param f pointer to a file (if @c NULL, uses @c stdout).
*/
void su_port_dump(su_port_t const *self, FILE *f)
{
int i;
#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "")
#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "")
#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "")
bytes = self->sup_maxfd ? FDSETSIZE(self->sup_maxfd - 1) : 0;
if (f == NULL)
f = stdout;
if (bytes) {
rset = memcpy(self->sup_readfds2, self->sup_readfds, bytes);
wset = memcpy(self->sup_writefds2, self->sup_writefds, bytes);
}
fprintf(f, "su_port_t at %p:\n", self);
fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not ");
#if SU_HAVE_PTHREADS
fprintf(f, "\tport tid %p\n", (void *)self->sup_tid);
fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
IS_WAIT_IN(&self->sup_mbox_wait),
IS_WAIT_OUT(&self->sup_mbox_wait),
IS_WAIT_ACCEPT(&self->sup_mbox_wait));
#endif
fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
for (i = 0; i < self->sup_n_waits; i++) {
tv.tv_sec = tout / 1000;
tv.tv_usec = (tout % 1000) * 1000;
n = select(self->sup_maxfd, rset, wset, NULL, &tv);
if (n <= 0) {
SU_DEBUG_0(("su_select_port_wait_events(%p): %s (%d)\n",
(void *)self, su_strerror(su_errno()), su_errno()));
return 0;
}
for (j = 1; j < self->sup_max_index; j++) {
struct su_select_register *ser;
su_root_magic_t *magic;
int fd;
ser = self->sup_indices[j];
if (!ser->ser_cb)
continue;
fd = ser->ser_wait->fd;
ser->ser_wait->revents = 0;
if (ser->ser_wait->events & SU_WAIT_IN)
if (FD_ISSET(fd, rset)) ser->ser_wait->revents |= SU_WAIT_IN, n--;
if (ser->ser_wait->events & SU_WAIT_OUT)
if (FD_ISSET(fd, wset)) ser->ser_wait->revents |= SU_WAIT_OUT, n--;
if (ser->ser_wait->revents) {
magic = ser->ser_root ? su_root_magic(ser->ser_root) : NULL;
ser->ser_cb(magic, ser->ser_wait, ser->ser_arg);
events++;
if (version != self->sup_registers)
/* Callback function used su_register()/su_deregister() */
return events;
if (!self->sup_multishot)
/* Callback function used su_register()/su_deregister() */
return events;
}
if (n == 0)
break;
}
assert(n == 0);
return events;
}
#endif
/** Create a port using select().
/** Create a port using epoll() or poll().
*/
su_port_t *su_select_port_create(void)
{
#if notyet
su_port_t *self = su_home_new(sizeof *self);
su_port_t *self;
self = su_home_new(sizeof *self);
if (!self)
return self;
return NULL;
if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0)
return su_home_unref(su_port_home(self)), NULL;
if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0 ||
!(self->sup_indices =
su_zalloc(su_port_home(self),
(sizeof self->sup_indices[0]) *
(self->sup_size_indices = __NFDBITS)))) {
su_home_unref(su_port_home(self));
return NULL;
}
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
if (su_pthread_port_init(self, su_select_port_vtable) < 0)
if (su_socket_port_init(self->sup_base, su_select_port_vtable) < 0)
return su_home_unref(su_port_home(self)), NULL;
return self;
#else
return NULL;
#endif
}
int su_select_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_pthreaded_port_start(su_select_port_create,
parent, return_clone, magic, init, deinit);
}
#endif
+68 -100
View File
@@ -193,7 +193,10 @@ RBTREE_BODIES(static inline, timers, su_timer_t,
IS_RED, SET_RED, IS_BLACK, SET_BLACK, COPY_COLOR,
CMP, INSERT, REMOVE);
/** Set the timer. */
/**@internal Set the timer.
*
* @retval 0 when successful (always)
*/
static inline int
su_timer_set0(su_timer_t **timers,
su_timer_t *t,
@@ -212,7 +215,10 @@ su_timer_set0(su_timer_t **timers,
return timers_append(timers, t);
}
/** Reset the timer. */
/**@internal Reset the timer.
*
* @retval 0 when successful (always)
*/
static inline int
su_timer_reset0(su_timer_t **timers,
su_timer_t *t)
@@ -229,6 +235,40 @@ su_timer_reset0(su_timer_t **timers,
return 0;
}
/**@internal Validate timer @a t and return pointer to per-port timer tree.
*
* @retval pointer to pointer to timer tree when successful
* @retval NULL upon an error
*/
static
su_timer_t **su_timer_tree(su_timer_t const *t,
int use_sut_duration,
char const *caller)
{
su_timer_t **timers;
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
"NULL argument"));
return NULL;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL)
SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
"invalid timer"));
if (use_sut_duration && t->sut_duration == 0) {
assert(t->sut_duration > 0);
SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
"timer without default duration"));
return NULL;
}
return timers;
}
/**Create a timer.
*
@@ -291,23 +331,12 @@ int su_timer_set_interval(su_timer_t *t,
su_timer_arg_t *arg,
su_duration_t interval)
{
char const *func = "su_timer_set_interval";
su_timer_t **timers;
su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_interval");
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (t == NULL)
return -1;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
return 0;
return su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
}
/** Set the timer for the default interval.
@@ -326,19 +355,12 @@ int su_timer_set(su_timer_t *t,
su_timer_f wakeup,
su_timer_arg_t *arg)
{
char const *func = "su_timer_set";
su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set");
if (t == NULL)
if (timers == NULL)
return -1;
assert(t->sut_duration > 0);
if (t->sut_duration == 0) {
SU_DEBUG_0(("%s(%p): %s\n", func, (void *)t,
"timer without default duration"));
return -1;
}
return su_timer_set_interval(t, wakeup, arg, t->sut_duration);
return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
}
/** Set timer at known time.
@@ -357,23 +379,12 @@ int su_timer_set_at(su_timer_t *t,
su_wakeup_arg_t *arg,
su_time_t when)
{
char const *func = "su_timer_set_at";
su_timer_t **timers;
su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_at");
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (timers == NULL)
return -1;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
su_timer_set0(timers, t, wakeup, arg, when, 0);
return 0;
return su_timer_set0(timers, t, wakeup, arg, when, 0);
}
/** Set the timer for regular intervals.
@@ -398,35 +409,17 @@ int su_timer_run(su_timer_t *t,
su_timer_f wakeup,
su_timer_arg_t *arg)
{
char const *func = "su_timer_run";
su_timer_t **timers;
su_time_t now = su_now();
su_timer_t **timers = su_timer_tree(t, 1, "su_timer_run");
su_time_t now;
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (timers == NULL)
return -1;
}
assert(t->sut_duration > 0);
if (t->sut_duration == 0) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t,
"timer without default duration"));
return -1;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
t->sut_running = run_at_intervals;
t->sut_run = now;
t->sut_run = now = su_now();
t->sut_woken = 0;
su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
return 0;
return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
}
/**Set the timer for regular intervals.
@@ -449,35 +442,17 @@ int su_timer_set_for_ever(su_timer_t *t,
su_timer_f wakeup,
su_timer_arg_t *arg)
{
char const *func = "su_timer_set_for_ever";
su_timer_t **timers;
su_time_t now = su_now();
su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set_for_ever");
su_time_t now;
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (timers == NULL)
return -1;
}
assert(t->sut_duration > 0);
if (t->sut_duration == 0) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t,
"timer without default duration"));
return -1;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
t->sut_running = run_for_ever;
t->sut_run = now;
t->sut_run = now = su_now();
t->sut_woken = 0;
su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
return 0;
return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
}
/**Reset the timer.
@@ -490,19 +465,12 @@ int su_timer_set_for_ever(su_timer_t *t,
*/
int su_timer_reset(su_timer_t *t)
{
char const *func = "su_timer_reset";
su_timer_t **timers;
su_timer_t **timers = su_timer_tree(t, 0, "su_timer_reset");
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (timers == NULL)
return -1;
}
timers = su_task_timers(t->sut_task);
su_timer_reset0(timers, t);
return 0;
return su_timer_reset0(timers, t);
}
/** @internal Check for expired timers in queue.
@@ -576,6 +544,7 @@ int su_timer_expire(su_timer_t ** const timers,
}
/** Calculate duration in milliseconds until next timer expires. */
su_duration_t su_timer_next_expires(su_timer_t const * t, su_time_t now)
{
su_duration_t tout;
@@ -625,14 +594,13 @@ int su_timer_reset_all(su_timer_t **timers, su_task_r task)
/** Get the root object owning the timer.
*
* The function su_timer_root() return pointer to the root object owning the
* timer.
* Return pointer to the root object owning the timer.
*
* @param t pointer to the timer
*
* @return Pointer to the root object owning the timer.
* @return Pointer to the root object.
*/
su_root_t *su_timer_root(su_timer_t const *t)
{
return su_task_root(t->sut_task);
return t ? su_task_root(t->sut_task) : NULL;
}
+66 -110
View File
@@ -23,19 +23,24 @@
*/
/**@ingroup su_wait
* @CFILE su_poll_port.c
* @CFILE su_win32_port.c
*
* Port implementation using poll()
* Port implementation using WSAEVENTs
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Tue Sep 14 15:51:04 1999 ppessi
* @date Created: Mon Feb 5 20:29:21 2007 ppessi
* @date Original: Tue Sep 14 15:51:04 1999 ppessi
*/
#include "config.h"
#if HAVE_POLL || HAVE_WIN32
#define su_port_s su_wsaevent_port_s
#include "sofia-sip/su.h"
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
#include <stdlib.h>
#include <assert.h>
@@ -45,18 +50,14 @@
#include <limits.h>
#include <errno.h>
#define su_port_s su_poll_port_s
/** Port based on su_wait() aka WSAWaitForMultipleEvents. */
#include "sofia-sip/su.h"
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
#define INDEX_MAX (64)
/** Port based on poll(). */
struct su_wsaevent_port_s {
su_socket_port_t sup_base[1];
struct su_poll_port_s {
su_pthread_port_t sup_base[1];
#define sup_home sup_base->sup_base->sup_home
#define sup_home sup_base->sup_base->sup_base->sup_home
unsigned sup_multishot; /**< Multishot operation? */
@@ -69,13 +70,6 @@ struct su_poll_port_s {
int sup_size_waits; /**< Size of allocated su_waits */
int sup_pri_offset; /**< Offset to prioritized waits */
#if !SU_HAVE_WINSOCK
#define INDEX_MAX (0x7fffffff)
#else
/* We use WSAWaitForMultipleEvents() */
#define INDEX_MAX (64)
#endif
/** Indices from index returned by su_root_register() to tables below.
*
* Free elements are negative. Free elements form a list, value of free
@@ -93,43 +87,43 @@ struct su_poll_port_s {
};
static void su_poll_port_decref(su_port_t *, int blocking, char const *who);
static void su_wsevent_port_decref(su_port_t *, int blocking, char const *who);
static int su_poll_port_register(su_port_t *self,
static int su_wsevent_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority);
static int su_poll_port_unregister(su_port_t *port,
static int su_wsevent_port_unregister(su_port_t *port,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg);
static int su_poll_port_deregister(su_port_t *self, int i);
static int su_poll_port_unregister_all(su_port_t *self, su_root_t *root);
static int su_poll_port_eventmask(su_port_t *self,
static int su_wsevent_port_deregister(su_port_t *self, int i);
static int su_wsevent_port_unregister_all(su_port_t *self, su_root_t *root);
static int su_wsevent_port_eventmask(su_port_t *self,
int index,
int socket,
int events);
static int su_poll_port_multishot(su_port_t *self, int multishot);
static int su_poll_port_wait_events(su_port_t *self, su_duration_t tout);
static char const *su_poll_port_name(su_port_t const *self);
static int su_wsevent_port_multishot(su_port_t *self, int multishot);
static int su_wsevent_port_wait_events(su_port_t *self, su_duration_t tout);
static char const *su_wsevent_port_name(su_port_t const *self);
su_port_vtable_t const su_poll_port_vtable[1] =
su_port_vtable_t const su_wsevent_port_vtable[1] =
{{
/* su_vtable_size: */ sizeof su_poll_port_vtable,
/* su_vtable_size: */ sizeof su_wsevent_port_vtable,
su_pthread_port_lock,
su_pthread_port_unlock,
su_base_port_incref,
su_poll_port_decref,
su_wsevent_port_decref,
su_base_port_gsource,
su_pthread_port_send,
su_poll_port_register,
su_poll_port_unregister,
su_poll_port_deregister,
su_poll_port_unregister_all,
su_poll_port_eventmask,
su_socket_port_send,
su_wsevent_port_register,
su_wsevent_port_unregister,
su_wsevent_port_deregister,
su_wsevent_port_unregister_all,
su_wsevent_port_eventmask,
su_base_port_run,
su_base_port_break,
su_base_port_step,
@@ -137,33 +131,33 @@ su_port_vtable_t const su_poll_port_vtable[1] =
su_base_port_add_prepoll,
su_base_port_remove_prepoll,
su_base_port_timers,
su_poll_port_multishot,
su_wsevent_port_multishot,
su_base_port_threadsafe,
su_base_port_yield,
su_poll_port_wait_events,
su_wsevent_port_wait_events,
su_base_port_getmsgs,
su_base_port_getmsgs_from,
su_poll_port_name,
su_wsevent_port_name,
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
}};
static char const *su_poll_port_name(su_port_t const *self)
static char const *su_wsevent_port_name(su_port_t const *self)
{
return "poll";
}
static void su_poll_port_deinit(void *arg)
static void su_wsevent_port_deinit(void *arg)
{
su_port_t *self = arg;
SU_DEBUG_9(("%s(%p) called\n", "su_poll_port_deinit", self));
SU_DEBUG_9(("%s(%p) called\n", "su_wsevent_port_deinit", self));
su_pthread_port_deinit(self);
su_socket_port_deinit(self->sup_base);
}
static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
static void su_wsevent_port_decref(su_port_t *self, int blocking, char const *who)
{
su_base_port_decref(self, blocking, who);
}
@@ -189,7 +183,7 @@ static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
* Positive index of the wait object,
* or -1 upon an error.
*/
int su_poll_port_register(su_port_t *self,
int su_wsevent_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
@@ -311,7 +305,7 @@ int su_poll_port_register(su_port_t *self,
}
/** Deregister a su_wait_t object. */
static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
static int su_wsevent_port_deregister0(su_port_t *self, int i, int destroy_wait)
{
int n, N, *indices, *reverses;
@@ -372,9 +366,8 @@ static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
/** Unregister a su_wait_t object.
*
* The function su_poll_port_unregister() unregisters a su_wait_t object. The
* wait object, a callback function and a argument are removed from the
* port object.
* Unregisters a su_wait_t object. The wait object, a callback function and
* a argument are removed from the port object.
*
* @param self - pointer to port object
* @param root - pointer to root object
@@ -383,11 +376,11 @@ static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
* @param arg - argument given to callback function when it is invoked
* (may be NULL)
*
* @deprecated Use su_poll_port_deregister() instead.
* @deprecated Use su_wsevent_port_deregister() instead.
*
* @return Nonzero index of the wait object, or -1 upon an error.
*/
int su_poll_port_unregister(su_port_t *self,
int su_wsevent_port_unregister(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback, /* XXX - ignored */
@@ -402,7 +395,7 @@ int su_poll_port_unregister(su_port_t *self,
for (n = 0; n < N; n++) {
if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) {
return su_poll_port_deregister0(self, self->sup_reverses[n], 0);
return su_wsevent_port_deregister0(self, self->sup_reverses[n], 0);
}
}
@@ -422,7 +415,7 @@ int su_poll_port_unregister(su_port_t *self,
*
* @return Index of the wait object, or -1 upon an error.
*/
int su_poll_port_deregister(su_port_t *self, int i)
int su_wsevent_port_deregister(su_port_t *self, int i)
{
su_wait_t wait[1] = { SU_WAIT_INIT };
int retval;
@@ -436,7 +429,7 @@ int su_poll_port_deregister(su_port_t *self, int i)
if (self->sup_indices[i] < 0)
return su_seterrno(EBADF);
retval = su_poll_port_deregister0(self, i, 1);
retval = su_wsevent_port_deregister0(self, i, 1);
su_wait_destroy(wait);
@@ -447,15 +440,15 @@ int su_poll_port_deregister(su_port_t *self, int i)
/** @internal
* Unregister all su_wait_t objects.
*
* The function su_poll_port_unregister_all() unregisters all su_wait_t objects
* and destroys all queued timers associated with given root object.
* Unregisters all su_wait_t objects and destroys all queued timers
* associated with given root object.
*
* @param self - pointer to port object
* @param root - pointer to root object
*
* @return Number of wait objects removed.
*/
int su_poll_port_unregister_all(su_port_t *self,
int su_wsevent_port_unregister_all(su_port_t *self,
su_root_t *root)
{
int i, j, index, N;
@@ -516,8 +509,7 @@ int su_poll_port_unregister_all(su_port_t *self,
/**Set mask for a registered event. @internal
*
* The function su_poll_port_eventmask() sets the mask describing events that can
* signal the registered callback.
* Sets the mask describing events that can signal the registered callback.
*
* @param port pointer to port object
* @param index registration index
@@ -527,7 +519,7 @@ int su_poll_port_unregister_all(su_port_t *self,
* @retval 0 when successful,
* @retval -1 upon an error.
*/
int su_poll_port_eventmask(su_port_t *self, int index, int socket, int events)
int su_wsevent_port_eventmask(su_port_t *self, int index, int socket, int events)
{
int n;
assert(self);
@@ -557,7 +549,7 @@ int su_poll_port_eventmask(su_port_t *self, int index, int socket, int events)
* @retval -1 an error occurred
*/
static
int su_poll_port_multishot(su_port_t *self, int multishot)
int su_wsevent_port_multishot(su_port_t *self, int multishot)
{
if (multishot < 0)
return self->sup_multishot;
@@ -577,7 +569,7 @@ int su_poll_port_multishot(su_port_t *self, int multishot)
* @return number of events handled
*/
static
int su_poll_port_wait_events(su_port_t *self, su_duration_t tout)
int su_wsevent_port_wait_events(su_port_t *self, su_duration_t tout)
{
int i, events = 0;
su_wait_t *waits = self->sup_waits;
@@ -620,68 +612,32 @@ int su_poll_port_wait_events(su_port_t *self, su_duration_t tout)
return events;
}
#if 0
/** @internal
* Prints out the contents of the port.
*
* @param self pointer to a port
* @param f pointer to a file (if @c NULL, uses @c stdout).
*/
void su_port_dump(su_port_t const *self, FILE *f)
{
int i;
#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "")
#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "")
#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "")
if (f == NULL)
f = stdout;
fprintf(f, "su_port_t at %p:\n", self);
fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not ");
#if SU_HAVE_PTHREADS
fprintf(f, "\tport tid %p\n", (void *)self->sup_tid);
fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
IS_WAIT_IN(&self->sup_mbox_wait),
IS_WAIT_OUT(&self->sup_mbox_wait),
IS_WAIT_ACCEPT(&self->sup_mbox_wait));
#endif
fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
for (i = 0; i < self->sup_n_waits; i++) {
}
}
#endif
/** Create a port using epoll() or poll().
*/
su_port_t *su_poll_port_create(void)
/** Create a port using WSAEVENTs and WSAWaitForMultipleEvents. */
su_port_t *su_wsaevent_port_create(void)
{
su_port_t *self = su_home_new(sizeof *self);
if (!self)
return self;
if (su_home_destructor(su_port_home(self), su_poll_port_deinit) < 0)
if (su_home_destructor(su_port_home(self), su_wsevent_port_deinit) < 0)
return su_home_unref(su_port_home(self)), NULL;
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
if (su_pthread_port_init(self, su_poll_port_vtable) < 0)
if (su_socket_port_init(self->sup_base, su_wsevent_port_vtable) < 0)
return su_home_unref(su_port_home(self)), NULL;
return self;
}
int su_poll_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
int su_wsaevent_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_pthreaded_port_start(su_poll_port_create,
return su_pthreaded_port_start(su_wsaevent_port_create,
parent, return_clone, magic, init, deinit);
}
#endif /* HAVE_POLL */
+121 -6
View File
@@ -100,7 +100,7 @@ int test_sockaddr(void)
TEST(su_setblocking(s, 1), 0);
TEST(su_close(s), 0);
su_freelocalinfo(res);
su_freelocalinfo(res), res = NULL;
#if SU_HAVE_IN6
hints->li_family = AF_INET6;
@@ -111,16 +111,17 @@ int test_sockaddr(void)
for (li = res; li; li = li->li_next)
TEST(li->li_family, AF_INET6);
su_freelocalinfo(res);
su_freelocalinfo(res), res = NULL;
#endif
hints->li_flags |= LI_NUMERIC;
TEST(su_getlocalinfo(hints, &res), 0);
su_freelocalinfo(res), res = NULL;
hints->li_flags |= LI_NAMEREQD;
res = NULL;
hints->li_flags |= LI_NAMEREQD;
su_getlocalinfo(hints, &res);
su_freelocalinfo(res);
su_freelocalinfo(res), res = NULL;
memset(a, 0, sizeof *a);
memset(b, 0, sizeof *b);
@@ -161,7 +162,7 @@ int test_sockaddr(void)
int test_sendrecv(void)
{
int s, l, a;
su_socket_t s, l, a;
int n;
su_sockaddr_t su, csu;
socklen_t sulen = sizeof su.su_sin, csulen = sizeof csu.su_sin;
@@ -260,6 +261,120 @@ int test_sendrecv(void)
END();
}
#if HAVE_SELECT
#if HAVE_WIN32
int test_select(void)
{
return 0;
}
#else
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#elif HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#ifndef __NFDBITS
#define __NFDBITS (8 * sizeof (long int))
#endif
#undef howmany
/* Size of fd set in bytes. Sorry, octets. */
#define howmany(n) (((n) + __NFDBITS - 1) / __NFDBITS * (__NFDBITS / 8))
#define FD_ZERO_TO(maxfd, set) \
memset((set), 0, howmany(maxfd))
/* Test assumptions in su_select_port implementation */
int test_select(void)
{
su_socket_t s;
su_sockaddr_t su;
socklen_t sulen = sizeof su.su_sin;
size_t bytes;
fd_set *rset, *wset;
struct timeval tv;
BEGIN();
s = su_socket(AF_INET, SOCK_DGRAM, 0); TEST_1(s != -1);
memset(&su, 0, sulen);
su.su_len = sulen;
su.su_family = AF_INET;
TEST(inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1);
TEST(bind(s, &su.su_sa, sulen), 0);
TEST(getsockname(s, &su.su_sa, &sulen), 0);
tv.tv_sec = 0; tv.tv_usec = 1000;
TEST(select(0, NULL, NULL, NULL, &tv), 0);
bytes = howmany(s);
TEST_1(rset = malloc(bytes));
TEST_1(wset = malloc(bytes));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, NULL, wset, NULL, &tv), 1);
TEST_1(FD_ISSET(s, wset));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_SET(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, wset, NULL, &tv), 1);
TEST_1(!FD_ISSET(s, rset));
TEST_1(FD_ISSET(s, wset));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_SET(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, NULL, NULL, &tv), 0);
TEST_1(!FD_ISSET(s, rset));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_CLR(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, wset, NULL, &tv), 0);
TEST_1(!FD_ISSET(s, rset));
TEST_1(!FD_ISSET(s, wset));
TEST(su_sendto(s, "foo", 3, 0, &su, sulen), 3);
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_CLR(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, wset, NULL, &tv), 1);
TEST_1(FD_ISSET(s, rset));
TEST_1(!FD_ISSET(s, wset));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_SET(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, wset, NULL, &tv), 2);
TEST_1(FD_ISSET(s, rset));
TEST_1(FD_ISSET(s, wset));
su_close(s);
free(wset);
free(rset);
END();
}
#endif
#else
int test_select(void)
{
return 0;
}
#endif
#include <sofia-sip/su_md5.h>
int test_md5(void)
@@ -395,10 +510,10 @@ int main(int argc, char *argv[])
retval |= test_sockaddr();
retval |= test_sendrecv();
retval |= test_select();
retval |= test_md5(); fflush(stdout);
su_deinit();
return retval;
}
@@ -533,10 +533,30 @@ void usage(void)
int main(int argc, char *argv[])
{
root_test_t rt[1] = {{{ SU_HOME_INIT(rt) }}};
root_test_t *rt, rt0[1] = {{{ SU_HOME_INIT(rt0) }}}, rt1[1];
int retval = 0;
int i;
struct {
su_port_create_f *create;
su_clone_start_f *start;
char const *preference;
} prefer[] =
{
{ NULL, NULL, "default" },
#if HAVE_POLL_PORT
#if HAVE_EPOLL
{ su_epoll_port_create, su_epoll_clone_start, "epoll", },
#endif
{ su_poll_port_create, su_poll_clone_start, "poll" },
#endif
#if HAVE_SELECT
{ su_select_port_create, su_select_clone_start, "select" },
#endif
{ NULL, NULL }
};
rt = rt0;
rt->rt_family = AF_INET;
for (i = 1; argv[i]; i++) {
@@ -550,14 +570,23 @@ int main(int argc, char *argv[])
usage();
}
retval |= init_test(rt);
retval |= register_test(rt);
retval |= event_test(rt);
su_root_threading(rt->rt_root, 1);
retval |= clone_test(rt);
su_root_threading(rt->rt_root, 0);
retval |= clone_test(rt);
retval |= deinit_test(rt);
i = 0;
do {
rt = rt1, *rt = *rt0;
printf("%s: testing %s implementation\n",
name, prefer[i].preference);
su_port_prefer(prefer[i].create, prefer[i].start);
retval |= init_test(rt);
retval |= register_test(rt);
retval |= event_test(rt);
su_root_threading(rt->rt_root, 1);
retval |= clone_test(rt);
su_root_threading(rt->rt_root, 0);
retval |= clone_test(rt);
retval |= deinit_test(rt);
} while (prefer[++i].create);
return retval;
}
+9 -4
View File
@@ -1117,7 +1117,7 @@ int tport_get_params(tport_t const *self,
|| !tport_is_primary(self) || !tport_is_dgram(self);
n = tl_tgets(ta_args(ta),
TPTAG_MTU(tpp->tpp_mtu),
TPTAG_MTU((usize_t)tpp->tpp_mtu),
TPTAG_REUSE(self->tp_reusable),
TPTAG_CONNECT(connect),
TPTAG_QUEUESIZE(tpp->tpp_qsize),
@@ -1153,14 +1153,16 @@ int tport_set_params(tport_t *self,
ta_list ta;
int n;
tport_params_t tpp[1], *tpp0;
usize_t mtu;
int connect, sdwn_error, reusable, stun_server;
if (self == NULL)
return su_seterrno(EINVAL);
memcpy(tpp, tpp0 = self->tp_params, sizeof *tpp);
mtu = tpp->tpp_mtu;
connect = tpp->tpp_conn_orient;
sdwn_error = tpp->tpp_sdwn_error;
reusable = self->tp_reusable;
@@ -1169,7 +1171,7 @@ int tport_set_params(tport_t *self,
ta_start(ta, tag, value);
n = tl_gets(ta_args(ta),
TPTAG_MTU_REF(tpp->tpp_mtu),
TPTAG_MTU_REF(mtu),
TAG_IF(!self->tp_queue, TPTAG_QUEUESIZE_REF(tpp->tpp_qsize)),
TPTAG_IDLE_REF(tpp->tpp_idle),
TPTAG_TIMEOUT_REF(tpp->tpp_timeout),
@@ -1202,6 +1204,9 @@ int tport_set_params(tport_t *self,
if (tpp->tpp_qsize >= 1000)
tpp->tpp_qsize = 1000;
if (mtu > UINT_MAX)
mtu = UINT_MAX;
tpp->tpp_mtu = (unsigned)mtu;
/* Currently only primary UDP transport can *not* be connection oriented */
tpp->tpp_conn_orient = connect;
tpp->tpp_sdwn_error = sdwn_error;