blob: b8d02f849eb277f904fce5d4dad75cd190c14dfe [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file accept.c SIP Session Accept
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <re_types.h>
7#include <re_mem.h>
8#include <re_mbuf.h>
9#include <re_sa.h>
10#include <re_list.h>
11#include <re_hash.h>
12#include <re_fmt.h>
13#include <re_uri.h>
14#include <re_tmr.h>
15#include <re_msg.h>
16#include <re_sip.h>
17#include <re_sipsess.h>
18#include "sipsess.h"
19
20
21static void cancel_handler(void *arg)
22{
23 struct sipsess *sess = arg;
24
25 (void)sip_treply(&sess->st, sess->sip, sess->msg,
26 487, "Request Terminated");
27
28 sess->peerterm = true;
29
30 if (sess->terminated)
31 return;
32
33 sipsess_terminate(sess, ECONNRESET, NULL);
34}
35
36
37/**
38 * Accept an incoming SIP Session connection
39 *
40 * @param sessp Pointer to allocated SIP Session
41 * @param sock SIP Session socket
42 * @param msg Incoming SIP message
43 * @param scode Response status code
44 * @param reason Response reason phrase
45 * @param cuser Contact username or URI
46 * @param ctype Session content-type
47 * @param desc Content description (e.g. SDP)
48 * @param authh SIP Authentication handler
49 * @param aarg Authentication handler argument
50 * @param aref True to mem_ref() aarg
51 * @param offerh Session offer handler
52 * @param answerh Session answer handler
53 * @param estabh Session established handler
54 * @param infoh Session info handler
55 * @param referh Session refer handler
56 * @param closeh Session close handler
57 * @param arg Handler argument
58 * @param fmt Formatted strings with extra SIP Headers
59 *
60 * @return 0 if success, otherwise errorcode
61 */
62int sipsess_accept(struct sipsess **sessp, struct sipsess_sock *sock,
63 const struct sip_msg *msg, uint16_t scode,
64 const char *reason, const char *cuser, const char *ctype,
65 struct mbuf *desc,
66 sip_auth_h *authh, void *aarg, bool aref,
67 sipsess_offer_h *offerh, sipsess_answer_h *answerh,
68 sipsess_estab_h *estabh, sipsess_info_h *infoh,
69 sipsess_refer_h *referh, sipsess_close_h *closeh,
70 void *arg, const char *fmt, ...)
71{
72 struct sipsess *sess;
73 va_list ap;
74 int err;
75
76 if (!sessp || !sock || !msg || scode < 101 || scode > 299 ||
77 !cuser || !ctype)
78 return EINVAL;
79
80 err = sipsess_alloc(&sess, sock, cuser, ctype, NULL, authh, aarg, aref,
81 offerh, answerh, NULL, estabh, infoh, referh,
82 closeh, arg);
83 if (err)
84 return err;
85
86 err = sip_dialog_accept(&sess->dlg, msg);
87 if (err)
88 goto out;
89
90 hash_append(sock->ht_sess,
91 hash_joaat_str(sip_dialog_callid(sess->dlg)),
92 &sess->he, sess);
93
94 sess->msg = mem_ref((void *)msg);
95
96 err = sip_strans_alloc(&sess->st, sess->sip, msg, cancel_handler,
97 sess);
98 if (err)
99 goto out;
100
101 va_start(ap, fmt);
102
103 if (scode >= 200)
104 err = sipsess_reply_2xx(sess, msg, scode, reason, desc,
105 fmt, &ap);
106 else {
107 struct sip_contact contact;
108
109 sip_contact_set(&contact, sess->cuser, &msg->dst, msg->tp);
110
111 err = sip_treplyf(&sess->st, NULL, sess->sip,
112 msg, true, scode, reason,
113 "%H"
114 "%v"
115 "%s%s%s"
116 "Content-Length: %zu\r\n"
117 "\r\n"
118 "%b",
119 sip_contact_print, &contact,
120 fmt, &ap,
121 desc ? "Content-Type: " : "",
122 desc ? sess->ctype : "",
123 desc ? "\r\n" : "",
124 desc ? mbuf_get_left(desc) : (size_t)0,
125 desc ? mbuf_buf(desc) : NULL,
126 desc ? mbuf_get_left(desc) : (size_t)0);
127 }
128
129 va_end(ap);
130
131 if (err)
132 goto out;
133
134 out:
135 if (err)
136 mem_deref(sess);
137 else
138 *sessp = sess;
139
140 return err;
141}
142
143
144/**
145 * Send progress response
146 *
147 * @param sess SIP Session
148 * @param scode Response status code
149 * @param reason Response reason phrase
150 * @param desc Content description (e.g. SDP)
151 * @param fmt Formatted strings with extra SIP Headers
152 *
153 * @return 0 if success, otherwise errorcode
154 */
155int sipsess_progress(struct sipsess *sess, uint16_t scode, const char *reason,
156 struct mbuf *desc, const char *fmt, ...)
157{
158 struct sip_contact contact;
159 va_list ap;
160 int err;
161
162 if (!sess || !sess->st || !sess->msg || scode < 101 || scode > 199)
163 return EINVAL;
164
165 va_start(ap, fmt);
166
167 sip_contact_set(&contact, sess->cuser, &sess->msg->dst, sess->msg->tp);
168
169 err = sip_treplyf(&sess->st, NULL, sess->sip, sess->msg, true,
170 scode, reason,
171 "%H"
172 "%v"
173 "%s%s%s"
174 "Content-Length: %zu\r\n"
175 "\r\n"
176 "%b",
177 sip_contact_print, &contact,
178 fmt, &ap,
179 desc ? "Content-Type: " : "",
180 desc ? sess->ctype : "",
181 desc ? "\r\n" : "",
182 desc ? mbuf_get_left(desc) : (size_t)0,
183 desc ? mbuf_buf(desc) : NULL,
184 desc ? mbuf_get_left(desc) : (size_t)0);
185
186 va_end(ap);
187
188 return err;
189}
190
191
192/**
193 * Answer an incoming SIP Session connection
194 *
195 * @param sess SIP Session
196 * @param scode Response status code
197 * @param reason Response reason phrase
198 * @param desc Content description (e.g. SDP)
199 * @param fmt Formatted strings with extra SIP Headers
200 *
201 * @return 0 if success, otherwise errorcode
202 */
203int sipsess_answer(struct sipsess *sess, uint16_t scode, const char *reason,
204 struct mbuf *desc, const char *fmt, ...)
205{
206 va_list ap;
207 int err;
208
209 if (!sess || !sess->st || !sess->msg || scode < 200 || scode > 299)
210 return EINVAL;
211
212 va_start(ap, fmt);
213 err = sipsess_reply_2xx(sess, sess->msg, scode, reason, desc,
214 fmt, &ap);
215 va_end(ap);
216
217 return err;
218}
219
220
221/**
222 * Reject an incoming SIP Session connection
223 *
224 * @param sess SIP Session
225 * @param scode Response status code
226 * @param reason Response reason phrase
227 * @param fmt Formatted strings with extra SIP Headers
228 *
229 * @return 0 if success, otherwise errorcode
230 */
231int sipsess_reject(struct sipsess *sess, uint16_t scode, const char *reason,
232 const char *fmt, ...)
233{
234 va_list ap;
235 int err;
236
237 if (!sess || !sess->st || !sess->msg || scode < 300)
238 return EINVAL;
239
240 va_start(ap, fmt);
241 err = sip_treplyf(&sess->st, NULL, sess->sip, sess->msg, false,
242 scode, reason, fmt ? "%v" : NULL, fmt, &ap);
243 va_end(ap);
244
245 return err;
246}