/// <summary>
        /// Attempts to initiate a data stream with the XMPP entity with the specified
        /// JID.
        /// </summary>
        /// <param name="to">The JID of the XMPP entity to initiate a data-stream
        /// with.</param>
        /// <param name="mimeType">The MIME type of the data to be transferred across
        /// the stream.</param>
        /// <param name="profile">The 'Stream Initiation' profile to use.</param>
        /// <param name="streamOptions">An enumerable collection of supported
        /// stream methods which are advertised to the receiving XMPP
        /// entity.</param>
        /// <param name="data">An XML element containing any additional data the
        /// specified 'Stream Initiation' profile may require.</param>
        /// <param name="cb">A callback method to invoke once the result of the
        /// stream-initation operation has been received.</param>
        /// <returns>An initialized instance of the InitiationResult class containing
        /// the negotiated stream-method and session identifier.</returns>
        /// <exception cref="ArgumentNullException">The to parameter or the mimeType
        /// parameter or the profile parameter or the streamOptions parameter
        /// is null.</exception>
        /// <exception cref="ArgumentException">The streamOptions enumerable contains
        /// no elements, or the stream-initiation response received contained no
        /// selection for the stream-method.</exception>
        /// <exception cref="NotSupportedException">The XMPP entity with
        /// the specified JID does not support the 'Stream Initiation' XMPP
        /// extension.</exception>
        public void InitiateStreamAsync(Jid to, string mimeType, string profile,
                                        IEnumerable <string> streamOptions, XmlElement data = null,
                                        Action <InitiationResult, Iq> cb = null)
        {
            to.ThrowIfNull("to");
            mimeType.ThrowIfNull("mimeType");
            profile.ThrowIfNull("profile");
            streamOptions.ThrowIfNull("streamOptions");
            if (streamOptions.Count() == 0)
            {
                throw new ArgumentException("The streamOptions enumerable must " +
                                            "include one or more stream-options.");
            }
            if (!ecapa.Supports(to, Extension.StreamInitiation))
            {
                throw new NotSupportedException("The XMPP entity does not support " +
                                                "the 'Stream Initiation' extension.");
            }
            string sid = GenerateSessionId();
            var    si  = CreateSiElement(sid, mimeType, profile, streamOptions, data);

            // Perform the actual request.
            im.IqRequestAsync(IqType.Set, to, im.Jid, si, null, (id, iq) => {
                if (cb == null)
                {
                    return;
                }
                InitiationResult result = null;
                if (iq.Type != IqType.Error)
                {
                    // Result must contain a 'feature' element.
                    var feat        = iq.Data["si"]["feature"];
                    string selected = ParseStreamMethod(feat);
                    // Construct the initiation result and call the provided callback.
                    result = new InitiationResult(sid, selected, iq.Data["si"]);
                }
                cb(result, iq);
            });
        }
Beispiel #2
0
        /// <summary>
        /// Invoked once the result of a pending stream-initiation operation has been
        /// received.
        /// </summary>
        /// <param name="result">The result of the stream-initiation operation. If
        /// this parameter is null, stream-initiation failed.</param>
        /// <param name="to">The JID of the XMPP user to offer the file to.</param>
        /// <param name="stream">The stream to read the file-data from.</param>
        /// <param name="name">The name of the file, as offered to the XMPP user
        /// with the specified JID.</param>
        /// <param name="size">The number of bytes to transfer.</param>
        /// <param name="cb">A callback method invoked once the other site has
        /// accepted or rejected the file-transfer request.</param>
        /// <param name="description">A description of the file so the receiver can
        /// better understand what is being sent.</param>
        /// <remarks>This is called in the context of an arbitrary thread.</remarks>
        void OnInitiationResult(InitiationResult result, Jid to, string name,
                                Stream stream, long size, string description, Action <bool, FileTransfer> cb)
        {
            FileTransfer transfer = new FileTransfer(im.Jid, to, name, size, null,
                                                     description);

            try {
                // Get the instance of the data-stream extension that the other site has
                // selected.
                IDataStream ext = im.GetExtension(result.Method) as IDataStream;
                // Register the session.
                SISession session = new SISession(result.SessionId, stream, size, false,
                                                  im.Jid, to, ext);
                siSessions.TryAdd(result.SessionId, session);
                // Store the file's meta data.
                metaData.TryAdd(result.SessionId, new FileMetaData(name, description));
                // Invoke user-provided callback.
                if (cb != null)
                {
                    cb.Invoke(true, transfer);
                }
                // Perform the actual data-transfer.
                try {
                    ext.Transfer(session);
                } catch (Exception e) {
                    // Nothing to do here.
                }
            } catch {
                // Something went wrong. Invoke user-provided callback to let them know
                // the file-transfer can't be performed.
                if (cb != null)
                {
                    cb.Invoke(false, transfer);
                }
            }
        }