📄 c2s.c
字号:
else log_write(c2s->log, LOG_NOTICE, "[%s, port=%d] listening for SSL connections", c2s->local_ip, c2s->local_ssl_port); } else c2s->server_ssl_fd = -1;#endif }#ifdef HAVE_SSL if(c2s->server_fd < 0 && c2s->server_ssl_fd < 0) { log_write(c2s->log, LOG_ERR, "both normal and SSL ports are disabled, nothing to do!");#else if(c2s->server_fd < 0) { log_write(c2s->log, LOG_ERR, "server port is disabled, nothing to do!");#endif exit(1); } /* we're online */ c2s->online = c2s->started = 1; log_write(c2s->log, LOG_NOTICE, "ready for connections", c2s->id); nad_free(nad); return 0; } /* need component packets */ if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_COMPONENT) || strncmp(uri_COMPONENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_COMPONENT)) != 0) { log_debug(ZONE, "wanted component packet, dropping"); nad_free(nad); return 0; } /* component presence */ if(NAD_ENAME_L(nad, 0) == 8 && strncmp("presence", NAD_ENAME(nad, 0), 8) == 0) { _c2s_component_presence(c2s, nad); return 0; } /* we want route */ if(NAD_ENAME_L(nad, 0) != 5 || strncmp("route", NAD_ENAME(nad, 0), 5) != 0) { log_debug(ZONE, "wanted {component}route, dropping"); nad_free(nad); return 0; } /* only handle unicasts */ if(nad_find_attr(nad, 0, -1, "type", NULL) >= 0) { log_debug(ZONE, "non-unicast packet, dropping"); nad_free(nad); return 0; } /* need some payload */ if(nad->ecur == 1) { log_debug(ZONE, "no route payload, dropping"); nad_free(nad); return 0; } ns = nad_find_namespace(nad, 1, uri_SESSION, NULL); if(ns < 0) { log_debug(ZONE, "not a c2s packet, dropping"); nad_free(nad); return 0; } /* figure out the session */ c2sid = nad_find_attr(nad, 1, ns, "c2s", NULL); if(c2sid < 0) { log_debug(ZONE, "no c2s id on payload, dropping"); nad_free(nad); return 0; } snprintf(skey, 10, "%.*s", NAD_AVAL_L(nad, c2sid), NAD_AVAL(nad, c2sid)); /* find the session, quietly drop if we don't have it */ sess = xhash_get(c2s->sessions, skey); if(sess == NULL) { /* !!! might want to send a stop to the sm; maybe it thinks we're still here? */ log_debug(ZONE, "no session for %s", skey); nad_free(nad); return 0; } /* if they're pre-stream, then this is leftovers from a previous session */ if(sess->s->state < state_STREAM) { log_debug(ZONE, "session %s is pre-stream", skey); nad_free(nad); return 0; } /* check the sm session id if they gave us one */ smid = nad_find_attr(nad, 1, ns, "sm", NULL); if(smid >= 0 && sess->sm_id[0] != '\0' && (strlen(sess->sm_id) != NAD_AVAL_L(nad, smid) || strncmp(sess->sm_id, NAD_AVAL(nad, smid), NAD_AVAL_L(nad, smid)) != 0)) { log_debug(ZONE, "expected packet from sm session %s, but got one from %.*s, dropping", sess->sm_id, NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid)); nad_free(nad); return 0; } /* it has to have come from the session manager */ from = nad_find_attr(nad, 0, -1, "from", NULL); if(strlen(sess->s->req_to) != NAD_AVAL_L(nad, from) || strncmp(sess->s->req_to, NAD_AVAL(nad, from), NAD_AVAL_L(nad, from)) != 0) { log_debug(ZONE, "packet from '%.*s' for %s, but they're not the sm for this sess", NAD_AVAL_L(nad, from), NAD_AVAL(nad, from), skey); nad_free(nad); return 0; } /* route errors */ if(nad_find_attr(nad, 0, -1, "error", NULL) >= 0) { log_debug(ZONE, "routing error"); /* !!! kill the session */ nad_free(nad); return 0; } /* session control packets */ if(NAD_ENS(nad, 1) == ns) { action = nad_find_attr(nad, 1, -1, "action", NULL); id = nad_find_attr(nad, 1, -1, "id", NULL); /* failed requests */ if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) { /* make sure the id matches */ if(id < 0 || sess->sm_request[0] == '\0' || strlen(sess->sm_request) != NAD_AVAL_L(nad, id) || strncmp(sess->sm_request, NAD_AVAL(nad, id), NAD_AVAL_L(nad, id)) != 0) { log_debug(ZONE, "got a response with id %.*s, but we were expecting %s", NAD_AVAL_L(nad, id), NAD_AVAL(nad, id), sess->sm_request); nad_free(nad); return 0; } /* handled request */ sess->sm_request[0] = '\0'; /* we only care about failed start and create */ if((NAD_AVAL_L(nad, action) == 5 && strncmp("start", NAD_AVAL(nad, action), 5) == 0) || (NAD_AVAL_L(nad, action) == 6 && strncmp("create", NAD_AVAL(nad, action), 6) == 0)) { /* create failed, so we need to remove them from authreg */ if(NAD_AVAL_L(nad, action) == 6 && c2s->ar->delete_user != NULL) { if((c2s->ar->delete_user)(c2s->ar, sess->jid->node, sess->realm) != 0) log_write(c2s->log, LOG_NOTICE, "[%d] user creation failed, and unable to delete user credentials: user=%s, realm=%s", sess->s->tag, sess->jid->node, sess->realm); else log_write(c2s->log, LOG_NOTICE, "[%d] user creation failed, so deleted user credentials: user=%s, realm=%s", sess->s->tag, sess->jid->node, sess->realm); } /* error the result and return it to the client */ sx_nad_write(sess->s, stanza_error(sess->result, 0, stanza_err_INTERNAL_SERVER_ERROR)); sess->result = NULL; jid_free(sess->jid); sess->jid = NULL; nad_free(nad); return 0; } log_debug(ZONE, "weird, got a failed session response, with a matching id, but the action is bogus *shrug*"); nad_free(nad); return 0; } /* if we're not active yet, then we only want "started" or "created" responses */ if(!sess->active) { /* make sure the id matches */ if(id < 0 || sess->sm_request[0] == '\0' || strlen(sess->sm_request) != NAD_AVAL_L(nad, id) || strncmp(sess->sm_request, NAD_AVAL(nad, id), NAD_AVAL_L(nad, id)) != 0) { log_debug(ZONE, "got a response with id %.*s, but we were expecting %s", NAD_AVAL_L(nad, id), NAD_AVAL(nad, id), sess->sm_request); nad_free(nad); return 0; } /* session started */ if(NAD_AVAL_L(nad, action) == 7 && strncmp("started", NAD_AVAL(nad, action), 7) == 0) { /* handled request */ sess->sm_request[0] = '\0'; /* copy the sm id */ if(smid >= 0) snprintf(sess->sm_id, 41, "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid)); nad_free(nad); /* bring them online, old-skool */ if(!sess->sasl_authd) { sx_auth(sess->s, "traditional", jid_user(sess->jid)); return 0; } /* return the auth result to the client */ sx_nad_write(sess->s, sess->result); sess->result = NULL; /* we're good to go */ sess->active = 1; return 0; } /* user created */ if(NAD_AVAL_L(nad, action) == 7 && strncmp("created", NAD_AVAL(nad, action), 7) == 0) { /* handled request */ sess->sm_request[0] = '\0'; nad_free(nad); /* return the result to the client */ sx_nad_write(sess->s, sess->result); sess->result = NULL; return 0; } /* anything else gets thrown out */ log_debug(ZONE, "got a packet for %s, but they don't have an active session yes", jid_full(sess->jid)); nad_free(nad); return 0; } /* end responses */ /* !!! this "replaced" stuff is a hack - its really a subaction of "ended". * hurrah, another control protocol rewrite is needed :( */ replaced = 0; if(NAD_AVAL_L(nad, action) == 8 && strncmp("replaced", NAD_AVAL(nad, action), NAD_AVAL_L(nad, action)) == 0) replaced = 1; if(replaced || (NAD_AVAL_L(nad, action) == 5 && strncmp("ended", NAD_AVAL(nad, action), NAD_AVAL_L(nad, action)) == 0)) { sess->active = 0; if(replaced) sx_error(sess->s, stream_err_CONFLICT, NULL); /* close them */ sx_close(sess->s); nad_free(nad); return 0; } /* make sure the id matches */ if(id < 0 || sess->sm_request[0] == '\0' || strncmp(sess->sm_request, NAD_AVAL(nad, id), NAD_AVAL_L(nad, id)) != 0) { log_debug(ZONE, "got a response with id %.*s, but we were expecting %s", NAD_AVAL_L(nad, id), NAD_AVAL(nad, id), sess->sm_request); nad_free(nad); return 0; } /* handled request */ sess->sm_request[0] = '\0'; log_debug(ZONE, "unknown action %.*s", NAD_AVAL_L(nad, id), NAD_AVAL(nad, id)); nad_free(nad); return 0; } /* client packets */ if(NAD_NURI_L(nad, NAD_ENS(nad, 1)) == strlen(uri_CLIENT) && strncmp(uri_CLIENT, NAD_NURI(nad, NAD_ENS(nad, 1)), strlen(uri_CLIENT)) == 0) { if(!sess->active) { /* its a strange world .. */ nad_free(nad); return 0; } /* sm is bouncing something */ if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) { /* there's really no graceful way to handle this */ sx_error(s, stream_err_INTERNAL_SERVER_ERROR, "session manager failed control action"); sx_close(s); nad_free(nad); return 0; } /* remove sm specifics */ nad_set_attr(nad, 1, ns, "c2s", NULL, 0); nad_set_attr(nad, 1, ns, "sm", NULL, 0); /* forget about the internal namespace too */ if(nad->elems[1].ns == ns) nad->elems[1].ns = nad->nss[ns].next; else { for(scan = nad->elems[1].ns; nad->nss[scan].next != -1 && nad->nss[scan].next != ns; scan = nad->nss[scan].next); /* got it */ if(nad->nss[scan].next != -1) nad->nss[scan].next = nad->nss[ns].next; } sx_nad_write_elem(sess->s, nad, 1); return 0; } /* its something else */ log_debug(ZONE, "unknown packet, dropping"); nad_free(nad); return 0; case event_CLOSED: mio_close(c2s->mio, c2s->fd); break; } return 0;}int c2s_router_mio_callback(mio_t m, mio_action_t a, int fd, void *data, void *arg) { c2s_t c2s = (c2s_t) arg; int nbytes; switch(a) { case action_READ: log_debug(ZONE, "read action on fd %d", fd); ioctl(fd, FIONREAD, &nbytes); if(nbytes == 0) { sx_kill(c2s->router); return 0; } return sx_can_read(c2s->router); case action_WRITE: log_debug(ZONE, "write action on fd %d", fd); return sx_can_write(c2s->router); case action_CLOSE: log_debug(ZONE, "close action on fd %d", fd); log_write(c2s->log, LOG_NOTICE, "connection to router closed"); c2s_lost_router = 1; /* we're offline */ c2s->online = 0; break; case action_ACCEPT: break; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -