Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
BC
public
belle-sip
Commits
1909e9f3
Commit
1909e9f3
authored
Jan 23, 2013
by
Ghislain MARY
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Asynchronous DNS query using dns.c in the resolver.
parent
dfc2fc73
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
174 additions
and
116 deletions
+174
-116
include/belle-sip/sipstack.h
include/belle-sip/sipstack.h
+1
-0
src/belle_sip_internal.h
src/belle_sip_internal.h
+1
-0
src/belle_sip_resolver.c
src/belle_sip_resolver.c
+155
-106
src/belle_sip_resolver.h
src/belle_sip_resolver.h
+6
-7
src/channel.c
src/channel.c
+1
-1
src/sipstack.c
src/sipstack.c
+5
-0
tester/belle_sip_resolver_tester.c
tester/belle_sip_resolver_tester.c
+5
-2
No files found.
include/belle-sip/sipstack.h
View file @
1909e9f3
...
...
@@ -55,6 +55,7 @@ void belle_sip_stack_sleep(belle_sip_stack_t *stack, unsigned int milliseconds);
int
belle_sip_stack_get_transport_timeout
(
const
belle_sip_stack_t
*
stack
);
int
belle_sip_stack_get_dns_timeout
(
const
belle_sip_stack_t
*
stack
);
void
belle_sip_hop_free
(
belle_sip_hop_t
*
hop
);
...
...
src/belle_sip_internal.h
View file @
1909e9f3
...
...
@@ -446,6 +446,7 @@ struct belle_sip_stack{
belle_sip_main_loop_t
*
ml
;
belle_sip_timer_config_t
timer_config
;
int
transport_timeout
;
int
dns_timeout
;
int
tx_delay
;
/*used to simulate network transmission delay, for tests*/
int
send_error
;
/* used to simulate network error. if <0, channel_send will return this value*/
};
...
...
src/belle_sip_resolver.c
View file @
1909e9f3
...
...
@@ -18,6 +18,139 @@
#include "belle_sip_resolver.h"
#include <stdlib.h>
#define DNS_EAGAIN EAGAIN
static
struct
dns_resolv_conf
*
resconf
(
belle_sip_resolver_context_t
*
ctx
)
{
const
char
*
path
;
int
error
;
if
(
ctx
->
resconf
)
return
ctx
->
resconf
;
if
(
!
(
ctx
->
resconf
=
dns_resconf_open
(
&
error
)))
{
belle_sip_error
(
"%s dns_resconf_open error: %s"
,
__FUNCTION__
,
dns_strerror
(
error
));
return
NULL
;
}
path
=
"/etc/resolv.conf"
;
error
=
dns_resconf_loadpath
(
ctx
->
resconf
,
path
);
if
(
error
)
{
belle_sip_error
(
"%s dns_resconf_loadpath error [%s]: %s"
,
__FUNCTION__
,
path
,
dns_strerror
(
error
));
return
NULL
;
}
path
=
"/etc/nsswitch.conf"
;
error
=
dns_nssconf_loadpath
(
ctx
->
resconf
,
path
);
if
(
error
)
{
belle_sip_error
(
"%s dns_nssconf_loadpath error [%s]: %s"
,
__FUNCTION__
,
path
,
dns_strerror
(
error
));
return
NULL
;
}
return
ctx
->
resconf
;
}
static
struct
dns_hosts
*
hosts
(
belle_sip_resolver_context_t
*
ctx
)
{
int
error
;
if
(
ctx
->
hosts
)
return
ctx
->
hosts
;
if
(
!
(
ctx
->
hosts
=
dns_hosts_local
(
&
error
)))
{
belle_sip_error
(
"%s dns_hosts_local error: %s"
,
__FUNCTION__
,
dns_strerror
(
error
));
return
NULL
;
}
return
ctx
->
hosts
;
}
struct
dns_cache
*
cache
(
belle_sip_resolver_context_t
*
ctx
)
{
return
NULL
;
}
static
int
resolver_process_a_data
(
belle_sip_resolver_context_t
*
ctx
,
unsigned
int
revents
)
{
struct
dns_packet
*
ans
;
struct
dns_rr_i
*
I
;
int
error
;
if
(
revents
&
BELLE_SIP_EVENT_TIMEOUT
)
{
belle_sip_error
(
"%s timed-out"
,
__FUNCTION__
);
return
BELLE_SIP_STOP
;
}
if
(
ctx
->
cancelled
)
{
return
BELLE_SIP_STOP
;
}
error
=
dns_res_check
(
ctx
->
R
);
if
(
!
error
)
{
struct
dns_rr
rr
;
union
dns_any
any
;
enum
dns_section
section
=
DNS_S_AN
;
ans
=
dns_res_fetch
(
ctx
->
R
,
&
error
);
I
=
dns_rr_i_new
(
ans
,
.
section
=
0
);
while
(
dns_rr_grep
(
&
rr
,
1
,
I
,
ans
,
&
error
))
{
if
(
rr
.
section
==
section
)
{
if
((
error
=
dns_any_parse
(
dns_any_init
(
&
any
,
sizeof
(
any
)),
&
rr
,
ans
)))
{
belle_sip_error
(
"%s dns_any_parse error: %s"
,
__FUNCTION__
,
dns_strerror
(
error
));
free
(
ans
);
return
BELLE_SIP_STOP
;
}
if
((
rr
.
class
==
DNS_C_IN
)
&&
(
rr
.
type
==
DNS_T_A
))
{
char
host
[
64
];
struct
dns_a
*
a
=
&
any
.
a
;
ctx
->
ai
=
belle_sip_ip_address_to_addrinfo
(
inet_ntoa
(
a
->
addr
),
ctx
->
port
);
belle_sip_addrinfo_to_ip
(
ctx
->
ai
,
host
,
sizeof
(
host
),
NULL
);
belle_sip_message
(
"%s has address %s"
,
ctx
->
name
,
host
);
break
;
}
}
}
free
(
ans
);
ctx
->
cb
(
ctx
->
cb_data
,
ctx
->
name
,
ctx
->
ai
);
return
BELLE_SIP_STOP
;
}
if
(
error
!=
DNS_EAGAIN
)
{
belle_sip_error
(
"%s dns_res_check error: %s (%d)"
,
__FUNCTION__
,
dns_strerror
(
error
),
error
);
return
BELLE_SIP_STOP
;
}
dns_res_poll
(
ctx
->
R
,
0
);
return
BELLE_SIP_CONTINUE
;
}
static
int
resolver_start_query
(
belle_sip_resolver_context_t
*
ctx
,
belle_sip_source_func_t
datafunc
,
enum
dns_type
type
,
int
timeout
)
{
struct
dns_hints
*
(
*
hints
)()
=
&
dns_hints_local
;
int
error
;
if
(
!
ctx
->
name
)
return
-
1
;
if
(
resconf
(
ctx
))
resconf
(
ctx
)
->
options
.
recurse
=
0
;
else
return
-
1
;
if
(
!
hosts
(
ctx
))
return
-
1
;
if
(
!
(
ctx
->
R
=
dns_res_open
(
ctx
->
resconf
,
ctx
->
hosts
,
dns_hints_mortal
(
hints
(
ctx
->
resconf
,
&
error
)),
cache
(
ctx
),
dns_opts
(),
&
error
)))
{
belle_sip_error
(
"%s dns_res_open error [%s]: %s"
,
__FUNCTION__
,
ctx
->
name
,
dns_strerror
(
error
));
return
-
1
;
}
if
((
error
=
dns_res_submit
(
ctx
->
R
,
ctx
->
name
,
type
,
DNS_C_IN
)))
{
belle_sip_error
(
"%s dns_res_submit error [%s]: %s"
,
__FUNCTION__
,
ctx
->
name
,
dns_strerror
(
error
));
return
-
1
;
}
(
*
datafunc
)(
ctx
,
0
);
belle_sip_socket_source_init
((
belle_sip_source_t
*
)
ctx
,
datafunc
,
ctx
,
dns_res_pollfd
(
ctx
->
R
),
BELLE_SIP_EVENT_READ
|
BELLE_SIP_EVENT_TIMEOUT
,
timeout
);
return
0
;
}
int
belle_sip_addrinfo_to_ip
(
const
struct
addrinfo
*
ai
,
char
*
ip
,
size_t
ip_size
,
int
*
port
){
char
serv
[
16
];
...
...
@@ -48,124 +181,41 @@ struct addrinfo * belle_sip_ip_address_to_addrinfo(const char *ipaddress, int po
static
void
belle_sip_resolver_context_destroy
(
belle_sip_resolver_context_t
*
ctx
){
if
(
ctx
->
thread
!=
0
){
belle_sip_thread_join
(
ctx
->
thread
,
NULL
);
}
if
(
ctx
->
name
)
belle_sip_free
(
ctx
->
name
);
if
(
ctx
->
ai
)
{
if
(
ctx
->
ai
)
freeaddrinfo
(
ctx
->
ai
);
}
#ifndef WIN32
close
(
ctx
->
ctlpipe
[
0
]);
close
(
ctx
->
ctlpipe
[
1
]);
#else
if
(
ctx
->
ctlevent
!=
(
belle_sip_fd_t
)
-
1
)
CloseHandle
(
ctx
->
ctlevent
);
#endif
if
(
ctx
->
R
)
dns_res_close
(
ctx
->
R
);
if
(
ctx
->
hosts
)
free
(
ctx
->
hosts
);
if
(
ctx
->
resconf
)
free
(
ctx
->
resconf
);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES
(
belle_sip_resolver_context_t
);
BELLE_SIP_INSTANCIATE_VPTR
(
belle_sip_resolver_context_t
,
belle_sip_source_t
,
belle_sip_resolver_context_destroy
,
NULL
,
NULL
,
FALSE
);
static
int
resolver_callback
(
belle_sip_resolver_context_t
*
ctx
){
belle_sip_message
(
"resolver_callback() for %p (%s) called, done=%i, cancelled=%i"
,
ctx
->
cb_data
,
ctx
->
name
,(
int
)
ctx
->
done
,(
int
)
ctx
->
cancelled
);
if
(
!
ctx
->
cancelled
){
ctx
->
cb
(
ctx
->
cb_data
,
ctx
->
name
,
ctx
->
ai
);
ctx
->
ai
=
NULL
;
}
#ifndef WIN32
{
char
tmp
;
if
(
read
(
ctx
->
source
.
fd
,
&
tmp
,
1
)
!=
1
){
belle_sip_fatal
(
"Unexpected read from resolver_callback"
);
}
}
#endif
/*by returning stop, we'll be removed from main loop and destroyed. */
return
BELLE_SIP_STOP
;
}
belle_sip_resolver_context_t
*
belle_sip_resolver_context_new
(){
belle_sip_resolver_context_t
*
ctx
=
belle_sip_object_new
(
belle_sip_resolver_context_t
);
#ifdef WIN32
ctx
->
ctlevent
=
(
belle_sip_fd_t
)
-
1
;
#endif
return
ctx
;
}
static
void
*
belle_sip_resolver_thread
(
void
*
ptr
){
belle_sip_resolver_context_t
*
ctx
=
(
belle_sip_resolver_context_t
*
)
ptr
;
struct
addrinfo
*
res
=
NULL
;
struct
addrinfo
hints
=
{
0
};
char
serv
[
10
];
int
err
;
/*the thread owns a ref on the resolver context*/
belle_sip_object_ref
(
ctx
);
belle_sip_message
(
"Resolver thread started."
);
snprintf
(
serv
,
sizeof
(
serv
),
"%i"
,
ctx
->
port
);
hints
.
ai_family
=
ctx
->
family
;
hints
.
ai_flags
=
AI_NUMERICSERV
;
err
=
getaddrinfo
(
ctx
->
name
,
serv
,
&
hints
,
&
res
);
if
(
err
!=
0
){
belle_sip_error
(
"DNS resolution of %s failed: %s"
,
ctx
->
name
,
gai_strerror
(
err
));
}
else
{
char
host
[
64
];
belle_sip_addrinfo_to_ip
(
res
,
host
,
sizeof
(
host
),
NULL
);
belle_sip_message
(
"%s has address %s."
,
ctx
->
name
,
host
);
ctx
->
ai
=
res
;
}
ctx
->
done
=
TRUE
;
#ifndef WIN32
if
(
write
(
ctx
->
ctlpipe
[
1
],
"q"
,
1
)
==-
1
){
belle_sip_error
(
"belle_sip_resolver_thread(): Fail to write on pipe."
);
}
#else
SetEvent
(
ctx
->
ctlevent
);
#endif
belle_sip_object_unref
(
ctx
);
return
NULL
;
}
static
void
belle_sip_resolver_context_start
(
belle_sip_resolver_context_t
*
ctx
){
belle_sip_fd_t
fd
=
(
belle_sip_fd_t
)
-
1
;
belle_sip_thread_create
(
&
ctx
->
thread
,
NULL
,
belle_sip_resolver_thread
,
ctx
);
#ifndef WIN32
if
(
pipe
(
ctx
->
ctlpipe
)
==-
1
){
belle_sip_fatal
(
"pipe() failed: %s"
,
strerror
(
errno
));
}
fd
=
ctx
->
ctlpipe
[
0
];
#else
/*we don't use the thread handle itself, because it is not a manual-reset event.
The mainloop implementation can only work with manual-reset events*/
ctx
->
ctlevent
=
CreateEvent
(
NULL
,
TRUE
,
FALSE
,
NULL
);
/*use CreateEventEx on wp8*/
fd
=
(
HANDLE
)
ctx
->
ctlevent
;
#endif
belle_sip_fd_source_init
(
&
ctx
->
source
,(
belle_sip_source_func_t
)
resolver_callback
,
ctx
,
fd
,
BELLE_SIP_EVENT_READ
,
-
1
);
}
unsigned
long
belle_sip_resolve
(
belle_sip_stack_t
*
stack
,
const
char
*
name
,
int
port
,
int
family
,
belle_sip_resolver_callback_t
cb
,
void
*
data
,
belle_sip_main_loop_t
*
ml
)
{
struct
addrinfo
*
res
=
belle_sip_ip_address_to_addrinfo
(
name
,
port
);
if
(
res
==
NULL
)
{
/* Then perform asynchronous DNS query */
belle_sip_resolver_context_t
*
ctx
=
belle_sip_object_new
(
belle_sip_resolver_context_t
);
ctx
->
cb_data
=
data
;
ctx
->
cb
=
cb
;
ctx
->
name
=
belle_sip_strdup
(
name
);
ctx
->
port
=
port
;
ctx
->
ai
=
NULL
;
if
(
family
==
0
)
family
=
AF_UNSPEC
;
ctx
->
family
=
family
;
resolver_start_query
(
ctx
,
(
belle_sip_source_func_t
)
resolver_process_a_data
,
DNS_T_A
,
belle_sip_stack_get_dns_timeout
(
stack
));
unsigned
long
belle_sip_resolve
(
const
char
*
name
,
int
port
,
int
family
,
belle_sip_resolver_callback_t
cb
,
void
*
data
,
belle_sip_main_loop_t
*
ml
){
struct
addrinfo
*
res
=
belle_sip_ip_address_to_addrinfo
(
name
,
port
);
if
(
res
==
NULL
){
/*then perform asynchronous DNS query */
belle_sip_resolver_context_t
*
ctx
=
belle_sip_resolver_context_new
();
ctx
->
cb_data
=
data
;
ctx
->
cb
=
cb
;
ctx
->
name
=
belle_sip_strdup
(
name
);
ctx
->
port
=
port
;
if
(
family
==
0
)
family
=
AF_UNSPEC
;
ctx
->
family
=
family
;
belle_sip_resolver_context_start
(
ctx
);
/*the resolver context must never be removed manually from the main loop*/
belle_sip_main_loop_add_source
(
ml
,(
belle_sip_source_t
*
)
ctx
);
belle_sip_object_unref
(
ctx
);
/*the main loop and the thread have a ref on it*/
return
ctx
->
source
.
id
;
}
else
{
cb
(
data
,
name
,
res
);
}
else
{
cb
(
data
,
name
,
res
);
return
0
;
}
}
...
...
@@ -211,4 +261,3 @@ fail:
}
if
(
sock
==
(
belle_sip_socket_t
)
-
1
)
close_socket
(
sock
);
}
src/belle_sip_resolver.h
View file @
1909e9f3
...
...
@@ -21,6 +21,7 @@
#define belle_sip_resolver_h
#include "belle_sip_internal.h"
#include "dns.h"
typedef
struct
belle_sip_resolver_context
belle_sip_resolver_context_t
;
...
...
@@ -38,22 +39,20 @@ struct belle_sip_resolver_context{
belle_sip_source_t
source
;
belle_sip_resolver_callback_t
cb
;
void
*
cb_data
;
struct
dns_resolv_conf
*
resconf
;
struct
dns_hosts
*
hosts
;
struct
dns_resolver
*
R
;
char
*
name
;
int
port
;
struct
addrinfo
*
ai
;
int
family
;
belle_sip_thread_t
thread
;
#ifndef WIN32
int
ctlpipe
[
2
];
#else
HANDLE
ctlevent
;
#endif
uint8_t
cancelled
;
uint8_t
done
;
};
int
belle_sip_addrinfo_to_ip
(
const
struct
addrinfo
*
ai
,
char
*
ip
,
size_t
ip_size
,
int
*
port
);
struct
addrinfo
*
belle_sip_ip_address_to_addrinfo
(
const
char
*
ipaddress
,
int
port
);
unsigned
long
belle_sip_resolve
(
const
char
*
name
,
int
port
,
int
family
,
belle_sip_resolver_callback_t
cb
,
void
*
data
,
belle_sip_main_loop_t
*
ml
);
unsigned
long
belle_sip_resolve
(
belle_sip_stack_t
*
stack
,
const
char
*
name
,
int
port
,
int
family
,
belle_sip_resolver_callback_t
cb
,
void
*
data
,
belle_sip_main_loop_t
*
ml
);
void
belle_sip_resolve_cancel
(
belle_sip_main_loop_t
*
ml
,
unsigned
long
id
);
void
belle_sip_get_src_addr_for
(
const
struct
sockaddr
*
dest
,
socklen_t
destlen
,
struct
sockaddr
*
src
,
socklen_t
*
srclen
);
...
...
src/channel.c
View file @
1909e9f3
...
...
@@ -451,7 +451,7 @@ static void channel_res_done(void *data, const char *name, struct addrinfo *res)
void
belle_sip_channel_resolve
(
belle_sip_channel_t
*
obj
){
channel_set_state
(
obj
,
BELLE_SIP_CHANNEL_RES_IN_PROGRESS
);
obj
->
resolver_id
=
belle_sip_resolve
(
obj
->
peer_name
,
obj
->
peer_port
,
0
,
channel_res_done
,
obj
,
obj
->
stack
->
ml
);
obj
->
resolver_id
=
belle_sip_resolve
(
obj
->
stack
,
obj
->
peer_name
,
obj
->
peer_port
,
0
,
channel_res_done
,
obj
,
obj
->
stack
->
ml
);
return
;
}
...
...
src/sipstack.c
View file @
1909e9f3
...
...
@@ -34,6 +34,7 @@ belle_sip_stack_t * belle_sip_stack_new(const char *properties){
stack
->
timer_config
.
T2
=
4000
;
stack
->
timer_config
.
T4
=
5000
;
stack
->
transport_timeout
=
30000
;
stack
->
dns_timeout
=
2000
;
return
stack
;
}
...
...
@@ -45,6 +46,10 @@ int belle_sip_stack_get_transport_timeout(const belle_sip_stack_t *stack){
return
stack
->
transport_timeout
;
}
int
belle_sip_stack_get_dns_timeout
(
const
belle_sip_stack_t
*
stack
)
{
return
stack
->
dns_timeout
;
}
belle_sip_listening_point_t
*
belle_sip_stack_create_listening_point
(
belle_sip_stack_t
*
s
,
const
char
*
ipaddress
,
int
port
,
const
char
*
transport
){
belle_sip_listening_point_t
*
lp
=
NULL
;
if
(
strcasecmp
(
transport
,
"UDP"
)
==
0
)
{
...
...
tester/belle_sip_resolver_tester.c
View file @
1909e9f3
...
...
@@ -29,6 +29,7 @@
typedef
struct
endpoint
{
belle_sip_stack_t
*
stack
;
long
unsigned
int
resolver_id
;
int
resolve_done
;
int
resolve_successful
;
}
endpoint_t
;
...
...
@@ -55,6 +56,7 @@ static void destroy_endpoint(endpoint_t* endpoint) {
static
void
resolve_done
(
void
*
data
,
const
char
*
name
,
struct
addrinfo
*
res
)
{
endpoint_t
*
client
=
(
endpoint_t
*
)
data
;
client
->
resolve_done
=
1
;
if
(
res
)
{
client
->
resolve_successful
=
1
;
}
...
...
@@ -64,8 +66,9 @@ static void resolve(void) {
const
char
*
peer_name
=
SIPDOMAIN
;
int
peer_port
=
SIPPORT
;
endpoint_t
*
client
=
create_endpoint
();
client
->
resolver_id
=
belle_sip_resolve
(
peer_name
,
peer_port
,
0
,
resolve_done
,
client
,
belle_sip_stack_get_main_loop
(
client
->
stack
));
CU_ASSERT_TRUE
(
wait_for
(
client
->
stack
,
&
client
->
resolve_successful
,
1
,
2000
));
client
->
resolver_id
=
belle_sip_resolve
(
client
->
stack
,
peer_name
,
peer_port
,
0
,
resolve_done
,
client
,
belle_sip_stack_get_main_loop
(
client
->
stack
));
CU_ASSERT_TRUE
(
wait_for
(
client
->
stack
,
&
client
->
resolve_done
,
1
,
2000
));
CU_ASSERT_TRUE
((
client
->
resolve_successful
==
1
));
destroy_endpoint
(
client
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment