コード例 #1
0
ファイル: ConcurrencyTest.cs プロジェクト: adamedx/locktest
        public ConcurrencyTest(Variant variant, string description)
            : base(variant.ToString() + ": " + description)
        {
            this.variant = variant;

            startThreadsEvent = new ManualResetEvent(false);
            endTestEvent = new ManualResetEvent(false);
        }
コード例 #2
0
ファイル: TestPrimitives.cs プロジェクト: proteanic/protean
        public void TestDateTime()
        {
            DateTime arg = new DateTime(2010, 1, 2, 3, 4, 5, 6);
            Variant v1 = new Variant(arg);
            Assert.AreEqual(v1.Type, Variant.EnumType.DateTime);
            Assert.IsTrue(v1.Is(Variant.EnumType.DateTime));
            Assert.IsTrue(v1.Is<DateTime>());
            Assert.AreEqual(v1.As<DateTime>(), arg);
            Assert.AreEqual(Convert.ToDateTime(v1), arg);

            Assert.AreEqual(v1.ToString(), "2010-01-02T03:04:05.006");

            Variant v2 = new Variant(v1);
            Assert.IsTrue(v1.Equals(v2));
        }
コード例 #3
0
ファイル: TestPrimitives.cs プロジェクト: proteanic/protean
        public void TestBoolean()
        {
            Variant vTrue = new Variant(true);
            Assert.AreEqual(vTrue.Type, Variant.EnumType.Boolean);
            Assert.IsTrue(vTrue.Is(Variant.EnumType.Boolean));
            Assert.IsTrue(vTrue.Is<bool>());
            Assert.IsTrue(vTrue.As<bool>());
            Assert.IsTrue(Convert.ToBoolean(vTrue));
            Assert.AreEqual(vTrue.ToString(), "true");

            Variant vFalse = new Variant(false);
            Assert.AreEqual(vFalse.Type, Variant.EnumType.Boolean);
            Assert.IsTrue(vFalse.Is(Variant.EnumType.Boolean));
            Assert.IsTrue(vFalse.Is<bool>());
            Assert.IsFalse(vFalse.As<bool>());
            Assert.IsFalse(Convert.ToBoolean(vFalse));
            Assert.AreEqual(vFalse.ToString(), "false");

            Variant v1 = new Variant(vTrue);
            Assert.IsTrue(v1.Equals(vTrue));

            Variant v2 = new Variant(vFalse);
            Assert.IsTrue(v2.Equals(vFalse));
        }
コード例 #4
0
ファイル: TestPrimitives.cs プロジェクト: proteanic/protean
        public void TestUInt64()
        {
            Variant v1 = new Variant((UInt64)4);
            Assert.AreEqual(v1.Type, Variant.EnumType.UInt64);
            Assert.IsTrue(v1.Is(Variant.EnumType.UInt64));
            Assert.IsTrue(v1.Is<UInt64>());
            Assert.AreEqual(v1.As<UInt64>(), 4);
            Assert.AreEqual(Convert.ToUInt64(v1), 4);
            Assert.AreEqual(v1.ToString(), "4");

            Variant v2 = new Variant(v1);
            Assert.IsTrue(v1.Equals(v2));
        }
コード例 #5
0
ファイル: TestPrimitives.cs プロジェクト: proteanic/protean
        public void TestTime()
        {
            TimeSpan arg = new TimeSpan(0, 2, 3, 4, 5);
            Variant v1 = new Variant(arg);
            Assert.AreEqual(v1.Type, Variant.EnumType.Time);
            Assert.IsTrue(v1.Is(Variant.EnumType.Time));
            Assert.IsTrue(v1.Is<TimeSpan>());
            Assert.AreEqual(v1.As<TimeSpan>(), arg);

            Assert.AreEqual(v1.ToString(), "02:03:04.005");

            Variant v2 = new Variant(v1);
            Assert.IsTrue(v1.Equals(v2));
        }
コード例 #6
0
ファイル: TestPrimitives.cs プロジェクト: proteanic/protean
        public void TestInt64()
        {
            Variant v1 = new Variant((Int64)3);
            Assert.AreEqual(v1.Type, Variant.EnumType.Int64);
            Assert.IsTrue(v1.Is(Variant.EnumType.Int64));
            Assert.IsTrue(v1.Is<Int64>());
            Assert.AreEqual(v1.As<Int64>(), 3);
            Assert.AreEqual(Convert.ToInt64(v1), 3);
            Assert.AreEqual(v1.ToString(), "3");

            Variant v2 = new Variant(v1);
            Assert.IsTrue(v1.Equals(v2));
        }
コード例 #7
0
ファイル: TestPrimitives.cs プロジェクト: proteanic/protean
        public void TestInt32()
        {
            Variant v1 = new Variant((Int32)1);
            Assert.AreEqual(v1.Type, Variant.EnumType.Int32);
            Assert.IsTrue(v1.Is(Variant.EnumType.Int32));
            Assert.IsTrue(v1.Is<Int32>());
            Assert.AreEqual(v1.As<Int32>(), 1);
            Assert.AreEqual(Convert.ToInt32(v1), 1);
            Assert.AreEqual(v1.ToString(), "1");

            Variant v2 = new Variant(v1);
            Assert.IsTrue(v1.Equals(v2));
        }
