Updated to release 1.7.0
[siplcs.git] / src / sipe-dialog.c
blob58b709bf6ff4f926b0d15ff19f6d599ea80dbbda
1 /**
2 * @file sipe-dialog.c
4 * pidgin-sipe
6 * Copyright (C) 2009 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <string.h>
24 #include <glib.h>
26 #include "debug.h"
28 #include "sipe.h"
29 #include "sipe-dialog.h"
30 #include "sipe-session.h"
31 #include "sipmsg.h"
33 void sipe_dialog_free(struct sip_dialog *dialog)
35 GSList *entry;
37 if (!dialog) return;
39 g_free(dialog->with);
40 g_free(dialog->endpoint_GUID);
41 entry = dialog->routes;
42 while (entry) {
43 g_free(entry->data);
44 entry = g_slist_remove(entry, entry->data);
46 entry = dialog->supported;
47 while (entry) {
48 g_free(entry->data);
49 entry = g_slist_remove(entry, entry->data);
52 g_free(dialog->callid);
53 g_free(dialog->ourtag);
54 g_free(dialog->theirtag);
55 g_free(dialog->theirepid);
56 g_free(dialog->request);
58 g_free(dialog);
61 void sipe_subscription_free(struct sip_subscription *subscription)
63 if (!subscription) return;
65 g_free(subscription->event);
66 sipe_dialog_free(&subscription->dialog);
69 struct sip_dialog *sipe_dialog_add(struct sip_session *session)
71 struct sip_dialog *dialog = g_new0(struct sip_dialog, 1);
72 session->dialogs = g_slist_append(session->dialogs, dialog);
73 return(dialog);
76 struct sip_dialog *sipe_dialog_find(struct sip_session *session,
77 const gchar *who)
79 if (session && who) {
80 SIPE_DIALOG_FOREACH {
81 if (dialog->with && !g_ascii_strcasecmp(who, dialog->with)) {
82 purple_debug_info("sipe", "sipe_dialog_find who='%s'\n", who);
83 return dialog;
85 } SIPE_DIALOG_FOREACH_END;
87 return NULL;
90 void sipe_dialog_remove(struct sip_session *session, const gchar *who)
92 struct sip_dialog *dialog = sipe_dialog_find(session, who);
93 if (dialog) {
94 purple_debug_info("sipe", "sipe_dialog_remove who='%s' with='%s'\n", who, dialog->with ? dialog->with : "");
95 session->dialogs = g_slist_remove(session->dialogs, dialog);
96 sipe_dialog_free(dialog);
100 void sipe_dialog_remove_all(struct sip_session *session)
102 GSList *entry = session->dialogs;
103 while (entry) {
104 sipe_dialog_free(entry->data);
105 entry = g_slist_remove(entry, entry->data);
109 static void sipe_get_route_header(const struct sipmsg *msg,
110 struct sip_dialog *dialog,
111 gboolean outgoing)
113 GSList *hdr = msg->headers;
114 gchar *contact;
116 while (hdr) {
117 struct siphdrelement *elem = hdr->data;
118 if(!g_ascii_strcasecmp(elem->name, "Record-Route")) {
119 gchar **parts = g_strsplit(elem->value, ",", 0);
120 gchar **part = parts;
122 while (*part) {
123 gchar *route = sipmsg_find_part_of_header(*part, "<", ">", NULL);
124 purple_debug_info("sipe", "sipe_get_route_header: route %s \n", route);
125 dialog->routes = g_slist_append(dialog->routes, route);
126 part++;
129 g_strfreev(parts);
131 hdr = g_slist_next(hdr);
134 if (outgoing) {
135 dialog->routes = g_slist_reverse(dialog->routes);
138 if (dialog->routes) {
139 dialog->request = dialog->routes->data;
140 dialog->routes = g_slist_remove(dialog->routes, dialog->routes->data);
143 contact = sipmsg_find_part_of_header(sipmsg_find_header(msg, "Contact"), "<", ">", NULL);
144 if (contact) {
145 dialog->routes = g_slist_append(dialog->routes, contact);
149 static void
150 sipe_get_supported_header(const struct sipmsg *msg,
151 struct sip_dialog *dialog,
152 SIPE_UNUSED_PARAMETER gboolean outgoing)
154 GSList *hdr = msg->headers;
155 struct siphdrelement *elem;
156 while(hdr)
158 elem = hdr->data;
159 if(!g_ascii_strcasecmp(elem->name, "Supported")
160 && !g_slist_find_custom(dialog->supported, elem->value, (GCompareFunc)g_ascii_strcasecmp))
162 dialog->supported = g_slist_append(dialog->supported, g_strdup(elem->value));
165 hdr = g_slist_next(hdr);
169 static gchar *find_tag(const gchar *hdr)
171 gchar * tag = sipmsg_find_part_of_header (hdr, "tag=", ";", NULL);
172 if (!tag) {
173 // In case it's at the end and there's no trailing ;
174 tag = sipmsg_find_part_of_header (hdr, "tag=", NULL, NULL);
176 return tag;
179 void sipe_dialog_parse(struct sip_dialog *dialog,
180 const struct sipmsg *msg,
181 gboolean outgoing)
183 gchar *us = outgoing ? "From" : "To";
184 gchar *them = outgoing ? "To" : "From";
186 g_free(dialog->ourtag);
187 g_free(dialog->theirtag);
189 dialog->ourtag = find_tag(sipmsg_find_header(msg, us));
190 dialog->theirtag = find_tag(sipmsg_find_header(msg, them));
191 if (!dialog->theirepid) {
192 dialog->theirepid = sipmsg_find_part_of_header(sipmsg_find_header(msg, them), "epid=", ";", NULL);
193 if (!dialog->theirepid) {
194 dialog->theirepid = sipmsg_find_part_of_header(sipmsg_find_header(msg, them), "epid=", NULL, NULL);
198 // Catch a tag on the end of the To Header and get rid of it.
199 if (dialog->theirepid && strstr(dialog->theirepid, "tag=")) {
200 dialog->theirepid = strtok(dialog->theirepid, ";");
203 sipe_get_route_header(msg, dialog, outgoing);
204 sipe_get_supported_header(msg, dialog, outgoing);
208 Local Variables:
209 mode: c
210 c-file-style: "bsd"
211 indent-tabs-mode: t
212 tab-width: 8
213 End: