Building a Webcasting Troubleshooter

At the Oxford Internet Institute (OII), we run a fair few services, one of which is a streaming service based on Wowza Streaming Server. Wowza is a great piece of software (once configured properly) and allows us to stream .h264 encoded mp4s, and also stream live.

Recently, we’ve been trialling the live service as a bit of a recruitment tool; as a department which studies the social effects of the Internet, it seems logical we should utilise social media and streaming video as a way of attracting students, but also to help with the open door effort of not excluding anyone who may wish to apply.

One of the difficulties in providing live webcasting services is the lack of control over the end user’s experience. By using an .h264 encoded stream over RTMP, there are certain conditions which need to be met on the client end. Testing for these conditions has recently proved a bit of a head-scratcher, but we’ve come up with a small testing suite which at least helps push the user in the correct direction.

So what do we need to test?
    • Firstly, Javascript has to be enabled;
    • Secondly, we need to test for Flash, and preferably a version number,
    • And lastly, we need to test that port 1935 is open on the client end, for streaming over RTMP.

The end user should hopefully see three check boxes, for Javascript, Flash and finally, the port 1935 tester. If any of the tests fail, then they should be directed to instructions for enabling Javascript, updating Flash, etc.

I won’t go into the details of the Javascript/Flash detection here, as it’s generally well documented on the web.

The challenge was the port 1935 check.

We didn’t want to go down the Java Applet route (as that would lead to yet another condition to test for), and we didn’t want to give end users instructions on how to ping / tracert etc, as that would simply be too complex for the majority of users. We wanted a solution which would integrate with the rest of the page easily.

As we just need to check 1935 is open from the client end, *any* response on 1935 can be measured as a successful connection. Wowza doesn’t run a HTTP server in the truest sense – it *does* however respond with the Wowza streaming server number on port 80, and also on 1935; It’s a seemingly non standard response though, at least as far as the http headers are concerned.

Via ColdFusion?

So initially, I wasn’t thinking straight, and suggested doing a CFHTTP request to the streaming server on port 1935 to try and gauge a response. As the returned request is slightly odd, CFHTTP threw a few parsing errors, and I ended up trying to get the page as a binary object, which worked. After all, at the time, I was just looking to get anything from the streaming server over 1935.

Obviously, that request would come from our webserver, not the client, so pretty useless for testing whether the  end user could connect on 1935. So that rules out Server side scripting straight away.

Via jQuery?

Next, jQuery was the obvious candidate: it’s a client-side language after all. Couldn’t we just do a get request via jQuery, and gauge the response that way? Unfortunately (well, fortunately for the world wide web) there’s a fair amount of browser restrictions on cross domain requests when it comes to Javascript. You can’t just grab a page hosted on another domain, on a non standard port that way, and access it via jQuery.

Via iFrame?

We can’t use an iFrame, as the browser won’t allow you to access the content from another domain, so passing the result to jQuery wasn’t possible. Also, returning the Wowza generated page wouldn’t be exactly user friendly, and a line such as ‘If you don’t see Wowza X.XXX.XXX below, there’s a connection issue’ isn’t a particularly useful response.

Via JQuery & JSONP?

JSONP (JSON with Padding) is the answer in this case – you could get jQuery to request JSONP – However, we really didn’t want to have to configure Wowza with it’s fairly complex configuration to return JSONP (I’m not even sure if it’s possible, as the Wowza generated page comes from a load of XML config, but it may well be). We also didn’t want to do anything to the rudimentary http server which might affect the video streaming.

Via Proxy?

We couldn’t also do a proxy, as the request would again not be originating from the client – or rather the client request would go over port 80 to the proxy, and then the proxy would continue on 1935. Same issue as Server side scripting.

Ok, Flash Proxy?

The one advantage is that we had control over the server we wanted to test. Enter flash proxy; there’s a good guide here: http://usejquery.com/posts/9/the-jquery-cross-domain-ajax-guide .

By opening up the crossdomain.xml on the streaming server (but restricting it to requests from our domain), we can allow flash to do the check and return the result to jQuery – see flHXR – http://flxhr.flensed.com/ (with the jQuery plugin).

All in all, quite a learning journey!

More links:

New site for drummers


I managed to scrape some time together recently, so I’ve created a drum video site.

Basically, I was bored of trawling through youTube looking for videos I knew to exist, I just wanted them in one place.

I built this in a couple of hours (and spent a few more populating it) using Drupal 6.

It’s basically a youTube directory – nothing’s actually hosted there, just pointing to decent videos. i’ve indexed them by artist, and also cross referenced solos/vs duets, whether they’re playing with a band etc..

