Beispiel #1
0
 public void Shutdown(SocketShutdown direction)
 {
     lock (_syncRoot) {
         if (direction == SocketShutdown.Send || direction == SocketShutdown.Both)
         {
             if (!MState.HasShutdown)
             {
                 MState |= MyStreamState.LocalShutdown;
                 var ls = lastSend;
                 if (ls?.IsCompleted == false)
                 {
                     lastSend = NaiveUtils.RunAsyncTask(async() => {
                         try {
                             await ls;
                         } catch (Exception) {
                             ;
                         }
                         SendFin().Forget();
                     });
                 }
                 else
                 {
                     SendFin().Forget();
                 }
             }
         }
         if (direction == SocketShutdown.Receive || direction == SocketShutdown.Both)
         {
             MState |= MyStreamState.RemoteShutdown;
         }
     }
 }
Beispiel #2
0
        public override void Update(BytesSegment bs)
        {
            bs.CheckAsParameter();
            var pos = (uint)bs.Offset;
            var end = pos + (uint)bs.Len;

            fixed(Context *ctx = &this.ctx)
            fixed(byte *bytes = bs.Bytes)
            {
                while (pos < end)
                {
                    var remainningKeystream = KeystreamBufferSize - keystreamBufferPos;
                    if (remainningKeystream == 0)
                    {
                        keystreamBufferPos  = 0;
                        remainningKeystream = KeystreamBufferSize;
                        NextKeystreamBuffer(ctx);
                    }
                    var count = end - pos;
                    count = count < remainningKeystream ? count : remainningKeystream;
                    NaiveUtils.XorBytesUnsafe(ctx->keyStreamBuffer + keystreamBufferPos, bytes + pos, count);
                    pos += count;
                    keystreamBufferPos += count;
                }
            }
        }
Beispiel #3
0
            public override void Update(BytesSegment bs)
            {
                bs.CheckAsParameter();
                var pos          = bs.Offset;
                var end          = pos + bs.Len;
                var keyStreamBuf = this.keyStreamBuf;

                fixed(byte *bytes = bs.Bytes)
                {
                    while (pos < end)
                    {
                        var remainningKeystream = KeystreamBufferSize - keystreamBufferPos;
                        if (remainningKeystream == 0)
                        {
                            keystreamBufferPos  = 0;
                            remainningKeystream = KeystreamBufferSize;
                            var ksb = keyStreamBuf;
                            for (int i = 0; i < KsBlockCount; i++)
                            {
                                ksb[i] = counter;
                                if (++counter.v1 == 0)
                                {
                                    ++counter.v0;
                                }
                                Cipher.encrypt_64_128(keys, &ksb[i]);
                            }
                        }
                        var count = end - pos;
                        count = count < remainningKeystream ? count : remainningKeystream;
                        NaiveUtils.XorBytesUnsafe((byte *)keyStreamBuf + keystreamBufferPos, bytes + pos, (uint32)count);
                        pos += count;
                        keystreamBufferPos += count;
                    }
                }
            }
Beispiel #4
0
        public override void Update(BytesSegment bs)
        {
            bs.CheckAsParameter();
            var pos = bs.Offset;
            var end = pos + bs.Len;

            while (pos < end)
            {
                var remainningFeed = toBeFeedBack.Length - feedingPos;
                if (remainningFeed == 0)
                {
                    feedingPos     = 0;
                    remainningFeed = toBeFeedBack.Length;
                    EcbTransform.TransformBlock(toBeFeedBack, 0, toBeFeedBack.Length, feedingBack, 0);
                }
                var feedEnd      = pos + remainningFeed;
                var thisBlockEnd = (feedEnd < end) ? feedEnd : end;
                var count        = thisBlockEnd - pos;
                if (IsEncrypting)
                {
                    NaiveUtils.XorBytes(feedingBack, feedingPos, bs.Bytes, pos, (uint)count);
                    NaiveUtils.CopyBytes(bs.Bytes, pos, toBeFeedBack, feedingPos, count);
                }
                else
                {
                    NaiveUtils.CopyBytes(bs.Bytes, pos, toBeFeedBack, feedingPos, count);
                    NaiveUtils.XorBytes(feedingBack, feedingPos, bs.Bytes, pos, (uint)count);
                }
                pos        += count;
                feedingPos += count;
            }
        }
