feat: Initial echo server
This commit is contained in:
7
.editorconfig
Normal file
7
.editorconfig
Normal file
@@ -0,0 +1,7 @@
|
||||
root = true
|
||||
|
||||
[*.swift]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
trim_trailing_whitespace = true
|
||||
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/configuration/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
||||
11
.swiftformat
Normal file
11
.swiftformat
Normal file
@@ -0,0 +1,11 @@
|
||||
--self init-only
|
||||
--indent 2
|
||||
--ifdef indent
|
||||
--trimwhitespace always
|
||||
--wraparguments before-first
|
||||
--wrapparameters before-first
|
||||
--wrapcollections preserve
|
||||
--wrapconditions after-first
|
||||
--typeblanklines preserve
|
||||
--commas inline
|
||||
--stripunusedargs closure-only
|
||||
9
.swiftlint.yml
Normal file
9
.swiftlint.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
disabled_rules:
|
||||
- closing_brace
|
||||
- fuction_body_length
|
||||
|
||||
included:
|
||||
- Sources
|
||||
- Tests
|
||||
|
||||
ignore_multiline_statement_conditions: true
|
||||
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1610"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "nio-echo"
|
||||
BuildableName = "nio-echo"
|
||||
BlueprintName = "nio-echo"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "nio-echo"
|
||||
BuildableName = "nio-echo"
|
||||
BlueprintName = "nio-echo"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "nio-echo"
|
||||
BuildableName = "nio-echo"
|
||||
BlueprintName = "nio-echo"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
42
Package.resolved
Normal file
42
Package.resolved
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"originHash" : "20f1c21ae87f9bea31b5f7dfef662b3911d92dc048f13b9fb09d350230df3c34",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "swift-atomics",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-atomics.git",
|
||||
"state" : {
|
||||
"revision" : "cd142fd2f64be2100422d658e7411e39489da985",
|
||||
"version" : "1.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-collections",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-collections.git",
|
||||
"state" : {
|
||||
"revision" : "671108c96644956dddcd89dd59c203dcdb36cec7",
|
||||
"version" : "1.1.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-nio",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio.git",
|
||||
"state" : {
|
||||
"revision" : "914081701062b11e3bb9e21accc379822621995e",
|
||||
"version" : "2.76.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-system",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-system.git",
|
||||
"state" : {
|
||||
"revision" : "c8a44d836fe7913603e246acab7c528c2e780168",
|
||||
"version" : "1.4.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 3
|
||||
}
|
||||
25
Package.swift
Normal file
25
Package.swift
Normal file
@@ -0,0 +1,25 @@
|
||||
// swift-tools-version: 6.0
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "swift-nio-echo",
|
||||
platforms: [
|
||||
.macOS(.v15)
|
||||
],
|
||||
products: [
|
||||
.executable(name: "nio-echo", targets: ["NIOEcho"])
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/apple/swift-nio.git", from: "2.76.1")
|
||||
],
|
||||
targets: [
|
||||
.executableTarget(
|
||||
name: "NIOEcho",
|
||||
dependencies: [
|
||||
.product(name: "NIO", package: "swift-nio")
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
72
Sources/NioEcho/main.swift
Normal file
72
Sources/NioEcho/main.swift
Normal file
@@ -0,0 +1,72 @@
|
||||
// The Swift Programming Language
|
||||
// https://docs.swift.org/swift-book
|
||||
import NIOCore
|
||||
import NIOPosix
|
||||
|
||||
private final class EchoHandler: ChannelInboundHandler {
|
||||
typealias InboundIn = ByteBuffer
|
||||
typealias OutboundOut = BackPressureHandler
|
||||
|
||||
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
|
||||
context.write(data, promise: nil)
|
||||
}
|
||||
|
||||
func channelReadComplete(context: ChannelHandlerContext) {
|
||||
context.flush()
|
||||
}
|
||||
|
||||
func errorCaught(context: ChannelHandlerContext, error: any Error) {
|
||||
print("error: \(error)")
|
||||
context.close(promise: nil)
|
||||
}
|
||||
}
|
||||
|
||||
let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
|
||||
let bootstrap = ServerBootstrap(group: group)
|
||||
.serverChannelOption(.backlog, value: 256)
|
||||
.serverChannelOption(.socketOption(.so_reuseaddr), value: 1)
|
||||
// set the handlers that are applied.
|
||||
.childChannelInitializer { channel in
|
||||
channel.eventLoop.makeCompletedFuture {
|
||||
try channel.pipeline.syncOperations.addHandler(BackPressureHandler())
|
||||
try channel.pipeline.syncOperations.addHandler(EchoHandler())
|
||||
}
|
||||
}
|
||||
.childChannelOption(.socketOption(.so_reuseaddr), value: 1)
|
||||
.childChannelOption(.maxMessagesPerRead, value: 16)
|
||||
.childChannelOption(.recvAllocator, value: AdaptiveRecvByteBufferAllocator())
|
||||
|
||||
defer { try? group.syncShutdownGracefully() }
|
||||
|
||||
// First argument is the program path
|
||||
let arguments = CommandLine.arguments
|
||||
let arg1 = arguments.dropFirst().first
|
||||
let arg2 = arguments.dropFirst(2).first
|
||||
|
||||
let defaultHost = "::1"
|
||||
let defaultPort = 9999
|
||||
|
||||
struct BindTo {
|
||||
let host: String
|
||||
let port: Int
|
||||
}
|
||||
|
||||
let bindTarget: BindTo
|
||||
switch (arg1, arg1.flatMap(Int.init), arg2.flatMap(Int.init)) {
|
||||
case let (_, .some(port), _):
|
||||
bindTarget = .init(host: defaultHost, port: port)
|
||||
case let (.some(host), _, .some(port)):
|
||||
bindTarget = .init(host: host, port: port)
|
||||
case let (.some(host), .none, .none):
|
||||
bindTarget = .init(host: host, port: defaultPort)
|
||||
default:
|
||||
bindTarget = .init(host: defaultHost, port: defaultPort)
|
||||
}
|
||||
|
||||
let channel = try bootstrap.bind(host: bindTarget.host, port: bindTarget.port).wait()
|
||||
|
||||
print("Server started and listening on: \(channel.localAddress!)")
|
||||
|
||||
try channel.closeFuture.wait()
|
||||
|
||||
print("Server closed!")
|
||||
Reference in New Issue
Block a user