It’s not drumtube.net (you can’t upload vids) and not drummerworld (I’m not actually creating any content), just an edited directory. A couple of others and I will be adding to it
gradually as time goes on..

It’s done purely for my own joy. If you like it, or have any suggestions, do let me know.

See: http://www.drumflam.com

CFWheels – logging the flash

One of the most useful features of CFWheels is ‘the Flash’.

Essentially, it’s a session scope which is designed to carry messages over page redirects, and only remove itself once it’s actually been viewed by the user.
I usually use it when a user has updated, deleted or requested something which requires some sort of feedback – like a password reset, a profile change etc.
Using filters, we can start using these flash scope messages as a basic logging device; did the user see an error message when they tried to update their profile? Was their password change successful? Were they told about it? etc.
In my Users.cfc controller, I’ve got one important line which makes this possible;

<cfset filters(through="logFlash", type="after")>

This means after any function in my Users.cfc controller is executed, logFlash() is called.

And in my Controller.cfc (where functions which may be required by all controllers live), I’ve got the two logging functions called logFlash, and addLogLine:

 
<cffunction name="logFlash" hint="Grabs the message in the flash scope and logs it">
<cfif structkeyexists(session.flash, "error")>
<cfset addLogLine(name=session.flash.error, type="error")>
</cfif>
<cfif structkeyexists(session.flash, "success")>
<cfset addLogLine(name=session.flash.success, type="success")>
</cfif>
</cffunction>

This function looks for struct keys of ‘error’ or ‘success’  in the flash scope and calls addLogLine() – this example creates a db row in a table called logfiles, but you could easily rewrite this to suit your needs (i.e email you, or write to a static file): I’m also logging the current userid, what type of message it was, and the calling IP address – plus I’m using createdAt in the logFiles table to automatically timestamp the entry.

 
<cffunction name="addLogLine" hint="Manually add a log line">
<cfargument name="name" required="yes" hint="The Actual Log Message">
<cfargument name="type" required="no" default="admin" hint="example options: public | admin | login | file | error | success">
<cfif NOT structkeyexists(session, "currentUser")>
<cfset thisuserid=0>
<cfelse>
<cfset thisuserid=session.currentUser.username>
</cfif>
<cfset logline=model("logfile").create(name=arguments.name, userid=thisuserid, 
type=arguments.type, ip=cgi.REMOTE_ADDR)>
<cfreturn true />
</cffunction>

Overall, a really useful way of working out what the user is seeing, and once you’ve set up these functions, calling them from other controllers is simply a matter of adding one line!

CFWheels – Don’t forget your filter

One of the features of CFWheels which I’ve been guilty of ignoring in the past is the combination ‘filter’ and init().

In your controller model, you have two really powerful tools at your disposal. The init() function, which runs before each request to the controller, can allow you to do lots of preprocessing logic, and make sure everything is ‘good to go’ with displaying your view. The filter function, when combined with init(), means you can call specific functions for a view, and keep any recurring code out of the view function itself.

I often have caught myself doing this multiple times in a controller (in this case, users.cfc)

<!---View User--->
<cffunction name="view">
<cfset currentuser=model("user").findOneByUsername(session.currentUser.email)>
</cffunction>

<!---Edit User--->
<cffunction name="edit">
<cfset currentuser=model("user").findOneByUsername(session.currentUser.email)>
</cffunction>

etc.

All I want is the current Users data, and often I’d want it for the view, list, edit functions etc. If you find that you’re repeating code in wheels, stop and ask your self whether there’s a better way.

Using the init function and filter, we can replace each call by simply writing the function once, and popping the call to the function in the filter. So:

<!--- init --->
<cffunction name="init">
<!---Filters--->
<cfset filters(through="getCurrentUser", only="view,edit")> 
</cffunction>

<!--- My new private function --->
<cffunction name="getCurrentUser" access="private">
<cfset currentuser=model("user").findOneByUsername(session.currentUser.email)>
</cffunction>

This means our object of currentuser is now available to the view and edit functions. We could also add some checks to see whether the session is valid, the object is returned, etc. Your resulting function might look something like this:

<cffunction name="getCurrentUser" access="private">
<cfif structkeyexists(session.currentuser, 'email')>
<cfset currentuser=model("user").findOneByUsername(session.currentUser.email)>
<cfif NOT isObject(currentuser)>
<cfset userError()>
</cfif>
<cfelse>
<cfset userError()>
</cfif>
</cffunction>

<!---An additional private function to throw a user related error--->
<cffunction name="userError" access="private">
<cfset flashInsert(error="User Not Found")>
<cfset redirectTo(back=true)>
</cffunction>

