Mobile phone detection with Varnish – Quick getting started guide

This is a quick reference guide, for a proper understanding of what you are doing use this guide. This solution is easier to implement and has less of a cpu overhead.

yum install libxml2-devel
#OR
apt-get intall libxml2-dev
wget https://gist.github.com/raw/805710/9f34a18e528c20eff1c92672c6f1856ed849f5ea/wurfl.c
wget https://gist.github.com/raw/805710/b9272d8a1d32d29034574c88b81fc79eb050e21b/wurfl.h
gcc -c -o wurfl.o wurfl.c -I/usr/include/libxml2 -fPIC
gcc -shared -Wl,-soname,libwurfl.so.1 -o libwurfl.so.1.0.1 wurfl.o -lxml2
wget http://downloads.sourceforge.net/project/wurfl/WURFL/latest/wurfl-latest.zip
unzip wurfl-latest.zip
mv wurfl.xml /etc/wurfl.xml
cp libwurfl.so /usr/lib
ln -s /usr/lib/libwurfl.so /usr/lib64/libwurfl.so

Edit your /etc/varnish/mobile.vcl using this as a guide

/etc/init.d/varnish stop
/usr/sbin/varnishd -s malloc,32M -a 0.0.0.0:80 -f /etc/varnish/mobile.vcl   -p 'cc_command=exec cc -fpic -shared -Wl,-x -lwurfl -o %o %s'

Test by looking in your server heads.. IE in PHP.. print_r ($_SERVER);

Introducing Catch – A multiplayer html game

Today I’m introducing catch, a game we have been developing for the last month or so as a side project.
Catch is like Tag or Tig or whatever you called it in the playground. Basically someone is “it” and you’re job is to avoid that person.. Avoiding the person gives you points.. Could it be any simpler?

Let’s get a few things out of the way:
It isn’t much of a game.. I mean you can win but we haven’t introduced many other game mechanics.
The code isn’t optimized, we wrote it to learn about socket messaging so once we had learned enough we moved onto a proper project and rushed the game out of the door.
You can embed the game and play against other visitors on your blog/whatever.
The game doesn’t require flash.
Embed probably doesn’t work in IE.
The game is built on NodeJS, Socket.IO, jQuery/Javascript. We don’t have any databases, we’re too lazy.
We host the game but we released it open source so go ahead and host your own and/or break/play with the game!

Technical accomplishments:
Slowest user render (see game.html)
Latency detection and sorting (see game.html)
Connectivity type detection and advice (see browser.js)
Strange UI scoreboard based on pixels per points (see game.html)

Here is the game.. Hosted by brightbox.

Web Socket latency tests in Firefox, Chrome and IE9 & Android Webkit

Testing Web Socket.IO(Learnboost) on NodeJS latency

Results: Latency in MS — All results minus mobile taken from same ISP.  These aren’t concrete but should make a decent reference point

chrome w/ ws = 30
ff w/ xhr multipart = 60
ff w/ websocket = 30
ie w/ htmlfile= 120
android phone webkit w/ xhr polling on wifi  = 200
android phone webkit w/ xhr polling on mobile phone network = N/A

Developing a collaborative game using NodeJS, SocketIO & jQuery

Quick link to the game I made

You may remember a few months ago I did an article on Real time mouse activity using NodeJS and Socket, well I wanted to extend that functionality into some sort of game. It was obvious from the demo I made that people enjoyed interacting with each others cursors and I quite enjoyed working on it.

Today was our second day working on the game and our UI design is pretty much done and so are 2 of the 3 minigames designs. The mechanics are coming along with a few cretins as we have to wrestle with Internet Explorer‘s(8+9b) interesting interpretation of how Socket should perform. Firefox and Chrome have been a dream to work with the jQuery implementation of the animations and the scoreboard have gone pretty smoothly..

We’re doing about 10 hours a day on it at the moment however the days only feel 6 hours or so long as it is a labour of love and is a nice change from the mundane PHP bugs I usually deal with.  The work we are doing is one of the small steps needed to move away from Abobe Flash based games.

We’re hoping to demo one of the mini games to the LeedsJS folks on the 9th of March so if you want to see then come along! By the 9th of March I will expect about 100 hours or so in total has been spent on the game and you wont be able to tell as nearly all of the work is done on the server/back end as we are writing mechanisms that mean the game can operate as leanly as possible on both desktop browser and mobile browsers.

Here are our goals for the project:

  1. Scalability
  2. Completion in time for some competition thingy in April
  3. Any browser on any device that supports socket
  4. Hopefully flash fall back on non-socket supporting devices.
  5. Push all code as Open Source  under Apache license in Summer.

Quick thanks to John at Brightbox for providing the hosting for the project 🙂 We’re using their very BETA vm hosting service which I don’t know much about but it is super fast and is speeding up our development somewhat.

Enhanced by Zemanta

Quick link to the game I made

Updated Varnish WordPress VCL

THIS VARNISH CONFIG HAS BEEN UPDATED AND IS AVAILABLE HERE

I have been tweaking a varnish vcl config for WordPress for quite some time and I wanted to share it..  Thanks to everyone(especially DocWilco)  in #varnish on Linpro IRC for helping

Features:

  1. Load balancing
  2. Probing
  3. Does not cache wp-admin
  4. Puts all uploads/content requests onto one server
  5. Purging
  6. Long timeout for file uploads
  7. XML RPC support
  8. Custom 404 and 500 message
  9. Forwards user IP address for comments

