├── .gitignore ├── .travis.yml ├── 3rdparty-wms-modules ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── wowza │ │ └── wms │ │ └── plugin │ │ └── collection │ │ ├── module │ │ ├── ModuleCalculateBitRate.java │ │ ├── ModuleCreateSnapshot.java │ │ ├── ModuleFCSubscribe.java │ │ ├── ModuleGetConnectionCount.java │ │ ├── ModuleHotlinkDenial.java │ │ ├── ModuleLimitConnectionsToApplication.java │ │ ├── ModuleLimitPublishedStreamBandwidth.java │ │ ├── ModuleLimitStreamViewers.java │ │ ├── ModuleLoadBalancerEdgeLimitConnections.java~ │ │ ├── ModuleLogViewerCounts.java │ │ ├── ModuleNoDuplicatePublishStreamname.java │ │ ├── ModuleOnConnectAuthenticate.java │ │ ├── ModuleOnConnectAuthenticate2.java │ │ ├── ModuleRequireSecureConnection.java │ │ ├── ModuleStreamControl.java │ │ ├── ModuleStreamWatchDog.java │ │ ├── ModuleVideoNameList.java │ │ └── ModuleWriteListener.java │ │ └── serverlistener │ │ └── ServerListenerStreamPublisher.java │ └── resources │ ├── log4j.properties │ ├── logback.xml │ └── web.xml ├── README.md ├── build.gradle ├── gradle.properties ├── settings.gradle ├── vpmedia-wms-app ├── build.gradle └── src │ └── main │ ├── java │ └── hu │ │ └── vpmedia │ │ └── media │ │ ├── core │ │ ├── RoomTypes.java │ │ └── UserTypes.java │ │ └── wms │ │ └── dev │ │ └── WebcamDev.java │ └── resources │ └── Application.xml ├── vpmedia-wms-bwcheck ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── bwcheck │ └── BWCheck.java ├── vpmedia-wms-connectionlimiter ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── connectionlimiter │ └── ConnectionLimiter.java ├── vpmedia-wms-dbauthentication ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── dbauthentication │ └── DBAuthentication.java ├── vpmedia-wms-fme ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── fme │ └── FME.java ├── vpmedia-wms-hotlinkdenial ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── hotlinkdenial │ └── HotlinkDenial.java ├── vpmedia-wms-keepalive ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── keepalive │ └── KeepAlive.java ├── vpmedia-wms-medialoader ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── medialoader │ └── MediaLoader.java ├── vpmedia-wms-mediareader ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── mediareader │ └── MediaReaderFLVInjectMetadata.java ├── vpmedia-wms-mediastreampassthru ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── mediastreampassthru │ ├── MediaStreamPassThru.java │ └── MediaStreamPassThruRecord.java ├── vpmedia-wms-remoting ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── remoting │ ├── FlashRemoteMessage.java │ ├── FlashRemoteResponseReader.java │ ├── FlashRemoteSession.java │ ├── IFlashRemoteResponse.java │ └── IFlashRemotingNotify.java ├── vpmedia-wms-security ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── security │ ├── HTTPSecureTokens.java │ ├── ModuleSecureToken.java │ ├── ModuleSecureToken2.java │ ├── ModuleSecureURLParams.java │ ├── SecureToken.java │ ├── SecureTokenDef.java │ ├── SecureTokenManager.java │ ├── SecureURLParams.java │ └── encryption │ └── TEA.java ├── vpmedia-wms-snapshot ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── snapshot │ └── Snapshot.java ├── vpmedia-wms-ssl ├── build.gradle └── src │ └── main │ ├── java │ └── hu │ │ └── vpmedia │ │ └── media │ │ └── wms │ │ └── plugin │ │ └── ssl │ │ ├── SSLContextFactory.java │ │ └── TrustManagerFactory.java │ └── resources │ └── wms-ssl │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── ssl │ └── vpmedia.jks ├── vpmedia-wms-streamnamealias ├── build.gradle └── src │ └── main │ └── java │ └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── streamnamealias │ ├── ModuleStreamNameAlias.java │ ├── StreamNameAliasFile.java │ ├── StreamNameAliasFiles.java │ └── StreamNameAliasMatch.java └── vpmedia-wms-test ├── build.gradle └── src └── main ├── java └── hu │ └── vpmedia │ └── media │ └── wms │ └── plugin │ └── test │ └── ModuleRequireSecureConnection.java └── resources ├── log4j.properties ├── logback.xml ├── web.xml └── wms-test └── Application.xml /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Excludes 3 | ################# 4 | 5 | # Directories 6 | doc/ 7 | build/ 8 | bin/ 9 | bin-debug/ 10 | target/ 11 | publish/ 12 | .gradle/ 13 | .idea/ 14 | 15 | # Auto-generated Files 16 | MANIFEST.MF 17 | *.class -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License (MIT) 3 | # 4 | # Copyright 2014 Andras Csizmadia (www.vpmedia.eu) 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | # this software and associated documentation files (the "Software"), to deal in 8 | # the Software without restriction, including without limitation the rights to 9 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | # the Software, and to permit persons to whom the Software is furnished to do so, 11 | # subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | # 23 | 24 | # Purpose: Java Template for Travis-CI 25 | # Author: Andras Csizmadia (www.github.com/vpmedia) 26 | # Version: 1.0.0 27 | 28 | git: 29 | depth: 1 30 | 31 | language: java 32 | 33 | env: 34 | - TERM=dumb 35 | 36 | script: 37 | - gradle -------------------------------------------------------------------------------- /3rdparty-wms-modules/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleCalculateBitRate.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.application.*; 5 | import com.wowza.wms.client.*; 6 | import com.wowza.wms.request.*; 7 | import com.wowza.wms.stream.*; 8 | import com.wowza.wms.util.*; 9 | import com.wowza.wms.module.*; 10 | 11 | public class ModuleCalculateBitRate extends ModuleBase 12 | { 13 | public void getStreamBitrate(IClient client, RequestFunction function, AMFDataList params) 14 | { 15 | double ret = 0; 16 | String streamName = getParamString(params, PARAM1); 17 | String streamExt = MediaStream.BASE_STREAM_EXT; 18 | String queryStr = ""; 19 | 20 | String[] streamDecode = ModuleUtils.decodeStreamExtension(streamName, streamExt); 21 | streamName = streamDecode[0]; 22 | streamExt = streamDecode[1]; 23 | 24 | boolean isStreamNameURL = streamName.indexOf("://") >= 0; 25 | int streamQueryIdx = streamName.indexOf("?"); 26 | if (!isStreamNameURL && streamQueryIdx >= 0) 27 | { 28 | queryStr = streamName.substring(streamQueryIdx+1); 29 | streamName = streamName.substring(0, streamQueryIdx); 30 | } 31 | 32 | IApplicationInstance appInstance = client.getAppInstance(); 33 | String oldStreamName = null; 34 | 35 | IMediaReader mediaReader = MediaReaderFactory.getInstance(appInstance, client.getVHost().getMediaReaders(), streamExt); 36 | if (mediaReader != null) 37 | { 38 | MediaStreamMap streams = appInstance.getStreams(); 39 | IMediaStream stream = new MediaStreamDisconnected(); 40 | stream.init(streams, 0, new WMSProperties()); 41 | stream.setName(streamName, oldStreamName, streamExt, queryStr, 0, -1, 1); 42 | stream.setClient(client); 43 | 44 | String basePath = client.getAppInstance().getStreamStoragePath(); 45 | mediaReader.init(client.getAppInstance(), stream, streamExt, basePath, streamName); 46 | long lastTC = mediaReader.getDuration(); 47 | double duration = (double)lastTC/1000.0; 48 | long length = mediaReader.getLength(); 49 | if (duration != 0) 50 | ret = (((double)length*8.0)/duration); 51 | mediaReader.close(); 52 | 53 | getLogger().debug("calculateBitrate duration:"+duration+" length:"+length+" ret:"+ret); 54 | } 55 | else 56 | getLogger().warn("calculateBitrate: Could not create MediaReader for stream: "+streamName); 57 | 58 | getLogger().info("calculateBitrate ["+streamName+"] bitrate:"+ret); 59 | sendResult(client, params, ret); 60 | } 61 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleCreateSnapshot.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | import java.io.*; 3 | 4 | import com.wowza.util.*; 5 | import com.wowza.wms.module.*; 6 | import com.wowza.wms.amf.*; 7 | import com.wowza.wms.application.*; 8 | import com.wowza.wms.client.IClient; 9 | import com.wowza.wms.stream.*; 10 | import com.wowza.wms.vhost.*; 11 | import com.wowza.wms.request.*; 12 | 13 | public class ModuleCreateSnapshot extends ModuleBase 14 | { 15 | Object lock = new Object(); 16 | 17 | public void createSnapshotLive(IClient client, RequestFunction function, AMFDataList params) 18 | { 19 | String streamName = params.getString(PARAM1); 20 | 21 | String fileName = ""; 22 | IApplicationInstance appInstance = client.getAppInstance(); 23 | MediaStreamMap streams = appInstance.getStreams(); 24 | IMediaStream stream = streams.getStream(streamName); 25 | if (stream != null) 26 | { 27 | AMFPacket packet = stream.getLastKeyFrame(); 28 | if (packet != null) 29 | { 30 | fileName = streamName + "_" + packet.getAbsTimecode() + ".flv"; 31 | File newFile = stream.getStreamFileForWrite(streamName, null, null); 32 | 33 | String filePath = newFile.getPath().substring(0, newFile.getPath().length()-4) + "_" + packet.getAbsTimecode() + ".flv"; 34 | 35 | try 36 | { 37 | synchronized(lock) 38 | { 39 | BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(filePath), false)); 40 | FLVUtils.writeHeader(out, 0, null); 41 | 42 | AMFPacket codecConfig = stream.getVideoCodecConfigPacket(packet.getAbsTimecode()); 43 | if (codecConfig != null) 44 | FLVUtils.writeChunk(out, codecConfig.getDataBuffer(), codecConfig.getSize(), 0, (byte)codecConfig.getType()); 45 | 46 | FLVUtils.writeChunk(out, packet.getDataBuffer(), packet.getSize(), 0, (byte)packet.getType()); 47 | out.close(); 48 | } 49 | 50 | getLogger().info("snapshot created: "+filePath); 51 | } 52 | catch (Exception e) 53 | { 54 | getLogger().error("createSnapshot: "+e.toString()); 55 | } 56 | } 57 | } 58 | 59 | sendResult(client, params, fileName); 60 | } 61 | 62 | public void createSnapshotVOD(IClient client, RequestFunction function, AMFDataList params) 63 | { 64 | String streamName = params.getString(PARAM1); 65 | int timecode = params.getInt(PARAM2); 66 | 67 | String fileName = ""; 68 | IApplicationInstance appInstance = client.getAppInstance(); 69 | 70 | String flvFilePath = appInstance.getStreamStoragePath() + "/" + streamName + ".flv"; 71 | File flvFile = new File(flvFilePath); 72 | 73 | if (flvFile.exists()) 74 | { 75 | AMFPacket lastVideoKeyFrame = null; 76 | try 77 | { 78 | BufferedInputStream is = new BufferedInputStream(new FileInputStream(flvFile)); 79 | FLVUtils.readHeader(is); 80 | AMFPacket amfPacket; 81 | while ((amfPacket = FLVUtils.readChunk(is)) != null) 82 | { 83 | if (lastVideoKeyFrame != null && amfPacket.getTimecode() > timecode) 84 | break; 85 | if (amfPacket.getType() != IVHost.CONTENTTYPE_VIDEO) 86 | continue; 87 | if (FLVUtils.isVideoKeyFrame(amfPacket)) //if (FLVUtils.getFrameType(amfPacket.getFirstByte()) == FLVUtils.FLV_KFRAME) 88 | lastVideoKeyFrame = amfPacket; 89 | } 90 | is.close(); 91 | } 92 | catch (Exception e) 93 | { 94 | getLogger().error("Error: createSnapshotVOD: reading flv: "+e.toString()); 95 | } 96 | 97 | if (lastVideoKeyFrame != null) 98 | { 99 | try 100 | { 101 | fileName = streamName + "_" + timecode; 102 | String filePath = appInstance.getStreamStoragePath() + "/" + fileName + ".flv"; 103 | BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(filePath), false)); 104 | FLVUtils.writeHeader(out, 0, null); 105 | FLVUtils.writeChunk(out, lastVideoKeyFrame.getDataBuffer(), lastVideoKeyFrame.getSize(), 0, (byte)lastVideoKeyFrame.getType()); 106 | out.close(); 107 | 108 | getLogger().info("snapshot created: "+filePath); 109 | } 110 | catch (Exception e) 111 | { 112 | getLogger().error("Error: createSnapshotVOD: writing flv: "+e.toString()); 113 | } 114 | } 115 | } 116 | 117 | sendResult(client, params, fileName); 118 | } 119 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleFCSubscribe.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.client.*; 5 | import com.wowza.wms.request.*; 6 | import com.wowza.wms.response.*; 7 | import com.wowza.wms.module.*; 8 | import com.wowza.wms.stream.*; 9 | 10 | public class ModuleFCSubscribe extends ModuleBase 11 | { 12 | public void FCSubscribe(IClient client, RequestFunction function, AMFDataList params) 13 | { 14 | String streamName = params.getString(PARAM1); 15 | 16 | IMediaStream stream = null; 17 | if (streamName != null) 18 | stream = client.getAppInstance().getStreams().getStream(streamName); 19 | 20 | String responseCode = (stream == null)?"NetStream.Play.StreamNotFound":"NetStream.Play.Start"; 21 | 22 | AMFDataObj data = null; 23 | ResponseFunction resp = null; 24 | ResponseFunctions respFunctions = client.getRespFunctions(); 25 | double clientID = client.getClientId(); 26 | 27 | resp = new ResponseFunction(client); 28 | resp.createDefaultMessage("onFCSubscribe", 0.0); 29 | 30 | data = new AMFDataObj(); 31 | data.put("level", new AMFDataItem("status")); 32 | data.put("code", new AMFDataItem(responseCode)); 33 | data.put("clientid", new AMFDataItem((double)clientID)); 34 | resp.addBody(data); 35 | 36 | respFunctions.add(resp); 37 | } 38 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleGetConnectionCount.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import java.util.*; 4 | 5 | import com.wowza.wms.amf.*; 6 | import com.wowza.wms.client.*; 7 | import com.wowza.wms.module.*; 8 | import com.wowza.wms.request.*; 9 | import com.wowza.wms.server.*; 10 | import com.wowza.wms.application.*; 11 | import com.wowza.wms.stream.*; 12 | 13 | public class ModuleGetConnectionCount extends ModuleBase 14 | { 15 | public void getServerConnectionCount(IClient client, RequestFunction function, AMFDataList params) 16 | { 17 | Server server = Server.getInstance(); 18 | int count = (int)server.getConnectionCounter().getCurrent(); 19 | sendResult(client, params, count); 20 | } 21 | 22 | public void getApplicationConnectionCount(IClient client, RequestFunction function, AMFDataList params) 23 | { 24 | IApplication application = client.getApplication(); 25 | int count = (int)application.getConnectionCounter().getCurrent(); 26 | sendResult(client, params, count); 27 | } 28 | 29 | public void getApplicationInstanceConnectionCount(IClient client, RequestFunction function, AMFDataList params) 30 | { 31 | IApplicationInstance applicationInstance = client.getAppInstance(); 32 | int count = (int)applicationInstance.getConnectionCounter().getCurrent(); 33 | sendResult(client, params, count); 34 | } 35 | 36 | public void getStreamConnectionCount(IClient client, RequestFunction function, AMFDataList params) 37 | { 38 | String streamName = params.getString(PARAM1); 39 | int count = 0; 40 | IApplicationInstance applicationInstance = client.getAppInstance(); 41 | List streamList = applicationInstance.getPlayStreamsByName(streamName); 42 | if (streamList != null) 43 | count = streamList.size(); 44 | sendResult(client, params, count); 45 | } 46 | 47 | public void getStreamClientIds(IClient client, RequestFunction function, AMFDataList params) 48 | { 49 | AMFDataArray clientList = new AMFDataArray(); 50 | String streamName = params.getString(PARAM1); 51 | IApplicationInstance applicationInstance = client.getAppInstance(); 52 | List streamList = applicationInstance.getPlayStreamsByName(streamName); 53 | if (streamList != null) 54 | { 55 | Iterator iter = streamList.iterator(); 56 | while (iter.hasNext()) 57 | { 58 | IMediaStream stream = iter.next(); 59 | if (stream == null) 60 | continue; 61 | IClient sclient = stream.getClient(); 62 | if (sclient == null) 63 | continue; 64 | clientList.add(new AMFDataItem(sclient.getClientId())); 65 | } 66 | } 67 | sendResult(client, params, clientList); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleHotlinkDenial.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.client.*; 5 | import com.wowza.wms.module.*; 6 | import com.wowza.wms.request.*; 7 | 8 | public class ModuleHotlinkDenial extends ModuleBase { 9 | 10 | public void onConnect(IClient client, RequestFunction function, 11 | AMFDataList params) { 12 | 13 | getLogger().info("onConnect HotlinkDenial Module: " + client.getClientId()); 14 | 15 | String flashver = client.getFlashVer(); 16 | getLogger().info("Flashver: " + flashver); 17 | 18 | Boolean isPublisher=false; 19 | String allowedEncoder=""; 20 | 21 | try 22 | { 23 | allowedEncoder = client.getAppInstance().getProperties().getPropertyStr("AllowEncoder"); 24 | isPublisher = flashver.startsWith(allowedEncoder); 25 | 26 | if (isPublisher) 27 | { 28 | client.acceptConnection(); 29 | return; 30 | } 31 | } 32 | catch(Exception ex) 33 | { 34 | } 35 | boolean reject = true; 36 | String[] domainLocks = null; 37 | String[] domainUrl = null;; 38 | 39 | try 40 | { 41 | domainLocks = client.getAppInstance().getProperties().getPropertyStr("domainLock").toLowerCase().split(","); 42 | String pageUrl = client.getProperties().getPropertyStr("connectpageUrl").toLowerCase(); 43 | domainUrl = pageUrl.split("/"); 44 | getLogger().info("domainLock: " + client.getAppInstance().getProperties().getPropertyStr("domainLock").toLowerCase()); 45 | getLogger().info("pageUrl: " + pageUrl); 46 | for (int i = 0; i < domainLocks.length; i++) 47 | { 48 | if (domainLocks[i].trim().startsWith("*")) 49 | { 50 | String lock = domainLocks[i].trim().substring(1); 51 | if (domainUrl[2].endsWith(lock)) 52 | { 53 | reject = false; 54 | } 55 | } 56 | else if (domainUrl[2].equalsIgnoreCase(domainLocks[i].trim())) 57 | { 58 | reject = false; 59 | } 60 | } 61 | } 62 | catch(Exception ex) 63 | { 64 | reject = true; 65 | } 66 | if (reject) 67 | { 68 | getLogger().info("Client Rejected. IP: " + client.getIp()); 69 | client.rejectConnection(); 70 | } 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleLimitConnectionsToApplication.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import com.wowza.util.IOPerformanceCounter; 4 | import com.wowza.wms.amf.*; 5 | import com.wowza.wms.application.*; 6 | import com.wowza.wms.client.*; 7 | import com.wowza.wms.httpstreamer.cupertinostreaming.httpstreamer.*; 8 | import com.wowza.wms.httpstreamer.smoothstreaming.httpstreamer.*; 9 | import com.wowza.wms.request.*; 10 | import com.wowza.wms.rtp.model.*; 11 | import com.wowza.wms.stream.IMediaStream; 12 | import com.wowza.wms.module.*; 13 | 14 | public class ModuleLimitConnectionsToApplication extends ModuleBase 15 | { 16 | static final public int MAXCONNECTIONS = 200; 17 | 18 | private int maxApplicationConnections = MAXCONNECTIONS; 19 | 20 | public void onAppStart(IApplicationInstance appInstance) 21 | { 22 | this.maxApplicationConnections = appInstance.getProperties().getPropertyInt("maxApplicationConnections", maxApplicationConnections); 23 | } 24 | 25 | public void changeLimit(IClient client, RequestFunction function, 26 | AMFDataList params) { 27 | client.getAppInstance().broadcastMsg("handlerName"); 28 | Integer newLimit = params.getInt(PARAM1); 29 | this.maxApplicationConnections = newLimit; 30 | } 31 | 32 | public void onConnect(IClient client, RequestFunction function, AMFDataList params) 33 | { 34 | IApplicationInstance appInstance = client.getAppInstance(); 35 | IApplication app = appInstance.getApplication(); 36 | long count = app.getConnectionCounter().getCurrent(); 37 | 38 | String flashver = client.getFlashVer(); 39 | getLogger().info("Flashver: " + flashver); 40 | 41 | Boolean isPublisher = false; 42 | try 43 | { 44 | isPublisher = flashver.startsWith(client.getAppInstance().getProperties().getPropertyStr("AllowEncoder")); 45 | } 46 | catch(Exception ex) 47 | { 48 | } 49 | 50 | if ((count+1) > this.maxApplicationConnections && !isPublisher) 51 | { 52 | client.rejectConnection("Over application connection limit ["+app.getName()+"/"+appInstance.getName()+"]: Limit is: "+this.maxApplicationConnections); 53 | } 54 | } 55 | 56 | public void onHTTPSmoothStreamingSessionCreate(HTTPStreamerSessionSmoothStreamer httpSmoothStreamingSession) 57 | { 58 | IApplicationInstance appInstance = httpSmoothStreamingSession.getAppInstance(); 59 | IApplication app = appInstance.getApplication(); 60 | long count = app.getConnectionCounter().getCurrent(); 61 | 62 | if ((count+1) > this.maxApplicationConnections) 63 | { 64 | httpSmoothStreamingSession.rejectSession(); 65 | } 66 | } 67 | 68 | public void onHTTPCupertinoStreamingSessionCreate(HTTPStreamerSessionCupertino httpCupertinoStreamingSession) 69 | { 70 | 71 | IApplicationInstance appInstance = httpCupertinoStreamingSession.getAppInstance(); 72 | IApplication app = appInstance.getApplication(); 73 | long count = app.getConnectionCounter().getCurrent(); 74 | 75 | if ((count+1) > this.maxApplicationConnections) 76 | { 77 | httpCupertinoStreamingSession.rejectSession(); 78 | } 79 | } 80 | public void onRTPSessionCreate(RTPSession rtpSession) 81 | { 82 | IApplicationInstance appInstance = rtpSession.getAppInstance(); 83 | IApplication app = appInstance.getApplication(); 84 | long count = app.getConnectionCounter().getCurrent(); 85 | 86 | if ((count+1) > this.maxApplicationConnections) 87 | { 88 | rtpSession.rejectSession(); 89 | } 90 | } 91 | 92 | public void onHTTPSmoothStreamingSessionDestroy(HTTPStreamerSessionSmoothStreamer session) 93 | { 94 | } 95 | 96 | public void onHTTPCupertinoStreamingSessionDestroy(HTTPStreamerSessionCupertino session) 97 | { 98 | } 99 | public void onRTPSessionDestroy(RTPSession session) 100 | { 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleLimitPublishedStreamBandwidth.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import java.util.Date; 4 | import java.util.Timer; 5 | import java.util.TimerTask; 6 | 7 | import com.wowza.util.IOPerformanceCounter; 8 | import com.wowza.wms.amf.AMFPacket; 9 | import com.wowza.wms.application.IApplicationInstance; 10 | import com.wowza.wms.application.WMSProperties; 11 | import com.wowza.wms.module.*; 12 | import com.wowza.wms.stream.IMediaStream; 13 | import com.wowza.wms.stream.IMediaStreamActionNotify2; 14 | 15 | public class ModuleLimitPublishedStreamBandwidth extends ModuleBase { 16 | 17 | int MAXBITRATE = 800; // 0 = no limit 18 | int INTERVAL = 5000; 19 | 20 | public void onAppStart(IApplicationInstance appInstance) 21 | { 22 | MAXBITRATE = appInstance.getApplication().getProperties().getPropertyInt("MaxBitrate",MAXBITRATE); 23 | } 24 | 25 | public void onStreamCreate(IMediaStream stream) { 26 | getLogger().info("StreamCreate Name: " + stream.getName()); 27 | 28 | IMediaStreamActionNotify2 actionNotify = new StreamListener(); 29 | WMSProperties props = stream.getProperties(); 30 | synchronized(props) 31 | { 32 | props.put("streamActionNotifier", actionNotify); 33 | } 34 | stream.addClientListener(actionNotify); 35 | } 36 | public void onStreamDestroy(IMediaStream stream) { 37 | getLogger().info("StreamDestroy: " + stream.getName()); 38 | 39 | IMediaStreamActionNotify2 actionNotify = null; 40 | WMSProperties props = stream.getProperties(); 41 | synchronized(props) 42 | { 43 | actionNotify = (IMediaStreamActionNotify2)stream.getProperties().get("streamActionNotifier"); 44 | } 45 | if (actionNotify != null) 46 | { 47 | stream.removeClientListener(actionNotify); 48 | getLogger().info("removeClientListener: "+stream.getSrc()); 49 | } 50 | stream.removeClientListener(actionNotify); 51 | } 52 | 53 | class StreamListener implements IMediaStreamActionNotify2 54 | { 55 | public void onPlay(IMediaStream stream, String streamName, double playStart, double playLen, int playReset) 56 | { 57 | getLogger().info("Play Stream: " + streamName); 58 | } 59 | 60 | public void onMetaData(IMediaStream stream, AMFPacket metaDataPacket) 61 | { 62 | getLogger().info("onMetaData By: " + stream.getClientId()); 63 | } 64 | 65 | public void onPauseRaw(IMediaStream stream, boolean isPause, double location) 66 | { 67 | getLogger().info("onPauseRaw By: " + stream.getClientId()); 68 | } 69 | 70 | public void onSeek(IMediaStream stream, double location) 71 | { 72 | getLogger().info("onSeek, stream name: " + stream.getName()); 73 | } 74 | 75 | public void onStop(IMediaStream stream) 76 | { 77 | getLogger().info("onStop By: " + stream.getClientId()); 78 | } 79 | 80 | public void onPause(IMediaStream stream, boolean isPause, double location) 81 | { 82 | getLogger().info("onPause"); 83 | } 84 | public void onUnPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) 85 | { 86 | getLogger().info("unPublish Stream: " + stream.getName()); 87 | WMSProperties props = stream.getProperties(); 88 | 89 | MonitorStream monitor; 90 | 91 | synchronized(props) 92 | { 93 | monitor = (MonitorStream)props.get("monitor"); 94 | } 95 | if (monitor!=null) 96 | monitor.stop(); 97 | } 98 | 99 | public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) 100 | { 101 | MonitorStream monitor = new MonitorStream(stream); 102 | WMSProperties props = stream.getProperties(); 103 | synchronized(props) 104 | { 105 | props.put("monitor", monitor); 106 | } 107 | monitor.start(); 108 | } 109 | } 110 | 111 | private class MonitorStream { 112 | public Timer mTimer; 113 | public TimerTask mTask; 114 | public IMediaStream stream; 115 | public MonitorStream(IMediaStream s){ 116 | stream = s; 117 | mTask = new TimerTask(){ 118 | public void run() { 119 | 120 | if (stream==null) 121 | stop(); 122 | 123 | getLogger().info(""); 124 | IOPerformanceCounter perf = stream.getMediaIOPerformance(); 125 | Double bitrate = perf.getMessagesInBytesRate() * 8 * .001; 126 | getLogger().info("Stream '" + stream.getName() + "' BitRate: " + Math.round(Math.floor(bitrate)) + "kbs"); 127 | if (bitrate > MAXBITRATE && MAXBITRATE > 0) 128 | { 129 | getLogger().info("Sent NetStream.Publish.Rejected to " + stream.getClientId() + " stream name: " + stream.getName()); 130 | sendStreamOnStatusError(stream, "NetStream.Publish.Rejected", "bitrate too high"); 131 | 132 | stream.getClient().setShutdownClient(true); 133 | } 134 | } 135 | }; 136 | mTimer = new Timer(); 137 | } 138 | 139 | public void start(){ 140 | if (mTimer==null) 141 | mTimer = new Timer(); 142 | mTimer.scheduleAtFixedRate(mTask, new Date(),INTERVAL); 143 | } 144 | 145 | public void stop(){ 146 | if (mTimer != null){ 147 | mTimer.cancel(); 148 | mTimer=null; 149 | } 150 | } 151 | } 152 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleLimitStreamViewers.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import java.util.*; 4 | 5 | import com.wowza.wms.amf.*; 6 | import com.wowza.wms.application.*; 7 | import com.wowza.wms.client.*; 8 | import com.wowza.wms.request.*; 9 | import com.wowza.wms.stream.*; 10 | import com.wowza.wms.module.*; 11 | 12 | public class ModuleLimitStreamViewers extends ModuleBase 13 | { 14 | static final public int MAXVIEWERS = 200; 15 | 16 | private int maxStreamViewers = MAXVIEWERS; 17 | 18 | public void onAppStart(IApplicationInstance appInstance) 19 | { 20 | this.maxStreamViewers = appInstance.getProperties().getPropertyInt("maxStreamViewers", MAXVIEWERS); 21 | } 22 | 23 | public void play(IClient client, RequestFunction function, AMFDataList params) 24 | { 25 | String streamName = params.getString(PARAM1); 26 | IMediaStream stream = getStream(client, function); 27 | 28 | IApplicationInstance appInstance = client.getAppInstance(); 29 | List streamList = appInstance.getPlayStreamsByName(streamName); 30 | int count = streamList==null?0:streamList.size(); 31 | 32 | if (count < this.maxStreamViewers) 33 | { 34 | this.invokePrevious(client, function, params); 35 | } 36 | else 37 | { 38 | if (stream != null) 39 | { 40 | String code = "NetStream.Play.Failed"; 41 | String description = "ModuleLimitViewers: Over viewer limit["+this.maxStreamViewers+"]"; 42 | sendStreamOnStatusError(stream, code, description); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleLoadBalancerEdgeLimitConnections.java~: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import com.wowza.wms.amf.AMFDataList; 4 | import com.wowza.wms.application.IApplicationInstance; 5 | import com.wowza.wms.client.ConnectionCounter; 6 | import com.wowza.wms.client.IClient; 7 | import com.wowza.wms.httpstreamer.cupertinostreaming.httpstreamer.HTTPStreamerSessionCupertino; 8 | import com.wowza.wms.httpstreamer.smoothstreaming.httpstreamer.HTTPStreamerSessionSmoothStreamer; 9 | import com.wowza.wms.module.ModuleBase; 10 | import com.wowza.wms.plugin.loadbalancer.LoadBalancerSender; 11 | import com.wowza.wms.plugin.loadbalancer.ServerListenerLoadBalancerSender; 12 | import com.wowza.wms.request.RequestFunction; 13 | import com.wowza.wms.rtp.model.RTPSession; 14 | import com.wowza.wms.server.Server; 15 | 16 | public class ModuleLoadBalancerEdgeLimitConnections extends ModuleBase 17 | { 18 | static final public int MAXCONNECTIONS = 200; 19 | 20 | private ConnectionCounter counter; 21 | private int maxApplicationConnections = MAXCONNECTIONS; 22 | 23 | private LoadBalancerSender loadBalancerSender = (LoadBalancerSender)Server.getInstance().getProperties().get(ServerListenerLoadBalancerSender.PROP_LOADBALANCERSENDER); 24 | 25 | public void onAppStart(IApplicationInstance appInstance) 26 | { 27 | this.counter = appInstance.getConnectionCounter(); 28 | this.maxApplicationConnections = appInstance.getProperties().getPropertyInt("maxApplicationConnections", maxApplicationConnections); 29 | } 30 | 31 | public void changeLimit(IClient client, RequestFunction function, 32 | AMFDataList params) { 33 | Integer newLimit = params.getInt(PARAM1); 34 | this.maxApplicationConnections = newLimit; 35 | } 36 | 37 | private void addConnection() { 38 | long count = counter.getCurrent(); 39 | 40 | if ((count+1) > this.maxApplicationConnections) 41 | { 42 | loadBalancerSender.pause(); 43 | } 44 | } 45 | 46 | private void removeConnection() { 47 | long count = counter.getCurrent(); 48 | 49 | if ((count-1) < this.maxApplicationConnections) 50 | { 51 | loadBalancerSender.unpause(); 52 | } 53 | } 54 | 55 | public void onConnect(IClient client, RequestFunction function, AMFDataList params) 56 | { 57 | addConnection(); 58 | } 59 | 60 | public void onDisconnect(IClient client, RequestFunction function, AMFDataList params) { 61 | removeConnection(); 62 | } 63 | 64 | public void onHTTPSmoothStreamingSessionCreate(HTTPStreamerSessionSmoothStreamer httpSmoothStreamingSession) 65 | { 66 | addConnection(); 67 | } 68 | 69 | public void onHTTPSmoothStreamingSessionDestroy(HTTPStreamerSessionSmoothStreamer httpSmoothStreamingSession) 70 | { 71 | removeConnection(); 72 | } 73 | 74 | public void onHTTPCupertinoStreamingSessionCreate(HTTPStreamerSessionCupertino httpCupertinoStreamingSession) 75 | { 76 | addConnection(); 77 | } 78 | 79 | public void onHTTPCupertinoStreamingSessionDestroy(HTTPStreamerSessionCupertino httpCupertinoStreamingSession) 80 | { 81 | removeConnection(); 82 | } 83 | 84 | public void onRTPSessionCreate(RTPSession rtpSession) 85 | { 86 | addConnection(); 87 | } 88 | 89 | public void onRTPSessionDestroy(RTPSession rtpSession) 90 | { 91 | removeConnection(); 92 | } 93 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleLogViewerCounts.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import java.util.*; 4 | 5 | import com.wowza.wms.logging.*; 6 | import com.wowza.wms.module.*; 7 | import com.wowza.wms.application.*; 8 | import com.wowza.wms.stream.*; 9 | import com.wowza.wms.amf.*; 10 | 11 | public class ModuleLogViewerCounts extends ModuleBase 12 | { 13 | class MyLogger extends Thread 14 | { 15 | private boolean running = true; 16 | private boolean quit = false; 17 | private int logTime = 10000; 18 | private long lastLogTime = -1; 19 | private IApplicationInstance appInstance = null; 20 | 21 | public MyLogger(IApplicationInstance appInstance) 22 | { 23 | this.appInstance = appInstance; 24 | } 25 | 26 | public synchronized void quit() 27 | { 28 | this.quit = true; 29 | } 30 | 31 | private Map getMetadataInfo(IMediaStream stream) 32 | { 33 | Map ret = new HashMap(); 34 | try 35 | { 36 | IMediaStreamMetaDataProvider metaDataProvider = stream.getMetaDataProvider(); 37 | 38 | while (true) 39 | { 40 | if (metaDataProvider == null) 41 | break; 42 | 43 | List metaDataList = new ArrayList(); 44 | long firstTimecode = 0; 45 | AMFPacket packet = stream.getLastPacket(); 46 | firstTimecode = packet==null?0:packet.getAbsTimecode(); 47 | metaDataProvider.onStreamStart(metaDataList, firstTimecode); 48 | 49 | if (metaDataList.size() <= 0) 50 | break; 51 | 52 | for(int i=0;i iter = arr.getKeys().iterator(); 65 | while(iter.hasNext()) 66 | { 67 | String key = iter.next(); 68 | String value = arr.getString(key); 69 | if (value == null) 70 | continue; 71 | ret.put(key, value); 72 | } 73 | } 74 | else if (dataList.get(1).getType() == AMFData.DATA_TYPE_OBJECT) 75 | { 76 | AMFDataObj obj = (AMFDataObj)dataList.get(1); 77 | Iterator iter = obj.getKeys().iterator(); 78 | while(iter.hasNext()) 79 | { 80 | String key = iter.next(); 81 | String value = obj.getString(key); 82 | if (value == null) 83 | continue; 84 | ret.put(key, value); 85 | } 86 | } 87 | } 88 | 89 | break; 90 | } 91 | } 92 | catch (Exception e) 93 | { 94 | 95 | } 96 | 97 | return ret; 98 | } 99 | 100 | public void run() 101 | { 102 | while(true) 103 | { 104 | try 105 | { 106 | long currTime = System.currentTimeMillis(); 107 | if (lastLogTime == -1) 108 | lastLogTime = currTime; 109 | 110 | if ((currTime - lastLogTime) > logTime) 111 | { 112 | MediaStreamMap streams = appInstance.getStreams(); 113 | List streamNames = streams.getPublishStreamNames(); 114 | 115 | Iterator iter = streamNames.iterator(); 116 | while(iter.hasNext()) 117 | { 118 | String streamName = iter.next(); 119 | 120 | 121 | List listeners = appInstance.getPlayStreamsByName(streamName); 122 | if (listeners == null) 123 | continue; 124 | 125 | //System.out.println("streamName: "+listeners.size()+":"+streamName); 126 | 127 | IMediaStream stream = streams.getStream(streamName); 128 | if (stream == null) 129 | continue; 130 | 131 | IMediaStreamMetaDataProvider metaDataProvider = stream.getMetaDataProvider(); 132 | 133 | List metaData = new ArrayList(); 134 | metaDataProvider.onStreamStart(metaData, 0); 135 | 136 | String metaDataStr = ""; 137 | int count = listeners.size(); 138 | metaDataStr += "viewers"+": \""+count+"\""; 139 | Map metaList = getMetadataInfo(stream); 140 | Iterator iter2 = metaList.keySet().iterator(); 141 | while(iter2.hasNext()) 142 | { 143 | String key = iter2.next(); 144 | String value = metaList.get(key); 145 | if (metaDataStr.length() > 0) 146 | metaDataStr += ", "; 147 | metaDataStr += key+": \""+value+"\""; 148 | } 149 | 150 | WMSLoggerFactory.getLogger(ModuleCore.class).info("{"+metaDataStr+"}", stream, WMSLoggerIDs.CAT_stream, "listeners", WMSLoggerIDs.STAT_general_successful, streamName); 151 | } 152 | 153 | lastLogTime = currTime; 154 | } 155 | 156 | synchronized(this) 157 | { 158 | Thread.currentThread().sleep(100); 159 | if (quit) 160 | { 161 | running = false; 162 | break; 163 | } 164 | } 165 | } 166 | catch (Exception e) 167 | { 168 | 169 | } 170 | } 171 | } 172 | } 173 | 174 | private MyLogger logger = null; 175 | 176 | public void onAppStart(IApplicationInstance appInstance) 177 | { 178 | Integer maxRate = appInstance.getProperties().getPropertyInt("maxBitRate", 500000); 179 | this.logger = new MyLogger(appInstance); 180 | this.logger.setDaemon(true); 181 | this.logger.start(); 182 | } 183 | 184 | public void onAppStop(IApplicationInstance appInstance) 185 | { 186 | if (this.logger != null) 187 | this.logger.quit(); 188 | this.logger = null; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleNoDuplicatePublishStreamname.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | // com.wowza.wms.plugin.collection.module.ModuleNoDuplicatePublishStreamname 4 | 5 | import com.wowza.wms.amf.AMFDataList; 6 | import com.wowza.wms.client.*; 7 | import com.wowza.wms.module.*; 8 | import com.wowza.wms.request.*; 9 | import com.wowza.wms.stream.IMediaStream; 10 | 11 | public class ModuleNoDuplicatePublishStreamname extends ModuleBase { 12 | 13 | public void publish(IClient client, RequestFunction function, AMFDataList params) 14 | { 15 | boolean bAuthorized = false; 16 | 17 | try { 18 | bAuthorized = checkPermissions(client, function, params); 19 | } 20 | catch (Exception ex) { 21 | 22 | } 23 | 24 | if (bAuthorized != true) 25 | { 26 | sendClientOnStatusError(client, "NetStream.Publish.Denied", "Invalid credentials supplied"); 27 | } 28 | else 29 | { 30 | invokePrevious(client, function, params); 31 | } 32 | } 33 | 34 | 35 | public void releaseStream(IClient client, RequestFunction function, AMFDataList params) 36 | { 37 | boolean bAuthorized = false; 38 | 39 | try { 40 | bAuthorized = checkPermissions(client, function, params); 41 | } 42 | catch (Exception ex) { 43 | // some error 44 | } 45 | 46 | if (bAuthorized != true) 47 | { 48 | sendClientOnStatusError(client, "NetStream.Publish.Denied", "Invalid credentials supplied"); 49 | client.setShutdownClient(true); 50 | } 51 | else 52 | { 53 | invokePrevious(client, function, params); 54 | } 55 | } 56 | public boolean checkPermissions(IClient client, RequestFunction function, AMFDataList params) 57 | { 58 | boolean doesStreamExist = false; 59 | boolean authorized = false; 60 | 61 | String streamName; 62 | try 63 | { 64 | streamName = params.getString(PARAM1).split("\\?")[0]; 65 | } 66 | catch(Exception ex) 67 | { 68 | return false; 69 | } 70 | 71 | IMediaStream stream = client.getAppInstance().getStreams().getStream(streamName); 72 | 73 | getLogger().info("Checking stream Name: " + streamName); 74 | 75 | doesStreamExist = (stream != null); 76 | 77 | if (doesStreamExist) 78 | { 79 | authorized = false; 80 | } 81 | else 82 | { 83 | authorized = true; 84 | } 85 | 86 | // add other permission checking 87 | 88 | getLogger().info("Authorized: " + authorized); 89 | 90 | return authorized; 91 | } 92 | 93 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleOnConnectAuthenticate.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import com.wowza.util.*; 7 | import com.wowza.wms.amf.*; 8 | import com.wowza.wms.application.*; 9 | import com.wowza.wms.authentication.*; 10 | import com.wowza.wms.authentication.file.*; 11 | import com.wowza.wms.client.*; 12 | import com.wowza.wms.module.*; 13 | import com.wowza.wms.request.*; 14 | import com.wowza.wms.util.*; 15 | import com.wowza.wms.vhost.*; 16 | 17 | public class ModuleOnConnectAuthenticate extends ModuleBase 18 | { 19 | public static final String AUTHPASSWORDFILEPATH = "${com.wowza.wms.context.VHostConfigHome}/conf/connect.password"; 20 | private File passwordFile = null; 21 | private String usernamePasswordProviderClass = null; 22 | 23 | public void onAppStart(IApplicationInstance appInstance) 24 | { 25 | WMSProperties props = appInstance.getProperties(); 26 | 27 | String passwordFileStr = props.getPropertyStr("rtmpAuthenticateFile", AUTHPASSWORDFILEPATH); 28 | this.usernamePasswordProviderClass = props.getPropertyStr("usernamePasswordProviderClass", this.usernamePasswordProviderClass); 29 | if (passwordFileStr != null) 30 | { 31 | Map envMap = new HashMap(); 32 | 33 | IVHost vhost = appInstance.getVHost(); 34 | envMap.put("com.wowza.wms.context.VHost", vhost.getName()); 35 | envMap.put("com.wowza.wms.context.VHostConfigHome", vhost.getHomePath()); 36 | envMap.put("com.wowza.wms.context.Application", appInstance.getApplication().getName()); 37 | envMap.put("com.wowza.wms.context.ApplicationInstance", appInstance.getName()); 38 | 39 | passwordFileStr = SystemUtils.expandEnvironmentVariables(passwordFileStr, envMap); 40 | passwordFile = new File(passwordFileStr); 41 | } 42 | 43 | if (passwordFile != null) 44 | getLogger().info("ModuleOnConnectAuthenticate: Authorization password file: "+passwordFile.getAbsolutePath()); 45 | if (usernamePasswordProviderClass != null) 46 | getLogger().info("ModuleOnConnectAuthenticate: Authorization password class: "+usernamePasswordProviderClass); 47 | } 48 | 49 | public void onConnect(IClient client, RequestFunction function, AMFDataList params) 50 | { 51 | boolean isAuthenticated = false; 52 | 53 | String username = null; 54 | String password = null; 55 | try 56 | { 57 | while(true) 58 | { 59 | if (params.size() <= PARAM2) 60 | break; 61 | 62 | username = params.getString(PARAM1); 63 | password = params.getString(PARAM2); 64 | 65 | if (username == null || password == null) 66 | break; 67 | 68 | IAuthenticateUsernamePasswordProvider filePtr = null; 69 | if (usernamePasswordProviderClass != null) 70 | filePtr = AuthenticationUtils.createUsernamePasswordProvider(usernamePasswordProviderClass); 71 | else if (passwordFile != null) 72 | filePtr = AuthenticationPasswordFiles.getInstance().getPasswordFile(passwordFile); 73 | 74 | if (filePtr == null) 75 | break; 76 | 77 | filePtr.setClient(client); 78 | 79 | String userPassword = filePtr.getPassword(username); 80 | if (userPassword == null) 81 | break; 82 | 83 | if (!userPassword.equals(password)) 84 | break; 85 | 86 | isAuthenticated = true; 87 | break; 88 | } 89 | } 90 | catch(Exception e) 91 | { 92 | getLogger().error("ModuleOnConnectAuthenticate.onConnect: "+e.toString()); 93 | isAuthenticated = false; 94 | } 95 | 96 | if (!isAuthenticated) 97 | client.rejectConnection("Authentication Failed["+client.getClientId()+"]: "+username); 98 | else 99 | client.acceptConnection(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleOnConnectAuthenticate2.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import com.wowza.util.*; 7 | import com.wowza.wms.amf.*; 8 | import com.wowza.wms.application.*; 9 | import com.wowza.wms.authentication.*; 10 | import com.wowza.wms.authentication.file.*; 11 | import com.wowza.wms.client.*; 12 | import com.wowza.wms.module.*; 13 | import com.wowza.wms.request.*; 14 | import com.wowza.wms.util.*; 15 | import com.wowza.wms.vhost.*; 16 | 17 | public class ModuleOnConnectAuthenticate2 extends ModuleBase 18 | { 19 | public static final String AUTHPASSWORDFILEPATH = "${com.wowza.wms.context.VHostConfigHome}/conf/connect.password"; 20 | private File passwordFile = null; 21 | private String usernamePasswordProviderClass = null; 22 | 23 | public void onAppStart(IApplicationInstance appInstance) 24 | { 25 | WMSProperties props = appInstance.getProperties(); 26 | 27 | String passwordFileStr = props.getPropertyStr("rtmpAuthenticateFile", AUTHPASSWORDFILEPATH); 28 | this.usernamePasswordProviderClass = props.getPropertyStr("usernamePasswordProviderClass", this.usernamePasswordProviderClass); 29 | if (passwordFileStr != null) 30 | { 31 | Map envMap = new HashMap(); 32 | 33 | IVHost vhost = appInstance.getVHost(); 34 | envMap.put("com.wowza.wms.context.VHost", vhost.getName()); 35 | envMap.put("com.wowza.wms.context.VHostConfigHome", vhost.getHomePath()); 36 | envMap.put("com.wowza.wms.context.Application", appInstance.getApplication().getName()); 37 | envMap.put("com.wowza.wms.context.ApplicationInstance", appInstance.getName()); 38 | 39 | passwordFileStr = SystemUtils.expandEnvironmentVariables(passwordFileStr, envMap); 40 | passwordFile = new File(passwordFileStr); 41 | } 42 | 43 | if (passwordFile != null) 44 | getLogger().info("ModuleOnConnectAuthenticate: Authorization password file: "+passwordFile.getAbsolutePath()); 45 | if (usernamePasswordProviderClass != null) 46 | getLogger().info("ModuleOnConnectAuthenticate: Authorization password class: "+usernamePasswordProviderClass); 47 | } 48 | 49 | public void onConnect(IClient client, RequestFunction function, AMFDataList params) 50 | { 51 | boolean isAuthenticated = false; 52 | 53 | String username = null; 54 | String password = null; 55 | 56 | try 57 | { 58 | while(true) 59 | { 60 | getLogger().info("size: " + params.size()); 61 | 62 | AMFDataMixedArray auth = getParamMixedArray(params, PARAM1); 63 | 64 | username = auth.getString(0); 65 | password = auth.getString(1); 66 | 67 | if (username == null || password == null) 68 | break; 69 | 70 | IAuthenticateUsernamePasswordProvider filePtr = null; 71 | if (usernamePasswordProviderClass != null) 72 | filePtr = AuthenticationUtils.createUsernamePasswordProvider(usernamePasswordProviderClass); 73 | else if (passwordFile != null) 74 | filePtr = AuthenticationPasswordFiles.getInstance().getPasswordFile(passwordFile); 75 | 76 | if (filePtr == null) 77 | break; 78 | 79 | filePtr.setClient(client); 80 | 81 | String userPassword = filePtr.getPassword(username); 82 | if (userPassword == null) 83 | break; 84 | 85 | if (!userPassword.equals(password)) 86 | break; 87 | 88 | isAuthenticated = true; 89 | break; 90 | } 91 | } 92 | catch(Exception e) 93 | { 94 | getLogger().error("ModuleOnConnectAuthenticate.onConnect: "+e.toString()); 95 | isAuthenticated = false; 96 | } 97 | 98 | if (!isAuthenticated) 99 | client.rejectConnection("Authentication Failed["+client.getClientId()+"]: "+username); 100 | else 101 | client.acceptConnection(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleRequireSecureConnection.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.client.*; 5 | import com.wowza.wms.module.*; 6 | import com.wowza.wms.request.*; 7 | 8 | public class ModuleRequireSecureConnection extends ModuleBase 9 | { 10 | public void onConnect(IClient client, RequestFunction function, AMFDataList params) 11 | { 12 | 13 | String flashver = client.getFlashVer(); 14 | getLogger().info("Flashver: " + flashver); 15 | 16 | Boolean isPublisher = false; 17 | try 18 | { 19 | isPublisher = flashver.startsWith(client.getAppInstance().getProperties().getPropertyStr("AllowEncoder")); 20 | } 21 | catch(Exception ex) 22 | { 23 | } 24 | 25 | if (!client.isSecure() && !isPublisher) 26 | { 27 | client.rejectConnection("Secure connection required."); 28 | getLogger().info("ModuleRequireSecureConnection.onConnect: rejectConnection: clientId:"+client.getClientId()); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleStreamControl.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.client.*; 5 | import com.wowza.wms.module.*; 6 | import com.wowza.wms.request.*; 7 | import com.wowza.wms.stream.publish.*; 8 | 9 | public class ModuleStreamControl extends ModuleBase { 10 | 11 | public void openPlaylistOnStream(IClient client, RequestFunction function, 12 | AMFDataList params) { 13 | 14 | String streamName = getParamString(params, PARAM1); 15 | 16 | String playlistName = getParamString(params, PARAM2); 17 | 18 | Stream stream = (Stream)client.getAppInstance().getProperties().getProperty(streamName); 19 | 20 | Playlist playlist = (Playlist)client.getAppInstance().getProperties().getProperty(playlistName); 21 | 22 | playlist.open(stream); 23 | 24 | } 25 | public void addItemToPlaylist(IClient client, RequestFunction function, 26 | AMFDataList params) { 27 | 28 | AMFDataObj obj = getParamObj(params, PARAM1); 29 | 30 | Playlist playlist = (Playlist)client.getAppInstance().getProperties().getProperty(obj.getString("playListName")); 31 | 32 | playlist.addItem(obj.getString("itemName"), obj.getInt("itemStart"), obj.getInt("itemDuration")); 33 | } 34 | 35 | public void removeItemFromPlaylist(IClient client, RequestFunction function, 36 | AMFDataList params) { 37 | 38 | String streamName = getParamString(params, PARAM1); 39 | 40 | Stream stream = (Stream)client.getAppInstance().getProperties().getProperty(streamName); 41 | 42 | Boolean success = stream.removeFromPlaylist("Extremists.flv"); 43 | } 44 | 45 | 46 | public void playNextPlaylistItem(IClient client, RequestFunction function, 47 | AMFDataList params) { 48 | 49 | String streamName = getParamString(params, PARAM1); 50 | 51 | Stream stream = (Stream)client.getAppInstance().getProperties().getProperty(streamName); 52 | 53 | stream.next(); 54 | 55 | } 56 | 57 | public void addNewStream(IClient client, RequestFunction function, 58 | AMFDataList params) { 59 | 60 | String streamName = getParamString(params, PARAM1); 61 | 62 | Stream stream = Stream.createInstance(client.getAppInstance(), streamName); 63 | 64 | client.getAppInstance().getProperties().put(streamName, stream); 65 | 66 | } 67 | 68 | public void addNewPlaylist(IClient client, RequestFunction function, 69 | AMFDataList params) { 70 | 71 | String playListName = getParamString(params, PARAM1); 72 | 73 | Playlist playlist = new Playlist(playListName); 74 | 75 | playlist.setRepeat(true); 76 | 77 | client.getAppInstance().getProperties().put(playListName, playlist); 78 | 79 | } 80 | public void stopStream(IClient client, RequestFunction function, 81 | AMFDataList params) { 82 | String streamName = getParamString(params, PARAM1); 83 | 84 | Stream stream = (Stream)client.getAppInstance().getProperties().remove(streamName); 85 | if(stream != null) 86 | stream.close(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleStreamWatchDog.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import java.util.*; 4 | import com.wowza.wms.application.*; 5 | import com.wowza.wms.amf.*; 6 | import com.wowza.wms.application.WMSProperties; 7 | import com.wowza.wms.module.*; 8 | import com.wowza.wms.stream.IMediaStream; 9 | import com.wowza.wms.stream.IMediaStreamActionNotify2; 10 | import com.wowza.wms.stream.MediaStreamMap; 11 | import java.util.Timer; 12 | import java.util.List; 13 | 14 | public class ModuleStreamWatchDog extends ModuleBase { 15 | 16 | public void onStreamCreate(IMediaStream stream) { 17 | getLogger().info("onStreamCreate by: " + stream.getClientId()); 18 | IMediaStreamActionNotify2 actionNotify = new StreamListener(); 19 | 20 | WMSProperties props = stream.getProperties(); 21 | synchronized(props) 22 | { 23 | props.put("streamActionNotifier", actionNotify); 24 | } 25 | stream.addClientListener(actionNotify); 26 | } 27 | public void onStreamDestroy(IMediaStream stream) { 28 | getLogger().info("onStreamDestroy by: " + stream.getClientId()); 29 | 30 | IMediaStreamActionNotify2 actionNotify = null; 31 | WMSProperties props = stream.getProperties(); synchronized(props) 32 | { 33 | actionNotify = (IMediaStreamActionNotify2)stream.getProperties().get("streamActionNotifier"); 34 | } 35 | if (actionNotify != null) 36 | { 37 | stream.removeClientListener(actionNotify); 38 | getLogger().info("removeClientListener: "+stream.getSrc()); 39 | } 40 | } 41 | 42 | class StreamListener implements IMediaStreamActionNotify2 43 | { 44 | public void onPlay(IMediaStream stream, String streamName, double playStart, double playLen, int playReset) 45 | { 46 | streamName = stream.getName(); 47 | getLogger().info("Stream Name: " + streamName); 48 | } 49 | 50 | public void onMetaData(IMediaStream stream, AMFPacket metaDataPacket) 51 | { 52 | getLogger().info("onMetaData By: " + stream.getClientId()); 53 | } 54 | 55 | public void onPauseRaw(IMediaStream stream, boolean isPause, double location) 56 | { 57 | getLogger().info("onPauseRaw By: " + stream.getClientId()); 58 | } 59 | 60 | public void onSeek(IMediaStream stream, double location) 61 | { 62 | getLogger().info("onSeek"); 63 | } 64 | 65 | public void onStop(IMediaStream stream) 66 | { 67 | getLogger().info("onStop By: " + stream.getClientId()); 68 | } 69 | 70 | public void onUnPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) 71 | { 72 | getLogger().info("onUNPublish"); 73 | StreamWatchDog watchdog = (StreamWatchDog)stream.getClient().getAppInstance().getProperties().getProperty(streamName); 74 | if (watchdog != null) 75 | watchdog.stop(); 76 | } 77 | 78 | public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) 79 | { 80 | getLogger().info("onPublish - stream name: " + stream.getName()); 81 | getLogger().info("query string: " + stream.getQueryStr()); 82 | getLogger().info("video codec: " + stream.getPublishVideoCodecId()); 83 | StreamWatchDog watchdog = new StreamWatchDog(); 84 | try 85 | { 86 | watchdog.appInstance = stream.getClient().getAppInstance(); 87 | watchdog.streamName = streamName; 88 | watchdog.start(); 89 | stream.getClient().getAppInstance().getProperties().setProperty(streamName, watchdog); 90 | } 91 | catch(Exception ex) 92 | { 93 | 94 | } 95 | } 96 | public void onPause(IMediaStream stream, boolean isPause, double location) 97 | { 98 | getLogger().info("onPause"); 99 | } 100 | } 101 | 102 | private class StreamWatchDog 103 | { 104 | public Timer mTimer; 105 | public TimerTask mTask; 106 | public String streamName; 107 | public IApplicationInstance appInstance; 108 | long streamLastSeq; 109 | boolean isMissing = false; 110 | long currSeq = 0; 111 | String msg; 112 | public StreamWatchDog(){ 113 | mTask = new TimerTask() 114 | { 115 | public void run() 116 | { 117 | getLogger().info("Run StreamWatchDog"); 118 | MediaStreamMap mediamap = appInstance.getStreams(); 119 | IMediaStream stream = mediamap.getStream(streamName); 120 | 121 | List packets = stream.getPlayPackets(); 122 | if (packets.size() == 0) 123 | { 124 | msg = "Stream not started"; 125 | } 126 | else 127 | { 128 | AMFPacket packet = (AMFPacket)packets.get(packets.size()-1); 129 | currSeq = packet.getSeq(); 130 | if (currSeq != streamLastSeq) 131 | { 132 | streamLastSeq = currSeq; 133 | msg = "Stream OK"; 134 | } 135 | else 136 | { 137 | msg = "Stream Appears Stalled"; 138 | } 139 | } 140 | appInstance.broadcastMsg("streamStats", streamName,currSeq,msg,new Date()); 141 | } 142 | }; 143 | } 144 | 145 | public void start(){ 146 | 147 | if (mTimer==null) 148 | mTimer = new Timer(); 149 | mTimer.schedule(mTask, 10000, 10000); 150 | getLogger().info("Start StreamWatchDog"); 151 | } 152 | 153 | public void stop(){ 154 | if (mTimer != null){ 155 | mTimer.cancel(); 156 | mTimer=null; 157 | getLogger().info("Stop StreamWatchDog"); 158 | } 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleVideoNameList.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.application.IApplicationInstance; 5 | import com.wowza.wms.client.*; 6 | import com.wowza.wms.module.*; 7 | import com.wowza.wms.request.*; 8 | import java.io.File; 9 | import com.wowza.util.FileUtils; 10 | import com.wowza.util.IFileProcess; 11 | 12 | public class ModuleVideoNameList extends ModuleBase { 13 | 14 | AMFDataMixedArray recordedMovies = new AMFDataMixedArray(); 15 | String storageDir; 16 | 17 | class PutFile implements IFileProcess 18 | { 19 | public void onFile(File file) 20 | { 21 | String sizeSuffix=""; 22 | String s = storageDir; 23 | if (file.length()<1024000) 24 | { 25 | sizeSuffix = "["+ Math.round((file.length() * .001)) + " kb]"; 26 | } 27 | else 28 | { 29 | sizeSuffix = "["+ Math.round((file.length() * .000001)) + " MB]"; 30 | } 31 | 32 | String fileName = file.getName(); 33 | 34 | String _abpath = file.getAbsolutePath().replace("\\", "/"); 35 | String _parent = file.getParent().replace("\\", "/"); 36 | String _path = file.getPath().replace("\\", "/"); 37 | 38 | 39 | 40 | fileName = fileName.replace(storageDir, ""); 41 | String fn = file.getName().toLowerCase(); 42 | if (fn.indexOf(".m4v")>-1 || fn.indexOf(".mov")>-1 || fn.indexOf(".mp4")>-1 || fn.indexOf(".f4v")>-1) 43 | { 44 | fileName="mp4:" + fileName; 45 | } 46 | 47 | if (file.length() > 0 && fileName.indexOf(".")>-1) 48 | { 49 | recordedMovies.put(fileName, new AMFDataItem(fileName.replace(".flv", "") + " " + sizeSuffix)); 50 | getLogger().info("fileName: " + fileName); 51 | } 52 | } 53 | } 54 | 55 | public void getVideoNames(IClient client, RequestFunction function, 56 | AMFDataList params) { 57 | getLogger().info("getFiles"); 58 | storageDir = client.getAppInstance().getStreamStoragePath(); 59 | recordedMovies = new AMFDataMixedArray(); 60 | 61 | IApplicationInstance app = client.getAppInstance(); 62 | 63 | PutFile putfile = new PutFile(); 64 | FileUtils.traverseDirectory(new File(app.getStreamStoragePath().replace("_definst_", app.getName())), putfile); 65 | sendResult(client, params, recordedMovies); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/module/ModuleWriteListener.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.module; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import com.wowza.wms.application.*; 7 | import com.wowza.wms.module.*; 8 | import com.wowza.wms.stream.*; 9 | 10 | public class ModuleWriteListener extends ModuleBase 11 | { 12 | // class WriteListener implements IMediaWriterActionNotify 13 | // { 14 | // public void onFLVAddMetadata(IMediaStream stream, Map extraMetadata) 15 | // { 16 | // getLogger().info("ModuleWriteListener.onFLVAddMetadata["+stream.getContextStr()+"]"); 17 | // } 18 | // 19 | // public void onWriteComplete(IMediaStream stream, File file) 20 | // { 21 | // getLogger().info("ModuleWriteListener.onWriteComplete["+stream.getContextStr()+"]: "+file); 22 | // } 23 | // } 24 | // 25 | // public void onAppStart(IApplicationInstance appInstance) 26 | // { 27 | // appInstance.addMediaWriterListener(new WriteListener()); 28 | // } 29 | } -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/java/com/wowza/wms/plugin/collection/serverlistener/ServerListenerStreamPublisher.java: -------------------------------------------------------------------------------- 1 | package com.wowza.wms.plugin.collection.serverlistener; 2 | 3 | import com.wowza.wms.amf.AMFDataObj; 4 | import com.wowza.wms.application.*; 5 | import com.wowza.wms.server.*; 6 | import com.wowza.wms.vhost.*; 7 | 8 | import com.wowza.wms.stream.IMediaStream; 9 | import com.wowza.wms.stream.publish.*; 10 | import com.wowza.wms.logging.*; 11 | import java.io.File; 12 | import java.text.SimpleDateFormat; 13 | import java.util.*; 14 | 15 | import javax.xml.parsers.DocumentBuilder; 16 | import javax.xml.parsers.DocumentBuilderFactory; 17 | import org.w3c.dom.Document; 18 | import org.w3c.dom.Element; 19 | import org.w3c.dom.Node; 20 | import org.w3c.dom.NodeList; 21 | 22 | public class ServerListenerStreamPublisher implements IServerNotify { 23 | 24 | WMSLogger log = WMSLoggerFactory.getLogger(null); 25 | 26 | Map streamMap = new HashMap(); 27 | Map playlistMap = new HashMap(); 28 | 29 | public void onServerInit(IServer server) 30 | { 31 | try 32 | { 33 | IVHost vhost = VHostSingleton.getInstance(server.getProperties().getPropertyStr("PublishToVHost", VHost.VHOST_DEFAULT)); 34 | IApplication app = vhost.getApplication(server.getProperties().getPropertyStr("PublishToApplication", "live")); 35 | Boolean passThruMetaData = server.getProperties().getPropertyBoolean("PassthruMetaData", true); 36 | 37 | String storageDir = app.getAppInstance("_definst_").getStreamStorageDir(); 38 | 39 | String smilLoc = storageDir + "/streamschedule.smil"; 40 | File playlistxml = new File(smilLoc); 41 | 42 | if (playlistxml.exists() == false){ 43 | log.info("Could not find playlist file: " + smilLoc); 44 | return; 45 | } 46 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 47 | DocumentBuilder db = dbf.newDocumentBuilder(); 48 | Document document = db.parse("file:///" + smilLoc); 49 | document.getDocumentElement().normalize(); 50 | 51 | NodeList streams = document.getElementsByTagName("stream"); 52 | for (int i = 0; i < streams.getLength(); i++) 53 | { 54 | Node streamItem = streams.item(i); 55 | if (streamItem.getNodeType() == Node.ELEMENT_NODE) 56 | { 57 | Element e = (Element) streamItem; 58 | String streamName = e.getAttribute("name"); 59 | Stream stream = Stream.createInstance(vhost, app.getName(), streamName); 60 | streamMap.put(streamName, stream); 61 | app.getAppInstance("_definst_").getProperties().setProperty(streamName, stream); 62 | } 63 | } 64 | 65 | NodeList playList = document.getElementsByTagName("playlist"); 66 | if (playList.getLength() == 0){ 67 | log.info("No playlists defined in smil file"); 68 | return; 69 | } 70 | for (int i = 0; i < playList.getLength(); i++) 71 | { 72 | Node scheduledPlayList = playList.item(i); 73 | 74 | if (scheduledPlayList.getNodeType() == Node.ELEMENT_NODE) 75 | { 76 | Element e = (Element) scheduledPlayList; 77 | 78 | NodeList videos = e.getElementsByTagName("video"); 79 | if (videos.getLength() == 0){ 80 | log.info("No videos defined in stream"); 81 | return; 82 | } 83 | 84 | String streamName = e.getAttribute("playOnStream"); 85 | if (streamName.length()==0) 86 | continue; 87 | 88 | Playlist playlist = new Playlist(streamName); 89 | playlist.setRepeat((e.getAttribute("repeat").equals("false"))?false:true); 90 | 91 | playlistMap.put(e.getAttribute("name"), playlist); 92 | 93 | for (int j = 0; j < videos.getLength(); j++) 94 | { 95 | Node video = videos.item(j); 96 | if (video.getNodeType() == Node.ELEMENT_NODE) 97 | { 98 | Element e2 = (Element) video; 99 | String src = e2.getAttribute("src"); 100 | Integer start = Integer.parseInt(e2.getAttribute("start")); 101 | Integer length = Integer.parseInt(e2.getAttribute("length")); 102 | playlist.addItem(src, start, length); 103 | } 104 | } 105 | String scheduled = e.getAttribute("scheduled"); 106 | SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 107 | Date startTime = parser.parse(scheduled); 108 | Stream stream = streamMap.get(streamName); 109 | stream.setSendOnMetadata(passThruMetaData); 110 | ScheduledItem item = new ScheduledItem(startTime, playlist, stream); 111 | item.start(); 112 | IStreamActionNotify actionNotify = new StreamListener(app.getAppInstance("_definst_")); 113 | stream.addListener(actionNotify); 114 | log.info("Scheduled: " + stream.getName() + " for: " + scheduled); 115 | } 116 | } 117 | } 118 | catch(Exception ex) 119 | { 120 | log.info(ex.getMessage()); 121 | } 122 | } 123 | 124 | private class ScheduledItem { 125 | public Timer mTimer; 126 | public TimerTask mTask; 127 | public Date mStart; 128 | public Playlist mPL; 129 | public Stream mStream; 130 | public ScheduledItem(Date d, Playlist pl, Stream s){ 131 | mStart = d; 132 | mPL = pl; 133 | mStream = s; 134 | mTask = new TimerTask(){ 135 | public void run() { 136 | //synchronized(mStream.getLock()) 137 | //{ 138 | mPL.open(mStream); 139 | //} 140 | log.info("Scheduled stream is now live: " + mStream.getName()); 141 | } 142 | }; 143 | mTimer = new Timer(); 144 | } 145 | 146 | public void start(){ 147 | 148 | if (mTimer==null) 149 | mTimer = new Timer(); 150 | mTimer.schedule(mTask, mStart); 151 | log.info("scheduled playlist: "+mPL.getName()+ 152 | " on stream: "+mStream.getName()+ 153 | " for:"+mStart.toString()); 154 | } 155 | 156 | public void stop(){ 157 | if (mTimer != null){ 158 | mTimer.cancel(); 159 | mTimer=null; 160 | log.info("cancelled playlist: "+mPL.getName()+ 161 | " on stream: "+mStream.getName()+ 162 | " for:"+mStart.toString()); 163 | } 164 | } 165 | } 166 | public void onServerCreate(IServer server) 167 | { 168 | } 169 | public void onServerShutdownComplete(IServer server) 170 | { 171 | log.info("Shutdown server start"); 172 | for (Map.Entry entry : streamMap.entrySet()) 173 | { 174 | try 175 | { 176 | Stream stream = entry.getValue(); 177 | stream.close(); 178 | stream = null; 179 | log.info("Closed Stream: " + entry.getKey()); 180 | } 181 | catch(Exception ex) 182 | { 183 | log.error(ex.getMessage()); 184 | } 185 | } 186 | for (Map.Entry entry : playlistMap.entrySet()) 187 | { 188 | try 189 | { 190 | Playlist pl = entry.getValue(); 191 | pl = null; 192 | } 193 | catch(Exception ex) 194 | { 195 | log.error(ex.getMessage()); 196 | } 197 | } 198 | } 199 | 200 | public void onServerShutdownStart(IServer server) 201 | { 202 | 203 | } 204 | 205 | class StreamListener implements IStreamActionNotify 206 | { 207 | StreamListener(IApplicationInstance appInstance) 208 | { 209 | } 210 | public void onPlaylistItemStop(Stream stream, PlaylistItem item) 211 | { 212 | } 213 | public void onPlaylistItemStart(Stream stream, PlaylistItem item) 214 | { 215 | IMediaStream theStream = stream.getPublisher().getStream(); 216 | AMFDataObj metaData = new AMFDataObj(); 217 | metaData.put("duration", ""); 218 | //theStream.send("onMetaData", metaData); 219 | } 220 | } 221 | } 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | com.webcam.media.red5.dev=DEBUG -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %date [%thread] %-5level %logger{35} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /3rdparty-wms-modules/src/main/resources/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Dev 6 | 7 | 8 | globalScope 9 | default 10 | 11 | 12 | 13 | contextConfigLocation 14 | /WEB-INF/red5-*.xml 15 | 16 | 17 | 18 | locatorFactorySelector 19 | red5.xml 20 | 21 | 22 | 23 | parentContextKey 24 | default.context 25 | 26 | 27 | 28 | webAppRootKey 29 | /dev 30 | 31 | 32 | 35 | 36 | 37 | 38 | gateway 39 | 40 | org.red5.server.net.servlet.AMFGatewayServlet 41 | 42 | 1 43 | 44 | 45 | 46 | gateway 47 | /gateway 48 | 49 | 50 | 51 | 52 | 53 | 54 | Forbidden 55 | /streams/* 56 | 57 | 58 | 59 | 60 | 61 | 62 | Forbidden 63 | /persistence/* 64 | 65 | 66 | 67 | 68 | 69 | 70 | Forbidden 71 | /WEB-INF/* 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | template-wowza [![Build Status](https://travis-ci.org/vpmedia/template-wowza.svg)](https://travis-ci.org/vpmedia/template-wowza) 2 | ============== 3 | 4 | Wowza Media Server modules 5 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpmedia/template-wowza/94ae44dcd19b8d23eb2ea9c7b3d9c72a54ffc103/gradle.properties -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | include 'vpmedia-wms-app', 14 | 'vpmedia-wms-bwcheck', 15 | 'vpmedia-wms-connectionlimiter', 16 | 'vpmedia-wms-dbauthentication', 17 | 'vpmedia-wms-fme', 18 | 'vpmedia-wms-hotlinkdenial', 19 | 'vpmedia-wms-keepalive', 20 | 'vpmedia-wms-medialoader', 21 | 'vpmedia-wms-mediareader', 22 | 'vpmedia-wms-mediastreampassthru', 23 | 'vpmedia-wms-remoting', 24 | 'vpmedia-wms-security', 25 | 'vpmedia-wms-snapshot', 26 | 'vpmedia-wms-ssl', 27 | 'vpmedia-wms-streamnamealias', 28 | 'vpmedia-wms-test' 29 | -------------------------------------------------------------------------------- /vpmedia-wms-app/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-app/src/main/java/hu/vpmedia/media/core/RoomTypes.java: -------------------------------------------------------------------------------- 1 | /* 2 | *=BEGIN CLOSED LICENSE 3 | * 4 | * Copyright(c) 2012 András Csizmadia. 5 | * http://www.vpmedia.eu 6 | * 7 | * For information about the licensing and copyright please 8 | * contact András Csizmadia at andras@vpmedia.eu. 9 | * 10 | *=END CLOSED LICENSE 11 | */ 12 | 13 | package hu.vpmedia.media.core; 14 | 15 | /** 16 | * Contains the room type codes 17 | * 18 | * @author Webcam Team - Andras Csizmadia 19 | * @version 1.0 20 | */ 21 | public interface RoomTypes 22 | { 23 | String LOGIN = "Login"; 24 | String OPEN = "Open"; 25 | String CLOSED = "Closed"; 26 | } 27 | -------------------------------------------------------------------------------- /vpmedia-wms-app/src/main/java/hu/vpmedia/media/core/UserTypes.java: -------------------------------------------------------------------------------- 1 | /* 2 | *=BEGIN CLOSED LICENSE 3 | * 4 | * Copyright(c) 2012 András Csizmadia. 5 | * http://www.vpmedia.eu 6 | * 7 | * For information about the licensing and copyright please 8 | * contact András Csizmadia at andras@vpmedia.eu. 9 | * 10 | *=END CLOSED LICENSE 11 | */ 12 | 13 | package hu.vpmedia.media.core; 14 | 15 | /** 16 | * Contains the user type codes 17 | * 18 | * @author Webcam Team - Andras Csizmadia 19 | * @version 1.0 20 | */ 21 | public interface UserTypes 22 | { 23 | String GUEST = "Guest"; 24 | String ADMIN = "Admin"; 25 | String HOST = "Host"; 26 | String PRESENTER = "Presenter"; 27 | String PARTICIPANT = "Participant"; 28 | } 29 | -------------------------------------------------------------------------------- /vpmedia-wms-app/src/main/java/hu/vpmedia/media/wms/dev/WebcamDev.java: -------------------------------------------------------------------------------- 1 | /* 2 | *=BEGIN CLOSED LICENSE 3 | * 4 | * Copyright(c) 2012 András Csizmadia. 5 | * http://www.vpmedia.eu 6 | * 7 | * For information about the licensing and copyright please 8 | * contact András Csizmadia at andras@vpmedia.eu. 9 | * 10 | *=END CLOSED LICENSE 11 | */ 12 | 13 | package hu.vpmedia.media.wms.dev; 14 | 15 | import java.util.*; 16 | 17 | import com.wowza.wms.amf.*; 18 | import com.wowza.wms.application.*; 19 | import com.wowza.wms.client.*; 20 | import com.wowza.wms.logging.*; 21 | import com.wowza.wms.module.*; 22 | import com.wowza.wms.request.*; 23 | import com.wowza.wms.server.*; 24 | import com.wowza.wms.stream.*; 25 | import hu.vpmedia.media.wms.plugin.bwcheck.BWCheck; 26 | import hu.vpmedia.media.core.*; 27 | 28 | import com.wowza.util.IOPerformanceCounter; 29 | 30 | public class WebcamDev extends ModuleBase 31 | { 32 | // Application Level API 33 | 34 | public void onAppStart( IApplicationInstance appInstance ) 35 | { 36 | getLogger().info( "onAppStart" + " " + appInstance.getApplication().getName() + "/"+appInstance.getName() ); 37 | } 38 | 39 | public void onAppStop(IApplicationInstance appInstance) 40 | { 41 | getLogger().info( "onAppStop" + " " + appInstance.getApplication().getName() + "/"+appInstance.getName() ); 42 | } 43 | 44 | // Client Level API 45 | 46 | public void onConnect( IClient client, RequestFunction function, AMFDataList params ) 47 | { 48 | getLogger().info( "onConnect" + " " + client.getClientId() ); 49 | getLogger().info( "flashVer: " + client.getFlashVer() 50 | + ", ip: " + client.getIp() 51 | + ", referrer: " + client.getReferrer() 52 | + ", connectTime: " + client.getConnectTime() 53 | + ", properties: " + client.getProperties() ); 54 | 55 | AMFDataObj param1 = (AMFDataObj)getParam(params, PARAM1); 56 | getLogger().info("Params: " + param1 ); 57 | 58 | client.acceptConnection(); 59 | 60 | // client.rejectConnection("ERROR_MESSAGE"); 61 | BWCheck.calculateClientBw( client ); 62 | } 63 | 64 | public void onDisconnect( IClient client ) 65 | { 66 | getLogger().info( "onDisconnect" + " " + client.getClientId() ); 67 | } 68 | 69 | public void onConnectAccept( IClient client ) 70 | { 71 | getLogger().info( "onConnectAccept" + " " + client.getClientId() ); 72 | // login 73 | AMFDataObj loginResult = new AMFDataObj(); 74 | loginResult.put( "userName", "user_" + client.getClientId() ); 75 | loginResult.put( "userType", UserTypes.GUEST ); 76 | client.call( "onRoomLogin", null, loginResult ); 77 | // user list 78 | AMFDataArray resultUsers = new AMFDataArray(); 79 | resultUsers.add( "user_" + client.getClientId() ); 80 | client.call( "onUserListChange", null, resultUsers ); 81 | // stream list 82 | AMFDataArray resultStreams = new AMFDataArray(); 83 | resultStreams.add( "user_" + client.getClientId() ); 84 | client.call( "onStreamListChange", null, resultStreams ); 85 | } 86 | 87 | public void onConnectReject( IClient client ) 88 | { 89 | getLogger().info( "onConnectReject" + " " + client.getClientId() ); 90 | } 91 | 92 | // Stream Level API 93 | 94 | public void onStreamCreate ( IMediaStream stream ) 95 | { 96 | getLogger().info( "onStreamCreate: " + stream.getSrc() ); 97 | } 98 | 99 | public void onStreamDestroy ( IMediaStream stream ) 100 | { 101 | getLogger().info( "onStreamDestroy: " + stream.getSrc() ); 102 | } 103 | 104 | // Flash Client API 105 | 106 | public void chatMessage( IClient client, RequestFunction function, AMFDataList params ) 107 | { 108 | getLogger().info( "chatMessage" + " " + client.getClientId() ); 109 | AMFDataItem param1 = (AMFDataItem)getParam(params, PARAM1); 110 | 111 | client.getAppInstance().broadcastMsg("onChatMessage", param1); 112 | //sendResult(client, params, "true"); 113 | } 114 | 115 | public void logoutRoom( IClient client, RequestFunction function, AMFDataList params ) 116 | { 117 | getLogger().info( "logoutRoom" + " " + client.getClientId() ); 118 | client.getAppInstance().shutdownClient(client); 119 | } 120 | 121 | // Flash Media Encoder API 122 | 123 | public void FCPublish( IClient client, RequestFunction function, AMFDataList params ) 124 | { 125 | getLogger().info( "FCPublish" + " " + client.getClientId() ); 126 | } 127 | 128 | public void FCUnpublish( IClient client, RequestFunction function, AMFDataList params ) 129 | { 130 | getLogger().info( "FCUnpublish" + " " + client.getClientId() ); 131 | } 132 | 133 | public void releaseStream( IClient client, RequestFunction function, AMFDataList params ) 134 | { 135 | getLogger().info( "FCUnpublish" + " " + client.getClientId() ); 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /vpmedia-wms-app/src/main/resources/Application.xml: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | 60000 18 | 12000 19 | 30000 20 | 21 | 22 | false 23 | 24 | 25 | 33 | 34 | 35 | live 36 | 37 | 38 | 39 | 40 | sharedobjects 41 | 42 | 43 | 44 | -1 45 | 46 | * 47 | * 48 | * 49 | * 50 | * 51 | * 52 | 53 | 54 | 55 | 60 | 61 | 62 | 63 | base 64 | Base 65 | com.wowza.wms.module.ModuleCore 66 | 67 | 68 | WebcamDev 69 | Main App 70 | hu.vpmedia.media.wms.dev.WebcamDev 71 | 72 | 73 | FME 74 | Flash Media Encoder plug-in 75 | hu.vpmedia.media.wms.plugin.fme.FME 76 | 77 | 78 | BWCheck 79 | Bandwidth Checker 80 | hu.vpmedia.media.wms.plugin.bwcheck.BWCheck 81 | 82 | 83 | properties 84 | Properties 85 | com.wowza.wms.module.ModuleProperties 86 | 87 | 88 | logging 89 | Client Logging 90 | com.wowza.wms.module.ModuleClientLogging 91 | 92 | 93 | 94 | 95 | 96 | 97 | connection_key 98 | J9BUEsaxiq5r2ZtPnakeg2MvAr477H7veryAE98AzEkeLdKkNl8H08wwMpjNpRGN 99 | 100 | 101 | production_server 102 | false 103 | 104 | 105 | debug_level 106 | 3 107 | 108 | 109 | gateway_url 110 | http://localhost/appframework_v2/src/common/php/gateway.php 111 | 112 | 113 | remoting_service 114 | vpmedia.Framework 115 | 116 | 117 | domainLock 118 | http://localhost 119 | 120 | 121 | maxApplicationConnections 122 | 100 123 | Integer 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /vpmedia-wms-bwcheck/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-bwcheck/src/main/java/hu/vpmedia/media/wms/plugin/bwcheck/BWCheck.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.bwcheck; 2 | 3 | import java.util.*; 4 | 5 | import com.wowza.wms.amf.*; 6 | import com.wowza.wms.client.*; 7 | import com.wowza.util.IOPerformanceCounter; 8 | import com.wowza.wms.module.*; 9 | import com.wowza.wms.request.*; 10 | import com.wowza.wms.logging.*; 11 | 12 | public class BWCheck extends ModuleBase { 13 | 14 | // BW Checker Encoder API 15 | 16 | public void checkBandwidth(IClient p_client, RequestFunction function, AMFDataList params) { 17 | getLogger().info("checkBandwidth"); 18 | calculateClientBw(p_client); 19 | } 20 | 21 | static public void calculateClientBw(IClient p_client) { 22 | getLogger().info("calculateClientBw"); 23 | AMFDataArray payload = new AMFDataArray(); 24 | for (int i=0;i<1200;i++) { 25 | payload.add(new AMFDataItem((double)Math.random())); 26 | } 27 | p_client.getProperties().put("payload", payload); 28 | AMFDataArray payload_1 = new AMFDataArray(); 29 | for (int i=0;i<12000;i++) { 30 | payload_1.add(new AMFDataItem((double)Math.random())); 31 | } 32 | p_client.getProperties().put("payload_1", payload_1); 33 | AMFDataArray payload_2 = new AMFDataArray(); 34 | for (int i=0;i<120000;i++) { 35 | payload_2.add(new AMFDataItem((double)Math.random())); 36 | } 37 | p_client.getProperties().put("payload_2", payload_2); 38 | 39 | List beginningValues = null; 40 | final IOPerformanceCounter beginningStats = p_client.getTotalIOPerformanceCounter(); 41 | final Long start = new Long(System.nanoTime()/1000000); //new Long(System.currentTimeMillis()); 42 | 43 | class ResultObj implements IModuleCallResult { 44 | IClient client = null; 45 | double latency = 0; 46 | double cumLatency = 1; 47 | int count = 0; 48 | int sent = 0; 49 | double kbitDown = 0; 50 | double deltaDown = 0; 51 | double deltaTime = 0; 52 | 53 | 54 | List pakSent = new ArrayList(); 55 | List pakRecv = new ArrayList(); 56 | 57 | 58 | List beginningValues = null; 59 | 60 | public ResultObj(IClient p_client) { 61 | this.client = p_client; 62 | 63 | beginningValues = new ArrayList(); 64 | beginningValues.add(0, beginningStats.getMessagesOutBytes()); 65 | beginningValues.add(1, beginningStats.getMessagesInBytes()); 66 | beginningValues.add(2, start); 67 | } 68 | 69 | public void onResult(IClient client, RequestFunction function, AMFDataList params) { 70 | Long now1 = new Long(System.nanoTime()/1000000); //new Long(System.currentTimeMillis()); 71 | pakRecv.add(now1); 72 | Long timePassed = (now1 - beginningValues.get(2)); 73 | count++; 74 | 75 | if (count == 1) { 76 | latency = Math.min(timePassed, 800); 77 | latency = Math.max(latency, 10); 78 | 79 | //WMSLoggerFactory.getLogger(null).info("count: "+count+ " sent: "+sent+" timePassed: "+timePassed+" latency: "+latency); 80 | 81 | // We now have a latency figure so can start sending test data. 82 | // Second call. 1st packet sent 83 | pakSent.add(now1); 84 | sent++; 85 | this.client.call("onBWCheck", this, this.client.getProperties().get("payload")); 86 | } 87 | 88 | //To run a very quick test, uncomment the following if statement and comment out the next 3 if statements. 89 | 90 | /* 91 | else if (count == 2 && (timePassed < 2000)) { 92 | pakSent.add(now1); 93 | sent++; 94 | cumLatency++; 95 | this.client.call("onBWCheck", this, this.client.getProperties().get("payload")); 96 | } 97 | */ 98 | 99 | //The following will progressivly increase the size of the packets been sent until 1 second has elapsed. 100 | else if ((count > 1 && count < 3) && (timePassed < 1000)) { 101 | pakSent.add(now1); 102 | sent++; 103 | cumLatency++; 104 | this.client.call("onBWCheck", this, this.client.getProperties().get("payload")); 105 | } 106 | else if ((count >=3 && count < 6) && (timePassed < 1000)) { 107 | pakSent.add(now1); 108 | sent++; 109 | cumLatency++; 110 | this.client.call("onBWCheck", this, this.client.getProperties().get("payload_1")); 111 | } 112 | else if (count >= 6 && (timePassed < 1000)) { 113 | pakSent.add(now1); 114 | sent++; 115 | cumLatency++; 116 | this.client.call("onBWCheck", this, this.client.getProperties().get("payload_2")); 117 | } 118 | //Time elapsed now do the calcs 119 | else if (sent == count) { 120 | // see if we need to normalize latency 121 | if (latency >= 100) { 122 | //make sure satelite and modem is detected properly 123 | if (pakRecv.get(1) - pakRecv.get(0) > 1000) { 124 | latency = 100; 125 | } 126 | } 127 | 128 | this.client.getProperties().remove("payload"); 129 | this.client.getProperties().remove("payload_1"); 130 | this.client.getProperties().remove("payload_2"); 131 | // tidy up 132 | // and compute bandwidth 133 | IOPerformanceCounter endStats = this.client.getTotalIOPerformanceCounter(); 134 | deltaDown = (endStats.getMessagesOutBytes() - beginningValues.get(0)) * 8 / 1000; // bytes to kbits 135 | deltaTime = ((now1 - beginningValues.get(2)) - (latency * cumLatency)) / 1000; // total dl time - latency for each packet sent in secs 136 | if (deltaTime <= 0) { 137 | deltaTime = (now1 - beginningValues.get(2)) / 1000; 138 | } 139 | kbitDown = Math.round(deltaDown / deltaTime); // kbits / sec 140 | 141 | this.client.call("onBWDone", null, this.kbitDown, this.deltaDown, this.deltaTime, this.latency); 142 | } 143 | } 144 | } 145 | getLogger().info("ResultObj"); 146 | ResultObj res = new ResultObj(p_client); 147 | 148 | res.pakSent.add(start); 149 | res.sent++; 150 | p_client.call("onBWCheck", res, ""); // 1st call sends empty packet to get latency 151 | } 152 | } -------------------------------------------------------------------------------- /vpmedia-wms-connectionlimiter/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-connectionlimiter/src/main/java/hu/vpmedia/media/wms/plugin/connectionlimiter/ConnectionLimiter.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.connectionlimiter; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.application.*; 5 | import com.wowza.wms.client.*; 6 | import com.wowza.wms.request.*; 7 | import com.wowza.wms.module.*; 8 | 9 | public class ConnectionLimiter extends ModuleBase 10 | { 11 | static final public int MAXCONNECTIONS = 200; 12 | 13 | private int maxApplicationConnections = MAXCONNECTIONS; 14 | 15 | public void onAppStart(IApplicationInstance appInstance) 16 | { 17 | this.maxApplicationConnections = appInstance.getProperties().getPropertyInt("maxApplicationConnections", maxApplicationConnections); 18 | } 19 | 20 | public void onConnect(IClient client, RequestFunction function, AMFDataList params) 21 | { 22 | IApplicationInstance appInstance = client.getAppInstance(); 23 | IApplication app = appInstance.getApplication(); 24 | long count = app.getConnectionCounter().getCurrent(); 25 | if ((count+1) > this.maxApplicationConnections) 26 | { 27 | client.rejectConnection("Over application connection limit ["+app.getName()+"/"+appInstance.getName()+"]: Limit is: "+this.maxApplicationConnections); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /vpmedia-wms-dbauthentication/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-dbauthentication/src/main/java/hu/vpmedia/media/wms/plugin/dbauthentication/DBAuthentication.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.dbauthentication; 2 | 3 | import java.sql.*; 4 | 5 | import com.wowza.wms.application.*; 6 | import com.wowza.wms.amf.*; 7 | import com.wowza.wms.client.*; 8 | import com.wowza.wms.module.*; 9 | import com.wowza.wms.request.*; 10 | 11 | public class DBAuthentication extends ModuleBase 12 | { 13 | 14 | static public void onConnect(IClient client, RequestFunction function, 15 | AMFDataList params) 16 | { 17 | 18 | String userName = getParamString(params, PARAM1); 19 | String password = getParamString(params, PARAM2); 20 | 21 | IApplicationInstance appInstance = client.getAppInstance(); 22 | 23 | String dbUser = appInstance.getProperties().getPropertyStr("dbuser"); 24 | String dbPass = appInstance.getProperties().getPropertyStr("dbpass"); 25 | String dbName = appInstance.getProperties().getPropertyStr("dbname"); 26 | String dbHost = appInstance.getProperties().getPropertyStr("dbhost"); 27 | 28 | // preload the driver class 29 | try 30 | { 31 | Class.forName("com.mysql.jdbc.Driver").newInstance(); 32 | } 33 | catch (Exception e) 34 | { 35 | getLogger().error("Error loading: com.mysql.jdbc.Driver: "+e.toString()); 36 | } 37 | 38 | Connection conn = null; 39 | try 40 | { 41 | conn = DriverManager.getConnection("jdbc:mysql://" + dbHost + "/" + dbName + "?user=" + dbUser+"&password=" + dbPass); 42 | 43 | Statement stmt = null; 44 | ResultSet rs = null; 45 | 46 | try 47 | { 48 | stmt = conn.createStatement(); 49 | rs = stmt.executeQuery("SELECT id(*) as id FROM user_auth where name = '"+userName+"' and word = '"+password+"'"); 50 | if (rs.next() == true) 51 | { 52 | if (rs.getInt("id") > 0) 53 | { 54 | client.acceptConnection(); 55 | } 56 | } 57 | 58 | } 59 | catch (SQLException sqlEx) 60 | { 61 | getLogger().error("sqlexecuteException: " + sqlEx.toString()); 62 | } 63 | finally 64 | { 65 | // it is a good idea to release resources in a finally{} block 66 | // in reverse-order of their creation if they are no-longer needed 67 | 68 | if (rs != null) 69 | { 70 | try 71 | { 72 | rs.close(); 73 | } 74 | catch (SQLException sqlEx) 75 | { 76 | 77 | rs = null; 78 | } 79 | } 80 | 81 | if (stmt != null) 82 | { 83 | try 84 | { 85 | stmt.close(); 86 | } 87 | catch (SQLException sqlEx) 88 | { 89 | stmt = null; 90 | } 91 | } 92 | } 93 | 94 | conn.close(); 95 | } 96 | catch (SQLException ex) 97 | { 98 | // handle any errors 99 | System.out.println("SQLException: " + ex.getMessage()); 100 | System.out.println("SQLState: " + ex.getSQLState()); 101 | System.out.println("VendorError: " + ex.getErrorCode()); 102 | } 103 | 104 | getLogger().info("onConnect: " + client.getClientId()); 105 | } 106 | 107 | static public void onConnectAccept(IClient client) 108 | { 109 | getLogger().info("onConnectAccept: " + client.getClientId()); 110 | } 111 | 112 | static public void onConnectReject(IClient client) 113 | { 114 | getLogger().info("onConnectReject: " + client.getClientId()); 115 | } 116 | 117 | static public void onDisconnect(IClient client) 118 | { 119 | getLogger().info("onDisconnect: " + client.getClientId()); 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /vpmedia-wms-fme/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-fme/src/main/java/hu/vpmedia/media/wms/plugin/fme/FME.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.fme; 2 | 3 | import java.util.*; 4 | 5 | import com.wowza.wms.amf.*; 6 | import com.wowza.wms.client.*; 7 | import com.wowza.util.IOPerformanceCounter; 8 | import com.wowza.wms.module.*; 9 | import com.wowza.wms.request.*; 10 | import com.wowza.wms.logging.*; 11 | 12 | public class FME extends ModuleBase 13 | { 14 | 15 | // Flash Media Encoder API 16 | 17 | public void FCPublish(IClient client, RequestFunction function, AMFDataList params) 18 | { 19 | getLogger().info("FCPublish"); 20 | } 21 | 22 | public void FCUnpublish(IClient client, RequestFunction function, AMFDataList params) 23 | { 24 | getLogger().info("FCUnpublish"); 25 | } 26 | 27 | public void releaseStream(IClient client, RequestFunction function, AMFDataList params) 28 | { 29 | getLogger().info("FCUnpublish"); 30 | } 31 | } -------------------------------------------------------------------------------- /vpmedia-wms-hotlinkdenial/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-hotlinkdenial/src/main/java/hu/vpmedia/media/wms/plugin/hotlinkdenial/HotlinkDenial.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.hotlinkdenial; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.client.*; 5 | import com.wowza.wms.module.*; 6 | import com.wowza.wms.request.*; 7 | 8 | public class HotlinkDenial extends ModuleBase 9 | { 10 | 11 | public void onConnect(IClient client, RequestFunction function, 12 | AMFDataList params) { 13 | getLogger().info("onConnect: " + client.getClientId()); 14 | boolean reject = true; 15 | try 16 | { 17 | String pageUrl = client.getProperties().getPropertyStr("connectpageUrl").toLowerCase(); 18 | String[] domainLock = client.getAppInstance().getProperties().getPropertyStr("domainLock").toLowerCase().split(","); 19 | getLogger().info("domainLock: " + client.getAppInstance().getProperties().getPropertyStr("domainLock").toLowerCase()); 20 | getLogger().info("pageUrl: " + pageUrl); 21 | for (int i=0; i= 0) 44 | { 45 | offset += numRead; 46 | } 47 | 48 | if (offset < fileBytes.length) 49 | { 50 | throw new IOException("Could not completely read file "+mediaFile.getName()); 51 | } 52 | 53 | in.close(); 54 | } else { 55 | getLogger().info("file read error!"); 56 | } 57 | } 58 | } 59 | catch (FileNotFoundException e) 60 | { 61 | e.printStackTrace(); 62 | } 63 | catch (IOException e) 64 | { 65 | e.printStackTrace(); 66 | } 67 | 68 | sendResult(client, params, AMFDataByteArray.wrap(fileBytes)); 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /vpmedia-wms-mediareader/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-mediareader/src/main/java/hu/vpmedia/media/wms/plugin/mediareader/MediaReaderFLVInjectMetadata.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.mediareader; 2 | 3 | import java.util.*; 4 | import java.nio.*; 5 | 6 | import com.wowza.wms.mediareader.flv.*; 7 | import com.wowza.wms.amf.*; 8 | 9 | public class MediaReaderFLVInjectMetadata extends MediaReaderFLV 10 | { 11 | public List getMetadata() 12 | { 13 | List ret = super.getMetadata(); 14 | 15 | while(true) 16 | { 17 | if (ret == null) 18 | break; 19 | if (ret.size() <= 0) 20 | break; 21 | 22 | ByteBuffer packet = (ByteBuffer)ret.get(0); 23 | 24 | AMFDataList myMetadata = new AMFDataList(packet); 25 | 26 | AMFDataMixedArray dataObj = (AMFDataMixedArray)myMetadata.get(1); 27 | dataObj.put("wowzafield", new AMFDataItem("wowzadata")); 28 | 29 | byte[] data = myMetadata.serialize(); 30 | ByteBuffer newPacket = ByteBuffer.wrap(data); 31 | ret.set(0, newPacket); 32 | break; 33 | } 34 | 35 | return ret; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /vpmedia-wms-mediastreampassthru/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-mediastreampassthru/src/main/java/hu/vpmedia/media/wms/plugin/mediastreampassthru/MediaStreamPassThru.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.mediastreampassthru; 2 | 3 | import java.nio.*; 4 | 5 | import com.wowza.wms.application.*; 6 | import com.wowza.wms.stream.*; 7 | import com.wowza.wms.stream.live.*; 8 | import com.wowza.wms.logging.*; 9 | 10 | public class MediaStreamPassThru extends MediaStreamLive 11 | { 12 | private int audioBytes = 0; 13 | private int videoBytes = 0; 14 | private int dataBytes = 0; 15 | private ByteBuffer audioBuffer = null; 16 | private ByteBuffer dataBuffer = null; 17 | private ByteBuffer videoBuffer = null; 18 | 19 | public MediaStreamPassThru() 20 | { 21 | super(); 22 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: create"); 23 | } 24 | 25 | public void init(MediaStreamMap parent, int src, WMSProperties properties) 26 | { 27 | super.init(parent, src, properties); 28 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: init"); 29 | } 30 | 31 | public void startPublishing() 32 | { 33 | super.startPublishing(); 34 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: startPublishing"); 35 | } 36 | 37 | public void stopPublishing() 38 | { 39 | super.stopPublishing(); 40 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: stopPublishing"); 41 | } 42 | 43 | public void publish() 44 | { 45 | super.publish(); 46 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: publish"); 47 | } 48 | 49 | public void trim() 50 | { 51 | super.trim(); 52 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: trim"); 53 | } 54 | 55 | public int getAudioMissing() 56 | { 57 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: getAudioMissing: "+(this.getAudioSize()-this.audioBytes)); 58 | return this.getAudioSize()-this.audioBytes; 59 | } 60 | 61 | public int getVideoMissing() 62 | { 63 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: getVideoMissing: "+(this.getVideoSize()-this.videoBytes)); 64 | return this.getVideoSize()-this.videoBytes; 65 | } 66 | 67 | public int getDataMissing() 68 | { 69 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: getDataMissing: "+(this.getDataSize()-this.dataBytes)); 70 | return this.getDataSize()-this.dataBytes; 71 | } 72 | 73 | public void addVideoData(byte[] data, int offset, int size) 74 | { 75 | super.addVideoData(data, offset, size); 76 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: addVideoData: offset:"+offset+" size:"+size); 77 | if (this.videoBuffer == null) 78 | this.videoBuffer = ByteBuffer.allocate(this.getVideoSize()); 79 | 80 | this.videoBytes += size; 81 | this.videoBuffer.put(data, offset, size); 82 | if (this.videoBytes == this.getVideoSize()) 83 | { 84 | this.videoBytes = 0; 85 | 86 | // this packets data is complete process 87 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: videoPacketComplete: timecode:"+this.getVideoTC()+" size:"+this.getVideoSize()); 88 | 89 | this.videoBuffer = null; 90 | } 91 | } 92 | 93 | public void addDataData(byte[] data, int offset, int size) 94 | { 95 | super.addDataData(data, offset, size); 96 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: addDataData: offset:"+offset+" size:"+size); 97 | if (this.dataBuffer == null) 98 | this.dataBuffer = ByteBuffer.allocate(this.getDataSize()); 99 | 100 | this.dataBytes += size; 101 | this.dataBuffer.put(data, offset, size); 102 | if (this.dataBytes == this.getDataSize()) 103 | { 104 | this.dataBytes = 0; 105 | 106 | // this packets data is complete process 107 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: dataPacketComplete: timecode:"+this.getDataTC()+" size:"+this.getDataSize()); 108 | 109 | this.dataBuffer = null; 110 | } 111 | } 112 | 113 | public void addAudioData(byte[] data, int offset, int size) 114 | { 115 | super.addAudioData(data, offset, size); 116 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: addAudioData: offset:"+offset+" size:"+size); 117 | if (this.audioBuffer == null) 118 | this.audioBuffer = ByteBuffer.allocate(this.getAudioSize()); 119 | 120 | this.audioBytes += size; 121 | this.audioBuffer.put(data, offset, size); 122 | if (this.audioBytes == this.getAudioSize()) 123 | { 124 | this.audioBytes = 0; 125 | 126 | // this packets data is complete process 127 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: audioPacketComplete: timecode:"+this.getAudioTC()+" size:"+this.getAudioSize()); 128 | 129 | this.audioBuffer = null; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /vpmedia-wms-mediastreampassthru/src/main/java/hu/vpmedia/media/wms/plugin/mediastreampassthru/MediaStreamPassThruRecord.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.mediastreampassthru; 2 | 3 | import java.nio.*; 4 | 5 | import com.wowza.wms.application.*; 6 | import com.wowza.wms.stream.*; 7 | import com.wowza.wms.stream.live.*; 8 | import com.wowza.wms.logging.*; 9 | 10 | public class MediaStreamPassThruRecord extends MediaStreamLiveRecord 11 | { 12 | private int audioBytes = 0; 13 | private int videoBytes = 0; 14 | private int dataBytes = 0; 15 | private ByteBuffer audioBuffer = null; 16 | private ByteBuffer dataBuffer = null; 17 | private ByteBuffer videoBuffer = null; 18 | 19 | public MediaStreamPassThruRecord() 20 | { 21 | super(); 22 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: create"); 23 | } 24 | 25 | public void init(MediaStreamMap parent, int src, WMSProperties properties) 26 | { 27 | super.init(parent, src, properties); 28 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: init"); 29 | } 30 | 31 | public void startPublishing() 32 | { 33 | super.startPublishing(); 34 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: startPublishing"); 35 | } 36 | 37 | public void stopPublishing() 38 | { 39 | super.stopPublishing(); 40 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: stopPublishing"); 41 | } 42 | 43 | public void publish() 44 | { 45 | super.publish(); 46 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: publish"); 47 | } 48 | 49 | public void trim() 50 | { 51 | super.trim(); 52 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: trim"); 53 | } 54 | 55 | public int getAudioMissing() 56 | { 57 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: getAudioMissing: "+(this.getAudioSize()-this.audioBytes)); 58 | return this.getAudioSize()-this.audioBytes; 59 | } 60 | 61 | public int getVideoMissing() 62 | { 63 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: getVideoMissing: "+(this.getVideoSize()-this.videoBytes)); 64 | return this.getVideoSize()-this.videoBytes; 65 | } 66 | 67 | public int getDataMissing() 68 | { 69 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: getDataMissing: "+(this.getDataSize()-this.dataBytes)); 70 | return this.getDataSize()-this.dataBytes; 71 | } 72 | 73 | public void addVideoData(byte[] data, int offset, int size) 74 | { 75 | super.addVideoData(data, offset, size); 76 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: addVideoData: offset:"+offset+" size:"+size); 77 | if (this.videoBuffer == null) 78 | this.videoBuffer = ByteBuffer.allocate(this.getVideoSize()); 79 | 80 | this.videoBytes += size; 81 | this.videoBuffer.put(data, offset, size); 82 | if (this.videoBytes == this.getVideoSize()) 83 | { 84 | this.videoBytes = 0; 85 | 86 | // this packets data is complete process 87 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: videoPacketComplete: timecode:"+this.getVideoTC()+" size:"+this.getVideoSize()); 88 | 89 | this.videoBuffer = null; 90 | } 91 | } 92 | 93 | public void addDataData(byte[] data, int offset, int size) 94 | { 95 | super.addDataData(data, offset, size); 96 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: addDataData: offset:"+offset+" size:"+size); 97 | if (this.dataBuffer == null) 98 | this.dataBuffer = ByteBuffer.allocate(this.getDataSize()); 99 | 100 | this.dataBytes += size; 101 | this.dataBuffer.put(data, offset, size); 102 | if (this.dataBytes == this.getDataSize()) 103 | { 104 | this.dataBytes = 0; 105 | 106 | // this packets data is complete process 107 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: dataPacketComplete: timecode:"+this.getDataTC()+" size:"+this.getDataSize()); 108 | 109 | this.dataBuffer = null; 110 | } 111 | } 112 | 113 | public void addAudioData(byte[] data, int offset, int size) 114 | { 115 | super.addAudioData(data, offset, size); 116 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: addAudioData: offset:"+offset+" size:"+size); 117 | if (this.audioBuffer == null) 118 | this.audioBuffer = ByteBuffer.allocate(this.getAudioSize()); 119 | 120 | this.audioBytes += size; 121 | this.audioBuffer.put(data, offset, size); 122 | if (this.audioBytes == this.getAudioSize()) 123 | { 124 | this.audioBytes = 0; 125 | 126 | // this packets data is complete process 127 | WMSLoggerFactory.getLogger(null).info("MediaStreamPassThru: audioPacketComplete: timecode:"+this.getAudioTC()+" size:"+this.getAudioSize()); 128 | 129 | this.audioBuffer = null; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /vpmedia-wms-remoting/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-remoting/src/main/java/hu/vpmedia/media/wms/plugin/remoting/FlashRemoteMessage.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.remoting; 2 | 3 | import com.wowza.wms.amf.AMFData; 4 | 5 | public class FlashRemoteMessage 6 | { 7 | String handlerName = null; 8 | int responseId = -1; 9 | AMFData[] amfParams = null; 10 | IFlashRemoteResponse response = null; 11 | } 12 | -------------------------------------------------------------------------------- /vpmedia-wms-remoting/src/main/java/hu/vpmedia/media/wms/plugin/remoting/FlashRemoteResponseReader.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.remoting; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import com.wowza.util.*; 6 | import com.wowza.wms.amf.*; 7 | import com.wowza.wms.logging.*; 8 | 9 | public class FlashRemoteResponseReader 10 | { 11 | byte[] buffer = null; 12 | int offset = 0; 13 | int len = 0; 14 | 15 | public FlashRemoteResponseReader(byte[] buffer, int len) 16 | { 17 | this.buffer = buffer; 18 | this.len = len; 19 | } 20 | 21 | public int remaining() 22 | { 23 | return this.len-this.offset; 24 | } 25 | 26 | public void inc(int inc) 27 | { 28 | this.offset += inc; 29 | } 30 | 31 | public void skip(int inc) 32 | { 33 | inc(inc); 34 | } 35 | 36 | public int position() 37 | { 38 | return this.offset; 39 | } 40 | 41 | public void position(int offset) 42 | { 43 | this.offset = offset; 44 | } 45 | 46 | public AMFData getAMF(long len) 47 | { 48 | AMFData ret = null; 49 | try 50 | { 51 | //System.out.println("getAMF: "+this.buffer+":"+this.offset+":"+len); 52 | 53 | if (len >= 0x0ffffffffL) 54 | { 55 | len = this.remaining(); 56 | ByteBuffer dataBuffer = ByteBuffer.wrap(this.buffer, this.offset, (int)len); 57 | long startPos = dataBuffer.position(); 58 | ret = AMFData.deserializeInnerObject(dataBuffer, AMFData.createContextDeserialize()); 59 | len = dataBuffer.position()-startPos; 60 | } 61 | else 62 | { 63 | ByteBuffer dataBuffer = ByteBuffer.wrap(this.buffer, this.offset, (int)len); 64 | ret = AMFData.deserializeInnerObject(dataBuffer, AMFData.createContextDeserialize()); 65 | } 66 | } 67 | catch(Exception e) 68 | { 69 | WMSLoggerFactory.getLogger(null).error("HTTPUtils.getString: "+e.toString()); 70 | e.printStackTrace(); 71 | } 72 | this.inc((int)len); 73 | 74 | return ret; 75 | } 76 | 77 | public int getByte() 78 | { 79 | int ret = 0; 80 | try 81 | { 82 | ret = BufferUtils.byteArrayToInt(this.buffer, this.offset, 1); 83 | } 84 | catch(Exception e) 85 | { 86 | WMSLoggerFactory.getLogger(null).error("HTTPUtils.getString: "+e.toString()); 87 | e.printStackTrace(); 88 | } 89 | this.inc(1); 90 | 91 | return ret; 92 | } 93 | 94 | public int getShort() 95 | { 96 | int ret = 0; 97 | try 98 | { 99 | ret = BufferUtils.byteArrayToInt(this.buffer, this.offset, 2); 100 | } 101 | catch(Exception e) 102 | { 103 | WMSLoggerFactory.getLogger(null).error("HTTPUtils.getString: "+e.toString()); 104 | e.printStackTrace(); 105 | } 106 | this.inc(2); 107 | 108 | return ret; 109 | } 110 | 111 | public long getInt() 112 | { 113 | long ret = 0; 114 | try 115 | { 116 | ret = BufferUtils.byteArrayToLong(this.buffer, this.offset, 4); 117 | } 118 | catch(Exception e) 119 | { 120 | WMSLoggerFactory.getLogger(null).error("HTTPUtils.getString: "+e.toString()); 121 | e.printStackTrace(); 122 | } 123 | this.inc(4); 124 | 125 | return ret; 126 | } 127 | 128 | public String getString() 129 | { 130 | String ret = null; 131 | 132 | int len = 0; 133 | try 134 | { 135 | len = BufferUtils.byteArrayToInt(this.buffer, this.offset, 2); 136 | this.inc(2); 137 | 138 | if (len > 0) 139 | ret = BufferUtils.byteArrayToString(this.buffer, this.offset, len); 140 | else 141 | ret = ""; 142 | } 143 | catch(Exception e) 144 | { 145 | WMSLoggerFactory.getLogger(null).error("HTTPUtils.getString: "+e.toString()); 146 | e.printStackTrace(); 147 | } 148 | this.inc(len); 149 | 150 | return ret; 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /vpmedia-wms-remoting/src/main/java/hu/vpmedia/media/wms/plugin/remoting/IFlashRemoteResponse.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.remoting; 2 | 3 | import com.wowza.wms.amf.*; 4 | 5 | /** 6 | * 7 | *

IFlashRemoteResponse: Interface for FlashRemoteSession calls.

8 | * @author Wowza Media Systems 9 | * 10 | */ 11 | 12 | public interface IFlashRemoteResponse 13 | { 14 | /** 15 | * Called if the Flash Remote call returns a value and the call was successful. 16 | * @param handlerName handler name 17 | * @param res message data 18 | */ 19 | public abstract void onResult(String handlerName, AMFData res); 20 | 21 | /** 22 | * Called if the Flash Remote call failed. 23 | * @param handlerName handler name 24 | * @param statusCode response code (HTTP status code) 25 | * @param responseMsg response message 26 | */ 27 | public abstract void onFailure(String handlerName, int statusCode, String responseMsg); 28 | } 29 | -------------------------------------------------------------------------------- /vpmedia-wms-remoting/src/main/java/hu/vpmedia/media/wms/plugin/remoting/IFlashRemotingNotify.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.remoting; 2 | 3 | import com.wowza.wms.amf.*; 4 | 5 | /** 6 | * 7 | *

IFlashRemotingNotify: FlashRemoteSession listener interface. Implement this interface and call FlashRemoteSession.addListener() 8 | * to add a raw listener to the session.

9 | * @author Wowza Media Systems 10 | * 11 | */ 12 | 13 | public interface IFlashRemotingNotify 14 | { 15 | /** 16 | * Called for each header message 17 | * @param headerName header name 18 | * @param data header data 19 | */ 20 | public abstract void onHeader(String headerName, AMFData data); 21 | 22 | /** 23 | * Called for each message 24 | * @param responseURI response URI 25 | * @param responseTarget response target 26 | * @param data message data 27 | */ 28 | public abstract void onMessage(String responseURI, String responseTarget, AMFData data); 29 | 30 | /** 31 | * Called if the FlashRemote call fails 32 | * @param responseCode response code (HTTP status code) 33 | * @param responseMsg response message 34 | */ 35 | public abstract void onRequestFailure(int responseCode, String responseMsg); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /vpmedia-wms-security/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/HTTPSecureTokens.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.security; 2 | 3 | import com.wowza.wms.application.WMSProperties; 4 | import com.wowza.wms.http.*; 5 | import com.wowza.wms.logging.WMSLogger; 6 | import com.wowza.wms.logging.WMSLoggerFactory; 7 | import hu.vpmedia.media.wms.plugin.security.encryption.TEA; 8 | import com.wowza.wms.vhost.HostPort; 9 | import com.wowza.wms.vhost.IVHost; 10 | import java.io.OutputStream; 11 | import java.util.Map; 12 | 13 | public class HTTPSecureTokens 14 | implements IHTTPProvider 15 | { 16 | 17 | public HTTPSecureTokens() 18 | { 19 | properties = null; 20 | } 21 | 22 | public void onBind(IVHost ivhost, HostPort hostport) 23 | { 24 | } 25 | 26 | public void onUnbind(IVHost ivhost, HostPort hostport) 27 | { 28 | } 29 | 30 | public void setProperties(WMSProperties wmsproperties) 31 | { 32 | properties = wmsproperties; 33 | } 34 | 35 | public void onHTTPRequest(IVHost ivhost, IHTTPRequest ihttprequest, IHTTPResponse ihttpresponse) 36 | { 37 | String s = ihttprequest.getParameter("secureTokenName"); 38 | if(s == null) 39 | s = "default"; 40 | if(s.length() == 0) 41 | s = "default"; 42 | SecureTokenManager securetokenmanager = SecureTokenManager.getInstance(ivhost); 43 | Map map = securetokenmanager.getTokenList(); 44 | String s1 = securetokenmanager.newGUID(); 45 | Map map1 = securetokenmanager.getSecureTokenDefs(); 46 | SecureTokenDef securetokendef = (SecureTokenDef)map1.get(s); 47 | String s2 = ""; 48 | if(securetokendef != null) 49 | { 50 | SecureToken securetoken = new SecureToken(s1, securetokendef); 51 | synchronized(map) 52 | { 53 | map.put(s1, securetoken); 54 | } 55 | s2 = TEA.encrypt(s1, securetokendef.getSharedSecret()); 56 | } else 57 | { 58 | // WMSLoggerFactory.getLogger(com/webcam/media/wms/plugin/security/HTTPSecureTokens).error((new StringBuilder()).append("Secure token definition missing for (").append(s).append(").").toString()); 59 | } 60 | String s3 = (new StringBuilder()).append("connectToken=").append(s2).toString(); 61 | try 62 | { 63 | OutputStream outputstream = ihttpresponse.getOutputStream(); 64 | byte abyte0[] = s3.toString().getBytes(); 65 | outputstream.write(abyte0); 66 | } 67 | catch(Exception exception) 68 | { 69 | // WMSLoggerFactory.getLogger(com/webcam/media/wms/plugin/security/HTTPSecureTokens).error((new StringBuilder()).append("HTMLServerVersion: ").append(exception.toString()).toString()); 70 | } 71 | } 72 | 73 | private WMSProperties properties; 74 | } 75 | -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/ModuleSecureToken.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.security; 2 | 3 | import com.wowza.wms.amf.AMFDataItem; 4 | import com.wowza.wms.amf.AMFDataList; 5 | import com.wowza.wms.application.*; 6 | import com.wowza.wms.client.Client; 7 | import com.wowza.wms.client.IClient; 8 | import com.wowza.wms.logging.WMSLogger; 9 | import com.wowza.wms.module.*; 10 | import hu.vpmedia.media.wms.plugin.security.encryption.TEA; 11 | import com.wowza.wms.request.RequestFunction; 12 | import com.wowza.wms.stream.IMediaStream; 13 | import com.wowza.wms.stream.IMediaStreamActionNotify; 14 | 15 | public class ModuleSecureToken extends ModuleBase 16 | implements IModuleOnConnect, IModuleOnStream 17 | { 18 | class StreamActions 19 | implements IMediaStreamActionNotify 20 | { 21 | 22 | public void onPause(IMediaStream imediastream, boolean flag, double d) 23 | { 24 | } 25 | 26 | public void onPlay(IMediaStream imediastream, String s, double d, double d1, int i) 27 | { 28 | if(doPlay) 29 | checkSecureToken(imediastream.getClient()); 30 | } 31 | 32 | public void onPublish(IMediaStream imediastream, String s, boolean flag, boolean flag1) 33 | { 34 | if(doPublish) 35 | checkSecureToken(imediastream.getClient()); 36 | } 37 | 38 | public void onSeek(IMediaStream imediastream, double d) 39 | { 40 | } 41 | 42 | public void onStop(IMediaStream imediastream) 43 | { 44 | } 45 | 46 | public void onUnPublish(IMediaStream imediastream, String s, boolean flag, boolean flag1) 47 | { 48 | } 49 | 50 | final ModuleSecureToken this$0; 51 | 52 | StreamActions() 53 | { 54 | super(); 55 | this$0 = ModuleSecureToken.this; 56 | } 57 | } 58 | 59 | 60 | public ModuleSecureToken() 61 | { 62 | doPlay = false; 63 | doPublish = false; 64 | doCreate = true; 65 | streamActions = new StreamActions(); 66 | } 67 | 68 | public void onConnect(IClient iclient, RequestFunction requestfunction, AMFDataList amfdatalist) 69 | { 70 | SecureTokenManager securetokenmanager = SecureTokenManager.getInstance(iclient.getVHost()); 71 | String s = securetokenmanager.newGUID(); 72 | iclient.getProperties().put("secureToken", s); 73 | iclient.getProperties().put("secureTokenOK", new Boolean(false)); 74 | String s1 = (String)iclient.getAppInstance().getProperties().get("secureTokenSharedSecret"); 75 | if(s1 != null) 76 | { 77 | iclient.addAcceptConnectionAttribute("secureToken", TEA.encrypt(s, s1)); 78 | } else 79 | { 80 | String s2 = (new StringBuilder()).append("Error: SecureToken: secureTokenSharedSecret property not defined in: ").append(iclient.getApplication().getConfigPath()).toString(); 81 | iclient.addAcceptConnectionAttribute("secureTokenError", s2); 82 | getLogger().error(s2); 83 | } 84 | String s3 = (String)iclient.getAppInstance().getProperties().get("secureTokenTarget"); 85 | if(s3 != null) 86 | { 87 | doPlay = false; 88 | doPublish = false; 89 | doCreate = false; 90 | String as[] = s3.split("[,]"); 91 | for(int i = 0; i < as.length; i++) 92 | { 93 | String s4 = as[i].trim().toLowerCase(); 94 | if(s4.equals("create")) 95 | { 96 | doCreate = true; 97 | continue; 98 | } 99 | if(s4.equals("publish")) 100 | { 101 | doPublish = true; 102 | continue; 103 | } 104 | if(s4.equals("play")) 105 | doPlay = true; 106 | } 107 | 108 | } 109 | getLogger().info((new StringBuilder()).append("SecureTokenTarget: create:").append(doCreate).append(" play:").append(doPlay).append(" publish:").append(doPublish).toString()); 110 | } 111 | 112 | private void killClient(IClient iclient) 113 | { 114 | ((Client)iclient).setShutdownClient(true); 115 | ((Client)iclient).doIdle(); 116 | } 117 | 118 | public void secureTokenResponse(IClient iclient, RequestFunction requestfunction, AMFDataList amfdatalist) 119 | { 120 | String s = amfdatalist.getString(3); 121 | WMSProperties wmsproperties = iclient.getProperties(); 122 | String s1 = null; 123 | synchronized(wmsproperties) 124 | { 125 | s1 = (String)wmsproperties.get("secureToken"); 126 | } 127 | boolean flag = false; 128 | if(s1 == null) 129 | { 130 | getLogger().error("Error: SecureToken: Challenge not found: kill connection"); 131 | killClient(iclient); 132 | } else 133 | if(s == null) 134 | { 135 | getLogger().error("Error: SecureToken: Response not found: kill connection"); 136 | killClient(iclient); 137 | } else 138 | if(!s.equals(s1)) 139 | { 140 | getLogger().error("Error: SecureToken: Challenge does not equal response: kill connection"); 141 | killClient(iclient); 142 | } else 143 | { 144 | getLogger().debug("SecureToken: Challenge matches response."); 145 | synchronized(wmsproperties) 146 | { 147 | wmsproperties.put("secureTokenOK", new Boolean(true)); 148 | } 149 | flag = true; 150 | } 151 | sendResult(iclient, amfdatalist, new AMFDataItem(flag)); 152 | } 153 | 154 | public void onConnectAccept(IClient iclient) 155 | { 156 | } 157 | 158 | public void onConnectReject(IClient iclient) 159 | { 160 | } 161 | 162 | public void onDisconnect(IClient iclient) 163 | { 164 | } 165 | 166 | private boolean checkSecureToken(IClient iclient) 167 | { 168 | boolean flag = true; 169 | if(iclient != null) 170 | { 171 | WMSProperties wmsproperties = iclient.getProperties(); 172 | synchronized(wmsproperties) 173 | { 174 | Boolean boolean1 = (Boolean)wmsproperties.get("secureTokenOK"); 175 | if(!boolean1.booleanValue()) 176 | { 177 | getLogger().error("Error: SecureToken: Action before response received: kill connection"); 178 | killClient(iclient); 179 | flag = false; 180 | } 181 | } 182 | } 183 | return flag; 184 | } 185 | 186 | public void onStreamCreate(IMediaStream imediastream) 187 | { 188 | boolean flag = true; 189 | if(doCreate) 190 | flag = checkSecureToken(imediastream.getClient()); 191 | if(flag && (doPlay || doPublish)) 192 | imediastream.addClientListener(streamActions); 193 | } 194 | 195 | public void onStreamDestroy(IMediaStream imediastream) 196 | { 197 | } 198 | 199 | private boolean doPlay; 200 | private boolean doPublish; 201 | private boolean doCreate; 202 | private StreamActions streamActions; 203 | 204 | 205 | 206 | } 207 | -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/ModuleSecureToken2.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.security; 2 | 3 | import com.wowza.util.URLUtils; 4 | import com.wowza.wms.amf.*; 5 | import com.wowza.wms.client.IClient; 6 | import com.wowza.wms.logging.WMSLogger; 7 | import com.wowza.wms.logging.WMSLoggerFactory; 8 | import com.wowza.wms.module.IModuleOnConnect; 9 | import com.wowza.wms.module.ModuleBase; 10 | import com.wowza.wms.request.RequestFunction; 11 | import com.wowza.wms.vhost.IVHost; 12 | import java.util.Date; 13 | import java.util.Map; 14 | 15 | public class ModuleSecureToken2 extends ModuleBase 16 | implements IModuleOnConnect 17 | { 18 | 19 | public ModuleSecureToken2() 20 | { 21 | } 22 | 23 | public void onConnect(IClient iclient, RequestFunction requestfunction, AMFDataList amfdatalist) 24 | { 25 | String s = iclient.getQueryStr(); 26 | String s1 = "Unknown reason"; 27 | String s2 = null; 28 | boolean flag = false; 29 | if(s == null) 30 | s1 = "Query string null"; 31 | else 32 | if(s.length() == 0) 33 | { 34 | s1 = "Query string empty"; 35 | } else 36 | { 37 | Map map = URLUtils.parseQueryStr(s, true); 38 | s2 = URLUtils.getParamValue(map, "secureToken"); 39 | if(s2 == null) 40 | s1 = (new StringBuilder()).append("Query string mising secureToken (").append(s).append(")").toString(); 41 | } 42 | if(s2 == null && amfdatalist.size() > 3) 43 | { 44 | AMFData amfdata = amfdatalist.get(amfdatalist.size() - 1); 45 | if(amfdata.getType() == 2) 46 | { 47 | s2 = amfdatalist.getString(amfdatalist.size() - 1); 48 | s1 = "Unknown reason"; 49 | } 50 | } 51 | if(s2 != null) 52 | { 53 | SecureTokenManager securetokenmanager = SecureTokenManager.getInstance(iclient.getVHost()); 54 | Map map1 = securetokenmanager.getTokenList(); 55 | SecureToken securetoken = (SecureToken)map1.get(s2); 56 | if(securetoken == null) 57 | { 58 | s1 = (new StringBuilder()).append("SecureToken not found (").append(s2).append(")").toString(); 59 | } else 60 | { 61 | int i = securetoken.incUsageCount(); 62 | if(i == 1) 63 | { 64 | securetoken.setClient(iclient); 65 | securetokenmanager.registerClient(iclient, securetoken); 66 | iclient.acceptConnection("SecureToken valid"); 67 | flag = true; 68 | } else 69 | { 70 | IClient iclient1 = securetoken.getClient(); 71 | if(iclient1 != null) 72 | { 73 | s1 = (new StringBuilder()).append("SecureToken already used by client (").append(iclient1.getClientId()).append(")").toString(); 74 | SecureTokenDef securetokendef = securetoken.getSecureTokenDef(); 75 | if(securetokendef != null) 76 | { 77 | if(securetokendef.isDoKill()) 78 | iclient1.getVHost().removeClient(iclient1.getClientId()); 79 | if(securetokendef.isDoNotify()) 80 | { 81 | AMFDataObj amfdataobj = new AMFDataObj(); 82 | amfdataobj.put("status", new AMFDataItem("error")); 83 | amfdataobj.put("reason", new AMFDataItem(s1)); 84 | amfdataobj.put("clientId", new AMFDataItem(iclient.getClientId())); 85 | amfdataobj.put("ipAddress", new AMFDataItem(iclient.getIp())); 86 | amfdataobj.put("date", new AMFDataItem(new Date())); 87 | iclient1.call("onSecureToken", null, new Object[] { 88 | amfdataobj 89 | }); 90 | } 91 | } 92 | } else 93 | { 94 | s1 = (new StringBuilder()).append("SecureToken usage count is wrong (").append(securetoken.getUsageCount()).append(")").toString(); 95 | } 96 | } 97 | } 98 | } 99 | if(!flag) 100 | { 101 | iclient.rejectConnection(s1); 102 | //WMSLoggerFactory.getLogger(com/wowza/wms/plugin/security/ModuleSecureToken2).info((new StringBuilder()).append("SecureToken: Connection refused (").append(iclient.getClientId()).append("): ").append(s1).toString()); 103 | } 104 | } 105 | 106 | public void onConnectAccept(IClient iclient) 107 | { 108 | } 109 | 110 | public void onConnectReject(IClient iclient) 111 | { 112 | } 113 | 114 | public void onDisconnect(IClient iclient) 115 | { 116 | SecureTokenManager securetokenmanager = SecureTokenManager.getInstance(iclient.getVHost()); 117 | securetokenmanager.unregisterClient(iclient); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/ModuleSecureURLParams.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.security; 2 | 3 | public class ModuleSecureURLParams extends SecureURLParams 4 | { 5 | 6 | public ModuleSecureURLParams() 7 | { 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/SecureToken.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.security; 2 | 3 | import com.wowza.wms.client.IClient; 4 | 5 | public class SecureToken 6 | { 7 | 8 | public SecureToken(String s, SecureTokenDef securetokendef) 9 | { 10 | guid = null; 11 | usageCount = 0; 12 | client = null; 13 | secureTokenDef = null; 14 | guid = s; 15 | secureTokenDef = securetokendef; 16 | } 17 | 18 | public synchronized int incUsageCount() 19 | { 20 | usageCount++; 21 | return usageCount; 22 | } 23 | 24 | public synchronized int getUsageCount() 25 | { 26 | return usageCount; 27 | } 28 | 29 | public IClient getClient() 30 | { 31 | return client; 32 | } 33 | 34 | public void setClient(IClient iclient) 35 | { 36 | client = iclient; 37 | } 38 | 39 | public SecureTokenDef getSecureTokenDef() 40 | { 41 | return secureTokenDef; 42 | } 43 | 44 | public void setSecureTokenDef(SecureTokenDef securetokendef) 45 | { 46 | secureTokenDef = securetokendef; 47 | } 48 | 49 | private String guid; 50 | private int usageCount; 51 | private IClient client; 52 | private SecureTokenDef secureTokenDef; 53 | } 54 | -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/SecureTokenDef.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.security; 2 | 3 | public class SecureTokenDef 4 | { 5 | 6 | public SecureTokenDef(String s, String s1) 7 | { 8 | name = ""; 9 | sharedSecret = ""; 10 | doKill = false; 11 | doNotify = false; 12 | name = s; 13 | sharedSecret = s1; 14 | } 15 | 16 | public String getName() 17 | { 18 | return name; 19 | } 20 | 21 | public void setName(String s) 22 | { 23 | name = s; 24 | } 25 | 26 | public String getSharedSecret() 27 | { 28 | return sharedSecret; 29 | } 30 | 31 | public void setSharedSecret(String s) 32 | { 33 | sharedSecret = s; 34 | } 35 | 36 | public boolean isDoKill() 37 | { 38 | return doKill; 39 | } 40 | 41 | public void setDoKill(boolean flag) 42 | { 43 | doKill = flag; 44 | } 45 | 46 | public boolean isDoNotify() 47 | { 48 | return doNotify; 49 | } 50 | 51 | public void setDoNotify(boolean flag) 52 | { 53 | doNotify = flag; 54 | } 55 | 56 | private String name; 57 | private String sharedSecret; 58 | private boolean doKill; 59 | private boolean doNotify; 60 | } 61 | -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/SecureTokenManager.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.security; 2 | 3 | import com.wowza.util.XMLUtils; 4 | import com.wowza.wms.client.IClient; 5 | import com.wowza.wms.logging.WMSLogger; 6 | import com.wowza.wms.logging.WMSLoggerFactory; 7 | import com.wowza.wms.vhost.IVHost; 8 | import java.io.File; 9 | import java.util.*; 10 | import javax.xml.parsers.DocumentBuilder; 11 | import javax.xml.parsers.DocumentBuilderFactory; 12 | import javax.xml.xpath.*; 13 | import org.w3c.dom.*; 14 | 15 | public class SecureTokenManager 16 | { 17 | 18 | public SecureTokenManager() 19 | { 20 | tokenLists = new HashMap(); 21 | secureTokenDefs = new HashMap(); 22 | clientMap = new HashMap(); 23 | } 24 | 25 | public static SecureTokenManager getInstance(IVHost ivhost) 26 | { 27 | SecureTokenManager securetokenmanager = (SecureTokenManager)instances.get(ivhost); 28 | if(securetokenmanager == null) 29 | { 30 | securetokenmanager = new SecureTokenManager(); 31 | securetokenmanager.loadConfig(ivhost); 32 | instances.put(ivhost, securetokenmanager); 33 | } 34 | return securetokenmanager; 35 | } 36 | 37 | public void loadConfig(IVHost ivhost) 38 | { 39 | String s = (new StringBuilder()).append(ivhost.getHomePath()).append("/conf/SecureTokens.xml").toString(); 40 | File file = new File(s); 41 | if(file.exists()) 42 | { 43 | //WMSLoggerFactory.getLogger(com/wowza/wms/plugin/security/HTTPSecureTokens).info((new StringBuilder()).append("HTTPSecureTokens: loading config: ").append(s).toString()); 44 | loadConfigFile(ivhost, new File(s)); 45 | } 46 | } 47 | 48 | private void loadConfigFile(IVHost ivhost, File file) 49 | { 50 | try 51 | { 52 | DocumentBuilderFactory documentbuilderfactory = DocumentBuilderFactory.newInstance(); 53 | DocumentBuilder documentbuilder = documentbuilderfactory.newDocumentBuilder(); 54 | Document document = documentbuilder.parse(file); 55 | XPathFactory xpathfactory = XMLUtils.newXPathFactory(); 56 | XPath xpath = xpathfactory.newXPath(); 57 | if(document != null) 58 | { 59 | Element element = document.getDocumentElement(); 60 | String s = "/Root/SecureTokens/SecureToken"; 61 | XPathExpression xpathexpression = xpath.compile(s); 62 | NodeList nodelist = (NodeList)xpathexpression.evaluate(element, XPathConstants.NODESET); 63 | if(nodelist != null) 64 | { 65 | SecureTokenManager securetokenmanager = this; 66 | Map map = securetokenmanager.getSecureTokenDefs(); 67 | for(int i = 0; i < nodelist.getLength(); i++) 68 | { 69 | org.w3c.dom.Node node = nodelist.item(i); 70 | Element element1 = (Element)node; 71 | String s1 = XMLUtils.getXMLPropertyStr(xpath, "Name", element1, null); 72 | String s2 = XMLUtils.getXMLPropertyStr(xpath, "SharedSecret", element1, null); 73 | if(s1 != null && s2 != null) 74 | { 75 | SecureTokenDef securetokendef = new SecureTokenDef(s1, s2); 76 | String s3 = XMLUtils.getXMLPropertyStr(xpath, "ClientAction", element1, null); 77 | if(s3 != null) 78 | { 79 | if(s3.equalsIgnoreCase("kill")) 80 | securetokendef.setDoKill(true); 81 | if(s3.equalsIgnoreCase("notify")) 82 | securetokendef.setDoNotify(true); 83 | } 84 | map.put(s1, securetokendef); 85 | //WMSLoggerFactory.getLogger(com/wowza/wms/plugin/security/HTTPSecureTokens).info((new StringBuilder()).append("HTTPSecureTokens: SecureToken: ").append(s1).toString()); 86 | } else 87 | { 88 | //WMSLoggerFactory.getLogger(com/wowza/wms/plugin/security/HTTPSecureTokens).error("HTTPSecureTokens: loadConfigFile: error parsing secure token file: Name and SharedSecret elements required."); 89 | } 90 | } 91 | 92 | } 93 | } 94 | } 95 | catch(Exception exception) 96 | { 97 | //WMSLoggerFactory.getLogger(com/wowza/wms/plugin/security/HTTPSecureTokens).error((new StringBuilder()).append("HTTPSecureTokens: loadConfigFile: error parsing secure token file: (").append(file).append(") error: ").append(exception.toString()).toString()); 98 | exception.printStackTrace(); 99 | } 100 | } 101 | 102 | public Map getTokenList() 103 | { 104 | return tokenLists; 105 | } 106 | 107 | public String newGUID() 108 | { 109 | return UUID.randomUUID().toString(); 110 | } 111 | 112 | public Map getSecureTokenDefs() 113 | { 114 | return secureTokenDefs; 115 | } 116 | 117 | public void registerClient(IClient iclient, SecureToken securetoken) 118 | { 119 | synchronized(clientMap) 120 | { 121 | clientMap.put(iclient, securetoken); 122 | } 123 | } 124 | 125 | public SecureToken unregisterClient(IClient iclient) 126 | { 127 | SecureToken securetoken = null; 128 | synchronized(clientMap) 129 | { 130 | securetoken = (SecureToken)clientMap.remove(iclient); 131 | } 132 | return securetoken; 133 | } 134 | 135 | public SecureToken getSecureTokenByClient(IClient iclient) 136 | { 137 | SecureToken securetoken = null; 138 | synchronized(clientMap) 139 | { 140 | securetoken = (SecureToken)clientMap.get(iclient); 141 | } 142 | return securetoken; 143 | } 144 | 145 | private static Map instances = new HashMap(); 146 | private Map tokenLists; 147 | private Map secureTokenDefs; 148 | private Map clientMap; 149 | 150 | } 151 | -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/SecureURLParams.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.security; 2 | 3 | import com.wowza.wms.amf.AMFDataItem; 4 | import com.wowza.wms.amf.AMFDataList; 5 | import com.wowza.wms.application.*; 6 | import com.wowza.wms.client.Client; 7 | import com.wowza.wms.client.IClient; 8 | import com.wowza.wms.logging.WMSLogger; 9 | import com.wowza.wms.logging.WMSLoggerFactory; 10 | import com.wowza.wms.module.ModuleBase; 11 | import hu.vpmedia.media.wms.plugin.security.encryption.TEA; 12 | import com.wowza.wms.request.RequestFunction; 13 | import java.io.File; 14 | import java.net.URLDecoder; 15 | import java.util.*; 16 | 17 | public class SecureURLParams extends ModuleBase 18 | { 19 | 20 | public SecureURLParams() 21 | { 22 | denyallConnections = false; 23 | } 24 | 25 | public void onAppStart(IApplicationInstance iapplicationinstance) 26 | { 27 | IApplication iapplication = iapplicationinstance.getApplication(); 28 | String s = (new StringBuilder()).append(iapplication.getApplicationPath()).append(File.separatorChar).append("secureurlparams").append(File.separatorChar).append(iapplicationinstance.getName()).toString(); 29 | File file = new File(s); 30 | if(!file.exists()) 31 | { 32 | boolean flag = false; 33 | String as[] = { 34 | "connect", "play", "publish" 35 | }; 36 | int i = 0; 37 | do 38 | { 39 | if(i >= as.length) 40 | break; 41 | String s1 = iapplicationinstance.getProperties().getPropertyStr((new StringBuilder()).append("secureurlparams.").append(as[i]).toString()); 42 | if(s1 != null) 43 | { 44 | flag = true; 45 | break; 46 | } 47 | i++; 48 | } while(true); 49 | if(!flag) 50 | denyallConnections = true; 51 | } 52 | getLogger().info((new StringBuilder()).append("SecureURLParams.onAppStart: ").append(iapplication.getName()).append("/").append(iapplicationinstance.getName()).toString()); 53 | if(denyallConnections) 54 | getLogger().info((new StringBuilder()).append("SecureURLParams.onAppStart: All connections to this application instance will be denied. The \"secureurlparams\" folder for this application instance is missing and there are no \"secureurlparams\" properties defined in [install-dir]/conf/").append(iapplication.getName()).append("/Application.xml.").toString()); 55 | } 56 | 57 | public void onAppStop(IApplicationInstance iapplicationinstance) 58 | { 59 | IApplication iapplication = iapplicationinstance.getApplication(); 60 | getLogger().info((new StringBuilder()).append("SecureURLParams.onAppStop: ").append(iapplication.getName()).append("/").append(iapplicationinstance.getName()).toString()); 61 | } 62 | 63 | String doURLDecodeStr(String s) 64 | { 65 | String s1 = s; 66 | try 67 | { 68 | s1 = URLDecoder.decode(s, "UTF-8"); 69 | } 70 | catch(Exception exception) 71 | { 72 | getLogger().error((new StringBuilder()).append("URLDecoder: ").append(exception.toString()).toString()); 73 | } 74 | return s1; 75 | } 76 | 77 | boolean checkFolder(String s, IClient iclient) 78 | { 79 | IApplicationInstance iapplicationinstance = getAppInstance(iclient); 80 | IApplication iapplication = getApplication(iclient); 81 | boolean flag = false; 82 | if(!flag) 83 | { 84 | String s1 = iapplication.getApplicationPath(); 85 | s1 = (new StringBuilder()).append(s1).append(File.separatorChar).append("secureurlparams").append(File.separatorChar).append(iapplicationinstance.getName()).toString(); 86 | File file = new File((new StringBuilder()).append(s1).append(File.separatorChar).append(s).toString()); 87 | flag = file.exists(); 88 | } 89 | if(!flag) 90 | flag = iapplicationinstance.getProperties().getPropertyStr((new StringBuilder()).append("secureurlparams.").append(s).toString()) != null; 91 | return flag; 92 | } 93 | 94 | List parseQueryStr(String s) 95 | { 96 | ArrayList arraylist = new ArrayList(); 97 | if(s != null && s.length() > 0) 98 | { 99 | String as[] = s.split("[&]"); 100 | for(int i = 0; i < as.length; i++) 101 | { 102 | String as1[] = as[i].split("[=]"); 103 | if(as1.length == 2) 104 | arraylist.add(as1); 105 | } 106 | 107 | } 108 | return arraylist; 109 | } 110 | 111 | boolean checkParams(String s, IClient iclient) 112 | { 113 | Boolean boolean1; 114 | label0: 115 | { 116 | boolean1 = Boolean.valueOf(false); 117 | IApplicationInstance iapplicationinstance = getAppInstance(iclient); 118 | IApplication iapplication = getApplication(iclient); 119 | String s1 = iapplication.getApplicationPath(); 120 | s1 = (new StringBuilder()).append(s1).append(File.separatorChar).append("secureurlparams").append(File.separatorChar).append(iapplicationinstance.getName()).toString(); 121 | WMSLogger wmslogger = null; 122 | if(WMSLoggerFactory.getLogger(null).isDebugEnabled()) 123 | wmslogger = WMSLoggerFactory.getLogger(null); 124 | File file = new File((new StringBuilder()).append(s1).append(File.separatorChar).append(s).toString()); 125 | if(file.exists()) 126 | { 127 | String s2 = iclient.getQueryStr(); 128 | List list = parseQueryStr(s2); 129 | if(list.size() > 0) 130 | { 131 | Iterator iterator = list.iterator(); 132 | boolean flag; 133 | do 134 | { 135 | if(!iterator.hasNext()) 136 | break label0; 137 | String as1[] = (String[])iterator.next(); 138 | File file1 = new File((new StringBuilder()).append(s1).append(File.separatorChar).append(s).append(File.separatorChar).append(doURLDecodeStr(as1[1])).append(".").append(doURLDecodeStr(as1[0])).toString()); 139 | flag = file1.exists(); 140 | if(wmslogger != null) 141 | wmslogger.debug((new StringBuilder()).append("SecureURLParams: ").append(s).append(": ").append(flag ? "SUCCEED" : "FAIL").append(" (file: ").append(file1.getPath()).append(")").toString()); 142 | } while(!flag); 143 | boolean1 = Boolean.valueOf(true); 144 | } else 145 | if(wmslogger != null) 146 | wmslogger.debug((new StringBuilder()).append("SecureURLParams: ").append(s).append(": FAIL (no query parameters)").toString()); 147 | break label0; 148 | } 149 | String s3 = iapplicationinstance.getProperties().getPropertyStr((new StringBuilder()).append("secureurlparams.").append(s).toString()); 150 | if(s3 == null) 151 | { 152 | boolean1 = Boolean.valueOf(true); 153 | if(wmslogger != null) 154 | wmslogger.debug((new StringBuilder()).append("SecureURLParams: ").append(s).append(": SUCCEED (no folder found [").append(s1).append("], no property found [").append("secureurlparams.").append(s).append("])").toString()); 155 | break label0; 156 | } 157 | s3 = s3.trim(); 158 | if(s3.length() == 0) 159 | { 160 | boolean1 = Boolean.valueOf(false); 161 | if(wmslogger != null) 162 | wmslogger.debug((new StringBuilder()).append("SecureURLParams: ").append(s).append(": FAIL (property is empty [").append("secureurlparams.").append(s).append("])").toString()); 163 | break label0; 164 | } 165 | ArrayList arraylist = new ArrayList(); 166 | String as[] = s3.split("[,]"); 167 | for(int i = 0; i < as.length; i++) 168 | { 169 | String s5 = as[i].trim(); 170 | arraylist.add(s5); 171 | } 172 | 173 | String s4 = iclient.getQueryStr(); 174 | List list1 = parseQueryStr(s4); 175 | if(list1.size() > 0) 176 | { 177 | Iterator iterator1 = list1.iterator(); 178 | boolean flag1; 179 | do 180 | { 181 | if(!iterator1.hasNext()) 182 | break label0; 183 | String as2[] = (String[])iterator1.next(); 184 | String s6 = (new StringBuilder()).append(doURLDecodeStr(as2[1])).append(".").append(doURLDecodeStr(as2[0])).toString(); 185 | flag1 = arraylist.contains(s6); 186 | if(wmslogger != null) 187 | wmslogger.debug((new StringBuilder()).append("SecureURLParams: ").append(s).append(": ").append(flag1 ? "SUCCEED" : "FAIL").append(" (property: ").append(s6).append(")").toString()); 188 | } while(!flag1); 189 | boolean1 = Boolean.valueOf(true); 190 | } else 191 | if(wmslogger != null) 192 | wmslogger.debug((new StringBuilder()).append("SecureURLParams: ").append(s).append(": FAIL (no query parameters)").toString()); 193 | } 194 | return boolean1.booleanValue(); 195 | } 196 | 197 | private void killClient(IClient iclient) 198 | { 199 | ((Client)iclient).setShutdownClient(true); 200 | ((Client)iclient).doIdle(); 201 | } 202 | 203 | public void secureTokenResponse(IClient iclient, RequestFunction requestfunction, AMFDataList amfdatalist) 204 | { 205 | String s = amfdatalist.getString(3); 206 | WMSProperties wmsproperties = iclient.getProperties(); 207 | String s1 = null; 208 | synchronized(wmsproperties) 209 | { 210 | s1 = (String)wmsproperties.get("secureToken"); 211 | } 212 | boolean flag = false; 213 | if(s1 == null) 214 | { 215 | getLogger().error("Error: SecureToken: Challenge not found: kill connection"); 216 | killClient(iclient); 217 | } else 218 | if(s == null) 219 | { 220 | getLogger().error("Error: SecureToken: Response not found: kill connection"); 221 | killClient(iclient); 222 | } else 223 | if(!s.equals(s1)) 224 | { 225 | getLogger().error("Error: SecureToken: Challenge does not equal response: kill connection"); 226 | killClient(iclient); 227 | } else 228 | { 229 | getLogger().debug("SecureToken: Challenge matches response."); 230 | synchronized(wmsproperties) 231 | { 232 | wmsproperties.put("secureTokenOK", new Boolean(true)); 233 | } 234 | flag = true; 235 | } 236 | sendResult(iclient, amfdatalist, new AMFDataItem(flag)); 237 | } 238 | 239 | public void onConnect(IClient iclient, RequestFunction requestfunction, AMFDataList amfdatalist) 240 | { 241 | if(denyallConnections || !checkParams("connect", iclient)) 242 | { 243 | getLogger().info("SecureURLParams: onConnect: rejected"); 244 | iclient.rejectConnection("SecureURLParams: reject connection"); 245 | } else 246 | { 247 | String s = (String)iclient.getAppInstance().getProperties().get("secureTokenSharedSecret"); 248 | if(s != null) 249 | { 250 | SecureTokenManager securetokenmanager = SecureTokenManager.getInstance(iclient.getVHost()); 251 | String s1 = securetokenmanager.newGUID(); 252 | iclient.getProperties().put("secureToken", s1); 253 | iclient.getProperties().put("secureTokenOK", new Boolean(false)); 254 | iclient.addAcceptConnectionAttribute("secureToken", TEA.encrypt(s1, s)); 255 | getLogger().debug("SecureURLParams: generate SecureToken GUID"); 256 | } 257 | } 258 | } 259 | 260 | private boolean checkSecureToken(IClient iclient) 261 | { 262 | boolean flag = true; 263 | if(iclient != null) 264 | { 265 | WMSProperties wmsproperties = iclient.getProperties(); 266 | synchronized(wmsproperties) 267 | { 268 | Boolean boolean1 = (Boolean)wmsproperties.get("secureTokenOK"); 269 | getLogger().debug((new StringBuilder()).append("SecureURLParams: Check SecureToken: ").append(boolean1.booleanValue()).toString()); 270 | if(!boolean1.booleanValue()) 271 | flag = false; 272 | } 273 | } 274 | return flag; 275 | } 276 | 277 | public void releaseStream(IClient iclient, RequestFunction requestfunction, AMFDataList amfdatalist) 278 | { 279 | boolean flag = true; 280 | if(checkFolder("publish", iclient)) 281 | flag = checkParams("publish", iclient); 282 | else 283 | if(iclient.getProperties().get("secureTokenOK") != null) 284 | flag = checkSecureToken(iclient); 285 | if(flag) 286 | { 287 | invokePrevious(this, iclient, requestfunction, amfdatalist); 288 | } else 289 | { 290 | getLogger().info("SecureURLParams: releaseStream: rejected"); 291 | killClient(iclient); 292 | } 293 | } 294 | 295 | public void publish(IClient iclient, RequestFunction requestfunction, AMFDataList amfdatalist) 296 | { 297 | boolean flag = true; 298 | if(checkFolder("publish", iclient)) 299 | flag = checkParams("publish", iclient); 300 | else 301 | if(iclient.getProperties().get("secureTokenOK") != null) 302 | flag = checkSecureToken(iclient); 303 | if(flag) 304 | { 305 | invokePrevious(this, iclient, requestfunction, amfdatalist); 306 | } else 307 | { 308 | getLogger().info("SecureURLParams: publish: rejected"); 309 | killClient(iclient); 310 | } 311 | } 312 | 313 | public void play(IClient iclient, RequestFunction requestfunction, AMFDataList amfdatalist) 314 | { 315 | boolean flag = true; 316 | if(checkFolder("play", iclient)) 317 | flag = checkParams("play", iclient); 318 | else 319 | if(iclient.getProperties().get("secureTokenOK") != null) 320 | flag = checkSecureToken(iclient); 321 | if(flag) 322 | { 323 | invokePrevious(this, iclient, requestfunction, amfdatalist); 324 | } else 325 | { 326 | getLogger().info("SecureURLParams: play: rejected"); 327 | killClient(iclient); 328 | } 329 | } 330 | 331 | private boolean denyallConnections; 332 | } 333 | -------------------------------------------------------------------------------- /vpmedia-wms-security/src/main/java/hu/vpmedia/media/wms/plugin/security/encryption/TEA.java: -------------------------------------------------------------------------------- 1 | // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. 2 | // Jad home page: http://www.kpdus.com/jad.html 3 | // Decompiler options: packimports(3) 4 | 5 | package hu.vpmedia.media.wms.plugin.security.encryption; 6 | 7 | 8 | public class TEA 9 | { 10 | 11 | public TEA() 12 | { 13 | } 14 | 15 | public static String encrypt(String s, String s1) 16 | { 17 | int ai[] = charsToLongs(strToChars(s)); 18 | int ai1[] = charsToLongs(strToChars(s1)); 19 | int ai2[] = new int[4]; 20 | for(int i = 0; i < ai2.length; i++) 21 | if(i < ai1.length) 22 | ai2[i] = ai1[i]; 23 | else 24 | ai2[i] = 0; 25 | 26 | int j = ai.length; 27 | boolean flag = false; 28 | if(j == 0) 29 | return ""; 30 | if(j == 1) 31 | ai[j++] = 0; 32 | int l = ai[j - 1]; 33 | int i1 = ai[0]; 34 | int l1 = 0x9e3779b9; 35 | int l2 = (int)Math.floor(6D + 52D / (double)j); 36 | int i3 = 0; 37 | while(l2-- > 0) 38 | { 39 | i3 += l1; 40 | int k2 = i3 >>> 2 & 3; 41 | int k; 42 | for(k = 0; k < j - 1; k++) 43 | { 44 | int j1 = ai[k + 1]; 45 | int i2 = (l >>> 5 ^ j1 << 2) + (j1 >>> 3 ^ l << 4) ^ (i3 ^ j1) + (ai2[k & 3 ^ k2] ^ l); 46 | l = ai[k] += i2; 47 | } 48 | 49 | int k1 = ai[0]; 50 | int j2 = (l >>> 5 ^ k1 << 2) + (k1 >>> 3 ^ l << 4) ^ (i3 ^ k1) + (ai2[k & 3 ^ k2] ^ l); 51 | l = ai[j - 1] += j2; 52 | } 53 | return charsToHex(longsToChars(ai)); 54 | } 55 | 56 | public static String decrypt(String s, String s1) 57 | { 58 | int ai[] = charsToLongs(hexToChars(s)); 59 | int ai1[] = charsToLongs(strToChars(s1)); 60 | int ai2[] = new int[4]; 61 | for(int i = 0; i < ai2.length; i++) 62 | if(i < ai1.length) 63 | ai2[i] = ai1[i]; 64 | else 65 | ai2[i] = 0; 66 | 67 | int j = ai.length; 68 | boolean flag = false; 69 | if(j == 0) 70 | return ""; 71 | int l = ai[j - 1]; 72 | int k1 = ai[0]; 73 | int l1 = 0x9e3779b9; 74 | boolean flag1 = false; 75 | boolean flag2 = false; 76 | int l2 = (int)Math.floor(6D + 52D / (double)j); 77 | for(int i3 = l2 * l1; i3 != 0; i3 -= l1) 78 | { 79 | int k2 = i3 >>> 2 & 3; 80 | int k; 81 | for(k = j - 1; k > 0; k--) 82 | { 83 | int i1 = ai[k - 1]; 84 | int i2 = (i1 >>> 5 ^ k1 << 2) + (k1 >>> 3 ^ i1 << 4) ^ (i3 ^ k1) + (ai2[k & 3 ^ k2] ^ i1); 85 | k1 = ai[k] -= i2; 86 | } 87 | 88 | int j1 = ai[j - 1]; 89 | int j2 = (j1 >>> 5 ^ k1 << 2) + (k1 >>> 3 ^ j1 << 4) ^ (i3 ^ k1) + (ai2[k & 3 ^ k2] ^ j1); 90 | k1 = ai[0] -= j2; 91 | } 92 | 93 | return charsToStr(longsToChars(ai)); 94 | } 95 | 96 | private static int[] charsToLongs(byte abyte0[]) 97 | { 98 | int ai[] = new int[(int)Math.ceil((double)abyte0.length / 4D)]; 99 | for(int i = 0; i < ai.length; i++) 100 | { 101 | ai[i] = 0; 102 | if(i * 4 + 3 < abyte0.length) 103 | ai[i] |= abyte0[i * 4 + 3] & 0xff; 104 | ai[i] <<= 8; 105 | if(i * 4 + 2 < abyte0.length) 106 | ai[i] |= abyte0[i * 4 + 2] & 0xff; 107 | ai[i] <<= 8; 108 | if(i * 4 + 1 < abyte0.length) 109 | ai[i] |= abyte0[i * 4 + 1] & 0xff; 110 | ai[i] <<= 8; 111 | ai[i] |= abyte0[i * 4] & 0xff; 112 | } 113 | 114 | return ai; 115 | } 116 | 117 | private static byte[] longsToChars(int ai[]) 118 | { 119 | byte abyte0[] = new byte[ai.length * 4]; 120 | for(int i = 0; i < ai.length; i++) 121 | { 122 | abyte0[i * 4 + 0] = (byte)(ai[i] & 0xff); 123 | abyte0[i * 4 + 1] = (byte)(ai[i] >> 8 & 0xff); 124 | abyte0[i * 4 + 2] = (byte)(ai[i] >> 16 & 0xff); 125 | abyte0[i * 4 + 3] = (byte)(ai[i] >> 24 & 0xff); 126 | } 127 | 128 | return abyte0; 129 | } 130 | 131 | private static String charsToHex(byte abyte0[]) 132 | { 133 | String s = ""; 134 | for(int i = 0; i < abyte0.length; i++) 135 | { 136 | String s1 = Integer.toHexString(abyte0[i] & 0xff); 137 | if(s1.length() < 2) 138 | s1 = (new StringBuilder()).append("0").append(s1).toString(); 139 | s = (new StringBuilder()).append(s).append(s1).toString(); 140 | } 141 | 142 | return s; 143 | } 144 | 145 | private static byte[] hexToChars(String s) 146 | { 147 | byte abyte0[] = new byte[s.length() / 2]; 148 | for(int i = 0; i < s.length() / 2; i++) 149 | abyte0[i] = (byte)(Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16) & 0xff); 150 | 151 | return abyte0; 152 | } 153 | 154 | private static String charsToStr(byte abyte0[]) 155 | { 156 | String s = null; 157 | try 158 | { 159 | s = new String(abyte0, "UTF-8"); 160 | s = s.trim(); 161 | } 162 | catch(Exception exception) { } 163 | return s; 164 | } 165 | 166 | private static byte[] strToChars(String s) 167 | { 168 | try 169 | { 170 | return s.getBytes("UTF-8"); 171 | } 172 | catch(Exception exception) 173 | { 174 | return null; 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /vpmedia-wms-snapshot/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-snapshot/src/main/java/hu/vpmedia/media/wms/plugin/snapshot/Snapshot.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.snapshot; 2 | 3 | import java.io.*; 4 | 5 | import com.wowza.util.*; 6 | import com.wowza.wms.module.*; 7 | import com.wowza.wms.amf.*; 8 | import com.wowza.wms.application.*; 9 | import com.wowza.wms.client.IClient; 10 | import com.wowza.wms.stream.*; 11 | import com.wowza.wms.vhost.*; 12 | import com.wowza.wms.request.*; 13 | 14 | public class Snapshot extends ModuleBase 15 | { 16 | Object lock = new Object(); 17 | 18 | public void createSnapshotLive(IClient client, RequestFunction function, AMFDataList params) 19 | { 20 | String streamName = params.getString(PARAM1); 21 | 22 | String fileName = ""; 23 | IApplicationInstance appInstance = client.getAppInstance(); 24 | MediaStreamMap streams = appInstance.getStreams(); 25 | IMediaStream stream = streams.getStream(streamName); 26 | if (stream != null) 27 | { 28 | AMFPacket packet = stream.getLastKeyFrame(); 29 | if (packet != null) 30 | { 31 | fileName = streamName + "_" + packet.getAbsTimecode() + ".flv"; 32 | File newFile = stream.getStreamFileForWrite(streamName, null, null); 33 | 34 | String filePath = newFile.getPath().substring(0, newFile.getPath().length()-4) + "_" + packet.getAbsTimecode() + ".flv"; 35 | 36 | try 37 | { 38 | synchronized(lock) 39 | { 40 | BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(filePath), false)); 41 | FLVUtils.writeHeader(out, 0, null); 42 | 43 | AMFPacket codecConfig = stream.getVideoCodecConfigPacket(packet.getAbsTimecode()); 44 | if (codecConfig != null) 45 | FLVUtils.writeChunk(out, codecConfig.getDataBuffer(), codecConfig.getSize(), 0, (byte)codecConfig.getType()); 46 | 47 | FLVUtils.writeChunk(out, packet.getDataBuffer(), packet.getSize(), 0, (byte)packet.getType()); 48 | out.close(); 49 | } 50 | 51 | getLogger().info("snapshot created: "+filePath); 52 | } 53 | catch (Exception e) 54 | { 55 | getLogger().error("createSnapshot: "+e.toString()); 56 | } 57 | } 58 | } 59 | 60 | sendResult(client, params, fileName); 61 | } 62 | 63 | public void createSnapshotVOD(IClient client, RequestFunction function, AMFDataList params) 64 | { 65 | String streamName = params.getString(PARAM1); 66 | int timecode = params.getInt(PARAM2); 67 | 68 | String fileName = ""; 69 | IApplicationInstance appInstance = client.getAppInstance(); 70 | 71 | String flvFilePath = appInstance.getStreamStoragePath() + "/" + streamName + ".flv"; 72 | File flvFile = new File(flvFilePath); 73 | 74 | if (flvFile.exists()) 75 | { 76 | AMFPacket lastVideoKeyFrame = null; 77 | try 78 | { 79 | BufferedInputStream is = new BufferedInputStream(new FileInputStream(flvFile)); 80 | FLVUtils.readHeader(is); 81 | AMFPacket amfPacket; 82 | while ((amfPacket = FLVUtils.readChunk(is)) != null) 83 | { 84 | if (lastVideoKeyFrame != null && amfPacket.getTimecode() > timecode) 85 | break; 86 | if (amfPacket.getType() != IVHost.CONTENTTYPE_VIDEO) 87 | continue; 88 | if (FLVUtils.isVideoKeyFrame(amfPacket)) //if (FLVUtils.getFrameType(amfPacket.getFirstByte()) == FLVUtils.FLV_KFRAME) 89 | lastVideoKeyFrame = amfPacket; 90 | } 91 | is.close(); 92 | } 93 | catch (Exception e) 94 | { 95 | getLogger().error("Error: createSnapshotVOD: reading flv: "+e.toString()); 96 | } 97 | 98 | if (lastVideoKeyFrame != null) 99 | { 100 | try 101 | { 102 | fileName = streamName + "_" + timecode; 103 | String filePath = appInstance.getStreamStoragePath() + "/" + fileName + ".flv"; 104 | BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(filePath), false)); 105 | FLVUtils.writeHeader(out, 0, null); 106 | FLVUtils.writeChunk(out, lastVideoKeyFrame.getDataBuffer(), lastVideoKeyFrame.getSize(), 0, (byte)lastVideoKeyFrame.getType()); 107 | out.close(); 108 | 109 | getLogger().info("snapshot created: "+filePath); 110 | } 111 | catch (Exception e) 112 | { 113 | getLogger().error("Error: createSnapshotVOD: writing flv: "+e.toString()); 114 | } 115 | } 116 | } 117 | 118 | sendResult(client, params, fileName); 119 | } 120 | } -------------------------------------------------------------------------------- /vpmedia-wms-ssl/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-ssl/src/main/java/hu/vpmedia/media/wms/plugin/ssl/SSLContextFactory.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.ssl; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.security.GeneralSecurityException; 6 | import java.security.KeyStore; 7 | import java.security.Security; 8 | 9 | import javax.net.ssl.KeyManagerFactory; 10 | import javax.net.ssl.SSLContext; 11 | 12 | /** 13 | * Factory to create a bougus SSLContext. 14 | * 15 | * @author The Apache Directory Project (mina-dev@directory.apache.org) 16 | * @version $Rev: 451854 $, $Date: 2006-10-02 11:30:11 +0900 (월, 02 10월 2006) $ 17 | */ 18 | public class SSLContextFactory 19 | { 20 | /** 21 | * Protocol to use. 22 | */ 23 | private static final String PROTOCOL = "TLS"; 24 | 25 | private static final String KEY_MANAGER_FACTORY_ALGORITHM; 26 | 27 | static { 28 | String algorithm = Security.getProperty( "ssl.KeyManagerFactory.algorithm" ); 29 | if( algorithm == null ) 30 | { 31 | algorithm = "SunX509"; 32 | } 33 | 34 | KEY_MANAGER_FACTORY_ALGORITHM = algorithm; 35 | } 36 | 37 | /** 38 | * Bougus Server certificate keystore file name. 39 | */ 40 | private static final String SSL_KEYSTORE = "vpmedia.jks"; 41 | 42 | /** 43 | * SSL keystore password. 44 | */ 45 | private static final char[] SSL_PW = { 'v', 'p', 'm', 'e', 'd', 'i', 'a' }; 46 | 47 | private static SSLContext serverInstance = null; 48 | private static SSLContext clientInstance = null; 49 | 50 | /** 51 | * Get SSLContext singleton. 52 | * 53 | * @return SSLContext 54 | * @throws java.security.GeneralSecurityException 55 | * 56 | */ 57 | public static SSLContext getInstance( boolean server ) 58 | throws GeneralSecurityException 59 | { 60 | SSLContext retInstance = null; 61 | 62 | if( server ) 63 | { 64 | if( serverInstance == null ) 65 | { 66 | synchronized( SSLContextFactory.class ) 67 | { 68 | if( serverInstance == null ) 69 | { 70 | try 71 | { 72 | serverInstance = createBougusServerSSLContext(); 73 | } 74 | catch( Exception ioe ) 75 | { 76 | throw new GeneralSecurityException( 77 | "Can't create Server SSLContext:" + ioe ); 78 | } 79 | } 80 | } 81 | } 82 | retInstance = serverInstance; 83 | } 84 | else 85 | { 86 | if( clientInstance == null ) 87 | { 88 | synchronized( SSLContextFactory.class ) 89 | { 90 | if( clientInstance == null ) 91 | { 92 | clientInstance = createBougusClientSSLContext(); 93 | } 94 | } 95 | } 96 | retInstance = clientInstance; 97 | } 98 | return retInstance; 99 | } 100 | 101 | private static SSLContext createBougusServerSSLContext() 102 | throws GeneralSecurityException, IOException 103 | { 104 | // Create keystore 105 | KeyStore ks = KeyStore.getInstance( "JKS" ); 106 | InputStream in = null; 107 | try 108 | { 109 | in = SSLContextFactory.class 110 | .getResourceAsStream( SSL_KEYSTORE ); 111 | ks.load( in, SSL_PW ); 112 | } 113 | finally 114 | { 115 | if( in != null ) 116 | { 117 | try 118 | { 119 | in.close(); 120 | } 121 | catch( IOException ignored ) 122 | { 123 | } 124 | } 125 | } 126 | 127 | // Set up key manager factory to use our key store 128 | KeyManagerFactory kmf = KeyManagerFactory.getInstance( 129 | KEY_MANAGER_FACTORY_ALGORITHM ); 130 | kmf.init( ks, SSL_PW ); 131 | 132 | // Initialize the SSLContext to work with our key managers. 133 | SSLContext sslContext = SSLContext.getInstance( PROTOCOL ); 134 | sslContext.init( kmf.getKeyManagers(), 135 | TrustManagerFactory.X509_MANAGERS, null ); 136 | 137 | return sslContext; 138 | } 139 | 140 | private static SSLContext createBougusClientSSLContext() 141 | throws GeneralSecurityException 142 | { 143 | SSLContext context = SSLContext.getInstance( PROTOCOL ); 144 | context.init( null, TrustManagerFactory.X509_MANAGERS, null ); 145 | return context; 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /vpmedia-wms-ssl/src/main/java/hu/vpmedia/media/wms/plugin/ssl/TrustManagerFactory.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.ssl; 2 | 3 | import java.security.InvalidAlgorithmParameterException; 4 | import java.security.KeyStore; 5 | import java.security.KeyStoreException; 6 | import java.security.cert.CertificateException; 7 | import java.security.cert.X509Certificate; 8 | 9 | import javax.net.ssl.ManagerFactoryParameters; 10 | import javax.net.ssl.TrustManager; 11 | import javax.net.ssl.TrustManagerFactorySpi; 12 | import javax.net.ssl.X509TrustManager; 13 | 14 | /** 15 | * Bogus trust manager factory. Creates BogusX509TrustManager 16 | * 17 | * @author The Apache Directory Project (mina-dev@directory.apache.org) 18 | * @version $Rev: 451854 $, $Date: 2006-10-02 11:30:11 +0900 (월, 02 10월 2006) $ 19 | */ 20 | class TrustManagerFactory extends TrustManagerFactorySpi 21 | { 22 | 23 | static final X509TrustManager X509 = new X509TrustManager() 24 | { 25 | public void checkClientTrusted( X509Certificate[] x509Certificates, 26 | String s ) throws CertificateException 27 | { 28 | } 29 | 30 | public void checkServerTrusted( X509Certificate[] x509Certificates, 31 | String s ) throws CertificateException 32 | { 33 | } 34 | 35 | public X509Certificate[] getAcceptedIssuers() 36 | { 37 | return new X509Certificate[ 0 ]; 38 | } 39 | }; 40 | 41 | static final TrustManager[] X509_MANAGERS = new TrustManager[] { X509 }; 42 | 43 | public TrustManagerFactory() 44 | { 45 | } 46 | 47 | protected TrustManager[] engineGetTrustManagers() 48 | { 49 | return X509_MANAGERS; 50 | } 51 | 52 | protected void engineInit( KeyStore keystore ) throws KeyStoreException 53 | { 54 | // noop 55 | } 56 | 57 | protected void engineInit( 58 | ManagerFactoryParameters managerFactoryParameters ) 59 | throws InvalidAlgorithmParameterException 60 | { 61 | // noop 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /vpmedia-wms-ssl/src/main/resources/wms-ssl/hu/vpmedia/media/wms/plugin/ssl/vpmedia.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpmedia/template-wowza/94ae44dcd19b8d23eb2ea9c7b3d9c72a54ffc103/vpmedia-wms-ssl/src/main/resources/wms-ssl/hu/vpmedia/media/wms/plugin/ssl/vpmedia.jks -------------------------------------------------------------------------------- /vpmedia-wms-streamnamealias/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-streamnamealias/src/main/java/hu/vpmedia/media/wms/plugin/streamnamealias/ModuleStreamNameAlias.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.streamnamealias; 2 | 3 | import java.util.*; 4 | import java.io.*; 5 | 6 | import com.wowza.util.*; 7 | import com.wowza.wms.module.*; 8 | import com.wowza.wms.request.*; 9 | import com.wowza.wms.amf.*; 10 | import com.wowza.wms.application.*; 11 | import com.wowza.wms.client.*; 12 | import com.wowza.wms.stream.*; 13 | 14 | public class ModuleStreamNameAlias extends ModuleBase 15 | { 16 | public static final String STREAMALIASFILE_PROPERTY = "streamNameAliasFile"; 17 | public static final String STREAMALIASDEBUG_PROPERTY = "streamNameAliasDebug"; 18 | public static final String STREAMALIASPATHDELIMITER_PROPERTY = "streamNameAliasPathDelimiter"; 19 | public static final String STREAMALIASNAMEDELIMITER_PROPERTY = "streamNameAliasNameDelimiter"; 20 | 21 | private Map envMap = new HashMap(); 22 | private File aliasFilePtr = null; 23 | private boolean debug = false; 24 | private String pathDelimiter = "/"; 25 | private String nameDelimiter = "="; 26 | 27 | public void onAppStart(IApplicationInstance appInstance) 28 | { 29 | WMSProperties props = appInstance.getProperties(); 30 | debug = props.getPropertyBoolean(STREAMALIASDEBUG_PROPERTY, debug); 31 | pathDelimiter = props.getPropertyStr(STREAMALIASPATHDELIMITER_PROPERTY, pathDelimiter); 32 | nameDelimiter = props.getPropertyStr(STREAMALIASNAMEDELIMITER_PROPERTY, nameDelimiter); 33 | 34 | StreamNameAliasFiles.setNameDelimeter(nameDelimiter); 35 | 36 | while(true) 37 | { 38 | String aliasPath = props.getPropertyStr(STREAMALIASFILE_PROPERTY); 39 | if (aliasPath == null) 40 | { 41 | getLogger().warn("ModuleStreamNameAlias.onAppStart: Property "+STREAMALIASFILE_PROPERTY+" is missing. Can't find alias file."); 42 | break; 43 | } 44 | 45 | Map envMap = new HashMap(); 46 | 47 | envMap.put("com.wowza.wms.context.VHost", appInstance.getVHost().getName()); 48 | envMap.put("com.wowza.wms.context.VHostConfigHome", appInstance.getVHost().getHomePath()); 49 | envMap.put("com.wowza.wms.context.Application", appInstance.getApplication().getName()); 50 | envMap.put("com.wowza.wms.context.ApplicationInstance", appInstance.getName()); 51 | 52 | aliasPath = SystemUtils.expandEnvironmentVariables(aliasPath, envMap); 53 | this.aliasFilePtr = new File(aliasPath); 54 | 55 | if (debug) 56 | getLogger().info("ModuleStreamNameAlias.onAppStart: "+STREAMALIASFILE_PROPERTY+": "+aliasFilePtr.getAbsolutePath()); 57 | break; 58 | } 59 | 60 | envMap.put("VHost.Name", appInstance.getVHost().getName()); 61 | envMap.put("Application.Name", appInstance.getApplication().getName()); 62 | envMap.put("ApplicationInstance.Name", appInstance.getName()); 63 | envMap.put("AppInstance.Name", appInstance.getName()); 64 | } 65 | 66 | public void onAppStop(IApplicationInstance appInstance) 67 | { 68 | getLogger().info("ModuleStreamNameAlias.onAppStop: "+appInstance.getApplication().getName()+"/"+appInstance.getName()); 69 | } 70 | 71 | private String streamNameToAlias(String streamName) 72 | { 73 | String ret = null; 74 | 75 | while(true) 76 | { 77 | if (aliasFilePtr == null) 78 | { 79 | if (debug) 80 | getLogger().info("ModuleStreamNameAlias.streamNameToAlias: aliasFilePtr is null"); 81 | break; 82 | } 83 | 84 | StreamNameAliasFiles aliasFiles = StreamNameAliasFiles.getInstance(); 85 | if (aliasFiles == null) 86 | { 87 | if (debug) 88 | getLogger().info("ModuleStreamNameAlias.streamNameToAlias: aliasFiles is null"); 89 | break; 90 | } 91 | 92 | StreamNameAliasFile aliasFile = aliasFiles.getMapFile(aliasFilePtr); 93 | if (aliasFile == null) 94 | { 95 | if (debug) 96 | getLogger().info("ModuleStreamNameAlias.streamNameToAlias: aliasFile missing: "+aliasFilePtr.getAbsolutePath()); 97 | break; 98 | } 99 | 100 | StreamNameAliasMatch aliasMatch = aliasFile.findMap(streamName); 101 | if (aliasMatch == null) 102 | { 103 | if (debug) 104 | getLogger().info("ModuleStreamNameAlias.streamNameToAlias: Can't find alias entry for: "+streamName); 105 | break; 106 | } 107 | 108 | Map sendMap = new HashMap(); 109 | sendMap.putAll(envMap); 110 | 111 | sendMap.put("Stream.Name", streamName); 112 | if (streamName.indexOf(pathDelimiter) >= 0) 113 | { 114 | String[] parts = streamName.split("["+pathDelimiter+"]"); 115 | for(int i=0;i iter = aliasMatch.wildcardMatches.iterator(); 125 | while(iter.hasNext()) 126 | { 127 | String value = iter.next(); 128 | sendMap.put("Wildcard.Match"+(gindex+1), value); 129 | gindex++; 130 | } 131 | } 132 | 133 | ret = SystemUtils.expandEnvironmentVariables(aliasMatch.alias, sendMap); 134 | if (debug) 135 | getLogger().info("ModuleStreamNameAlias.streamNameToAlias: streamName:"+streamName+" alias:"+aliasMatch+" result:"+ret); 136 | break; 137 | } 138 | 139 | return ret; 140 | } 141 | 142 | public void play(IClient client, RequestFunction function, AMFDataList params) 143 | { 144 | boolean doNext = true; 145 | 146 | if (params.get(PARAM1).getType() == AMFData.DATA_TYPE_STRING) 147 | { 148 | String streamName = params.getString(PARAM1); 149 | String newName = streamNameToAlias(streamName); 150 | IMediaStream stream = getStream(client, function); 151 | 152 | if (newName == null) 153 | { 154 | String code = "NetStream.Play.Failed"; 155 | String description = "ModuleStreamNameAlias: No match for stream name "+streamName+"."; 156 | sendStreamOnStatusError(stream, code, description); 157 | doNext = false; 158 | if (debug) 159 | getLogger().warn("ModuleStreamNameAlias.play: No match: "+streamName); 160 | } 161 | else 162 | { 163 | if (debug) 164 | getLogger().info("ModuleStreamNameAlias.play: "+streamName+"="+newName); 165 | params.set(PARAM1, new AMFDataItem(newName)); 166 | } 167 | } 168 | 169 | if (doNext) 170 | this.invokePrevious(client, function, params); 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /vpmedia-wms-streamnamealias/src/main/java/hu/vpmedia/media/wms/plugin/streamnamealias/StreamNameAliasFile.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.streamnamealias; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | import java.util.regex.*; 6 | 7 | import com.wowza.wms.logging.*; 8 | 9 | public class StreamNameAliasFile 10 | { 11 | class StreamAlias 12 | { 13 | String pattern = null; 14 | String alias = null; 15 | 16 | public StreamAlias(String pattern, String alias) 17 | { 18 | this.pattern = pattern; 19 | this.alias = alias; 20 | } 21 | 22 | public String toString() 23 | { 24 | return "{pattern: \""+pattern+"\" alias: \""+alias+"\"}"; 25 | } 26 | } 27 | 28 | private long lastModDate = -1; 29 | private long lastSize = -1; 30 | private File file = null; 31 | private List aliasVals = new ArrayList(); 32 | 33 | 34 | public StreamNameAliasFile(File file) 35 | { 36 | this.file = file; 37 | load(); 38 | } 39 | 40 | private void load() 41 | { 42 | WMSLoggerFactory.getLogger(StreamNameAliasFile.class).debug("StreamNameAliasFile.load: "+file.getAbsolutePath()); 43 | aliasVals.clear(); 44 | 45 | String delimter = StreamNameAliasFiles.getNameDelimeter(); 46 | 47 | try 48 | { 49 | BufferedReader inf = new BufferedReader(new FileReader(file)); 50 | String line; 51 | while ((line = inf.readLine()) != null) 52 | { 53 | line = line.trim(); 54 | if (line.startsWith("#")) 55 | continue; 56 | if (line.length() == 0) 57 | continue; 58 | 59 | String pattern = null; 60 | String alias = null; 61 | int pos = line.indexOf(delimter); 62 | if (pos >= 0) 63 | { 64 | pattern = line.substring(0, pos).trim(); 65 | alias = line.substring(pos+1).trim(); 66 | } 67 | if (pattern != null && alias != null) 68 | aliasVals.add(new StreamAlias(pattern, alias)); 69 | } 70 | inf.close(); 71 | } 72 | catch (Exception e) 73 | { 74 | WMSLoggerFactory.getLogger(StreamNameAliasFile.class).error("StreamNameAliasFile.load: "+e.toString()); 75 | } 76 | 77 | lastModDate = file.lastModified(); 78 | lastSize = file.length(); 79 | } 80 | 81 | private void checkReload() 82 | { 83 | if (lastModDate != file.lastModified() || lastSize != file.length()) 84 | load(); 85 | } 86 | 87 | public synchronized StreamNameAliasMatch findMap(String streamName) 88 | { 89 | checkReload(); 90 | 91 | StreamNameAliasMatch ret = null; 92 | Iterator iter = aliasVals.iterator(); 93 | List wildcardMatches = null; 94 | 95 | while(iter.hasNext()) 96 | { 97 | StreamAlias streamAlias = iter.next(); 98 | String pattern = streamAlias.pattern; 99 | boolean isMatch = false; 100 | 101 | if (pattern.indexOf("*") >= 0) 102 | { 103 | String regPattern = pattern; 104 | regPattern = regPattern.replace(".", "\\."); 105 | regPattern = regPattern.replace("*", "(.*)"); 106 | regPattern = "^"+regPattern+"$"; 107 | Pattern p = Pattern.compile(regPattern); 108 | Matcher m = p.matcher(streamName); 109 | if (m.find()) 110 | { 111 | isMatch = (m.start() == 0 && m.end() == streamName.length()); 112 | if (isMatch && m.groupCount() > 0) 113 | { 114 | wildcardMatches = new ArrayList(); 115 | for(int i=0;i aliasFiles = new HashMap(); 13 | 14 | public static void setNameDelimeter(String nameDelimiter) 15 | { 16 | StreamNameAliasFiles.nameDelimiter = nameDelimiter; 17 | } 18 | 19 | public static String getNameDelimeter() 20 | { 21 | return StreamNameAliasFiles.nameDelimiter; 22 | } 23 | 24 | public static StreamNameAliasFiles getInstance() 25 | { 26 | synchronized(StreamNameAliasFiles.lock) 27 | { 28 | if (StreamNameAliasFiles.instance == null) 29 | StreamNameAliasFiles.instance = new StreamNameAliasFiles(); 30 | return StreamNameAliasFiles.instance; 31 | } 32 | } 33 | 34 | public StreamNameAliasFile getMapFile(File file) 35 | { 36 | StreamNameAliasFile ret = null; 37 | 38 | synchronized(StreamNameAliasFiles.lock) 39 | { 40 | if (file.exists()) 41 | { 42 | String fileKey = file.getAbsolutePath(); 43 | ret = aliasFiles.get(fileKey); 44 | if (ret == null) 45 | { 46 | ret = new StreamNameAliasFile(file); 47 | aliasFiles.put(fileKey, ret); 48 | } 49 | } 50 | } 51 | 52 | return ret; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /vpmedia-wms-streamnamealias/src/main/java/hu/vpmedia/media/wms/plugin/streamnamealias/StreamNameAliasMatch.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.streamnamealias; 2 | 3 | import java.util.*; 4 | 5 | public class StreamNameAliasMatch 6 | { 7 | String pattern = null; 8 | String alias = null; 9 | List wildcardMatches = null; 10 | 11 | public String toString() 12 | { 13 | String ret = "{pattern: \""+pattern+"\" alias:\""+alias+"\" wildcardMatches:"; 14 | if (wildcardMatches == null) 15 | ret += "null"; 16 | else 17 | { 18 | ret += "{"; 19 | int index = 0; 20 | Iterator iter = wildcardMatches.iterator(); 21 | while(iter.hasNext()) 22 | { 23 | String value = iter.next(); 24 | if (index > 0) 25 | ret += ", "; 26 | ret += "["+index+"]: \""+value+"\""; 27 | index++; 28 | } 29 | ret += "}"; 30 | } 31 | 32 | ret += "}"; 33 | return ret; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /vpmedia-wms-test/build.gradle: -------------------------------------------------------------------------------- 1 | // 2 | //=BEGIN CLOSED LICENSE 3 | // 4 | // Copyright(c) 2012 András Csizmadia. 5 | // http://www.vpmedia.eu 6 | // 7 | // For information about the licensing and copyright please 8 | // contact András Csizmadia at andras@vpmedia.eu. 9 | // 10 | //=END CLOSED LICENSE 11 | // 12 | 13 | apply plugin: 'java' 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | compile fileTree(dir: 'c:\\Work\\servers\\wowza\\lib\\', includes: ['*.jar']) 21 | } -------------------------------------------------------------------------------- /vpmedia-wms-test/src/main/java/hu/vpmedia/media/wms/plugin/test/ModuleRequireSecureConnection.java: -------------------------------------------------------------------------------- 1 | package hu.vpmedia.media.wms.plugin.test; 2 | 3 | import com.wowza.wms.amf.*; 4 | import com.wowza.wms.client.*; 5 | import com.wowza.wms.module.*; 6 | import com.wowza.wms.request.*; 7 | 8 | public class ModuleRequireSecureConnection extends ModuleBase 9 | { 10 | public void onConnect(IClient client, RequestFunction function, AMFDataList params) 11 | { 12 | if (!client.isSecure()) 13 | { 14 | client.rejectConnection("Secure connection required."); 15 | getLogger().info("ModuleRequireSecureConnection.onConnect: rejectConnection: clientId:"+client.getClientId()); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /vpmedia-wms-test/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | com.webcam.media.red5.dev=DEBUG -------------------------------------------------------------------------------- /vpmedia-wms-test/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %date [%thread] %-5level %logger{35} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /vpmedia-wms-test/src/main/resources/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Dev 6 | 7 | 8 | globalScope 9 | default 10 | 11 | 12 | 13 | contextConfigLocation 14 | /WEB-INF/red5-*.xml 15 | 16 | 17 | 18 | locatorFactorySelector 19 | red5.xml 20 | 21 | 22 | 23 | parentContextKey 24 | default.context 25 | 26 | 27 | 28 | webAppRootKey 29 | /dev 30 | 31 | 32 | 35 | 36 | 37 | 38 | gateway 39 | 40 | org.red5.server.net.servlet.AMFGatewayServlet 41 | 42 | 1 43 | 44 | 45 | 46 | gateway 47 | /gateway 48 | 49 | 50 | 51 | 52 | 53 | 54 | Forbidden 55 | /streams/* 56 | 57 | 58 | 59 | 60 | 61 | 62 | Forbidden 63 | /persistence/* 64 | 65 | 66 | 67 | 68 | 69 | 70 | Forbidden 71 | /WEB-INF/* 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /vpmedia-wms-test/src/main/resources/wms-test/Application.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 60000 5 | 12000 6 | 30000 7 | 8 | 9 | true 10 | * 11 | 12 | 13 | 21 | 22 | 23 | -1 24 | 25 | * 26 | * 27 | * 28 | * 29 | * 30 | * 31 | 32 | 33 | 34 | 35 | live 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 48 | 49 | 50 | 51 | base 52 | Base 53 | com.wowza.wms.module.ModuleCore 54 | 55 | 56 | properties 57 | Properties 58 | com.wowza.wms.module.ModuleProperties 59 | 60 | 61 | logging 62 | Client Logging 63 | com.wowza.wms.module.ModuleClientLogging 64 | 65 | 66 | DBAuthentication 67 | DataBase Authentication plug-in 68 | hu.vpmedia.media.wms.plugin.dbauthentication.DBAuthentication 69 | 70 | 71 | BWCheck 72 | Bandwidth Checker 73 | hu.vpmedia.media.wms.plugin.bwcheck.BWCheck 74 | 75 | 76 | FME 77 | Flash Media Encoder plug-in 78 | hu.vpmedia.media.wms.plugin.fme.FME 79 | 80 | 81 | MediaLoader 82 | Media Loader plug-in 83 | hu.vpmedia.media.wms.plugin.medialoader.MediaLoader 84 | 85 | 86 | 87 | 88 | 89 | 90 | production_server 91 | false 92 | 93 | 94 | domainLock 95 | http://localhost 96 | 97 | 98 | maxApplicationConnections 99 | 100 100 | Integer 101 | 102 | 103 | dbHost 104 | 127.0.0.1 105 | 106 | 107 | dbName 108 | appframework 109 | 110 | 111 | dbUser 112 | root 113 | 114 | 115 | dbPass 116 | a1b2c3d4 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | --------------------------------------------------------------------------------