21 static volatile unsigned active_routes = 0;
22 static volatile unsigned active_entries = 0;
23 static volatile unsigned active_targets = 0;
24 static volatile unsigned published_routes = 0;
25 static volatile unsigned allocated_routes = 0;
26 static volatile unsigned allocated_targets = 0;
27 static volatile unsigned allocated_entries = 0;
28 static unsigned mapped_entries = 999;
30 static unsigned keysize = 177;
31 static registry::mapped **extmap = NULL;
39 static condlock_t locking;
40 static stats *statmap = NULL;
52 assert(
id != NULL && *
id != 0);
74 void *registry::target::operator
new(
size_t size)
82 void registry::target::operator
delete(
void *obj)
90 void *registry::route::operator
new(
size_t size)
98 void registry::route::operator
delete(
void *obj)
118 #ifdef HAVE_GETHOSTNAME
119 static char hostbuf[256] = {0};
121 gethostname(hostbuf,
sizeof(hostbuf));
197 assert(
id != NULL && *
id != 0);
199 linked_pointer<mapped> rp;
200 unsigned path = NamedObject::keyindex(
id, keysize);
205 if(!strcmp(rp->userid,
id))
214 assert((caddr_t)rr >=
reg.addr());
224 shell::log(
DEBUG1,
"starting registry; mapping %d entries", mapped_entries);
227 shell::log(shell::FAIL,
"registry could not be mapped");
234 shell::log(shell::INFO,
"checking registry...");
244 shell::log(
DEBUG1,
"stopping registry");
245 MappedMemory::release();
255 unsigned regcount = 0;
257 linked_pointer<target> tp;
258 linked_pointer<route> rp;
262 fprintf(fp,
"Registry:\n");
263 fprintf(fp,
" mapped entries: %d\n", mapped_entries);
264 fprintf(fp,
" active entries: %d\n", active_entries);
265 fprintf(fp,
" active routes: %d\n", active_routes);
266 fprintf(fp,
" active targets: %d\n", active_targets);
267 fprintf(fp,
" published routes: %d\n", published_routes);
268 fprintf(fp,
" allocated routes: %d\n", allocated_routes);
269 fprintf(fp,
" allocated targets: %d\n", allocated_targets);
270 fprintf(fp,
" allocated entries: %d\n", allocated_entries);
272 while(regcount < mapped_entries) {
274 rr =
static_cast<mapped*
>(
reg(regcount++));
276 fprintf(fp,
" temp %s; use=%d\n", rr->
userid, rr->
inuse);
280 snprintf(buffer,
sizeof(buffer),
"%d", rr->
ext);
282 String::set(buffer,
sizeof(buffer),
"none");
284 fprintf(fp,
" user %s; extension=%s, profile=%s, use=%d,",
287 fprintf(fp,
" gateway %s; use=%d,", rr->
userid, rr->
inuse);
289 fprintf(fp,
" service %s; use=%d", rr->
userid, rr->
inuse);
291 fprintf(fp,
" refer %s; extensions=%s,",
294 fprintf(fp,
" reject %s; extension=%s,",
297 fprintf(fp,
" address=none\n");
302 Socket::query((
struct sockaddr *)(&tp->address), buffer,
sizeof(buffer));
303 fprintf(fp,
" address=%s, contact=%s", buffer, tp->contact);
304 if(tp->expires && tp->expires <= now)
305 fprintf(fp,
", expired");
307 fprintf(fp,
", expires %ld", (
long)(tp->expires - now));
315 fprintf(fp,
" services=");
317 fprintf(fp,
" routes=");
319 fputs(rp->entry.text, fp);
328 fprintf(fp,
" published=");
330 fputs(rp->entry.text, fp);
367 assert(
id != NULL && *
id != 0);
377 store_unsafe<mapped>(save, rr);
399 route *nr = rp.getNext();
401 path = NamedObject::keyindex(rp->entry.text, keysize);
402 rp->entry.delist(&contacts[path]);
405 rp->entry.delist(&primap[rp->entry.priority]);
406 rp->entry.text[0] = 0;
412 route *nr = rp.getNext();
414 path = NamedObject::keyindex(rp->entry.text, keysize);
415 rp->entry.delist(&publishing[path]);
416 rp->entry.text[0] = 0;
422 if(tp->index.address) {
423 path = Socket::keyindex(tp->index.address, keysize);
424 tp->index.delist(&addresses[path]);
425 tp->index.address = NULL;
426 tp->index.registry = NULL;
428 target *nt = tp.getNext();
440 shell::log(shell::INFO,
"expiring %s; extension=%d", rr->
userid, rr->
ext);
441 path = NamedObject::keyindex(rr->
userid, keysize);
448 rr->delist(&keys[path]);
449 rr->enlist(&freelist);
455 unsigned regcount = 0;
458 unsigned expcount = 0;
460 while(regcount < mapped_entries) {
463 rr =
static_cast<mapped*
>(
reg(regcount++));
464 store_unsafe<mapped>(save, rr);
488 static const char *olddigest =
"MD5";
489 static const char *oldrealm =
"-";
491 linked_pointer<service::keynode> sp = cfg->
getList(
"registry");
498 value = sp->getPointer();
501 mapped_entries = atoi(value);
502 else if(!stricmp(key,
"digest")) {
504 String::upper((
char *)
digest);
506 else if(!stricmp(key,
"realm"))
507 realm = cfg->dup(value);
514 else if(!stricmp(key,
"expires"))
517 keysize = atoi(value);
528 if(!getuid() || !
realm)
529 fs.open(DEFAULT_CFGPATH
"/siprealm", fsys::RDONLY);
530 if(!is(fs) && !
realm)
531 fs.open(
"uuid", fsys::RDONLY);
533 memset(buffer, 0,
sizeof(buffer));
534 fs.read(buffer,
sizeof(buffer) - 1);
537 cp = strchr(buffer,
'\n');
541 cp = strchr(buffer,
':');
545 realm = cfg->dup(buffer);
553 memset(buffer, 0,
sizeof(buffer));
554 Random::uuid(buffer);
555 String::add(buffer,
sizeof(buffer),
":");
556 String::add(buffer,
sizeof(buffer),
digest);
557 fs.open(
"uuid", 0440, fsys::WRONLY);
559 fs.write(buffer,
sizeof(buffer));
562 cp = strchr(buffer,
':');
565 realm = cfg->dup(buffer);
570 if(!String::equal(
realm, oldrealm)) {
572 shell::log(shell::NOTIFY,
"new realm %s",
realm);
574 }
else if(!String::equal(
digest, olddigest)) {
575 shell::log(shell::INFO,
"digest changed to %s",
digest);
602 memset(publishing, 0,
sizeof(
LinkedObject *) * keysize);
608 return mapped_entries;
613 assert(
id != NULL && *
id != 0);
616 unsigned path = NamedObject::keyindex(
id, keysize);
632 freelist = rr->getNext();
634 else if(allocated_entries < mapped_entries)
654 leaf = node->leaf(
"extension");
655 if(leaf && leaf->getPointer())
656 ext = atoi(leaf->getPointer());
662 leaf = node->leaf(
"display");
663 if(leaf && leaf->getPointer())
664 String::set(rr->
display,
sizeof(rr->
display), leaf->getPointer());
670 rr->enlist(&keys[path]);
680 assert(
id != NULL && *
id != 0);
682 mapped *rr = NULL, *prior;
683 unsigned path = NamedObject::keyindex(
id, keysize);
684 linked_pointer<service::keynode> rp;
687 const char *cp =
"none";
688 const char *cos =
"none";
705 freelist = rr->getNext();
706 }
else if(allocated_entries < mapped_entries)
732 if(!stricmp(cp,
"admin") || !stricmp(cp,
"user"))
734 else if(!stricmp(cp,
"refer"))
736 else if(!stricmp(cp,
"reject"))
738 else if(!stricmp(cp,
"gateway"))
740 else if(!stricmp(cp,
"service") || !stricmp(cp,
"device"))
744 if(listed && rr->
inuse)
747 rr->delist(&keys[path]);
751 rr->enlist(&freelist);
757 rp = node->leaf(
"contacts");
762 if(!stricmp(rp->getId(),
"contact") && rp->getPointer())
768 rp = node->leaf(
"published");
770 node->leaf(
"publish");
772 if(is(rp) && rp->getPointer())
775 if(is(rp) && !rp->getPointer() && !rp->getFirst())
782 if(!stricmp(rp->getId(),
"contact") && rp->getPointer())
787 rp = node->leaf(
"display");
788 if(is(rp) && rp->getPointer())
793 rp = node->leaf(
"routes");
799 unsigned priority = 0;
800 linked_pointer<service::keynode>
route;
803 if(!stricmp(rp->getId(),
"route"))
804 route = rp->getFirst();
806 const char *
id = route->getId();
807 const char *
value = route->getPointer();
809 if(
id && value && !stricmp(
id,
"pattern"))
811 else if(
id && value && !stricmp(
id,
"priority"))
812 priority = atoi(value);
813 else if(
id && value && !stricmp(
id,
"prefix"))
815 else if(
id && value && !stricmp(
id,
"suffix"))
820 rr->
addRoute(pattern, priority, prefix, suffix);
823 leaf = node->leaf(
"extension");
824 if(leaf && leaf->getPointer())
825 ext = atoi(leaf->getPointer());
829 leaf = node->leaf(
"profile");
846 rr->enlist(&keys[path]);
851 if(prior && prior != rr) {
852 shell::log(shell::INFO,
"releasing %s from extension %d", prior->userid, ext);
857 shell::log(shell::INFO,
"activating %s; extension=%d", rr->
userid, ext);
871 assert(addr != NULL);
874 linked_pointer<target::indexing> ind;
876 unsigned path = Socket::keyindex(addr, keysize);
882 ind = addresses[path];
885 target = ind->getTarget();
886 if(target && target->
expires > now && Socket::equal(addr, ind->address)) {
900 assert(uri != NULL && *uri != 0);
903 const struct sockaddr *addr = NULL;
904 Socket::address *
target = NULL;
908 if(!strnicmp(uri,
"sip:", 4))
910 else if(!strnicmp(uri,
"sips:", 5))
913 String::set(buffer,
sizeof(buffer), uri);
914 cp = strchr(buffer,
'@');
917 if(strchr(uri,
'@')) {
920 addr = target->getAddr();
934 assert(addr != NULL);
935 assert(uid != NULL && *uid != 0);
938 linked_pointer<route> rp;
939 unsigned path = NamedObject::keyindex(uid, keysize);
943 if(!stricmp(uid, rp->entry.text) && Socket::equal(addr, (
struct sockaddr *)(&rp->entry.registry->contact)))
952 rr = rp->entry.registry;
958 assert(
id != NULL && *
id != 0);
966 if(strchr(
id,
'@') || strchr(
id,
':'))
974 assert(
id != NULL && *
id != 0);
976 unsigned ext = atoi(
id);
979 if(*id < '0' || *id >
'9')
995 assert(
id != NULL && *
id != 0);
997 linked_pointer<pattern> pp;
1019 assert(
id != NULL && *
id != 0);
1021 unsigned ext = atoi(
id);
1057 assert(
id != NULL && *
id != 0);
1083 assert(
id != NULL && *
id != 0);
1115 assert(!isnull(target_addr));
1116 assert(target_contact != NULL && *target_contact != 0);
1118 Socket::address *origin = NULL;
1119 const struct sockaddr *ai, *oi = NULL;
1120 linked_pointer<target> tp;
1122 bool creating =
false;
1124 ai = target_addr.getAddr();
1131 len = Socket::len(ai);
1133 locking.exclusive();
1134 tp =
source.internal.targets;
1135 while(is(tp) &&
count > 1) {
1144 tp->enlist(&
source.internal.targets);
1145 tp->context = context;
1148 tp->address.address.sa_family = 0;
1151 expires = tp->expires = lease;
1152 if(!Socket::equal((
struct sockaddr *)(&tp->address), ai)) {
1153 if(tp->index.address) {
1154 tp->index.delist(&addresses[Socket::keyindex(tp->index.address, keysize)]);
1155 tp->index.address = NULL;
1156 tp->index.registry = NULL;
1162 oi = origin->getAddr();
1165 memcpy(&tp->address, ai, len);
1168 tp->index.registry =
this;
1169 tp->index.address = (
struct sockaddr *)(&tp->address);
1170 tp->index.enlist(&addresses[Socket::keyindex(tp->index.address, keysize)]);
1175 tp->context = context;
1176 Socket::store(&tp->peering, target_peering);
1177 String::set(tp->network,
sizeof(tp->network), target_network);
1178 String::set(tp->contact,
sizeof(tp->contact), target_contact);
1187 assert(route_pattern != NULL && *route_pattern != 0);
1189 locking.exclusive();
1202 rp->
entry.enlist(&primap[route_priority]);
1203 rp->enlist(&source.internal.routes);
1209 assert(published_id != NULL && *published_id != 0);
1211 unsigned path = NamedObject::keyindex(published_id, keysize);
1212 locking.exclusive();
1217 rp->
entry.enlist(&publishing[path]);
1218 rp->enlist(&source.internal.published);
1225 assert(contact_id != NULL && *contact_id != 0);
1227 unsigned path = NamedObject::keyindex(contact_id, keysize);
1229 locking.exclusive();
1234 rp->
entry.enlist(&contacts[path]);
1235 rp->enlist(&source.internal.routes);
1241 linked_pointer<target> tp = source.internal.targets;
1246 unsigned total = 0, busy = 0, away = 0, dnd = 0, offline = 0;
1253 if(type == EXPIRED || !is(tp)) {
1254 offline = total = 1;
1256 else while(is(tp)) {
1271 if(offline == total) {
1275 else if(away + offline == total) {
1279 else if(away + dnd + offline == total) {
1283 else if(busy + dnd + offline + away == total) {
1295 shell::debug(3,
"update: %s changed to %s", userid, text);
1300 unsigned active_count = 0;
1302 linked_pointer<target> tp;
1309 tp = source.internal.targets;
1311 if(Socket::equal(saddr.getAddr(), (
struct sockaddr *)(&tp->address)))
1312 tp->expires = now - 10;
1313 else if(tp->expires >= now)
1319 Mutex::protect(
this);
1320 store_unsafe<registry::mapped>(save,
this);
1323 Mutex::release(
this);
1334 linked_pointer<target> tp;
1341 tp = source.internal.targets;
1343 if(Socket::equal(saddr.getAddr(), (
struct sockaddr *)(&tp->address))) {
1344 if(tp->status != changed) {
1359 linked_pointer<target> tp;
1366 tp = source.internal.targets;
1368 if(Socket::equal(saddr.getAddr(), (
struct sockaddr *)(&tp->address))) {
1372 uri::userid(target_contact, target_userid,
sizeof(target_userid));
1373 uri::userid(tp->contact, contact_userid,
sizeof(contact_userid));
1374 if(String::equal(target_userid, contact_userid)) {
1375 Mutex::protect(
this);
1378 Mutex::release(
this);
1379 tp->expires = lease;
1390 assert(!isnull(target_addr));
1391 assert(target_contact != NULL && *target_contact != 0);
1394 Socket::address *origin;
1395 const struct sockaddr *ai, *oi = NULL;
1396 linked_pointer<target> tp;
1401 ai = target_addr.getAddr();
1408 locking.exclusive();
1409 tp = source.internal.targets;
1413 len = Socket::len(ai);
1416 if(tp->expires < now)
1418 if(Socket::equal((
struct sockaddr *)(&tp->address), ai))
1423 if(expired && expired != *tp) {
1425 expired->
index.delist(&addresses[Socket::keyindex(expired->
index.
address, keysize)]);
1429 expired->delist(&source.internal.targets);
1433 if(tp->expires < now)
1435 tp->expires = lease;
1436 tp->context = context;
1437 Socket::store(&tp->peering, target_peering);
1438 String::set(tp->contact,
sizeof(tp->contact), target_contact);
1439 String::set(tp->network,
sizeof(tp->network), target_network);
1446 oi = origin->getAddr();
1452 expired->enlist(&source.internal.targets);
1455 String::set(network,
sizeof(network), target_network);
1456 uri::userid(target_contact, remote,
sizeof(remote));
1464 memcpy(&expired->
address, ai, len);
1465 Socket::store(&expired->
peering, target_peering);
1466 String::set(expired->
contact,
sizeof(expired->
contact), target_contact);
1467 String::set(expired->
network,
sizeof(expired->
network), target_network);
1470 expired->
index.enlist(&addresses[Socket::keyindex(expired->
index.
address, keysize)]);
1478 assert(!isnull(target_addr));
1481 struct addrinfo *al;
1482 linked_pointer<target> tp;
1485 al = target_addr.getList();
1489 locking.exclusive();
1498 tp = source.internal.targets;
1503 source.internal.targets = NULL;
1506 len = Socket::len(al->ai_addr);
1513 tp->peering = subnet->
iface;
1514 String::set(tp->network,
sizeof(tp->network), subnet->
getId());
1518 String::set(tp->network,
sizeof(tp->network),
"*");
1521 String::set(network,
sizeof(network), tp->network);
1522 memcpy(&tp->address, al->ai_addr, len);
1523 memcpy(&
contact, &tp->address, len);
1528 tp->context = context;
1530 tp->enlist(&source.internal.targets);
1542 caddr_t cp = (caddr_t)
address;
1544 size_t offset = (size_t)(&tp->
address);
1551 return reinterpret_cast<target *
>(cp);
Some convenience methods for manipulating SIP uri's.
struct sockaddr_internet address
static bool remove(const char *id)
static stats * create(void)
Create stats in shared memory pool.
static bool userid(const char *sipuri, char *buffer, size_t size)
static const char * getDomain(void)
static Socket::address * getAddress(const char *uri, Socket::address *addr=NULL)
Pointer to a provisioned user xml subtree.
User profiles are used to map features and toll restriction level together under a common identifier...
void assign(stat_t element)
Assign a call to inbound or outbound statistic for this stat node.
static volatile dialmode_t dialmode
static unsigned getEntries(void)
bool expire(Socket::address &addr)
static void clear(mapped *rr)
unsigned setTargets(Socket::address &addr, voip::context_t context)
char prefix[MAX_USERID_SIZE]
static stack::subnet * getPolicy(const struct sockaddr *addr)
void addRoute(const char *pat, unsigned pri, const char *prefix, const char *suffix)
Representation of a mapped active user record.
sockaddr_internet contact
keynode * getList(const char *path)
sipwitch::registry::target::indexing index
static unsigned cleanup(time_t period)
static unsigned sip_prefix
bool is_profiled(void) const
void reload(service *cfg)
void operator=(mapped *ptr)
union sipwitch::MappedRegistry::@6 source
unsigned addTarget(Socket::address &via, time_t expires, const char *contact, const char *policy, struct sockaddr *peer, voip::context_t context)
static unsigned getIndex(mapped *rr)
struct sockaddr_storage peering
static unsigned allocate(void)
static const char * sip_realm
struct sockaddr_storage iface
static mapped * contact(const char *uri)
static bool isUserid(const char *id)
static void published(struct sockaddr_storage *peer)
static void expire(mapped *rr)
static char session_uuid[40]
char contact[MAX_URI_SIZE]
static bool match(const char *digits, const char *pattern, bool partial)
struct sipwitch::MappedRegistry::@6::@8 internal
static void release(stack::subnet *access)
static bool is_configured(void)
static mapped * address(const struct sockaddr *addr)
char network[MAX_NETWORK_SIZE]
void release(stat_t element)
Release a call from inbound or outbound stastic for this stat node.
static void incUse(mapped *rr, stats::stat_t stat)
static bool isExtension(const char *id)
static void detach(mapped *m)
struct sipwitch::MappedRegistry::@6::@7 external
void addPublished(const char *id)
static pattern * getRouting(unsigned trs, const char *id)
static bool exists(const char *id)
static void getProvision(const char *id, usernode &user)
static mapped * getExtension(const char *id)
static char * sipAddress(struct sockaddr_internet *addr, char *buf, const char *user=NULL, size_t size=MAX_URI_SIZE)
static voip::context_t out_context
static void release(void)
Release stat nodes shared memory segment.
bool refresh(Socket::address &addr, time_t expires, const char *target_contact)
char text[MAX_USERID_SIZE]
unsigned setTarget(Socket::address &via, time_t expires, const char *contact, const char *policy, struct sockaddr *peer, voip::context_t context)
static mapped * find(const char *id)
static mapped * access(const char *id)
System configuration instance and service functions.
void addContact(const char *id)
char suffix[MAX_USERID_SIZE]
static void expire(MappedRegistry *rr)
static void decUse(mapped *rr, stats::stat_t stat)
static unsigned sip_range
static mapped * dialing(const char *id)
static mapped * allocate(const char *id)
struct sockaddr * address
static profile_t * getProfile(const char *id)
static const char * env(const char *id)
Return the value of a server environment variable.
treemap< char * > keynode
Definition of a xml node.
enum sipwitch::MappedRegistry::@5 type
static mapped * invite(const char *id, stats::stat_t stat)