![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3_services.c File Reference
Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)
Definition in file sip3_services.c.
#include "asterisk.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/udptl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/acl.h"
#include "asterisk/srv.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
#include "sip3.h"
#include "sip3funcs.h"
Include dependency graph for sip3_services.c:

Go to the source code of this file.
Functions | |
| static int | __sip_do_register (struct sip_registry *r) |
| Register with SIP proxy. | |
| static void | build_callid_registry (struct sip_registry *reg, struct in_addr ourip, const char *fromdomain) |
| Build SIP Call-ID value for a REGISTER transaction. | |
| int | handle_response_register (struct sip_dialog *p, int resp, char *rest, struct sip_request *req, int seqno) |
| Handle responses on REGISTER to services. | |
| char * | regstate2str (enum sipregistrystate regstate) |
| Convert registration state status to string. | |
| static int | sip_reg_timeout (void *data) |
| Registration timeout, register again. | |
| int | sip_register (char *value, int lineno, struct sip_device *peer) |
| Parse register=> line in sip.conf and add to registry. | |
| void | sip_registry_destroy (struct sip_registry *reg) |
| Destroy registry object Objects created with the register= statement in static configuration. | |
| static int | sip_reregister (void *data) |
| Update registration with SIP Proxy. | |
| void | sip_send_all_registers (void) |
| Send all known registrations. | |
| int | transmit_register (struct sip_registry *r, int sipmethod, const char *auth, const char *authheader) |
| Transmit register to SIP proxy or UA. | |
Variables | |
| sip_register_list | regl |
| The register list: Other SIP proxys we register with and place calls to. | |
|
|
Register with SIP proxy.
Definition at line 298 of file sip3_services.c. References SIP_REGISTER, and transmit_register(). 00299 { 00300 int res; 00301 00302 res = transmit_register(r, SIP_REGISTER, NULL, NULL); 00303 return res; 00304 }
|
|
||||||||||||||||
|
Build SIP Call-ID value for a REGISTER transaction.
Definition at line 126 of file sip3_services.c. References ast_inet_ntoa(), ast_string_field_build, generate_random_string(), and S_OR. 00127 { 00128 char buf[33]; 00129 00130 const char *host = S_OR(fromdomain, ast_inet_ntoa(ourip)); 00131 00132 ast_string_field_build(reg, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 00133 }
|
|
||||||||||||||||||||||||
|
Handle responses on REGISTER to services.
Definition at line 556 of file sip3_services.c. References __get_header(), ast_log(), ast_sched_del(), ast_set_flag, ast_strlen_zero(), sip_dialog::authtries, sip_registry::call, DEFAULT_TRANS_TIMEOUT, do_register_auth(), EVENT_FLAG_SYSTEM, sip_registry::expire, sip_registry::expiry, expiry, sip_dialog::flags, get_header(), global, sip_dialog::initreq, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_event, MAX_AUTHTRIES, option_debug, REG_STATE_REGISTERED, REG_STATE_REJECTED, REG_STATE_UNREGISTERED, sip_registry::regattempts, sip_globals::regattempts_max, sip_dialog::registry, sip_registry::regstate, regstate2str(), sip_registry::regtime, SIP_NEEDDESTROY, SIP_REGISTER, sip_scheddestroy(), sip_registry::timeout, and transmit_register(). 00557 { 00558 int expires, expires_ms; 00559 struct sip_registry *r; 00560 r = p->registry; 00561 00562 switch (resp) { 00563 case 401: /* Unauthorized */ 00564 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 00565 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s@%s' (Tries %d)\n", p->registry->username, p->registry->hostname, p->authtries); 00566 ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 00567 } 00568 break; 00569 case 403: /* Forbidden */ 00570 ast_log(LOG_WARNING, "Forbidden - wrong password on authentication for REGISTER for '%s' to '%s'\n", p->registry->username, p->registry->hostname); 00571 if (global.regattempts_max) 00572 p->registry->regattempts = global.regattempts_max+1; 00573 ast_sched_del(sched, r->timeout); 00574 ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 00575 break; 00576 case 404: /* Not found */ 00577 ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username, p->registry->hostname); 00578 if (global.regattempts_max) 00579 p->registry->regattempts = global.regattempts_max+1; 00580 ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 00581 r->call = NULL; 00582 ast_sched_del(sched, r->timeout); 00583 break; 00584 case 407: /* Proxy auth */ 00585 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 00586 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s' (tries '%d')\n", get_header(p->initreq, "From"), p->authtries); 00587 ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 00588 } 00589 break; 00590 case 423: /* Interval too brief */ 00591 r->expiry = atoi(get_header(req, "Min-Expires")); 00592 ast_log(LOG_WARNING, "Got 423 Interval too brief for service %s@%s, minimum is %d seconds\n", p->registry->username, p->registry->hostname, r->expiry); 00593 ast_sched_del(sched, r->timeout); 00594 r->timeout = -1; 00595 if (r->call) { 00596 r->call = NULL; 00597 ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 00598 } 00599 if (r->expiry > expiry.max_expiry) { 00600 ast_log(LOG_WARNING, "Required expiration time from %s@%s is too high, giving up\n", p->registry->username, p->registry->hostname); 00601 r->expiry = expiry.default_expiry; 00602 r->regstate = REG_STATE_REJECTED; 00603 } else { 00604 r->regstate = REG_STATE_UNREGISTERED; 00605 transmit_register(r, SIP_REGISTER, NULL, NULL); 00606 } 00607 manager_event(EVENT_FLAG_SYSTEM, "Registry", "Channel: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate)); 00608 break; 00609 case 479: /* SER: Not able to process the URI - address is wrong in register*/ 00610 ast_log(LOG_WARNING, "Got error 479 on register to %s@%s, giving up (check config)\n", p->registry->username,p->registry->hostname); 00611 if (global.regattempts_max) 00612 p->registry->regattempts = global.regattempts_max+1; 00613 ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 00614 r->call = NULL; 00615 ast_sched_del(sched, r->timeout); 00616 break; 00617 case 200: /* 200 OK */ 00618 p->authtries = 0; 00619 if (!r) { 00620 ast_log(LOG_WARNING, "Got 200 OK on REGISTER that isn't a register\n"); 00621 ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 00622 return 0; 00623 } 00624 00625 r->regstate = REG_STATE_REGISTERED; 00626 r->regtime = time(NULL); /* Reset time of last succesful registration */ 00627 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: SIP\r\nDomain: %s\r\nStatus: %s\r\n", r->hostname, regstate2str(r->regstate)); 00628 r->regattempts = 0; 00629 if (option_debug) 00630 ast_log(LOG_DEBUG, "Registration successful\n"); 00631 if (r->timeout > -1) { 00632 if (option_debug) 00633 ast_log(LOG_DEBUG, "Cancelling timeout %d\n", r->timeout); 00634 ast_sched_del(sched, r->timeout); 00635 } 00636 r->timeout=-1; 00637 r->call = NULL; 00638 p->registry = NULL; 00639 /* Let this one hang around until we have all the responses */ 00640 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 00641 /* ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); */ 00642 00643 /* set us up for re-registering */ 00644 /* figure out how long we got registered for */ 00645 if (r->expire > -1) 00646 ast_sched_del(sched, r->expire); 00647 /* according to section 6.13 of RFC, contact headers override 00648 expires headers, so check those first */ 00649 expires = 0; 00650 00651 /* XXX todo: try to save the extra call */ 00652 if (!ast_strlen_zero(get_header(req, "Contact"))) { 00653 const char *contact = NULL; 00654 const char *tmptmp = NULL; 00655 int start = 0; 00656 for(;;) { 00657 contact = __get_header(req, "Contact", &start); 00658 /* this loop ensures we get a contact header about our register request */ 00659 if(!ast_strlen_zero(contact)) { 00660 if( (tmptmp=strstr(contact, p->our_contact))) { 00661 contact=tmptmp; 00662 break; 00663 } 00664 } else 00665 break; 00666 } 00667 tmptmp = strcasestr(contact, "expires="); 00668 if (tmptmp) { 00669 if (sscanf(tmptmp + 8, "%d;", &expires) != 1) 00670 expires = 0; 00671 } 00672 00673 } 00674 if (!expires) 00675 expires = atoi(get_header(req, "expires")); 00676 if (!expires) 00677 expires = expiry.default_expiry; 00678 00679 expires_ms = expires * 1000; 00680 if (expires <= EXPIRY_GUARD_LIMIT) 00681 expires_ms -= MAX((expires_ms * EXPIRY_GUARD_PCT),EXPIRY_GUARD_MIN); 00682 else 00683 expires_ms -= EXPIRY_GUARD_SECS * 1000; 00684 if (sipdebug) 00685 ast_log(LOG_NOTICE, "Outbound Registration: Expiry for %s is %d sec (Scheduling reregistration in %d s)\n", r->hostname, expires, expires_ms/1000); 00686 00687 r->refresh= (int) expires_ms / 1000; 00688 00689 /* Schedule re-registration before we expire */ 00690 r->expire = ast_sched_add(sched, expires_ms, sip_reregister, r); 00691 ASTOBJ_UNREF(r, sip_registry_destroy); 00692 } 00693 return 1; 00694 }
|
|
|
Convert registration state status to string.
Definition at line 101 of file sip3_services.c. References REG_STATE_AUTHSENT, REG_STATE_FAILED, REG_STATE_NOAUTH, REG_STATE_REGISTERED, REG_STATE_REGSENT, REG_STATE_REJECTED, REG_STATE_TIMEOUT, and REG_STATE_UNREGISTERED. 00102 { 00103 switch(regstate) { 00104 case REG_STATE_FAILED: 00105 return "Failed"; 00106 case REG_STATE_UNREGISTERED: 00107 return "Unregistered"; 00108 case REG_STATE_REGSENT: 00109 return "Request Sent"; 00110 case REG_STATE_AUTHSENT: 00111 return "Auth. Sent"; 00112 case REG_STATE_REGISTERED: 00113 return "Registered"; 00114 case REG_STATE_REJECTED: 00115 return "Rejected"; 00116 case REG_STATE_TIMEOUT: 00117 return "Timeout"; 00118 case REG_STATE_NOAUTH: 00119 return "No Authentication"; 00120 default: 00121 return "Unknown"; 00122 } 00123 }
|
|
|
Registration timeout, register again.
Definition at line 330 of file sip3_services.c. References __sip_pretend_ack(), ast_log(), ast_set_flag, ASTOBJ_REF, ASTOBJ_UNREF, sip_registry::call, EVENT_FLAG_SYSTEM, sip_dialog::flags, global, LOG_NOTICE, manager_event, REG_STATE_FAILED, REG_STATE_UNREGISTERED, sip_registry::regattempts, sip_globals::regattempts_max, sip_dialog::registry, sip_registry::regstate, regstate2str(), SIP_NEEDDESTROY, SIP_REGISTER, sip_registry_destroy(), sip_registry::timeout, and transmit_register(). 00331 { 00332 00333 /* if we are here, our registration timed out, so we'll just do it over */ 00334 struct sip_registry *r = ASTOBJ_REF((struct sip_registry *) data); 00335 struct sip_dialog *p; 00336 int res; 00337 00338 /* if we couldn't get a reference to the registry object, punt */ 00339 if (!r) 00340 return 0; 00341 00342 ast_log(LOG_NOTICE, " -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts); 00343 if (r->call) { 00344 /* Unlink us, destroy old call. Locking is not relevant here because all this happens 00345 in the single SIP manager thread. */ 00346 p = r->call; 00347 if (p->registry) 00348 ASTOBJ_UNREF(p->registry, sip_registry_destroy); 00349 r->call = NULL; 00350 ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 00351 /* Pretend to ACK anything just in case */ 00352 __sip_pretend_ack(p); /* XXX we need p locked, not sure we have */ 00353 } 00354 /* If we have a limit, stop registration and give up */ 00355 if (global.regattempts_max && (r->regattempts > global.regattempts_max)) { 00356 /* Ok, enough is enough. Don't try any more */ 00357 /* We could add an external notification here... 00358 steal it from app_voicemail :-) */ 00359 ast_log(LOG_NOTICE, " -- Giving up forever trying to register '%s@%s'\n", r->username, r->hostname); 00360 r->regstate = REG_STATE_FAILED; 00361 } else { 00362 r->regstate = REG_STATE_UNREGISTERED; 00363 r->timeout = -1; 00364 res = transmit_register(r, SIP_REGISTER, NULL, NULL); 00365 } 00366 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate)); 00367 ASTOBJ_UNREF(r, sip_registry_destroy); 00368 return 0; 00369 }
|
|
||||||||||||||||
|
Parse register=> line in sip.conf and add to registry.
Definition at line 161 of file sip3_services.c. References ast_calloc, ast_log(), ast_string_field_build, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ASTOBJ_CONTAINER_LINK, ASTOBJ_INIT, ASTOBJ_UNREF, expiry, sip_device::extra, FALSE, free, generate_random_string(), hostname, INITIAL_CSEQ, LOG_ERROR, LOG_WARNING, sip_registry::peer, REG_MAGICMARKER, sip_device::registry, channel_counters::registry_objects, regl, secret, sip_registry_destroy(), sipcounters, sipdebug, and sip_device_extra::tohost. 00162 { 00163 struct sip_registry *reg; 00164 char username[256] = ""; 00165 char randomcontact[256]; 00166 char *hostname = NULL, *secret = NULL, *authuser = NULL; 00167 char *porta = NULL; 00168 char *contact = NULL; 00169 char *extension = NULL; 00170 int portnum = 0; 00171 00172 if (peer != NULL) { /* Build registration string from peer info */ 00173 /* Need to copy port number as well */ 00174 if (ast_strlen_zero(peer->extra.fromuser)) 00175 snprintf(username, sizeof(username), "%s:%s@%s/%s", 00176 peer->name, peer->secret, peer->extra.tohost, peer->extra.regexten); 00177 else 00178 snprintf(username, sizeof(username), "%s:%s:%s@%s/%s", 00179 peer->name, peer->secret, peer->extra.fromuser, peer->extra.tohost, peer->extra.regexten); 00180 } else if (value) 00181 ast_copy_string(username, value, sizeof(username)); 00182 else 00183 username[0] = '\0'; 00184 00185 00186 /* ------ Parse registration string ----------- */ 00187 /* First split around the last '@' then parse the two components. */ 00188 hostname = strrchr(username, '@'); /* allow @ in the first part */ 00189 if (hostname) 00190 *hostname++ = '\0'; 00191 if (ast_strlen_zero(username) || ast_strlen_zero(hostname)) { 00192 ast_log(LOG_WARNING, "Format for registration is user[:secret[:authuser]]@host[:port][/contact] at line %d\n", lineno); 00193 return -1; 00194 } 00195 /* split user[:secret[:authuser]] */ 00196 secret = strchr(username, ':'); 00197 if (secret) { 00198 *secret++ = '\0'; 00199 authuser = strchr(secret, ':'); 00200 if (authuser) 00201 *authuser++ = '\0'; 00202 } 00203 /* split host[:port][/contact] */ 00204 contact = strchr(hostname, '/'); 00205 if (contact) 00206 *contact++ = '\0'; 00207 if (ast_strlen_zero(contact)) 00208 contact = "s"; 00209 porta = strchr(hostname, ':'); 00210 if (porta) { 00211 *porta++ = '\0'; 00212 portnum = atoi(porta); 00213 if (portnum == 0) { 00214 ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); 00215 return -1; 00216 } 00217 } 00218 00219 /* Allocate data */ 00220 if (!(reg = ast_calloc(1, sizeof(*reg)))) { 00221 ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n"); 00222 return -1; 00223 } 00224 00225 if (ast_string_field_init(reg, 256)) { 00226 ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry strings\n"); 00227 free(reg); 00228 return -1; 00229 } 00230 00231 if (peer) { 00232 reg->peer = peer; 00233 peer->registry = reg; 00234 // xxx?? ASTOBJ_REF(peer); /* Add reference counter to peer */ 00235 } 00236 00237 sipcounters.registry_objects++; 00238 ASTOBJ_INIT(reg); 00239 if (username) 00240 ast_string_field_set(reg, username, username); 00241 if (hostname) 00242 ast_string_field_set(reg, hostname, hostname); 00243 if (authuser) 00244 ast_string_field_set(reg, authuser, authuser); 00245 if (secret) 00246 ast_string_field_set(reg, secret, secret); 00247 00248 if (extension) 00249 ast_string_field_set(reg, extension, extension); 00250 /* Build a random contact string for this registration entry */ 00251 generate_random_string(randomcontact, sizeof(randomcontact)); 00252 if (sipdebug) 00253 ast_string_field_build(reg, contact, "%s-%s-%s-debug", REG_MAGICMARKER, randomcontact, extension); 00254 else 00255 ast_string_field_build(reg, contact, "%s-%s", REG_MAGICMARKER, randomcontact); 00256 00257 reg->expire = -1; 00258 reg->expiry = expiry.default_expiry; 00259 reg->timeout = -1; 00260 reg->refresh = expiry.default_expiry; 00261 reg->portno = porta ? atoi(porta) : 0; 00262 reg->callid_valid = FALSE; 00263 reg->ocseq = INITIAL_CSEQ; 00264 ASTOBJ_CONTAINER_LINK(®l, reg); /* Add the new registry entry to the list */ 00265 ASTOBJ_UNREF(reg,sip_registry_destroy); 00266 return 0; 00267 }
|
|
|
Destroy registry object Objects created with the register= statement in static configuration.
Definition at line 271 of file sip3_services.c. References ast_log(), ast_sched_del(), ast_string_field_free_pools, sip_registry::call, sip_registry::expire, free, LOG_DEBUG, option_debug, sip_registry::peer, sip_pvt::registry, sip_device::registry, channel_counters::registry_objects, sip_destroy(), sipcounters, and sip_registry::timeout. 00272 { 00273 /* Really delete */ 00274 if (option_debug > 2) 00275 ast_log(LOG_DEBUG, "Destroying registry entry for %s@%s\n", reg->username, reg->hostname); 00276 00277 if (reg->call) { 00278 /* Clear registry before destroying to ensure 00279 we don't get reentered trying to grab the registry lock */ 00280 reg->call->registry = NULL; 00281 if (option_debug > 2) 00282 ast_log(LOG_DEBUG, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname); 00283 sip_destroy(reg->call); 00284 } 00285 if (reg->expire > -1) 00286 ast_sched_del(sched, reg->expire); 00287 if (reg->timeout > -1) 00288 ast_sched_del(sched, reg->timeout); 00289 if (reg->peer) 00290 reg->peer->registry = NULL; /* XXX ASTOBJ_UNREF ??? */ 00291 ast_string_field_free_pools(reg); 00292 sipcounters.registry_objects--; 00293 free(reg); 00294 00295 }
|
|
|
Update registration with SIP Proxy.
Definition at line 307 of file sip3_services.c. References __sip_do_register(), append_history, ast_log(), ast_test_flag, ASTOBJ_REF, ASTOBJ_UNREF, sip_registry::call, sip_registry::expire, sip_pvt::flags, LOG_NOTICE, SIP_NO_HISTORY, sip_registry_destroy(), and sipdebug. 00308 { 00309 /* if we are here, we know that we need to reregister. */ 00310 struct sip_registry *r= ASTOBJ_REF((struct sip_registry *) data); 00311 00312 /* if we couldn't get a reference to the registry object, punt */ 00313 if (!r) 00314 return 0; 00315 00316 if (r->call && !ast_test_flag(&r->call->flags[0], SIP_NO_HISTORY)) 00317 append_history(r->call, "RegistryRenew", "Account: %s@%s", r->username, r->hostname); 00318 /* Since registry's are only added/removed by the the monitor thread, this 00319 may be overkill to reference/dereference at all here */ 00320 if (sipdebug) 00321 ast_log(LOG_NOTICE, " -- Re-registration for %s@%s\n", r->username, r->hostname); 00322 00323 r->expire = -1; 00324 __sip_do_register(r); 00325 ASTOBJ_UNREF(r, sip_registry_destroy); 00326 return 0; 00327 }
|
|
|
Send all known registrations.
Definition at line 139 of file sip3_services.c. References ast_sched_add(), ast_sched_del(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, expiry, channel_counters::registry_objects, regl, sip_reregister(), and sipcounters. 00140 { 00141 int ms; 00142 int regspacing; 00143 if (!sipcounters.registry_objects) 00144 return; 00145 regspacing = expiry.default_expiry * 1000/sipcounters.registry_objects; 00146 if (regspacing > 100) 00147 regspacing = 100; 00148 ms = regspacing; 00149 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 00150 ASTOBJ_WRLOCK(iterator); 00151 if (iterator->expire > -1) 00152 ast_sched_del(sched, iterator->expire); 00153 ms += regspacing; 00154 iterator->expire = ast_sched_add(sched, ms, sip_reregister, iterator); 00155 ASTOBJ_UNLOCK(iterator); 00156 } while (0) 00157 ); 00158 }
|
|
||||||||||||||||||||
|
Transmit register to SIP proxy or UA.
Definition at line 372 of file sip3_services.c. References sip_network::__ourip, add_header(), add_header_contentLength(), append_history, append_maxforwards(), ast_log(), ast_sched_add(), ast_sched_del(), ast_set_flag, ast_string_field_free, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose(), ASTOBJ_REF, sip_network::bindaddr, build_callid_registry(), build_contact(), build_reply_digest(), build_via(), sip_registry::call, sip_registry::callid_valid, create_addr(), sip_globals::default_fromdomain, sip_registry::expiry, exten, sip_device::extra, sip_dialog::flags, sip_request::from, global, sip_request::headers, init_req(), initialize_initreq(), sip_dialog::initreq, sip_request::lines, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, make_our_tag(), sip_dialog::noncecount, sip_registry::noncecount, sip_registry::ocseq, sip_dialog::ocseq, option_debug, sip_registry::peer, sip_registry::portno, REG_STATE_AUTHSENT, REG_STATE_REGSENT, sip_globals::reg_timeout, sip_registry::regattempts, sip_pvt::registry, sip_registry::regstate, S_OR, send_request(), sip_request::seqno, sip_alloc(), sip_debug_test_pvt(), sip_destroy(), SIP_MAX_PACKET, sip_method2txt(), SIP_NO_HISTORY, sip_ouraddrfor(), SIP_OUTGOING, sip_reg_timeout(), SIP_REGISTER, sipdebug, sipnet, siprequest_alloc(), sip_dialog::tag, sip_registry::timeout, sip_request::to, TRUE, sip_globals::useragent, and XMIT_CRITICAL. 00373 { 00374 struct sip_request *req; 00375 char from[256]; 00376 char to[256]; 00377 char tmp[80]; 00378 char addr[80]; 00379 struct sip_dialog *dialog; 00380 00381 req = siprequest_alloc(SIP_MAX_PACKET, &sipnet); 00382 00383 /* exit if we are already in process with this registrar ?*/ 00384 if ( r == NULL || ((auth==NULL) && (r->regstate==REG_STATE_REGSENT || r->regstate==REG_STATE_AUTHSENT))) { 00385 ast_log(LOG_NOTICE, "Strange, trying to register %s@%s when registration already pending\n", r->username, r->hostname); 00386 return 0; 00387 } 00388 00389 if (r->call) { /* We have a registration */ 00390 if (!auth) { 00391 ast_log(LOG_WARNING, "Already have a REGISTER going on to %s@%s?? \n", r->username, r->hostname); 00392 return 0; 00393 } else { 00394 dialog = r->call; 00395 make_our_tag(dialog->tag, sizeof(dialog->tag)); /* create a new local tag for every register attempt */ 00396 ast_string_field_free(dialog, theirtag); /* forget their old tag, so we don't match tags when getting response */ 00397 } 00398 } else { 00399 /* Build callid for registration if we haven't registered before */ 00400 if (!r->callid_valid) { 00401 build_callid_registry(r, sipnet.__ourip, global.default_fromdomain); 00402 r->callid_valid = TRUE; 00403 } 00404 /* Allocate SIP packet for registration */ 00405 if (!(dialog = sip_alloc( r->callid, NULL, 0, SIP_REGISTER))) { 00406 ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n"); 00407 return 0; 00408 } 00409 if (!ast_test_flag(&dialog->flags[0], SIP_NO_HISTORY)) 00410 append_history(dialog, "RegistryInit", "Account: %s@%s", r->username, r->hostname); 00411 /* Find address to hostname */ 00412 if (create_addr(dialog, NULL, r->hostname, NULL)) { 00413 /* we have what we hope is a temporary network error, 00414 * probably DNS. We need to reschedule a registration try */ 00415 sip_destroy(dialog); 00416 if (r->timeout > -1) { 00417 ast_sched_del(sched, r->timeout); 00418 r->timeout = ast_sched_add(sched, global.reg_timeout*1000, sip_reg_timeout, r); 00419 ast_log(LOG_WARNING, "Still have a registration timeout for %s@%s (create_addr() error), %d\n", r->username, r->hostname, r->timeout); 00420 } else { 00421 r->timeout = ast_sched_add(sched, global.reg_timeout*1000, sip_reg_timeout, r); 00422 ast_log(LOG_WARNING, "Probably a DNS error for registration to %s@%s, trying REGISTER again (after %d seconds)\n", r->username, r->hostname, global.reg_timeout); 00423 } 00424 r->regattempts++; 00425 return 0; 00426 } 00427 /* Copy back Call-ID in case create_addr changed it */ 00428 ast_string_field_set(r, callid, dialog->callid); 00429 if (r->portno) 00430 dialog->sa.sin_port = htons(r->portno); 00431 else /* Set registry port to the port set from the peer definition/srv or default */ 00432 r->portno = ntohs(dialog->sa.sin_port); 00433 ast_set_flag(&dialog->flags[0], SIP_OUTGOING); /* Registration is outgoing call */ 00434 r->call = dialog; /* Save pointer to SIP packet */ 00435 dialog->registry = ASTOBJ_REF(r); /* Add pointer to registry in packet */ 00436 if (!ast_strlen_zero(r->secret)) /* Secret (password) */ 00437 ast_string_field_set(dialog, peersecret, r->secret); 00438 if (!ast_strlen_zero(r->md5secret)) 00439 ast_string_field_set(dialog, peermd5secret, r->md5secret); 00440 /* User name in this realm 00441 - if authuser is set, use that, otherwise use username */ 00442 if (!ast_strlen_zero(r->authuser)) { 00443 ast_string_field_set(dialog, peername, r->authuser); 00444 ast_string_field_set(dialog, authname, r->authuser); 00445 } else if (!ast_strlen_zero(r->username)) { 00446 ast_string_field_set(dialog, peername, r->username); 00447 ast_string_field_set(dialog, authname, r->username); 00448 ast_string_field_set(dialog, fromuser, r->username); 00449 } 00450 if (!ast_strlen_zero(r->username)) 00451 ast_string_field_set(dialog, username, r->username); 00452 /* Save extension in packet */ 00453 00454 /* If we have a peer relationship, fetch som more data from taht peer. 00455 */ 00456 if (r->peer) { 00457 if (!ast_strlen_zero(r->peer->extra.fromdomain)) 00458 ast_string_field_set(dialog, fromdomain, r->peer->extra.fromdomain); 00459 } 00460 ast_string_field_set(dialog, exten, r->contact); 00461 00462 /* 00463 check which address we should use in our contact header 00464 based on whether the remote host is on the external or 00465 internal network so we can register through nat 00466 */ 00467 if (sip_ouraddrfor(&dialog->sa.sin_addr, &dialog->ourip)) 00468 dialog->ourip = sipnet.bindaddr.sin_addr; 00469 build_contact(dialog); 00470 } 00471 00472 /* set up a timeout */ 00473 if (auth == NULL) { 00474 if (r->timeout > -1) { 00475 ast_log(LOG_WARNING, "Still have a registration timeout, #%d - deleting it\n", r->timeout); 00476 ast_sched_del(sched, r->timeout); 00477 } 00478 r->timeout = ast_sched_add(sched, global.reg_timeout * 1000, sip_reg_timeout, r); 00479 if (option_debug) 00480 ast_log(LOG_DEBUG, "Scheduled a registration timeout for %s id #%d \n", r->hostname, r->timeout); 00481 } 00482 00483 if (strchr(r->username, '@')) { 00484 snprintf(from, sizeof(from), "<sip:%s>;tag=%s", r->username, dialog->tag); 00485 if (!ast_strlen_zero(dialog->theirtag)) 00486 snprintf(to, sizeof(to), "<sip:%s>;tag=%s", r->username, dialog->theirtag); 00487 else 00488 snprintf(to, sizeof(to), "<sip:%s>", r->username); 00489 } else { 00490 snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", r->username, dialog->tohost, dialog->tag); 00491 if (!ast_strlen_zero(dialog->theirtag)) 00492 snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%s", r->username, dialog->tohost, dialog->theirtag); 00493 else 00494 snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, dialog->tohost); 00495 } 00496 00497 /* Fromdomain is what we are registering to, regardless of actual 00498 host name from SRV */ 00499 snprintf(addr, sizeof(addr), "sip:%s", S_OR(dialog->fromdomain, r->hostname)); 00500 ast_string_field_set(dialog, uri, addr); 00501 00502 init_req(req, sipmethod, addr); 00503 00504 /* Add to CSEQ */ 00505 snprintf(tmp, sizeof(tmp), "%u %s", ++r->ocseq, sip_method2txt(sipmethod)); 00506 req->seqno = dialog->ocseq = r->ocseq; 00507 build_via(dialog, TRUE); 00508 add_header(req, "Via", dialog->via); 00509 add_header(req, "From", from); 00510 add_header(req, "To", to); 00511 add_header(req, "Call-ID", dialog->callid); 00512 add_header(req, "CSeq", tmp); 00513 add_header(req, "User-Agent", global.useragent); 00514 append_maxforwards(req); 00515 00516 if (auth) /* Add auth header */ 00517 add_header(req, authheader, auth); 00518 else if (!ast_strlen_zero(r->nonce)) { 00519 char digest[1024]; 00520 00521 /* We have auth data to reuse, build a digest header! */ 00522 if (sipdebug) 00523 ast_log(LOG_DEBUG, " >>> Re-using Auth data for %s@%s\n", r->username, r->hostname); 00524 ast_string_field_set(dialog, realm, r->realm); 00525 ast_string_field_set(dialog, nonce, r->nonce); 00526 ast_string_field_set(dialog, domain, r->domain); 00527 ast_string_field_set(dialog, opaque, r->opaque); 00528 ast_string_field_set(dialog, qop, r->qop); 00529 dialog->noncecount = r->noncecount++; 00530 00531 memset(digest, 0, sizeof(digest)); 00532 if(!build_reply_digest(dialog, sipmethod, digest, sizeof(digest))) 00533 add_header(req, "Authorization", digest); 00534 else 00535 ast_log(LOG_NOTICE, "No authorization available for authentication of registration to %s@%s\n", r->username, r->hostname); 00536 00537 } 00538 00539 snprintf(tmp, sizeof(tmp), "%d", r->expiry); 00540 add_header(req, "Expires", tmp); 00541 add_header(req, "Contact", dialog->our_contact); 00542 add_header(req, "Event", "registration"); 00543 add_header_contentLength(req, 0); 00544 00545 initialize_initreq(dialog, req); 00546 if (sip_debug_test_pvt(dialog)) 00547 ast_verbose("REGISTER %d headers, %d lines\n", dialog->initreq->headers, dialog->initreq->lines); 00548 r->regstate = auth ? REG_STATE_AUTHSENT : REG_STATE_REGSENT; 00549 r->regattempts++; /* Another attempt */ 00550 if (option_debug > 3) 00551 ast_verbose("REGISTER attempt %d to %s@%s\n", r->regattempts, r->username, r->hostname); 00552 return send_request(dialog, req, XMIT_CRITICAL); 00553 }
|
|
|
The register list: Other SIP proxys we register with and place calls to. Registration list Definition at line 98 of file sip3_services.c. |