protected bool Send( int connectionId, byte[] key, InternalMessage message, ChannelIndex channel, BitWriter writer, bool sendImmediately, out string error ) { MessageSecurity security = AlpacaConstant.GetSecurity( channel ); if( !WrapMessage( message, security, writer, key, out error ) ) { return false; } //_profiler.StartEvent(TickType.Send, (uint)stream.Length, channelName, AlpacaConstant.INTERNAL_MESSAGE_NAME[messageType]); DataStream s = writer.GetStream(); byte errorAsByte; if( sendImmediately ) { NetworkTransport.Send ( 0, connectionId, channel.GetIndex(), s.GetBuffer(), s.GetByteLength(), out errorAsByte); } else { NetworkTransport.QueueMessageForSending( 0, connectionId, channel.GetIndex(), s.GetBuffer(), s.GetByteLength(), out errorAsByte); } //_profiler.EndEvent(); if( (NetworkError)errorAsByte != NetworkError.Ok ) { error = $"Send {AlpacaConstant.GetName(message)} to node {connectionId} failed with error{StringFromError(errorAsByte)}"; return false; } return true; }
protected bool WrapMessage( InternalMessage message, MessageSecurity security, BitWriter writer, byte[] key, out string error ) { if( !_commonSettings.enableEncryption && security != MessageSecurity.None ) { error = "Attempted to send encrypted and/or authenticated message but encryption was not enabled"; return false; } bool authenticated = ((security & MessageSecurity.Authenticated) != 0); bool encrypted = ((security & MessageSecurity.Encrypted ) != 0); if( authenticated || encrypted ) { Debug.Assert( false ); // TODO: handle encryption and authentication here error = "WrapMessage: tried to apply encryption, but it was not enabled."; return false; } DataStream writerStream = writer.GetStream(); int lastBytePos = writerStream.GetBytePosition(); // reset write head to write authentication and encryption bits writer.Normal(authenticated); writer.Normal(encrypted); writerStream.SetBytePosition( lastBytePos ); byte messageByte = (byte)(((int)message) << 2); writer.Normal<byte>( messageByte ); error = null; return true; }
bool Send( NodeIndex client, InternalMessage message, ChannelIndex channel, BitWriter writer, bool sendImmediately, out string error ) { int clientIndex = client.GetClientIndex(); byte[] key = _connection.GetAt(clientIndex-1).GetSharedSecretKey(); // for the server, connectionId == clientIndex return base.Send( clientIndex, key, message, channel, writer, sendImmediately, out error ); }
// Extracts body of message, which could include decrypting and/or authentication. protected InternalMessage UnwrapMessage( BitReader reader, NodeIndex client ) { DataStream readerStream = reader.GetStream(); int byteLength = readerStream.GetByteLength(); Log.Info( $"Unwrapping incoming message from {client} : {byteLength} bytes" ); if( byteLength < 1 ) { Log.Error( $"The incoming message from {client} was too small" ); return InternalMessage.INVALID; } // The last byte of the wrapped message is: // 2 bits indicating encryption and authentication, followed by // 6 bits containing the packed message type byte. // TODO: Security: This means the message type is outside encryption, // which enables an attacker to get some info. Does this matter enough? int messageBodyStart = readerStream.GetBytePosition(); readerStream.SetBytePosition( byteLength - 1 ); bool isAuthenticated = reader.Normal<bool>(); bool isEncrypted = reader.Normal<bool>(); // reset the read head so that we can read the message byte readerStream.SetBytePosition( byteLength - 1 ); byte messageByte = reader.Normal<byte>(); InternalMessage message = (InternalMessage)((int)messageByte >> 2); readerStream.SetBytePosition( messageBodyStart ); if( isEncrypted || isAuthenticated ) { if( !_commonSettings.enableEncryption ) { Log.Error( "Got a encrypted and/or authenticated message but encryption was not enabled" ); return InternalMessage.INVALID; } if( isAuthenticated ) { if( !CheckAuthentication( reader, client ) ) { return InternalMessage.INVALID; } } if( isEncrypted ) { if( !PerformDecryption( reader, client ) ) { return InternalMessage.INVALID; } } } return message; }
void HandleMessage( BitReader reader, ChannelIndex channel ) { InternalMessage messageType = UnwrapMessage( reader, NodeIndex.SERVER_NODE_INDEX ); if( messageType == InternalMessage.INVALID ) { return; } //_profiler.StartEvent(TickType.Receive, size, channelId, messageType); Log.Info( $"Handling message {AlpacaConstant.GetName(messageType)} from server" ); if( (_status == Status.WaitingForChallenge) && (messageType != InternalMessage.ConnectionChallenge) ) { Log.Error( $"We are waiting for challenge, but server sent message {AlpacaConstant.GetName(messageType)} instead." ); return; } if( (_status == Status.WaitingForConnectionApproval) && (messageType != InternalMessage.ConnectionApproved ) ) { Log.Error( $"We are waiting for connection approval, but server sent message {AlpacaConstant.GetName(messageType)} instead." ); return; } switch( messageType ) { case InternalMessage.ConnectionChallenge: // TODO: cozeroff crypto implementation Log.Error( "Crypto not implemented yet!" ); break; case InternalMessage.ConnectionApproved: OnMessageConnectionApproved( reader ); break; // TODO: cozeroff handle sibling connect/disconnect case InternalMessage.EntityCreate: OnEntityCreate( reader ); break; case InternalMessage.CustomClient: OnMessageCustomClient( reader ); break; default: Log.Error( $"Read unrecognized messageType{AlpacaConstant.GetName(messageType)}" ); break; } //_profiler.EndEvent(); }
void HandleMessage( BitReader reader, NodeIndex client, ChannelIndex channel ) { InternalMessage messageType = UnwrapMessage( reader, client ); if( messageType == InternalMessage.INVALID ) { return; } //_profiler.StartEvent(TickType.Receive, size, channelId, messageType); Log.Info( $"Handling message {AlpacaConstant.GetName(messageType)} from client {client.GetClientIndex()}" ); ClientConnection connection = _connection.GetAt( client.GetClientIndex() - 1 ); ClientConnection.Status state = connection.GetState(); if( (state == ClientConnection.Status.PendingConnectionChallengeResponse) && (messageType != InternalMessage.ConnectionResponse ) ) { Log.Error( $"Client {client.GetClientIndex()} is pending connection response, but client sent message {AlpacaConstant.GetName(messageType)} instead." ); return; } if( (state == ClientConnection.Status.PendingConnectionRequest) && (messageType != InternalMessage.ConnectionRequest) ) { Log.Error( $"Client {client.GetClientIndex()} is pending connection request, but client sent message {AlpacaConstant.GetName(messageType)} instead." ); return; } switch( messageType ) { case InternalMessage.ConnectionRequest: OnMessageConnectionRequest( client, reader ); break; case InternalMessage.ConnectionResponse: // TODO: cozeroff crypto implementation Log.Error( "Crypto not implemented yet!" ); break; case InternalMessage.CustomServer: OnMessageCustomServer( client, reader ); break; default: Log.Error( $"Read unrecognized messageType{AlpacaConstant.GetName(messageType)}" ); break; } //_profiler.EndEvent(); }
public void Read(BitReader reader) { _byteCount = reader.Packed <UInt32>(); _channel.Read(reader); _message = (InternalMessage)reader.Packed <UInt32>(); }
public TickEvent(UInt32 byteCount, ChannelIndex channel, InternalMessage message) { _byteCount = byteCount; _channel = channel; _message = message; }
public void RecordEvent(UInt32 byteCount, ChannelIndex channel, InternalMessage message) { _events.Add(new TickEvent(byteCount, channel, message)); _totalByteCount += byteCount; }
bool Send( InternalMessage message, ChannelIndex channel, BitWriter writer, bool sendImmediately, out string error ) { // for the client, connectionId == 1 always (server) return base.Send( 1, _serverKey, message, channel, writer, sendImmediately, out error ); }
// PRIVATE // sends an internal message to the server (Alpaca layer) bool SendInternal( InternalMessage message, InternalChannel channel, BitWriter writer, bool sendImmediately, out string error ) { return Send( message, ChannelIndex.CreateInternal(channel), writer, sendImmediately, out error ); }