Example #1
0
static void _ensure_pool_cleanup_gracefully_handles_cleaned_up_pool( void )
{
	pool_t pool;
	pool_init( &pool, 4, 16, allocator_default( ) );
	pool_cleanup( &pool );
	pool_cleanup( &pool );
}
Example #2
0
static int _vacation_user_load(mod_instance_t mi, user_t user) {
    module_t mod = mi->mod;
    vacation_t v;
    os_t os;
    os_object_t o;

    v = (vacation_t) calloc(1, sizeof(struct _vacation_st));
    user->module_data[mod->index] = v;

    if(storage_get(mod->mm->sm->st, "vacation-settings", jid_user(user->jid), NULL, &os) == st_SUCCESS) {
        if(os_iter_first(os)) {
            o = os_iter_object(os);

            if(os_object_get_time(os, o, "start", &v->start) &&
               os_object_get_time(os, o, "end", &v->end) &&
               os_object_get_str(os, o, "message", &v->msg))
                v->msg = strdup(v->msg);
            else {
                v->start = 0;
                v->end = 0;
                v->msg = NULL;
            }
        }

        os_free(os);
    }

    pool_cleanup(user->p, (void (*))(void *) _vacation_user_free, v);

    return 0;
}
Example #3
0
/* public queue creation function, queue lives as long as the pool */
mtq mtq_new(pool p)
{
    mtq q;
    int n,mtq_n;
    int count;

	if (p==NULL)
	  return NULL;

    if(mtq__master == NULL)  {
	  mtq_init();
	}

	/* find queue with less users */
	count=999999;
	mtq_n = 0;
	for(n = 0; n < MTQ_THREADS; n++)
	  if(mtq__master->all[n]->mtq->users_count < count)  {	    
		count = mtq__master->all[n]->mtq->users_count;
		mtq_n = n;
	  }
	q = mtq__master->all[mtq_n]->mtq;    

    q->users_count++;    
    pool_cleanup(p, mtq_cleanup, (void *)q);

    return q;
}
Example #4
0
static void _ensure_pool_is_empty_returns_non_zero_on_empty_legitimate_pool( void )
{
	pool_t pool;
	pool_init( &pool, 4, 1, allocator_default( ) );
	TEST_REQUIRE( pool_is_empty( &pool ) == 0 );
	pool_cleanup( &pool );
}
Example #5
0
static void _ensure_pool_is_empty_gracefully_handles_cleaned_up_pool( void )
{
	pool_t pool;
	pool_init( &pool, 4, 1, allocator_default( ) );
	pool_cleanup( &pool );
	TEST_REQUIRE( pool_is_empty( &pool ) != 0 );
}
Example #6
0
void aim_transport(instance i, xmlnode x)
{
    ati ti;
    xmlnode config;
	char *eightbitcode, *utf8code = "UTF-8", *latin1code = "CP1252";
    
    ti = pmalloco(i->p, sizeof(_ati));

    ti->i = i;
    ti->xc = xdb_cache(i);
    log_notice(i->id, "AIM-Transport starting up for instance %s...", i->id);
    
    config = xdb_get(ti->xc, jid_new(xmlnode_pool(x), "config@-internal"), "jabber:config:aimtrans");
    
    ti->vcard = xmlnode_new_tag_pool(i->p,"vCard");
    xmlnode_put_attrib(ti->vcard,"xmlns",NS_VCARD);
    xmlnode_insert_node(ti->vcard,xmlnode_get_firstchild(xmlnode_get_tag(config,"vCard")));

    ti->start_time = time(NULL);
    

    ti->session__list=xhash_new(101);
    ti->iq__callbacks = xhash_new(23);
    ti->pending__buddies = xhash_new(101);

    /* The aim.exe binary should not be necessary any more. */
    ti->aimbinarydir = pstrdup(i->p, xmlnode_get_tag_data(config, "aimbinarydir"));

	eightbitcode = pstrdup(i->p, xmlnode_get_tag_data(config, "charset"));
	if( eightbitcode == NULL )
	{
		log_notice( i->id, "Charset is not specified, using CP1252" );
		eightbitcode = latin1code;
	}

    xmlnode_free(config);

	fromutf8 = iconv_open(eightbitcode, utf8code);
	if(fromutf8 == (iconv_t)(-1))
	{
		log_error(i->id, "Conversion from %s to %s is not supported", utf8code, eightbitcode);
		raise(SIGINT);
	}
	toutf8 = iconv_open(utf8code, eightbitcode);
	if(toutf8 == (iconv_t)(-1))
	{
		log_error(i->id, "Conversion from %s to %s is not supported", eightbitcode, utf8code);
		raise(SIGINT);
	}

    ti->send_buf = NULL;
    ti->modname = NULL;

    pth_mutex_init(&ti->buddies_mutex);

    at_init_iqcbs(ti);

    register_phandler(i, o_DELIVER, at_phandler, ti);
    pool_cleanup(i->p, at_shutdown, (void*)i);
}
Example #7
0
xdbcache xdb_cache(instance id)
{
    xdbcache newx;

    if(id == NULL)
    {
        fprintf(stderr, "Programming Error: xdb_cache() called with NULL\n");
        return NULL;
    }

    newx = pmalloco(id->p, sizeof(_xdbcache));
    newx->i = id; /* flags it as the top of the ring too */
    newx->next = newx->prev = newx; /* init ring */
    pthread_mutex_init(&(newx->sem),NULL);

    /* register the handler in the instance to filter out xdb results */
    register_phandler(id, o_PRECOND, xdb_results, (void *)newx);

    /* heartbeat to keep a watchful eye on xdb_cache */
    register_beat(10,xdb_thump,(void *)newx);

    register_shutdown_first(xdb_shutdown, (void *)newx);

	pool_cleanup(id->p, xdb_shutdown, (void*)newx);
	
    return newx;
}
Example #8
0
static void _ensure_pool_return_gracefully_handles_cleaned_up_pool( void )
{
	void * item;
	pool_t pool;
	pool_init( &pool, 4, 1, allocator_default( ) );
	item = pool_take( &pool );
	pool_cleanup( &pool );
	pool_return( &pool, item );
}
Example #9
0
static void _ensure_pool_delete_gracefully_handles_cleaned_up_pool( void )
{
	pool_t * pool;
	allocator_counted_t alloc;
	allocator_counted_init_default( &alloc );
	pool = pool_new( 128, 4, allocator_counted_get( &alloc ) );
	pool_cleanup( pool );
	pool_delete( pool );
	TEST_REQUIRE( allocator_counted_get_current_count( &alloc ) == 0 );
}
Example #10
0
static void _ensure_pool_return_gracefully_handles_address_not_in_pool( void )
{
	unsigned item_not_in_pool;
	pool_t pool;
	pool_init( &pool, 4, 1, allocator_default( ) );
	pool_return( &pool, &item_not_in_pool );
	TEST_REQUIRE( pool_take( &pool ) != &item_not_in_pool );
	TEST_REQUIRE( pool_take( &pool ) == 0 );
	pool_cleanup( &pool );
}
Example #11
0
static void _ensure_pool_take_reuses_returned_elements( void )
{
	void * item;
	pool_t pool;
	pool_init( &pool, 4, 1, allocator_default( ) );
	item = pool_take( &pool );
	pool_return( &pool, item );
	TEST_REQUIRE( pool_take( &pool ) == item );
	pool_cleanup( &pool );
}
Example #12
0
static void _ensure_pool_take_returns_null_when_empty( void )
{
	void * item;
	pool_t pool;
	pool_init( &pool, 4, 1, allocator_default( ) );
	pool_take( &pool );
	item = pool_take( &pool );
	TEST_REQUIRE( item == 0 );
	pool_cleanup( &pool );
}
Example #13
0
static void _ensure_pool_take_returns_object_when_not_empty( void )
{
	void * item;
	pool_t pool;
	pool_init( &pool, 4, 16, allocator_default( ) );
	item = pool_take( &pool );
	TEST_REQUIRE( item );
	item = 0;
	pool_cleanup( &pool );
}
Example #14
0
static void _ensure_pool_cleanup_releases_underlying_buffer( void )
{
	allocator_counted_t alloc;
	pool_t pool;

	allocator_counted_init_default( &alloc );
	pool_init( &pool, 4, 16, allocator_counted_get( &alloc ) );
	pool_cleanup( &pool );
	TEST_REQUIRE( allocator_counted_get_current_count( &alloc ) == 0 );
}
Example #15
0
static void _ensure_pool_init_with_zero_element_count_constructs_valid_empty_pool( void )
{
	allocator_counted_t alloc;
	pool_t pool;

	allocator_counted_init_default( &alloc );
	pool_init( &pool, 4, 0, allocator_counted_get( &alloc ) );
	TEST_REQUIRE( pool_is_empty( &pool ) );
	pool_cleanup( &pool );
	TEST_REQUIRE( allocator_counted_get_current_count( &alloc ) == 0 );
}
Example #16
0
void slab_cleanup(slab_ctxt_t *ctxt)
{
    /* any data to destruct ?*/
    if(ctxt->destructor) {
        while( ++ctxt->const_bottom < ctxt->pool.count) {
            void *object = pool_get_raw(& ctxt->pool, ctxt->const_bottom);
            ctxt->destructor( object, ctxt->userdata);
        }
    }
    /* now cleanup the pool */
    pool_cleanup(& ctxt->pool);
}
Example #17
0
// ---------------------------------------------------------------------
//  _dc_cleanup_pools
// ---------------------------------------------------------------------
void _dc_cleanup_pools() {

    if (dc_init_cons_pool_g != NULL)
        pool_cleanup(dc_init_cons_pool_g);

    if (dc_group_pool_g != NULL)
        pool_cleanup(dc_group_pool_g);

    if (dc_cons_pool_g != NULL)
        pool_cleanup(dc_cons_pool_g);

    if (dc_cell_pool_g != NULL)
        pool_cleanup(dc_cell_pool_g);

    if (dc_dep_pool_g != NULL)
        pool_cleanup(dc_dep_pool_g);

    dc_init_cons_pool_g = dc_group_pool_g = 
        dc_cons_pool_g = dc_cell_pool_g = 
            dc_dep_pool_g = NULL;
}
Example #18
0
/* public queue creation function, queue lives as long as the pool */
mtq mtq_new_que(pool p,  mtq que)
{
    mtq q;
    int n,mtq_n;
    int count;

    log_debug(ZONE,"MTQ(new)");


	if (p==NULL)
	  return NULL;

    if(mtq__master == NULL)  {
	  mtq_init();
	}
	
	if (que) {
	  que->users_count++;
	  pool_cleanup(p, mtq_cleanup, (void *)que);
	  return que;
	}

	/* find queue with less users */
	count=999999;
	mtq_n = 0;
	for(n = 0; n < MTQ_THREADS; n++)
	  if(mtq__master->all[n]->mtq->users_count < count)  {	    
		count = mtq__master->all[n]->mtq->users_count;
		mtq_n = n;
	  }
	q = mtq__master->all[mtq_n]->mtq;    

    q->users_count++;    
    pool_cleanup(p, mtq_cleanup, (void *)q);

    return q;
}
Example #19
0
/**
 * main
 */
