/// <summary> /// call the server method /// </summary> /// <typeparam name="T">any type can be used here when the server is void</typeparam> /// <param name="fun">data generated by Fun.fun</param> /// <returns>the data returned by the server is null when there is no return value</returns> public T Invoke <T>(ByteQue fun) { byte[] data = new SendData(fun).ToArray(); int write = 0; while (true) { write += socket.Send(data, write, data.Length - write, SocketFlags.None); if (write >= data.Length) { break; } } RecvBuf recv = new RecvBuf(); byte[] buf = new byte[1024]; while (true) { if (recv.Size.HasValue && recv.Size == recv.Len) { break; } int read = socket.Receive(buf); if (read > 0) { recv.Append(buf, read); } else { Dispose(); throw new Exception("remote connection has been disconnected"); } } ByteQue ret = recv.ByteQue; String msg = ret.Pop <string>(); if (msg != null) { throw new Exception(msg); } if (ret.Len > 0) { return(ret.Pop <T>()); } return(default(T)); }
/// <summary> /// call the registered method /// </summary> /// <param name="que">the queue generated by fun</param> /// <returns>serialize error messages or call results into a queue</returns> public ByteQue Invoke(ByteQue que) { byte[] arr = new byte[que.PopSize()]; for (int i = 0; i < arr.Length; ++i) { arr[i] = que.Pop <byte>(); } string name = Encoding.UTF8.GetString(arr); if (!funs.ContainsKey(name)) { return(Except(name + " function not found")); } ObjectMethod om = funs[name]; ParameterInfo[] types = om.fun.GetParameters(); object[] args = new object[types.Length]; for (int i = 0; i < types.Length; ++i) { Type type = types[i].ParameterType; if (que.Len == 0) { return(Except("error when calling function " + name + " to restore parameters to the " + i + "th parameter " + type.ToString())); } try { args[i] = que.Pop(type); } catch (Exception e) { return(Except("error when calling function " + name + " to restore parameters to the " + i + "th parameter " + type.ToString() + ": " + e.ToString())); } } if (que.Len != 0) { return(Except("error when calling function " + name + " to restore parameters")); } ByteQue ret = new ByteQue(); object rst; try { rst = om.fun.Invoke(om.obj, args); } catch (Exception e) { return(Except("error calling function " + name + " " + e.ToString())); } ret.Push(false); Type rtp = om.fun.ReturnType; if (rtp != typeof(void)) { try { ret.Push(rtp, rst); } catch (Exception e) { return(Except("error calling function " + name + " to store result " + e.ToString())); } } return(ret); }
/// <summary> /// add some data to the buffer until it reaches the specified length /// </summary> /// <param name="other">part of the data</param> /// <param name="length">actual data length</param> public void Append(byte[] other, int length) { if (length < 0) { length = other.Length; } if (size.HasValue) { if (size.Value > buff.Len) { int l = size.Value - buff.Len; if (l < length) { buff.AddAll(other, 0, l); } else { buff.AddAll(other, 0, length); } } } else { if (buff.Len == 0) { for (int x = 0; x < length; ++x) { if (x == 4 || other[x] <= 0x7f) { int s = 0; for (int i = 0; i <= x; ++i) { s |= (other[i] & 0x7f) << 7 * i; } size = s; s += x + 1; if (s < length) { buff.AddAll(other, x + 1, s); } else { buff.AddAll(other, x + 1, length); } return; } } buff.AddAll(other, 0, length); } else { buff.AddAll(other, 0, length); byte[] arr = buff.ToArray(); for (int x = 0; x < arr.Length; ++x) { if (x == 4 || arr[x] <= 0x7f) { int s = 0; for (int i = 0; i <= x; ++i) { s |= (buff.Pop <byte>() & 0x7f) << 7 * i; } size = s; s += x + 1; if (arr.Length > s) { buff = new ByteQue(); buff.AddAll(arr, x + 1, s); } break; } } } } }