//private string _rootpath = "c:\\"; public RokuFileServer(int port,int hlsport,string rootpath) { this.server = new HttpServer(port); this._hlsport = hlsport; //this._rootpath = rootpath; this._roots = new List<string>(); foreach (string s in rootpath.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { this._roots.Add(s); } }
protected override void Run() { byte[] buffer = new byte[10240]; int count = 0; try { count = stream.Read(buffer, 0, buffer.Length); } catch (ObjectDisposedException) { stream.Close(); this.parent.RemoveConnection(this); this.parent = null; return; } int startpos = 0; int pos = 0; byte NL = (byte)'\n'; byte CR = (byte)'\r'; string url = ""; Dictionary<string, string> headers = new Dictionary<string, string>(); Dictionary<string, string> querys = new Dictionary<string, string>(); byte[] body = null; int i = startpos; for (; i < count; i++) { if (buffer[i] == NL) { string commandline = Encoding.ASCII.GetString(buffer, startpos, (i > 1 && buffer[i - 1] == CR ? i - 1 : i) - startpos); Log.WriteLine("requesting " + commandline); url = commandline.Substring(commandline.IndexOf(' ') + 1, commandline.LastIndexOf(' ') - commandline.IndexOf(' ') - 1); Log.WriteLine("url=" + url); pos = url.IndexOf('?'); if (pos > -1 && pos < url.Length - 1) { string[] querysstr = url.Substring(pos + 1).Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries); foreach (string q in querysstr) { string[] nv = q.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (nv.Length == 2) { if (!querys.ContainsKey(nv[0])) { querys.Add(nv[0], nv[1]); } } } url = url.Substring(0, pos); } break; } } ++i; startpos = i; for (; i < count; i++) { if (buffer[i] == NL) { string line = Encoding.ASCII.GetString(buffer, startpos, (i > 1 && buffer[i - 1] == CR ? i - 1 : i) - startpos); if (line == "") break; else { pos = line.IndexOf(':'); if (pos > 0) { string name = line.Substring(0, pos).Trim(); string value = (pos == line.Length - 1 ? "" : line.Substring(pos + 1)).Trim(); if (headers.ContainsKey(name)) headers[name] += ";" + value; else headers[name] = value; } startpos = i + 1; } } } ++i; startpos = i; int contentlength = 0; if (headers.ContainsKey("Content-Length")) { if (!int.TryParse(headers["Content-Length"], out contentlength)) contentlength = 0; } if (contentlength > 0) { body = new byte[contentlength]; int leftbytes = count - startpos; Buffer.BlockCopy(buffer, startpos, body, 0, Math.Min(leftbytes, contentlength)); if (contentlength > leftbytes) { count = 0; int tryreadcount = 0; while (count < contentlength - leftbytes && tryreadcount < 10) { try { count += stream.Read(body, leftbytes + count, body.Length - count - leftbytes); } catch (ObjectDisposedException) { stream.Close(); this.parent.RemoveConnection(this); this.parent = null; return; } ++tryreadcount; Thread.Sleep(200); } } } if (!string.IsNullOrEmpty(url)) { HttpServer.HttpConnectionEventArgs eventargs = new HttpServer.HttpConnectionEventArgs(url, headers,querys, body,this._local,this._remote); this.parent.OnHttpConnection(this, eventargs); //回复 StringBuilder sb = new StringBuilder(); sb.Append("HTTP/1.1 " + (int)eventargs.responseCode + " " + eventargs.responseDesc + "\r\n"); foreach (string name in eventargs.responseHeaders.Keys) { sb.Append(name + ": " + eventargs.responseHeaders[name] + "\r\n"); } if (eventargs.responseBody != null && eventargs.responseBody.Length > 0 && !eventargs.headers.ContainsKey("Content-Length")) { sb.Append("Content-Length: " + eventargs.responseBody.Length + "\r\n"); } sb.Append("\r\n"); byte[] responsedata = Encoding.ASCII.GetBytes(sb.ToString()); try { stream.Write(responsedata, 0, responsedata.Length); } catch (ObjectDisposedException) { stream.Close(); this.parent.RemoveConnection(this); this.parent = null; return; } if (eventargs.responseBody != null && eventargs.responseBody.Length > 0) { try { stream.Write(eventargs.responseBody, 0, eventargs.responseBody.Length); } catch (ObjectDisposedException) { stream.Close(); this.parent.RemoveConnection(this); this.parent = null; return; } } } stream.Close(); this.parent.RemoveConnection(this); this.parent = null; }
public override void Stop() { stream.Close(); this.parent = null; base.Stop(); }
public HttpConnection(HttpServer parent,TcpClient client) { this.stream = client.GetStream(); this.parent = parent; this._local = (IPEndPoint)client.Client.LocalEndPoint; this._remote = (IPEndPoint)client.Client.RemoteEndPoint; }
void server_HttpConnectionEvent(object sender, HttpServer.HttpConnectionEventArgs e) { string path = e.url.Replace('/', '\\').Trim('\\'); if (path.EndsWith(".m3u8")) { string file = path.Substring(0, path.Length - ".m3u8".Length); if (File.Exists(file)) { e.responseCode = System.Net.HttpStatusCode.OK; e.responseDesc = "OK"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Content-Type", "application/vnd.apple.mpegurl"); e.responseHeaders.Add("Connection", "Close"); string respbody = @"#EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000 http://" + Regex.Replace(e.headers["Host"], ":.*", "") + ":" + this._hlsport + "/" + path.Replace('\\', '/').Trim('/') + "?sid=" + (e.querys.ContainsKey("sid") ? e.querys["sid"] : Guid.NewGuid().ToString("N")); e.responseBody = Encoding.UTF8.GetBytes(respbody); return; } } XmlDocument doc = new XmlDocument(); doc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><root></root>"); if (path == "") { #if SUPPORTTV { XmlElement element = doc.CreateElement("tv"); XmlAttribute attribute; attribute = doc.CreateAttribute("name"); attribute.Value = "HD-PVR"; element.Attributes.Append(attribute); attribute = doc.CreateAttribute("bitrate"); attribute.Value = "2048"; element.Attributes.Append(attribute); attribute = doc.CreateAttribute("format"); attribute.Value = "hls"; element.Attributes.Append(attribute); string u = "http://" + Regex.Replace(e.headers["Host"], ":.*", "") + ":91"; element.InnerXml = RokuEncode(u); doc.DocumentElement.AppendChild(element); } #endif foreach (string s in this._roots) { XmlElement element = doc.CreateElement("folder"); XmlAttribute attribute; attribute = doc.CreateAttribute("name"); attribute.Value = s; element.Attributes.Append(attribute); string u = "http://" + e.headers["Host"] + "/" + s.Replace('\\', '/').Trim('/'); element.InnerXml = RokuEncode(u); doc.DocumentElement.AppendChild(element); } } else if (Directory.Exists(path)) { DirectoryInfo dir = new DirectoryInfo(path); DirectoryInfo[] subdirs = dir.GetDirectories(); foreach (DirectoryInfo subdir in subdirs) { if (subdir.Name[0] == '$' || subdir.Name.ToUpper() == "RECYCLER" || subdir.Name.ToUpper() == "System Volume Information") continue; XmlElement element = doc.CreateElement("folder"); XmlAttribute attribute; attribute = doc.CreateAttribute("name"); attribute.Value = subdir.Name; element.Attributes.Append(attribute); string u = "http://" + e.headers["Host"] + "/" + subdir.FullName.Replace('\\', '/').Trim('/'); element.InnerXml = RokuEncode(u); doc.DocumentElement.AppendChild(element); } FileInfo[] subfiles = dir.GetFiles("*.*", SearchOption.TopDirectoryOnly); foreach (FileInfo subfile in subfiles) { if (!(subfile.Name.EndsWith(".ts") || subfile.Name.EndsWith(".mp4") || subfile.Name.EndsWith(".mkv"))) continue; XmlElement element = doc.CreateElement("file"); XmlAttribute attribute; attribute = doc.CreateAttribute("name"); attribute.Value = subfile.Name; element.Attributes.Append(attribute); attribute = doc.CreateAttribute("bitrate"); attribute.Value = "2048"; element.Attributes.Append(attribute); attribute = doc.CreateAttribute("format"); attribute.Value = "hls"; element.Attributes.Append(attribute); string sid = Guid.NewGuid().ToString("N"); string u = "http://" + e.headers["Host"] + "/" + subfile.FullName.Replace('\\', '/').Trim('/') + ".m3u8?sid=" + sid; element.InnerXml = RokuEncode(u); string stopurl = "http://" + Regex.Replace(e.headers["Host"], ":.*", "") + ":" + this._hlsport + "/action?sid=" + sid + "&action=stop"; attribute = doc.CreateAttribute("stopurl"); attribute.Value = stopurl; element.Attributes.Append(attribute); string pauseurl = "http://" + Regex.Replace(e.headers["Host"], ":.*", "") + ":" + this._hlsport + "/action?sid=" + sid + "&action=pause"; attribute = doc.CreateAttribute("pauseurl"); attribute.Value = pauseurl; element.Attributes.Append(attribute); string resumeurl = "http://" + Regex.Replace(e.headers["Host"], ":.*", "") + ":" + this._hlsport + "/action?sid=" + sid + "&action=resume"; attribute = doc.CreateAttribute("resumeurl"); attribute.Value = resumeurl; element.Attributes.Append(attribute); doc.DocumentElement.AppendChild(element); } } else { onerror: e.responseCode = System.Net.HttpStatusCode.NotFound; e.responseDesc = "Not Found"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Connection", "Close"); e.responseBody = new byte[] { }; return; } e.responseCode = System.Net.HttpStatusCode.OK; e.responseDesc = "OK"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Content-Type", "text/xml"); e.responseHeaders.Add("Connection", "Close"); MemoryStream ms = new MemoryStream(); doc.Save(ms); e.responseBody = ms.ToArray(); ms.Close(); return; }
protected override void server_HttpConnectionEvent(object sender, HttpServer.HttpConnectionEventArgs e) { FFMpeg ffmpeg = this._transcodingInstance[0]; ffmpeg.Start(); ffmpeg._lastActiveTime = DateTime.Now; if (e.url.EndsWith(".m3u8"))//请求url { string filewithchannel = e.url.Substring(e.url.LastIndexOf('/') + 1); int channel = 0; Log.WriteLine("Channel is:" + filewithchannel); if (int.TryParse(filewithchannel.Substring(0, filewithchannel.Length - ".m3u8".Length), out channel) && channel != 0 && channel != this.currentChannel) { this.currentChannel = channel; Log.WriteLine("频道更换为:" + channel); //换频道 HDPVR.Instance.ChangeChannel(channel.ToString()); } string body = @"#EXTM3U #EXT-X-TARGETDURATION:" + tsfiletimelength + @" #EXT-X-MEDIA-SEQUENCE:" + ffmpeg.fileSequence + "\r\n"; while (ffmpeg.cachedVideo.Count < 2) { Thread.Sleep(1000); } lock (ffmpeg.cachedVideo) { for (int i = 0; i < ffmpeg.cachedVideo.Count - 1; i++) { body += "#EXTINF:" + tsfiletimelength + ", no desc\r\n" + (ffmpeg.fileSequence + i).ToString() + ".ts\r\n"; } } if (body.Length > 0) body = body.Substring(0, body.Length - 2); e.responseCode = System.Net.HttpStatusCode.OK; e.responseDesc = "OK"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Content-Type", "application/vnd.apple.mpegurl"); e.responseHeaders.Add("Connection", "Close"); e.responseBody = Encoding.UTF8.GetBytes(body); return; } else if (e.url.EndsWith(".ts")) { int sequence = 0; string filename = e.url.Substring(0, e.url.Length - ".ts".Length).Trim('/'); e.responseCode = System.Net.HttpStatusCode.OK; e.responseDesc = "OK"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Content-Type", "mpeg/ts"); e.responseHeaders.Add("Connection", "Close"); if (int.TryParse(filename, out sequence)) { sequence = sequence - ffmpeg.fileSequence; if (sequence >= 0 && sequence < ffmpeg.cachedVideo.Count - 1) { lock (ffmpeg.cachedVideo) { e.responseBody = ffmpeg.cachedVideo[sequence].ToArray(); } return; } else goto onerror; } else goto onerror; } else goto onerror; onerror: e.responseCode = System.Net.HttpStatusCode.NotFound; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Connection", "Close"); e.responseDesc = "Not Exist Any More"; e.responseBody = new byte[] { }; }
protected override void server_HttpConnectionEvent(object sender, HttpServer.HttpConnectionEventArgs e) { if (e.querys.ContainsKey("sid")) { FFMpeg ffmpeg = this._transcodingInstance.Find(delegate(FFMpeg f) { return f.Sid == e.querys["sid"]; }); if (e.url.EndsWith(".m3u8") && ffmpeg == null) { string path = e.url.Replace('/', '\\').Trim('\\'); if (path.EndsWith(".m3u8")) { path = path.Substring(0, path.Length - ".m3u8".Length); if (File.Exists(path)) { ffmpeg = new FFMpeg(new FileInput(path), e.querys["sid"]); ffmpeg.Start(); lock (this._transcodingInstance) { this._transcodingInstance.Add(ffmpeg); } } else goto onerror; } else goto onerror; } if (ffmpeg == null) goto onerror; else ffmpeg._lastActiveTime = DateTime.Now; if (e.url.Trim('/') == "action" && e.querys.ContainsKey("action")) { if (e.querys["action"] == "pause") { ffmpeg.Pause(); } else if (e.querys["action"] == "stop") { ffmpeg.Stop(); lock (this._transcodingInstance) { this._transcodingInstance.Remove(ffmpeg); } } else if (e.querys["action"] == "resume") { ffmpeg.Restart(); } e.responseCode = System.Net.HttpStatusCode.OK; e.responseDesc = "OK"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Content-Type", "application/vnd.apple.mpegurl"); e.responseHeaders.Add("Connection", "Close"); e.responseBody = new byte[] { }; return; } if (e.url.EndsWith(".m3u8")) { string body = @"#EXTM3U #EXT-X-TARGETDURATION:" + tsfiletimelength + @" #EXT-X-MEDIA-SEQUENCE:" + ffmpeg.fileSequence + "\r\n"; ffmpeg.Start(); while (ffmpeg.cachedVideo.Count <= 1) { Thread.Sleep(1000); } lock (ffmpeg.cachedVideo) { for (int i = 0; i < ffmpeg.cachedVideo.Count - 1; i++) { body += "#EXTINF:" + tsfiletimelength + ", no desc\r\nhttp://" + e.headers["Host"] + "/" + (ffmpeg.fileSequence + i).ToString() + ".ts?sid=" + e.querys["sid"] + "\r\n"; } } if (ffmpeg.transcodefinished) body += "#EXT-X-ENDLIST\r\n"; if (body.Length > 0) body = body.Substring(0, body.Length - 2); e.responseCode = System.Net.HttpStatusCode.OK; e.responseDesc = "OK"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Content-Type", "application/vnd.apple.mpegurl"); e.responseHeaders.Add("Connection", "Close"); e.responseBody = Encoding.UTF8.GetBytes(body); Log.WriteLine("请求当前频道数据文件:" + body); return; } else if (e.url.EndsWith(".ts")) { int sequence = 0; if (int.TryParse(e.url.Substring(0, e.url.Length - ".ts".Length).Trim('/'), out sequence)) { sequence = sequence - ffmpeg.fileSequence; if (sequence >= 0 && sequence < ffmpeg.cachedVideo.Count - 1) { e.responseCode = System.Net.HttpStatusCode.OK; e.responseDesc = "OK"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Content-Type", "mpeg/ts"); e.responseHeaders.Add("Connection", "Close"); lock (ffmpeg.cachedVideo) { e.responseBody = ffmpeg.cachedVideo[sequence].ToArray(); } return; } else goto onerror; } else goto onerror; } else goto onerror; } onerror: e.responseCode = System.Net.HttpStatusCode.NotFound; e.responseDesc = "Not Exist Any More"; e.responseHeaders = new Dictionary<string, string>(); e.responseHeaders.Add("Server", "Cute Server"); e.responseHeaders.Add("Connection", "Close"); e.responseBody = new byte[] { }; base.server_HttpConnectionEvent(sender, e); }
protected virtual void server_HttpConnectionEvent(object sender, HttpServer.HttpConnectionEventArgs e) { }
public HttpLiveStreaming(int port) { this.server = new HttpServer(port); this.server.HttpConnectionEvent += new EventHandler<HttpServer.HttpConnectionEventArgs>(server_HttpConnectionEvent); this._transcodingInstance = new List<FFMpeg>(); }