int main(int argc, char *argv[])
{
    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
    struct mysqlfs_opt opt = {
	.init_conns	= 1,
	.max_idling_conns = 5,
	.mycnf_group	= "mysqlfs",
#ifdef DEBUG
	.logfile	= "mysqlfs.log",
#endif
    };

    log_file = stderr;

    /** theopts kludge is used for both statusdir (if configured at build) and for osxnospotlight */
    theopts = &opt;

    fuse_opt_parse(&args, &opt, mysqlfs_opts, mysqlfs_opt_proc);

    if (pool_init(&opt) < 0) {
        log_printf(LOG_ERROR, "Error: pool_init() failed\n");
        fuse_opt_free_args(&args);
        return EXIT_FAILURE;        
    }

    /*
     * I found that -- running from a script (ie no term?) -- the MySQLfs would not background, so the terminal is held; this makes automated testing difficult.
     *
     * I (allanc) put this into here to allow for AUTOTEST, but then autotest has to seek-and-destroy the app.  This isn't quite perfect yet, I get some flakiness here, othertines the pid is 4 more than the parent, which is odd.
     */
    if (0 < opt.bg)
    {
        if (0 < fork())
            return EXIT_SUCCESS;
        //else
        //    fprintf (stderr, "forked %d\n", getpid());
    }

    /* only create a log file if we have a logfile set; note that --enable-debug sets a default above */
    if (NULL != opt.logfile)
        log_file = log_init(opt.logfile, 1);

    fuse_main(args.argc, args.argv, &mysqlfs_oper);
    fuse_opt_free_args(&args);

    pool_cleanup();

    return EXIT_SUCCESS;
}
Example #20
0
File: user.c Project: 6wei/jabberd2
/** make a new one */
static user_t _user_alloc(sm_t sm, jid_t jid) {
    pool_t p;
    user_t user;

    p = pool_new();

    user = (user_t) pmalloco(p, sizeof(struct user_st));

    user->p = p;
    user->sm = sm;

    user->jid = jid_dup(jid);
    pool_cleanup(p, (void (*)(void *)) jid_free, user->jid);

    /* a place for modules to store stuff */
    user->module_data = (void **) pmalloco(p, sizeof(void *) * sm->mm->nindex);

    return user;
}
Example #21
0
// Rate limit check:  Prevent denial-of-service due to excessive database queries
// Make sure owner is responsible for the query!
int sm_storage_rate_limit(sm_t sm, const char *owner) {
    rate_t rt;
    user_t user;
    sess_t sess;
    item_t item;

    if (sm->query_rate_total == 0 || owner == NULL)
    return FALSE;

    user = xhash_get(sm->users, owner);
    if (user != NULL) {
        rt = (rate_t) xhash_get(sm->query_rates, owner);
        if (rt == NULL) {
            rt = rate_new(sm->query_rate_total, sm->query_rate_seconds, sm->query_rate_wait);
            xhash_put(sm->query_rates, pstrdup(xhash_pool(sm->query_rates), owner), (void *) rt);
            pool_cleanup(xhash_pool(sm->query_rates), (void (*)(void *)) rate_free, rt);
        }

        if(rate_check(rt) == 0) {
            log_write(sm->log, LOG_WARNING, "[%s] is being disconnected, too many database queries within %d seconds", owner, sm->query_rate_seconds);
            user = xhash_get(sm->users, owner);
            for (sess = user->sessions; sess != NULL; sess = sess->next) {
                sm_c2s_action(sess, "ended", NULL);
            }
            if(xhash_iter_first(user->roster))
                do {
                    xhash_iter_get(user->roster, NULL, NULL, (void *) &item);
                    if(item->to) {
                        pkt_router(pkt_create(user->sm, "presence", "unavailable", jid_full(item->jid), jid_full(user->jid)));
                    }
                } while(xhash_iter_next(user->roster));
            return TRUE;
            } else {
                rate_add(rt, 1);
            }
        } else {
            log_debug(ZONE, "Error: could not get user data for %s", owner);
    }
    return FALSE;
}
Example #22
0
result base_file_config(instance id, xmlnode x, void *arg)
{
    basefile bf;
        
    if(id == NULL)
    {
        log_debug(ZONE,"base_file_config validating configuration");

        if (xmlnode_get_data(x) == NULL)
        {
            log_debug(ZONE,"base_file_config error: no filename provided.");
            xmlnode_put_attrib(x,"error","'file' tag must contain a filename to write to");
            return r_ERR;
        }
        return r_PASS;
    }

    log_debug(ZONE,"base_file configuring instance %s",id->id);

    if(id->type != p_LOG)
    {
        log_alert(NULL,"ERROR in instance %s: <file>..</file> element only allowed in log sections", id->id);
        return r_ERR;
    }

    bf = pmalloco(id->p,sizeof(_basefile));
    bf->filename = pstrdup(id->p,xmlnode_get_data(x));
    bf->yesterday.tm_mday = -1;
    bf->last_time = 0;
    bf->f = NULL;
    pthread_mutex_init(&(bf->sem),NULL);

    /* Register a handler for this instance... */
    register_phandler(id, o_DELIVER, base_file_deliver, (void*)bf);

    pool_cleanup(id->p, _base_file_shutdown, (void*)bf);
    
    return r_DONE;
}
Example #23
0
os_object_t os_object_new(os_t os) {
    os_object_t o;

    log_debug(ZONE, "creating new object");

    o = (os_object_t) pmalloco(os->p, sizeof(struct os_object_st));
    o->os = os;

    o->hash = xhash_new(51);

    /* make sure that the hash gets freed when the os pool gets freed */
    pool_cleanup(os->p, (pool_cleanup_t) xhash_free, (void *)(o->hash) );

    /* insert at the end, we have to preserve order */
    o->prev = os->tail;
    if(os->tail != NULL) os->tail->next = o;
    os->tail = o;
    if(os->head == NULL) os->head = o;
    
    os->count++;

    return o;
}
Example #24
0
void os_object_put(os_object_t o, const char *key, const void *val, os_type_t type) {
    os_field_t osf;
    nad_t nad;

    log_debug(ZONE, "adding field %s (val %x type %d) to object", key, val, type);

    osf = pmalloco(o->os->p, sizeof(struct os_field_st));
    osf->key = pstrdup(o->os->p, key);

    switch(type) {
        case os_type_BOOLEAN:
        case os_type_INTEGER:
            osf->val = (void *) (intptr_t) (* (int *) val);
            break;

        case os_type_STRING:
            osf->val = (void *) pstrdup(o->os->p, (char *) val);
            break;

        case os_type_NAD:
            nad = nad_copy((nad_t) val);

            /* make sure that the nad gets freed when the os pool gets freed */
            pool_cleanup(o->os->p, (pool_cleanup_t) nad_free, (void *) nad);

            osf->val = (void *) nad;
            break;

        case os_type_UNKNOWN:
            break;
    }

    osf->type = type;

    xhash_put(o->hash, osf->key, (void *) osf);
}
Example #25
0
int os_object_get(os_t os, os_object_t o, const char *key, void **val, os_type_t type, os_type_t *ot) {
    os_field_t osf;
    nad_t nad;

   /* Type complexity is to deal with string/NADs. If an object contains xml, it will only be 
      parsed and returned as a NAD if type == os_type_NAD, otherwise if type == os_type_UNKNOWN
      it will be returned as string, unless it's already been converted to a NAD */

    osf = (os_field_t) xhash_get(o->hash, key);
    if(osf == NULL) {
        *val = NULL;
        return 0;
    }

    if (ot != NULL)
      *ot = osf->type; 

    if (type == os_type_UNKNOWN)
      type = osf->type;

    if (type == os_type_UNKNOWN)
      type = osf->type; 

    switch(type) {
        case os_type_BOOLEAN:
        case os_type_INTEGER:
            * (int *) val = (int) (intptr_t) osf->val;
            break;

        case os_type_STRING:
            *val = osf->val;
            break;

        case os_type_NAD:
            /* check to see whether it's already a NAD */
            if (osf->type == os_type_NAD) {
                   *val = osf->val;  
            } else {
                   /* parse the string into a NAD */
                   nad = nad_parse(((char *) osf->val) + 3, strlen(osf->val) - 3); 
                   if(nad == NULL) {
                            /* unparseable NAD */
                            log_debug(ZONE, "cell returned from storage for key %s has unparseable XML content (%lu bytes)", key, strlen(osf->val)-3);
                            *val = NULL;
                            return 0;
                   } 

                   /* replace the string with a NAD */
                   osf->val = (void *) nad;

                   pool_cleanup(os->p, (pool_cleanup_t) nad_free, (void *) nad);

                   *val = osf->val;
                   osf->type = os_type_NAD;

            }
            break;

        default:
            *val = NULL;
    }

    log_debug(ZONE, "got field %s (val %x type %d) to object", key, *val, type);

    return 1;
}
Example #26
0
static void _ensure_pool_cleanup_gracefully_handles_null_pool( void )
{
	pool_cleanup( 0 );
}
Example #27
0
void dnsrv(instance i, xmlnode x)
{
     xdbcache xc = NULL;
     xmlnode  config = NULL;
     xmlnode  iternode   = NULL;
     dns_resend_list tmplist = NULL;

     /* Setup a struct to hold dns_io handles */
     dns_io di;
     di = pmalloco(i->p, sizeof(_dns_io));

     di->mempool = i->p;

     /* Load config from xdb */
     xc = xdb_cache(i);
     config = xdb_get(xc, jid_new(xmlnode_pool(x), "config@-internal"), "jabber:config:dnsrv");

     /* Build a list of services/resend hosts */
     iternode = xmlnode_get_lastchild(config);
     while (iternode != NULL)
     {
          if (j_strcmp("resend", xmlnode_get_name(iternode)) != 0)
          {
               iternode = xmlnode_get_prevsibling(iternode);
               continue;
          }

          /* Allocate a new list node */
          tmplist = pmalloco(di->mempool, sizeof(_dns_resend_list));
          tmplist->service = pstrdup(di->mempool, xmlnode_get_attrib(iternode, "service"));
          tmplist->host    = pstrdup(di->mempool, xmlnode_get_data(iternode));
          /* Insert this node into the list */
          tmplist->next = di->svclist;    
          di->svclist = tmplist;
          /* Move to next child */
          iternode = xmlnode_get_prevsibling(iternode);
     }
     log_debug(ZONE, "dnsrv debug: %s\n", xmlnode2str(config));

     /* Setup the hash of dns_packet_list */
     di->packet_table = xhash_new(j_atoi(xmlnode_get_attrib(config,"queuemax"),101));
     di->packet_timeout = j_atoi(xmlnode_get_attrib(config,"queuetimeout"),60);
     register_beat(di->packet_timeout, dnsrv_beat_packets, (void *)di);


     /* Setup the internal hostname cache */
     di->cache_table = xhash_new(j_atoi(xmlnode_get_attrib(config,"cachemax"),1999));
     di->cache_timeout = j_atoi(xmlnode_get_attrib(config,"cachetimeout"),3600); /* 1 hour dns cache? XXX would be nice to get the right value from dns! */

     xmlnode_free(config);

     /* spawn a thread that get's forked, and wait for it since it sets up the fd's */
     pth_join(pth_spawn(PTH_ATTR_DEFAULT,(void*)dnsrv_thread,(void*)di),NULL);

     if(di->pid < 0)
     {
         log_error(i->id,"dnsrv failed to start, unable to fork and/or create pipes");
         return;
     }

     /* Start IO thread */
     pth_spawn(PTH_ATTR_DEFAULT, dnsrv_process_io, di);

     /* Register an incoming packet handler */
     register_phandler(i, o_DELIVER, dnsrv_deliver, (void*)di);
     /* register a cleanup function */
     pool_cleanup(i->p, dnsrv_shutdown, (void*)di);
}
Example #28
0
static mod_ret_t _iq_private_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
    module_t mod = mi->mod;
    int ns, elem, target, targetns;
    st_ret_t ret;
    char filter[4096];
    os_t os;
    os_object_t o;
    nad_t nad;
    pkt_t result;
    sess_t sscan;

    /* only handle private sets and gets */
    if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_PRIVATE)
        return mod_PASS;

    /* we're only interested in no to, to our host, or to us */
    if(pkt->to != NULL && jid_compare_user(sess->jid, pkt->to) != 0 && strcmp(sess->jid->domain, jid_user(pkt->to)) != 0)
        return mod_PASS;

    ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVATE, NULL);
    elem = nad_find_elem(pkt->nad, 1, ns, "query", 1);

    /* find the first child */
    target = elem + 1;
    while(target < pkt->nad->ecur)
    {
        if(pkt->nad->elems[target].depth > pkt->nad->elems[elem].depth)
            break;

        target++;
    }

    /* not found, so we're done */
    if(target == pkt->nad->ecur)
        return -stanza_err_BAD_REQUEST;

    /* find the target namespace */
    targetns = NAD_ENS(pkt->nad, target);

    /* gotta have a namespace */
    if(targetns < 0)
    {
        log_debug(ZONE, "no namespace specified");
        return -stanza_err_BAD_REQUEST;
    }

    log_debug(ZONE, "processing private request for %.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));

    /* get */
    if(pkt->type == pkt_IQ) {
#ifdef ENABLE_EXPERIMENTAL
        /* remember that this resource requested the namespace */
        if(sess->module_data[mod->index] == NULL) {
            /* create new hash if necesary */
            sess->module_data[mod->index] = xhash_new(101);
            pool_cleanup(sess->p, (void (*))(void *) xhash_free, sess->module_data[mod->index]);
        }
        xhash_put(sess->module_data[mod->index], pstrdupx(sess->p, NAD_NURI(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns)), (void *) 1);
#endif
        snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
        ret = storage_get(sess->user->sm->st, "private", jid_user(sess->jid), filter, &os);
        switch(ret) {
            case st_SUCCESS:
                if(os_iter_first(os)) {
                    o = os_iter_object(os);
                    if(os_object_get_nad(os, o, "xml", &nad)) {
                        result = pkt_new(sess->user->sm, nad_copy(nad));
                        if(result != NULL) {
                            nad_set_attr(result->nad, 1, -1, "type", "result", 6);

                            pkt_id(pkt, result);

                            pkt_sess(result, sess);

                            pkt_free(pkt);

                            os_free(os);
                
                            return mod_HANDLED;
                        }
                    }
                }

                os_free(os);

                /* drop through */
                log_debug(ZONE, "storage_get succeeded, but couldn't make packet, faking st_NOTFOUND");

            case st_NOTFOUND:

                log_debug(ZONE, "namespace not found, returning");

                /*
                 * !!! really, we should just return a 404. 1.4 just slaps a
                 *     result on the packet and sends it back. hurrah for
                 *     legacy namespaces.
                 */
                nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);

                pkt_sess(pkt_tofrom(pkt), sess);
                
                return mod_HANDLED;

            case st_FAILED:
                return -stanza_err_INTERNAL_SERVER_ERROR;

            case st_NOTIMPL:
                return -stanza_err_FEATURE_NOT_IMPLEMENTED;
        }
    }

    os = os_new();
    o = os_object_new(os);

    snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
    os_object_put(o, "ns", filter, os_type_STRING);
    os_object_put(o, "xml", pkt->nad, os_type_NAD);

    snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));

    ret = storage_replace(sess->user->sm->st, "private", jid_user(sess->jid), filter, os);
    os_free(os);

    switch(ret) {
        case st_FAILED:
            return -stanza_err_INTERNAL_SERVER_ERROR;

        case st_NOTIMPL:
            return -stanza_err_FEATURE_NOT_IMPLEMENTED;

        default:
            /* create result packet */
            result = pkt_create(sess->user->sm, "iq", "result", NULL, NULL);
            pkt_id(pkt, result);
            /* and flush it to the session */
            pkt_sess(result, sess);
#ifdef ENABLE_EXPERIMENTAL
            /* push it to all resources that read this xmlns item */
            snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
            for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
                /* skip our resource and those that didn't read any private-storage */
                if(sscan == sess || sscan->module_data[mod->index] == NULL)
                    continue;

                /* check whether namespace was read */
                if(xhash_get(sscan->module_data[mod->index], filter)) {
                    result = pkt_dup(pkt, jid_full(sscan->jid), NULL);
                    if(result->from != NULL) {
                        jid_free(result->from);
                        nad_set_attr(result->nad, 1, -1, "from", NULL, 0);
                    }
                    pkt_id_new(result);
                    pkt_sess(result, sscan);
                }
            }
