Mercurial > pidgin
annotate src/protocols/simple/simple.c @ 12758:ef1a954512bc
[gaim-migrate @ 15105]
If NTLM and Basic auth is configured in squid with different passwords
the order of the headers seems to matter and only NTLM is checked.
Now first Basic is checked and then NTLM in the next request (or NTLM in
the first if no Basic auth is configured in squid).
Should fix bug #1384428
committer: Tailor Script <tailor@pidgin.im>
| author | Thomas Butter <tbutter> |
|---|---|
| date | Sat, 07 Jan 2006 22:54:03 +0000 |
| parents | 505bc707b641 |
| children | c5acba513363 |
| 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)) { | |
| 12755 | 202 gchar *buf = g_strdup_printf("sip:%s",buddy->name); |
| 203 gaim_blist_rename_buddy(buddy, buf); | |
| 11181 | 204 g_free(buf); |
| 205 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
206 if(!g_hash_table_lookup(sip->buddies, buddy->name)) { |
| 11181 | 207 b = g_new0(struct simple_buddy, 1); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
208 gaim_debug_info("simple","simple_add_buddy %s\n",buddy->name); |
| 11181 | 209 b->name = g_strdup(buddy->name); |
| 210 g_hash_table_insert(sip->buddies, b->name, b); | |
| 211 } else { | |
| 212 gaim_debug_info("simple","buddy %s already in internal list\n", buddy->name); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 static void simple_get_buddies(GaimConnection *gc) { | |
| 217 GaimBlistNode *gnode, *cnode, *bnode; | |
| 218 | |
| 219 gaim_debug_info("simple","simple_get_buddies\n"); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
220 |
| 11181 | 221 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { |
| 222 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) continue; | |
| 223 for(cnode = gnode->child; cnode; cnode = cnode->next) { | |
| 224 if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) continue; | |
| 225 for(bnode = cnode->child; bnode; bnode = bnode->next) { | |
| 226 if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) continue; | |
| 11192 | 227 if(((GaimBuddy*)bnode)->account == gc->account) |
| 228 simple_add_buddy(gc, (GaimBuddy*)bnode, (GaimGroup *)gnode); | |
| 11181 | 229 } |
| 230 } | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 static void simple_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) | |
| 235 { | |
| 236 struct simple_account_data *sip = (struct simple_account_data *)gc->proto_data; | |
| 237 struct simple_buddy *b = g_hash_table_lookup(sip->buddies, buddy->name); | |
| 238 g_hash_table_remove(sip->buddies, buddy->name); | |
| 239 g_free(b->name); | |
| 240 g_free(b); | |
| 241 } | |
| 242 | |
| 243 static GList *simple_status_types(GaimAccount *acc) { | |
| 244 GaimStatusType *type; | |
| 245 GList *types = NULL; | |
| 12456 | 246 |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
247 type = gaim_status_type_new_with_attrs( |
|
12595
3169cd6727ad
[gaim-migrate @ 14925]
Richard Laager <rlaager@wiktel.com>
parents:
12571
diff
changeset
|
248 GAIM_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, |
|
3169cd6727ad
[gaim-migrate @ 14925]
Richard Laager <rlaager@wiktel.com>
parents:
12571
diff
changeset
|
249 "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), |
|
3169cd6727ad
[gaim-migrate @ 14925]
Richard Laager <rlaager@wiktel.com>
parents:
12571
diff
changeset
|
250 NULL); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
251 types = g_list_append(types, type); |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
252 |
| 12657 | 253 type = gaim_status_type_new_full( |
| 254 GAIM_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE); | |
| 255 types = g_list_append(types, type); | |
| 256 | |
| 11181 | 257 return types; |
| 258 } | |
| 259 | |
| 11346 | 260 static gchar *auth_header(struct simple_account_data *sip, struct sip_auth *auth, gchar *method, gchar *target) { |
| 261 gchar noncecount[9]; | |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
262 gchar *response; |
| 11346 | 263 gchar *ret; |
| 11409 | 264 gchar *tmp; |
| 265 | |
| 266 if(auth->type == 1) { /* Digest */ | |
| 267 sprintf(noncecount, "%08d", auth->nc++); | |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
268 response = gaim_cipher_http_digest_calculate_response( |
|
12389
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12382
diff
changeset
|
269 "md5", method, target, NULL, NULL, |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
270 auth->nonce, noncecount, NULL, auth->digest_session_key); |
| 11409 | 271 gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response); |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
272 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
273 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); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
274 g_free(response); |
| 11409 | 275 return ret; |
| 276 } else if(auth->type == 2) { /* NTLM */ | |
| 277 if(auth->nc == 3) { | |
| 278 ret = gaim_ntlm_gen_type3(sip->username, sip->password, "gaim", sip->servername, auth->nonce); | |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
279 tmp = g_strdup_printf("NTLM qop=\"auth\" realm=\"%s\" targetname=\"%s\" response=\"%s\"\r\n", auth->realm, auth->target, ret); |
| 11409 | 280 g_free(ret); |
| 281 return tmp; | |
| 282 } | |
| 283 ret = gaim_ntlm_gen_type1("gaim", sip->servername); | |
| 11483 | 284 tmp = g_strdup_printf("NTLM qop=\"auth\" realm=\"%s\" targetname=\"%s\" response=\"%s\"\r\n", auth->realm, auth->target, ret); |
| 11409 | 285 g_free(ret); |
| 286 return tmp; | |
| 287 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
288 |
| 11346 | 289 sprintf(noncecount, "%08d", auth->nc++); |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
290 response = gaim_cipher_http_digest_calculate_response( |
|
12389
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12382
diff
changeset
|
291 "md5", method, target, NULL, NULL, |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
292 auth->nonce, noncecount, NULL, auth->digest_session_key); |
| 11346 | 293 gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response); |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
294 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
295 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); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
296 g_free(response); |
| 11346 | 297 return ret; |
| 298 } | |
| 299 | |
|
12746
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
300 static char * parse_attribute(const char *attrname, char *source) { |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
301 char *tmp, *tmp2, *retval = NULL; |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
302 int len = strlen(attrname); |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
303 |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
304 if(!strncmp(source, attrname, len)) { |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
305 tmp = source + len; |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
306 tmp2 = g_strstr_len(tmp, strlen(tmp), "\""); |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
307 if(tmp2) |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
308 retval = g_strndup(tmp, tmp2 - tmp); |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
309 } |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
310 |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
311 return retval; |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
312 } |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
313 |
| 11346 | 314 static void fill_auth(struct simple_account_data *sip, gchar *hdr, struct sip_auth *auth) { |
| 11409 | 315 int i=0; |
| 11424 | 316 char *tmp; |
|
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
317 gchar **parts; |
| 11346 | 318 if(!hdr) { |
| 11409 | 319 gaim_debug_error("simple", "fill_auth: hdr==NULL\n"); |
| 11346 | 320 return; |
| 321 } | |
| 11409 | 322 |
| 323 if(!g_strncasecmp(hdr, "NTLM", 4)) { | |
| 324 gaim_debug_info("simple", "found NTLM\n"); | |
| 325 auth->type = 2; | |
| 326 if(!auth->nonce && !auth->nc) { | |
|
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
327 parts = g_strsplit(hdr, " ", 0); |
| 11424 | 328 while(parts[i]) { |
|
12746
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
329 if((tmp = parse_attribute("targetname=\"", |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
330 parts[i]))) { |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
331 auth->target = tmp; |
| 11424 | 332 } |
|
12746
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
333 else if((tmp = parse_attribute("realm=\"", |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
334 parts[i]))) { |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
335 auth->realm = tmp; |
| 11424 | 336 } |
| 337 i++; | |
| 338 } | |
|
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
339 g_strfreev(parts); |
|
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
340 parts = NULL; |
| 11409 | 341 auth->nc = 1; |
| 342 } | |
| 343 if(!auth->nonce && auth->nc==2) { | |
| 344 auth->nc = 3; | |
| 345 auth->nonce = gaim_ntlm_parse_type2(hdr+5); | |
| 346 } | |
| 347 return; | |
| 348 } | |
| 349 | |
| 350 auth->type = 1; | |
|
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
351 parts = g_strsplit(hdr, " ", 0); |
| 11346 | 352 while(parts[i]) { |
|
12746
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
353 if((tmp = parse_attribute("nonce=\"", parts[i]))) { |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
354 auth->nonce = tmp; |
| 11346 | 355 } |
|
12746
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
356 else if((tmp = parse_attribute("realm=\"", parts[i]))) { |
|
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
357 auth->realm = tmp; |
| 11346 | 358 } |
| 359 i++; | |
| 360 } | |
|
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
361 g_strfreev(parts); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
362 |
|
12745
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
363 gaim_debug(GAIM_DEBUG_MISC, "simple", "nonce: %s realm: %s ", auth->nonce ? auth->nonce : "(null)", auth->realm ? auth->realm : "(null)"); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
364 |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
365 auth->digest_session_key = gaim_cipher_http_digest_calculate_session_key( |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
12216
diff
changeset
|
366 "md5", sip->username, auth->realm, sip->password, auth->nonce, NULL); |
| 11346 | 367 |
| 368 auth->nc=1; | |
| 369 } | |
| 370 | |
| 11181 | 371 static void simple_input_cb(gpointer data, gint source, GaimInputCondition cond); |
| 372 | |
| 373 static void send_later_cb(gpointer data, gint source, GaimInputCondition cond) { | |
| 374 GaimConnection *gc = data; | |
| 375 struct simple_account_data *sip = gc->proto_data; | |
| 376 struct sip_connection *conn; | |
| 377 | |
| 378 if( source < 0 ) { | |
| 379 gaim_connection_error(gc,"Could not connect"); | |
| 380 return; | |
| 381 } | |
| 382 | |
| 383 sip->fd = source; | |
| 384 sip->connecting = 0; | |
| 385 write(sip->fd, sip->sendlater, strlen(sip->sendlater)); | |
| 386 conn = connection_create(sip, source); | |
| 387 conn->inputhandler = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_input_cb, gc); | |
| 388 g_free(sip->sendlater); | |
| 389 sip->sendlater = 0; | |
| 390 } | |
| 391 | |
| 392 | |
| 393 static void sendlater(GaimConnection *gc, const char *buf) { | |
| 394 struct simple_account_data *sip = gc->proto_data; | |
| 395 int error = 0; | |
| 396 if(!sip->connecting) { | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
397 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
|
398 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
|
399 if(error) { |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
400 gaim_connection_error(gc, _("Couldn't create socket")); |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
401 } |
| 11181 | 402 sip->connecting = 1; |
| 403 } | |
| 404 if(sip->sendlater) { | |
| 405 gchar *old = sip->sendlater; | |
| 406 sip->sendlater = g_strdup_printf("%s\r\n%s",old, buf); | |
| 407 } else { | |
| 408 sip->sendlater = g_strdup(buf); | |
| 409 } | |
| 410 } | |
| 411 | |
| 412 static int sendout_pkt(GaimConnection *gc, const char *buf) { | |
| 413 struct simple_account_data *sip = gc->proto_data; | |
| 414 time_t currtime = time(NULL); | |
| 11189 | 415 int ret = 0; |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
416 |
| 11181 | 417 gaim_debug(GAIM_DEBUG_MISC, "simple", "\n\nsending - %s\n######\n%s\n######\n\n", ctime(&currtime), buf); |
| 11189 | 418 if(sip->udp) { |
| 419 if(sendto(sip->fd, buf, strlen(buf), 0, (struct sockaddr*)&sip->serveraddr, sizeof(struct sockaddr_in)) < strlen(buf)) { | |
| 420 gaim_debug_info("simple", "could not send packet\n"); | |
| 421 } | |
| 422 } else { | |
| 423 if(sip->fd <0 ) { | |
| 424 sendlater(gc, buf); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
425 return 0; |
| 11189 | 426 } |
| 427 ret = write(sip->fd, buf, strlen(buf)); | |
| 428 if(ret < 0) { | |
| 429 sendlater(gc,buf); | |
| 430 return 0; | |
| 431 } | |
| 11181 | 432 } |
| 433 return ret; | |
| 434 } | |
| 435 | |
| 11194 | 436 static void sendout_sipmsg(struct simple_account_data *sip, struct sipmsg *msg) { |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
437 GSList *tmp = msg->headers; |
| 11194 | 438 gchar *name; |
| 439 gchar *value; | |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
440 GString *outstr = g_string_new(""); |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
441 g_string_append_printf(outstr, "%s %s SIP/2.0\r\n", msg->method, msg->target); |
| 11194 | 442 while(tmp) { |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
443 name = ((struct siphdrelement*) (tmp->data))->name; |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
444 value = ((struct siphdrelement*) (tmp->data))->value; |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
445 g_string_append_printf(outstr, "%s: %s\r\n", name, value); |
| 11194 | 446 tmp = g_slist_next(tmp); |
| 447 } | |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
448 g_string_append_printf(outstr, "\r\n%s", msg->body ? msg->body : ""); |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
449 sendout_pkt(sip->gc, outstr->str); |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
450 g_string_free(outstr, TRUE); |
| 11194 | 451 } |
| 452 | |
| 11181 | 453 static void send_sip_response(GaimConnection *gc, struct sipmsg *msg, int code, char *text, char *body) { |
| 454 GSList *tmp = msg->headers; | |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
455 gchar *name; |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
456 gchar *value; |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
457 GString *outstr = g_string_new(""); |
| 12754 | 458 |
| 459 /* When sending the acknowlegements and errors, the content length from the original | |
| 460 message is still here, but there is no body; we need to make sure we're sending the | |
| 461 correct content length */ | |
| 462 sipmsg_remove_header(msg, "Content-Length"); | |
| 463 if(body) { | |
| 464 gchar len[12]; | |
| 465 sprintf(len, "%" G_GSIZE_FORMAT , strlen(body)); | |
| 466 sipmsg_add_header(msg, "Content-Length",len); | |
| 467 } | |
| 468 else | |
| 469 sipmsg_add_header(msg, "Content-Length", "0"); | |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
470 g_string_append_printf(outstr, "SIP/2.0 %d %s\r\n", code, text); |
| 11181 | 471 while(tmp) { |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
472 name = ((struct siphdrelement*) (tmp->data))->name; |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
473 value = ((struct siphdrelement*) (tmp->data))->value; |
|
12745
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
474 |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
475 g_string_append_printf(outstr, "%s: %s\r\n", name, value); |
| 11181 | 476 tmp = g_slist_next(tmp); |
| 477 } | |
|
12741
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
478 g_string_append_printf(outstr, "\r\n%s", body ? body : ""); |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
479 sendout_pkt(gc, outstr->str); |
|
2b61e6ed85c3
[gaim-migrate @ 15088]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
480 g_string_free(outstr, TRUE); |
| 11181 | 481 } |
| 482 | |
| 11194 | 483 static void transactions_remove(struct simple_account_data *sip, struct transaction *trans) { |
| 484 if(trans->msg) sipmsg_free(trans->msg); | |
| 485 sip->transactions = g_slist_remove(sip->transactions, trans); | |
| 486 g_free(trans); | |
| 487 } | |
| 488 | |
| 11181 | 489 static void transactions_add_buf(struct simple_account_data *sip, gchar *buf, void *callback) { |
| 490 struct transaction *trans = g_new0(struct transaction, 1); | |
| 491 trans->time = time(NULL); | |
| 492 trans->msg = sipmsg_parse_msg(buf); | |
| 493 trans->cseq = sipmsg_find_header(trans->msg, "CSeq"); | |
| 494 trans->callback = callback; | |
| 495 sip->transactions = g_slist_append(sip->transactions, trans); | |
| 496 } | |
| 497 | |
| 498 static struct transaction *transactions_find(struct simple_account_data *sip, struct sipmsg *msg) { | |
| 499 struct transaction *trans; | |
| 500 GSList *transactions = sip->transactions; | |
| 501 gchar *cseq = sipmsg_find_header(msg, "CSeq"); | |
| 502 | |
| 503 while(transactions) { | |
| 504 trans = transactions->data; | |
| 505 if(!strcmp(trans->cseq, cseq)) { | |
| 506 return trans; | |
| 507 } | |
| 508 transactions = transactions->next; | |
| 509 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
510 |
| 11181 | 511 return (struct transaction *)NULL; |
| 512 } | |
| 513 | |
| 514 static void send_sip_request(GaimConnection *gc, gchar *method, gchar *url, gchar *to, gchar *addheaders, gchar *body, struct sip_dialog *dialog, TransCallback tc) { | |
| 515 struct simple_account_data *sip = gc->proto_data; | |
| 516 char *callid= dialog ? g_strdup(dialog->callid) : gencallid(); | |
| 12216 | 517 char *auth=""; |
| 518 char *addh=""; | |
| 519 gchar *branch = genbranch(); | |
| 520 char *buf; | |
| 521 | |
| 12196 | 522 if(!strcmp(method,"REGISTER")) { |
| 523 if(sip->regcallid) callid = g_strdup(sip->regcallid); | |
| 524 else sip->regcallid = g_strdup(callid); | |
| 525 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
526 |
| 11181 | 527 if(addheaders) addh=addheaders; |
| 11409 | 528 if(sip->registrar.type && !strcmp(method,"REGISTER")) { |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
529 buf = auth_header(sip, &sip->registrar, method, url); |
|
12563
b7f7f3a685ea
[gaim-migrate @ 14882]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12492
diff
changeset
|
530 auth = g_strdup_printf("Authorization: %s", buf); |
| 11346 | 531 g_free(buf); |
| 11181 | 532 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth); |
| 533 } | |
| 534 | |
| 11409 | 535 if(sip->proxy.type && strcmp(method,"REGISTER")) { |
| 11346 | 536 buf = auth_header(sip, &sip->proxy, method, url); |
|
12563
b7f7f3a685ea
[gaim-migrate @ 14882]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12492
diff
changeset
|
537 auth = g_strdup_printf("Proxy-Authorization: %s", buf); |
| 11346 | 538 g_free(buf); |
| 11181 | 539 gaim_debug(GAIM_DEBUG_MISC, "simple", "header %s", auth); |
| 540 } | |
| 541 | |
| 12753 | 542 if(!sip->ip || !strcmp(sip->ip,"0.0.0.0") || !strcmp(sip->ip,"127.0.0.1")) { /* if there was no known ip retry now */ |
| 543 if(gaim_network_get_public_ip()) { | |
| 544 g_free(sip->ip); | |
| 545 sip->ip = g_strdup(gaim_network_get_public_ip()); | |
| 546 } | |
| 12196 | 547 } |
| 11181 | 548 buf = g_strdup_printf("%s %s SIP/2.0\r\n" |
| 11190 | 549 "Via: SIP/2.0/%s %s:%d;branch=%s\r\n" |
| 11181 | 550 "From: <sip:%s@%s>;tag=%s\r\n" |
| 551 "To: <%s>%s%s\r\n" | |
| 552 "Max-Forwards: 10\r\n" | |
| 553 "CSeq: %d %s\r\n" | |
| 554 "User-Agent: Gaim SIP/SIMPLE Plugin\r\n" | |
| 555 "Call-ID: %s\r\n" | |
| 556 "%s%s" | |
| 11658 | 557 "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n%s", |
| 11181 | 558 method, |
| 559 url, | |
| 11190 | 560 sip->udp ? "UDP" : "TCP", |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
561 sip->ip ? sip->ip : "", |
| 11181 | 562 sip->listenport, |
| 563 branch, | |
| 564 sip->username, | |
| 565 sip->servername, | |
| 566 dialog ? dialog->ourtag : gentag(), | |
| 567 to, | |
| 568 dialog ? ";tag=" : "", | |
| 569 dialog ? dialog->theirtag : "", | |
| 570 ++sip->cseq, | |
| 571 method, | |
| 572 callid, | |
| 573 auth, | |
| 574 addh, | |
| 575 strlen(body), | |
| 576 body); | |
| 577 g_free(branch); | |
| 578 g_free(callid); | |
| 579 | |
| 11341 | 580 /* add to ongoing transactions */ |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
581 |
| 11181 | 582 transactions_add_buf(sip, buf, tc); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
583 |
| 11181 | 584 sendout_pkt(gc,buf); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
585 |
| 11181 | 586 g_free(buf); |
| 587 } | |
| 588 | |
| 11194 | 589 static void do_register_exp(struct simple_account_data *sip, int expire) { |
| 11181 | 590 char *uri = g_strdup_printf("sip:%s",sip->servername); |
| 591 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
|
592 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
|
593 |
|
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
594 sip->registerstatus = 1; |
|
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
595 |
| 11194 | 596 if(expire) { |
| 597 sip->reregister = time(NULL) + expire - 50; | |
| 598 } else { | |
| 599 sip->reregister = time(NULL) + 600; | |
| 600 } | |
| 601 send_sip_request(sip->gc,"REGISTER",uri,to, contact, "", NULL, process_register_response); | |
| 11341 | 602 g_free(contact); |
| 11181 | 603 g_free(uri); |
| 604 g_free(to); | |
| 605 } | |
| 606 | |
| 11194 | 607 static void do_register(struct simple_account_data *sip) { |
| 608 do_register_exp(sip, sip->registerexpire); | |
| 609 } | |
| 610 | |
| 11181 | 611 static gchar *parse_from(gchar *hdr) { |
| 612 gchar *from = hdr; | |
| 613 gchar *tmp; | |
| 614 | |
| 615 if(!from) return NULL; | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
616 gaim_debug_info("simple", "parsing address out of %s\n",from); |
| 11181 | 617 tmp = strchr(from, '<'); |
| 618 | |
| 11341 | 619 /* i hate the different SIP UA behaviours... */ |
| 620 if(tmp) { /* sip address in <...> */ | |
| 11181 | 621 from = tmp+1; |
| 622 tmp = strchr(from,'>'); | |
| 623 if(tmp) { | |
| 624 from = g_strndup(from,tmp-from); | |
| 625 } else { | |
| 626 gaim_debug_info("simple", "found < without > in From\n"); | |
| 627 return NULL; | |
| 628 } | |
| 629 } else { | |
| 630 tmp = strchr(from, ';'); | |
| 631 if(tmp) { | |
| 632 from = g_strndup(from,tmp-from); | |
| 11483 | 633 } else { |
| 634 from = g_strdup(from); | |
| 11181 | 635 } |
| 636 } | |
| 637 gaim_debug_info("simple", "got %s\n",from); | |
| 638 return from; | |
| 639 } | |
| 640 | |
| 641 static gboolean process_subscribe_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { | |
| 11341 | 642 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
|
643 |
| 11181 | 644 if(msg->response==200 || msg->response==202) { |
| 645 return TRUE; | |
| 646 } | |
| 647 | |
| 11341 | 648 /* 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
|
649 |
| 11181 | 650 gaim_prpl_got_user_status(sip->account, to, "offline", NULL); |
| 651 g_free(to); | |
| 652 return TRUE; | |
| 653 } | |
| 654 | |
| 655 static void simple_subscribe(struct simple_account_data *sip, struct simple_buddy *buddy) { | |
| 11341 | 656 gchar *contact = "Expires: 300\r\nAccept: application/pidf+xml\r\nEvent: presence\r\n"; |
| 11181 | 657 gchar *to; |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
658 if(strstr(buddy->name,"sip:")) to = g_strdup(buddy->name); |
| 11181 | 659 else to = g_strdup_printf("sip:%s",buddy->name); |
| 11341 | 660 contact = g_strdup_printf("%sContact: <%s@%s>\r\n", contact, sip->username, sip->servername); |
| 661 /* subscribe to buddy presence | |
| 662 * 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
|
663 |
| 11181 | 664 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
|
665 |
| 11181 | 666 g_free(to); |
| 11341 | 667 g_free(contact); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
668 |
| 11341 | 669 /* resubscribe before subscription expires */ |
| 670 /* add some jitter */ | |
| 671 buddy->resubscribe = time(NULL)+250+(rand()%50); | |
| 11181 | 672 } |
| 673 | |
| 674 static void simple_buddy_resub(char *name, struct simple_buddy *buddy, struct simple_account_data *sip) { | |
| 675 time_t curtime = time(NULL); | |
| 11341 | 676 gaim_debug_info("simple","buddy resub\n"); |
| 11181 | 677 if(buddy->resubscribe < curtime) { |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
678 gaim_debug(GAIM_DEBUG_MISC, "simple", "simple_buddy_resub %s\n",name); |
| 11181 | 679 simple_subscribe(sip, buddy); |
| 680 } | |
| 681 } | |
| 682 | |
| 11194 | 683 static gboolean resend_timeout(struct simple_account_data *sip) { |
| 684 GSList *tmp = sip->transactions; | |
| 685 time_t currtime = time(NULL); | |
| 686 while(tmp) { | |
| 687 struct transaction *trans = tmp->data; | |
| 688 tmp = tmp->next; | |
| 689 gaim_debug_info("simple", "have open transaction age: %d\n", currtime- trans->time); | |
| 690 if((currtime - trans->time > 5) && trans->retries >= 1) { | |
| 11341 | 691 /* TODO 408 */ |
| 11194 | 692 } else { |
| 693 if((currtime - trans->time > 2) && trans->retries == 0) { | |
| 694 trans->retries++; | |
| 695 sendout_sipmsg(sip, trans->msg); | |
| 696 } | |
| 697 } | |
| 698 } | |
| 699 return TRUE; | |
| 700 } | |
| 701 | |
| 11181 | 702 static gboolean register_timeout(struct simple_account_data *sip) { |
| 703 GSList *tmp; | |
| 704 time_t curtime = time(NULL); | |
| 11341 | 705 /* register again if first registration expires */ |
| 11181 | 706 if(sip->reregister < curtime) { |
| 11194 | 707 do_register(sip); |
| 11181 | 708 } |
| 11341 | 709 gaim_debug_info("simple","in register timeout\n"); |
| 710 /* check for every subscription if we need to resubscribe */ | |
| 11181 | 711 g_hash_table_foreach(sip->buddies, (GHFunc)simple_buddy_resub, (gpointer)sip); |
| 712 | |
| 11341 | 713 /* remove a timed out suscriber */ |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
714 |
| 11181 | 715 tmp = sip->watcher; |
| 716 while(tmp) { | |
| 717 struct simple_watcher *watcher = tmp->data; | |
| 718 if(watcher->expire < curtime) { | |
| 719 watcher_remove(sip, watcher->name); | |
| 720 tmp = sip->watcher; | |
| 721 } | |
| 722 if(tmp) tmp = tmp->next; | |
| 723 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
724 |
| 11181 | 725 return TRUE; |
| 726 } | |
| 727 | |
| 728 static void simple_send_message(struct simple_account_data *sip, char *to, char *msg, char *type) { | |
| 729 gchar *hdr; | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
730 if(type) { |
| 11181 | 731 hdr = g_strdup_printf("Content-Type: %s\r\n",type); |
| 732 } else { | |
| 733 hdr = g_strdup("Content-Type: text/plain\r\n"); | |
| 734 } | |
| 735 send_sip_request(sip->gc, "MESSAGE", to, to, hdr, msg, NULL, NULL); | |
| 736 g_free(hdr); | |
| 737 } | |
| 738 | |
| 12216 | 739 static int simple_im_send(GaimConnection *gc, const char *who, const char *what, GaimMessageFlags flags) { |
| 11181 | 740 struct simple_account_data *sip = gc->proto_data; |
| 741 char *to = g_strdup(who); | |
| 12216 | 742 char *text = gaim_unescape_html(what); |
| 11181 | 743 simple_send_message(sip, to, text, NULL); |
| 744 g_free(to); | |
| 745 g_free(text); | |
| 746 return 1; | |
| 747 } | |
| 748 | |
| 749 static void process_incoming_message(struct simple_account_data *sip, struct sipmsg *msg) { | |
| 750 gchar *from; | |
| 751 gchar *contenttype; | |
| 752 gboolean found = FALSE; | |
| 753 | |
| 754 from = parse_from(sipmsg_find_header(msg, "From")); | |
| 755 | |
| 756 if(!from) return; | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
757 |
| 11181 | 758 gaim_debug(GAIM_DEBUG_MISC, "simple", "got message from %s: %s\n", from, msg->body); |
| 759 | |
| 760 contenttype = sipmsg_find_header(msg, "Content-Type"); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
761 if(!contenttype || !strncmp(contenttype, "text/plain", 10) || !strncmp(contenttype, "text/html", 9)) { |
| 11181 | 762 serv_got_im(sip->gc, from, msg->body, 0, time(NULL)); |
| 763 send_sip_response(sip->gc, msg, 200, "OK", NULL); | |
| 764 found = TRUE; | |
| 765 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
766 if(!strncmp(contenttype, "application/im-iscomposing+xml",30)) { |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
767 xmlnode *isc = xmlnode_from_str(msg->body, msg->bodylen); |
| 11181 | 768 xmlnode *state; |
| 769 gchar *statedata; | |
| 770 | |
| 771 if(!isc) { | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
772 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
|
773 return; |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
774 } |
| 11181 | 775 |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
776 state = xmlnode_get_child(isc, "state"); |
| 11181 | 777 |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
778 if(!state) { |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
779 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
|
780 return; |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
781 } |
| 11181 | 782 |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
783 statedata = xmlnode_get_data(state); |
| 11181 | 784 if(statedata) { |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
785 if(strstr(statedata,"active")) serv_got_typing(sip->gc, from, 0, GAIM_TYPING); |
| 11181 | 786 else serv_got_typing_stopped(sip->gc, from); |
| 787 } | |
| 788 xmlnode_free(isc); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
789 send_sip_response(sip->gc, msg, 200, "OK", NULL); |
| 11181 | 790 found = TRUE; |
| 791 } | |
| 792 if(!found) { | |
| 793 gaim_debug_info("simple", "got unknown mime-type"); | |
| 794 send_sip_response(sip->gc, msg, 415, "Unsupported media type", NULL); | |
| 795 } | |
| 796 g_free(from); | |
| 797 } | |
| 798 | |
| 799 | |
| 800 gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { | |
| 801 gchar *tmp; | |
| 802 gaim_debug(GAIM_DEBUG_MISC, "simple", "in process register response response: %d\n", msg->response); | |
| 803 switch (msg->response) { | |
| 804 case 200: | |
| 11341 | 805 if(sip->registerstatus<3) { /* registered */ |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
806 if(gaim_account_get_bool(sip->account, "dopublish", TRUE)) { |
| 11345 | 807 send_publish(sip); |
| 808 } | |
| 11181 | 809 } |
| 810 sip->registerstatus=3; | |
| 811 gaim_connection_set_state(sip->gc, GAIM_CONNECTED); | |
| 11341 | 812 |
| 813 /* get buddies from blist */ | |
| 814 simple_get_buddies(sip->gc); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
815 |
| 11181 | 816 register_timeout(sip); |
| 817 break; | |
| 818 case 401: | |
| 819 if(sip->registerstatus!=2) { | |
| 11346 | 820 gaim_debug_info("simple","REGISTER retries %d\n",sip->registrar.retries); |
| 821 if(sip->registrar.retries>3) { | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
822 gaim_connection_error(sip->gc,"Wrong Password"); |
| 11346 | 823 return TRUE; |
| 824 } | |
| 11181 | 825 tmp = sipmsg_find_header(msg, "WWW-Authenticate"); |
| 826 fill_auth(sip, tmp, &sip->registrar); | |
| 827 sip->registerstatus=2; | |
| 11194 | 828 do_register(sip); |
| 11181 | 829 } |
| 830 break; | |
| 831 } | |
| 832 return TRUE; | |
| 833 } | |
| 834 | |
| 835 static void process_incoming_notify(struct simple_account_data *sip, struct sipmsg *msg) { | |
| 836 gchar *from; | |
| 837 gchar *fromhdr; | |
| 838 gchar *tmp2; | |
| 839 xmlnode *pidf; | |
| 840 xmlnode *basicstatus; | |
| 841 gboolean isonline = FALSE; | |
| 842 | |
| 843 fromhdr = sipmsg_find_header(msg,"From"); | |
| 844 from = parse_from(fromhdr); | |
| 845 if(!from) return; | |
| 846 | |
| 847 pidf = xmlnode_from_str(msg->body, msg->bodylen); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
848 |
| 11181 | 849 if(!pidf) { |
| 850 gaim_debug_info("simple","process_incoming_notify: no parseable pidf\n"); | |
| 851 return; | |
| 852 } | |
| 853 | |
| 854 basicstatus = xmlnode_get_child(xmlnode_get_child(xmlnode_get_child(pidf,"tuple"),"status"), "basic"); | |
| 855 | |
| 856 if(!basicstatus) { | |
| 857 gaim_debug_info("simple","process_incoming_notify: no basic found\n"); | |
| 858 return; | |
| 859 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
860 |
| 11181 | 861 tmp2 = xmlnode_get_data(basicstatus); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
862 |
| 11181 | 863 if(!tmp2) { |
| 864 gaim_debug_info("simple","process_incoming_notify: no basic data found\n"); | |
| 865 return; | |
| 866 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
867 |
| 11181 | 868 if(strstr(tmp2, "open")) { |
| 869 isonline = TRUE; | |
| 870 } | |
| 871 | |
| 872 if(isonline) gaim_prpl_got_user_status(sip->account, from, "available", NULL); | |
| 873 else gaim_prpl_got_user_status(sip->account, from, "offline", NULL); | |
| 874 | |
| 875 xmlnode_free(pidf); | |
| 876 | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
877 g_free(from); |
| 11181 | 878 send_sip_response(sip->gc, msg, 200, "OK", NULL); |
| 879 } | |
| 880 | |
| 881 static int simple_typing(GaimConnection *gc, const char *name, int typing) { | |
| 882 struct simple_account_data *sip = gc->proto_data; | |
| 883 | |
| 884 gchar *xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | |
| 885 "<isComposing xmlns=\"urn:ietf:params:xml:ns:im-iscomposing\"\n" | |
| 886 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" | |
| 887 "xsi:schemaLocation=\"urn:ietf:params:xml:ns:im-composing iscomposing.xsd\">\n" | |
| 888 "<state>%s</state>\n" | |
| 889 "<contenttype>text/plain</contenttype>\n" | |
| 890 "<refresh>60</refresh>\n" | |
| 891 "</isComposing>"; | |
| 892 gchar *recv = g_strdup(name); | |
| 893 if(typing == GAIM_TYPING) { | |
| 894 gchar *msg = g_strdup_printf(xml, "active"); | |
| 895 simple_send_message(sip, recv, msg, "application/im-iscomposing+xml"); | |
| 896 g_free(msg); | |
| 897 } else { | |
| 898 gchar *msg = g_strdup_printf(xml, "idle"); | |
| 899 simple_send_message(sip, recv, msg, "application/im-iscomposing+xml"); | |
| 900 g_free(msg); | |
| 901 } | |
| 902 g_free(recv); | |
| 903 return 1; | |
| 904 } | |
| 905 | |
| 906 static gchar *find_tag(gchar *hdr) { | |
| 907 gchar *tmp = strstr(hdr, ";tag="); | |
| 908 gchar *tmp2; | |
| 909 if(!tmp) return NULL; | |
| 910 tmp += 5; | |
| 911 if((tmp2 = strchr(tmp, ';'))) { | |
| 912 tmp2[0] = '\0'; | |
| 913 tmp = g_strdup(tmp); | |
| 914 tmp2[0] = ';'; | |
| 915 return tmp; | |
| 916 } | |
| 917 return g_strdup(tmp); | |
| 918 } | |
| 919 | |
| 920 static gchar* gen_pidf(struct simple_account_data *sip) { | |
| 921 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
|
922 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n" |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
923 "xmlns:im=\"urn:ietf:params:xml:ns:pidf:im\"\n" |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
924 "entity=\"sip:%s@%s\">\n" |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
925 "<tuple id=\"bs35r9f\">\n" |
| 11181 | 926 "<status>\n" |
| 927 "<basic>open</basic>\n" | |
| 928 "<im:im>%s</im:im>\n" | |
| 929 "</status>\n" | |
| 930 "</tuple>\n" | |
| 931 "</presence>", | |
| 932 sip->username, | |
| 933 sip->servername, | |
| 934 sip->status); | |
| 935 return doc; | |
| 936 } | |
| 937 | |
| 938 static void send_notify(struct simple_account_data *sip, struct simple_watcher *watcher) { | |
| 939 gchar *doc = gen_pidf(sip); | |
| 940 send_sip_request(sip->gc, "NOTIFY", watcher->name, watcher->name, "Event: presence\r\nContent-Type: application/pidf+xml\r\n", doc, &watcher->dialog, NULL); | |
| 941 g_free(doc); | |
| 942 } | |
| 943 | |
| 944 static gboolean process_publish_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc) { | |
| 11345 | 945 if(msg->response != 200 && msg->response != 408) { |
| 11341 | 946 /* never send again */ |
| 11181 | 947 sip->republish = -1; |
| 948 } | |
| 949 return TRUE; | |
| 950 } | |
| 951 | |
| 952 static void send_publish(struct simple_account_data *sip) { | |
| 953 gchar *uri = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); | |
| 954 gchar *doc = gen_pidf(sip); | |
| 11341 | 955 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 | 956 sip->republish = time(NULL) + 500; |
| 957 g_free(doc); | |
| 958 } | |
| 959 | |
| 960 static void process_incoming_subscribe(struct simple_account_data *sip, struct sipmsg *msg) { | |
| 961 gchar *from = parse_from(sipmsg_find_header(msg, "From")); | |
| 962 gchar *theirtag = find_tag(sipmsg_find_header(msg, "From")); | |
| 963 gchar *ourtag = find_tag(sipmsg_find_header(msg, "To")); | |
| 964 gboolean tagadded = FALSE; | |
| 965 gchar *callid = sipmsg_find_header(msg, "Call-ID"); | |
| 966 gchar *expire = sipmsg_find_header(msg, "Expire"); | |
| 967 gchar *tmp; | |
| 968 struct simple_watcher *watcher = watcher_find(sip, from); | |
| 969 if(!ourtag) { | |
| 970 tagadded = TRUE; | |
| 971 ourtag = gentag(); | |
| 972 } | |
| 11341 | 973 if(!watcher) { /* new subscription */ |
| 11345 | 974 if(!gaim_privacy_check(sip->account, from)) { |
| 975 send_sip_response(sip->gc, msg, 202, "Ok", NULL); | |
| 976 goto privend; | |
| 977 } | |
| 11181 | 978 watcher = watcher_create(sip, from, callid, ourtag, theirtag); |
| 979 } | |
| 980 if(tagadded) { | |
| 981 gchar *to = g_strdup_printf("%s;tag=%s", sipmsg_find_header(msg, "To"), ourtag); | |
| 982 sipmsg_remove_header(msg, "To"); | |
| 983 sipmsg_add_header(msg, "To", to); | |
| 984 } | |
| 985 if(expire) | |
| 986 watcher->expire = time(NULL) + strtol(expire, NULL, 10); | |
| 987 else | |
| 988 watcher->expire = time(NULL) + 600; | |
| 989 sipmsg_remove_header(msg, "Contact"); | |
| 990 tmp = g_strdup_printf("<%s@%s>",sip->username, sip->servername); | |
| 991 sipmsg_add_header(msg, "Contact", tmp); | |
| 992 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); | |
| 993 send_sip_response(sip->gc, msg, 200, "Ok", NULL); | |
| 994 g_free(tmp); | |
| 995 send_notify(sip, watcher); | |
| 11345 | 996 privend: |
| 997 g_free(from); | |
| 998 g_free(theirtag); | |
| 999 g_free(ourtag); | |
| 1000 g_free(callid); | |
| 1001 g_free(expire); | |
| 11181 | 1002 } |
| 1003 | |
| 11189 | 1004 static void process_input_message(struct simple_account_data *sip, struct sipmsg *msg) { |
|
12745
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1005 gboolean found = FALSE; |
|
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1006 if(msg->response == 0) { /* request */ |
| 11189 | 1007 if(!strcmp(msg->method, "MESSAGE")) { |
| 1008 process_incoming_message(sip, msg); | |
|
12745
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1009 found = TRUE; |
|
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1010 } else if(!strcmp(msg->method, "NOTIFY")) { |
| 11189 | 1011 process_incoming_notify(sip, msg); |
|
12745
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1012 found = TRUE; |
|
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1013 } else if(!strcmp(msg->method, "SUBSCRIBE")) { |
| 11189 | 1014 process_incoming_subscribe(sip, msg); |
|
12745
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1015 found = TRUE; |
|
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1016 } else { |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1017 send_sip_response(sip->gc, msg, 501, "Not implemented", NULL); |
| 11190 | 1018 } |
| 11341 | 1019 } else { /* response */ |
| 11189 | 1020 struct transaction *trans = transactions_find(sip, msg); |
| 1021 if(trans) { | |
| 1022 if(msg->response == 407) { | |
|
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
1023 gchar *resend, *auth, *ptmp; |
|
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
1024 |
| 11346 | 1025 if(sip->proxy.retries>3) return; |
| 1026 sip->proxy.retries++; | |
| 11341 | 1027 /* do proxy authentication */ |
| 11189 | 1028 |
|
11439
617e67e1c985
[gaim-migrate @ 13676]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11424
diff
changeset
|
1029 ptmp = sipmsg_find_header(msg, "Proxy-Authenticate"); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1030 |
| 11189 | 1031 fill_auth(sip, ptmp, &sip->proxy); |
| 11346 | 1032 auth = auth_header(sip, &sip->proxy, trans->msg->method, trans->msg->target); |
| 11189 | 1033 sipmsg_remove_header(msg, "Proxy-Authorization"); |
| 1034 sipmsg_add_header(trans->msg, "Proxy-Authorization", auth); | |
| 1035 g_free(auth); | |
| 1036 resend = sipmsg_to_string(trans->msg); | |
| 11341 | 1037 /* resend request */ |
| 11189 | 1038 sendout_pkt(sip->gc, resend); |
| 1039 g_free(resend); | |
| 1040 } else { | |
| 11517 | 1041 if(msg->response == 100) { |
| 1042 /* ignore provisional response */ | |
| 1043 gaim_debug_info("simple","got trying response\n"); | |
| 1044 } else { | |
| 1045 sip->proxy.retries = 0; | |
| 1046 if(msg->response == 401) sip->registrar.retries++; | |
| 1047 else sip->registrar.retries = 0; | |
| 1048 if(trans->callback) { | |
| 1049 /* call the callback to process response*/ | |
| 1050 (trans->callback)(sip, msg, trans); | |
| 1051 } | |
| 1052 transactions_remove(sip, trans); | |
| 11189 | 1053 } |
| 1054 } | |
|
12745
e788741f4840
[gaim-migrate @ 15092]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12741
diff
changeset
|
1055 found = TRUE; |
| 11189 | 1056 } else { |
| 1057 gaim_debug(GAIM_DEBUG_MISC, "simple", "received response to unknown transaction"); | |
| 1058 } | |
| 1059 } | |
| 1060 if(!found) { | |
|
12746
4f7dab030b1a
[gaim-migrate @ 15093]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12745
diff
changeset
|
1061 gaim_debug(GAIM_DEBUG_MISC, "simple", "received a unknown sip message with method %s and response %d\n",msg->method, msg->response); |
| 11189 | 1062 } |
| 1063 } | |
| 1064 | |
| 11181 | 1065 static void process_input(struct simple_account_data *sip, struct sip_connection *conn) |
| 1066 { | |
| 1067 char *cur; | |
| 1068 char *dummy; | |
| 1069 struct sipmsg *msg; | |
| 1070 int restlen; | |
| 1071 cur = conn->inbuf; | |
| 1072 | |
| 11341 | 1073 /* according to the RFC remove CRLF at the beginning */ |
| 11181 | 1074 while(*cur == '\r' || *cur == '\n') { |
| 1075 cur++; | |
| 1076 } | |
| 1077 if(cur != conn->inbuf) { | |
| 1078 memmove(conn->inbuf, cur, conn->inbufused-(cur-conn->inbuf)); | |
| 1079 conn->inbufused=strlen(conn->inbuf); | |
| 1080 } | |
| 1081 | |
| 11341 | 1082 /* Received a full Header? */ |
| 11181 | 1083 if((cur = strstr(conn->inbuf, "\r\n\r\n"))!=NULL) { |
| 1084 time_t currtime = time(NULL); | |
| 1085 cur += 2; | |
| 1086 cur[0] = '\0'; | |
| 1087 gaim_debug_info("simple","\n\nreceived - %s\n######\n%s\n#######\n\n",ctime(&currtime), conn->inbuf); | |
| 1088 msg = sipmsg_parse_header(conn->inbuf); | |
| 1089 cur[0] = '\r'; | |
| 1090 cur += 2; | |
| 1091 restlen = conn->inbufused - (cur-conn->inbuf); | |
| 1092 if(restlen>=msg->bodylen) { | |
| 1093 dummy = g_malloc(msg->bodylen+1); | |
| 1094 memcpy(dummy, cur, msg->bodylen); | |
| 1095 dummy[msg->bodylen]='\0'; | |
| 1096 msg->body = dummy; | |
| 1097 cur+=msg->bodylen; | |
| 1098 memmove(conn->inbuf, cur, conn->inbuflen); | |
| 1099 conn->inbufused=strlen(conn->inbuf); | |
| 1100 } else { | |
| 1101 sipmsg_free(msg); | |
| 1102 return; | |
| 1103 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1104 gaim_debug(GAIM_DEBUG_MISC, "simple", "in process response response: %d\n", msg->response); |
| 11189 | 1105 process_input_message(sip,msg); |
| 11181 | 1106 } else { |
| 1107 gaim_debug(GAIM_DEBUG_MISC, "simple", "received a incomplete sip msg: %s\n", conn->inbuf); | |
| 1108 } | |
| 1109 } | |
| 1110 | |
| 11189 | 1111 static void simple_udp_process(gpointer data, gint source, GaimInputCondition con) { |
| 1112 GaimConnection *gc = data; | |
| 1113 struct simple_account_data *sip = gc->proto_data; | |
| 1114 struct sipmsg *msg; | |
| 1115 int len; | |
| 1116 time_t currtime; | |
| 1117 | |
| 1118 static char buffer[65536]; | |
| 12751 | 1119 if((len = recv(source, buffer, 65536, 0)) > 0) { |
|
12748
dd271caf25b0
[gaim-migrate @ 15095]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12746
diff
changeset
|
1120 buffer[len] = '\0'; |
|
dd271caf25b0
[gaim-migrate @ 15095]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12746
diff
changeset
|
1121 gaim_debug_info("simple","\n\nreceived - %s\n######\n%s\n#######\n\n",ctime(&currtime), buffer); |
|
dd271caf25b0
[gaim-migrate @ 15095]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12746
diff
changeset
|
1122 msg = sipmsg_parse_msg(buffer); |
|
dd271caf25b0
[gaim-migrate @ 15095]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12746
diff
changeset
|
1123 if(msg) process_input_message(sip, msg); |
|
dd271caf25b0
[gaim-migrate @ 15095]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12746
diff
changeset
|
1124 } |
| 11189 | 1125 } |
| 1126 | |
| 11181 | 1127 static void simple_input_cb(gpointer data, gint source, GaimInputCondition cond) |
| 1128 { | |
| 1129 GaimConnection *gc = data; | |
| 1130 struct simple_account_data *sip = gc->proto_data; | |
| 1131 int len; | |
| 1132 struct sip_connection *conn = connection_find(sip, source); | |
| 1133 if(!conn) { | |
| 1134 gaim_debug_error("simple", "Connection not found!\n"); | |
| 1135 return; | |
| 1136 } | |
| 1137 | |
| 1138 if (conn->inbuflen < conn->inbufused + SIMPLE_BUF_INC) { | |
| 1139 conn->inbuflen += SIMPLE_BUF_INC; | |
| 1140 conn->inbuf = g_realloc(conn->inbuf, conn->inbuflen); | |
| 1141 } | |
| 1142 | |
| 1143 if ((len = read(source, conn->inbuf + conn->inbufused, SIMPLE_BUF_INC - 1)) <= 0) { | |
| 1144 gaim_debug_info("simple","simple_input_cb: read error\n"); | |
| 1145 connection_remove(sip, source); | |
| 1146 if(sip->fd == source) sip->fd = -1; | |
| 1147 return; | |
| 1148 } | |
| 1149 if(len == 0) { | |
| 11341 | 1150 /* connection was closed */ |
| 11181 | 1151 connection_remove(sip, source); |
| 1152 if(sip->fd == source) sip->fd = -1; | |
| 1153 } | |
| 1154 | |
| 1155 conn->inbufused += len; | |
| 1156 conn->inbuf[conn->inbufused]='\0'; | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1157 |
| 11181 | 1158 process_input(sip, conn); |
| 1159 } | |
| 1160 | |
| 1161 /* Callback for new connections on incoming TCP port */ | |
| 1162 static void simple_newconn_cb(gpointer data, gint source, GaimInputCondition cond) { | |
| 1163 GaimConnection *gc = data; | |
| 1164 struct simple_account_data *sip = gc->proto_data; | |
| 1165 struct sip_connection *conn; | |
| 1166 | |
| 1167 int newfd = accept(source, NULL, NULL); | |
| 1168 | |
| 1169 conn = connection_create(sip, newfd); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1170 |
| 11181 | 1171 conn->inputhandler = gaim_input_add(newfd, GAIM_INPUT_READ, simple_input_cb, gc); |
| 1172 } | |
| 1173 | |
| 1174 static void login_cb(gpointer data, gint source, GaimInputCondition cond) { | |
| 1175 GaimConnection *gc = data; | |
| 1176 struct simple_account_data *sip = gc->proto_data; | |
| 1177 struct sip_connection *conn; | |
| 1178 | |
| 1179 if( source < 0 ) { | |
| 1180 gaim_connection_error(gc,"Could not connect"); | |
| 1181 return; | |
| 1182 } | |
| 1183 | |
| 1184 sip->fd = source; | |
| 1185 | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1186 conn = connection_create(sip, source); |
| 11181 | 1187 |
| 11341 | 1188 /* get the local ip */ |
| 11181 | 1189 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
|
1190 |
| 11194 | 1191 do_register(sip); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1192 |
| 11181 | 1193 conn->inputhandler = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_input_cb, gc); |
| 1194 } | |
| 1195 | |
| 1196 static guint simple_ht_hash_nick(const char *nick) { | |
| 1197 char *lc = g_utf8_strdown(nick, -1); | |
| 1198 guint bucket = g_str_hash(lc); | |
| 1199 g_free(lc); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1200 |
| 11181 | 1201 return bucket; |
| 1202 } | |
| 1203 | |
| 1204 static gboolean simple_ht_equals_nick(const char *nick1, const char *nick2) { | |
| 1205 return (gaim_utf8_strcasecmp(nick1, nick2) == 0); | |
| 1206 } | |
| 1207 | |
|
12686
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
12657
diff
changeset
|
1208 static void srvresolved(GaimSrvResponse *resp, int results, gpointer data) { |
| 11383 | 1209 struct simple_account_data *sip = (struct simple_account_data*) data; |
| 1210 | |
| 1211 gchar *hostname; | |
|
12730
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1212 int port = gaim_account_get_int(sip->account, "port", 0); |
| 11383 | 1213 |
| 1214 int error = 0; | |
| 1215 struct hostent *h; | |
| 1216 | |
| 1217 /* find the host to connect to */ | |
| 1218 if(results) { | |
| 1219 hostname = g_strdup(resp->hostname); | |
|
12730
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1220 /* TODO: Should this work more like Jabber where the SRV value will be ignored |
|
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1221 * if there is one manually specified? */ |
| 11383 | 1222 port = resp->port; |
| 1223 g_free(resp); | |
| 1224 } else { | |
| 1225 if(!gaim_account_get_bool(sip->account, "useproxy", FALSE)) { | |
| 1226 hostname = g_strdup(sip->servername); | |
| 1227 } else { | |
| 1228 hostname = g_strdup(gaim_account_get_string(sip->account, "proxy", sip->servername)); | |
| 1229 } | |
| 1230 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1231 |
| 11383 | 1232 sip->realhostname = hostname; |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1233 sip->realport = port; |
| 11383 | 1234 /* TCP case */ |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1235 if(! sip->udp) { |
| 11409 | 1236 /* create socket for incoming connections */ |
|
12730
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1237 sip->listenfd = gaim_network_listen_range(5060, 5160, SOCK_STREAM); |
| 11409 | 1238 if(sip->listenfd == -1) { |
| 1239 gaim_connection_error(sip->gc, _("Could not create listen socket")); | |
| 1240 return; | |
| 1241 } | |
| 1242 gaim_debug_info("simple", "listenfd: %d\n", sip->listenfd); | |
| 1243 sip->listenport = gaim_network_get_port_from_fd(sip->listenfd); | |
| 1244 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
|
1245 gaim_debug_info("simple","connecting to %s port %d\n", hostname, port); |
| 11383 | 1246 /* open tcp connection to the server */ |
| 1247 error = gaim_proxy_connect(sip->account, hostname, port, login_cb, sip->gc); | |
| 1248 if(error) { | |
| 1249 gaim_connection_error(sip->gc, _("Couldn't create socket")); | |
| 1250 } | |
| 1251 | |
| 1252 } else { /* UDP */ | |
| 1253 gaim_debug_info("simple", "using udp with server %s and port %d\n", hostname, port); | |
|
12565
3f895385e841
[gaim-migrate @ 14884]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12563
diff
changeset
|
1254 |
|
3f895385e841
[gaim-migrate @ 14884]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12563
diff
changeset
|
1255 /** TODO: this should probably be async, right? */ |
|
3f895385e841
[gaim-migrate @ 14884]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12563
diff
changeset
|
1256 if (!(h = gethostbyname(hostname))) { |
|
3f895385e841
[gaim-migrate @ 14884]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12563
diff
changeset
|
1257 gaim_connection_error(sip->gc, _("Couldn't resolve host")); |
|
12570
f6762269699a
[gaim-migrate @ 14889]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12565
diff
changeset
|
1258 return; |
|
12565
3f895385e841
[gaim-migrate @ 14884]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12563
diff
changeset
|
1259 } |
|
3f895385e841
[gaim-migrate @ 14884]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12563
diff
changeset
|
1260 |
|
12730
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1261 /* create socket for incoming connections */ |
|
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1262 sip->fd = gaim_network_listen_range(5060, 5160, SOCK_DGRAM); |
| 11383 | 1263 |
|
12730
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1264 if(sip->fd == -1) { |
|
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1265 gaim_connection_error(sip->gc, _("Could not create listen socket")); |
|
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1266 return; |
| 11383 | 1267 } |
|
12730
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1268 |
| 12753 | 1269 sip->listenport = gaim_network_get_port_from_fd(sip->fd); |
| 11383 | 1270 sip->listenfd = sip->fd; |
| 1271 | |
|
12689
e893563d965d
[gaim-migrate @ 15032]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12686
diff
changeset
|
1272 sip->listenpa = gaim_input_add(sip->fd, GAIM_INPUT_READ, simple_udp_process, sip->gc); |
| 11383 | 1273 sip->serveraddr.sin_family = AF_INET; |
| 1274 sip->serveraddr.sin_port = htons(port); | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1275 |
| 11383 | 1276 sip->serveraddr.sin_addr.s_addr = ((struct in_addr*)h->h_addr)->s_addr; |
| 12753 | 1277 sip->ip = g_strdup(gaim_network_get_my_ip(-1)); |
| 11383 | 1278 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
|
1279 do_register(sip); |
| 11383 | 1280 } |
| 1281 } | |
| 1282 | |
| 11837 | 1283 static void simple_login(GaimAccount *account) |
| 11181 | 1284 { |
| 1285 GaimConnection *gc; | |
| 1286 struct simple_account_data *sip; | |
| 1287 gchar **userserver; | |
| 11210 | 1288 gchar *hosttoconnect; |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1289 |
| 11181 | 1290 const char *username = gaim_account_get_username(account); |
| 1291 | |
| 1292 gc = gaim_account_get_connection(account); | |
| 1293 gc->proto_data = sip = g_new0(struct simple_account_data,1); | |
| 1294 sip->gc=gc; | |
| 11189 | 1295 sip->account = account; |
| 11194 | 1296 sip->registerexpire = 900; |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1297 sip->udp = gaim_account_get_bool(account, "udp", FALSE); |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1298 if (strpbrk(username, " \t\v\r\n") != NULL) { |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1299 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
|
1300 return; |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1301 } |
| 11181 | 1302 |
| 1303 userserver = g_strsplit(username, "@", 2); | |
| 1304 gaim_connection_set_display_name(gc,userserver[0]); | |
| 1305 sip->username = g_strdup(userserver[0]); | |
| 1306 sip->servername = g_strdup(userserver[1]); | |
| 1307 sip->password = g_strdup(gaim_connection_get_password(gc)); | |
| 1308 g_strfreev(userserver); | |
| 1309 | |
| 1310 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
|
1311 |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1312 gaim_connection_update_progress(gc, _("Connecting"), 1, 2); |
| 11181 | 1313 |
| 11837 | 1314 /* TODO: Set the status correctly. */ |
| 11181 | 1315 sip->status = g_strdup("available"); |
| 11189 | 1316 |
| 11210 | 1317 if(!gaim_account_get_bool(account, "useproxy", FALSE)) { |
| 1318 hosttoconnect = g_strdup(sip->servername); | |
| 1319 } else { | |
| 1320 hosttoconnect = g_strdup(gaim_account_get_string(account, "proxy", sip->servername)); | |
| 1321 } | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1322 |
| 11341 | 1323 /* TCP case */ |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1324 if(! sip->udp) { |
| 11383 | 1325 gaim_srv_resolve("sip","tcp",hosttoconnect,srvresolved, sip); |
| 11341 | 1326 } else { /* UDP */ |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1327 gaim_srv_resolve("sip","udp",hosttoconnect,srvresolved, sip); |
| 11181 | 1328 } |
| 11210 | 1329 g_free(hosttoconnect); |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1330 |
| 11341 | 1331 /* register timeout callback for register / subscribe renewal */ |
| 12489 | 1332 /* TODO: What if the timeout is called before gaim_srv_resolve() finishes?! */ |
| 11194 | 1333 sip->registertimeout = gaim_timeout_add((rand()%100)+10*1000, (GSourceFunc)register_timeout, sip); |
| 11181 | 1334 } |
| 1335 | |
| 1336 static void simple_close(GaimConnection *gc) | |
| 1337 { | |
| 1338 struct simple_account_data *sip = gc->proto_data; | |
| 11194 | 1339 |
| 11341 | 1340 /* unregister */ |
| 11194 | 1341 do_register_exp(sip, 0); |
| 11346 | 1342 connection_free_all(sip); |
| 11341 | 1343 if(sip) { |
| 11650 | 1344 g_free(sip->servername); |
| 1345 g_free(sip->username); | |
| 1346 g_free(sip->password); | |
| 1347 g_free(sip->registrar.nonce); | |
| 1348 g_free(sip->registrar.realm); | |
| 1349 g_free(sip->proxy.nonce); | |
| 1350 g_free(sip->proxy.realm); | |
| 1351 g_free(sip->sendlater); | |
| 1352 g_free(sip->ip); | |
| 1353 g_free(sip->realhostname); | |
| 11409 | 1354 if(sip->listenpa) gaim_input_remove(sip->listenpa); |
|
12571
2c73e08032a1
[gaim-migrate @ 14890]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12570
diff
changeset
|
1355 if(sip->resendtimeout) gaim_timeout_remove(sip->resendtimeout); |
| 11346 | 1356 if(sip->registertimeout) gaim_timeout_remove(sip->registertimeout); |
| 11383 | 1357 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 | 1358 } |
| 11650 | 1359 g_free(gc->proto_data); |
|
12571
2c73e08032a1
[gaim-migrate @ 14890]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12570
diff
changeset
|
1360 gc->proto_data = NULL; |
| 11181 | 1361 } |
| 1362 | |
| 11345 | 1363 /* not needed since privacy is checked for every subscribe */ |
| 1364 static void dummy_add_deny(GaimConnection *gc, const char *name) { | |
| 1365 } | |
| 1366 | |
| 1367 static void dummy_permit_deny(GaimConnection *gc) { | |
| 1368 } | |
| 1369 | |
| 11181 | 1370 static GaimPluginProtocolInfo prpl_info = |
| 1371 { | |
| 1372 0, | |
| 1373 NULL, /* user_splits */ | |
| 1374 NULL, /* protocol_options */ | |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1375 NO_BUDDY_ICONS, /* icon_spec */ |
| 11181 | 1376 simple_list_icon, /* list_icon */ |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1377 NULL, /* list_emblems */ |
| 11181 | 1378 NULL, /* status_text */ |
| 1379 NULL, /* tooltip_text */ | |
| 1380 simple_status_types, /* away_states */ | |
| 1381 NULL, /* blist_node_menu */ | |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1382 NULL, /* chat_info */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1383 NULL, /* chat_info_defaults */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1384 simple_login, /* login */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1385 simple_close, /* close */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1386 simple_im_send, /* send_im */ |
| 11181 | 1387 NULL, /* set_info */ |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1388 simple_typing, /* send_typing */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1389 NULL, /* get_info */ |
| 11181 | 1390 simple_set_status, /* set_status */ |
| 1391 NULL, /* set_idle */ | |
| 1392 NULL, /* change_passwd */ | |
| 1393 simple_add_buddy, /* add_buddy */ | |
| 1394 NULL, /* add_buddies */ | |
| 1395 simple_remove_buddy, /* remove_buddy */ | |
| 1396 NULL, /* remove_buddies */ | |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1397 dummy_add_deny, /* add_permit */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1398 dummy_add_deny, /* add_deny */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1399 dummy_add_deny, /* rem_permit */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1400 dummy_add_deny, /* rem_deny */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1401 dummy_permit_deny, /* set_permit_deny */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1402 NULL, /* join_chat */ |
| 11181 | 1403 NULL, /* reject_chat */ |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1404 NULL, /* get_chat_name */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1405 NULL, /* chat_invite */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1406 NULL, /* chat_leave */ |
| 11181 | 1407 NULL, /* chat_whisper */ |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1408 NULL, /* chat_send */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1409 simple_keep_alive, /* keepalive */ |
| 11181 | 1410 NULL, /* register_user */ |
| 1411 NULL, /* get_cb_info */ | |
| 1412 NULL, /* get_cb_away */ | |
| 1413 NULL, /* alias_buddy */ | |
| 1414 NULL, /* group_buddy */ | |
| 1415 NULL, /* rename_group */ | |
| 1416 NULL, /* buddy_free */ | |
| 1417 NULL, /* convo_closed */ | |
| 1418 NULL, /* normalize */ | |
| 1419 NULL, /* set_buddy_icon */ | |
| 1420 NULL, /* remove_group */ | |
| 1421 NULL, /* get_cb_real_name */ | |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1422 NULL, /* set_chat_topic */ |
| 11181 | 1423 NULL, /* find_blist_chat */ |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1424 NULL, /* roomlist_get_list */ |
|
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1425 NULL, /* roomlist_cancel */ |
| 11181 | 1426 NULL, /* roomlist_expand_category */ |
| 1427 NULL, /* can_receive_file */ | |
|
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11837
diff
changeset
|
1428 NULL, /* send_file */ |
|
12600
e856f985a0b9
[gaim-migrate @ 14934]
Richard Laager <rlaager@wiktel.com>
parents:
12595
diff
changeset
|
1429 NULL, /* new_xfer */ |
|
12645
fc28451f5d96
[gaim-migrate @ 14983]
Richard Laager <rlaager@wiktel.com>
parents:
12600
diff
changeset
|
1430 NULL, /* offline_message */ |
|
12600
e856f985a0b9
[gaim-migrate @ 14934]
Richard Laager <rlaager@wiktel.com>
parents:
12595
diff
changeset
|
1431 NULL, /* whiteboard_prpl_ops */ |
|
e856f985a0b9
[gaim-migrate @ 14934]
Richard Laager <rlaager@wiktel.com>
parents:
12595
diff
changeset
|
1432 NULL, /* media_prpl_ops */ |
| 11181 | 1433 }; |
| 1434 | |
| 1435 | |
| 1436 static GaimPluginInfo info = | |
| 1437 { | |
| 1438 GAIM_PLUGIN_MAGIC, | |
| 1439 GAIM_MAJOR_VERSION, | |
| 1440 GAIM_MINOR_VERSION, | |
| 1441 GAIM_PLUGIN_PROTOCOL, /**< type */ | |
| 1442 NULL, /**< ui_requirement */ | |
| 1443 0, /**< flags */ | |
| 1444 NULL, /**< dependencies */ | |
| 1445 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
| 1446 | |
| 12489 | 1447 "prpl-simple", /**< id */ |
| 1448 "SIMPLE", /**< name */ | |
| 11181 | 1449 VERSION, /**< version */ |
| 12489 | 1450 N_("SIP/SIMPLE Protocol Plugin"), /** summary */ |
| 1451 N_("The SIP/SIMPLE Protocol Plugin"), /** description */ | |
| 1452 "Thomas Butter <butter@uni-mannheim.de>", /**< author */ | |
| 11181 | 1453 GAIM_WEBSITE, /**< homepage */ |
| 1454 | |
| 1455 NULL, /**< load */ | |
| 1456 NULL, /**< unload */ | |
| 1457 NULL, /**< destroy */ | |
| 1458 | |
| 1459 NULL, /**< ui_info */ | |
| 1460 &prpl_info, /**< extra_info */ | |
| 1461 NULL, | |
| 1462 NULL | |
| 1463 }; | |
| 1464 | |
| 1465 static void _init_plugin(GaimPlugin *plugin) | |
| 1466 { | |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1467 GaimAccountUserSplit *split; |
| 11189 | 1468 GaimAccountOption *option; |
| 11181 | 1469 |
|
11396
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1470 split = gaim_account_user_split_new(_("Server"), "", '@'); |
|
be776f9b1818
[gaim-migrate @ 13627]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11383
diff
changeset
|
1471 prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); |
| 11181 | 1472 |
| 12489 | 1473 option = gaim_account_option_bool_new(_("Publish status (note: everyone may watch you)"), "dopublish", TRUE); |
| 11345 | 1474 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
| 1475 | |
|
12730
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1476 option = gaim_account_option_int_new(_("Connect port"), "port", 5060); |
|
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1477 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1478 |
|
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12689
diff
changeset
|
1479 |
| 11189 | 1480 option = gaim_account_option_bool_new(_("Use UDP"), "udp", FALSE); |
| 1481 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
| 12489 | 1482 option = gaim_account_option_bool_new(_("Use proxy"), "useproxy", FALSE); |
| 11210 | 1483 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
| 1484 option = gaim_account_option_string_new(_("Proxy"), "proxy", ""); | |
| 1485 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); | |
| 11181 | 1486 } |
| 1487 | |
| 1488 GAIM_INIT_PLUGIN(simple, _init_plugin, info); |