First of all.. Let’s define some backends..

// BACKEND CONFIGS
backend server1 {
  .host = "server1.example.com";
  .port = "8080";
  .probe = {
                .url = "/";
                .interval = 5s;
                .timeout = 1 s;
                .window = 5;
                .threshold = 3;
  }
// we include time outs so uploads don't time out
 .connect_timeout = 600s;
 .first_byte_timeout = 600s;
 .between_bytes_timeout = 600s;
}

backend server2 {
  .host = "server2.example.com;
  .port = "8080";
  .probe = {
                .url = "/";
                .interval = 5s;
                .timeout = 1 s;
                .window = 5;
                .threshold = 3;
  }
// we include time outs so uploads don't time out
 .connect_timeout = 600s;
 .first_byte_timeout = 600s;
 .between_bytes_timeout = 600s;
}

// define round-robin for backends
director cluster round-robin {
        {.backend = server1;}
        {.backend = server2;}
}

// set the servers wordpress can purge from
acl purge {
        "server1.example.com";
        "server2.example.com";
}

sub vcl_fetch {
 if (req.http.host ~ "ourdomain.com"
     || req.http.host ~ "ourotherdomain.com"
// don't cache wp-admin ever cause that's not cool
     && req.url !~ "wp-admin")
{
// we cache these domains for 8 hours unless they are purged.
        set beresp.ttl = 8h;
        set beresp.grace = 600s;
// don't cache 404 or 500 errors
        if (beresp.status == 404 || beresp.status >= 500) {
                  set beresp.ttl = 0s;
        }
}
// tell all of the files to use server1
if (req.url ~ "files") {set req.backend = server;set beresp.ttl = 8h;}
}

sub vcl_recv {
// Purge WordPress requests for purge
  if (req.request == "PURGE") {
                if (!client.ip ~ purge) {
                        error 405 "Not allowed.";
                }
                purge("req.url == " req.url " && req.http.host == " req.http.host);
                error 200 "Purged.";
        }

// forward the client IP so comments show up properly
set req.http.X-Forwarded-For = client.ip;

// let server2 handle all feeds
    if (req.url ~ "/feed/")
    {set req.backend = server2;}

// server1 must handle file uploads
    if (req.url ~ "media-upload.php"
    || req.url ~ "file.php"
    || req.url ~ "async-upload.php")
    {set req.backend = server1;return(pass);}

// server1 can serve all files.
    if (req.url ~ "/files/")
    {set req.backend = server1;}

// do not cache xmlrpc.php
    if (req.url ~ "xmlrpc.php")
    {return(pass);}

// strip cookies from xmlrpc
    if (req.request == "GET" && req.url ~ "xmlrpc.php")
    remove req.http.cookie;return(pass);}

// caching these files is fine
if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
            remove req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            remove req.http.Accept-Encoding;
        }
}

// Remove cookies and query string for real static files
    if (req.url ~ "^/[^?]+\.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.*|)$") {
       unset req.http.cookie;
       set req.url = regsub(req.url, "\?.*$", "");
    }

// Remove cookies from front page
    if (req.url ~ "^/$") {
       unset req.http.cookie;
    }

// if the request is for our domain and not for wp-admin then load balance it to a server that is responding or send it to server1
if (req.http.host ~ "ourdomain.com"
    || req.http.host ~ "ourotherdomain.com"
    && req.url !~ "wp-admin")
{
        set req.http.X-Forwarded-For = client.ip;
        set req.backend = cluster;
        } else {
        set req.http.X-Forwarded-For = client.ip;
        set req.backend = server1;
}

// Custom error message
sub vcl_error {
if(obj.status == 404) {
        set obj.ttl = 0s;
  set obj.http.Content-Type = "text/html; charset=utf-8";
    synthetic {" <!--?xml version="1.0" encoding="utf-8"?-->

    "} obj.status " " obj.response {"
</pre>
<div style="background-color: white;"><center>
 <img src="http://whatever.com/heavyload.jpg" alt="" width="600px" /></center>
<h1>This page is unavailable</h1>
If you are seeing this page, either maintenance is being
performed or you are trying to access a file that doesn't exist. Please <a href="http://whatever.com/contact.html">contact us</a> if you believe this is an error
<h2>Error "} obj.status " " obj.response {"</h2>
"} obj.response {" on server "} req.backend {"
<address><a href="http://whatever.com/">Us.</a></address></div>
<pre>
  "};
    return (deliver);
error 404 "Not found";
 }
else
{
    set obj.http.Content-Type = "text/html; charset=utf-8";
    synthetic {" <!--?xml version="1.0" encoding="utf-8"?-->  
  
    "} obj.status " " obj.response {"
  

</pre>
<div style="background-color: white;"><center>
 <img src="http://whatever.com/heavyload.jpg" alt="" width="600px" /></center>
<h1>This website is unavailable</h1>
If you are seeing this page, either maintenance is being
performed
 or something really bad has happened. Try returning in a few
minutes. If you still see this error in a few minutes please <a href="http://whatever.com/contact.html">contact us</a>
<h2>Error "} obj.status " " obj.response {"</h2>
"} obj.response {" on server "} req.backend {"
<address><a href="http://whatever.com/">Us.</a></address></div>
<pre>
  "};
    return (deliver);
}
}