Beispiel #5
0
        protected override Task <int> ReadAsyncImpl(BytesSegment bs)
        {
            var e         = readArgPool.GetValue();
            var userToken = ((ReadUserToken)e.UserToken);
            var tcs       = _unusedReadTcs ?? new TaskCompletionSource <int>();

            _unusedReadTcs = null;
            userToken.tcs  = tcs;
            var sw = userToken.sw = this;

            e.SetBuffer(bs.Bytes, bs.Offset, bs.Len);
            try {
                if (Socket.ReceiveAsync(e))   // if opearation not completed synchronously
                {
                    return(tcs.Task);
                }
            } catch (Exception) {
                recycleReadArgs(e, userToken);
                throw;
            }
            var r = ReadCompleted(e, userToken, sw, out var ex);

            if (r < 0)
            {
                throw ex;
            }
            _unusedReadTcs = tcs;
            return(NaiveUtils.GetCachedTaskInt(r));
        }
Beispiel #6
0
        // HKDF_SHA1
        // libsscrypto/hkdf.c mbedtls_hkdf
        public static byte[] GetAeadSubkey(byte[] key, byte[] salt, byte[] info, int outputLen)
        {
            byte[] prk;
            using (var h = new HMACSHA1(salt)) {
                prk = h.ComputeHash(key);
            }
            var N = outputLen / prk.Length;

            if (outputLen % prk.Length != 0)
            {
                N++;
            }
            var T      = new byte[0];
            var c      = new byte[1];
            var output = new byte[outputLen];
            var cur    = 0;

            using (var h = new HMACSHA1(prk)) {
                for (int i = 0; i < N; i++)
                {
                    h.TransformBlock(T, 0, T.Length, T, 0);
                    h.TransformBlock(info, 0, info.Length, info, 0);
                    c[0] = (byte)i;
                    T    = h.TransformFinalBlock(c, 0, 1);
                    NaiveUtils.CopyBytes(T, 0, output, cur, (i < N) ? T.Length : outputLen - cur);
                    cur += T.Length;
                }
            }
            return(output);
        }
Beispiel #7
0
        public override async Task <ConnectResult> ProtectedConnect(ConnectArgument arg)
        {
            var dest       = arg.Dest;
            var baseResult = await ConnectHelper.Connect(this, server.WithDefaultPort(80), connect_timeout);

            if (!baseResult.Ok)
            {
                return(baseResult);
            }
            try {
                var dataStream = baseResult.Stream;
                var asStream   = MyStream.ToStream(dataStream);
                var sw         = new StringWriter(new StringBuilder(1024));
                var destStr    = dest.ToString();
                HttpClient.WriteHttpRequestHeader(sw, "CONNECT", destStr, new Dictionary <string, string> {
                    ["Host"] = destStr
                });
                await dataStream.WriteAsync(NaiveUtils.GetUTF8Bytes(sw.ToString()));

                var responseStr = await NaiveUtils.ReadStringUntil(asStream, NaiveUtils.DoubleCRLFBytes);

                var sr       = new StringReader(responseStr);
                var response = HttpClient.ReadHttpResponseHeader(sr);
                if (response.StatusCode != "200")
                {
                    throw new Exception($"remote server response '{response.StatusCode} {response.ReasonPhrase}'");
                }
                return(CreateConnectResultWithStream(dataStream));
            } catch (Exception) {
                MyStream.CloseWithTimeout(baseResult.Stream);
                throw;
            }
        }