#endif
            /* finally free the packet */
            pkt_free(pkt);
            return mod_HANDLED;
    }

    /* we never get here */
    return 0;
}
Example #29
0
File: sess.c Project: 6wei/jabberd2
sess_t sess_start(sm_t sm, jid_t jid) {
    pool_t p;
    user_t user;
    sess_t sess, scan;
    sha1_state_t sha1;
    unsigned char hash[20];
    int replaced = 0;

    log_debug(ZONE, "session requested for %s", jid_full(jid));

    /* check whether it is to serviced domain */
    if(xhash_get(sm->hosts, jid->domain) == NULL) {
        log_write(sm->log, LOG_ERR, "request to start session in non-serviced domain: jid=%s", jid_full(jid));
        return NULL;
    }

    /* get user data for this guy */
    user = user_load(sm, jid);

    /* unknown user */
    if(user == NULL) {
        if(config_get(sm->config, "user.auto-create") == NULL) {
            log_write(sm->log, LOG_NOTICE, "user not found and user.auto-create not enabled, can't start session: jid=%s", jid_full(jid));
            return NULL;
        }

        log_debug(ZONE, "auto-creating user %s", jid_user(jid));

        if(user_create(sm, jid) != 0)
            return NULL;

        user = user_load(sm, jid);
        if(user == NULL) {
            log_write(sm->log, LOG_NOTICE, "couldn't load user, can't start session: jid=%s", jid_full(jid));
            return NULL;
        }
    }

    /* kill their old session if they have one */
    for(scan = user->sessions; scan != NULL; scan = scan->next)
        if(jid_compare_full(scan->jid, jid) == 0) {
            log_debug(ZONE, "replacing session %s (%s)", jid_full(jid), scan->c2s_id);

            /* !!! this "replaced" stuff is a hack - its really a subaction of "ended".
             *     hurrah, another control protocol rewrite is needed :(
             */
            sm_c2s_action(scan, "replaced", NULL);

            _sess_end_guts(scan);

            pool_free(scan->p);

            replaced = 1;

            break;
        }

    /* make a new session */
    p = pool_new();

    sess = (sess_t) pmalloco(p, sizeof(struct sess_st));
    sess->p = p;

    /* fill it out */
    sess->pri = 0;
    sess->user = user;

    sess->jid = jid_dup(jid);
    pool_cleanup(sess->p, (void (*))(void *) jid_free, sess->jid);

    /* a place for modules to store stuff */
    sess->module_data = (void **) pmalloco(sess->p, sizeof(void *) * sess->user->sm->mm->nindex);

    /* add it to the list */
    sess->next = user->sessions;
    user->sessions = sess;

    /* who c2s should address things to */
    sha1_init(&sha1);
    datetime_out(time(NULL), dt_DATETIME, sess->sm_id, 41);
    sha1_append(&sha1, sess->sm_id, strlen(sess->sm_id));
    sha1_append(&sha1, jid_full(sess->jid), strlen(jid_full(sess->jid)));
    sha1_finish(&sha1, hash);
    hex_from_raw(hash, 20, sess->sm_id);

    log_debug(ZONE, "smid is %s", sess->sm_id);

    /* remember it */
    xhash_put(sm->sessions, sess->sm_id, sess);

    /* inform the modules */
    /* !!! catch the return value - if its 1, don't let them in */
    mm_sess_start(sm->mm, sess);

    if(replaced)
        log_write(sm->log, LOG_NOTICE, "session replaced: jid=%s", jid_full(sess->jid));
    else
        log_write(sm->log, LOG_NOTICE, "session started: jid=%s", jid_full(sess->jid));
            
    return sess;
}