/// <summary> /// Write packet, packet header and tracking information to the given buffer space. This buffer /// should contain the reliability Context at the front, that contains the capacity of the buffer /// and pointer offsets needed to find the slots we can copy the packet to. /// </summary> /// <param name="self">Buffer space where we can store packets.</param> /// <param name="sequence">The sequence ID of the packet, this is used to find a slot inside the buffer.</param> /// <param name="header">The packet header which we'll store with the packet payload.</param> /// <param name="data">The packet data which we're storing.</param> /// <exception cref="OverflowException"></exception> public static unsafe void SetHeaderAndPacket(NativeSlice <byte> self, int sequence, PacketHeader header, InboundBufferVec data, long timestamp) { byte * ptr = (byte *)self.GetUnsafePtr(); Context *ctx = (Context *)ptr; int totalSize = data.buffer1.Length + data.buffer2.Length; if (totalSize > ctx->DataStride) #if ENABLE_UNITY_COLLECTIONS_CHECKS { throw new OverflowException(); } #else { return; } #endif var index = sequence % ctx->Capacity; PacketInformation *info = GetPacketInformation(self, sequence); info->SequenceId = sequence; info->Size = totalSize; info->SendTime = timestamp; Packet *packet = GetPacket(self, sequence); packet->Header = header; var offset = (ctx->DataPtrOffset + (index * ctx->DataStride)) + UnsafeUtility.SizeOf <PacketHeader>(); void *dataPtr = (ptr + offset); if (data.buffer1.Length > 0) { UnsafeUtility.MemCpy(dataPtr, data.buffer1.GetUnsafeReadOnlyPtr(), data.buffer1.Length); } if (data.buffer2.Length > 0) { UnsafeUtility.MemCpy(&dataPtr + data.buffer1.Length, data.buffer2.GetUnsafeReadOnlyPtr(), data.buffer2.Length); } }
public static unsafe PacketInformation *GetPacketInformation(byte *self, int sequence) { Context *ctx = (Context *)self; var index = sequence % ctx->Capacity; return((PacketInformation *)((self + ctx->IndexPtrOffset) + (index * ctx->IndexStride))); }
/// <summary> /// Resume or play back a packet we had received earlier out of order. When an out of order packet is received /// it is stored since we need to first return the packet with the next sequence ID. When that packet finally /// arrives it is returned but a pipeline resume is requested since we already have the next packet stored /// and it can be processed immediately after. /// </summary> /// <param name="context">Pipeline context, we'll use both the shared reliability context and receive context.</param> /// <param name="startSequence">The first packet which we need to retrieve now, there could be more after that.</param> /// <param name="needsResume">Indicates if we need the pipeline to resume again.</param> /// <returns></returns> public static unsafe NativeSlice <byte> ResumeReceive(NetworkPipelineContext context, int startSequence, ref bool needsResume) { if (startSequence == NullEntry) { return(default(NativeSlice <byte>)); } SharedContext *shared = (SharedContext *)context.internalSharedProcessBuffer.GetUnsafePtr(); Context * reliable = (Context *)context.internalProcessBuffer.GetUnsafePtr(); reliable->Resume = NullEntry; PacketInformation *info = GetPacketInformation(context.internalProcessBuffer, startSequence); var latestReceivedPacket = shared->ReceivedPackets.Sequence; if (info->SequenceId == startSequence) { var offset = reliable->DataPtrOffset + ((startSequence % reliable->Capacity) * reliable->DataStride); NativeSlice <byte> slice = new NativeSlice <byte>(context.internalProcessBuffer, offset, info->Size); reliable->Delivered = startSequence; if ((ushort)(startSequence + 1) <= latestReceivedPacket) { reliable->Resume = (ushort)(startSequence + 1); needsResume = true; } return(slice); } return(default(NativeSlice <byte>)); }
/// <summary> /// Write packet, packet header and tracking information to the given buffer space. This buffer /// should contain the reliability Context at the front, that contains the capacity of the buffer /// and pointer offsets needed to find the slots we can copy the packet to. /// </summary> /// <param name="self">Buffer space where we can store packets.</param> /// <param name="sequence">The sequence ID of the packet, this is used to find a slot inside the buffer.</param> /// <param name="header">The packet header which we'll store with the packet payload.</param> /// <param name="data">The packet data which we're storing.</param> /// <exception cref="OverflowException"></exception> public static unsafe void SetHeaderAndPacket(byte *self, int sequence, PacketHeader header, InboundSendBuffer data, long timestamp) { Context *ctx = (Context *)self; int totalSize = data.bufferLength + data.headerPadding; if (totalSize + UnsafeUtility.SizeOf <PacketHeader>() > ctx->DataStride) #if ENABLE_UNITY_COLLECTIONS_CHECKS { throw new OverflowException(); } #else { return; } #endif var index = sequence % ctx->Capacity; PacketInformation *info = GetPacketInformation(self, sequence); info->SequenceId = sequence; info->Size = (ushort)totalSize; info->HeaderPadding = (ushort)data.headerPadding; info->SendTime = timestamp; Packet *packet = GetPacket(self, sequence); packet->Header = header; var offset = (ctx->DataPtrOffset + (index * ctx->DataStride)) + UnsafeUtility.SizeOf <PacketHeader>(); void *dataPtr = (self + offset); if (data.bufferLength > 0) { UnsafeUtility.MemCpy((byte *)dataPtr + data.headerPadding, data.buffer, data.bufferLength); } }
public static unsafe void InitializeContext(Parameters param, byte *sharedProcessBuffer) { // Store parameters in the shared buffer space Context *ctx = (Context *)sharedProcessBuffer; ctx->MaxPacketCount = param.MaxPacketCount; ctx->MaxPacketSize = param.MaxPacketSize; ctx->PacketDelayMs = param.PacketDelayMs; ctx->PacketJitterMs = param.PacketJitterMs; ctx->PacketDrop = param.PacketDropInterval; ctx->FuzzFactor = param.FuzzFactor; ctx->FuzzOffset = param.FuzzOffset; ctx->PacketCount = 0; ctx->PacketDropCount = 0; ctx->Random = new Random(); if (param.RandomSeed > 0) { ctx->Random.InitState(param.RandomSeed); ctx->RandomSeed = param.RandomSeed; } else { ctx->Random.InitState(); } }
static unsafe int GetIndex(byte *self, int index) { Context *ctx = (Context *)self; int *value = (int *)((self + ctx->IndexPtrOffset) + (index * ctx->IndexStride)); return(*value); }
static unsafe void SetIndex(byte *self, int index, int sequence) { Context *ctx = (Context *)self; int *value = (int *)((self + ctx->IndexPtrOffset) + (index * ctx->IndexStride)); *value = sequence; }
public static unsafe PacketInformation *GetPacketInformation(NativeSlice <byte> self, int sequence) { byte * ptr = (byte *)self.GetUnsafePtr(); Context *ctx = (Context *)ptr; var index = sequence % ctx->Capacity; return((PacketInformation *)((ptr + ctx->IndexPtrOffset) + (index * ctx->IndexStride))); }
public static unsafe void Release(NativeSlice <byte> self, int start_sequence, int count) { Context *ctx = (Context *)self.GetUnsafePtr(); for (int i = 0; i < count; i++) { SetIndex(self, (start_sequence + i) % ctx->Capacity, NullEntry); } }
public static unsafe Packet *GetPacket(byte *self, int sequence) { Context *ctx = (Context *)self; var index = sequence % ctx->Capacity; var offset = ctx->DataPtrOffset + (index * ctx->DataStride); return((Packet *)(self + offset)); }
static unsafe int GetIndex(NativeSlice <byte> self, int index) { byte * ptr = (byte *)self.GetUnsafePtr(); Context *ctx = (Context *)ptr; int *value = (int *)((ptr + ctx->IndexPtrOffset) + (index * ctx->IndexStride)); return(*value); }
public void KphSetContextThread(ThreadHandle threadHandle, Context *context) { byte *inData = stackalloc byte[8]; *(int *)inData = threadHandle; *(int *)(inData + 4) = (int)context; _fileHandle.IoControl(CtlCode(Control.KphSetContextThread), inData, 8, null, 0); }
static unsafe void SetIndex(NativeSlice <byte> self, int index, int sequence) { byte * ptr = (byte *)self.GetUnsafePtr(); Context *ctx = (Context *)ptr; int *value = (int *)((ptr + ctx->IndexPtrOffset) + (index * ctx->IndexStride)); *value = sequence; }
public static unsafe void Release(byte *self, int start_sequence, int count) { Context *ctx = (Context *)self; for (int i = 0; i < count; i++) { SetIndex(self, (start_sequence + i) % ctx->Capacity, NullEntry); } }
public static unsafe Packet *GetPacket(NativeSlice <byte> self, int sequence) { byte * ptr = (byte *)self.GetUnsafePtr(); Context *ctx = (Context *)ptr; var index = sequence % ctx->Capacity; var offset = ctx->DataPtrOffset + (index * ctx->DataStride); return((Packet *)(ptr + offset)); }
public void drawSurface(int contextId) { Render.Context context = getContext(contextId); #if PENDING ENTER(Java_scenic_jni_Renderer_drawSurface); Context * context = getContext(contextId); int diffuse = context->color.getRGBA32(); ClipArea *surface; VertexStore vs(VSF_TEX1, context, 0); context->setPrimitives(0); surface = context->clip; context->clip = context->clip->parent; context->setRenderTarget(context->clip->surface); surface->surface->release(); surface->surface = NULL; for (int y = 0; y < 2; y++) { for (int x = 0; x < 2; x++) { double lx = surface->x + x * surface->width; double ly = surface->y + y * surface->height; double tx1 = (float)x / surface->textureWidth * surface->width; double ty1 = (float)y / surface->textureHeight * surface->height; vs.addVertex(lx, ly, diffuse, tx1, ty1); } } vs.addTriangle(0, 1, 2); vs.addTriangle(3, 2, 1); context->device->setTexture(0, surface->texture); context->device->setSamplerStates(0, FILTER_POINT, ADDRESS_CLAMP); context->device->setTextureStageModulation(0, surface->getModulation()); context->device->setBlendFunc(BLEND_ONE, BLEND_ONE_MINUS_SRC_ALPHA); if (surface->linearColorSpace && !context->clip->linearColorSpace) { context->device->setState(STATE_SRGBWRITEENABLE, BOOLEAN_TRUE); } vs.draw(); context->device->setTexture(0, NULL); context->device->setState(STATE_SRGBWRITEENABLE, BOOLEAN_FALSE); textureCache.addTexture(surface->texture); delete surface; #endif }
public static unsafe void InitializeContext(Parameters param, NativeSlice<byte> sharedProcessBuffer) { // Store parameters in the shared buffer space Context* ctx = (Context*) sharedProcessBuffer.GetUnsafePtr(); ctx->MaxPacketCount = param.MaxPacketCount; ctx->MaxPacketSize = param.MaxPacketSize; ctx->PacketDelayMs = param.PacketDelayMs; ctx->PacketDrop = param.PacketDropInterval; ctx->PacketCount = 0; ctx->PacketDropCount = 0; ctx->Random = new Random(); ctx->Random.InitState(); }
void CompletionProc( IntPtr pObject, eNkMAIDCommand ulCommand, UInt32 ulParam, eNkMAIDDataType ulDataType, IntPtr data, IntPtr refComplete, eNkMAIDResult nResult) { Context *context = (Context *)refComplete.ToPointer(); context->Complete = true; context->Result = nResult; }
public unsafe bool ShouldDropPacket(Context* ctx, Parameters param, long timestamp) { if (param.PacketDropInterval > 0 && (ctx->PacketCount - 1) % param.PacketDropInterval == 0) return true; if (param.PacketDropPercentage > 0) { //var packetLoss = new System.Random().NextDouble() * 100; var packetLoss = ctx->Random.NextDouble() * 100; if (packetLoss <= param.PacketDropPercentage) { return true; } } return false; }
public static unsafe bool TryAquire(NativeSlice <byte> self, int sequence) { Context *ctx = (Context *)self.GetUnsafePtr(); var index = sequence % ctx->Capacity; var currentSequenceId = GetIndex(self, index); if (currentSequenceId == NullEntry) { SetIndex(self, index, sequence); return(true); } return(false); }
public AudioOutput(int channels = 1, int sampleRate = 44100) { if (channels < 1 || channels > 2) { throw new ArgumentOutOfRangeException(nameof(channels)); } if (sampleRate < 2000 || sampleRate > 200000) { throw new ArgumentOutOfRangeException(nameof(sampleRate)); } try { al = AL.GetApi(true); alContext = ALContext.GetApi(true); } catch { al = AL.GetApi(false); alContext = ALContext.GetApi(false); } device = alContext.OpenDevice(""); Available = device != null; if (Available) { context = alContext.CreateContext(device, null); alContext.MakeContextCurrent(context); if (al.GetError() != AudioError.NoError) { Available = false; if (context != null) { alContext.DestroyContext(context); } alContext.CloseDevice(device); al.Dispose(); alContext.Dispose(); disposed = true; return; } source = al.GenSource(); al.SetSourceProperty(source, SourceBoolean.Looping, true); al.SetSourceProperty(source, SourceFloat.Gain, 1.0f); } }
/// <summary> /// Resend a packet which we have not received an acknowledgement for in time. Pipeline resume /// will be enabled if there are more packets which we need to resend. The send reliability context /// will then also be updated to track the next packet we need to resume. /// </summary> /// <param name="context">Pipeline context, we'll use both the shared reliability context and send context.</param> /// <param name="header">Packet header for the packet payload we're resending.</param> /// <param name="needsResume">Indicates if a pipeline resume is needed again.</param> /// <returns>Buffer slice to packet payload.</returns> /// <exception cref="ApplicationException"></exception> public static unsafe NativeSlice <byte> ResumeSend(NetworkPipelineContext context, out PacketHeader header, ref bool needsResume) { SharedContext *reliable = (SharedContext *)context.internalSharedProcessBuffer.GetUnsafePtr(); Context * ctx = (Context *)context.internalProcessBuffer.GetUnsafePtr(); #if ENABLE_UNITY_COLLECTIONS_CHECKS if (ctx->Resume == NullEntry) { throw new ApplicationException("This function should not be called unless there is data in resume"); } #endif var sequence = (ushort)ctx->Resume; PacketInformation *information; information = GetPacketInformation(context.internalProcessBuffer, sequence); // Reset the resend timer information->SendTime = context.timestamp; Packet *packet = GetPacket(context.internalProcessBuffer, sequence); header = packet->Header; // Update acked/ackmask to latest values header.AckedSequenceId = (ushort)reliable->ReceivedPackets.Sequence; header.AckMask = reliable->ReceivedPackets.AckMask; var offset = (ctx->DataPtrOffset + ((sequence % ctx->Capacity) * ctx->DataStride)) + UnsafeUtility.SizeOf <PacketHeader>(); NativeSlice <byte> slice = new NativeSlice <byte>(context.internalProcessBuffer, offset, information->Size); reliable->stats.PacketsResent++; needsResume = false; ctx->Resume = -1; // Check if another packet needs to be resent right after this one for (int i = sequence + 1; i < reliable->ReceivedPackets.Sequence + 1; i++) { var timeToResend = CurrentResendTime(context.internalSharedProcessBuffer); information = GetPacketInformation(context.internalProcessBuffer, i); if (information->SequenceId >= 0 && information->SendTime + timeToResend > context.timestamp) { needsResume = true; ctx->Resume = i; } } return(slice); }
public Status RMW(Key *key, Input *input, Context *userContext, long monotonicSerialNum) { var context = default(PendingContext); var internalStatus = InternalRMW(key, input, userContext, ref context); var status = default(Status); if (internalStatus == OperationStatus.SUCCESS || internalStatus == OperationStatus.NOTFOUND) { status = (Status)internalStatus; } else { status = HandleOperationStatus(threadCtx, context, internalStatus); } threadCtx.serialNum = monotonicSerialNum; return(status); }
/// <summary> /// Acknowledge the reception of packets which have been sent. The reliability /// shared context/state is updated when packets are received from the other end /// of the connection. The other side will update it's ackmask with which packets /// have been received (starting from last received sequence ID) each time it sends /// a packet back. This checks the resend timers on each non-acknowledged packet /// and notifies if it's time to resend yet. /// </summary> /// <param name="context">Pipeline context, contains the buffer slices this pipeline connection owns.</param> /// <returns></returns> public static unsafe bool ReleaseOrResumePackets(NetworkPipelineContext context) { SharedContext *reliable = (SharedContext *)context.internalSharedProcessBuffer.GetUnsafePtr(); Context * ctx = (Context *)context.internalProcessBuffer.GetUnsafePtr(); // Last sequence ID and ackmask we received from the remote peer, these are confirmed delivered packets var lastReceivedAckMask = reliable->SentPackets.AckMask; var lastOwnSequenceIdAckedByRemote = (ushort)reliable->SentPackets.Acked; // To deal with wrapping, chop off the upper half of the sequence ID and multiply by window size, it // will then never wrap but will map to the correct index in the packet storage, wrapping happens when // sending low sequence IDs (since it checks sequence IDs backwards in time). var sequence = (ushort)(reliable->WindowSize * ((1 - lastOwnSequenceIdAckedByRemote) >> 15)); // Check each slot in the window, starting from the sequence ID calculated above (this isn't the // latest sequence ID though as it was adjusted to avoid wrapping) for (int i = 0; i < reliable->WindowSize; i++) { var info = GetPacketInformation(context.internalProcessBuffer, sequence); if (info->SequenceId >= 0) { // Check the bit for this sequence ID against the ackmask. Bit 0 in the ackmask is the latest // ackedSeqId, bit 1 latest ackedSeqId - 1 (one older) and so on. If bit X is 1 then ackedSeqId-X is acknowledged var ackBits = 1 << (lastOwnSequenceIdAckedByRemote - info->SequenceId); // Release if this seqId has been flipped on in the ackmask (so it's acknowledged) // Ignore if sequence ID is out of window range of the last acknowledged id if (SequenceHelpers.AbsDistance((ushort)lastOwnSequenceIdAckedByRemote, (ushort)info->SequenceId) < reliable->WindowSize && (ackBits & lastReceivedAckMask) != 0) { Release(context.internalProcessBuffer, info->SequenceId); info->SendTime = -1; sequence = (ushort)(sequence - 1); continue; } var timeToResend = CurrentResendTime(context.internalSharedProcessBuffer); if (context.timestamp > info->SendTime + timeToResend) { ctx->Resume = info->SequenceId; } } sequence = (ushort)(sequence - 1); } return(ctx->Resume != NullEntry); }
public static unsafe int InitializeProcessContext(byte *buffer, int bufferLength, Parameters param) { int totalCapacity = ProcessCapacityNeeded(param); if (bufferLength != totalCapacity) { return((int)ErrorCodes.InsufficientMemory); } Context *ctx = (Context *)buffer; ctx->Capacity = param.WindowSize; ctx->IndexStride = AlignedSizeOf <PacketInformation>(); ctx->IndexPtrOffset = AlignedSizeOf <Context>(); ctx->DataStride = (Packet.Length + UnsafeUtility.SizeOf <PacketHeader>() + NetworkPipelineProcessor.AlignmentMinusOne) & (~NetworkPipelineProcessor.AlignmentMinusOne); ctx->DataPtrOffset = ctx->IndexPtrOffset + (ctx->IndexStride * ctx->Capacity); ctx->Resume = NullEntry; ctx->Delivered = NullEntry; Release(buffer, 0, param.WindowSize); return(0); }
public static unsafe int InitializeProcessContext(NativeSlice <byte> self, Parameters param) { int totalCapacity = ProcessCapacityNeeded(param); if (self.Length != totalCapacity) { return((int)ErrorCodes.InsufficientMemory); } Context *ctx = (Context *)self.GetUnsafePtr(); ctx->Capacity = param.WindowSize; ctx->IndexStride = (UnsafeUtility.SizeOf <PacketInformation>() + 3) & ~3; ctx->IndexPtrOffset = sizeof(Context); ctx->DataStride = (Packet.Length + 3) & ~3; ctx->DataPtrOffset = ctx->IndexPtrOffset + (ctx->IndexStride * ctx->Capacity); ctx->Resume = NullEntry; ctx->Delivered = NullEntry; Release(self, 0, param.WindowSize); return(0); }
protected override unsafe void OnStop() { // Cleanup: nuke our context if we have it. This is hacky and bad - we should really destroy // our buffers and sources. I have _no_ idea if OpenAL will leak memory. if (_context != null) { XPlane.Trace.WriteLine($"[OpenAL Sample] Deleting my context 0x{((ulong)_context):X8}"); _alc.DestroyContext(_context); _context = null; } if (_device != null) { _alc.CloseDevice(_device); _device = null; } _flightLoop.Dispose(); _flightLoop = null; Menu.PluginsMenu.Dispose(); }
public unsafe void FuzzPacket(Context *ctx, ref InboundSendBuffer inboundBuffer) { int fuzzFactor = ctx->FuzzFactor; int fuzzOffset = ctx->FuzzOffset; int rand = ctx->Random.NextInt(0, 100); if (rand > fuzzFactor) { return; } var length = inboundBuffer.bufferLength; for (int i = fuzzOffset; i < length; ++i) { for (int j = 0; j < 8; ++j) { if (fuzzFactor > ctx->Random.NextInt(0, 100)) { inboundBuffer.buffer[i] ^= (byte)(1 << j); } } } }
public Status RMW(Key *key, Input *input, Context *userContext, long monotonicSerialNum) { /* * if (((RecordInfo*)hlog.GetPhysicalAddress(0))->Invalid != true) * { * Debugger.Break(); * }*/ var context = default(PendingContext); var internalStatus = InternalRMW(key, input, userContext, ref context); var status = default(Status); if (internalStatus == OperationStatus.SUCCESS || internalStatus == OperationStatus.NOTFOUND) { status = (Status)internalStatus; } else { status = HandleOperationStatus(threadCtx, context, internalStatus); } threadCtx.serialNum = monotonicSerialNum; return(status); }
public static unsafe void SetPacket(NativeSlice <byte> self, int sequence, void *data, int length) { byte * ptr = (byte *)self.GetUnsafePtr(); Context *ctx = (Context *)ptr; if (length > ctx->DataStride) #if ENABLE_UNITY_COLLECTIONS_CHECKS { throw new OverflowException(); } #else { return; } #endif var index = sequence % ctx->Capacity; PacketInformation *info = GetPacketInformation(self, sequence); info->SequenceId = sequence; info->Size = length; info->SendTime = -1; // Not used for packets queued for resume receive var offset = ctx->DataPtrOffset + (index * ctx->DataStride); void *dataPtr = (ptr + offset); UnsafeUtility.MemCpy(dataPtr, data, length); }