/// <summary> /// Opens the output. /// </summary> /// <param name="Client">SOCKS5 client with established connection.</param> public async Task Opened(Socks5Client Client) { Client.OnWriteQueueEmpty += this.WriteQueueEmpty; this.client = Client; if (!(this.tempFile is null)) { if (!await this.syncObject.TryBeginWrite(10000)) { throw new TimeoutException(); } try { if (!this.isWriting && (this.tempFile.Length - this.pos >= this.blockSize || (this.done && this.tempFile.Length > this.pos))) { await this.WriteBlockLocked(); } } finally { await this.syncObject.EndWrite(); } } }
/// <summary> /// Event arguments for data reception events. /// </summary> /// <param name="Buffer">Binary Data Buffer</param> /// <param name="Offset">Start index of first byte received.</param> /// <param name="Count">Number of bytes received.</param> /// <param name="Stream">SOCKS5 client stream.</param> /// <param name="State">State</param> internal DataReceivedEventArgs(byte[] Buffer, int Offset, int Count, Socks5Client Stream, object State) { this.buffer = Buffer; this.offset = Offset; this.count = Count; this.stream = Stream; this.state = State; }
/// <summary> /// Opens the output. /// </summary> /// <param name="Client">SOCKS5 client with established connection.</param> public void Opened(Socks5Client Client) { Client.OnWriteQueueEmpty += this.WriteQueueEmpty; this.client = Client; if (!this.isWriting && this.tempFile.Length - this.pos >= this.blockSize) { this.WriteBlockLocked(); } }
/// <summary> /// Class managing the transmission of a SOCKS5 bytestream. /// </summary> /// <param name="Client">XMPP client.</param> /// <param name="To">To</param> /// <param name="BlockSize">Block size</param> /// <param name="E2E">End-to-end encryption, if used.</param> public OutgoingStream(XmppClient Client, string To, int BlockSize, IEndToEndEncryption E2E) { this.xmppClient = Client; this.client = null; this.to = To; this.blockSize = BlockSize; this.e2e = E2E; this.isWriting = false; this.done = false; this.tempFile = new TemporaryFile(); }
private async Task ClientStateChanged(object Sender, EventArgs e3) { Socks5Client Client = (Socks5Client)Sender; Socks5QueryState State = (Socks5QueryState)Client.Tag; switch (Client.State) { case Socks5State.Authenticated: Client.CONNECT(State.streamId, State.eventargs.From, this.client.FullJID); break; case Socks5State.Connected: StringBuilder Xml = new StringBuilder(); Xml.Append("<query xmlns=\""); Xml.Append(Namespace); Xml.Append("\" sid=\""); Xml.Append(State.streamId); Xml.Append("\"><streamhost-used jid=\""); Xml.Append(Client.Host); Xml.Append("\"/></query>"); State.eventargs.IqResult(Xml.ToString()); break; case Socks5State.Error: case Socks5State.Offline: if (Client.State == Socks5State.Error) { State.eventargs.IqError(new BadRequestException("Unable to establish a SOCKS5 connection.", State.eventargs.IQ)); } Client.Dispose(); lock (this.streams) { this.streams.Remove(State.streamId); } if (State.eventargs2.CloseCallback != null) { try { await State.eventargs2.CloseCallback(this, new StreamEventArgs(false, Client, State.eventargs2.State)); } catch (Exception ex) { Log.Critical(ex); } } break; } }
/// <summary> /// Class managing the transmission of a SOCKS5 bytestream. /// </summary> /// <param name="StreamId">Stream ID.</param> /// <param name="From">From</param> /// <param name="To">To</param> /// <param name="BlockSize">Block size</param> /// <param name="E2E">End-to-end encryption, if used.</param> public OutgoingStream(string StreamId, string From, string To, int BlockSize, IEndToEndEncryption E2E) { this.client = null; this.sid = StreamId; this.from = From; this.to = To; this.blockSize = BlockSize; this.e2e = E2E; this.isWriting = false; this.done = false; this.tempFile = new TemporaryFile(); }
/// <summary> /// Class managing the transmission of a SOCKS5 bytestream. /// </summary> /// <param name="StreamId">Stream ID.</param> /// <param name="From">From</param> /// <param name="To">To</param> /// <param name="BlockSize">Block size</param> /// <param name="E2E">End-to-end encryption, if used.</param> public OutgoingStream(string StreamId, string From, string To, int BlockSize, IEndToEndEncryption E2E) { this.client = null; this.sid = StreamId; this.from = From; this.to = To; this.blockSize = BlockSize; this.e2e = E2E; this.isWriting = false; this.done = false; this.tempStream = new TemporaryStream(); this.syncObject = new MultiReadSingleWriteObject(); }
/// <summary> /// Opens the output. /// </summary> /// <param name="Client">SOCKS5 client with established connection.</param> public void Opened(Socks5Client Client) { Client.OnWriteQueueEmpty += this.WriteQueueEmpty; this.client = Client; if (!(this.tempFile is null)) { lock (this.tempFile) { if (!this.isWriting && (this.tempFile.Length - this.pos >= this.blockSize || (this.done && this.tempFile.Length > this.pos))) { this.WriteBlockLocked(); } } } }
private void Callback(StreamEventHandler Callback, object State, bool Ok, Socks5Client Stream, string StreamId) { if (!Ok && !string.IsNullOrEmpty(StreamId)) { lock (this.streams) { this.streams.Remove(StreamId); } } if (Callback != null) { try { Callback(this, new StreamEventArgs(Ok, Stream, State)); } catch (Exception ex) { Log.Critical(ex); } } }
private async Task QueryHandler(object Sender, IqEventArgs e) { string StreamId = XML.Attribute(e.Query, "sid"); XmlElement E; if (string.IsNullOrEmpty(StreamId) || StreamId != Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(StreamId))) { throw new NotAcceptableException("Invalid Stream ID.", e.IQ); } string Host = null; string JID = null; int Port = 0; foreach (XmlNode N in e.Query.ChildNodes) { E = N as XmlElement; if (E is null) { continue; } if (E.LocalName == "streamhost" && E.NamespaceURI == Namespace) { Host = XML.Attribute(E, "host"); JID = XML.Attribute(E, "jid"); Port = XML.Attribute(E, "port", 0); break; } } if (string.IsNullOrEmpty(JID) || string.IsNullOrEmpty(Host) || Port <= 0 || Port >= 0x10000) { throw new BadRequestException("Invalid parameters.", e.IQ); } ValidateStreamEventHandler h = this.OnOpen; ValidateStreamEventArgs e2 = new ValidateStreamEventArgs(this.client, e, StreamId); if (h != null) { try { await h(this, e2); } catch (Exception ex) { Log.Critical(ex); } } if (e2.DataCallback is null || e2.CloseCallback is null) { throw new NotAcceptableException("Stream not expected.", e.IQ); } Socks5Client Client; lock (this.streams) { if (this.streams.ContainsKey(StreamId)) { throw new ConflictException("Stream already exists.", e.IQ); } Client = new Socks5Client(Host, Port, JID) { CallbackState = e2.State }; this.streams[StreamId] = Client; } Client.Tag = new Socks5QueryState() { streamId = StreamId, eventargs = e, eventargs2 = e2 }; Client.OnDataReceived += e2.DataCallback; Client.OnStateChange += this.ClientStateChanged; }
/// <summary> /// Event arguments for data reception events. /// </summary> /// <param name="Data">Data received.</param> /// <param name="Stream">SOCKS5 client stream.</param> /// <param name="State">State</param> internal DataReceivedEventArgs(byte[] Data, Socks5Client Stream, object State) { this.data = Data; this.stream = Stream; this.state = State; }
/// <summary> /// Event arguments for stream callbacks. /// </summary> /// <param name="Ok">If request was successful.</param> /// <param name="Stream">Stream object.</param> /// <param name="State">State object.</param> public StreamEventArgs(bool Ok, Socks5Client Stream, object State) { this.ok = Ok; this.stream = Stream; this.state = State; }