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);