Exemple #1
0
        private void ReturnMessage(RtmptConnection connection, ByteBuffer data, RtmptRequest request)
        {
            ByteBuffer   buffer        = ByteBuffer.Allocate((int)data.Length + 30);
            StreamWriter sw            = new StreamWriter(buffer);
            int          contentLength = data.Limit + 1;

            if (request.HttpVersion == 1)
            {
                sw.Write("HTTP/1.1 200 OK\r\n");
                sw.Write("Cache-Control: no-cache\r\n");
            }
            else
            {
                sw.Write("HTTP/1.0 200 OK\r\n");
                sw.Write("Pragma: no-cache\r\n");
            }
            sw.Write(string.Format("Content-Length: {0}\r\n", contentLength));
            sw.Write("Connection: Keep-Alive\r\n");
            sw.Write(string.Format("Content-Type: {0}\r\n", ContentType.RTMPT));
            sw.Write("\r\n");
            sw.Write((char)connection.PollingDelay);
            sw.Flush();
            BinaryWriter bw = new BinaryWriter(buffer);

            byte[] buf = data.ToArray();
            bw.Write(buf);
            bw.Flush();
            request.Connection.Write(buffer);
        }
Exemple #2
0
        private void ReturnMessage(RtmptConnection connection, ByteBuffer data, RtmptRequest request)
        {
            ByteBuffer   stream = ByteBuffer.Allocate(((int)data.Length) + 30);
            StreamWriter writer = new StreamWriter(stream);
            int          num    = data.Limit + 1;

            if (request.HttpVersion == 1)
            {
                writer.Write("HTTP/1.1 200 OK\r\n");
                writer.Write("Cache-Control: no-cache\r\n");
            }
            else
            {
                writer.Write("HTTP/1.0 200 OK\r\n");
                writer.Write("Pragma: no-cache\r\n");
            }
            writer.Write(string.Format("Content-Length: {0}\r\n", num));
            writer.Write("Connection: Keep-Alive\r\n");
            writer.Write(string.Format("Content-Type: {0}\r\n", "application/x-fcs"));
            writer.Write("\r\n");
            writer.Write((char)connection.PollingDelay);
            writer.Flush();
            BinaryWriter writer2 = new BinaryWriter(stream);

            byte[] buffer = data.ToArray();
            writer2.Write(buffer);
            writer2.Flush();
            request.Connection.Send(stream);
        }
Exemple #3
0
        private void HandleOpen(RtmptRequest request)
        {
            RtmptConnection connection = new RtmptConnection(request.Connection.RemoteEndPoint, this, null, null);

            this._connections[connection.ConnectionId] = connection;
            this.ReturnMessage(connection.ConnectionId + "\n", request);
        }
Exemple #4
0
        private void HandleIdent(RtmptRequest request)
        {
            RtmptConnection connection = new RtmptConnection(this, request.Connection.RemoteEndPoint, null, null);

            FluorineRtmpContext.Initialize(connection);
            _connections[connection.ConnectionId] = connection;
            // Return connection id to client
            ReturnMessage(Ident, request);
        }
Exemple #5
0
        public void Service(RtmptRequest request)
        {
            if (request.HttpMethod != "POST" || request.ContentLength == 0)
            {
                HandleBadRequest(__Res.GetString(__Res.Rtmpt_CommandBadRequest), request);
            }

            string path = request.Url;
            char   p    = path[1];

            switch (p)
            {
            case 'o':     // OPEN_REQUEST
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(__Res.GetString(__Res.Rtmpt_CommandOpen, path));
                }
                HandleOpen(request);
                break;

            case 'c':     // CLOSE_REQUEST
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(__Res.GetString(__Res.Rtmpt_CommandClose, path));
                }
                HandleClose(request);
                break;

            case 's':     // SEND_REQUEST
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(__Res.GetString(__Res.Rtmpt_CommandSend, path));
                }
                HandleSend(request);
                break;

            case 'i':     // IDLE_REQUEST
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(__Res.GetString(__Res.Rtmpt_CommandIdle, path));
                }
                HandleIdle(request);
                break;

            case 'f':     // HTTPIdent request (ident and ident2)
                HandleIdent(request);
                break;

            default:
                HandleBadRequest(__Res.GetString(__Res.Rtmpt_CommandNotSupported, path), request);
                break;
            }
        }
