loudmouth/lm-socket.c
changeset 244 8a05b79bad24
parent 243 fa0794ef3570
child 245 df2655dbe873
equal deleted inserted replaced
243:fa0794ef3570 244:8a05b79bad24
    37 #include "lm-error.h"
    37 #include "lm-error.h"
    38 
    38 
    39 #define IN_BUFFER_SIZE 1024
    39 #define IN_BUFFER_SIZE 1024
    40 #define MIN_PORT 1
    40 #define MIN_PORT 1
    41 #define MAX_PORT 65536
    41 #define MAX_PORT 65536
       
    42 #define SRV_LEN 8192
    42 
    43 
    43 struct _LmSocket {
    44 struct _LmSocket {
    44 	LmConnection *connection;
    45 	LmConnection *connection;
    45 	GMainContext *context;
    46 	GMainContext *context;
    46 
    47 
    47 	gchar        *server;
    48 	gchar        *server;
    48 	guint         port;
    49 	guint         port;
       
    50 
       
    51 	gboolean      use_srv;
    49 
    52 
    50 	gboolean      blocking;
    53 	gboolean      blocking;
    51 
    54 
    52 	LmSSL        *ssl;
    55 	LmSSL        *ssl;
    53 	LmProxy      *proxy;
    56 	LmProxy      *proxy;
    87 					      LmSocket     *socket);
    90 					      LmSocket     *socket);
    88 static gboolean
    91 static gboolean
    89 socket_buffered_write_cb (GIOChannel   *source, 
    92 socket_buffered_write_cb (GIOChannel   *source, 
    90 			      GIOCondition  condition,
    93 			      GIOCondition  condition,
    91 			      LmSocket     *socket);
    94 			      LmSocket     *socket);
       
    95 static gboolean socket_parse_srv_response (unsigned char  *srv, 
       
    96 					   int             srv_len, 
       
    97 					   gchar         **out_server, 
       
    98 					   guint          *out_port);
    92 
    99 
    93 static void
   100 static void
    94 socket_free (LmSocket *socket)
   101 socket_free (LmSocket *socket)
    95 {
   102 {
    96 	g_free (socket->server);
   103 	g_free (socket->server);
   576 				      socket);
   583 				      socket);
   577 }
   584 }
   578 
   585 
   579 static gboolean
   586 static gboolean
   580 socket_buffered_write_cb (GIOChannel   *source, 
   587 socket_buffered_write_cb (GIOChannel   *source, 
   581 			      GIOCondition  condition,
   588 			  GIOCondition  condition,
   582 			      LmSocket     *socket)
   589 			  LmSocket     *socket)
   583 {
   590 {
   584 	gint     b_written;
   591 	gint     b_written;
   585 	GString *out_buf;
   592 	GString *out_buf;
   586 	/* FIXME: Do the writing */
   593 	/* FIXME: Do the writing */
   587 
   594 
   615 
   622 
   616 	return TRUE;
   623 	return TRUE;
   617 }
   624 }
   618 
   625 
   619 static gboolean
   626 static gboolean
   620 _parse_srv_response (unsigned char *srv, int srv_len, gchar **out_server, guint *out_port)
   627 socket_parse_srv_response (unsigned char  *srv, 
   621 {
   628 			   int             srv_len, 
   622 	int qdcount;
   629 			   gchar         **out_server, 
   623 	int ancount;
   630 			   guint          *out_port)
   624 	int len;
   631 {
   625 	const unsigned char *pos = srv + sizeof(HEADER);
   632 	int                  qdcount;
   626 	unsigned char *end = srv + srv_len;
   633 	int                  ancount;
   627 	HEADER *head = (HEADER *)srv;
   634 	int                  len;
   628 	char name[256];
   635 	const unsigned char *pos;
   629 	char pref_name[256];
   636 	unsigned char       *end;
   630 	guint pref_port = 0;
   637 	HEADER              *head;
   631 	guint pref_prio = 9999;
   638 	char                 name[256];
       
   639 	char                 pref_name[256];
       
   640 	guint                pref_port = 0;
       
   641 	guint                pref_prio = 9999;
   632 
   642 
   633 	pref_name[0] = 0;
   643 	pref_name[0] = 0;
       
   644 
       
   645 	pos = srv + sizeof (HEADER);
       
   646 	end = srv + srv_len;
       
   647 	head = (HEADER *) srv;
   634 
   648 
   635 	qdcount = ntohs (head->qdcount);
   649 	qdcount = ntohs (head->qdcount);
   636 	ancount = ntohs (head->ancount);
   650 	ancount = ntohs (head->ancount);
   637 
   651 
   638 	/* Ignore the questions */
   652 	/* Ignore the questions */
   643 
   657 
   644 	/* Parse the answers */
   658 	/* Parse the answers */
   645 	while (ancount-- > 0 && (len = dn_expand (srv, end, pos, name, 255)) >= 0) {
   659 	while (ancount-- > 0 && (len = dn_expand (srv, end, pos, name, 255)) >= 0) {
   646 		/* Ignore the initial string */
   660 		/* Ignore the initial string */
   647 		uint16_t pref, weight, port;
   661 		uint16_t pref, weight, port;
       
   662 
   648 		g_assert (len >= 0);
   663 		g_assert (len >= 0);
   649 		pos += len;
   664 		pos += len;
   650 		/* Ignore type, ttl, class and dlen */
   665 		/* Ignore type, ttl, class and dlen */
   651 		pos += 10;
   666 		pos += 10;
   652 		GETSHORT (pref, pos);
   667 		GETSHORT (pref, pos);
   653 		GETSHORT (weight, pos);
   668 		GETSHORT (weight, pos);
   654 		GETSHORT (port, pos);
   669 		GETSHORT (port, pos);
       
   670 
   655 		len = dn_expand (srv, end, pos, name, 255);
   671 		len = dn_expand (srv, end, pos, name, 255);
   656 		if (pref < pref_prio) {
   672 		if (pref < pref_prio) {
   657 			pref_prio = pref;
   673 			pref_prio = pref;
   658 			strcpy (pref_name, name);
   674 			strcpy (pref_name, name);
   659 			pref_port = port;
   675 			pref_port = port;
   675 		  gpointer           user_data,
   691 		  gpointer           user_data,
   676 		  LmConnection      *connection,
   692 		  LmConnection      *connection,
   677 		  gboolean           blocking,
   693 		  gboolean           blocking,
   678 		  const gchar       *server,
   694 		  const gchar       *server,
   679 		  guint              port, 
   695 		  guint              port, 
       
   696 		  gboolean           use_srv,
   680 		  LmSSL             *ssl,
   697 		  LmSSL             *ssl,
   681 		  LmProxy           *proxy,
   698 		  LmProxy           *proxy,
   682 		  GError           **error)
   699 		  GError           **error)
   683 {
   700 {
   684 	LmSocket        *socket;
   701 	LmSocket        *socket;
   685 	struct addrinfo  req;
   702 	struct addrinfo  req;
   686 	struct addrinfo *ans;
   703 	struct addrinfo *ans;
   687 	const char      *remote_addr;
   704 	const char      *remote_addr;
   688 	LmConnectData   *data;
   705 	LmConnectData   *data;
   689 	int              err;
   706 	int              err;
   690 	char            *srv;
   707 	
   691 #define SRV_LEN 8192
       
   692 	unsigned char    srv_ans[SRV_LEN];
       
   693 
       
   694 	g_return_val_if_fail (server != NULL, NULL);
   708 	g_return_val_if_fail (server != NULL, NULL);
   695 	g_return_val_if_fail ((port >= MIN_PORT && port <= MAX_PORT), NULL);
   709 	g_return_val_if_fail ((port >= MIN_PORT && port <= MAX_PORT), NULL);
   696 	g_return_val_if_fail (func != NULL, NULL);
   710 	g_return_val_if_fail (func != NULL, NULL);
   697 
   711 
   698 	socket = g_new0 (LmSocket, 1);
   712 	socket = g_new0 (LmSocket, 1);
   706 	socket->ref_count = 1;
   720 	socket->ref_count = 1;
   707 
   721 
   708 	socket->connection = connection;
   722 	socket->connection = connection;
   709 	socket->server = g_strdup (server);
   723 	socket->server = g_strdup (server);
   710 	socket->port = port;
   724 	socket->port = port;
       
   725 	socket->use_srv = use_srv;
   711 	socket->cancel_open = FALSE;
   726 	socket->cancel_open = FALSE;
   712 	socket->ssl = NULL;
   727 	socket->ssl = NULL;
   713 	socket->proxy = NULL;
   728 	socket->proxy = NULL;
   714 	socket->blocking = blocking;
   729 	socket->blocking = blocking;
   715 	socket->func = func;
   730 	socket->func = func;
   716 	socket->user_data = user_data;
   731 	socket->user_data = user_data;
   717 
   732 
   718 	res_init ();
   733 	if (use_srv) {
   719 	srv = g_strdup_printf ("_xmpp-client._tcp.%s", socket->server);
   734 		char          *srv;
   720 	err = res_query (srv, C_IN, T_SRV, srv_ans, SRV_LEN);
   735 		unsigned char  srv_ans[SRV_LEN];
   721 	if (err > 0) {
   736 
   722 		_parse_srv_response (srv_ans, err, &(socket->server), &(socket->port));
   737 		res_init ();
   723 	}
   738 
   724 	g_free (srv);
   739 		srv = g_strdup_printf ("_xmpp-client._tcp.%s", socket->server);
       
   740 		err = res_query (srv, C_IN, T_SRV, srv_ans, SRV_LEN);
       
   741 		if (err > 0) {
       
   742 			gchar    *new_server;
       
   743 			guint     new_port;
       
   744 			gboolean  result;
       
   745 			
       
   746 			result = socket_parse_srv_response (srv_ans, err, 
       
   747 							    &new_server, 
       
   748 							    &new_port);
       
   749 			if (result == TRUE) {
       
   750 				g_free (socket->server);
       
   751 				socket->server = new_server;
       
   752 				socket->port = new_port;
       
   753 			}
       
   754 		}
       
   755 		g_free (srv);
       
   756 	}
   725 
   757 
   726 	if (context) {
   758 	if (context) {
   727 		socket->context = g_main_context_ref (context);
   759 		socket->context = g_main_context_ref (context);
   728 	}
   760 	}
   729 
   761 
   772 			LM_ERROR,
   804 			LM_ERROR,
   773 			LM_ERROR_CONNECTION_FAILED,
   805 			LM_ERROR_CONNECTION_FAILED,
   774 			"unable to connect");
   806 			"unable to connect");
   775 		return NULL;
   807 		return NULL;
   776 	}
   808 	}
       
   809 
   777 	return socket;
   810 	return socket;
   778 }
   811 }
   779 
   812 
   780 void
   813 void
   781 lm_socket_flush (LmSocket *socket)
   814 lm_socket_flush (LmSocket *socket)