Skip to content

Commit

Permalink
DLS1 server added
Browse files Browse the repository at this point in the history
Split NAS's DLS1 code
  • Loading branch information
sepalani committed Feb 20, 2018
1 parent 5b94a02 commit d3eed4c
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 77 deletions.
10 changes: 10 additions & 0 deletions altwfc.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ LoggerOutputFile = ON
[NasServer]
IP = 127.0.0.1
Port = 9000
SvcHost = dls1.nintendowifi.net
LoggerName = NasServer
LoggerFilename = nas_server.log
LoggerLevel = -1
Expand All @@ -40,6 +41,15 @@ LoggerLevel = -1
LoggerOutputConsole = ON
LoggerOutputFile = ON

[Dls1Server]
IP = 127.0.0.1
Port = 9003
LoggerName = Dls1Server
LoggerFilename = dls1_server.log
LoggerLevel = -1
LoggerOutputConsole = ON
LoggerOutputFile = ON

[AdminPage]
IP = 127.0.0.1
Port = 9009
Expand Down
10 changes: 10 additions & 0 deletions altwfc_nas.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ LoggerOutputFile = ON
[NasServer]
IP = 127.0.0.1
Port = 80
SvcHost = dls1.nintendowifi.net
LoggerName = NasServer
LoggerFilename = nas_server.log
LoggerLevel = -1
Expand All @@ -36,6 +37,15 @@ LoggerLevel = -1
LoggerOutputConsole = ON
LoggerOutputFile = ON

[Dls1Server]
IP = 127.0.0.1
Port = 9003
LoggerName = Dls1Server
LoggerFilename = dls1_server.log
LoggerLevel = -1
LoggerOutputConsole = ON
LoggerOutputFile = ON

[AdminPage]
IP = 127.0.0.1
Port = 9009
Expand Down
161 changes: 161 additions & 0 deletions dls1_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
"""DWC Network Server Emulator
Copyright (C) 2014 polaris-
Copyright (C) 2014 ToadKing
Copyright (C) 2014 AdmiralCurtiss
Copyright (C) 2014 msoucy
Copyright (C) 2015 Sepalani
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import logging
import BaseHTTPServer
import SocketServer
import os
import traceback

from other import dlc, utils
import dwc_config

logger = dwc_config.get_logger('Dls1Server')


def handle_post(handler, addr, post):
"""Handle unknown path."""
logger.log(logging.WARNING, "Unknown path request %s from %s:%d!",
handler.path, *addr)
handler.send_response(404)
return None


def handle_download_action(handler, dlc_path, post):
"""Handle unknown download action request."""
logger.log(logging.WARNING, "Unknown download action: %s", handler.path)
handler.send_response(200)
return None


def handle_download_count(handler, dlc_path, post):
"""Handle download count request."""
ret = dlc.download_count(dlc_path, post)
handler.send_response(200)
handler.send_header("Content-type", "text/plain")
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret


def handle_download_list(handler, dlc_path, post):
"""Handle download list request."""
ret = dlc.download_list(dlc_path, post)
handler.send_response(200)
handler.send_header("Content-type", "text/plain")
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret


def handle_download_contents(handler, dlc_path, post):
"""Handle download contents request."""
ret = dlc.download_contents(dlc_path, post)

if ret is None:
handler.send_response(404)
else:
handler.send_response(200)
handler.send_header("Content-type", "application/x-dsdl")
handler.send_header("Content-Disposition",
'attachment; filename="%s"' % post["contents"])
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret


def handle_download(handler, addr, post):
"""Handle download POST request."""
logger.log(logging.DEBUG, "Download request to %s from %s:%d",
handler.path, *addr)
logger.log(logging.DEBUG, "%s", post)

action = str(post["action"]).lower()
dlc_dir = os.path.abspath("dlc")
dlc_path = os.path.abspath(os.path.join("dlc", post["gamecd"]))

if os.path.commonprefix([dlc_dir, dlc_path]) != dlc_dir:
logging.log(logging.WARNING,
'Attempted directory traversal attack "%s",'
' cancelling.', dlc_path)
handler.send_response(403)
return

command = handler.download_actions.get(action, handle_download_action)
ret = command(handler, dlc_path, post)

logger.log(logging.DEBUG, "Download response to %s:%d", *addr)
return ret


class Dls1HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Nintendo Dls1 server handler."""

post_paths = {
"/download": handle_download
}

download_actions = {
"count": handle_download_count,
"list": handle_download_list,
"contents": handle_download_contents,
}

def version_string(self):
return "Nintendo Wii (http)"

def do_POST(self):
try:
length = int(self.headers['content-length'])
post = utils.qs_to_dict(self.rfile.read(length))
client_address = (
self.headers.get('x-forwarded-for', self.client_address[0]),
self.client_address[1]
)
post['ipaddr'] = client_address[0]

command = self.post_paths.get(self.path, handle_post)
ret = command(self, client_address, post)

if ret is not None:
self.send_header("Content-Length", str(len(ret)))
self.end_headers()
self.wfile.write(ret)
except:
logger.log(logging.ERROR, "Exception occurred on POST request!")
logger.log(logging.ERROR, "%s", traceback.format_exc())


class Dls1HTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
"""Threading HTTP server."""
pass


class Dls1Server(object):
def start(self):
address = dwc_config.get_ip_port('Dls1Server')
httpd = Dls1HTTPServer(address, Dls1HTTPServerHandler)
logger.log(logging.INFO, "Now listening for connections on %s:%d...",
*address)
httpd.serve_forever()


