private async Task HandleWebsocketRequest(WebSocketContext context) { string key = null; try { var timeout = new CancellationTokenSource(new TimeSpan(0, 0, 3)); string filename = await context.WebSocket.ReceiveString(timeout.Token); long?filesize = null; if (long.TryParse(await context.WebSocket.ReceiveString(timeout.Token), out long size)) { filesize = size; } string mimetype = await context.WebSocket.ReceiveString(timeout.Token); SocketRelay relay = new SocketRelay(context.WebSocket, filename, filesize, mimetype); key = AddRelay(relay); await context.WebSocket.SendString($"code={key}", timeout.Token); OnSocketRelay?.Invoke(filename, filesize, key, relay); await relay.HandleUpload(); } catch (TaskCanceledException) { await context.WebSocket.CloseOutputAsync(WebSocketCloseStatus.Empty, null, CancellationToken.None); } // client disconnects without closing catch (WebSocketException) { } catch (Exception e) when(e.InnerException is WebSocketException) { } finally { if (key != null) { activeRelays.TryRemove(key, out IRelay x); } } }
private async void ProcessLocalConnection(object state) { var connection = (ConnectionInfo)state; var buffer = new byte[BufferSize]; try { var bytesRead = connection.LocalSocket.Receive(buffer); if (bytesRead < 1 || buffer[0] != Protocol.Socks4.Version) { connection.Terminate(); return; } OnLogMessage?.Invoke(this, $"Got {bytesRead} bytes from "); } catch (SocketException ex) { OnLogMessage?.Invoke(this, $"Caught SocketException in ProcessLocalConnection with error code {ex.SocketErrorCode}"); } try { switch (buffer[1]) { case Protocol.Socks4.CommandStreamConnection: { var portBuffer = new[] { buffer[2], buffer[3] }; var port = (ushort)(portBuffer[0] << 8 | portBuffer[1]); var address = new[] { buffer[4], buffer[5], buffer[6], buffer[7] }; var destAddress = new IPAddress(address).ToString(); var destAddressFamily = AddressFamily.InterNetwork; if (IsSocks4AProtocol(address)) { var hostBuffer = new byte[256]; Buffer.BlockCopy(buffer, 9, hostBuffer, 0, 100); // Resolve hostname, fallback to remote proxy dns resolution var hostname = Encoding.ASCII.GetString(hostBuffer).TrimEnd((char)0); if (!ResolveHostnamesRemotely) { var resolvedHostname = await DnsResolver.TryResolve(hostname); if (resolvedHostname == null) { OnLogMessage?.Invoke(this, $"DNS resolution failed for {hostname}"); SendSocks4Reply(connection.LocalSocket, Protocol.Socks4.StatusRequestGranted, address, portBuffer); connection.Terminate(); break; } destAddress = resolvedHostname.ToString(); destAddressFamily = resolvedHostname.AddressFamily; } else { destAddress = hostname; destAddressFamily = AddressFamily.Unspecified; } } connection.RemoteSocket = Socks5Client.Connect( RemotEndPoint.Address.ToString(), RemotEndPoint.Port, destAddress, port, Username, Password, SendTimeout, ReceiveTimeout); OnRemoteConnect?.Invoke(this, new DnsEndPoint(destAddress, port, destAddressFamily)); if (connection.RemoteSocket.Connected) { OnLogMessage?.Invoke(this, "RelayBiDirectionally between server and client started"); SendSocks4Reply(connection.LocalSocket, Protocol.Socks4.StatusRequestGranted, address, portBuffer); SocketRelay.RelayBiDirectionally(connection.RemoteSocket, connection.LocalSocket); } else { OnLogMessage?.Invoke(this, "RemoteSocket connection failed"); SendSocks4Reply(connection.LocalSocket, Protocol.Socks4.StatusRequestFailed, address, portBuffer); connection.Terminate(); } break; } case Protocol.Socks4.CommandBindingConnection: { var portBuffer = new[] { buffer[2], buffer[3] }; var address = new[] { buffer[4], buffer[5], buffer[6], buffer[7] }; // TCP/IP port binding not supported SendSocks4Reply(connection.LocalSocket, Protocol.Socks4.StatusRequestFailed, address, portBuffer); connection.Terminate(); break; } default: OnLogMessage?.Invoke(this, "Unknown protocol on LocalSocket"); connection.Terminate(); break; } } catch (SocketException ex) { OnLogMessage?.Invoke(this, $"Caught SocketException in ProcessLocalConnection with error code {ex.SocketErrorCode.ToString()}"); } catch (Socks5Exception ex) { var portBuffer = new[] { buffer[2], buffer[3] }; var address = new[] { buffer[4], buffer[5], buffer[6], buffer[7] }; SendSocks4Reply(connection.LocalSocket, Protocol.Socks4.StatusRequestFailed, address, portBuffer); connection.Terminate(); OnLogMessage?.Invoke(this, $"Caught Socks5Exception in ProcessLocalConnection with message {ex.Message}"); } }
private void AcceptCallback(IAsyncResult ar) { Socket sktActive = null; try { var state = (Tuple<Socket, EventWaitHandle>)ar.AsyncState; state.Item2.Set(); sktActive = state.Item1.EndAccept(ar); } catch (ObjectDisposedException) { // Accept has been cancelled. return; } try { // 安全验证 //if (!m_confirm.Confirm(sktActive)) //{ // sktActive.Close(); // return; //} Socket sktPassive = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sktPassive.Connect(m_epDest); SocketRelay relay = new SocketRelay(sktActive, sktPassive); relay.OnFinished += OnSocketRelayFinished; relay.Run(); lock (m_listSR) m_listSR.Add(relay); } catch (SocketException ex) { string strbuf = String.Format("{0}({1})", ex.Message, ex.ErrorCode); byte[] buf = Encoding.Default.GetBytes(strbuf); sktActive.Send(buf); sktActive.Shutdown(SocketShutdown.Both); sktActive.Close(); } }
private void OnSocketRelayFinished(SocketRelay item) { lock (m_listSR) { if (m_listSR.Contains(item)) m_listSR.Remove(item); } }