aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/misc.c80
-rw-r--r--lib/misc.h3
-rw-r--r--protocols/jabber/jabber.c18
3 files changed, 66 insertions, 35 deletions
diff --git a/lib/misc.c b/lib/misc.c
index fda19c19..b696b8c4 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -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. */
diff --git a/lib/misc.h b/lib/misc.h
index 12a9edff..83ba9e67 100644
--- a/lib/misc.h
+++ b/lib/misc.h
@@ -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 )
{