# Thursday, October 04, 2012

A customer recently contacted me with a Padarn Web Server problem.  They wanted users to be able to download data files from their device to a client browser, but they were running out of device memory when the file got large (38MB in their case, but the size would be completely hardware and environment dependent).

What you have to understand is that Padarn caches your Page’s response in memory until such time as you either tell it to Flush explicitly, or until the Page has full rendered (in Padarn’s view) at which point it will call Flush for you.

For a large file, it’s going to be bad to try to hold the entire thing in memory before pushing it across the wire, so the strategy would be to read the local file in packets, then send those packets across to the client using Response.BinaryWrite.

Now BinaryWrite simply puts the data into the memory cache, so you have to actually tell Padarn to send it across the wire by calling Flush.  The issue there, though, is that on the first Flush, Padarn has to assemble and send the payload header to the client, and part of that header is the total length of the content.  If you haven’t explicitly set the content length, Padarn has no idea how big it might be, so it defaults to the length what it has in the buffer, and sends the header.  The browser then decodes that header and expects a length of only that first packet.

The solution is to set the Response.ContentLength property before you send any data.  Padarn will use your override value when it sends it to the client, and all will be well.

Here’s a quick example of a page that I used to send a 1.1GB media file from a page request with no problem.  You might want to tune the packet size based on device memory and speed, but 64k worked pretty well for my test.

   1: class LargeFileDownload : Page
   2: {
   3:     protected override void Render(HtmlTextWriter writer)
   4:     {
   5:         var largeFilePath = @"D:\Media\Movies\short_circuit.mp4";
   6:  
   7:         var packetSize = 0x10000; // 64k packets
   8:  
   9:         using(var stream = new FileStream(
  10:             largeFilePath, 
  11:             FileMode.Open, 
  12:             FileAccess.Read))
  13:         {
  14:             var toSend = stream.Length;
  15:             var packet = new byte[packetSize];
  16:  
  17:             // set the response content length
  18:             Response.ContentLength = toSend;
  19:             // set the content type as a binary stream
  20:             Response.ContentType = "application/octet-stream";
  21:             // set the filename so the browser doesn't try to render it
  22:             Response.AppendHeader("Content-Disposition", 
  23:                 string.Format("attachment; filename={0}", 
  24:                 Path.GetFileName(largeFilePath)));
  25:  
  26:             // send the content in packets
  27:             while (toSend > 0)
  28:             {
  29:                 var actual = stream.Read(packet, 0, packetSize);
  30:  
  31:                 if (!Response.IsClientConnected)
  32:                 {
  33:                     Debug.WriteLine(
  34:                         "Client disconnected.  Aborting file send.");
  35:                     return;
  36:                 }
  37:                 else
  38:                 {
  39:                     Debug.WriteLine(
  40:                         string.Format("Sending {0} bytes. {1} to go.", 
  41:                         actual, toSend));
  42:                 }
  43:  
  44:                 if (actual == packetSize)
  45:                 {
  46:                     Response.BinaryWrite(packet);
  47:                 }
  48:                 else
  49:                 {
  50:                     // partial packet, so crop
  51:                     var last = new byte[actual];
  52:                     Array.Copy(packet, last, actual);
  53:                     Response.BinaryWrite(packet);
  54:                 }
  55:  
  56:                 // send the packet acrtoss the wire
  57:                 Response.Flush();
  58:  
  59:                 toSend -= actual;
  60:             }
  61:         }
  62:     }
  63: }
Thursday, October 04, 2012 1:03:37 PM (Central Daylight Time, UTC-05:00)  #     | 
# Monday, October 31, 2011

This post is part of my "Software Development" series.  The TOC for the entire series can be found here.


Developing good software is hard.  Really hard.  Sure, anyone can buy a book on writing software or pull up some code samples and get something that compiles and runs, but that’s not’s really developing software.  A lot of code in the wild – I’d bet a vast majority of it – just plain sucks.

It’s hard to point out where the blame lies.  It seems that most developers are environmentally or institutionally destined to write bad code. Schools teach how to write code, but not how to architect it or to follow reasonable design practices.  In the zeal for clarity, publishers churn out books, blogs and samples that show bad practices (when is it ever a good idea to access a data model from your UI event handler?).  Managers and customers alike push hard to get things done now, not necessarily done right – only to find months or years later that doing it right would have saved a boatload of time and money.  And let’s face it – many developers are simply showing up to work to pull a paycheck.  You know who they are.  You’ve no doubt worked with them in the past.  You’re probably working with them now.