Beispiel #8
0
 static void Update(byte *bytes, uint len,
                    QWords128 *keyStreamBuf, ref uint keystreamBufferPos, ref QWords128 counter, Keys128128 keys)
 {
     while (len > 0)
     {
         var remainningKeystream = KeystreamBufferSize - keystreamBufferPos;
         if (remainningKeystream == 0)
         {
             keystreamBufferPos  = 0;
             remainningKeystream = KeystreamBufferSize;
             var ksb = keyStreamBuf;
             for (uint i = 0; i < KsBlockCount; i += 4)
             {
                 for (uint j = 0; j < 4; j++)
                 {
                     ksb[i + j] = counter;
                     if (++counter.v1 == 0)
                     {
                         ++counter.v0;
                     }
                 }
                 Cipher.encrypt_128_128_4blocks(keys, &ksb[i]);
             }
         }
         var count = len < remainningKeystream ? len : remainningKeystream;
         NaiveUtils.XorBytesUnsafe((byte *)keyStreamBuf + keystreamBufferPos, bytes, count);
         bytes += count;
         len   -= count;
         keystreamBufferPos += count;
     }
 }
Beispiel #9
0
        public async Task <int> _readAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            if (IsChunkedEncoding)
            {
                if (remainingChunkSize == -1)
                {
                    throw new EndOfStreamException();
                }
                if (remainingChunkSize == 0)
                {
                    var str = await NaiveUtils.ReadStringUntil(baseStream, NaiveUtils.CRLFBytes, maxLength : 32, withPattern : false);

                    remainingChunkSize = Convert.ToInt64(str, 16);
                    if (remainingChunkSize == 0)
                    {
                        remainingChunkSize = -1; // EOF
                        return(0);
                    }
                }
                int bytesToRead = (int)Math.Min(count, remainingChunkSize);
                var ret         = await baseStream.ReadAsync(buffer, offset, bytesToRead, cancellationToken).CAF();

                if (ret == 0)
                {
                    throw new DisconnectedException("unexpected EOF while reading chunked http request content.");
                }
                readedLength       += ret;
                remainingChunkSize -= ret;
                if (remainingChunkSize == 0)
                {
                    var read = 0;
                    do   // read CRLF
                    {
                        read += await baseStream.ReadAsync(new byte[2], read, 2 - read);
                    } while (read < 2);
                }
                return(ret);
            }
            else
            {
                int bytesToRead = (int)(count < RemainingLength ? count : RemainingLength);
                if (bytesToRead > 0)
                {
                    var ret = await baseStream.ReadAsync(buffer, offset, bytesToRead, cancellationToken).CAF();

                    if (ret == 0)
                    {
                        throw new DisconnectedException("unexpected EOF while reading http request content.");
                    }
                    readedLength += ret;
                    return(ret);
                }
                else
                {
                    return(0);
                }
            }
        }
Beispiel #10
0
        public async Task <bool> ReadNextPartHeader()
        {
            if (IsReadingPart)
            {
                throw new InvalidOperationException("cannot read next part while IsReadingPart == true");
            }
            if (!firstBoundaryRead)
            {
                await NaiveUtils.ReadStringUntil(BaseStream, Boundary, withPattern : false);

                Boundary          = NaiveUtils.ConcatBytes(NaiveUtils.CRLFBytes, Boundary);
                firstBoundaryRead = true;
            }
            var twoBytes = new byte[2];
            await myStream.ReadFullAsyncR(twoBytes);

            bool noMoreParts = false;

            if (twoBytes[0] == '-' && twoBytes[1] == '-')
            {
                noMoreParts = true;
                // read the last CRLF to buf
                await myStream.ReadFullAsyncR(twoBytes);
            }
            if (twoBytes[0] != '\r' || twoBytes[1] != '\n')
            {
                throw new Exception($"unexcepted data: {twoBytes[0]}({(char)twoBytes[0]}), {twoBytes[1]}({(char)twoBytes[1]})");
            }
            if (noMoreParts)
            {
                return(false);
            }
            CurrentPartRawHeader = (await NaiveUtils.ReadStringUntil(BaseStream, NaiveUtils.DoubleCRLFBytes, withPattern: true));
            var headers = CurrentPartRawHeader.Split(separator, StringSplitOptions.None);
            var i       = 0;

            while (HttpConnection.ParseHeader(headers[i++], out var key, out var value))
            {
                CurrentPartHeaders[key] = value;
            }
            var content_disposition = CurrentPartHeaders["Content-Disposition"];
            var regexResult         = re_Content_Disposition.Match(content_disposition);

            if (regexResult.Success == false)
            {
                throw new Exception("bad Content-Disposition");
            }
            CurrentPartName     = regexResult.Groups[1].Value;
            CurrentPartFileName = regexResult.Groups[2].Value;
            state         = 0;
            _position     = 0;
            IsReadingPart = true;
            return(true);
        }
