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;