I was watching Gordon Ramsay the other day and it occurred to me that he and I are alike in our own peculiar way.  I’m not saying that I see myself as the “Gordon Ramsay of Software Development” – hardly -   but we share a common trait.  Just as Gordon gets angry and starts spewing colorful language when he walks into a crap kitchen, it bothers the hell out of me to see complete idiots in my chosen field out there just making a mess of things.  When I see bad code – not necessarily minor errors, or code that could be refactored and made better – but just outright shit code that should not have occurred to a developer in the first place it pisses me off.  By the nature of my work, often getting called in only when the project is off the rails, I see it all the time. Code that, on review, a peer or mentor should have seen and said “Whoa!  There’s no way that’s going into our code base”.  Code that just makes it harder for the next person to do their job.

In an effort to simplify things for my own code, for my customers’ code as well as anyone who is willing to listen to my ravings, I’ve spent a lot of time building, testing, fixing and extending tools and frameworks that many of which I turn around and give away.  This isn’t out of altruism, no, it’s largely because I’m a lazy developer.  I hate writing the same thing twice.  When I start a project, I don’t want to spend large amounts of time building up the same infrastructure that every project needs. Building up a framework for handling UI navigation isn’t what I’d call interesting, but just about every project needs it.  Handling object dependencies and events is common.  Writing a DAL for serializing and deserializing entities is not just drudgery, I find it’s highly susceptible to errors because you end up doing a lot of copy and paste.

I have these cool tools and frameworks that I use in literally every project I work on now.  That’s great for me, but it doesn’t really help others, right?  Without reasonable documentation or explanation, only a small handful of people are going to go through the effort of getting the tools and trying to understand them – even if they are deceptively simple and could potentially save you weeks of effort. 

So I’ve decided to put together a series of blogs over the coming weeks and months that explain, hopefully in simple terms, what these frameworks do, how to use them, and most importantly, why they are worth using.  There’s nothing groundbreaking here.  I didn’t invent some new way to do things.  I’ve simply appropriated other peoples’ ideas and extended them to work in the environments that I work.

Generally I’ll be covering the following topics and frameworks:

  • Dependency Injection and Inversion of Control (using OpenNETCF IoC)
  • Event Aggregation (using OpenNETCF IoC)
  • Plug-in Architectures and interface-based programming (using OpenNETCF IoC)
  • Software features as services (using OpenNETCF IoC)
  • Data Access through an ORM (using OpenNETCF ORM)
  • Parameter Checking (using OpenNETCF Extensions)
  • Exposing data services over HTTP (using Padarn)
  • Whatever else I think of

If there’s a topic you’d like me to talk about, feel free to send me an email.  I may turn on comments here and let you post ideas, but I find that when I enable comments on my blog, I start getting more comment spam than I really want to deal with, so if comments are turned off just drop me a line.

Monday, October 31, 2011 10:11:24 AM (Central Standard Time, UTC-06:00)  #     | 
# Monday, December 06, 2010

IIS is a robust web server.  I'd never try to argue that it isn't or that Padarn could in any way try to replace it.  There are instances, however, where IIS just isn't a very good fit, and Padarn really is.  Some examples might be:

  • You want a simple web-based configuration interface for an embedded device
  • You want to expose REST APIs from your device in a small footprint
  • You want to expose data from your device but don't want users to have to fight configuring IIS
  • You actually have a size limitation and IIS makes it tough to achieve
  • You'd like your WebRequests to not all be in their own AppDomain
  • You'd like to share code assets between Windows CE and Embedded Standard/XPe

Padarn fits all of these scenarios well, and we continue to improve both performance and feature sets.

We just published a set of evaluation binaries compatible with desktop OSes (XP, Vista and Windows 7).  Make sure you're registered and logged in to see the downloads.

Monday, December 06, 2010 4:40:36 PM (Central Standard Time, UTC-06:00)  #     | 
# Friday, May 28, 2010

Every time we start a new project using our Padarn Web Server, I always like to see if we can improve the server's capabilities to make our job a little easier.  On the last project that turned into adding custom IHttpHandler support so we could easily serve up REST-based web services.

