/// <summary> /// Append another Data object to this array /// </summary> /// <param name="data">The object do append</param> /// <returns>Return itself</returns> public DataArray AddData(Data data) { if (Format != data.Format) throw new FormatException("Data element must match the DataArray format: '" + data.Format + "' was given, '" + Format + "' was expected"); Buffer.Append(data.Buffer); Length++; return this; }
/// <summary> /// Create a new exception. It must be declared in the Registry /// </summary> /// <param name="type">The type of the exception</param> /// <param name="data">The data pack</param> public CallException(uint type, Data data) { // Validate the exception type Registry.RegisteredException entry = Registry.GetException(type); if (entry == null) throw new ArgumentException("Invalid exception type " + type); // Validate the data format if (data.Format != entry.DataFormat.FormatString) throw new ArgumentException("Invalid data type '" + data.Format + "' for exception " + type); Type = type; Data = data; }
/// <summary> /// Internal method to send the answer /// </summary> /// <param name="exceptionType">The exception type (0 means no exception, normal return instead)</param> /// <param name="data">The data pack to send</param> /// <returns>Return whether the answer was sent (false if the connection is closed)</returns> bool Answer(uint exceptionType, Data data) { // Validate the connection if (answered) throw new InvalidOperationException("Answer already sent"); if (!Conn.IsReady) return false; // Validate the arguments if (exceptionType != 0) { if (!Call.HasException(exceptionType)) throw new ArgumentException("Invalid exception " + exceptionType + " to call " + Call.Id); } else { if (data.Format != Call.ReturnFormat.FormatString) throw new ArgumentException("Invalid data type '" + data.Format + "' for return type " + Call.Id); } // Send the answer byte[] binData = data.GetBytes(); byte[] binMeta = new Data().AddUint((ulong)0).AddInt(CallId).AddInt(exceptionType).GetBytes(); byte[] binLength = new Data().AddUint((ulong)(binData.Length + binMeta.Length)).GetBytes(); Conn.Socket.Write(binLength); Conn.Socket.Write(binMeta); Conn.Socket.Write(binData); answered = true; return true; }
/// <summary> /// Answer the call with a given return /// </summary> /// <param name="data">The data pack to send</param> /// <returns>Return whether the answer was sent (false if the connection is closed)</returns> public bool Answer(Data data) { return Answer(0, data); }
/// <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)); }
/// <summary> /// Append something to the Data object /// </summary> /// <param name="data">Another Data object</param> /// <returns>Return itself</returns> public Data AddData(Data data) { Buffer.Append(data.Buffer); Format += data.Format; return this; }