package com.hls.encryption;

import com.wowza.util.*;
import com.wowza.wms.http.*;
import com.wowza.wms.httpstreamer.cupertinostreaming.httpstreamer.*;
import com.wowza.wms.module.*;
import com.wowza.wms.application.*;

public class HLSEncryption extends ModuleBase {
	/**
	 * Controls access to the encryption key.
	 * <p>
	 * Gives or denies access to an HLS streaming session encryption key.
	 * <p>
	 * 
	 * @param httpCupertinoStreamingSession the HLS streaming session
	 * @param req the request for the encryption key
	 * @param resp the response
	 */
	public void onHTTPCupertinoEncryptionKeyRequest(
			HTTPStreamerSessionCupertino httpCupertinoStreamingSession,
			IHTTPRequest req, IHTTPResponse resp) {
		boolean isGood = true;

		// These properties could be used to control access to the encryption
		// key
		// String queryStr = req.getQueryString();
		// String ipAddress = httpCupertinoStreamingSession.getIpAddress();
		// String referrer = httpCupertinoStreamingSession.getReferrer();
		// String cookieStr = httpCupertinoStreamingSession.getCookieStr();
		// String userAgent = httpCupertinoStreamingSession.getUserAgent();
		// String sessionId = httpCupertinoStreamingSession.getSessionId();
		// String streamName = httpCupertinoStreamingSession.getStreamName();

		// reject encryption key requests that are not delivered over SSL
		// if (!req.isSecure())
		// isGood = false;

		IApplicationInstance appInstance = httpCupertinoStreamingSession
				.getAppInstance();
		getLogger().info("HLSEncryption.onHTTPCupertinoEncryptionKeyRequest["
				+ appInstance.getContextStr() + "/"
				+ httpCupertinoStreamingSession.getStreamName() + "]: accept:"
				+ isGood);

		if (!isGood)
			httpCupertinoStreamingSession.rejectSession();
	}

	/**
	 * Controls access to the encryption key data.
	 * 
	 * @param httpCupertinoStreamingSession the HLS streaming session
	 * @param req the request for the encryption key
	 * @param resp the response
	 * @param encKeyData the encrypted key data
	 */
	public void onHTTPCupertinoEncryptionKeyData(
			HTTPStreamerSessionCupertino httpCupertinoStreamingSession,
			IHTTPRequest req, IHTTPResponse resp, byte[] encKeyData) {
		// Look at the key data, change or output something else for the request
		// via the resp object
	}

	/**
	 * Control the key for encryption for each live HLS playback session.
	 * 
	 * @param appInstance the application instance
	 * @param streamName the stream name
	 * @param encKey the encryption key
	 */
	public void onHTTPCupertinoEncryptionKeyCreateLive(
			IApplicationInstance appInstance, String streamName,
			byte[] encKey) {
		String mySharedSecret = appInstance.getProperties()
				.getPropertyStr("cupertinoEncryptionSharedSecret", "");

		String hashStr = mySharedSecret + ":"
				+ appInstance.getApplication().getName() + ":"
				+ appInstance.getName() + ":" + streamName;

		byte[] tmpBytes = MD5DigestUtils.generateHashBytes(hashStr);
		if (tmpBytes != null)
			System.arraycopy(tmpBytes, 0, encKey, 0, encKey.length);

		getLogger().info("HLSEncryption.onHTTPCupertinoEncryptionKeyCreateLive["
				+ appInstance.getContextStr() + "/" + streamName + "]: *"
				+ BufferUtils.encodeHexString(encKey).substring(28));
	}

	/**
	 * Generates an encryption key for each on demand HLS playback session.
	 * <p>
	 * The encryption key is generated based on a shared secret, the session ID,
	 * and the stream's context path.
	 * <p>
	 * 
	 * @param httpCupertinoStreamingSession the streaming session
	 * @param encKey the encryption key
	 */
	public void onHTTPCupertinoEncryptionKeyCreateVOD(
			HTTPStreamerSessionCupertino httpCupertinoStreamingSession,
			byte[] encKey) {
		IApplicationInstance appInstance = httpCupertinoStreamingSession
				.getAppInstance();
		String sessionId = httpCupertinoStreamingSession.getSessionId();

		String mySharedSecret = appInstance.getProperties()
				.getPropertyStr("cupertinoEncryptionSharedSecret", "");

		String hashStr = mySharedSecret + ":"
				+ (httpCupertinoStreamingSession.isHTTPOrigin() ? ""
						: sessionId + ":")
				+ appInstance.getApplication().getName() + ":"
				+ appInstance.getName() + ":"
				+ httpCupertinoStreamingSession.getStreamName();

		byte[] tmpBytes = MD5DigestUtils.generateHashBytes(hashStr);
		if (tmpBytes != null)
			System.arraycopy(tmpBytes, 0, encKey, 0, encKey.length);

		getLogger().info("HLSEncryption.onHTTPCupertinoEncryptionKeyCreateVOD["
				+ appInstance.getContextStr() + "/"
				+ httpCupertinoStreamingSession.getStreamName() + "]: *"
				+ BufferUtils.encodeHexString(encKey).substring(28));
	}
}