Sun, 13 Jan 2013 15:09:02 -0600
Merge revision 33422 from release-2.x.y
|
31609
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
1 | /* $Id: http.c 1036 2010-12-15 00:02:28Z wojtekka $ */ |
| 11360 | 2 | |
| 3 | /* | |
| 4 | * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> | |
| 5 | * | |
| 6 | * This program is free software; you can redistribute it and/or modify | |
| 7 | * it under the terms of the GNU Lesser General Public License Version | |
| 8 | * 2.1 as published by the Free Software Foundation. | |
| 9 | * | |
| 10 | * This program is distributed in the hope that it will be useful, | |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 | * GNU Lesser General Public License for more details. | |
| 14 | * | |
| 15 | * You should have received a copy of the GNU Lesser General Public | |
| 16 | * License along with this program; if not, write to the Free Software | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, |
| 11360 | 18 | * USA. |
| 19 | */ | |
| 20 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
21 | /** |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
22 | * \file http.c |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
23 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
24 | * \brief Obsługa połączeń HTTP |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
25 | */ |
|
29106
51c7b2177e42
Fix all the remaining files for which internal.h doesn't end up being the first include.
Paul Aurich <darkrain42@pidgin.im>
parents:
19859
diff
changeset
|
26 | |
| 11360 | 27 | #include <sys/types.h> |
| 28 | ||
|
31826
0f6ab56fbf9d
Update libgadu to 0.11.0 plus local changes; thanks to Tomasz Wasilczyk.
Ethan Blanton <elb@pidgin.im>
parents:
31609
diff
changeset
|
29 | #include "compat.h" |
|
0f6ab56fbf9d
Update libgadu to 0.11.0 plus local changes; thanks to Tomasz Wasilczyk.
Ethan Blanton <elb@pidgin.im>
parents:
31609
diff
changeset
|
30 | #include "libgadu.h" |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
31 | #include "resolver.h" |
| 11360 | 32 | |
| 33 | #include <ctype.h> | |
| 34 | #include <errno.h> | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
35 | #include <signal.h> |
| 11360 | 36 | #include <stdarg.h> |
| 37 | #include <stdio.h> | |
| 38 | #include <stdlib.h> | |
| 39 | #include <string.h> | |
| 40 | #include <unistd.h> | |
| 41 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
42 | /** |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
43 | * Rozpoczyna połączenie HTTP. |
| 11360 | 44 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
45 | * Funkcja przeprowadza połączenie HTTP przy połączeniu synchronicznym, |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
46 | * zwracając wynik w polach struktury \c gg_http, lub błąd, gdy sesja się |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
47 | * nie powiedzie. |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
48 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
49 | * Przy połączeniu asynchronicznym, funkcja rozpoczyna połączenie, a dalsze |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
50 | * etapy będą przeprowadzane po wykryciu zmian (\c watch) na obserwowanym |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
51 | * deskryptorze (\c fd) i wywołaniu funkcji \c gg_http_watch_fd(). |
| 11360 | 52 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
53 | * Po zakończeniu, należy zwolnić strukturę za pomocą funkcji |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
54 | * \c gg_http_free(). Połączenie asynchroniczne można zatrzymać w każdej |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
55 | * chwili za pomocą \c gg_http_stop(). |
| 11360 | 56 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
57 | * \param hostname Adres serwera |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
58 | * \param port Port serwera |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
59 | * \param async Flaga asynchronicznego połączenia |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
60 | * \param method Metoda HTTP |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
61 | * \param path Ścieżka do zasobu (musi być poprzedzona znakiem '/') |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
62 | * \param header Nagłówek zapytania plus ewentualne dane dla POST |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
63 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
64 | * \return Zaalokowana struktura \c gg_http lub NULL, jeśli wystąpił błąd. |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
65 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
66 | * \ingroup http |
| 11360 | 67 | */ |
| 68 | struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header) | |
| 69 | { | |
| 70 | struct gg_http *h; | |
| 71 | ||
| 72 | if (!hostname || !port || !method || !path || !header) { | |
| 73 | gg_debug(GG_DEBUG_MISC, "// gg_http_connect() invalid arguments\n"); | |
| 74 | errno = EFAULT; | |
| 75 | return NULL; | |
| 76 | } | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
77 | |
| 11360 | 78 | if (!(h = malloc(sizeof(*h)))) |
| 79 | return NULL; | |
| 80 | memset(h, 0, sizeof(*h)); | |
| 81 | ||
| 82 | h->async = async; | |
| 83 | h->port = port; | |
| 84 | h->fd = -1; | |
| 85 | h->type = GG_SESSION_HTTP; | |
| 86 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
87 | gg_http_set_resolver(h, GG_RESOLVER_DEFAULT); |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
88 | |
| 11360 | 89 | if (gg_proxy_enabled) { |
| 90 | char *auth = gg_proxy_auth(); | |
| 91 | ||
| 92 | h->query = gg_saprintf("%s http://%s:%d%s HTTP/1.0\r\n%s%s", | |
| 93 | method, hostname, port, path, (auth) ? auth : | |
| 94 | "", header); | |
| 95 | hostname = gg_proxy_host; | |
| 96 | h->port = port = gg_proxy_port; | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
97 | free(auth); |
| 11360 | 98 | |
| 99 | } else { | |
| 100 | h->query = gg_saprintf("%s %s HTTP/1.0\r\n%s", | |
| 101 | method, path, header); | |
| 102 | } | |
| 103 | ||
| 104 | if (!h->query) { | |
| 105 | gg_debug(GG_DEBUG_MISC, "// gg_http_connect() not enough memory for query\n"); | |
| 106 | free(h); | |
| 107 | errno = ENOMEM; | |
| 108 | return NULL; | |
| 109 | } | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
110 | |
| 11360 | 111 | gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", h->query); |
| 112 | ||
| 113 | if (async) { | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
114 | if (h->resolver_start(&h->fd, &h->resolver, hostname) == -1) { |
| 11360 | 115 | gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver failed\n"); |
| 116 | gg_http_free(h); | |
| 117 | errno = ENOENT; | |
| 118 | return NULL; | |
| 119 | } | |
| 120 | ||
| 121 | gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver = %p\n", h->resolver); | |
| 122 | ||
| 123 | h->state = GG_STATE_RESOLVING; | |
| 124 | h->check = GG_CHECK_READ; | |
| 125 | h->timeout = GG_DEFAULT_TIMEOUT; | |
| 126 | } else { | |
|
31609
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
127 | struct in_addr *addr_list = NULL; |
|
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
128 | int addr_count; |
| 11360 | 129 | |
|
31609
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
130 | if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, 0) == -1 || addr_count == 0) { |
| 11360 | 131 | gg_debug(GG_DEBUG_MISC, "// gg_http_connect() host not found\n"); |
| 132 | gg_http_free(h); | |
|
31609
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
133 | free(addr_list); |
| 11360 | 134 | errno = ENOENT; |
| 135 | return NULL; | |
| 136 | } | |
| 137 | ||
|
31609
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
138 | if ((h->fd = gg_connect(&addr_list[0], port, 0)) == -1) { |
| 11360 | 139 | gg_debug(GG_DEBUG_MISC, "// gg_http_connect() connection failed (errno=%d, %s)\n", errno, strerror(errno)); |
| 140 | gg_http_free(h); | |
|
31609
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
141 | free(addr_list); |
| 11360 | 142 | return NULL; |
| 143 | } | |
| 144 | ||
|
31609
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
145 | free(addr_list); |
|
d67fbc90b28a
matekm and kkszysiu collaborated on this patch to update our internal libgadu
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29752
diff
changeset
|
146 | |
| 11360 | 147 | h->state = GG_STATE_CONNECTING; |
| 148 | ||
| 149 | while (h->state != GG_STATE_ERROR && h->state != GG_STATE_PARSING) { | |
| 150 | if (gg_http_watch_fd(h) == -1) | |
| 151 | break; | |
| 152 | } | |
| 153 | ||
| 154 | if (h->state != GG_STATE_PARSING) { | |
| 155 | gg_debug(GG_DEBUG_MISC, "// gg_http_connect() some strange error\n"); | |
| 156 | gg_http_free(h); | |
| 157 | return NULL; | |
| 158 | } | |
| 159 | } | |
| 160 | ||
| 161 | h->callback = gg_http_watch_fd; | |
| 162 | h->destroy = gg_http_free; | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
163 | |
| 11360 | 164 | return h; |
| 165 | } | |
| 166 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
167 | #ifndef DOXYGEN |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
168 | |
| 11360 | 169 | #define gg_http_error(x) \ |
| 170 | close(h->fd); \ | |
| 171 | h->fd = -1; \ | |
| 172 | h->state = GG_STATE_ERROR; \ | |
| 173 | h->error = x; \ | |
| 174 | return 0; | |
| 175 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
176 | #endif /* DOXYGEN */ |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
177 | |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
178 | /** |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
179 | * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia. |
| 11360 | 180 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
181 | * Operacja będzie zakończona, gdy pole \c state będzie równe |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
182 | * \c GG_STATE_PARSING. W tym miejscu działanie przejmuje zwykle funkcja |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
183 | * korzystająca z \c gg_http_watch_fd(). W przypadku błędu połączenia, |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
184 | * pole \c state będzie równe \c GG_STATE_ERROR, a kod błędu znajdzie się |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
185 | * w polu \c error. |
| 11360 | 186 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
187 | * \param h Struktura połączenia |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
188 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
189 | * \return \return 0 jeśli się powiodło, -1 w przypadku błędu |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
190 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
191 | * \ingroup http |
| 11360 | 192 | */ |
| 193 | int gg_http_watch_fd(struct gg_http *h) | |
| 194 | { | |
| 195 | gg_debug(GG_DEBUG_FUNCTION, "** gg_http_watch_fd(%p);\n", h); | |
| 196 | ||
| 197 | if (!h) { | |
| 198 | gg_debug(GG_DEBUG_MISC, "// gg_http_watch_fd() invalid arguments\n"); | |
| 199 | errno = EFAULT; | |
| 200 | return -1; | |
| 201 | } | |
| 202 | ||
| 203 | if (h->state == GG_STATE_RESOLVING) { | |
| 204 | struct in_addr a; | |
| 205 | ||
| 206 | gg_debug(GG_DEBUG_MISC, "=> http, resolving done\n"); | |
| 207 | ||
| 208 | if (read(h->fd, &a, sizeof(a)) < (signed)sizeof(a) || a.s_addr == INADDR_NONE) { | |
| 209 | gg_debug(GG_DEBUG_MISC, "=> http, resolver thread failed\n"); | |
| 210 | gg_http_error(GG_ERROR_RESOLVING); | |
| 211 | } | |
| 212 | ||
| 213 | close(h->fd); | |
| 214 | h->fd = -1; | |
| 215 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
216 | h->resolver_cleanup(&h->resolver, 0); |
| 11360 | 217 | |
| 218 | gg_debug(GG_DEBUG_MISC, "=> http, connecting to %s:%d\n", inet_ntoa(a), h->port); | |
| 219 | ||
| 220 | if ((h->fd = gg_connect(&a, h->port, h->async)) == -1) { | |
| 221 | gg_debug(GG_DEBUG_MISC, "=> http, connection failed (errno=%d, %s)\n", errno, strerror(errno)); | |
| 222 | gg_http_error(GG_ERROR_CONNECTING); | |
| 223 | } | |
| 224 | ||
| 225 | h->state = GG_STATE_CONNECTING; | |
| 226 | h->check = GG_CHECK_WRITE; | |
| 227 | h->timeout = GG_DEFAULT_TIMEOUT; | |
| 228 | ||
| 229 | return 0; | |
| 230 | } | |
| 231 | ||
| 232 | if (h->state == GG_STATE_CONNECTING) { | |
| 233 | int res = 0; | |
|
29752
5cb6314b2477
Partially fix libgadu build on Win32. Refs #10542. I'm still not sure how to
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29751
diff
changeset
|
234 | socklen_t res_size = sizeof(res); |
| 11360 | 235 | |
| 236 | if (h->async && (getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { | |
| 237 | gg_debug(GG_DEBUG_MISC, "=> http, async connection failed (errno=%d, %s)\n", (res) ? res : errno , strerror((res) ? res : errno)); | |
| 238 | close(h->fd); | |
| 239 | h->fd = -1; | |
| 240 | h->state = GG_STATE_ERROR; | |
| 241 | h->error = GG_ERROR_CONNECTING; | |
| 242 | if (res) | |
| 243 | errno = res; | |
| 244 | return 0; | |
| 245 | } | |
| 246 | ||
| 247 | gg_debug(GG_DEBUG_MISC, "=> http, connected, sending request\n"); | |
| 248 | ||
| 249 | h->state = GG_STATE_SENDING_QUERY; | |
| 250 | } | |
| 251 | ||
| 252 | if (h->state == GG_STATE_SENDING_QUERY) { | |
|
32675
a8ba546a18bc
Gadu-Gadu: synchronize internal libgadu with upstream. Refs #343
Tomasz Wasilczyk <tomkiewicz@cpw.pidgin.im>
parents:
31826
diff
changeset
|
253 | ssize_t res; |
| 11360 | 254 | |
| 255 | if ((res = write(h->fd, h->query, strlen(h->query))) < 1) { | |
| 256 | gg_debug(GG_DEBUG_MISC, "=> http, write() failed (len=%d, res=%d, errno=%d)\n", strlen(h->query), res, errno); | |
| 257 | gg_http_error(GG_ERROR_WRITING); | |
| 258 | } | |
| 259 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
260 | if (res < strlen(h->query)) { |
| 11360 | 261 | gg_debug(GG_DEBUG_MISC, "=> http, partial header sent (led=%d, sent=%d)\n", strlen(h->query), res); |
| 262 | ||
| 263 | memmove(h->query, h->query + res, strlen(h->query) - res + 1); | |
| 264 | h->state = GG_STATE_SENDING_QUERY; | |
| 265 | h->check = GG_CHECK_WRITE; | |
| 266 | h->timeout = GG_DEFAULT_TIMEOUT; | |
| 267 | } else { | |
| 268 | gg_debug(GG_DEBUG_MISC, "=> http, request sent (len=%d)\n", strlen(h->query)); | |
| 269 | free(h->query); | |
| 270 | h->query = NULL; | |
| 271 | ||
| 272 | h->state = GG_STATE_READING_HEADER; | |
| 273 | h->check = GG_CHECK_READ; | |
| 274 | h->timeout = GG_DEFAULT_TIMEOUT; | |
| 275 | } | |
| 276 | ||
| 277 | return 0; | |
| 278 | } | |
| 279 | ||
| 280 | if (h->state == GG_STATE_READING_HEADER) { | |
| 281 | char buf[1024], *tmp; | |
| 282 | int res; | |
| 283 | ||
| 284 | if ((res = read(h->fd, buf, sizeof(buf))) == -1) { | |
| 285 | gg_debug(GG_DEBUG_MISC, "=> http, reading header failed (errno=%d)\n", errno); | |
| 286 | if (h->header) { | |
| 287 | free(h->header); | |
| 288 | h->header = NULL; | |
| 289 | } | |
| 290 | gg_http_error(GG_ERROR_READING); | |
| 291 | } | |
| 292 | ||
| 293 | if (!res) { | |
| 294 | gg_debug(GG_DEBUG_MISC, "=> http, connection reset by peer\n"); | |
| 295 | if (h->header) { | |
| 296 | free(h->header); | |
| 297 | h->header = NULL; | |
| 298 | } | |
| 299 | gg_http_error(GG_ERROR_READING); | |
| 300 | } | |
| 301 | ||
| 302 | gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of header\n", res); | |
| 303 | ||
| 304 | if (!(tmp = realloc(h->header, h->header_size + res + 1))) { | |
| 305 | gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for header\n"); | |
| 306 | free(h->header); | |
| 307 | h->header = NULL; | |
| 308 | gg_http_error(GG_ERROR_READING); | |
| 309 | } | |
| 310 | ||
| 311 | h->header = tmp; | |
| 312 | ||
| 313 | memcpy(h->header + h->header_size, buf, res); | |
| 314 | h->header_size += res; | |
| 315 | ||
| 316 | gg_debug(GG_DEBUG_MISC, "=> http, header_buf=%p, header_size=%d\n", h->header, h->header_size); | |
| 317 | ||
| 318 | h->header[h->header_size] = 0; | |
| 319 | ||
| 320 | if ((tmp = strstr(h->header, "\r\n\r\n")) || (tmp = strstr(h->header, "\n\n"))) { | |
| 321 | int sep_len = (*tmp == '\r') ? 4 : 2; | |
| 322 | unsigned int left; | |
| 323 | char *line; | |
| 324 | ||
| 325 | left = h->header_size - ((long)(tmp) - (long)(h->header) + sep_len); | |
| 326 | ||
| 327 | gg_debug(GG_DEBUG_MISC, "=> http, got all header (%d bytes, %d left)\n", h->header_size - left, left); | |
| 328 | ||
| 329 | /* HTTP/1.1 200 OK */ | |
| 330 | if (strlen(h->header) < 16 || strncmp(h->header + 9, "200", 3)) { | |
| 331 | gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header); | |
| 332 | ||
| 333 | gg_debug(GG_DEBUG_MISC, "=> http, didn't get 200 OK -- no results\n"); | |
| 334 | free(h->header); | |
| 335 | h->header = NULL; | |
| 336 | gg_http_error(GG_ERROR_CONNECTING); | |
| 337 | } | |
| 338 | ||
| 339 | h->body_size = 0; | |
| 340 | line = h->header; | |
| 341 | *tmp = 0; | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
342 | |
| 11360 | 343 | gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header); |
| 344 | ||
| 345 | while (line) { | |
|
18565
6cf6fd1e3d53
Once again revert the g_ascii_strncasecmp/g_ascii_strncasecmp changes here.
Richard Laager <rlaager@pidgin.im>
parents:
18552
diff
changeset
|
346 | if (!strncasecmp(line, "Content-length: ", 16)) { |
| 11360 | 347 | h->body_size = atoi(line + 16); |
| 348 | } | |
| 349 | line = strchr(line, '\n'); | |
| 350 | if (line) | |
| 351 | line++; | |
| 352 | } | |
| 353 | ||
| 354 | if (h->body_size <= 0) { | |
| 355 | gg_debug(GG_DEBUG_MISC, "=> http, content-length not found\n"); | |
| 356 | h->body_size = left; | |
| 357 | } | |
| 358 | ||
| 359 | if (left > h->body_size) { | |
| 360 | gg_debug(GG_DEBUG_MISC, "=> http, oversized reply (%d bytes needed, %d bytes left)\n", h->body_size, left); | |
| 361 | h->body_size = left; | |
| 362 | } | |
| 363 | ||
| 364 | gg_debug(GG_DEBUG_MISC, "=> http, body_size=%d\n", h->body_size); | |
| 365 | ||
| 366 | if (!(h->body = malloc(h->body_size + 1))) { | |
| 367 | gg_debug(GG_DEBUG_MISC, "=> http, not enough memory (%d bytes for body_buf)\n", h->body_size + 1); | |
| 368 | free(h->header); | |
| 369 | h->header = NULL; | |
| 370 | gg_http_error(GG_ERROR_READING); | |
| 371 | } | |
| 372 | ||
| 373 | if (left) { | |
| 374 | memcpy(h->body, tmp + sep_len, left); | |
| 375 | h->body_done = left; | |
| 376 | } | |
| 377 | ||
| 378 | h->body[left] = 0; | |
| 379 | ||
| 380 | h->state = GG_STATE_READING_DATA; | |
| 381 | h->check = GG_CHECK_READ; | |
| 382 | h->timeout = GG_DEFAULT_TIMEOUT; | |
| 383 | } | |
| 384 | ||
| 385 | return 0; | |
| 386 | } | |
| 387 | ||
| 388 | if (h->state == GG_STATE_READING_DATA) { | |
| 389 | char buf[1024]; | |
| 390 | int res; | |
| 391 | ||
| 392 | if ((res = read(h->fd, buf, sizeof(buf))) == -1) { | |
| 393 | gg_debug(GG_DEBUG_MISC, "=> http, reading body failed (errno=%d)\n", errno); | |
| 394 | if (h->body) { | |
| 395 | free(h->body); | |
| 396 | h->body = NULL; | |
| 397 | } | |
| 398 | gg_http_error(GG_ERROR_READING); | |
| 399 | } | |
| 400 | ||
| 401 | if (!res) { | |
| 402 | if (h->body_done >= h->body_size) { | |
| 403 | gg_debug(GG_DEBUG_MISC, "=> http, we're done, closing socket\n"); | |
| 404 | h->state = GG_STATE_PARSING; | |
| 405 | close(h->fd); | |
| 406 | h->fd = -1; | |
| 407 | } else { | |
| 408 | gg_debug(GG_DEBUG_MISC, "=> http, connection closed while reading (have %d, need %d)\n", h->body_done, h->body_size); | |
| 409 | if (h->body) { | |
| 410 | free(h->body); | |
| 411 | h->body = NULL; | |
| 412 | } | |
| 413 | gg_http_error(GG_ERROR_READING); | |
| 414 | } | |
| 415 | ||
| 416 | return 0; | |
| 417 | } | |
| 418 | ||
| 419 | gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of body\n", res); | |
| 420 | ||
| 421 | if (h->body_done + res > h->body_size) { | |
| 422 | char *tmp; | |
| 423 | ||
| 424 | gg_debug(GG_DEBUG_MISC, "=> http, too much data (%d bytes, %d needed), enlarging buffer\n", h->body_done + res, h->body_size); | |
| 425 | ||
| 426 | if (!(tmp = realloc(h->body, h->body_done + res + 1))) { | |
| 427 | gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for data (%d needed)\n", h->body_done + res + 1); | |
| 428 | free(h->body); | |
| 429 | h->body = NULL; | |
| 430 | gg_http_error(GG_ERROR_READING); | |
| 431 | } | |
| 432 | ||
| 433 | h->body = tmp; | |
| 434 | h->body_size = h->body_done + res; | |
| 435 | } | |
| 436 | ||
| 437 | h->body[h->body_done + res] = 0; | |
| 438 | memcpy(h->body + h->body_done, buf, res); | |
| 439 | h->body_done += res; | |
| 440 | ||
| 441 | gg_debug(GG_DEBUG_MISC, "=> body_done=%d, body_size=%d\n", h->body_done, h->body_size); | |
| 442 | ||
| 443 | return 0; | |
| 444 | } | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
445 | |
| 11360 | 446 | if (h->fd != -1) |
| 447 | close(h->fd); | |
| 448 | ||
| 449 | h->fd = -1; | |
| 450 | h->state = GG_STATE_ERROR; | |
| 451 | h->error = 0; | |
| 452 | ||
| 453 | return -1; | |
| 454 | } | |
| 455 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
456 | /** |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
457 | * Kończy asynchroniczne połączenie HTTP. |
| 11360 | 458 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
459 | * Po zatrzymaniu należy zwolnić zasoby funkcją \c gg_http_free(). |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
460 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
461 | * \param h Struktura połączenia |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
462 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
463 | * \ingroup http |
| 11360 | 464 | */ |
| 465 | void gg_http_stop(struct gg_http *h) | |
| 466 | { | |
| 467 | if (!h) | |
| 468 | return; | |
| 469 | ||
| 470 | if (h->state == GG_STATE_ERROR || h->state == GG_STATE_DONE) | |
| 471 | return; | |
| 472 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
473 | if (h->fd != -1) { |
| 11360 | 474 | close(h->fd); |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
475 | h->fd = -1; |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
476 | } |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
477 | |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
478 | h->resolver_cleanup(&h->resolver, 1); |
| 11360 | 479 | } |
| 480 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
481 | /** |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
482 | * \internal Zwalnia pola struktury \c gg_http. |
| 11360 | 483 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
484 | * Funkcja zwalnia same pola, nie zwalnia struktury. |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
485 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
486 | * \param h Struktura połączenia |
| 11360 | 487 | */ |
| 488 | void gg_http_free_fields(struct gg_http *h) | |
| 489 | { | |
| 490 | if (!h) | |
| 491 | return; | |
| 492 | ||
| 493 | if (h->body) { | |
| 494 | free(h->body); | |
| 495 | h->body = NULL; | |
| 496 | } | |
| 497 | ||
| 498 | if (h->query) { | |
| 499 | free(h->query); | |
| 500 | h->query = NULL; | |
| 501 | } | |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
502 | |
| 11360 | 503 | if (h->header) { |
| 504 | free(h->header); | |
| 505 | h->header = NULL; | |
| 506 | } | |
| 507 | } | |
| 508 | ||
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
509 | /** |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
510 | * Zwalnia zasoby po połączeniu HTTP. |
| 11360 | 511 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
512 | * Jeśli połączenie nie zostało jeszcze zakończone, jest przerywane. |
| 11360 | 513 | * |
|
29751
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
514 | * \param h Struktura połączenia |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
515 | * |
|
438f88ecc11e
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
29106
diff
changeset
|
516 | * \ingroup http |
| 11360 | 517 | */ |
| 518 | void gg_http_free(struct gg_http *h) | |
| 519 | { | |
| 520 | if (!h) | |
| 521 | return; | |
| 522 | ||
| 523 | gg_http_stop(h); | |
| 524 | gg_http_free_fields(h); | |
| 525 | free(h); | |
| 526 | } | |
| 527 | ||
| 528 | /* | |
| 529 | * Local variables: | |
| 530 | * c-indentation-style: k&r | |
| 531 | * c-basic-offset: 8 | |
| 532 | * indent-tabs-mode: notnil | |
| 533 | * End: | |
| 534 | * | |
| 535 | * vim: shiftwidth=8: | |
| 536 | */ |