protected override void ProcessPackage(PendingPackage package) { // Locked by TcpConnection. if (!_connected && package.Type != PackageType.Handshake) { SendError(ProtocolError.InvalidPackageType); return; } switch (package.Type) { case PackageType.Handshake: ProcessHandshake(package); break; default: base.ProcessPackage(package); break; } }
private void ProcessHandshake(PendingPackage package) { // Receive the handshake response. var response = (Messages.HandshakeResponse)ReadMessage( TypeModel, typeof(Messages.HandshakeResponse), (int)package.Length ); // Validate the protocol number. int protocolNumber = (int)response.Protocol; if ( protocolNumber < _host.Configuration.MinimumProtocolNumber || protocolNumber > _host.Configuration.MaximumProtocolNumber ) { SendError(ProtocolError.InvalidProtocol); } else { // Else, we've got a valid connection and can proceed with // creating the service client. // Create the callback channel so we can provide it with the // operation context. if (_host.Service.CallbackContractType != null) { // Else, if we have a callback contract, we create the // channel. CallbackChannel = (ProtoCallbackChannel)Activator.CreateInstance( _host.Service.CallbackContractType ); CallbackChannel.Connection = this; } using (OperationContext.SetScope(new OperationContext(this, CallbackChannel))) { Client = _host.RaiseClientConnected(this, protocolNumber); } if (Client == null) { // When creating the client failed, we shut down because there's // nothing more to do. Dispose(); } } }
private void ProcessHandshake(PendingPackage package) { // Receive the handshake request. var request = (Messages.HandshakeRequest)ReadMessage( TypeModel, typeof(Messages.HandshakeRequest), (int)package.Length ); // Ask the client which protocol we're going to connect with. int protocol = _client.ChooseProtocol((int)request.ProtocolMin, (int)request.ProtocolMax); // Push our response long packageStart = BeginSendPackage(); WriteMessage(TypeModel, new Messages.HandshakeResponse { Protocol = (uint)protocol }); EndSendPackage(PackageType.Handshake, packageStart); _connected = true; // Once we're connected, we can go into async mode. IsAsync = true; Read(); }
protected override void ProcessPackage(PendingPackage package) { // Locked by TcpConnection. switch (_state) { case State.Authenticating: case State.ReceivingProlog: SendError(ProtocolError.InvalidPackageType); return; case State.ReceivingHandshake: if (package.Type != PackageType.Handshake) { SendError(ProtocolError.InvalidPackageType); return; } break; case State.Connected: break; default: throw new NotSupportedException("Invalid state"); } switch (package.Type) { case PackageType.Handshake: ProcessHandshake(package); break; default: base.ProcessPackage(package); break; } }
private void ProcessStreamPackage(PendingPackage package) { if (package.Length < 4) { SendError(ProtocolError.InvalidPackageLength); return; } // Parse the header. byte[] buffer = new byte[4]; buffer[0] = 0; Read(buffer, 0, buffer.Length); uint header = BitConverterEx.ToNetworkUInt32(buffer, 0); // Get the details from the header. uint streamPackageTypeNumber = header & 0x7; int associationId = (int)(header >> 3); // Process the stream package. switch ((StreamPackageType)streamPackageTypeNumber) { case StreamPackageType.StartStream: ProcessStartStreamPackage(associationId, (int)package.Length - 4); break; case StreamPackageType.AcceptStream: ProcessAcceptStreamPackage(associationId); break; case StreamPackageType.RejectStream: ProcessRejectStreamPackage(associationId); break; case StreamPackageType.StreamData: ProcessStreamDataPackage(associationId, (int)package.Length - 4); break; case StreamPackageType.EndStream: case StreamPackageType.StreamFailed: ProcessEndStreamPackage(associationId, (StreamPackageType)streamPackageTypeNumber != StreamPackageType.StreamFailed); break; default: SendError(ProtocolError.InvalidStreamPackageType); break; } }
private void ProcessMessagePackage(PendingPackage package) { // We need at least three bytes for a valid message. if (package.Length < 4) { SendError(ProtocolError.InvalidPackageLength); return; } uint length = package.Length - 4; byte[] buffer = new byte[4]; buffer[0] = 0; Read(buffer, 0, buffer.Length); uint header = BitConverterEx.ToNetworkUInt32(buffer, 0); uint messageKindNumber = header & 0x3; uint messageType = header >> 2; // Validate the message kind. if (messageKindNumber == 3) { SendError(ProtocolError.InvalidMessageKind); return; } var messageKind = (MessageKind)messageKindNumber; uint associationId = 0; if (messageKind != MessageKind.OneWay) { // Verify that there is an association ID in the request. if (package.Length < 5) { SendError(ProtocolError.InvalidPackageLength); return; } length -= 2; Read(buffer, 0, 2); associationId = BitConverterEx.ToNetworkUInt16(buffer, 0); } ProcessMessage(messageKind, messageType, length, associationId); }
private void ProcessErrorPackage(PendingPackage package) { var error = (Messages.Error)ReadMessage( TypeModel, typeof(Messages.Error), (int)package.Length ); var exception = new ProtoChannelException((ProtocolError)error.ErrorNumber); _messageManager.SetError(exception); _receiveStreamManager.SetError(exception); RaiseUnhandledException(exception); Dispose(); }
protected virtual void ProcessPackage(PendingPackage package) { switch (package.Type) { case PackageType.Error: ProcessErrorPackage(package); break; case PackageType.NoOp: case PackageType.Pong: // No-op's and pongs are just dropped. break; case PackageType.Message: ProcessMessagePackage(package); break; case PackageType.Stream: ProcessStreamPackage(package); break; case PackageType.Ping: EndSendPackage(PackageType.Pong, BeginSendPackage()); break; default: throw new NotSupportedException("Invalid package type"); } }