Once you get your head round this relatively simple principle, it makes creating your controllers very quick indeed..!

SOTR2010

I’ve just come back from ‘Scotch on the Rocks’ 2010, held in London. This has been quite a step up from last year!

I’ve had the pleasure of hearing Ben Nadel (@bennadel), Ray Camden (@cfjedimaster), Terry Ryan, Gert Franz and Aral Balkan (@aral). All great presentations, with Aral’s sheer passion for design (or should I say, ‘experience’)  coming through in particular.

Ben talked on CF’s Application framework, talking about session manipulation is a way I’d really just never thought of before – by opening the subject up, he definitely made it more accessible, and has some great code examples I must get my hands on.

Ray was on CFBuilder duty, and whilst it is something I *really* should get around to trying, the amount of times he said ‘oh and this doesn’t work, but don’t worry I’ve filed a bug’ did leave me slightly worried 🙂 I enjoyed his Ajax Q&A session too – as something which doesn’t always come into my projects, it was interesting to hear that my thoughts on Ajax generally are pretty well reflected from those that spoke. 

Railo 4 is looking to be stellar; there’s a billion things they’re planning which are a bit beyond me (particularly the whole Java integration and command line stuff) but it’s very encouraging to see Railo doing so well; I’ve been using Railo alongside CF8 for a year now, and it really is a fantastic open source project.

Apart from the 6am ‘get up grab train and run’ (and having to leave early) it’s been a great couple of days. Nice to meet so many of the other CF Twitter(er)s too; not to mention seeing people whose blogs I’ve been reading for 5 years for the first time! Congrats to the whole SOTR team, and all the speakers.

CFWheels Wallpaper

Ok, so I had 5 minutes to myself; inspired by the Model Glue Wallpapers I saw the other day (http://www.model-glue.com/wallpaper.cfm) I thought I’d brush up on my Photoshop skills, and do some CFWheels based ones.

Enjoy the below! All are 1920×1200.

Note to Mango Blog Users: check your log table if you use plugins

Had a small shock the other day – whilst being all responsible and backing up all my MySQL databases, I noticed this blog’s backup taking a rather long time.

There really aren’t that many entries here, so the .sql dump should be a few hundred k, certainly no more than a few MB.

Imagine to my horror when I discovered that the total dump size was over 750MB!!

Turns out a plugin I’d tried a while back was failing, and Mango blog was logging the fail silently in the database. Annoyingly, I’d not deactivated the plugin, but as I’d not gotten any indication of it failing, it just kept on being logged, on *every* request.

The real problem is that the entire error struct is stored, so  imagine the raw HTML of  a cfdump error struct x 15000+ rows… it builds up over time!!

Select Multiple Values for select() CFWheels

Just found this nice little feature, which is basically undocumented..

There are two Form helpers for drop down select boxes in CfWheels – one is the standard selectTag(), and the other is select() which will bind itself to an object automatically. The selectTag() function is just designed for bog standard forms with no object property.

In CfWheels, you can pass normal HTML attributes into the form helpers, like ‘id’, ‘class’ etc.. these are largely undocumented in the CfWheels docs, as they’re well, fairly obvious.

What I’ve just found, which plesantly surprised me, is that you can pass ‘multiple=true’ into the select() form helper, and if the corresponding object’s value is a comma deliminated list, it automatically puts in the necessary markers for it to be selected: this is one step up from the standard logic of just passing through the attribute, as CfWheels seems to be doing conditional statements to determine whether it’s selected or not. Nice.

So with the following (with the options ‘allBlocks’ being a query of available blocks):

#select(objectName="page", 
    multiple='true', 
    label="Prepend to Content", 
    property="prepend_blockid", 
    options=allBlocks)#

If in my object ‘page’, page.prepend_blockid = ’1,4,5,6,7′, then wheels will automatically give me

<select id=“page-prepend_blockid” multiple=“multiple” name=“page[prepend_blockid]“>
<option value=“”></option>
<option selected=“selected” value=“1″>About Menu Block</option>
<option value=“2″>About Us Quick Text</option>
<option value=“3″>Site Information Menu</option>
<option selected=“selected” value=“4″>What We Do Menu Block</option>
<option selected=“selected” value=“5″>Google Search Form</option>
<option selected=“selected” value=“6″>Contact Form</option>
<option selected=“selected” value=“7″>Twitter Update</option>
<option value=“8″>Resources Menu</option>
<option value=“9″>Latest 5 Webcasts</option>
<option value=“10″>Latest 5 Podcasts</option>
</select>

