Mercurial > pidgin
annotate src/protocols/simple/simple.c @ 12339:fdac1c5e6c68
[gaim-migrate @ 14643]
Don't show offline bonjour uses as away. Of course, the only time you
would ever have an offline bonjour user is if you add some random person
to your buddy list
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 05 Dec 2005 03:42:48 +0000 |
parents | 4d3119205a33 |
children | cfc808463763 |
rev | line source |
---|---|
11181 | 1 /** |
2 * @file simple.c | |
3 * | |
4 * gaim | |
5 * | |
6 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de> | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
7 * |
11345 | 8 * *** |
9 * Thanks to Google's Summer of Code Program and the helpful mentors | |
10 * *** | |
11181 | 11 * |
12 * This program is free software; you can redistribute it and/or modify | |
13 * it under the terms of the GNU General Public License as published by | |
14 * the Free Software Foundation; either version 2 of the License, or | |
15 * (at your option) any later version. | |
16 * | |
17 * This program is distributed in the hope that it will be useful, | |
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 * GNU General Public License for more details. | |
21 * | |
22 * You should have received a copy of the GNU General Public License | |
23 * along with this program; if not, write to the Free Software | |
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
25 */ | |
26 | |
27 #include "internal.h" | |
28 | |
29 #include "accountopt.h" | |
30 #include "blist.h" | |
31 #include "conversation.h" | |
32 #include "debug.h" | |
33 #include "notify.h" | |
11345 | 34 #include "privacy.h" |
11181 | 35 #include "prpl.h" |
36 #include "plugin.h" | |
37 #include "util.h" | |
38 #include "version.h" | |
39 #include "network.h" | |
40 #include "xmlnode.h" | |
41 | |
42 #include "simple.h" | |
43 #include "sipmsg.h" | |
11383 | 44 #include "dnssrv.h" |
11409 | 45 #include "ntlm.h" |
11181 | 46 |
47 static char *gentag() { | |
48 return g_strdup_printf("%04d%04d", rand() & 0xFFFF, rand() & 0xFFFF); | |
49 } | |
50 | |
51 static char *genbranch() { | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
52 return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X", |
11181 | 53 rand() & 0xFFFF, |
54 rand() & 0xFFFF, | |
55 rand() & 0xFFFF, | |
56 rand() & 0xFFFF, | |
57 rand() & 0xFFFF); | |
58 } | |
59 | |
60 static char *gencallid() { | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
61 return g_strdup_printf("%04Xg%04Xa%04Xi%04Xm%04Xt%04Xb%04Xx%04Xx", |
11181 | 62 rand() & 0xFFFF, |
63 rand() & 0xFFFF, | |
64 rand() & 0xFFFF, | |
65 rand() & 0xFFFF, | |
66 rand() & 0xFFFF, | |
67 rand() & 0xFFFF, | |
68 rand() & 0xFFFF, | |
69 rand() & 0xFFFF); | |
70 } | |
71 | |
72 static const char *simple_list_icon(GaimAccount *a, GaimBuddy *b) { | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
73 return "simple"; |
11181 | 74 } |
75 | |
76 static void simple_keep_alive(GaimConnection *gc) { | |
11194 | 77 struct simple_account_data *sip = gc->proto_data; |
11341 | 78 if(sip->udp) { /* in case of UDP send a packet only with a 0 byte to |
79 remain in the NAT table */ | |
11194 | 80 gchar buf[2]={0,0}; |
81 gaim_debug_info("simple", "sending keep alive\n"); | |
82 sendto(sip->fd, buf, 1, 0, (struct sockaddr*)&sip->serveraddr, sizeof(struct sockaddr_in)); | |
83 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
84 return; |
11181 | 85 } |
86 | |
87 static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc); | |
88 static void send_notify(struct simple_account_data *sip, struct simple_watcher *); | |
89 | |
90 static void send_publish(struct simple_account_data *sip); | |
91 | |
92 static void do_notifies(struct simple_account_data *sip) { | |
93 GSList *tmp = sip->watcher; | |
94 gaim_debug_info("simple", "do_notifies()\n"); | |
11345 | 95 if((sip->republish != -1) || sip->republish < time(NULL)) { |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
96 if(gaim_account_get_bool(sip->account, "dopublish", TRUE)) { |
11345 | 97 send_publish(sip); |
98 } | |
99 } | |
11181 | 100 |
101 while(tmp) { | |
102 gaim_debug_info("simple", "notifying %s\n", ((struct simple_watcher*)tmp->data)->name); | |
103 send_notify(sip, tmp->data); | |
104 tmp = tmp->next; | |
105 } | |
106 } | |
107 | |
108 static void simple_set_status(GaimAccount *account, GaimStatus *status) { | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
109 GaimStatusPrimitive primitive = gaim_status_type_get_primitive(gaim_status_get_type(status)); |
11181 | 110 struct simple_account_data *sip = NULL; |
11718 | 111 |
11181 | 112 if (!gaim_status_is_active(status)) |
113 return; | |
114 | |
11718 | 115 if (account->gc) |
116 sip = account->gc->proto_data; | |
117 | |
118 if (sip) | |
119 { | |
11650 | 120 g_free(sip->status); |
11718 | 121 if (primitive == GAIM_STATUS_AVAILABLE) |
122 sip->status = g_strdup("available"); | |
123 else | |
124 sip->status = g_strdup("busy"); | |
11181 | 125 |
126 do_notifies(sip); | |
127 } | |
128 } | |
129 | |
130 static struct sip_connection *connection_find(struct simple_account_data *sip, int fd) { | |
131 struct sip_connection *ret = NULL; | |
132 GSList *entry = sip->openconns; | |
133 while(entry) { | |
134 ret = entry->data; | |
135 if(ret->fd == fd) return ret; | |
136 entry = entry->next; | |
137 } | |
138 return NULL; | |
139 } | |
140 | |
141 static struct simple_watcher *watcher_find(struct simple_account_data *sip, gchar *name) { | |
142 struct simple_watcher *watcher; | |
143 GSList *entry = sip->watcher; | |
144 while(entry) { | |
145 watcher = entry->data; | |
146 if(!strcmp(name, watcher->name)) return watcher; | |
147 entry = entry->next; | |
148 } | |
149 return NULL; | |
150 } | |
151 | |
152 static struct simple_watcher *watcher_create(struct simple_account_data *sip, gchar *name, gchar *callid, gchar *ourtag, gchar *theirtag) { | |
153 struct simple_watcher *watcher = g_new0(struct simple_watcher,1); | |
154 watcher->name = g_strdup(name); | |
155 watcher->dialog.callid = g_strdup(callid); | |
156 watcher->dialog.ourtag = g_strdup(ourtag); | |
157 watcher->dialog.theirtag = g_strdup(theirtag); | |
158 sip->watcher = g_slist_append(sip->watcher, watcher); | |
159 return watcher; | |
160 } | |
161 | |
162 static void watcher_remove(struct simple_account_data *sip, gchar *name) { | |
163 struct simple_watcher *watcher = watcher_find(sip, name); | |
164 sip->watcher = g_slist_remove(sip->watcher, watcher); | |
165 g_free(watcher->name); | |
166 g_free(watcher->dialog.callid); | |
167 g_free(watcher->dialog.ourtag); | |
168 g_free(watcher->dialog.theirtag); | |
169 g_free(watcher); | |
170 } | |
171 | |
172 static struct sip_connection *connection_create(struct simple_account_data *sip, int fd) { | |
173 struct sip_connection *ret = g_new0(struct sip_connection,1); | |
174 ret->fd = fd; | |
175 sip->openconns = g_slist_append(sip->openconns, ret); | |
176 return ret; | |
177 } | |
178 | |
179 static void connection_remove(struct simple_account_data *sip, int fd) { | |
180 struct sip_connection *conn = connection_find(sip, fd); | |
181 sip->openconns = g_slist_remove(sip->openconns, conn); | |
182 if(conn->inputhandler) gaim_input_remove(conn->inputhandler); | |
11650 | 183 g_free(conn->inbuf); |
11181 | 184 g_free(conn); |
185 } | |
186 | |
11346 | 187 static void connection_free_all(struct simple_account_data *sip) { |
188 struct sip_connection *ret = NULL; | |
189 GSList *entry = sip->openconns; | |
190 while(entry) { | |
191 ret = entry->data; | |
192 connection_remove(sip, ret->fd); | |
193 entry = sip->openconns; | |
194 } | |
195 } | |
196 | |
11181 | 197 static void simple_add_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) |
198 { | |
199 struct simple_account_data *sip = (struct simple_account_data *)gc->proto_data; | |
200 struct simple_buddy *b; | |
201 if(strncmp("sip:", buddy->name,4)) { | |
202 gchar *buf = g_strdup_printf(_("Could not add the buddy %s because every simple user has to start with 'sip:'."), buddy->name); | |
203 gaim_notify_error(gc, NULL, _("Unable To Add"), buf); | |
204 g_free(buf); | |
205 gaim_blist_remove_buddy(buddy); | |
206 return; | |
207 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
208 if(!g_hash_table_lookup(sip->buddies, buddy->name)) { |
11181 | 209 b = g_new0(struct simple_buddy, 1); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
210 gaim_debug_info("simple","simple_add_buddy %s\n",buddy->name); |
11181 | 211 b->name = g_strdup(buddy->name); |
212 g_hash_table_insert(sip->buddies, b->name, b); | |
213 } else { | |
214 gaim_debug_info("simple","buddy %s already in internal list\n", buddy->name); | |
215 } | |
216 } | |
217 | |
218 static void simple_get_buddies(GaimConnection *gc) { | |
219 GaimBlistNode *gnode, *cnode, *bnode; | |
220 | |
221 gaim_debug_info("simple","simple_get_buddies\n"); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
222 |
11181 | 223 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { |
224 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) continue; | |
225 for(cnode = gnode->child; cnode; cnode = cnode->next) { | |
226 if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) continue; | |
227 for(bnode = cnode->child; bnode; bnode = bnode->next) { | |
228 if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) continue; | |
11192 | 229 if(((GaimBuddy*)bnode)->account == gc->account) |
230 simple_add_buddy(gc, (GaimBuddy*)bnode, (GaimGroup *)gnode); | |
11181 | 231 } |
232 } | |
233 } | |
234 } | |
235 | |
236 static void simple_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) | |
237 { | |
238 struct simple_account_data *sip = (struct simple_account_data *)gc->proto_data; | |
239 struct simple_buddy *b = g_hash_table_lookup(sip->buddies, buddy->name); | |
240 g_hash_table_remove(sip->buddies, buddy->name); | |
241 g_free(b->name); | |
242 g_free(b); | |
243 } | |
244 | |
245 static GList *simple_status_types(GaimAccount *acc) { | |
246 GaimStatusType *type; | |
247 GList *types = NULL; | |
248 gaim_debug_info("simple","called simple_status_types\n"); | |
249 type = gaim_status_type_new(GAIM_STATUS_OFFLINE, "offline", _("Offline"), FALSE); | |
250 types = g_list_append(types, type); | |
251 | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
252 type = gaim_status_type_new_with_attrs( |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
253 GAIM_STATUS_AVAILABLE, "available", _("Available"), |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
254 TRUE, TRUE, FALSE, |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
255 "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
256 types = g_list_append(types, type); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
257 |
11181 | 258 return types; |
259 } | |
260 | |
11346 | 261 static gchar *auth_header(struct simple_account_data *sip, struct sip_auth *auth, gchar *method, gchar *target) { |
262 gchar noncecount[9]; | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
263 HASHHEX HA2; |
11346 | 264 HASHHEX response; |
265 gchar *ret; | |
11409 | 266 gchar *tmp; |
267 | |
268 if(auth->type == 1) { /* Digest */ | |
269 sprintf(noncecount, "%08d", auth->nc++); | |
270 DigestCalcResponse(auth->HA1, auth->nonce, noncecount, "", "", method, target, HA2, response); | |
271 gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response); | |
272 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); | |
273 return ret; | |
274 } else if(auth->type == 2) { /* NTLM */ | |
275 if(auth->nc == 3) { | |
276 ret = gaim_ntlm_gen_type3(sip->username, sip->password, "gaim", sip->servername, auth->nonce); | |
11424 | 277 tmp = g_strdup_printf("NTLM qop=\"auth\" realm=\"%s\" targetname=\"%s\" response=\"%s\"\r\n",auth->realm, auth->target, ret); |
11409 | 278 g_free(ret); |
279 return tmp; | |
280 } | |
281 ret = gaim_ntlm_gen_type1("gaim", sip->servername); | |
11483 | 282 tmp = g_strdup_printf("NTLM qop=\"auth\" realm=\"%s\" targetname=\"%s\" response=\"%s\"\r\n", auth->realm, auth->target, ret); |
11409 | 283 g_free(ret); |
284 return tmp; | |
285 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
286 |
11346 | 287 sprintf(noncecount, "%08d", auth->nc++); |
288 DigestCalcResponse(auth->HA1, auth->nonce, noncecount, "", "", method, target, HA2, response); | |
289 gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response); | |
290 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); | |
291 return ret; | |
292 } | |
293 | |
294 static void fill_auth(struct simple_account_data *sip, gchar *hdr, struct sip_auth *auth) { | |
11409 | 295 int i=0; |
11424 | 296 char *tmp; |
297 char *tmp2; | |
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
298 gchar **parts; |
11346 | 299 if(!hdr) { |
11409 | 300 gaim_debug_error("simple", "fill_auth: hdr==NULL\n"); |
11346 | 301 return; |
302 } | |
11409 | 303 |
304 if(!g_strncasecmp(hdr, "NTLM", 4)) { | |
305 gaim_debug_info("simple", "found NTLM\n"); | |
306 auth->type = 2; | |
307 if(!auth->nonce && !auth->nc) { | |
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
308 parts = g_strsplit(hdr, " ", 0); |
11424 | 309 while(parts[i]) { |
310 if(!strncmp(parts[i],"targetname",10)) { | |
311 auth->target = g_strndup(parts[i]+12,strlen(parts[i]+12)-1); | |
312 } | |
313 if(!strncmp(parts[i],"realm",5)) { | |
314 tmp = strstr(hdr, "realm="); | |
315 tmp += 7; | |
316 tmp2 = strchr(tmp, '"'); | |
317 *tmp2 = 0; | |
318 auth->realm = g_strdup(tmp); | |
319 *tmp2 = '"'; | |
320 } | |
321 i++; | |
322 } | |
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
323 g_strfreev(parts); |
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
324 parts = NULL; |
11409 | 325 auth->nc = 1; |
326 } | |
327 if(!auth->nonce && auth->nc==2) { | |
328 auth->nc = 3; | |
329 auth->nonce = gaim_ntlm_parse_type2(hdr+5); | |
330 } | |
331 return; | |
332 } | |
333 | |
334 auth->type = 1; | |
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
335 parts = g_strsplit(hdr, " ", 0); |
11346 | 336 while(parts[i]) { |
337 if(!strncmp(parts[i],"nonce",5)) { | |
338 auth->nonce = g_strndup(parts[i]+7,strlen(parts[i]+7)-1); | |
339 } | |
340 if(!strncmp(parts[i],"realm",5)) { | |
341 auth->realm = g_strndup(parts[i]+7,strlen(parts[i]+7)-2); | |
342 } | |
343 i++; | |
344 } | |
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
345 g_strfreev(parts); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
346 |
11346 | 347 gaim_debug(GAIM_DEBUG_MISC, "simple", "nonce: %s realm: %s ", auth->nonce, auth->realm); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
348 |
11346 | 349 DigestCalcHA1("md5", sip->username, auth->realm, sip->password, auth->nonce, "", auth->HA1); |
350 | |
351 auth->nc=1; | |
352 } | |
353 | |
11181 | 354 static void simple_input_cb(gpointer data, gint source, GaimInputCondition cond); |
355 | |
356 static void send_later_cb(gpointer data, gint source, GaimInputCondition cond) { | |
357 GaimConnection *gc = data; | |
358 struct simple_account_data *sip = gc->proto_data; | |
359 struct sip_connection *conn; | |
360 | |
361 if( source < 0 ) { | |
362 gaim_connection_error(gc,"Could not connect"); | |
363 return; | |
364 } | |
365 | |
366 sip->fd = source; | |
367 sip->connecting = 0; | |
368 write(sip->fd, sip->sendlater, strlen(sip->sendlater)); | |
369 conn = connection_create(sip, source); | |
370 conn->inputhandler = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_input_cb, gc); | |
371 g_free(sip->sendlater); | |
372 sip->sendlater = 0; | |
373 } | |
374 | |
375 | |
376 static void sendlater(GaimConnection *gc, const char *buf) { | |
377 struct simple_account_data *sip = gc->proto_data; | |
378 int error = 0; | |
379 if(!sip->connecting) { | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
380 gaim_debug_info("simple","connecting to %s port %d\n", sip->realhostname ? sip->realhostname : "{NULL}", sip->realport); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
381 error = gaim_proxy_connect(sip->account, sip->realhostname, sip->realport, send_later_cb, gc); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
382 if(error) { |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
383 gaim_connection_error(gc, _("Couldn't create socket")); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
384 } |
11181 | 385 sip->connecting = 1; |
386 } | |
387 if(sip->sendlater) { | |
388 gchar *old = sip->sendlater; | |
389 sip->sendlater = g_strdup_printf("%s\r\n%s",old, buf); | |
390 } else { | |
391 sip->sendlater = g_strdup(buf); | |
392 } | |
393 } | |
394 | |
395 static int sendout_pkt(GaimConnection *gc, const char *buf) { | |
396 struct simple_account_data *sip = gc->proto_data; | |
397 time_t currtime = time(NULL); | |
11189 | 398 int ret = 0; |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
399 |
11181 | 400 gaim_debug(GAIM_DEBUG_MISC, "simple", "\n\nsending - %s\n######\n%s\n######\n\n", ctime(&currtime), buf); |
11189 | 401 if(sip->udp) { |
402 if(sendto(sip->fd, buf, strlen(buf), 0, (struct sockaddr*)&sip->serveraddr, sizeof(struct sockaddr_in)) < strlen(buf)) { | |
403 gaim_debug_info("simple", "could not send packet\n"); | |
404 } | |
405 } else { | |
406 if(sip->fd <0 ) { | |
407 sendlater(gc, buf); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
408 return 0; |
11189 | 409 } |
410 ret = write(sip->fd, buf, strlen(buf)); | |
411 if(ret < 0) { | |
412 sendlater(gc,buf); | |
413 return 0; | |
414 } | |
11181 | 415 } |
416 return ret; | |
417 } | |
418 | |
11194 | 419 static void sendout_sipmsg(struct simple_account_data *sip, struct sipmsg *msg) { |
420 gchar *oldstr; | |
421 gchar *outstr = g_strdup_printf("%s %s SIP/2.0\r\n", msg->method, msg->target); | |
422 gchar *name; | |
423 gchar *value; | |
424 GSList *tmp = msg->headers; | |
425 while(tmp) { | |
426 oldstr = outstr; | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
427 name = ((struct siphdrelement*)(tmp->data))->name; |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
428 value = ((struct siphdrelement*)(tmp->data))->value; |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
429 outstr = g_strdup_printf("%s%s: %s\r\n",oldstr, name, value); |
11194 | 430 g_free(oldstr); |
431 tmp = g_slist_next(tmp); | |
432 } | |
433 oldstr = outstr; | |
434 if(msg->body) outstr = g_strdup_printf("%s\r\n%s", outstr, msg->body); | |
435 else outstr = g_strdup_printf("%s\r\n", outstr); | |
436 g_free(oldstr); | |
437 sendout_pkt(sip->gc, outstr); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
438 g_free(outstr); |
11194 | 439 } |
440 | |
11181 | 441 static void send_sip_response(GaimConnection *gc, struct sipmsg *msg, int code, char *text, char *body) { |
442 GSList *tmp = msg->headers; | |
443 char *oldstr; | |
444 char *name; | |
445 char *value; | |
446 char *outstr = g_strdup_printf("SIP/2.0 %d %s\r\n",code, text); | |
447 while(tmp) { | |
448 oldstr = outstr; | |
449 name = ((struct siphdrelement*)(tmp->data))->name; | |
450 value = ((struct siphdrelement*)(tmp->data))->value; | |
451 outstr = g_strdup_printf("%s%s: %s\r\n",oldstr, name, value); | |
452 g_free(oldstr); | |
453 tmp = g_slist_next(tmp); | |
454 } | |
455 oldstr = outstr; | |
456 if(body) outstr = g_strdup_printf("%s\r\n%s",outstr,body); | |
457 else outstr = g_strdup_printf("%s\r\n",outstr); | |
458 g_free(oldstr); | |
459 sendout_pkt(gc, outstr); | |
460 g_free(outstr); | |
461 } | |
462 | |
11194 | 463 static void transactions_remove(struct simple_account_data *sip, struct transaction *trans) { |
464 if(trans->msg) sipmsg_free(trans->msg); | |
465 sip->transactions = g_slist_remove(sip->transactions, trans); | |
466 g_free(trans); | |
467 } | |
468 | |
11181 | 469 static void transactions_add_buf(struct simple_account_data *sip, gchar *buf, void *callback) { |
470 struct transaction *trans = g_new0(struct transaction, 1); | |
471 trans->time = time(NULL); | |
472 trans->msg = sipmsg_parse_msg(buf); | |
473 trans->cseq = sipmsg_find_header(trans->msg, "CSeq"); | |
474 trans->callback = callback; | |
475 sip->transactions = g_slist_append(sip->transactions, trans); | |
476 } | |
477 | |
478 static struct transaction *transactions_find(struct simple_account_data *sip, struct sipmsg *msg) { | |
479 struct transaction *trans; | |
480 GSList *transactions = sip->transactions; | |
481 gchar *cseq = sipmsg_find_header(msg, "CSeq"); | |
482 | |
483 while(transactions) { | |
484 trans = transactions->data; | |
485 if(!strcmp(trans->cseq, cseq)) { | |
486 return trans; | |
487 } | |
488 transactions = transactions->next; | |
489 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
490 |
11181 | 491 return (struct transaction *)NULL; |
492 } | |
493 | |
494 static void send_sip_request(GaimConnection *gc, gchar *method, gchar *url, gchar *to, gchar *addheaders, gchar *body, struct sip_dialog *dialog, TransCallback tc) { | |
495 struct simple_account_data *sip = gc->proto_data; | |
496 char *callid= dialog ? g_strdup(dialog->callid) : gencallid(); | |
12216 | 497 char *auth=""; |
498 char *addh=""; | |
499 gchar *branch = genbranch(); | |
500 char *buf; | |
501 | |
12196 | 502 if(!strcmp(method,"REGISTER")) { |
503 if(sip->regcallid) callid = g_strdup(sip->regcallid); | |
504 else sip->regcallid = g_strdup(callid); | |
505 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
506 |
11181 | 507 if(addheaders) addh=addheaders; |
11409 | 508 if(sip->registrar.type && !strcmp(method,"REGISTER")) { |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
509 buf = auth_header(sip, &sip->registrar, method, url); |
11346 | 510 auth = g_strdup_printf("Authorization: %s",buf); |
511 g_free(buf); | |
11181 | 512 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth); |
513 } | |
514 | |
11409 | 515 if(sip->proxy.type && strcmp(method,"REGISTER")) { |
11346 | 516 buf = auth_header(sip, &sip->proxy, method, url); |
517 auth = g_strdup_printf("Proxy-Authorization: %s",buf); | |
518 g_free(buf); | |
11181 | 519 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth); |
520 } | |
521 | |
12196 | 522 if(!sip->ip || !strcmp(sip->ip,"0.0.0.0")) { // if there was no known ip retry now |
523 g_free(sip->ip); | |
524 sip->ip = g_strdup(gaim_network_get_public_ip()); | |
525 } | |
11181 | 526 buf = g_strdup_printf("%s %s SIP/2.0\r\n" |
11190 | 527 "Via: SIP/2.0/%s %s:%d;branch=%s\r\n" |
11181 | 528 "From: <sip:%s@%s>;tag=%s\r\n" |
529 "To: <%s>%s%s\r\n" | |
530 "Max-Forwards: 10\r\n" | |
531 "CSeq: %d %s\r\n" | |
532 "User-Agent: Gaim SIP/SIMPLE Plugin\r\n" | |
533 "Call-ID: %s\r\n" | |
534 "%s%s" | |
11658 | 535 "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n%s", |
11181 | 536 method, |
537 url, | |
11190 | 538 sip->udp ? "UDP" : "TCP", |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
539 sip->ip ? sip->ip : "", |
11181 | 540 sip->listenport, |
541 branch, | |
542 sip->username, | |
543 sip->servername, | |
544 dialog ? dialog->ourtag : gentag(), | |
545 to, | |
546 dialog ? ";tag=" : "", | |
547 dialog ? dialog->theirtag : "", | |
548 ++sip->cseq, | |
549 method, | |
550 callid, | |
551 auth, | |
552 addh, | |
553 strlen(body), | |
554 body); | |
555 g_free(branch); | |
556 g_free(callid); | |
557 | |
11341 | 558 /* add to ongoing transactions */ |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
559 |
11181 | 560 transactions_add_buf(sip, buf, tc); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
561 |
11181 | 562 sendout_pkt(gc,buf); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
563 |
11181 | 564 g_free(buf); |
565 } | |
566 | |
11194 | 567 static void do_register_exp(struct simple_account_data *sip, int expire) { |
11181 | 568 char *uri = g_strdup_printf("sip:%s",sip->servername); |
569 char *to = g_strdup_printf("sip:%s@%s",sip->username,sip->servername); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
570 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); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
571 |
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
572 sip->registerstatus = 1; |
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
573 |
11194 | 574 if(expire) { |
575 sip->reregister = time(NULL) + expire - 50; | |
576 } else { | |
577 sip->reregister = time(NULL) + 600; | |
578 } | |
579 send_sip_request(sip->gc,"REGISTER",uri,to, contact, "", NULL, process_register_response); | |
11341 | 580 g_free(contact); |
11181 | 581 g_free(uri); |
582 g_free(to); | |
583 } | |
584 | |
11194 | 585 static void do_register(struct simple_account_data *sip) { |
586 do_register_exp(sip, sip->registerexpire); | |
587 } | |
588 | |
11181 | 589 static gchar *parse_from(gchar *hdr) { |
590 gchar *from = hdr; | |
591 gchar *tmp; | |
592 | |
593 if(!from) return NULL; | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
594 gaim_debug_info("simple", "parsing address out of %s\n",from); |
11181 | 595 tmp = strchr(from, '<'); |
596 | |
11341 | 597 /* i hate the different SIP UA behaviours... */ |
598 if(tmp) { /* sip address in <...> */ | |
11181 | 599 from = tmp+1; |
600 tmp = strchr(from,'>'); | |
601 if(tmp) { | |
602 from = g_strndup(from,tmp-from); | |
603 } else { | |
604 gaim_debug_info("simple", "found < without > in From\n"); | |
605 return NULL; | |
606 } | |
607 } else { | |
608 tmp = strchr(from, ';'); | |
609 if(tmp) { | |
610 from = g_strndup(from,tmp-from); | |
11483 | 611 } else { |
612 from = g_strdup(from); | |
11181 | 613 } |
614 } | |
615 gaim_debug_info("simple", "got %s\n",from); | |
616 return from; | |
617 } | |
618 | |
619 static gboolean process_subscribe_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { | |
11341 | 620 gchar *to = parse_from(sipmsg_find_header(tc->msg,"To")); /* cant be NULL since it is our own msg */ |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
621 |
11181 | 622 if(msg->response==200 || msg->response==202) { |
623 return TRUE; | |
624 } | |
625 | |
11341 | 626 /* we can not subscribe -> user is offline (TODO unknown status?) */ |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
627 |
11181 | 628 gaim_prpl_got_user_status(sip->account, to, "offline", NULL); |
629 g_free(to); | |
630 return TRUE; | |
631 } | |
632 | |
633 static void simple_subscribe(struct simple_account_data *sip, struct simple_buddy *buddy) { | |
11341 | 634 gchar *contact = "Expires: 300\r\nAccept: application/pidf+xml\r\nEvent: presence\r\n"; |
11181 | 635 gchar *to; |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
636 if(strstr(buddy->name,"sip:")) to = g_strdup(buddy->name); |
11181 | 637 else to = g_strdup_printf("sip:%s",buddy->name); |
11341 | 638 contact = g_strdup_printf("%sContact: <%s@%s>\r\n", contact, sip->username, sip->servername); |
639 /* subscribe to buddy presence | |
640 * we dont need to know the status so we do not need a callback */ | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
641 |
11181 | 642 send_sip_request(sip->gc, "SUBSCRIBE",to, to, contact, "", NULL, process_subscribe_response); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
643 |
11181 | 644 g_free(to); |
11341 | 645 g_free(contact); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
646 |
11341 | 647 /* resubscribe before subscription expires */ |
648 /* add some jitter */ | |
649 buddy->resubscribe = time(NULL)+250+(rand()%50); | |
11181 | 650 } |
651 | |
652 static void simple_buddy_resub(char *name, struct simple_buddy *buddy, struct simple_account_data *sip) { | |
653 time_t curtime = time(NULL); | |
11341 | 654 gaim_debug_info("simple","buddy resub\n"); |
11181 | 655 if(buddy->resubscribe < curtime) { |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
656 gaim_debug(GAIM_DEBUG_MISC, "simple", "simple_buddy_resub %s\n",name); |
11181 | 657 simple_subscribe(sip, buddy); |
658 } | |
659 } | |
660 | |
11194 | 661 static gboolean resend_timeout(struct simple_account_data *sip) { |
662 GSList *tmp = sip->transactions; | |
663 time_t currtime = time(NULL); | |
664 while(tmp) { | |
665 struct transaction *trans = tmp->data; | |
666 tmp = tmp->next; | |
667 gaim_debug_info("simple", "have open transaction age: %d\n", currtime- trans->time); | |
668 if((currtime - trans->time > 5) && trans->retries >= 1) { | |
11341 | 669 /* TODO 408 */ |
11194 | 670 } else { |
671 if((currtime - trans->time > 2) && trans->retries == 0) { | |
672 trans->retries++; | |
673 sendout_sipmsg(sip, trans->msg); | |
674 } | |
675 } | |
676 } | |
677 return TRUE; | |
678 } | |
679 | |
11181 | 680 static gboolean register_timeout(struct simple_account_data *sip) { |
681 GSList *tmp; | |
682 time_t curtime = time(NULL); | |
11341 | 683 /* register again if first registration expires */ |
11181 | 684 if(sip->reregister < curtime) { |
11194 | 685 do_register(sip); |
11181 | 686 } |
11341 | 687 gaim_debug_info("simple","in register timeout\n"); |
688 /* check for every subscription if we need to resubscribe */ | |
11181 | 689 g_hash_table_foreach(sip->buddies, (GHFunc)simple_buddy_resub, (gpointer)sip); |
690 | |
11341 | 691 /* remove a timed out suscriber */ |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
692 |
11181 | 693 tmp = sip->watcher; |
694 while(tmp) { | |
695 struct simple_watcher *watcher = tmp->data; | |
696 if(watcher->expire < curtime) { | |
697 watcher_remove(sip, watcher->name); | |
698 tmp = sip->watcher; | |
699 } | |
700 if(tmp) tmp = tmp->next; | |
701 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
702 |
11181 | 703 return TRUE; |
704 } | |
705 | |
706 static void simple_send_message(struct simple_account_data *sip, char *to, char *msg, char *type) { | |
707 gchar *hdr; | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
708 if(type) { |
11181 | 709 hdr = g_strdup_printf("Content-Type: %s\r\n",type); |
710 } else { | |
711 hdr = g_strdup("Content-Type: text/plain\r\n"); | |
712 } | |
713 send_sip_request(sip->gc, "MESSAGE", to, to, hdr, msg, NULL, NULL); | |
714 g_free(hdr); | |
715 } | |
716 | |
12216 | 717 static int simple_im_send(GaimConnection *gc, const char *who, const char *what, GaimMessageFlags flags) { |
11181 | 718 struct simple_account_data *sip = gc->proto_data; |
719 char *to = g_strdup(who); | |
12216 | 720 char *text = gaim_unescape_html(what); |
11181 | 721 simple_send_message(sip, to, text, NULL); |
722 g_free(to); | |
723 g_free(text); | |
724 return 1; | |
725 } | |
726 | |
727 static void process_incoming_message(struct simple_account_data *sip, struct sipmsg *msg) { | |
728 gchar *from; | |
729 gchar *contenttype; | |
730 gboolean found = FALSE; | |
731 | |
732 from = parse_from(sipmsg_find_header(msg, "From")); | |
733 | |
734 if(!from) return; | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
735 |
11181 | 736 gaim_debug(GAIM_DEBUG_MISC, "simple", "got message from %s: %s\n", from, msg->body); |
737 | |
738 contenttype = sipmsg_find_header(msg, "Content-Type"); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
739 if(!contenttype || !strncmp(contenttype, "text/plain", 10) || !strncmp(contenttype, "text/html", 9)) { |
11181 | 740 serv_got_im(sip->gc, from, msg->body, 0, time(NULL)); |
741 send_sip_response(sip->gc, msg, 200, "OK", NULL); | |
742 found = TRUE; | |
743 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
744 if(!strncmp(contenttype, "application/im-iscomposing+xml",30)) { |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
745 xmlnode *isc = xmlnode_from_str(msg->body, msg->bodylen); |
11181 | 746 xmlnode *state; |
747 gchar *statedata; | |
748 | |
749 if(!isc) { | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
750 gaim_debug_info("simple","process_incoming_message: can not parse iscomposing\n"); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
751 return; |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
752 } |
11181 | 753 |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
754 state = xmlnode_get_child(isc, "state"); |
11181 | 755 |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
756 if(!state) { |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
757 gaim_debug_info("simple","process_incoming_message: no state found\n"); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
758 return; |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
759 } |
11181 | 760 |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
761 statedata = xmlnode_get_data(state); |
11181 | 762 if(statedata) { |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
763 if(strstr(statedata,"active")) serv_got_typing(sip->gc, from, 0, GAIM_TYPING); |
11181 | 764 else serv_got_typing_stopped(sip->gc, from); |
765 } | |
766 xmlnode_free(isc); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
767 send_sip_response(sip->gc, msg, 200, "OK", NULL); |
11181 | 768 found = TRUE; |
769 } | |
770 if(!found) { | |
771 gaim_debug_info("simple", "got unknown mime-type"); | |
772 send_sip_response(sip->gc, msg, 415, "Unsupported media type", NULL); | |
773 } | |
774 g_free(from); | |
775 } | |
776 | |
777 | |
778 gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { | |
779 gchar *tmp; | |
780 gaim_debug(GAIM_DEBUG_MISC, "simple", "in process register response response: %d\n", msg->response); | |
781 switch (msg->response) { | |
782 case 200: | |
11341 | 783 if(sip->registerstatus<3) { /* registered */ |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
784 if(gaim_account_get_bool(sip->account, "dopublish", TRUE)) { |
11345 | 785 send_publish(sip); |
786 } | |
11181 | 787 } |
788 sip->registerstatus=3; | |
789 gaim_connection_set_state(sip->gc, GAIM_CONNECTED); | |
11341 | 790 |
791 /* get buddies from blist */ | |
792 simple_get_buddies(sip->gc); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
793 |
11181 | 794 register_timeout(sip); |
795 break; | |
796 case 401: | |
797 if(sip->registerstatus!=2) { | |
11346 | 798 gaim_debug_info("simple","REGISTER retries %d\n",sip->registrar.retries); |
799 if(sip->registrar.retries>3) { | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
800 gaim_connection_error(sip->gc,"Wrong Password"); |
11346 | 801 return TRUE; |
802 } | |
11181 | 803 tmp = sipmsg_find_header(msg, "WWW-Authenticate"); |
804 fill_auth(sip, tmp, &sip->registrar); | |
805 sip->registerstatus=2; | |
11194 | 806 do_register(sip); |
11181 | 807 } |
808 break; | |
809 } | |
810 return TRUE; | |
811 } | |
812 | |
813 static void process_incoming_notify(struct simple_account_data *sip, struct sipmsg *msg) { | |
814 gchar *from; | |
815 gchar *fromhdr; | |
816 gchar *tmp2; | |
817 xmlnode *pidf; | |
818 xmlnode *basicstatus; | |
819 gboolean isonline = FALSE; | |
820 | |
821 fromhdr = sipmsg_find_header(msg,"From"); | |
822 from = parse_from(fromhdr); | |
823 if(!from) return; | |
824 | |
825 pidf = xmlnode_from_str(msg->body, msg->bodylen); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
826 |
11181 | 827 if(!pidf) { |
828 gaim_debug_info("simple","process_incoming_notify: no parseable pidf\n"); | |
829 return; | |
830 } | |
831 | |
832 basicstatus = xmlnode_get_child(xmlnode_get_child(xmlnode_get_child(pidf,"tuple"),"status"), "basic"); | |
833 | |
834 if(!basicstatus) { | |
835 gaim_debug_info("simple","process_incoming_notify: no basic found\n"); | |
836 return; | |
837 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
838 |
11181 | 839 tmp2 = xmlnode_get_data(basicstatus); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
840 |
11181 | 841 if(!tmp2) { |
842 gaim_debug_info("simple","process_incoming_notify: no basic data found\n"); | |
843 return; | |
844 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
845 |
11181 | 846 if(strstr(tmp2, "open")) { |
847 isonline = TRUE; | |
848 } | |
849 | |
850 if(isonline) gaim_prpl_got_user_status(sip->account, from, "available", NULL); | |
851 else gaim_prpl_got_user_status(sip->account, from, "offline", NULL); | |
852 | |
853 xmlnode_free(pidf); | |
854 | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
855 g_free(from); |
11181 | 856 send_sip_response(sip->gc, msg, 200, "OK", NULL); |
857 } | |
858 | |
859 static int simple_typing(GaimConnection *gc, const char *name, int typing) { | |
860 struct simple_account_data *sip = gc->proto_data; | |
861 | |
862 gchar *xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | |
863 "<isComposing xmlns=\"urn:ietf:params:xml:ns:im-iscomposing\"\n" | |
864 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" | |
865 "xsi:schemaLocation=\"urn:ietf:params:xml:ns:im-composing iscomposing.xsd\">\n" | |
866 "<state>%s</state>\n" | |
867 "<contenttype>text/plain</contenttype>\n" | |
868 "<refresh>60</refresh>\n" | |
869 "</isComposing>"; | |
870 gchar *recv = g_strdup(name); | |
871 if(typing == GAIM_TYPING) { | |
872 gchar *msg = g_strdup_printf(xml, "active"); | |
873 simple_send_message(sip, recv, msg, "application/im-iscomposing+xml"); | |
874 g_free(msg); | |
875 } else { | |
876 gchar *msg = g_strdup_printf(xml, "idle"); | |
877 simple_send_message(sip, recv, msg, "application/im-iscomposing+xml"); | |
878 g_free(msg); | |
879 } | |
880 g_free(recv); | |
881 return 1; | |
882 } | |
883 | |
884 static gchar *find_tag(gchar *hdr) { | |
885 gchar *tmp = strstr(hdr, ";tag="); | |
886 gchar *tmp2; | |
887 if(!tmp) return NULL; | |
888 tmp += 5; | |
889 if((tmp2 = strchr(tmp, ';'))) { | |
890 tmp2[0] = '\0'; | |
891 tmp = g_strdup(tmp); | |
892 tmp2[0] = ';'; | |
893 return tmp; | |
894 } | |
895 return g_strdup(tmp); | |
896 } | |
897 | |
898 static gchar* gen_pidf(struct simple_account_data *sip) { | |
899 gchar *doc = g_strdup_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
900 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n" |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
901 "xmlns:im=\"urn:ietf:params:xml:ns:pidf:im\"\n" |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
902 "entity=\"sip:%s@%s\">\n" |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
903 "<tuple id=\"bs35r9f\">\n" |
11181 | 904 "<status>\n" |
905 "<basic>open</basic>\n" | |
906 "<im:im>%s</im:im>\n" | |
907 "</status>\n" | |
908 "</tuple>\n" | |
909 "</presence>", | |
910 sip->username, | |
911 sip->servername, | |
912 sip->status); | |
913 return doc; | |
914 } | |
915 | |
916 static void send_notify(struct simple_account_data *sip, struct simple_watcher *watcher) { | |
917 gchar *doc = gen_pidf(sip); | |
918 send_sip_request(sip->gc, "NOTIFY", watcher->name, watcher->name, "Event: presence\r\nContent-Type: application/pidf+xml\r\n", doc, &watcher->dialog, NULL); | |
919 g_free(doc); | |
920 } | |
921 | |
922 static gboolean process_publish_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { | |
11345 | 923 if(msg->response != 200 && msg->response != 408) { |
11341 | 924 /* never send again */ |
11181 | 925 sip->republish = -1; |
926 } | |
927 return TRUE; | |
928 } | |
929 | |
930 static void send_publish(struct simple_account_data *sip) { | |
931 gchar *uri = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); | |
932 gchar *doc = gen_pidf(sip); | |
11341 | 933 send_sip_request(sip->gc, "PUBLISH", uri, uri, "Expires: 600\r\nEvent: presence\r\nContent-Type: application/pidf+xml\r\n", doc, NULL, process_publish_response); |
11181 | 934 sip->republish = time(NULL) + 500; |
935 g_free(doc); | |
936 } | |
937 | |
938 static void process_incoming_subscribe(struct simple_account_data *sip, struct sipmsg *msg) { | |
939 gchar *from = parse_from(sipmsg_find_header(msg, "From")); | |
940 gchar *theirtag = find_tag(sipmsg_find_header(msg, "From")); | |
941 gchar *ourtag = find_tag(sipmsg_find_header(msg, "To")); | |
942 gboolean tagadded = FALSE; | |
943 gchar *callid = sipmsg_find_header(msg, "Call-ID"); | |
944 gchar *expire = sipmsg_find_header(msg, "Expire"); | |
945 gchar *tmp; | |
946 struct simple_watcher *watcher = watcher_find(sip, from); | |
947 if(!ourtag) { | |
948 tagadded = TRUE; | |
949 ourtag = gentag(); | |
950 } | |
11341 | 951 if(!watcher) { /* new subscription */ |
11345 | 952 if(!gaim_privacy_check(sip->account, from)) { |
953 send_sip_response(sip->gc, msg, 202, "Ok", NULL); | |
954 goto privend; | |
955 } | |
11181 | 956 watcher = watcher_create(sip, from, callid, ourtag, theirtag); |
957 } | |
958 if(tagadded) { | |
959 gchar *to = g_strdup_printf("%s;tag=%s", sipmsg_find_header(msg, "To"), ourtag); | |
960 sipmsg_remove_header(msg, "To"); | |
961 sipmsg_add_header(msg, "To", to); | |
962 } | |
963 if(expire) | |
964 watcher->expire = time(NULL) + strtol(expire, NULL, 10); | |
965 else | |
966 watcher->expire = time(NULL) + 600; | |
967 sipmsg_remove_header(msg, "Contact"); | |
968 tmp = g_strdup_printf("<%s@%s>",sip->username, sip->servername); | |
969 sipmsg_add_header(msg, "Contact", tmp); | |
970 gaim_debug_info("simple","got subscribe: name %s ourtag %s theirtag %s callid %s\n", watcher->name, watcher->dialog.ourtag, watcher->dialog.theirtag, watcher->dialog.callid); | |
971 send_sip_response(sip->gc, msg, 200, "Ok", NULL); | |
972 g_free(tmp); | |
973 send_notify(sip, watcher); | |
11345 | 974 privend: |
975 g_free(from); | |
976 g_free(theirtag); | |
977 g_free(ourtag); | |
978 g_free(callid); | |
979 g_free(expire); | |
11181 | 980 } |
981 | |
11189 | 982 static void process_input_message(struct simple_account_data *sip, struct sipmsg *msg) { |
983 int found = 0; | |
11341 | 984 if( msg->response == 0 ) { /* request */ |
11189 | 985 if(!strcmp(msg->method, "MESSAGE")) { |
986 process_incoming_message(sip, msg); | |
987 found = 1; | |
988 } | |
989 if(!strcmp(msg->method, "NOTIFY")) { | |
990 process_incoming_notify(sip, msg); | |
991 found = 1; | |
992 } | |
993 if(!strcmp(msg->method, "SUBSCRIBE")) { | |
994 process_incoming_subscribe(sip, msg); | |
995 found = 1; | |
996 } | |
11190 | 997 if(!found) { |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
998 send_sip_response(sip->gc, msg, 501, "Not implemented", NULL); |
11190 | 999 } |
11341 | 1000 } else { /* response */ |
11189 | 1001 struct transaction *trans = transactions_find(sip, msg); |
1002 if(trans) { | |
1003 if(msg->response == 407) { | |
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
1004 gchar *resend, *auth, *ptmp; |
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
1005 |
11346 | 1006 if(sip->proxy.retries>3) return; |
1007 sip->proxy.retries++; | |
11341 | 1008 /* do proxy authentication */ |
11189 | 1009 |
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
1010 ptmp = sipmsg_find_header(msg, "Proxy-Authenticate"); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1011 |
11189 | 1012 fill_auth(sip, ptmp, &sip->proxy); |
11346 | 1013 auth = auth_header(sip, &sip->proxy, trans->msg->method, trans->msg->target); |
11189 | 1014 sipmsg_remove_header(msg, "Proxy-Authorization"); |
1015 sipmsg_add_header(trans->msg, "Proxy-Authorization", auth); | |
1016 g_free(auth); | |
1017 resend = sipmsg_to_string(trans->msg); | |
11341 | 1018 /* resend request */ |
11189 | 1019 sendout_pkt(sip->gc, resend); |
1020 g_free(resend); | |
1021 } else { | |
11517 | 1022 if(msg->response == 100) { |
1023 /* ignore provisional response */ | |
1024 gaim_debug_info("simple","got trying response\n"); | |
1025 } else { | |
1026 sip->proxy.retries = 0; | |
1027 if(msg->response == 401) sip->registrar.retries++; | |
1028 else sip->registrar.retries = 0; | |
1029 if(trans->callback) { | |
1030 /* call the callback to process response*/ | |
1031 (trans->callback)(sip, msg, trans); | |
1032 } | |
1033 transactions_remove(sip, trans); | |
11189 | 1034 } |
1035 } | |
1036 found = 1; | |
1037 } else { | |
1038 gaim_debug(GAIM_DEBUG_MISC, "simple", "received response to unknown transaction"); | |
1039 } | |
1040 } | |
1041 if(!found) { | |
1042 gaim_debug(GAIM_DEBUG_MISC, "simple", "received a unknown sip message with method %sand response %d\n",msg->method, msg->response); | |
1043 } | |
1044 } | |
1045 | |
11181 | 1046 static void process_input(struct simple_account_data *sip, struct sip_connection *conn) |
1047 { | |
1048 char *cur; | |
1049 char *dummy; | |
1050 struct sipmsg *msg; | |
1051 int restlen; | |
1052 cur = conn->inbuf; | |
1053 | |
11341 | 1054 /* according to the RFC remove CRLF at the beginning */ |
11181 | 1055 while(*cur == '\r' || *cur == '\n') { |
1056 cur++; | |
1057 } | |
1058 if(cur != conn->inbuf) { | |
1059 memmove(conn->inbuf, cur, conn->inbufused-(cur-conn->inbuf)); | |
1060 conn->inbufused=strlen(conn->inbuf); | |
1061 } | |
1062 | |
11341 | 1063 /* Received a full Header? */ |
11181 | 1064 if((cur = strstr(conn->inbuf, "\r\n\r\n"))!=NULL) { |
1065 time_t currtime = time(NULL); | |
1066 cur += 2; | |
1067 cur[0] = '\0'; | |
1068 gaim_debug_info("simple","\n\nreceived - %s\n######\n%s\n#######\n\n",ctime(&currtime), conn->inbuf); | |
1069 msg = sipmsg_parse_header(conn->inbuf); | |
1070 cur[0] = '\r'; | |
1071 cur += 2; | |
1072 restlen = conn->inbufused - (cur-conn->inbuf); | |
1073 if(restlen>=msg->bodylen) { | |
1074 dummy = g_malloc(msg->bodylen+1); | |
1075 memcpy(dummy, cur, msg->bodylen); | |
1076 dummy[msg->bodylen]='\0'; | |
1077 msg->body = dummy; | |
1078 cur+=msg->bodylen; | |
1079 memmove(conn->inbuf, cur, conn->inbuflen); | |
1080 conn->inbufused=strlen(conn->inbuf); | |
1081 } else { | |
1082 sipmsg_free(msg); | |
1083 return; | |
1084 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1085 gaim_debug(GAIM_DEBUG_MISC, "simple", "in process response response: %d\n", msg->response); |
11189 | 1086 process_input_message(sip,msg); |
11181 | 1087 } else { |
1088 gaim_debug(GAIM_DEBUG_MISC, "simple", "received a incomplete sip msg: %s\n", conn->inbuf); | |
1089 } | |
1090 } | |
1091 | |
11189 | 1092 static void simple_udp_process(gpointer data, gint source, GaimInputCondition con) { |
1093 GaimConnection *gc = data; | |
1094 struct simple_account_data *sip = gc->proto_data; | |
1095 struct sipmsg *msg; | |
1096 int len; | |
1097 time_t currtime; | |
1098 | |
1099 static char buffer[65536]; | |
1100 len = recv(source, buffer, 65536, 0); | |
1101 buffer[len] = 0; | |
1102 gaim_debug_info("simple","\n\nreceived - %s\n######\n%s\n#######\n\n",ctime(&currtime), buffer); | |
1103 msg = sipmsg_parse_msg(buffer); | |
1104 if(msg) process_input_message(sip, msg); | |
1105 } | |
1106 | |
11181 | 1107 static void simple_input_cb(gpointer data, gint source, GaimInputCondition cond) |
1108 { | |
1109 GaimConnection *gc = data; | |
1110 struct simple_account_data *sip = gc->proto_data; | |
1111 int len; | |
1112 struct sip_connection *conn = connection_find(sip, source); | |
1113 if(!conn) { | |
1114 gaim_debug_error("simple", "Connection not found!\n"); | |
1115 return; | |
1116 } | |
1117 | |
1118 if (conn->inbuflen < conn->inbufused + SIMPLE_BUF_INC) { | |
1119 conn->inbuflen += SIMPLE_BUF_INC; | |
1120 conn->inbuf = g_realloc(conn->inbuf, conn->inbuflen); | |
1121 } | |
1122 | |
1123 if ((len = read(source, conn->inbuf + conn->inbufused, SIMPLE_BUF_INC - 1)) <= 0) { | |
1124 gaim_debug_info("simple","simple_input_cb: read error\n"); | |
1125 connection_remove(sip, source); | |
1126 if(sip->fd == source) sip->fd = -1; | |
1127 return; | |
1128 } | |
1129 if(len == 0) { | |
11341 | 1130 /* connection was closed */ |
11181 | 1131 connection_remove(sip, source); |
1132 if(sip->fd == source) sip->fd = -1; | |
1133 } | |
1134 | |
1135 conn->inbufused += len; | |
1136 conn->inbuf[conn->inbufused]='\0'; | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1137 |
11181 | 1138 process_input(sip, conn); |
1139 } | |
1140 | |
1141 /* Callback for new connections on incoming TCP port */ | |
1142 static void simple_newconn_cb(gpointer data, gint source, GaimInputCondition cond) { | |
1143 GaimConnection *gc = data; | |
1144 struct simple_account_data *sip = gc->proto_data; | |
1145 struct sip_connection *conn; | |
1146 | |
1147 int newfd = accept(source, NULL, NULL); | |
1148 | |
1149 conn = connection_create(sip, newfd); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1150 |
11181 | 1151 conn->inputhandler = gaim_input_add(newfd, GAIM_INPUT_READ, simple_input_cb, gc); |
1152 } | |
1153 | |
1154 static void login_cb(gpointer data, gint source, GaimInputCondition cond) { | |
1155 GaimConnection *gc = data; | |
1156 struct simple_account_data *sip = gc->proto_data; | |
1157 struct sip_connection *conn; | |
1158 | |
1159 if( source < 0 ) { | |
1160 gaim_connection_error(gc,"Could not connect"); | |
1161 return; | |
1162 } | |
1163 | |
1164 sip->fd = source; | |
1165 | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1166 conn = connection_create(sip, source); |
11181 | 1167 |
11341 | 1168 /* get the local ip */ |
11181 | 1169 sip->ip = g_strdup(gaim_network_get_my_ip(source)); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1170 |
11194 | 1171 do_register(sip); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1172 |
11181 | 1173 conn->inputhandler = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_input_cb, gc); |
1174 } | |
1175 | |
1176 static guint simple_ht_hash_nick(const char *nick) { | |
1177 char *lc = g_utf8_strdown(nick, -1); | |
1178 guint bucket = g_str_hash(lc); | |
1179 g_free(lc); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1180 |
11181 | 1181 return bucket; |
1182 } | |
1183 | |
1184 static gboolean simple_ht_equals_nick(const char *nick1, const char *nick2) { | |
1185 return (gaim_utf8_strcasecmp(nick1, nick2) == 0); | |
1186 } | |
1187 | |
11383 | 1188 static void srvresolved(struct srv_response *resp, int results, gpointer data) { |
1189 struct simple_account_data *sip = (struct simple_account_data*) data; | |
1190 | |
1191 gchar *hostname; | |
1192 int port = 5060; | |
1193 | |
1194 int error = 0; | |
1195 struct sockaddr_in addr; | |
1196 struct hostent *h; | |
1197 | |
1198 /* find the host to connect to */ | |
1199 if(results) { | |
1200 hostname = g_strdup(resp->hostname); | |
1201 port = resp->port; | |
1202 g_free(resp); | |
1203 } else { | |
1204 if(!gaim_account_get_bool(sip->account, "useproxy", FALSE)) { | |
1205 hostname = g_strdup(sip->servername); | |
1206 } else { | |
1207 hostname = g_strdup(gaim_account_get_string(sip->account, "proxy", sip->servername)); | |
1208 } | |
1209 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1210 |
11383 | 1211 sip->realhostname = hostname; |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1212 sip->realport = port; |
11383 | 1213 /* TCP case */ |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1214 if(! sip->udp) { |
11409 | 1215 /* create socket for incoming connections */ |
1216 sip->listenfd = gaim_network_listen_range(5060, 5160); | |
1217 if(sip->listenfd == -1) { | |
1218 gaim_connection_error(sip->gc, _("Could not create listen socket")); | |
1219 return; | |
1220 } | |
1221 gaim_debug_info("simple", "listenfd: %d\n", sip->listenfd); | |
1222 sip->listenport = gaim_network_get_port_from_fd(sip->listenfd); | |
1223 sip->listenpa = gaim_input_add(sip->listenfd, GAIM_INPUT_READ, simple_newconn_cb, sip->gc); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1224 gaim_debug_info("simple","connecting to %s port %d\n", hostname, port); |
11383 | 1225 /* open tcp connection to the server */ |
1226 error = gaim_proxy_connect(sip->account, hostname, port, login_cb, sip->gc); | |
1227 if(error) { | |
1228 gaim_connection_error(sip->gc, _("Couldn't create socket")); | |
1229 } | |
1230 | |
1231 } else { /* UDP */ | |
1232 gaim_debug_info("simple", "using udp with server %s and port %d\n", hostname, port); | |
1233 sip->fd = socket(AF_INET, SOCK_DGRAM, 0); | |
1234 | |
1235 addr.sin_family = AF_INET; | |
1236 addr.sin_port = htons(5060); | |
1237 addr.sin_addr.s_addr = INADDR_ANY; | |
1238 while((bind(sip->fd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) <0) && ntohs(addr.sin_port)<5160) { | |
1239 addr.sin_port = htons(ntohs(addr.sin_port)+1); | |
1240 } | |
1241 sip->listenport = ntohs(addr.sin_port); | |
1242 sip->listenfd = sip->fd; | |
1243 | |
1244 gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_udp_process, sip->gc); | |
1245 sip->serveraddr.sin_family = AF_INET; | |
1246 sip->serveraddr.sin_port = htons(port); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1247 |
11383 | 1248 h = gethostbyname(hostname); |
1249 sip->serveraddr.sin_addr.s_addr = ((struct in_addr*)h->h_addr)->s_addr; | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1250 sip->ip = g_strdup(gaim_network_get_my_ip(sip->listenfd)); |
11383 | 1251 sip->resendtimeout = gaim_timeout_add(2500, (GSourceFunc)resend_timeout, sip); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1252 do_register(sip); |
11383 | 1253 } |
1254 } | |
1255 | |
11837 | 1256 static void simple_login(GaimAccount *account) |
11181 | 1257 { |
1258 GaimConnection *gc; | |
1259 struct simple_account_data *sip; | |
1260 gchar **userserver; | |
11210 | 1261 gchar *hosttoconnect; |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1262 |
11181 | 1263 const char *username = gaim_account_get_username(account); |
1264 | |
1265 gc = gaim_account_get_connection(account); | |
1266 gc->proto_data = sip = g_new0(struct simple_account_data,1); | |
1267 sip->gc=gc; | |
11189 | 1268 sip->account = account; |
11194 | 1269 sip->registerexpire = 900; |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1270 sip->udp = gaim_account_get_bool(account, "udp", FALSE); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1271 if (strpbrk(username, " \t\v\r\n") != NULL) { |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1272 gaim_connection_error(gc, _("SIP usernames may not contain whitespaces or @ symbols")); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1273 return; |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1274 } |
11181 | 1275 |
1276 userserver = g_strsplit(username, "@", 2); | |
1277 gaim_connection_set_display_name(gc,userserver[0]); | |
1278 sip->username = g_strdup(userserver[0]); | |
1279 sip->servername = g_strdup(userserver[1]); | |
1280 sip->password = g_strdup(gaim_connection_get_password(gc)); | |
1281 g_strfreev(userserver); | |
1282 | |
1283 sip->buddies = g_hash_table_new((GHashFunc)simple_ht_hash_nick, (GEqualFunc)simple_ht_equals_nick); | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1284 |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1285 gaim_connection_update_progress(gc, _("Connecting"), 1, 2); |
11181 | 1286 |
11837 | 1287 /* TODO: Set the status correctly. */ |
11181 | 1288 sip->status = g_strdup("available"); |
11189 | 1289 |
11210 | 1290 if(!gaim_account_get_bool(account, "useproxy", FALSE)) { |
1291 hosttoconnect = g_strdup(sip->servername); | |
1292 } else { | |
1293 hosttoconnect = g_strdup(gaim_account_get_string(account, "proxy", sip->servername)); | |
1294 } | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1295 |
11341 | 1296 /* TCP case */ |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1297 if(! sip->udp) { |
11383 | 1298 gaim_srv_resolve("sip","tcp",hosttoconnect,srvresolved, sip); |
11341 | 1299 } else { /* UDP */ |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1300 gaim_srv_resolve("sip","udp",hosttoconnect,srvresolved, sip); |
11181 | 1301 } |
11210 | 1302 g_free(hosttoconnect); |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1303 |
11341 | 1304 /* register timeout callback for register / subscribe renewal */ |
11194 | 1305 sip->registertimeout = gaim_timeout_add((rand()%100)+10*1000, (GSourceFunc)register_timeout, sip); |
11181 | 1306 } |
1307 | |
1308 static void simple_close(GaimConnection *gc) | |
1309 { | |
1310 struct simple_account_data *sip = gc->proto_data; | |
11194 | 1311 |
11341 | 1312 /* unregister */ |
11194 | 1313 do_register_exp(sip, 0); |
11346 | 1314 connection_free_all(sip); |
11341 | 1315 if(sip) { |
11650 | 1316 g_free(sip->servername); |
1317 g_free(sip->username); | |
1318 g_free(sip->password); | |
1319 g_free(sip->registrar.nonce); | |
1320 g_free(sip->registrar.realm); | |
1321 g_free(sip->proxy.nonce); | |
1322 g_free(sip->proxy.realm); | |
1323 g_free(sip->sendlater); | |
1324 g_free(sip->ip); | |
1325 g_free(sip->realhostname); | |
11409 | 1326 if(sip->listenpa) gaim_input_remove(sip->listenpa); |
11346 | 1327 if(sip->registertimeout) gaim_timeout_remove(sip->registertimeout); |
11383 | 1328 sip->servername = sip->username = sip->password = sip->registrar.nonce = sip->registrar.realm = sip->proxy.nonce = sip->proxy.realm = sip->sendlater = sip->ip = sip->realhostname = NULL; |
11181 | 1329 } |
11650 | 1330 g_free(gc->proto_data); |
11341 | 1331 gc->proto_data = 0; |
11181 | 1332 } |
1333 | |
11345 | 1334 /* not needed since privacy is checked for every subscribe */ |
1335 static void dummy_add_deny(GaimConnection *gc, const char *name) { | |
1336 } | |
1337 | |
1338 static void dummy_permit_deny(GaimConnection *gc) { | |
1339 } | |
1340 | |
11181 | 1341 static GaimPluginProtocolInfo prpl_info = |
1342 { | |
1343 0, | |
1344 NULL, /* user_splits */ | |
1345 NULL, /* protocol_options */ | |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1346 NO_BUDDY_ICONS, /* icon_spec */ |
11181 | 1347 simple_list_icon, /* list_icon */ |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1348 NULL, /* list_emblems */ |
11181 | 1349 NULL, /* status_text */ |
1350 NULL, /* tooltip_text */ | |
1351 simple_status_types, /* away_states */ | |
1352 NULL, /* blist_node_menu */ | |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1353 NULL, /* chat_info */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1354 NULL, /* chat_info_defaults */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1355 simple_login, /* login */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1356 simple_close, /* close */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1357 simple_im_send, /* send_im */ |
11181 | 1358 NULL, /* set_info */ |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1359 simple_typing, /* send_typing */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1360 NULL, /* get_info */ |
11181 | 1361 simple_set_status, /* set_status */ |
1362 NULL, /* set_idle */ | |
1363 NULL, /* change_passwd */ | |
1364 simple_add_buddy, /* add_buddy */ | |
1365 NULL, /* add_buddies */ | |
1366 simple_remove_buddy, /* remove_buddy */ | |
1367 NULL, /* remove_buddies */ | |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1368 dummy_add_deny, /* add_permit */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1369 dummy_add_deny, /* add_deny */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1370 dummy_add_deny, /* rem_permit */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1371 dummy_add_deny, /* rem_deny */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1372 dummy_permit_deny, /* set_permit_deny */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1373 NULL, /* join_chat */ |
11181 | 1374 NULL, /* reject_chat */ |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1375 NULL, /* get_chat_name */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1376 NULL, /* chat_invite */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1377 NULL, /* chat_leave */ |
11181 | 1378 NULL, /* chat_whisper */ |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1379 NULL, /* chat_send */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1380 simple_keep_alive, /* keepalive */ |
11181 | 1381 NULL, /* register_user */ |
1382 NULL, /* get_cb_info */ | |
1383 NULL, /* get_cb_away */ | |
1384 NULL, /* alias_buddy */ | |
1385 NULL, /* group_buddy */ | |
1386 NULL, /* rename_group */ | |
1387 NULL, /* buddy_free */ | |
1388 NULL, /* convo_closed */ | |
1389 NULL, /* normalize */ | |
1390 NULL, /* set_buddy_icon */ | |
1391 NULL, /* remove_group */ | |
1392 NULL, /* get_cb_real_name */ | |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1393 NULL, /* set_chat_topic */ |
11181 | 1394 NULL, /* find_blist_chat */ |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1395 NULL, /* roomlist_get_list */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1396 NULL, /* roomlist_cancel */ |
11181 | 1397 NULL, /* roomlist_expand_category */ |
1398 NULL, /* can_receive_file */ | |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1399 NULL, /* send_file */ |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1400 NULL /* new_xfer */ |
11181 | 1401 }; |
1402 | |
1403 | |
1404 static GaimPluginInfo info = | |
1405 { | |
1406 GAIM_PLUGIN_MAGIC, | |
1407 GAIM_MAJOR_VERSION, | |
1408 GAIM_MINOR_VERSION, | |
1409 GAIM_PLUGIN_PROTOCOL, /**< type */ | |
1410 NULL, /**< ui_requirement */ | |
1411 0, /**< flags */ | |
1412 NULL, /**< dependencies */ | |
1413 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
1414 | |
1415 "prpl-simple", /**< id */ | |
1416 "SIMPLE", /**< name */ | |
1417 VERSION, /**< version */ | |
1418 N_("SIP/SIMPLE Protocol Plugin"), /** summary */ | |
1419 N_("The SIP/SIMPLE Protocol Plugin"), /** description */ | |
1420 N_("Thomas Butter <butter@uni-mannheim.de>"), /**< author */ | |
1421 GAIM_WEBSITE, /**< homepage */ | |
1422 | |
1423 NULL, /**< load */ | |
1424 NULL, /**< unload */ | |
1425 NULL, /**< destroy */ | |
1426 | |
1427 NULL, /**< ui_info */ | |
1428 &prpl_info, /**< extra_info */ | |
1429 NULL, | |
1430 NULL | |
1431 }; | |
1432 | |
1433 static void _init_plugin(GaimPlugin *plugin) | |
1434 { | |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1435 GaimAccountUserSplit *split; |
11189 | 1436 GaimAccountOption *option; |
11181 | 1437 |
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1438 split = gaim_account_user_split_new(_("Server"), "", '@'); |
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1439 prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); |
11181 | 1440 |
11345 | 1441 option = gaim_account_option_bool_new(_("Publish Status (note: everyone may watch you)"), "dopublish", TRUE); |
1442 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
1443 | |
11189 | 1444 option = gaim_account_option_bool_new(_("Use UDP"), "udp", FALSE); |
1445 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
11210 | 1446 option = gaim_account_option_bool_new(_("Use Proxy"), "useproxy", FALSE); |
1447 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
1448 option = gaim_account_option_string_new(_("Proxy"), "proxy", ""); | |
1449 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
11181 | 1450 } |
1451 | |
1452 GAIM_INIT_PLUGIN(simple, _init_plugin, info); |