Accessing Connection Count XML Information - Cross-Domain

I’ve written some javascript (using jquery) that will access the wowza server’s built-in connectioncounts information. It takes this XML information, cleans it up, and displays the information in an easy-to-read HTML page.

Everything works great – on the localhost (on my personal computer)… but as soon as I place the HTML and javascript on an actual server (using Amazon S3 in this case) it doesn’t work. I’m assuming there is a crossdomain issue.

I have the crossdomain.xml file in wowza’s conf directory – and even set it to allow all. No dice. I also changed the HTTPProviders in the Vhost.xml file to “none” for the AuthenticationMethod, thinking that might allow things to work. Again… no luck at all.

Any ideas on what I could do in order to make the XML that wowza generates readable? I thought that maybe I could place the HTML and javascript on the wowza server itself (var/www/html/ directory for Apache) but it will not allow me to alter or add to that directory (I’m running Wowza 2.X on Amazon EC2).

Any help or pointers would be greatly appreciated.

David L Good

Hi David,

I’m facing exactly the same problem. Did you find any solution?

Here is my thread : Can't set crossdomain.xml to allow access to connectioncounts from javascript

Best regards

Richard

Open /conf/VHost.xml /HostPort in a text editor and search for “connectioncounts”, then on the line below that change the AuthenticationMethod to “none”

<AuthenticationMethod>none</AuthenticationMethod>

Or set it to “admin-basic” then add username and password inline like thois

xmlhttp.open("GET", "http://richard:myPassword@owncloud.afopi.com:8086/connectioncounts", false);

Richard

Great! Glad it’s working Thanks for the update.

Richard

Thank you for your answer but the authentification part is not the problem.

