public bool Dispatch(StreamBuffer buffer) { var responses = new List<Data>(); lock (_listResponseAction) { foreach (var data in _listResponseAction) responses.Add(data); } foreach (var data in responses) { if (data.Predicate(buffer) == true) { lock (_listResponseAction) _listResponseAction.Remove(data); var result = new IOEventResult(_session, IOEventType.Read, buffer.Buffer, 0, buffer.WrittenBytes, AegisResult.Ok); data.Dispatcher(result); return true; } } return false; }
public void SendPacket(StreamBuffer buffer, Action<StreamBuffer> onSent = null) { try { lock (_session) { if (_session.Socket == null) return; // ReadIndex가 OnSocket_Send에서 사용되므로 ReadIndex를 초기화해야 한다. buffer.ResetReadIndex(); SocketAsyncEventArgs saea = new SocketAsyncEventArgs(); saea.Completed += SendComplete; saea.SetBuffer(buffer.Buffer, 0, buffer.WrittenBytes); if (onSent != null) saea.UserToken = new NetworkSendToken(buffer, onSent); if (_session.Socket.SendAsync(saea) == false) ReceiveComplete(null, saea); } } catch (SocketException) { } catch (Exception e) { Logger.Err(LogMask.Aegis, e.ToString()); } }
public void SendPacket(StreamBuffer buffer, Action<StreamBuffer> onSent = null) { try { lock (_session) { if (_session.Socket != null) { // ReadIndex가 OnSocket_Send에서 사용되므로 ReadIndex를 초기화해야 한다. buffer.ResetReadIndex(); if (onSent == null) _session.Socket.BeginSend(buffer.Buffer, 0, buffer.WrittenBytes, SocketFlags.None, Socket_Send, null); else _session.Socket.BeginSend(buffer.Buffer, 0, buffer.WrittenBytes, SocketFlags.None, Socket_Send, new NetworkSendToken(buffer, onSent)); } } } catch (SocketException) { } catch (Exception e) { Logger.Err(LogMask.Aegis, e.ToString()); } }
public StreamBuffer(StreamBuffer source) { ReadBytes = 0; WrittenBytes = 0; Capacity(source.WrittenBytes); Write(source.Buffer, 0, source.WrittenBytes); }
public StreamBuffer(StreamBuffer source, int index, int size) { ReadBytes = 0; WrittenBytes = 0; Capacity(size); Write(source.Buffer, index, size); }
public void Send(StreamBuffer buffer) { lock (this) { var socket = _socket; socket?.BeginSendTo(buffer.Buffer, 0, buffer.WrittenBytes, SocketFlags.None, _endPoint, Socket_Send, null); } }
public SessionMethodAsyncEvent(Session session) { _session = session; _receivedBuffer = new StreamBuffer(2048); _dispatchBuffer = new StreamBuffer(2048); _saeaRecv = new SocketAsyncEventArgs(); _saeaRecv.Completed += ReceiveComplete; _responseSelector = new ResponseSelector(_session); }
public virtual StreamBuffer Clone() { StreamBuffer newStream = new StreamBuffer(this); newStream.ReadBytes = ReadBytes; newStream.WrittenBytes = WrittenBytes; return newStream; }
public static ulong GetUInt64(StreamBuffer source, int readIndex) { if (readIndex + sizeof(ulong) > source.WrittenBytes) throw new AegisException(AegisResult.BufferUnderflow, "No more readable buffer."); return BitConverter.ToUInt64(source.Buffer, readIndex); }
public static string GetStringAsUtf16(StreamBuffer source, int readIndex) { int i, stringBytes = 0; for (i = readIndex; i < source.WrittenBytes; i += 2) { if (source.Buffer[i + 0] == 0 && source.Buffer[i + 1] == 0) break; stringBytes += 2; if (readIndex + stringBytes + 2 > source.WrittenBytes) throw new AegisException(AegisResult.BufferUnderflow, "No more readable buffer."); } // String으로 변환할 때 Null terminate를 포함시켜서는 안된다. return Encoding.Unicode.GetString(source.Buffer, readIndex, stringBytes); }
/// <summary> /// 패킷을 전송합니다. /// </summary> /// <param name="buffer">전송할 데이터가 담긴 StreamBuffer</param> /// <param name="onSent">패킷 전송이 완료된 후 호출할 Action</param> public virtual void SendPacket(StreamBuffer buffer, Action<StreamBuffer> onSent = null) { _method.SendPacket(buffer, onSent); }
public void Write(StreamBuffer source, int sourceIndex) { if (sourceIndex >= source.WrittenBytes) throw new AegisException(AegisResult.BufferUnderflow, "The argument index(={0}) is larger then source size(={1}).", sourceIndex, source.WrittenBytes); int copyBytes = source.WrittenBytes - sourceIndex; if (WrittenBytes + copyBytes > BufferSize) Resize(BufferSize + copyBytes); Array.Copy(source.Buffer, sourceIndex, Buffer, WrittenBytes, copyBytes); WrittenBytes += copyBytes; OnWritten(); }
/// <summary> /// 패킷 버퍼를 초기화하고 source 데이터를 저장합니다. Packet Header의 Size는 source 버퍼의 헤더값이 사용됩니다. /// </summary> /// <param name="source">저장할 데이터</param> public virtual void Clear(StreamBuffer source) { if (source.BufferSize < HeaderSize) throw new AegisException(AegisResult.InvalidArgument, "The source size must be at lest {0} bytes.", HeaderSize); base.Clear(); Write(source.Buffer, 0, source.WrittenBytes); Size = GetUInt16(0); }
/// <summary> /// 수신된 데이터가 유효한 패킷인지 여부를 확인합니다. /// 유효한 패킷으로 판단되면 packetSize에 이 패킷의 정확한 크기를 입력하고 true를 반환해야 합니다. /// </summary> /// <param name="buffer">수신된 데이터가 담긴 버퍼</param> /// <param name="packetSize">유효한 패킷의 크기</param> /// <returns>true를 반환하면 EventReceive 통해 수신된 데이터가 전달됩니다.</returns> public static bool IsValidPacket(StreamBuffer buffer, out int packetSize) { if (buffer.WrittenBytes < HeaderSize) { packetSize = 0; return false; } // 최초 2바이트를 수신할 패킷의 크기로 처리 packetSize = buffer.GetUInt16(0); return (packetSize > 0 && buffer.WrittenBytes >= packetSize); }
/// <summary> /// 지정된 버퍼에서 PacketId 값을 가져옵니다. /// buffer는 패킷 헤더가 온전히 포함된 데이터로 지정되어야 합니다. /// </summary> /// <param name="buffer">패킷 데이터가 담긴 버퍼</param> /// <returns>패킷의 PacketId를 반환합니다.</returns> public static ushort GetPacketId(StreamBuffer buffer) { if (buffer.Buffer.Length < 4) return 0; return BitConverter.ToUInt16(buffer.Buffer, 2); }
/// <summary> /// StreamBuffer의 데이터를 복사하여 패킷을 생성합니다. /// </summary> /// <param name="source">복사할 데이터가 담긴 StreamBuffer 객체</param> public SecurePacket(StreamBuffer source) { Write(source.Buffer, 0, source.WrittenBytes); }
internal void OnReceived(StreamBuffer buffer) { if (_methodSelector?.Dispatch(buffer) == false) EventReceive?.Invoke(new IOEventResult(this, IOEventType.Read, buffer.Buffer, 0, buffer.WrittenBytes, AegisResult.Ok)); }
/// <summary> /// 패킷을 전송하고, 특정 패킷이 수신될 경우 dispatcher에 지정된 핸들러를 실행합니다. /// 이 기능은 AwaitableMethod보다는 빠르지만, 동시에 많이 호출될 경우 성능이 저하될 수 있습니다. /// </summary> /// <param name="buffer">전송할 데이터가 담긴 StreamBuffer</param> /// <param name="predicate">dispatcher에 지정된 핸들러를 호출할 것인지 여부를 판단하는 함수를 지정합니다.</param> /// <param name="dispatcher">실행될 함수를 지정합니다.</param> /// <param name="onSent">패킷 전송이 완료된 후 호출할 Action</param> public virtual void SendPacket(StreamBuffer buffer, PacketPredicate predicate, IOEventHandler dispatcher, Action<StreamBuffer> onSent = null) { _method.SendPacket(buffer, predicate, dispatcher, onSent); }
public void Write(StreamBuffer source) { int srcSize = source.WrittenBytes; if (WrittenBytes + srcSize > BufferSize) Resize(BufferSize + srcSize); Array.Copy(source.Buffer, 0, Buffer, WrittenBytes, srcSize); WrittenBytes += srcSize; OnWritten(); }
public void SendPacket(StreamBuffer buffer, PacketPredicate predicate, IOEventHandler dispatcher, Action<StreamBuffer> onSent = null) { if (predicate == null || dispatcher == null) throw new AegisException(AegisResult.InvalidArgument, "The argument predicate and dispatcher cannot be null."); try { lock (_session) { if (_session.Socket == null) return; // ReadIndex가 OnSocket_Send에서 사용되므로 ReadIndex를 초기화해야 한다. buffer.ResetReadIndex(); SocketAsyncEventArgs saea = new SocketAsyncEventArgs(); saea.Completed += SendComplete; saea.SetBuffer(buffer.Buffer, 0, buffer.WrittenBytes); if (onSent != null) saea.UserToken = new NetworkSendToken(buffer, onSent); _responseSelector.Add(predicate, dispatcher); if (_session.Socket.SendAsync(saea) == false) ReceiveComplete(null, saea); } } catch (SocketException) { } catch (Exception e) { Logger.Err(LogMask.Aegis, e.ToString()); } }
public void Write(StreamBuffer source, int sourceIndex, int length) { if (sourceIndex + length > source.WrittenBytes) throw new AegisException(AegisResult.BufferUnderflow, "The source buffer is small then requested."); int copyBytes = length; if (WrittenBytes + copyBytes > BufferSize) Resize(BufferSize + copyBytes); Array.Copy(source.Buffer, sourceIndex, Buffer, WrittenBytes, copyBytes); WrittenBytes += copyBytes; OnWritten(); }
public void SendPacket(StreamBuffer buffer, PacketPredicate predicate, IOEventHandler dispatcher, Action<StreamBuffer> onSent = null) { if (predicate == null || dispatcher == null) throw new AegisException(AegisResult.InvalidArgument, "The argument predicate and dispatcher cannot be null."); try { lock (_session) { _responseSelector.Add(predicate, dispatcher); if (_session.Socket != null) { // ReadIndex가 OnSocket_Send에서 사용되므로 ReadIndex를 초기화해야 한다. buffer.ResetReadIndex(); if (onSent == null) _session.Socket.BeginSend(buffer.Buffer, 0, buffer.WrittenBytes, SocketFlags.None, Socket_Send, null); else _session.Socket.BeginSend(buffer.Buffer, 0, buffer.WrittenBytes, SocketFlags.None, Socket_Send, new NetworkSendToken(buffer, onSent)); } } } catch (SocketException) { } catch (Exception e) { Logger.Err(LogMask.Aegis, e.ToString()); } }
private void ReceiveComplete(object sender, SocketAsyncEventArgs saea) { try { lock (_session) { // transBytes가 0이면 원격지 혹은 네트워크에 의해 연결이 끊긴 상태 int transBytes = saea.BytesTransferred; if (transBytes == 0) { _session.Close(AegisResult.ClosedByRemote); return; } _receivedBuffer.Write(transBytes); while (_receivedBuffer.ReadableSize > 0) { // 패킷 하나가 정상적으로 수신되었는지 확인 int packetSize; StreamBuffer tmpBuffer = new StreamBuffer(_receivedBuffer, _receivedBuffer.ReadBytes, _receivedBuffer.ReadableSize); if (_session.PacketValidator == null || _session.PacketValidator(tmpBuffer, out packetSize) == false) break; try { // 수신 이벤트 처리 중 종료 이벤트가 발생한 경우 if (_session.Socket == null) return; // 수신버퍼에서 제거 _receivedBuffer.Read(packetSize); // 수신처리(Dispatch) StreamBuffer dispatchBuffer = new StreamBuffer(tmpBuffer, 0, packetSize); SpinWorker.Dispatch(() => { if (_responseSelector.Dispatch(dispatchBuffer) == false) _session.OnReceived(dispatchBuffer); }); } catch (Exception e) { Logger.Err(LogMask.Aegis, e.ToString()); } } // 처리된 패킷을 버퍼에서 제거 _receivedBuffer.PopReadBuffer(); // ReceiveBuffer의 안정적인 처리를 위해 작업이 끝난 후에 다시 수신대기 WaitForReceive(); } } catch (SocketException) { _session.Close(AegisResult.ClosedByRemote); } catch (Exception e) { Logger.Err(LogMask.Aegis, e.ToString()); } }
public static bool GetBoolean(StreamBuffer source, int readIndex) { if (readIndex + sizeof(byte) > source.WrittenBytes) throw new AegisException(AegisResult.BufferUnderflow, "No more readable buffer."); return (source.Buffer[readIndex] == 1); }
public static sbyte GetSByte(StreamBuffer source, int readIndex) { if (readIndex + sizeof(sbyte) > source.WrittenBytes) throw new AegisException(AegisResult.BufferUnderflow, "No more readable buffer."); return (sbyte)source.Buffer[readIndex]; }
public SessionMethodAsyncResult(Session session) { _session = session; _receivedBuffer = new StreamBuffer(2048); _responseSelector = new ResponseSelector(_session); }