using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; using System.Text; using System.Threading; namespace ContentServer { class ContentItem { public String name; public String filePath; public ContentItem(string Name,string FilePath) { if(File.Exists(FilePath)) { filePath = FilePath; name = Name; } else { throw new FileNotFoundException(); } } } class ContentClient { public ContentClient(ContentServer Server, Socket ClientSocket) { clientSock = ClientSocket; baseServ = Server; Server.Clients.Add(this); baseServ.WriteDebugOutput("PSVita Connected @ " + clientSock.RemoteEndPoint.ToString()); ProcessRequests(); clientSock.Close(); } private ContentServer baseServ; private Socket clientSock; private byte[] ReadData() { while (clientSock.Available < 1) { } byte[] by = new byte[clientSock.Available]; clientSock.Receive(by); return by; } private void SendString(string str) { byte[] response = Encoding.UTF8.GetBytes(str); clientSock.Send(response); } private string GenerateHeaders(string path, long content_length = 0) { string headers = ""; if (path == "/") { headers += "HTTP/1.1 200 OK\r\n"; headers += "Content-Type: text/html\r\n"; headers += "Accept-Ranges: bytes\r\n"; headers += "Server: ContentServer\r\n"; headers += "Content-Length: " + content_length + "\r\n"; headers += "Cache-Control: max-age=3600\r\n"; headers += "Connection: keep-alive\r\n"; headers += "\r\n"; } else if (File.Exists(path)) { FileInfo info = new FileInfo(path); long length = info.Length; if (content_length != 0) length = content_length; headers += "HTTP/1.1 200 OK\r\n"; headers += "Content-Type: application/octet-stream\r\n"; headers += "Accept-Ranges: bytes\r\n"; headers += "Server: ContentServer\r\n"; headers += "Content-Length: " + length + "\r\n"; headers += "Cache-Control: max-age=3600\r\n"; headers += "Connection: keep-alive\r\n"; headers += "\r\n"; } else { headers += "HTTP/1.1 404 Not Found\r\n"; headers += "Content-Type: text/plain\r\n"; headers += "Accept-Ranges: bytes\r\n"; headers += "Server: ContentServer\r\n"; headers += "Content-Length: " + content_length + "\r\n"; headers += "Cache-Control: max-age=3600\r\n"; headers += "Connection: keep-alive\r\n"; headers += "\r\n"; } return headers; } private void RespondGet(string path, Dictionary query) { baseServ.WriteDebugOutput("GET " + path); string name = Path.GetFileName(path); if (ContentItemExists(name)) { ContentItem ci = GetContentItem(name); FileStream fs = File.OpenRead(ci.filePath); try { string requestStr = GenerateHeaders(ci.filePath, fs.Length - fs.Position); SendString(requestStr); while(fs.Position < fs.Length) { int BUFFER_SIZE = 0x8500000; if(fs.Position + BUFFER_SIZE <= fs.Length) { byte[] buffer = new byte[BUFFER_SIZE]; fs.Read(buffer, 0x00, BUFFER_SIZE); clientSock.Send(buffer); } else { byte[] buffer = new byte[fs.Length - fs.Position]; fs.Read(buffer, 0x00, buffer.Length); clientSock.Send(buffer); } } } catch (Exception) { fs.Close(); }; } else { string body = GeneratePage(path); string requestStr = GenerateHeaders(path, body.Length); requestStr += body; SendString(requestStr); } } private void RespondHead(string path) { string name = Path.GetFileName(path); baseServ.WriteDebugOutput("HEAD " + path); if (ContentItemExists(name)) { ContentItem ci = GetContentItem(name); string requestStr = GenerateHeaders(ci.filePath); SendString(requestStr); } else { string body = GeneratePage(path); string requestStr = GenerateHeaders(path, body.Length); SendString(requestStr); } } private bool ContentItemExists(string name) { bool exists = false; foreach (ContentItem ci in baseServ.Contents) { if (ci.name == name) { exists = true; } } return exists; } private ContentItem GetContentItem(string name) { foreach (ContentItem ci in baseServ.Contents) { if (ci.name == name) { return ci; } } throw new FileNotFoundException(); } private string GeneratePage(string path) { if (path == "/") { string body = "Content Downloader Server.
Open this url in PSVita's \"Content Downloader\" To view avalible files."; foreach (ContentItem content in baseServ.Contents) { body += ""; } return body; } else { string body = "File not found."; return body; } } private string ExtractPath(string relativeUri) { int questionIndex = relativeUri.IndexOf("?"); if (questionIndex != -1) return relativeUri.Substring(0, questionIndex); else return relativeUri; } private Dictionary ExtractQuery(string relativeUri) { int questionIndex = relativeUri.IndexOf("?"); if (questionIndex != -1) { string[] queryStrList = relativeUri.Substring(questionIndex + 1).Split('&'); Dictionary queryDict = new Dictionary(); foreach(string queryStr in queryStrList) { string[] qStr = queryStr.Split('='); queryDict.Add(qStr[0], qStr[1]); } return queryDict; } else return new Dictionary(); } private string ExtractRelativeUrl(string header) { int slashIndex = header.IndexOf("/"); int httpLen = header.IndexOf(" HTTP/1.1") - slashIndex; string path = header.Substring(slashIndex, httpLen); return path; } private void ProcessRequests() { byte[] data = ReadData(); // Parse Request string curReq = Encoding.UTF8.GetString(data); curReq = curReq.Replace("\r\n", "\n"); string[] reqLines = curReq.Split('\n'); foreach (string line in reqLines) { if (line.StartsWith("GET")) { string relUrl = ExtractRelativeUrl(line); string path = ExtractPath(relUrl); Dictionary query = ExtractQuery(relUrl); RespondGet(path, query); return; } else if (line.StartsWith("HEAD")) { string relUrl = ExtractRelativeUrl(line); string path = ExtractPath(relUrl); RespondHead(path); return; } } } } class ContentServer { public List Contents = new List(); public List Clients = new List(); public void WriteDebugOutput(string txt) { Program.MainForm.Invoke((Action)delegate { Program.MainForm.AppendToConsole(txt + "\r\n"); }); } public ContentServer() { new Thread(() => { WriteDebugOutput("Listening for connections on port 1337."); IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 1337); Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); newsock.Bind(localEndPoint); newsock.Listen(20); while(true) { Socket clientSock = newsock.Accept(); new Thread(() => { ContentClient client = new ContentClient(this, clientSock); Clients.Remove(client); }).Start(); } }).Start(); } } }