UNPKG

@fnlb-project/stanza

Version:

Modern XMPP in the browser, with a JSON API

266 lines (265 loc) 7.98 kB
// ==================================================================== // RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core // -------------------------------------------------------------------- // Source: https://tools.ietf.org/html/rfc6120 // ==================================================================== import { SASLFailureCondition, StanzaErrorCondition, StreamErrorCondition, StreamType } from '../Constants'; import { attribute, childAlternateLanguageText, childBoolean, childEnum, childText, JIDAttribute, languageAttribute, multipleChildText, textBuffer } from '../jxt'; import { NS_BIND, NS_CLIENT, NS_SASL, NS_STANZAS, NS_STARTTLS, NS_STREAM, NS_STREAMS } from '../Namespaces'; const _Stream = { defaultType: 'stream', element: 'stream', fields: { from: attribute('from'), id: attribute('id'), lang: languageAttribute(), to: attribute('to'), version: attribute('version') }, namespace: NS_STREAM, path: 'stream', type: 'stream', typeField: 'action' }; const _StreamFeatures = { element: 'features', namespace: NS_STREAM, path: 'features' }; const _StreamError = { element: 'error', fields: { alternateLanguageText: childAlternateLanguageText(NS_STREAMS, 'text'), condition: childEnum(NS_STREAMS, Object.values(StreamErrorCondition), StreamErrorCondition.UndefinedCondition), seeOtherHost: childText(NS_STREAMS, StreamErrorCondition.SeeOtherHost), text: childText(NS_STREAMS, 'text') }, namespace: NS_STREAM, path: 'streamError' }; // -------------------------------------------------------------------- const _StanzaError = Object.values(StreamType).map(streamNS => ({ aliases: ['stanzaError', 'message.error', 'presence.error', 'iq.error'], defaultType: NS_CLIENT, element: 'error', fields: { alternateLanguageText: childAlternateLanguageText(NS_STANZAS, 'text'), by: JIDAttribute('by'), condition: childEnum(NS_STANZAS, Object.values(StanzaErrorCondition), StanzaErrorCondition.UndefinedCondition), gone: childText(NS_STANZAS, StanzaErrorCondition.Gone), redirect: childText(NS_STANZAS, StanzaErrorCondition.Redirect), text: childText(NS_STANZAS, 'text'), type: attribute('type') }, namespace: streamNS, type: streamNS, typeField: 'streamType' })); // -------------------------------------------------------------------- const baseIQFields = new Set([ 'from', 'id', 'lang', 'to', 'type', 'payloadType', 'error', 'streamType' ]); const _IQ = Object.values(StreamType).map((streamNS) => ({ childrenExportOrder: { error: 200000 }, defaultType: NS_CLIENT, element: 'iq', fields: { from: JIDAttribute('from'), id: attribute('id'), lang: languageAttribute(), payloadType: { order: -10000, importer(xml, context) { if (context.data.type !== 'get' && context.data.type !== 'set') { return; } const childCount = xml.children.filter(child => typeof child !== 'string') .length; if (childCount !== 1) { return 'invalid-payload-count'; } const extensions = Object.keys(context.data).filter(key => !baseIQFields.has(key)); if (extensions.length !== 1) { return 'unknown-payload'; } return extensions[0]; } }, to: JIDAttribute('to'), type: attribute('type') }, namespace: streamNS, path: 'iq', type: streamNS, typeField: 'streamType' })); // -------------------------------------------------------------------- const _Message = Object.values(StreamType).map(streamNS => ({ childrenExportOrder: { error: 200000 }, defaultType: NS_CLIENT, element: 'message', fields: { from: JIDAttribute('from'), id: attribute('id'), lang: languageAttribute(), to: JIDAttribute('to') }, namespace: streamNS, path: 'message', type: streamNS, typeField: 'streamType' })); // -------------------------------------------------------------------- const _Presence = Object.values(StreamType).map(streamNS => ({ childrenExportOrder: { error: 200000 }, defaultType: NS_CLIENT, element: 'presence', fields: { from: JIDAttribute('from'), id: attribute('id'), lang: languageAttribute(), to: JIDAttribute('to') }, namespace: streamNS, path: 'presence', type: streamNS, typeField: 'streamType' })); // -------------------------------------------------------------------- const _SASL = [ { element: 'mechanisms', fields: { mechanisms: multipleChildText(null, 'mechanism') }, namespace: NS_SASL, path: 'features.sasl' }, { element: 'abort', namespace: NS_SASL, path: 'sasl', type: 'abort', typeField: 'type' }, { element: 'auth', fields: { mechanism: attribute('mechanism'), value: textBuffer('base64') }, namespace: NS_SASL, path: 'sasl', type: 'auth', typeField: 'type' }, { element: 'challenge', fields: { value: textBuffer('base64') }, namespace: NS_SASL, path: 'sasl', type: 'challenge', typeField: 'type' }, { element: 'response', fields: { value: textBuffer('base64') }, namespace: NS_SASL, path: 'sasl', type: 'response', typeField: 'type' }, { element: 'success', fields: { value: textBuffer('base64') }, namespace: NS_SASL, path: 'sasl', type: 'success', typeField: 'type' }, { element: 'failure', fields: { alternateLanguageText: childAlternateLanguageText(NS_SASL, 'text'), condition: childEnum(NS_SASL, Object.values(SASLFailureCondition)), text: childText(NS_SASL, 'text') }, namespace: NS_SASL, path: 'sasl', type: 'failure', typeField: 'type' } ]; // -------------------------------------------------------------------- const _STARTTLS = [ { aliases: ['features.tls'], defaultType: 'start', element: 'starttls', fields: { required: childBoolean(null, 'required') }, namespace: NS_STARTTLS, path: 'tls', type: 'start', typeField: 'type' }, { element: 'proceed', namespace: NS_STARTTLS, path: 'tls', type: 'proceed', typeField: 'type' }, { element: 'failure', namespace: NS_STARTTLS, path: 'tls', type: 'failure', typeField: 'type' } ]; // -------------------------------------------------------------------- const _Bind = { aliases: ['features.bind', 'iq.bind'], element: 'bind', fields: { jid: childText(null, 'jid'), resource: childText(null, 'resource') }, namespace: NS_BIND }; // -------------------------------------------------------------------- const Protocol = [ _Stream, _StreamFeatures, _StreamError, ..._StanzaError, ..._SASL, ..._STARTTLS, ..._IQ, ..._Message, ..._Presence, _Bind ]; export default Protocol;