Well we started a new project last week, and unlike the last one, this one is UI-focused (the last one used Padarn strictly for services).  With that in mind, I went about looking at how to improve and simply building pages.

Of course I came back to our lack of support for server controls.  I did a little more playing and decided once again that it's a gigantic amount of work and it requires a boatload of RegEx and string manipulation - not necessarily a recipe for success on a low-memory, slow-CPU Windows CE device.

Still, there had to be other thing that full-blown ASP.NET offers that would be reasonable to add and that would help.  The existing samples we'd created in the past used overrode Page_Load method and then went about doing Response.Writes to emit page code.  The first time I did it I found it painful, so I created a class library that had objects for a lot of the basic HTML constructs and used that to at least help in generating well-formed code.

Still, I didn't really like the object model - it was still way too verbose - and it wasn't really like what anyone does on the desktop.  Additionally, rending in Page_Load really didn't feel right.

So I started looking around and found that the ASP.NET Page class provides a Render method.  That sounds a lot more like where I should be, oh maybe *rendering* a page.  Of course it required implementing the HtmlTextWriter, but that wasn't too terrible.

Once I implemented the Render method and started using the HtmlTextWriter, I quickly concluded that it, too, really sucked for generating page code.  It's just crazy verbose, it doesn't read anything like the page you're attempting to render and it's got things that just feel plain wrong (like having to add attributes before the tag they apply to? WTF is that?).