Beispiel #11
0
        public async Task HandshakeAsync(bool enterRecvLoop, Dictionary <string, string> addHeaders)
        {
            var wskey   = Guid.NewGuid().ToString("D");
            var headers = new Dictionary <string, string> {
                ["Upgrade"]               = "websocket",
                ["Connection"]            = "Upgrade",
                ["Sec-WebSocket-Version"] = "13",
                ["Sec-WebSocket-Key"]     = wskey
            };

            if (Host != null)
            {
                headers.Add("Host", Host);
            }
            if (addHeaders != null)
            {
                foreach (var item in addHeaders)
                {
                    headers[item.Key] = item.Value;
                }
            }
            var strw = new StringWriter(new StringBuilder(1024));

            HttpClient.WriteHttpRequestHeader(strw, "GET", Path, headers);
            await BaseStream.WriteAsync(NaiveUtils.GetUTF8Bytes(strw.ToString()));

            var responseString = await NaiveUtils.ReadStringUntil(BaseStream.ToStream(), NaiveUtils.DoubleCRLFBytes);

            HttpResponse response;

            try {
                response = HttpClient.ReadHttpResponseHeader(new StringReader(responseString));
            } catch (Exception e) {
                throw new Exception("error parsing response:\n" + responseString, e);
            }
            var statusCode = response.StatusCode.Split(' ')[0];

            if (statusCode == "101" &&
                response.TestHeader("Connection", "Upgrade") &&
                response.TestHeader("Upgrade", "websocket") &&
                response.TestHeader("Sec-WebSocket-Accept", GetWebsocketAcceptKey(wskey))
                )
            {
                ConnectionState = States.Open;
                if (enterRecvLoop)
                {
                    await recvLoopAsync();
                }
            }
            else
            {
                throw new Exception($"websocket handshake failed ({response.StatusCode})");
            }
        }
Beispiel #12
0
 public static Task SendString(this IMsgStream ms, string str)
 {
     if (ms is IMsgStreamStringSupport isss)
     {
         return(isss.SendString(str));
     }
     return(NaiveUtils.RunAsyncTask(async() => {
         var buf = NaiveUtils.GetUTF8Bytes_AllocFromPool(str);
         await ms.SendMsg(new BytesView(buf.Bytes, 0, buf.Len));
         BufferPool.GlobalPut(buf.Bytes);
     }));
 }
Beispiel #13
0
        public override Task <int> ReadAsync(BytesSegment bs)
        {
            int r = TryDequeue(bs);

            if (r > 0)
            {
                return(NaiveUtils.GetCachedTaskInt(r));
            }
            if (WaitBeforeRead.IsCompleted == false || ReadEventRegistered)
            {
                return(ComplexRead(bs));
            }
            return(BaseStream.ReadAsync(bs));
        }
Beispiel #14
0
        public static async Task <ConnectResult> Connect(IAdapter adapter, AddrPort dest, int timeoutSeconds)
        {
            Socket socket;

            try {
                socket = await NaiveUtils.ConnectTcpAsync(dest, timeoutSeconds * 1000);
            } catch (Exception e) {
                return(new ConnectResult(adapter, ConnectResultEnum.Failed)
                {
                    FailedReason = e.Message,
                    Exception = e
                });
            }
            return(new ConnectResult(adapter, MyStream.FromSocket(socket, adapter.GetAdapter().socket_impl)));
        }
