PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/RTMPConnector/SharedObject.cs

https://code.google.com/
C# | 670 lines | 633 code | 16 blank | 21 comment | 113 complexity | d984c739d3a39acbf49ec0fa7d7b4ece MD5 | raw file
  1. /*
  2. * Created by SharpDevelop.
  3. * User: sanmadmin
  4. * Date: 6/29/2011
  5. * Time: 5:57 PM
  6. *
  7. * To change this template use Tools | Options | Coding | Edit Standard Headers.
  8. */
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Net.Security;
  12. using System.Net;
  13. using System.Text;
  14. using System.Reflection;
  15. using System.Runtime.Serialization;
  16. using System.Runtime.Serialization.Formatters.Binary;
  17. using System.IO;
  18. namespace RTMP
  19. {
  20. /// <summary>
  21. /// Description of SharedObject.
  22. /// </summary>
  23. public enum SOEvents : int
  24. {
  25. Use=1, // Client --> Server inform creation of a named shared object
  26. Release=2, // Client --> Server SO deleted client side
  27. RequestChange=3, // Client --> Server request of changing the value of a named parameter
  28. Change=4, // Server --> Client notify all clients (except requester) about changing the vale of a named parameter
  29. Success=5, // Server --> Client inform requester about accepting change of the parameter
  30. SendMessage=6, // Client --> Server broadcast a message
  31. // Server --> Client broadcast a message to all clients(including originator)
  32. Status=7, // Server --> Client inform error status
  33. Clear=8, // Server --> Client clear shared object
  34. Remove=9, // Server --> Client delete a named parameter
  35. RequestRemove=10, // Client --> Client request of deleting a named parameter
  36. UseSuccess=11 // Server --> Client successful connection
  37. };
  38. public class SharedObject
  39. {
  40. private NetConnection con;
  41. public string name="";
  42. public bool IsConnected=false;
  43. public bool IsPersistant=false;
  44. public Logger logger=new Logger();
  45. private object data;
  46. public object client=null;
  47. private Dictionary<object, object>PendingData=new Dictionary<object, object>();
  48. public delegate void SyncEventHandler(string name,object oldData,object newData);
  49. public delegate void ConnectEventHandler();
  50. public delegate void ClearEventHandler();
  51. public delegate void StatusEventHandler(string status,string message);
  52. public event SyncEventHandler Sync;
  53. public event ConnectEventHandler Connected;
  54. public event ClearEventHandler Cleared;
  55. public event StatusEventHandler Status;
  56. private bool initrunning=false;
  57. public SharedObject()
  58. {
  59. }
  60. public Dictionary<object, object> getData()
  61. {
  62. if(data==null)
  63. return null;
  64. IFormatter formatter = new BinaryFormatter();
  65. Stream stream = new MemoryStream();
  66. formatter.Serialize(stream, data);
  67. stream.Seek(0, SeekOrigin.Begin);
  68. return (Dictionary<object, object>)formatter.Deserialize(stream);
  69. //return new Dictionary<object, object>((Dictionary<object, object>)data);
  70. }
  71. public bool setProperty(string property, object objValue)
  72. {
  73. if(PendingData.ContainsKey((object)property))
  74. return false;
  75. PendingData.Add((object)property,objValue);
  76. return true;
  77. }
  78. public void getRemote(NetConnection con,string name,bool bPersistent=false)
  79. {
  80. this.con=con;
  81. this.name=name;
  82. this.IsPersistant=bPersistent;
  83. if(!con.SOList.ContainsKey(name))
  84. con.SOList.Add(name,this);
  85. RTMPPacket packet=new RTMPPacket();
  86. packet.m_nChannel = 0x03; // control channel (invoke)
  87. packet.HeaderType=HeaderType.Large;
  88. packet.PacketType= PacketType.SharedObject;
  89. packet.AllocPacket(4096);
  90. List<byte>enc=new List<byte>();
  91. short length = IPAddress.HostToNetworkOrder((short)name.Length);
  92. enc.AddRange(BitConverter.GetBytes(length));
  93. enc.AddRange(Encoding.ASCII.GetBytes(name));
  94. Coding.EncodeInt32(enc,0,0);
  95. if(IsPersistant)
  96. Coding.EncodeInt32(enc,2,0);
  97. else
  98. Coding.EncodeInt32(enc,0,0);
  99. Coding.EncodeInt32(enc,0,0);
  100. enc.Add(0x01);
  101. Coding.EncodeInt32(enc,0,0);
  102. Array.Copy(enc.ToArray(), packet.m_body, enc.Count);
  103. packet.m_nBodySize = (uint)enc.Count;
  104. if(con.SendPacket(packet))
  105. logger.Log("SO connect request sent");
  106. else
  107. logger.Log("SO connect request failed to send");
  108. }
  109. public void Close()
  110. {
  111. if(!con.SOList.ContainsKey(name))
  112. con.SOList.Add(name,this);
  113. RTMPPacket packet=new RTMPPacket();
  114. packet.m_nChannel = 0x03; // control channel (invoke)
  115. packet.HeaderType=HeaderType.Large;
  116. packet.PacketType= PacketType.SharedObject;
  117. packet.AllocPacket(4096);
  118. List<byte>enc=new List<byte>();
  119. short length = IPAddress.HostToNetworkOrder((short)name.Length);
  120. enc.AddRange(BitConverter.GetBytes(length));
  121. enc.AddRange(Encoding.ASCII.GetBytes(name));
  122. Coding.EncodeInt32(enc,0,0);
  123. if(IsPersistant)
  124. Coding.EncodeInt32(enc,2,0);
  125. else
  126. Coding.EncodeInt32(enc,0,0);
  127. Coding.EncodeInt32(enc,0,0);
  128. enc.Add(0x02);
  129. Coding.EncodeInt32(enc,0,0);
  130. Array.Copy(enc.ToArray(), packet.m_body, enc.Count);
  131. packet.m_nBodySize = (uint)enc.Count;
  132. if(con.SendPacket(packet))
  133. logger.Log("SO close request sent");
  134. else
  135. logger.Log("SO close request failed to send");
  136. }
  137. public bool send(string message, object param)
  138. {
  139. try
  140. {
  141. List<byte>enc=new List<byte>();
  142. List<byte>temp=new List<byte>();
  143. encodeName(enc,name);
  144. Coding.EncodeInt32(enc,0x2);
  145. Coding.EncodeInt32(enc,0x0);
  146. Coding.EncodeInt32(enc,0x0);
  147. enc.Add(0x6); // client sends message event
  148. encodeString(temp,message);
  149. if(param.GetType()==typeof(bool))
  150. encodeBoolean(temp,(bool)param);
  151. else if(param.GetType()==typeof(double))
  152. encodeNumber(temp,(double)param);
  153. else if(param.GetType()==typeof(string))
  154. encodeString(temp,(string)param);
  155. else if(param.GetType()==typeof(List<object>) || param.GetType()==typeof(Dictionary<object,object>))
  156. encodeObject(ref temp,param);
  157. else
  158. return false;
  159. byte[] bl=BitConverter.GetBytes(temp.Count);
  160. enc.AddRange(new byte[]{bl[3],bl[2],bl[1],bl[0]});
  161. enc.AddRange(temp);
  162. RTMPPacket packet=new RTMPPacket();
  163. packet.m_nChannel = 0x03; // control channel (invoke)
  164. packet.HeaderType=HeaderType.Large;
  165. packet.PacketType= PacketType.SharedObject;
  166. packet.AllocPacket(4096);
  167. Array.Copy(enc.ToArray(), packet.m_body, enc.Count);
  168. packet.m_nBodySize = (uint)enc.Count;
  169. con.SendPacket(packet,true);
  170. }
  171. catch{return false;}
  172. return true;
  173. }
  174. public bool setDirty(string property)
  175. {
  176. if(data==null)
  177. return false;
  178. if(data.GetType()!=typeof(Dictionary<object, object>))
  179. return false;
  180. try
  181. {
  182. List<byte>enc=new List<byte>();
  183. List<byte>temp=new List<byte>();
  184. encodeName(enc,name);
  185. Coding.EncodeInt32(enc,0x2);
  186. Coding.EncodeInt32(enc,0x0);
  187. Coding.EncodeInt32(enc,0x0);
  188. enc.Add(0x3); // client side named parameter changed event
  189. Dictionary<object, object>dic=(Dictionary<object, object>)this.data;
  190. object obj=null;
  191. if(!dic.TryGetValue((object)property,out obj))
  192. return false;
  193. if(obj==null)
  194. return false;
  195. encodeName(temp,property);
  196. if(obj.GetType()==typeof(bool))
  197. encodeBoolean(temp,(bool)obj);
  198. else if(obj.GetType()==typeof(double))
  199. encodeNumber(temp,(double)obj);
  200. else if(obj.GetType()==typeof(string))
  201. encodeString(temp,(string)obj);
  202. else if(obj.GetType()==typeof(List<object>) || obj.GetType()==typeof(Dictionary<object,object>))
  203. encodeObject(ref temp,obj);
  204. else
  205. return false;
  206. byte[] bl=BitConverter.GetBytes(temp.Count);
  207. enc.AddRange(new byte[]{bl[3],bl[2],bl[1],bl[0]});
  208. enc.AddRange(temp);
  209. RTMPPacket packet=new RTMPPacket();
  210. packet.m_nChannel = 0x03; // control channel (invoke)
  211. packet.HeaderType=HeaderType.Large;
  212. packet.PacketType= PacketType.SharedObject;
  213. packet.AllocPacket(4096);
  214. Array.Copy(enc.ToArray(), packet.m_body, enc.Count);
  215. packet.m_nBodySize = (uint)enc.Count;
  216. con.SendPacket(packet,true);
  217. }
  218. catch{return false;}
  219. return true;
  220. }
  221. private int handleStatus(byte[] data,int offset,int size)
  222. {
  223. string message=Coding.ReadString(data,offset);
  224. int msgsize=Coding.ReadInt16(data,offset);
  225. string status=Coding.ReadString(data,offset+msgsize+2);
  226. int statussize=Coding.ReadInt16(data,offset+msgsize+2);
  227. onStatus(status,message);
  228. logger.Log("SO: "+name+"--->Status message arrived: "+status+": "+message);
  229. return msgsize+statussize+4;
  230. }
  231. private object insertAMFObject(AMFObject prop)
  232. {
  233. object pdata=null;
  234. foreach(AMFObjectProperty p in prop.m_properties)
  235. {
  236. object obj=null;
  237. if(p.m_type==AMFDataType.AMF_NUMBER)
  238. obj=p.m_dNumVal;
  239. else if(p.m_type==AMFDataType.AMF_BOOLEAN)
  240. {
  241. if(p.m_dNumVal==0) obj=false;
  242. else obj=true;
  243. }
  244. else if(p.m_type== AMFDataType.AMF_STRING)
  245. obj=p.m_strVal;
  246. else if(p.m_type==AMFDataType.AMF_STRICT_ARRAY || p.m_type==AMFDataType.AMF_OBJECT ||
  247. p.m_type==AMFDataType.AMF_TYPED_OBJECT)
  248. obj=insertAMFObject(p.m_objVal);
  249. else
  250. {
  251. logger.Log("Unsupported shared object type");
  252. continue;
  253. }
  254. if(pdata==null)
  255. {
  256. if(p.m_strName.Length>0)
  257. pdata=new Dictionary<object, object>();
  258. else
  259. pdata=new List<object>();
  260. }
  261. if(pdata.GetType()==typeof(List<object>))
  262. ((List<object>)pdata).Add(obj);
  263. else
  264. ((Dictionary<object, object>)pdata).Add(p.m_strName,obj);
  265. }
  266. return pdata;
  267. }
  268. private void encodeObject(ref List<byte>data,object amfdata)
  269. {
  270. List<byte>temp=new List<byte>();
  271. byte[] bcount=null;
  272. if(amfdata.GetType()==typeof(List<object>))
  273. {
  274. byte[] btemp=BitConverter.GetBytes(((List<object>)amfdata).Count);
  275. bcount=new Byte[]{btemp[3],btemp[2],btemp[1],btemp[0]};
  276. foreach(object obj in (List<object>)amfdata)
  277. {
  278. try
  279. {
  280. if(obj.GetType()==typeof(bool))
  281. encodeBoolean(temp,(bool)obj);
  282. else if(obj.GetType()==typeof(double))
  283. encodeNumber(temp,(double)obj);
  284. else if(obj.GetType()==typeof(string))
  285. encodeString(temp,(string)obj);
  286. else if(obj.GetType()==typeof(List<object>) || obj.GetType()==typeof(Dictionary<object,object>))
  287. encodeObject(ref data,obj);
  288. else
  289. continue;
  290. }
  291. catch{continue;}
  292. }
  293. data.Add((byte)AMFDataType.AMF_STRICT_ARRAY);
  294. }
  295. else if(amfdata.GetType()==typeof(Dictionary<object, object>))
  296. {
  297. byte[] btemp=BitConverter.GetBytes(((Dictionary<object, object>)amfdata).Keys.Count);
  298. bcount=new Byte[]{10,btemp[3],btemp[2],btemp[1],btemp[0]};
  299. foreach(object nameobj in ((Dictionary<object, object>)amfdata).Keys)
  300. {
  301. try
  302. {
  303. object obj=null;
  304. encodeName(temp,(string)nameobj);
  305. if(!((Dictionary<object, object>)amfdata).TryGetValue(nameobj,out obj))
  306. continue;
  307. if(obj.GetType()==typeof(bool))
  308. encodeBoolean(temp,(bool)obj);
  309. else if(obj.GetType()==typeof(double))
  310. encodeNumber(temp,(double)obj);
  311. else if(obj.GetType()==typeof(string))
  312. encodeString(temp,(string)obj);
  313. else if(obj.GetType()==typeof(List<object>) || obj.GetType()==typeof(Dictionary<object,object>))
  314. encodeObject(ref data,obj);
  315. else
  316. continue;
  317. }
  318. catch{continue;}
  319. }
  320. data.Add((byte)AMFDataType.AMF_ECMA_ARRAY);
  321. }
  322. data.AddRange(bcount);
  323. data.AddRange(temp);
  324. }
  325. private bool deleteData(string name)
  326. {
  327. if(data==null)
  328. return false;
  329. if(data.GetType()!=typeof(Dictionary<object, object>))
  330. return false;
  331. Dictionary<object, object>dic=(Dictionary<object, object>)data;
  332. if(dic.Remove((object)name))
  333. return true;
  334. return false;
  335. }
  336. private int insertData(byte[] data,int offset,int size)
  337. {
  338. int pos=0;
  339. AMFObjectProperty prop=new AMFObjectProperty();
  340. pos+=prop.Decode(data,offset,size,true);
  341. object obj=null;
  342. if(pos==-1)
  343. return size;
  344. if(prop.m_type==AMFDataType.AMF_NUMBER)
  345. obj=prop.m_dNumVal;
  346. else if(prop.m_type==AMFDataType.AMF_BOOLEAN)
  347. {
  348. if(prop.m_dNumVal==0)
  349. obj=false;
  350. else
  351. obj=true;
  352. }
  353. else if(prop.m_type== AMFDataType.AMF_STRING)
  354. obj=prop.m_strVal;
  355. else if(prop.m_type==AMFDataType.AMF_STRICT_ARRAY || prop.m_type==AMFDataType.AMF_OBJECT ||
  356. prop.m_type==AMFDataType.AMF_TYPED_OBJECT)
  357. obj=insertAMFObject(prop.m_objVal);
  358. else
  359. {
  360. logger.Log("Unsupported shared object type");
  361. return size;
  362. }
  363. if(this.data==null)
  364. {
  365. if(prop.m_strName.Length==0)
  366. this.data=new List<object>();
  367. else
  368. this.data=new Dictionary<object, object>();
  369. }
  370. if(this.data.GetType()==typeof(List<object>))
  371. ((List<object>)this.data).Add(obj);
  372. else
  373. {
  374. Dictionary<object, object>sodata=(Dictionary<object, object>)this.data;
  375. if(!initrunning)
  376. {
  377. if(sodata.ContainsKey(prop.m_strName))
  378. onSync(prop.m_strName,sodata[prop.m_strName],obj);
  379. else
  380. onSync(prop.m_strName,null,obj);
  381. }
  382. if(sodata.ContainsKey(prop.m_strName))
  383. deleteData(prop.m_strName);
  384. sodata.Add(prop.m_strName,obj);
  385. }
  386. return pos;
  387. }
  388. private int handleUpdateData(byte[] data,int offset,int size)
  389. {
  390. int pos=0;
  391. while(pos<size)
  392. {
  393. pos+=insertData(data,offset,size);
  394. }
  395. return pos;
  396. }
  397. private int handleAcceptRequest(byte[] data, int offset,int size)
  398. {
  399. int pos=0;
  400. while(pos<size)
  401. {
  402. string name=Coding.ReadString(data,offset+pos);
  403. object newData=null;
  404. if(PendingData.TryGetValue((object)name,out newData))
  405. {
  406. object oldData=null;
  407. ((Dictionary<object, object>)this.data).TryGetValue((object)name,out oldData);
  408. onSync(name,oldData,newData);
  409. Dictionary<object, object>dic=(Dictionary<object, object>)this.data;
  410. if(dic.ContainsKey((object)name))
  411. dic[(object)name]=newData;
  412. else
  413. dic.Add((object)name,newData);
  414. PendingData.Remove((object)name);
  415. }
  416. pos+=name.Length+2;
  417. logger.Log("SO "+name+": ---> Update data accepted on property: "+name);
  418. }
  419. return pos;
  420. }
  421. private int handleDeleteData(byte[] data,int offset,int size)
  422. {
  423. int pos=0;
  424. while(pos<size)
  425. {
  426. AMFObjectProperty prop=new AMFObjectProperty();
  427. prop.Decode(data,offset,size,true);
  428. pos+=prop.m_strName.Length+2;
  429. if(prop.m_strName.Length>0)
  430. {
  431. Dictionary<object, object>sodata=(Dictionary<object, object>)this.data;
  432. if(!sodata.ContainsKey(prop.m_strName))
  433. continue;
  434. onSync(prop.m_strName,sodata[prop.m_strName],null);
  435. if(deleteData(prop.m_strName))
  436. {}
  437. //logger.Log("SO "+name+": ---> Property: "+prop.m_strName+" deleted");
  438. }
  439. }
  440. return pos;
  441. }
  442. private int handleInitData(byte[] data, int offset,int size)
  443. {
  444. int pos=0;
  445. logger.Log("SO: "+name+"---> Connect success message arrived!");
  446. while(pos<size)
  447. {
  448. AMFObjectProperty prop=new AMFObjectProperty();
  449. pos+=prop.Decode(data,offset,size,true);
  450. }
  451. return pos;
  452. }
  453. private int handleClear(byte[] data,int offset,int size)
  454. {
  455. this.data=null;
  456. logger.Log("SO: "+name+"---> Clear request arrived!");
  457. return 0;
  458. }
  459. private int handleSendMessage(byte[] data,int offset,int size)
  460. {
  461. if(client==null)
  462. return size;
  463. int pos=0;
  464. AMFObject obj=new AMFObject();
  465. pos+=obj.Decode(data,offset,size,false);
  466. try
  467. {
  468. string methodname=obj.GetProperty(0).GetString();
  469. Type t=client.GetType();
  470. if(t==null)
  471. throw new Exception();
  472. MethodInfo method=t.GetMethod(methodname);
  473. if(method==null)
  474. return size;
  475. if(obj.m_properties.Count>1)
  476. {
  477. List<object>param=new List<object>();
  478. for(int i=1;i<obj.m_properties.Count;i++)
  479. {
  480. AMFObjectProperty prop=obj.m_properties[i];
  481. if(prop.m_type==AMFDataType.AMF_BOOLEAN || prop.m_type== AMFDataType.AMF_NUMBER)
  482. param.Add((object)prop.m_dNumVal);
  483. else if(prop.m_type==AMFDataType.AMF_STRING)
  484. param.Add((object)prop.m_strVal);
  485. else if(prop.m_objVal!=null)
  486. param.Add((object)prop.m_objVal);
  487. }
  488. method.Invoke(client,param.ToArray());
  489. }
  490. else
  491. method.Invoke(client,null);
  492. }
  493. catch{}
  494. return size;
  495. }
  496. private int handleEvent(byte[] data,int offset)
  497. {
  498. int type=(int)data[offset];
  499. int size=(int)Coding.ReadInt32(data,offset+1);
  500. int dataoffset=offset+5;
  501. int pos=size;
  502. switch(type)
  503. {
  504. case (int)SOEvents.Change:
  505. pos=handleUpdateData(data,dataoffset,size);
  506. //logger.Log("-------------Shared object: "+name+"----------------");
  507. //dump(this.data);
  508. break;
  509. case (int)SOEvents.Success:
  510. pos=handleAcceptRequest(data,dataoffset,size);
  511. //logger.Log("-------------Shared object: "+name+"----------------");
  512. //dump(this.data);
  513. break;
  514. case (int)SOEvents.SendMessage:
  515. pos=handleSendMessage(data,dataoffset,size);
  516. break;
  517. case (int)SOEvents.Status:
  518. pos=handleStatus(data,dataoffset,size);
  519. break;
  520. case (int)SOEvents.Clear:
  521. pos=handleClear(data,dataoffset,size);
  522. onCleared();
  523. break;
  524. case (int)SOEvents.Remove:
  525. pos=handleDeleteData(data,dataoffset,size);
  526. //logger.Log("-------------Shared object: "+name+"----------------");
  527. //dump(this.data);
  528. break;
  529. case (int)SOEvents.UseSuccess:
  530. IsConnected=true;
  531. initrunning=true;
  532. pos=handleInitData(data,dataoffset,size);
  533. break;
  534. default:
  535. logger.Log("Unknown shared object event arrived: "+type.ToString());
  536. break;
  537. }
  538. return 5+pos;
  539. }
  540. internal void handleEvents(byte[] data)
  541. {
  542. int offset=0;
  543. int count=0;
  544. while(offset<data.Length && count<5000)
  545. {
  546. offset+=handleEvent(data,offset);
  547. count++;
  548. }
  549. if(initrunning)
  550. {
  551. initrunning=false;
  552. //dump(this.data);
  553. onConnected();
  554. }
  555. if(count==4999 && offset<data.Length)
  556. logger.Log("SharedObject<"+name+ "> error: event overflow");
  557. }
  558. private void encodeBoolean(List<byte> output, bool bVal)
  559. {
  560. output.Add(0x1); // type: Boolean
  561. output.Add(bVal ? (byte)0x1 : (byte)0x0);
  562. }
  563. private void encodeName(List<byte>output,string strValue)
  564. {
  565. short length = IPAddress.HostToNetworkOrder((short)strValue.Length);
  566. output.AddRange(BitConverter.GetBytes(length));
  567. output.AddRange(Encoding.ASCII.GetBytes(strValue));
  568. }
  569. private void encodeString(List<byte>output,string strValue)
  570. {
  571. output.Add(0x2); // type: Number
  572. short length = IPAddress.HostToNetworkOrder((short)strValue.Length);
  573. output.AddRange(BitConverter.GetBytes(length));
  574. output.AddRange(Encoding.ASCII.GetBytes(strValue));
  575. }
  576. private void encodeNumber(List<byte> output, double dVal)
  577. {
  578. output.Add(0x0); // type: Number
  579. byte[] bytes = BitConverter.GetBytes(dVal);
  580. for (int i = bytes.Length - 1; i >= 0; i--) output.Add(bytes[i]); // add in reversed byte order
  581. }
  582. internal void dump(object data)
  583. {
  584. if(data==null)
  585. return;
  586. if(data.GetType()==typeof(List<object>))
  587. {
  588. foreach(object obj in ((List<object>)data))
  589. {
  590. try
  591. {
  592. if(obj.GetType()!=typeof(List<object>) && obj.GetType()!=typeof(Dictionary<object, object>))
  593. logger.Log(obj.ToString());
  594. else
  595. {
  596. logger.Log("-------------");
  597. dump(obj);
  598. logger.Log("-------------");
  599. }
  600. }
  601. catch(Exception e)
  602. {
  603. logger.Log(e.Message);
  604. }
  605. }
  606. }
  607. else
  608. {
  609. foreach(object obj in ((Dictionary<object,object>)data).Keys)
  610. {
  611. try
  612. {
  613. object d=((Dictionary<object, object>)data)[obj];
  614. if(d.GetType()!=typeof(List<object>) && d.GetType()!=typeof(Dictionary<object, object>))
  615. logger.Log(obj.ToString()+": "+d.ToString());
  616. else
  617. {
  618. logger.Log("-------------");
  619. logger.Log(obj.ToString());
  620. logger.Log("-------------");
  621. dump(d);
  622. logger.Log("-------------");
  623. logger.Log(" ");
  624. }
  625. }
  626. catch(Exception e)
  627. {
  628. logger.Log(e.Message);
  629. }
  630. }
  631. }
  632. }
  633. private void onSync(string name,object oldData,object newData)
  634. {
  635. if(Sync!=null)
  636. Sync(name,oldData,newData);
  637. }
  638. private void onConnected()
  639. {
  640. if(Connected!=null)
  641. Connected();
  642. }
  643. private void onStatus(string status,string message)
  644. {
  645. if(Status!=null)
  646. Status(status,message);
  647. }
  648. private void onCleared()
  649. {
  650. if(Cleared!=null)
  651. Cleared();
  652. }
  653. }
  654. }