So I started looking at how ASP.NET developers who render their own controls with this monstrosity got around in.  It turns out that there is a pretty nice fluent interface to the HtmlTextWriter available on CodePlex.  It was missing a lot of stuff that I needed (and had a load of non-HtmlTextWriter stuff I didn't need), but it was a great start.  So after expanding the object model there I can now render a page in something that doesn't give me quite so much heartburn.

What originally looked like this:

protected override void Page_Load(object sender, EventArgs e)
{
  Response.Write(DoctypeTags.XHTML1);

  Response.Write("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
  Response.Write("<head>");
  Response.Write("<link rel=\"stylesheet\" type=\"text/css\" href=\"css/mystyle.css\" />");
  Response.Write("</head>");

  Response.Write("<body>");

  Response.Write("<h1>");
  Response.Write("Hello World!");
  Response.Write("</h1>");

  Response.Write("</body>");
  Response.Write("</html>");
  Response.Flush();
}

Ends up looking more like this:

protected override void Render2(HtmlTextWriter writer)
{
  writer.Write(DoctypeTags.XHTML1);

  writer
    .Tag(HtmlTextWriterTag.Html, t => t["xmlns", "http://www.w3.org/1999/xhtml"])

      .Tag(HtmlTextWriterTag.Head)
        .StylesheetLink("/css/mystyle.css")
      .EndTag() // head

      .Tag(HtmlTextWriterTag.Body)
        .H1("Hello World!")
      .EndTag() // body
    .EndTag(); // html
}

And it gets much cleaner looking the larger the page is.  I also find I'm doing a lot less searching for where I malformed my HTML.

I think the next Item I'll look into is the __doPostBack Javascript method that IIS injects into pretty much every page.  It's probably the next incremental step toward better productivity.

Friday, May 28, 2010 6:43:06 PM (Central Daylight Time, UTC-05:00)  #     | 
# Thursday, May 06, 2010

I've just rolled a new Padarn release - version 1.4.10126 - to add a new Authentication feature.  In previous versions of Padarn, you had to put your username/password pairs into the WebServer's configuration file.  This isn't too useful if you want to do run-time checking of credentials against something like a database.

Currently Padarn using what would be an analog to IIS authentication - that is to say that the user credentials are checked before any page code is run.  This means that, for now anyway, Forms authentication is not an option.  Instead I opted to allow you to set up the server to give you a callback whenever an authentication request occurs whether you're using Basic or Digest authentication.  For simplicity, the simple act of setting the callback tells the server to no longer look in the user list in the config file.

Setting up for dynamic authentication looks something like this.  First, you create your server instance and then simply set the authentication callback:

m_ws = new WebServer();
m_ws.Configuration.Authentication.AuthenticationCallback = VerifyUsername;

And then you might define you callback like this (note that I've desinged it to handle both Basic and Digest - you probably would pick just one):

bool VerifyUsername(IAuthenticationCallbackInfo info)
{
  // no username is invalid
  if (string.IsNullOrEmpty(info.UserName)) return false;

  // first do a lookup of the password - this might come from a database, file, etc
  string password = GetPasswordForUser(info.UserName);
  if (password == null) return false;

  // determine the type
  BasicAuthInfo basic = info as BasicAuthInfo;
  if (basic != null)
  {
    // we're using basic auth
    return (basic.Password == password);
  }

  // it wasn't basic, so it must be digest
  DigestAuthInfo digest = info as DigestAuthInfo;
  return digest.MatchCredentials(password);
}

The GetPasswordForUser function would look up a password given a username.
 

Thursday, May 06, 2010 11:32:58 AM (Central Daylight Time, UTC-05:00)  #     | 
# Friday, February 05, 2010

In the last article we looked at setting up Padarn for using custom HttpHandlers.  In this article we'll look at exactly how we use a custom handler to get data.

The GET Service

Probably the most common HTTP method is the GET method.  It's what your browser used to pull the content of this page, and it's what our REST service will use to get back a list of all Books in our database.

First, I create an entity that defines a Book.  This code file will actually get shared between the device and desktop projects to make things simple.

public class Book
{
  public int ID { get; set; }
  public string Title { get; set; }
  public string Author { get; set; }
  public int? Pages { get; set; }

  public static Book FromXml(string xml)
  {
    // omitted for brevity
  }

  public string AsXml()
  {
    // omitted for brevity
  }
}

I've left out the XML serialization/deserialization routines because they take up a lot of space and aren't really that interesting.  They're in the example source (I'll post it when I get these articles up - be patient) if you want to see them.

So next I need a way to get a list of these from my Database.  To encapsulate all of this logic, I created a DatabaseConnector singleton class that resides in the same assembly as the HttpHandlers.  Remember, these handlers are stateless and get created and called every time a URL is requested, so it would be pointless to put a connector instance in the handler itself.

The DatabaseConnector exposes a GetAllBooks method:

public Book[] GetAllBooks()
{
  string sql = "SELECT BookID, Title, Author, Pages FROM Books";
  List<Book> books = new List<Book>();

  using(SqlCeCommand cmd = new SqlCeCommand(sql, Connection))
  using(var resultset = cmd.ExecuteResultSet(ResultSetOptions.Scrollable))
  {
    if (resultset.HasRows)
    {
      while (resultset.Read())
      {
        books.Add(new Book
        {
          ID = resultset.GetInt32(0),
          Title = resultset.GetString(1),
          Author = resultset.GetString(2),
          Pages = resultset.IsDBNull(3) ? null : (int?)resultset.GetInt32(3)
        });
      }
    }
  }

  return books.ToArray();
}

Now all that I need to do is call this from my GetHandler like so:

public class GetHandler : BaseHandler
{
public override void ProcessRequest(HttpContext context)
{
  string entity = GetEntityName(context.Request.Path);

  // the only entity we support is "Books"
  if (string.Compare(entity, "books", true) != 0)
  {
    throw new HttpException(HttpErrorCode.NotFound, string.Format("Entity '{0}' not supported", entity));
  }

  Book[] books = DataConnector.GetInstance().GetAllBooks();

  StringBuilder sb = new StringBuilder(XML_HEADER);
  sb.Append("<books>");

  foreach (var b in books)
  {
    sb.Append(b.AsXml());
  }

  sb.Append("</books>");

  context.Response.Write(sb.ToString());
  context.Response.Flush();
}

That's all there is to it.  We now have implemented a REST service to get all Books from our Windows CE device.  When the Padarn server sees a GET request at http://<ip address>/books/ it will return an XML stream of all of the books in the database.  Here's an example of the output:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book>
    <id>1</id>
    <title>The Count of Monte Cristo</title>
    <author>Alexandre Dumas</author>
    <pages>1573</pages>
  </book>
  <book>
    <id>2</id>
    <title>Programming WCF Services</title>
    <author>Juval Loewy</author>
    <pages>610</pages>
  </book>
</books>

The GET Client

Now let's look at how a non-browser client (i.e. a desktop application) might make use of this service.

First, since I like abstraction and encapsulation, I created a class named RestConnector that handles all communications for REST services and a class named BookClient who's job is to handle nothing but interactions with the Books service.  RestConnector handles any GET requirements through the following methods:

public string Get(string directory)
{
  string page = string.Format("http://{0}/{1}", DeviceAddress, directory);

  StringBuilder sb = new StringBuilder();

  byte[] buf = new byte[8192];

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(page);

  HttpWebResponse response = (HttpWebResponse)request.GetResponse();

  return GetResponseData(response);
}

private string GetResponseData(HttpWebResponse response)
{
  StringBuilder sb = new StringBuilder();

  byte[] buf = new byte[8192];

  Stream stream = response.GetResponseStream();

  string result = null;
  int count = 0;

  do
  {
    count = stream.Read(buf, 0, buf.Length);

    if (count != 0)
    {
      // look for a UTF8 header
      if ((buf[0] == 0xEF) && (buf[1] == 0xBB) && (buf[2] == 0xBF))
      {
        result = Encoding.UTF8.GetString(buf, 3, count - 3);
      }
      else
      {
        result = Encoding.UTF8.GetString(buf, 0, count);
      }
      sb.Append(result);
    }
  } while (count > 0);

  return sb.ToString();
}

The BookClient uses the Get method to retrieve the XML for a list of books from the service and then deserializes that XML like this:

public Book[] GetAllBooks()
{
  List<Book> books = new List<Book>();

  string xml = Connector.Get(ENTITY_NAME);

    XmlDocument doc = new XmlDocument();
  doc.LoadXml(xml);

  foreach (XmlNode node in doc.SelectNodes("books/book"))
  {
    books.Add(Book.FromXml(node.OuterXml));
  }

  return books.ToArray();
}

It's really that simple.  At this point we have a simple array of Book instances passed from our service to our desktop client so we can do whatever we'd like with them (I'm just displaying them).

Up next: Using POST to add a new entity

Friday, February 05, 2010 4:51:01 PM (Central Standard Time, UTC-06:00)  #     | 

I've spent a bit of time lately adding HttpHandler support to our Padarn Web Server for Windows CE, and today I just wrapped up the code for a pretty in-depth example for using it to host RESTful Web Services.  I'm going to give some highlights on how it works here in my blog as well, because while it's remarkably easy to get working, there's still a lot going on.

Background

The general idea is to have a database on a Windows CE device and a client application on the desktop that could access that database via a Web Service hosted on the device.  I want to be able to do all of the CRUD operations through the service, and nicely these to the HTTP methods:

POST - Create a new entity in the database
PUT - Update an existing entity in the database
GET - Read an entity (or list of entities) from the database
DELETE - Delete an entity from the database

To make things simple, I created a very simple database that contains only one table.  The simple data model isn't real-world, but if you can make it work for one table, making it work for your entire database is really just an extension of the code base.

Setting Up Padarn

I'm going to use custom HttpHandlers to act as the service entry points.  HttpHandlers in Padarn look and work just like they do under IIS, the only difference is how they get "installed:. For Padarn, the handlers are configured, like everything else, in Padarn's configuration file.  To make my life simpler, and the code easier to read, I'll create a separate handler for each separate HTTP method, so one for GET, one for POST and so on.  This is how they get registered with the server:

<httpHandlers>
  <assembly>SampleSite.dll</assembly>
  <add verb="GET" path="/*" type="SampleSite.Handlers.GetHandler, SampleSite"/>
  <add verb="PUT" path="/*" type="SampleSite.Handlers.PutHandler, SampleSite"/>
  <add verb="POST" path="/*" type="SampleSite.Handlers.PostHandler, SampleSite"/>
  <add verb="DELETE" path="/*" type="SampleSite.Handlers.DeleteHandler, SampleSite"/>
</httpHandlers>

Pretty simple. the "add" nodes simply say what method/verb in any given server path maps to a given class.  Padarn uses regex to parse the path, so the first add line basically says "for GET methods to any path on the server, call into an instance of a GetHandler class".  Since the GetHandler is in a separate assembly from my hosting executable, Padarn needs to know about that assembly so it can load it at run time.  The assembly node simply tells Padarn to load up that assembly before it tries creating any custom handler class instances.

Once this is configured, the only thing left to do is to implement the handlers.  An HttpHandler is really simple - it contains a single overriden method that gets called when a page is requested.  Here's what the GetHandler stub looks like:

namespace SampleSite.Handlers
{
  public class GetHandler : BaseHandler
  {
    public override void ProcessRequest(HttpContext context)
    {
      // do stuff here
    }
  }
}

I get in an HttpContext, which has both the HttpRequest and HttpResponse objects. Note how we're trying very hard to mirror the object model Microsoft uses to make the learning curve much easier and to make your code more portable.  The HttpRequest contains, among other things, the incoming path and data.  The HttpResponse is where we write back out our data. 

SImple enough so far, right?  Next up: getting data from our RESTful service.
 

Friday, February 05, 2010 4:18:58 PM (Central Standard Time, UTC-06:00)  #     | 
# Wednesday, July 01, 2009

It's now easier than ever to evaluate Padarn, our ASP.NET Web Server for Windows CE.  We now have available an Evaluation Kit that comes with:

  • A 600MHz fanless Windows CE 6.0 device
  • 13 hands-on labs with full source code
  • A full sample Padarn web site with source code
  • Fully-functional Padarn evaluation binaries

The kit is being offered at an introductory price of $300.00, and if that isn't enough to convince you, we'll even credit that against any purchase of Padarn you make.

For more information, see the Padarn web site.

Wednesday, July 01, 2009 3:06:15 PM (Central Daylight Time, UTC-05:00)  #     | 
# Monday, June 29, 2009

The latest version of our Padarn Mobile Server supports VirtualPathProviders.  This means that now it is easy to create REST Web Services that run on your Windows CE or Windows Mobile device.  Download the latest hands-on lab "HOL P303 - Using VirtualPathProviders in Padarn to provide REST Web Services" from the web site here.

Monday, June 29, 2009 12:31:39 PM (Central Daylight Time, UTC-05:00)  #     | 
# Wednesday, May 13, 2009

We've been doing a ton of internal work lately on our Padarn ASP.NET Web Server for Windows CE - both on features as well as just the general stuff you have to do to have a product.  Part of this work was to create a series of hands-on labs to demonstrate how to use Padarn effectively.  The PDFs (a dozen in all so far), along with the latest Developer's Guide are available for public viewing on the Padarn Downloads page.

Wednesday, May 13, 2009 6:47:53 PM (Central Daylight Time, UTC-05:00)  #     | 
# Thursday, May 29, 2008

We're just about to release a new version of Padarn, out ASP.NET Web Server for Windows CE.  This version brings SSL support as well as Basic and Digest authentication.  Another part of this release was trying to keep the footprint reasonably small.  Here's a screen shot of all of the assemblies needed for the entire engine implementation:

padarnfootprint.PNG

So yes, we have an ASP.NET web server with SSL and authentication support and it's just 305KB - and half of that is for SSL alone.

 

Thursday, May 29, 2008 11:26:56 AM (Central Daylight Time, UTC-05:00)  #     | 
# Monday, January 21, 2008
A customer asked us to integrate a new camera with Padarn recently (the D-Link DCS-900) to try to do a similar thing that I had done in my PTZ camera demo.  Well this camera was a little different and a whole lot easier to get "streaming" data from.  I ended up writing a small wrapper class that takes the MJPG data coming from the camera, parses it into in-memory Image classes, and then those are available for use.

Once I had that I figured it would be interesting to serve up a Padarn page that did nothing but return the latest frame data from that camera - after all the camera doesn't support PTZ and just a button that takes a picture didn't seem terribly new or informative. 

The problem was that the version of Padarn I was using (1.0.5020) didn't support writing a stream of bytes to the Response.  Well as of 1.0.5030 Padarn now supports WriteBytes (and a few other things like CacheBehavior) and I created a page that dynamically loads the images into an on-page IFrame and allows you to adjust the refresh rate dynamically without ever having to send a full page request in again.

I can see that this could be useful for dynamic updates to a page for something like a control system gauge or for animating building automation status items.

Check out the new sample here.

The code for the DCS-900 looks like this (notice that the ICamera interface changed a little, so the PTZ camera also had to be altered.  I simply stubbed out the new methods).

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
using OpenNETCF.Peripherals.Camera;

namespace OpenNETCF.Peripherals
{
  public class DCS900 : ICamera
  {
    private Image m_lastImage = null;
    private volatile bool m_stopThread = true;
    Thread m_grabberThread;
    private IPAddress m_ip;

    public DCS900()
    {
    }

    public void Initialize(IPAddress ipAddress, string userName, string password)
    {
        m_ip = ipAddress;
    }

    public bool SupportsPanTilt
    {
        get { return false; }
    }

    private int FindFrameBoundary(byte[] data, int offset, int maxLength)
    {
        byte[] frameDelimiter = Encoding.ASCII.GetBytes("--video boundary--");
        int n = 0;
        bool match;

        for (; offset < maxLength; offset++)
        {
            match = true;
            if (data[offset] == frameDelimiter[n])
            {
                match &= true;
                n++;
                if (n >= frameDelimiter.Length)
                {
                    // we've found the header
                    return offset + 1;
                }
            }
            else
            {
                match = false;
                n = 0;
            }
        }

        return -1;
    }

    private Image ImageFromFrameData(byte[] data, int frameLength)
    {
        int start = 50;

        // find the data start - it will be between 50 and 54 bytes in from the frame start
        while (data[start] != 0xFF)
        {
            start++;
            if (start > 54) return null;
            if (data[start + 1] == 0xD9) break;
        }

        try
        {
            using (MemoryStream stream = new MemoryStream(data, start, frameLength - start))
            {
                Image image = new Bitmap(stream);
                stream.Close();
                return image;
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }

        return null;
    }

    public void Start()
    {
        m_grabberThread = new Thread(GrabberThreadProc);
        m_grabberThread.IsBackground = true;
        m_grabberThread.Start();
    }

    public void Stop()
    {
        m_stopThread = true;
    }

    public bool IsRunning
    {
        get { return !m_stopThread; }
    }

    private void GrabberThreadProc()
    {
        lock (m_grabberThread)
        {
            m_stopThread = false;

            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s.Connect(new IPEndPoint(m_ip, 80));

            string header = "GET /VIDEO.CGI HTTP/1.0\r\nUser-Agent: user\r\nAuthorization: Basic YWRtaW46REVVU1Q=\r\n\r\n";
            byte[] data = Encoding.ASCII.GetBytes(header);
            byte[] image = new byte[32768]; // 32k buffer is more than adequate for this camera

            s.Send(data);

            data = new byte[2048];

            int offsetStart = 0;
            int offsetEnd = 0;
            int ptr = 0;

            int length = s.Receive(data);

            do
            {
                offsetStart = FindFrameBoundary(data, 0, length);
            } while (offsetStart < 0);

            while (!m_stopThread)
            {
                offsetEnd = FindFrameBoundary(data, offsetStart, length);

                while (offsetEnd < 0)
                {
                    int copyLength = length - offsetStart;
                    Buffer.BlockCopy(data, offsetStart, image, ptr, copyLength);
                    offsetStart = 0;
                    ptr += copyLength;

                    length = s.Receive(data);
                    offsetEnd = FindFrameBoundary(data, offsetStart, length);
                }

                if (ptr > 50)
                {
                    Buffer.BlockCopy(data, offsetStart, image, ptr, offsetEnd - 18);
                    ptr += offsetEnd - 18;

                    m_lastImage = ImageFromFrameData(image, ptr);

                }
                offsetStart = offsetEnd;
                ptr = 0;

                Thread.Sleep(200);
            }

            s.Close();
        }
    }

    public Image GetImage()
    {
        return m_lastImage;
    }

    public void Pan(PanDirection direction)
    {
        throw new NotSupportedException();
    }

    public void Tilt(TiltDirection direction)
    {
        throw new NotSupportedException();
    }
  }
}


Monday, January 21, 2008 6:56:46 PM (Central Standard Time, UTC-06:00)  #     | 
# Thursday, December 13, 2007
Today we rolled out an update to Padarn: version 1.0.5010.

"So what's new," you ask? 

  1. We added support for the Page.Request.Browser property.  On the surface it seemed quite simple, but the implementation was actually quite a challenge.
  2. We fixed a bug that Page.Request.Headers always came back null
  3. We updated the SampleSite demo including:
    1. Updates and additions to the OpenNETCF.Web.Html namespace
    2. A new Camera Demo page that controls a camera in our "server closet"
    3. A page showing hosting the WMP control service media off of Padarn
    4. A page that shows client browser capability detection
The docs and live page are updated - you can reach them both from here:  www.opennetcf.com/padarn.ocf


We are also now offering Padarn free of charge for academic use.  Contact us for details.

Thursday, December 13, 2007 6:26:16 PM (Central Standard Time, UTC-06:00)  #     |