/// <summary>
        /// Analyzes and responds if required to the given <see cref="RTMPPacket"/>.
        /// </summary>
        /// <param name="packet">The packet to inspect and react to.</param>
        /// <returns>0 (false) for OK/Failed/error, 1 for 'Stop or Complete' (true)</returns>
        private bool HandleInvoke(RTMPPacket packet)
        {
            bool ret = false;

            if (packet.Body[0] != 0x02) // make sure it is a string method name we start with
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.NetConnection.HandleInvoke] Sanity failed. no string method in invoke packet");
                return false;
            }

            AMFObject obj = new AMFObject();
            int nRes = obj.Decode(packet.Body, 0, (int)packet.BodySize, false);
            if (nRes < 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.NetConnection.HandleInvoke] Error decoding invoke packet");
                return false;
            }

            obj.Dump();
            string method = obj.GetProperty(0).StringValue;
            double txn = obj.GetProperty(1).NumberValue;

            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] Server invoking <{0}>", method));

            if (method == "_result")
            {
                int transactionResultNum = (int)obj.GetProperty(1).NumberValue;
                string methodInvoked = "";
                if (methodCallDictionary.ContainsKey(transactionResultNum))
                {
                    methodInvoked = methodCallDictionary[transactionResultNum];
                    methodCallDictionary.Remove(transactionResultNum);
                }

                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] received result for method call <{0}>", methodInvoked));

                if (methodInvoked == "connect")
                {
                    // Get some info out of the result connection
                    DecodeNetConnectionInfo_Connect_Result(obj);

                    // Is SecureToken activate (when using wowza server)
                    string tmpSecureTokenPassword = string.Empty;
                    lock (lockVAR)
                    {
                        tmpSecureTokenPassword = secureTokenPassword;
                    }
                    if (!string.IsNullOrEmpty(tmpSecureTokenPassword))
                    {
                        List<AMFObjectProperty> props = new List<AMFObjectProperty>();
                        obj.FindMatchingProperty("secureToken", props, int.MaxValue);
                        if (props.Count > 0)
                        {
#if INCLUDE_TMPE
#endif
                        }
                    }
                    MQInternal_SendServerBW();

                    // Send OnConnect event
                }
                else if (methodInvoked == "createStream")
                {
                    int transactionNum = (int)obj.GetProperty(1).NumberValue;
                    int stream_id = (int)obj.GetProperty(3).NumberValue;

                    if (transactionIDReferenceTable.ContainsKey(transactionNum) && transactionIDReferenceTable[transactionNum] is NetStream)
                    {
                        NetStream netStream = (NetStream)transactionIDReferenceTable[transactionNum];
                        transactionIDReferenceTable.Remove(transactionNum);
                        LibRTMPLogger.Log(LibRTMPLogLevel.Info, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] Received createStream(stream_id={0})", stream_id));

                        netStream.Stream_ID = stream_id;
                        // make sure we know which NetStreams use this NetCOnnection
                        RegisterNetStream(netStream);

                        int contentBufferTime = NetConnection.DefaultContentBufferTime;
                        netStream.HandleOnAssignStream_ID(packet, stream_id, out contentBufferTime);
                        if (contentBufferTime <= 0)
                        {
                            contentBufferTime = NetConnection.DefaultContentBufferTime;
                        }
                        // Tell buffer time we want to use for this channel
                        MQ_SendPing(3, (uint)netStream.Stream_ID, (uint)contentBufferTime);
                    }
                    else
                    {
                        // We haven't found a NetStream for which this is intended, so delete it again
                        MQ_SendDeleteStream(stream_id);
                    }
                }
                else if (methodInvoked == "play")
                {
                    // Server send the play command?
                }
            }
            else if (method == "onBWDone")
            {
                if (bwCheckCounter == 0)
                {
                    MQInternal_SendCheckBW();
                }
            }
            else if (method == "_onbwcheck")
            {
                MQInternal_SendCheckBWResult(txn);
            }
            else if (method == "_onbwdone")
            {
                int transactionResultNum = (int)obj.GetProperty(1).NumberValue;
                if (methodCallDictionary.ContainsValue("_checkbw"))
                {
                    var item = methodCallDictionary.First(x => x.Value == "_checkbw");
                    methodCallDictionary.Remove(item.Key);
                }
            }
            else if (method == "_error")
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "[CDR.LibRTMP.NetConnection.HandleInvoke] rtmp server sent error");
            }
            else if (method == "close")
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "[CDR.LibRTMP.NetConnection.HandleInvoke] rtmp server requested close");
                CloseConnection();
            }
            else if (method == "onStatus")
            {
                int stream_id = packet.InfoField2;
                string code = obj[3].ObjectValue.GetProperty("code").StringValue;
                string level = obj[3].ObjectValue.GetProperty("level").StringValue;

                LibRTMPLogger.Log(LibRTMPLogLevel.Info, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] stream_id={0}, method={1}, code={2}, level={3}", stream_id, method, code, level));
                // Zoek NetStream op en geef OnStatus door
                if (netStreams[stream_id] != null)
                {
                    if (code == "NetStream.Pause.Notify")
                    {
                        // fix to help netstream
                        packet.TimeStamp = channelTimestamp[netStreams[stream_id].MediaChannel];
                    }
                    netStreams[stream_id].HandleOnStatus(packet);
                }
                else
                {
                    LibRTMPLogger.Log(LibRTMPLogLevel.Info, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] UNHANDLED | stream_id={0}, method={1}, code={2}, level={3}", stream_id, method, code, level));
                }
            }
            else if (dMethodLookup.ContainsKey(method))
            {
                ret = true;

                SynchronizationContext sc;
                State_NC_MethodCall stateMethodCall = new State_NC_MethodCall();
                lock (lockVAR)
                {
                    sc = synchronizationContext;
                    stateMethodCall.Call = dMethodLookup[method];
                } //lock
                stateMethodCall.thisObject = this;
                stateMethodCall.MethodParam = obj;

                if (sc != null)
                {
                    switch (synchronizationContextMethod)
                    {
                        case SynchronizationContextMethod.Post:
                            sc.Post(HandleOnMethodCall, stateMethodCall);
                            break;
                        case SynchronizationContextMethod.Send:
                            sc.Send(HandleOnMethodCall, stateMethodCall);
                            break;
                    } //switch
                }
                else
                {
                    HandleOnMethodCall(stateMethodCall);
                }
            }
            else
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetConnection.HandleInvoke] [EVENT]={0}", method));
            }

            return ret;
        }
