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); }
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; } }
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); }
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; }
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; } }
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(); }
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; }
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; }
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 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 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); }
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 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 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; }
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); }
private RtmptConnection GetConnection(RtmptRequest request) { string id = GetClientId(request); return _connections[id] 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); }
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; }
private RtmptConnection GetConnection(RtmptRequest request) { string id = GetClientId(request); return(_connections[id] as RtmptConnection); }
public void Service(RtmptRequest rtmptRequest) { _rtmptServer.Service(rtmptRequest); }
private void HandleRtmpt(RtmptRequest rtmptRequest) { IEndpoint endpoint = this.Endpoint.GetMessageBroker().GetEndpoint(RtmptEndpoint.FluorineRtmptEndpointId); RtmptEndpoint rtmptEndpoint = endpoint as RtmptEndpoint; if (rtmptEndpoint != null) { rtmptEndpoint.Service(rtmptRequest); } }