PageRenderTime 30ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ATF2/FlightSim/coreApps/sockrw.m

http://atf2flightsim.googlecode.com/
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
  1. function [stat, output, remoteHost] = sockrw(req,arg1,arg2)
  2. % [stat, output] = sockrw(req,arg1,arg2)
  3. % tcp socket communication
  4. % must issue 'init-flserv', 'init-casserv', 'init-flclient' or 'init-casclient'
  5. % before using read/write functionality
  6. % Useage:
  7. % -------------------------------------------------------------------------
  8. % req: 'init-flserv' : setup floodland tcp server
  9. % 'init-flclient' : setup floodland tcp client
  10. % 'init-casserv' : setup CA access server
  11. % 'init-casclient : setup CA access client
  12. % 'set_user' : set user to communicate with to arg2 (string)
  13. % arg1=client/server type ('fl' | 'cas')
  14. % 'get_user' : get name of current user set to communicate with
  15. % arg1=client/server type ('fl' | 'cas')
  16. % (string returned in output)
  17. % 'get_userList' : get name list of all connected users
  18. % arg1=client/server type ('fl' | 'cas')
  19. % string returned in output cell array:
  20. % output{nusers,2} - columns are: user id | ip addr
  21. % 'readchar' : read char string from input buffer, arg1=
  22. % client to use ('fl' | 'cas')
  23. % if arg2 passed, then blocking with this
  24. % timeout value in seconds
  25. % 'writechar' : write char string (arg2 (char)) to socket,
  26. % arg1=client to use ('fl' | 'cas')
  27. % 'readdbl' : read double scalar or vector from socket, arg1=
  28. % client to use ('fl' | 'cas')
  29. % if arg2 passed, then blocking with this
  30. % timeout value in seconds
  31. % 'writedbl' : write double scalar or vector (arg2 (double)) to
  32. % socket, arg1=client to use ('fl' | 'cas')
  33. % 'close' : close socket connection arg1=client to use ('fl' | 'cas')
  34. % 'flush' : flush input and output buffers arg1=client to use ('fl' | 'cas')
  35. % -------------------------------------------------------------------------
  36. % Output: cell array char output from socket stream if readchar requested
  37. % : scalar or vector double if readdbl requested
  38. % remoteHost: IP address of remote client/server
  39. % Stat: Lucretia status return
  40. % -------------------------------------------------------------------------
  41. global FL
  42. persistent userID
  43. % Initialise userID to user1 (this is the only userID if client)
  44. if isempty(userID)
  45. userID='user1';
  46. end % if empty currentUser
  47. import java.net.*
  48. import java.io.*
  49. remoteHost='';
  50. % socket parameters
  51. flsock=8844;
  52. assock=8866;
  53. timeout=FL.socketTimeout; % socket timeout / s
  54. % initialise status returns
  55. stat{1}=1; stat{2}=[];
  56. % Initialisation
  57. output={};
  58. switch lower(req)
  59. case 'close'
  60. if regexp(arg1,'cas')
  61. % Remove any function internals associated with this user
  62. latticeStatus('clearUser',userID);
  63. % Close socket and remove user field
  64. FL.AS.(userID).socket.close;
  65. FL.AS=rmfield(FL.AS,userID);
  66. else
  67. FL.Server.(userID).socket.close;
  68. FL.Server=rmfield(FL.Server,userID);
  69. end % if cas | fl
  70. return
  71. case 'get_user'
  72. output=userID;
  73. return
  74. case 'set_user'
  75. if userListFuncs('test',arg1,arg2)
  76. userID=arg2;
  77. else
  78. stat{1}=-1; stat{2}='unkown user id';
  79. end % if userID in list
  80. return
  81. case 'get_userlist'
  82. output=userListFuncs('get',arg1);
  83. return
  84. case {'init-casserv','init-casclient','init-flserv','init-flclient'}
  85. disp('Initialising socket connection...')
  86. if regexp(req,'cas')
  87. sock=assock;
  88. srvsel='AS';
  89. serverHost=FL.trusted.hostname;
  90. else
  91. sock=flsock;
  92. srvsel='Server';
  93. serverHost='localhost';
  94. end % Server or AS
  95. if isfield(FL,srvsel) && isfield(FL.(srvsel),'t_connect') && isequal(FL.(srvsel).t_connect.running,'on')
  96. stop(FL.(srvsel).t_connect);
  97. end % stop connection timer if running
  98. if isfield(FL,srvsel) && isfield(FL.(srvsel),'servSocket')
  99. if ~FL.(srvsel).servSocket.isClosed
  100. FL.(srvsel).servSocket.close;
  101. end % if not closed, then close
  102. FL.(srvsel)=rmfield(FL.(srvsel),'servSocket');
  103. end % delete servSocket if already there
  104. if isfield(FL,srvsel) && isfield(FL.(srvsel),'socket')
  105. if ~FL.(srvsel).socket.isClosed
  106. FL.(srvsel).socket.close;
  107. end % if not closed, then close
  108. FL.(srvsel)=rmfield(FL.(srvsel),'socket');
  109. end % delete socket if already there
  110. if regexp(req,'serv')
  111. FL.(srvsel).servSocket = ServerSocket(sock);
  112. FL.(srvsel).servSocket.setSoTimeout(10); % socket timeout / ms
  113. if ~isfield(FL.(srvsel),'t_connect')
  114. % create connection timer object
  115. FL.(srvsel).t_connect=timer('StartDelay',1,'Period',timeout*2,...
  116. 'ExecutionMode','FixedRate','BusyMode','drop');
  117. FL.(srvsel).t_connect.ErrorFcn = 'ServerConnect(''ErrorHandler'')';
  118. FL.(srvsel).t_connect.TimerFcn = ['ServerConnect(''',srvsel,''')'];
  119. end % if FL.(srvsel).t_connect
  120. start(FL.(srvsel).t_connect);
  121. else
  122. % Connect to server socket
  123. FL.(srvsel).servSocket = Socket(serverHost,sock);
  124. FL.(srvsel).servSocket.setSoTimeout(30*1000); % socket timeout / ms
  125. input_stream=FL.(srvsel).servSocket.getInputStream;
  126. FL.(srvsel).servSocket_input_stream=DataInputStream(input_stream);
  127. FL.(srvsel).user1.remotehost=char(FL.(srvsel).servSocket.getInetAddress);
  128. pause(2); t0=toc; comSocket=[];
  129. % Get new socket number from server
  130. while 1
  131. if FL.(srvsel).servSocket_input_stream.available
  132. if strcmp(srvsel,'AS')
  133. comSocket=char(FL.(srvsel).servSocket_input_stream.readUTF);
  134. else
  135. while FL.(srvsel).servSocket_input_stream.available
  136. comSocket=[comSocket char(FL.(srvsel).servSocket_input_stream.readByte)];
  137. end % while bytes available
  138. end
  139. break
  140. else
  141. pause(1)
  142. if (toc-t0)>30; error('Timeout waiting for a port number from server'); end;
  143. end % if bytes available
  144. end % while 1
  145. pause(2);
  146. % Connect to given socket on server
  147. if isnan(str2double(comSocket))
  148. uiwait(errordlg(comSocket,'Error connecting to server'));
  149. exit
  150. end
  151. FL.(srvsel).(userID).socket = Socket(serverHost,str2double(comSocket));
  152. FL.(srvsel).(userID).socket.setSoTimeout(30*1000); % socket timeout / ms
  153. FL.(srvsel).(userID).socket.setReceiveBufferSize(FL.sendSize);
  154. FL.(srvsel).(userID).socket.setSendBufferSize(FL.sendSize);
  155. input_stream=FL.(srvsel).(userID).socket.getInputStream;
  156. FL.(srvsel).(userID).socket_input_stream=DataInputStream(input_stream);
  157. FL.(srvsel).(userID).socketIn=BufferedReader(InputStreamReader(input_stream));
  158. output_stream=FL.(srvsel).(userID).socket.getOutputStream;
  159. FL.(srvsel).(userID).socket_output_stream=DataOutputStream(output_stream);
  160. FL.(srvsel).(userID).socketOut=PrintWriter(output_stream);
  161. % Close Server socket
  162. FL.(srvsel).servSocket.close;
  163. FL.(srvsel)=rmfield(FL.(srvsel),{'servSocket' 'servSocket_input_stream'});
  164. end % if server else client
  165. case 'readdbl'
  166. % argument check
  167. if ~exist('arg1','var') || ~ischar(arg1)
  168. errordlg('Incorrect arguments to sockrw!','Socket error');
  169. error('Incorrect arguments to sockrw!');
  170. end % arg check
  171. switch lower(arg1)
  172. case {'cas','fl'}
  173. if strcmp(arg1,'cas')
  174. srv='AS';
  175. else
  176. srv='Server';
  177. end % if arg1==cas
  178. t0=toc;
  179. remoteHost=FL.(srv).(userID).remotehost;
  180. while 1
  181. try
  182. output=[]; firstcall=true;
  183. while FL.(srv).(userID).socket_input_stream.available
  184. if firstcall
  185. pause(0.1)
  186. firstcall=false;
  187. end % wait for data once
  188. output=[output FL.(srv).(userID).socket_input_stream.readDouble];
  189. end % while bytes available
  190. catch
  191. stat{1}=-1; stat{2}=['Socket read error: ',lasterr]; %#ok<LERR>
  192. pause(1);
  193. return
  194. end % try/catch
  195. if exist('arg2','var') && isnumeric(arg2)
  196. if isempty(output)
  197. if (toc-t0)>arg2
  198. stat{1}=-1; stat{2}='User set socket timeout waiting for read';
  199. pause(1);
  200. return
  201. else
  202. continue
  203. end % if timeout
  204. else
  205. return
  206. end % if empty output
  207. else
  208. return
  209. end % if arg2 (timeout for waiting for read)
  210. end % while 1
  211. otherwise
  212. errordlg('Incorrect arguments to sockrw','Socket error');
  213. error('Incorrect arguments to sockrw');
  214. end % switch arg1
  215. case 'writedbl'
  216. if ~exist('arg1','var') || ~exist('arg2','var') || ~ischar(arg1) || ~isnumeric(arg2)
  217. errordlg('Incorrect arguments to sockrw','Socket error');
  218. error('Incorrect arguments to sockrw!');
  219. end % arg check
  220. switch arg1
  221. case {'cas','fl'}
  222. if strcmp(arg1,'cas')
  223. srv='AS';
  224. else
  225. srv='Server';
  226. end % if arg1==cas
  227. % Connection test, if fail -> reconnect
  228. try
  229. for ind=1:length(arg2)
  230. FL.(srv).(userID).socket_output_stream.writeDouble(arg2(ind));
  231. end % for icell
  232. catch
  233. stat{1}=-1; stat{2}=['Socket write error: ',lasterr]; %#ok<LERR>
  234. return
  235. end % try/catch
  236. otherwise
  237. errordlg('Incorrect arguments to sockrw','Socket error');
  238. error('Incorrect arguments to sockrw');
  239. end % switch arg1
  240. case 'readchar'
  241. % argument check
  242. if ~exist('arg1','var') || ~ischar(arg1)
  243. errordlg('Incorrect arguments to sockrw!','Socket error');
  244. error('Incorrect arguments to sockrw!');
  245. end % arg check
  246. % read from tcp stream into output
  247. switch lower(arg1)
  248. case {'cas' 'fl'}
  249. if strcmpi(arg1,'cas')
  250. stype='AS';
  251. else
  252. stype='Server';
  253. end
  254. t0=toc;
  255. remoteHost=FL.(stype).(userID).remotehost;
  256. looprun=true;
  257. pauseBeforeRead=0.1;
  258. while looprun
  259. try
  260. rstr=[]; % havepaused=false;
  261. while FL.(stype).(userID).socket_input_stream.available
  262. if strcmpi(arg1,'cas')
  263. rstr=[rstr char(FL.(stype).(userID).socket_input_stream.readUTF)];
  264. else
  265. rstr=[rstr char(FL.(stype).(userID).socket_input_stream.readByte)];
  266. end
  267. if length(rstr)<7 || ~strcmp(rstr(end-6:end),'/\END/\')
  268. tt0=clock;
  269. while ~FL.(stype).(userID).socket_input_stream.available
  270. if etime(clock,tt0)>10
  271. stat{1}=-1; stat{2}='Timeout waiting for server data';
  272. return
  273. end
  274. if strcmpi(arg1,'cas'); pause(0.1); end;
  275. end
  276. end
  277. end % while bytes available
  278. if ~isempty(rstr);rstr=regexprep(rstr,'/\\END/\\','');end;
  279. if exist('arg2','var') && isnumeric(arg2)
  280. if isempty(rstr)
  281. if (toc-t0)>arg2
  282. stat{1}=-1; stat{2}='User set socket timeout waiting for read';
  283. pause(1);
  284. return
  285. else
  286. continue
  287. end % if timeout
  288. else
  289. looprun=false;
  290. end % if empty output
  291. else
  292. if isempty(rstr)
  293. return
  294. else
  295. looprun=false;
  296. end % if no read data
  297. end % if arg2 (timeout for waiting for read)
  298. % if no ; at end, wait for more data and then wack one on the end and hope for the best...
  299. t1=toc;
  300. while (toc-t1)<10 && ~strcmp(rstr(end),';')
  301. havepaused=false;
  302. while FL.(stype).(userID).socket_input_stream.available
  303. if ~havepaused
  304. pause(pauseBeforeRead)
  305. havepaused=true;
  306. end % if ~havepaused
  307. if strcmpi(arg1,'cas')
  308. rstr=[rstr char(FL.(stype).(userID).socket_input_stream.readUTF)];
  309. else
  310. rstr=[rstr char(FL.(stype).(userID).socket_input_stream.readByte)];
  311. end
  312. end % while bytes available
  313. end % while no timeout
  314. if ~strcmp(rstr(end),';'); rstr=[rstr,';']; end;
  315. C=textscan([rstr],'%s','Delimiter',';','BufSize',length(rstr)+101); %#ok<NBRAK>
  316. for ic=1:length(C{1})
  317. if ~isempty(C{1}{ic})
  318. output{end+1}=C{1}{ic};
  319. end % if ~empty C
  320. end % for ic
  321. catch
  322. stat{1}=-1; stat{2}=['Socket read error: ',lasterr]; %#ok<LERR>
  323. pause(1);
  324. return
  325. end % try/catch
  326. end % while 1
  327. % case 'fl'
  328. % remoteHost=FL.Server.(userID).remotehost;
  329. % try
  330. % rstr=[];
  331. % while FL.Server.(userID).socket_input_stream.available
  332. % rstr=[rstr char(FL.Server.(userID).socket_input_stream.readByte)];
  333. % end % while bytes available
  334. % if ~isempty(rstr)
  335. % % Split commands by ';'
  336. % if rstr(end)~=';'
  337. % % check no more data coming down the pipe (give it 10s)
  338. % t1=toc;
  339. % while FL.AS.(userID).socket_input_stream.available || (toc-t1)<10
  340. % rstr=[rstr char(FL.AS.(userID).socket_input_stream.readByte)];
  341. % end % while bytes available
  342. % % if still no ;, wack one on the end and hope for the best...
  343. % if ~strcmp(rstr(end),';'); rstr=[rstr,';']; end;
  344. % end
  345. % C=textscan([rstr],'%s','Delimiter',';','BufSize',length(rstr)+100); %#ok<NBRAK>
  346. % for ic=1:length(C{1})
  347. % if ~isempty(C{1}{ic})
  348. % output{end+1}=C{1}{ic};
  349. % end % if ~empty C
  350. % end % while ~empty rem
  351. % else
  352. % output={};
  353. % end % if ~ empty rstr
  354. % catch
  355. % stat{1}=-1; stat{2}=['Socket read error: ',lasterr]; %#ok<LERR>
  356. % pause(1);
  357. % return
  358. % end % try/catch
  359. otherwise
  360. errordlg('Incorrect arguments to sockrw','Socket error');
  361. error('Incorrect arguments to sockrw');
  362. end % switch arg1
  363. case 'writechar'
  364. if ~exist('arg1','var') || ~exist('arg2','var') || ~ischar(arg1) || (~ischar(arg2) && ~iscell(arg2))
  365. errordlg('Incorrect arguments to sockrw','Socket error');
  366. error('Incorrect arguments to sockrw!');
  367. end % arg check
  368. switch arg1
  369. case {'cas' 'fl'}
  370. if strcmpi(arg1,'cas')
  371. stype='AS';
  372. else
  373. stype='Server';
  374. end
  375. try
  376. if ~iscell(arg2)
  377. sendstr={arg2};
  378. else
  379. sendstr=arg2;
  380. end % if ~cell arg2
  381. % Each command should be terminated with ';'
  382. for istr=1:length(sendstr)
  383. if ~strcmp(sendstr{istr}(end),';')
  384. sendstr{istr}(end+1)=';';
  385. end % if no ; at end
  386. end % for istr
  387. % check cell contents
  388. if any(cellfun(@(x) ~ischar(x),sendstr))
  389. errordlg('Incorrect arguments to sockrw','Socket error');
  390. error('Incorrect arguments to sockrw!');
  391. end % cell check
  392. % Now send string
  393. for icell=1:length(sendstr)
  394. ssize=FL.sendSize;
  395. while length(sendstr{icell})>ssize
  396. if strcmpi(arg1,'cas')
  397. FL.(stype).(userID).socket_output_stream.writeUTF(sendstr{icell}(1:ssize));
  398. else
  399. FL.(stype).(userID).socket_output_stream.writeBytes(sendstr{icell}(1:ssize));
  400. end
  401. sendstr{icell}=sendstr{icell}(ssize+1:end);
  402. end
  403. if ~isempty(sendstr{icell})
  404. if strcmpi(arg1,'cas')
  405. FL.(stype).(userID).socket_output_stream.writeUTF(sendstr{icell});
  406. else
  407. FL.(stype).(userID).socket_output_stream.writeBytes(sendstr{icell});
  408. end
  409. end
  410. end % for icell
  411. % Add terminator
  412. if ~isempty(sendstr{icell}) && strcmpi(arg1,'cas')
  413. FL.(stype).(userID).socket_output_stream.writeUTF('/\END/\');
  414. elseif ~isempty(sendstr{icell})
  415. FL.(stype).(userID).socket_output_stream.writeBytes('/\END/\');
  416. end
  417. catch
  418. stat{1}=-1; stat{2}=['Socket write error: ',lasterr]; %#ok<LERR>
  419. return
  420. end % try/catch
  421. % case 'fl'
  422. % try
  423. % if ~iscell(arg2)
  424. % sendstr={arg2};
  425. % else
  426. % sendstr=arg2;
  427. % end % if ~cell arg2
  428. % % check cell contents
  429. % if any(cellfun(@(x) ~ischar(x),sendstr))
  430. % errordlg('Incorrect arguments to sockrw','Socket error');
  431. % error('Incorrect arguments to sockrw!');
  432. % end % cell check
  433. % for icell=1:length(sendstr)
  434. % ssize=FL.sendSize;
  435. % while length(sendstr{icell})>ssize
  436. % FL.Server.(userID).socket_output_stream.writeBytes(sendstr{icell}(1:ssize));
  437. % sendstr{icell}=sendstr{icell}(ssize+1:end);
  438. % lastchar=sendstr{icell}(end);
  439. % end % while length > 1e4
  440. % if ~isempty(sendstr{icell})
  441. % FL.Server.(userID).socket_output_stream.writeBytes(sendstr{icell});
  442. % lastchar=sendstr{icell}(end);
  443. % end % send rest
  444. % if ~isequal(lastchar,';'); FL.Server.(userID).socket_output_stream.writeBytes(';'); end;
  445. % end % for icell
  446. % catch
  447. % stat{1}=-1; stat{2}=['Socket write error: ',lasterr]; %#ok<LERR>
  448. % return
  449. % end % try/catch
  450. otherwise
  451. errordlg('Incorrect arguments to sockrw','Socket error');
  452. error('Incorrect arguments to sockrw');
  453. end % switch arg1
  454. case 'flush'
  455. if strcmp(arg1,'cas')
  456. srv='AS';
  457. else
  458. srv='Server';
  459. end % if arg1==cas
  460. try
  461. FL.(srv).(userID).socket_output_stream.flush;
  462. % Flush socket at other end too
  463. if FL.isthread || ~strcmp(FL.mode,'trusted')
  464. stat=sockrw('writechar',arg1,'flush');
  465. if stat{1}~=1; error(stat{2}); end;
  466. stat=sockrw('readchar',arg1,10);
  467. if stat{1}~=1; error(stat{2}); end;
  468. end
  469. catch
  470. stat{1}=-1;
  471. stat{2}='Error sending buffer flush command';
  472. end
  473. otherwise
  474. errordlg('Incorrect arguments to sockrw','Socket error');
  475. error('Incorrect arguments to sockrw');
  476. end % switch req
  477. function output=userListFuncs(cmd,srvreq,user)
  478. global FL
  479. if strcmp(srvreq,'fl')
  480. srv='Server';
  481. else
  482. srv='AS';
  483. end % if srvreq=fl
  484. fnames=fieldnames(FL.(srv));
  485. userList={};
  486. output=[];
  487. switch cmd
  488. case 'get'
  489. for iname=1:length(fnames)
  490. if strcmp(fnames{iname}(1:4),'user')
  491. userList{end+1,1}=fnames{iname};
  492. userList{end,2}=FL.(srv).(userList{end,1}).remotehost;
  493. end % if userID field
  494. end % for iname
  495. output=userList;
  496. case 'test'
  497. output=ismember(user,fnames);
  498. end