Exemple #6
0
        private void HandleClose(RtmptRequest request)
        {
            RtmptConnection connection = GetConnection(request);

            if (connection == null)
            {
                HandleBadRequest(__Res.GetString(__Res.Rtmpt_UnknownClient, request.Url), request);
                return;
            }
            FluorineRtmpContext.Initialize(connection);
            RemoveConnection(connection.ConnectionId);
            _rtmpHandler.ConnectionClosed(connection);
            ReturnMessage(0, request);
            connection.RealClose();
        }
Exemple #7
0
        private void HandleSend(RtmptRequest request)
        {
            RtmptConnection connection = this.GetConnection(request);

            if (connection == null)
            {
                this.HandleBadRequest(__Res.GetString("Rtmpt_UnknownClient", new object[] { request.Url }), request);
            }
            else
            {
                if (connection.Client != null)
                {
                    connection.Client.Renew();
                }
                int        contentLength = request.ContentLength;
                ByteBuffer data          = request.Data;
                IList      list          = connection.Decode(data);
                if ((list == null) || (list.Count == 0))
                {
                    this.ReturnMessage(connection.PollingDelay, request);
                }
                else
                {
                    foreach (object obj2 in list)
                    {
                        try
                        {
                            if (obj2 is ByteBuffer)
                            {
                                ByteBuffer packet = obj2 as ByteBuffer;
                                connection.RawWrite(packet);
                            }
                            else
                            {
                                FluorineRtmpContext.Initialize(connection);
                                this._rtmpHandler.MessageReceived(connection, obj2);
                            }
                        }
                        catch (Exception exception)
                        {
                            log.Error(__Res.GetString("Rtmp_CouldNotProcessMessage"), exception);
                        }
                    }
                    this.ReturnPendingMessages(connection, request);
                }
            }
        }
Exemple #8
0
        public void Service(RtmptRequest request)
        {
            if ((request.HttpMethod != "POST") || (request.ContentLength == 0))
            {
                this.HandleBadRequest(__Res.GetString("Rtmpt_CommandBadRequest"), request);
            }
            string url = request.Url;

            switch (url[1])
            {
            case 'o':
                if (log.get_IsDebugEnabled())
                {
                    log.Debug(__Res.GetString("Rtmpt_CommandOpen", new object[] { url }));
                }
                this.HandleOpen(request);
                break;

            case 's':
                if (log.get_IsDebugEnabled())
                {
                    log.Debug(__Res.GetString("Rtmpt_CommandSend", new object[] { url }));
                }
                this.HandleSend(request);
                break;

            case 'c':
                if (log.get_IsDebugEnabled())
                {
                    log.Debug(__Res.GetString("Rtmpt_CommandClose", new object[] { url }));
                }
                this.HandleClose(request);
                break;

            case 'i':
                if (log.get_IsDebugEnabled())
                {
                    log.Debug(__Res.GetString("Rtmpt_CommandIdle", new object[] { url }));
                }
                this.HandleIdle(request);
                break;

            default:
                this.HandleBadRequest(__Res.GetString("Rtmpt_CommandNotSupported", new object[] { url }), request);
                break;
            }
        }
