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; }
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 ); }
// Initializes the network transport and builds the _channel array. // Returns null on failure, and sets error string with description. protected ConnectionConfig InitializeNetwork( out string error ) { _maxEventCount = _commonSettings.maxEventCount > 0 ? _commonSettings.maxEventCount : UInt32.MaxValue; GlobalConfig gConfig = new GlobalConfig(); // default settings gConfig.MaxPacketSize = _commonSettings.messageBufferSize; NetworkTransport.Init(); ConnectionConfig config = new ConnectionConfig(); config.SendDelay = 0; int channelCount = AlpacaConstant.InternalChannelCount + _commonSettings.customChannel.Length; _channel = new Channel[channelCount]; // add internal channels for( int i = 0; i < AlpacaConstant.InternalChannelCount; ++i ) { string name = AlpacaConstant.INTERNAL_CHANNEL_NAME[i]; QosType qos = AlpacaConstant.INTERNAL_CHANNEL_TYPE[i]; int index = config.AddChannel( qos ); if( index != i ) { error = Log.PrefixMessage( string.Format( "Unexpected channel index {0} while attempting to create {1}", index, name ) ); return null; } _channel[i] = new Channel( ChannelIndex.CreateInternal( (InternalChannel)i ), name, qos ); } // add custom channels for( int i = 0; i < _commonSettings.customChannel.Length; ++i ) { CustomChannelSettings c = _commonSettings.customChannel[i]; int index = config.AddChannel( c.type ); int offsetIndex = i + AlpacaConstant.InternalChannelCount; if( index != offsetIndex ) { error = Log.PrefixMessage( string.Format( "Unexpected channel index {0} while attempting to create {1}", index, c.name ) ); return null; } _channel[offsetIndex] = new Channel( ChannelIndex.CreateCustom( (UInt32)i ), c.name, c.type ); } error = ""; return config; }
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(); }
// polls the underlying UNET transport for packets. Note that we return the connectionId without // converting it into a NodeIndex because the interpretation depends on whether or not the node // executing this function is a ServerNode or a ClientNode protected ReceiveEvent PollReceive( DataStream stream, out int connectionId, out ChannelIndex channel ) { int hostId; // this will always be the same port, we don't care about this int channelId; // corresponds to ChannelIndex int receivedSize; byte errorByte; NetworkEventType unetEvent = NetworkTransport.Receive( out hostId, out connectionId, out channelId, stream.GetBuffer(), stream.GetByteCapacity(), out receivedSize, out errorByte ); stream.SetByteLength( receivedSize ); NetworkError error = (NetworkError)errorByte; if( error != NetworkError.Ok && error != NetworkError.Timeout ) { // polling failed Log.Error( StringFromError( errorByte ) ); channel = new ChannelIndex(); return ReceiveEvent.Error; } channel = _channel[channelId].GetIndex(); // translate UNET NetworkEventType to EventType if( error == NetworkError.Timeout ) { return ReceiveEvent.Disconnect; } else { switch( unetEvent ) { case NetworkEventType.DataEvent: return ReceiveEvent.Message; case NetworkEventType.ConnectEvent: return ReceiveEvent.Connect; case NetworkEventType.DisconnectEvent: return ReceiveEvent.Disconnect; case NetworkEventType.Nothing: return ReceiveEvent.NoMoreEvents; case NetworkEventType.BroadcastEvent: default: Log.Error( "Received Broadcast or unknown message type from UNET transport layer" ); return ReceiveEvent.Error; } } }
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 static MessageSecurity GetSecurity( ChannelIndex index ) { return INTERNAL_CHANNEL_SECURITY[(int)index.GetIndex()]; }
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 ); }
// sends a custom message to the server public bool SendCustomServer( uint customChannel, BitWriter writer, bool sendImmediately, out string error ) { return Send( InternalMessage.CustomServer, ChannelIndex.CreateCustom( customChannel ), writer, sendImmediately, out error ); }
// sends a custom message to the server via the default channel public bool SendCustomServer( BitWriter writer, bool sendImmediately, out string error ) { return Send( InternalMessage.CustomServer, ChannelIndex.CreateInternal( InternalChannel.ClientReliable ), writer, sendImmediately, out error ); }
public Channel( ChannelIndex index, string name, QosType type ) { _index = index; _name = name; _quality = type; }
// sends a custom message to the server public bool SendCustomClient( NodeIndex client, uint customChannel, BitWriter writer, bool sendImmediately, out string error ) { return Send( client, InternalMessage.CustomClient, ChannelIndex.CreateCustom( customChannel ), writer, sendImmediately, out error ); }