JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
register coffeescript compiler
[peach-cgt.git] / server.coffee
index 3c370e7..e20223d 100644 (file)
@@ -14,7 +14,7 @@
 # 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/>.
 
-listen_port = 8333
+listen_port = process.env.PORT ? process.env.app_port ? 9988
 sys = require 'sys'
 fs = require 'fs'
 http = require 'http'
@@ -26,10 +26,11 @@ model = require './common.coffee'
 
 games = {}
 max_concurrent_games = 50
-max_game_idle = 2 * 60 * 60 * 1000 # two hours (in miliseconds)
+max_game_idle = 3 * 60 * 60 * 1000 # three hours (in miliseconds)
 
 # timeout function with args in convenient order
 timeout = (ms, func) -> setTimeout func, ms
+interval = (ms, func) -> setInterval func, ms
 
 now_s = ->
        d = new Date()
@@ -104,7 +105,7 @@ js_handler = (args, out, request, url_parts) ->
 html_handler = (args, out, request, url_parts) ->
        fs.readFile 'index.html', 'utf8', (err, data) ->
                if err
-                       return out.end 'Server failed to read index.html'
+                       return out.end "Server failed to read index.html: #{err}"
                out.end data
 
 clean_pathname_regex = new RegExp('[^a-zA-Z/_.-]')
@@ -115,9 +116,9 @@ clean_pathname = (str) ->
        str = str.replace clean_pathname_regex2, '/_'
        return str.replace clean_pathname_regex3, '_'
 
-# serve javascript files from within /usr/share/javascript
-javascript_handler = (args, out, request, url_parts) ->
-       filename = clean_pathname "/usr/share/#{url_parts.pathname}"
+# serve javascript files from within external/
+external_javascript_handler = (args, out, request, url_parts) ->
+       filename = clean_pathname "external/#{url_parts.pathname.substr 10}"
        fs.readFile filename, 'utf8', (err, data) ->
                if err
                        out.writeHead 404
@@ -143,10 +144,10 @@ get_handler = (args, out, request, url_parts) ->
                return
 
        game = games[args.game]
+       out.writeHead 200, 'Content-Type': 'text/javascript'
 
        waiter = games["#{args.agent}_waiter"]
        if waiter?
-               waiter.writeHead 200, 'Content-Type': 'text/javascript'
                waiter.end '[]'
 
        game["#{args.agent}_waiter"] = out
@@ -211,14 +212,12 @@ answer_now = (game) ->
                queue = game.p1_queue
                game.p1_waiter = false
                game.p1_queue = []
-               waiter.writeHead 200, 'Content-Type': 'text/javascript'
                waiter.end JSON.stringify queue
        if game.p2_waiter and game.p2_queue.length
                waiter = game.p2_waiter
                queue = game.p2_queue
                game.p2_waiter = false
                game.p2_queue = []
-               waiter.writeHead 200, 'Content-Type': 'text/javascript'
                waiter.end JSON.stringify queue
 
 # this marks a game as "dirty" and makes sure there's exactly one timeout
@@ -267,6 +266,15 @@ new_game = (slug) ->
 
        return game
 
+long_poll_keepalive = ->
+       for slug, g of games
+               if g.p1_waiter? and g.p1_waiter isnt false
+                       g.p1_waiter.write '\n'
+               if g.p2_waiter? and g.p2_waiter isnt false
+                       g.p2_waiter.write '\n'
+
+interval 12000, long_poll_keepalive
+
 http_server = http.createServer (req, res) ->
        url_parts = url.parse req.url, true
        if url_parts.query is undefined
@@ -274,15 +282,15 @@ http_server = http.createServer (req, res) ->
 
        rel_path = url_parts.pathname.substr 1
 
-       if rel_path.substr(0, 11) is 'javascript/'
-               return javascript_handler url_parts.query, res, req, url_parts
+       if rel_path.substr(0, 9) is 'external/'
+               return external_javascript_handler url_parts.query, res, req, url_parts
        else if rel_path.substr(rel_path.length - 4) is '.css'
                res.writeHead 200, 'Content-Type': 'text/css'
                return css_handler url_parts.query, res, req, url_parts
        else if rel_path.substr(rel_path.length - 3) is '.js'
                res.writeHead 200, 'Content-Type': 'text/javascript'
                return js_handler url_parts.query, res, req, url_parts
-       else if rel_path.substr(rel_path.length - 4) is '/set'
+       else if rel_path is 'set'
                data = ''
                req.on 'data', (chunk) ->
                        data += chunk
@@ -293,7 +301,7 @@ http_server = http.createServer (req, res) ->
                                query[key] = parg
                        return set_handler query, res, req, url_parts
                return
-       else if rel_path.substr(rel_path.length - 4) is '/get'
+       else if rel_path is 'get'
                return get_handler url_parts.query, res, req, url_parts
        else if rel_path.substr(rel_path.length - 4) is '.ico'
                res.writeHead 404
@@ -301,7 +309,11 @@ http_server = http.createServer (req, res) ->
 
        return html_handler url_parts.query, res, req, url_parts
 
+################## INIT ####################
+# make sure the current working directory is correct
+process.chdir __dirname
+
 setInterval expire_old_games, 2 * 60 * 1000 # check every 2 minutes for expired games
 
-http_server.listen listen_port, "127.0.0.1"
+http_server.listen listen_port
 console.log "Server running at http://127.0.0.1:#{listen_port}/"