comparison src/protocols/simple/simple.c @ 11396:be776f9b1818

[gaim-migrate @ 13627] Compiles and at least partially works on win32. Also some whitespace cleanup. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Wed, 31 Aug 2005 21:10:19 +0000
parents b4cf724b64f8
children 1e495a5fcbbc
comparison
equal deleted inserted replaced
11395:f0e03a3ca3b5 11396:be776f9b1818
2 * @file simple.c 2 * @file simple.c
3 * 3 *
4 * gaim 4 * gaim
5 * 5 *
6 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de> 6 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
7 * 7 *
8 * *** 8 * ***
9 * Thanks to Google's Summer of Code Program and the helpful mentors 9 * Thanks to Google's Summer of Code Program and the helpful mentors
10 * *** 10 * ***
11 * 11 *
12 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
46 static char *gentag() { 46 static char *gentag() {
47 return g_strdup_printf("%04d%04d", rand() & 0xFFFF, rand() & 0xFFFF); 47 return g_strdup_printf("%04d%04d", rand() & 0xFFFF, rand() & 0xFFFF);
48 } 48 }
49 49
50 static char *genbranch() { 50 static char *genbranch() {
51 return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X", 51 return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X",
52 rand() & 0xFFFF, 52 rand() & 0xFFFF,
53 rand() & 0xFFFF, 53 rand() & 0xFFFF,
54 rand() & 0xFFFF, 54 rand() & 0xFFFF,
55 rand() & 0xFFFF, 55 rand() & 0xFFFF,
56 rand() & 0xFFFF); 56 rand() & 0xFFFF);
57 } 57 }
58 58
59 static char *gencallid() { 59 static char *gencallid() {
60 return g_strdup_printf("%04Xg%04Xa%04Xi%04Xm%04Xt%04Xb%04Xx%04Xx", 60 return g_strdup_printf("%04Xg%04Xa%04Xi%04Xm%04Xt%04Xb%04Xx%04Xx",
61 rand() & 0xFFFF, 61 rand() & 0xFFFF,
62 rand() & 0xFFFF, 62 rand() & 0xFFFF,
63 rand() & 0xFFFF, 63 rand() & 0xFFFF,
64 rand() & 0xFFFF, 64 rand() & 0xFFFF,
65 rand() & 0xFFFF, 65 rand() & 0xFFFF,
67 rand() & 0xFFFF, 67 rand() & 0xFFFF,
68 rand() & 0xFFFF); 68 rand() & 0xFFFF);
69 } 69 }
70 70
71 static const char *simple_list_icon(GaimAccount *a, GaimBuddy *b) { 71 static const char *simple_list_icon(GaimAccount *a, GaimBuddy *b) {
72 return "simple"; 72 return "simple";
73 } 73 }
74 74
75 static void simple_keep_alive(GaimConnection *gc) { 75 static void simple_keep_alive(GaimConnection *gc) {
76 struct simple_account_data *sip = gc->proto_data; 76 struct simple_account_data *sip = gc->proto_data;
77 if(sip->udp) { /* in case of UDP send a packet only with a 0 byte to 77 if(sip->udp) { /* in case of UDP send a packet only with a 0 byte to
78 remain in the NAT table */ 78 remain in the NAT table */
79 gchar buf[2]={0,0}; 79 gchar buf[2]={0,0};
80 gaim_debug_info("simple", "sending keep alive\n"); 80 gaim_debug_info("simple", "sending keep alive\n");
81 sendto(sip->fd, buf, 1, 0, (struct sockaddr*)&sip->serveraddr, sizeof(struct sockaddr_in)); 81 sendto(sip->fd, buf, 1, 0, (struct sockaddr*)&sip->serveraddr, sizeof(struct sockaddr_in));
82 } 82 }
83 return; 83 return;
84 } 84 }
85 85
86 static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc); 86 static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc);
87 static void send_notify(struct simple_account_data *sip, struct simple_watcher *); 87 static void send_notify(struct simple_account_data *sip, struct simple_watcher *);
88 88
90 90
91 static void do_notifies(struct simple_account_data *sip) { 91 static void do_notifies(struct simple_account_data *sip) {
92 GSList *tmp = sip->watcher; 92 GSList *tmp = sip->watcher;
93 gaim_debug_info("simple", "do_notifies()\n"); 93 gaim_debug_info("simple", "do_notifies()\n");
94 if((sip->republish != -1) || sip->republish < time(NULL)) { 94 if((sip->republish != -1) || sip->republish < time(NULL)) {
95 if(gaim_account_get_bool(sip->account, "dopublish", TRUE)) { 95 if(gaim_account_get_bool(sip->account, "dopublish", TRUE)) {
96 send_publish(sip); 96 send_publish(sip);
97 } 97 }
98 } 98 }
99 99
100 while(tmp) { 100 while(tmp) {
103 tmp = tmp->next; 103 tmp = tmp->next;
104 } 104 }
105 } 105 }
106 106
107 static void simple_set_status(GaimAccount *account, GaimStatus *status) { 107 static void simple_set_status(GaimAccount *account, GaimStatus *status) {
108 GaimStatusPrimitive primitive = gaim_status_type_get_primitive(gaim_status_get_type(status)); 108 GaimStatusPrimitive primitive = gaim_status_type_get_primitive(gaim_status_get_type(status));
109 struct simple_account_data *sip = NULL; 109 struct simple_account_data *sip = NULL;
110 if (!gaim_status_is_active(status)) 110 if (!gaim_status_is_active(status))
111 return; 111 return;
112 112
113 if(account->gc) sip = account->gc->proto_data; 113 if(account->gc) sip = account->gc->proto_data;
116 if(primitive == GAIM_STATUS_AVAILABLE) sip->status = g_strdup("available"); 116 if(primitive == GAIM_STATUS_AVAILABLE) sip->status = g_strdup("available");
117 else sip->status = g_strdup("busy"); 117 else sip->status = g_strdup("busy");
118 118
119 do_notifies(sip); 119 do_notifies(sip);
120 } 120 }
121 if ((primitive != GAIM_STATUS_OFFLINE) 121 if ((primitive != GAIM_STATUS_OFFLINE)
122 && (!gaim_account_is_connected(account))) { 122 && (!gaim_account_is_connected(account))) {
123 gaim_account_connect(account); 123 gaim_account_connect(account);
124 } 124 }
125 } 125 }
126 126
200 gaim_notify_error(gc, NULL, _("Unable To Add"), buf); 200 gaim_notify_error(gc, NULL, _("Unable To Add"), buf);
201 g_free(buf); 201 g_free(buf);
202 gaim_blist_remove_buddy(buddy); 202 gaim_blist_remove_buddy(buddy);
203 return; 203 return;
204 } 204 }
205 if(!g_hash_table_lookup(sip->buddies, buddy->name)) { 205 if(!g_hash_table_lookup(sip->buddies, buddy->name)) {
206 b = g_new0(struct simple_buddy, 1); 206 b = g_new0(struct simple_buddy, 1);
207 gaim_debug_info("simple","simple_add_buddy %s\n",buddy->name); 207 gaim_debug_info("simple","simple_add_buddy %s\n",buddy->name);
208 b->name = g_strdup(buddy->name); 208 b->name = g_strdup(buddy->name);
209 g_hash_table_insert(sip->buddies, b->name, b); 209 g_hash_table_insert(sip->buddies, b->name, b);
210 } else { 210 } else {
211 gaim_debug_info("simple","buddy %s already in internal list\n", buddy->name); 211 gaim_debug_info("simple","buddy %s already in internal list\n", buddy->name);
212 } 212 }
214 214
215 static void simple_get_buddies(GaimConnection *gc) { 215 static void simple_get_buddies(GaimConnection *gc) {
216 GaimBlistNode *gnode, *cnode, *bnode; 216 GaimBlistNode *gnode, *cnode, *bnode;
217 217
218 gaim_debug_info("simple","simple_get_buddies\n"); 218 gaim_debug_info("simple","simple_get_buddies\n");
219 219
220 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { 220 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) {
221 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) continue; 221 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) continue;
222 for(cnode = gnode->child; cnode; cnode = cnode->next) { 222 for(cnode = gnode->child; cnode; cnode = cnode->next) {
223 if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) continue; 223 if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) continue;
224 for(bnode = cnode->child; bnode; bnode = bnode->next) { 224 for(bnode = cnode->child; bnode; bnode = bnode->next) {
247 types = g_list_append(types, type); 247 types = g_list_append(types, type);
248 248
249 type = gaim_status_type_new(GAIM_STATUS_ONLINE, "online", _("Online"), FALSE); 249 type = gaim_status_type_new(GAIM_STATUS_ONLINE, "online", _("Online"), FALSE);
250 types = g_list_append(types, type); 250 types = g_list_append(types, type);
251 251
252 type = gaim_status_type_new_with_attrs( 252 type = gaim_status_type_new_with_attrs(
253 GAIM_STATUS_AVAILABLE, "available", _("Available"), 253 GAIM_STATUS_AVAILABLE, "available", _("Available"),
254 TRUE, TRUE, FALSE, 254 TRUE, TRUE, FALSE,
255 "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); 255 "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL);
256 types = g_list_append(types, type); 256 types = g_list_append(types, type);
257 257
258 return types; 258 return types;
259 } 259 }
260 260
261 static gchar *auth_header(struct simple_account_data *sip, struct sip_auth *auth, gchar *method, gchar *target) { 261 static gchar *auth_header(struct simple_account_data *sip, struct sip_auth *auth, gchar *method, gchar *target) {
262 gchar noncecount[9]; 262 gchar noncecount[9];
263 HASHHEX HA2; 263 HASHHEX HA2;
264 HASHHEX response; 264 HASHHEX response;
265 gchar *ret; 265 gchar *ret;
266 266
267 sprintf(noncecount, "%08d", auth->nc++); 267 sprintf(noncecount, "%08d", auth->nc++);
268 DigestCalcResponse(auth->HA1, auth->nonce, noncecount, "", "", method, target, HA2, response); 268 DigestCalcResponse(auth->HA1, auth->nonce, noncecount, "", "", method, target, HA2, response);
269 gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response); 269 gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response);
270 ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n",sip->username, auth->realm, auth->nonce, target, noncecount, response); 270 ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n",sip->username, auth->realm, auth->nonce, target, noncecount, response);
271 return ret; 271 return ret;
285 if(!strncmp(parts[i],"realm",5)) { 285 if(!strncmp(parts[i],"realm",5)) {
286 auth->realm = g_strndup(parts[i]+7,strlen(parts[i]+7)-2); 286 auth->realm = g_strndup(parts[i]+7,strlen(parts[i]+7)-2);
287 } 287 }
288 i++; 288 i++;
289 } 289 }
290 290
291 gaim_debug(GAIM_DEBUG_MISC, "simple", "nonce: %s realm: %s ", auth->nonce, auth->realm); 291 gaim_debug(GAIM_DEBUG_MISC, "simple", "nonce: %s realm: %s ", auth->nonce, auth->realm);
292 292
293 DigestCalcHA1("md5", sip->username, auth->realm, sip->password, auth->nonce, "", auth->HA1); 293 DigestCalcHA1("md5", sip->username, auth->realm, sip->password, auth->nonce, "", auth->HA1);
294 294
295 auth->nc=1; 295 auth->nc=1;
296 } 296 }
297 297
319 319
320 static void sendlater(GaimConnection *gc, const char *buf) { 320 static void sendlater(GaimConnection *gc, const char *buf) {
321 struct simple_account_data *sip = gc->proto_data; 321 struct simple_account_data *sip = gc->proto_data;
322 int error = 0; 322 int error = 0;
323 if(!sip->connecting) { 323 if(!sip->connecting) {
324 gaim_debug_info("simple","connecting to %s port %d\n", sip->realhostname, sip->realport); 324 gaim_debug_info("simple","connecting to %s port %d\n", sip->realhostname ? sip->realhostname : "{NULL}", sip->realport);
325 error = gaim_proxy_connect(sip->account, sip->realhostname, sip->realport, send_later_cb, gc); 325 error = gaim_proxy_connect(sip->account, sip->realhostname, sip->realport, send_later_cb, gc);
326 if(error) { 326 if(error) {
327 gaim_connection_error(gc, _("Couldn't create socket")); 327 gaim_connection_error(gc, _("Couldn't create socket"));
328 } 328 }
329 sip->connecting = 1; 329 sip->connecting = 1;
330 } 330 }
331 if(sip->sendlater) { 331 if(sip->sendlater) {
332 gchar *old = sip->sendlater; 332 gchar *old = sip->sendlater;
333 sip->sendlater = g_strdup_printf("%s\r\n%s",old, buf); 333 sip->sendlater = g_strdup_printf("%s\r\n%s",old, buf);
338 338
339 static int sendout_pkt(GaimConnection *gc, const char *buf) { 339 static int sendout_pkt(GaimConnection *gc, const char *buf) {
340 struct simple_account_data *sip = gc->proto_data; 340 struct simple_account_data *sip = gc->proto_data;
341 time_t currtime = time(NULL); 341 time_t currtime = time(NULL);
342 int ret = 0; 342 int ret = 0;
343 343
344 gaim_debug(GAIM_DEBUG_MISC, "simple", "\n\nsending - %s\n######\n%s\n######\n\n", ctime(&currtime), buf); 344 gaim_debug(GAIM_DEBUG_MISC, "simple", "\n\nsending - %s\n######\n%s\n######\n\n", ctime(&currtime), buf);
345 if(sip->udp) { 345 if(sip->udp) {
346 if(sendto(sip->fd, buf, strlen(buf), 0, (struct sockaddr*)&sip->serveraddr, sizeof(struct sockaddr_in)) < strlen(buf)) { 346 if(sendto(sip->fd, buf, strlen(buf), 0, (struct sockaddr*)&sip->serveraddr, sizeof(struct sockaddr_in)) < strlen(buf)) {
347 gaim_debug_info("simple", "could not send packet\n"); 347 gaim_debug_info("simple", "could not send packet\n");
348 } 348 }
349 } else { 349 } else {
350 if(sip->fd <0 ) { 350 if(sip->fd <0 ) {
351 sendlater(gc, buf); 351 sendlater(gc, buf);
352 return 0; 352 return 0;
353 } 353 }
354 ret = write(sip->fd, buf, strlen(buf)); 354 ret = write(sip->fd, buf, strlen(buf));
355 if(ret < 0) { 355 if(ret < 0) {
356 sendlater(gc,buf); 356 sendlater(gc,buf);
357 return 0; 357 return 0;
366 gchar *name; 366 gchar *name;
367 gchar *value; 367 gchar *value;
368 GSList *tmp = msg->headers; 368 GSList *tmp = msg->headers;
369 while(tmp) { 369 while(tmp) {
370 oldstr = outstr; 370 oldstr = outstr;
371 name = ((struct siphdrelement*)(tmp->data))->name; 371 name = ((struct siphdrelement*)(tmp->data))->name;
372 value = ((struct siphdrelement*)(tmp->data))->value; 372 value = ((struct siphdrelement*)(tmp->data))->value;
373 outstr = g_strdup_printf("%s%s: %s\r\n",oldstr, name, value); 373 outstr = g_strdup_printf("%s%s: %s\r\n",oldstr, name, value);
374 g_free(oldstr); 374 g_free(oldstr);
375 tmp = g_slist_next(tmp); 375 tmp = g_slist_next(tmp);
376 } 376 }
377 oldstr = outstr; 377 oldstr = outstr;
378 if(msg->body) outstr = g_strdup_printf("%s\r\n%s", outstr, msg->body); 378 if(msg->body) outstr = g_strdup_printf("%s\r\n%s", outstr, msg->body);
379 else outstr = g_strdup_printf("%s\r\n", outstr); 379 else outstr = g_strdup_printf("%s\r\n", outstr);
380 g_free(oldstr); 380 g_free(oldstr);
381 sendout_pkt(sip->gc, outstr); 381 sendout_pkt(sip->gc, outstr);
382 g_free(outstr); 382 g_free(outstr);
383 } 383 }
384 384
385 static void send_sip_response(GaimConnection *gc, struct sipmsg *msg, int code, char *text, char *body) { 385 static void send_sip_response(GaimConnection *gc, struct sipmsg *msg, int code, char *text, char *body) {
386 GSList *tmp = msg->headers; 386 GSList *tmp = msg->headers;
387 char *oldstr; 387 char *oldstr;
429 if(!strcmp(trans->cseq, cseq)) { 429 if(!strcmp(trans->cseq, cseq)) {
430 return trans; 430 return trans;
431 } 431 }
432 transactions = transactions->next; 432 transactions = transactions->next;
433 } 433 }
434 434
435 return (struct transaction *)NULL; 435 return (struct transaction *)NULL;
436 } 436 }
437 437
438 static void send_sip_request(GaimConnection *gc, gchar *method, gchar *url, gchar *to, gchar *addheaders, gchar *body, struct sip_dialog *dialog, TransCallback tc) { 438 static void send_sip_request(GaimConnection *gc, gchar *method, gchar *url, gchar *to, gchar *addheaders, gchar *body, struct sip_dialog *dialog, TransCallback tc) {
439 struct simple_account_data *sip = gc->proto_data; 439 struct simple_account_data *sip = gc->proto_data;
440 char *callid= dialog ? g_strdup(dialog->callid) : gencallid(); 440 char *callid= dialog ? g_strdup(dialog->callid) : gencallid();
441 char *auth=""; 441 char *auth="";
442 char *addh=""; 442 char *addh="";
443 gchar *branch = genbranch(); 443 gchar *branch = genbranch();
444 char *buf; 444 char *buf;
445 445
446 if(addheaders) addh=addheaders; 446 if(addheaders) addh=addheaders;
447 if(sip->registrar.nonce && !strcmp(method,"REGISTER")) { 447 if(sip->registrar.nonce && !strcmp(method,"REGISTER")) {
448 buf = auth_header(sip, &sip->registrar, method, url); 448 buf = auth_header(sip, &sip->registrar, method, url);
449 auth = g_strdup_printf("Authorization: %s",buf); 449 auth = g_strdup_printf("Authorization: %s",buf);
450 g_free(buf); 450 g_free(buf);
451 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth); 451 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth);
452 } 452 }
453 453
456 auth = g_strdup_printf("Proxy-Authorization: %s",buf); 456 auth = g_strdup_printf("Proxy-Authorization: %s",buf);
457 g_free(buf); 457 g_free(buf);
458 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth); 458 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth);
459 } 459 }
460 460
461
462 buf = g_strdup_printf("%s %s SIP/2.0\r\n" 461 buf = g_strdup_printf("%s %s SIP/2.0\r\n"
463 "Via: SIP/2.0/%s %s:%d;branch=%s\r\n" 462 "Via: SIP/2.0/%s %s:%d;branch=%s\r\n"
464 "From: <sip:%s@%s>;tag=%s\r\n" 463 "From: <sip:%s@%s>;tag=%s\r\n"
465 "To: <%s>%s%s\r\n" 464 "To: <%s>%s%s\r\n"
466 "Max-Forwards: 10\r\n" 465 "Max-Forwards: 10\r\n"
470 "%s%s" 469 "%s%s"
471 "Content-Length: %d\r\n\r\n%s", 470 "Content-Length: %d\r\n\r\n%s",
472 method, 471 method,
473 url, 472 url,
474 sip->udp ? "UDP" : "TCP", 473 sip->udp ? "UDP" : "TCP",
475 sip->ip, 474 sip->ip ? sip->ip : "",
476 sip->listenport, 475 sip->listenport,
477 branch, 476 branch,
478 sip->username, 477 sip->username,
479 sip->servername, 478 sip->servername,
480 dialog ? dialog->ourtag : gentag(), 479 dialog ? dialog->ourtag : gentag(),
490 body); 489 body);
491 g_free(branch); 490 g_free(branch);
492 g_free(callid); 491 g_free(callid);
493 492
494 /* add to ongoing transactions */ 493 /* add to ongoing transactions */
495 494
496 transactions_add_buf(sip, buf, tc); 495 transactions_add_buf(sip, buf, tc);
497 496
498 sendout_pkt(gc,buf); 497 sendout_pkt(gc,buf);
499 498
500 g_free(buf); 499 g_free(buf);
501 } 500 }
502 501
503 static void do_register_exp(struct simple_account_data *sip, int expire) { 502 static void do_register_exp(struct simple_account_data *sip, int expire) {
504 sip->registerstatus = 1; 503 sip->registerstatus = 1;
505 504
506 char *uri = g_strdup_printf("sip:%s",sip->servername); 505 char *uri = g_strdup_printf("sip:%s",sip->servername);
507 char *to = g_strdup_printf("sip:%s@%s",sip->username,sip->servername); 506 char *to = g_strdup_printf("sip:%s@%s",sip->username,sip->servername);
508 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); 507 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->ip : "", sip->listenport, sip->udp ? "udp" : "tcp", expire);
509 508
510 if(expire) { 509 if(expire) {
511 sip->reregister = time(NULL) + expire - 50; 510 sip->reregister = time(NULL) + expire - 50;
512 } else { 511 } else {
513 sip->reregister = time(NULL) + 600; 512 sip->reregister = time(NULL) + 600;
514 } 513 }
525 static gchar *parse_from(gchar *hdr) { 524 static gchar *parse_from(gchar *hdr) {
526 gchar *from = hdr; 525 gchar *from = hdr;
527 gchar *tmp; 526 gchar *tmp;
528 527
529 if(!from) return NULL; 528 if(!from) return NULL;
530 gaim_debug_info("simple", "parsing address out of %s\n",from); 529 gaim_debug_info("simple", "parsing address out of %s\n",from);
531 tmp = strchr(from, '<'); 530 tmp = strchr(from, '<');
532 531
533 /* i hate the different SIP UA behaviours... */ 532 /* i hate the different SIP UA behaviours... */
534 if(tmp) { /* sip address in <...> */ 533 if(tmp) { /* sip address in <...> */
535 from = tmp+1; 534 from = tmp+1;
550 return from; 549 return from;
551 } 550 }
552 551
553 static gboolean process_subscribe_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { 552 static gboolean process_subscribe_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) {
554 gchar *to = parse_from(sipmsg_find_header(tc->msg,"To")); /* cant be NULL since it is our own msg */ 553 gchar *to = parse_from(sipmsg_find_header(tc->msg,"To")); /* cant be NULL since it is our own msg */
555 554
556
557 if(msg->response==200 || msg->response==202) { 555 if(msg->response==200 || msg->response==202) {
558 return TRUE; 556 return TRUE;
559 } 557 }
560 558
561 /* we can not subscribe -> user is offline (TODO unknown status?) */ 559 /* we can not subscribe -> user is offline (TODO unknown status?) */
562 560
563 gaim_prpl_got_user_status(sip->account, to, "offline", NULL); 561 gaim_prpl_got_user_status(sip->account, to, "offline", NULL);
564 g_free(to); 562 g_free(to);
565 return TRUE; 563 return TRUE;
566 } 564 }
567 565
568 static void simple_subscribe(struct simple_account_data *sip, struct simple_buddy *buddy) { 566 static void simple_subscribe(struct simple_account_data *sip, struct simple_buddy *buddy) {
569 gchar *contact = "Expires: 300\r\nAccept: application/pidf+xml\r\nEvent: presence\r\n"; 567 gchar *contact = "Expires: 300\r\nAccept: application/pidf+xml\r\nEvent: presence\r\n";
570 gchar *to; 568 gchar *to;
571 if(strstr(buddy->name,"sip:")) to = g_strdup(buddy->name); 569 if(strstr(buddy->name,"sip:")) to = g_strdup(buddy->name);
572 else to = g_strdup_printf("sip:%s",buddy->name); 570 else to = g_strdup_printf("sip:%s",buddy->name);
573 contact = g_strdup_printf("%sContact: <%s@%s>\r\n", contact, sip->username, sip->servername); 571 contact = g_strdup_printf("%sContact: <%s@%s>\r\n", contact, sip->username, sip->servername);
574 /* subscribe to buddy presence 572 /* subscribe to buddy presence
575 * we dont need to know the status so we do not need a callback */ 573 * we dont need to know the status so we do not need a callback */
576 574
577 send_sip_request(sip->gc, "SUBSCRIBE",to, to, contact, "", NULL, process_subscribe_response); 575 send_sip_request(sip->gc, "SUBSCRIBE",to, to, contact, "", NULL, process_subscribe_response);
578 576
579 g_free(to); 577 g_free(to);
580 g_free(contact); 578 g_free(contact);
581 579
582 /* resubscribe before subscription expires */ 580 /* resubscribe before subscription expires */
583 /* add some jitter */ 581 /* add some jitter */
584 buddy->resubscribe = time(NULL)+250+(rand()%50); 582 buddy->resubscribe = time(NULL)+250+(rand()%50);
585 } 583 }
586 584
587 static void simple_buddy_resub(char *name, struct simple_buddy *buddy, struct simple_account_data *sip) { 585 static void simple_buddy_resub(char *name, struct simple_buddy *buddy, struct simple_account_data *sip) {
588 time_t curtime = time(NULL); 586 time_t curtime = time(NULL);
589 gaim_debug_info("simple","buddy resub\n"); 587 gaim_debug_info("simple","buddy resub\n");
590 if(buddy->resubscribe < curtime) { 588 if(buddy->resubscribe < curtime) {
591 gaim_debug(GAIM_DEBUG_MISC, "simple", "simple_buddy_resub %s\n",name); 589 gaim_debug(GAIM_DEBUG_MISC, "simple", "simple_buddy_resub %s\n",name);
592 simple_subscribe(sip, buddy); 590 simple_subscribe(sip, buddy);
593 } 591 }
594 } 592 }
595 593
596 static gboolean resend_timeout(struct simple_account_data *sip) { 594 static gboolean resend_timeout(struct simple_account_data *sip) {
622 gaim_debug_info("simple","in register timeout\n"); 620 gaim_debug_info("simple","in register timeout\n");
623 /* check for every subscription if we need to resubscribe */ 621 /* check for every subscription if we need to resubscribe */
624 g_hash_table_foreach(sip->buddies, (GHFunc)simple_buddy_resub, (gpointer)sip); 622 g_hash_table_foreach(sip->buddies, (GHFunc)simple_buddy_resub, (gpointer)sip);
625 623
626 /* remove a timed out suscriber */ 624 /* remove a timed out suscriber */
627 625
628 tmp = sip->watcher; 626 tmp = sip->watcher;
629 while(tmp) { 627 while(tmp) {
630 struct simple_watcher *watcher = tmp->data; 628 struct simple_watcher *watcher = tmp->data;
631 if(watcher->expire < curtime) { 629 if(watcher->expire < curtime) {
632 watcher_remove(sip, watcher->name); 630 watcher_remove(sip, watcher->name);
633 tmp = sip->watcher; 631 tmp = sip->watcher;
634 } 632 }
635 if(tmp) tmp = tmp->next; 633 if(tmp) tmp = tmp->next;
636 } 634 }
637 635
638 return TRUE; 636 return TRUE;
639 } 637 }
640 638
641 static void simple_send_message(struct simple_account_data *sip, char *to, char *msg, char *type) { 639 static void simple_send_message(struct simple_account_data *sip, char *to, char *msg, char *type) {
642 gchar *hdr; 640 gchar *hdr;
643 if(type) { 641 if(type) {
644 hdr = g_strdup_printf("Content-Type: %s\r\n",type); 642 hdr = g_strdup_printf("Content-Type: %s\r\n",type);
645 } else { 643 } else {
646 hdr = g_strdup("Content-Type: text/plain\r\n"); 644 hdr = g_strdup("Content-Type: text/plain\r\n");
647 } 645 }
648 send_sip_request(sip->gc, "MESSAGE", to, to, hdr, msg, NULL, NULL); 646 send_sip_request(sip->gc, "MESSAGE", to, to, hdr, msg, NULL, NULL);
665 gboolean found = FALSE; 663 gboolean found = FALSE;
666 664
667 from = parse_from(sipmsg_find_header(msg, "From")); 665 from = parse_from(sipmsg_find_header(msg, "From"));
668 666
669 if(!from) return; 667 if(!from) return;
670 668
671 gaim_debug(GAIM_DEBUG_MISC, "simple", "got message from %s: %s\n", from, msg->body); 669 gaim_debug(GAIM_DEBUG_MISC, "simple", "got message from %s: %s\n", from, msg->body);
672 670
673 contenttype = sipmsg_find_header(msg, "Content-Type"); 671 contenttype = sipmsg_find_header(msg, "Content-Type");
674 if(!contenttype || !strncmp(contenttype, "text/plain", 10) || !strncmp(contenttype, "text/html", 9)) { 672 if(!contenttype || !strncmp(contenttype, "text/plain", 10) || !strncmp(contenttype, "text/html", 9)) {
675 serv_got_im(sip->gc, from, msg->body, 0, time(NULL)); 673 serv_got_im(sip->gc, from, msg->body, 0, time(NULL));
676 send_sip_response(sip->gc, msg, 200, "OK", NULL); 674 send_sip_response(sip->gc, msg, 200, "OK", NULL);
677 found = TRUE; 675 found = TRUE;
678 } 676 }
679 if(!strncmp(contenttype, "application/im-iscomposing+xml",30)) { 677 if(!strncmp(contenttype, "application/im-iscomposing+xml",30)) {
680 xmlnode *isc = xmlnode_from_str(msg->body, msg->bodylen); 678 xmlnode *isc = xmlnode_from_str(msg->body, msg->bodylen);
681 xmlnode *state; 679 xmlnode *state;
682 gchar *statedata; 680 gchar *statedata;
683 681
684 if(!isc) { 682 if(!isc) {
685 gaim_debug_info("simple","process_incoming_message: can not parse iscomposing\n"); 683 gaim_debug_info("simple","process_incoming_message: can not parse iscomposing\n");
686 return; 684 return;
687 } 685 }
688 686
689 state = xmlnode_get_child(isc, "state"); 687 state = xmlnode_get_child(isc, "state");
690 688
691 if(!state) { 689 if(!state) {
692 gaim_debug_info("simple","process_incoming_message: no state found\n"); 690 gaim_debug_info("simple","process_incoming_message: no state found\n");
693 return; 691 return;
694 } 692 }
695 693
696 statedata = xmlnode_get_data(state); 694 statedata = xmlnode_get_data(state);
697 if(statedata) { 695 if(statedata) {
698 if(strstr(statedata,"active")) serv_got_typing(sip->gc, from, 0, GAIM_TYPING); 696 if(strstr(statedata,"active")) serv_got_typing(sip->gc, from, 0, GAIM_TYPING);
699 else serv_got_typing_stopped(sip->gc, from); 697 else serv_got_typing_stopped(sip->gc, from);
700 } 698 }
701 xmlnode_free(isc); 699 xmlnode_free(isc);
702 send_sip_response(sip->gc, msg, 200, "OK", NULL); 700 send_sip_response(sip->gc, msg, 200, "OK", NULL);
703 found = TRUE; 701 found = TRUE;
704 } 702 }
705 if(!found) { 703 if(!found) {
706 gaim_debug_info("simple", "got unknown mime-type"); 704 gaim_debug_info("simple", "got unknown mime-type");
707 send_sip_response(sip->gc, msg, 415, "Unsupported media type", NULL); 705 send_sip_response(sip->gc, msg, 415, "Unsupported media type", NULL);
714 gchar *tmp; 712 gchar *tmp;
715 gaim_debug(GAIM_DEBUG_MISC, "simple", "in process register response response: %d\n", msg->response); 713 gaim_debug(GAIM_DEBUG_MISC, "simple", "in process register response response: %d\n", msg->response);
716 switch (msg->response) { 714 switch (msg->response) {
717 case 200: 715 case 200:
718 if(sip->registerstatus<3) { /* registered */ 716 if(sip->registerstatus<3) { /* registered */
719 if(gaim_account_get_bool(sip->account, "dopublish", TRUE)) { 717 if(gaim_account_get_bool(sip->account, "dopublish", TRUE)) {
720 send_publish(sip); 718 send_publish(sip);
721 } 719 }
722 } 720 }
723 sip->registerstatus=3; 721 sip->registerstatus=3;
724 gaim_connection_set_state(sip->gc, GAIM_CONNECTED); 722 gaim_connection_set_state(sip->gc, GAIM_CONNECTED);
725 723
726 /* get buddies from blist */ 724 /* get buddies from blist */
727 simple_get_buddies(sip->gc); 725 simple_get_buddies(sip->gc);
728 726
729 register_timeout(sip); 727 register_timeout(sip);
730 break; 728 break;
731 case 401: 729 case 401:
732 if(sip->registerstatus!=2) { 730 if(sip->registerstatus!=2) {
733 gaim_debug_info("simple","REGISTER retries %d\n",sip->registrar.retries); 731 gaim_debug_info("simple","REGISTER retries %d\n",sip->registrar.retries);
734 if(sip->registrar.retries>3) { 732 if(sip->registrar.retries>3) {
735 gaim_connection_error(sip->gc,"Wrong Password"); 733 gaim_connection_error(sip->gc,"Wrong Password");
736 return TRUE; 734 return TRUE;
737 } 735 }
738 tmp = sipmsg_find_header(msg, "WWW-Authenticate"); 736 tmp = sipmsg_find_header(msg, "WWW-Authenticate");
739 fill_auth(sip, tmp, &sip->registrar); 737 fill_auth(sip, tmp, &sip->registrar);
740 sip->registerstatus=2; 738 sip->registerstatus=2;
757 fromhdr = sipmsg_find_header(msg,"From"); 755 fromhdr = sipmsg_find_header(msg,"From");
758 from = parse_from(fromhdr); 756 from = parse_from(fromhdr);
759 if(!from) return; 757 if(!from) return;
760 758
761 pidf = xmlnode_from_str(msg->body, msg->bodylen); 759 pidf = xmlnode_from_str(msg->body, msg->bodylen);
762 760
763 if(!pidf) { 761 if(!pidf) {
764 gaim_debug_info("simple","process_incoming_notify: no parseable pidf\n"); 762 gaim_debug_info("simple","process_incoming_notify: no parseable pidf\n");
765 return; 763 return;
766 } 764 }
767 765
768
769 basicstatus = xmlnode_get_child(xmlnode_get_child(xmlnode_get_child(pidf,"tuple"),"status"), "basic"); 766 basicstatus = xmlnode_get_child(xmlnode_get_child(xmlnode_get_child(pidf,"tuple"),"status"), "basic");
770 767
771 if(!basicstatus) { 768 if(!basicstatus) {
772 gaim_debug_info("simple","process_incoming_notify: no basic found\n"); 769 gaim_debug_info("simple","process_incoming_notify: no basic found\n");
773 return; 770 return;
774 } 771 }
775 772
776 tmp2 = xmlnode_get_data(basicstatus); 773 tmp2 = xmlnode_get_data(basicstatus);
777 774
778 if(!tmp2) { 775 if(!tmp2) {
779 gaim_debug_info("simple","process_incoming_notify: no basic data found\n"); 776 gaim_debug_info("simple","process_incoming_notify: no basic data found\n");
780 return; 777 return;
781 } 778 }
782 779
783 if(strstr(tmp2, "open")) { 780 if(strstr(tmp2, "open")) {
784 isonline = TRUE; 781 isonline = TRUE;
785 } 782 }
786 783
787 if(isonline) gaim_prpl_got_user_status(sip->account, from, "available", NULL); 784 if(isonline) gaim_prpl_got_user_status(sip->account, from, "available", NULL);
788 else gaim_prpl_got_user_status(sip->account, from, "offline", NULL); 785 else gaim_prpl_got_user_status(sip->account, from, "offline", NULL);
789 786
790 xmlnode_free(pidf); 787 xmlnode_free(pidf);
791 788
792 g_free(from); 789 g_free(from);
793 send_sip_response(sip->gc, msg, 200, "OK", NULL); 790 send_sip_response(sip->gc, msg, 200, "OK", NULL);
794 } 791 }
795 792
796 static int simple_typing(GaimConnection *gc, const char *name, int typing) { 793 static int simple_typing(GaimConnection *gc, const char *name, int typing) {
797 struct simple_account_data *sip = gc->proto_data; 794 struct simple_account_data *sip = gc->proto_data;
832 return g_strdup(tmp); 829 return g_strdup(tmp);
833 } 830 }
834 831
835 static gchar* gen_pidf(struct simple_account_data *sip) { 832 static gchar* gen_pidf(struct simple_account_data *sip) {
836 gchar *doc = g_strdup_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 833 gchar *doc = g_strdup_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
837 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n" 834 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n"
838 "xmlns:im=\"urn:ietf:params:xml:ns:pidf:im\"\n" 835 "xmlns:im=\"urn:ietf:params:xml:ns:pidf:im\"\n"
839 "entity=\"sip:%s@%s\">\n" 836 "entity=\"sip:%s@%s\">\n"
840 "<tuple id=\"bs35r9f\">\n" 837 "<tuple id=\"bs35r9f\">\n"
841 "<status>\n" 838 "<status>\n"
842 "<basic>open</basic>\n" 839 "<basic>open</basic>\n"
843 "<im:im>%s</im:im>\n" 840 "<im:im>%s</im:im>\n"
844 "</status>\n" 841 "</status>\n"
845 "</tuple>\n" 842 "</tuple>\n"
930 if(!strcmp(msg->method, "SUBSCRIBE")) { 927 if(!strcmp(msg->method, "SUBSCRIBE")) {
931 process_incoming_subscribe(sip, msg); 928 process_incoming_subscribe(sip, msg);
932 found = 1; 929 found = 1;
933 } 930 }
934 if(!found) { 931 if(!found) {
935 send_sip_response(sip->gc, msg, 501, "Not implemented", NULL); 932 send_sip_response(sip->gc, msg, 501, "Not implemented", NULL);
936 } 933 }
937 } else { /* response */ 934 } else { /* response */
938 struct transaction *trans = transactions_find(sip, msg); 935 struct transaction *trans = transactions_find(sip, msg);
939 if(trans) { 936 if(trans) {
940 if(msg->response == 407) { 937 if(msg->response == 407) {
943 /* do proxy authentication */ 940 /* do proxy authentication */
944 941
945 gchar *ptmp = sipmsg_find_header(msg,"Proxy-Authenticate"); 942 gchar *ptmp = sipmsg_find_header(msg,"Proxy-Authenticate");
946 gchar *resend; 943 gchar *resend;
947 gchar *auth; 944 gchar *auth;
948 945
949 fill_auth(sip, ptmp, &sip->proxy); 946 fill_auth(sip, ptmp, &sip->proxy);
950 auth = auth_header(sip, &sip->proxy, trans->msg->method, trans->msg->target); 947 auth = auth_header(sip, &sip->proxy, trans->msg->method, trans->msg->target);
951 sipmsg_remove_header(msg, "Proxy-Authorization"); 948 sipmsg_remove_header(msg, "Proxy-Authorization");
952 sipmsg_add_header(trans->msg, "Proxy-Authorization", auth); 949 sipmsg_add_header(trans->msg, "Proxy-Authorization", auth);
953 g_free(auth); 950 g_free(auth);
979 { 976 {
980 char *cur; 977 char *cur;
981 char *dummy; 978 char *dummy;
982 struct sipmsg *msg; 979 struct sipmsg *msg;
983 int restlen; 980 int restlen;
984
985 cur = conn->inbuf; 981 cur = conn->inbuf;
986 982
987 /* according to the RFC remove CRLF at the beginning */ 983 /* according to the RFC remove CRLF at the beginning */
988 while(*cur == '\r' || *cur == '\n') { 984 while(*cur == '\r' || *cur == '\n') {
989 cur++; 985 cur++;
1013 conn->inbufused=strlen(conn->inbuf); 1009 conn->inbufused=strlen(conn->inbuf);
1014 } else { 1010 } else {
1015 sipmsg_free(msg); 1011 sipmsg_free(msg);
1016 return; 1012 return;
1017 } 1013 }
1018 gaim_debug(GAIM_DEBUG_MISC, "simple", "in process response response: %d\n", msg->response); 1014 gaim_debug(GAIM_DEBUG_MISC, "simple", "in process response response: %d\n", msg->response);
1019 process_input_message(sip,msg); 1015 process_input_message(sip,msg);
1020 } else { 1016 } else {
1021 gaim_debug(GAIM_DEBUG_MISC, "simple", "received a incomplete sip msg: %s\n", conn->inbuf); 1017 gaim_debug(GAIM_DEBUG_MISC, "simple", "received a incomplete sip msg: %s\n", conn->inbuf);
1022 } 1018 }
1023 } 1019 }
1065 if(sip->fd == source) sip->fd = -1; 1061 if(sip->fd == source) sip->fd = -1;
1066 } 1062 }
1067 1063
1068 conn->inbufused += len; 1064 conn->inbufused += len;
1069 conn->inbuf[conn->inbufused]='\0'; 1065 conn->inbuf[conn->inbufused]='\0';
1070 1066
1071 process_input(sip, conn); 1067 process_input(sip, conn);
1072 } 1068 }
1073 1069
1074 /* Callback for new connections on incoming TCP port */ 1070 /* Callback for new connections on incoming TCP port */
1075 static void simple_newconn_cb(gpointer data, gint source, GaimInputCondition cond) { 1071 static void simple_newconn_cb(gpointer data, gint source, GaimInputCondition cond) {
1076 GaimConnection *gc = data; 1072 GaimConnection *gc = data;
1077 struct simple_account_data *sip = gc->proto_data; 1073 struct simple_account_data *sip = gc->proto_data;
1078 struct sip_connection *conn; 1074 struct sip_connection *conn;
1079 1075
1080
1081 int newfd = accept(source, NULL, NULL); 1076 int newfd = accept(source, NULL, NULL);
1082 1077
1083 conn = connection_create(sip, newfd); 1078 conn = connection_create(sip, newfd);
1084 1079
1085 conn->inputhandler = gaim_input_add(newfd, GAIM_INPUT_READ, simple_input_cb, gc); 1080 conn->inputhandler = gaim_input_add(newfd, GAIM_INPUT_READ, simple_input_cb, gc);
1086 } 1081 }
1087 1082
1088 static void login_cb(gpointer data, gint source, GaimInputCondition cond) { 1083 static void login_cb(gpointer data, gint source, GaimInputCondition cond) {
1089 GaimConnection *gc = data; 1084 GaimConnection *gc = data;
1095 return; 1090 return;
1096 } 1091 }
1097 1092
1098 sip->fd = source; 1093 sip->fd = source;
1099 1094
1100
1101 conn = connection_create(sip, source); 1095 conn = connection_create(sip, source);
1102 1096
1103 /* get the local ip */ 1097 /* get the local ip */
1104 sip->ip = g_strdup(gaim_network_get_my_ip(source)); 1098 sip->ip = g_strdup(gaim_network_get_my_ip(source));
1105 1099
1106 do_register(sip); 1100 do_register(sip);
1107 1101
1108 conn->inputhandler = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_input_cb, gc); 1102 conn->inputhandler = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_input_cb, gc);
1109 } 1103 }
1110 1104
1111 static guint simple_ht_hash_nick(const char *nick) { 1105 static guint simple_ht_hash_nick(const char *nick) {
1112 char *lc = g_utf8_strdown(nick, -1); 1106 char *lc = g_utf8_strdown(nick, -1);
1113 guint bucket = g_str_hash(lc); 1107 guint bucket = g_str_hash(lc);
1114 g_free(lc); 1108 g_free(lc);
1115 1109
1116 return bucket; 1110 return bucket;
1117 } 1111 }
1118 1112
1119 static gboolean simple_ht_equals_nick(const char *nick1, const char *nick2) { 1113 static gboolean simple_ht_equals_nick(const char *nick1, const char *nick2) {
1120 return (gaim_utf8_strcasecmp(nick1, nick2) == 0); 1114 return (gaim_utf8_strcasecmp(nick1, nick2) == 0);
1140 hostname = g_strdup(sip->servername); 1134 hostname = g_strdup(sip->servername);
1141 } else { 1135 } else {
1142 hostname = g_strdup(gaim_account_get_string(sip->account, "proxy", sip->servername)); 1136 hostname = g_strdup(gaim_account_get_string(sip->account, "proxy", sip->servername));
1143 } 1137 }
1144 } 1138 }
1145 1139
1146 sip->realhostname = hostname; 1140 sip->realhostname = hostname;
1147 sip->realport = port; 1141 sip->realport = port;
1148 /* TCP case */ 1142 /* TCP case */
1149 if(! sip->udp) { 1143 if(! sip->udp) {
1150 gaim_debug_info("simple","connecting to %s port %d\n", hostname, port); 1144 gaim_debug_info("simple","connecting to %s port %d\n", hostname, port);
1151 /* open tcp connection to the server */ 1145 /* open tcp connection to the server */
1152 error = gaim_proxy_connect(sip->account, hostname, port, login_cb, sip->gc); 1146 error = gaim_proxy_connect(sip->account, hostname, port, login_cb, sip->gc);
1153 if(error) { 1147 if(error) {
1154 gaim_connection_error(sip->gc, _("Couldn't create socket")); 1148 gaim_connection_error(sip->gc, _("Couldn't create socket"));
1155 } 1149 }
1176 sip->listenfd = sip->fd; 1170 sip->listenfd = sip->fd;
1177 1171
1178 gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_udp_process, sip->gc); 1172 gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_udp_process, sip->gc);
1179 sip->serveraddr.sin_family = AF_INET; 1173 sip->serveraddr.sin_family = AF_INET;
1180 sip->serveraddr.sin_port = htons(port); 1174 sip->serveraddr.sin_port = htons(port);
1181 1175
1182 h = gethostbyname(hostname); 1176 h = gethostbyname(hostname);
1183 sip->serveraddr.sin_addr.s_addr = ((struct in_addr*)h->h_addr)->s_addr; 1177 sip->serveraddr.sin_addr.s_addr = ((struct in_addr*)h->h_addr)->s_addr;
1184 sip->ip = g_strdup(gaim_network_get_my_ip(sip->listenfd)); 1178 sip->ip = g_strdup(gaim_network_get_my_ip(sip->listenfd));
1185 sip->resendtimeout = gaim_timeout_add(2500, (GSourceFunc)resend_timeout, sip); 1179 sip->resendtimeout = gaim_timeout_add(2500, (GSourceFunc)resend_timeout, sip);
1186 do_register(sip); 1180 do_register(sip);
1187 } 1181 }
1188 } 1182 }
1189 1183
1190 static void simple_login(GaimAccount *account, GaimStatus *status) 1184 static void simple_login(GaimAccount *account, GaimStatus *status)
1191 { 1185 {
1192 GaimConnection *gc; 1186 GaimConnection *gc;
1193 struct simple_account_data *sip; 1187 struct simple_account_data *sip;
1194 gchar **userserver; 1188 gchar **userserver;
1195 gchar *hosttoconnect; 1189 gchar *hosttoconnect;
1196 1190
1197 const char *username = gaim_account_get_username(account); 1191 const char *username = gaim_account_get_username(account);
1198 1192
1199 gc = gaim_account_get_connection(account); 1193 gc = gaim_account_get_connection(account);
1200 gc->proto_data = sip = g_new0(struct simple_account_data,1); 1194 gc->proto_data = sip = g_new0(struct simple_account_data,1);
1201 sip->gc=gc; 1195 sip->gc=gc;
1202 sip->account = account; 1196 sip->account = account;
1203 sip->registerexpire = 900; 1197 sip->registerexpire = 900;
1204 sip->udp = gaim_account_get_bool(account, "udp", FALSE); 1198 sip->udp = gaim_account_get_bool(account, "udp", FALSE);
1205 if (strpbrk(username, " \t\v\r\n") != NULL) { 1199 if (strpbrk(username, " \t\v\r\n") != NULL) {
1206 gaim_connection_error(gc, _("SIP usernames may not contain whitespaces or @ symbols")); 1200 gaim_connection_error(gc, _("SIP usernames may not contain whitespaces or @ symbols"));
1207 return; 1201 return;
1208 } 1202 }
1209 1203
1210 userserver = g_strsplit(username, "@", 2); 1204 userserver = g_strsplit(username, "@", 2);
1211 gaim_connection_set_display_name(gc,userserver[0]); 1205 gaim_connection_set_display_name(gc,userserver[0]);
1212 sip->username = g_strdup(userserver[0]); 1206 sip->username = g_strdup(userserver[0]);
1213 sip->servername = g_strdup(userserver[1]); 1207 sip->servername = g_strdup(userserver[1]);
1214 sip->password = g_strdup(gaim_connection_get_password(gc)); 1208 sip->password = g_strdup(gaim_connection_get_password(gc));
1215 g_strfreev(userserver); 1209 g_strfreev(userserver);
1216 1210
1217 sip->buddies = g_hash_table_new((GHashFunc)simple_ht_hash_nick, (GEqualFunc)simple_ht_equals_nick); 1211 sip->buddies = g_hash_table_new((GHashFunc)simple_ht_hash_nick, (GEqualFunc)simple_ht_equals_nick);
1218 1212
1219 gaim_connection_update_progress(gc, _("Connecting"), 1, 2); 1213 gaim_connection_update_progress(gc, _("Connecting"), 1, 2);
1220 1214
1221 sip->status = g_strdup("available"); 1215 sip->status = g_strdup("available");
1222 1216
1223 if(!gaim_account_get_bool(account, "useproxy", FALSE)) { 1217 if(!gaim_account_get_bool(account, "useproxy", FALSE)) {
1224 hosttoconnect = g_strdup(sip->servername); 1218 hosttoconnect = g_strdup(sip->servername);
1225 } else { 1219 } else {
1226 hosttoconnect = g_strdup(gaim_account_get_string(account, "proxy", sip->servername)); 1220 hosttoconnect = g_strdup(gaim_account_get_string(account, "proxy", sip->servername));
1227 } 1221 }
1228 1222
1229 /* TCP case */ 1223 /* TCP case */
1230 if(! sip->udp) { 1224 if(! sip->udp) {
1231 gaim_srv_resolve("sip","tcp",hosttoconnect,srvresolved, sip); 1225 gaim_srv_resolve("sip","tcp",hosttoconnect,srvresolved, sip);
1232 } else { /* UDP */ 1226 } else { /* UDP */
1233 gaim_srv_resolve("sip","udp",hosttoconnect,srvresolved, sip); 1227 gaim_srv_resolve("sip","udp",hosttoconnect,srvresolved, sip);
1234 } 1228 }
1235 g_free(hosttoconnect); 1229 g_free(hosttoconnect);
1236 1230
1237 /* register timeout callback for register / subscribe renewal */ 1231 /* register timeout callback for register / subscribe renewal */
1238 sip->registertimeout = gaim_timeout_add((rand()%100)+10*1000, (GSourceFunc)register_timeout, sip); 1232 sip->registertimeout = gaim_timeout_add((rand()%100)+10*1000, (GSourceFunc)register_timeout, sip);
1239 } 1233 }
1240 1234
1241 static void simple_close(GaimConnection *gc) 1235 static void simple_close(GaimConnection *gc)
1361 NULL 1355 NULL
1362 }; 1356 };
1363 1357
1364 static void _init_plugin(GaimPlugin *plugin) 1358 static void _init_plugin(GaimPlugin *plugin)
1365 { 1359 {
1366 GaimAccountUserSplit *split; 1360 GaimAccountUserSplit *split;
1367 GaimAccountOption *option; 1361 GaimAccountOption *option;
1368 1362
1369 split = gaim_account_user_split_new(_("Server"), "", '@'); 1363 split = gaim_account_user_split_new(_("Server"), "", '@');
1370 prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); 1364 prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
1371 1365
1372 option = gaim_account_option_bool_new(_("Publish Status (note: everyone may watch you)"), "dopublish", TRUE); 1366 option = gaim_account_option_bool_new(_("Publish Status (note: everyone may watch you)"), "dopublish", TRUE);
1373 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); 1367 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
1374 1368
1375 option = gaim_account_option_bool_new(_("Use UDP"), "udp", FALSE); 1369 option = gaim_account_option_bool_new(_("Use UDP"), "udp", FALSE);