Radius and Mysql with hourly Accounting
I've been setting up a Radius server (freeradius) to handle auth'ing users on our community wifi network. It made sense to get the data (users, accounting etc.) into Mysql and its is relatively easy to compile Freeradius with Mysql support. I used MacPorts and had to use this patch
The user authorisation worked with very little effort. Theres some useful information on getting it set up on the Freeradius Wiki.
However, the accounting was more difficult. The NAS (Network Access Servers) that we use (Ubiquiti Rocket M5's) dont sent the "NAS-Port" number in the data packet they send to the radius server (at leaste, not in the current beta firmeware). As the server uses this to create a hash to uniquely identify the session, we got lots of duplicate rows in Mysql and several rows were getting updated by the "Interim-Update" packets that our NAS send every ten minutes.
Luckily there was a simple solution. Freeradius includes several configuration files for different database servers. I noticed that some of the others had a much more robust mechanism for updating the accounting mysql table ("radacct" is the default table name).
I'm using the default "dialup.conf" as the configuration file for the various SQL statements. By appending "AND acctstoptime IS NULL" to the accounting_update_query and the accounting_start_query_alt statements, the problem was resolved. I have no idea why this is the default for the Mysql config that ships with radius as this is how the statemenst for Oracle and some of the other DBS servers are configured. ...Maybe I'm mising something(I'm new to radius), but its working for me at the moment.
I wnated to be able to generate graphs of hour by hour bandwidth usage for our network usage. Our NAS send updates every ten minutes so I knoew this showuld be possible. However the Radius accounting table only maintains a cumulative total for each session, so it was goung to need a separate approach.
Having done some research I realised that using a Myql trigger was the way to go. Everytime my radacct table was updated (i.e. every ten minutes for each session) the trigger could invoke a routine to store the data in a separate stats table. The sql for the stats table is below.
DROP TABLE IF EXISTS `user_stats`; CREATE TABLE `user_stats` ( `id` int(11) NOT NULL AUTO_INCREMENT, `radacct_id` int(11) NOT NULL, `acctsessionid` varchar(64) NOT NULL, `acctuniqueid` varchar(32) NOT NULL, `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `acctinputoctets` bigint(20) NOT NULL, `acctoutputoctets` bigint(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
I'm actually duplicating quite a bit of unecessart data here(e.g. acctsessionid and acctuniqueid) are both available in the radact table. radacct_id is a reference to the 'parent' record.
The trigger was really easy:
delimiter $$ CREATE TRIGGER radacct_after_update AFTER update ON radacct FOR EACH ROW BEGIN INSERT INTO user_stats SET radacct_id = OLD.radacctid, acctsessionid=OLD.acctsessionid, acctuniqueid = OLD.acctuniqueid, acctinputoctets = (NEW.acctinputoctets - OLD.acctinputoctets), acctoutputoctets = (NEW.acctoutputoctets - OLD.acctoutputoctets) END$$ delimiter ;
The trick is to subtract the old cumlative data totals from the new - that gives the total for the period in question.
This is still very much a work-in-progress but I hope it helps someone!
4:30am Technology Blog
Automatically pause iTunes when your phone leaves the building
Heres a neat way to have iTunes automatically pause iTunes when (you and) your phone moves out of bluetooth range. It will then resume playing when you return.
You may already be familiar with Proximity, a Mac Application that will trigger an applescript based on whether it detects your phones bluetooth signal.
You'll need to install this first: http://code.google.com/p/reduxcomputing-proximity/
Once Proximity is installed, fire up Apple Script Editor and create the script that will run when you move out of range.
The nice theing about this is that it will neatly fade down iTunes and its sister script (that will run when you come back into range) fades the volume back up to the same level.
The scripts also use a system default to decide whether to trigger iTunes to resume playing. The nice thing about this is that iTunes will only resume playing, if it was Proximity that caused it to pause...so iTunes wont suddenly and unexpectedly start playing. This was a big issue with other scripts I had used.
(* db iTunes Fade-in/Fade-out By Al Fleming, 430am.com Based on ideas from David Battino, Batmosphere.com, Doug's AppleScripts and Mac OS Hints Thanks to Jacob Rus for the "global" tip This script fades out iTunes if it's playing and fades it in if it's stopped. *) global okflag set okflag to false set iChatRunning to false set front_app to (path to frontmost application as Unicode text) -- So we can switch back to this after running the fade -- check if iTunes is running tell application "System Events" if process "iTunes" exists then set okflag to true --iTunes is running end if if exists process "iChat" then set iChatRunning to true end if end tell if okflag is true then try tell application "iTunes" set currentvolume to the sound volume if (player state is playing) then do shell script "defaults write 'com.430am.iTuneswasrunning' wasrunning \"true\"" repeat --Fade down repeat with i from currentvolume to 0 by -1 --try by -4 on slower Macs set the sound volume to i delay 0.03 -- Adjust this to change fadeout duration (delete this line on slower Macs) end repeat pause --Restore original volume set the sound volume to currentvolume exit repeat end repeat end if end tell tell application front_app activate end tell on error beep end try end if if iChatRunning is true then tell application "iChat" log out end tell end if
You'll notice that this also logs out of of iChat as well. If you dont want that then remove that part of the script.
Save this as a script called proximity_away.scpt
Now create a new script. This one will be triggered when you arrive back:
tell application "System Events" if process "iTunes" exists then set okflag to true --iTunes is running set wasrunning to do shell script "defaults read 'com.430am.iTuneswasrunning' wasrunning" end if if exists process "iChat" then set iChatRunning to true end if end tell if okflag is true then try tell application "iTunes" set currentvolume to the sound volume if (player state is playing) then -- could add functions here for when you arrive back and itunes is already playing else --Fade up if (wasrunning is "true") then set the sound volume to 0 play repeat with i from 0 to currentvolume by 1 --try by -4 on slower Macs set the sound volume to i delay 0.03 -- Adjust this to change fadeout duration (delete this line on slower Macs) end repeat do shell script "defaults write 'com.430am.iTuneswasrunning' wasrunning \"false\"" (*play repeat with j from 0 to currentvolume by 2 --try by 4 on slower Macs set the sound volume to j end repeat*) end if end if end tell tell application front_app activate end tell on error beep end try end if if iChatRunning is true then tell application "iChat" log in end tell end if
Saving this as proximity_here.scpt
Now open up the Proximity preferences and set the Out Of Range scrip to the proximity_away.scpt script and the In Range to the proximity_here.scpt
I changed the Device monitoring time to 10 seconds (not sure whether theres significant CPU overhead for this).
CSS Expandable Div with rounded corners - using only one element!
Having nicely-styled, expandable, divs using rounded corners, drop shadows or whatever has always been difficult to achieve without either resorting to using the CSS3 border-radius (which isnt fully supported yet) or using complex nested divs and background images.
I came across a posting on Nicolas Gallaghers site about using the CSS :before and :after psuedo elements to create interesting effects. These elements are CSS 2.1 so they should be supported by all modern browser incarnations. I realised that the same technique could be used to create expandable divs with rounded corners and/or drop shadows using only one element.
e.g.:
<div id="expandbox">Content here</div>
Check out the demo here. You can get the method by looking at the source and linked css
New Technology - Node.js
Every once in a while something new comes along that gets us excited. Node.js is one of those.
Node.js is described as "A toolkit for writing extremely high performance non-blocking event driven network servers in JavaScript". It is an evented I/O Framework that is built on top of Google's V8 javascript engine which already has a reputation for being blindingly fast.
But most importantly, it allows developers to create high performance network servers with just a few lines of javascript code.
Server-side javascript is becoming more popular and with the performance that Node.js can give, the arguments for using it are stronger than ever.
Furthermore, Ryan Dahl, the creator, has focussed on making Node.js completely event driven and non-blocking. A traditional web-server thread would spend much of its time waiting for, say, a database query to complete before it can send the response back to the browser. This ties up a thread doing essentially nothing and is a serious restriction to scalability. Because Node.js is event driven, processes can get on with doing other stuff and only go back to delivering the results of the database query when they are ready.
in a nutshell, this makes it extremely fast and scaleable.
Node.js also has a plug-in architecture and theres an ever-growing list of modules to enhance and expand its capabilities.
Node.js is low-level. That is to say, it doesnt do much out of the box. But you can "write" your own webserver with just a few lines of code.
Example of a (very!) basic web-server listening on port 8080:
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World\n'); }).listen(8080); console.log('Server running at http://127.0.0.1:8080/');
As Node.js supports calls to the file-system, code to serve static files is also very easy:
var sys = require("sys"), http = require("http"), url = require("url"), path = require("path"), fs = require("fs"); http.createServer(function(request, response) { var uri = url.parse(request.url).pathname; var filename = path.join(process.cwd(), uri); path.exists(filename, function(exists) { if(!exists) { response.writeHead(404, {"Content-Type": "text/plain"}); response.write("404 Not Found\n"); response.end(); return; } fs.readFile(filename, "binary", function(err, file) { if(err) { response.writeHead(500, {"Content-Type": "text/plain"}); response.write(err + "\n"); response.end(); return; } response.writeHead(200); response.write(file, "binary"); response.end(); }); }); }).listen(8080); sys.puts("Server running at http://localhost:8080/");
Obviously theres a lot more to a production-level server than this code snippet but the good news is that there a whole raft of 3rd party modules and frameworks to handle things like logging and mime-types etc.
So, if you know javascript already, give node.js a whirl!
Hide comments