Mercurial > pidgin
comparison src/protocols/yahoo/yahoo_filexfer.c @ 13200:33bef17125c2
[gaim-migrate @ 15563]
This is the soon-to-be-infamous nonblocking network activity patch that I've been working on. Feel free to yell at me if this makes you unhappy.
committer: Tailor Script <tailor@pidgin.im>
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Thu, 09 Feb 2006 04:17:56 +0000 |
parents | a1d5f154585b |
children | aaeb6ea63c56 |
comparison
equal
deleted
inserted
replaced
13199:d8f238864c88 | 13200:33bef17125c2 |
---|---|
37 gchar *path; | 37 gchar *path; |
38 int port; | 38 int port; |
39 GaimConnection *gc; | 39 GaimConnection *gc; |
40 long expires; | 40 long expires; |
41 gboolean started; | 41 gboolean started; |
42 guchar *txbuf; | |
43 gsize txbuflen; | |
44 gsize txbuf_written; | |
45 guint tx_handler; | |
42 gchar *rxqueue; | 46 gchar *rxqueue; |
43 guint rxlen; | 47 guint rxlen; |
44 }; | 48 }; |
45 | 49 |
46 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) | 50 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) |
47 { | 51 { |
48 if (xd->host) | 52 g_free(xd->host); |
49 g_free(xd->host); | 53 g_free(xd->path); |
50 if (xd->path) | 54 g_free(xd->txbuf); |
51 g_free(xd->path); | 55 if (xd->tx_handler) |
56 gaim_input_remove(xd->tx_handler); | |
52 g_free(xd); | 57 g_free(xd); |
53 } | 58 } |
54 | 59 |
55 static void yahoo_receivefile_connected(gpointer data, gint source, GaimInputCondition condition) | 60 static void yahoo_receivefile_connected(gpointer data, gint source, GaimInputCondition condition) |
56 { | 61 { |
57 GaimXfer *xfer; | 62 GaimXfer *xfer; |
58 struct yahoo_xfer_data *xd; | 63 struct yahoo_xfer_data *xd; |
59 gchar *buf; | 64 int total_len, written; |
60 | 65 |
61 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | 66 gaim_debug(GAIM_DEBUG_INFO, "yahoo", |
62 "AAA - in yahoo_receivefile_connected\n"); | 67 "AAA - in yahoo_receivefile_connected\n"); |
63 if (!(xfer = data)) | 68 if (!(xfer = data)) |
64 return; | 69 return; |
69 xfer->who, _("Unable to connect.")); | 74 xfer->who, _("Unable to connect.")); |
70 gaim_xfer_cancel_remote(xfer); | 75 gaim_xfer_cancel_remote(xfer); |
71 return; | 76 return; |
72 } | 77 } |
73 | 78 |
79 /* The first time we get here, assemble the tx buffer */ | |
80 if (xd->txbuflen == 0) { | |
81 xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", | |
82 xd->path, xd->host); | |
83 xd->txbuflen = strlen(xd->txbuf); | |
84 xd->txbuf_written = 0; | |
85 } | |
86 | |
87 total_len = xd->txbuflen - xd->txbuf_written; | |
88 | |
74 xfer->fd = source; | 89 xfer->fd = source; |
90 | |
91 written = write(xfer->fd, xd->txbuf + xd->txbuf_written, total_len); | |
92 | |
93 if (written < 0 && errno == EAGAIN) | |
94 written = 0; | |
95 else if (written <= 0) { | |
96 gaim_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno); | |
97 gaim_xfer_cancel_remote(xfer); | |
98 return; | |
99 } | |
100 | |
101 if (written < total_len) { | |
102 if (!xd->tx_handler) | |
103 xd->tx_handler = gaim_input_add(source, GAIM_INPUT_WRITE, | |
104 yahoo_receivefile_connected, xfer); | |
105 xd->txbuf_written += written; | |
106 return; | |
107 } | |
108 | |
109 if (xd->tx_handler) | |
110 gaim_input_remove(xd->tx_handler); | |
111 xd->tx_handler = 0; | |
112 g_free(xd->txbuf); | |
113 xd->txbuf = NULL; | |
114 xd->txbuflen = 0; | |
115 | |
75 gaim_xfer_start(xfer, source, NULL, 0); | 116 gaim_xfer_start(xfer, source, NULL, 0); |
76 | 117 |
77 buf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", | 118 } |
78 xd->path, xd->host); | 119 |
79 write(xfer->fd, buf, strlen(buf)); | |
80 g_free(buf); | |
81 | |
82 return; | |
83 } | |
84 | 120 |
85 static void yahoo_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) | 121 static void yahoo_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) |
86 { | 122 { |
87 GaimXfer *xfer; | 123 GaimXfer *xfer; |
88 struct yahoo_xfer_data *xd; | 124 struct yahoo_xfer_data *xd; |
89 struct yahoo_packet *pkt; | 125 int written, total_len; |
90 gchar *size, *post, *buf; | |
91 const char *host; | |
92 int content_length, port; | |
93 GaimConnection *gc; | |
94 GaimAccount *account; | |
95 struct yahoo_data *yd; | |
96 char *filename, *encoded_filename; | |
97 | 126 |
98 gaim_debug(GAIM_DEBUG_INFO, "yahoo", | 127 gaim_debug(GAIM_DEBUG_INFO, "yahoo", |
99 "AAA - in yahoo_sendfile_connected\n"); | 128 "AAA - in yahoo_sendfile_connected\n"); |
100 if (!(xfer = data)) | 129 if (!(xfer = data)) |
101 return; | 130 return; |
102 if (!(xd = xfer->data)) | 131 if (!(xd = xfer->data)) |
103 return; | 132 return; |
104 | 133 |
105 gc = xd->gc; | |
106 account = gaim_connection_get_account(gc); | |
107 yd = gc->proto_data; | |
108 | 134 |
109 if (source < 0) { | 135 if (source < 0) { |
110 gaim_xfer_error(GAIM_XFER_RECEIVE, gaim_xfer_get_account(xfer), | 136 gaim_xfer_error(GAIM_XFER_RECEIVE, gaim_xfer_get_account(xfer), |
111 xfer->who, _("Unable to connect.")); | 137 xfer->who, _("Unable to connect.")); |
112 gaim_xfer_cancel_remote(xfer); | 138 gaim_xfer_cancel_remote(xfer); |
113 return; | 139 return; |
114 } | 140 } |
115 | 141 |
142 /* The first time we get here, assemble the tx buffer */ | |
143 if (xd->txbuflen == 0) { | |
144 struct yahoo_packet *pkt; | |
145 gchar *size, *filename, *encoded_filename, *header; | |
146 guchar *pkt_buf; | |
147 const char *host; | |
148 int port; | |
149 gsize content_length, header_len, pkt_buf_len; | |
150 GaimConnection *gc; | |
151 GaimAccount *account; | |
152 struct yahoo_data *yd; | |
153 | |
154 gc = xd->gc; | |
155 account = gaim_connection_get_account(gc); | |
156 yd = gc->proto_data; | |
157 | |
158 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER, | |
159 YAHOO_STATUS_AVAILABLE, yd->session_id); | |
160 | |
161 size = g_strdup_printf("%" G_GSIZE_FORMAT, gaim_xfer_get_size(xfer)); | |
162 filename = g_path_get_basename(gaim_xfer_get_local_filename(xfer)); | |
163 encoded_filename = yahoo_string_encode(gc, filename, NULL); | |
164 | |
165 yahoo_packet_hash(pkt, "sssss", 0, gaim_connection_get_display_name(gc), | |
166 5, xfer->who, 14, "", 27, encoded_filename, 28, size); | |
167 g_free(size); | |
168 g_free(encoded_filename); | |
169 g_free(filename); | |
170 | |
171 content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt); | |
172 | |
173 pkt_buf_len = yahoo_packet_build(pkt, 8, FALSE, &pkt_buf); | |
174 yahoo_packet_free(pkt); | |
175 | |
176 host = gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST); | |
177 port = gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT); | |
178 header = g_strdup_printf( | |
179 "POST http://%s:%d/notifyft HTTP/1.0\r\n" | |
180 "Content-length: %" G_GSIZE_FORMAT "\r\n" | |
181 "Host: %s:%d\r\n" | |
182 "Cookie: Y=%s; T=%s\r\n" | |
183 "\r\n", | |
184 host, port, content_length + 4 + gaim_xfer_get_size(xfer), | |
185 host, port, yd->cookie_y, yd->cookie_t); | |
186 | |
187 | |
188 header_len = strlen(header); | |
189 | |
190 xd->txbuflen = header_len + pkt_buf_len + 4; | |
191 xd->txbuf = g_malloc(xd->txbuflen); | |
192 | |
193 memcpy(xd->txbuf, header, header_len); | |
194 g_free(header); | |
195 memcpy(xd->txbuf + header_len, pkt_buf, pkt_buf_len); | |
196 g_free(pkt_buf); | |
197 memcpy(xd->txbuf + header_len + pkt_buf_len, "29\xc0\x80", 4); | |
198 | |
199 xd->txbuf_written = 0; | |
200 } | |
201 | |
202 total_len = xd->txbuflen - xd->txbuf_written; | |
203 | |
116 xfer->fd = source; | 204 xfer->fd = source; |
205 | |
206 written = write(xfer->fd, xd->txbuf + xd->txbuf_written, total_len); | |
207 | |
208 if (written < 0 && errno == EAGAIN) | |
209 written = 0; | |
210 else if (written <= 0) { | |
211 gaim_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno); | |
212 gaim_xfer_cancel_remote(xfer); | |
213 return; | |
214 } | |
215 | |
216 if (written < total_len) { | |
217 if (!xd->tx_handler) | |
218 xd->tx_handler = gaim_input_add(source, GAIM_INPUT_WRITE, | |
219 yahoo_sendfile_connected, xfer); | |
220 xd->txbuf_written += written; | |
221 return; | |
222 } | |
223 | |
224 if (xd->tx_handler) | |
225 gaim_input_remove(xd->tx_handler); | |
226 xd->tx_handler = 0; | |
227 g_free(xd->txbuf); | |
228 xd->txbuf = NULL; | |
229 xd->txbuflen = 0; | |
230 | |
117 gaim_xfer_start(xfer, source, NULL, 0); | 231 gaim_xfer_start(xfer, source, NULL, 0); |
118 | |
119 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
120 | |
121 size = g_strdup_printf("%" G_GSIZE_FORMAT, gaim_xfer_get_size(xfer)); | |
122 filename = g_path_get_basename(gaim_xfer_get_local_filename(xfer)); | |
123 encoded_filename = yahoo_string_encode(gc, filename, NULL); | |
124 | |
125 yahoo_packet_hash(pkt, "sssss", 0, gaim_connection_get_display_name(gc), | |
126 5, xfer->who, 14, "", 27, encoded_filename, 28, size); | |
127 | |
128 content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt); | |
129 | |
130 buf = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t); | |
131 | |
132 host = gaim_account_get_string(account, "xfer_host", YAHOO_XFER_HOST); | |
133 port = gaim_account_get_int(account, "xfer_port", YAHOO_XFER_PORT); | |
134 post = g_strdup_printf("POST http://%s:%d/notifyft HTTP/1.0\r\n" | |
135 "Content-length: %" G_GSIZE_FORMAT "\r\n" | |
136 "Host: %s:%d\r\n" | |
137 "Cookie: %s\r\n" | |
138 "\r\n", | |
139 host, port, content_length + 4 + gaim_xfer_get_size(xfer), | |
140 host, port, buf); | |
141 write(xfer->fd, post, strlen(post)); | |
142 | |
143 yahoo_packet_send_special(pkt, xfer->fd, 8); | |
144 yahoo_packet_free(pkt); | |
145 | |
146 write(xfer->fd, "29\xc0\x80", 4); | |
147 | |
148 g_free(size); | |
149 g_free(post); | |
150 g_free(buf); | |
151 g_free(encoded_filename); | |
152 g_free(filename); | |
153 } | 232 } |
154 | 233 |
155 static void yahoo_xfer_init(GaimXfer *xfer) | 234 static void yahoo_xfer_init(GaimXfer *xfer) |
156 { | 235 { |
157 struct yahoo_xfer_data *xfer_data; | 236 struct yahoo_xfer_data *xfer_data; |