public static (int, byte[]) Header(SyncBufManager bufferManager, byte version, uint devId, long startTick, BrainDevState state) { var buf = bufferManager.TakeBuffer(CntStartIndex); buf[0] = version; var ind = 1; unsafe { WritePrimitive((byte *)&devId, sizeof(uint), buf, ref ind); WritePrimitive((byte *)&startTick, sizeof(long), buf, ref ind); buf[ind++] = state.DevCode; buf[ind++] = state.ChannelCount; buf[ind++] = state.Gain; buf[ind++] = (byte)state.SampleRate; buf[ind++] = (byte)state.TrapOption; buf[ind++] = state.EnalbeFilter ? (byte)1 : (byte)0; for (var i = ind; i < CntStartIndex; i++) { buf[i] = 0; } } return(CntStartIndex, buf); }
public static async Task <int> SendCompletelyAsync(this Socket socket, IList <ArraySegment <byte> > buffers, SocketFlags socketFlags, CancellationToken token, SyncBufManager bufMgr) { token.ThrowIfCancellationRequested(); var sent = 0; var count = 0; for (var i = 0; i < buffers.Count; i++) { count += buffers[i].Count; } var copy = bufMgr.TakeBuffer(count); try { count = 0; for (var i = 0; i < buffers.Count; i++) { ArraySegment <byte> arraySegment = buffers[i]; Buffer.BlockCopy(arraySegment.Array, arraySegment.Offset, copy, count, arraySegment.Count); count += arraySegment.Count; } var bytes = await socket.SendCompletelyAsync(copy, count, socketFlags, token); sent += bytes; AppLogger.Debug($"SendCompletelyAsync:{sent},{buffers.Show()}"); return(sent); } finally { bufMgr.ReturnBuffer(copy); } }
public static IObservable <DisposableValue <ArraySegment <byte> > > ToFixedLenFrameObservable(this Socket socket, SyncBufManager bufferManager, IFixedLenFrameDecoder decoder) { return(Observable.Create <DisposableValue <ArraySegment <byte> > >(async(observer, token) => { var receivedFlag = decoder.ReceivedFlags; var decoderLenByteCount = decoder.LenByteCount; var hc = 1 + decoderLenByteCount; var decoderHeader = decoder.Header; var decoderTail = decoder.Tail; var headerBuffer = new byte[hc]; try { while (!token.IsCancellationRequested) { if (await socket.ReceiveCompletelyAsync(headerBuffer, hc, receivedFlag, token) != hc) { break; } if (headerBuffer[0] != decoderHeader) { AppLogger.Warning($"corruted packet: invalid frame header"); break; } var length = LengthBitConverter.FromByte(headerBuffer, 1, decoderLenByteCount) - 1; var buffer = bufferManager.TakeBuffer(length); if (await socket.ReceiveCompletelyAsync(buffer, length, receivedFlag, token) != length) { break; } var arraySegment = new ArraySegment <byte>(buffer, 0, length); observer.OnNext( new DisposableValue <ArraySegment <byte> >(arraySegment, Disposable.Create(() => bufferManager.ReturnBuffer(buffer)))); if (await socket.ReceiveAsync(headerBuffer, 0, 1, receivedFlag) == 0) { break; } if (headerBuffer[0] != decoderTail) { AppLogger.Warning($"corruted packet: invalid frame tail," + headerBuffer[0].Show()); break; } } observer.OnCompleted(); } catch (Exception error) { observer.OnError(error); } })); }
private static async Task SendSampleData(int sampleTimeTick, SampleRateEnum rate, Socket socket, CancellationToken ctsToken) { byte size = 2 + ChannelCount * 3; var buf = bmgr.TakeBuffer(size); //_r.NextBytes(buf); var passTimes = BrainDevState.PassTimeMs(rate, sampleTimeTick); const float max = 4.5f / 24; buf[0] = (byte)DevCommandFuncId.StartStop; buf[1] = _brainState.SamplePacketOrder++; for (int i = 0; i < ChannelCount; i++) { var sampleValue = Math.Sin(passTimes * 2 / 1000f * Math.PI + i * simalatedDelta) * max; var(b0, b1, b2) = BitDataConverter.ConvertTo(sampleValue, 4.5f, 24); buf[2 + i * 3] = b0; buf[2 + 1 + i * 3] = b1; buf[2 + 2 + i * 3] = b2; } await SendWithHeadTail(socket, buf, size, ctsToken); bmgr.ReturnBuffer(buf); }
//version 1 (byte version, uint devId, long startTick,BrainDevState state,byte[] MD5Hash) public static (byte, uint, long, BrainDevState, byte[]) ReadHeader(this FileStream fs, SyncBufManager bufferManager) { var buf = bufferManager.TakeBuffer(CntStartIndex); var count = fs.Read(buf, 0, CntStartIndex); if (count < CntStartIndex) { throw new Exception("Invalid Sample Data File Format"); } var version = buf[0]; if (version != 1) { throw new Exception("not supported sample data format, only version 1 is supported"); } var ind = 1; uint devId; long startTick; var state = default(BrainDevState); unsafe { ReadPrimitive((byte *)&devId, sizeof(uint), buf, ref ind); ReadPrimitive((byte *)&startTick, sizeof(long), buf, ref ind); state.DevCode = buf[ind++]; state.ChannelCount = buf[ind++]; state.Gain = buf[ind++]; state.SampleRate = (SampleRateEnum)buf[ind++]; state.TrapOption = (TrapSettingEnum)buf[ind++]; state.EnalbeFilter = buf[ind++] == 1; } var md5Buf = new byte[Md5Len]; Buffer.BlockCopy(buf, ind, md5Buf, 0, Md5Len); bufferManager.ReturnBuffer(buf); return(version, devId, startTick, state, md5Buf); }
public static IObservable <DisposableValue <ArraySegment <byte> > > ToDynamicFrameObservable(this Socket socket, SyncBufManager bufferManager, IDynamicFrameDecoder decoder) { return(Observable.Create <DisposableValue <ArraySegment <byte> > >(async(observer, token) => { try { var state = decoder.InitState(); byte[] leftoverBuf = null; //rider suggestion is buggy: this variable must declare outside the loop in the case when receive length is zero int leftoverCount = 0; while (!token.IsCancellationRequested) { byte[] bufferArray; int startIdx; if (leftoverBuf != null) { bufferArray = leftoverBuf; startIdx = leftoverCount; leftoverBuf = null; } else { bufferArray = bufferManager.TakeBuffer(decoder.BufferSize); startIdx = 0; } var pair = await socket.ReceiveDynamicFrame(state, bufferArray, startIdx, decoder, token); var receiveLen = pair.Item1; leftoverCount = pair.Item2; if (receiveLen == 0) //no data received, and leftoverCount should be zero { var dropFrameStrategy = decoder.CheckDropFrame(state, bufferArray, startIdx); switch (dropFrameStrategy) { case DropFrameStrategyEnum.DropAndClose: //reclaim buffer array bufferManager.ReturnBuffer(bufferArray); break; case DropFrameStrategyEnum.DropAndRestart: //reclaim buffer array bufferManager.ReturnBuffer(bufferArray); continue; case DropFrameStrategyEnum.KeepAndContinue: //keep last received data leftoverBuf = bufferArray; leftoverCount = startIdx; continue; } if (dropFrameStrategy == DropFrameStrategyEnum.DropAndClose) { break; } } if (receiveLen == -1) //overflow,TODO support extensible frame in future { //reclaim buffer array bufferManager.ReturnBuffer(bufferArray); break; } //copy leftover if (leftoverCount > 0) { leftoverBuf = bufferManager.TakeBuffer(decoder.BufferSize); Buffer.BlockCopy(bufferArray, receiveLen - leftoverCount, leftoverBuf, 0, leftoverCount); } var arraySegment = decoder.BuildFrame(state, bufferArray, receiveLen, leftoverCount); observer.OnNext( new DisposableValue <ArraySegment <byte> >(arraySegment, Disposable.Create(() => bufferManager.ReturnBuffer(bufferArray)))); } observer.OnCompleted(); socket.Close(); } catch (Exception error) { observer.OnError(error); } })); }