MATLAB: Setting callbacks to respond to incoming messages on a LightStreamer channel.

lightstreamerurlread2

I want to read an open channel from LightStreamer, in particular the LightStreamer service from IG.
LS operates in two modes: streaming and polling (streaming being preferred). I have quite successfully written a lot of code to handle a polling connection (setting LS_polling=true on /lightstreamer/create_session.txt ; false is the default) but handling a stream connection would be much more efficient and simplify the process quite considerably.
I've been using Jim Hokanson's excellent URLREAD2 function for polling but this appears to hang if I try it in a streaming mode, on line 263 of the following, if that's helpful to anyone.
260 byteArrayOutputStream = java.io.ByteArrayOutputStream;
261 % This StreamCopier is unsupported and may change at any time. OH GREAT :/
262 isc = InterruptibleStreamCopier.getInterruptibleStreamCopier;
263 isc.copyStream(inputStream,byteArrayOutputStream);
264 inputStream.close;
265 byteArrayOutputStream.close;
I'm wondering if some modification to URLREAD2 might be possible that would open the connection and allow the setting of callbacks to handle incoming messages?

Best Answer

This is somewhat like having a conversation with myself (it happens). Anyway, as I started I'll continue. It turns out not to be as complicated as I thought it would be. I can strip out much of URLREAD2 for this dedicated situation, and then decoding the stream is very well defined. All that's left is to cast this into the classdef and handle the events.
function output = urlreadls(url,body,varargin)
% + URL
try
protocol = url(1:find(url==':',1)-1);
handler = sun.net.www.protocol.(protocol).Handler;
url = java.net.URL([],url,handler);
urlConnection = url.openConnection;
urlConnection.setRequestMethod('POST');
catch ME
% TODO


rethrow(ME)
end
% + BODY
try
body = unicode2native(body,'');
urlConnection.setRequestProperty('Content-Length',int2str(length(body)));
urlConnection.setDoOutput(true);
catch ME
% TODO
rethrow(ME)
end
% + POST
try
outputStream = urlConnection.getOutputStream;
outputStream.write(body);
outputStream.close;
catch ME
% TODO
rethrow(ME)
end
% + STEAM
inputStream = urlConnection.getInputStream;
% Read the first line; it will be either "ERROR", "OK",
% or possibly HTTP error 500.
line = linereader(inputStream);
switch line
case 'ERROR'
% There will be 2 more lines only; then close the stream.
output.ERROR.err_code = linereader(inputStream);
output.ERROR.err_msg = linereader(inputStream);
inputStream.close;
case 'OK'
% There will be between 3 and 6 lines following in the form:
% "ParamName:" + ParamValue + "\r\n", followed finally by a blank
% line. The blank line marks the start of the push phase.
line = linereader(inputStream);
while ~isempty(line)
param = regexp(line,':','split');
output.OK.(param{1}) = param{2};
line = linereader(inputStream);
end
% Handle the push phase.
try
while true
line = linereader(inputStream);
disp(line)
end
catch ME
end
otherwise
% Probably HTTP 500; I don't know exactly what this looks like
% until I see one. TODO: confirm it's a 500 or handle seperately.
output.ERROR.err_code = '500';
output.ERROR.err_msg = line;
save errorline line
inputStream.close;
end
function line = linereader(inputStream)
byteArray(1) = inputStream.read; % <--- 'O'
byteArray(2) = inputStream.read; % <--- 'K'
while ~isequal(byteArray(end-1:end),[13 10])
byteArray(end+1) = inputStream.read;
end
line = char(byteArray(1:end-2));