repository cleanup

This commit is contained in:
wish
2022-07-29 03:25:23 +10:00
parent a0be6c627c
commit 2c0e7a5267
645 changed files with 996 additions and 903 deletions

View File

@@ -0,0 +1,20 @@
package launcherserver
import (
"net/http"
)
// ServerHandler is a handler function akin to http.Handler's ServeHTTP,
// but has an additional *Server argument.
type ServerHandler func(*Server, http.ResponseWriter, *http.Request)
// ServerHandlerFunc is a small type that implements http.Handler and
// wraps a calling ServerHandler with a *Server argument.
type ServerHandlerFunc struct {
server *Server
f ServerHandler
}
func (shf ServerHandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
shf.f(shf.server, w, r)
}

View File

@@ -0,0 +1,98 @@
package launcherserver
import (
"context"
"fmt"
"net/http"
"os"
"sync"
"time"
"erupe-ce/config"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/jmoiron/sqlx"
"go.uber.org/zap"
)
// Config struct allows configuring the server.
type Config struct {
Logger *zap.Logger
DB *sqlx.DB
ErupeConfig *config.Config
UseOriginalLauncherFiles bool
}
// Server is the MHF launcher HTTP server.
type Server struct {
sync.Mutex
logger *zap.Logger
erupeConfig *config.Config
db *sqlx.DB
httpServer *http.Server
useOriginalLauncherFiles bool
isShuttingDown bool
}
// NewServer creates a new Server type.
func NewServer(config *Config) *Server {
s := &Server{
logger: config.Logger,
erupeConfig: config.ErupeConfig,
db: config.DB,
useOriginalLauncherFiles: config.UseOriginalLauncherFiles,
httpServer: &http.Server{},
}
return s
}
// Start starts the server in a new goroutine.
func (s *Server) Start() error {
// Set up the routes responsible for serving the launcher HTML, serverlist, unique name check, and JP auth.
r := mux.NewRouter()
// Universal serverlist.xml route
s.setupServerlistRoutes(r)
// Change the launcher HTML routes if we are using the custom launcher instead of the original.
if s.useOriginalLauncherFiles {
s.setupOriginalLauncherRotues(r)
} else {
s.setupCustomLauncherRotues(r)
}
s.httpServer.Addr = fmt.Sprintf(":%d", s.erupeConfig.Launcher.Port)
s.httpServer.Handler = handlers.LoggingHandler(os.Stdout, r)
serveError := make(chan error, 1)
go func() {
if err := s.httpServer.ListenAndServe(); err != nil {
// Send error if any.
serveError <- err
}
}()
// Get the error from calling ListenAndServe, otherwise assume it's good after 250 milliseconds.
select {
case err := <-serveError:
return err
case <-time.After(250 * time.Millisecond):
return nil
}
}
// Shutdown exits the server gracefully.
func (s *Server) Shutdown() {
s.logger.Debug("Shutting down")
s.Lock()
s.isShuttingDown = true
s.Unlock()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := s.httpServer.Shutdown(ctx); err != nil {
// Just warn because we are shutting down the server anyway.
s.logger.Warn("Got error on httpServer shutdown", zap.Error(err))
}
}

View File

@@ -0,0 +1,79 @@
package launcherserver
import (
"fmt"
"html"
"net/http"
"github.com/gorilla/mux"
//"github.com/julienschmidt/httprouter"
)
func serverList(s *Server, w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w,
`<?xml version="1.0"?><server_groups><group idx='0' nam='Erupe' ip='%s' port="%d"/></server_groups>`,
s.erupeConfig.HostIP,
s.erupeConfig.Sign.Port,
)
}
func serverUniqueName(w http.ResponseWriter, r *http.Request) {
// TODO(Andoryuuta): Implement checking for unique character name.
fmt.Fprintf(w, `<?xml version="1.0" encoding="ISO-8859-1"?><uniq code="200">OK</uniq>`)
}
func jpLogin(w http.ResponseWriter, r *http.Request) {
// HACK(Andoryuuta): Return the given password back as the `skey` to defer the login logic to the sign server.
resultJSON := fmt.Sprintf(`{"result": "Ok", "skey": "%s", "code": "000", "msg": ""}`, r.FormValue("pw"))
fmt.Fprintf(w,
`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<body onload="doPost();">
<script type="text/javascript">
function doPost(){
parent.postMessage(document.getElementById("result").getAttribute("value"), "http://cog-members.mhf-z.jp");
}
</script>
<input id="result" value="%s"/>
</body>
</html>`, html.EscapeString(resultJSON))
}
func (s *Server) setupServerlistRoutes(r *mux.Router) {
// TW
twServerList := r.Host("mhf-n.capcom.com.tw").Subrouter()
twServerList.HandleFunc("/server/unique.php", serverUniqueName) // Name checking is also done on this host.
twServerList.Handle("/server/serverlist.xml", ServerHandlerFunc{s, serverList})
// JP
jpServerList := r.Host("srv-mhf.capcom-networks.jp").Subrouter()
jpServerList.Handle("/serverlist.xml", ServerHandlerFunc{s, serverList})
}
func (s *Server) setupOriginalLauncherRotues(r *mux.Router) {
// TW
twMain := r.Host("mhfg.capcom.com.tw").Subrouter()
twMain.PathPrefix("/").Handler(http.FileServer(http.Dir("./www/tw/")))
// JP
jpMain := r.Host("cog-members.mhf-z.jp").Subrouter()
jpMain.PathPrefix("/").Handler(http.FileServer(http.Dir("./www/jp/")))
// JP Launcher does additional auth over HTTP that the TW launcher doesn't.
jpAuth := r.Host("www.capcom-onlinegames.jp").Subrouter()
jpAuth.HandleFunc("/auth/launcher/login", jpLogin) //.Methods("POST")
jpAuth.PathPrefix("/auth/").Handler(http.StripPrefix("/auth/", http.FileServer(http.Dir("./www/jp/auth/"))))
}
func (s *Server) setupCustomLauncherRotues(r *mux.Router) {
// TW
twMain := r.Host("mhfg.capcom.com.tw").Subrouter()
twMain.PathPrefix("/g6_launcher/").Handler(http.StripPrefix("/g6_launcher/", http.FileServer(http.Dir("./www/erupe/"))))
// JP
jpMain := r.Host("cog-members.mhf-z.jp").Subrouter()
jpMain.PathPrefix("/launcher/").Handler(http.StripPrefix("/launcher/", http.FileServer(http.Dir("./www/erupe"))))
}