Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tanner0101 committed Sep 27, 2018
0 parents commit 8c992df
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
DerivedData
Package.resolved
17 changes: 17 additions & 0 deletions Package.swift
@@ -0,0 +1,17 @@
// swift-tools-version:4.2
import PackageDescription

let package = Package(
name: "nio-postgres",
products: [
.library(name: "NIOPostgres", targets: ["NIOPostgres"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "1.0.0"),
],
targets: [
.target(name: "NIOPostgres", dependencies: ["NIO", "NIOOpenSSL"]),
.testTarget(name: "NIOPostgresTests", dependencies: ["NIOPostgres"]),
]
)
3 changes: 3 additions & 0 deletions README.md
@@ -0,0 +1,3 @@
# nio-postgres

A description of this package.
1 change: 1 addition & 0 deletions Sources/NIOPostgres/PostgresConnection.swift
@@ -0,0 +1 @@
public final class PostgresConnection { }
158 changes: 158 additions & 0 deletions Sources/NIOPostgres/PostgresMessage+Identifier.swift
@@ -0,0 +1,158 @@
extension PostgresMessage {
/// Identifies an incoming or outgoing postgres message. Sent as the first byte, before the message size.
/// Values are not unique across all identifiers, meaning some messages will require keeping state to identify.
struct Identifier: ExpressibleByIntegerLiteral {
/// AuthenticationOk (B)
static let authenticationOk: Identifier = 0x52 // 'R'

/// AuthenticationKerberosV5 (B)
static let authenticationKerberosV5: Identifier = 0x52 // 'R'

/// AuthenticationCleartextPassword (B)
static let authenticationCleartextPassword: Identifier = 0x52 // 'R'

/// AuthenticationMD5Password (B)
static let authenticationMD5Password: Identifier = 0x52 // 'R'

/// AuthenticationSCMCredential (B)
static let authenticationSCMCredential: Identifier = 0x52 // 'R'

/// AuthenticationGSS (B)
static let authenticationGSS: Identifier = 0x52 // 'R'

/// AuthenticationSSPI (B)
static let authenticationSSPI: Identifier = 0x52 // 'R'

/// AuthenticationGSSContinue (B)
static let authenticationGSSContinue: Identifier = 0x52 // 'R'

/// AuthenticationSASL (B)
static let authenticationSASL: Identifier = 0x52 // 'R'

/// AuthenticationSASLContinue (B)
static let authenticationSASLContinue: Identifier = 0x52 // 'R'

/// AuthenticationSASLFinal (B)
static let authenticationSASLFinal: Identifier = 0x52 // 'R'

/// BackendKeyData (B)
static let backendKeyData: Identifier = 0x4B // 'K'

/// Bind (F)
static let bind: Identifier = 0x42 // 'B'

/// BindComplete (B)
static let bindComplete: Identifier = 0x32 // '2'

/// Close (F)
static let close: Identifier = 0x43 // 'C'

/// CloseComplete (B)
static let closeComplete: Identifier = 0x33 // '3'

/// CommandComplete (B)
static let commandComplete: Identifier = 0x43 // 'C'

/// CopyData (F & B)
static let copyData: Identifier = 0x64 // 'd'

/// CopyDone (F & B)
static let copyDone: Identifier = 0x63 // 'c'

/// CopyFail (F)
static let copyFail: Identifier = 0x66 // 'f'

/// CopyInResponse (B)
static let copyInResponse: Identifier = 0x47 // 'G'

/// CopyOutResponse (B)
static let copyOutResponse: Identifier = 0x48 // 'H'

// CopyBothResponse (B)
static let copyBothResponse: Identifier = 0x57 // 'W'

/// DataRow (B)
static let dataRow: Identifier = 0x44 // 'D'

/// Describe (F)
static let describe: Identifier = 0x44 // 'D'

/// EmptyQueryResponse (B)
static let emptyQueryResponse: Identifier = 0x49 // 'I'

/// ErrorResponse (B)
static let errorResponse: Identifier = 0x45 // 'E'

/// Execute (F)
static let execute: Identifier = 0x45 // 'E'

/// Flush (F)
static let flush: Identifier = 0x48 // 'H'

/// FunctionCall (F)
static let functionCall: Identifier = 0x46 // 'F'

/// FunctionCallResponse (B)
static let functionCallResponse: Identifier = 0x56 // 'V'

/// GSSResponse (F)
static let gssResponse: Identifier = 0x70 // 'p'

/// NegotiateProtocolVersion (B)
static let negotiateProtocolVersion: Identifier = 0x76 // 'v'

/// NoData (B)
static let noData: Identifier = 0x6E // 'n'

/// NoticeResponse (B)
static let noticeResponse: Identifier = 0x4E // 'N'

/// NotificationResponse (B)
static let notificationResponse: Identifier = 0x41 // 'A'

/// ParameterDescription (B)
static let parameterDescription: Identifier = 0x74 // 't'

/// ParameterStatus (B)
static let parameterStatus: Identifier = 0x53 // 'S'

/// Parse (F)
static let parse: Identifier = 0x50 // 'P'

/// ParseComplete (B)
static let parseComplete: Identifier = 0x31 // '1'

/// PasswordMessage (F)
static let passwordMessage: Identifier = 0x70 // 'p'

/// PortalSuspended (B)
static let portalSuspended: Identifier = 0x73 // 's'

/// Query (F)
static let query: Identifier = 0x51 // 'Q'

/// ReadyForQuery (B)
static let readyForQuery: Identifier = 0x5A // 'Z'

/// RowDescription (B)
static let rowDescription: Identifier = 0x54 // 'T'

/// SASLInitialResponse (F)
static let saslInitialResponse: Identifier = 0x70 // 'p'

/// SASLResponse (F)
static let saslResponse: Identifier = 0x70 // 'p'

/// Sync (F)
static let sync: Identifier = 0x53 // 'S'

/// Terminate (F)
static let terminate: Identifier = 0x58 // 'X'

let value: UInt8

init(integerLiteral value: UInt8) {
self.value = value
}
}
}
1 change: 1 addition & 0 deletions Sources/NIOPostgres/PostgresMessage.swift
@@ -0,0 +1 @@
enum PostgresMessage { }
40 changes: 40 additions & 0 deletions Sources/NIOPostgres/PostgresMessageDecoder.swift
@@ -0,0 +1,40 @@
import NIO

/// Decodes `PostgresMessage`s from incoming data.
final class PostgresMessageDecoder: ByteToMessageDecoder {
/// See `ByteToMessageDecoder`.
var cumulationBuffer: ByteBuffer?

/// If `true`, the server has asked for authentication.
var hasRequestedAuthentication: Bool

/// Creates a new `PostgresMessageDecoder`.
init() {
self.hasRequestedAuthentication = false
}

/// See `ByteToMessageDecoder`.
func decode(ctx: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState {
// peek at the message identifier
// the message identifier is always the first byte of a message
guard let messageIdentifier = buffer.getInteger(at: buffer.readerIndex, as: UInt8.self).map(PostgresMessage.Identifier.init) else {
return .needMoreData
}

#warning("check for TLS support")

// peek at the message size
// the message size is always a 4 byte integer appearing immediately after the message identifier
guard let messageSize = buffer.getInteger(at: buffer.readerIndex + 1, as: Int32.self).flatMap(Int.init) else {
return .needMoreData
}

// ensure message is large enough (skipping message type) or reject
guard buffer.readableBytes - 1 >= messageSize else {
return .needMoreData
}

// skip message identifier and message size
buffer.moveReaderIndex(forwardBy: 1 + 4)
}
}
7 changes: 7 additions & 0 deletions Tests/LinuxMain.swift
@@ -0,0 +1,7 @@
import XCTest

import nio_postgresTests

var tests = [XCTestCaseEntry]()
tests += nio_postgresTests.allTests()
XCTMain(tests)
9 changes: 9 additions & 0 deletions Tests/NIOPostgresTests/XCTestManifests.swift
@@ -0,0 +1,9 @@
import XCTest

#if !os(macOS)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(nio_postgresTests.allTests),
]
}
#endif
15 changes: 15 additions & 0 deletions Tests/NIOPostgresTests/nio_postgresTests.swift
@@ -0,0 +1,15 @@
import XCTest
@testable import nio_postgres

final class nio_postgresTests: XCTestCase {
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
XCTAssertEqual(nio_postgres().text, "Hello, World!")
}

static var allTests = [
("testExample", testExample),
]
}
27 changes: 27 additions & 0 deletions docker-compose.yml
@@ -0,0 +1,27 @@
version: '2'

services:
psql-10:
image: postgres:10
environment:
POSTGRES_USER: vapor_username
POSTGRES_DB: vapor_database
POSTGRES_PASSWORD: vapor_password
ports:
- 5432:5432
psql-9:
image: postgres:9
environment:
POSTGRES_USER: vapor_username
POSTGRES_DB: vapor_database
POSTGRES_PASSWORD: vapor_password
ports:
- 5432:5432
psql-ssl:
image: scenecheck/postgres-ssl:latest
environment:
POSTGRES_USER: vapor_username
POSTGRES_DB: vapor_database
POSTGRES_PASSWORD: vapor_password
ports:
- 5432:5432

0 comments on commit 8c992df

Please sign in to comment.