Beispiel #15
0
            private Task SendMsg(Msg msg)
            {
                if (ivSent)
                {
                    return(ws.SendMsg(msg));
                }
                ivSent = true;
                return(NaiveUtils.RunAsyncTask(async() => {
                    var writeEnc = enc(true);
                    await ws.SendBytesAsync(writeEnc.IV);
                    ws.AddWriteFilter(FilterBase.GetStreamFilterFromIVEncryptor(true, writeEnc, true));

                    await ws.SendMsg(msg);
                }));
            }
Beispiel #16
0
        public static async Task <WebSocketClient> ConnectToAsync(AddrPort dest, string path,
                                                                  int timeout, CancellationToken ct)
        {
            Socket socket = await NaiveUtils.ConnectTcpAsync(dest, timeout, async x => x, ct);

            try {
                var socketStream = MyStream.FromSocket(socket);
                var ws           = new WebSocketClient(MyStream.ToStream(socketStream), path);
                ws.Host = dest.Host;
                return(ws);
            } catch (Exception) {
                socket.Dispose();
                throw;
            }
        }
Beispiel #17
0
        private static async Task SaveResponseToFile(string filepath, HttpWebResponse resp)
        {
            string tmpPath = filepath + ".downloading";

            using (var fs = File.Open(tmpPath, FileMode.Create, FileAccess.ReadWrite)) {
                await NaiveUtils.StreamCopyAsync(resp.GetResponseStream(), fs);
            }
            if (File.Exists(filepath))
            {
                File.Replace(tmpPath, filepath, null, true);
            }
            else
            {
                File.Move(tmpPath, filepath);
            }
        }
Beispiel #18
0
            public async Task Listen()
            {
                try {
                    IsRunning = true;
                    try {
                        tcpListener.Start();
                    } catch (Exception e) {
                        Logger.error($"starting listening on {localEP}: {e.Message}");
                        return;
                    }
                    if (LogInfo)
                    {
                        Logger.info($"listening on {localEP}");
                    }
                    while (true)
                    {
                        try {
                            var client = await tcpListener.AcceptTcpClientAsync();

                            NaiveUtils.ConfigureSocket(client.Client);
                            Task.Run(() => server.HandleAcceptedTcp(client)).Forget();
                        } catch (Exception e) {
                            if (IsRunning)
                            {
                                server.logException(e, Logging.Level.Error, $"({localEP}) accepting connection:");
                                await Task.Delay(300);
                            }
                            else
                            {
                                return;
                            }
                        }
                    }
                } catch (Exception e) {
                    if (IsRunning)
                    {
                        server.logException(e, Logging.Level.Error, $"({localEP}) Run():");
                    }
                } finally {
                    IsRunning = false;
                    if (LogInfo)
                    {
                        server.log($"({localEP}) listening thread exiting", Logging.Level.Warning);
                    }
                }
            }
Beispiel #19
0
        public static async Task <WebSocketClient> ConnectToTlsAsync(AddrPort dest, string path,
                                                                     int timeout, CancellationToken ct)
        {
            var stream = await NaiveUtils.ConnectTlsAsync(dest, timeout,
                                                          System.Security.Authentication.SslProtocols.Tls11
                                                          | System.Security.Authentication.SslProtocols.Tls12,
                                                          ct);

            try {
                var ws = new WebSocketClient(stream, path);
                ws.Host = dest.Host;
                return(ws);
            } catch (Exception) {
                stream.Dispose();
                throw;
            }
        }
Beispiel #20
0
 public static AwaitableWrapper WriteMultipleAsyncR(this IMyStream myStream, BytesView bv)
 {
     if (myStream is IMyStreamMultiBuffer bvs)
     {
         return(bvs.WriteMultipleAsyncR(bv));
     }
     else
     {
         return(new AwaitableWrapper(NaiveUtils.RunAsyncTask(async() => {
             foreach (var item in bv)
             {
                 if (item.len > 0)
                 {
                     await myStream.WriteAsync(new BytesSegment(item));
                 }
             }
         })));
     }
 }
