Mercurial > pidgin
comparison src/protocols/simple/simple.c @ 11194:4c1f45ac00e9
[gaim-migrate @ 13317]
- added retries for UDP transport
- added keep alive for UDP to stay in NAT tables
- unregistering contact on logout
- start of argument unification (struct simple_account_data *sip, ...)
committer: Tailor Script <tailor@pidgin.im>
| author | Thomas Butter <tbutter> |
|---|---|
| date | Sat, 06 Aug 2005 12:25:15 +0000 |
| parents | fd6232f9a418 |
| children | 5ba038e1b21f |
comparison
equal
deleted
inserted
replaced
| 11193:e865bdbbf91d | 11194:4c1f45ac00e9 |
|---|---|
| 66 static const char *simple_list_icon(GaimAccount *a, GaimBuddy *b) { | 66 static const char *simple_list_icon(GaimAccount *a, GaimBuddy *b) { |
| 67 return "simple"; | 67 return "simple"; |
| 68 } | 68 } |
| 69 | 69 |
| 70 static void simple_keep_alive(GaimConnection *gc) { | 70 static void simple_keep_alive(GaimConnection *gc) { |
| 71 return; // need it? | 71 struct simple_account_data *sip = gc->proto_data; |
| 72 if(sip->udp) { // in case of UDP send a packet only with a 0 byte to | |
| 73 // stay in the NAT table | |
| 74 gchar buf[2]={0,0}; | |
| 75 gaim_debug_info("simple", "sending keep alive\n"); | |
| 76 sendto(sip->fd, buf, 1, 0, (struct sockaddr*)&sip->serveraddr, sizeof(struct sockaddr_in)); | |
| 77 } | |
| 78 return; | |
| 72 } | 79 } |
| 73 | 80 |
| 74 static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc); | 81 static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc); |
| 75 static void send_notify(struct simple_account_data *sip, struct simple_watcher *); | 82 static void send_notify(struct simple_account_data *sip, struct simple_watcher *); |
| 76 | 83 |
| 296 sendlater(gc,buf); | 303 sendlater(gc,buf); |
| 297 return 0; | 304 return 0; |
| 298 } | 305 } |
| 299 } | 306 } |
| 300 return ret; | 307 return ret; |
| 308 } | |
| 309 | |
| 310 static void sendout_sipmsg(struct simple_account_data *sip, struct sipmsg *msg) { | |
| 311 gchar *oldstr; | |
| 312 gchar *outstr = g_strdup_printf("%s %s SIP/2.0\r\n", msg->method, msg->target); | |
| 313 gchar *name; | |
| 314 gchar *value; | |
| 315 GSList *tmp = msg->headers; | |
| 316 while(tmp) { | |
| 317 oldstr = outstr; | |
| 318 name = ((struct siphdrelement*)(tmp->data))->name; | |
| 319 value = ((struct siphdrelement*)(tmp->data))->value; | |
| 320 outstr = g_strdup_printf("%s%s: %s\r\n",oldstr, name, value); | |
| 321 g_free(oldstr); | |
| 322 tmp = g_slist_next(tmp); | |
| 323 } | |
| 324 oldstr = outstr; | |
| 325 if(msg->body) outstr = g_strdup_printf("%s\r\n%s", outstr, msg->body); | |
| 326 else outstr = g_strdup_printf("%s\r\n", outstr); | |
| 327 g_free(oldstr); | |
| 328 sendout_pkt(sip->gc, outstr); | |
| 329 g_free(outstr); | |
| 301 } | 330 } |
| 302 | 331 |
| 303 static void send_sip_response(GaimConnection *gc, struct sipmsg *msg, int code, char *text, char *body) { | 332 static void send_sip_response(GaimConnection *gc, struct sipmsg *msg, int code, char *text, char *body) { |
| 304 GSList *tmp = msg->headers; | 333 GSList *tmp = msg->headers; |
| 305 char *oldstr; | 334 char *oldstr; |
| 318 if(body) outstr = g_strdup_printf("%s\r\n%s",outstr,body); | 347 if(body) outstr = g_strdup_printf("%s\r\n%s",outstr,body); |
| 319 else outstr = g_strdup_printf("%s\r\n",outstr); | 348 else outstr = g_strdup_printf("%s\r\n",outstr); |
| 320 g_free(oldstr); | 349 g_free(oldstr); |
| 321 sendout_pkt(gc, outstr); | 350 sendout_pkt(gc, outstr); |
| 322 g_free(outstr); | 351 g_free(outstr); |
| 352 } | |
| 353 | |
| 354 static void transactions_remove(struct simple_account_data *sip, struct transaction *trans) { | |
| 355 if(trans->msg) sipmsg_free(trans->msg); | |
| 356 sip->transactions = g_slist_remove(sip->transactions, trans); | |
| 357 g_free(trans); | |
| 323 } | 358 } |
| 324 | 359 |
| 325 static void transactions_add_buf(struct simple_account_data *sip, gchar *buf, void *callback) { | 360 static void transactions_add_buf(struct simple_account_data *sip, gchar *buf, void *callback) { |
| 326 struct transaction *trans = g_new0(struct transaction, 1); | 361 struct transaction *trans = g_new0(struct transaction, 1); |
| 327 trans->time = time(NULL); | 362 trans->time = time(NULL); |
| 416 sendout_pkt(gc,buf); | 451 sendout_pkt(gc,buf); |
| 417 | 452 |
| 418 g_free(buf); | 453 g_free(buf); |
| 419 } | 454 } |
| 420 | 455 |
| 421 static void do_register(GaimConnection *gc) { | 456 static void do_register_exp(struct simple_account_data *sip, int expire) { |
| 422 struct simple_account_data *sip = gc->proto_data; | |
| 423 sip->registerstatus = 1; | 457 sip->registerstatus = 1; |
| 424 | 458 |
| 425 char *uri = g_strdup_printf("sip:%s",sip->servername); | 459 char *uri = g_strdup_printf("sip:%s",sip->servername); |
| 426 char *to = g_strdup_printf("sip:%s@%s",sip->username,sip->servername); | 460 char *to = g_strdup_printf("sip:%s@%s",sip->username,sip->servername); |
| 427 char *contact = g_strdup_printf("Contact: <sip:%s@%s:%d;transport=%s>;methods=\"MESSAGE, SUBSCRIBE, NOTIFY\"\r\nExpires: 900\r\n", sip->username, sip->ip, sip->listenport, sip->udp ? "udp" : "tcp"); | 461 char *contact = g_strdup_printf("Contact: <sip:%s@%s:%d;transport=%s>;methods=\"MESSAGE, SUBSCRIBE, NOTIFY\"\r\nExpires: %d\r\n", sip->username, sip->ip, sip->listenport, sip->udp ? "udp" : "tcp", expire); |
| 428 | 462 |
| 429 // allow one auth try per register | 463 // allow one auth try per register |
| 430 sip->proxy.fouroseven = 0; | 464 sip->proxy.fouroseven = 0; |
| 431 sip->registrar.fouroseven = 0; | 465 sip->registrar.fouroseven = 0; |
| 432 | 466 |
| 433 sip->reregister = time(NULL) + 540; | 467 if(expire) { |
| 434 send_sip_request(gc,"REGISTER",uri,to, contact, "", NULL, process_register_response); | 468 sip->reregister = time(NULL) + expire - 50; |
| 469 } else { | |
| 470 sip->reregister = time(NULL) + 600; | |
| 471 } | |
| 472 send_sip_request(sip->gc,"REGISTER",uri,to, contact, "", NULL, process_register_response); | |
| 435 g_free(uri); | 473 g_free(uri); |
| 436 g_free(to); | 474 g_free(to); |
| 475 } | |
| 476 | |
| 477 static void do_register(struct simple_account_data *sip) { | |
| 478 do_register_exp(sip, sip->registerexpire); | |
| 437 } | 479 } |
| 438 | 480 |
| 439 static gchar *parse_from(gchar *hdr) { | 481 static gchar *parse_from(gchar *hdr) { |
| 440 gchar *from = hdr; | 482 gchar *from = hdr; |
| 441 gchar *tmp; | 483 gchar *tmp; |
| 503 gaim_debug(GAIM_DEBUG_MISC, "simple", "simple_buddy_resub %s\n",name); | 545 gaim_debug(GAIM_DEBUG_MISC, "simple", "simple_buddy_resub %s\n",name); |
| 504 simple_subscribe(sip, buddy); | 546 simple_subscribe(sip, buddy); |
| 505 } | 547 } |
| 506 } | 548 } |
| 507 | 549 |
| 550 static gboolean resend_timeout(struct simple_account_data *sip) { | |
| 551 GSList *tmp = sip->transactions; | |
| 552 time_t currtime = time(NULL); | |
| 553 while(tmp) { | |
| 554 struct transaction *trans = tmp->data; | |
| 555 tmp = tmp->next; | |
| 556 gaim_debug_info("simple", "have open transaction age: %d\n", currtime- trans->time); | |
| 557 if((currtime - trans->time > 5) && trans->retries >= 1) { | |
| 558 // TODO 408 | |
| 559 } else { | |
| 560 if((currtime - trans->time > 2) && trans->retries == 0) { | |
| 561 trans->retries++; | |
| 562 sendout_sipmsg(sip, trans->msg); | |
| 563 } | |
| 564 } | |
| 565 } | |
| 566 return TRUE; | |
| 567 } | |
| 568 | |
| 508 static gboolean register_timeout(struct simple_account_data *sip) { | 569 static gboolean register_timeout(struct simple_account_data *sip) { |
| 509 GSList *tmp; | 570 GSList *tmp; |
| 510 time_t curtime = time(NULL); | 571 time_t curtime = time(NULL); |
| 511 // register again if first registration expires | 572 // register again if first registration expires |
| 512 if(sip->reregister < curtime) { | 573 if(sip->reregister < curtime) { |
| 513 do_register(sip->gc); | 574 do_register(sip); |
| 514 } | 575 } |
| 515 | 576 |
| 516 // check for every subscription if we need to resubscribe | 577 // check for every subscription if we need to resubscribe |
| 517 g_hash_table_foreach(sip->buddies, (GHFunc)simple_buddy_resub, (gpointer)sip); | 578 g_hash_table_foreach(sip->buddies, (GHFunc)simple_buddy_resub, (gpointer)sip); |
| 518 | 579 |
| 643 if(sip->registerstatus!=2) { | 704 if(sip->registerstatus!=2) { |
| 644 tmp = sipmsg_find_header(msg, "WWW-Authenticate"); | 705 tmp = sipmsg_find_header(msg, "WWW-Authenticate"); |
| 645 fill_auth(sip, tmp, &sip->registrar); | 706 fill_auth(sip, tmp, &sip->registrar); |
| 646 sip->registerstatus=2; | 707 sip->registerstatus=2; |
| 647 gaim_debug(GAIM_DEBUG_MISC, "simple", "HA1: %s\n",sip->registrar.HA1); | 708 gaim_debug(GAIM_DEBUG_MISC, "simple", "HA1: %s\n",sip->registrar.HA1); |
| 648 do_register(sip->gc); | 709 do_register(sip); |
| 649 } | 710 } |
| 650 break; | 711 break; |
| 651 } | 712 } |
| 652 return TRUE; | 713 return TRUE; |
| 653 } | 714 } |
| 863 if(msg->response == 401) sip->registrar.fouroseven++; | 924 if(msg->response == 401) sip->registrar.fouroseven++; |
| 864 else sip->registrar.fouroseven = 0; | 925 else sip->registrar.fouroseven = 0; |
| 865 if(trans->callback) { | 926 if(trans->callback) { |
| 866 // call the callback to process response | 927 // call the callback to process response |
| 867 (trans->callback)(sip, msg, trans); | 928 (trans->callback)(sip, msg, trans); |
| 868 sip->transactions = g_slist_remove(sip->transactions, trans); | |
| 869 } else { | |
| 870 // transaction has no callback - just remove it | |
| 871 sip->transactions = g_slist_remove(sip->transactions, trans); | |
| 872 } | 929 } |
| 930 transactions_remove(sip, trans); | |
| 873 } | 931 } |
| 874 found = 1; | 932 found = 1; |
| 875 } else { | 933 } else { |
| 876 gaim_debug(GAIM_DEBUG_MISC, "simple", "received response to unknown transaction"); | 934 gaim_debug(GAIM_DEBUG_MISC, "simple", "received response to unknown transaction"); |
| 877 } | 935 } |
| 1011 conn = connection_create(sip, source); | 1069 conn = connection_create(sip, source); |
| 1012 | 1070 |
| 1013 // get the local ip | 1071 // get the local ip |
| 1014 sip->ip = g_strdup(gaim_network_get_my_ip(source)); | 1072 sip->ip = g_strdup(gaim_network_get_my_ip(source)); |
| 1015 | 1073 |
| 1016 do_register(gc); | 1074 do_register(sip); |
| 1017 | 1075 |
| 1018 conn->inputhandler = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_input_cb, gc); | 1076 conn->inputhandler = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_input_cb, gc); |
| 1019 } | 1077 } |
| 1020 | 1078 |
| 1021 static guint simple_ht_hash_nick(const char *nick) { | 1079 static guint simple_ht_hash_nick(const char *nick) { |
| 1043 gc = gaim_account_get_connection(account); | 1101 gc = gaim_account_get_connection(account); |
| 1044 | 1102 |
| 1045 gc->proto_data = sip = g_new0(struct simple_account_data,1); | 1103 gc->proto_data = sip = g_new0(struct simple_account_data,1); |
| 1046 sip->gc=gc; | 1104 sip->gc=gc; |
| 1047 sip->account = account; | 1105 sip->account = account; |
| 1048 | 1106 sip->registerexpire = 900; |
| 1049 sip->udp = gaim_account_get_bool(account, "udp", FALSE); | 1107 sip->udp = gaim_account_get_bool(account, "udp", FALSE); |
| 1050 if (strpbrk(username, " \t\v\r\n") != NULL) { | 1108 if (strpbrk(username, " \t\v\r\n") != NULL) { |
| 1051 gaim_connection_error(gc, _("SIP usernames may not contain whitespaces or @ symbols")); | 1109 gaim_connection_error(gc, _("SIP usernames may not contain whitespaces or @ symbols")); |
| 1052 return; | 1110 return; |
| 1053 } | 1111 } |
| 1110 sip->serveraddr.sin_port = htons(serveradr->port); | 1168 sip->serveraddr.sin_port = htons(serveradr->port); |
| 1111 | 1169 |
| 1112 h = gethostbyname(serveradr->name); | 1170 h = gethostbyname(serveradr->name); |
| 1113 sip->serveraddr.sin_addr.s_addr = ((struct in_addr*)h->h_addr)->s_addr; | 1171 sip->serveraddr.sin_addr.s_addr = ((struct in_addr*)h->h_addr)->s_addr; |
| 1114 sip->ip = g_strdup(gaim_network_get_my_ip(sip->listenfd)); | 1172 sip->ip = g_strdup(gaim_network_get_my_ip(sip->listenfd)); |
| 1115 | 1173 sip->resendtimeout = gaim_timeout_add(2500, (GSourceFunc)resend_timeout, sip); |
| 1116 do_register(gc); | 1174 do_register(sip); |
| 1117 | 1175 |
| 1118 } | 1176 } |
| 1119 | 1177 |
| 1120 // register timeout callback for register / subscribe renewal | 1178 // register timeout callback for register / subscribe renewal |
| 1121 sip->registertimeout = gaim_timeout_add((rand()%10)+10*1000, (GSourceFunc)register_timeout, sip); | 1179 sip->registertimeout = gaim_timeout_add((rand()%100)+10*1000, (GSourceFunc)register_timeout, sip); |
| 1122 } | 1180 } |
| 1123 | 1181 |
| 1124 static void simple_close(GaimConnection *gc) | 1182 static void simple_close(GaimConnection *gc) |
| 1125 { | 1183 { |
| 1126 struct simple_account_data *sip = gc->proto_data; | 1184 struct simple_account_data *sip = gc->proto_data; |
| 1185 | |
| 1186 // unregister | |
| 1187 do_register_exp(sip, 0); | |
| 1127 // if(sip) { | 1188 // if(sip) { |
| 1128 if(0) { | 1189 if(0) { |
| 1129 if(sip->servername) g_free(sip->servername); | 1190 if(sip->servername) g_free(sip->servername); |
| 1130 if(sip->username) g_free(sip->username); | 1191 if(sip->username) g_free(sip->username); |
| 1131 if(sip->password) g_free(sip->password); | 1192 if(sip->password) g_free(sip->password); |
