Index: channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.882 diff -u -r1.882 chan_sip.c --- channels/chan_sip.c 5 Oct 2005 01:40:01 -0000 1.882 +++ channels/chan_sip.c 5 Oct 2005 21:04:43 -0000 @@ -559,6 +559,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; @@ -590,6 +591,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 */ @@ -627,6 +629,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 *rpid; /* Our RPID header */ @@ -737,6 +740,7 @@ char fromuser[80]; /* From: user when calling this peer */ char fromdomain[MAXHOSTNAMELEN]; /* From: domain when calling this peer */ char fullcontact[256]; /* Contact registered 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 */ @@ -903,6 +907,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 = { @@ -1019,12 +1024,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; } @@ -1629,6 +1642,7 @@ struct ast_variable *var; struct ast_variable *tmp; char *newpeername = (char *) peername; + char *fullcontact = NULL; char iabuf[80]; /* First check on peer name */ @@ -1653,6 +1667,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; } @@ -1663,12 +1681,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); @@ -1683,6 +1706,10 @@ ast_set_flag(peer, SIP_REALTIME); } ast_variables_destroy(var); + + if(fullcontact) { + reg_source_db(peer); + } return peer; } @@ -1796,6 +1823,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) { @@ -4718,6 +4748,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:"); @@ -5542,7 +5586,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; @@ -5575,8 +5627,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, ":"); @@ -5755,7 +5812,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'; @@ -5768,6 +5833,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 */ @@ -5828,8 +5898,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); @@ -7060,6 +7135,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)); @@ -7867,6 +7943,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) @@ -11871,12 +11948,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)); @@ -12021,12 +12102,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); }