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