| 106 } |
119 } |
| 107 irc_send_len(irc, buf, len); |
120 irc_send_len(irc, buf, len); |
| 108 return len; |
121 return len; |
| 109 } |
122 } |
| 110 |
123 |
| 111 static void |
124 static gboolean |
| 112 irc_send_cb(gpointer data, gint source, PurpleInputCondition cond) |
125 irc_send_handler_cb(gpointer data) { |
| 113 { |
126 struct irc_conn *irc = (struct irc_conn *)data; |
| 114 struct irc_conn *irc = data; |
127 gint available = 0; |
| 115 int ret, writelen; |
128 gint interval = 0; |
| 116 |
129 |
| 117 writelen = purple_circ_buffer_get_max_read(irc->outbuf); |
130 interval = purple_account_get_int(irc->account, "ratelimit-interval", |
| 118 |
131 IRC_DEFAULT_COMMAND_INTERVAL); |
| 119 if (writelen == 0) { |
132 |
| 120 purple_input_remove(irc->writeh); |
133 /* Check if we're enabled. */ |
| 121 irc->writeh = 0; |
134 if(interval < 1) { |
| 122 return; |
135 available = G_MAXINT; |
| 123 } |
136 } else { |
| 124 |
137 gint burst = purple_account_get_int(irc->account, "ratelimit-burst", |
| 125 ret = do_send(irc, irc->outbuf->outptr, writelen); |
138 IRC_DEFAULT_COMMAND_MAX_BURST); |
| 126 |
139 available = (time(NULL) - irc->send_time) / interval; |
| 127 if (ret < 0 && errno == EAGAIN) |
140 if(available > burst) { |
| 128 return; |
141 available = burst; |
| 129 else if (ret <= 0) { |
142 } |
| 130 PurpleConnection *gc = purple_account_get_connection(irc->account); |
143 } |
| 131 gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), |
144 |
| 132 g_strerror(errno)); |
145 while(available > 0) { |
| 133 purple_connection_error_reason (gc, |
146 gchar *msg = NULL; |
| 134 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); |
147 gpointer raw = NULL; |
| 135 g_free(tmp); |
148 gint length = 0, ret = 0; |
| 136 return; |
149 |
| 137 } |
150 /* No message in the queue should be NULL, so a NULL value means the |
| 138 |
151 * queue is empty. |
| 139 purple_circ_buffer_mark_read(irc->outbuf, ret); |
152 */ |
| 140 |
153 raw = g_queue_pop_head(irc->send_queue); |
| 141 #if 0 |
154 if(raw == NULL) { |
| 142 /* We *could* try to write more if we wrote it all */ |
155 break; |
| 143 if (ret == write_len) { |
156 } |
| 144 irc_send_cb(data, source, cond); |
157 |
| 145 } |
158 msg = (gchar *)raw; |
| 146 #endif |
159 length = strlen(msg); |
| 147 } |
160 |
| 148 |
161 ret = do_send(irc, msg, length); |
| 149 int irc_send(struct irc_conn *irc, const char *buf) |
162 if(ret <= 0 && errno != EAGAIN) { |
| |
163 PurpleConnection *gc = purple_account_get_connection(irc->account); |
| |
164 gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), |
| |
165 g_strerror(errno)); |
| |
166 |
| |
167 purple_connection_error_reason(gc, |
| |
168 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
| |
169 tmp); |
| |
170 g_free(tmp); |
| |
171 |
| |
172 g_free(msg); |
| |
173 |
| |
174 irc->send_handler = 0; |
| |
175 |
| |
176 return G_SOURCE_REMOVE; |
| |
177 } else if(ret < length) { |
| |
178 gchar *partial = NULL; |
| |
179 |
| |
180 /* The preceeding conditional allows EAGAIN to fall through to |
| |
181 * here so that we can retransmit it. There shouldn't even be a |
| |
182 * case where ret < 0 and != EAGAIN, which is why we have the |
| |
183 * assert. |
| |
184 */ |
| |
185 if(ret < 0) { |
| |
186 if(ret == EAGAIN) { |
| |
187 ret = 0; |
| |
188 } else { |
| |
189 g_assert_not_reached(); |
| |
190 } |
| |
191 } |
| |
192 |
| |
193 /* We need to move past the characters we already wrote and requeue |
| |
194 * the rest of the string. We know ret is less than length, so the |
| |
195 * starting address of msg plus ret can never get outside of the |
| |
196 * string, and likewise, length minus ret will always be < length |
| |
197 * because ret is less than length and if it was somehow negative, |
| |
198 * it has been reset to zero. |
| |
199 */ |
| |
200 partial = g_strndup(msg + ret, length - ret); |
| |
201 |
| |
202 /* requeue the item to the start of the queue */ |
| |
203 g_queue_push_head(irc->send_queue, partial); |
| |
204 irc->sent_partial = TRUE; |
| |
205 } else { |
| |
206 /* We successfully sent a message so decrement the counter. */ |
| |
207 available -= 1; |
| |
208 irc->sent_partial = FALSE; |
| |
209 } |
| |
210 |
| |
211 /* Message was processed successfully or a partial message was |
| |
212 * allocated and requeued so we can free the one we popped off. |
| |
213 */ |
| |
214 g_free(msg); |
| |
215 } |
| |
216 |
| |
217 return G_SOURCE_CONTINUE; |
| |
218 } |
| |
219 |
| |
220 void irc_send(struct irc_conn *irc, const char *buf) |
| 150 { |
221 { |
| 151 return irc_send_len(irc, buf, strlen(buf)); |
222 return irc_send_len(irc, buf, strlen(buf)); |
| 152 } |
223 } |
| 153 |
224 |
| 154 int irc_send_len(struct irc_conn *irc, const char *buf, int buflen) |
225 void |
| 155 { |
226 irc_send_len(struct irc_conn *irc, const char *buf, int buflen) { |
| 156 int ret; |
227 char *tosend = g_strdup(buf); |
| 157 char *tosend = g_strdup(buf); |
|
| 158 |
228 |
| 159 purple_signal_emit(_irc_plugin, "irc-sending-text", purple_account_get_connection(irc->account), &tosend); |
229 purple_signal_emit(_irc_plugin, "irc-sending-text", purple_account_get_connection(irc->account), &tosend); |
| 160 |
230 |
| 161 if (tosend == NULL) |
231 if(tosend == NULL) { |
| 162 return 0; |
232 return; |
| 163 |
233 } |
| 164 if (!purple_strequal(tosend, buf)) { |
234 |
| 165 buflen = strlen(tosend); |
235 if(purple_debug_is_verbose()) { |
| 166 } |
|
| 167 |
|
| 168 if (purple_debug_is_verbose()) { |
|
| 169 char *clean = purple_utf8_salvage(tosend); |
236 char *clean = purple_utf8_salvage(tosend); |
| 170 clean = g_strstrip(clean); |
237 clean = g_strstrip(clean); |
| 171 purple_debug_misc("irc", "<< %s\n", clean); |
238 purple_debug_misc("irc", "<< %s\n", clean); |
| 172 g_free(clean); |
239 g_free(clean); |
| 173 } |
240 } |
| 174 |
241 |
| 175 /* If we're not buffering writes, try to send immediately */ |
242 g_queue_push_tail(irc->send_queue, tosend); |
| 176 if (!irc->writeh) |
|
| 177 ret = do_send(irc, tosend, buflen); |
|
| 178 else { |
|
| 179 ret = -1; |
|
| 180 errno = EAGAIN; |
|
| 181 } |
|
| 182 |
|
| 183 /* purple_debug(PURPLE_DEBUG_MISC, "irc", "sent%s: %s", |
|
| 184 irc->gsc ? " (ssl)" : "", tosend); */ |
|
| 185 if (ret <= 0 && errno != EAGAIN) { |
|
| 186 PurpleConnection *gc = purple_account_get_connection(irc->account); |
|
| 187 gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), |
|
| 188 g_strerror(errno)); |
|
| 189 purple_connection_error_reason (gc, |
|
| 190 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); |
|
| 191 g_free(tmp); |
|
| 192 } else if (ret < buflen) { |
|
| 193 if (ret < 0) |
|
| 194 ret = 0; |
|
| 195 if (!irc->writeh) |
|
| 196 irc->writeh = purple_input_add( |
|
| 197 irc->gsc ? irc->gsc->fd : irc->fd, |
|
| 198 PURPLE_INPUT_WRITE, irc_send_cb, irc); |
|
| 199 purple_circ_buffer_append(irc->outbuf, tosend + ret, |
|
| 200 buflen - ret); |
|
| 201 } |
|
| 202 g_free(tosend); |
|
| 203 return ret; |
|
| 204 } |
243 } |
| 205 |
244 |
| 206 /* XXX I don't like messing directly with these buddies */ |
245 /* XXX I don't like messing directly with these buddies */ |
| 207 gboolean irc_blist_timeout(struct irc_conn *irc) |
246 gboolean irc_blist_timeout(struct irc_conn *irc) |
| 208 { |
247 { |
| 448 |
490 |
| 449 buf = irc_format(irc, "vvvv:", "USER", tmp ? tmp : identname, "*", server, |
491 buf = irc_format(irc, "vvvv:", "USER", tmp ? tmp : identname, "*", server, |
| 450 strlen(realname) ? realname : nickname); |
492 strlen(realname) ? realname : nickname); |
| 451 g_free(tmp); |
493 g_free(tmp); |
| 452 g_free(server); |
494 g_free(server); |
| 453 if (irc_send(irc, buf) < 0) { |
495 if (do_send(irc, buf, strlen(buf)) < 0) { |
| 454 g_free(buf); |
496 g_free(buf); |
| 455 return FALSE; |
497 return FALSE; |
| 456 } |
498 } |
| 457 g_free(buf); |
499 g_free(buf); |
| 458 |
500 |
| 459 buf = irc_format(irc, "vn", "NICK", nickname); |
501 buf = irc_format(irc, "vn", "NICK", nickname); |
| 460 irc->reqnick = g_strdup(nickname); |
502 irc->reqnick = g_strdup(nickname); |
| 461 irc->nickused = FALSE; |
503 irc->nickused = FALSE; |
| 462 if (irc_send(irc, buf) < 0) { |
504 if (do_send(irc, buf, strlen(buf)) < 0) { |
| 463 g_free(buf); |
505 g_free(buf); |
| 464 return FALSE; |
506 return FALSE; |
| 465 } |
507 } |
| 466 g_free(buf); |
508 g_free(buf); |
| 467 |
509 |
| 468 irc->recv_time = time(NULL); |
510 irc->recv_time = time(NULL); |
| |
511 |
| |
512 /* Give ourselves one full burst for startup commands. */ |
| |
513 interval = purple_account_get_int(irc->account, "ratelimit-interval", |
| |
514 IRC_DEFAULT_COMMAND_INTERVAL); |
| |
515 burst = purple_account_get_int(irc->account, "ratelimit-burst", |
| |
516 IRC_DEFAULT_COMMAND_MAX_BURST); |
| |
517 |
| |
518 irc->send_time = time(NULL) - (interval * burst); |
| |
519 irc->send_handler = g_timeout_add_seconds(1, irc_send_handler_cb, irc); |
| 469 |
520 |
| 470 return TRUE; |
521 return TRUE; |
| 471 } |
522 } |
| 472 |
523 |
| 473 static void irc_login_cb_ssl(gpointer data, PurpleSslConnection *gsc, |
524 static void irc_login_cb_ssl(gpointer data, PurpleSslConnection *gsc, |