Skip to content

Commit

Permalink
- vcb protocol intercepted and licence is made to work only when a vi…
Browse files Browse the repository at this point in the history
…deo is clicked or downloaded.
  • Loading branch information
hishamMuneer committed Oct 4, 2018
1 parent 410bf52 commit 239e726
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.google.android.exoplayer2.upstream.DefaultDataSource;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.vocab.CredUpdateSingleton;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
Expand Down Expand Up @@ -134,6 +135,7 @@ private void onSampleGroups(final List<SampleGroup> groups, boolean sawError) {
@Override
public boolean onChildClick(
ExpandableListView parent, View view, int groupPosition, int childPosition, long id) {
CredUpdateSingleton.getInstance().setVideoId("5");
Sample sample = (Sample) view.getTag();
startActivity(sample.buildIntent(this));
return true;
Expand Down Expand Up @@ -424,6 +426,7 @@ public boolean isChildSelectable(int groupPosition, int childPosition) {

@Override
public void onClick(View view) {
CredUpdateSingleton.getInstance().setVideoId("5");
onSampleDownloadButtonClicked((Sample) view.getTag());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,38 @@
public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
implements Downloader {

private VocaDataSourceHelper.LicenceModel licenceModel;
private Thread currentThread;
// A network thread to get the details of licence file
Thread lecenceThread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Network API Hit
LicenceObtainer licenceObtainer = new LicenceObtainer(800, new LicenceObtainer.ILicenceData() {
@Override
public void onLicenceReceived(VocaDataSourceHelper.LicenceModel model) {
// TODO Handle licence model and get the key_path from the same.
licenceModel = model;
try{
synchronized (currentThread) {
currentThread.notify();
}
}
catch (Exception e)
{
e.printStackTrace();
}
// notifyAll();
}
});

try {
licenceObtainer.getLicence();
} catch (IOException e) {
e.printStackTrace();
}
}
});
// private VocaDataSourceHelper.LicenceModel licenceModel;
// private Thread currentThread;
// // A network thread to get the details of licence file
// Thread lecenceThread = new Thread(new Runnable() {
// @Override
// public void run() {
//// TODO Network API Hit
// LicenceObtainer licenceObtainer = new LicenceObtainer(800, new LicenceObtainer.ILicenceData() {
// @Override
// public void onLicenceReceived(VocaDataSourceHelper.LicenceModel model) {
// // TODO Handle licence model and get the key_path from the same.
// licenceModel = model;
// try{
// synchronized (currentThread) {
// currentThread.notify();
// }
// }
// catch (Exception e)
// {
// e.printStackTrace();
// }
//// notifyAll();
// }
// });
//
// try {
// licenceObtainer.getLicence();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// });


/** Smallest unit of content to be downloaded. */
Expand Down Expand Up @@ -258,28 +258,28 @@ private List<Segment> initDownload() throws IOException, InterruptedException {
// DataSource source = DataSource.Factory.createDataSource();

// TODO Get the licence details via network API
currentThread = Thread.currentThread();
lecenceThread.start();
synchronized (currentThread) {
currentThread.wait();
}
// currentThread = Thread.currentThread();
// lecenceThread.start();
// synchronized (currentThread) {
// currentThread.wait();
// }

// String licenceJson = "{ \"key_path\": \"https://vocatest-a40ab.firebaseapp.com/small_files/enc.key\" }";

VocaDataSourceHelper.LicenceModel model = licenceModel;

Segment segLicence = new Segment(0, new DataSpec(Uri.parse(model.getPath())));

ListIterator<Segment> segmentListIterator = segments.listIterator();
while (segmentListIterator.hasNext()){
Segment segment = segmentListIterator.next();
if(segment.dataSpec.uri.toString().contains("custom://") || segment.dataSpec.uri.toString().contains(".key")){
segmentListIterator.remove();
break;
}
}

segments.add(0, segLicence); // add licence to front
// VocaDataSourceHelper.LicenceModel model = licenceModel;

// Segment segLicence = new Segment(0, new DataSpec(Uri.parse(model.getPath())));
//
// ListIterator<Segment> segmentListIterator = segments.listIterator();
// while (segmentListIterator.hasNext()){
// Segment segment = segmentListIterator.next();
// if(segment.dataSpec.uri.toString().contains("custom://") || segment.dataSpec.uri.toString().contains(".key")){
// segmentListIterator.remove();
// break;
// }
// }
//
// segments.add(0, segLicence); // add licence to front

/**
* Changes end here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,22 @@
import android.util.Log;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.vocabimate_stream.AesEncryptionUtil;
import com.google.android.exoplayer2.upstream.vocabimate_stream.VocaDataSourceHelper;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Predicate;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.vocab.CredUpdateSingleton;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.NoRouteToHostException;
import java.net.ProtocolException;
import java.net.URL;
Expand Down Expand Up @@ -185,12 +191,12 @@ public void clearAllRequestProperties() {
}

@Override
public long open(DataSpec dataSpec) throws HttpDataSourceException {
public long open(DataSpec dataSpec) throws HttpDataSourceException { // Note: This method is not called in offline case. -Hisham
this.dataSpec = dataSpec;
this.bytesRead = 0;
this.bytesSkipped = 0;
try {
connection = makeConnection(dataSpec); // hisham - 3 it calls for m3u8 hit
connection = makeConnection(dataSpec);
} catch (IOException e) {
throw new HttpDataSourceException("Unable to connect to " + dataSpec.uri.toString(), e,
dataSpec, HttpDataSourceException.TYPE_OPEN);
Expand All @@ -205,14 +211,6 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException {
dataSpec, HttpDataSourceException.TYPE_OPEN);
}

if(responseCode == 500 || responseCode == 404) { // for custom server hisham
try {
connection = makeConnectionCustom(dataSpec);
} catch (IOException e) {
e.printStackTrace();
}
} else

// Check for a valid response code.
if (responseCode < 200 || responseCode > 299) {
Map<String, List<String>> headers = connection.getHeaderFields();
Expand Down Expand Up @@ -276,29 +274,91 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException {
*/
private HttpURLConnection makeConnectionCustom(DataSpec dataSpec) throws IOException {

String licenceUrl = "https://vocatest-a40ab.firebaseapp.com/license_key_path_absolute.json";
String videoId = CredUpdateSingleton.getInstance().getVideoIdAndResetIt();
if(videoId == null){
throw new NullPointerException("Video id is not set, call: CredUpdateSingleton.getInstance().setVideoId(int);");
}

URL keyUrl = null;

String licenceUrl = "https://voca2hosting.firebaseapp.com/small_files/license_key_path_absolute.json";
URL url = new URL(licenceUrl);

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(connectTimeoutMillis);
connection.setReadTimeout(readTimeoutMillis);
if (defaultRequestProperties != null) {
for (Map.Entry<String, String> property : defaultRequestProperties.getSnapshot().entrySet()) {
connection.setRequestProperty(property.getKey(), property.getValue());
// parse licence
HttpURLConnection httpURLConnection = null;
try {
httpURLConnection = (HttpURLConnection) url
.openConnection();

InputStream in = httpURLConnection.getInputStream();
String result = readStream(in);
VocaDataSourceHelper.LicenceModel licenceModel = new Gson().fromJson(result, VocaDataSourceHelper.LicenceModel.class);
if(licenceModel != null){
keyUrl = new URL(licenceModel.getPath());
}

/*InputStreamReader isw = new InputStreamReader(in);
int data = isw.read();
while (data != -1) {
char current = (char) data;
data = isw.read();
System.out.print(current);
}*/
} catch (Exception e) {
e.printStackTrace();
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
for (Map.Entry<String, String> property : requestProperties.getSnapshot().entrySet()) {
connection.setRequestProperty(property.getKey(), property.getValue());
}
connection.setRequestProperty("User-Agent", userAgent);
connection.setRequestMethod("GET");

HttpURLConnection connection = null;
if (keyUrl != null) {
connection = (HttpURLConnection) keyUrl.openConnection();
connection.setConnectTimeout(connectTimeoutMillis);
connection.setReadTimeout(readTimeoutMillis);
if (defaultRequestProperties != null) {
for (Map.Entry<String, String> property : defaultRequestProperties.getSnapshot()
.entrySet()) {
connection.setRequestProperty(property.getKey(), property.getValue());
}
}
for (Map.Entry<String, String> property : requestProperties.getSnapshot().entrySet()) {
connection.setRequestProperty(property.getKey(), property.getValue());
}
connection.setRequestProperty("User-Agent", userAgent);
connection.setRequestMethod("GET");
// if(!TextUtils.isEmpty(TokenManager.getToken())) {
// connection.setRequestProperty("token", TokenManager.getToken());
// }
Log.d(TAG, "hisham: " + connection.getResponseCode());
Log.d(TAG, "hisham: " + connection.getResponseCode());
}
return connection;
}

private String readStream(InputStream in) {
BufferedReader reader = null;
StringBuffer response = new StringBuffer();
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return response.toString();
}


@Override
public int read(byte[] buffer, int offset, int readLength) throws HttpDataSourceException {
Expand Down Expand Up @@ -378,7 +438,15 @@ protected final long bytesRemaining() {
* Establishes a connection, following redirects to do so where permitted.
*/
private HttpURLConnection makeConnection(DataSpec dataSpec) throws IOException {
URL url = new URL(dataSpec.uri.toString());
URL url = null;
try {
url = new URL(dataSpec.uri.toString());
} catch (MalformedURLException e) {
if (e.getMessage().contains("vcb")) {
connection = makeConnectionCustom(dataSpec);
return connection;
}
}
byte[] postBody = dataSpec.postBody;
long position = dataSpec.position;
long length = dataSpec.length;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.google.android.exoplayer2.vocab;

/**
* Created by Hisham on 04/Oct/2018 - 17:51
*/
public class CredUpdateSingleton {

private CredUpdateSingleton() {
}

private static final CredUpdateSingleton ourInstance = new CredUpdateSingleton();

private String token;
private String videoId;
private String licecnceUrl;

public static CredUpdateSingleton getInstance() {
return ourInstance;
}


public String getToken() {
return token;
}

public CredUpdateSingleton setToken(String token) {
this.token = token;
return this;
}

public String getVideoIdAndResetIt() {
String temp = videoId;
videoId = null;
return temp;
}

public CredUpdateSingleton setVideoId(String videoId) {
this.videoId = videoId;
return this;
}

public String getLicecnceUrl() {
return licecnceUrl;
}

public CredUpdateSingleton setLicecnceUrl(String licecnceUrl) {
this.licecnceUrl = licecnceUrl;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,9 @@ private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String
encryptionKeyUri = parseStringAttr(line, REGEX_URI); // hisham - reading the key line in m3u8
//28-09-2018 for custom offline play back
//it will change in future
if(encryptionKeyUri.contains("vcb://")){
encryptionKeyUri = encryptionKeyUri.replace("vcb://vocatest-a40ab.firebaseapp.com","https://voca2hosting.firebaseapp.com");
}
// if(encryptionKeyUri.contains("vcb://")){
// encryptionKeyUri = encryptionKeyUri.replace("vcb://vocatest-a40ab.firebaseapp.com","https://voca2hosting.firebaseapp.com");
// }
} else {
// Do nothing. Samples are encrypted using an identity key, but this is not supported.
// Hopefully, a traditional DRM alternative is also provided.
Expand Down

0 comments on commit 239e726

Please sign in to comment.