コード例 #8
0
        private bool HandleRTSPResponse200Setup(RtspProtocol rtspProtocol, Variant requestHeaders, ref string requestContent, Variant responseHeaders, ref string responseContent)
        {
            if (rtspProtocol.CustomParameters["connectionType"] == "pull")
            {
                if (responseHeaders[RTSP_FIRST_LINE, RTSP_STATUS_CODE] != 200)
                {
                    FATAL("request {0} failed with response {1}",
                        (requestHeaders.ToString()),
                        (responseHeaders.ToString()));
                    return false;
                }
                if (rtspProtocol.CustomParameters["pendingTracks"].ArrayLength != 0)
                    return SendSetupTrackMessages(rtspProtocol);
                //2. Do the play command
                var uri = rtspProtocol.CustomParameters["uri", "fullUri"];
                //3. prepare the play command
                rtspProtocol.PushRequestFirstLine(RTSP_METHOD_PLAY, uri, RTSP_VERSION_1_0);
                return rtspProtocol.SendRequestMessage();
            }
            else
            {
                if (responseHeaders[RTSP_HEADERS, RTSP_HEADERS_TRANSPORT] == null)
                {
                    FATAL("RTSP {0} request doesn't have {1} header line",
                    RTSP_METHOD_SETUP,
                    RTSP_HEADERS_TRANSPORT);
                    return false;
                }
                //3. get the transport header line
                var raw = responseHeaders[RTSP_HEADERS, RTSP_HEADERS_TRANSPORT];
                var transport = Variant.Get();
                if (!SDP.ParseTransportLine(raw, transport))
                {
                    FATAL("Unable to parse transport line {0}", (raw));
                    return false;
                }
                bool forceTcp;
                if (transport["server_port"] != null &&
                    (transport["rtp/avp/udp"] != null || transport["rtp/avp"] != null))
                {
                    forceTcp = false;
                }else if (transport["interleaved"] != null && transport["rtp/avp/tcp"] != null)
                {
                    forceTcp = true;
                }
                else
                {
                    FATAL("Invalid transport line: {0}", (transport.ToString()));
                    return false;
                }
                if (forceTcp != (bool)rtspProtocol.CustomParameters["forceTcp"])
                {
                    FATAL("Invalid transport line: {0}", (transport.ToString()));
                    return false;
                }
                var pConnectivity = GetOutboundConnectivity(rtspProtocol, forceTcp);
                if (pConnectivity == null)
                {
                    FATAL("Unable to get outbound connectivity");
                    return false;
                }
                var param = rtspProtocol.CustomParameters;
                param[param["lastSetup"] == "audio" ? "audioTransport" : "videoTransport"] = transport;
                var variantUri = param["uri"];
                string trackId = "";
                bool isAudio = false;
                if (param["audioTrackId"] != null)
                {
                    trackId = param["audioTrackId"];
                    param["audioTrackId"] = null;
                    param["lastSetup"] = "audio";
                    isAudio = true;
                    pConnectivity.HasAudio = true;
                }
                else
                {
                    if (param["videoTrackId"] != null)
                    {
                        trackId = param["videoTrackId"];
                        param["videoTrackId"] = null;
                        param["lastSetup"] = "video";
                        pConnectivity.HasVideo = true;
                    }
                }
                if (trackId != "")
                {
                    var uri = variantUri["fullUri"] + "/trackID=" + trackId;
                    rtspProtocol.PushRequestFirstLine(RTSP_METHOD_SETUP, uri, RTSP_VERSION_1_0);
             
                    transport = forceTcp ? $"RTP/AVP/TCP;unicast;interleaved={(isAudio ? pConnectivity.AudioChannels : pConnectivity.VideoChannels)};mode=record" : $"RTP/AVP;unicast;client_port={(isAudio ? pConnectivity.AudioChannels : pConnectivity.VideoChannels)};mode=record";
                    rtspProtocol.PushRequestHeader(RTSP_HEADERS_TRANSPORT, transport);
                    return rtspProtocol.SendRequestMessage();
                }
                else
                {
                    rtspProtocol.PushRequestFirstLine(RTSP_METHOD_RECORD,variantUri["fullUri"],RTSP_VERSION_1_0);
                    return rtspProtocol.SendRequestMessage();
                }

            }
        }
コード例 #9
0
        //public void SignalONS(BaseOutNetRTMPStream pONS)
        //{
        //    if (_pSignaledRTMPOutNetStream.Contains(pONS)) return;
        //    _pSignaledRTMPOutNetStream.AddLast(pONS);
        //}

        public InFileRTMPStream CreateIFS(Variant metadata)
        {
            var pRtmpInFileStream = InFileRTMPStream.GetInstance(this, Application.StreamsManager, metadata);
            if (pRtmpInFileStream == null)
            {
                WARN("Unable to get file stream. Metadata:\n{0}", metadata.ToString());
                return null;
            }
            if (!pRtmpInFileStream.Initialize(metadata[CONF_APPLICATION_CLIENTSIDEBUFFER]))
            {
                WARN("Unable to initialize file inbound stream");
                pRtmpInFileStream.Dispose();
                return null;
            }
           // _inFileStreams.Add(pRtmpInFileStream);
            return pRtmpInFileStream;
        }
コード例 #10
0
ファイル: Program.cs プロジェクト: fifoforlifo/QRBuild
        static void TestBuildVariant()
        {
            Variant v = new Variant();

            string format = v.GetVariantStringFormat();
            Console.WriteLine("VariantStringFormat  = {0}", format);
            string value = v.ToString();
            Console.WriteLine("VariantString        = {0}", value);
            string options = v.GetVariantStringOptions("\t");
            Console.WriteLine("VariantStringOptions = \n{0}", options);

            Variant v2 = new Variant();
            v2.FromString("Develop.x64.NopeNotThisTime");
            Console.WriteLine("FromString,ToString  = {0}", v2.ToString());
        }
コード例 #11
0
 private bool HandleRTSPResponse(RtspProtocol rtspProtocol, Variant requestHeaders,ref string requestContent, Variant responseHeaders,ref string responseContent)
 {
     switch ((uint)responseHeaders[RTSP_FIRST_LINE, RTSP_STATUS_CODE])
     {
         case 200:
             switch ((string)requestHeaders[RTSP_FIRST_LINE,RTSP_METHOD])
             {
                 case RTSP_METHOD_OPTIONS:
                     return HandleRTSPResponse200Options(rtspProtocol,requestHeaders,ref requestContent, responseHeaders,ref responseContent);
                 case RTSP_METHOD_DESCRIBE:
                     return HandleRTSPResponse200Describe(rtspProtocol, requestHeaders, ref requestContent, responseHeaders, ref responseContent);
                 case RTSP_METHOD_SETUP:
                     return HandleRTSPResponse200Setup(rtspProtocol, requestHeaders, ref requestContent, responseHeaders, ref responseContent);
                 case RTSP_METHOD_PLAY:
                     return HandleRTSPResponse200Play(rtspProtocol, requestHeaders, ref requestContent, responseHeaders, ref responseContent);
                 case RTSP_METHOD_ANNOUNCE:
                     return HandleRTSPResponse200Announce(rtspProtocol, requestHeaders, ref requestContent, responseHeaders, ref responseContent);
                 case RTSP_METHOD_RECORD:
                     return HandleRTSPResponse200Record(rtspProtocol, requestHeaders, ref requestContent, responseHeaders, ref responseContent);
                 case RTSP_METHOD_TEARDOWN:
                     return true;
                 default:
                     return false;
             }
         case 401:
             var username = rtspProtocol.CustomParameters["uri", "userName"];
             var password = rtspProtocol.CustomParameters["uri", "password"];
             if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
             {
                 FATAL("No username/password provided");
                 return false;
             }
             string auth = responseHeaders[RTSP_HEADERS, HTTP_HEADERS_WWWAUTHENTICATE];
             if (string.IsNullOrEmpty(auth))
             {
                 FATAL("Invalid 401 response: {0}", (responseHeaders.ToString()));
                 return false;
             }
             if (!rtspProtocol.SetAuthentication(auth, username, password))
             {
                 FATAL("Unable to authenticate: request headers:\n{0}\nresponseHeaders:\n{1}",
         (requestHeaders.ToString()),
         (responseHeaders.ToString()));
                 return false;
             }
             return true;
         case 404:
             switch ((string)requestHeaders[RTSP_FIRST_LINE, RTSP_METHOD])
             {
                 case RTSP_METHOD_PLAY:
                     FATAL("PLAY: Resource not found: "+(requestHeaders[RTSP_FIRST_LINE][RTSP_URL]));
                     return false;
                 case RTSP_METHOD_DESCRIBE:
                     FATAL("DESCRIBE: Resource not found: "+(requestHeaders[RTSP_FIRST_LINE][RTSP_URL]));
                     return false;
                 default:
                     FATAL("Response for method {0} not implemented yet\n{1}", ((string)requestHeaders[RTSP_FIRST_LINE, RTSP_METHOD]),
         (responseHeaders.ToString()));
                     return false;
             }
         default:
             return false;
     }
 }
