@ -110,6 +110,8 @@
# include "asterisk/res_pjproject.h"
# include "asterisk/vector.h"
# include "asterisk/sorcery.h"
# include "asterisk/test.h"
# include "asterisk/netsock2.h"
static struct ast_sorcery * pjproject_sorcery ;
static pj_log_func * log_cb_orig ;
@ -471,6 +473,176 @@ void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
pj_caching_pool_destroy ( cp ) ;
}
int ast_sockaddr_to_pj_sockaddr ( const struct ast_sockaddr * addr , pj_sockaddr * pjaddr )
{
if ( addr - > ss . ss_family = = AF_INET ) {
struct sockaddr_in * sin = ( struct sockaddr_in * ) & addr - > ss ;
pjaddr - > ipv4 . sin_family = pj_AF_INET ( ) ;
pjaddr - > ipv4 . sin_addr = sin - > sin_addr ;
pjaddr - > ipv4 . sin_port = sin - > sin_port ;
} else if ( addr - > ss . ss_family = = AF_INET6 ) {
struct sockaddr_in6 * sin = ( struct sockaddr_in6 * ) & addr - > ss ;
pjaddr - > ipv6 . sin6_family = pj_AF_INET6 ( ) ;
pjaddr - > ipv6 . sin6_port = sin - > sin6_port ;
pjaddr - > ipv6 . sin6_flowinfo = sin - > sin6_flowinfo ;
pjaddr - > ipv6 . sin6_scope_id = sin - > sin6_scope_id ;
memcpy ( & pjaddr - > ipv6 . sin6_addr , & sin - > sin6_addr , sizeof ( pjaddr - > ipv6 . sin6_addr ) ) ;
} else {
memset ( pjaddr , 0 , sizeof ( * pjaddr ) ) ;
return - 1 ;
}
return 0 ;
}
int ast_sockaddr_from_pj_sockaddr ( struct ast_sockaddr * addr , const pj_sockaddr * pjaddr )
{
if ( pjaddr - > addr . sa_family = = pj_AF_INET ( ) ) {
struct sockaddr_in * sin = ( struct sockaddr_in * ) & addr - > ss ;
sin - > sin_family = AF_INET ;
sin - > sin_addr = pjaddr - > ipv4 . sin_addr ;
sin - > sin_port = pjaddr - > ipv4 . sin_port ;
addr - > len = sizeof ( struct sockaddr_in ) ;
} else if ( pjaddr - > addr . sa_family = = pj_AF_INET6 ( ) ) {
struct sockaddr_in6 * sin = ( struct sockaddr_in6 * ) & addr - > ss ;
sin - > sin6_family = AF_INET6 ;
sin - > sin6_port = pjaddr - > ipv6 . sin6_port ;
sin - > sin6_flowinfo = pjaddr - > ipv6 . sin6_flowinfo ;
sin - > sin6_scope_id = pjaddr - > ipv6 . sin6_scope_id ;
memcpy ( & sin - > sin6_addr , & pjaddr - > ipv6 . sin6_addr , sizeof ( sin - > sin6_addr ) ) ;
addr - > len = sizeof ( struct sockaddr_in6 ) ;
} else {
memset ( addr , 0 , sizeof ( * addr ) ) ;
return - 1 ;
}
return 0 ;
}
# ifdef TEST_FRAMEWORK
static void fill_with_garbage ( void * x , ssize_t len )
{
unsigned char * w = x ;
while ( len > 0 ) {
int r = ast_random ( ) ;
memcpy ( w , & r , len > sizeof ( r ) ? sizeof ( r ) : len ) ;
w + = sizeof ( r ) ;
len - = sizeof ( r ) ;
}
}
AST_TEST_DEFINE ( ast_sockaddr_to_pj_sockaddr_test )
{
char * candidates [ ] = {
" 127.0.0.1:5555 " ,
" [::]:4444 " ,
" 192.168.0.100:0 " ,
" [fec0::1:80]:0 " ,
" [fec0::1]:80 " ,
NULL ,
} , * * candidate = candidates ;
switch ( cmd ) {
case TEST_INIT :
info - > name = " ast_sockaddr_to_pj_sockaddr_test " ;
info - > category = " /res/res_pjproject/ " ;
info - > summary = " Validate conversions from an ast_sockaddr to a pj_sockaddr " ;
info - > description = " This test converts an ast_sockaddr to a pj_sockaddr and validates \n "
" that the two evaluate to the same string when formatted. " ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
while ( * candidate ) {
struct ast_sockaddr addr = { { 0 , } } ;
pj_sockaddr pjaddr ;
char buffer [ 512 ] ;
fill_with_garbage ( & pjaddr , sizeof ( pj_sockaddr ) ) ;
if ( ! ast_sockaddr_parse ( & addr , * candidate , 0 ) ) {
ast_test_status_update ( test , " Failed to parse candidate IP: %s \n " , * candidate ) ;
return AST_TEST_FAIL ;
}
if ( ast_sockaddr_to_pj_sockaddr ( & addr , & pjaddr ) ) {
ast_test_status_update ( test , " Failed to convert ast_sockaddr to pj_sockaddr: %s \n " , * candidate ) ;
return AST_TEST_FAIL ;
}
pj_sockaddr_print ( & pjaddr , buffer , sizeof ( buffer ) , 1 | 2 ) ;
if ( strcmp ( * candidate , buffer ) ) {
ast_test_status_update ( test , " Converted sockaddrs do not match: \" %s \" and \" %s \" \n " ,
* candidate ,
buffer ) ;
return AST_TEST_FAIL ;
}
candidate + + ;
}
return AST_TEST_PASS ;
}
AST_TEST_DEFINE ( ast_sockaddr_from_pj_sockaddr_test )
{
char * candidates [ ] = {
" 127.0.0.1:5555 " ,
" [::]:4444 " ,
" 192.168.0.100:0 " ,
" [fec0::1:80]:0 " ,
" [fec0::1]:80 " ,
NULL ,
} , * * candidate = candidates ;
switch ( cmd ) {
case TEST_INIT :
info - > name = " ast_sockaddr_from_pj_sockaddr_test " ;
info - > category = " /res/res_pjproject/ " ;
info - > summary = " Validate conversions from a pj_sockaddr to an ast_sockaddr " ;
info - > description = " This test converts a pj_sockaddr to an ast_sockaddr and validates \n "
" that the two evaluate to the same string when formatted. " ;
return AST_TEST_NOT_RUN ;
case TEST_EXECUTE :
break ;
}
while ( * candidate ) {
struct ast_sockaddr addr = { { 0 , } } ;
pj_sockaddr pjaddr ;
pj_str_t t ;
char buffer [ 512 ] ;
fill_with_garbage ( & addr , sizeof ( addr ) ) ;
pj_strset ( & t , * candidate , strlen ( * candidate ) ) ;
if ( pj_sockaddr_parse ( pj_AF_UNSPEC ( ) , 0 , & t , & pjaddr ) ! = PJ_SUCCESS ) {
ast_test_status_update ( test , " Failed to parse candidate IP: %s \n " , * candidate ) ;
return AST_TEST_FAIL ;
}
if ( ast_sockaddr_from_pj_sockaddr ( & addr , & pjaddr ) ) {
ast_test_status_update ( test , " Failed to convert pj_sockaddr to ast_sockaddr: %s \n " , * candidate ) ;
return AST_TEST_FAIL ;
}
snprintf ( buffer , sizeof ( buffer ) , " %s " , ast_sockaddr_stringify ( & addr ) ) ;
if ( strcmp ( * candidate , buffer ) ) {
ast_test_status_update ( test , " Converted sockaddrs do not match: \" %s \" and \" %s \" \n " ,
* candidate ,
buffer ) ;
return AST_TEST_FAIL ;
}
candidate + + ;
}
return AST_TEST_PASS ;
}
# endif
static int load_module ( void )
{
ast_debug ( 3 , " Starting PJPROJECT logging to Asterisk logger \n " ) ;
@ -540,6 +712,9 @@ static int load_module(void)
ast_cli_register_multiple ( pjproject_cli , ARRAY_LEN ( pjproject_cli ) ) ;
AST_TEST_REGISTER ( ast_sockaddr_to_pj_sockaddr_test ) ;
AST_TEST_REGISTER ( ast_sockaddr_from_pj_sockaddr_test ) ;
return AST_MODULE_LOAD_SUCCESS ;
}
@ -563,6 +738,9 @@ static int unload_module(void)
ast_sorcery_unref ( pjproject_sorcery ) ;
AST_TEST_UNREGISTER ( ast_sockaddr_to_pj_sockaddr_test ) ;
AST_TEST_UNREGISTER ( ast_sockaddr_from_pj_sockaddr_test ) ;
return 0 ;
}