添加项目文件。
This commit is contained in:
parent
5b39a543fd
commit
553b7f8c07
25
FastGithub.sln
Normal file
25
FastGithub.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31320.298
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGithub", "FastGithub\FastGithub.csproj", "{C1099390-6103-4917-A740-A3002B542FE0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C1099390-6103-4917-A740-A3002B542FE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C1099390-6103-4917-A740-A3002B542FE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C1099390-6103-4917-A740-A3002B542FE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C1099390-6103-4917-A740-A3002B542FE0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {AC66D417-C355-4DFD-BC3C-DD0383F855D3}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
20
FastGithub/FastGithub.csproj
Normal file
20
FastGithub/FastGithub.csproj
Normal file
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Nullable>enable</Nullable>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="meta.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
66
FastGithub/GithubBuilder.cs
Normal file
66
FastGithub/GithubBuilder.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示中间件创建者
|
||||
/// </summary>
|
||||
sealed class GithubBuilder : IGithubBuilder
|
||||
{
|
||||
private readonly GithubDelegate completedHandler;
|
||||
private readonly List<Func<GithubDelegate, GithubDelegate>> middlewares = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取服务提供者
|
||||
/// </summary>
|
||||
public IServiceProvider AppServices { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 中间件创建者
|
||||
/// </summary>
|
||||
/// <param name="appServices"></param>
|
||||
public GithubBuilder(IServiceProvider appServices)
|
||||
: this(appServices, context => Task.CompletedTask)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 中间件创建者
|
||||
/// </summary>
|
||||
/// <param name="appServices"></param>
|
||||
/// <param name="completedHandler">完成执行内容处理者</param>
|
||||
public GithubBuilder(IServiceProvider appServices, GithubDelegate completedHandler)
|
||||
{
|
||||
this.AppServices = appServices;
|
||||
this.completedHandler = completedHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用中间件
|
||||
/// </summary>
|
||||
/// <param name="middleware"></param>
|
||||
/// <returns></returns>
|
||||
public IGithubBuilder Use(Func<GithubDelegate, GithubDelegate> middleware)
|
||||
{
|
||||
this.middlewares.Add(middleware);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建所有中间件执行处理者
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public GithubDelegate Build()
|
||||
{
|
||||
var handler = this.completedHandler;
|
||||
for (var i = this.middlewares.Count - 1; i >= 0; i--)
|
||||
{
|
||||
handler = this.middlewares[i](handler);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
FastGithub/GithubBuilderExtensions.cs
Normal file
36
FastGithub/GithubBuilderExtensions.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
/// <summary>
|
||||
/// 中间件创建者扩展
|
||||
/// </summary>
|
||||
static class GithubBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用中间件
|
||||
/// </summary>
|
||||
/// <typeparam name="TMiddleware"></typeparam>
|
||||
/// <param name="builder"></param>
|
||||
/// <returns></returns>
|
||||
public static IGithubBuilder Use<TMiddleware>(this IGithubBuilder builder) where TMiddleware : class, IGithubMiddleware
|
||||
{
|
||||
return builder.AppServices.GetService(typeof(TMiddleware)) is TMiddleware middleware
|
||||
? builder.Use(middleware.InvokeAsync)
|
||||
: throw new InvalidOperationException($"无法获取服务{typeof(TMiddleware)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用中间件
|
||||
/// </summary>
|
||||
/// <typeparam name="TContext"></typeparam>
|
||||
/// <param name="builder"></param>
|
||||
/// <param name="middleware"></param>
|
||||
/// <returns></returns>
|
||||
public static IGithubBuilder Use(this IGithubBuilder builder, Func<GithubContext, Func<Task>, Task> middleware)
|
||||
{
|
||||
return builder.Use(next => context => middleware(context, () => next(context)));
|
||||
}
|
||||
}
|
||||
}
|
||||
14
FastGithub/GithubContext.cs
Normal file
14
FastGithub/GithubContext.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
class GithubContext
|
||||
{
|
||||
[AllowNull]
|
||||
public IPAddress Address { get; set; }
|
||||
|
||||
public TimeSpan? HttpElapsed { get; set; }
|
||||
}
|
||||
}
|
||||
11
FastGithub/GithubDelegate.cs
Normal file
11
FastGithub/GithubDelegate.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示所有中间件执行委托
|
||||
/// </summary>
|
||||
/// <param name="context">中间件上下文</param>
|
||||
/// <returns></returns>
|
||||
delegate Task GithubDelegate(GithubContext context);
|
||||
}
|
||||
68
FastGithub/GithubHostedService.cs
Normal file
68
FastGithub/GithubHostedService.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using FastGithub.Middlewares;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
sealed class GithubHostedService : BackgroundService
|
||||
{
|
||||
private readonly GithubDelegate githubDelegate;
|
||||
private readonly ILogger<GithubHostedService> logger;
|
||||
|
||||
public GithubHostedService(
|
||||
IServiceProvider appServiceProvider,
|
||||
ILogger<GithubHostedService> logger)
|
||||
{
|
||||
this.githubDelegate = new GithubBuilder(appServiceProvider, ctx => Task.CompletedTask)
|
||||
.Use<ConcurrentMiddleware>()
|
||||
.Use<PortScanMiddleware>()
|
||||
.Use<HttpTestMiddleware>()
|
||||
.Build();
|
||||
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
using var stream = File.OpenRead("meta.json");
|
||||
var meta = await JsonSerializer.DeserializeAsync<Meta>(stream, cancellationToken: stoppingToken);
|
||||
|
||||
if (meta != null)
|
||||
{
|
||||
var contexts = new List<GithubContext>();
|
||||
var tasks = this.GetScanTasks(meta, contexts);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
var orderByContexts = contexts
|
||||
.Where(item => item.HttpElapsed != null)
|
||||
.OrderBy(item => item.HttpElapsed);
|
||||
|
||||
foreach (var context in orderByContexts)
|
||||
{
|
||||
this.logger.LogInformation($"{context.Address} {context.HttpElapsed}");
|
||||
}
|
||||
}
|
||||
this.logger.LogInformation("扫描结束");
|
||||
}
|
||||
|
||||
private IEnumerable<Task> GetScanTasks(Meta meta, IList<GithubContext> contexts)
|
||||
{
|
||||
foreach (var address in meta.ToIPv4Address())
|
||||
{
|
||||
var context = new GithubContext
|
||||
{
|
||||
Address = address,
|
||||
};
|
||||
contexts.Add(context);
|
||||
yield return this.githubDelegate(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
FastGithub/IGithubBuilder.cs
Normal file
28
FastGithub/IGithubBuilder.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义中间件管道创建者的接口
|
||||
/// </summary>
|
||||
interface IGithubBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取服务提供者
|
||||
/// </summary>
|
||||
IServiceProvider AppServices { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用中间件
|
||||
/// </summary>
|
||||
/// <param name="middleware">中间件</param>
|
||||
/// <returns></returns>
|
||||
IGithubBuilder Use(Func<GithubDelegate, GithubDelegate> middleware);
|
||||
|
||||
/// <summary>
|
||||
/// 创建所有中间件执行处理者
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
GithubDelegate Build();
|
||||
}
|
||||
}
|
||||
19
FastGithub/IGithubMiddleware.cs
Normal file
19
FastGithub/IGithubMiddleware.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义中间件的接口
|
||||
/// </summary>
|
||||
interface IGithubMiddleware
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行中间件
|
||||
/// </summary>
|
||||
/// <param name="context">上下文</param>
|
||||
/// <param name="next">下一个中间件</param>
|
||||
/// <returns></returns>
|
||||
Task InvokeAsync(GithubContext context, Func<Task> next);
|
||||
}
|
||||
}
|
||||
78
FastGithub/IPv4CIDR.cs
Normal file
78
FastGithub/IPv4CIDR.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
sealed class IPv4CIDR
|
||||
{
|
||||
public IPAddress IPAddress { get; }
|
||||
|
||||
public int Mask { get; }
|
||||
|
||||
public int Size { get; }
|
||||
|
||||
public IPv4CIDR(IPAddress ipAddress, int mask)
|
||||
{
|
||||
this.IPAddress = ipAddress;
|
||||
this.Mask = mask;
|
||||
this.Size = (int)(uint.MaxValue << mask >> mask);
|
||||
}
|
||||
|
||||
public IEnumerable<IPAddress> GetAllIPAddress()
|
||||
{
|
||||
for (var i = 0; i < this.Size; i++)
|
||||
{
|
||||
yield return Add(this.IPAddress, i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加值
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
private static IPAddress Add(IPAddress ip, int value)
|
||||
{
|
||||
var span = ip.GetAddressBytes().AsSpan();
|
||||
var hostValue = BinaryPrimitives.ReadInt32BigEndian(span);
|
||||
BinaryPrimitives.WriteInt32BigEndian(span, hostValue + value);
|
||||
return new IPAddress(span);
|
||||
}
|
||||
|
||||
public static bool TryParse(ReadOnlySpan<char> cidr, [MaybeNullWhen(false)] out IPv4CIDR value)
|
||||
{
|
||||
value = null;
|
||||
var index = cidr.IndexOf('/');
|
||||
if (index <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var addressSpan = cidr.Slice(0, index);
|
||||
if (IPAddress.TryParse(addressSpan, out var address) == false
|
||||
|| address.AddressFamily != AddressFamily.InterNetwork)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var maskSpan = cidr.Slice(index + 1);
|
||||
if (int.TryParse(maskSpan, out var mask) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = new IPv4CIDR(address, mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{this.IPAddress}/{this.Mask}";
|
||||
}
|
||||
}
|
||||
}
|
||||
54
FastGithub/Meta.cs
Normal file
54
FastGithub/Meta.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
class Meta
|
||||
{
|
||||
[JsonPropertyName("hooks")]
|
||||
public string[] Hooks { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("web")]
|
||||
public string[] Web { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("api")]
|
||||
public string[] Api { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("git")]
|
||||
public string[] Git { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("packages")]
|
||||
public string[] Packages { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("pages")]
|
||||
public string[] Pages { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("importer")]
|
||||
public string[] Importer { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("actions")]
|
||||
public string[] Actions { get; set; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("dependabot")]
|
||||
public string[] Dependabot { get; set; } = Array.Empty<string>();
|
||||
|
||||
|
||||
public IEnumerable<IPAddress> ToIPv4Address()
|
||||
{
|
||||
var cidrs = this.Web.Concat(this.Api);
|
||||
foreach (var cidr in cidrs)
|
||||
{
|
||||
if (IPv4CIDR.TryParse(cidr, out var value))
|
||||
{
|
||||
foreach (var ip in value.GetAllIPAddress())
|
||||
{
|
||||
yield return ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
FastGithub/Middlewares/ConcurrentMiddleware.cs
Normal file
24
FastGithub/Middlewares/ConcurrentMiddleware.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Middlewares
|
||||
{
|
||||
sealed class ConcurrentMiddleware : IGithubMiddleware
|
||||
{
|
||||
private readonly SemaphoreSlim semaphoreSlim = new(50);
|
||||
|
||||
public async Task InvokeAsync(GithubContext context, Func<Task> next)
|
||||
{
|
||||
try
|
||||
{
|
||||
await this.semaphoreSlim.WaitAsync();
|
||||
await next();
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.semaphoreSlim.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
52
FastGithub/Middlewares/HttpTestMiddleware.cs
Normal file
52
FastGithub/Middlewares/HttpTestMiddleware.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Middlewares
|
||||
{
|
||||
sealed class HttpTestMiddleware : IGithubMiddleware
|
||||
{
|
||||
private readonly TimeSpan timeout = TimeSpan.FromSeconds(5d);
|
||||
private readonly ILogger<HttpTestMiddleware> logger;
|
||||
|
||||
public HttpTestMiddleware(ILogger<HttpTestMiddleware> logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(GithubContext context, Func<Task> next)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new HttpRequestMessage
|
||||
{
|
||||
Method = HttpMethod.Get,
|
||||
RequestUri = new Uri($"https://{context.Address}/manifest.json"),
|
||||
};
|
||||
request.Headers.Host = "github.com";
|
||||
|
||||
using var httpClient = new HttpClient(new HttpClientHandler
|
||||
{
|
||||
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
|
||||
});
|
||||
|
||||
var startTime = DateTime.Now;
|
||||
using var cancellationTokenSource = new CancellationTokenSource(this.timeout);
|
||||
var response = await httpClient.SendAsync(request, cancellationTokenSource.Token);
|
||||
var media = response.EnsureSuccessStatusCode().Content.Headers.ContentType?.MediaType;
|
||||
|
||||
if (string.Equals(media, "application/manifest+json"))
|
||||
{
|
||||
context.HttpElapsed = DateTime.Now.Subtract(startTime);
|
||||
await next();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.logger.LogInformation($"{context.Address} {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
FastGithub/Middlewares/PortScanMiddleware.cs
Normal file
35
FastGithub/Middlewares/PortScanMiddleware.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Middlewares
|
||||
{
|
||||
sealed class PortScanMiddleware : IGithubMiddleware
|
||||
{
|
||||
private readonly TimeSpan timeout = TimeSpan.FromSeconds(1d);
|
||||
private readonly ILogger<PortScanMiddleware> logger;
|
||||
|
||||
public PortScanMiddleware(ILogger<PortScanMiddleware> logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(GithubContext context, Func<Task> next)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
using var cancellationTokenSource = new CancellationTokenSource(this.timeout);
|
||||
await socket.ConnectAsync(context.Address, 443, cancellationTokenSource.Token);
|
||||
|
||||
await next();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.logger.LogInformation($"{context.Address}的443端口未开放");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
FastGithub/Program.cs
Normal file
39
FastGithub/Program.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using FastGithub.Middlewares;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// 程序入口
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建host
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||
{
|
||||
return Host
|
||||
.CreateDefaultBuilder(args)
|
||||
.ConfigureServices((ctx, services) =>
|
||||
{
|
||||
services
|
||||
.AddSingleton<PortScanMiddleware>()
|
||||
.AddSingleton<HttpTestMiddleware>()
|
||||
.AddSingleton<ConcurrentMiddleware>()
|
||||
.AddHostedService<GithubHostedService>()
|
||||
;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
1977
FastGithub/meta.json
Normal file
1977
FastGithub/meta.json
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user