In fact : [HTML]xmlhttp.open(“GET”, “http://richard:myPassword@owncloud.afopi.com:8086/connectioncounts”, false);[/HTML]

returns me

[HTML]XMLHttpRequest cannot load http://owncloud.afopi.com:8086/connectioncounts. Origin http://dev.afopi.com is not allowed by Access-Control-Allow-Origin. [/HTML]

Which seems to be a crossdomain policy.

I tried to configure my crossdomain.xml but it doesn’t seems to have any effect.

best regards

richard

Hi Everybody,

I solved my problem yesterday night, the solution i found was to recompile a new “HTTPConnectionCountsXML” class (the HTTPProvider in charge of giving the connection count) with Wowza IDE and include inside :

resp.setHeader("Access-Control-Allow-Origin", "*");

Here is the code of the class based on the one available in the documentation :

package com.wowza.wms.http;
import java.io.*;
import java.util.*;
import java.net.*;
import com.wowza.wms.application.*;
import com.wowza.wms.client.*;
import com.wowza.wms.logging.*;
import com.wowza.wms.server.*;
import com.wowza.wms.vhost.*;
import com.wowza.wms.http.*;
import com.wowza.util.*;
import com.wowza.wms.httpstreamer.model.*;
//import org.json.*;
public class HTTPConnectionCountsXMLCORS extends HTTProvider2Base
{
	class MyCounter
	{
		int total = 0;
	}
	private void outputConnectionInfo(StringBuffer ret, ConnectionCounter counter)
	{
		ret.append("<ConnectionsCurrent>"+counter.getCurrent()+"</ConnectionsCurrent>");
		ret.append("<ConnectionsTotal>"+counter.getTotal()+"</ConnectionsTotal>");
		ret.append("<ConnectionsTotalAccepted>"+counter.getTotalAccepted()+"</ConnectionsTotalAccepted>");
		ret.append("<ConnectionsTotalRejected>"+counter.getTotalRejected()+"</ConnectionsTotalRejected>");
	}
	
	private void outputIOPerformanceInfo(StringBuffer ret, IOPerformanceCounter ioPerformance)
	{
		ret.append("<MessagesInBytesRate>"+ioPerformance.getMessagesInBytesRate()+"</MessagesInBytesRate>");
		ret.append("<MessagesOutBytesRate>"+ioPerformance.getMessagesOutBytesRate()+"</MessagesOutBytesRate>");
	}
	
	private int toCount(Integer intObj, MyCounter counter)
	{
		int ret = intObj==null?0:intObj.intValue();
		counter.total += ret;
		return ret;
	}
	public void onHTTPRequest(IVHost inVhost, IHTTPRequest req, IHTTPResponse resp)
	{
		if (!doHTTPAuthentication(inVhost, req, resp))
			return;
		StringBuffer ret = new StringBuffer();
		
		String queryStr = req.getQueryString();
		Map<String, String> queryMap = HTTPUtils.splitQueryStr(queryStr);
		boolean isFlat = false;
		isFlat = this.properties.getPropertyBoolean("isFlat", isFlat);
		if (queryMap.containsKey("flat"))
			isFlat = true;
		
		try
		{
			List<String> vhostNames = VHostSingleton.getVHostNames();
			ret.append("<?xml version=\"1.0\"?>\n<WowzaMediaServer>");
			
			IServer server = Server.getInstance();
			if (!isFlat)
			{
				outputConnectionInfo(ret, server.getConnectionCounter());
				outputIOPerformanceInfo(ret, server.getIoPerformanceCounter());
			}
			
			Iterator<String> iter = vhostNames.iterator();
			while (iter.hasNext())
			{
				String vhostName = iter.next();
				IVHost vhost = (IVHost)VHostSingleton.getInstance(vhostName);
				if (vhost != null)
				{
					if (!isFlat)
					{
						ret.append("<VHost>");
						ret.append("<Name>"+URLEncoder.encode(vhostName, "UTF-8")+"</Name>");
						ret.append("<TimeRunning>"+vhost.getTimeRunningSeconds()+"</TimeRunning>");
						ret.append("<ConnectionsLimit>"+vhost.getConnectionLimit()+"</ConnectionsLimit>");
						outputConnectionInfo(ret, vhost.getConnectionCounter());
						outputIOPerformanceInfo(ret, vhost.getIoPerformanceCounter());
					}
					List<String> appNames = vhost.getApplicationNames();
					Iterator<String> appNameIterator = appNames.iterator();
					while (appNameIterator.hasNext())
					{
						String applicationName = appNameIterator.next();
						IApplication application = vhost.getApplication(applicationName);
						if (application == null)
							continue;
						if (!isFlat)
						{
							ret.append("<Application>");
							ret.append("<Name>"+URLEncoder.encode(applicationName, "UTF-8")+"</Name>");
							ret.append("<Status>loaded</Status>");
							ret.append("<TimeRunning>"+application.getTimeRunningSeconds()+"</TimeRunning>");
							
							outputConnectionInfo(ret, application.getConnectionCounter());
							outputIOPerformanceInfo(ret, application.getIoPerformanceCounter());
						}
						
						List<String> appInstances = application.getAppInstanceNames();
						Iterator<String> iterAppInstances = appInstances.iterator();
						while (iterAppInstances.hasNext())
						{
							String appInstanceName = iterAppInstances.next();
							IApplicationInstance appInstance = application.getAppInstance(appInstanceName);
							if (appInstance == null)
								continue;
							
							if (!isFlat)
							{
								ret.append("<ApplicationInstance>");
								ret.append("<Name>"+URLEncoder.encode(appInstance.getName(), "UTF-8")+"</Name>");
								ret.append("<TimeRunning>"+appInstance.getTimeRunningSeconds()+"</TimeRunning>");
								
								outputConnectionInfo(ret, appInstance.getConnectionCounter());
								outputIOPerformanceInfo(ret, appInstance.getIOPerformanceCounter());
							}
							
							Map<String, Integer> flashCounts = appInstance.getPlayStreamCountsByName();
							Map<String, Integer> smoothCounts = appInstance.getHTTPStreamerSessionCountsByName(IHTTPStreamerSession.SESSIONPROTOCOL_SMOOTHSTREAMING);
							Map<String, Integer> cupertinoCounts = appInstance.getHTTPStreamerSessionCountsByName(IHTTPStreamerSession.SESSIONPROTOCOL_CUPERTINOSTREAMING);
							Map<String, Integer> sanjoseCounts = appInstance.getHTTPStreamerSessionCountsByName(IHTTPStreamerSession.SESSIONPROTOCOL_SANJOSESTREAMING);
							Map<String, Integer> rtspCounts = appInstance.getRTPSessionCountsByName();
							
							List<String> publishStreams = appInstance.getStreams().getPublishStreamNames();
							
							Set<String> streamNames = new HashSet<String>();
							streamNames.addAll(publishStreams);
							streamNames.addAll(flashCounts.keySet());
							streamNames.addAll(smoothCounts.keySet());
							streamNames.addAll(cupertinoCounts.keySet());
							streamNames.addAll(sanjoseCounts.keySet());
							streamNames.addAll(rtspCounts.keySet());
							
							Iterator<String> siter = streamNames.iterator();
							while(siter.hasNext())
							{
								String streamName = siter.next();
								MyCounter counter = new MyCounter();
								if (isFlat)
								{
									int flashCount = toCount(flashCounts.get(streamName), counter);
									int cupertinoCount = toCount(cupertinoCounts.get(streamName), counter);
									int smoothCount = toCount(smoothCounts.get(streamName), counter);
									int sanjoseCount = toCount(sanjoseCounts.get(streamName), counter);
									int rtspCount = toCount(rtspCounts.get(streamName), counter);
									ret.append("<Stream ");
									ret.append("vhostName=\""+URLEncoder.encode(vhostName, "UTF-8")+"\" ");
									ret.append("applicationName=\""+URLEncoder.encode(applicationName, "UTF-8")+"\" ");
									ret.append("appInstanceName=\""+URLEncoder.encode(appInstanceName, "UTF-8")+"\" ");
									ret.append("streamName=\""+URLEncoder.encode(streamName, "UTF-8")+"\" ");
									ret.append("sessionsFlash=\""+flashCount+"\" ");
									ret.append("sessionsCupertino=\""+cupertinoCount+"\" ");
									ret.append("sessionsSanJose=\""+sanjoseCount+"\" ");
									ret.append("sessionsSmooth=\""+smoothCount+"\" ");
									ret.append("sessionsRTSP=\""+rtspCount+"\" ");
									ret.append("sessionsTotal=\""+counter.total+"\" ");
									ret.append("/>");
								}
								else
								{
									ret.append("<Stream>");
									ret.append("<Name>"+URLEncoder.encode(streamName, "UTF-8")+"</Name>");
									ret.append("<SessionsFlash>"+toCount(flashCounts.get(streamName), counter)+"</SessionsFlash>");
									ret.append("<SessionsCupertino>"+toCount(cupertinoCounts.get(streamName), counter)+"</SessionsCupertino>");
									ret.append("<SessionsSanJose>"+toCount(sanjoseCounts.get(streamName), counter)+"</SessionsSanJose>");
									ret.append("<SessionsSmooth>"+toCount(smoothCounts.get(streamName), counter)+"</SessionsSmooth>");
									ret.append("<SessionsRTSP>"+toCount(rtspCounts.get(streamName), counter)+"</SessionsRTSP>");
									ret.append("<SessionsTotal>"+counter.total+"</SessionsTotal>");
									ret.append("</Stream>");
								}
							}
							
							if (!isFlat)
								ret.append("</ApplicationInstance>");
						}
						
						if (!isFlat)
							ret.append("</Application>");
					}
					
					if (!isFlat)
						ret.append("</VHost>");
				}
			}
			
			ret.append("</WowzaMediaServer>");
		}
		catch (Exception e)
		{
			WMSLoggerFactory.getLogger(HTTPServerVersion.class).error("HTTPServerInfoXML.onHTTPRequest: "+e.toString());
			e.printStackTrace();
		}
						
		try
		{
			resp.setHeader("Access-Control-Allow-Origin", "*");
			resp.setHeader("Content-Type", "text/xml");
			OutputStream out = resp.getOutputStream();
			byte[] outBytes = ret.toString().getBytes();
			out.write(outBytes);
		}
		catch (Exception e)
		{
			WMSLoggerFactory.getLogger(HTTPServerVersion.class).error("HTTPServerInfoXML.onHTTPRequest: "+e.toString());
			e.printStackTrace();
		}
		
	}
}

After that the new .jar is automaticaly put by Wowza IDE inside the /lib/ directory.

and you just have to add a new HTTPProvider in the VHost.xml like this :

</SocketConfiguration>
                                <HTTPStreamerAdapterIDs></HTTPStreamerAdapterIDs>
                                <HTTPProviders>
                                        <HTTPProvider>
                                                <BaseClass>com.wowza.wms.http.streammanager.HTTPStreamManager</BaseClass>
                                                <RequestFilters>streammanager*</RequestFilters>
                                                <AuthenticationMethod>admin-digest</AuthenticationMethod>
                                        </HTTPProvider>
                                        <HTTPProvider>
                                                <BaseClass>com.wowza.wms.http.HTTPServerInfoXML</BaseClass>
                                                <RequestFilters>serverinfo*</RequestFilters>
                                                <AuthenticationMethod>admin-digest</AuthenticationMethod>
                                        </HTTPProvider>
                                        <HTTPProvider>
                                                <BaseClass>com.wowza.wms.http.HTTPConnectionInfo</BaseClass>
                                                <RequestFilters>connectioninfo*</RequestFilters>
                                                <AuthenticationMethod>admin-digest</AuthenticationMethod>
                                        </HTTPProvider>
                                        <HTTPProvider>
                                                <BaseClass>com.wowza.wms.http.HTTPConnectionCountsXML</BaseClass>
                                                <RequestFilters>connectioncounts*</RequestFilters>
                                                <AuthenticationMethod>none</AuthenticationMethod>
                                        </HTTPProvider>
                                        <HTTPProvider>
                                                <BaseClass>com.wowza.wms.http.HTTPConnectionCountsXMLCORS</BaseClass>
                                                <RequestFilters>statsXMLCORS*</RequestFilters>
                                                <AuthenticationMethod>none</AuthenticationMethod>
                                        </HTTPProvider>

The page now return the “Access-Control-Allow-Origin” header with * and allow javascript to perform a crossdomain request at the adress http://IP-WOWZA:8086/statsXMLCORS.

Best regards

Richard