- line <- recv_line h
-
- if (xml_prologue `isPrefixOf` line && not (null buffer))
- then do
- -- This is the beginning of a new document, and we have an "old"
- -- one to save. The buffer is in reverse (newest first) order,
- -- though, so we have to reverse it first. We then concatenate all
- -- of its lines into one big string.
- let document = concat $ reverse buffer
- save_document cfg document
- loop cfg h [line] -- empty the buffer before looping again
- else
- loop cfg h (line : buffer) -- append line to the head of the buffer and loop
-
-
+ line' <- timeout fifteen_minutes $ recv_line h
+ case line' of
+ -- If we haven't received anything in fifteen minutes, return back
+ -- to the calling function. This should only happen in the case of
+ -- an error, and our caller should be prepared to handle it.
+ Nothing -> report_warning "No data received for 15 minutes."
+
+ Just line -> do
+ -- If the recv didn't timeout, proceed normally.
+ let new_buffer = line : buffer
+
+ -- Use isPrefixOf to avoid line-ending issues. Hopefully they won't
+ -- send invalid junk (on the same line) after closing the root
+ -- element.
+ if "</message>" `isPrefixOf` line
+ then do
+ -- The buffer is in reverse (newest first) order, though, so we
+ -- have to reverse it first. We then concatenate all of its lines
+ -- into one big string.
+ let document = concat $ reverse new_buffer
+ save_document cfg document
+ loop cfg h [] -- Empty the buffer before looping again.
+ else
+ -- Append line to the head of the buffer and loop.
+ loop cfg h new_buffer
+ where
+ fifteen_minutes :: Int
+ fifteen_minutes = 15 * 60 * 1000000
+
+
+-- | Once we're connected to a feed, we need to log in. There's no
+-- protocol for this (the docs don't mention one), but we have
+-- (apparently) successfully guessed it.
+--
+-- The first thing TSN sends once we've connected is the string
+-- \"Username: \", containing 10 ASCII characters. We then send a
+-- username, followed by a newline. If TSN likes the username, the
+-- second they'll send is the string \"Password: \", also containing
+-- 10 ASCII characters, to which we reply in kind.
+--
+-- Assuming the above will always hold, it is implemented as follows:
+--
+-- 1. Receive 10 chars
+--
+-- 2. Send username if we got the username prompt
+--
+-- 3. Receive 10 chars
+--
+-- 4. Send password if we got the password prompt
+--
+-- If TSN likes the password as well, they send the string \"The
+-- Sports Network\" before finally beginning to stream the feed.
+--