コード例 #1
0
ファイル: Processors.cs プロジェクト: derole1/ModNationServer
        public static void MainServerProcessor(HttpListenerContext context)
        {
            try
            {
                //Sets up various things for http request and response
                HttpListenerRequest  request  = context.Request;
                HttpListenerResponse response = context.Response;
                System.IO.Stream     input    = request.InputStream;
                System.IO.Stream     output   = response.OutputStream;
                try
                {
                    //Reads the http data
                    byte[] recvBuffer = new byte[request.ContentLength64];
                    if (request.ContentLength64 > 0)
                    {
                        int          recvBytes = 0;
                        MemoryStream ms        = new MemoryStream();
                        do
                        {
                            byte[] tempBuf = new byte[20000];
                            int    bytes   = input.Read(tempBuf, 0, tempBuf.Length);
                            ms.Write(tempBuf, 0, bytes);
                            recvBytes += bytes;
                        } while (recvBytes < request.ContentLength64);
                        recvBuffer = ms.ToArray();
                    }
                    byte[] buffer = recvBuffer;
                    //Creates receiving and response xml documents
                    XmlDocument recDoc = new XmlDocument();
                    XmlDocument resDoc = new XmlDocument();
                    //Sets up response with proper values
                    XmlElement result = AppendCommon(resDoc);
                    resDoc.AppendChild(result);
                    //if (request.HttpMethod == "POST")
                    //{
                    //    recDoc.LoadXml(Encoding.UTF8.GetString(recvBuffer));
                    //}
                    Console.WriteLine("Request URL: {0}", request.RawUrl.Split('?')[0]);
                    Dictionary <string, string> urlEncodedData = new Dictionary <string, string>();
                    //Decode url encoding if urlencoded data is sent
                    if (request.ContentType == "application/x-www-form-urlencoded")
                    {
                        DecodeURLEncoding(Encoding.UTF8.GetString(recvBuffer), urlEncodedData);
                    }
                    //Open a database connection (TODO: Put into DatabaseManager?)
                    SQLiteConnection sqlite_conn = new SQLiteConnection("Data Source=database.sqlite;Version=3;");
                    sqlite_conn.Open();
                    SQLiteCommand sqlite_cmd = sqlite_conn.CreateCommand();
                    bool          respond    = false;
                    bool          isXml      = true;
                    string[]      url        = request.RawUrl.Substring(1, request.RawUrl.Length - 1).Split('/');
                    //Test page
                    if (!request.UserAgent.Contains("PlayerConnect"))
                    {
                        response.ContentType = "text/html";
                        buffer = Encoding.ASCII.GetBytes("<h1>Your PS3 is connecting to ModNation!</h1>");
                        response.ContentLength64 = buffer.Length;
                        output.Write(buffer, 0, buffer.Length);
                        output.Close();
                        return;
                    }
                    //Decide if the server wants resources, player creations or wants to access database stuff
                    switch (url[0])
                    {
                    case "resources":
                        respond = true;
                        isXml   = false;
                        if (File.Exists(string.Join("\\", url)))
                        {
                            response.ContentType = "application/xml; charset=utf-8";
                            buffer = xmlSchemas[string.Join("\\", url)];
                        }
                        break;

                    case "player_avatars":
                        respond = true;
                        isXml   = false;
                        response.ContentType = "image/png";
                        if (File.Exists(string.Join("\\", url)))
                        {
                            buffer = File.ReadAllBytes(string.Join("\\", url));
                        }
                        break;

                    case "player_creations":
                        respond = true;
                        isXml   = false;
                        if (File.Exists(string.Join("\\", url)))
                        {
                            //Decide what the content is and set the mime type accordingly
                            if (Path.GetExtension(string.Join("\\", url)) == ".png")
                            {
                                response.ContentType = "image/png";
                            }
                            else
                            {
                                response.ContentType = "application/octet-stream";
                            }
                            buffer = File.ReadAllBytes(string.Join("\\", url));
                        }
                        break;

                    default:
                        //This probably isnt needed, but was just put in for debugging purposes
                        //response.AddHeader("X-Rack-Cache", "pass");
                        //response.AddHeader("X-Runtime", "7");
                        //response.AddHeader("Last-Modified", "Thu, 31 Dec 2037 23:55:55 GMT");
                        //response.AddHeader("Expires", "Thu, 31 Dec 2037 23:55:55 GMT");
                        //response.AddHeader("Cache-Control", "private, max-age=0, must-revalidate");
                        //response.SetCookie(new Cookie("playerconnect_session_id", request.Cookies["playerconnect_session_id"].Value));
                        break;
                    }
                    if (isXml)
                    {
                        //response.ContentType = "text/xml; charset=utf-8";
                        //Game requires the "charset=utf-8" part to properly decode some xml responses
                        response.ContentType = "application/xml; charset=utf-8";
                        int paramStart = request.RawUrl.IndexOf('?') + 1;
                        //BIG switch statement that decides what handler the data goes to
                        switch (url[0].Split('?')[0])
                        {
                        case "preferences.xml":
                            respond = Handlers.PreferencesUpdateHandler(request, response, urlEncodedData, resDoc);
                            break;

                        case "policy.view.xml":
                            string sessionID = SessionManager.RandomSessionID(0x20);
                            response.SetCookie(new Cookie("playerconnect_session_id", SessionManager.EncodeInitialSessionID(sessionID)));
                            DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                            respond = Handlers.PolicyViewHandler(request, response, urlEncodedData, resDoc);
                            break;

                        case "policy.accept.xml":
                            respond = Handlers.PolicyAcceptHandler(request, response, urlEncodedData, resDoc);
                            break;

                        case "session.login_np.xml":
                            respond = Handlers.SessionLoginHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                            break;

                        case "session.ping.xml":
                            respond = Handlers.SessionPingHandler(request, response, urlEncodedData, resDoc);
                            break;

                        case "profanity_filter.list.xml":
                            respond = Handlers.ProfanityFilterListHandler(request, response, urlEncodedData, resDoc);
                            break;

                        default:
                            //Check if session exists for requests that require auth
                            if (SessionManager.PingSession(request.Cookies["playerconnect_session_id"].Value))
                            {
                                Console.WriteLine("SESSION ID: {0}", SessionManager.GetSessionID(request.Cookies["playerconnect_session_id"].Value));
                                response.SetCookie(new Cookie("playerconnect_session_id", request.Cookies["playerconnect_session_id"].Value));
                                response.SetCookie(new Cookie("path", "/"));
                                switch (url[0].Split('?')[0])
                                {
                                case "session.set_presence.xml":
                                    respond = Handlers.SessionSetPresenceHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "content_url.list.xml":
                                    respond = Handlers.ContentUrlListHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "skill_level.list.xml":
                                    respond = Handlers.SkillLevelListHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "player_creation.mine.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerCreationMineHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation.show.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerCreationShowHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation.download.xml":
                                    respond = Handlers.PlayerCreationDownloadHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation.list.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerCreationListHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation.search.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerCreationSearchHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation.verify.xml":
                                    respond = Handlers.PlayerCreationVerifyHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "player_creation.create.xml":
                                    respond = Handlers.PlayerCreationCreateHandler(request, response, MultipartFormDataParser.Parse(new MemoryStream(recvBuffer)), resDoc, sqlite_cmd);
                                    break;

                                case "player_creation.destroy.xml":
                                    respond = Handlers.PlayerCreationDestroyHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation.friends_view.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerCreationFriendsViewHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation_complaint.create.xml":
                                    respond = Handlers.PlayerCreationComplaintCreateHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation_rating.view.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerCreationRatingViewHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation_rating.create.xml":
                                    respond = Handlers.PlayerCreationRatingCreateHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_creation_rating.list.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerCreationRatingListHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player.to_id.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerToIdHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "mail_message.create.xml":
                                    respond = Handlers.MailMessageCreateHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "tag.list.xml":
                                    respond = Handlers.TagListHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "player_metric.show.xml":
                                    respond = Handlers.PlayerMetricShowHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "player_metric.update.xml":
                                    respond = Handlers.PlayerMetricUpdateHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "mail_message.list.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.MailMessageListHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "achievement.list.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.AchievementListHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "content_update.latest.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.ContentUpdateLatestHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "leaderboard.view.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.LeaderboardViewHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "leaderboard.player_stats.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.LeaderboardPlayerStatsHandler(request, response, urlEncodedData, resDoc);
                                    break;

                                case "announcement.list.xml":
                                    respond = Handlers.AnnouncementListHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player.info.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.PlayerInfoHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_rating.create.xml":
                                    respond = Handlers.PlayerRatingCreateHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_complaint.create.xml":
                                    respond = Handlers.PlayerComplaintCreateHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "favorite_player.create.xml":
                                    respond = Handlers.FavoritePlayerCreateHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "favorite_player.list.xml":
                                    DecodeURLEncoding(request.RawUrl.Substring(paramStart, request.RawUrl.Length - paramStart), urlEncodedData);
                                    respond = Handlers.FavoritePlayerListHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "favorite_player.remove.xml":
                                    respond = Handlers.FavoritePlayerRemoveHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "single_player_game.create_finish_and_post_stats.xml":
                                    //respond = Handlers.SinglePlayerGameCreateFinishAndPostStatsHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_profile.update.xml":
                                    respond = Handlers.PlayerProfileUpdateHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                case "player_avatar.update.xml":
                                    respond = Handlers.PlayerAvatarUpdateHandler(request, response, MultipartFormDataParser.Parse(new MemoryStream(recvBuffer)), resDoc, sqlite_cmd);
                                    break;

                                case "server.select.xml":
                                    respond = Handlers.ServerSelectHandler(request, response, urlEncodedData, resDoc, sqlite_cmd);
                                    break;

                                default:
                                    respond = Handlers.DefaultHandler(request, response, urlEncodedData, resDoc);
                                    Console.WriteLine("Unimplemented request!");
                                    break;
                                }
                            }
                            else
                            {
                                //respond = true;
                                //resDoc.ChildNodes[0].ChildNodes[0].ChildNodes[0].InnerText = "-105";
                                //resDoc.ChildNodes[0].ChildNodes[0].ChildNodes[1].InnerText = "NP Auth Failed: ticket is expired";
                                sqlite_conn.Close();
                                output.Close();
                                response.Close();
                            }
                            break;
                        }
                    }
                    sqlite_conn.Close();
                    //Determine if we need to respond and if the data is xml
                    if (respond)
                    {
                        if (isXml)
                        {
                            //Console.WriteLine("Response XML: {0}", resDoc.InnerXml);
                            buffer = Encoding.UTF8.GetBytes(resDoc.InnerXml);
                        }
                        //Calculate an S3 ETag (Required for image previews), its just an MD5 hash
                        response.AddHeader("ETag", "\"" + BitConverter.ToString(MD5.Create().ComputeHash(buffer)).Replace("-", "").ToLower() + "\"");
                        response.KeepAlive       = false;
                        response.ContentLength64 = buffer.Length;
                        output.Write(buffer, 0, buffer.Length);
                    }
                }
                catch (Exception e) { try { File.AppendAllText("error.log", e.ToString() + "\n\n"); } catch { } }
                output.Close();
            } catch { }
        }