| 69 { |
69 { |
| 70 ggp_resolver_purple_data *data = (ggp_resolver_purple_data*)cbdata; |
70 ggp_resolver_purple_data *data = (ggp_resolver_purple_data*)cbdata; |
| 71 const int fd = data->pipes[1]; |
71 const int fd = data->pipes[1]; |
| 72 int ipv4_count, all_count, write_size; |
72 int ipv4_count, all_count, write_size; |
| 73 struct in_addr *addresses; |
73 struct in_addr *addresses; |
| 74 |
74 |
| 75 purple_debug_misc("gg", "ggp_resolver_purple_cb(%p, %p, \"%s\")\n", |
75 purple_debug_misc("gg", "ggp_resolver_purple_cb(%p, %p, \"%s\")\n", |
| 76 hosts, cbdata, error_message); |
76 hosts, cbdata, error_message); |
| 77 |
77 |
| 78 data->purpleQuery = NULL; |
78 data->purpleQuery = NULL; |
| 79 |
79 |
| 80 if (error_message) |
80 if (error_message) |
| 81 { |
81 { |
| 82 purple_debug_error("gg", "ggp_resolver_purple_cb failed: %s\n", |
82 purple_debug_error("gg", "ggp_resolver_purple_cb failed: %s\n", |
| 83 error_message); |
83 error_message); |
| 84 } |
84 } |
| 85 |
85 |
| 86 all_count = g_slist_length(hosts); |
86 all_count = g_slist_length(hosts); |
| 87 g_assert(all_count % 2 == 0); |
87 g_assert(all_count % 2 == 0); |
| 88 all_count /= 2; |
88 all_count /= 2; |
| 89 addresses = malloc((all_count + 1) * sizeof(struct in_addr)); |
89 addresses = malloc((all_count + 1) * sizeof(struct in_addr)); |
| 90 |
90 |
| 91 ipv4_count = 0; |
91 ipv4_count = 0; |
| 92 while (hosts && (hosts = g_slist_delete_link(hosts, hosts))) |
92 while (hosts && (hosts = g_slist_delete_link(hosts, hosts))) |
| 93 { |
93 { |
| 94 const struct sockaddr *addr = hosts->data; |
94 const struct sockaddr *addr = hosts->data; |
| 95 char dst[INET6_ADDRSTRLEN]; |
95 char dst[INET6_ADDRSTRLEN]; |
| 96 |
96 |
| 97 if (addr->sa_family == AF_INET6) |
97 if (addr->sa_family == AF_INET6) |
| 98 { |
98 { |
| 99 inet_ntop(addr->sa_family, |
99 inet_ntop(addr->sa_family, |
| 100 &((struct sockaddr_in6 *) addr)->sin6_addr, |
100 &((struct sockaddr_in6 *) addr)->sin6_addr, |
| 101 dst, sizeof(dst)); |
101 dst, sizeof(dst)); |
| 108 ((struct sockaddr_in *) addr)->sin_addr; |
108 ((struct sockaddr_in *) addr)->sin_addr; |
| 109 inet_ntop(addr->sa_family, &addr_ipv4, |
109 inet_ntop(addr->sa_family, &addr_ipv4, |
| 110 dst, sizeof(dst)); |
110 dst, sizeof(dst)); |
| 111 purple_debug_misc("gg", "ggp_resolver_purple_cb " |
111 purple_debug_misc("gg", "ggp_resolver_purple_cb " |
| 112 "ipv4: %s\n", dst); |
112 "ipv4: %s\n", dst); |
| 113 |
113 |
| 114 g_assert(ipv4_count < all_count); |
114 g_assert(ipv4_count < all_count); |
| 115 addresses[ipv4_count++] = addr_ipv4; |
115 addresses[ipv4_count++] = addr_ipv4; |
| 116 } |
116 } |
| 117 else |
117 else |
| 118 { |
118 { |
| 119 purple_debug_warning("gg", "ggp_resolver_purple_cb " |
119 purple_debug_warning("gg", "ggp_resolver_purple_cb " |
| 120 "unexpected sa_family: %d\n", addr->sa_family); |
120 "unexpected sa_family: %d\n", addr->sa_family); |
| 121 } |
121 } |
| 122 |
122 |
| 123 g_free(hosts->data); |
123 g_free(hosts->data); |
| 124 hosts = g_slist_delete_link(hosts, hosts); |
124 hosts = g_slist_delete_link(hosts, hosts); |
| 125 } |
125 } |
| 126 |
126 |
| 127 addresses[ipv4_count].s_addr = INADDR_NONE; |
127 addresses[ipv4_count].s_addr = INADDR_NONE; |
| 128 |
128 |
| 129 write_size = (ipv4_count + 1) * sizeof(struct in_addr); |
129 write_size = (ipv4_count + 1) * sizeof(struct in_addr); |
| 130 if (write(fd, addresses, write_size) != write_size) |
130 if (write(fd, addresses, write_size) != write_size) |
| 131 { |
131 { |
| 132 purple_debug_error("gg", |
132 purple_debug_error("gg", |
| 133 "ggp_resolver_purple_cb write error\n"); |
133 "ggp_resolver_purple_cb write error\n"); |
| 139 const char *hostname) |
139 const char *hostname) |
| 140 { |
140 { |
| 141 ggp_resolver_purple_data *data; |
141 ggp_resolver_purple_data *data; |
| 142 purple_debug_misc("gg", "ggp_resolver_purple_start(%p, %p, \"%s\")\n", |
142 purple_debug_misc("gg", "ggp_resolver_purple_start(%p, %p, \"%s\")\n", |
| 143 fd, private_data, hostname); |
143 fd, private_data, hostname); |
| 144 |
144 |
| 145 data = malloc(sizeof(ggp_resolver_purple_data)); |
145 data = malloc(sizeof(ggp_resolver_purple_data)); |
| 146 *private_data = (void*)data; |
146 *private_data = (void*)data; |
| 147 data->purpleQuery = NULL; |
147 data->purpleQuery = NULL; |
| 148 data->pipes[0] = 0; |
148 data->pipes[0] = 0; |
| 149 data->pipes[1] = 0; |
149 data->pipes[1] = 0; |
| 150 |
150 |
| 151 if (purple_input_pipe(data->pipes) != 0) |
151 if (purple_input_pipe(data->pipes) != 0) |
| 152 { |
152 { |
| 153 purple_debug_error("gg", "ggp_resolver_purple_start: " |
153 purple_debug_error("gg", "ggp_resolver_purple_start: " |
| 154 "unable to create pipe\n"); |
154 "unable to create pipe\n"); |
| 155 ggp_resolver_purple_cleanup(private_data, 0); |
155 ggp_resolver_purple_cleanup(private_data, 0); |
| 156 return -1; |
156 return -1; |
| 157 } |
157 } |
| 158 |
158 |
| 159 *fd = data->pipes[0]; |
159 *fd = data->pipes[0]; |
| 160 |
160 |
| 161 /* account and port is unknown in this context */ |
161 /* account and port is unknown in this context */ |
| 162 data->purpleQuery = purple_dnsquery_a(NULL, hostname, 80, |
162 data->purpleQuery = purple_dnsquery_a(NULL, hostname, 80, |
| 163 ggp_resolver_purple_cb, (gpointer)data); |
163 ggp_resolver_purple_cb, (gpointer)data); |
| 164 |
164 |
| 165 if (!data->purpleQuery) |
165 if (!data->purpleQuery) |
| 167 purple_debug_error("gg", "ggp_resolver_purple_start: " |
167 purple_debug_error("gg", "ggp_resolver_purple_start: " |
| 168 "unable to call purple_dnsquery_a\n"); |
168 "unable to call purple_dnsquery_a\n"); |
| 169 ggp_resolver_purple_cleanup(private_data, 0); |
169 ggp_resolver_purple_cleanup(private_data, 0); |
| 170 return -1; |
170 return -1; |
| 171 } |
171 } |
| 172 |
172 |
| 173 return 0; |
173 return 0; |
| 174 } |
174 } |
| 175 |
175 |
| 176 void ggp_resolver_purple_cleanup(void **private_data, int force) |
176 void ggp_resolver_purple_cleanup(void **private_data, int force) |
| 177 { |
177 { |
| 178 ggp_resolver_purple_data *data = |
178 ggp_resolver_purple_data *data = |
| 179 (ggp_resolver_purple_data*)(*private_data); |
179 (ggp_resolver_purple_data*)(*private_data); |
| 180 |
180 |
| 181 purple_debug_misc("gg", "ggp_resolver_purple_cleanup(%p, %d)\n", |
181 purple_debug_misc("gg", "ggp_resolver_purple_cleanup(%p, %d)\n", |
| 182 private_data, force); |
182 private_data, force); |
| 183 |
183 |
| 184 if (!data) |
184 if (!data) |
| 185 return; |
185 return; |
| 186 *private_data = NULL; |
186 *private_data = NULL; |
| 187 |
187 |
| 188 if (data->purpleQuery) |
188 if (data->purpleQuery) |
| 189 purple_dnsquery_destroy(data->purpleQuery); |
189 purple_dnsquery_destroy(data->purpleQuery); |
| 190 if (data->pipes[0]) |
190 if (data->pipes[0]) |
| 191 close(data->pipes[0]); |
191 close(data->pipes[0]); |
| 192 if (data->pipes[1]) |
192 if (data->pipes[1]) |
| 193 close(data->pipes[1]); |
193 close(data->pipes[1]); |
| 194 |
194 |
| 195 free(data); |
195 free(data); |
| 196 } |
196 } |