├── Public └── .gitkeep ├── cloud.yml ├── Config ├── app.json ├── mysql.json ├── crypto.json ├── server.json ├── fluent.json └── droplet.json ├── Sources └── App │ ├── Controller │ ├── GroupController.swift │ ├── MessageController.swift │ ├── SessionController.swift │ └── GobangController.swift │ ├── Server │ ├── ServerProtocol.swift │ ├── ServerRouteTool.swift │ ├── AudioServer.swift │ ├── LoginServer.swift │ ├── GobangServer.swift │ └── MessageServer.swift │ ├── Category │ ├── Dictionary+Ext.swift │ ├── String+Extension.swift │ ├── Int+Extension.swift │ ├── ModelProtocol.swift │ ├── DataInputStream.swift │ └── DataOutputStream.swift │ ├── Middleware │ ├── InterfaceDefine.swift │ └── TokenMiddleware.swift │ ├── Config+Setup.swift │ ├── Model │ ├── Member.swift │ ├── Group.swift │ ├── GameMember.swift │ ├── Session.swift │ ├── Message.swift │ └── GameRoom.swift │ ├── main.swift │ └── Protobuf │ ├── IM.Audio.pb.swift │ ├── G.Gobang.pb.swift │ ├── IM.Login.pb.swift │ ├── IM.BaseDefine.pb.swift │ └── IM.Message.pb.swift ├── Tests ├── LinuxMain.swift └── AppTests │ ├── Utilities.swift │ ├── RouteTests.swift │ └── PostControllerTests.swift ├── .circleci └── config.yml ├── Package.swift ├── .travis.yml ├── README.md └── license /Public/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cloud.yml: -------------------------------------------------------------------------------- 1 | swift_version: "4.0.0" 2 | -------------------------------------------------------------------------------- /Config/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": "foo-bar" 3 | } 4 | -------------------------------------------------------------------------------- /Config/mysql.json: -------------------------------------------------------------------------------- 1 | { 2 | "hostname": "", 3 | "user": "", 4 | "password": "", 5 | "database": "", 6 | "encoding": "utf8mb4", 7 | "port": "3306" 8 | } 9 | -------------------------------------------------------------------------------- /Sources/App/Controller/GroupController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GroupController.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2018/1/1. 6 | // 7 | 8 | import Foundation 9 | 10 | struct GroupController { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Sources/App/Controller/MessageController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageController.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2018/1/1. 6 | // 7 | 8 | import Foundation 9 | 10 | struct MessageController { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Sources/App/Controller/SessionController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SessionController.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2017/12/31. 6 | // 7 | 8 | import Foundation 9 | 10 | struct SessionController { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | #if os(Linux) 2 | 3 | import XCTest 4 | @testable import AppTests 5 | 6 | XCTMain([ 7 | // AppTests 8 | testCase(PostControllerTests.allTests), 9 | testCase(RouteTests.allTests) 10 | ]) 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /Sources/App/Server/ServerProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServerProtocol.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2017/12/31. 6 | // 7 | import Foundation 8 | import Vapor 9 | protocol ServerProrocol { 10 | func registered() 11 | func route(_ header: apiHeader,_ ws: WebSocket, _ contentData: Data) 12 | } 13 | -------------------------------------------------------------------------------- /Config/crypto.json: -------------------------------------------------------------------------------- 1 | { 2 | "hash": { 3 | "method": "sha256", 4 | "encoding": "hex", 5 | "key": "0000000000000123" 6 | }, 7 | 8 | "cipher": { 9 | "method": "aes256", 10 | "encoding": "base64", 11 | "key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANIU=" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/App/Category/Dictionary+Ext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dic.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2017/10/8. 6 | // 7 | 8 | 9 | import Foundation 10 | 11 | extension Dictionary { 12 | mutating func merge(_ sequence: S) where S.Iterator.Element == (key:Key,value:Value) { 13 | sequence.forEach{ self[$0]=$1 } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /Config/server.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "The $PORT:8080 call tells the json file to see if there", 3 | "//": "is any value at the 'PORT' environment variable.", 4 | "//": "If there is no value there, it will fallback to '8080'", 5 | "port": "$PORT:12138", 6 | 7 | "host": "0.0.0.0", 8 | 9 | "//": "It's very rare that a server manages its own TLS.", 10 | "//": "More commonly, vapor is served behind a proxy like nginx.", 11 | "securityLayer": "none" 12 | } 13 | -------------------------------------------------------------------------------- /Sources/App/Category/String+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String(md5).swift 3 | // NHServer 4 | // 5 | // Created by niuhui on 2017/5/10. 6 | // 7 | // 8 | 9 | import Crypto 10 | import Vapor 11 | 12 | extension String { 13 | 14 | var md5 : String { 15 | do { 16 | let byes = self.makeBytes() 17 | let result = try Hash.make(.md5, byes) 18 | return result.hexString 19 | } catch { 20 | return "" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | macos: 5 | macos: 6 | xcode: "9.0" 7 | steps: 8 | - run: brew install vapor/tap/vapor 9 | - checkout 10 | - run: swift build 11 | - run: swift test 12 | linux: 13 | docker: 14 | - image: swift:4.0.3 15 | steps: 16 | - run: apt-get install -yq libssl-dev 17 | - checkout 18 | - run: swift build 19 | - run: swift test 20 | 21 | workflows: 22 | version: 2 23 | tests: 24 | jobs: 25 | - macos 26 | - linux 27 | -------------------------------------------------------------------------------- /Sources/App/Category/Int+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Int+Extension.swift 3 | // NHServer 4 | // 5 | // Created by niuhui on 2017/7/26. 6 | // 7 | // 8 | import Foundation 9 | import Vapor 10 | 11 | 12 | extension Int { 13 | var is_toDay_Hour : Bool { 14 | let format = DateFormatter() 15 | format.dateFormat = "yyyyMMddHH" 16 | let now_at = Int(Date().timeIntervalSince1970) 17 | if now_at - self < 60*60 { 18 | return true 19 | } else { 20 | return false 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "WloveIMServer", 5 | targets: [ 6 | Target(name: "App"), 7 | ], 8 | dependencies: [ 9 | .Package(url: "https://github.com/vapor/vapor.git", majorVersion: 2), 10 | .Package(url: "https://github.com/vapor/mysql-provider.git", majorVersion: 2), 11 | .Package(url: "https://github.com/apple/swift-protobuf",Version(1,0,2)), 12 | ], 13 | exclude: [ 14 | "Config", 15 | "Database", 16 | "Localization", 17 | "Public", 18 | "Resources", 19 | ] 20 | ) 21 | 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | - osx 4 | language: generic 5 | sudo: required 6 | dist: trusty 7 | 8 | osx_image: xcode8.3 9 | before_install: 10 | - if [ $TRAVIS_OS_NAME == "osx" ]; then 11 | brew tap vapor/tap; 12 | brew update; 13 | brew install vapor; 14 | else 15 | eval "$(curl -sL https://apt.vapor.sh)"; 16 | sudo apt-get install vapor; 17 | sudo chmod -R a+rx /usr/; 18 | fi 19 | 20 | script: 21 | - swift build 22 | - swift build -c release 23 | - swift test 24 | 25 | after_success: 26 | - eval "$(curl -sL https://swift.vapor.sh/codecov)" 27 | -------------------------------------------------------------------------------- /Sources/App/Middleware/InterfaceDefine.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InterfaceDefine.swift 3 | // NHServer 4 | // 5 | // Created by niuhui on 2017/5/10. 6 | // 7 | // 8 | import Vapor 9 | 10 | let code : String = "code" 11 | let msg : String = "message" 12 | func callFail(_ m: String) -> JSON { 13 | return JSON([code: 1,msg : JSON(m)]) 14 | } 15 | extension JSON { 16 | func success() throws -> JSON { 17 | var temp = JSON([code: 0,msg : "success"]).object 18 | if let dic = self.object{ 19 | for (key,value) in dic { 20 | temp?[key] = value 21 | } 22 | } 23 | return try JSON(temp.makeNode(in: nil)) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/App/Middleware/TokenMiddleware.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TokenMiddleware.swift 3 | // NHServer 4 | // 5 | // Created by niuhui on 2017/5/9. 6 | // 7 | // 8 | 9 | import Vapor 10 | import HTTP 11 | import Foundation 12 | 13 | 14 | final class TokenMiddleware: Middleware { 15 | 16 | func respond(to request: Request, chainingTo next: Responder) throws -> Response { 17 | guard let user_id = request.data["user_id"]?.string else{ 18 | return try JSON([code: 1,msg : "未登录"]).makeResponse() 19 | } 20 | if connectionUsers[user_id] == nil { 21 | return try JSON([code: 1,msg : "未连接游戏服务器"]).makeResponse() 22 | } 23 | return try next.respond(to: request) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/AppTests/Utilities.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | @testable import App 3 | @testable import Vapor 4 | import XCTest 5 | import Testing 6 | import FluentProvider 7 | 8 | extension Droplet { 9 | static func testable() throws -> Droplet { 10 | let config = try Config(arguments: ["vapor", "--env=test"]) 11 | try config.setup() 12 | let drop = try Droplet(config) 13 | try drop.setup() 14 | return drop 15 | } 16 | func serveInBackground() throws { 17 | background { 18 | try! self.run() 19 | } 20 | console.wait(seconds: 0.5) 21 | } 22 | } 23 | 24 | class TestCase: XCTestCase { 25 | override func setUp() { 26 | Node.fuzzy = [Row.self, JSON.self, Node.self] 27 | Testing.onFail = XCTFail 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/App/Category/ModelProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ModelP.swift 3 | // walkingLoveServer 4 | // 5 | // Created by 牛辉 on 2017/9/8. 6 | // 7 | // 8 | import Vapor 9 | import FluentProvider 10 | 11 | extension Model { 12 | func wildcardRow() throws -> Row { 13 | var row = Row() 14 | let hMirror = Mirror(reflecting: self) 15 | for case let (label?, value) in hMirror.children { 16 | switch label { 17 | case "storage" : break 18 | default : try row.set(label, value) 19 | } 20 | } 21 | return row 22 | } 23 | } 24 | extension WebSocket: Hashable { 25 | public var hashValue: Int { 26 | return Unmanaged.passUnretained(self).toOpaque().hashValue 27 | } 28 | public static func ==(lhs: WebSocket, rhs: WebSocket) -> Bool { 29 | return lhs.hashValue == rhs.hashValue 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/AppTests/RouteTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Foundation 3 | import Testing 4 | import HTTP 5 | @testable import Vapor 6 | @testable import App 7 | 8 | /// This file shows an example of testing 9 | /// routes through the Droplet. 10 | 11 | class RouteTests: TestCase { 12 | let drop = try! Droplet.testable() 13 | 14 | func testHello() throws { 15 | try drop 16 | .testResponse(to: .get, at: "hello") 17 | .assertStatus(is: .ok) 18 | .assertJSON("hello", equals: "world") 19 | } 20 | 21 | func testInfo() throws { 22 | try drop 23 | .testResponse(to: .get, at: "info") 24 | .assertStatus(is: .ok) 25 | .assertBody(contains: "0.0.0.0") 26 | } 27 | } 28 | 29 | // MARK: Manifest 30 | 31 | extension RouteTests { 32 | /// This is a requirement for XCTest on Linux 33 | /// to function properly. 34 | /// See ./Tests/LinuxMain.swift for examples 35 | static let allTests = [ 36 | ("testHello", testHello), 37 | ("testInfo", testInfo), 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | MySQL 3 |
4 |
5 | 6 | Documentation 7 | 8 | 9 | Slack Team 10 | 11 | 12 | MIT License 13 | 14 | 15 | Continuous Integration 16 | 17 | 18 | Build Status 19 | 20 | 21 | Swift 3.1 22 | 23 | 24 | -------------------------------------------------------------------------------- /Sources/App/Config+Setup.swift: -------------------------------------------------------------------------------- 1 | import MySQLProvider 2 | 3 | extension Config { 4 | public func setup() throws { 5 | // allow fuzzy conversions for these types 6 | // (add your own types here) 7 | Node.fuzzy = [Row.self, JSON.self, Node.self] 8 | 9 | try setupProviders() 10 | try setupPreparations() 11 | 12 | //游戏的,im的 13 | LoginServer().registered() 14 | MessageServer().registered() 15 | GobangServer().registered() 16 | AudioServer().registered() 17 | } 18 | 19 | private func setupProviders() throws { 20 | try addProvider(MySQLProvider.Provider.self) 21 | } 22 | 23 | private func setupPreparations() throws { 24 | preparations.append(Message.self) 25 | preparations.append(Session.self) 26 | preparations.append(Group.self) 27 | preparations.append(Member.self) 28 | 29 | //游戏的 30 | preparations.append(GameRoom.self) 31 | preparations.append(GameMember.self) 32 | } 33 | } 34 | 35 | 36 | 37 | func registeredRoute() { 38 | GobangController().registeredRouting() 39 | } 40 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Qutheory, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Sources/App/Category/DataInputStream.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataInputStream.swift 3 | // 4 | // Created by 牛辉 on 2017/4/2. 5 | // Copyright © 2017年 Niu. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | struct DataInputStream { 11 | var data: NSData 12 | var length: Int = 0 13 | 14 | init(_ Data : NSData) { 15 | self.data = Data 16 | self.length = 0 17 | } 18 | public mutating func readInt() -> Int32 { 19 | let ch1 = read() 20 | let ch2 = read() 21 | let ch3 = read() 22 | let ch4 = read() 23 | if (ch1 | ch2 | ch3 | ch4) < 0 { 24 | return 0 25 | } 26 | return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)) 27 | } 28 | public mutating func readShort() -> Int16 { 29 | let ch1 = read() 30 | let ch2 = read() 31 | if (ch1 | ch2) < 0 { 32 | 33 | } 34 | return Int16((ch1 << 8) + (ch2 << 0)) 35 | } 36 | private mutating func read() -> Int32 { 37 | 38 | var v : Int8 = 0 39 | data.getBytes(&v, range: NSRange(location: length, length: 1)) 40 | length += 1 41 | return (Int32(v)&0x0ff) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Config/fluent.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "The underlying database technology to use.", 3 | "//": "memory: SQLite in-memory DB.", 4 | "//": "sqlite: Persisted SQLite DB (configure with sqlite.json)", 5 | "//": "Other drivers are available through Vapor providers", 6 | "//": "https://github.com/search?q=topic:vapor-provider+topic:database", 7 | "driver": "mysql", 8 | 9 | "//": "Naming convention to use for creating foreign id keys,", 10 | "//": "e.g., `user_id`", 11 | "//": "`camelCase` option is also available.", 12 | "keyNamingConvention": "snake_case", 13 | 14 | "//": "Name of the table Fluent uses to track migrations.", 15 | "//": "If null, preparations will not be run.", 16 | "migrationEntityName": "fluent", 17 | 18 | "//": "Character used to join pivot tables, e.g., `user_pet`", 19 | "pivotNameConnector": "_", 20 | 21 | "//": "If true, foreign keys will automatically be added", 22 | "//": "to any `builder.foreignId(...)` calls.", 23 | "autoForeignKeys": true, 24 | 25 | "//": "Key to specify page number for paginated responses", 26 | "//": "e.g., `?page=2` ", 27 | "defaultPageKey": "page", 28 | 29 | "//": "Default page size if not otherwise specified on models", 30 | "defaultPageSize": 10, 31 | 32 | "//": "If true, all queries made to the database will be logged.", 33 | "log": false 34 | } 35 | -------------------------------------------------------------------------------- /Sources/App/Server/ServerRouteTool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServerRouteTool.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2017/12/31. 6 | // 7 | 8 | 9 | 10 | import SwiftProtobuf 11 | import Foundation 12 | import Vapor 13 | 14 | var connections: [WebSocket : String] = [:] 15 | var connectionUsers: [String : WebSocket] = [:] 16 | /// 定义元组 包头主要信息 区分业务 17 | typealias apiHeader = (sid: Int,cid: Int,seq: Int) 18 | 19 | var servers: [String : ServerProrocol] = [:] 20 | 21 | func serverRoute(_ ws: WebSocket, _ data: Bytes) { 22 | 23 | let data = Data(bytes: data) 24 | if data.count < 16 { 25 | return 26 | } 27 | let headerData = data[0...15] 28 | var inputData = DataInputStream(NSData(data: headerData)) 29 | let dataLen = inputData.readInt() 30 | if Int(dataLen) > data.count { 31 | return 32 | } 33 | _ = inputData.readShort() 34 | _ = inputData.readShort() 35 | let serviceId = inputData.readShort() 36 | let commandId = inputData.readShort() 37 | let reserved = inputData.readShort() 38 | _ = inputData.readShort() 39 | print("收到信息 服务id=\(serviceId) 命令id=\(commandId) 序列号=\(reserved)") 40 | let key = "\(serviceId)-\(commandId)" 41 | if let server = servers[key] { 42 | let header = apiHeader(Int(serviceId),Int(commandId),Int(reserved)) 43 | let contentData = data[16.. Row { 26 | return try wildcardRow() 27 | } 28 | init (_ user_id: String, _ group_id: Int, _ cid: String) { 29 | self.user_id = user_id 30 | self.create_time = Int(Date().timeIntervalSince1970) 31 | self.cid = cid 32 | } 33 | } 34 | extension Member: Preparation { 35 | static func prepare(_ database: Database) throws { 36 | try database.create(self) { bar in 37 | bar.id() 38 | bar.string("cid") 39 | bar.string("user_id") 40 | bar.int("create_time") 41 | bar.foreignKey("cid", references: "cid", on: Group.self) 42 | } 43 | try database.index("cid", for: self) 44 | try database.index("user_id", for: self) 45 | } 46 | static func revert(_ database: Database) throws { 47 | try database.delete(self) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Sources/App/main.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftProtobuf 3 | import Foundation 4 | import Vapor 5 | 6 | let config = try Config() 7 | try config.setup() 8 | let drop = try Droplet(config) 9 | // 基础api 10 | let api = drop.grouped("api") 11 | let v1 = api.grouped("v1") 12 | let token = v1.grouped(TokenMiddleware()) 13 | 14 | //http业务 15 | registeredRoute() 16 | 17 | // websocket 18 | drop.socket("socket") {(req, ws) in 19 | print(Int(bitPattern: Unmanaged.passUnretained(ws).toOpaque())) 20 | print("New WebSocket connected: \(ws.hashValue)") 21 | background { 22 | while ws.state == .open { 23 | drop.console.wait(seconds: 20) // every 10 seconds 24 | if let _ = connections[ws] { 25 | if ws.state == .open { 26 | print("发送ping") 27 | try? ws.ping() 28 | } 29 | } else { 30 | if ws.state == .open { 31 | print("身份没有验证") 32 | try? ws.close() 33 | } 34 | } 35 | } 36 | } 37 | ws.onBinary = { ws ,data in 38 | serverRoute(ws, data) 39 | } 40 | ws.onPing = { ws ,_ in 41 | print("ping") 42 | } 43 | ws.onPong = { ws ,_ in 44 | print("pong") 45 | } 46 | ws.onClose = { ws, code, reason, clean in 47 | print("Closed.\(ws.hashValue)") 48 | if let user_id = connections[ws] { 49 | connectionUsers[user_id] = nil 50 | try closed(user_id) 51 | } 52 | connections[ws] = nil 53 | } 54 | } 55 | try drop.run() 56 | 57 | -------------------------------------------------------------------------------- /Sources/App/Model/Group.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Group.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2018/1/1. 6 | // 7 | 8 | import Vapor 9 | import FluentProvider 10 | import Foundation 11 | import HTTP 12 | import SwiftProtobuf 13 | 14 | final class Group: Model { 15 | let storage = Storage() 16 | static let entity = "Groups" 17 | var owner : String = "" 18 | var cid : String = "" 19 | var name : String = "" 20 | var avatar : String = "" 21 | var create_time : Int = 0 22 | init(row: Row) throws { 23 | owner = try row.get("owner") 24 | cid = try row.get("cid") 25 | name = try row.get("name") 26 | avatar = try row.get("avatar") 27 | create_time = try row.get("create_time") 28 | } 29 | func makeRow() throws -> Row { 30 | return try wildcardRow() 31 | } 32 | init (_ user_id: String) { 33 | self.owner = user_id 34 | self.create_time = Int(Date().timeIntervalSince1970) 35 | self.cid = "g_" + "\(user_id)+\(self.create_time)".md5 36 | } 37 | } 38 | extension Group: Preparation { 39 | static func prepare(_ database: Database) throws { 40 | try database.create(self) { bar in 41 | bar.id() 42 | bar.string("owner") 43 | bar.string("cid") 44 | bar.string("name") 45 | bar.string("avatar") 46 | bar.int("create_time") 47 | } 48 | try database.index("cid", for: self) 49 | try database.index("owner", for: self) 50 | } 51 | static func revert(_ database: Database) throws { 52 | try database.delete(self) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/App/Category/DataOutputStream.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataOutputStream.swift 3 | // 4 | // Created by 牛辉 on 2017/4/3. 5 | // Copyright © 2017年 Niu. All rights reserved. 6 | // 7 | import Foundation 8 | import Vapor 9 | struct DataOutputStream { 10 | 11 | var data: NSMutableData 12 | var lenght: Int = 0 13 | init() { 14 | self.data = NSMutableData() 15 | self.lenght = 0 16 | } 17 | mutating func writeShort(_ v: Int32) { 18 | var ch = [UInt8](repeating: 0, count: 2) 19 | ch[0] = UInt8((v & 0x0ff00)>>8) 20 | ch[1] = UInt8( v & 0x0ff ) 21 | data.append(ch, length: 2) 22 | self.lenght = self.lenght + 2 23 | } 24 | mutating func directWriteBytes(_ data: NSData) { 25 | let len = data.length 26 | self.data.append(Data(bytes: data.bytes, count: len)) 27 | self.lenght = self.lenght + len 28 | } 29 | func writeDataCount() { 30 | var ch = [UInt8](repeating: 0, count: 4) 31 | for i in 0..<4 { 32 | ch[i] = (UInt8((self.lenght >> ((3 - i)*8)) & 0x0ff)) 33 | } 34 | data.replaceBytes(in: NSMakeRange(0, 4), withBytes: ch, length: 4) 35 | } 36 | mutating func writeInt(_ v: Int32) { 37 | var ch = [UInt8](repeating: 0, count: 4) 38 | for i in 0..<4 { 39 | ch[i] = (UInt8(UInt8((v >> ((3 - i)*8)) & 0x0ff))) 40 | } 41 | self.data.append(ch, length: 4) 42 | lenght = lenght + 4; 43 | } 44 | } 45 | extension DataOutputStream { 46 | mutating func write(_ header: apiHeader) { 47 | writeShort(1) 48 | writeShort(0) 49 | writeShort(Int32(header.sid)) 50 | writeShort(Int32(header.cid)) 51 | writeShort(Int32(header.seq)) 52 | writeShort(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/App/Model/GameMember.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameMember.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2018/1/1. 6 | // 7 | 8 | import Vapor 9 | import FluentProvider 10 | import Foundation 11 | import HTTP 12 | import SwiftProtobuf 13 | 14 | final class GameMember: Model { 15 | let storage = Storage() 16 | static let entity = "GameMembers" 17 | //1.五子棋 2.不知道 18 | var user_id : String = "" 19 | var gameroom_id : Int = 0 20 | var create_time : Int = 0 21 | init(row: Row) throws { 22 | user_id = try row.get("user_id") 23 | gameroom_id = try row.get("gameroom_id") 24 | create_time = try row.get("create_time") 25 | } 26 | func makeRow() throws -> Row { 27 | return try wildcardRow() 28 | } 29 | init (_ user_id: String, _ gameroom_id: Int) { 30 | self.user_id = user_id 31 | self.gameroom_id = gameroom_id 32 | self.create_time = Int(Date().timeIntervalSince1970) 33 | } 34 | } 35 | extension GameMember { 36 | func makeJSON() throws -> JSON { 37 | var json = JSON() 38 | try json.set("user_id", user_id) 39 | try json.set("gameroom_id", gameroom_id) 40 | try json.set("create_time", create_time) 41 | return json 42 | } 43 | } 44 | extension GameMember: Preparation { 45 | static func prepare(_ database: Database) throws { 46 | try database.create(self) { bar in 47 | bar.id() 48 | bar.string("user_id") 49 | bar.int("gameroom_id") 50 | bar.int("create_time") 51 | } 52 | try database.index("gameroom_id", for: self) 53 | try database.index("user_id", for: self) 54 | 55 | } 56 | static func revert(_ database: Database) throws { 57 | try database.delete(self) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Sources/App/Model/Session.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2017/12/31. 6 | // 7 | 8 | import Vapor 9 | import FluentProvider 10 | import Foundation 11 | import HTTP 12 | import SwiftProtobuf 13 | 14 | final class Session: Model { 15 | let storage = Storage() 16 | static let entity = "Sessions" 17 | var msg_id : Int = 0 18 | var cid : String = "" 19 | var user_id : String = "" 20 | // 1.单聊 2.群聊 21 | var type : Int = 0 22 | var update_at : Int = 0 23 | var unread : Int = 0 24 | init(row: Row) throws { 25 | msg_id = try row.get("msg_id") 26 | cid = try row.get("cid") 27 | user_id = try row.get("user_id") 28 | type = try row.get("type") 29 | update_at = try row.get("update_at") 30 | unread = try row.get("unread") 31 | } 32 | func makeRow() throws -> Row { 33 | return try wildcardRow() 34 | } 35 | init (_ user_id: String, cid: String, type: Int , msg_id: Int) { 36 | self.msg_id = msg_id 37 | self.type = type 38 | self.cid = cid 39 | self.user_id = user_id 40 | } 41 | } 42 | extension Session: Preparation { 43 | static func prepare(_ database: Database) throws { 44 | try database.create(self) { bar in 45 | bar.id() 46 | bar.int("msg_id") 47 | bar.string("cid") 48 | bar.string("user_id") 49 | bar.int("type") 50 | bar.int("update_at") 51 | bar.int("unread") 52 | } 53 | try database.index("cid", for: self) 54 | try database.index("user_id", for: self) 55 | try database.index("unread", for: self) 56 | } 57 | static func revert(_ database: Database) throws { 58 | try database.delete(self) 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /Config/droplet.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "The type of server to use for handling requests.", 3 | "//": "engine: Vapor's blazing fast Engine HTTP server.", 4 | "server": "engine", 5 | 6 | "//": "The type of client to use for requesting data from other services.", 7 | "//": "engine: Vapor's blazing fast Engine HTTP client.", 8 | "//": "foundation: A wrapper around Foundation's URLSession.", 9 | "client": "engine", 10 | 11 | "//": "The type of console to use for displaying information and prompting input.", 12 | "//": "terminal: Vapor's default terminal console.", 13 | "console": "terminal", 14 | 15 | "//": "The type of logger to use for recording logs, warnings, errors, etc.", 16 | "//": "console: Vapor's default logger sends logs directly to the chosen console.", 17 | "log": "console", 18 | 19 | "//": "The type of hasher to use for hashing messages.", 20 | "//": "crypto: Vapor's default hasher powered by OpenSSL (configure in crypto.json)", 21 | "//": "bcrypt: Performant BCrypt hashing implementation (configure in bcrypt.json)", 22 | "hash": "crypto", 23 | 24 | "//": "The type of cipher to use for encrypting and decrypting messages.", 25 | "//": "crypto: Vapor's default cipher powered by OpenSSL (configure in crypto.json)", 26 | "cipher": "crypto", 27 | 28 | "//": "Choose which middleware are enabled (and in which order).", 29 | "//": "error: Catches errors thrown in your application and returns a nice response.", 30 | "//": "date: Adds the 'Date' header to HTTP requests.", 31 | "//": "file: Catches 404 errors and checks for files in the Public/ folder", 32 | "middleware": [ 33 | "error", 34 | "date", 35 | "file" 36 | ], 37 | 38 | "//": "Choose which commands this application can run", 39 | "//": "prepare: Supplied by the Fluent provider. Prepares the database (configure in fluent.json)", 40 | "commands": [ 41 | "prepare" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /Sources/App/Model/Message.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Message.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2017/12/31. 6 | // 7 | 8 | import Vapor 9 | import FluentProvider 10 | import Foundation 11 | import HTTP 12 | import SwiftProtobuf 13 | 14 | final class Message: Model { 15 | let storage = Storage() 16 | static let entity = "Messages" 17 | var msg_id : Int = 0 18 | var from : String = "" 19 | var to : String = "" 20 | var type : String = "" 21 | var subtype : String = "" 22 | var msg_data : String = "" 23 | var create_time : Int = 0 24 | init(row: Row) throws { 25 | msg_id = try row.get("msg_id") 26 | from = try row.get("from") 27 | to = try row.get("to") 28 | type = try row.get("type") 29 | subtype = try row.get("subtype") 30 | msg_data = try row.get("msg_data") 31 | create_time = try row.get("create_time") 32 | } 33 | func makeRow() throws -> Row { 34 | return try wildcardRow() 35 | } 36 | init (_ msg: IM_Message_IMMsgData) { 37 | from = msg.from 38 | to = msg.to 39 | type = msg.type 40 | subtype = msg.subtype 41 | msg_data = msg.msgData 42 | create_time = Int(Date().timeIntervalSince1970) 43 | } 44 | } 45 | extension Message: Preparation { 46 | static func prepare(_ database: Database) throws { 47 | try database.create(self) { bar in 48 | bar.id() 49 | bar.int("msg_id") 50 | bar.string("from") 51 | bar.string("to") 52 | bar.string("type") 53 | bar.string("subtype") 54 | bar.string("msg_data") 55 | bar.int("create_time") 56 | } 57 | try database.index("from", for: self) 58 | try database.index("to", for: self) 59 | try database.index("create_time", for: self) 60 | } 61 | static func revert(_ database: Database) throws { 62 | try database.delete(self) 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Sources/App/Server/AudioServer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AudioServer.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2018/1/10. 6 | // 7 | 8 | import Foundation 9 | import Vapor 10 | 11 | struct AudioServer: ServerProrocol { 12 | func registered() { 13 | let key = "\(IM_BaseDefine_ServiceID.sidAudio.rawValue)-\(IM_BaseDefine_AudioCmdID.cidAudioData.rawValue)" 14 | servers[key] = self 15 | } 16 | 17 | func route(_ header: apiHeader, _ ws: WebSocket, _ contentData: Data) { 18 | do { 19 | let audio = try IM_Audio_IMAudioData(serializedData: contentData) 20 | //1.转发 21 | try msgForward(header, audio) 22 | if audio.type != 99 { 23 | //2.ack 24 | try msgAck(ws, header, audio: audio) 25 | } 26 | } catch { 27 | print(error) 28 | } 29 | 30 | } 31 | func msgForward(_ header: apiHeader, _ audio: IM_Audio_IMAudioData) throws { 32 | //1.header 33 | var dataOut = DataOutputStream() 34 | dataOut.writeInt(0) 35 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidAudio.rawValue, 36 | IM_BaseDefine_AudioCmdID.cidAudioData.rawValue, 37 | 0)) 38 | //3.content,leng 39 | try dataOut.directWriteBytes(NSData(data: audio.serializedData())) 40 | dataOut.writeDataCount() 41 | let sendData = Data(referencing: dataOut.data) 42 | if let ws = connectionUsers[audio.to] { 43 | try ws.send(sendData.array) 44 | } 45 | } 46 | func msgAck(_ ws: WebSocket, _ header: apiHeader, audio: IM_Audio_IMAudioData) throws { 47 | //1.header 48 | var dataOut = DataOutputStream() 49 | dataOut.writeInt(0) 50 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidAudio.rawValue, 51 | IM_BaseDefine_AudioCmdID.cidAudioAck.rawValue, 52 | header.seq)) 53 | //2.content 54 | var msgRes = IM_Audio_IMAudioAck() 55 | msgRes.errCode = "0" 56 | msgRes.errMsg = "success" 57 | //3.leng 58 | try dataOut.directWriteBytes(NSData(data: msgRes.serializedData())) 59 | dataOut.writeDataCount() 60 | let sendData = Data(referencing: dataOut.data) 61 | try ws.send(sendData.array) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Sources/App/Model/GameRoom.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameRoom.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2018/1/1. 6 | // 7 | 8 | import Vapor 9 | import FluentProvider 10 | import Foundation 11 | import HTTP 12 | import SwiftProtobuf 13 | 14 | final class GameRoom: Model { 15 | let storage = Storage() 16 | static let entity = "GameRooms" 17 | var name : String = "" 18 | //1.五子棋 2.不知道 19 | var type : Int = 0 20 | var passWord : String = "" 21 | var is_lock : Bool = false 22 | var create_time : Int = 0 23 | init(row: Row) throws { 24 | name = try row.get("name") 25 | type = try row.get("type") 26 | passWord = try row.get("passWord") 27 | is_lock = try row.get("is_lock") 28 | create_time = try row.get("create_time") 29 | } 30 | func makeRow() throws -> Row { 31 | return try wildcardRow() 32 | } 33 | init (_ name:String, _ type: Int, _ passWord: String, _ is_lock: Bool) { 34 | self.name = name 35 | self.type = type 36 | self.passWord = passWord 37 | self.is_lock = is_lock 38 | self.create_time = Int(Date().timeIntervalSince1970) 39 | } 40 | } 41 | extension GameRoom { 42 | func makeJSON() throws -> JSON { 43 | var json = JSON() 44 | try json.set("id", id) 45 | try json.set("type", type) 46 | try json.set("name", name) 47 | try json.set("is_lock", is_lock) 48 | try json.set("create_time", create_time) 49 | try json.set("members", memberJson().map{try $0.makeJSON()}) 50 | return json 51 | } 52 | } 53 | extension GameRoom { 54 | func memberJson() throws -> [GameMember] { 55 | let files = try GameMember.makeQuery().filter("gameroom_id", self.id).all() 56 | return files 57 | } 58 | } 59 | extension GameRoom: Preparation { 60 | static func prepare(_ database: Database) throws { 61 | try database.create(self) { bar in 62 | bar.id() 63 | bar.string("name") 64 | bar.string("passWord") 65 | bar.bool("is_lock") 66 | bar.int("type") 67 | bar.int("create_time") 68 | } 69 | try database.index("create_time", for: self) 70 | try database.index("type", for: self) 71 | 72 | } 73 | static func revert(_ database: Database) throws { 74 | try database.delete(self) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Sources/App/Server/LoginServer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoginController.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2017/12/31. 6 | // 7 | 8 | import Foundation 9 | import Vapor 10 | struct LoginServer: ServerProrocol { 11 | //业务服务器内部地址 校验token信息 12 | static let loginUrl: String = "http://0.0.0.0:8000/api/v1/inner/accesstoken" 13 | func registered() { 14 | let key = "\(IM_BaseDefine_ServiceID.sidLogin.rawValue)-\(IM_BaseDefine_LoginCmdID.cidLoginReqUserlogin.rawValue)" 15 | servers[key] = self 16 | } 17 | func route(_ header: apiHeader, _ ws: WebSocket, _ contentData: Data) { 18 | do { 19 | let loginReq = try IM_Login_IMLoginReq(serializedData: contentData) 20 | let req = try drop.client.post(LoginServer.loginUrl, query: ["token":loginReq.accessToken]) 21 | print(req) 22 | if req.status.hashValue == 200,let user_id = req.json?["user_id"]?.string { 23 | connections[ws] = user_id 24 | connectionUsers[user_id] = ws 25 | //ws返回res 26 | //1.header 27 | var dataOut = DataOutputStream() 28 | dataOut.writeInt(0) 29 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidLogin.rawValue, 30 | IM_BaseDefine_LoginCmdID.cidLoginResUserlogin.rawValue, 31 | header.seq)) 32 | //2.content 33 | var loginRes = IM_Login_IMLoginRes() 34 | loginRes.errCode = .ok 35 | loginRes.errMsg = "success" 36 | loginRes.serverTime = UInt32(Date().timeIntervalSince1970) 37 | //3.leng 38 | try dataOut.directWriteBytes(NSData(data: loginRes.serializedData())) 39 | dataOut.writeDataCount() 40 | let sendData = Data(referencing: dataOut.data) 41 | try ws.send(sendData.array) 42 | } else { 43 | //ws返回res 44 | //1.header 45 | var dataOut = DataOutputStream() 46 | dataOut.writeInt(0) 47 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidLogin.rawValue, 48 | IM_BaseDefine_LoginCmdID.cidLoginResUserlogin.rawValue, 49 | header.seq)) 50 | //2.content 51 | var loginRes = IM_Login_IMLoginRes() 52 | loginRes.errCode = .refused 53 | loginRes.errMsg = "校验失败" 54 | loginRes.serverTime = UInt32(Date().timeIntervalSince1970) 55 | //3.leng 56 | try dataOut.directWriteBytes(NSData(data: loginRes.serializedData())) 57 | dataOut.writeDataCount() 58 | let sendData = Data(referencing: dataOut.data) 59 | try ws.send(sendData.array) 60 | } 61 | } catch { 62 | print(error) 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /Sources/App/Server/GobangServer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameServer.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2018/1/1. 6 | // 7 | 8 | import Foundation 9 | import Vapor 10 | //五子棋 11 | struct GobangServer: ServerProrocol { 12 | func registered() { 13 | let key = "\(IM_BaseDefine_ServiceID.sidGame.rawValue)-\(IM_BaseDefine_GameCmdID.cidGobangData.rawValue)" 14 | servers[key] = self 15 | } 16 | func route(_ header: apiHeader, _ ws: WebSocket, _ contentData: Data) { 17 | do { 18 | let goBang = try G_Gobang_GobangData(serializedData: contentData) 19 | //1.转发 20 | try msgForward(header, goBang) 21 | //2.ack 22 | try msgAck(ws, header, goBang: goBang) 23 | } catch { 24 | print(error) 25 | } 26 | } 27 | 28 | func msgForward(_ header: apiHeader, _ goBang: G_Gobang_GobangData) throws { 29 | //1.header 30 | var dataOut = DataOutputStream() 31 | dataOut.writeInt(0) 32 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidGame.rawValue, 33 | IM_BaseDefine_GameCmdID.cidGobangData.rawValue, 34 | 0)) 35 | //3.content,leng 36 | try dataOut.directWriteBytes(NSData(data: goBang.serializedData())) 37 | dataOut.writeDataCount() 38 | let sendData = Data(referencing: dataOut.data) 39 | if let ws = connectionUsers[goBang.to] { 40 | try ws.send(sendData.array) 41 | } 42 | } 43 | func msgAck(_ ws: WebSocket, _ header: apiHeader, goBang: G_Gobang_GobangData) throws { 44 | //1.header 45 | var dataOut = DataOutputStream() 46 | dataOut.writeInt(0) 47 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidGame.rawValue, 48 | IM_BaseDefine_GameCmdID.cidGobangAck.rawValue, 49 | header.seq)) 50 | //2.content 51 | var msgRes = G_Gobang_GobangAck() 52 | msgRes.errCode = "0" 53 | msgRes.errMsg = "success" 54 | //3.leng 55 | try dataOut.directWriteBytes(NSData(data: msgRes.serializedData())) 56 | dataOut.writeDataCount() 57 | let sendData = Data(referencing: dataOut.data) 58 | try ws.send(sendData.array) 59 | } 60 | } 61 | 62 | func closed(_ user_id: String) throws { 63 | if let members = try? GameMember.makeQuery().filter("user_id", user_id).all() { 64 | for member in members { 65 | try member.delete() 66 | let roomMembers = try GameMember.makeQuery().filter("gameroom_id", member.gameroom_id).all() 67 | if roomMembers.count == 0 { 68 | let room = try GameRoom.makeQuery().filter("id", member.gameroom_id).first() 69 | try room?.delete() 70 | } else { 71 | for memb in roomMembers { 72 | try msgDisConnect(room_id: memb.gameroom_id, user_id: memb.user_id) 73 | } 74 | } 75 | } 76 | } 77 | } 78 | func msgDisConnect(room_id: Int,user_id: String)throws { 79 | //1.header 80 | var dataOut = DataOutputStream() 81 | dataOut.writeInt(0) 82 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidGame.rawValue, 83 | IM_BaseDefine_GameCmdID.cidGobangData.rawValue, 84 | 0)) 85 | //gobang 86 | var goBang = G_Gobang_GobangData() 87 | goBang.type = 8 88 | goBang.subtype = 0 89 | goBang.from = "sunny_sunny" 90 | goBang.roomID = UInt32(room_id) 91 | goBang.to = user_id 92 | goBang.x = 0 93 | goBang.y = 0 94 | goBang.msg = "" 95 | //3.content,leng 96 | try dataOut.directWriteBytes(NSData(data: goBang.serializedData())) 97 | dataOut.writeDataCount() 98 | let sendData = Data(referencing: dataOut.data) 99 | if let ws = connectionUsers[user_id] { 100 | try ws.send(sendData.array) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Sources/App/Controller/GobangController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameController.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2018/1/1. 6 | // 7 | 8 | import Foundation 9 | import Vapor 10 | import HTTP 11 | 12 | struct GobangController { 13 | 14 | func registeredRouting() { 15 | v1.get("game","gobang", handler: self.getGoBangs) 16 | v1.get("game","gobang","detail", handler: self.getGoBangDetail) 17 | token.post("game","gobang", handler: self.createGoBang) 18 | v1.post("game","gobang","quit", handler: self.quitGoBang) 19 | token.post("game","gobang","add", handler: self.addGoBang) 20 | } 21 | func getGoBangs(_ request: Request) throws -> ResponseRepresentable { 22 | 23 | var rooms:[GameRoom] = [] 24 | let roomQuery = try GameRoom.makeQuery().filter("type", 1).sort("create_time", .descending) 25 | if var page = request.data["pagenum"]?.int { 26 | if page == 0 { 27 | page = 1 28 | } 29 | rooms = try roomQuery.limit(20, offset: 20*(page - 1)).all() 30 | } else { 31 | rooms = try roomQuery.limit(20, offset: 0).all() 32 | } 33 | return try JSON(node: [ 34 | "rooms": rooms.map{try $0.makeJSON()} 35 | ]).success() 36 | } 37 | func getGoBangDetail(_ request: Request) throws -> ResponseRepresentable { 38 | 39 | guard let room_id = request.data["room_id"]?.int else{ 40 | return try JSON(node: [code: 1,msg : "缺少room_id"]) 41 | } 42 | guard let room = try GameRoom.makeQuery().filter("id", room_id).first() else{ 43 | return try JSON(node: [code: 1,msg : "房间不存在"]) 44 | } 45 | return try JSON(node: [ 46 | "room": room.makeJSON() 47 | ]).success() 48 | } 49 | func createGoBang(_ request: Request) throws -> ResponseRepresentable { 50 | guard let user_id = request.data["user_id"]?.string else{ 51 | return try JSON(node: [code: 1,msg : "缺少参数"]) 52 | } 53 | guard let type = request.data["type"]?.int else{ 54 | return try JSON(node: [code: 1,msg : "缺少type"]) 55 | } 56 | let room = GameRoom("", type, "", false) 57 | if let name = request.data["name"]?.string { 58 | room.name = name 59 | } 60 | if let passWord = request.data["passWord"]?.string { 61 | room.passWord = passWord 62 | } 63 | if let is_lock = request.data["is_lock"]?.bool { 64 | room.is_lock = is_lock; 65 | } 66 | try room.save() 67 | let member = GameMember(user_id, room.id!.int!) 68 | try member.save() 69 | return try JSON(node: [code: 0,msg: "success", "id": room.id?.int ?? 0, 70 | ]) 71 | } 72 | func quitGoBang(_ request: Request) throws -> ResponseRepresentable { 73 | guard let user_id = request.data["user_id"]?.string else{ 74 | return try JSON(node: [code: 1,msg : "缺少参数"]) 75 | } 76 | guard let room_id = request.data["room_id"]?.int else{ 77 | return try JSON(node: [code: 1,msg : "缺少room_id"]) 78 | } 79 | if let member = try GameMember.makeQuery().filter("user_id", user_id).filter("gameroom_id", room_id).first() { 80 | try member.delete() 81 | } 82 | let count = try GameMember.makeQuery().filter("gameroom_id", room_id).count() 83 | if count == 0 { 84 | let room = try GameRoom.makeQuery().filter("id", room_id).first() 85 | try room?.delete() 86 | } 87 | return try JSON(node: [code: 0,msg: "success"]) 88 | } 89 | func addGoBang(_ request: Request) throws -> ResponseRepresentable { 90 | guard let user_id = request.data["user_id"]?.string else{ 91 | return try JSON(node: [code: 1,msg : "缺少参数"]) 92 | } 93 | guard let room_id = request.data["room_id"]?.int else{ 94 | return try JSON(node: [code: 1,msg : "缺少room_id"]) 95 | } 96 | guard let room = try GameRoom.makeQuery().filter("id", room_id).first() else{ 97 | return try JSON(node: [code: 1,msg : "房间不存在"]) 98 | } 99 | if let _ = try GameMember.makeQuery().filter("user_id", user_id).filter("gameroom_id", room_id).first() { 100 | return try JSON(node: [code: 1,msg : "已经加入了房间"]) 101 | } 102 | if room.is_lock { 103 | guard let passWord = request.data["passWord"]?.string else{ 104 | return try JSON(node: [code: 1,msg : "缺少密码"]) 105 | } 106 | if passWord != room.passWord { 107 | return try JSON(node: [code: 1,msg : "请输入正确的房间密码"]) 108 | } 109 | } 110 | let member = GameMember(user_id, room_id) 111 | try member.save() 112 | return try JSON(node: [code: 0,msg: "success"]) 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Tests/AppTests/PostControllerTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Testing 3 | import HTTP 4 | import Sockets 5 | @testable import Vapor 6 | @testable import App 7 | 8 | /// This file shows an example of testing an 9 | /// individual controller without initializing 10 | /// a Droplet. 11 | 12 | class PostControllerTests: TestCase { 13 | let initialMessage = "I'm a post" 14 | let updatedMessage = "I have been updated \(Date())" 15 | 16 | /// For these tests, we won't be spinning up a live 17 | /// server, and instead we'll be passing our constructed 18 | /// requests programmatically 19 | /// this is usually an effective way to test your 20 | /// application in a convenient and safe manner 21 | /// See RouteTests for an example of a live server test 22 | let controller = PostController() 23 | 24 | func testPostRoutes() throws { 25 | guard let postOne = try storeNewPost(), let idOne = postOne.id?.int else { 26 | XCTFail() 27 | return 28 | } 29 | 30 | try fetchOne(id: idOne) 31 | try fetchAll(expectCount: 1) 32 | try patch(id: idOne) 33 | try put(id: idOne) 34 | 35 | guard let postTwo = try storeNewPost(), let idTwo = postTwo.id?.int else { 36 | XCTFail() 37 | return 38 | } 39 | 40 | try fetchAll(expectCount: 2) 41 | 42 | try deleteOne(id: idOne) 43 | try fetchAll(expectCount: 1) 44 | 45 | try deleteOne(id: idTwo) 46 | try fetchAll(expectCount: 0) 47 | 48 | for _ in 1...5 { 49 | _ = try storeNewPost() 50 | } 51 | try fetchAll(expectCount: 5) 52 | try deleteAll() 53 | try fetchAll(expectCount: 0) 54 | } 55 | 56 | func storeNewPost() throws -> Post? { 57 | let req = Request.makeTest(method: .post) 58 | req.json = try JSON(node: ["content": initialMessage]) 59 | let res = try controller.store(req).makeResponse() 60 | 61 | let json = res.json 62 | XCTAssertNotNil(json) 63 | let newId: Int? = try json?.get("id") 64 | XCTAssertNotNil(newId) 65 | XCTAssertNotNil(json?["content"]) 66 | XCTAssertEqual(json?["content"], req.json?["content"]) 67 | return try Post.find(newId) 68 | } 69 | 70 | func fetchOne(id: Int) throws { 71 | let req = Request.makeTest(method: .get) 72 | let post = try Post.find(id)! 73 | let res = try controller.show(req, post: post).makeResponse() 74 | 75 | let json = res.json 76 | XCTAssertNotNil(json) 77 | XCTAssertNotNil(json?["content"]) 78 | XCTAssertNotNil(json?["id"]) 79 | XCTAssertEqual(json?["id"]?.int, id) 80 | XCTAssertEqual(json?["content"]?.string, initialMessage) 81 | } 82 | 83 | func fetchAll(expectCount count: Int) throws { 84 | let req = Request.makeTest(method: .get) 85 | let res = try controller.index(req).makeResponse() 86 | 87 | let json = res.json 88 | XCTAssertNotNil(json?.array) 89 | XCTAssertEqual(json?.array?.count, count) 90 | } 91 | 92 | func patch(id: Int) throws { 93 | let req = Request.makeTest(method: .patch) 94 | req.json = try JSON(node: ["content": updatedMessage]) 95 | let post = try Post.find(id)! 96 | let res = try controller.update(req, post: post).makeResponse() 97 | 98 | let json = res.json 99 | XCTAssertNotNil(json) 100 | XCTAssertNotNil(json?["content"]) 101 | XCTAssertNotNil(json?["id"]) 102 | XCTAssertEqual(json?["id"]?.int, id) 103 | XCTAssertEqual(json?["content"]?.string, updatedMessage) 104 | } 105 | 106 | func put(id: Int) throws { 107 | let req = Request.makeTest(method: .put) 108 | req.json = try JSON(node: ["content": updatedMessage]) 109 | let post = try Post.find(id)! 110 | let res = try controller.replace(req, post: post).makeResponse() 111 | 112 | let json = res.json 113 | XCTAssertNotNil(json) 114 | XCTAssertNotNil(json?["content"]) 115 | XCTAssertNotNil(json?["id"]) 116 | XCTAssertEqual(json?["id"]?.int, id) 117 | XCTAssertEqual(json?["content"]?.string, updatedMessage) 118 | } 119 | 120 | func deleteOne(id: Int) throws { 121 | let req = Request.makeTest(method: .delete) 122 | 123 | let post = try Post.find(id)! 124 | _ = try controller.delete(req, post: post) 125 | } 126 | 127 | func deleteAll() throws { 128 | let req = Request.makeTest(method: .delete) 129 | _ = try controller.clear(req) 130 | } 131 | } 132 | 133 | // MARK: Manifest 134 | 135 | extension PostControllerTests { 136 | /// This is a requirement for XCTest on Linux 137 | /// to function properly. 138 | /// See ./Tests/LinuxMain.swift for examples 139 | static let allTests = [ 140 | ("testPostRoutes", testPostRoutes), 141 | ] 142 | } 143 | -------------------------------------------------------------------------------- /Sources/App/Server/MessageServer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageController.swift 3 | // App 4 | // 5 | // Created by 牛辉 on 2017/12/31. 6 | // 7 | 8 | import Foundation 9 | import Vapor 10 | 11 | struct MessageServer: ServerProrocol { 12 | 13 | func registered() { 14 | let key = "\(IM_BaseDefine_ServiceID.sidMsg.rawValue)-\(IM_BaseDefine_MessageCmdID.cidMsgData.rawValue)" 15 | servers[key] = self 16 | } 17 | func route(_ header: apiHeader, _ ws: WebSocket, _ contentData: Data) { 18 | do { 19 | //单聊 20 | var msg = try IM_Message_IMMsgData(serializedData: contentData) 21 | //1.保存msg到数据库 22 | let message = try saveMessage(&msg) 23 | //2.处理session 24 | if msg.to.contains("g_") {//群 25 | try groupSession(header, msg, message: message) 26 | } else { 27 | try singleSession(msg, message: message) 28 | //3.先转发给to 29 | try msgForward(header, msg) 30 | } 31 | //4.返回ack 32 | try msgAck(ws, header, msg: msg) 33 | 34 | } catch { 35 | print(error) 36 | } 37 | } 38 | func saveMessage(_ msg:inout IM_Message_IMMsgData) throws -> Message { 39 | let message = Message(msg) 40 | var count = 0 41 | if msg.to.contains("g_") {//群 42 | count = try Message.makeQuery().filter("to", msg.to).count() 43 | } else { 44 | count = try message.makeQuery().or({ (orQuery) in 45 | try orQuery.filter("form", msg.from).filter("to", msg.to) 46 | try orQuery.filter("form", msg.to).filter("to", msg.from) 47 | }).count() 48 | } 49 | message.msg_id = count + 1 50 | msg.msgID = "\(message.msg_id)" 51 | msg.createTime = UInt32(message.create_time) 52 | try message.save() 53 | return message 54 | } 55 | func singleSession(_ msg: IM_Message_IMMsgData, message: Message) throws { 56 | //1.发送方的session 57 | if let fromSession = try Session.makeQuery().filter("user_id", msg.from).filter("cid", msg.to).first() { 58 | fromSession.msg_id = message.msg_id 59 | fromSession.update_at = message.create_time 60 | fromSession.unread += 1 61 | try fromSession.save() 62 | } else { 63 | let session = Session(msg.from, cid: msg.to, type: 1, msg_id: message.msg_id) 64 | session.unread += 1 65 | try session.save() 66 | } 67 | //2.接受方的session 68 | if let toSession = try Session.makeQuery().filter("user_id", msg.to).filter("cid", msg.from).first() { 69 | toSession.msg_id = message.msg_id 70 | toSession.update_at = message.create_time 71 | toSession.unread += 1 72 | try toSession.save() 73 | } else { 74 | let session = Session(msg.to, cid: msg.from, type: 1, msg_id: message.msg_id) 75 | session.unread += 1 76 | try session.save() 77 | } 78 | } 79 | 80 | func groupSession(_ header: apiHeader, _ msg: IM_Message_IMMsgData, message: Message) throws { 81 | let members = try Member.makeQuery().filter("cid", msg.to).all() 82 | for member in members { 83 | if let session = try Session.makeQuery().filter("user_id", member.user_id).filter("cid", msg.to).first() { 84 | session.msg_id = message.msg_id 85 | session.update_at = message.create_time 86 | session.unread += 1 87 | try session.save() 88 | } else { 89 | let session = Session(msg.from, cid: msg.to, type: 2, msg_id: message.msg_id) 90 | session.unread += 1 91 | try session.save() 92 | } 93 | //1.header 94 | var dataOut = DataOutputStream() 95 | dataOut.writeInt(0) 96 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidMsg.rawValue, 97 | IM_BaseDefine_MessageCmdID.cidMsgData.rawValue, 98 | 0)) 99 | //3.content,leng 100 | try dataOut.directWriteBytes(NSData(data: msg.serializedData())) 101 | dataOut.writeDataCount() 102 | let sendData = Data(referencing: dataOut.data) 103 | if msg.from != member.user_id { //不给自己发送 104 | try groupMsgForward(sendData, member) 105 | } 106 | } 107 | } 108 | 109 | func msgForward(_ header: apiHeader, _ msg: IM_Message_IMMsgData) throws { 110 | //1.header 111 | var dataOut = DataOutputStream() 112 | dataOut.writeInt(0) 113 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidMsg.rawValue, 114 | IM_BaseDefine_MessageCmdID.cidMsgData.rawValue, 115 | 0)) 116 | //3.content,leng 117 | try dataOut.directWriteBytes(NSData(data: msg.serializedData())) 118 | dataOut.writeDataCount() 119 | let sendData = Data(referencing: dataOut.data) 120 | if let ws = connectionUsers[msg.to] { 121 | try ws.send(sendData.array) 122 | } else { 123 | //推送 124 | } 125 | } 126 | func groupMsgForward(_ sendData: Data, _ member: Member) throws { 127 | if let ws = connectionUsers[member.user_id] { 128 | try ws.send(sendData.array) 129 | } else { 130 | //推送 131 | } 132 | } 133 | 134 | func msgAck(_ ws: WebSocket, _ header: apiHeader, msg: IM_Message_IMMsgData) throws { 135 | //1.header 136 | var dataOut = DataOutputStream() 137 | dataOut.writeInt(0) 138 | dataOut.write(apiHeader(IM_BaseDefine_ServiceID.sidMsg.rawValue, 139 | IM_BaseDefine_MessageCmdID.cidMsgDataAck.rawValue, 140 | header.seq)) 141 | //2.content 142 | var msgRes = IM_Message_IMMsgDataAck() 143 | msgRes.errCode = "0" 144 | msgRes.errMsg = "success" 145 | msgRes.createTime = "\(msg.createTime)" 146 | msgRes.msgID = msg.msgID 147 | //3.leng 148 | try dataOut.directWriteBytes(NSData(data: msgRes.serializedData())) 149 | dataOut.writeDataCount() 150 | let sendData = Data(referencing: dataOut.data) 151 | try ws.send(sendData.array) 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /Sources/App/Protobuf/IM.Audio.pb.swift: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. 2 | // 3 | // Generated by the Swift generator plugin for the protocol buffer compiler. 4 | // Source: IM.Audio.proto 5 | // 6 | // For information on using the generated types, please see the documenation: 7 | // https://github.com/apple/swift-protobuf/ 8 | 9 | import Foundation 10 | import SwiftProtobuf 11 | 12 | // If the compiler emits an error on this type, it is because this file 13 | // was generated by a version of the `protoc` Swift plug-in that is 14 | // incompatible with the version of SwiftProtobuf to which you are linking. 15 | // Please ensure that your are building against the same version of the API 16 | // that was used to generate this file. 17 | fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { 18 | struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} 19 | typealias Version = _2 20 | } 21 | 22 | struct IM_Audio_IMAudioData: SwiftProtobuf.Message { 23 | static let protoMessageName: String = _protobuf_package + ".IMAudioData" 24 | 25 | /// 信息类型 1请求语音通话,2同意语音通话,3挂断语音通话 26 | var type: UInt32 = 0 27 | 28 | /// 房间id 29 | var roomID: UInt32 = 0 30 | 31 | /// 消息发送方 32 | var from: String = String() 33 | 34 | /// 消息接受方 35 | var to: String = String() 36 | 37 | /// 消息接受方 38 | var msg: String = String() 39 | 40 | /// 语音data 41 | var audioData: Data = SwiftProtobuf.Internal.emptyData 42 | 43 | var unknownFields = SwiftProtobuf.UnknownStorage() 44 | 45 | init() {} 46 | 47 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 48 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 49 | /// initializers are defined in the SwiftProtobuf library. See the Message and 50 | /// Message+*Additions` files. 51 | mutating func decodeMessage(decoder: inout D) throws { 52 | while let fieldNumber = try decoder.nextFieldNumber() { 53 | switch fieldNumber { 54 | case 1: try decoder.decodeSingularUInt32Field(value: &self.type) 55 | case 2: try decoder.decodeSingularUInt32Field(value: &self.roomID) 56 | case 3: try decoder.decodeSingularStringField(value: &self.from) 57 | case 4: try decoder.decodeSingularStringField(value: &self.to) 58 | case 5: try decoder.decodeSingularStringField(value: &self.msg) 59 | case 6: try decoder.decodeSingularBytesField(value: &self.audioData) 60 | default: break 61 | } 62 | } 63 | } 64 | 65 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 66 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 67 | /// other serializer methods are defined in the SwiftProtobuf library. See the 68 | /// `Message` and `Message+*Additions` files. 69 | func traverse(visitor: inout V) throws { 70 | if self.type != 0 { 71 | try visitor.visitSingularUInt32Field(value: self.type, fieldNumber: 1) 72 | } 73 | if self.roomID != 0 { 74 | try visitor.visitSingularUInt32Field(value: self.roomID, fieldNumber: 2) 75 | } 76 | if !self.from.isEmpty { 77 | try visitor.visitSingularStringField(value: self.from, fieldNumber: 3) 78 | } 79 | if !self.to.isEmpty { 80 | try visitor.visitSingularStringField(value: self.to, fieldNumber: 4) 81 | } 82 | if !self.msg.isEmpty { 83 | try visitor.visitSingularStringField(value: self.msg, fieldNumber: 5) 84 | } 85 | if !self.audioData.isEmpty { 86 | try visitor.visitSingularBytesField(value: self.audioData, fieldNumber: 6) 87 | } 88 | try unknownFields.traverse(visitor: &visitor) 89 | } 90 | } 91 | 92 | struct IM_Audio_IMAudioAck: SwiftProtobuf.Message { 93 | static let protoMessageName: String = _protobuf_package + ".IMAudioAck" 94 | 95 | /// 0:发送成功,msg_id有效;1+:发送失败; 96 | var errCode: String = String() 97 | 98 | /// 错误消息 99 | var errMsg: String = String() 100 | 101 | var unknownFields = SwiftProtobuf.UnknownStorage() 102 | 103 | init() {} 104 | 105 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 106 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 107 | /// initializers are defined in the SwiftProtobuf library. See the Message and 108 | /// Message+*Additions` files. 109 | mutating func decodeMessage(decoder: inout D) throws { 110 | while let fieldNumber = try decoder.nextFieldNumber() { 111 | switch fieldNumber { 112 | case 1: try decoder.decodeSingularStringField(value: &self.errCode) 113 | case 2: try decoder.decodeSingularStringField(value: &self.errMsg) 114 | default: break 115 | } 116 | } 117 | } 118 | 119 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 120 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 121 | /// other serializer methods are defined in the SwiftProtobuf library. See the 122 | /// `Message` and `Message+*Additions` files. 123 | func traverse(visitor: inout V) throws { 124 | if !self.errCode.isEmpty { 125 | try visitor.visitSingularStringField(value: self.errCode, fieldNumber: 1) 126 | } 127 | if !self.errMsg.isEmpty { 128 | try visitor.visitSingularStringField(value: self.errMsg, fieldNumber: 2) 129 | } 130 | try unknownFields.traverse(visitor: &visitor) 131 | } 132 | } 133 | 134 | // MARK: - Code below here is support for the SwiftProtobuf runtime. 135 | 136 | fileprivate let _protobuf_package = "IM.Audio" 137 | 138 | extension IM_Audio_IMAudioData: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 139 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 140 | 1: .same(proto: "type"), 141 | 2: .standard(proto: "room_id"), 142 | 3: .same(proto: "from"), 143 | 4: .same(proto: "to"), 144 | 5: .same(proto: "msg"), 145 | 6: .standard(proto: "audio_data"), 146 | ] 147 | 148 | func _protobuf_generated_isEqualTo(other: IM_Audio_IMAudioData) -> Bool { 149 | if self.type != other.type {return false} 150 | if self.roomID != other.roomID {return false} 151 | if self.from != other.from {return false} 152 | if self.to != other.to {return false} 153 | if self.msg != other.msg {return false} 154 | if self.audioData != other.audioData {return false} 155 | if unknownFields != other.unknownFields {return false} 156 | return true 157 | } 158 | } 159 | 160 | extension IM_Audio_IMAudioAck: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 161 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 162 | 1: .standard(proto: "err_code"), 163 | 2: .standard(proto: "err_msg"), 164 | ] 165 | 166 | func _protobuf_generated_isEqualTo(other: IM_Audio_IMAudioAck) -> Bool { 167 | if self.errCode != other.errCode {return false} 168 | if self.errMsg != other.errMsg {return false} 169 | if unknownFields != other.unknownFields {return false} 170 | return true 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Sources/App/Protobuf/G.Gobang.pb.swift: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. 2 | // 3 | // Generated by the Swift generator plugin for the protocol buffer compiler. 4 | // Source: G.Gobang.proto 5 | // 6 | // For information on using the generated types, please see the documenation: 7 | // https://github.com/apple/swift-protobuf/ 8 | 9 | import Foundation 10 | import SwiftProtobuf 11 | 12 | // If the compiler emits an error on this type, it is because this file 13 | // was generated by a version of the `protoc` Swift plug-in that is 14 | // incompatible with the version of SwiftProtobuf to which you are linking. 15 | // Please ensure that your are building against the same version of the API 16 | // that was used to generate this file. 17 | fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { 18 | struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} 19 | typealias Version = _2 20 | } 21 | 22 | struct G_Gobang_GobangData: SwiftProtobuf.Message { 23 | static let protoMessageName: String = _protobuf_package + ".GobangData" 24 | 25 | /// 信息类型 1进入房间,2离开房间,3准备,4开始,5悔棋,6同意悔棋,100下棋 26 | var type: UInt32 = 0 27 | 28 | /// 1.黑子 2.白子 29 | var subtype: UInt32 = 0 30 | 31 | /// 房间id 32 | var roomID: UInt32 = 0 33 | 34 | /// 消息发送方 35 | var from: String = String() 36 | 37 | /// 消息接受方 38 | var to: String = String() 39 | 40 | /// 棋盘 x轴 41 | var x: UInt32 = 0 42 | 43 | /// 棋盘 y轴 44 | var y: UInt32 = 0 45 | 46 | /// 消息接受方 47 | var msg: String = String() 48 | 49 | var unknownFields = SwiftProtobuf.UnknownStorage() 50 | 51 | init() {} 52 | 53 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 54 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 55 | /// initializers are defined in the SwiftProtobuf library. See the Message and 56 | /// Message+*Additions` files. 57 | mutating func decodeMessage(decoder: inout D) throws { 58 | while let fieldNumber = try decoder.nextFieldNumber() { 59 | switch fieldNumber { 60 | case 1: try decoder.decodeSingularUInt32Field(value: &self.type) 61 | case 2: try decoder.decodeSingularUInt32Field(value: &self.subtype) 62 | case 3: try decoder.decodeSingularUInt32Field(value: &self.roomID) 63 | case 4: try decoder.decodeSingularStringField(value: &self.from) 64 | case 5: try decoder.decodeSingularStringField(value: &self.to) 65 | case 6: try decoder.decodeSingularUInt32Field(value: &self.x) 66 | case 7: try decoder.decodeSingularUInt32Field(value: &self.y) 67 | case 8: try decoder.decodeSingularStringField(value: &self.msg) 68 | default: break 69 | } 70 | } 71 | } 72 | 73 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 74 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 75 | /// other serializer methods are defined in the SwiftProtobuf library. See the 76 | /// `Message` and `Message+*Additions` files. 77 | func traverse(visitor: inout V) throws { 78 | if self.type != 0 { 79 | try visitor.visitSingularUInt32Field(value: self.type, fieldNumber: 1) 80 | } 81 | if self.subtype != 0 { 82 | try visitor.visitSingularUInt32Field(value: self.subtype, fieldNumber: 2) 83 | } 84 | if self.roomID != 0 { 85 | try visitor.visitSingularUInt32Field(value: self.roomID, fieldNumber: 3) 86 | } 87 | if !self.from.isEmpty { 88 | try visitor.visitSingularStringField(value: self.from, fieldNumber: 4) 89 | } 90 | if !self.to.isEmpty { 91 | try visitor.visitSingularStringField(value: self.to, fieldNumber: 5) 92 | } 93 | if self.x != 0 { 94 | try visitor.visitSingularUInt32Field(value: self.x, fieldNumber: 6) 95 | } 96 | if self.y != 0 { 97 | try visitor.visitSingularUInt32Field(value: self.y, fieldNumber: 7) 98 | } 99 | if !self.msg.isEmpty { 100 | try visitor.visitSingularStringField(value: self.msg, fieldNumber: 8) 101 | } 102 | try unknownFields.traverse(visitor: &visitor) 103 | } 104 | } 105 | 106 | struct G_Gobang_GobangAck: SwiftProtobuf.Message { 107 | static let protoMessageName: String = _protobuf_package + ".GobangAck" 108 | 109 | /// 0:发送成功,msg_id有效;1+:发送失败; 110 | var errCode: String = String() 111 | 112 | /// 错误消息 113 | var errMsg: String = String() 114 | 115 | var unknownFields = SwiftProtobuf.UnknownStorage() 116 | 117 | init() {} 118 | 119 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 120 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 121 | /// initializers are defined in the SwiftProtobuf library. See the Message and 122 | /// Message+*Additions` files. 123 | mutating func decodeMessage(decoder: inout D) throws { 124 | while let fieldNumber = try decoder.nextFieldNumber() { 125 | switch fieldNumber { 126 | case 1: try decoder.decodeSingularStringField(value: &self.errCode) 127 | case 2: try decoder.decodeSingularStringField(value: &self.errMsg) 128 | default: break 129 | } 130 | } 131 | } 132 | 133 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 134 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 135 | /// other serializer methods are defined in the SwiftProtobuf library. See the 136 | /// `Message` and `Message+*Additions` files. 137 | func traverse(visitor: inout V) throws { 138 | if !self.errCode.isEmpty { 139 | try visitor.visitSingularStringField(value: self.errCode, fieldNumber: 1) 140 | } 141 | if !self.errMsg.isEmpty { 142 | try visitor.visitSingularStringField(value: self.errMsg, fieldNumber: 2) 143 | } 144 | try unknownFields.traverse(visitor: &visitor) 145 | } 146 | } 147 | 148 | // MARK: - Code below here is support for the SwiftProtobuf runtime. 149 | 150 | fileprivate let _protobuf_package = "G.Gobang" 151 | 152 | extension G_Gobang_GobangData: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 153 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 154 | 1: .same(proto: "type"), 155 | 2: .same(proto: "subtype"), 156 | 3: .standard(proto: "room_id"), 157 | 4: .same(proto: "from"), 158 | 5: .same(proto: "to"), 159 | 6: .same(proto: "x"), 160 | 7: .same(proto: "y"), 161 | 8: .same(proto: "msg"), 162 | ] 163 | 164 | func _protobuf_generated_isEqualTo(other: G_Gobang_GobangData) -> Bool { 165 | if self.type != other.type {return false} 166 | if self.subtype != other.subtype {return false} 167 | if self.roomID != other.roomID {return false} 168 | if self.from != other.from {return false} 169 | if self.to != other.to {return false} 170 | if self.x != other.x {return false} 171 | if self.y != other.y {return false} 172 | if self.msg != other.msg {return false} 173 | if unknownFields != other.unknownFields {return false} 174 | return true 175 | } 176 | } 177 | 178 | extension G_Gobang_GobangAck: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 179 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 180 | 1: .standard(proto: "err_code"), 181 | 2: .standard(proto: "err_msg"), 182 | ] 183 | 184 | func _protobuf_generated_isEqualTo(other: G_Gobang_GobangAck) -> Bool { 185 | if self.errCode != other.errCode {return false} 186 | if self.errMsg != other.errMsg {return false} 187 | if unknownFields != other.unknownFields {return false} 188 | return true 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /Sources/App/Protobuf/IM.Login.pb.swift: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. 2 | // 3 | // Generated by the Swift generator plugin for the protocol buffer compiler. 4 | // Source: IM.Login.proto 5 | // 6 | // For information on using the generated types, please see the documenation: 7 | // https://github.com/apple/swift-protobuf/ 8 | 9 | import Foundation 10 | import SwiftProtobuf 11 | 12 | // If the compiler emits an error on this type, it is because this file 13 | // was generated by a version of the `protoc` Swift plug-in that is 14 | // incompatible with the version of SwiftProtobuf to which you are linking. 15 | // Please ensure that your are building against the same version of the API 16 | // that was used to generate this file. 17 | fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { 18 | struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} 19 | typealias Version = _2 20 | } 21 | 22 | struct IM_Login_IMLoginReq: SwiftProtobuf.Message { 23 | static let protoMessageName: String = _protobuf_package + ".IMLoginReq" 24 | 25 | ///cmd id: 0x0103 26 | var clientType: IM_BaseDefine_ClientType = .unknown 27 | 28 | var clientVersion: String = String() 29 | 30 | var deviceToken: String = String() 31 | 32 | var accessToken: String = String() 33 | 34 | var unknownFields = SwiftProtobuf.UnknownStorage() 35 | 36 | init() {} 37 | 38 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 39 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 40 | /// initializers are defined in the SwiftProtobuf library. See the Message and 41 | /// Message+*Additions` files. 42 | mutating func decodeMessage(decoder: inout D) throws { 43 | while let fieldNumber = try decoder.nextFieldNumber() { 44 | switch fieldNumber { 45 | case 1: try decoder.decodeSingularEnumField(value: &self.clientType) 46 | case 2: try decoder.decodeSingularStringField(value: &self.clientVersion) 47 | case 3: try decoder.decodeSingularStringField(value: &self.deviceToken) 48 | case 4: try decoder.decodeSingularStringField(value: &self.accessToken) 49 | default: break 50 | } 51 | } 52 | } 53 | 54 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 55 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 56 | /// other serializer methods are defined in the SwiftProtobuf library. See the 57 | /// `Message` and `Message+*Additions` files. 58 | func traverse(visitor: inout V) throws { 59 | if self.clientType != .unknown { 60 | try visitor.visitSingularEnumField(value: self.clientType, fieldNumber: 1) 61 | } 62 | if !self.clientVersion.isEmpty { 63 | try visitor.visitSingularStringField(value: self.clientVersion, fieldNumber: 2) 64 | } 65 | if !self.deviceToken.isEmpty { 66 | try visitor.visitSingularStringField(value: self.deviceToken, fieldNumber: 3) 67 | } 68 | if !self.accessToken.isEmpty { 69 | try visitor.visitSingularStringField(value: self.accessToken, fieldNumber: 4) 70 | } 71 | try unknownFields.traverse(visitor: &visitor) 72 | } 73 | } 74 | 75 | struct IM_Login_IMLoginRes: SwiftProtobuf.Message { 76 | static let protoMessageName: String = _protobuf_package + ".IMLoginRes" 77 | 78 | ///cmd id: 0x0104 79 | var serverTime: UInt32 = 0 80 | 81 | var errCode: IM_BaseDefine_ResultType = .ok 82 | 83 | var errMsg: String = String() 84 | 85 | var unknownFields = SwiftProtobuf.UnknownStorage() 86 | 87 | init() {} 88 | 89 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 90 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 91 | /// initializers are defined in the SwiftProtobuf library. See the Message and 92 | /// Message+*Additions` files. 93 | mutating func decodeMessage(decoder: inout D) throws { 94 | while let fieldNumber = try decoder.nextFieldNumber() { 95 | switch fieldNumber { 96 | case 1: try decoder.decodeSingularUInt32Field(value: &self.serverTime) 97 | case 2: try decoder.decodeSingularEnumField(value: &self.errCode) 98 | case 3: try decoder.decodeSingularStringField(value: &self.errMsg) 99 | default: break 100 | } 101 | } 102 | } 103 | 104 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 105 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 106 | /// other serializer methods are defined in the SwiftProtobuf library. See the 107 | /// `Message` and `Message+*Additions` files. 108 | func traverse(visitor: inout V) throws { 109 | if self.serverTime != 0 { 110 | try visitor.visitSingularUInt32Field(value: self.serverTime, fieldNumber: 1) 111 | } 112 | if self.errCode != .ok { 113 | try visitor.visitSingularEnumField(value: self.errCode, fieldNumber: 2) 114 | } 115 | if !self.errMsg.isEmpty { 116 | try visitor.visitSingularStringField(value: self.errMsg, fieldNumber: 3) 117 | } 118 | try unknownFields.traverse(visitor: &visitor) 119 | } 120 | } 121 | 122 | ///cmd id: 0x0105 123 | struct IM_Login_IMLogoutReq: SwiftProtobuf.Message { 124 | static let protoMessageName: String = _protobuf_package + ".IMLogoutReq" 125 | 126 | var unknownFields = SwiftProtobuf.UnknownStorage() 127 | 128 | init() {} 129 | 130 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 131 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 132 | /// initializers are defined in the SwiftProtobuf library. See the Message and 133 | /// Message+*Additions` files. 134 | mutating func decodeMessage(decoder: inout D) throws { 135 | while let _ = try decoder.nextFieldNumber() { 136 | } 137 | } 138 | 139 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 140 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 141 | /// other serializer methods are defined in the SwiftProtobuf library. See the 142 | /// `Message` and `Message+*Additions` files. 143 | func traverse(visitor: inout V) throws { 144 | try unknownFields.traverse(visitor: &visitor) 145 | } 146 | } 147 | 148 | struct IM_Login_IMLogoutRsp: SwiftProtobuf.Message { 149 | static let protoMessageName: String = _protobuf_package + ".IMLogoutRsp" 150 | 151 | ///cmd id: 0x0106 152 | var errCode: UInt32 = 0 153 | 154 | var unknownFields = SwiftProtobuf.UnknownStorage() 155 | 156 | init() {} 157 | 158 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 159 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 160 | /// initializers are defined in the SwiftProtobuf library. See the Message and 161 | /// Message+*Additions` files. 162 | mutating func decodeMessage(decoder: inout D) throws { 163 | while let fieldNumber = try decoder.nextFieldNumber() { 164 | switch fieldNumber { 165 | case 1: try decoder.decodeSingularUInt32Field(value: &self.errCode) 166 | default: break 167 | } 168 | } 169 | } 170 | 171 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 172 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 173 | /// other serializer methods are defined in the SwiftProtobuf library. See the 174 | /// `Message` and `Message+*Additions` files. 175 | func traverse(visitor: inout V) throws { 176 | if self.errCode != 0 { 177 | try visitor.visitSingularUInt32Field(value: self.errCode, fieldNumber: 1) 178 | } 179 | try unknownFields.traverse(visitor: &visitor) 180 | } 181 | } 182 | 183 | // MARK: - Code below here is support for the SwiftProtobuf runtime. 184 | 185 | fileprivate let _protobuf_package = "IM.Login" 186 | 187 | extension IM_Login_IMLoginReq: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 188 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 189 | 1: .standard(proto: "client_type"), 190 | 2: .standard(proto: "client_version"), 191 | 3: .standard(proto: "device_token"), 192 | 4: .standard(proto: "access_token"), 193 | ] 194 | 195 | func _protobuf_generated_isEqualTo(other: IM_Login_IMLoginReq) -> Bool { 196 | if self.clientType != other.clientType {return false} 197 | if self.clientVersion != other.clientVersion {return false} 198 | if self.deviceToken != other.deviceToken {return false} 199 | if self.accessToken != other.accessToken {return false} 200 | if unknownFields != other.unknownFields {return false} 201 | return true 202 | } 203 | } 204 | 205 | extension IM_Login_IMLoginRes: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 206 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 207 | 1: .standard(proto: "server_time"), 208 | 2: .standard(proto: "err_code"), 209 | 3: .standard(proto: "err_msg"), 210 | ] 211 | 212 | func _protobuf_generated_isEqualTo(other: IM_Login_IMLoginRes) -> Bool { 213 | if self.serverTime != other.serverTime {return false} 214 | if self.errCode != other.errCode {return false} 215 | if self.errMsg != other.errMsg {return false} 216 | if unknownFields != other.unknownFields {return false} 217 | return true 218 | } 219 | } 220 | 221 | extension IM_Login_IMLogoutReq: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 222 | static let _protobuf_nameMap = SwiftProtobuf._NameMap() 223 | 224 | func _protobuf_generated_isEqualTo(other: IM_Login_IMLogoutReq) -> Bool { 225 | if unknownFields != other.unknownFields {return false} 226 | return true 227 | } 228 | } 229 | 230 | extension IM_Login_IMLogoutRsp: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 231 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 232 | 1: .standard(proto: "err_code"), 233 | ] 234 | 235 | func _protobuf_generated_isEqualTo(other: IM_Login_IMLogoutRsp) -> Bool { 236 | if self.errCode != other.errCode {return false} 237 | if unknownFields != other.unknownFields {return false} 238 | return true 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /Sources/App/Protobuf/IM.BaseDefine.pb.swift: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. 2 | // 3 | // Generated by the Swift generator plugin for the protocol buffer compiler. 4 | // Source: IM.BaseDefine.proto 5 | // 6 | // For information on using the generated types, please see the documenation: 7 | // https://github.com/apple/swift-protobuf/ 8 | 9 | import Foundation 10 | import SwiftProtobuf 11 | 12 | // If the compiler emits an error on this type, it is because this file 13 | // was generated by a version of the `protoc` Swift plug-in that is 14 | // incompatible with the version of SwiftProtobuf to which you are linking. 15 | // Please ensure that your are building against the same version of the API 16 | // that was used to generate this file. 17 | fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { 18 | struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} 19 | typealias Version = _2 20 | } 21 | 22 | /// service id 23 | enum IM_BaseDefine_ServiceID: SwiftProtobuf.Enum { 24 | typealias RawValue = Int 25 | case sidUnused // = 0 26 | 27 | /// for login 28 | case sidLogin // = 1 29 | 30 | /// for IM 31 | case sidMsg // = 3 32 | 33 | /// for GAME 34 | case sidGame // = 4 35 | 36 | /// for 语音 37 | case sidAudio // = 5 38 | 39 | /// for 其他 40 | case sidOther // = 257 41 | case UNRECOGNIZED(Int) 42 | 43 | init() { 44 | self = .sidUnused 45 | } 46 | 47 | init?(rawValue: Int) { 48 | switch rawValue { 49 | case 0: self = .sidUnused 50 | case 1: self = .sidLogin 51 | case 3: self = .sidMsg 52 | case 4: self = .sidGame 53 | case 5: self = .sidAudio 54 | case 257: self = .sidOther 55 | default: self = .UNRECOGNIZED(rawValue) 56 | } 57 | } 58 | 59 | var rawValue: Int { 60 | switch self { 61 | case .sidUnused: return 0 62 | case .sidLogin: return 1 63 | case .sidMsg: return 3 64 | case .sidGame: return 4 65 | case .sidAudio: return 5 66 | case .sidOther: return 257 67 | case .UNRECOGNIZED(let i): return i 68 | } 69 | } 70 | 71 | } 72 | 73 | /// command 74 | enum IM_BaseDefine_LoginCmdID: SwiftProtobuf.Enum { 75 | typealias RawValue = Int 76 | case cidLoginUnused // = 0 77 | 78 | /// 登陆 79 | case cidLoginReqUserlogin // = 259 80 | case cidLoginResUserlogin // = 260 81 | 82 | /// 登出 83 | case cidLoginReqUserlogout // = 261 84 | case cidLoginResUserlogout // = 262 85 | case UNRECOGNIZED(Int) 86 | 87 | init() { 88 | self = .cidLoginUnused 89 | } 90 | 91 | init?(rawValue: Int) { 92 | switch rawValue { 93 | case 0: self = .cidLoginUnused 94 | case 259: self = .cidLoginReqUserlogin 95 | case 260: self = .cidLoginResUserlogin 96 | case 261: self = .cidLoginReqUserlogout 97 | case 262: self = .cidLoginResUserlogout 98 | default: self = .UNRECOGNIZED(rawValue) 99 | } 100 | } 101 | 102 | var rawValue: Int { 103 | switch self { 104 | case .cidLoginUnused: return 0 105 | case .cidLoginReqUserlogin: return 259 106 | case .cidLoginResUserlogin: return 260 107 | case .cidLoginReqUserlogout: return 261 108 | case .cidLoginResUserlogout: return 262 109 | case .UNRECOGNIZED(let i): return i 110 | } 111 | } 112 | 113 | } 114 | 115 | ///command 116 | enum IM_BaseDefine_MessageCmdID: SwiftProtobuf.Enum { 117 | typealias RawValue = Int 118 | case cidMsgUnused // = 0 119 | case cidMsgData // = 769 120 | case cidMsgDataAck // = 770 121 | case UNRECOGNIZED(Int) 122 | 123 | init() { 124 | self = .cidMsgUnused 125 | } 126 | 127 | init?(rawValue: Int) { 128 | switch rawValue { 129 | case 0: self = .cidMsgUnused 130 | case 769: self = .cidMsgData 131 | case 770: self = .cidMsgDataAck 132 | default: self = .UNRECOGNIZED(rawValue) 133 | } 134 | } 135 | 136 | var rawValue: Int { 137 | switch self { 138 | case .cidMsgUnused: return 0 139 | case .cidMsgData: return 769 140 | case .cidMsgDataAck: return 770 141 | case .UNRECOGNIZED(let i): return i 142 | } 143 | } 144 | 145 | } 146 | 147 | ///command 148 | enum IM_BaseDefine_GameCmdID: SwiftProtobuf.Enum { 149 | typealias RawValue = Int 150 | case cidGobangUnused // = 0 151 | 152 | ///五子棋 153 | case cidGobangData // = 1 154 | 155 | ///五子棋 156 | case cidGobangAck // = 2 157 | case UNRECOGNIZED(Int) 158 | 159 | init() { 160 | self = .cidGobangUnused 161 | } 162 | 163 | init?(rawValue: Int) { 164 | switch rawValue { 165 | case 0: self = .cidGobangUnused 166 | case 1: self = .cidGobangData 167 | case 2: self = .cidGobangAck 168 | default: self = .UNRECOGNIZED(rawValue) 169 | } 170 | } 171 | 172 | var rawValue: Int { 173 | switch self { 174 | case .cidGobangUnused: return 0 175 | case .cidGobangData: return 1 176 | case .cidGobangAck: return 2 177 | case .UNRECOGNIZED(let i): return i 178 | } 179 | } 180 | 181 | } 182 | 183 | ///command 184 | enum IM_BaseDefine_AudioCmdID: SwiftProtobuf.Enum { 185 | typealias RawValue = Int 186 | case cidAudioUnused // = 0 187 | 188 | ///语音 189 | case cidAudioData // = 1 190 | 191 | ///语音 192 | case cidAudioAck // = 2 193 | case UNRECOGNIZED(Int) 194 | 195 | init() { 196 | self = .cidAudioUnused 197 | } 198 | 199 | init?(rawValue: Int) { 200 | switch rawValue { 201 | case 0: self = .cidAudioUnused 202 | case 1: self = .cidAudioData 203 | case 2: self = .cidAudioAck 204 | default: self = .UNRECOGNIZED(rawValue) 205 | } 206 | } 207 | 208 | var rawValue: Int { 209 | switch self { 210 | case .cidAudioUnused: return 0 211 | case .cidAudioData: return 1 212 | case .cidAudioAck: return 2 213 | case .UNRECOGNIZED(let i): return i 214 | } 215 | } 216 | 217 | } 218 | 219 | enum IM_BaseDefine_OtherCmdID: SwiftProtobuf.Enum { 220 | typealias RawValue = Int 221 | case cidOtherUnused // = 0 222 | case cidOtherHeartbeat // = 1793 223 | case cidOtherStopRecvPacket // = 1794 224 | case UNRECOGNIZED(Int) 225 | 226 | init() { 227 | self = .cidOtherUnused 228 | } 229 | 230 | init?(rawValue: Int) { 231 | switch rawValue { 232 | case 0: self = .cidOtherUnused 233 | case 1793: self = .cidOtherHeartbeat 234 | case 1794: self = .cidOtherStopRecvPacket 235 | default: self = .UNRECOGNIZED(rawValue) 236 | } 237 | } 238 | 239 | var rawValue: Int { 240 | switch self { 241 | case .cidOtherUnused: return 0 242 | case .cidOtherHeartbeat: return 1793 243 | case .cidOtherStopRecvPacket: return 1794 244 | case .UNRECOGNIZED(let i): return i 245 | } 246 | } 247 | 248 | } 249 | 250 | enum IM_BaseDefine_ResultType: SwiftProtobuf.Enum { 251 | typealias RawValue = Int 252 | case ok // = 0 253 | case refused // = 1 254 | case UNRECOGNIZED(Int) 255 | 256 | init() { 257 | self = .ok 258 | } 259 | 260 | init?(rawValue: Int) { 261 | switch rawValue { 262 | case 0: self = .ok 263 | case 1: self = .refused 264 | default: self = .UNRECOGNIZED(rawValue) 265 | } 266 | } 267 | 268 | var rawValue: Int { 269 | switch self { 270 | case .ok: return 0 271 | case .refused: return 1 272 | case .UNRECOGNIZED(let i): return i 273 | } 274 | } 275 | 276 | } 277 | 278 | enum IM_BaseDefine_ClientType: SwiftProtobuf.Enum { 279 | typealias RawValue = Int 280 | case unknown // = 0 281 | case android // = 1 282 | case ios // = 2 283 | case windows // = 3 284 | case mac // = 4 285 | case webim // = 5 286 | case UNRECOGNIZED(Int) 287 | 288 | init() { 289 | self = .unknown 290 | } 291 | 292 | init?(rawValue: Int) { 293 | switch rawValue { 294 | case 0: self = .unknown 295 | case 1: self = .android 296 | case 2: self = .ios 297 | case 3: self = .windows 298 | case 4: self = .mac 299 | case 5: self = .webim 300 | default: self = .UNRECOGNIZED(rawValue) 301 | } 302 | } 303 | 304 | var rawValue: Int { 305 | switch self { 306 | case .unknown: return 0 307 | case .android: return 1 308 | case .ios: return 2 309 | case .windows: return 3 310 | case .mac: return 4 311 | case .webim: return 5 312 | case .UNRECOGNIZED(let i): return i 313 | } 314 | } 315 | 316 | } 317 | 318 | // MARK: - Code below here is support for the SwiftProtobuf runtime. 319 | 320 | extension IM_BaseDefine_ServiceID: SwiftProtobuf._ProtoNameProviding { 321 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 322 | 0: .same(proto: "SID_UNUSED"), 323 | 1: .same(proto: "SID_LOGIN"), 324 | 3: .same(proto: "SID_MSG"), 325 | 4: .same(proto: "SID_GAME"), 326 | 5: .same(proto: "SID_AUDIO"), 327 | 257: .same(proto: "SID_OTHER"), 328 | ] 329 | } 330 | 331 | extension IM_BaseDefine_LoginCmdID: SwiftProtobuf._ProtoNameProviding { 332 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 333 | 0: .same(proto: "CID_LOGIN_UNUSED"), 334 | 259: .same(proto: "CID_LOGIN_REQ_USERLOGIN"), 335 | 260: .same(proto: "CID_LOGIN_RES_USERLOGIN"), 336 | 261: .same(proto: "CID_LOGIN_REQ_USERLOGOUT"), 337 | 262: .same(proto: "CID_LOGIN_RES_USERLOGOUT"), 338 | ] 339 | } 340 | 341 | extension IM_BaseDefine_MessageCmdID: SwiftProtobuf._ProtoNameProviding { 342 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 343 | 0: .same(proto: "CID_MSG_UNUSED"), 344 | 769: .same(proto: "CID_MSG_DATA"), 345 | 770: .same(proto: "CID_MSG_DATA_ACK"), 346 | ] 347 | } 348 | 349 | extension IM_BaseDefine_GameCmdID: SwiftProtobuf._ProtoNameProviding { 350 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 351 | 0: .same(proto: "CID_GOBANG_UNUSED"), 352 | 1: .same(proto: "CID_GOBANG_DATA"), 353 | 2: .same(proto: "CID_GOBANG_ACK"), 354 | ] 355 | } 356 | 357 | extension IM_BaseDefine_AudioCmdID: SwiftProtobuf._ProtoNameProviding { 358 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 359 | 0: .same(proto: "CID_AUDIO_UNUSED"), 360 | 1: .same(proto: "CID_AUDIO_DATA"), 361 | 2: .same(proto: "CID_AUDIO_ACK"), 362 | ] 363 | } 364 | 365 | extension IM_BaseDefine_OtherCmdID: SwiftProtobuf._ProtoNameProviding { 366 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 367 | 0: .same(proto: "CID_OTHER_UNUSED"), 368 | 1793: .same(proto: "CID_OTHER_HEARTBEAT"), 369 | 1794: .same(proto: "CID_OTHER_STOP_RECV_PACKET"), 370 | ] 371 | } 372 | 373 | extension IM_BaseDefine_ResultType: SwiftProtobuf._ProtoNameProviding { 374 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 375 | 0: .same(proto: "Ok"), 376 | 1: .same(proto: "REFUSED"), 377 | ] 378 | } 379 | 380 | extension IM_BaseDefine_ClientType: SwiftProtobuf._ProtoNameProviding { 381 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 382 | 0: .same(proto: "CLIENT_TYPE_UNKNOWN"), 383 | 1: .same(proto: "CLIENT_TYPE_ANDROID"), 384 | 2: .same(proto: "CLIENT_TYPE_IOS"), 385 | 3: .same(proto: "CLIENT_TYPE_WINDOWS"), 386 | 4: .same(proto: "CLIENT_TYPE_MAC"), 387 | 5: .same(proto: "CLIENT_TYPE_WEBIM"), 388 | ] 389 | } 390 | -------------------------------------------------------------------------------- /Sources/App/Protobuf/IM.Message.pb.swift: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. 2 | // 3 | // Generated by the Swift generator plugin for the protocol buffer compiler. 4 | // Source: IM.Message.proto 5 | // 6 | // For information on using the generated types, please see the documenation: 7 | // https://github.com/apple/swift-protobuf/ 8 | 9 | import Foundation 10 | import SwiftProtobuf 11 | 12 | // If the compiler emits an error on this type, it is because this file 13 | // was generated by a version of the `protoc` Swift plug-in that is 14 | // incompatible with the version of SwiftProtobuf to which you are linking. 15 | // Please ensure that your are building against the same version of the API 16 | // that was used to generate this file. 17 | fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { 18 | struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} 19 | typealias Version = _2 20 | } 21 | 22 | ///service id 0x0003 23 | struct IM_Message_IMMsgData: SwiftProtobuf.Message { 24 | static let protoMessageName: String = _protobuf_package + ".IMMsgData" 25 | 26 | ///cmd id: 0x0301 27 | var type: String = String() 28 | 29 | /// 消息子类型 m_txt,m_image,m_audio,m_video,m_location等 30 | var subtype: String = String() 31 | 32 | /// 消息发送方 33 | var from: String = String() 34 | 35 | /// 消息接受方,个人的id,或者群组的id 36 | var to: String = String() 37 | 38 | /// 服务端维护 39 | var msgID: String = String() 40 | 41 | /// 消息数据,json格式 42 | var msgData: String = String() 43 | 44 | /// 服务端时间戳 45 | var createTime: UInt32 = 0 46 | 47 | var unknownFields = SwiftProtobuf.UnknownStorage() 48 | 49 | init() {} 50 | 51 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 52 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 53 | /// initializers are defined in the SwiftProtobuf library. See the Message and 54 | /// Message+*Additions` files. 55 | mutating func decodeMessage(decoder: inout D) throws { 56 | while let fieldNumber = try decoder.nextFieldNumber() { 57 | switch fieldNumber { 58 | case 1: try decoder.decodeSingularStringField(value: &self.type) 59 | case 2: try decoder.decodeSingularStringField(value: &self.subtype) 60 | case 3: try decoder.decodeSingularStringField(value: &self.from) 61 | case 4: try decoder.decodeSingularStringField(value: &self.to) 62 | case 5: try decoder.decodeSingularStringField(value: &self.msgID) 63 | case 6: try decoder.decodeSingularStringField(value: &self.msgData) 64 | case 7: try decoder.decodeSingularUInt32Field(value: &self.createTime) 65 | default: break 66 | } 67 | } 68 | } 69 | 70 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 71 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 72 | /// other serializer methods are defined in the SwiftProtobuf library. See the 73 | /// `Message` and `Message+*Additions` files. 74 | func traverse(visitor: inout V) throws { 75 | if !self.type.isEmpty { 76 | try visitor.visitSingularStringField(value: self.type, fieldNumber: 1) 77 | } 78 | if !self.subtype.isEmpty { 79 | try visitor.visitSingularStringField(value: self.subtype, fieldNumber: 2) 80 | } 81 | if !self.from.isEmpty { 82 | try visitor.visitSingularStringField(value: self.from, fieldNumber: 3) 83 | } 84 | if !self.to.isEmpty { 85 | try visitor.visitSingularStringField(value: self.to, fieldNumber: 4) 86 | } 87 | if !self.msgID.isEmpty { 88 | try visitor.visitSingularStringField(value: self.msgID, fieldNumber: 5) 89 | } 90 | if !self.msgData.isEmpty { 91 | try visitor.visitSingularStringField(value: self.msgData, fieldNumber: 6) 92 | } 93 | if self.createTime != 0 { 94 | try visitor.visitSingularUInt32Field(value: self.createTime, fieldNumber: 7) 95 | } 96 | try unknownFields.traverse(visitor: &visitor) 97 | } 98 | } 99 | 100 | struct IM_Message_IMMsgDataAck: SwiftProtobuf.Message { 101 | static let protoMessageName: String = _protobuf_package + ".IMMsgDataAck" 102 | 103 | ///cmd id: 0x0302 104 | var errCode: String = String() 105 | 106 | /// 错误消息 107 | var errMsg: String = String() 108 | 109 | /// 发送成功后server会改写为实际的消息ID 110 | var msgID: String = String() 111 | 112 | /// 消息对应服务器时间戳 113 | var createTime: String = String() 114 | 115 | var unknownFields = SwiftProtobuf.UnknownStorage() 116 | 117 | init() {} 118 | 119 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 120 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 121 | /// initializers are defined in the SwiftProtobuf library. See the Message and 122 | /// Message+*Additions` files. 123 | mutating func decodeMessage(decoder: inout D) throws { 124 | while let fieldNumber = try decoder.nextFieldNumber() { 125 | switch fieldNumber { 126 | case 1: try decoder.decodeSingularStringField(value: &self.errCode) 127 | case 2: try decoder.decodeSingularStringField(value: &self.errMsg) 128 | case 3: try decoder.decodeSingularStringField(value: &self.msgID) 129 | case 4: try decoder.decodeSingularStringField(value: &self.createTime) 130 | default: break 131 | } 132 | } 133 | } 134 | 135 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 136 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 137 | /// other serializer methods are defined in the SwiftProtobuf library. See the 138 | /// `Message` and `Message+*Additions` files. 139 | func traverse(visitor: inout V) throws { 140 | if !self.errCode.isEmpty { 141 | try visitor.visitSingularStringField(value: self.errCode, fieldNumber: 1) 142 | } 143 | if !self.errMsg.isEmpty { 144 | try visitor.visitSingularStringField(value: self.errMsg, fieldNumber: 2) 145 | } 146 | if !self.msgID.isEmpty { 147 | try visitor.visitSingularStringField(value: self.msgID, fieldNumber: 3) 148 | } 149 | if !self.createTime.isEmpty { 150 | try visitor.visitSingularStringField(value: self.createTime, fieldNumber: 4) 151 | } 152 | try unknownFields.traverse(visitor: &visitor) 153 | } 154 | } 155 | 156 | struct IM_Message_IMGroupChange: SwiftProtobuf.Message { 157 | static let protoMessageName: String = _protobuf_package + ".IMGroupChange" 158 | 159 | var uid: String = String() 160 | 161 | var changeType: String = String() 162 | 163 | var gid: String = String() 164 | 165 | ///现有的成员id 166 | var curUidList: [String] = [] 167 | 168 | ///add: 表示添加成功的id, del: 表示删除的id 169 | var chgUidList: [String] = [] 170 | 171 | var unknownFields = SwiftProtobuf.UnknownStorage() 172 | 173 | init() {} 174 | 175 | /// Used by the decoding initializers in the SwiftProtobuf library, not generally 176 | /// used directly. `init(serializedData:)`, `init(jsonUTF8Data:)`, and other decoding 177 | /// initializers are defined in the SwiftProtobuf library. See the Message and 178 | /// Message+*Additions` files. 179 | mutating func decodeMessage(decoder: inout D) throws { 180 | while let fieldNumber = try decoder.nextFieldNumber() { 181 | switch fieldNumber { 182 | case 1: try decoder.decodeSingularStringField(value: &self.uid) 183 | case 2: try decoder.decodeSingularStringField(value: &self.changeType) 184 | case 3: try decoder.decodeSingularStringField(value: &self.gid) 185 | case 4: try decoder.decodeRepeatedStringField(value: &self.curUidList) 186 | case 5: try decoder.decodeRepeatedStringField(value: &self.chgUidList) 187 | default: break 188 | } 189 | } 190 | } 191 | 192 | /// Used by the encoding methods of the SwiftProtobuf library, not generally 193 | /// used directly. `Message.serializedData()`, `Message.jsonUTF8Data()`, and 194 | /// other serializer methods are defined in the SwiftProtobuf library. See the 195 | /// `Message` and `Message+*Additions` files. 196 | func traverse(visitor: inout V) throws { 197 | if !self.uid.isEmpty { 198 | try visitor.visitSingularStringField(value: self.uid, fieldNumber: 1) 199 | } 200 | if !self.changeType.isEmpty { 201 | try visitor.visitSingularStringField(value: self.changeType, fieldNumber: 2) 202 | } 203 | if !self.gid.isEmpty { 204 | try visitor.visitSingularStringField(value: self.gid, fieldNumber: 3) 205 | } 206 | if !self.curUidList.isEmpty { 207 | try visitor.visitRepeatedStringField(value: self.curUidList, fieldNumber: 4) 208 | } 209 | if !self.chgUidList.isEmpty { 210 | try visitor.visitRepeatedStringField(value: self.chgUidList, fieldNumber: 5) 211 | } 212 | try unknownFields.traverse(visitor: &visitor) 213 | } 214 | } 215 | 216 | // MARK: - Code below here is support for the SwiftProtobuf runtime. 217 | 218 | fileprivate let _protobuf_package = "IM.Message" 219 | 220 | extension IM_Message_IMMsgData: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 221 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 222 | 1: .same(proto: "type"), 223 | 2: .same(proto: "subtype"), 224 | 3: .same(proto: "from"), 225 | 4: .same(proto: "to"), 226 | 5: .standard(proto: "msg_id"), 227 | 6: .standard(proto: "msg_data"), 228 | 7: .standard(proto: "create_time"), 229 | ] 230 | 231 | func _protobuf_generated_isEqualTo(other: IM_Message_IMMsgData) -> Bool { 232 | if self.type != other.type {return false} 233 | if self.subtype != other.subtype {return false} 234 | if self.from != other.from {return false} 235 | if self.to != other.to {return false} 236 | if self.msgID != other.msgID {return false} 237 | if self.msgData != other.msgData {return false} 238 | if self.createTime != other.createTime {return false} 239 | if unknownFields != other.unknownFields {return false} 240 | return true 241 | } 242 | } 243 | 244 | extension IM_Message_IMMsgDataAck: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 245 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 246 | 1: .standard(proto: "err_code"), 247 | 2: .standard(proto: "err_msg"), 248 | 3: .standard(proto: "msg_id"), 249 | 4: .standard(proto: "create_time"), 250 | ] 251 | 252 | func _protobuf_generated_isEqualTo(other: IM_Message_IMMsgDataAck) -> Bool { 253 | if self.errCode != other.errCode {return false} 254 | if self.errMsg != other.errMsg {return false} 255 | if self.msgID != other.msgID {return false} 256 | if self.createTime != other.createTime {return false} 257 | if unknownFields != other.unknownFields {return false} 258 | return true 259 | } 260 | } 261 | 262 | extension IM_Message_IMGroupChange: SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 263 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 264 | 1: .same(proto: "uid"), 265 | 2: .standard(proto: "change_type"), 266 | 3: .same(proto: "gid"), 267 | 4: .standard(proto: "cur_uid_list"), 268 | 5: .standard(proto: "chg_uid_list"), 269 | ] 270 | 271 | func _protobuf_generated_isEqualTo(other: IM_Message_IMGroupChange) -> Bool { 272 | if self.uid != other.uid {return false} 273 | if self.changeType != other.changeType {return false} 274 | if self.gid != other.gid {return false} 275 | if self.curUidList != other.curUidList {return false} 276 | if self.chgUidList != other.chgUidList {return false} 277 | if unknownFields != other.unknownFields {return false} 278 | return true 279 | } 280 | } 281 | --------------------------------------------------------------------------------