1 // Copyright (C) 2007-2014 David Sugar, Tycho Softworks.
2 // Copyright (C) 2015 Cherokees of Idaho.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 #include <sipwitch-config.h>
19 #include <ucommon/secure.h>
20 #include <stddef.h>
21
22 namespace sipwitch {
23
24 static class __LOCAL subscriber : private modules::sipwitch
25 {
26 private:
27 static subscriber _sub;
28
30 bool authenticate(
voip::reg_t id,
const char *remote_realm);
31 void update(void);
32
33 public:
34 subscriber();
35
36 void reload(service *cfg);
37 void start(service *cfg);
38 void stop(service *cfg);
39 void snapshot(FILE *fp);
40 } _sub;
41
42 static volatile bool changed = false;
43 static volatile timeout_t interval = 50;
44 static volatile time_t refresh = 60;
45 static volatile time_t updated = 0;
46 static int priority = 0;
47 static const char *iface = NULL;
48 static char *server = NULL;
49 static char *proxy = NULL;
50 static char *userid = NULL;
51 static char *schema = (char *)"sip";
52 static char *volatile secret = NULL;
53 static char *identity = NULL;
55 static MappedRegistry provider; // fake provider record to be used...
56 static unsigned short port = 9000;
57
58 subscriber::subscriber() :
59 modules::sipwitch()
60 {
61 zero_unsafe<MappedRegistry>(provider);
64 // we already know provider is normally external / outside NAT....
66 }
67
68 void subscriber::update(void)
69 {
73 unsigned len;
74 Socket::address dest = server;
75
76 Random::uuid(provider.
remote);
77 snprintf(uri, sizeof(uri), "%s:%s@%s", schema, userid, server);
78 snprintf(reg, sizeof(reg), "%s:%s", schema, server);
79 snprintf(contact,
sizeof(contact),
"%s:%s@", schema, provider.
remote);
80
81 changed = false;
82 len = strlen(contact);
83 Socket::via((
struct sockaddr *)&provider.
contact, dest.getAddr());
84 Socket::query((
struct sockaddr *)&provider.
contact, contact + len,
sizeof(contact) - len);
85 len = strlen(contact);
86 snprintf(contact + len, sizeof(contact) - len, ":%u", sip_port);
87 shell::debug(3, "registering %s with %s", contact, server);
88
91 if(provider.
rid == -1 || !msg)
93 else {
99 }
100 }
101
102 void subscriber::start(service *cfg)
103 {
104 assert(cfg != NULL);
105
108
109 if(changed)
110 update();
111 }
112 }
113
114 void subscriber::stop(service *cfg)
115 {
116 if(provider.
rid != -1)
118
119 assert(cfg != NULL);
120 }
121
122 void subscriber::snapshot(FILE *fp)
123 {
124 assert(fp != NULL);
125
126 fprintf(fp, "subscriber:\n");
127 }
128
129 void subscriber::reload(service *cfg)
130 {
131 assert(cfg != NULL);
132
133 char *temp;
134 const char *key = NULL, *
value;
135 linked_pointer<service::keynode> sp = cfg->getList("subscriber");
136 char buffer[160];
137 srv resolver;
139
140 updated = 0l;
141
142 while(is(sp)) {
143 key = sp->getId();
144 value = sp->getPointer();
145 if(key && value) {
146 if(!stricmp(key, "count") && !is_configured())
148 else if(!stricmp(key, "interface") && !is_configured())
149 iface = strdup(value);
150 else if(!stricmp(key, "interval"))
151 interval = atol(value);
152 else if(!stricmp(key, "priority") && !is_configured())
153 priority = atoi(value);
154 else if(!stricmp(key, "port") && !is_configured())
155 port = atoi(value);
156 // very rare we may wish to override provider network/nat state
157 else if(!stricmp(key, "network"))
159 else if(!stricmp(key, "refresh"))
160 refresh = atoi(value);
161 else if(!stricmp(key, "registrar") || !stricmp(key, "server")) {
162 tmp_context = resolver.route(value, buffer, sizeof(buffer));
163 if(tmp_context) {
164 changed = true;
165 server = cfg->dup(buffer);
166 shell::debug(2, "subscriber provider is %s", buffer);
167 }
168 else {
169 changed = false;
170 shell::log(shell::ERR, "subscriber: %s: cannot resolve", value);
171 }
172 }
173 else if(!stricmp(key, "proxy")) {
174 temp = proxy;
175 proxy = strdup(value);
176 if(temp)
177 free(temp);
178 }
179 else if(!stricmp(key, "userid")) {
180 temp = userid;
181 userid = strdup(value);
182 if(temp)
183 free(temp);
184 }
185 else if(!stricmp(key, "secret")) {
186 temp = secret;
187 secret = strdup(value);
188 if(temp)
189 free(temp);
190 }
191 else if(!stricmp(key, "identity")) {
192 temp = identity;
193 identity = strdup(value);
194 if(temp)
195 free(temp);
196 }
197 }
198 sp.next();
199 }
200
201 if(tmp_context)
202 context = tmp_context;
203
204 if(!is_configured() &&
count)
206 }
207
209 {
210 if(
id == -1 ||
id != provider.
rid)
211 return;
212
213 switch(mode) {
215 shell::log(shell::ERR, "service provider failed");
218 if(changed)
219 update();
220 return;
222 shell::log(shell::NOTIFY, "service provider active");
224 return;
225 }
226 }
227
228 bool subscriber::authenticate(
voip::reg_t id,
const char *remote_realm)
229 {
230 if(
id == -1 ||
id != provider.
rid)
231 return false;
232
233 if(secret && *secret)
234 shell::debug(3, "authorizing %s for %s", userid, remote_realm);
235 else {
236 shell::debug(3, "cannot authorize %s for %s", userid, remote_realm);
237 return false;
238 }
239
241 return true;
242 }
243
244 } // end namespace
static void add_authentication(context_t ctx, const char *user, const char *secret, const char *realm, bool automatic=false)
sockaddr_internet contact
static void send_registry_request(context_t ctx, reg_t rid, msg_t msg)
union sipwitch::MappedRegistry::@6 source
Top level include directory for GNU Telephony SIP Witch Server.
static stats * request(const char *id)
Request a stat node from the memory pool by id.
static void server_supports(voip::msg_t msg, const char *txt)
struct sipwitch::MappedRegistry::@6::@7 external
static reg_t make_registry_request(context_t ctx, const char *uri, const char *s, const char *c, unsigned exp, msg_t *msg)
static void allocate(unsigned count)
Server allocate x number of stat nodes at startup.
static void header(msg_t msg, const char *key, const char *value)
enum sipwitch::MappedRegistry::@5 type
static bool release_registry(context_t ctx, reg_t rid)