void ICommunicationOwner.OnTunnelingClosing(CommunicationSubType communicationSubType, Exception exception) { switch (communicationSubType) { case CommunicationSubType.Session: // log if (exception != null) { LogError($"Error: {exception.Message}"); } LogVerbose("Closing tunneling mode."); break; case CommunicationSubType.UpStream: case CommunicationSubType.DownStream: string direction = communicationSubType.ToString(); if (exception != null) { // terminate the communication StopCommunication(); // decide error severity Tuple <TraceEventType, string> logContent = GetLogContent(exception); // log Log(logContent.Item1, $"Error in {direction} tunneling: {logContent.Item2}"); } else { // shutdown the communication of another direction bool downStream = (communicationSubType == CommunicationSubType.DownStream); lock (this.instanceLocker) { if (this.server.IsConnecting) { Socket socket = this.server.Socket; socket.Shutdown(downStream ? SocketShutdown.Receive : SocketShutdown.Send); } if (this.client != null) { Socket socket = this.client.Client; socket.Shutdown(downStream ? SocketShutdown.Send : SocketShutdown.Receive); } } } LogVerbose($"Closing {communicationSubType.ToString()} tunneling."); break; } }
void ICommunicationOwner.OnTunnelingStarted(CommunicationSubType communicationSubType) { // log switch (communicationSubType) { case CommunicationSubType.Session: LogVerbose("Started tunneling mode."); break; case CommunicationSubType.UpStream: case CommunicationSubType.DownStream: LogVerbose($"Started {communicationSubType.ToString()} tunneling."); break; } return; }
private static void Forward(ICommunicationOwner owner, CommunicationSubType type) { // argument checks Debug.Assert(owner != null); IMessageIO io; switch (type) { case CommunicationSubType.UpStream: io = owner.RequestIO; break; case CommunicationSubType.DownStream: io = owner.ResponseIO; break; default: throw new ArgumentOutOfRangeException(nameof(type)); } Debug.Assert(io != null); Stream input = io.Input; Debug.Assert(input != null); Stream output = io.Output; Debug.Assert(output != null); // forward bytes from the input to the output try { // notify the owner owner.OnTunnelingStarted(type); // forward bytes byte[] buf = ComponentFactory.AllocMemoryBlock(); try { do { int readCount = input.Read(buf, 0, buf.Length); if (readCount <= 0) { // the end of the stream break; } output.Write(buf, 0, readCount); output.Flush(); } while (true); } catch (EndOfStreamException) { // continue } finally { ComponentFactory.FreeMemoryBlock(buf); } // notify the owner of its normal closing owner.OnTunnelingClosing(type, null); } catch (Exception exception) { // notify the owner of the exception try { owner.OnTunnelingClosing(type, exception); } catch { // continue } // continue } return; }