예제 #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);
        }
예제 #2
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;
			}
		}
예제 #3
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);
        }
예제 #4
0
		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;
		}
예제 #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;
            }
        }
예제 #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();
        }
예제 #7
0
		public static ByteBuffer 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();
			return buffer;
		}
예제 #8
0
		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;
		}
예제 #9
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);
        }
예제 #10
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);
        }
예제 #11
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);
        }
예제 #12
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);
        }
예제 #13
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);
        }
예제 #14
0
		public static ByteBuffer ReturnMessage(byte pollingDelay, 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)pollingDelay);
			sw.Flush();
			BinaryWriter bw = new BinaryWriter(buffer);
			byte[] buf = data.ToArray();
			bw.Write(buf);
			bw.Flush();
			return buffer;
		}
예제 #15
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);
        }
예제 #16
0
		private RtmptConnection GetConnection(RtmptRequest request) {
			string id = GetClientId(request);
			return _connections[id] as RtmptConnection;
		}
예제 #17
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);
		}
예제 #18
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();
		}
예제 #19
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);
		}
예제 #20
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);
		}
예제 #21
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;
		}
예제 #22
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);
		}
예제 #23
0
        private RtmptConnection GetConnection(RtmptRequest request)
        {
            string id = GetClientId(request);

            return(_connections[id] as RtmptConnection);
        }
예제 #24
0
		public void Service(RtmptRequest rtmptRequest) {
			_rtmptServer.Service(rtmptRequest);
		}
예제 #25
0
		private void HandleRtmpt(RtmptRequest rtmptRequest) {
			IEndpoint endpoint = this.Endpoint.GetMessageBroker().GetEndpoint(RtmptEndpoint.FluorineRtmptEndpointId);
			RtmptEndpoint rtmptEndpoint = endpoint as RtmptEndpoint;
			if (rtmptEndpoint != null) {
				rtmptEndpoint.Service(rtmptRequest);
			}
		}