/// <summary> /// Send a call to the server /// </summary> /// <param name="type">The call type (must have been registered with Registry.RegisterClientCall)</param> /// <param name="data">The data pack to send</param> /// <param name="onReturn">The callback to be executed when the server answers this call</param> /// <param name="onException">The callback to be executed when the server answer this call with an exception (or the call timeouts or the connection closes)</param> /// <param name="timeout">The timeout (in ms), 0 means no timeout</param> public void SendCall(uint type, Data data, ReturnDelegate onReturn = null, ExceptionDelegate onException = null, int timeout = 60000) { // Validate the data if (!IsReady) { throw new InvalidOperationException("The connection has already been closed"); } Registry.RegisteredCall call = Registry.GetClientCall(type); if (call == null) { throw new ArgumentException("Invalid call type " + type); } if (data.Format != call.ArgsFormat.FormatString) { throw new ArgumentException("Invalid data type '" + data.Format + "' for call " + type); } // Create the meta-data byte[] binData = data.GetBytes(); byte[] binMeta = new Data().AddUint(type).AddUint(++LastSentId).GetBytes(); byte[] binLength = new Data().AddUint((ulong)(binData.Length + binMeta.Length)).GetBytes(); // Send the call Socket.Write(binLength); Socket.Write(binMeta); Socket.Write(binData); // Set timeout Timer interval = null; if (timeout != 0) { interval = new Timer(timeout); interval.AutoReset = false; interval.Elapsed += TimeoutCallback; interval.Start(); } // Save info about the sent call PendingCalls.AddLast(new PendingCall(LastSentId, call, onReturn, onException, interval)); }