All pastes #44171 Raw Edit

Someone

public text v1 · immutable
#44171 ·published 2006-03-02 00:24 UTC
rendered paste body
/*! \brief  parse_register_contact: Parse contact header and save registration ---*/
static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req)
{
        char contact[80];
        char data[256];
        char iabuf[INET_ADDRSTRLEN];
        char *expires = get_header(req, "Expires");
        int expiry = atoi(expires);
        char *c, *n, *pt;
        int port;
        char *useragent;
        struct hostent *hp;
        struct ast_hostent ahp;
        struct sockaddr_in oldsin;

        if (ast_strlen_zero(expires)) { /* No expires header */
                expires = strcasestr(get_header(req, "Contact"), ";expires=");
                if (expires) {
                        char *ptr;
                        if ((ptr = strchr(expires, ';')))
                                *ptr = '\0';
                        if (sscanf(expires + 9, "%d", &expiry) != 1)
                                expiry = default_expiry;
                } else {
                        /* Nothing has been specified */
                        expiry = default_expiry;
                }
        }
        /* Look for brackets */
        ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
        if (strchr(contact, '<') == NULL) {     /* No <, check for ; and strip it */
                char *ptr = strchr(contact, ';');       /* This is Header options, not URI options */
                if (ptr)
                        *ptr = '\0';
        }
        c = get_in_brackets(contact);

        /* if they did not specify Contact: or Expires:, they are querying
           what we currently have stored as their contact address, so return
           it
        */
        if (ast_strlen_zero(c) && ast_strlen_zero(expires)) {
                if ((p->expire > -1) && !ast_strlen_zero(p->fullcontact)) {
                        /* tell them when the registration is going to expire */
                        pvt->expiry = ast_sched_when(sched, p->expire);
                        return PARSE_REGISTER_QUERY;
                } else {
                        return PARSE_REGISTER_FAILED;
                }
        } else if (!strcasecmp(c, "*") || !expiry) {    /* Unregister this peer */
                /* This means remove all registrations and return OK */
                memset(&p->addr, 0, sizeof(p->addr));
                if (p->expire > -1)
                        ast_sched_del(sched, p->expire);
                p->expire = -1;

                destroy_association(p);

                register_peer_exten(p, 0);
                p->fullcontact[0] = '\0';
                p->useragent[0] = '\0';
                p->sipoptions = 0;
                p->lastms = 0;

                if (option_verbose > 2)
                        ast_verbose(VERBOSE_PREFIX_3 "Unregistered SIP '%s'\n", p->name);
                        manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unregistered\r\n", p->name);
                return PARSE_REGISTER_UPDATE;
        }
        ast_copy_string(p->fullcontact, c, sizeof(p->fullcontact));
        /* 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 */
        if (strncasecmp(c, "sip:", 4)) {
                ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", c);
        } else
                c += 4;
        /* Ditch q */
        n = strchr(c, ';');
        if (n) {
                *n = '\0';
        }
        /* Grab host */
        n = strchr(c, '@');
        if (!n) {
                n = c;
                c = NULL;
        } else {
                *n = '\0';
                n++;
        }
        pt = strchr(n, ':');
        if (pt) {
                *pt = '\0';
                pt++;
                port = atoi(pt);
        } else
                port = DEFAULT_SIP_PORT;
        memcpy(&oldsin, &p->addr, sizeof(oldsin));
        if (!(ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)) {
                /* XXX This could block for a long time XXX */
                hp = ast_gethostbyname(n, &ahp);
                if (!hp)  {
                        ast_log(LOG_WARNING, "Invalid host '%s'\n", n);
                        return PARSE_REGISTER_FAILED;
                }
                p->addr.sin_family = AF_INET;
                memcpy(&p->addr.sin_addr, hp->h_addr, sizeof(p->addr.sin_addr));
                p->addr.sin_port = htons(port);
        } else {
                /* Don't trust the contact field.  Just use what they came to us
                   with */
                memcpy(&p->addr, &pvt->recv, sizeof(p->addr));
        }

        if (c)  /* Overwrite the default username from config at registration */
                ast_copy_string(p->username, c, sizeof(p->username));
        else
                p->username[0] = '\0';

        if (p->expire > -1)
                ast_sched_del(sched, p->expire);
        if ((expiry < 1) || (expiry > max_expiry))
                expiry = max_expiry;
        if (!ast_test_flag(p, SIP_REALTIME))
                p->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, p);
        else
                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->flags_page2), SIP_PAGE2_RT_FROMCONTACT))
                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);
                if (option_verbose > 2)
                        ast_log(LOG_NOTICE, "Registered SIP '%s' at %s port %d expires %d\n", p->name, ast_inet_ntoa(iabuf, sizeof(iabuf), p->addr.sin_addr), ntohs(p->addr.sin_port)
, expiry);
                register_peer_exten(p, 1);
        }

        /* Save SIP options profile */
        p->sipoptions = pvt->sipoptions;

        /* Save User agent */
        useragent = get_header(req, "User-Agent");
        if (useragent && strcasecmp(useragent, p->useragent)) {
                ast_copy_string(p->useragent, useragent, sizeof(p->useragent));
                if (option_verbose > 3) {
                        ast_log(LOG_NOTIFY, "Saved useragent \"%s\" for peer %s\n",p->useragent,p->name);
                }
        }
        return PARSE_REGISTER_UPDATE;
}