if __name__ == "__main__":
dls1 = Dls1Server()
dls1.start()
7 changes: 7 additions & 0 deletions dwc_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,10 @@ def get_logger(section, filename='altwfc.cfg'):
config.getboolean(section, 'LoggerOutputConsole'),
config.getboolean(section, 'LoggerOutputFile')
)


def get_svchost(section, filename='altwfc.cfg'):
"""Return the svchost of the corresponding section."""
config = ConfigParser.RawConfigParser(allow_no_value=True)
config.read(get_config_filename(filename))
return config.get(section, 'SvcHost')
1 change: 1 addition & 0 deletions dwc_network_server_emulator.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<Compile Include="internal_stats_server.py" />
<Compile Include="master_server.py" />
<Compile Include="nas_server.py" />
<Compile Include="dls1_server.py" />
<Compile Include="register_page.py" />
<Compile Include="storage_server.py" />
<Compile Include="gamespy\gs_database.py" />
Expand Down
2 changes: 2 additions & 0 deletions master_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from gamespy_server_browser_server import GameSpyServerBrowserServer
from gamespy_gamestats_server import GameSpyGamestatsServer
from nas_server import NasServer
from dls1_server import Dls1Server
from internal_stats_server import InternalStatsServer
from admin_page_server import AdminPageServer
from storage_server import StorageServer
Expand Down Expand Up @@ -59,6 +60,7 @@
# GameSpyServerBrowserServer,
GameSpyNatNegServer,
NasServer,
Dls1Server,
InternalStatsServer,
AdminPageServer,
RegPageServer,
Expand Down
79 changes: 4 additions & 75 deletions nas_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@

import logging
import time
import urlparse
import BaseHTTPServer
import SocketServer
import os
import traceback

from gamespy import gs_database
from other import dlc, utils
from other import utils
import dwc_config

logger = dwc_config.get_logger('NasServer')
Expand Down Expand Up @@ -134,7 +132,9 @@ def handle_ac_svcloc(handler, db, addr, post):
# DLC host = 9000
# In case the client's DNS isn't redirecting to
# dls1.nintendowifi.net
ret["svchost"] = handler.headers['host']
# NB: NAS config overrides this if set
svchost = dwc_config.get_svchost('NasServer')
ret["svchost"] = svchost if svchost else handler.headers['host']

# Brawl has 2 host headers which Apache chokes
# on, so only return the first one or else it
Expand Down Expand Up @@ -205,77 +205,12 @@ def handle_pr(handler, addr, post):
return utils.dict_to_qs(ret)


def handle_download_action(handler, dlc_path, post):
"""Handle unknown download action request."""
logger.log(logging.WARNING, "Unknown download action: %s", handler.path)
handler.send_response(200)
return None


def handle_download_count(handler, dlc_path, post):
"""Handle download count request."""
ret = dlc.download_count(dlc_path, post)
handler.send_response(200)
handler.send_header("Content-type", "text/plain")
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret


def handle_download_list(handler, dlc_path, post):
"""Handle download list request."""
ret = dlc.download_list(dlc_path, post)
handler.send_response(200)
handler.send_header("Content-type", "text/plain")
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret


def handle_download_contents(handler, dlc_path, post):
"""Handle download contents request."""
ret = dlc.download_contents(dlc_path, post)

if ret is None:
handler.send_response(404)
else:
handler.send_response(200)
handler.send_header("Content-type", "application/x-dsdl")
handler.send_header("Content-Disposition",
'attachment; filename="%s"' % post["contents"])
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret


def handle_download(handler, addr, post):
"""Handle download POST request."""
logger.log(logging.DEBUG, "Download request to %s from %s:%d",
handler.path, *addr)
logger.log(logging.DEBUG, "%s", post)

action = str(post["action"]).lower()
dlc_dir = os.path.abspath("dlc")
dlc_path = os.path.abspath(os.path.join("dlc", post["gamecd"]))

if os.path.commonprefix([dlc_dir, dlc_path]) != dlc_dir:
logging.log(logging.WARNING,
'Attempted directory traversal attack "%s",'
' cancelling.', dlc_path)
handler.send_response(403)
return

command = handler.download_actions.get(action, handle_download_action)
ret = command(handler, dlc_path, post)

logger.log(logging.DEBUG, "Download response to %s:%d", *addr)
return ret


class NasHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Nintendo NAS server handler."""

post_paths = {
"/ac": handle_ac,
"/pr": handle_pr,
"/download": handle_download
}

ac_actions = {
Expand All @@ -284,12 +219,6 @@ class NasHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"svcloc": handle_ac_svcloc,
}

download_actions = {
"count": handle_download_count,
"list": handle_download_list,
"contents": handle_download_contents,
}

def version_string(self):
return "Nintendo Wii (http)"

Expand Down
9 changes: 9 additions & 0 deletions tools/apache-hosts/dls1.nintendowifi.net.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName dls1.nintendowifi.net
ServerAlias "dls1.nintendowifi.net"
ServerAlias "dls1.nintendowifi.net, dls1.nintendowifi.net"
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:9003/
ProxyPassReverse / http://127.0.0.1:9003/
</VirtualHost>
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
ServerAlias "naswii.nintendowifi.net, naswii.nintendowifi.net"
ServerAlias "nas.nintendowifi.net"
ServerAlias "nas.nintendowifi.net, nas.nintendowifi.net"
ServerAlias "dls1.nintendowifi.net"
ServerAlias "dls1.nintendowifi.net, dls1.nintendowifi.net"
ServerAlias "conntest.nintendowifi.net"
ServerAlias "conntest.nintendowifi.net, conntest.nintendowifi.net"
ProxyPreserveHost On
Expand Down

0 comments on commit d3eed4c

Please sign in to comment.