Exemple #9
0
        private void HandleSend(RtmptRequest request)
        {
            RtmptConnection connection = GetConnection(request);

            if (connection == null)
            {
                HandleBadRequest(__Res.GetString(__Res.Rtmpt_UnknownClient, request.Url), request);
                return;
            }
            FluorineRtmpContext.Initialize(connection);
            //int length = request.ContentLength;
            ByteBuffer buffer   = request.Data;
            IList      messages = connection.Decode(buffer);

            if (messages == null || messages.Count == 0)
            {
                ReturnMessage(connection.PollingDelay, request);
                return;
            }
            // Execute the received RTMP messages
            foreach (object message in messages)
            {
                try
                {
                    if (message is ByteBuffer)
                    {
                        connection.Write(message as ByteBuffer);
                    }
                    else if (message is byte[])
                    {
                        connection.Write(message as byte[]);
                    }
                    else
                    {
                        _rtmpHandler.MessageReceived(connection, message);
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(__Res.GetString(__Res.Rtmp_CouldNotProcessMessage), ex);
                }
            }
            // Send results to client
            ReturnPendingMessages(connection, request);
        }
Exemple #10
0
        private void HandleClose(RtmptRequest request)
        {
            RtmptConnection connection = this.GetConnection(request);

            if (connection == null)
            {
                this.HandleBadRequest(__Res.GetString("Rtmpt_UnknownClient", new object[] { request.Url }), request);
            }
            else
            {
                if (connection.Client != null)
                {
                    connection.Client.Renew();
                }
                connection.DeferredClose();
                this.ReturnMessage((byte)0, request);
            }
        }
Exemple #11
0
        private void HandleIdle(RtmptRequest request)
        {
            RtmptConnection connection = GetConnection(request);

            if (connection == null)
            {
                HandleBadRequest(__Res.GetString(__Res.Rtmpt_UnknownClient, request.Url), request);
                return;
            }
            if (connection.IsClosing)
            {
                // Tell client to close the connection
                ReturnMessage(0, request);
                connection.RealClose();
                return;
            }
            FluorineRtmpContext.Initialize(connection);
            ReturnPendingMessages(connection, request);
        }
Exemple #12
0
        private void ReturnPendingMessages(RtmptConnection connection, RtmptRequest request)
        {
            ByteBuffer pendingMessages = connection.GetPendingMessages(RESPONSE_TARGET_SIZE);

            if (pendingMessages == null)
            {
                if (connection.IsClosing)
                {
                    this.ReturnMessage((byte)0, request);
                }
                else
                {
                    this.ReturnMessage(connection.PollingDelay, request);
                }
            }
            else
            {
                this.ReturnMessage(connection, pendingMessages, request);
            }
        }
Exemple #13
0
        private void ReturnPendingMessages(RtmptConnection connection, RtmptRequest request)
        {
            ByteBuffer data = connection.GetPendingMessages(RtmptConnection.RESPONSE_TARGET_SIZE);

            if (data == null)
            {
                // no more messages to send...
                if (connection.IsClosing)
                {
                    // Tell client to close connection
                    ReturnMessage(0, request);
                }
                else
                {
                    ReturnMessage(connection.PollingDelay, request);
                }
                return;
            }
            ReturnMessage(connection, data, request);
        }
Exemple #14
0
        private string GetClientId(RtmptRequest request)
        {
            string url = request.Url;

            if (url == string.Empty)
            {
                return(null);
            }
            while ((url.Length > 1) && (url[0] == '/'))
            {
                url = url.Substring(1);
            }
            int index = url.IndexOf('/');
            int num2  = url.IndexOf('/', index + 1);

            if ((index != -1) && (num2 != -1))
            {
                url = url.Substring(index + 1, (num2 - index) - 1);
            }
            return(url);
        }
 public static ByteBuffer HandleBadRequest(string message, RtmptRequest request)
 {
     ByteBuffer buffer = ByteBuffer.Allocate(100);
     StreamWriter sw = new StreamWriter(buffer);
     if (request.HttpVersion == 1)
     {
         sw.Write("HTTP/1.1 400 " + message + "\r\n");
         sw.Write("Cache-Control: no-cache\r\n");
     }
     else
     {
         sw.Write("HTTP/1.0 400 " + message + "\r\n");
         sw.Write("Pragma: no-cache\r\n");
     }
     sw.Write("Content-Type: text/plain\r\n");
     sw.Write("Content-Length: " + message.Length.ToString() + "\r\n");
     sw.Write("Connection: Keep-Alive\r\n");
     sw.Write("\r\n");
     sw.Write(message);
     sw.Flush();
     return buffer;
 }
 public static ByteBuffer ReturnMessage(string message, RtmptRequest request)
 {
     ByteBuffer buffer = ByteBuffer.Allocate(100);
     StreamWriter sw = new StreamWriter(buffer);
     if (request.HttpVersion == 1)
     {
         sw.Write("HTTP/1.1 200 OK\r\n");
         sw.Write("Cache-Control: no-cache\r\n");
     }
     else
     {
         sw.Write("HTTP/1.0 200 OK\r\n");
         sw.Write("Pragma: no-cache\r\n");
     }
     sw.Write("Content-Length: " + message.Length.ToString() + "\r\n");
     sw.Write(string.Format("Content-Type: {0}\r\n", ContentType.RTMPT));
     sw.Write("Connection: Keep-Alive\r\n");
     sw.Write("\r\n");
     sw.Write(message);
     sw.Flush();
     return buffer;
 }
Exemple #17
0
        private void ReturnMessage(byte message, RtmptRequest request)
        {
            ByteBuffer   buffer = ByteBuffer.Allocate(100);
            StreamWriter sw     = new StreamWriter(buffer);

            if (request.HttpVersion == 1)
            {
                sw.Write("HTTP/1.1 200 OK\r\n");
                sw.Write("Cache-Control: no-cache\r\n");
            }
            else
            {
                sw.Write("HTTP/1.0 200 OK\r\n");
                sw.Write("Pragma: no-cache\r\n");
            }
            sw.Write("Content-Length: 1\r\n");
            sw.Write("Connection: Keep-Alive\r\n");
            sw.Write(string.Format("Content-Type: {0}\r\n", ContentType.RTMPT));
            sw.Write("\r\n");
            sw.Write((char)message);
            sw.Flush();
            request.Connection.Write(buffer);
        }
Exemple #18
0
        private void ReturnMessage(string message, RtmptRequest request)
        {
            ByteBuffer   stream = ByteBuffer.Allocate(100);
            StreamWriter writer = new StreamWriter(stream);

            if (request.HttpVersion == 1)
            {
                writer.Write("HTTP/1.1 200 OK\r\n");
                writer.Write("Cache-Control: no-cache\r\n");
            }
            else
            {
                writer.Write("HTTP/1.0 200 OK\r\n");
                writer.Write("Pragma: no-cache\r\n");
            }
            writer.Write("Content-Length: " + message.Length.ToString() + "\r\n");
            writer.Write(string.Format("Content-Type: {0}\r\n", "application/x-fcs"));
            writer.Write("Connection: Keep-Alive\r\n");
            writer.Write("\r\n");
            writer.Write(message);
            writer.Flush();
            request.Connection.Send(stream);
        }
Exemple #19
0
        private string GetClientId(RtmptRequest request)
        {
            string path = request.Url;

            if (path == string.Empty)
            {
                return(null);
            }

            while (path.Length > 1 && path[0] == '/')
            {
                path = path.Substring(1);
            }

            int startPos = path.IndexOf('/');
            int endPos   = path.IndexOf('/', startPos + 1);

            if (startPos != -1 && endPos != -1)
            {
                path = path.Substring(startPos + 1, endPos - startPos - 1);
            }
            return(path);
        }
Exemple #20
0
        private void HandleBadRequest(string message, RtmptRequest request)
        {
            ByteBuffer   buffer = ByteBuffer.Allocate(100);
            StreamWriter sw     = new StreamWriter(buffer);

            if (request.HttpVersion == 1)
            {
                sw.Write("HTTP/1.1 400 " + message + "\r\n");
                sw.Write("Cache-Control: no-cache\r\n");
            }
            else
            {
                sw.Write("HTTP/1.0 400 " + message + "\r\n");
                sw.Write("Pragma: no-cache\r\n");
            }
            sw.Write("Content-Type: text/plain\r\n");
            sw.Write("Content-Length: " + message.Length + "\r\n");
            sw.Write("Connection: Keep-Alive\r\n");
            sw.Write("\r\n");
            sw.Write(message);
            sw.Flush();
            request.Connection.Write(buffer);
        }
 private void HandleIdle(RtmptRequest request)
 {
     RtmptConnection connection = GetConnection(request);
     if (connection == null)
     {
         HandleBadRequest(__Res.GetString(__Res.Rtmpt_UnknownClient, request.Url), request);
         return;
     }
     if (connection.IsClosing)
     {
         // Tell client to close the connection
         ReturnMessage(0, request);
         connection.RealClose();
         return;
     }
     FluorineRtmpContext.Initialize(connection); 
     ReturnPendingMessages(connection, request);
 }
 private RtmptConnection GetConnection(RtmptRequest request)
 {
     string id = GetClientId(request);
     return _connections[id] as RtmptConnection;
 }
        private string GetClientId(RtmptRequest request)
        {
            string path = request.Url;
            if (path == string.Empty)
                return null;

            while (path.Length > 1 && path[0] == '/')
            {
                path = path.Substring(1);
            }

            int startPos = path.IndexOf('/');
            int endPos = path.IndexOf('/', startPos + 1);
            if (startPos != -1 && endPos != -1)
                path = path.Substring(startPos + 1, endPos - startPos - 1);
            return path;
        }
        public void Service(RtmptRequest request)
        {
            if (request.HttpMethod != "POST" || request.ContentLength == 0)
                HandleBadRequest(__Res.GetString(__Res.Rtmpt_CommandBadRequest), request);

            string path = request.Url;
            char p = path[1];
            switch (p)
            {
                case 'o': // OPEN_REQUEST
                    if (Log.IsDebugEnabled)
                        Log.Debug(__Res.GetString(__Res.Rtmpt_CommandOpen, path));
                    HandleOpen(request);
                    break;
                case 'c': // CLOSE_REQUEST
                    if (Log.IsDebugEnabled)
                        Log.Debug(__Res.GetString(__Res.Rtmpt_CommandClose, path));
                    HandleClose(request);
                    break;
                case 's': // SEND_REQUEST
                    if (Log.IsDebugEnabled)
                        Log.Debug(__Res.GetString(__Res.Rtmpt_CommandSend, path));
                    HandleSend(request);
                    break;
                case 'i': // IDLE_REQUEST
                    if (Log.IsDebugEnabled)
                        Log.Debug(__Res.GetString(__Res.Rtmpt_CommandIdle, path));
                    HandleIdle(request);
                    break;
                case 'f': // HTTPIdent request (ident and ident2)
                    HandleIdent(request);
                    break;
                default:
                    HandleBadRequest(__Res.GetString(__Res.Rtmpt_CommandNotSupported, path), request);
                    break;
            }
        }
Exemple #25
0
        private RtmptConnection GetConnection(RtmptRequest request)
        {
            string id = GetClientId(request);

            return(_connections[id] as RtmptConnection);
        }
 private void HandleRtmpt(RtmptRequest rtmptRequest)
 {
     IEndpoint endpoint = this.Endpoint.GetMessageBroker().GetEndpoint(RtmptEndpoint.FluorineRtmptEndpointId);
     RtmptEndpoint rtmptEndpoint = endpoint as RtmptEndpoint;
     if (rtmptEndpoint != null)
     {
         rtmptEndpoint.Service(rtmptRequest);
     }
 }
 private void HandleIdent(RtmptRequest request)
 {
     RtmptConnection connection = new RtmptConnection(this, request.Connection.RemoteEndPoint, null, null);
     FluorineRtmpContext.Initialize(connection);
     _connections[connection.ConnectionId] = connection;
     // Return connection id to client
     ReturnMessage(Ident, request);
 }
 private void ReturnMessage(RtmptConnection connection, ByteBuffer data, RtmptRequest request)
 {
     ByteBuffer buffer = ByteBuffer.Allocate((int)data.Length + 30);
     StreamWriter sw = new StreamWriter(buffer);
     int contentLength = data.Limit + 1;
     if (request.HttpVersion == 1)
     {
         sw.Write("HTTP/1.1 200 OK\r\n");
         sw.Write("Cache-Control: no-cache\r\n");
     }
     else
     {
         sw.Write("HTTP/1.0 200 OK\r\n");
         sw.Write("Pragma: no-cache\r\n");
     }
     sw.Write(string.Format("Content-Length: {0}\r\n", contentLength));
     sw.Write("Connection: Keep-Alive\r\n");
     sw.Write(string.Format("Content-Type: {0}\r\n", ContentType.RTMPT));
     sw.Write("\r\n");
     sw.Write((char)connection.PollingDelay);
     sw.Flush();
     BinaryWriter bw = new BinaryWriter(buffer);
     byte[] buf = data.ToArray();
     bw.Write(buf);
     bw.Flush();
     request.Connection.Write(buffer);
 }
 private void HandleSend(RtmptRequest request)
 {
     RtmptConnection connection = GetConnection(request);
     if (connection == null)
     {
         HandleBadRequest(__Res.GetString(__Res.Rtmpt_UnknownClient, request.Url), request);
         return;
     }
     FluorineRtmpContext.Initialize(connection); 
     //int length = request.ContentLength;
     ByteBuffer buffer = request.Data;
     IList messages = connection.Decode(buffer);
     if (messages == null || messages.Count == 0)
     {
         ReturnMessage(connection.PollingDelay, request);
         return;
     }
     // Execute the received RTMP messages
     foreach (object message in messages)
     {
         try
         {
             if (message is ByteBuffer)
             {
                 connection.Write(message as ByteBuffer);
             }
             else if (message is byte[])
             {
                 connection.Write(message as byte[]);
             }
             else
             {
                 _rtmpHandler.MessageReceived(connection, message);
             }
         }
         catch (Exception ex)
         {
             Log.Error(__Res.GetString(__Res.Rtmp_CouldNotProcessMessage), ex);
         }
     }
     // Send results to client
     ReturnPendingMessages(connection, request);
 }
 private void HandleClose(RtmptRequest request)
 {
     RtmptConnection connection = GetConnection(request);
     if (connection == null)
     {
         HandleBadRequest(__Res.GetString(__Res.Rtmpt_UnknownClient, request.Url), request);
         return;
     }
     FluorineRtmpContext.Initialize(connection);
     RemoveConnection(connection.ConnectionId);
     _rtmpHandler.ConnectionClosed(connection);
     ReturnMessage(0, request);
     connection.RealClose();
 }
Exemple #31
0
 public void Service(RtmptRequest rtmptRequest)
 {
     _rtmptServer.Service(rtmptRequest);
 }
 private void ReturnMessage(byte message, RtmptRequest request)
 {
     ByteBuffer buffer = ByteBuffer.Allocate(100);
     StreamWriter sw = new StreamWriter(buffer);
     if (request.HttpVersion == 1)
     {
         sw.Write("HTTP/1.1 200 OK\r\n");
         sw.Write("Cache-Control: no-cache\r\n");
     }
     else
     {
         sw.Write("HTTP/1.0 200 OK\r\n");
         sw.Write("Pragma: no-cache\r\n");
     }
     sw.Write("Content-Length: 1\r\n");
     sw.Write("Connection: Keep-Alive\r\n");
     sw.Write(string.Format("Content-Type: {0}\r\n", ContentType.RTMPT));
     sw.Write("\r\n");
     sw.Write((char)message);
     sw.Flush();
     request.Connection.Write(buffer);
 }
Exemple #33
0
        private RtmptConnection GetConnection(RtmptRequest request)
        {
            string clientId = this.GetClientId(request);

            return(this._connections[clientId] as RtmptConnection);
        }
 private void ReturnPendingMessages(RtmptConnection connection, RtmptRequest request)
 {
     ByteBuffer data = connection.GetPendingMessages(RtmptConnection.RESPONSE_TARGET_SIZE);
     if (data == null)
     {
         // no more messages to send...
         if (connection.IsClosing)
         {
             // Tell client to close connection
             ReturnMessage(0, request);
         }
         else
             ReturnMessage(connection.PollingDelay, request);
         return;
     }
     ReturnMessage(connection, data, request);
 }
 public static RtmptRequest DecodeBuffer(RtmpConnection connection, ByteBuffer stream)
 {
     RtmpContext context = connection.Context;
     int position = (int)stream.Position;
     try
     {
         BufferStreamReader sr = new BufferStreamReader(stream);
         string request = sr.ReadLine();
         string[] tokens = request.Split(new char[] { ' ' });
         string method = tokens[0];
         string url = tokens[1];
         // Decode all encoded parts of the URL using the built in URI processing class
         int i = 0;
         while ((i = url.IndexOf("%", i)) != -1)
         {
             url = url.Substring(0, i) + Uri.HexUnescape(url, ref i) + url.Substring(i);
         }
         // Lets just make sure we are using HTTP, thats about all I care about
         string protocol = tokens[2];// "HTTP/"
         //Read headers
         Hashtable headers = new Hashtable();
         string line;
         string name = null;
         while ((line = sr.ReadLine()) != null && line != string.Empty)
         {
             // If the value begins with a space or a hard tab then this
             // is an extension of the value of the previous header and
             // should be appended
             if (name != null && Char.IsWhiteSpace(line[0]))
             {
                 headers[name] += line;
                 continue;
             }
             // Headers consist of [NAME]: [VALUE] + possible extension lines
             int firstColon = line.IndexOf(":");
             if (firstColon != -1)
             {
                 name = line.Substring(0, firstColon);
                 string value = line.Substring(firstColon + 1).Trim();
                 headers[name] = value;
             }
             else
             {
                 //400, "Bad header: " + line
                 break;
             }
         }
         RtmptRequest rtmptRequest = new RtmptRequest(connection, url, protocol, method, headers);
         if (stream.Remaining == rtmptRequest.ContentLength)
         {
             stream.Compact();
             rtmptRequest.Data = ByteBuffer.Wrap(stream.ToArray());
             stream.Flip();
             return rtmptRequest;
         }
         else
         {
             // Move the position back to the start
             stream.Position = position;
         }
     }
     catch
     {
         // Move the position back to the start
         stream.Position = position;
         throw;
     }
     return null;
 }