Beispiel #21
0
        public override Task <int> ReadAsync(BytesSegment bs)
        {
            // We use an internal read-ahead buffer to reduce many read() syscalls when bs.Len is very small.
            // It's important since there is a hardware bug named 'Meltdown' in Intel CPUs.
            // TESTED: This optimization made ReadAsync 20x faster when bs.Len == 4,
            //         on Windows 10 x64 16299.192 with a laptop Haswell CPU.
            var ret = PreReadAsync(ref bs, false);

            if (ret > 0)
            {
                return(NaiveUtils.GetCachedTaskInt(ret));
            }
            if ((ret = TryReadNonblocking(bs)) > 0)
            {
                Interlocked.Increment(ref ctr.Rsync);
                return(NaiveUtils.GetCachedTaskInt(ret));
            }
            Interlocked.Increment(ref ctr.Rasync);
            return(ReadAsyncImpl(bs));
        }
Beispiel #22
0
        public override unsafe void Update(BytesSegment bs)
        {
            uint i   = (uint)bs.Offset;
            uint len = (uint)bs.Len;
            uint end = i + len;
            var  realEncryptedCounterPos = this.encryptedCounterPos;

            this.encryptedCounterPos = (realEncryptedCounterPos + (uint)bs.Len) % keystreamSize;
            fixed(byte *encCtr = keystream)
            fixed(byte *bytes = bs.Bytes)
            while (i < end)
            {
                var unusedEncryptedCounter = keystreamSize - realEncryptedCounterPos;

                if (unusedEncryptedCounter == 0)
                {
                    realEncryptedCounterPos = 0;
                    if (keystreamSize > blockSize)
                    {
                        for (int j = 0; j < keystreamSize; j += blockSize)
                        {
                            Buffer.BlockCopy(Counter, 0, counterBlocks, j, blockSize);
                            IncrementCounter();
                        }
                    }
                    else
                    {
                        IncrementCounter();
                    }
                    EcbTransform.TransformBlock(counterBlocks, 0, (int)keystreamSize, keystream, 0);
                    unusedEncryptedCounter = keystreamSize;
                }
                uint blockEnd  = i + unusedEncryptedCounter;
                uint blocksEnd = (blockEnd < end) ? blockEnd : end;
                var  count     = blocksEnd - i;

                NaiveUtils.XorBytesUnsafe(encCtr + realEncryptedCounterPos, bytes + i, count);
                realEncryptedCounterPos += count;
                i = blocksEnd;
            }
        }
Beispiel #23
0
 public static Action <BytesView> GetDeflateFilter(bool isCompress)
 {
     return((bv) => {
         using (var tostream = new MemoryStream()) {
             using (var ds = new DeflateStream(
                        isCompress ? tostream : new MemoryStream(bv.bytes, bv.offset, bv.len),
                        isCompress ? CompressionMode.Compress : CompressionMode.Decompress)) {
                 if (isCompress)
                 {
                     ds.Write(bv.bytes, bv.offset, bv.len);
                     ds.Flush();
                 }
                 else
                 {
                     NaiveUtils.StreamToStream(ds, tostream);
                 }
             }
             bv.Set(tostream.ToArray());
         }
     });
 }
Beispiel #24
0
        private void CopyEncoded(string text)
        {
            var srcBytes = NaiveUtils.GetUTF8Bytes_AllocFromPool(text);

            byte[] gzBytes;
            int    len;

            using (var ms = new MemoryStream()) {
                using (var gz = new GZipStream(ms, CompressionLevel.Optimal, true)) {
                    gz.Write(srcBytes);
                    BufferPool.GlobalPut(srcBytes.Bytes);
                }
                gzBytes = ms.GetBuffer();
                len     = (int)ms.Length;
            }
            var encoded = Base64GzTag + Convert.ToBase64String(gzBytes, 0, len);
            var cs      = this.GetSystemService(Context.ClipboardService) as ClipboardManager;

            cs.PrimaryClip = ClipData.NewPlainText("text", encoded);
            Toast.MakeText(this, R.String.copied, ToastLength.Short).Show();
        }
