diff options
-rw-r--r-- | lib/misc.c | 80 | ||||
-rw-r--r-- | lib/misc.h | 3 | ||||
-rw-r--r-- | protocols/jabber/jabber.c | 18 |
3 files changed, 66 insertions, 35 deletions
@@ -507,16 +507,17 @@ int bool2int( char *value ) return 0; } -struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ) +struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain ) { - struct ns_srv_reply *reply = NULL; + struct ns_srv_reply **replies = NULL; #ifdef HAVE_RESOLV_A + struct ns_srv_reply *reply = NULL; char name[1024]; unsigned char querybuf[1024]; const unsigned char *buf; ns_msg nsh; ns_rr rr; - int i, len, size; + int i, n, len, size; g_snprintf( name, sizeof( name ), "_%s._%s.%s", service, protocol, domain ); @@ -526,37 +527,56 @@ struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ) if( ns_initparse( querybuf, size, &nsh ) != 0 ) return NULL; - if( ns_parserr( &nsh, ns_s_an, 0, &rr ) != 0 ) - return NULL; - - size = ns_rr_rdlen( rr ); - buf = ns_rr_rdata( rr ); - - len = 0; - for( i = 6; i < size && buf[i]; i += buf[i] + 1 ) - len += buf[i] + 1; - - if( i > size ) - return NULL; - - reply = g_malloc( sizeof( struct ns_srv_reply ) + len ); - memcpy( reply->name, buf + 7, len ); - - for( i = buf[6]; i < len && buf[7+i]; i += buf[7+i] + 1 ) - reply->name[i] = '.'; - - if( i > len ) + n = 0; + while( ns_parserr( &nsh, ns_s_an, n, &rr ) == 0 ) { - g_free( reply ); - return NULL; + size = ns_rr_rdlen( rr ); + buf = ns_rr_rdata( rr ); + + len = 0; + for( i = 6; i < size && buf[i]; i += buf[i] + 1 ) + len += buf[i] + 1; + + if( i > size ) + break; + + reply = g_malloc( sizeof( struct ns_srv_reply ) + len ); + memcpy( reply->name, buf + 7, len ); + + for( i = buf[6]; i < len && buf[7+i]; i += buf[7+i] + 1 ) + reply->name[i] = '.'; + + if( i > len ) + { + g_free( reply ); + break; + } + + reply->prio = ( buf[0] << 8 ) | buf[1]; + reply->weight = ( buf[2] << 8 ) | buf[3]; + reply->port = ( buf[4] << 8 ) | buf[5]; + + n ++; + replies = g_renew( struct ns_srv_reply *, replies, n + 1 ); + replies[n-1] = reply; } - - reply->prio = ( buf[0] << 8 ) | buf[1]; - reply->weight = ( buf[2] << 8 ) | buf[3]; - reply->port = ( buf[4] << 8 ) | buf[5]; + if( replies ) + replies[n] = NULL; #endif - return reply; + return replies; +} + +void srv_free( struct ns_srv_reply **srv ) +{ + int i; + + if( srv == NULL ) + return; + + for( i = 0; srv[i]; i ++ ) + g_free( srv[i] ); + g_free( srv ); } /* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */ @@ -60,7 +60,8 @@ G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count ); G_MODULE_EXPORT int is_bool( char *value ); G_MODULE_EXPORT int bool2int( char *value ); -G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ); +G_MODULE_EXPORT struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain ); +G_MODULE_EXPORT void srv_free( struct ns_srv_reply **srv ); G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len ); diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 229e35bf..e3717526 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -95,7 +95,7 @@ static void jabber_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); struct jabber_data *jd = g_new0( struct jabber_data, 1 ); - struct ns_srv_reply *srv = NULL; + struct ns_srv_reply **srvl = NULL, *srv; char *connect_to, *s; int i; @@ -195,9 +195,19 @@ static void jabber_login( account_t *acc ) /* Figure out the hostname to connect to. */ if( acc->server && *acc->server ) connect_to = acc->server; - else if( ( srv = srv_lookup( "xmpp-client", "tcp", jd->server ) ) || - ( srv = srv_lookup( "jabber-client", "tcp", jd->server ) ) ) + else if( ( srvl = srv_lookup( "xmpp-client", "tcp", jd->server ) ) || + ( srvl = srv_lookup( "jabber-client", "tcp", jd->server ) ) ) + { + /* Find the lowest-priority one. These usually come + back in random/shuffled order. Not looking at + weights etc for now. */ + srv = *srvl; + for( i = 1; srvl[i]; i ++ ) + if( srvl[i]->prio < srv->prio ) + srv = srvl[i]; + connect_to = srv->name; + } else connect_to = jd->server; @@ -226,7 +236,7 @@ static void jabber_login( account_t *acc ) { jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, ic ); } - g_free( srv ); + srv_free( srvl ); if( jd->fd == -1 ) { |