xht xhash_new(int prime) { xht xnew; pool p; /* log_debug(ZONE,"creating new hash table of size %d",prime); */ p = pool_heap(sizeof(_xhn) * prime + sizeof(_xht)); xnew = pmalloco(p, sizeof(_xht)); xnew->prime = prime; xnew->p = p; xnew->zen = pmalloco(p, sizeof(_xhn) * prime); /* array of xhn size of prime */ return xnew; }
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; }
/* actually deliver the xdb request */ void xdb_deliver(instance i, xdbcache xc, int another_thread) { xmlnode x; char ids[15]; x = xmlnode_new_tag("xdb"); if(xc->set) { xmlnode_put_attrib(x,"type","set"); xmlnode_insert_tag_node(x,xc->data); /* copy in the data */ if(xc->act != NULL) xmlnode_put_attrib(x,"action",xc->act); if(xc->match != NULL) xmlnode_put_attrib(x,"match",xc->match); } else { xmlnode_put_attrib(x,"type","get"); } xmlnode_put_attrib(x,"to",jid_full(xc->owner)); xmlnode_put_attrib(x,"from",i->id); xmlnode_put_attrib(x,"ns",xc->ns); sprintf(ids,"%d",xc->id); xmlnode_put_attrib(x,"id",ids); /* to track response */ if (another_thread) { xdb_resend cur = pmalloco(xmlnode_pool(x),sizeof(_xdb_resend)); cur->x = x; cur->i = i; mtq_send(NULL,NULL,resend_xdb,(void *)cur); } else { deliver(dpacket_new(x), i); } }
/** * init the module, register callbacks * * builds a list of JabberIDs where presences should be blind carbon copied to. * (Enclosing each in a <bcc/> element, which are contained in one <presence/> * element in the session manager configuration.) * * registers mod_presence_session() as a callback, that gets notified on new sessions * and mod_presence_deliver() as a callback to deliver presence stanzas locally. * * @param si the session manager instance */ JSM_FUNC void mod_presence(jsmi si) { xmlnode cfg = js_config(si, "presence"); modpres_conf conf = (modpres_conf) pmalloco(si->p, sizeof(_modpres_conf)); log_debug("init"); for (cfg = xmlnode_get_firstchild(cfg); cfg != NULL; cfg = xmlnode_get_nextsibling(cfg)) { char *element_name = NULL; if (xmlnode_get_type(cfg) != NTYPE_TAG) continue; element_name = xmlnode_get_name(cfg); if (j_strcmp(element_name, "bcc") == 0) { if (conf->bcc == NULL) conf->bcc = jid_new(si->p, xmlnode_get_data(cfg)); else jid_append(conf->bcc, jid_new(si->p, xmlnode_get_data(cfg))); } else if (j_strcmp(element_name, "presence2xdb") == 0) { conf->pres_to_xdb++; } } js_mapi_register(si, e_DELIVER, mod_presence_deliver, NULL); js_mapi_register(si, e_SESSION, mod_presence_session, (void *) conf); }
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); }
/* handle a packet from jabberd */ result at_phandler(instance i,dpacket p,void *arg) { int ret; ati ti; at_mtq_data amd; if(i == NULL || p == NULL) return r_ERR; ti = (ati)arg; switch(p->type) { case p_NONE: case p_NORM: log_debug(ZONE, "[AT] we got a packet from jabberd: %s", xmlnode2str(p->x)); amd = pmalloco(p->p, sizeof(_at_mtq_data)); amd->jp = jpacket_new(p->x); amd->p = p->p; amd->ti = ti; mtq_send(NULL, p->p, at_parse_packet, (void *)amd); return r_DONE; default: log_debug(ZONE, "[AT] ignoring packet from jabberd: %s", xmlnode2str(p->x)); return r_PASS; } }
xmlnode xdb_file_parse(char *file,pool p) { XML_Parser parser; xf_parse xfp; char buf[READ_BUF_SIZE]; int done, fd, len; if(NULL == file) return NULL; fd = open(file,O_RDONLY); if(fd < 0) return NULL; xfp = pmalloco(p,sizeof(_xf_parse)); xfp->p = p; parser = XML_ParserCreate(NULL); XML_SetUserData(parser, xfp); XML_SetElementHandler(parser, xdb_file_startElement, xdb_file_endElement); XML_SetCharacterDataHandler(parser, xdb_file_charData); do{ len = read(fd, buf, READ_BUF_SIZE); done = len < READ_BUF_SIZE; if(!XML_Parse(parser, buf, len, done)) done = 1; }while(!done); XML_ParserFree(parser); close(fd); return xfp->current; }
void mtq_init() { mtq mtq = NULL; /* queue */ mth t = NULL; int n,k; pool newp; mtq__master = malloc(sizeof(_mtqmaster)); /* happens once, global */ mtq__master->random = 0; /* start MTQ threads */ for(n=0;n<MTQ_THREADS;n++) { newp = pool_new(); t = pmalloco(newp, sizeof(_mth)); t->p = newp; t->mtq = pmalloco(newp,sizeof(_mtq)); t->mtq->first = t->mtq->last = NULL; t->mtq->free_first = t->mtq->free_last = NULL; t->mtq->users_count = 0; t->mtq->dl = 0; t->mtq->length = 0; mtq = t->mtq; /* build queue cache */ for (k=0;k<MTQ_QUEUE_LONG;k++) { /* mtq->free_last if the first to take from queue*/ mtq->queue[k].memory = 0; mtq->queue[k].prev = NULL; /* if queue is empty */ if (mtq->free_last == NULL) mtq->free_last = &(mtq->queue[k]); else mtq->free_first->prev = &(mtq->queue[k]); mtq->free_first = &(mtq->queue[k]); mtq->length++; } SEM_INIT(t->mtq->sem); COND_INIT(t->mtq->cond); pthread_create(&(t->thread), NULL, mtq_main, (void *)t); mtq__master->all[n] = t; /* assign it as available */ } }
static void _s2s_hosts_expand(s2s_t s2s) { char *realm; config_elem_t elem; char id[1024]; int i; elem = config_get(s2s->config, "local.id"); if (elem) for(i = 0; i < elem->nvalues; i++) { host_t host = (host_t) pmalloco(xhash_pool(s2s->hosts), sizeof(struct host_st)); if(!host) { log_write(s2s->log, LOG_ERR, "cannot allocate memory for new host, aborting"); exit(1); } realm = j_attr((const char **) elem->attrs[i], "realm"); /* stringprep ids (domain names) so that they are in canonical form */ strncpy(id, elem->values[i], 1024); id[1023] = '\0'; if (stringprep_nameprep(id, 1024) != 0) { log_write(s2s->log, LOG_ERR, "cannot stringprep id %s, aborting", id); exit(1); } host->realm = (realm != NULL) ? realm : pstrdup(xhash_pool(s2s->hosts), id); host->host_pemfile = j_attr((const char **) elem->attrs[i], "pemfile"); host->host_cachain = j_attr((const char **) elem->attrs[i], "cachain"); host->host_verify_mode = j_atoi(j_attr((const char **) elem->attrs[i], "verify-mode"), 0); #ifdef HAVE_SSL if(host->host_pemfile != NULL) { if(s2s->sx_ssl == NULL) { s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode); if(s2s->sx_ssl == NULL) { log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm); host->host_pemfile = NULL; } } else { if(sx_ssl_server_addcert(s2s->sx_ssl, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode) != 0) { log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm); host->host_pemfile = NULL; } } } #endif /* insert into vHosts xhash */ xhash_put(s2s->hosts, pstrdup(xhash_pool(s2s->hosts), id), host); log_write(s2s->log, LOG_NOTICE, "[%s] configured; realm=%s", id, host->realm); } }
/** 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; }
/* Hostname lookup requested */ void dnsrv_lookup(dns_io d, dpacket p) { dns_packet_list l, lnew; xmlnode req; char *reqs; /* make sure we have a child! */ if(d->out <= 0) { deliver_fail(p, "DNS Resolver Error"); return; } /* Attempt to lookup this hostname in the packet table */ l = (dns_packet_list)xhash_get(d->packet_table, p->host); /* IF: hashtable has the hostname, a lookup is already pending, so push the packet on the top of the list (most recent at the top) */ if (l != NULL) { log_debug(ZONE, "dnsrv: Adding lookup request for %s to pending queue.", p->host); lnew = pmalloco(p->p, sizeof(_dns_packet_list)); lnew->packet = p; lnew->stamp = time(NULL); lnew->next = l; xhash_put(d->packet_table, p->host, lnew); return; } /* insert the packet into the packet_table using the hostname as the key and send a request to the coprocess */ log_debug(ZONE, "dnsrv: Creating lookup request queue for %s", p->host); l = pmalloco(p->p, sizeof(_dns_packet_list)); l->packet = p; l->stamp = time(NULL); xhash_put(d->packet_table, p->host, l); req = xmlnode_new_tag_pool(p->p,"host"); xmlnode_insert_cdata(req,p->host,-1); reqs = xmlnode2str(req); log_debug(ZONE, "dnsrv: Transmitting lookup request: %s", reqs); pth_write(d->out, reqs, strlen(reqs)); }
/* match will find a child in the parent, and either replace (if it's an insert) or remove (if data is NULL) */ int xdb_act(xdbcache xc, jid owner, char *ns, char *act, char *match, xmlnode data) { xdbcache newx; pool p; if(xc == NULL || owner == NULL || ns == NULL) { fprintf(stderr,"Programming Error: xdb_set() called with NULL\n"); return 1; } log_debug(ZONE,"XDB SET"); /* init this newx */ p = pool_new(); newx = pmalloco(p, sizeof(_xdbcache)); newx->i = xc->i; newx->set = 1; newx->data = data; newx->ns = ns; newx->act = act; newx->match = match; newx->owner = owner; newx->sent = time(NULL); newx->preblock = 0; /* flag */ pthread_mutex_lock(&(xc->sem)); newx->id = xc->id++; newx->next = xc->next; newx->prev = xc; newx->next->prev = newx; xc->next = newx; pthread_mutex_unlock(&(xc->sem)); /* send it on it's way */ xdb_deliver(xc->i, newx,0); /* if it hasn't already returned, we should block here until it returns */ while (newx->preblock != 1) usleep(10); /* if it didn't actually get set, flag that */ if(newx->data == NULL) { pool_free(p); return 1; } xmlnode_free(newx->data); pool_free(p); return 0; }
os_t os_new(void) { pool_t p; os_t os; p = pool_new(); os = (os_t) pmalloco(p, sizeof(struct os_st)); os->p = p; return os; }
void js_session_from(session s, jpacket jp) { packet_thread_p pt; /* queue the call to child, hide session in packet */ jp->aux1 = (void *) s; pt = pmalloco(jp->p, sizeof(packet_thread_t)); pt->jp = jp; pt->type = 2; fast_mtq_send(s->q->mtq, pt); }
/* * js_session_end -- shut down the session * * This function gets called when the user disconnects or when the server shuts * down. It changes the user's presence to offline, cleans up the session data * and sends an end spacket * * parameters * s -- the session to end * reason -- the reason the session is shutting down (for logging) * */ void js_session_end(session s, char *reason) { session cur; /* used to iterate over the user's session list when removing the session from the list */ /* ignore illegal calls */ if (s == NULL || s->exit_flag == 1 || reason == NULL) return; /* so it doesn't get freed */ THREAD_INC(s->u->ref); /* log the reason the session ended */ log_debug("end %d '%s'", s, reason); /* flag the session to exit ASAP */ s->exit_flag = 1; /* make sure we're not the primary session */ s->priority = -129; /* presence will be updated in _js_session_end to be shore that only session thread is changing this value */ /* * remove this session from the user's session list -- * first check if this session is at the head of the list */ SEM_LOCK(s->u->sem); if (s == s->u->sessions) { /* yup, just bump up the next session */ s->u->sessions = s->next; } else { /* no, we have to traverse the list to find it */ for (cur = s->u->sessions; cur->next != s; cur = cur->next); cur->next = s->next; } s->u->scount--; SEM_UNLOCK(s->u->sem); /* end */ { packet_thread_p pt; pt = pmalloco(s->p, sizeof(packet_thread_t)); pt->s = s; pt->type = 1; fast_mtq_send(s->q->mtq, pt); } }
jqueue_t jqueue_new(void) { pool_t p; jqueue_t q; p = pool_new(); q = (jqueue_t)pmalloco(p, sizeof(struct _jqueue_st)); q->p = p; q->init_time = time(NULL); return q; }
/* blocks until namespace is retrieved, host must map back to this service! */ xmlnode xdb_get(xdbcache xc, jid owner, char *ns) { xdbcache newx; xmlnode x; pool p; if(xc == NULL || owner == NULL || ns == NULL) { fprintf(stderr,"Programming Error: xdb_get() called with NULL\n"); return NULL; } log_debug(ZONE,"XDB GET"); /* init this newx */ p = pool_new(); newx = pmalloco(p, sizeof(_xdbcache)); newx->i = xc->i; newx->set = 0; newx->data = NULL; newx->ns = ns; newx->owner = owner; newx->sent = time(NULL); newx->preblock = 0; /* flag */ pthread_mutex_lock(&(xc->sem)); newx->id = xc->id++; newx->next = xc->next; newx->prev = xc; newx->next->prev = newx; xc->next = newx; pthread_mutex_unlock(&(xc->sem)); /* send it on it's way */ xdb_deliver(xc->i, newx,0); /* if it hasn't already returned, we should block here until it returns */ while (newx->preblock != 1) usleep(10); /* newx.data is now the returned xml packet */ /* return the xmlnode inside <xdb>...</xdb> */ for(x = xmlnode_get_firstchild(newx->data); x != NULL && xmlnode_get_type(x) != NTYPE_TAG; x = xmlnode_get_nextsibling(x)); /* there were no children (results) to the xdb request, free the packet */ if(x == NULL) xmlnode_free(newx->data); pool_free(p); return x; }
jid jid_user(jid a) { jid ret; if(a == NULL || a->resource == NULL) return a; ret = pmalloco(a->p,sizeof(struct jid_struct)); ret->p = a->p; ret->user = a->user; ret->server = a->server; return ret; }
jid jid_new(pool p, const char *idstr) { char *server, *resource, *type, *str; jid id; if(p == NULL || idstr == NULL || *idstr == '\0') return NULL; /* user@server/resource */ str = pstrdup(p, idstr); id = pmalloco(p,sizeof(struct jid_struct)); id->p = p; resource = strstr(str,"/"); if(resource != NULL) { *resource = '\0'; ++resource; if(*resource != '\0') id->resource = resource; }else{ resource = str + strlen(str); /* point to end */ } type = strstr(str,":"); if(type != NULL && type < resource) { *type = '\0'; ++type; str = type; /* ignore the type: prefix */ } server = strstr(str,"@"); if(server == NULL || server > resource) { /* if there's no @, it's just the server address */ id->server = str; }else{ *server = '\0'; ++server; id->server = server; if(*str != '\0') id->user = str; } return jid_safe(id); }
xhn _xhash_node_new(xht h, int index) { xhn n; int i = index % h->prime; /* get existing empty one */ for (n = &h->zen[i]; n != NULL; n = n->next) if (n->key == NULL) return n; /* overflowing, new one! */ n = pmalloco(h->p, sizeof(_xhn)); n->next = h->zen[i].next; h->zen[i].next = n; return n; }
/** * callback, that gets called if a new session is establisched, registers all session oriented callbacks * * This callback is responsible for initializing a new instance of the _modpres structure, that holds * the list of entites that know that a user is available. * * @param m the mapi structure * @param arg the list of JabberIDs that get a bcc of all presences * @return always M_PASS */ mreturn mod_presence_session(mapi m, void *arg) { modpres_conf conf = (modpres_conf) arg; modpres mp; /* track our session stuff */ mp = pmalloco(m->s->p, sizeof(_modpres)); // mp->A = jid_user(m->s->id); mp->A = m->s->uid; mp->conf = conf; /* no no, it's ok, these live longer than us */ js_mapi_session(es_IN, m->s, mod_presence_in, mp); js_mapi_session(es_OUT, m->s, mod_presence_avails, mp); /* must come first, it passes, _out handles */ js_mapi_session(es_OUT, m->s, mod_presence_out, mp); js_mapi_session(es_END, m->s, mod_presence_avails_end, mp); return M_PASS; }
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; }
/* returns a valid nick from the list, x is the first <nick>foo</nick> xmlnode, checks siblings */ char *con_room_nick(cnr room, cnu user, xmlnode x) { char *nick = NULL; xmlnode cur; int count = 1; if(room == NULL || user == NULL) { log_warn(NAME, "[%s] Aborting - NULL attribute found", FZONE); return NULL; } log_debug(NAME, "[%s] looking for valid nick in room %s from starter %s", FZONE, jid_full(room->id), xmlnode2str(x)); /* make-up-a-nick phase */ if(x == NULL) { nick = pmalloco(user->p, j_strlen(user->realid->user) + 10); log_debug(NAME, "[%s] Malloc: Nick = %d", FZONE, j_strlen(user->realid->user) + 10); sprintf(nick, "%s", user->realid->user); while(g_hash_table_lookup(room->local, nick) != NULL) sprintf(nick, "%s%d", user->realid->user,count++); return nick; } /* scan the list */ for(cur = x; cur != NULL; cur = xmlnode_get_nextsibling(cur)) { if(j_strcmp(xmlnode_get_name(cur),"nick") == 0 && (nick = xmlnode_get_data(cur)) != NULL) if(g_hash_table_lookup(room->local, nick) == NULL) break; } if(is_registered(room->master, jid_full(jid_user(user->realid)), nick) == -1) nick = NULL; return nick; }
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; }
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); }
/* Internal routines */ static xmlnode _xmlnode_new(pool p, const char* name, unsigned int type) { xmlnode result = NULL; if (type > NTYPE_LAST) return NULL; if (type != NTYPE_CDATA && name == NULL) return NULL; if (p == NULL) { p = pool_heap(1*1024); } /* Allocate & zero memory */ result = (xmlnode)pmalloco(p, sizeof(_xmlnode)); /* Initialize fields */ if (type != NTYPE_CDATA) result->name = pstrdup(p,name); result->type = type; result->p = p; return result; }
xdbcache xdb_cache(instance id) { xdbcache xc; if (id == NULL) { log_alert("xdb", "Programming Error: xdb_cache() called with NULL\n"); return NULL; } xc = pmalloco(id->p, sizeof(_xdbcache)); xc->i = id; /* flags it as the top of the ring too */ xc->first = NULL; /* init ring */ SEM_INIT(xc->sem); /* register the handler in the instance to filter out xdb results */ register_phandler(id, o_PRECOND, xdb_results, (void *) xc); /* heartbeat to keep a watchful eye on xdb_cache */ register_beat(10, xdb_thump, (void *) xc); register_shutdown_first(xdb_shutdown, (void *) xc); return xc; }
/* * js_session_new -- creates a new session, registers the resource for it * * Sets up all the data associated with the new session, then send it a * start spacket, which basically notifies all modules about the new session * * returns * a pointer to the new session */ session js_session_new(jsmi si, dpacket dp) { pool p; session s, cur; udata u; int i; char routeres[10]; /* screen out illegal calls */ if (dp == NULL || dp->id->user == NULL || dp->id->resource == NULL || xmlnode_get_attrib(dp->x, "from") == NULL) return NULL; if ((u = js_user(si, dp->id, 0)) == NULL) return NULL; if (u->scount >= MAX_USER_SESSIONS) { THREAD_DEC(u->ref); return NULL; } log_debug("session_create %s", jid_full(dp->id)); /* create session */ p = pool_heap(1024); s = pmalloco(p, sizeof(struct session_struct)); s->p = p; s->si = si; /* save authorative remote session id */ s->sid = jid_new(p, xmlnode_get_attrib(dp->x, "from")); /* session identity */ s->id = jid_new(p, jid_full(dp->id)); /* id bez resource */ s->uid = jid_user(s->id); s->route = jid_new(p, jid_full(dp->id)); snprintf(routeres, 9, "%X", s); jid_set(s->route, routeres, JID_RESOURCE); s->res = pstrdup(p, dp->id->resource); s->u = u; jid_full(s->sid); jid_full(s->uid); jid_full(s->id); jid_full(s->route); { register char *text; text = xmlnode_get_attrib(dp->x, "ip"); if (text) { s->ip = pstrdup(s->p, xmlnode_get_attrib(dp->x, "ip")); xmlnode_hide_attrib(dp->x, "ip"); } else s->ip = "none"; } /* default settings */ s->exit_flag = 0; s->roster = 0; s->priority = -129; s->presence = jutil_presnew(JPACKET__UNAVAILABLE, NULL, NULL); xmlnode_put_attrib(s->presence, "from", jid_full(s->id)); s->c_in = s->c_out = 0; for (i = 0; i < es_LAST; i++) s->events[i] = NULL; SEM_LOCK(u->sem); if (u->sessions != NULL) { s->q = get_mtq_queue(si, u->sessions->q); for (cur = u->sessions; cur != NULL; cur = cur->next) if (j_strcmp(dp->id->resource, cur->res) == 0) js_session_end_nosem(cur, "Replaced by new connection"); } else { s->q = get_mtq_queue(si, NULL); } /* make sure we're linked with the user */ s->next = s->u->sessions; s->u->sessions = s; s->u->scount++; SEM_UNLOCK(u->sem); /* session start */ { packet_thread_p pt; pt = malloc(sizeof(packet_thread_t)); pt->s = s; pt->type = 0; fast_mtq_send(s->q->mtq, pt); } THREAD_DEC(u->ref); return s; }
/* simple utility for concat strings */ char *xdb_file_full(int create, pool p, char *spl, char *host, char *file, char *ext) { struct stat s; int lenf = strlen(file); int lenh = strlen(host); int lens = strlen(spl); int lene = strlen(ext); int index; char xdb_file[lenf+10]; char xdb_path[20]; char *full = pmalloco(p,lens+lenh+lenf+lene+15); memcpy(full,spl,lens); index = lens; full[index] = '/'; index++; memcpy(full+index,host,lenh); index += lenh; full[index] = '/'; index++; memcpy(xdb_file,file,lenf); xdb_file[lenf]='.'; memcpy(xdb_file+lenf+1,ext,lene); xdb_file[lenf+lene+1] = 0; generate_dir(xdb_file,xdb_path,20); memcpy(full+index,xdb_path+1,5); index+=5; /* check dir */ if (stat(full,&s) == 0) { full[index] = '/'; index++; memcpy(full+index,xdb_file,lenf+lene+2); return full; } /* if GET why create */ if (!create) { return NULL; } /* try to create directory */ index = lens+lenh+1; full[index] = 0; /* create host */ if (stat(full,&s) < 0) { mkdir(full, S_IRWXU); } full[index] = '/'; index+=3; full[index] = 0; /* create 1 dir */ if (stat(full,&s) < 0) { mkdir(full, S_IRWXU); } full[index] = '/'; index+=3; full[index] = 0; /* create 2 dir */ if (stat(full,&s) < 0) { mkdir(full, S_IRWXU); } full[index] = '/'; index++; memcpy(full+index,xdb_file,lenf+lene+2); return full; }
static st_filter_t _storage_filter(pool_t p, const char *f, int len) { char *c, *key, *val, *sub; int vallen; st_filter_t res, sf; if(f[0] != '(' && f[len] != ')') return NULL; /* key/value pair */ /* if value is numeric, then represented as is. */ /* if value is string, it is preceded by length: e.g. "key=5:abcde" */ /* (needed to pass values which include a closing bracket ')', e.g. in resourcenames */ if(isalpha(f[1])) { key = strdup(f+1); c = strchr(key, '='); if(c == NULL) { free(key); return NULL; } *c = '\0'; c++; val = c; /* decide whether number or string by checking for ':' before ')' */ while (*c != ':' && *c != ')' && *c) c++; if (!*c) { free(key); return NULL; } if (*c == ':') { /* string */ *c = '\0'; vallen = atoi(val); c++; val = c; c += vallen; } *c = '\0'; log_debug(ZONE, "extracted key %s val %s", key, val); res = pmalloco(p, sizeof(struct st_filter_st)); res->p = p; res->type = st_filter_type_PAIR; res->key = pstrdup(p, key); res->val = pstrdup(p, val); free(key); return res; } /* operator */ if(f[1] != '&' && f[1] != '|' && f[1] != '!') return NULL; res = pmalloco(p, sizeof(struct st_filter_st)); res->p = p; switch(f[1]) { case '&': res->type = st_filter_type_AND; break; case '|': res->type = st_filter_type_OR; break; case '!': res->type = st_filter_type_NOT; break; } /* remove const for now, we will not change the string */ c = (char *) &f[2]; while(*c == '(') { sub = c; c = strchr(sub, ')'); c++; sf = _storage_filter(p, (const char *) sub, c - sub); sf->next = res->sub; res->sub = sf; } return res; }