/* * Copyright (C) 2014 Michell Bak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.miz.smbstreamer; import android.util.Log; import com.miz.utils.NetworkUtils; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Properties; import jcifs.smb.SmbFile; import static com.miz.smbstreamer.Response.HTTP_FORBIDDEN; import static com.miz.smbstreamer.Response.HTTP_NOTFOUND; import static com.miz.smbstreamer.Response.HTTP_OK; import static com.miz.smbstreamer.Response.HTTP_PARTIALCONTENT; import static com.miz.smbstreamer.Response.HTTP_RANGE_NOT_SATISFIABLE; public class Streamer extends StreamServer { public static final int PORT = 50002; private String mUrl = "http://127.0.0.1:" + PORT; private SmbFile mFile; private List<SmbFile> mExtras; // subtitles, etc. private static Streamer sInstance; protected Streamer(int port) throws IOException { super(port, new File(".")); mUrl = "http://" + NetworkUtils.getIPAddress(true) + ":" + PORT; } public String getUrl() { return mUrl; } public static Streamer getInstance() { if (sInstance == null) try { sInstance = new Streamer(PORT); } catch (IOException e) { e.printStackTrace(); } return sInstance; } public void setStreamSrc(SmbFile file,List<SmbFile> extraFiles) { mFile = file; mExtras = extraFiles; } @Override public Response serve(String uri, String method, Properties header, Properties parms, Properties files) { Response res = null; try { SmbFile sourceFile = null; String name = getNameFromPath(uri); if (mFile != null && mFile.getName().equals(name)) sourceFile = mFile; else if (mExtras != null){ for (SmbFile i : mExtras){ if (i != null && i.getName().equals(name)){ sourceFile = i; break; } } } if (sourceFile == null) res = new Response(HTTP_NOTFOUND, MIME_PLAINTEXT, null); else { long startFrom = 0; long endAt = -1; String range = header.getProperty("range"); if (range != null) { if (range.startsWith("bytes=")) { range = range.substring("bytes=".length()); int minus = range.indexOf('-'); try { if (minus > 0) { startFrom = Long.parseLong(range.substring(0, minus)); endAt = Long.parseLong(range.substring(minus + 1)); } } catch (NumberFormatException nfe) {} } } Log.d("Streamer", "Request: " + range + " from: " + startFrom + ", to: " + endAt); // Change return code and add Content-Range header when skipping is requested final StreamSource source = new StreamSource(sourceFile); long fileLen = source.length(); if (range != null && startFrom > 0) { if (startFrom >= fileLen) { res = new Response(HTTP_RANGE_NOT_SATISFIABLE, MIME_PLAINTEXT, null); res.addHeader("Content-Range", "bytes 0-0/" + fileLen); } else { if (endAt < 0) endAt = fileLen - 1; long newLen = fileLen - startFrom; if (newLen < 0) newLen = 0; Log.d("Streamer", "start=" + startFrom + ", endAt=" + endAt + ", newLen=" + newLen); final long dataLen = newLen; source.moveTo(startFrom); Log.d("Streamer", "Skipped " + startFrom + " bytes"); res = new Response(HTTP_PARTIALCONTENT, source.getMimeType(), source); res.addHeader("Content-length", "" + dataLen); res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen); } } else { source.reset(); res = new Response(HTTP_OK, source.getMimeType(), source); res.addHeader("Content-Length", "" + fileLen); } } } catch (IOException ioe) { res = new Response(HTTP_FORBIDDEN, MIME_PLAINTEXT, null); } // Announce that the file server accepts partial content requestes res.addHeader("Accept-Ranges", "bytes"); return res; } public static String getNameFromPath(String path) { if (path == null || path.length() < 2) return null; int slash = path.lastIndexOf('/'); if (slash == -1) return path; return path.substring(slash+1); } }