blob: e30bc0d5e86988978742b5b5ea30b667db7d6f69 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file info.c SIP Session Info
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 int info_request(struct sipsess_request *req);
22
23
24static void info_resp_handler(int err, const struct sip_msg *msg, void *arg)
25{
26 struct sipsess_request *req = arg;
27
28 if (err || sip_request_loops(&req->ls, msg->scode))
29 goto out;
30
31 if (msg->scode < 200) {
32 return;
33 }
34 else if (msg->scode < 300) {
35 ;
36 }
37 else {
38 if (req->sess->terminated)
39 goto out;
40
41 switch (msg->scode) {
42
43 case 401:
44 case 407:
45 err = sip_auth_authenticate(req->sess->auth, msg);
46 if (err) {
47 err = (err == EAUTH) ? 0 : err;
48 break;
49 }
50
51 err = info_request(req);
52 if (err)
53 break;
54
55 return;
56
57 case 408:
58 case 481:
59 sipsess_terminate(req->sess, 0, msg);
60 break;
61 }
62 }
63
64 out:
65 if (!req->sess->terminated) {
66 if (err == ETIMEDOUT)
67 sipsess_terminate(req->sess, err, NULL);
68 else
69 req->resph(err, msg, req->arg);
70 }
71
72 mem_deref(req);
73}
74
75
76static int info_request(struct sipsess_request *req)
77{
78 return sip_drequestf(&req->req, req->sess->sip, true, "INFO",
79 req->sess->dlg, 0, req->sess->auth,
80 NULL, info_resp_handler, req,
81 "Content-Type: %s\r\n"
82 "Content-Length: %zu\r\n"
83 "\r\n"
84 "%b",
85 req->ctype,
86 mbuf_get_left(req->body),
87 mbuf_buf(req->body), mbuf_get_left(req->body));
88}
89
90
91/**
92 * Send a SIP INFO request in the SIP Session
93 *
94 * @param sess SIP Session
95 * @param ctype Content-type
96 * @param body Content description (e.g. SDP)
97 * @param resph Response handler
98 * @param arg Handler argument
99 *
100 * @return 0 if success, otherwise errorcode
101 */
102int sipsess_info(struct sipsess *sess, const char *ctype, struct mbuf *body,
103 sip_resp_h *resph, void *arg)
104{
105 struct sipsess_request *req;
106 int err;
107
108 if (!sess || sess->terminated || !ctype || !body)
109 return EINVAL;
110
111 if (!sip_dialog_established(sess->dlg))
112 return ENOTCONN;
113
114 err = sipsess_request_alloc(&req, sess, ctype, body, resph, arg);
115 if (err)
116 return err;
117
118 err = info_request(req);
119 if (err)
120 mem_deref(req);
121
122 return err;
123}