Beispiel #25
0
        public static async Task HandleSeekableStreamAsync(this HttpConnection p, Stream stream)
        {
            var  fileLength = stream.Length;
            long beginpos   = 0;
            long endpos     = fileLength - 1;

            p.ResponseHeaders["Accept-Ranges"] = "bytes";
            if (p.RequestHeaders["Range"] is string ranges)
            {
                var match = regexBytes.Match(ranges);
                beginpos = Convert.ToInt64(match.Groups[1].Value);
                if (match.Groups[2].Success)
                {
                    endpos = Convert.ToInt64(match.Groups[2].Value);
                }
                p.ResponseStatusCode = "206 Partial Content";
                p.ResponseHeaders["Content-Range"] = $"bytes {beginpos}-{endpos}/{fileLength}";
            }
            if (p.Method == "HEAD")
            {
                await p.outputStream.SwitchToKnownLengthModeAsync(fileLength);

                await p.EndResponseAsync();
            }
            else
            {
                long realLength = endpos - beginpos + 1;
                if (p.outputStream.CurrentCompressionType == CompressionType.None)
                {
                    await p.outputStream.SwitchToKnownLengthModeAsync(realLength);
                }
                else
                {
                    await p.outputStream.SwitchToChunkedModeAsync();
                }
                stream.Position = beginpos;
                await NaiveUtils.StreamCopyAsync(from : stream, to : p.outputStream,
                                                 size : realLength, bs : (int)Math.Min(64 * 1024, realLength));
            }
        }
Beispiel #26
0
        public async Task Run(int backlog)
        {
            stopping = false;
            EndPoint ep;

            try {
                BaseListener.Server.NoDelay = true;
                BaseListener.Start(backlog);
                ep = BaseListener.LocalEndpoint;
            } catch (Exception e) {
                Logger.error($"starting on {BaseListener.LocalEndpoint}: {e.Message}");
                return;
            }
            if (LogInfo)
            {
                Logger.info($"listening on {ep}");
            }
            while (true)
            {
                TcpClient cli = null;
                try {
                    try {
                        cli = await BaseListener.AcceptTcpClientAsync().CAF();

                        NaiveUtils.ConfigureSocket(cli.Client);
                    } catch (Exception) when(stopping)
                    {
                        if (LogInfo)
                        {
                            Logger.info($"stopped on {ep}");
                        }
                        return;
                    }
                    Accepted?.Invoke(cli);
                } catch (Exception e) {
                    Logger.exception(e, Logging.Level.Error, ep?.ToString());
                }
            }
        }
Beispiel #27
0
        public static Task <ConnectResult> ConnectWrapper(IConnectionHandler handler, ConnectArgument arg)
        {
            var tcs    = new TaskCompletionSource <ConnectResult>();
            var newinc = InConnectionTcp.Create(arg.InAdapter, arg.Dest, async(r) => {
                if (r.Ok)
                {
                    var stream = new LoopbackStream();
                    r.Stream   = stream;
                    tcs.SetResult(r);
                    return(stream.Another);
                }
                else
                {
                    tcs.SetResult(r);
                    return(null);
                }
            });

            newinc.Url = arg.Url;
            newinc.DestOriginalName = arg.DestOriginalName;
            NaiveUtils.RunAsyncTask(async() => {
                try {
                    await handler.HandleTcpConnection(newinc).CAF();
                } catch (Exception e) {
                    tcs.SetException(e);
                    return;
                }
                if (newinc.IsRedirected && tcs.Task.IsCompleted == false)
                {
                    tcs.SetResult(ConnectResult.RedirectTo(handler, newinc.Redirected));
                }
                else
                {
                    tcs.SetException(new Exception("handleConnection() did nothing."));
                }
            });
            return(tcs.Task);
        }
Beispiel #28
0
        private void parseRequest(string requestLine)
        {
            var splits = requestLine.Split(' ');

            if (splits.Length != 3)
            {
                throw new Exception("Bad Request: " + requestLine);
            }
            foreach (var item in splits)
            {
                if (item.Length == 0)
                {
                    throw new Exception("Bad Request: " + requestLine);
                }
            }
            Method      = splits[0];
            RealUrl     = Url = splits[1];
            HttpVersion = splits[2];
            IsHttp1_1   = HttpVersion == "HTTP/1.1";
            NaiveUtils.SplitUrl(Url, out var path, out Url_qstr);
            RealPathEscaped = path;
            RealPath        = Url_path = HttpUtil.UrlDecode(path);
        }
