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); |
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 |