#include #include #include #include #include #include #include #include #include #include #include #include /* The default component port Prosody uses. */ #define DEFAULT_PROSODY_PORT 5347 XMPPComponent * XMPPInitialiseCompStream(char *host, int port) { int sd = -1; struct addrinfo hints, *res, *res0; int error; char serv[8]; Stream *stream; XMPPComponent *comp; snprintf(serv, sizeof(serv), "%hu", port ? port : DEFAULT_PROSODY_PORT); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host, serv, &hints, &res0); for (res = res0; res; res = res->ai_next) { sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sd < 0) { continue; } if (connect(sd, res->ai_addr, res->ai_addrlen) < 0) { close(sd); sd = -1; continue; } break; } if (sd < 0) { return NULL; } freeaddrinfo(res0); stream = StreamFd(sd); if (!stream) { close(sd); return NULL; } comp = Malloc(sizeof(*comp)); comp->host = StrDuplicate(host); comp->stream = stream; pthread_mutex_init(&comp->write_lock, NULL); (void) error; return comp; } #include static char * ComputeHandshake(char *shared, char *stream) { char *source; char *sha; source = StrConcat(2, stream, shared); sha = ParseeSHA1(source); Free(source); return sha; } bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared) { /* TODO */ XMLexer *sax; XMLEvent *ev; char *stream_id, *handshake; bool ret = false; Stream *stream; char *as; if (!comp || !shared) { return false; } pthread_mutex_lock(&comp->write_lock); stream = comp->stream; as = comp->host; StreamPrintf(stream, "", as ); StreamFlush(stream); sax = XMLCreateLexer(stream, false); while ((ev = XMLCrank(sax))) { if (ev->type == XML_RELAX) { XMLFreeEvent(ev); continue; } break; } if (ev->type != XML_LEXER_STARTELEM || !StrEquals(ev->element, "stream:stream")) { Log(LOG_ERR, "Excepted stream:stream element."); XMLFreeEvent(ev); goto end; } stream_id = StrDuplicate(HashMapGet(ev->attrs, "id")); handshake = ComputeHandshake(shared, stream_id); Log(LOG_DEBUG, "- sID='%s'", stream_id); StreamPrintf(stream, "%s", handshake); StreamFlush(stream); XMLFreeEvent(ev); while ((ev = XMLCrank(sax))) { if (ev->type == XML_RELAX) { XMLFreeEvent(ev); continue; } break; } if (ev->type != XML_LEXER_ELEM || !StrEquals(ev->element, "handshake")) { Log(LOG_ERR, "Excepted empty handshake reply, got nonsense."); Log(LOG_ERR, "Another service (possibly Parsee) may have taken over."); Log(LOG_ERR, ""); Log(LOG_ERR, "Simply jealous of that other service..."); Free(stream_id); Free(handshake); XMLFreeEvent(ev); goto end; } ret = true; /* We can uhh, send stanzas, and receive them! */ Log(LOG_INFO, "Communications to '%s' established.", as); XMLFreeEvent(ev); Free(stream_id); Free(handshake); end: XMLFreeLexer(sax); pthread_mutex_unlock(&comp->write_lock); return ret; } void XMPPFinishCompStream(XMPPComponent *comp) { if (!comp) { return; } pthread_mutex_lock(&comp->write_lock); StreamPrintf(comp->stream, ""); StreamFlush(comp->stream); pthread_mutex_unlock(&comp->write_lock); } void XMPPEndCompStream(XMPPComponent *comp) { if (!comp) { return; } pthread_mutex_lock(&comp->write_lock); StreamClose(comp->stream); comp->stream = NULL; pthread_mutex_unlock(&comp->write_lock); pthread_mutex_destroy(&comp->write_lock); Free(comp->host); Free(comp); }