Beispiel #29
0
        public Task <Msg> RecvMsg(BytesView buf)
        {
            if (PreReadEnabled && recvTasks == null)
            {
                recvTasks = new Task <Msg> [recvStreams.Length];
                for (int i = 0; i < recvStreams.Length; i++)
                {
                    var i2 = i;
                    recvTasks[i] = Task.Run(() => recvStreams[i2].RecvMsg(null));
                }
            }
            if (nextRecv == recvStreams.Length)
            {
                nextRecv = 0;
            }
            var curRecv2 = nextRecv++;

            if (recvTasks != null)
            {
                var task = recvTasks[curRecv2];
                recvTasks[curRecv2] = (!task.IsCompleted)
                    ? NaiveUtils.RunAsyncTask(async(s) => {
                    await s.prevTask;
                    return(await s.curStream.RecvMsg(null));
                }, new recvArgs {
                    prevTask = task, curStream = recvStreams[curRecv2]
                })
                                      //? task.ContinueWith((t, s) => s.CastTo<IMsgStream>().RecvMsg(null), recvStreams[curRecv2], TaskContinuationOptions.ExecuteSynchronously).Unwrap()
                    : recvStreams[curRecv2].RecvMsg(null);
                return(task);
            }
            else
            {
                return(recvStreams[curRecv2].RecvMsg(buf));
            }
        }
Beispiel #30
0
        private void InitAdapters()
        {
            dnsResolver    = null;
            socksInAdapter = null;

            var controller = Bg.Controller;

            if (VpnConfig.Handler == null)
            {
                socksInAdapter = controller.FindAdapter <SocksInAdapter>(VpnConfig.Socks) ?? throw new Exception($"SocksInAdapter '{VpnConfig.Socks}' not found.");
            }
            else
            {
                var existVpn = controller.FindAdapter <NaiveSocks.Adapter>("VPN");
                if (existVpn != null)
                {
                    throw new Exception("adapter 'VPN' already exists.");
                }
                else
                {
                    var handlerRef = controller.AdapterRefFromName(VpnConfig.Handler);
                    if (handlerRef.Adapter == null)
                    {
                        throw new Exception("Handler not found.");
                    }
                    socksInAdapter = new SocksInAdapter()
                    {
                        Name   = "VPN",
                        listen = NaiveUtils.ParseIPEndPoint("127.1:" + VpnConfig.SocksPort),
                        @out   = handlerRef
                    };
                    AddInAdapter(controller, socksInAdapter);
                }
            }
            if (VpnConfig.DnsResolver != null)
            {
                dnsResolver = controller.FindAdapter <NaiveSocks.Adapter>(VpnConfig.DnsResolver) as NaiveSocks.IAdapter;
                if (dnsResolver == null)
                {
                    Logging.warning($"Specified DNS resolver '{VpnConfig.DnsResolver}' is not found!");
                }
            }
            else
            {
                dnsResolver = controller.FindAdapter <NaiveSocks.IAdapter>(VpnConfig.Handler);
            }
            if (VpnConfig.LocalDnsPort > 0 && dnsResolver == null)
            {
                throw new Exception("local dns is enabled but cannot find a dns resolver. Check Handler or DnsResolver in configuration.");
            }
            Logging.info("VPN connections handler: " + socksInAdapter.QuotedName);

            if (VpnConfig.LocalDnsPort > 0)
            {
                InitLocalDns(controller);
            }

            if (VpnConfig.UdpRelay)
            {
                var relay = new UdpRelay()
                {
                    Name         = "VPNUDP",
                    listen       = new IPEndPoint(IPAddress.Loopback, VpnConfig.SocksPort),
                    redirect_dns = new IPEndPoint(IPAddress.Loopback, VpnConfig.LocalDnsPort)
                };
                AddInAdapter(controller, relay);
            }
        }