diff --git a/Package.swift b/Package.swift index dc3b90f4..0707fe62 100644 --- a/Package.swift +++ b/Package.swift @@ -110,8 +110,12 @@ var targets: [PackageDescription.Target] = [ .target( name: "CNIOExtrasZlib", dependencies: [], + cSettings: [ + .define("_CRT_SECURE_NO_WARNINGS", .when(platforms: [.windows])), + ], linkerSettings: [ - .linkedLibrary("z") + .linkedLibrary("z", .when(platforms: [.linux, .macOS, .iOS, .tvOS, .watchOS, .visionOS])), + .linkedLibrary("zlib", .when(platforms: [.windows])), ] ), .testTarget( diff --git a/Sources/HTTPServerWithQuiescingDemo/main.swift b/Sources/HTTPServerWithQuiescingDemo/main.swift index 23e0d0ef..41c14585 100644 --- a/Sources/HTTPServerWithQuiescingDemo/main.swift +++ b/Sources/HTTPServerWithQuiescingDemo/main.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#if !os(Windows) import Dispatch import NIOCore import NIOExtras @@ -133,3 +134,6 @@ private func runServer() throws { } try runServer() +#else +print("This demo is not supported on Windows.") +#endif \ No newline at end of file diff --git a/Sources/NIOExtras/DebugInboundEventsHandler.swift b/Sources/NIOExtras/DebugInboundEventsHandler.swift index 1c322635..b1a55374 100644 --- a/Sources/NIOExtras/DebugInboundEventsHandler.swift +++ b/Sources/NIOExtras/DebugInboundEventsHandler.swift @@ -19,6 +19,8 @@ import Darwin @preconcurrency import Musl #elseif canImport(Android) @preconcurrency import Android +#elseif canImport(ucrt) +@preconcurrency import ucrt #else @preconcurrency import Glibc #endif @@ -175,6 +177,10 @@ public class DebugInboundEventsHandler: ChannelInboundHandler { message = "Channel caught error: \(error)" } print(message + " in \(context.name)") + + #if os(Windows) + let stdout = __acrt_iob_func(1) + #endif fflush(stdout) } } diff --git a/Sources/NIOExtras/DebugOutboundEventsHandler.swift b/Sources/NIOExtras/DebugOutboundEventsHandler.swift index b3a1f7eb..1f16f070 100644 --- a/Sources/NIOExtras/DebugOutboundEventsHandler.swift +++ b/Sources/NIOExtras/DebugOutboundEventsHandler.swift @@ -20,6 +20,8 @@ import Darwin @preconcurrency import Musl #elseif canImport(Android) @preconcurrency import Android +#elseif canImport(ucrt) +@preconcurrency import ucrt #else @preconcurrency import Glibc #endif @@ -171,6 +173,9 @@ public class DebugOutboundEventsHandler: ChannelOutboundHandler { message = "Triggering user outbound event: { \(event) }" } print(message + " in \(context.name)") + #if os(Windows) + let stdout = __acrt_iob_func(1) + #endif fflush(stdout) } } diff --git a/Sources/NIOExtras/WritePCAPHandler.swift b/Sources/NIOExtras/WritePCAPHandler.swift index 25d12d05..2e02cac3 100644 --- a/Sources/NIOExtras/WritePCAPHandler.swift +++ b/Sources/NIOExtras/WritePCAPHandler.swift @@ -22,6 +22,27 @@ import Darwin import Musl #elseif canImport(Android) import Android +#elseif canImport(ucrt) +import ucrt +import WinSDK + +fileprivate func gettimeofday(_ tp: inout timeval, _ tzp: Never?) { + var file_time = FILETIME() + var system_time = SYSTEMTIME() + var time: UInt64 = 0 + + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + let epoch: UInt64 = 116444736000000000 + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + time = UInt64(file_time.dwLowDateTime) + time += UInt64(file_time.dwHighDateTime) << 32 + + tp.tv_sec = Int32((time - epoch) / 10000000) + tp.tv_usec = Int32(system_time.wMilliseconds * 1000) +} #else import Glibc #endif @@ -614,8 +635,13 @@ extension ByteBuffer { self.writeInteger(.max, as: UInt8.self) // TTL, `.max` as we don't care about the TTL self.writeInteger(6, as: UInt8.self) // TCP self.writeInteger(0, as: UInt16.self) // checksum + #if os(Windows) + self.writeInteger(la.address.sin_addr.S_un.S_addr, endianness: .host, as: UInt32.self) + self.writeInteger(ra.address.sin_addr.S_un.S_addr, endianness: .host, as: UInt32.self) + #else self.writeInteger(la.address.sin_addr.s_addr, endianness: .host, as: UInt32.self) self.writeInteger(ra.address.sin_addr.s_addr, endianness: .host, as: UInt32.self) + #endif case .v6(let la, let ra): let ipv6PayloadLength = tcpLength let recordLength = ipv6PayloadLength + 4 + 40 // IPv6 header length (+4 gives 32 bits for protocol id) @@ -724,6 +750,15 @@ extension NIOWritePCAPHandler { fileWritingMode: FileWritingMode = .createNewPCAPFile, errorHandler: @escaping (Swift.Error) -> Void ) throws -> SynchronizedFileSink { + #if os(Windows) + let fd = try path.withCString(encodedAs: UTF16.self) { pathPtr -> CInt in + let fd = _wsopen_s(nil, pathPtr, _O_WRONLY | (fileWritingMode == FileWritingMode.createNewPCAPFile ? (_O_TRUNC | _O_CREAT) : _O_APPEND), _SH_DENYNO, _S_IREAD | _S_IWRITE) + guard fd >= 0 else { + throw SynchronizedFileSink.Error(errorCode: Error.ErrorCode.cannotOpenFileError.rawValue) + } + return fd + } + #else let oflag: CInt = fileWritingMode == FileWritingMode.createNewPCAPFile ? (O_TRUNC | O_CREAT) : O_APPEND let fd = try path.withCString { pathPtr -> CInt in let fd = open(pathPtr, O_WRONLY | oflag, 0o600) @@ -732,10 +767,16 @@ extension NIOWritePCAPHandler { } return fd } + #endif if fileWritingMode == .createNewPCAPFile { let writeOk = NIOWritePCAPHandler.pcapFileHeader.withUnsafeReadableBytes { ptr in - sysWrite(fd, ptr.baseAddress, ptr.count) == ptr.count + #if os(Windows) + let size = UInt32(ptr.count) + #else + let size = ptr.count + #endif + return sysWrite(fd, ptr.baseAddress, size) == size } guard writeOk else { throw SynchronizedFileSink.Error(errorCode: Error.ErrorCode.cannotWriteToFileError.rawValue) @@ -794,12 +835,17 @@ extension NIOWritePCAPHandler { var buffer = buffer while buffer.readableBytes > 0 { try buffer.readWithUnsafeReadableBytes { dataPtr in - let r = sysWrite(fd, dataPtr.baseAddress, dataPtr.count) - assert(r != 0, "write returned 0 but we tried to write \(dataPtr.count) bytes") + #if os(Windows) + let size = UInt32(dataPtr.count) + #else + let size = dataPtr.count + #endif + let r = sysWrite(fd, dataPtr.baseAddress, size) + assert(r != 0, "write returned 0 but we tried to write \(size) bytes") guard r > 0 else { throw Error.init(errorCode: Error.ErrorCode.cannotWriteToFileError.rawValue) } - return r + return Int(r) } } } diff --git a/Sources/NIOHTTPCompression/HTTPCompression.swift b/Sources/NIOHTTPCompression/HTTPCompression.swift index f6968715..d85d090d 100644 --- a/Sources/NIOHTTPCompression/HTTPCompression.swift +++ b/Sources/NIOHTTPCompression/HTTPCompression.swift @@ -107,7 +107,7 @@ public enum NIOCompression: Sendable { // some compression algorithms and so it should be used only when necessary. This completes the current deflate block and // follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes // (00 00 ff ff). - let bufferSize = Int(deflateBound(&stream, UInt(inputBuffer.readableBytes))) + let bufferSize = Int(deflateBound(&stream, .init(inputBuffer.readableBytes))) var outputBuffer = allocator.buffer(capacity: bufferSize + 5) stream.oneShotDeflate(from: &inputBuffer, to: &outputBuffer, flag: flags) return outputBuffer diff --git a/Sources/NIOSOCKS/Messages/SOCKSRequest.swift b/Sources/NIOSOCKS/Messages/SOCKSRequest.swift index c507e858..63d34b9f 100644 --- a/Sources/NIOSOCKS/Messages/SOCKSRequest.swift +++ b/Sources/NIOSOCKS/Messages/SOCKSRequest.swift @@ -21,6 +21,9 @@ import Darwin import Musl #elseif canImport(Android) import Android +#elseif os(Windows) +import ucrt +import WinSDK #else import Glibc #endif