SIP Witch 1.9.15
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
subscriber.cpp
Go to the documentation of this file.
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>
18 #include <sipwitch/sipwitch.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 
29  void registration(voip::reg_t, modules::regmode_t mode);
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;
54 static voip::context_t context = 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);
62  provider.rid = -1;
63  provider.type = MappedRegistry::EXTERNAL;
64  // we already know provider is normally external / outside NAT....
65  String::set(provider.network, sizeof(provider.network), "*");
66 }
67 
68 void subscriber::update(void)
69 {
70  char contact[MAX_URI_SIZE];
71  char uri[MAX_URI_SIZE];
72  char reg[MAX_URI_SIZE];
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 
89  voip::msg_t msg = NULL;
90  provider.rid = voip::make_registry_request(context, uri, reg, contact, (unsigned)refresh, &msg);
91  if(provider.rid == -1 || !msg)
93  else {
94  voip::server_supports(msg, "100rel");
95  voip::header(msg, "Event", "Registration");
96  voip::header(msg, "Allow-Events", "presence");
97  voip::send_registry_request(context, provider.rid, msg);
98  provider.status = MappedRegistry::IDLE;
99  }
100 }
101 
102 void subscriber::start(service *cfg)
103 {
104  assert(cfg != NULL);
105 
106  if(count) {
107  provider.source.external.statnode = stats::request("provider");
108 
109  if(changed)
110  update();
111  }
112 }
113 
114 void subscriber::stop(service *cfg)
115 {
116  if(provider.rid != -1)
117  voip::release_registry(context, provider.rid);
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;
138  voip::context_t tmp_context = NULL;
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())
147  count = atoi(value);
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"))
158  String::set(provider.network, sizeof(provider.network), value);
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)
205  stats::allocate(1);
206 }
207 
208 void subscriber::registration(voip::reg_t id, modules::regmode_t mode)
209 {
210  if(id == -1 || id != provider.rid)
211  return;
212 
213  switch(mode) {
214  case modules::REG_FAILED:
215  shell::log(shell::ERR, "service provider failed");
216  provider.rid = -1;
217  provider.status = MappedRegistry::OFFLINE;
218  if(changed)
219  update();
220  return;
222  shell::log(shell::NOTIFY, "service provider active");
223  provider.status = MappedRegistry::IDLE;
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 
240  voip::add_authentication(context, userid, secret, remote_realm, true);
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)
Definition: voip.cpp:488
unsigned count
Definition: cgiserver.cpp:92
sockaddr_internet contact
Definition: mapped.h:111
static void send_registry_request(context_t ctx, reg_t rid, msg_t msg)
Definition: voip.cpp:631
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.
Definition: stats.cpp:59
static void server_supports(voip::msg_t msg, const char *txt)
Definition: voip.cpp:923
struct sipwitch::MappedRegistry::@6::@7 external
char * value[96]
Definition: cgiserver.cpp:90
void * context_t
Definition: voip.h:53
int reg_t
Definition: voip.h:59
osip_message_t * msg_t
Definition: voip.h:64
static reg_t make_registry_request(context_t ctx, const char *uri, const char *s, const char *c, unsigned exp, msg_t *msg)
Definition: voip.cpp:618
static void allocate(unsigned count)
Server allocate x number of stat nodes at startup.
Definition: stats.cpp:71
static void header(msg_t msg, const char *key, const char *value)
Definition: voip.cpp:928
enum sipwitch::MappedRegistry::@5 type
static bool release_registry(context_t ctx, reg_t rid)
Definition: voip.cpp:639
#define MAX_URI_SIZE
Definition: mapped.h:71