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