Exemple #1
0
/** unregister a global ns */
void sm_unregister_ns(sm_t sm, const char *uri) {
    int refcount = (int) (long) xhash_get(sm->xmlns_refcount, uri);
    if (refcount == 1) {
        xhash_zap(sm->xmlns, uri);
        xhash_zap(sm->xmlns_refcount, uri);
    } else if (refcount > 1) {
        xhash_put(sm->xmlns_refcount, uri, (void *) ((long) xhash_get(sm->xmlns_refcount, uri) - 1));
    }
}
/*
 * get group's descriptive name by it's text id
 * returned value needs to be freed by caller
 */
static const char *_roster_publish_get_group_name(sm_t sm, roster_publish_t rp, const char *groupid)
{
    os_t os;
    os_object_t o;
    char *str;
    char *group;

#ifndef NO_SM_CACHE
    _roster_publish_group_cache_t group_cached;
#endif

    if(!groupid) return groupid;

#ifndef NO_SM_CACHE
    /* check for remembered group value in cache */
    if( rp->group_cache_ttl ) {
        if( rp->group_cache ) {
            group_cached = xhash_get(rp->group_cache, groupid);
            if( group_cached != NULL ) {
                if( (time(NULL) - group_cached->time) >= rp->group_cache_ttl ) {
                    log_debug(ZONE,"group cache: expiring cached value for %s",groupid);
                    xhash_zap(rp->group_cache, groupid);
                    free(group_cached);
                } else {
                    log_debug(ZONE,"group cache: returning cached value for %s",groupid);
                    return strdup(group_cached->groupname);
                }
            }
        } else {
            log_debug(ZONE,"group cache: creating cache");
            rp->group_cache = xhash_new(401);
        }
    }
#endif

    if(storage_get(sm->st, "published-roster-groups", groupid, NULL, &os) == st_SUCCESS && os_iter_first(os)) {
        o = os_iter_object(os);
        if( os_object_get_str(os, o, "groupname", &str) && str ) {
            group=strdup(str);
        } else {
            group=NULL;
        }
        os_free(os);
#ifndef NO_SM_CACHE
        if( rp->group_cache_ttl && group ) {
            log_debug(ZONE,"group cache: updating cache value for %s",groupid);
            group_cached = calloc(1, sizeof(struct _roster_publish_group_cache_st));
            group_cached->time = time(NULL);
            group_cached->groupid = strdup(groupid);
            group_cached->groupname = strdup(group);
            xhash_put(rp->group_cache, group_cached->groupid, group_cached);
        }
#endif
        return group;
    } else {
        return NULL;
    }
}
Exemple #3
0
static void _router_process_unbind(component_t comp, nad_t nad) {
    int attr;
    jid_t name;

    attr = nad_find_attr(nad, 0, -1, "name", NULL);
    if(attr < 0 || (name = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
        log_debug(ZONE, "no or invalid 'name' on unbind packet, bouncing");
        nad_set_attr(nad, 0, -1, "error", "400", 3);
        sx_nad_write(comp->s, nad);
        return;
    }

    if(xhash_get(comp->routes, name->domain) == NULL) {
        log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to unbind '%s', but it's not bound to this component", comp->ip, comp->port, name->domain);
        nad_set_attr(nad, 0, -1, "name", NULL, 0);
        nad_set_attr(nad, 0, -1, "error", "404", 3);
        sx_nad_write(comp->s, nad);
        jid_free(name);
        return;
    }

    xhash_zap(comp->r->log_sinks, name->domain);
    _route_remove(comp->r->routes, name->domain, comp);
    xhash_zap(comp->routes, name->domain);

    if(comp->r->default_route != NULL && strcmp(comp->r->default_route, name->domain) == 0) {
        log_write(comp->r->log, LOG_NOTICE, "[%s] default route offline", name->domain);
        free((void*)(comp->r->default_route));
        comp->r->default_route = NULL;
    }

    log_write(comp->r->log, LOG_NOTICE, "[%s] offline", name->domain);

    nad_set_attr(nad, 0, -1, "name", NULL, 0);
    sx_nad_write(comp->s, nad);

    /* deadvertise name */
    if(xhash_get(comp->r->routes, name->domain) == NULL)
        _router_advertise(comp->r, name->domain, comp, 1);

    jid_free(name);
}
Exemple #4
0
/** unregister feature */
void feature_unregister(sm_t sm, const char *feature)
{
    int refcount = (int) (long) xhash_get(sm->features, feature);

    log_debug(ZONE, "unregistering feature %s", feature);

    if (refcount == 1) {
        xhash_zap(sm->features, feature);
    } else if (refcount > 1) {
        xhash_put(sm->features, feature, (void *) ((long) refcount - 1));
    }
}
Exemple #5
0
int at_register_iqns(ati ti, const char *ns, iqcb cb)
{
    iqcb cur;

    log_debug(ZONE, "Registering callback for %s", ns);
    cur = xhash_get(ti->iq__callbacks, ns);
    if(cur)
    {
        xhash_zap(ti->iq__callbacks, ns);
    }
    xhash_put(ti->iq__callbacks, ns, cb);

    return;
}
Exemple #6
0
void dnsrv_process_xstream_io(int type, xmlnode x, void* arg)
{
     dns_io di            = (dns_io)arg;
     char* hostname       = NULL;
     char* ipaddr         = NULL;
     char* resendhost     = NULL;
     dns_packet_list head = NULL;
     dns_packet_list heado = NULL;

     /* Node Format: <host ip="201.83.28.2">foo.org</host> */
     if (type == XSTREAM_NODE)
     {    
          log_debug(ZONE,"incoming resolution: %s",xmlnode2str(x));
          hostname = xmlnode_get_data(x);

          /* whatever the response was, let's cache it */
          xmlnode_free((xmlnode)xhash_get(di->cache_table,hostname)); /* free any old cache, shouldn't ever be any */
          xmlnode_put_vattrib(x,"t",(void*)time(NULL));
          xhash_put(di->cache_table,hostname,(void*)x);

          /* Get the hostname and look it up in the hashtable */
          head = xhash_get(di->packet_table, hostname);
          /* Process the packet list */
          if (head != NULL)
          {
               ipaddr = xmlnode_get_attrib(x, "ip");
               resendhost = xmlnode_get_attrib(x, "to");

               /* Remove the list from the hashtable */
               xhash_zap(di->packet_table, hostname);
               
               /* Walk the list and insert IPs */
               while(head != NULL)
               {
                    heado = head;
                    /* Move to next.. */
                    head = head->next;
                    /* Deliver the packet */
                    dnsrv_resend(heado->packet->x, ipaddr, resendhost);
               }
          }
          /* Host name was not found, something is _TERRIBLY_ wrong! */
          else
               log_debug(ZONE, "Resolved unknown host/ip request: %s\n", xmlnode2str(x));

          return; /* we cached x above, so we don't free it below :) */
     }
     xmlnode_free(x);
} 
Exemple #7
0
result dnsrv_deliver(instance i, dpacket p, void* args)
{
     dns_io di = (dns_io)args;
     xmlnode c;
     int timeout = di->cache_timeout;
     char *ip;
     jid to;

     /* if we get a route packet, it has to be to *us* and have the child as the real packet */
     if(p->type == p_ROUTE)
     {
        if(j_strcmp(p->host,i->id) != 0 || (to = jid_new(p->p,xmlnode_get_attrib(xmlnode_get_firstchild(p->x),"to"))) == NULL)
            return r_ERR;
        p->x=xmlnode_get_firstchild(p->x);
        p->id = to;
        p->host = to->server;
     }

     /* Ensure this packet doesn't already have an IP */
     if(xmlnode_get_attrib(p->x, "ip") || xmlnode_get_attrib(p->x, "iperror"))
     {
        log_notice(p->host, "dropping looping dns lookup request: %s", xmlnode2str(p->x));
        xmlnode_free(p->x);
        return r_DONE;
     }

     /* try the cache first */
     if((c = xhash_get(di->cache_table, p->host)) != NULL)
     {
         /* if there's no IP, cached failed lookup, time those out 10 times faster! (weird, I know, *shrug*) */
         if((ip = xmlnode_get_attrib(c,"ip")) == NULL)
            timeout = timeout / 10;
         if((time(NULL) - (int)xmlnode_get_vattrib(c,"t")) > timeout)
         { /* timed out of the cache, lookup again */
             xmlnode_free(c);
             xhash_zap(di->cache_table,p->host);
         }else{
             /* yay, send back right from the cache */
             dnsrv_resend(p->x, ip, xmlnode_get_attrib(c,"to"));
             return r_DONE;
         }
     }

    dnsrv_lookup(di, p);
    return r_DONE;
}
Exemple #8
0
static void _route_remove(xht hroutes, const char *name, component_t comp) {
    routes_t routes;
    int i;

    routes = xhash_get(hroutes, name);
    if(routes == NULL) return;

    if(routes->ncomp > 1) {
        for(i = 0; i < routes->ncomp; i++) {
            if(routes->comp[i] == comp) {
                if(i != routes->ncomp - 1) {
                    routes->comp[i] = routes->comp[routes->ncomp - 1];
                }
                routes->ncomp--;
            }
        }
    }
    else {
        jqueue_push(comp->r->deadroutes, (void *) routes, 0);
        xhash_zap(hroutes, name);
    }
}
Exemple #9
0
static void _sess_end_guts(sess_t sess) {
    sess_t scan;

    /* fake an unavailable presence from this session, so that modules and externals know we're gone */
    if(sess->available || sess->A != NULL)
        mm_in_sess(sess->user->sm->mm, sess, pkt_create(sess->user->sm, "presence", "unavailable", NULL, NULL));

    /* inform the modules */
    mm_sess_end(sess->user->sm->mm, sess);

    /* unlink it from this users sessions */
    if(sess->user->sessions == sess)
        sess->user->sessions = sess->next;
    else {
        for(scan = sess->user->sessions; scan != NULL && scan->next != sess; scan = scan->next);
        if(scan != NULL)
            scan->next = sess->next;
    }

    /* and from global sessions */
    xhash_zap(sess->user->sm->sessions, sess->sm_id);
}
Exemple #10
0
/* callback for walking the connecting hash tree */
void _dnsrv_beat_packets(xht h, const char *key, void *data, void *arg)
{
    dns_io di = (dns_io)arg;
    dns_packet_list n, l = (dns_packet_list)data;
    int now = time(NULL);
    int reap = 0;

    /* first, check the head */
    if((now - l->stamp) > di->packet_timeout)
    {
        log_notice(l->packet->host,"timed out from dnsrv queue");
        xhash_zap(di->packet_table,l->packet->host);
        reap = 1;
    }else{
        while(l->next != NULL)
        {
            if((now - l->next->stamp) > di->packet_timeout)
            {
                reap = 1;
                n = l->next;
                l->next = NULL; /* chop off packets to be killed */
                l = n;
                break;
            }
            l = l->next;
        }
    }

    if(reap == 0) return;

    /* time out individual queue'd packets */
    while(l != NULL)
    {
        n = l->next;
        deliver_fail(l->packet,"Hostname Resolution Timeout");
        l = n;
    }
}
Exemple #11
0
void nad_free(nad_t nad)
{
    if(nad == NULL) return;

#ifdef NAD_DEBUG
    _nad_ptr_check(__func__, nad);
    {
    char loc[24];
    snprintf(loc, sizeof(loc), "%x", (int) nad);
    xhash_zap(_nad_alloc_tracked, loc);
    xhash_put(_nad_free_tracked, pstrdup(xhash_pool(_nad_free_tracked), loc), (void *) nad);
    }
#endif

    /* Free nad */
    free(nad->elems);
    free(nad->attrs);
    free(nad->cdata);
    free(nad->nss);
    free(nad->depths);
#ifndef NAD_DEBUG
    free(nad);
#endif
}
Exemple #12
0
int router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
    component_t comp = (component_t) arg;
    router_t r = (router_t) arg;
    struct sockaddr_storage sa;
    socklen_t namelen = sizeof(sa);
    int port, nbytes;

    switch(a) {
        case action_READ:
            log_debug(ZONE, "read action on fd %d", fd->fd);

            /* they did something */
            comp->last_activity = time(NULL);

            ioctl(fd->fd, FIONREAD, &nbytes);
            if(nbytes == 0) {
                sx_kill(comp->s);
                return 0;
            }

            return sx_can_read(comp->s);

        case action_WRITE:
            log_debug(ZONE, "write action on fd %d", fd->fd);

           /* update activity timestamp */
            comp->last_activity = time(NULL);

            return sx_can_write(comp->s);

        case action_CLOSE:
            log_debug(ZONE, "close action on fd %d", fd->fd);

            r = comp->r;

            log_write(r->log, LOG_NOTICE, "[%s, port=%d] disconnect", comp->ip, comp->port);

            /* unbind names */
            xhash_walk(comp->routes, _router_route_unbind_walker, (void *) comp);

            /* deregister component */
            xhash_zap(r->components, comp->ipport);

            xhash_free(comp->routes);

            if(comp->tq != NULL)
                /* !!! bounce packets */
                jqueue_free(comp->tq);

            rate_free(comp->rate);

            jqueue_push(comp->r->dead, (void *) comp->s, 0);

            free(comp);

            break;

        case action_ACCEPT:
            log_debug(ZONE, "accept action on fd %d", fd->fd);

            getpeername(fd->fd, (struct sockaddr *) &sa, &namelen);
            port = j_inet_getport(&sa);

            log_write(r->log, LOG_NOTICE, "[%s, port=%d] connect", (char *) data, port);

            if(_router_accept_check(r, fd, (char *) data) != 0)
                return 1;

            comp = (component_t) calloc(1, sizeof(struct component_st));

            comp->r = r;

            comp->fd = fd;

            snprintf(comp->ip, INET6_ADDRSTRLEN, "%s", (char *) data);
            comp->port = port;

            snprintf(comp->ipport, INET6_ADDRSTRLEN + 6, "%s:%d", comp->ip, comp->port);

            comp->s = sx_new(r->sx_env, fd->fd, _router_sx_callback, (void *) comp);
            mio_app(m, fd, router_mio_callback, (void *) comp);

            if(r->byte_rate_total != 0)
                comp->rate = rate_new(r->byte_rate_total, r->byte_rate_seconds, r->byte_rate_wait);

            comp->routes = xhash_new(51);

            /* register component */
            log_debug(ZONE, "new component (%p) \"%s\"", comp, comp->ipport);
            xhash_put(r->components, comp->ipport, (void *) comp);

#ifdef HAVE_SSL
            sx_server_init(comp->s, SX_SSL_STARTTLS_OFFER | SX_SASL_OFFER);
#else
            sx_server_init(comp->s, SX_SASL_OFFER);
#endif

            break;
    }

    return 0;
}
Exemple #13
0
Fichier : in.c Projet : zipo/zipo
int in_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
    conn_t in = (conn_t) arg;
    s2s_t s2s = (s2s_t) arg;
    struct sockaddr_storage sa;
    int namelen = sizeof(sa), port, nbytes;
    char ipport[INET6_ADDRSTRLEN + 17];

    switch(a) {
        case action_READ:
            log_debug(ZONE, "read action on fd %d", fd->fd);

            ioctl(fd->fd, FIONREAD, &nbytes);
            if(nbytes == 0) {
                sx_kill(in->s);
                return 0;
            }

            return sx_can_read(in->s);

        case action_WRITE:
            log_debug(ZONE, "write action on fd %d", fd->fd);
            return sx_can_write(in->s);

        case action_CLOSE:
            log_debug(ZONE, "close action on fd %d", fd->fd);

            /* !!! logging */
            log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect, packets: %i", fd->fd, in->ip, in->port, in->packet_count);

            jqueue_push(in->s2s->dead, (void *) in->s, 0);

            /* remove from open streams hash if online, or open connections if not */
            if (in->online)
                xhash_zap(in->s2s->in, in->key);
            else {
                snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
                xhash_zap(in->s2s->in_accept, ipport);
            }

            jqueue_push(in->s2s->dead_conn, (void *) in, 0);

            break;

        case action_ACCEPT:
            s2s = (s2s_t) arg;

            log_debug(ZONE, "accept action on fd %d", fd->fd);
            
            getpeername(fd->fd, (struct sockaddr *) &sa, &namelen);
            port = j_inet_getport(&sa);

            log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming connection", fd->fd, (char *) data, port);

            /* new conn */
            in = (conn_t) calloc(1, sizeof(struct conn_st));

            in->s2s = s2s;

            strncpy(in->ip, (char *) data, INET6_ADDRSTRLEN);
            in->port = port;

            in->states = xhash_new(101);
            in->states_time = xhash_new(101);

            in->fd = fd;

            in->init_time = time(NULL);

            in->s = sx_new(s2s->sx_env, in->fd->fd, _in_sx_callback, (void *) in);
            mio_app(m, in->fd, in_mio_callback, (void *) in);

            if(s2s->stanza_size_limit != 0)
                in->s->rbytesmax = s2s->stanza_size_limit;

            /* add to incoming connections hash */
            snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
            xhash_put(s2s->in_accept, pstrdup(xhash_pool(s2s->in_accept),ipport), (void *) in);

#ifdef HAVE_SSL
            sx_server_init(in->s, S2S_DB_HEADER | ((s2s->sx_ssl != NULL) ? SX_SSL_STARTTLS_OFFER : 0) );
#else
            sx_server_init(in->s, S2S_DB_HEADER);
#endif
            break;
    }

    return 0;
}
Exemple #14
0
Fichier : in.c Projet : zipo/zipo
static int _in_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
    conn_t in = (conn_t) arg;
    sx_buf_t buf = (sx_buf_t) data;
    int len;
    sx_error_t *sxe;
    nad_t nad;
    char ipport[INET6_ADDRSTRLEN + 17];

    switch(e) {
        case event_WANT_READ:
            log_debug(ZONE, "want read");
            mio_read(in->s2s->mio, in->fd);
            break;

        case event_WANT_WRITE:
            log_debug(ZONE, "want write");
            mio_write(in->s2s->mio, in->fd);
            break;

        case event_READ:
            log_debug(ZONE, "reading from %d", in->fd->fd);

            /* do the read */
            len = recv(in->fd->fd, buf->data, buf->len, 0);

            if(len < 0) {
                if(MIO_WOULDBLOCK) {
                    buf->len = 0;
                    return 0;
                }

                log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] read error: %s (%d)", in->fd->fd, in->ip, in->port, MIO_STRERROR(MIO_ERROR), MIO_ERROR);

                sx_kill(s);
                
                return -1;
            }

            else if(len == 0) {
                /* they went away */
                sx_kill(s);

                return -1;
            }

            log_debug(ZONE, "read %d bytes", len);

            buf->len = len;

            return len;

        case event_WRITE:
            log_debug(ZONE, "writing to %d", in->fd->fd);

            len = send(in->fd->fd, buf->data, buf->len, 0);
            if(len >= 0) {
                log_debug(ZONE, "%d bytes written", len);
                return len;
            }

            if(MIO_WOULDBLOCK)
                return 0;

            log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] write error: %s (%d)", in->fd->fd, in->ip, in->port, MIO_STRERROR(MIO_ERROR), MIO_ERROR);

            sx_kill(s);

            return -1;

        case event_ERROR:
            sxe = (sx_error_t *) data;
            log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] error: %s (%s)", in->fd->fd, in->ip, in->port, sxe->generic, sxe->specific);

            break;

        case event_STREAM:
        case event_OPEN:

            log_debug(ZONE, "STREAM or OPEN event from %s port %d (id %s)", in->ip, in->port, s->id);

            /* first time, bring them online */
            if ((!in->online)||(strcmp(in->key,s->id)!=0)) { 
                log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming stream online (id %s)", in->fd->fd, in->ip, in->port, s->id);

                in->online = 1;

                /* record the id */
                if (in->key != NULL) {
                   log_debug(ZONE,"adding new SSL stream id %s for stream id %s", s->id, in->key);

                   /* remove the initial (non-SSL) stream id from the in connections hash */
                   xhash_zap(in->s2s->in, in->key);
                   free(in->key);
                }

                in->key = strdup(s->id);

                /* track it - add to open streams hash and remove from new connections hash */
                xhash_put(in->s2s->in, in->key, (void *) in);

                snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
                xhash_zap(in->s2s->in_accept, ipport);
            }  

            break;

        case event_PACKET:
            /* we're counting packets */
            in->packet_count++;
            in->s2s->packet_count++;

            nad = (nad_t) data;

            /* update last packet timestamp */
            in->last_packet = time(NULL);

            /* dialback packets */
            if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_DIALBACK) && strncmp(uri_DIALBACK, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_DIALBACK)) == 0) {
                /* only result and verify mean anything */
                if(NAD_ENAME_L(nad, 0) == 6) {
                    if(strncmp("result", NAD_ENAME(nad, 0), 6) == 0) {
                        _in_result(in, nad);
                        return 0;
                    }

                    if(strncmp("verify", NAD_ENAME(nad, 0), 6) == 0) {
                        _in_verify(in, nad);
                        return 0;
                    }
                }
                
                log_debug(ZONE, "unknown dialback packet, dropping it");

                nad_free(nad);
                return 0;
            }

            /*
             * not dialback, so it has to be a normal-ish jabber packet:
             *  - jabber:client or jabber:server
             *  - message, presence or iq
             *  - has to and from attributes
             */

            if(!(
                 /* must be jabber:client or jabber:server */
                 NAD_ENS(nad, 0) >= 0 &&
                 ((NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_CLIENT) && strncmp(uri_CLIENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_CLIENT)) == 0) ||
                 (NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_SERVER) && strncmp(uri_SERVER, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_SERVER)) == 0)) && (
                    /* can be message */
                    (NAD_ENAME_L(nad, 0) == 7 && strncmp("message", NAD_ENAME(nad, 0), 7) == 0) ||
                    /* or presence */
                    (NAD_ENAME_L(nad, 0) == 8 && strncmp("presence", NAD_ENAME(nad, 0), 8) == 0) ||
                    /* or iq */
                    (NAD_ENAME_L(nad, 0) == 2 && strncmp("iq", NAD_ENAME(nad, 0), 2) == 0)
                 ) &&
                 /* to and from required */
                 nad_find_attr(nad, 0, -1, "to", NULL) >= 0 && nad_find_attr(nad, 0, -1, "from", NULL) >= 0
               )) {
                log_debug(ZONE, "they sent us a non-jabber looking packet, dropping it");
                nad_free(nad);
                return 0;
            }

            _in_packet(in, nad);
            return 0;

        case event_CLOSED:
            mio_close(in->s2s->mio, in->fd);
            return -1;
    }

    return 0;
}
Exemple #15
0
/**
 * process commandline
 * @return: 0 to indicate that output needs to be written
 */
