/// <summary> /// Will attempt to unregister a client from a server. /// </summary> /// <param name="serviceProxy">The server's service proxy. (Provides callback methods to the server.)</param> /// <param name="client">The client to unregister.</param> public void Unregister(IService serviceProxy, IClient client) { if ((serviceProxy != null) && (client != null)) { var boolConverter = new dodSON.Core.Converters.TypeSerializer <bool>(); var transportDataConverter = new dodSON.Core.Converters.TypeSerializer <TransportData>(); var clientConfigurationConverter = new dodSON.Core.Converters.TypeSerializer <IClientConfiguration>(); // ######## HELLO (create tunnel) // create public/private keys System.Security.Cryptography.RSACryptoServiceProvider serverCryptoProvider = null; var clientCryptoProvider = AsymmetricCryptoProvider; var clientPublicKey = clientCryptoProvider.ToXmlString(false); var clientPrivateKey = clientCryptoProvider.ToXmlString(true); var request = transportDataConverter.ToByteArray( new TransportData() { Alpha = ContextFor("Hello"), Beta = client.Id, Gamma = System.Text.Encoding.Unicode.GetBytes(clientPublicKey), Delta = null, Epsilon = null }); var response = transportDataConverter.FromByteArray(serviceProxy.RegistrationChannel(RegistrationTypeEnum.Unregister, request)); // ######## test for HELLO if ((response.Alpha == ContextFor("Hello")) && (response.Beta == client.Id)) { // ######## get server public key var serverPublicKey = System.Text.Encoding.Unicode.GetString(response.Gamma); serverCryptoProvider = AsymmetricCryptoProvider; serverCryptoProvider.FromXmlString(serverPublicKey); // ######## meet challenge request = transportDataConverter.ToByteArray( new TransportData() { Alpha = ContextFor("Challenge"), Beta = client.Id, Gamma = null, Delta = null, Epsilon = PrepareForTransport(ChallengeEvidence, serverCryptoProvider, TransportPartsLengthInBytes) }); if (boolConverter.FromByteArray(serviceProxy.RegistrationChannel(RegistrationTypeEnum.Unregister, request))) { request = transportDataConverter.ToByteArray( new TransportData() { Alpha = ContextFor("Unregister"), Beta = client.Id, Gamma = null, Delta = PrepareForTransport(clientConfigurationConverter.ToByteArray(client.ClientConfiguration), serverCryptoProvider, TransportPartsLengthInBytes), Epsilon = PrepareForTransport(ChallengeEvidence, serverCryptoProvider, TransportPartsLengthInBytes) }); serviceProxy.RegistrationChannel(RegistrationTypeEnum.Unregister, request); } } } }
/// <summary> /// Prepares and converts a <see cref="IMessage"/> into a collection of <see cref="TransportEnvelope"/>s. /// </summary> /// <param name="message">The <see cref="IMessage"/> to prepare to transmission.</param> /// <returns>A collection of <see cref="TransportEnvelope"/>s created from the <paramref name="message"/>.</returns> public IEnumerable <TransportEnvelope> PrepareMessageForTransport(IMessage message) { if (message == null) { throw new ArgumentNullException("message"); } // update statistics lock (_SyncRootTransportStatistics) { _TransportStatistics.OutgoingMessages++; } // convert message to byte[] var worker = (new dodSON.Core.Converters.TypeSerializer <IMessage>()).ToByteArray(message); // compress byte[] worker = TransportConfiguration.Compressor.Compress(worker); // encrypt byte[] worker = TransportConfiguration.Encryptor.Encrypt(worker); // chunk byte[] IEnumerable <byte[]> chunks = null; if (TransportConfiguration.UseChunking) { chunks = dodSON.Core.Common.ByteArrayHelper.SplitByteArray(worker, TransportConfiguration.ChunkSize); } else { chunks = new List <byte[]>(); ((List <byte[]>)chunks).Add(worker); } // create envelopes var chunkIndex = 0; var converter = new dodSON.Core.Converters.TypeSerializer <ITransportEnvelopeHeader>(); foreach (var item in chunks) { var header = new TransportEnvelopeHeader(message.Id, message.ServerIds, message.ClientId, message.TargetId, message.TypeInfo, ++chunkIndex, chunks.Count()); var encryptedHeader = TransportConfiguration.Encryptor.Encrypt(TransportConfiguration.Compressor.Compress(converter.ToByteArray(header))); // update statistics lock (_SyncRootTransportStatistics) { _TransportStatistics.OutgoingEnvelopes++; _TransportStatistics.OutgoingBytes += encryptedHeader.Length + item.Length; } // yield return(new TransportEnvelope(encryptedHeader, item)); } }
// **** // **** SERVER-ONLY CALLED METHODS // **** /// <summary> /// Attempts to register the client with the server. /// </summary> /// <param name="data">Information related to registration.</param> /// <param name="newRegisterableClientConfiguration">A <see cref="IClientConfiguration"/> for the newly registered client.</param> /// <returns>A response relative to the registration process.</returns> public byte[] TryAddDataFromRegistrationChannel(byte[] data, out IClientConfiguration newRegisterableClientConfiguration) { if ((data == null) || (data.Length == 0)) { throw new ArgumentNullException("data"); } newRegisterableClientConfiguration = null; var transportConfigurationConvertor = new dodSON.Core.Converters.TypeSerializer <ITransportConfiguration>(); var transportDataConverter = new dodSON.Core.Converters.TypeSerializer <TransportData>(); var listConverter = new dodSON.Core.Converters.TypeSerializer <List <byte[]> >(); var boolConverter = new dodSON.Core.Converters.TypeSerializer <bool>(); var clientConfigurationConverter = new dodSON.Core.Converters.TypeSerializer <IClientConfiguration>(); // var request = transportDataConverter.FromByteArray(data); if (request.Alpha == ContextFor("Hello")) { // ######## create tunnel // create public/private keys var KeyGenerator = AsymmetricCryptoProvider; var serverPublicKey = KeyGenerator.ToXmlString(false); var serverPrivateKey = KeyGenerator.ToXmlString(true); // clear some bullshit here, I do not understand this, it refuses to register clients whom have, in theory, already unregistered... if (_RegistrationCandidates.ContainsKey(request.Beta)) { _RegistrationCandidates.Remove(request.Beta); } // add candidate _RegistrationCandidates.Add(request.Beta, new ServerRegistrationCandidate() { ClientId = request.Beta, ClientPublicKey = System.Text.Encoding.Unicode.GetString(request.Gamma), CreatedDate = DateTime.Now, ServerPrivateKey = serverPrivateKey, ServerPublicKey = serverPublicKey }); // generate response var response = transportDataConverter.ToByteArray( new TransportData() { Alpha = ContextFor("Hello"), Beta = request.Beta, Gamma = System.Text.Encoding.Unicode.GetBytes(serverPublicKey), Delta = null, Epsilon = null }); return(response); } else if (request.Alpha == ContextFor("Challenge")) { if (_RegistrationCandidates.ContainsKey(request.Beta)) { var candidate = _RegistrationCandidates[request.Beta]; var cryptoProvider = AsymmetricCryptoProvider; cryptoProvider.FromXmlString(candidate.ServerPrivateKey); var challengeEvidence = RestoreFromTransport(request.Epsilon, cryptoProvider); if (ChallengeController.Challenge(challengeEvidence)) { return(boolConverter.ToByteArray(true)); } _RegistrationCandidates.Remove(request.Beta); return(boolConverter.ToByteArray(false)); } return(boolConverter.ToByteArray(false)); } else if (request.Alpha == ContextFor("RequestServerSetup")) { if (_RegistrationCandidates.ContainsKey(request.Beta)) { var candidate = _RegistrationCandidates[request.Beta]; var cryptoProvider = AsymmetricCryptoProvider; cryptoProvider.FromXmlString(candidate.ServerPrivateKey); var challengeEvidence = RestoreFromTransport(request.Epsilon, cryptoProvider); if (ChallengeController.Challenge(challengeEvidence)) { var clientProvider = AsymmetricCryptoProvider; clientProvider.FromXmlString(candidate.ClientPublicKey); // ################ // TODO: Problem ID: dc95c9d1ab4a422cbca3834e1361aa0 : The Problem // The Problem. The TransportConfiguration referenced here is different depending on the ctor used to create it. // Using the Standard Ctors, this reference here is the same as the reference in RegistrationController. // However, using the IConfigurable interface code results in the two references being different objects. // // ######## When building in code, be sure to use the same reference in all types ########. // // Search for the Problem ID: dc95c9d1ab4a422cbca3834e1361aa0 for other elements of this problem. // Current hypothesis is that somehow the referenced registration controller are different in the two places when it should be one. // This problem manifests itself ONLY when the objects are created using the IConfiguration system. // The answer is apparent, the IConfiguration system is creating two of these items. var response = listConverter.ToByteArray(PrepareForTransport(transportConfigurationConvertor.ToByteArray(TransportConfiguration), clientProvider, TransportPartsLengthInBytes)); return(response); } _RegistrationCandidates.Remove(request.Beta); return(null); } return(null); } else if (request.Alpha == ContextFor("Register")) { if (_RegistrationCandidates.ContainsKey(request.Beta)) { var candidate = _RegistrationCandidates[request.Beta]; var cryptoProvider = AsymmetricCryptoProvider; cryptoProvider.FromXmlString(candidate.ServerPrivateKey); var challengeEvidence = RestoreFromTransport(request.Epsilon, cryptoProvider); if (ChallengeController.Challenge(challengeEvidence)) { // register newRegisterableClientConfiguration = clientConfigurationConverter.FromByteArray(RestoreFromTransport(request.Delta, cryptoProvider)); _RegistrationCandidates.Remove(request.Beta); // generate response return(boolConverter.ToByteArray(true)); } _RegistrationCandidates.Remove(request.Beta); return(boolConverter.ToByteArray(false)); } return(boolConverter.ToByteArray(false)); } else if (request.Alpha == ContextFor("Unregister")) { if (_RegistrationCandidates.ContainsKey(request.Beta)) { var candidate = _RegistrationCandidates[request.Beta]; var cryptoProvider = AsymmetricCryptoProvider; cryptoProvider.FromXmlString(candidate.ServerPrivateKey); var challengeEvidence = RestoreFromTransport(request.Epsilon, cryptoProvider); if (ChallengeController.Challenge(challengeEvidence)) { // unregister newRegisterableClientConfiguration = clientConfigurationConverter.FromByteArray(RestoreFromTransport(request.Delta, cryptoProvider)); _RegistrationCandidates.Remove(request.Beta); // generate response return(boolConverter.ToByteArray(true)); } _RegistrationCandidates.Remove(request.Beta); return(boolConverter.ToByteArray(false)); } return(boolConverter.ToByteArray(false)); } return(null); }