Starting out with CfWheels + jQuery + Colorbox

One of the things I’m writing at the moment is a fairly complex bespoke content management system. I’ve done a fair few CMSes in my time, but most of them have had relatively simple back ends – you know the type, where you’ve got a separate ‘admin’ section, which in CF terms is often a completely different application; this is usually for authentication’s sake (let’s face it, it’s fairly easy to secure an entire application.cfc) and to keep it relatively contained in a single folder.

As I’ve been playing around with CfWheels of late, I thought I’d force myself to use it with this project, as for me, that’s usually the best way to learn something – plus I always had the ‘get out’ clause of being able to override internal wheels behaviour if needed. Wheels instantly throws you into a different mindset when it comes to CMS-like apps; as there are various conventions like MVC and ORM already in place, it makes sense to approach everything from that ‘wheels’ point of view.

As building forms is so insanely easy in wheels (see the form helpers), I very quickly got to the point where I started to crave a little more interaction; especially when starting to deal with many to many relationships, and how to update those. But my main objective was to break out of the ‘separate-page-in-a-different-application-to-update’ mindset.

Enter jQuery & colorbox based forms. Having not really played around with jQuery that much (I know, I know) I’ve been pretty shocked about how quickly I managed to pull together some proof of concept forms. Add something like colorbox into the mix, and suddenly you’ve got instant editing ability from any page in your application, without going to have to find the entry in the admin section.

I’m going to try my best to explain where I’ve got to, with the usual caveats – there’s almost always a better way to do this, and I’ve probably just not come across it yet – so comments welcomed..

I’m going to assume you have a basic wheels framework in place, complete with your datasource. For this example, I’m just going to concentrate on one controller and a couple of views.

Starting up – the layout file

The first thing is to include the necessary JS & CSS files, so in my layout.cfm file I’ve got

#styleSheetLinkTag(sources="colorbox", media="screen,projection")#
#javaScriptIncludeTag("jquery-1.3.2,jquery.colorbox")#

The Main View page

We need a page view which will output our page object, and provide our edit link: so in /views/pages/view.cfm you might have something like this:

<cfparam name="page">
<cfoutput><p class="admin-links">
#linkTo(text="Edit This Page", class="colorbox", action="edit", key=page.id)#
</p>
#page.content#
</cfoutput>

Note the class=”colorbox” – this we will use later to tie in the form submission with javascript. So this page is essentially providing a link which points at /pages/edit/[pageid].

Next, we need a form:

In my /views/pages folder, I’ve got a ‘partial’ called _form.cfm, which is basically a view designed to be called without layout.

#startFormTag(action="update")#
#hiddenField(objectName="page", property="id")#
#textArea(objectName="page", property="content")#
#submitTag()#
#endFormTag()#

Nothing too unusual there, move along..

Controller: Pages.cfc

In this file, i’ve got 3 functions: A view, edit and update function. The edit function is fired when the form is loaded, and the update function is fired on the submission of the form.

<cffunction name="view">
     <cfset page = model("page").findAllBySESURL(value=params.title)>
</cffunction>

<cffunction name="edit">
     <cfset page = model("page").findByKey(key=params.key)>
      <cfset renderPartial("pageform")>
</cffunction>
        
<cffunction name="update">
     <cfset page = model("page").findByKey(params.page.id)>
     <cfset page.update(params.page)>      
     <cfif page.hasErrors()>             
             <cfset flashInsert(error="Page Content couldn't update.")>
             <cfset redirectTo(back=true)>
     <cfelse>
            <cfset flashInsert(success="Page Content updated successfully.")>
            <cfset redirectTo(back=true)>
     </cfif>
 </cffunction>

Note the renderPartial(“form”) line. This makes wheels look for a “_form.cfm” file in my /views/pages/ folder. The other bit of note is ‘redirectTo(back=true)’ – this closes the modal window and updates our initial page.

Tie it all together:

The last bit is just the javascript to tie the link into loading the form in a modal window:

 <script type="text/javascript">
 $(document).ready(function(){
$(".colorbox").colorbox({
                         transition: 'fade',
                         speed: 200
  });
 </script>

This tells colorbox to open any link with a class of .colorbox.

So really, it’s three simple things to remember:

  • opening the form via colorbox requires a class/id in the link (at least, that’s one way of doing it, there are many others)
  • Using partials in modal windows means you don’t have to have the layout, and you can reuse that form from anywhere (you could also use renderPage(layout=false))
  • Using redirectTo(back=true) does refresh the page, but the most important thing is, you’ve not really left it due to the overlay.