Subsonic doesn't properly send 416 response on range request

Third-party modifications and add-ons, Apps and Clients

Moderator: moderators

Subsonic doesn't properly send 416 response on range request

Postby mike.ihde » Sun Jun 05, 2011 8:13 pm

I've been building a roku frontend for Subsonic, the source code is here

https://github.com/maihde/roku_subsonic

Since the roku only support WMA and MP3 audio, I transcode m4a files, but the roku audio player would only play 10-15 seconds of audio before skipping to the next song.

After poking around, this Roku forum thread put me on the right path

http://forums.roku.com/viewtopic.php?f= ... 353162f4a8

Essentially, if the roku doesn't receive a content-length it will keep pulling from the URL until it receives a 416 response. WIth Subsonic transcoding, the entire file is transferred in the first GET and then the roku does a second GET with a range like this
Range: <end-of-file>-

As of Subsonic 4.4, instead of returning a 416 error code it will send a 0-length response. For whatever reason, ROKU interprets this to immediately stop playback of the song; but the correct behavior per HTTP/1.1 part 5 does seem to indicate that a 416 status should be returned.

The below patch appears to fix the problem for me without breaking anything else.


Code: Select all
diff -ur release-4.4/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java release-4.4-patched/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java
--- release-4.4/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java   2011-02-06 03:43:41.000000000 -0500
+++ release-4.4-patched/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java   2011-06-05 15:36:59.273570620 -0400
@@ -202,6 +202,15 @@
                     int n = in.read(buf);
                     if (n == -1) {
                         if (isPodcast || isSingleFile) {
+             // If the range request was not satisfied return 416
+             if ((range != null) && (out instanceof RangeOutputStream)) {
+            if (!((RangeOutputStream) out).isSatisfied()) {
+                LOG.info("Range request not satisifed: " + range);
+                response.setStatus(416);
+            } else {
+                LOG.info("Range request satisifed: " + range);
+            }
+             }
                             break;
                         } else {
                             sendDummy(buf, out);
diff -ur release-4.4/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java release-4.4-patched/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java
--- release-4.4/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java   2011-02-06 03:43:41.000000000 -0500
+++ release-4.4-patched/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java   2011-06-05 15:58:12.613549299 -0400
@@ -48,6 +48,12 @@
     protected long pos;

     /**
+     * Range satisfied.
+     * true if the start of the range was reached
+     */
+    protected boolean satisfied;
+
+    /**
      * Wraps the given output stream in a RangeOutputStream, using the values
      * in the given range, unless the range is <code>null</code> in which case
      * the original OutputStream is returned.
@@ -75,6 +81,7 @@
         this.start = start;
         this.end = end;
         pos = 0;
+   satisfied = false;
     }

     /**
@@ -87,6 +94,7 @@
     @Override
     public void write(int b) throws IOException {
         if ((pos >= start) && (pos <= end)) {
+       satisfied = true;
             super.write(b);
         }
         pos++;
@@ -139,12 +147,17 @@
         }

         // If we have enabled writing, do the write!
-        if (allowWrite) {
+        if ((allowWrite) && (newLen > 0)) {
+       satisfied = true;
             out.write(b, (int) newOff, (int) newLen);
         }

         // Move the cursor along
         pos += off + len;
     }
+
+    public boolean isSatisfied() {
+   return satisfied;
+    }
}

mike.ihde
 
Posts: 2
Joined: Sun Jun 05, 2011 8:02 pm

Return to Mods, Apps and Clients

Who is online

Users browsing this forum: No registered users and 14 guests