コード例 #12
0
        public bool HandleRTSPResponse(RtspProtocol rtspProtocol, Variant responseHeaders,ref string responseContent)
        {
           
            if (responseHeaders[RTSP_HEADERS, RTSP_HEADERS_SESSION] != null)
            {
                rtspProtocol.SessionId = responseHeaders[RTSP_HEADERS, RTSP_HEADERS_SESSION];
            }
            if (responseHeaders[RTSP_HEADERS, RTSP_HEADERS_CSEQ] == null)
            {
                FATAL("Invalid response:\n{0}", (responseHeaders.ToString()));
                return false;
            }
            Variant requestHeaders = Variant.Get();
            string requestContent = "";
            rtspProtocol.GetRequest(responseHeaders[RTSP_HEADERS, RTSP_HEADERS_CSEQ], requestHeaders, ref requestContent);
            
            //2. Get the request, get the response and call the stack further
            return HandleRTSPResponse(rtspProtocol,
                    requestHeaders,
                   ref requestContent,
                    responseHeaders,
                   ref responseContent);

        }
コード例 #13
0
        private bool HandleRTSPRequestAnnounce(RtspProtocol pFrom, Variant requestHeaders, string requestContent)
        {
            //1. Make sure we ONLY handle application/sdp
            if ((string)requestHeaders[RTSP_HEADERS,RTSP_HEADERS_CONTENT_TYPE]!= RTSP_HEADERS_ACCEPT_APPLICATIONSDP)
            {
                FATAL("Invalid ANNOUNCE request:\n{0}", (requestHeaders.ToString()));
                return false;
            }

            //2. Get the SDP
            var sdp = pFrom.InboundSDP;

            //3. Parse the SDP
            if (!SDP.ParseSDP(sdp, requestContent))
            {
                FATAL("Unable to parse the SDP");
                return false;
            }

            //4. Get the first video track
            var videoTrack = sdp.GetVideoTrack(0,requestHeaders[RTSP_FIRST_LINE,RTSP_URL]);
                    
            var audioTrack = sdp.GetAudioTrack(0,requestHeaders[RTSP_FIRST_LINE,RTSP_URL]);
                    

            //5. Store the tracks inside the session for later use
            if (audioTrack != VariantType.Null)
            {
                pFrom.CustomParameters["pendingTracks",audioTrack["globalTrackIndex"]] = audioTrack;
            }
            if (videoTrack != VariantType.Null)
            {
                pFrom.CustomParameters["pendingTracks",videoTrack["globalTrackIndex"]] = videoTrack;
            }

            //6. Mark this connection as inbound connection
            pFrom.CustomParameters["isInbound"] = true;

            //7. Save the streamName
            string streamName = sdp.GetStreamName();
            if (streamName == "")
            {
                streamName = $"rtsp_stream_{pFrom.Id}";
            }
            pFrom.CustomParameters["sdpStreamName"] = streamName;
            streamName = new Uri(requestHeaders[RTSP_FIRST_LINE, RTSP_URL],UriKind.Absolute).Segments.Last();
            //8. Save the bandwidth hint
            pFrom.CustomParameters["sdpBandwidthHint"] = sdp.GetTotalBandwidth();

            //9. Get the inbound connectivity
            InboundConnectivity pInboundConnectivity = pFrom.GetInboundConnectivity(
                    streamName,
                    sdp.GetTotalBandwidth(),Application.Configuration[CONF_APPLICATION_RTCPDETECTIONINTERVAL]);
            if (pInboundConnectivity == null)
            {
                FATAL("Unable to create inbound connectivity");
                return false;
            }

            //8. Send back the response
            pFrom.PushResponseFirstLine(RTSP_VERSION_1_0, 200, "OK");
            return pFrom.SendResponseMessage();
        }
コード例 #14
0
 private bool HandleRTSPResponse200Options(RtspProtocol rtspProtocol, Variant requestHeaders, ref string requestContent, Variant responseHeaders, ref string responseContent)
 {
     if (rtspProtocol.HasConnectivity) return true;
     if (rtspProtocol.CustomParameters["connectionType"] == null)
     {
         FATAL("Bogus connection");
         rtspProtocol.EnqueueForDelete();
         return false;
     }
     //1. Sanitize
     if (responseHeaders[RTSP_HEADERS, RTSP_HEADERS_PUBLIC] == null)
     {
         FATAL("Invalid response:\n{0}", (responseHeaders.ToString()));
         return false;
     }
     //2. get the raw options
     string raw = responseHeaders[RTSP_HEADERS, RTSP_HEADERS_PUBLIC];
     //3. split and normalize the options
     var parts = raw.Split(',').Select(x => x.Split(':')).ToDictionary(x => x[0], x => x[1]);
     string url = requestHeaders[RTSP_FIRST_LINE, RTSP_URL];
     switch ((string)rtspProtocol.CustomParameters["connectionType"])
     {
         case "pull":
             //4. Test the presence of the wanted methods
             if (!parts.ContainsKey(RTSP_METHOD_DESCRIBE) || !parts.ContainsKey(RTSP_METHOD_SETUP) ||
                 !parts.ContainsKey(RTSP_METHOD_PLAY))
             {
                 FATAL("Some of the supported methods are missing: {0}", (raw));
                 return false;
             }
             rtspProtocol.PushRequestFirstLine(RTSP_METHOD_DESCRIBE, url, RTSP_VERSION_1_0);
             rtspProtocol.PushRequestHeader(RTSP_HEADERS_ACCEPT, RTSP_HEADERS_ACCEPT_APPLICATIONSDP);
             return rtspProtocol.SendRequestMessage();
         case "push":
             //4. Test the presence of the wanted methods
             if (!parts.ContainsKey(RTSP_METHOD_ANNOUNCE) || !parts.ContainsKey(RTSP_METHOD_SETUP) ||
                 !parts.ContainsKey(RTSP_METHOD_RECORD))
             {
                 FATAL("Some of the supported methods are missing: {0}", (raw));
                 return false;
             }
             var parameters = rtspProtocol.CustomParameters;
             rtspProtocol.PushRequestFirstLine(RTSP_METHOD_ANNOUNCE,url,RTSP_VERSION_1_0);
             var sdp = ComputeSDP(rtspProtocol,
                 parameters["customParameters","localStreamConfig","localStreamName"],
                 parameters["customParameters","localStreamConfig","targetStreamName"],
                 parameters["customParameters","localStreamConfig","targetUri","host"]);
             if (sdp == "")
             {
                 FATAL("Unable to compute sdp");
                 return false;
             }
             rtspProtocol.PushRequestHeader(RTSP_HEADERS_CONTENT_TYPE, RTSP_HEADERS_ACCEPT_APPLICATIONSDP);
             rtspProtocol.PushRequestContent(sdp,false);
             return rtspProtocol.SendRequestMessage();
         default:
             FATAL("Bogus connection");
             rtspProtocol.EnqueueForDelete();
             return false;
     }
 }