int _pbx_process_command(c2s_t c2s, char *cmd)
{
	jid_t jid;
	int action = 0, len;
	sess_t sess;
	unsigned char hashbuf[44] = "PBX";
	unsigned char *sesshash;

	sesshash = hashbuf+3;

	/* get command */
	if(!strncasecmp("START ", cmd, 6)) {
		cmd += 6;
		action = 1;
	}
	if(!strncasecmp("STOP ", cmd, 5)) {
		cmd += 5;
		action = 2;
	}
	if(action != 0) {
		len = _pbx_command_part_len(cmd);
		if(len > 0) {
			jid = jid_new(cmd, len);
			if(jid) {
				cmd += len;
				if(*cmd != '\0') cmd++;

				shahash_r(jid_full(jid), sesshash);
				sess = xhash_get(c2s->sessions, hashbuf);

				switch(action) {
					case 1:
						log_debug(ZONE, "STARTing session for %s/%s (%s) with commandline: %s", jid_user(jid), jid->resource, hashbuf, cmd);

						if(sess == NULL) {
						/* create new session */
							sess = (sess_t) calloc(1, sizeof(struct sess_st));
							sess->c2s = c2s;
							sess->last_activity = time(NULL);
							/* put into sessions hash */
							snprintf(sess->skey, sizeof(sess->skey), "%s", hashbuf);
							xhash_put(c2s->sessions, sess->skey, (void *) sess);
							/* generate bound resource */
							sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
							snprintf(sess->resources->c2s_id, sizeof(sess->resources->c2s_id), "%s", hashbuf);
							sess->resources->jid = jid;
							/* open SM session */
							log_write(sess->c2s->log, LOG_NOTICE, "[PBX] requesting session: jid=%s", jid_full(jid));
							sm_start(sess, sess->resources);

							/* generate presence packet to get session online */
							/* a bit hacky, but we need to emulate _some_ of the client behavior */
							sess->result = _pbx_presence_nad(1, cmd);
						}
						else {
							/* just send the presence */
							sm_packet(sess, sess->resources, _pbx_presence_nad(1, cmd));
						}

						break;

					case 2:
						log_debug(ZONE, "STOPping session for %s/%s with commandline: %s", jid_user(jid), jid->resource, cmd);

						if(sess != NULL) {
							/* send unavailable presence */
							sm_packet(sess, sess->resources, _pbx_presence_nad(0, cmd));
							/* end the session */
							sm_end(sess, sess->resources);
							xhash_zap(c2s->sessions, sess->skey);
							jqueue_push(c2s->dead_sess, (void *) sess, 0);
						}

						break;
				}

				/* TODO: respond with "OK", return 0 */
				return -1;
			}
		}
		/* TODO: generate "ERR" response, return 0 */
		return -1;
	}
	if(!strncasecmp("STATUS", cmd, 6)) {
		log_write(c2s->log, LOG_INFO, "STATUS PBX command not implemented yet");
		return -1;
	}
    return -1;
}
Exemple #16
0
void user_free(user_t user) {
    log_debug(ZONE, "freeing user %s", jid_user(user->jid));

    xhash_zap(user->sm->users, jid_user(user->jid));
    pool_free(user->p);
}
Exemple #17
0
static void _s2s_time_checks(s2s_t s2s) {
    conn_t conn;
    time_t now;
    char *rkey, *key;
    int keylen;
    jqueue_t q;
    dnscache_t dns;
    char *c;
    int c_len;
    union xhashv xhv;

    now = time(NULL);

    /* queue expiry */
    if(s2s->check_queue > 0) {
        if(xhash_iter_first(s2s->outq))
            do {
                xhv.jq_val = &q;
                xhash_iter_get(s2s->outq, (const char **) &rkey, &keylen, xhv.val);

                log_debug(ZONE, "running time checks for %.*s", keylen, rkey);
                c = memchr(rkey, '/', keylen);
                c++;
                c_len = keylen - (c - rkey);

                /* dns lookup timeout check first */
                dns = xhash_getx(s2s->dnscache, c, c_len);
                if(dns != NULL && dns->pending) {
                    log_debug(ZONE, "dns lookup pending for %.*s", c_len, c);
                    if(now > dns->init_time + s2s->check_queue) {
                        log_write(s2s->log, LOG_NOTICE, "dns lookup for %.*s timed out", c_len, c);

                        /* bounce queue */
                        out_bounce_route_queue(s2s, rkey, keylen, stanza_err_REMOTE_SERVER_NOT_FOUND);

                        /* expire pending dns entry */
                        xhash_zap(s2s->dnscache, dns->name);
                        xhash_free(dns->results);
                        if (dns->query != NULL) {
                            if (dns->query->query != NULL)
                                dns_cancel(NULL, dns->query->query);
                            xhash_free(dns->query->hosts);
                            xhash_free(dns->query->results);
                            free(dns->query->name);
                            free(dns->query);
                        }
                        free(dns);
                    }

                    continue;
                }

                /* get the conn */
                conn = xhash_getx(s2s->out_dest, c, c_len);
                if(conn == NULL) {
                    if(jqueue_size(q) > 0) {
                       /* no pending conn? perhaps it failed? */
                       log_debug(ZONE, "no pending connection for %.*s, bouncing %i packets in queue", c_len, c, jqueue_size(q));

                       /* bounce queue */
                       out_bounce_route_queue(s2s, rkey, keylen, stanza_err_REMOTE_SERVER_TIMEOUT);
                    }

                    continue;
                }

                /* connect timeout check */
                if(!conn->online && now > conn->init_time + s2s->check_queue) {
                    dnsres_t bad;
                    char *ipport;

                    log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] connection to %s timed out", conn->fd->fd, conn->ip, conn->port, c);

                    if (s2s->dns_bad_timeout > 0) {
                        /* mark this host as bad */
                        ipport = dns_make_ipport(conn->ip, conn->port);
                        bad = xhash_get(s2s->dns_bad, ipport);
                        if (bad == NULL) {
                            bad = (dnsres_t) calloc(1, sizeof(struct dnsres_st));
                            bad->key = ipport;
                            xhash_put(s2s->dns_bad, ipport, bad);
                        } else {
                            free(ipport);
                        }
                        bad->expiry = time(NULL) + s2s->dns_bad_timeout;
                    }

                    /* close connection as per XMPP/RFC3920 */
                    /* the close function will retry or bounce the queue */
                    sx_close(conn->s);
                }
            } while(xhash_iter_next(s2s->outq));
    }

    /* expiry of connected routes in conn_INPROGRESS state */
    if(s2s->check_queue > 0) {

        /* outgoing connections */
        if(s2s->out_reuse) {
            if(xhash_iter_first(s2s->out_host))
                do {
                    xhv.conn_val = &conn;
                    xhash_iter_get(s2s->out_host, (const char **) &key, &keylen, xhv.val);
                    log_debug(ZONE, "checking dialback state for outgoing conn %.*s", keylen, key);
                    if (_s2s_check_conn_routes(s2s, conn, "outgoing")) {
                        log_debug(ZONE, "checking pending verify requests for outgoing conn %.*s", keylen, key);
                        if (conn->verify > 0 && now > conn->last_verify + s2s->check_queue) {
                            log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback verify request timed out", conn->fd->fd, conn->ip, conn->port);
                            sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback verify request timed out");
                            sx_close(conn->s);
                        }
                    }
                } while(xhash_iter_next(s2s->out_host));
        } else {
            if(xhash_iter_first(s2s->out_dest))
                do {
                    xhv.conn_val = &conn;
                    xhash_iter_get(s2s->out_dest, (const char **) &key, &keylen, xhv.val);
                    log_debug(ZONE, "checking dialback state for outgoing conn %s (%s)", conn->dkey, conn->key);
                    if (_s2s_check_conn_routes(s2s, conn, "outgoing")) {
                        log_debug(ZONE, "checking pending verify requests for outgoing conn %s (%s)", conn->dkey, conn->key);
                        if (conn->verify > 0 && now > conn->last_verify + s2s->check_queue) {
                            log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback verify request timed out", conn->fd->fd, conn->ip, conn->port);
                            sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback verify request timed out");
                            sx_close(conn->s);
                        }
                    }
                } while(xhash_iter_next(s2s->out_dest));
        }

        /* incoming open streams */
        if(xhash_iter_first(s2s->in))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->in, (const char **) &key, &keylen, xhv.val);

                log_debug(ZONE, "checking dialback state for incoming conn %.*s", keylen, key);
                if (_s2s_check_conn_routes(s2s, conn, "incoming"))
                    /* if the connection is still valid, check that dialbacks have been initiated */
                    if(!xhash_count(conn->states) && now > conn->init_time + s2s->check_queue) {
                        log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] no dialback started", conn->fd->fd, conn->ip, conn->port);
                        sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "no dialback initiated");
                        sx_close(conn->s);
                    }
            } while(xhash_iter_next(s2s->in));

        /* incoming open connections (not yet streams) */
        if(xhash_iter_first(s2s->in_accept))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->in_accept, (const char **) &key, &keylen, xhv.val);

                log_debug(ZONE, "checking stream connection state for incoming conn %i", conn->fd->fd);
                if(!conn->online && now > conn->init_time + s2s->check_queue) {
                    log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] stream initiation timed out", conn->fd->fd, conn->ip, conn->port);
                    sx_close(conn->s);
                }
            } while(xhash_iter_next(s2s->in_accept));

    }

    /* keepalives */
    if(s2s->out_reuse) {
        if(xhash_iter_first(s2s->out_host))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->out_host, NULL, NULL, xhv.val);

                if(s2s->check_keepalive > 0 && conn->last_activity > 0 && now > conn->last_activity + s2s->check_keepalive && conn->s->state >= state_STREAM) {
                    log_debug(ZONE, "sending keepalive for %d", conn->fd->fd);

                    sx_raw_write(conn->s, " ", 1);
                }
            } while(xhash_iter_next(s2s->out_host));
    } else {
        if(xhash_iter_first(s2s->out_dest))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->out_dest, NULL, NULL, xhv.val);

                if(s2s->check_keepalive > 0 && conn->last_activity > 0 && now > conn->last_activity + s2s->check_keepalive && conn->s->state >= state_STREAM) {
                    log_debug(ZONE, "sending keepalive for %d", conn->fd->fd);

                    sx_raw_write(conn->s, " ", 1);
                }
            } while(xhash_iter_next(s2s->out_dest));
    }

    /* idle timeouts - disconnect connections through which no packets have been sent for <idle> seconds */
    if(s2s->check_idle > 0) {

        /* outgoing connections */
        if(s2s->out_reuse) {
            if(xhash_iter_first(s2s->out_host))
                do {
                    xhv.conn_val = &conn;
                    xhash_iter_get(s2s->out_host, (const char **) &key, &keylen, xhv.val);
                    log_debug(ZONE, "checking idle state for %.*s", keylen, key);
                    if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
                        log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
                        sx_close(conn->s);
                    }
                } while(xhash_iter_next(s2s->out_host));
        } else {
            if(xhash_iter_first(s2s->out_dest))
                do {
                    xhv.conn_val = &conn;
                    xhash_iter_get(s2s->out_dest, (const char **) &key, &keylen, xhv.val);
                    log_debug(ZONE, "checking idle state for %s (%s)", conn->dkey, conn->key);
                    if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
                        log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
                        sx_close(conn->s);
                    }
                } while(xhash_iter_next(s2s->out_dest));
        }

        /* incoming connections */
        if(xhash_iter_first(s2s->in))
            do {
                xhv.conn_val = &conn;
                xhash_iter_get(s2s->in, (const char **) &key, &keylen, xhv.val);
                log_debug(ZONE, "checking idle state for %.*s", keylen, key);
                if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
                    log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
                    sx_close(conn->s);
                }
            } while(xhash_iter_next(s2s->in));

    }

    return;
}