| 126 SilcPurple sg = gc->proto_data; |
126 SilcPurple sg = gc->proto_data; |
| 127 silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0, |
127 silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0, |
| 128 NULL, 0); |
128 NULL, 0); |
| 129 } |
129 } |
| 130 |
130 |
| |
131 #if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1) |
| 131 static gboolean |
132 static gboolean |
| 132 silcpurple_scheduler(gpointer *context) |
133 silcpurple_scheduler(gpointer *context) |
| 133 { |
134 { |
| 134 SilcClient client = (SilcClient)context; |
135 SilcClient client = (SilcClient)context; |
| 135 silc_client_run_one(client); |
136 silc_client_run_one(client); |
| 136 return TRUE; |
137 return TRUE; |
| 137 } |
138 } |
| |
139 #else |
| |
140 typedef struct { |
| |
141 SilcPurple sg; |
| |
142 SilcUInt32 fd; |
| |
143 guint tag; |
| |
144 } *SilcPurpleTask; |
| |
145 |
| |
146 /* A timeout occurred. Call SILC scheduler. */ |
| |
147 |
| |
148 static gboolean |
| |
149 silcpurple_scheduler_timeout(gpointer context) |
| |
150 { |
| |
151 SilcPurpleTask task = (SilcPurpleTask)context; |
| |
152 silc_client_run_one(task->sg->client); |
| |
153 silc_dlist_del(task->sg->tasks, task); |
| |
154 silc_free(task); |
| |
155 return FALSE; |
| |
156 } |
| |
157 |
| |
158 /* An fd task event occurred. Call SILC scheduler. */ |
| |
159 |
| |
160 static void |
| |
161 silcpurple_scheduler_fd(gpointer data, gint fd, PurpleInputCondition cond) |
| |
162 { |
| |
163 SilcClient client = (SilcClient)data; |
| |
164 silc_client_run_one(client); |
| |
165 } |
| |
166 |
| |
167 /* SILC Scheduler notify callback. This is called whenever task is added to |
| |
168 or deleted from SILC scheduler. It's also called when fd task events |
| |
169 change. Here we add same tasks to glib's main loop. */ |
| |
170 |
| |
171 static void |
| |
172 silcpurple_scheduler(SilcSchedule schedule, |
| |
173 SilcBool added, SilcTask task, |
| |
174 SilcBool fd_task, SilcUInt32 fd, |
| |
175 SilcTaskEvent event, |
| |
176 long seconds, long useconds, |
| |
177 void *context) |
| |
178 { |
| |
179 SilcClient client = (SilcClient)context; |
| |
180 PurpleConnection *gc = client->application; |
| |
181 SilcPurple sg = gc->proto_data; |
| |
182 SilcPurpleTask ptask = NULL; |
| |
183 |
| |
184 if (added) { |
| |
185 if (fd_task) { |
| |
186 /* Add fd or change fd events */ |
| |
187 PurpleInputCondition e = 0; |
| |
188 |
| |
189 silc_dlist_start(sg->tasks); |
| |
190 while ((ptask = silc_dlist_get(sg->tasks))) |
| |
191 if (ptask->fd == fd) { |
| |
192 purple_input_remove(ptask->tag); |
| |
193 break; |
| |
194 } |
| |
195 |
| |
196 if (event & SILC_TASK_READ) |
| |
197 e |= PURPLE_INPUT_READ; |
| |
198 if (event & SILC_TASK_WRITE) |
| |
199 e |= PURPLE_INPUT_WRITE; |
| |
200 |
| |
201 if (e) { |
| |
202 if (!ptask) { |
| |
203 ptask = silc_calloc(1, sizeof(*ptask)); |
| |
204 ptask->fd = fd; |
| |
205 silc_dlist_add(sg->tasks, ptask); |
| |
206 } |
| |
207 ptask->tag = purple_input_add(fd, e, silcpurple_scheduler_fd, |
| |
208 client); |
| |
209 } else if (ptask) { |
| |
210 silc_dlist_del(sg->tasks, ptask); |
| |
211 silc_free(ptask); |
| |
212 } |
| |
213 } else { |
| |
214 /* Add timeout */ |
| |
215 ptask = silc_calloc(1, sizeof(*ptask)); |
| |
216 ptask->sg = sg; |
| |
217 ptask->tag = purple_timeout_add((seconds * 1000) + |
| |
218 (useconds / 1000), |
| |
219 silcpurple_scheduler_timeout, |
| |
220 ptask); |
| |
221 silc_dlist_add(sg->tasks, ptask); |
| |
222 } |
| |
223 } else { |
| |
224 if (fd_task) { |
| |
225 /* Remove fd */ |
| |
226 silc_dlist_start(sg->tasks); |
| |
227 while ((ptask = silc_dlist_get(sg->tasks))) |
| |
228 if (ptask->fd == fd) { |
| |
229 purple_input_remove(ptask->tag); |
| |
230 silc_dlist_del(sg->tasks, ptask); |
| |
231 silc_free(ptask); |
| |
232 break; |
| |
233 } |
| |
234 } |
| |
235 } |
| |
236 } |
| |
237 #endif /* __SILC_TOOLKIT_VERSION */ |
| 138 |
238 |
| 139 static void |
239 static void |
| 140 silcpurple_connect_cb(SilcClient client, SilcClientConnection conn, |
240 silcpurple_connect_cb(SilcClient client, SilcClientConnection conn, |
| 141 SilcClientConnectionStatus status, SilcStatus error, |
241 SilcClientConnectionStatus status, SilcStatus error, |
| 142 const char *message, void *context) |
242 const char *message, void *context) |
| 314 silc_free(sg); |
414 silc_free(sg); |
| 315 gc->proto_data = NULL; |
415 gc->proto_data = NULL; |
| 316 return; |
416 return; |
| 317 } |
417 } |
| 318 |
418 |
| |
419 silc_hash_alloc("sha1", &sg->sha1hash); |
| |
420 |
| 319 /* Wrap socket to TCP stream */ |
421 /* Wrap socket to TCP stream */ |
| 320 silc_socket_tcp_stream_create(source, TRUE, FALSE, |
422 silc_socket_tcp_stream_create(source, TRUE, FALSE, |
| 321 sg->client->schedule, |
423 sg->client->schedule, |
| 322 silcpurple_stream_created, gc); |
424 silcpurple_stream_created, gc); |
| 323 } |
425 } |
| 324 |
426 |
| 325 static void silcpurple_running(SilcClient client, void *context) |
427 static void silcpurple_running(SilcClient client, void *context) |
| 326 { |
428 { |
| 327 PurpleAccount *account = context; |
429 SilcPurple sg = context; |
| 328 PurpleConnection *gc = account->gc; |
430 PurpleConnection *gc = sg->gc; |
| 329 SilcPurple sg; |
431 PurpleAccount *account = purple_connection_get_account(gc); |
| 330 char pkd[256], prd[256]; |
432 char pkd[256], prd[256]; |
| 331 |
|
| 332 sg = silc_calloc(1, sizeof(*sg)); |
|
| 333 if (!sg) |
|
| 334 return; |
|
| 335 memset(sg, 0, sizeof(*sg)); |
|
| 336 sg->client = client; |
|
| 337 sg->gc = gc; |
|
| 338 sg->account = account; |
|
| 339 sg->scheduler = SILC_PTR_TO_32(gc->proto_data); |
|
| 340 gc->proto_data = sg; |
|
| 341 |
433 |
| 342 /* Progress */ |
434 /* Progress */ |
| 343 purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5); |
435 purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5); |
| 344 |
436 |
| 345 /* Load SILC key pair */ |
437 /* Load SILC key pair */ |
| 429 if (!strcmp(silc_default_hmacs[i].name, hmac)) { |
521 if (!strcmp(silc_default_hmacs[i].name, hmac)) { |
| 430 silc_hmac_register(&(silc_default_hmacs[i])); |
522 silc_hmac_register(&(silc_default_hmacs[i])); |
| 431 break; |
523 break; |
| 432 } |
524 } |
| 433 |
525 |
| |
526 sg = silc_calloc(1, sizeof(*sg)); |
| |
527 if (!sg) |
| |
528 return; |
| |
529 sg->client = client; |
| |
530 sg->gc = gc; |
| |
531 sg->account = account; |
| |
532 gc->proto_data = sg; |
| |
533 |
| 434 /* Init SILC client */ |
534 /* Init SILC client */ |
| 435 if (!silc_client_init(client, username, hostname, realname, |
535 if (!silc_client_init(client, username, hostname, realname, |
| 436 silcpurple_running, account)) { |
536 silcpurple_running, sg)) { |
| 437 gc->wants_to_die = TRUE; |
537 gc->wants_to_die = TRUE; |
| 438 purple_connection_error(gc, _("Cannot initialize SILC protocol")); |
538 purple_connection_error(gc, _("Cannot initialize SILC protocol")); |
| |
539 gc->proto_data = NULL; |
| |
540 silc_free(sg); |
| 439 return; |
541 return; |
| 440 } |
542 } |
| 441 |
543 |
| 442 /* Check the ~/.silc dir and create it, and new key pair if necessary. */ |
544 /* Check the ~/.silc dir and create it, and new key pair if necessary. */ |
| 443 if (!silcpurple_check_silc_dir(gc)) { |
545 if (!silcpurple_check_silc_dir(gc)) { |
| 444 gc->wants_to_die = TRUE; |
546 gc->wants_to_die = TRUE; |
| 445 purple_connection_error(gc, _("Error loading SILC key pair")); |
547 purple_connection_error(gc, _("Error loading SILC key pair")); |
| 446 return; |
548 gc->proto_data = NULL; |
| 447 } |
549 silc_free(sg); |
| 448 |
550 return; |
| |
551 } |
| |
552 |
| |
553 #if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1) |
| 449 /* Schedule SILC using Glib's event loop */ |
554 /* Schedule SILC using Glib's event loop */ |
| 450 scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client); |
555 sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client); |
| 451 gc->proto_data = SILC_32_TO_PTR(scheduler); |
556 #else |
| |
557 /* Run SILC scheduler */ |
| |
558 sg->tasks = silc_dlist_init(); |
| |
559 silc_schedule_set_notify(client->schedule, silcpurple_scheduler, |
| |
560 client); |
| |
561 silc_client_run_one(client); |
| |
562 #endif /* __SILC_TOOLKIT_VERSION */ |
| 452 } |
563 } |
| 453 |
564 |
| 454 static int |
565 static int |
| 455 silcpurple_close_final(gpointer *context) |
566 silcpurple_close_final(gpointer *context) |
| 456 { |
567 { |
| 457 SilcPurple sg = (SilcPurple)context; |
568 SilcPurple sg = (SilcPurple)context; |
| |
569 |
| 458 silc_client_stop(sg->client, NULL, NULL); |
570 silc_client_stop(sg->client, NULL, NULL); |
| 459 silc_client_free(sg->client); |
571 silc_client_free(sg->client); |
| |
572 if (sg->sha1hash) |
| |
573 silc_hash_free(sg->sha1hash); |
| 460 if (sg->mimeass) |
574 if (sg->mimeass) |
| 461 silc_mime_assembler_free(sg->mimeass); |
575 silc_mime_assembler_free(sg->mimeass); |
| 462 silc_free(sg); |
576 silc_free(sg); |
| 463 return 0; |
577 return 0; |
| 464 } |
578 } |
| 465 |
579 |
| 466 static void |
580 static void |
| 467 silcpurple_close(PurpleConnection *gc) |
581 silcpurple_close(PurpleConnection *gc) |
| 468 { |
582 { |
| 469 SilcPurple sg = gc->proto_data; |
583 SilcPurple sg = gc->proto_data; |
| |
584 #if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1) |
| |
585 SilcPurpleTask task; |
| |
586 #endif /* __SILC_TOOLKIT_VERSION */ |
| 470 |
587 |
| 471 g_return_if_fail(sg != NULL); |
588 g_return_if_fail(sg != NULL); |
| 472 |
589 |
| 473 /* Send QUIT */ |
590 /* Send QUIT */ |
| 474 silc_client_command_call(sg->client, sg->conn, NULL, |
591 silc_client_command_call(sg->client, sg->conn, NULL, |
| 475 "QUIT", "Download Pidgin: " PURPLE_WEBSITE, NULL); |
592 "QUIT", "Download Pidgin: " PURPLE_WEBSITE, |
| |
593 NULL); |
| 476 |
594 |
| 477 if (sg->conn) |
595 if (sg->conn) |
| 478 silc_client_close_connection(sg->client, sg->conn); |
596 silc_client_close_connection(sg->client, sg->conn); |
| |
597 |
| |
598 #if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1) |
| |
599 if (sg->conn) |
| |
600 silc_client_run_one(sg->client); |
| |
601 silc_schedule_set_notify(sg->client->schedule, NULL, NULL); |
| |
602 |
| |
603 silc_dlist_start(sg->tasks); |
| |
604 while ((task = silc_dlist_get(sg->tasks))) { |
| |
605 purple_input_remove(task->tag); |
| |
606 silc_free(task); |
| |
607 } |
| |
608 silc_dlist_uninit(sg->tasks); |
| |
609 #endif /* __SILC_TOOLKIT_VERSION */ |
| 479 |
610 |
| 480 purple_timeout_remove(sg->scheduler); |
611 purple_timeout_remove(sg->scheduler); |
| 481 purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg); |
612 purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg); |
| 482 } |
613 } |
| 483 |
614 |
| 1153 SilcBuffer buf; |
1284 SilcBuffer buf; |
| 1154 |
1285 |
| 1155 silc_dlist_start(list); |
1286 silc_dlist_start(list); |
| 1156 while ((buf = silc_dlist_get(list)) != SILC_LIST_END) |
1287 while ((buf = silc_dlist_get(list)) != SILC_LIST_END) |
| 1157 silc_client_send_private_message(client, conn, |
1288 silc_client_send_private_message(client, conn, |
| 1158 client_entry, im->flags, NULL, |
1289 client_entry, im->flags, sg->sha1hash, |
| 1159 buf->data, |
1290 buf->data, |
| 1160 silc_buffer_len(buf)); |
1291 silc_buffer_len(buf)); |
| 1161 silc_mime_partial_free(list); |
1292 silc_mime_partial_free(list); |
| 1162 purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, |
1293 purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, |
| 1163 im->message, 0, time(NULL)); |
1294 im->message, 0, time(NULL)); |