/ATF2/FlightSim/coreApps/sockrw.m
MATLAB | 505 lines | 377 code | 7 blank | 121 comment | 86 complexity | b5b9a1d19d6e7bd74de654adbd5f2cd2 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
- function [stat, output, remoteHost] = sockrw(req,arg1,arg2)
- % [stat, output] = sockrw(req,arg1,arg2)
- % tcp socket communication
- % must issue 'init-flserv', 'init-casserv', 'init-flclient' or 'init-casclient'
- % before using read/write functionality
- % Useage:
- % -------------------------------------------------------------------------
- % req: 'init-flserv' : setup floodland tcp server
- % 'init-flclient' : setup floodland tcp client
- % 'init-casserv' : setup CA access server
- % 'init-casclient : setup CA access client
- % 'set_user' : set user to communicate with to arg2 (string)
- % arg1=client/server type ('fl' | 'cas')
- % 'get_user' : get name of current user set to communicate with
- % arg1=client/server type ('fl' | 'cas')
- % (string returned in output)
- % 'get_userList' : get name list of all connected users
- % arg1=client/server type ('fl' | 'cas')
- % string returned in output cell array:
- % output{nusers,2} - columns are: user id | ip addr
- % 'readchar' : read char string from input buffer, arg1=
- % client to use ('fl' | 'cas')
- % if arg2 passed, then blocking with this
- % timeout value in seconds
- % 'writechar' : write char string (arg2 (char)) to socket,
- % arg1=client to use ('fl' | 'cas')
- % 'readdbl' : read double scalar or vector from socket, arg1=
- % client to use ('fl' | 'cas')
- % if arg2 passed, then blocking with this
- % timeout value in seconds
- % 'writedbl' : write double scalar or vector (arg2 (double)) to
- % socket, arg1=client to use ('fl' | 'cas')
- % 'close' : close socket connection arg1=client to use ('fl' | 'cas')
- % 'flush' : flush input and output buffers arg1=client to use ('fl' | 'cas')
- % -------------------------------------------------------------------------
- % Output: cell array char output from socket stream if readchar requested
- % : scalar or vector double if readdbl requested
- % remoteHost: IP address of remote client/server
- % Stat: Lucretia status return
- % -------------------------------------------------------------------------
- global FL
- persistent userID
- % Initialise userID to user1 (this is the only userID if client)
- if isempty(userID)
- userID='user1';
- end % if empty currentUser
- import java.net.*
- import java.io.*
- remoteHost='';
- % socket parameters
- flsock=8844;
- assock=8866;
- timeout=FL.socketTimeout; % socket timeout / s
- % initialise status returns
- stat{1}=1; stat{2}=[];
- % Initialisation
- output={};
- switch lower(req)
- case 'close'
- if regexp(arg1,'cas')
- % Remove any function internals associated with this user
- latticeStatus('clearUser',userID);
- % Close socket and remove user field
- FL.AS.(userID).socket.close;
- FL.AS=rmfield(FL.AS,userID);
- else
- FL.Server.(userID).socket.close;
- FL.Server=rmfield(FL.Server,userID);
- end % if cas | fl
- return
- case 'get_user'
- output=userID;
- return
- case 'set_user'
- if userListFuncs('test',arg1,arg2)
- userID=arg2;
- else
- stat{1}=-1; stat{2}='unkown user id';
- end % if userID in list
- return
- case 'get_userlist'
- output=userListFuncs('get',arg1);
- return
- case {'init-casserv','init-casclient','init-flserv','init-flclient'}
- disp('Initialising socket connection...')
- if regexp(req,'cas')
- sock=assock;
- srvsel='AS';
- serverHost=FL.trusted.hostname;
- else
- sock=flsock;
- srvsel='Server';
- serverHost='localhost';
- end % Server or AS
- if isfield(FL,srvsel) && isfield(FL.(srvsel),'t_connect') && isequal(FL.(srvsel).t_connect.running,'on')
- stop(FL.(srvsel).t_connect);
- end % stop connection timer if running
- if isfield(FL,srvsel) && isfield(FL.(srvsel),'servSocket')
- if ~FL.(srvsel).servSocket.isClosed
- FL.(srvsel).servSocket.close;
- end % if not closed, then close
- FL.(srvsel)=rmfield(FL.(srvsel),'servSocket');
- end % delete servSocket if already there
- if isfield(FL,srvsel) && isfield(FL.(srvsel),'socket')
- if ~FL.(srvsel).socket.isClosed
- FL.(srvsel).socket.close;
- end % if not closed, then close
- FL.(srvsel)=rmfield(FL.(srvsel),'socket');
- end % delete socket if already there
- if regexp(req,'serv')
- FL.(srvsel).servSocket = ServerSocket(sock);
- FL.(srvsel).servSocket.setSoTimeout(10); % socket timeout / ms
- if ~isfield(FL.(srvsel),'t_connect')
- % create connection timer object
- FL.(srvsel).t_connect=timer('StartDelay',1,'Period',timeout*2,...
- 'ExecutionMode','FixedRate','BusyMode','drop');
- FL.(srvsel).t_connect.ErrorFcn = 'ServerConnect(''ErrorHandler'')';
- FL.(srvsel).t_connect.TimerFcn = ['ServerConnect(''',srvsel,''')'];
- end % if FL.(srvsel).t_connect
- start(FL.(srvsel).t_connect);
- else
- % Connect to server socket
- FL.(srvsel).servSocket = Socket(serverHost,sock);
- FL.(srvsel).servSocket.setSoTimeout(30*1000); % socket timeout / ms
- input_stream=FL.(srvsel).servSocket.getInputStream;
- FL.(srvsel).servSocket_input_stream=DataInputStream(input_stream);
- FL.(srvsel).user1.remotehost=char(FL.(srvsel).servSocket.getInetAddress);
- pause(2); t0=toc; comSocket=[];
- % Get new socket number from server
- while 1
- if FL.(srvsel).servSocket_input_stream.available
- if strcmp(srvsel,'AS')
- comSocket=char(FL.(srvsel).servSocket_input_stream.readUTF);
- else
- while FL.(srvsel).servSocket_input_stream.available
- comSocket=[comSocket char(FL.(srvsel).servSocket_input_stream.readByte)];
- end % while bytes available
- end
- break
- else
- pause(1)
- if (toc-t0)>30; error('Timeout waiting for a port number from server'); end;
- end % if bytes available
- end % while 1
- pause(2);
- % Connect to given socket on server
- if isnan(str2double(comSocket))
- uiwait(errordlg(comSocket,'Error connecting to server'));
- exit
- end
- FL.(srvsel).(userID).socket = Socket(serverHost,str2double(comSocket));
- FL.(srvsel).(userID).socket.setSoTimeout(30*1000); % socket timeout / ms
- FL.(srvsel).(userID).socket.setReceiveBufferSize(FL.sendSize);
- FL.(srvsel).(userID).socket.setSendBufferSize(FL.sendSize);
- input_stream=FL.(srvsel).(userID).socket.getInputStream;
- FL.(srvsel).(userID).socket_input_stream=DataInputStream(input_stream);
- FL.(srvsel).(userID).socketIn=BufferedReader(InputStreamReader(input_stream));
- output_stream=FL.(srvsel).(userID).socket.getOutputStream;
- FL.(srvsel).(userID).socket_output_stream=DataOutputStream(output_stream);
- FL.(srvsel).(userID).socketOut=PrintWriter(output_stream);
- % Close Server socket
- FL.(srvsel).servSocket.close;
- FL.(srvsel)=rmfield(FL.(srvsel),{'servSocket' 'servSocket_input_stream'});
- end % if server else client
- case 'readdbl'
- % argument check
- if ~exist('arg1','var') || ~ischar(arg1)
- errordlg('Incorrect arguments to sockrw!','Socket error');
- error('Incorrect arguments to sockrw!');
- end % arg check
- switch lower(arg1)
- case {'cas','fl'}
- if strcmp(arg1,'cas')
- srv='AS';
- else
- srv='Server';
- end % if arg1==cas
- t0=toc;
- remoteHost=FL.(srv).(userID).remotehost;
- while 1
- try
- output=[]; firstcall=true;
- while FL.(srv).(userID).socket_input_stream.available
- if firstcall
- pause(0.1)
- firstcall=false;
- end % wait for data once
- output=[output FL.(srv).(userID).socket_input_stream.readDouble];
- end % while bytes available
- catch
- stat{1}=-1; stat{2}=['Socket read error: ',lasterr]; %#ok<LERR>
- pause(1);
- return
- end % try/catch
- if exist('arg2','var') && isnumeric(arg2)
- if isempty(output)
- if (toc-t0)>arg2
- stat{1}=-1; stat{2}='User set socket timeout waiting for read';
- pause(1);
- return
- else
- continue
- end % if timeout
- else
- return
- end % if empty output
- else
- return
- end % if arg2 (timeout for waiting for read)
- end % while 1
- otherwise
- errordlg('Incorrect arguments to sockrw','Socket error');
- error('Incorrect arguments to sockrw');
- end % switch arg1
- case 'writedbl'
- if ~exist('arg1','var') || ~exist('arg2','var') || ~ischar(arg1) || ~isnumeric(arg2)
- errordlg('Incorrect arguments to sockrw','Socket error');
- error('Incorrect arguments to sockrw!');
- end % arg check
- switch arg1
- case {'cas','fl'}
- if strcmp(arg1,'cas')
- srv='AS';
- else
- srv='Server';
- end % if arg1==cas
- % Connection test, if fail -> reconnect
- try
- for ind=1:length(arg2)
- FL.(srv).(userID).socket_output_stream.writeDouble(arg2(ind));
- end % for icell
- catch
- stat{1}=-1; stat{2}=['Socket write error: ',lasterr]; %#ok<LERR>
- return
- end % try/catch
- otherwise
- errordlg('Incorrect arguments to sockrw','Socket error');
- error('Incorrect arguments to sockrw');
- end % switch arg1
- case 'readchar'
- % argument check
- if ~exist('arg1','var') || ~ischar(arg1)
- errordlg('Incorrect arguments to sockrw!','Socket error');
- error('Incorrect arguments to sockrw!');
- end % arg check
- % read from tcp stream into output
- switch lower(arg1)
- case {'cas' 'fl'}
- if strcmpi(arg1,'cas')
- stype='AS';
- else
- stype='Server';
- end
- t0=toc;
- remoteHost=FL.(stype).(userID).remotehost;
- looprun=true;
- pauseBeforeRead=0.1;
- while looprun
- try
- rstr=[]; % havepaused=false;
- while FL.(stype).(userID).socket_input_stream.available
- if strcmpi(arg1,'cas')
- rstr=[rstr char(FL.(stype).(userID).socket_input_stream.readUTF)];
- else
- rstr=[rstr char(FL.(stype).(userID).socket_input_stream.readByte)];
- end
- if length(rstr)<7 || ~strcmp(rstr(end-6:end),'/\END/\')
- tt0=clock;
- while ~FL.(stype).(userID).socket_input_stream.available
- if etime(clock,tt0)>10
- stat{1}=-1; stat{2}='Timeout waiting for server data';
- return
- end
- if strcmpi(arg1,'cas'); pause(0.1); end;
- end
- end
- end % while bytes available
- if ~isempty(rstr);rstr=regexprep(rstr,'/\\END/\\','');end;
- if exist('arg2','var') && isnumeric(arg2)
- if isempty(rstr)
- if (toc-t0)>arg2
- stat{1}=-1; stat{2}='User set socket timeout waiting for read';
- pause(1);
- return
- else
- continue
- end % if timeout
- else
- looprun=false;
- end % if empty output
- else
- if isempty(rstr)
- return
- else
- looprun=false;
- end % if no read data
- end % if arg2 (timeout for waiting for read)
- % if no ; at end, wait for more data and then wack one on the end and hope for the best...
- t1=toc;
- while (toc-t1)<10 && ~strcmp(rstr(end),';')
- havepaused=false;
- while FL.(stype).(userID).socket_input_stream.available
- if ~havepaused
- pause(pauseBeforeRead)
- havepaused=true;
- end % if ~havepaused
- if strcmpi(arg1,'cas')
- rstr=[rstr char(FL.(stype).(userID).socket_input_stream.readUTF)];
- else
- rstr=[rstr char(FL.(stype).(userID).socket_input_stream.readByte)];
- end
- end % while bytes available
- end % while no timeout
- if ~strcmp(rstr(end),';'); rstr=[rstr,';']; end;
- C=textscan([rstr],'%s','Delimiter',';','BufSize',length(rstr)+101); %#ok<NBRAK>
- for ic=1:length(C{1})
- if ~isempty(C{1}{ic})
- output{end+1}=C{1}{ic};
- end % if ~empty C
- end % for ic
- catch
- stat{1}=-1; stat{2}=['Socket read error: ',lasterr]; %#ok<LERR>
- pause(1);
- return
- end % try/catch
- end % while 1
- % case 'fl'
- % remoteHost=FL.Server.(userID).remotehost;
- % try
- % rstr=[];
- % while FL.Server.(userID).socket_input_stream.available
- % rstr=[rstr char(FL.Server.(userID).socket_input_stream.readByte)];
- % end % while bytes available
- % if ~isempty(rstr)
- % % Split commands by ';'
- % if rstr(end)~=';'
- % % check no more data coming down the pipe (give it 10s)
- % t1=toc;
- % while FL.AS.(userID).socket_input_stream.available || (toc-t1)<10
- % rstr=[rstr char(FL.AS.(userID).socket_input_stream.readByte)];
- % end % while bytes available
- % % if still no ;, wack one on the end and hope for the best...
- % if ~strcmp(rstr(end),';'); rstr=[rstr,';']; end;
- % end
- % C=textscan([rstr],'%s','Delimiter',';','BufSize',length(rstr)+100); %#ok<NBRAK>
- % for ic=1:length(C{1})
- % if ~isempty(C{1}{ic})
- % output{end+1}=C{1}{ic};
- % end % if ~empty C
- % end % while ~empty rem
- % else
- % output={};
- % end % if ~ empty rstr
- % catch
- % stat{1}=-1; stat{2}=['Socket read error: ',lasterr]; %#ok<LERR>
- % pause(1);
- % return
- % end % try/catch
- otherwise
- errordlg('Incorrect arguments to sockrw','Socket error');
- error('Incorrect arguments to sockrw');
- end % switch arg1
- case 'writechar'
- if ~exist('arg1','var') || ~exist('arg2','var') || ~ischar(arg1) || (~ischar(arg2) && ~iscell(arg2))
- errordlg('Incorrect arguments to sockrw','Socket error');
- error('Incorrect arguments to sockrw!');
- end % arg check
- switch arg1
- case {'cas' 'fl'}
- if strcmpi(arg1,'cas')
- stype='AS';
- else
- stype='Server';
- end
- try
- if ~iscell(arg2)
- sendstr={arg2};
- else
- sendstr=arg2;
- end % if ~cell arg2
- % Each command should be terminated with ';'
- for istr=1:length(sendstr)
- if ~strcmp(sendstr{istr}(end),';')
- sendstr{istr}(end+1)=';';
- end % if no ; at end
- end % for istr
- % check cell contents
- if any(cellfun(@(x) ~ischar(x),sendstr))
- errordlg('Incorrect arguments to sockrw','Socket error');
- error('Incorrect arguments to sockrw!');
- end % cell check
- % Now send string
- for icell=1:length(sendstr)
- ssize=FL.sendSize;
- while length(sendstr{icell})>ssize
- if strcmpi(arg1,'cas')
- FL.(stype).(userID).socket_output_stream.writeUTF(sendstr{icell}(1:ssize));
- else
- FL.(stype).(userID).socket_output_stream.writeBytes(sendstr{icell}(1:ssize));
- end
- sendstr{icell}=sendstr{icell}(ssize+1:end);
- end
- if ~isempty(sendstr{icell})
- if strcmpi(arg1,'cas')
- FL.(stype).(userID).socket_output_stream.writeUTF(sendstr{icell});
- else
- FL.(stype).(userID).socket_output_stream.writeBytes(sendstr{icell});
- end
- end
- end % for icell
- % Add terminator
- if ~isempty(sendstr{icell}) && strcmpi(arg1,'cas')
- FL.(stype).(userID).socket_output_stream.writeUTF('/\END/\');
- elseif ~isempty(sendstr{icell})
- FL.(stype).(userID).socket_output_stream.writeBytes('/\END/\');
- end
- catch
- stat{1}=-1; stat{2}=['Socket write error: ',lasterr]; %#ok<LERR>
- return
- end % try/catch
- % case 'fl'
- % try
- % if ~iscell(arg2)
- % sendstr={arg2};
- % else
- % sendstr=arg2;
- % end % if ~cell arg2
- % % check cell contents
- % if any(cellfun(@(x) ~ischar(x),sendstr))
- % errordlg('Incorrect arguments to sockrw','Socket error');
- % error('Incorrect arguments to sockrw!');
- % end % cell check
- % for icell=1:length(sendstr)
- % ssize=FL.sendSize;
- % while length(sendstr{icell})>ssize
- % FL.Server.(userID).socket_output_stream.writeBytes(sendstr{icell}(1:ssize));
- % sendstr{icell}=sendstr{icell}(ssize+1:end);
- % lastchar=sendstr{icell}(end);
- % end % while length > 1e4
- % if ~isempty(sendstr{icell})
- % FL.Server.(userID).socket_output_stream.writeBytes(sendstr{icell});
- % lastchar=sendstr{icell}(end);
- % end % send rest
- % if ~isequal(lastchar,';'); FL.Server.(userID).socket_output_stream.writeBytes(';'); end;
- % end % for icell
- % catch
- % stat{1}=-1; stat{2}=['Socket write error: ',lasterr]; %#ok<LERR>
- % return
- % end % try/catch
- otherwise
- errordlg('Incorrect arguments to sockrw','Socket error');
- error('Incorrect arguments to sockrw');
- end % switch arg1
- case 'flush'
- if strcmp(arg1,'cas')
- srv='AS';
- else
- srv='Server';
- end % if arg1==cas
- try
- FL.(srv).(userID).socket_output_stream.flush;
- % Flush socket at other end too
- if FL.isthread || ~strcmp(FL.mode,'trusted')
- stat=sockrw('writechar',arg1,'flush');
- if stat{1}~=1; error(stat{2}); end;
- stat=sockrw('readchar',arg1,10);
- if stat{1}~=1; error(stat{2}); end;
- end
- catch
- stat{1}=-1;
- stat{2}='Error sending buffer flush command';
- end
- otherwise
- errordlg('Incorrect arguments to sockrw','Socket error');
- error('Incorrect arguments to sockrw');
- end % switch req
- function output=userListFuncs(cmd,srvreq,user)
- global FL
- if strcmp(srvreq,'fl')
- srv='Server';
- else
- srv='AS';
- end % if srvreq=fl
- fnames=fieldnames(FL.(srv));
- userList={};
- output=[];
- switch cmd
- case 'get'
- for iname=1:length(fnames)
- if strcmp(fnames{iname}(1:4),'user')
- userList{end+1,1}=fnames{iname};
- userList{end,2}=FL.(srv).(userList{end,1}).remotehost;
- end % if userID field
- end % for iname
- output=userList;
- case 'test'
- output=ismember(user,fnames);
- end