Esempio n. 2
0
        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] // hide it for code completion
        virtual internal bool HandleOnMetaData(RTMPPacket packet)
        {
            AMFObject obj = new AMFObject();
            int nRes = obj.Decode(packet.Body, 0, (int)packet.BodySize, false);
            if (nRes < 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.NetStream.HandleOnMetaData] Error decoding meta data packet");
                return false;
            }

            /* For video:
             *   canSeekToEnd = true
             *   videocodecid = 4
             *   framerate = 15
             *   videodatarate = 400
             *   height = 215
             *   width = 320
             *   duration = 7.347
             *   
             * For Audio (MP3): metastring =="onID3"
             * 
             */


            string metastring = obj.GetProperty(0).StringValue;
            switch (metastring)
            {
                case "onMetaData":
                    List<AMFObjectProperty> props = new List<AMFObjectProperty>();

                    props.Clear();
                    obj.FindMatchingProperty("audiodatarate", props, 1);
                    if (props.Count > 0)
                    {
                        int rate = (int)props[0].NumberValue;
                        audioDatarate += rate;
                        LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] audiodatarate: {0}", audioDatarate));
                    }
                    props.Clear();
                    obj.FindMatchingProperty("videodatarate", props, 1);
                    if (props.Count > 0)
                    {
                        int rate = (int)props[0].NumberValue;
                        videoDatarate += rate;
                        LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] videodatarate: {0}", videoDatarate));
                    }
                    if (audioDatarate == 0 && videoDatarate == 0)
                    {
                        props.Clear();
                        obj.FindMatchingProperty("filesize", props, int.MaxValue);
                        if (props.Count > 0)
                        {
                            combinedTracksLength = (int)props[0].NumberValue;
                            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] Set CombinedTracksLength from filesize: {0}", combinedTracksLength));
                        }
                    }
                    if (combinedTracksLength == 0)
                    {
                        props.Clear();
                        obj.FindMatchingProperty("datasize", props, int.MaxValue);
                        if (props.Count > 0)
                        {
                            combinedTracksLength = (int)props[0].NumberValue;
                            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] Set CombinedTracksLength from datasize: {0}", combinedTracksLength));
                        }
                    }
                    props.Clear();
                    obj.FindMatchingProperty("duration", props, 1);
                    if (props.Count > 0)
                    {
                        double duration = props[0].NumberValue;
                        LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnMetaData] Set duration: {0}", duration));
                        lock (lockVAR)
                        {
                            metaDataDurationInMS = Convert.ToInt64(duration * 1000);
                        }

                        // Looks the same as the "onPlayStatus" (See NetConnection.HandleMetadata (we route it there through HandleOnStatusDecoded
                        // doing it here also)
                        Internal_HandleOnStatusDecoded(packet, "onStatus", "NetStream.Play.OnMetaData", "onPlayStatus", obj);
                    }
                    break;
                // Looks more as an invoke to me Let NetStream.OnStatus handle it
                case "onStatus": // -=> "NetStream.Data.Start"
                    Internal_HandleOnStatusDecoded(packet, "onStatus", obj.GetProperty(1).ObjectValue.GetProperty("code").StringValue, "", obj);
                    break;
                case "onPlayStatus":
                    // "code" = "NetStream.Play.Switch"
                    // "level"= "status" ,made it "onPlayStatus" 
                    // Has also "duration" and "bytes" as additional metadata (looks like a normal onMetaData to me with less options as the normal)
                    Internal_HandleOnStatusDecoded(packet, "onStatus", obj.GetProperty(1).ObjectValue.GetProperty("code").StringValue, "onPlayStatus", obj);
                    break;
                case "onID3":
                    return HandleOnID3(obj);
                default:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetConnection.NetStream.HandleOnMetaData] metastring= {0}", metastring));
                    break;
            } //switch

            return true;
        }
        private void HandleMetadata(RTMPPacket packet)
        {
            int stream_id = packet.InfoField2;

            // Find matching NetStream and forward this packet.
            if (netStreams[stream_id] == null)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, string.Format("[CDR.LibRTMP.NetConnection.HandleMetadata] No matching NetStream found for stream_id {0}", stream_id));
                return;
            }

            AMFObject obj = new AMFObject();
            int nRes = obj.Decode(packet.Body, 0, (int)packet.BodySize, false);
            if (nRes < 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.NetConnection.HandleMetadata] Error decoding meta data packet");
                return;
            }

            string metastring = obj.GetProperty(0).StringValue;
            switch (metastring)
            {
                case "|RtmpSampleAccess":
                    // Ignore this, unknown
                    return;

                // Looks more as an invoke to me Let NetStream.OnStatus handle it
                case "onStatus": // -=> "NetStream.Data.Start"
                case "onPlayStatus": // -=> "NetStream.Play.Switch"
                case "onMetaData": // This seams to me te real metadata
                case "onID3":
                    // Let NetStream Handle it
                    netStreams[stream_id].HandleOnMetaData(packet);
                    break;

                default:
                    LibRTMPLogger.Log(LibRTMPLogLevel.Warning, string.Format("[CDR.LibRTMP.NetConnection.HandleMetadata] Unknown metadata {0}", metastring));
                    break;
            } //switch


            return;
        }
Esempio n. 4
0
        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] // hide it for code completion
        internal bool HandleOnStatus(RTMPPacket packet)
        {
            AMFObject obj = new AMFObject();
            int nRes = obj.Decode(packet.Body, 0, (int)packet.BodySize, false);
            if (nRes < 0)
            {
                return false;
            }

            // string method = obj.GetProperty(0).GetString(); // always onStatus
            int stream_id = packet.InfoField2;
            string code = obj.GetProperty(3).ObjectValue.GetProperty("code").StringValue;
            string level = obj.GetProperty(3).ObjectValue.GetProperty("level").StringValue;
            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.NetStream.HandleOnStatus] code :{0}, level: {1}", code, level));

            return Internal_HandleOnStatusDecoded(packet, "onStatus", code, level, obj);
        }