コード例 #15
0
 private bool HandleRTSPResponse200Describe(RtspProtocol rtspProtocol, Variant requestHeaders, ref string requestContent, Variant responseHeaders, ref string responseContent)
 {
     //1. Make sure we ONLY handle application/sdp
     if (responseHeaders[RTSP_HEADERS, RTSP_HEADERS_CONTENT_TYPE] == null)
     {
         FATAL("Invalid DESCRIBE response:\n{0}", (requestHeaders.ToString()));
         return false;
     }
     if (responseHeaders[RTSP_HEADERS, RTSP_HEADERS_CONTENT_TYPE] == RTSP_HEADERS_ACCEPT_APPLICATIONSDP)
     {
         FATAL("Invalid DESCRIBE response:\n{0}", (requestHeaders.ToString()));
         return false;
     }
     //2. Get the SDP
     var sdp = rtspProtocol.InboundSDP;
     //3. Parse the SDP
     if (!SDP.ParseSDP(sdp, responseContent))
     {
         FATAL("Unable to parse the SDP");
         return false;
     }
     //4. Get the first video track
     var videoTrack = sdp.GetVideoTrack(0,requestHeaders[RTSP_FIRST_LINE,RTSP_URL]);
     var audioTrack = sdp.GetAudioTrack(0,requestHeaders[RTSP_FIRST_LINE,RTSP_URL]);
     if ((videoTrack == VariantType.Null) && (audioTrack == VariantType.Null))
     {
         FATAL("No compatible tracks found");
         return false;
     }
     var forceTcp = rtspProtocol.CustomParameters["forceTcp"];
     var rtcpDetectionInterval = Application.Configuration[CONF_APPLICATION_RTCPDETECTIONINTERVAL];
     if (rtspProtocol.CustomParameters[CONF_APPLICATION_RTCPDETECTIONINTERVAL]!=null)
         rtcpDetectionInterval = (byte)rtspProtocol.CustomParameters[CONF_APPLICATION_RTCPDETECTIONINTERVAL];
     //5. Store the tracks inside the session for later use
     if (audioTrack != VariantType.Null)
     {
         audioTrack["isTcp"] = (bool)forceTcp;
         rtspProtocol.CustomParameters["pendingTracks"][(int)audioTrack["globalTrackIndex"]] = audioTrack;
     }
     if (videoTrack != VariantType.Null)
     {
         videoTrack["isTcp"] = (bool)forceTcp;
         rtspProtocol.CustomParameters["pendingTracks"][(int)videoTrack["globalTrackIndex"]] = videoTrack;
     }
     //6. Save the streamName
     string streamName = sdp.GetStreamName();
     if (streamName == "")
     {
         streamName = "rtsp_stream_"+rtspProtocol.Id;
     }
     rtspProtocol.CustomParameters["sdpStreamName"] = streamName;
     //7. Save the bandwidth hint
     rtspProtocol.CustomParameters["sdpBandwidthHint"] = sdp.GetTotalBandwidth();
     //8. Get the inbound connectivity
     var pInboundConnectivity = rtspProtocol.GetInboundConnectivity(streamName, sdp.GetTotalBandwidth(),
         rtcpDetectionInterval);
     if (pInboundConnectivity == null)
     {
         FATAL("Unable to create inbound connectivity");
         return false;
     }
     //9. Start sending the setup commands on the pending tracks;
     return SendSetupTrackMessages(rtspProtocol);
 }
コード例 #16
0
ファイル: TestPrimitives.cs プロジェクト: proteanic/protean
        public void TestDouble()
        {
            Variant v1 = new Variant((double)5.0);
            Assert.AreEqual(v1.Type, Variant.EnumType.Double);
            Assert.IsTrue(v1.Is(Variant.EnumType.Double));
            Assert.IsTrue(v1.Is<double>());
            Assert.AreEqual(v1.As<double>(), 5.0);
            Assert.AreEqual(Convert.ToDouble(v1), 5.0);
            Assert.AreEqual(v1.ToString(), "5");

            Variant vNaN = new Variant(double.NaN);
            Assert.AreEqual(vNaN.ToString(), "NaN");

            Variant vINF = new Variant(double.PositiveInfinity);
            Assert.AreEqual(vINF.ToString(), "INF");

            Variant vNEGINF = new Variant(double.NegativeInfinity);
            Assert.AreEqual(vNEGINF.ToString(), "-INF");

            Variant v2 = new Variant(v1);
            Assert.IsTrue(v1.Equals(v2));
        }
コード例 #17
0
 public static bool SignalProtocolCreated(BaseProtocol protocol, Variant customParameters)
 {
     var application = ClientApplicationManager.FindAppByName(customParameters[Defines.CONF_APPLICATION_NAME]);
     if (application == null)
     {
         Logger.FATAL("Application {0} not found",customParameters[Defines.CONF_APPLICATION_NAME]);
         return false;
     }
     if (protocol == null)
     {
         Logger.FATAL("Connection failed:{0}", customParameters.ToString());
         return application.OutboundConnectionFailed(customParameters);
     }
     protocol.Application = application;
     var outboundRTMPProtocol = protocol as OutboundRTMPProtocol;
     outboundRTMPProtocol.CustomParameters = customParameters;
     return outboundRTMPProtocol.SignalInputData(0);
 }
コード例 #18
0
ファイル: Module.cs プロジェクト: langhuihui/csharprtmp
 bool BindAcceptor(Variant node)
 {
     //1. Get the chain
    var chain = ProtocolFactoryManager.ResolveProtocolChain(node[CONF_PROTOCOL]);
     if (chain.Count == 0)
     {
         WARN("Invalid protocol chain: {0}",node[CONF_PROTOCOL]);
     }
     //2. Is it TCP or UDP based?
     if (chain[0] == ProtocolTypes.PT_TCP)
     {
         //3. This is a tcp acceptor. Instantiate it and start accepting connections
         var pAcceptor = new TCPAcceptor( node[CONF_IP], node[CONF_PORT], node, chain);
         if (!pAcceptor.Bind())
         {
             FATAL("Unable to fire up acceptor from this config node:{0}",node.ToString());
             return false;
         }
         acceptors.Add(pAcceptor);
         return true;
     }
     else if (chain[0] == ProtocolTypes.PT_UDP)
     {
         //4. Ok, this is an UDP acceptor. Because of that, we can instantiate
         //the full stack. Get the stack first
         var pProtocol = ProtocolFactoryManager.CreateProtocolChain(chain, node);
         if (pProtocol == null)
         {
             FATAL("Unable to instantiate protocol stack {0}", node[CONF_PROTOCOL]);
             return false;
         }
         //5. Create the carrier and bind it
         var pUDPCarrier = UDPCarrier.Create(node[CONF_IP], node[CONF_PORT], pProtocol);
         if (pUDPCarrier == null)
         {
             FATAL("Unable to instantiate UDP carrier on {0}:{1}", node[CONF_IP],
                 node[CONF_PORT]);
             pProtocol.EnqueueForDelete();
             return false;
         }
         pUDPCarrier.Parameters = node;
         acceptors.Add(pUDPCarrier);
         return true;
     }
     else
     {
         FATAL("Invalid carrier type");
         return false;
     }
 }
