Index: channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.866 diff -u -r1.866 chan_sip.c --- channels/chan_sip.c 26 Sep 2005 23:14:59 -0000 1.866 +++ channels/chan_sip.c 27 Sep 2005 03:50:50 -0000 @@ -552,6 +552,7 @@ #define SIP_PAGE2_RTUPDATE (1 << 1) #define SIP_PAGE2_RTAUTOCLEAR (1 << 2) #define SIP_PAGE2_RTIGNOREREGEXPIRE (1 << 3) +#define SIP_PAGE2_RT_FROMCONTACT (1 << 4) static int global_rtautoclear = 120; @@ -583,6 +584,7 @@ int sessionid; /* SDP Session ID */ int sessionversion; /* SDP Session Version */ struct sockaddr_in sa; /* Our peer */ + struct sockaddr_in defaddr; /* Our peer */ struct sockaddr_in redirip; /* Where our RTP should be going if not to us */ struct sockaddr_in vredirip; /* Where our Video RTP should be going if not to us */ int redircodecs; /* Redirect codecs */ @@ -620,6 +622,7 @@ char cid_name[256]; /* Caller*ID */ char via[256]; /* Via: header */ char fullcontact[128]; /* The Contact: that the UA registers with us */ + char rtfullcontact[128]; /* The last loaded fullcontact from realtime*/ char accountcode[AST_MAX_ACCOUNT_CODE]; /* Account code */ char our_contact[256]; /* Our contact header */ char realm[MAXHOSTNAMELEN]; /* Authorization realm */ @@ -727,6 +730,7 @@ char fromuser[80]; /* From: user when calling this peer */ char fromdomain[MAXHOSTNAMELEN]; /* From: domain when calling this peer */ char fullcontact[256]; /* Contact registred with us (not in sip.conf) */ + char rtfullcontact[128]; /* The last loaded fullcontact from realtime*/ char cid_num[80]; /* Caller ID num */ char cid_name[80]; /* Caller ID name */ int callingpres; /* Calling id presentation */ @@ -894,6 +898,7 @@ static void sip_dump_history(struct sip_pvt *dialog); /* Dump history to LOG_DEBUG at end of dialog, before destroying data */ static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype); static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate); +static void reg_source_db(struct sip_peer *peer); /* Definition of this channel for channel registration */ static const struct ast_channel_tech sip_tech = { @@ -1010,12 +1015,20 @@ int res; char iabuf[INET_ADDRSTRLEN]; - if (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE) + if (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE) { + if (!ntohs(p->recv.sin_port)) { + p->recv.sin_port = p->defaddr.sin_port; + } res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->recv, sizeof(struct sockaddr_in)); - else + } else { + if (!ntohs(p->sa.sin_port)) { + p->sa.sin_port = p->defaddr.sin_port; + } res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_in)); + } + if (res != len) { - ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s returned %d: %s\n", data, len, ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr), res, strerror(errno)); + ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr), res, ntohs(p->sa.sin_port), strerror(errno)); } return res; } @@ -1620,6 +1633,7 @@ struct ast_variable *var; struct ast_variable *tmp; char *newpeername = (char *) peername; + char *fullcontact = NULL; char iabuf[80]; /* First check on peer name */ @@ -1644,6 +1658,10 @@ } else if (!newpeername && !strcasecmp(tmp->name, "name")) { newpeername = tmp->value; } + if (!strcasecmp(tmp->name, "fullcontact")) { + fullcontact = ast_strdupa(tmp->value); + ast_uri_decode(fullcontact); + } tmp = tmp->next; } @@ -1654,12 +1672,17 @@ } /* Peer found in realtime, now build it in memory */ - peer = build_peer(newpeername, var, !ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS)); - - if (!peer) { + if ((peer = build_peer(newpeername, var, !ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS)))) { + if (fullcontact) { + ast_copy_string(peer->rtfullcontact, fullcontact, sizeof(peer->rtfullcontact)); + } + } else { ast_variables_destroy(var); return (struct sip_peer *) NULL; } + + ast_set_flag((&peer->flags_page2), SIP_PAGE2_RT_FROMCONTACT); + if (ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS)) { /* Cache peer */ ast_copy_flags((&peer->flags_page2),(&global_flags_page2), SIP_PAGE2_RTAUTOCLEAR|SIP_PAGE2_RTCACHEFRIENDS); @@ -1674,6 +1697,10 @@ ast_set_flag(peer, SIP_REALTIME); } ast_variables_destroy(var); + + if(fullcontact) { + reg_source_db(peer); + } return peer; } @@ -1787,6 +1814,9 @@ { char *callhost; + r->defaddr.sin_addr = peer->defaddr.sin_addr; + r->defaddr.sin_port = peer->defaddr.sin_port; + if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) && (!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) { if (peer->addr.sin_addr.s_addr) { @@ -4565,6 +4595,20 @@ if (!ast_strlen_zero(p->fullcontact)) { /* If we have full contact, trust it */ ast_build_string(&invite, &invite_max, "%s", p->fullcontact); + /* If we have RT full contact, trust it */ + } else if (!ast_strlen_zero(p->rtfullcontact)) { + char *ptr = p->rtfullcontact; + int x = 0; + while ((ptr = strchr(ptr, ':'))) { + ptr++; + x++; + if (x == 4) { + break; + } + } + if (ptr) { + ast_copy_string(invite, ptr, sizeof(invite)); + } } else { /* Otherwise, use the username while waiting for registration */ ast_build_string(&invite, &invite_max, "sip:"); @@ -5379,7 +5423,15 @@ struct sip_peer *peer = data; memset(&peer->addr, 0, sizeof(peer->addr)); - ast_db_del("SIP/Registry", peer->name); + + if (ast_test_flag(&(peer->flags_page2), SIP_PAGE2_RT_FROMCONTACT)) { + if (!ast_test_flag((&global_flags_page2), SIP_PAGE2_RTIGNOREREGEXPIRE)) { + ast_update_realtime("sippeers", "name", peer->name, "fullcontact", "", NULL); + } + } else { + ast_db_del("SIP/Registry", peer->name); + } + manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); register_peer_exten(peer, 0); peer->expire = -1; @@ -5412,8 +5464,13 @@ int port; char *scan, *addr, *port_str, *expiry_str, *username, *contact; - if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data))) - return; + if (ast_test_flag(&(peer->flags_page2), SIP_PAGE2_RT_FROMCONTACT)) { + if (!ast_strlen_zero(peer->rtfullcontact)) { + ast_copy_string(data, peer->rtfullcontact, sizeof(data)); + } + } else { + ast_db_get("SIP/Registry", peer->name, data, sizeof(data)); + } scan = data; addr = strsep(&scan, ":"); @@ -5592,7 +5649,15 @@ if (p->expire > -1) ast_sched_del(sched, p->expire); p->expire = -1; - ast_db_del("SIP/Registry", p->name); + + if (ast_test_flag(&(p->flags_page2), SIP_PAGE2_RT_FROMCONTACT)) { + if (!ast_test_flag((&global_flags_page2), SIP_PAGE2_RTIGNOREREGEXPIRE)) { + ast_update_realtime("sippeers", "name", p->name, "fullcontact", "", NULL); + } + } else { + ast_db_del("SIP/Registry", p->name); + } + register_peer_exten(p, 0); p->fullcontact[0] = '\0'; p->useragent[0] = '\0'; @@ -5605,6 +5670,11 @@ return PARSE_REGISTER_UPDATE; } ast_copy_string(p->fullcontact, c, sizeof(p->fullcontact)); + if (ast_test_flag((&global_flags_page2), SIP_PAGE2_RTUPDATE)) { + char buf[128]; + ast_uri_encode(c, buf, sizeof(buf), 1); + ast_update_realtime("sippeers", "name", p->name, "fullcontact", buf, NULL); + } /* For the 200 OK, we should use the received contact */ snprintf(pvt->our_contact, sizeof(pvt->our_contact) - 1, "<%s>", c); /* Make sure it's a SIP URL */ @@ -5665,8 +5735,13 @@ p->expire = -1; pvt->expiry = expiry; snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(iabuf, sizeof(iabuf), p->addr.sin_addr), ntohs(p->addr.sin_port), expiry, p->username, p->fullcontact); - if (!(ast_test_flag(p, SIP_REALTIME) && ast_test_flag((&p->flags_page2), SIP_PAGE2_RTCACHEFRIENDS))) + if (ast_test_flag((&p->flags_page2), SIP_PAGE2_RT_FROMCONTACT)) { + char buf[128]; + ast_uri_encode(data, buf, sizeof(buf), 1); + ast_update_realtime("sippeers", "name", p->name, "fullcontact", buf, NULL); + } else { ast_db_put("SIP/Registry", p->name, data); + } manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Registered\r\n", p->name); if (inaddrcmp(&p->addr, &oldsin)) { sip_poke_peer(p); @@ -6889,6 +6964,7 @@ if (!ast_strlen_zero(peer->cid_name) && !ast_strlen_zero(p->cid_name)) ast_copy_string(p->cid_name, peer->cid_name, sizeof(p->cid_name)); ast_copy_string(p->fullcontact, peer->fullcontact, sizeof(p->fullcontact)); + ast_copy_string(p->rtfullcontact, peer->rtfullcontact, sizeof(p->rtfullcontact)); if (!ast_strlen_zero(peer->context)) ast_copy_string(p->context, peer->context, sizeof(p->context)); ast_copy_string(p->peersecret, peer->secret, sizeof(p->peersecret)); @@ -7702,6 +7778,7 @@ ast_cli(fd, "%s\n",status); ast_cli(fd, " Useragent : %s\n", peer->useragent); ast_cli(fd, " Reg. Contact : %s\n", peer->fullcontact); + ast_cli(fd, " RT data : %s\n", peer->rtfullcontact); if (peer->chanvars) { ast_cli(fd, " Variables :\n"); for (v = peer->chanvars ; v ; v = v->next) @@ -11685,12 +11762,16 @@ continue; } - if (realtime && !strcasecmp(v->name, "regseconds")) { + if (!strcasecmp(v->name, "regseconds")) { if (sscanf(v->value, "%li", ®seconds) != 1) regseconds = 0; - } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) { + } else if (!strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) { inet_aton(v->value, &(peer->addr.sin_addr)); - } else if (realtime && !strcasecmp(v->name, "name")) + if (ast_test_flag((&global_flags_page2), SIP_PAGE2_RTIGNOREREGEXPIRE)) { + inet_aton(v->value, &(peer->defaddr.sin_addr)); + found++; + } + } else if (!strcasecmp(v->name, "name")) ast_copy_string(peer->name, v->value, sizeof(peer->name)); else if (!strcasecmp(v->name, "secret")) ast_copy_string(peer->secret, v->value, sizeof(peer->secret)); @@ -11840,12 +11921,13 @@ */ v=v->next; } - if (realtime && !ast_test_flag((&global_flags_page2), SIP_PAGE2_RTIGNOREREGEXPIRE) && ast_test_flag(peer, SIP_DYNAMIC)) { + if (!ast_test_flag((&global_flags_page2), SIP_PAGE2_RTIGNOREREGEXPIRE) && ast_test_flag(peer, SIP_DYNAMIC)) { time_t nowtime; time(&nowtime); if ((nowtime - regseconds) > 0) { memset(&peer->addr, 0, sizeof(peer->addr)); + ast_update_realtime("sippeers", "name", peer->name, "fullcontact", "", NULL); if (option_debug) ast_log(LOG_DEBUG, "Bah, we're expired (%ld/%ld/%ld)!\n", nowtime - regseconds, regseconds, nowtime); }