コード例 #19
0
        public bool InboundMessageAvailable(BaseRTMPProtocol pFrom,  Variant messageBody, Channel channel,out bool recycleBody)
        {
            recycleBody = true;
            AmfMessage message;
            message.Header = channel.lastInHeader;
            message.Body = messageBody;
            var parameters = pFrom.CustomParameters;
            if (parameters["authState"] == null)
            {
                parameters["authState"] = Variant.GetMap(new VariantMapHelper
                {
                    {"stage","authenticated"},
                    {"canPublish",true},
                    {"canOverrideStreamName",false}
                });
               
            }
            var authState = parameters["authState"];
            if (pFrom.Type == ProtocolTypes.PT_INBOUND_RTMP && !string.IsNullOrEmpty(_authMethod))
            {
                if (!AuthenticateInbound(pFrom, message, authState))
                {
                    Logger.FATAL("Unable to authenticate");
                    return false;
                }
            }
            uint size;
            Dictionary<uint, IStream> possibleStreams;
            InNetRTMPStream pInNetRTMPStream;
            switch (message.MessageType)
            {
                case Defines.RM_HEADER_MESSAGETYPE_WINACKSIZE:
                    if (messageBody[Defines.RM_WINACKSIZE] != VariantType.Numberic)
                    {
                        Logger.FATAL("Invalid message:{0}", messageBody.ToString());
                        return false;
                    }
                    size = messageBody[Defines.RM_WINACKSIZE];
                    if ((size > 4 * 1024 * 1024) || size == 0)
                    {
                        Logger.FATAL("Invalid message:{0}", messageBody.ToString());
                        return false;
                    }
                    pFrom.SetWinAckSize(size);
                    return true;
                case Defines.RM_HEADER_MESSAGETYPE_PEERBW:
                    Logger.WARN("ProcessPeerBW");
                    return true;
                case Defines.RM_HEADER_MESSAGETYPE_ACK:
                    return true;
                case Defines.RM_HEADER_MESSAGETYPE_CHUNKSIZE:
                    if (messageBody[Defines.RM_CHUNKSIZE] != VariantType.Numberic)
                    {
                        Logger.FATAL("Invalid message:{0}", messageBody.ToString());
                        return false;
                    }
                    size = messageBody[Defines.RM_CHUNKSIZE];
                    if ((size > 4 * 1024 * 1024) || size == 0)
                    {
                        Logger.FATAL("Invalid message:{0}", messageBody.ToString());
                        return false;
                    }
                    if (!pFrom.SetInboundChunkSize(size))
                    {
                        Logger.FATAL("Unable to set chunk size:{0}", messageBody.ToString());
                        return false;
                    }
                    return true;
                case Defines.RM_HEADER_MESSAGETYPE_USRCTRL:
                    switch ((ushort)messageBody[Defines.RM_USRCTRL, Defines.RM_USRCTRL_TYPE])
                    {
                        case Defines.RM_USRCTRL_TYPE_PING_REQUEST:
                            return SendRTMPMessage(pFrom,  ConnectionMessageFactory.GetPong());
                        case Defines.RM_USRCTRL_TYPE_STREAM_BEGIN:
                        case Defines.RM_USRCTRL_TYPE_STREAM_SET_BUFFER_LENGTH:
                        case Defines.RM_USRCTRL_TYPE_STREAM_IS_RECORDED:
                        case Defines.RM_USRCTRL_TYPE_PING_RESPONSE:
                            Logger.WARN("User control message type: {0}",
                                messageBody[Defines.RM_USRCTRL, Defines.RM_USRCTRL_TYPE_STRING]);
                            return true;
                        case Defines.RM_USRCTRL_TYPE_UNKNOWN1:
                        case Defines.RM_USRCTRL_TYPE_UNKNOWN2:
                            return true;
                        default:
                            Logger.FATAL("Invalid user ctrl:\n{0}", messageBody.ToString());
                            return false;
                    }
                case Defines.RM_HEADER_MESSAGETYPE_NOTIFY:
                    //1. Find the corresponding inbound stream
                    possibleStreams = Application.StreamsManager.FindByProtocolIdByType(pFrom.Id,
                        StreamTypes.ST_IN_NET_RTMP, false);
                    pInNetRTMPStream = possibleStreams.Select(x => x.Value as InNetRTMPStream)
                        .SingleOrDefault(
                            x => x.RtmpStreamId == message.StreamId);
                    if (pInNetRTMPStream == null)
                    {
                        Logger.WARN("No stream found. Serached for {0}:{1}. Message was:{2}", pFrom.Id, message.StreamId, messageBody.ToString());
                        return true;
                    }
                    //2. Remove all string values starting with @
                    foreach (var item in messageBody[Defines.RM_NOTIFY, Defines.RM_NOTIFY_PARAMS].Children.Where(
                        x => x.Value == VariantType.String && ((string)x.Value).StartsWith("@")).Select(x => x.Key).ToArray())
                    {
                        messageBody[Defines.RM_NOTIFY, Defines.RM_NOTIFY_PARAMS].Children.Remove(item);
                    }
                    recycleBody = false;
                    //3. Brodcast the message on the inbound stream
                    pInNetRTMPStream.SendStreamMessage(new BufferWithOffset(((MemoryStream)channel.inputData.BaseStream).GetBuffer(), length: (int)message.MessageLength));
                    return true;
                case Defines.RM_HEADER_MESSAGETYPE_FLEXSTREAMSEND:
                    recycleBody = false;
                    //1. Find the corresponding inbound stream
                    possibleStreams = Application.StreamsManager.FindByProtocolIdByType(pFrom.Id, StreamTypes.ST_IN_NET_RTMP, false);
                    pInNetRTMPStream = possibleStreams.Select(x => x.Value as InNetRTMPStream)
                        .SingleOrDefault(x => x.RtmpStreamId == message.StreamId);
                    if (pInNetRTMPStream == null)
                    {
                        Logger.WARN("No stream found. Serached for {0}:{1}. Message was:{2}", pFrom.Id, message.StreamId, messageBody.ToString());
                        return true;
                    }
                    //2. Remove all string values starting with @
                    foreach (var item in messageBody[Defines.RM_FLEXSTREAMSEND, Defines.RM_FLEXSTREAMSEND_PARAMS].Children.Where(
                        x => x.Value == VariantType.String && ((string)x.Value).StartsWith("@")).Select(x => x.Key).ToArray())
                    {
                        messageBody[Defines.RM_FLEXSTREAMSEND, Defines.RM_FLEXSTREAMSEND_PARAMS].Children.Remove(item);
                    }
                    //写入文件
                    //pInNetRTMPStream.SendStreamMessage(channel);
                    //3. Brodcast the message on the inbound stream
                    pInNetRTMPStream.SendStreamMessage(new BufferWithOffset(((MemoryStream)channel.inputData.BaseStream).GetBuffer(),length: (int)message.MessageLength));
                    return true;
                case Defines.RM_HEADER_MESSAGETYPE_SHAREDOBJECT:
                case Defines.RM_HEADER_MESSAGETYPE_FLEXSHAREDOBJECT:
                    return Application.SOManager.Process(pFrom, messageBody);
                case Defines.RM_HEADER_MESSAGETYPE_INVOKE:
                case Defines.RM_HEADER_MESSAGETYPE_FLEX:
                    string functionName = messageBody[Defines.RM_INVOKE][Defines.RM_INVOKE_FUNCTION];
                    Logger.INFO(functionName);
                    uint currentInvokeId = messageBody[Defines.RM_INVOKE, Defines.RM_INVOKE_ID];
                    if (currentInvokeId != 0 && _nextInvokeId[pFrom.Id] <= currentInvokeId)
                    {
                        _nextInvokeId[pFrom.Id] = currentInvokeId + 1;
                    }
                    string streamName;
                    BaseOutNetRTMPStream pBaseOutNetRTMPStream = null;
                    double timeOffset;
                    Variant metadata;
                    switch (functionName)
                    {
                        case Defines.RM_INVOKE_FUNCTION_CONNECT:
                            return ProcessInvokeConnect(pFrom,  message);
                        case Defines.RM_INVOKE_FUNCTION_CREATESTREAM:
                            //1. Create the neutral stream
                            uint id = 0;
                            if (pFrom.CreateNeutralStream(ref id) == null)
                            {
                                Logger.FATAL("Unable to create stream");
                                return false;
                            }
                            //2. Send the response
                            return SendRTMPMessage(pFrom,  StreamMessageFactory.GetInvokeCreateStreamResult(message, id));
                        case Defines.RM_INVOKE_FUNCTION_PUBLISH:
                            //1. gather the required data from the request
                            var param1 = messageBody[Defines.RM_INVOKE, Defines.RM_INVOKE_PARAMS][1];
                            if (param1 != VariantType.String && param1 != VariantType.Boolean)
                            {
                                Logger.FATAL("Invalid request:{0}", messageBody.ToString());
                                return false;
                            }
                            if (param1 == VariantType.Boolean)
                            {
                                if (param1 != false)
                                {
                                    Logger.FATAL("Invalid request {0}", messageBody.ToString());
                                    return false;
                                }
                                this.Log().Info("Closing stream via publish(false)");
                                return pFrom.CloseStream(message.StreamId, true);
                            }
                            streamName = param1;
                            //2. Check to see if we are allowed to create inbound streams
                            if (!pFrom.CustomParameters["authState"]["canPublish"])
                            {
                                return
                                    pFrom.SendMessage(StreamMessageFactory.GetInvokeOnStatusStreamPublishBadName(
                                        message, streamName),true);
                            }
                            var recording = string.Equals(message.InvokeParam[2], Defines.RM_INVOKE_PARAMS_PUBLISH_TYPERECORD);
                            var appending = string.Equals(message.InvokeParam[2], Defines.RM_INVOKE_PARAMS_PUBLISH_TYPEAPPEND);
                            //3. Test to see if this stream name is already published somewhere
                            if (Application.AllowDuplicateInboundNetworkStreams)
                            {
                                var existingStreams =
                                    Application.StreamsManager.FindByTypeByName(StreamTypes.ST_IN_NET_RTMP, streamName,false, false);
                                        
                                if (existingStreams.Count > 0)
                                {
                                    if (pFrom.CustomParameters["authState"]["canOverrideStreamName"])
                                    {
                                        foreach (var existingStream in existingStreams.Values.OfType<InNetRTMPStream>().Where(existingStream => existingStream.Protocol != null))
                                        {
                                            Logger.WARN(
                                                "Overriding stream {0}:{1} with name {2} from conneciton {3}",
                                                existingStream.RtmpStreamId, existingStream.UniqueId,
                                                existingStream.Name, existingStream.Protocol.Id);
                                            (existingStream.Protocol as BaseRTMPProtocol).CloseStream(
                                                existingStream.RtmpStreamId, true);
                                        }
                                    }
                                    else
                                    {
                                        Logger.WARN(
                                            "Unable to override stream {0} because this connection dosen't have the right",
                                            streamName);
                                        return
                                            pFrom.SendMessage(
                                                StreamMessageFactory.GetInvokeOnStatusStreamPublishBadName(message,
                                                    streamName),true);
                                    }
                                }
                            }
                            else if (!Application.StreamNameAvailable(streamName, pFrom))
                            {
                                Logger.WARN("Stream name {0} already occupied and application doesn't allow duplicated inbound network streams", streamName);
                                return
                                    pFrom.SendMessage( StreamMessageFactory.GetInvokeOnStatusStreamPublishBadName(
                                        message, streamName), true);
                            }
                            //4. Create the network inbound stream
                            pInNetRTMPStream = pFrom.CreateINS(message.ChannelId, message.StreamId, streamName);
                            if (pInNetRTMPStream == null)
                            {
                                Logger.FATAL("Unable to create inbound stream");
                                return false;
                            }
                            //7. Bind the waiting subscribers
                            Application.OnPublish(pFrom, pInNetRTMPStream, message.InvokeParam[2]);
                            //8. Send the streamPublished status message
                            if (!pInNetRTMPStream.SendOnStatusStreamPublished())
                            {
                                Logger.FATAL("Unable to send OnStatusStreamPublished");
                                return false;
                            }
                            //9. Start recording if necessary
                            //if (recording || appending)
                            //{
                                
                            //    var meta = GetMetaData(streamName, false);
                            //    var pOutFileStream = CreateOutFileStream(pFrom, meta, appending);
                            //    if (pOutFileStream != null && pOutFileStream.Link(pInNetRTMPStream)) return true;
                            //    Logger.FATAL("Unable to bind the recording stream");
                            //    return false;
                            //}
                            return true;
                        case Defines.RM_INVOKE_FUNCTION_PLAY:
                            //1. Minimal validation
                            if (message.InvokeParam[1] != VariantType.String)
                            {
                                Logger.FATAL("Invalid request:{0}", message.Body.ToString());
                                return false;
                            }
                            //2. Close any streams left open
                            if (!pFrom.CloseStream(message.StreamId, true))
                            {
                                Logger.FATAL("Unable to close stream {0} {1}", pFrom.Id, message.StreamId);
                                return false;
                            }
                            //3. Gather required data from the request
                            streamName = message.InvokeParam[1];
                            double startTime = message.InvokeParam[2] == VariantType.Double ? (double)message.InvokeParam[2] : -2000;
                            double length = message.InvokeParam[3] == VariantType.Double ? (double)message.InvokeParam[3] : -1000;
                            if (startTime < 0 && startTime != -2000 && startTime != -1000) startTime = -2000;
                            if (length < 0 && length != -1) length = -1;
                            
                            Logger.INFO("Play request for stream name `{0}`. Start:{1}; length: {2}",    streamName, startTime, length);
                            //6. bind the network outbound stream to the inbound stream
                            //depending on the type of the outbound stream
                            switch ((int)startTime)
                            {
                                case -2000:
                                    bool linked;
                                    //7. try to link to live stream
                                    if (!TryLinkToLiveStream(pFrom, message.StreamId, streamName, out linked))
                                    {
                                        Logger.FATAL("Unable to link streams");
                                        return false;
                                    }
                                    if (linked) return true;

                                    metadata = GetMetaData(streamName, true);
                                    //8. try to link to file stream
                                    if (!TryLinkToFileStream(pFrom, message.StreamId, metadata, streamName, startTime, length, out linked))
                                    {
                                        Logger.FATAL("Unable to link streams");
                                        return false;
                                    }
                                    if (linked) return true;
                                    //9. Ok, no live/file stream. Just wait for the live stream now...
                                    Logger.WARN("We are going to wait for the live stream `{0}`", streamName);
                                    pBaseOutNetRTMPStream = pFrom.CreateONS(message.StreamId, streamName, StreamTypes.ST_IN_NET_RTMP);
                                    goto case -999;
                                case -1000://only live
                                    if (!TryLinkToLiveStream(pFrom, message.StreamId, streamName, out linked))
                                    {
                                        Logger.FATAL("Unable to link streams");
                                        return false;
                                    }
                                    if (linked) return true;
                                    Logger.WARN("We are going to wait for the live stream `%s`", streamName);
                                    pBaseOutNetRTMPStream = pFrom.CreateONS(
                                        message.StreamId, streamName, StreamTypes.ST_IN_NET_RTMP);
                                    goto case -999;
                                case -999:
                                    //Application.ClusterAppProtocolHandler.PlayStream(Application.InstanceName,streamName);
                                    if (ClientApplicationManager.ClusterApplication != null)
                                    {
                                        ClientApplicationManager.ClusterApplication.GetProtocolHandler<BaseClusterAppProtocolHandler>().PlayStream(Application.Id, streamName);
                                    }
                                    //request["waitForLiveStream"] = true;
                                    //request["streamName"] = streamName;
                                    //if (pFrom.CustomParameters["origin"] != null)
                                    //{
                                        //if (_externalStreamProtocol == null)
                                        //    Application.PullExternalStream(new Variant
                                        //    {
                                        //        {"uri", "rtmp://192.168.20.56/live"},
                                        //        {"localStreamName", streamName},
                                        //        {"emulateUserAgent", "MAC 10,1,82,76"},
                                        //        {"swfUrl", "my crtmpserver"},
                                        //        {"pageUrl", "linkage"}
                                        //    });
                                        //else
                                        //{
                                        //    PlayAnotherStream(_externalStreamProtocol, streamName);
                                        //}
                                    //}
                                    return pBaseOutNetRTMPStream != null;
                                default://only recorded
                                    metadata = GetMetaData(streamName, true);
                                    //12. Perform little adjustment on metadata
                                    if ((string)metadata[Defines.META_MEDIA_TYPE] == Defines.MEDIA_TYPE_LIVE_OR_FLV)
                                    {
                                        metadata[Defines.META_MEDIA_TYPE] = Defines.MEDIA_TYPE_FLV;
                                    }

                                    //13. try to link to file stream

                                    if (!TryLinkToFileStream(pFrom, message.StreamId, metadata, streamName,
                                            startTime, length, out linked))
                                    {
                                        Logger.FATAL("Unable to link streams");
                                        return false;
                                    }
                                    return linked;
                            }
                        case Defines.RM_INVOKE_FUNCTION_PAUSERAW:
                        case Defines.RM_INVOKE_FUNCTION_PAUSE:
                            pBaseOutNetRTMPStream = Application.StreamsManager.FindByProtocolIdByType(pFrom.Id,
                                StreamTypes.ST_OUT_NET_RTMP, true).Values.OfType<BaseOutNetRTMPStream>().SingleOrDefault(x => x.RTMPStreamId == message.StreamId);
                            if (pBaseOutNetRTMPStream == null)
                            {
                                Logger.FATAL("No out stream");
                                return false;
                            }
                            //3. get the operation
                            bool pause = message.InvokeParam[1];
                            if (pause)
                            {
                                //4. Pause it
                                return pBaseOutNetRTMPStream.Pause();
                            }
                            else
                            {
                                timeOffset = 0.0;
                                if (message.InvokeParam[2] == VariantType.Numberic)
                                    timeOffset = message.InvokeParam[2];

                                //8. Perform seek
                                if (!pBaseOutNetRTMPStream.Seek(timeOffset))
                                {
                                    Logger.FATAL("Unable to seek");
                                    return false;
                                }

                                //9. Resume
                                return pBaseOutNetRTMPStream.Resume();
                            }
                        case Defines.RM_INVOKE_FUNCTION_CLOSESTREAM:
                            return pFrom.CloseStream(message.StreamId, true);
                        case Defines.RM_INVOKE_FUNCTION_SEEK:
                            //1. Read stream index and offset in millisecond

                            timeOffset = 0.0;
                            if (message.InvokeParam[1] == VariantType.Numberic)
                                timeOffset = message.InvokeParam[1];

                            //2. Find the corresponding outbound stream
                            pBaseOutNetRTMPStream = Application.StreamsManager.FindByProtocolIdByType(pFrom.Id,
                                StreamTypes.ST_OUT_NET_RTMP, true).Values.OfType<BaseOutNetRTMPStream>().SingleOrDefault(x => x.RTMPStreamId == message.StreamId);
                            if (pBaseOutNetRTMPStream == null)
                            {
                                Logger.FATAL("No out stream");
                                return false;
                            }

                            return pBaseOutNetRTMPStream.Seek(timeOffset);
                        case Defines.RM_INVOKE_FUNCTION_RELEASESTREAM:
                            //1. Attempt to find the stream
                            var streams = Application.StreamsManager.FindByProtocolIdByName(pFrom.Id,
                                message.InvokeParam[1], false);
                            uint streamId = 0;
                            if (streams.Count > 0)
                            {
                                //2. Is this the correct kind?
                                if (streams.Values.First().Type.TagKindOf(StreamTypes.ST_IN_NET_RTMP))
                                {
                                    //3. get the rtmp stream id
                                    pInNetRTMPStream = (InNetRTMPStream)streams.Values.First();
                                    streamId = pInNetRTMPStream.RtmpStreamId;

                                    //4. close the stream
                                    if (!pFrom.CloseStream(streamId, true))
                                    {
                                        Logger.FATAL("Unable to close stream");
                                        return true;
                                    }
                                }
                            }
                            if (streamId > 0)
                            {
                                //5. Send the response
                                if (!pFrom.SendMessage( StreamMessageFactory.GetInvokeReleaseStreamResult(3,
                                        streamId, message.InvokeId, streamId), true))
                                {
                                    Logger.FATAL("Unable to send message to client");
                                    return false;
                                }
                            }
                            else
                            {
                                if (!pFrom.SendMessage( StreamMessageFactory.GetInvokeReleaseStreamErrorNotFound(message), true))
                                {
                                    Logger.FATAL("Unable to send message to client");
                                    return false;
                                }
                            }
                            //3. Done
                            return true;
                        case Defines.RM_INVOKE_FUNCTION_DELETESTREAM:
                            return pFrom.CloseStream(message.InvokeParam[1], false);
                        case Defines.RM_INVOKE_FUNCTION_RESULT:
                        case Defines.RM_INVOKE_FUNCTION_ERROR:
                            if (!_resultMessageTracking.ContainsKey(pFrom.Id) ||
                                !_resultMessageTracking[pFrom.Id].ContainsKey(message.InvokeId))
                                return true;
                            var request0 = _resultMessageTracking[pFrom.Id][message.InvokeId];
                            switch (request0.InvokeFunction)
                            {
                                case Defines.RM_INVOKE_FUNCTION_CONNECT:
                                    return ProcessInvokeConnectResult(pFrom, request0, message);
                                case Defines.RM_INVOKE_FUNCTION_CREATESTREAM:
                                    return ProcessInvokeCreateStreamResult(pFrom, request0, message);
                                case Defines.RM_INVOKE_FUNCTION_FCSUBSCRIBE:
                                    return true;
                                case Defines.RM_INVOKE_FUNCTION_ONBWCHECK:
                                    startTime = pFrom.CustomParameters["lastOnnBWCheckMessage"];
                                    double totalTime = (DateTime.Now.Ticks - startTime) / (double)1000000;
                                    var speed = (int)(ONBWCHECK_SIZE / totalTime / 1024.0 * 8.0);
                                    return SendRTMPMessage(pFrom, GenericMessageFactory.GetInvokeOnBWDone(speed));
                                default:
                                    Logger.WARN("Invoke result not yet implemented: Request:{0} Response:{1}", request0.ToString(), message.ToString());
                                    return true;
                            }
                        case Defines.RM_INVOKE_FUNCTION_ONSTATUS:
                            return ProcessInvokeOnStatus(pFrom, message);
                        case Defines.RM_INVOKE_FUNCTION_FCPUBLISH:
                            //1. Get the stream name
                            streamName = message.InvokeParam[1];

                            //2. Send the release stream response. Is identical to the one
                            //needed by this f****r
                            //TODO: this is a nasty hack
                            if (!pFrom.SendMessage( StreamMessageFactory.GetInvokeReleaseStreamResult(3, 0, message.InvokeId, 0), true))
                            {
                                Logger.FATAL("Unable to send message to client");
                                return false;
                            }

                            //3. send the onFCPublish message
                            if (!SendRTMPMessage(pFrom,  StreamMessageFactory.GetInvokeOnFCPublish(3, 0, 0, false, 0,
                                    Defines.RM_INVOKE_PARAMS_ONSTATUS_CODE_NETSTREAMPUBLISHSTART, streamName)))
                            {
                                Logger.FATAL("Unable to send message to client");
                                return false;
                            }

                            //4. Done
                            return true;
                        case Defines.RM_INVOKE_FUNCTION_GETSTREAMLENGTH:
                            metadata = GetMetaData(message.InvokeParam[1], true);
                            var _params = Variant.GetList(Variant.Get(),metadata == VariantType.Map
                                ?  metadata[Defines.META_FILE_DURATION]/1000.00 : 0.0);
                            if (!SendRTMPMessage(pFrom,  GenericMessageFactory.GetInvokeResult(message, _params)))
                            {
                                Logger.FATAL("Unable to send message to client");
                                return false;
                            }
                            return true;
                        case Defines.RM_INVOKE_FUNCTION_ONBWDONE:
                            return true;
                        case Defines.RM_INVOKE_FUNCTION_CHECKBANDWIDTH:
                        case "_checkbw":
                            if (!_enableCheckBandwidth)
                            {
                                Logger.WARN("checkBandwidth is disabled.");
                                return true;
                            }
                            if (!SendRTMPMessage(pFrom,  _onBWCheckMessage,true, false))
                            {
                                Logger.FATAL("Unable to send message to flash player");
                                return false;
                            }
                            pFrom.CustomParameters["lastOnnBWCheckMessage"] = DateTime.Now.Ticks;
                            return true;
                        case "receiveAudio":
                            pBaseOutNetRTMPStream = Application.StreamsManager.FindByProtocolIdByType(pFrom.Id,
                               StreamTypes.ST_OUT_NET_RTMP, true).Values.OfType<BaseOutNetRTMPStream>().SingleOrDefault(x => x.RTMPStreamId ==message.StreamId);
                            if (pBaseOutNetRTMPStream != null)
                                pBaseOutNetRTMPStream.ReceiveAudio = message.InvokeParam[1];
                            return true;
                        case "receiveVideo":
                             pBaseOutNetRTMPStream = Application.StreamsManager.FindByProtocolIdByType(pFrom.Id,
                               StreamTypes.ST_OUT_NET_RTMP, true).Values.OfType<BaseOutNetRTMPStream>().SingleOrDefault(x => x.RTMPStreamId == message.StreamId);
                            if (pBaseOutNetRTMPStream != null)
                                pBaseOutNetRTMPStream.ReceiveVideo = message.InvokeParam[1];
                            return true;
                        default:
                            return ProcessInvokeGeneric(pFrom,  message);
                            
                    }
                case Defines.RM_HEADER_MESSAGETYPE_ABORTMESSAGE:
                    if (messageBody[Defines.RM_ABORTMESSAGE] != VariantType.Numberic)
                    {
                        Logger.FATAL("Invalid message {0}", messageBody.ToString());
                        return false;
                    }
                    return pFrom.ResetChannel(messageBody[Defines.RM_ABORTMESSAGE]);
                default:
                    Logger.FATAL("Request type not yet implemented:{0}", messageBody.ToString());
                    return false;
            }
        }