├── .gitignore ├── .travis.yml ├── README.md ├── build.gradle ├── ci └── travis.sh ├── example-idl ├── build.gradle ├── gradle │ └── dependency-locks │ │ ├── annotationProcessor.lockfile │ │ ├── compile.lockfile │ │ ├── compileClasspath.lockfile │ │ ├── kotlinCompilerClasspath.lockfile │ │ ├── kotlinCompilerPluginClasspath.lockfile │ │ ├── protobuf.lockfile │ │ ├── protobufToolsLocator_protoc.lockfile │ │ ├── testCompile.lockfile │ │ ├── testCompileClasspath.lockfile │ │ └── testProtobuf.lockfile └── src │ └── main │ └── proto │ └── example.proto ├── example ├── build.gradle ├── gradle │ └── dependency-locks │ │ ├── annotationProcessor.lockfile │ │ ├── compile.lockfile │ │ ├── compileClasspath.lockfile │ │ ├── kotlinCompilerClasspath.lockfile │ │ ├── kotlinCompilerPluginClasspath.lockfile │ │ ├── protobuf.lockfile │ │ ├── protobufToolsLocator_protoc.lockfile │ │ ├── runtimeClasspath.lockfile │ │ ├── testCompile.lockfile │ │ ├── testCompileClasspath.lockfile │ │ └── testProtobuf.lockfile └── src │ └── main │ ├── kotlin │ └── io │ │ └── rsocket │ │ └── rpc │ │ └── kotlin │ │ └── example │ │ └── RpcExample.kt │ └── resources │ └── log4j.properties ├── gradle.properties ├── gradle ├── bintray.gradle ├── dependency-management.gradle ├── publishing-compiler.gradle ├── publishing-library.gradle ├── publishing-pom.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── rsocket-rpc-core ├── build.gradle ├── gradle │ └── dependency-locks │ │ ├── annotationProcessor.lockfile │ │ ├── compile.lockfile │ │ ├── compileClasspath.lockfile │ │ ├── kotlinCompilerClasspath.lockfile │ │ ├── kotlinCompilerPluginClasspath.lockfile │ │ ├── protobuf.lockfile │ │ ├── protobufToolsLocator_protoc.lockfile │ │ ├── testAnnotationProcessor.lockfile │ │ ├── testCompile.lockfile │ │ ├── testCompileClasspath.lockfile │ │ ├── testProtobuf.lockfile │ │ └── testRuntimeClasspath.lockfile └── src │ └── main │ └── kotlin │ └── io │ └── rsocket │ └── rpc │ └── kotlin │ ├── AbstractRSocketService.kt │ ├── RSocketRpcService.kt │ ├── annotations │ ├── Annotation.kt │ ├── Generated.kt │ ├── GeneratedMethod.kt │ └── ResourceType.kt │ ├── exception │ └── ServiceNotFound.kt │ ├── frames │ └── Metadata.kt │ ├── rsocket │ └── RequestHandlingRSocket.kt │ ├── tracing │ ├── ImmutableTag.kt │ ├── Tag.kt │ ├── TraceOperator.kt │ ├── TraceSubscriber.kt │ └── Tracing.kt │ └── util │ └── StreamSplitter.kt ├── rsocket-rpc-protobuf-idl ├── build.gradle ├── gradle │ └── dependency-locks │ │ ├── compile.lockfile │ │ ├── compileClasspath.lockfile │ │ ├── kotlinCompilerClasspath.lockfile │ │ ├── protobuf.lockfile │ │ ├── testCompile.lockfile │ │ ├── testCompileClasspath.lockfile │ │ └── testProtobuf.lockfile └── src │ └── main │ └── proto │ └── rsocket │ └── options.proto ├── rsocket-rpc-protobuf ├── build.gradle ├── gradle │ └── dependency-locks │ │ ├── compile.lockfile │ │ ├── compileClasspath.lockfile │ │ ├── kotlinCompilerClasspath.lockfile │ │ ├── protobuf.lockfile │ │ ├── protobufToolsLocator_protoc.lockfile │ │ ├── testCompile.lockfile │ │ ├── testCompileClasspath.lockfile │ │ └── testProtobuf.lockfile └── src │ └── kotlin_plugin │ └── cpp │ ├── kotlin_generator.cpp │ ├── kotlin_generator.h │ ├── kotlin_plugin.cpp │ └── rsocket │ ├── options.pb.cc │ └── options.pb.h ├── settings.gradle └── test ├── build.gradle ├── gradle └── dependency-locks │ ├── compile.lockfile │ ├── compileClasspath.lockfile │ ├── kotlinCompilerClasspath.lockfile │ ├── kotlinCompilerPluginClasspath.lockfile │ ├── protobuf.lockfile │ ├── protobufToolsLocator_protoc.lockfile │ ├── testAnnotationProcessor.lockfile │ ├── testCompile.lockfile │ ├── testCompileClasspath.lockfile │ ├── testProtobuf.lockfile │ └── testRuntimeClasspath.lockfile └── src ├── main └── kotlin │ └── io │ └── rsocket │ └── rpc │ └── kotlin │ └── transport │ └── internal │ └── netty │ ├── Ext.kt │ ├── InternalWebsocketDuplexConnection.kt │ └── server │ ├── CloseableChannel.kt │ └── InternalWebsocketServerTransport.kt └── test ├── kotlin └── io │ └── rsocket │ └── rpc │ └── kotlin │ ├── InteractionsTest.kt │ └── util │ └── LongTest.kt └── proto └── test.proto /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/gradle,intellij,java,linux,osx 2 | 3 | ### Proteus ### 4 | *.db 5 | 6 | ### Intellij ### 7 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 8 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 9 | 10 | .idea 11 | 12 | ## File-based project format: 13 | *.iws 14 | 15 | ## Plugin-specific files: 16 | 17 | # IntelliJ 18 | **/out/ 19 | 20 | # mpeltonen/sbt-idea plugin 21 | .idea_modules/ 22 | 23 | # JIRA plugin 24 | atlassian-ide-plugin.xml 25 | 26 | # Crashlytics plugin (for Android Studio and IntelliJ) 27 | com_crashlytics_export_strings.xml 28 | crashlytics.properties 29 | crashlytics-build.properties 30 | fabric.properties 31 | 32 | ### Intellij Patch ### 33 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 34 | 35 | *.iml 36 | # modules.xml 37 | 38 | 39 | ### OSX ### 40 | *.DS_Store 41 | .AppleDouble 42 | .LSOverride 43 | 44 | # Icon must end with two \r 45 | Icon 46 | 47 | 48 | # Thumbnails 49 | ._* 50 | 51 | # Files that might appear in the root of a volume 52 | .DocumentRevisions-V100 53 | .fseventsd 54 | .Spotlight-V100 55 | .TemporaryItems 56 | .Trashes 57 | .VolumeIcon.icns 58 | .com.apple.timemachine.donotpresent 59 | 60 | # Directories potentially created on remote AFP share 61 | .AppleDB 62 | .AppleDesktop 63 | Network Trash Folder 64 | Temporary Items 65 | .apdisk 66 | 67 | 68 | ### Java ### 69 | *.class 70 | classes 71 | .project 72 | 73 | # Mobile Tools for Java (J2ME) 74 | .mtj.tmp/ 75 | 76 | # Package Files # 77 | *.jar 78 | *.war 79 | *.ear 80 | 81 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 82 | hs_err_pid* 83 | 84 | 85 | ### Gradle ### 86 | .gradle 87 | **/build 88 | 89 | # Ignore Gradle GUI config 90 | gradle-app.setting 91 | 92 | # Local Gradle Properties 93 | gradle-local.properties 94 | 95 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 96 | !gradle-wrapper.jar 97 | 98 | # Cache of project 99 | .gradletasknamecache 100 | 101 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 102 | # gradle/wrapper/gradle-wrapper.properties 103 | ${sys:appHome} 104 | 105 | */logs/** 106 | **/generated 107 | *.db 108 | **/logs 109 | **/generated 110 | 111 | # Node JS Modules 112 | **/node_modules/ 113 | 114 | # Webpack 115 | main.bundle.js 116 | 117 | **/.settings 118 | **/bin/* 119 | gc.log* 120 | 121 | broker-console/src/main/resources/imgs/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | jobs: 3 | include: 4 | - stage: build 5 | language: cpp 6 | os: linux 7 | jdk: openjdk8 8 | before_install: 9 | - wget https://github.com/google/protobuf/releases/download/v3.6.1/protobuf-cpp-3.6.1.tar.gz 10 | - tar -xzvf protobuf-cpp-3.6.1.tar.gz 11 | - pushd protobuf-3.6.1 12 | - ./configure --disable-shared && make && sudo make install 13 | - popd 14 | script: "./ci/travis.sh" 15 | - stage: build 16 | language: cpp 17 | os: windows 18 | filter_secrets: false 19 | env: 20 | - GRADLE_OPTS="-Dorg.gradle.daemon=false" 21 | before_install: 22 | - rm -r "/c/Program Files (x86)/Microsoft Visual Studio 14.0" 23 | - export PATH=$PATH:"/c/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.16.27023/bin/HostX86/x64" 24 | - choco install -y adoptopenjdk8 25 | - export PATH=$PATH:"/c/Program Files/AdoptOpenJDK/jdk8u222-b10/bin" 26 | - wget https://github.com/google/protobuf/releases/download/v3.6.1/protobuf-cpp-3.6.1.tar.gz 27 | - tar -xzf protobuf-cpp-3.6.1.tar.gz 28 | - pushd protobuf-3.6.1/cmake 29 | - mkdir build && cd build 30 | - cmake -A x64 -DCMAKE_INSTALL_PREFIX="/c/Program Files/protobuf" -DCMAKE_CXX_FLAGS="-std=c++11 -EHsc" -Dprotobuf_BUILD_TESTS=OFF .. 31 | - cmake --build . --config Release --target install 32 | - popd 33 | script: "./ci/travis.sh" 34 | - stage: deploy 35 | language: cpp 36 | os: osx 37 | osx_image: xcode10.1 38 | compiler: clang 39 | before_install: 40 | - curl -O -L https://github.com/google/protobuf/releases/download/v3.6.1/protobuf-cpp-3.6.1.tar.gz 41 | - tar -xzf protobuf-cpp-3.6.1.tar.gz 42 | - pushd protobuf-3.6.1 43 | - ./autogen.sh 44 | - ./configure --disable-shared && make && sudo make install 45 | - popd 46 | script: "./ci/travis.sh" 47 | notifications: 48 | email: false 49 | before_cache: 50 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 51 | cache: 52 | directories: 53 | - $HOME/.gradle/caches/ 54 | - $HOME/.gradle/wrapper/ 55 | env: 56 | global: 57 | - bintrayUser=rsocket-admin 58 | - bintrayKey=34ef2bcc235ccf3d5be62527e978698ee5ea8e51 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RSOCKET RPC - KOTLIN 2 | [![Build Status](https://travis-ci.com/rsocket/rsocket-rpc-kotlin.svg?branch=develop)](https://travis-ci.com/rsocket/rsocket-rpc-kotlin) 3 | 4 | The standard [RSocket](http://rsocket.io) RPC implementation based on [RSocket-kotlin](https://github.com/rsocket/rsocket-kotlin), [RxJava2](https://github.com/ReactiveX/RxJava) and [Protocol Buffers](https://github.com/protocolbuffers/protobuf). 5 | [RSocket](https://github.com/rsocket/rsocket) is binary application protocol with pluggable transports which models all communication as [Reactive Streams](https://github.com/reactive-streams/reactive-streams-jvm/blob/master/README.md) of messages multiplexed over a single network connection, and never synchronously blocks while waiting for a response. 6 | 7 | ## Build and binaries 8 | 9 | Releases 10 | 11 | ```groovy 12 | repositories { 13 | maven { url 'https://oss.jfrog.org/libs-release' } 14 | } 15 | ``` 16 | 17 | ```groovy 18 | dependencies { 19 | compile 'io.rsocket.rpc.kotlin:rsocket-rpc-core:0.2.13' 20 | } 21 | ``` 22 | 23 | Snapshots 24 | 25 | ```groovy 26 | repositories { 27 | maven { url 'https://oss.jfrog.org/libs-snapshot' } 28 | } 29 | ``` 30 | 31 | ```groovy 32 | dependencies { 33 | compile 'io.rsocket.rpc.kotlin:rsocket-rpc-core:0.2.13-SNAPSHOT' 34 | } 35 | ``` 36 | 37 | ## Getting started 38 | 39 | ### Prerequisites 40 | 41 | * JDK7 42 | 43 | * [Protobuf](https://github.com/google/protobuf) compiler. RSocket RPC requires Protobuf 3.6.x or higher. 44 | 45 | Mac users can install the Protobuf compiler using Homebrew: 46 | 47 | $ brew install protobuf 48 | 49 | For other operating systems Protobuf compiler can be installed from pre-built packages hosted on the [Protobuf Releases](https://github.com/google/protobuf/releases) 50 | 51 | ### Services definition 52 | 53 | RPC relies on languages agnostic, Protocol Buffers based service definitions (IDL). 54 | IDL defines service (and its data types) as set of methods which correspond to RSocket protocol interactions: 55 | 56 | ``` 57 | message Request { 58 | string message = 1; 59 | } 60 | 61 | message Response { 62 | string message = 1; 63 | } 64 | 65 | service ExampleService { 66 | 67 | rpc RequestResponse (Request) returns (Response) {} 68 | 69 | rpc RequestStream (Request) returns (stream Response) {} 70 | 71 | rpc StreamRequest (stream Request) returns (Response) {} 72 | 73 | rpc Channel (stream Request) returns (stream Response) {} 74 | 75 | rpc FireAndForget(Request) returns (google.protobuf.Empty) { 76 | option (options).fire_and_forget = true; 77 | } 78 | } 79 | ``` 80 | 81 | ### Compilation 82 | 83 | RSocket RPC-Kotlin compiler generates `Service` interfaces, `Clients` and `Servers` for available IDLs. 84 | For gradle, RPC compiler can be configured as follows (check [example](https://github.com/rsocket/rsocket-rpc-kotlin/blob/develop/example/build.gradle) for full reference): 85 | ``` 86 | protobuf { 87 | generatedFilesBaseDir = "${projectDir}/src/generated" 88 | 89 | protoc { 90 | artifact = "com.google.protobuf:protoc" 91 | } 92 | plugins { 93 | rsocketRpcKotlin { 94 | path = kotlinPluginPath 95 | } 96 | } 97 | generateProtoTasks { 98 | all().each { task -> 99 | task.dependsOn ':rsocket-rpc-protobuf:kotlin_pluginExecutable' 100 | // Recompile protos when the codegen has been changed 101 | task.inputs.file kotlinPluginPath 102 | // Recompile protos when build.gradle has been changed, because 103 | // it's possible the version of protoc has been changed. 104 | task.inputs.file "${rootProject.projectDir}/build.gradle" 105 | task.plugins { 106 | rsocketRpcKotlin {} 107 | } 108 | } 109 | } 110 | } 111 | ``` 112 | 113 | Client and server can be constructed based on generated clients & servers, and RSocket-Kotlin implementation: 114 | ``` 115 | val server = RSocketFactory.receive() 116 | .acceptor { 117 | { _, rSocket -> 118 | /*RSocket is symmetric so both client and server have can have Client(requester) to make requests*/ 119 | Single.just( 120 | ExampleServiceServer(ServerAcceptor()) 121 | ) 122 | } 123 | /*transport is pluggable*/ 124 | }.transport(InternalWebsocketServerTransport.create("localhost", 0)) 125 | .start() 126 | .timeout(5, TimeUnit.SECONDS) 127 | .blockingGet() 128 | ``` 129 | 130 | Here, `ServerAcceptor` implements generated `ExampleService`, and is wired using generated `ExampleServiceServer` 131 | 132 | Client is constructed in similar fashion: 133 | ``` 134 | val rSocket = RSocketFactory 135 | .connect() 136 | /*transport is pluggable */ 137 | .transport(OkhttpWebsocketClientTransport.create(url)) 138 | .start() 139 | .timeout(5, TimeUnit.SECONDS) 140 | .blockingGet() 141 | 142 | /*Requester of client side of connection*/ 143 | val exampleClient = ExampleServiceClient(rSocket) 144 | ``` 145 | 146 | Generated `ExampleServiceClient` accepts `RSocket`. 147 | 148 | RSocket is symmetric, both RPC client and server can have requesters and responders, RPC support for this is available in 149 | [examples](https://github.com/rsocket/rsocket-rpc-kotlin/tree/develop/example) 150 | 151 | ## Development 152 | 153 | 1. Run the following Gradle command to build the project: 154 | 155 | $ ./gradlew clean build 156 | 157 | ## Bugs and Feedback 158 | 159 | For bugs, questions, and discussions please use the [Github Issues](https://github.com/rsocket/rsocket-rpc-kotlin/issues). 160 | 161 | ## License 162 | Copyright 2019 [Netifi Inc.](https://www.netifi.com) 163 | 164 | Licensed under the Apache License, Version 2.0 (the "License"); 165 | you may not use this file except in compliance with the License. 166 | You may obtain a copy of the License at 167 | 168 | http://www.apache.org/licenses/LICENSE-2.0 169 | 170 | Unless required by applicable law or agreed to in writing, software 171 | distributed under the License is distributed on an "AS IS" BASIS, 172 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 173 | See the License for the specific language governing permissions and 174 | limitations under the License. 175 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | plugins { 18 | // declare before any other plugin 19 | id 'com.google.osdetector' 20 | id 'com.palantir.git-version' 21 | id 'com.gradle.build-scan' 22 | id 'com.google.protobuf' apply false 23 | id 'com.github.johnrengelman.shadow' apply false 24 | id 'org.jetbrains.kotlin.jvm' apply false 25 | id 'io.spring.dependency-management' apply false 26 | } 27 | 28 | def versionSuffix = versionSuffix() 29 | 30 | allprojects { 31 | dependencyLocking { 32 | lockAllConfigurations() 33 | } 34 | 35 | project.version += versionSuffix 36 | println "project: ${project.name} version: ${project.version}" 37 | } 38 | 39 | subprojects { 40 | apply plugin: 'java-library' 41 | apply plugin: 'org.jetbrains.kotlin.jvm' 42 | apply plugin: 'com.google.protobuf' 43 | 44 | repositories { 45 | mavenCentral() 46 | maven { url 'https://oss.jfrog.org/oss-release-local' } 47 | } 48 | 49 | /*need to generate kdocs*/ 50 | tasks.withType(Javadoc).all { enabled = false } 51 | 52 | compileJava { 53 | options.compilerArgs << '-Xlint:all,-overloads,-rawtypes,-unchecked' 54 | options.warnings = false 55 | 56 | sourceCompatibility = 1.7 57 | targetCompatibility = 1.7 58 | } 59 | 60 | compileKotlin { 61 | kotlinOptions.jvmTarget = "1.6" 62 | } 63 | compileTestKotlin { 64 | kotlinOptions.jvmTarget = "1.6" 65 | } 66 | 67 | task sourcesJar(type: Jar, dependsOn: classes) { 68 | classifier = 'sources' 69 | from sourceSets.main.allSource 70 | baseName = "${project.name}" 71 | version = "${project.version}" 72 | } 73 | 74 | artifacts { 75 | archives sourcesJar, jar 76 | } 77 | } 78 | 79 | apply from: 'gradle/publishing-library.gradle' 80 | apply from: 'gradle/bintray.gradle' 81 | apply from: 'gradle/dependency-management.gradle' 82 | 83 | buildScan { 84 | termsOfServiceUrl = 'https://gradle.com/terms-of-service' 85 | termsOfServiceAgree = 'yes' 86 | } 87 | 88 | def versionSuffix() { 89 | def versionSuffix 90 | def branchName = project.findProperty('branch'); 91 | if (branchName == null) { 92 | def details = versionDetails() 93 | if (details != null) { 94 | branchName = details.branchName 95 | } 96 | } 97 | /*branch*/ 98 | if (branchName != null) { 99 | if (branchName == 'master') { 100 | versionSuffix = '' 101 | } else if (branchName == 'develop') { 102 | versionSuffix = '-SNAPSHOT' 103 | } else { 104 | versionSuffix = "-${branchName.replace("/", "-")}-SNAPSHOT" 105 | } 106 | /*tag*/ 107 | } else { 108 | versionSuffix = '' 109 | } 110 | return versionSuffix 111 | } -------------------------------------------------------------------------------- /ci/travis.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then 4 | 5 | echo -e "Build Pull Request #$TRAVIS_PULL_REQUEST => Branch [$TRAVIS_BRANCH]" 6 | ./gradlew \ 7 | -Pbranch="${TRAVIS_BRANCH}" \ 8 | -PvcProtobufLibs="/c/Program Files/protobuf/lib" -PvcProtobufInclude="/c/Program Files/protobuf/include" \ 9 | build 10 | 11 | elif [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" == "" ] ; then 12 | 13 | echo -e "Build Branch => Branch ['$TRAVIS_BRANCH']" 14 | ./gradlew \ 15 | -PbintrayUser="${bintrayUser}" -PbintrayKey="${bintrayKey}" \ 16 | -Pbranch="${TRAVIS_BRANCH}" \ 17 | -PvcProtobufLibs="/c/Program Files/protobuf/lib" -PvcProtobufInclude="/c/Program Files/protobuf/include" \ 18 | build artifactoryPublish --stacktrace 19 | else 20 | 21 | echo -e "Build Tag => Tag ['$TRAVIS_TAG']" 22 | ./gradlew \ 23 | -PvcProtobufLibs="/c/Program Files/protobuf/lib" -PvcProtobufInclude="/c/Program Files/protobuf/include" \ 24 | build 25 | 26 | fi 27 | 28 | -------------------------------------------------------------------------------- /example-idl/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'idea' 3 | } 4 | 5 | description = 'Example of using RSocket-kotlin RPC Library' 6 | 7 | dependencies { 8 | protobuf project (':rsocket-rpc-protobuf-idl') 9 | } 10 | 11 | protobuf { 12 | generateProtoTasks { 13 | all().each { task -> 14 | task.enabled = false 15 | } 16 | } 17 | } 18 | 19 | idea { 20 | module { 21 | sourceDirs += file("src/main/proto") 22 | } 23 | } -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/annotationProcessor.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/compile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/compileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/kotlinCompilerClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.intellij.deps:trove4j:1.0.20181211 5 | org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.50 6 | org.jetbrains.kotlin:kotlin-daemon-embeddable:1.3.50 7 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 8 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 9 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 11 | org.jetbrains:annotations:13.0 12 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/kotlinCompilerPluginClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 5 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 6 | org.jetbrains.kotlin:kotlin-scripting-common:1.3.50 7 | org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.3.50 8 | org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.3.50 9 | org.jetbrains.kotlin:kotlin-scripting-jvm:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 11 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 12 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1 13 | org.jetbrains:annotations:13.0 14 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/protobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/protobufToolsLocator_protoc.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protoc:3.6.1 5 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/testCompile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/testCompileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example-idl/gradle/dependency-locks/testProtobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example-idl/src/main/proto/example.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | syntax = "proto3"; 18 | 19 | package io.rsocket.rpc.kotlin.example.protos; 20 | 21 | import "google/protobuf/empty.proto"; 22 | import "rsocket/options.proto"; 23 | 24 | option java_package = "io.rsocket.rpc.kotlin.example.protos"; 25 | option java_outer_classname = "Test"; 26 | option java_multiple_files = true; 27 | 28 | message Request { 29 | string message = 1; 30 | } 31 | 32 | message Response { 33 | string message = 1; 34 | } 35 | 36 | service ExampleService { 37 | 38 | rpc RequestResponse (Request) returns (Response) {} 39 | 40 | rpc RequestStream (Request) returns (stream Response) {} 41 | 42 | rpc StreamRequest (stream Request) returns (Response) {} 43 | 44 | rpc Channel (stream Request) returns (stream Response) {} 45 | 46 | rpc DefaultChannel (stream Request) returns (stream Response) {} 47 | 48 | rpc FireAndForget(Request) returns (google.protobuf.Empty) { 49 | option (options).fire_and_forget = true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /example/build.gradle: -------------------------------------------------------------------------------- 1 | import static org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS 2 | import static org.apache.tools.ant.taskdefs.condition.Os.isFamily 3 | 4 | plugins { 5 | id 'application' 6 | id 'idea' 7 | } 8 | 9 | description = 'Example of using RSocket-kotlin RPC Library' 10 | 11 | application { 12 | mainClassName = "io.rsocket.rpc.kotlin.example.RpcExample" 13 | } 14 | 15 | dependencies { 16 | protobuf project(":example-idl") 17 | 18 | implementation project(":rsocket-rpc-core") 19 | /*provides internal netty-based websocket server transport */ 20 | implementation project(":test") 21 | /*provides okhttp-based websocket client transport */ 22 | implementation 'io.rsocket.kotlin:rsocket-transport-okhttp' 23 | implementation 'org.slf4j:slf4j-log4j12' 24 | } 25 | 26 | def protocPluginBaseName = "rsocket-rpc-protobuf-${osdetector.os}-${osdetector.arch}" 27 | def kotlinPluginPath = "$rootDir/rsocket-rpc-protobuf/build/exe/kotlin_plugin/$protocPluginBaseName" 28 | 29 | if(isFamily(FAMILY_WINDOWS)){ 30 | kotlinPluginPath = kotlinPluginPath + ".exe" 31 | } 32 | 33 | protobuf { 34 | generatedFilesBaseDir = "${projectDir}/src/generated" 35 | 36 | protoc { 37 | artifact = "com.google.protobuf:protoc" 38 | } 39 | plugins { 40 | rsocketRpcKotlin { 41 | path = kotlinPluginPath 42 | } 43 | } 44 | generateProtoTasks { 45 | all().each { task -> 46 | task.dependsOn ':rsocket-rpc-protobuf:kotlin_pluginExecutable' 47 | // Recompile protos when the codegen has been changed 48 | task.inputs.file kotlinPluginPath 49 | // Recompile protos when build.gradle has been changed, because 50 | // it's possible the version of protoc has been changed. 51 | task.inputs.file "${rootProject.projectDir}/build.gradle" 52 | task.plugins { 53 | rsocketRpcKotlin {} 54 | } 55 | } 56 | } 57 | } 58 | 59 | clean { 60 | delete protobuf.generatedFilesBaseDir 61 | } 62 | 63 | idea { 64 | module { 65 | sourceDirs += file("src/generated/main/java") 66 | sourceDirs += file("src/generated/main/rsocketRpcKotlin") 67 | 68 | generatedSourceDirs += file("src/generated/main/java") 69 | generatedSourceDirs += file("src/generated/main/rsocketRpcKotlin") 70 | } 71 | } -------------------------------------------------------------------------------- /example/gradle/dependency-locks/annotationProcessor.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/compile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/compileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | com.squareup.okhttp3:okhttp:3.14.2 6 | com.squareup.okio:okio:1.17.2 7 | io.netty:netty-buffer:4.1.37.Final 8 | io.netty:netty-codec-http2:4.1.36.Final 9 | io.netty:netty-codec-http:4.1.36.Final 10 | io.netty:netty-codec-socks:4.1.36.Final 11 | io.netty:netty-codec:4.1.36.Final 12 | io.netty:netty-common:4.1.37.Final 13 | io.netty:netty-handler-proxy:4.1.36.Final 14 | io.netty:netty-handler:4.1.36.Final 15 | io.netty:netty-resolver:4.1.36.Final 16 | io.netty:netty-transport-native-epoll:4.1.36.Final 17 | io.netty:netty-transport-native-unix-common:4.1.36.Final 18 | io.netty:netty-transport:4.1.36.Final 19 | io.opentracing:opentracing-api:0.31.0 20 | io.projectreactor.netty:reactor-netty:0.8.10.RELEASE 21 | io.projectreactor:reactor-core:3.2.10.RELEASE 22 | io.reactivex.rxjava2:rxjava:2.2.12 23 | io.rsocket.kotlin:rsocket-core:0.9.7 24 | io.rsocket.kotlin:rsocket-transport-okhttp:0.9.7 25 | javax.annotation:javax.annotation-api:1.3.2 26 | javax.inject:javax.inject:1 27 | log4j:log4j:1.2.17 28 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 29 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 30 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 31 | org.jetbrains:annotations:13.0 32 | org.reactivestreams:reactive-streams:1.0.2 33 | org.slf4j:slf4j-api:1.7.28 34 | org.slf4j:slf4j-log4j12:1.7.28 35 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/kotlinCompilerClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.intellij.deps:trove4j:1.0.20181211 5 | org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.50 6 | org.jetbrains.kotlin:kotlin-daemon-embeddable:1.3.50 7 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 8 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 9 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 11 | org.jetbrains:annotations:13.0 12 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/kotlinCompilerPluginClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 5 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 6 | org.jetbrains.kotlin:kotlin-scripting-common:1.3.50 7 | org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.3.50 8 | org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.3.50 9 | org.jetbrains.kotlin:kotlin-scripting-jvm:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 11 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 12 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1 13 | org.jetbrains:annotations:13.0 14 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/protobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/protobufToolsLocator_protoc.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protoc:3.6.1 5 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/runtimeClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | com.squareup.okhttp3:okhttp:3.14.2 6 | com.squareup.okio:okio:1.17.2 7 | io.netty:netty-buffer:4.1.37.Final 8 | io.netty:netty-codec-http2:4.1.36.Final 9 | io.netty:netty-codec-http:4.1.36.Final 10 | io.netty:netty-codec-socks:4.1.36.Final 11 | io.netty:netty-codec:4.1.36.Final 12 | io.netty:netty-common:4.1.37.Final 13 | io.netty:netty-handler-proxy:4.1.36.Final 14 | io.netty:netty-handler:4.1.36.Final 15 | io.netty:netty-resolver:4.1.36.Final 16 | io.netty:netty-transport-native-epoll:4.1.36.Final 17 | io.netty:netty-transport-native-unix-common:4.1.36.Final 18 | io.netty:netty-transport:4.1.36.Final 19 | io.opentracing:opentracing-api:0.31.0 20 | io.projectreactor.netty:reactor-netty:0.8.10.RELEASE 21 | io.projectreactor:reactor-core:3.2.10.RELEASE 22 | io.reactivex.rxjava2:rxjava:2.2.12 23 | io.rsocket.kotlin:rsocket-core:0.9.7 24 | io.rsocket.kotlin:rsocket-transport-okhttp:0.9.7 25 | javax.annotation:javax.annotation-api:1.3.2 26 | javax.inject:javax.inject:1 27 | log4j:log4j:1.2.17 28 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 29 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 30 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 31 | org.jetbrains:annotations:13.0 32 | org.reactivestreams:reactive-streams:1.0.2 33 | org.slf4j:slf4j-api:1.7.28 34 | org.slf4j:slf4j-log4j12:1.7.28 35 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/testCompile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/testCompileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | com.squareup.okhttp3:okhttp:3.14.2 6 | com.squareup.okio:okio:1.17.2 7 | io.netty:netty-buffer:4.1.37.Final 8 | io.netty:netty-codec-http2:4.1.36.Final 9 | io.netty:netty-codec-http:4.1.36.Final 10 | io.netty:netty-codec-socks:4.1.36.Final 11 | io.netty:netty-codec:4.1.36.Final 12 | io.netty:netty-common:4.1.37.Final 13 | io.netty:netty-handler-proxy:4.1.36.Final 14 | io.netty:netty-handler:4.1.36.Final 15 | io.netty:netty-resolver:4.1.36.Final 16 | io.netty:netty-transport-native-epoll:4.1.36.Final 17 | io.netty:netty-transport-native-unix-common:4.1.36.Final 18 | io.netty:netty-transport:4.1.36.Final 19 | io.opentracing:opentracing-api:0.31.0 20 | io.projectreactor.netty:reactor-netty:0.8.10.RELEASE 21 | io.projectreactor:reactor-core:3.2.10.RELEASE 22 | io.reactivex.rxjava2:rxjava:2.2.12 23 | io.rsocket.kotlin:rsocket-core:0.9.7 24 | io.rsocket.kotlin:rsocket-transport-okhttp:0.9.7 25 | javax.annotation:javax.annotation-api:1.3.2 26 | javax.inject:javax.inject:1 27 | log4j:log4j:1.2.17 28 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 29 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 30 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 31 | org.jetbrains:annotations:13.0 32 | org.reactivestreams:reactive-streams:1.0.2 33 | org.slf4j:slf4j-api:1.7.28 34 | org.slf4j:slf4j-log4j12:1.7.28 35 | -------------------------------------------------------------------------------- /example/gradle/dependency-locks/testProtobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /example/src/main/kotlin/io/rsocket/rpc/kotlin/example/RpcExample.kt: -------------------------------------------------------------------------------- 1 | package io.rsocket.rpc.kotlin.example 2 | 3 | import io.netty.buffer.ByteBuf 4 | import io.reactivex.Completable 5 | import io.reactivex.Flowable 6 | import io.reactivex.Single 7 | import io.rsocket.kotlin.RSocketFactory 8 | import io.rsocket.rpc.kotlin.example.protos.* 9 | import io.rsocket.rpc.kotlin.rsocket.RequestHandlingRSocket 10 | import io.rsocket.rpc.kotlin.transport.internal.netty.server.InternalWebsocketServerTransport 11 | import io.rsocket.transport.okhttp.client.OkhttpWebsocketClientTransport 12 | import okhttp3.HttpUrl 13 | import org.reactivestreams.Publisher 14 | import org.slf4j.LoggerFactory 15 | import java.net.InetSocketAddress 16 | import java.util.concurrent.TimeUnit 17 | 18 | class RpcExample { 19 | 20 | companion object { 21 | 22 | @JvmStatic 23 | fun main(args: Array) { 24 | 25 | val context = RSocketFactory.receive() 26 | .acceptor { 27 | { _, rSocket -> 28 | /*RSocket is symmetric so both client and server have can have Client(requester) to make requests*/ 29 | Single.just( 30 | ExampleServiceServer(ServerAcceptor(ExampleServiceClient(rSocket))) 31 | ) 32 | } 33 | /*transport is pluggable*/ 34 | }.transport(InternalWebsocketServerTransport.create("localhost", 0)) 35 | .start() 36 | .timeout(5, TimeUnit.SECONDS) 37 | .blockingGet() 38 | 39 | val url = createUrl(context.address()) 40 | 41 | val rSocket = RSocketFactory 42 | .connect() 43 | /*RSocket is symmetric so both client and server can have Server(responder) to respond to requests*/ 44 | .acceptor { { RequestHandlingRSocket(ExampleServiceServer(ClientAcceptor())) } } 45 | /*transport is pluggable */ 46 | .transport(OkhttpWebsocketClientTransport.create(url)) 47 | .start() 48 | .timeout(5, TimeUnit.SECONDS) 49 | .blockingGet() 50 | 51 | /*Requester of client side of connection*/ 52 | val exampleClient = ExampleServiceClient(rSocket) 53 | 54 | val fnf = 55 | Flowable.interval(7, TimeUnit.SECONDS) 56 | .onBackpressureDrop() 57 | .flatMapCompletable { exampleClient.fireAndForget(request("client fire-and-forget")) } 58 | 59 | val requestResponse = 60 | Flowable.interval(3, TimeUnit.SECONDS) 61 | .onBackpressureDrop() 62 | .flatMapSingle { exampleClient.requestResponse(request("client: request-response")) } 63 | 64 | val serverStream = 65 | exampleClient.requestStream(request("client: server stream request")) 66 | 67 | val clientStream = 68 | exampleClient.streamRequest( 69 | Flowable.interval(10, TimeUnit.SECONDS) 70 | .onBackpressureDrop() 71 | .map { request("client: client stream request") } 72 | ).toFlowable() 73 | 74 | val channel = 75 | exampleClient.channel( 76 | Flowable.interval(10, TimeUnit.SECONDS) 77 | .onBackpressureDrop() 78 | .map { request("client: channel request") }) 79 | 80 | Flowable.merge(Flowable.just(fnf.toFlowable(), requestResponse, serverStream, clientStream, channel)) 81 | .ignoreElements() 82 | .blockingAwait() 83 | } 84 | 85 | private fun createUrl(address: InetSocketAddress): HttpUrl = 86 | HttpUrl.Builder() 87 | .scheme("http") 88 | .host(address.hostName) 89 | .port(address.port) 90 | .build() 91 | } 92 | 93 | /*Request acceptor of server side of connection. It can initiate requests to client side acceptor 94 | with provided ExampleServiceClient*/ 95 | class ServerAcceptor(private val exampleService: ExampleServiceClient) : ExampleService { 96 | companion object { 97 | val logger = LoggerFactory.getLogger(ServerAcceptor::class.java) 98 | } 99 | 100 | override fun requestResponse(message: Request, metadata: ByteBuf): Single { 101 | return Single.defer { 102 | logger.info("Server acceptor received request response message") 103 | Single.just(response("server response")) 104 | } 105 | } 106 | 107 | override fun requestStream(message: Request, metadata: ByteBuf): Flowable = 108 | Flowable.interval(4, TimeUnit.SECONDS) 109 | .onBackpressureDrop() 110 | .map { response("server stream response") } 111 | 112 | override fun streamRequest(message: Publisher, metadata: ByteBuf): Single = 113 | Flowable.fromPublisher(message) 114 | .doOnNext { _ -> logger.info("Server acceptor received client streaming message") } 115 | .lastOrError() 116 | .map { m -> Response.newBuilder().setMessage(m.message).build() } 117 | 118 | override fun channel(message: Publisher, metadata: ByteBuf): Flowable = 119 | Flowable.fromPublisher(message) 120 | .doOnNext { _ -> logger.info("Server acceptor received channel message") } 121 | .map { m -> response(m.message) } 122 | 123 | override fun fireAndForget(message: Request, metadata: ByteBuf): Completable = 124 | Completable.defer { 125 | logger.info("Server acceptor received fire-and-forget message") 126 | exampleService.fireAndForget(request("Server acceptor fire-and-forget")) 127 | } 128 | } 129 | 130 | 131 | class ClientAcceptor : ExampleService { 132 | companion object { 133 | val logger = LoggerFactory.getLogger(ClientAcceptor::class.java) 134 | } 135 | 136 | override fun fireAndForget( 137 | message: Request, 138 | metadata: ByteBuf 139 | ): Completable = 140 | Completable.complete() 141 | .doOnSubscribe { logger.info("Client acceptor received fire-and-forget message") } 142 | } 143 | } 144 | 145 | private fun response(msg: String) = Response 146 | .newBuilder() 147 | .setMessage(msg) 148 | .build() 149 | 150 | private fun request(msg: String) = Request 151 | .newBuilder() 152 | .setMessage(msg) 153 | .build() -------------------------------------------------------------------------------- /example/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015-2018 the original author or authors. 3 | #

4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | # the License. You may obtain a copy of the License at 6 | #

7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | #

9 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | # specific language governing permissions and limitations under the License. 12 | # 13 | 14 | 15 | # 16 | # 17 | # Licensed under the Apache License, Version 2.0 (the "License"); 18 | # you may not use this file except in compliance with the License. 19 | # You may obtain a copy of the License at 20 | # 21 | # http://www.apache.org/licenses/LICENSE-2.0 22 | # 23 | # Unless required by applicable law or agreed to in writing, software 24 | # distributed under the License is distributed on an "AS IS" BASIS, 25 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 | # See the License for the specific language governing permissions and 27 | # limitations under the License. 28 | # 29 | log4j.rootLogger=INFO, stdout 30 | 31 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 32 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 33 | log4j.appender.stdout.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss,SSS} %5p [%t] (%F:%L) - %m%n -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2015-2018 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | group=io.rsocket.rpc.kotlin 18 | version=0.2.13 19 | 20 | osDetectorPluginVersion=1.6.2 21 | buildScanPluginVersion=2.4.1 22 | shadowPluginVersion=5.1.0 23 | dependencyManagementPluginVersion=1.0.8.RELEASE 24 | bintrayPluginVersion=1.8.4 25 | artifactoryPluginVersion=4.9.8 26 | kotlinPluginVersion=1.3.50 27 | gitPluginVersion=0.12.0-rc2 28 | protobufPluginVersion=0.8.10 29 | 30 | protobufVersion=3.6.1 31 | kotlinStdlibVersion=1.3.50 32 | nettyBufferVersion=4.1.37.Final 33 | rsocketKotlinVersion=0.9.7 34 | reactorNettyVersion=0.8.10.RELEASE 35 | opentracingVersion=0.31.0 36 | javaxInjectVersion =1 37 | javaxAnnotationVersion=1.3.2 38 | slf4jApiVersion=1.7.28 39 | slf4jLog4jVersion=1.7.28 40 | junit5Version=5.5.1 41 | assertjVersion=3.13.2 42 | 43 | kotlin.code.style=official -------------------------------------------------------------------------------- /gradle/bintray.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | if (project.hasProperty('bintrayUser') && project.hasProperty('bintrayKey')) { 18 | 19 | subprojects { 20 | plugins.withId('com.jfrog.bintray') { 21 | bintray { 22 | user = project.property('bintrayUser') 23 | key = project.property('bintrayKey') 24 | 25 | publications = ['maven'] 26 | publish = true 27 | override = true 28 | 29 | pkg { 30 | repo = 'RSocket' 31 | name = 'rsocket-rpc-kotlin' 32 | licenses = ['Apache-2.0'] 33 | 34 | issueTrackerUrl = 'https://github.com/rsocket/rsocket-rpc-kotlin/issues' 35 | websiteUrl = 'https://github.com/rsocket/rsocket-rpc-kotlin' 36 | vcsUrl = 'https://github.com/rsocket/rsocket-rpc-kotlin.git' 37 | 38 | githubRepo = 'rsocket/rsocket-rpc-kotlin' //Optional Github repository 39 | githubReleaseNotesFile = 'README.md' //Optional Github readme file 40 | 41 | version { 42 | name = project.version 43 | released = new Date() 44 | vcsTag = project.version 45 | 46 | gpg { 47 | sign = true 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | plugins.withId('com.jfrog.artifactory') { 55 | artifactory { 56 | publish { 57 | contextUrl = 'https://oss.jfrog.org' 58 | 59 | repository { 60 | repoKey = version.contains('SNAPSHOT') ? 'oss-snapshot-local' : 'oss-release-local' 61 | 62 | // Credentials for oss.jfrog.org are a user's Bintray credentials 63 | username = project.property('bintrayUser') 64 | password = project.property('bintrayKey') 65 | } 66 | 67 | defaults { 68 | publications('maven') 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /gradle/dependency-management.gradle: -------------------------------------------------------------------------------- 1 | subprojects { 2 | apply plugin: 'io.spring.dependency-management' 3 | 4 | dependencyManagement { 5 | dependencies { 6 | dependency "javax.inject:javax.inject:${javaxInjectVersion}" 7 | dependency "javax.annotation:javax.annotation-api:${javaxAnnotationVersion}" 8 | dependency "io.netty:netty-buffer:${nettyBufferVersion}" 9 | dependency "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${kotlinStdlibVersion}" 10 | dependency "com.google.protobuf:protobuf-java:${protobufVersion}" 11 | dependency "com.google.protobuf:protoc:${protobufVersion}" 12 | dependency "io.rsocket.kotlin:rsocket-core:${rsocketKotlinVersion}" 13 | dependency "io.opentracing:opentracing-api:${opentracingVersion}" 14 | dependency "org.slf4j:slf4j-api:${slf4jApiVersion}" 15 | dependency "org.slf4j:slf4j-log4j12:${slf4jLog4jVersion}" 16 | dependency "io.projectreactor.netty:reactor-netty:${reactorNettyVersion}" 17 | 18 | /*testing*/ 19 | dependency "io.rsocket.kotlin:rsocket-transport-okhttp:${rsocketKotlinVersion}" 20 | dependency "io.rsocket.kotlin:rsocket-transport-netty:${rsocketKotlinVersion}" 21 | dependency "org.assertj:assertj-core:${assertjVersion}" 22 | dependencySet(group: "org.junit.jupiter", version: "${junit5Version}") { 23 | entry "junit-jupiter-api" 24 | entry "junit-jupiter-engine" 25 | entry "junit-jupiter-params" 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /gradle/publishing-compiler.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | apply from: '../gradle/publishing-pom.gradle' 18 | 19 | publishing { 20 | publications { 21 | maven(MavenPublication) { 22 | groupId project.group 23 | 24 | from components.java 25 | 26 | def pluginPrefix = "rsocket-rpc-protobuf-${osdetector.os}-${osdetector.arch}" 27 | def pluginName = "${pluginPrefix}.exe" 28 | def artifactStagingPath = "$buildDir/artifacts" as File 29 | def pathToPlugin = "${artifactStagingPath.getPath()}/${pluginName}" 30 | 31 | artifact(pathToPlugin) { 32 | classifier osdetector.os + "-" + osdetector.arch 33 | builtBy buildArtifacts 34 | } 35 | 36 | configurePom(pom) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /gradle/publishing-library.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | subprojects { 18 | 19 | apply from: '../gradle/publishing-pom.gradle' 20 | 21 | if (project.name != 'rsocket-rpc-protobuf') { 22 | plugins.withType(MavenPublishPlugin) { 23 | publishing { 24 | publications { 25 | maven(MavenPublication) { 26 | groupId project.group 27 | 28 | from components.java 29 | 30 | artifact sourcesJar 31 | 32 | configurePom(pom) 33 | } 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /gradle/publishing-pom.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | project.ext.configurePom = { pom -> 18 | pom.withXml { 19 | asNode().':version' + { 20 | resolveStrategy = DELEGATE_FIRST 21 | 22 | name project.name 23 | description project.description 24 | url 'http://rsocket.io' 25 | 26 | licenses { 27 | license { 28 | name 'The Apache Software License, Version 2.0' 29 | url 'http://www.apache.org/license/LICENSE-2.0.txt' 30 | } 31 | } 32 | 33 | developers { 34 | developer { 35 | id 'robertroeser' 36 | name 'Robert Roeser' 37 | email 'robert@netifi.com' 38 | } 39 | developer { 40 | id 'rdegnan' 41 | name 'Ryland Degnan' 42 | email 'ryland@netifi.com' 43 | } 44 | developer { 45 | id 'mostroverkhov' 46 | name 'Maksym Ostroverkhov' 47 | email 'maksym@netifi.com' 48 | } 49 | } 50 | 51 | scm { 52 | connection 'scm:git:https://github.com/rsocket/rsocket-rpc-kotlin.git' 53 | developerConnection 'scm:git:https://github.com/rsocket/rsocket-rpc-kotlin.git' 54 | url 'https://github.com/rsocket/rsocket-rpc-kotlin' 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsocket/rsocket-rpc-kotlin/94f3cc316e93b10dd76a3310ee5e7c10dcaa70a9/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /rsocket-rpc-core/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | plugins { 18 | id 'com.jfrog.artifactory' 19 | id 'com.jfrog.bintray' 20 | id 'maven-publish' 21 | } 22 | 23 | description = 'RSocket-kotlin RPC Library' 24 | 25 | dependencies { 26 | api 'io.opentracing:opentracing-api' 27 | api 'io.rsocket.kotlin:rsocket-core' 28 | api 'com.google.protobuf:protobuf-java' 29 | api 'javax.inject:javax.inject' 30 | api 'javax.annotation:javax.annotation-api' 31 | api 'org.slf4j:slf4j-api' 32 | 33 | testImplementation 'org.junit.jupiter:junit-jupiter-api' 34 | testImplementation 'org.junit.jupiter:junit-jupiter-engine' 35 | testImplementation 'org.junit.jupiter:junit-jupiter-params' 36 | } 37 | 38 | test { 39 | useJUnitPlatform() 40 | testLogging { 41 | events "passed", "skipped", "failed" 42 | } 43 | } -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/annotationProcessor.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/compile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/compileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | io.netty:netty-buffer:4.1.37.Final 6 | io.netty:netty-common:4.1.37.Final 7 | io.opentracing:opentracing-api:0.31.0 8 | io.reactivex.rxjava2:rxjava:2.2.12 9 | io.rsocket.kotlin:rsocket-core:0.9.7 10 | javax.annotation:javax.annotation-api:1.3.2 11 | javax.inject:javax.inject:1 12 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 13 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 14 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 15 | org.jetbrains:annotations:13.0 16 | org.reactivestreams:reactive-streams:1.0.2 17 | org.slf4j:slf4j-api:1.7.28 18 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/kotlinCompilerClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.intellij.deps:trove4j:1.0.20181211 5 | org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.50 6 | org.jetbrains.kotlin:kotlin-daemon-embeddable:1.3.50 7 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 8 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 9 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 11 | org.jetbrains:annotations:13.0 12 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/kotlinCompilerPluginClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 5 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 6 | org.jetbrains.kotlin:kotlin-scripting-common:1.3.50 7 | org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.3.50 8 | org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.3.50 9 | org.jetbrains.kotlin:kotlin-scripting-jvm:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 11 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 12 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1 13 | org.jetbrains:annotations:13.0 14 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/protobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/protobufToolsLocator_protoc.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protoc:3.6.1 5 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/testAnnotationProcessor.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/testCompile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/testCompileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | io.netty:netty-buffer:4.1.37.Final 6 | io.netty:netty-common:4.1.37.Final 7 | io.opentracing:opentracing-api:0.31.0 8 | io.reactivex.rxjava2:rxjava:2.2.12 9 | io.rsocket.kotlin:rsocket-core:0.9.7 10 | javax.annotation:javax.annotation-api:1.3.2 11 | javax.inject:javax.inject:1 12 | org.apiguardian:apiguardian-api:1.1.0 13 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 14 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 15 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 16 | org.jetbrains:annotations:13.0 17 | org.junit.jupiter:junit-jupiter-api:5.5.1 18 | org.junit.jupiter:junit-jupiter-engine:5.5.1 19 | org.junit.jupiter:junit-jupiter-params:5.5.1 20 | org.junit.platform:junit-platform-commons:1.5.1 21 | org.junit.platform:junit-platform-engine:1.5.1 22 | org.opentest4j:opentest4j:1.2.0 23 | org.reactivestreams:reactive-streams:1.0.2 24 | org.slf4j:slf4j-api:1.7.28 25 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/testProtobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-core/gradle/dependency-locks/testRuntimeClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | io.netty:netty-buffer:4.1.37.Final 6 | io.netty:netty-common:4.1.37.Final 7 | io.opentracing:opentracing-api:0.31.0 8 | io.reactivex.rxjava2:rxjava:2.2.12 9 | io.rsocket.kotlin:rsocket-core:0.9.7 10 | javax.annotation:javax.annotation-api:1.3.2 11 | javax.inject:javax.inject:1 12 | org.apiguardian:apiguardian-api:1.1.0 13 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 14 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 15 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 16 | org.jetbrains:annotations:13.0 17 | org.junit.jupiter:junit-jupiter-api:5.5.1 18 | org.junit.jupiter:junit-jupiter-engine:5.5.1 19 | org.junit.jupiter:junit-jupiter-params:5.5.1 20 | org.junit.platform:junit-platform-commons:1.5.1 21 | org.junit.platform:junit-platform-engine:1.5.1 22 | org.opentest4j:opentest4j:1.2.0 23 | org.reactivestreams:reactive-streams:1.0.2 24 | org.slf4j:slf4j-api:1.7.28 25 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/AbstractRSocketService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin 18 | 19 | import io.reactivex.Flowable 20 | import io.rsocket.kotlin.Payload 21 | import io.rsocket.kotlin.util.AbstractRSocket 22 | 23 | abstract class AbstractRSocketService : AbstractRSocket(), RSocketRpcService { 24 | 25 | abstract val serviceClass: Class<*> 26 | 27 | override fun requestChannel(payload: Payload, publisher: Flowable): Flowable { 28 | return Flowable.error(UnsupportedOperationException("Request-Channel not implemented.")) 29 | } 30 | 31 | override fun availability(): Double = 1.0 32 | } 33 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/RSocketRpcService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin 18 | 19 | import io.reactivex.Flowable 20 | import io.rsocket.kotlin.Payload 21 | import io.rsocket.kotlin.RSocket 22 | 23 | interface RSocketRpcService : RSocket { 24 | 25 | val service: String 26 | 27 | fun requestChannel(payload: Payload, publisher: Flowable): Flowable 28 | } 29 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/annotations/Annotation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.annotations 18 | 19 | 20 | /** Meta-annotation that marks all RSocketRpc related annotations. */ 21 | @Target(AnnotationTarget.ANNOTATION_CLASS) 22 | @Retention(AnnotationRetention.RUNTIME) 23 | annotation class Annotation 24 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/annotations/Generated.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.annotations 18 | 19 | import kotlin.reflect.KClass 20 | 21 | /** 22 | * Annotation that identifies RSocketRpc generated services and stores metadata that can 23 | * be used by dependency injection frameworks and custom annotation processors. 24 | */ 25 | @Annotation 26 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) 27 | @Retention(AnnotationRetention.RUNTIME) 28 | annotation class Generated( 29 | /** 30 | * Type of the generated RSocketRpc resource. 31 | * 32 | * @return type of generated resource 33 | */ 34 | val type: ResourceType, 35 | /** 36 | * Class of the RSocketRpc service hosted by the annotated class. 37 | * 38 | * @return RSocketRpc service class 39 | */ 40 | val idlClass: KClass<*> 41 | ) 42 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/annotations/GeneratedMethod.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.annotations 18 | 19 | import io.rsocket.rpc.kotlin.annotations.Annotation 20 | import kotlin.reflect.KClass 21 | 22 | @Annotation 23 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) 24 | @Retention(AnnotationRetention.RUNTIME) 25 | annotation class GeneratedMethod( 26 | /** 27 | * Type of the class returned from the generated method. 28 | * 29 | * @return parameterized type of return class 30 | */ 31 | val returnTypeClass: KClass<*> 32 | ) 33 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/annotations/ResourceType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.annotations 18 | 19 | enum class ResourceType { 20 | CLIENT, 21 | SERVICE 22 | } 23 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/exception/ServiceNotFound.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.exception 18 | 19 | class ServiceNotFound(service: String) : RuntimeException("can not find service $service") { 20 | companion object { 21 | private const val serialVersionUID = 1L 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/frames/Metadata.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.frames 18 | 19 | import io.netty.buffer.ByteBuf 20 | import io.netty.buffer.ByteBufAllocator 21 | import io.netty.buffer.ByteBufUtil 22 | import io.netty.buffer.Unpooled 23 | import java.nio.charset.StandardCharsets 24 | 25 | object Metadata { 26 | // Version 27 | const val VERSION: Short = 1 28 | private const val SHORT_BYTES = Short.SIZE_BYTES 29 | 30 | @JvmStatic 31 | fun encode( 32 | allocator: ByteBufAllocator, 33 | service: String, 34 | method: String, 35 | metadata: ByteBuf): ByteBuf { 36 | return encode(allocator, service, method, Unpooled.EMPTY_BUFFER, metadata) 37 | } 38 | 39 | @JvmStatic 40 | fun encode( 41 | allocator: ByteBufAllocator, 42 | service: String, 43 | method: String, 44 | tracing: ByteBuf, 45 | metadata: ByteBuf): ByteBuf { 46 | val byteBuf = allocator.buffer().writeShort(VERSION.toInt()) 47 | 48 | val serviceLength = requireUnsignedShort(ByteBufUtil.utf8Bytes(service)) 49 | byteBuf.writeShort(serviceLength) 50 | ByteBufUtil.reserveAndWriteUtf8(byteBuf, service, serviceLength) 51 | 52 | val methodLength = requireUnsignedShort(ByteBufUtil.utf8Bytes(method)) 53 | byteBuf.writeShort(methodLength) 54 | ByteBufUtil.reserveAndWriteUtf8(byteBuf, method, methodLength) 55 | 56 | byteBuf.writeShort(tracing.readableBytes()) 57 | byteBuf.writeBytes(tracing) 58 | 59 | byteBuf.writeBytes(metadata, metadata.readerIndex(), metadata.readableBytes()) 60 | 61 | return byteBuf 62 | } 63 | 64 | @JvmStatic 65 | fun getVersion(byteBuf: ByteBuf): Int { 66 | return byteBuf.getShort(0).toInt() and 0x7FFF 67 | } 68 | 69 | @JvmStatic 70 | fun getService(byteBuf: ByteBuf): String { 71 | var offset = SHORT_BYTES 72 | 73 | val serviceLength = byteBuf.getShort(offset).toInt() 74 | offset += SHORT_BYTES 75 | 76 | return byteBuf.toString(offset, serviceLength, StandardCharsets.UTF_8) 77 | } 78 | 79 | @JvmStatic 80 | fun getMethod(byteBuf: ByteBuf): String { 81 | var offset = SHORT_BYTES 82 | 83 | val serviceLength = byteBuf.getShort(offset).toInt() 84 | offset += SHORT_BYTES + serviceLength 85 | 86 | val methodLength = byteBuf.getShort(offset).toInt() 87 | offset += SHORT_BYTES 88 | 89 | return byteBuf.toString(offset, methodLength, StandardCharsets.UTF_8) 90 | } 91 | 92 | @JvmStatic 93 | fun getTracing(byteBuf: ByteBuf): ByteBuf { 94 | var offset = SHORT_BYTES 95 | 96 | val serviceLength = byteBuf.getShort(offset).toInt() 97 | offset += SHORT_BYTES + serviceLength 98 | 99 | val methodLength = byteBuf.getShort(offset).toInt() 100 | offset += SHORT_BYTES + methodLength 101 | 102 | val tracingLength = byteBuf.getShort(offset).toInt() 103 | offset += SHORT_BYTES 104 | 105 | return if (tracingLength > 0) byteBuf.slice(offset, tracingLength) else Unpooled.EMPTY_BUFFER 106 | } 107 | 108 | @JvmStatic 109 | fun getMetadata(byteBuf: ByteBuf): ByteBuf { 110 | var offset = SHORT_BYTES 111 | 112 | val serviceLength = byteBuf.getShort(offset).toInt() 113 | offset += SHORT_BYTES + serviceLength 114 | 115 | val methodLength = byteBuf.getShort(offset).toInt() 116 | offset += SHORT_BYTES + methodLength 117 | 118 | val tracingLength = byteBuf.getShort(offset).toInt() 119 | offset += SHORT_BYTES + tracingLength 120 | 121 | val metadataLength = byteBuf.readableBytes() - offset 122 | return if (metadataLength > 0) byteBuf.slice(offset, metadataLength) else Unpooled.EMPTY_BUFFER 123 | } 124 | 125 | private const val UNSIGNED_SHORT_SIZE = 16 126 | private const val UNSIGNED_SHORT_MAX_VALUE = (1 shl UNSIGNED_SHORT_SIZE) - 1 127 | 128 | private fun requireUnsignedShort(i: Int): Int { 129 | if (i > UNSIGNED_SHORT_MAX_VALUE) { 130 | throw IllegalArgumentException( 131 | String.format("%d is larger than %d bits", i, UNSIGNED_SHORT_SIZE)) 132 | } 133 | 134 | return i 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/rsocket/RequestHandlingRSocket.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.rsocket 18 | 19 | import io.netty.buffer.ByteBuf 20 | import io.netty.buffer.Unpooled 21 | import io.rsocket.rpc.kotlin.exception.ServiceNotFound 22 | import io.rsocket.rpc.kotlin.frames.Metadata 23 | import io.rsocket.rpc.kotlin.util.StreamSplitter 24 | import io.netty.util.ReferenceCountUtil 25 | import io.reactivex.Completable 26 | import io.reactivex.Flowable 27 | import io.reactivex.Single 28 | import io.rsocket.kotlin.Payload 29 | import io.rsocket.kotlin.util.AbstractRSocket 30 | import io.rsocket.rpc.kotlin.RSocketRpcService 31 | import org.reactivestreams.Publisher 32 | import java.util.concurrent.ConcurrentHashMap 33 | 34 | class RequestHandlingRSocket(vararg services: RSocketRpcService) : AbstractRSocket() { 35 | private val registeredServices = ConcurrentHashMap() 36 | 37 | init { 38 | for (rSocketRpcService in services) { 39 | val service = rSocketRpcService.service 40 | registeredServices[service] = rSocketRpcService 41 | } 42 | } 43 | 44 | fun addService(rSocketRpcService: RSocketRpcService) { 45 | val service = rSocketRpcService.service 46 | registeredServices[service] = rSocketRpcService 47 | } 48 | 49 | override fun fireAndForget(payload: Payload): Completable { 50 | try { 51 | val metadata = payload.byteBufMetadata() 52 | val service = Metadata.getService(metadata) 53 | 54 | val rSocketRpcService = registeredServices[service] 55 | 56 | if (rSocketRpcService == null) { 57 | ReferenceCountUtil.safeRelease(payload) 58 | return Completable.error(ServiceNotFound(service)) 59 | } 60 | 61 | return rSocketRpcService.fireAndForget(payload) 62 | } catch (t: Throwable) { 63 | ReferenceCountUtil.safeRelease(payload) 64 | return Completable.error(t) 65 | } 66 | 67 | } 68 | 69 | override fun requestResponse(payload: Payload): Single { 70 | try { 71 | val metadata = payload.byteBufMetadata() 72 | val service = Metadata.getService(metadata) 73 | 74 | val rSocketRpcService = registeredServices[service] 75 | 76 | if (rSocketRpcService == null) { 77 | ReferenceCountUtil.safeRelease(payload) 78 | return Single.error(ServiceNotFound(service)) 79 | } else { 80 | return rSocketRpcService.requestResponse(payload) 81 | } 82 | } catch (t: Throwable) { 83 | ReferenceCountUtil.safeRelease(payload) 84 | return Single.error(t) 85 | } 86 | } 87 | 88 | override fun requestStream(payload: Payload): Flowable { 89 | try { 90 | val metadata = payload.byteBufMetadata() 91 | val service = Metadata.getService(metadata) 92 | 93 | val rSocketRpcService = registeredServices[service] 94 | 95 | if (rSocketRpcService == null) { 96 | ReferenceCountUtil.safeRelease(payload) 97 | return Flowable.error(ServiceNotFound(service)) 98 | } 99 | 100 | return rSocketRpcService.requestStream(payload) 101 | } catch (t: Throwable) { 102 | ReferenceCountUtil.safeRelease(payload) 103 | return Flowable.error(t) 104 | } 105 | } 106 | 107 | override fun requestChannel(payloads: Publisher): Flowable { 108 | return StreamSplitter.split(payloads).flatMap { split -> 109 | val payload = split.head 110 | val flow = split.tail 111 | try { 112 | val metadata = payload.byteBufMetadata() 113 | val service = Metadata.getService(metadata) 114 | val rSocketRpcService = registeredServices[service] 115 | if (rSocketRpcService == null) { 116 | ReferenceCountUtil.safeRelease(payload) 117 | Flowable.error(ServiceNotFound(service)) 118 | } else { 119 | rSocketRpcService.requestChannel(payload, flow) 120 | } 121 | } catch (t: Throwable) { 122 | ReferenceCountUtil.safeRelease(payload) 123 | Flowable.error(t) 124 | } 125 | } 126 | } 127 | 128 | private fun Payload.byteBufMetadata(): ByteBuf = Unpooled.wrappedBuffer(metadata) 129 | } 130 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/tracing/ImmutableTag.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.tracing 18 | 19 | internal class ImmutableTag(override val key: String, override val value: String) : Tag { 20 | 21 | override fun toString(): String { 22 | return "ImmutableTag{" + "key='" + key + '\''.toString() + ", value='" + value + '\''.toString() + '}'.toString() 23 | } 24 | 25 | override fun equals(other: Any?): Boolean { 26 | if (this === other) return true 27 | if (javaClass != other?.javaClass) return false 28 | 29 | other as ImmutableTag 30 | 31 | if (key != other.key) return false 32 | if (value != other.value) return false 33 | 34 | return true 35 | } 36 | 37 | override fun hashCode(): Int { 38 | var result = key.hashCode() 39 | result = 31 * result + value.hashCode() 40 | return result 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/tracing/Tag.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.tracing 18 | 19 | interface Tag { 20 | 21 | val key: String 22 | 23 | val value: String 24 | 25 | companion object { 26 | fun of(key: String, value: String): Tag = ImmutableTag(key, value) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/tracing/TraceOperator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.tracing 18 | 19 | import io.opentracing.SpanContext 20 | import io.opentracing.Tracer 21 | import io.reactivex.FlowableOperator 22 | import org.reactivestreams.Subscriber 23 | 24 | class TraceOperator( 25 | private val tracer: Tracer, 26 | private val tracingMetadata: Map?, 27 | private val spanContext: SpanContext?, 28 | private val name: String, 29 | private val tags: Array 30 | ) : FlowableOperator { 31 | 32 | constructor( 33 | tracer: Tracer, 34 | tracingMetadata: Map?, 35 | name: String, 36 | vararg tags: Tag 37 | ) : this(tracer, tracingMetadata, null, name, tags) 38 | 39 | override fun apply(observer: Subscriber): Subscriber = 40 | if (spanContext != null) 41 | TraceSubscriber( 42 | observer, 43 | tracer, 44 | tracingMetadata, 45 | spanContext, 46 | name, 47 | *tags 48 | ) 49 | else 50 | TraceSubscriber( 51 | observer, 52 | tracer, 53 | tracingMetadata, 54 | name, 55 | *tags 56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/tracing/TraceSubscriber.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.tracing 18 | 19 | import io.opentracing.Span 20 | import io.opentracing.SpanContext 21 | import io.opentracing.Tracer 22 | import io.opentracing.propagation.Format 23 | import io.opentracing.propagation.TextMapInjectAdapter 24 | import io.reactivex.FlowableSubscriber 25 | import org.reactivestreams.Subscriber 26 | import org.reactivestreams.Subscription 27 | import java.util.concurrent.TimeUnit 28 | import java.util.concurrent.atomic.AtomicBoolean 29 | 30 | class TraceSubscriber : AtomicBoolean, FlowableSubscriber, Subscription { 31 | private val span: Span 32 | private val rootSpan: Span? 33 | private val tracer: Tracer 34 | private val downstream: Subscriber 35 | internal var upstream: Subscription? = null 36 | 37 | constructor( 38 | downstream: Subscriber, 39 | tracer: Tracer, 40 | tracingMetadata: Map?, 41 | spanContext: SpanContext, 42 | name: String, 43 | vararg tags: Tag 44 | ) { 45 | this.downstream = downstream 46 | this.tracer = tracer 47 | this.rootSpan = null 48 | 49 | val spanBuilder = this.tracer.buildSpan(name).asChildOf(spanContext) 50 | if (tags.isNotEmpty()) { 51 | for (tag in tags) { 52 | spanBuilder.withTag(tag.key, tag.value) 53 | } 54 | } 55 | this.span = spanBuilder.start() 56 | 57 | if (tracingMetadata != null) { 58 | val adapter = TextMapInjectAdapter(tracingMetadata) 59 | tracer.inject(span.context(), Format.Builtin.TEXT_MAP, adapter) 60 | } 61 | } 62 | 63 | constructor( 64 | downstream: Subscriber, 65 | tracer: Tracer, 66 | tracingMetadata: Map?, 67 | name: String, 68 | vararg tags: Tag 69 | ) { 70 | 71 | this.downstream = downstream 72 | this.tracer = tracer 73 | val root = this.tracer.activeSpan() 74 | this.rootSpan = root 75 | 76 | val spanBuilder = this.tracer.buildSpan(name) 77 | if (tags.isNotEmpty()) { 78 | for (tag in tags) { 79 | spanBuilder.withTag(tag.key, tag.value) 80 | } 81 | } 82 | 83 | if (root != null) { 84 | spanBuilder.asChildOf(root) 85 | } 86 | 87 | this.span = spanBuilder.start() 88 | 89 | if (tracingMetadata != null) { 90 | val adapter = TextMapInjectAdapter(tracingMetadata) 91 | tracer.inject(span.context(), Format.Builtin.TEXT_MAP, adapter) 92 | } 93 | } 94 | 95 | override fun onSubscribe(s: Subscription) { 96 | if (upstream != null) { 97 | s.cancel() 98 | } else { 99 | upstream = s 100 | downstream.onSubscribe(this) 101 | this.tracer.scopeManager().activate(span, false).use { scope -> 102 | scope.span().log(TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()), "onSubscribe") 103 | downstream.onSubscribe(this) 104 | } 105 | } 106 | } 107 | 108 | override fun onNext(t: T) { 109 | downstream.onNext(t) 110 | } 111 | 112 | override fun onError(t: Throwable) { 113 | try { 114 | this.tracer.scopeManager().activate(span, false).use { scope -> 115 | scope.span().log(TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()), "onError") 116 | } 117 | } finally { 118 | cleanup() 119 | } 120 | } 121 | 122 | override fun onComplete() { 123 | try { 124 | this.tracer.scopeManager().activate(span, false).use { scope -> 125 | scope.span().log(TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()), "onComplete") 126 | downstream.onComplete() 127 | } 128 | } finally { 129 | cleanup() 130 | } 131 | } 132 | 133 | override fun request(n: Long) { 134 | this.upstream!!.request(n) 135 | } 136 | 137 | override fun cancel() { 138 | try { 139 | this.tracer.scopeManager().activate(span, false).use { scope -> 140 | scope.span().log(TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()), "cancel") 141 | this.upstream!!.cancel() 142 | } 143 | } finally { 144 | cleanup() 145 | } 146 | } 147 | 148 | internal fun cleanup() { 149 | if (compareAndSet(false, true)) { 150 | span.finish() 151 | rootSpan?.finish() 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/tracing/Tracing.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.tracing 18 | 19 | import io.netty.buffer.ByteBuf 20 | import io.netty.buffer.ByteBufAllocator 21 | import io.netty.buffer.ByteBufUtil 22 | import io.netty.buffer.Unpooled 23 | import io.opentracing.SpanContext 24 | import io.opentracing.Tracer 25 | import io.opentracing.propagation.Format 26 | import io.opentracing.propagation.TextMapExtractAdapter 27 | import io.reactivex.FlowableTransformer 28 | import io.rsocket.rpc.kotlin.frames.Metadata 29 | import java.nio.charset.StandardCharsets 30 | import java.util.* 31 | 32 | object Tracing { 33 | private const val UNSIGNED_SHORT_SIZE = 16 34 | private const val UNSIGNED_SHORT_MAX_VALUE = (1 shl UNSIGNED_SHORT_SIZE) - 1 35 | 36 | fun deserializeTracingMetadata(tracer: Tracer?, metadata: ByteBuf): SpanContext? { 37 | if (tracer == null) { 38 | return null 39 | } 40 | 41 | val tracing = Metadata.getTracing(metadata) 42 | 43 | if (tracing.readableBytes() < 0) { 44 | return null 45 | } 46 | 47 | val metadataMap = byteBufToMap(tracing) 48 | return if (metadataMap.isEmpty()) { 49 | null 50 | } else deserializeTracingMetadata(tracer, metadataMap) 51 | 52 | } 53 | 54 | fun mapToByteBuf(allocator: ByteBufAllocator, map: Map?): ByteBuf { 55 | if (map == null || map.isEmpty()) { 56 | return Unpooled.EMPTY_BUFFER 57 | } 58 | 59 | val byteBuf = allocator.buffer() 60 | 61 | for ((key, value) in map) { 62 | val keyLength = requireUnsignedShort(ByteBufUtil.utf8Bytes(key)) 63 | byteBuf.writeShort(keyLength) 64 | ByteBufUtil.reserveAndWriteUtf8(byteBuf, key, keyLength) 65 | 66 | val valueLength = requireUnsignedShort(ByteBufUtil.utf8Bytes(value)) 67 | byteBuf.writeShort(valueLength) 68 | ByteBufUtil.reserveAndWriteUtf8(byteBuf, value, keyLength) 69 | } 70 | 71 | return byteBuf 72 | } 73 | 74 | fun trace(): (Map) -> FlowableTransformer = 75 | { FlowableTransformer { upstream -> upstream } } 76 | 77 | fun traceAsChild(): (SpanContext?) -> FlowableTransformer = 78 | { FlowableTransformer { upstream -> upstream } } 79 | 80 | fun trace( 81 | tracer: Tracer, name: String, vararg tags: Tag 82 | ): (Map) -> FlowableTransformer = 83 | { map -> 84 | FlowableTransformer { upstream -> 85 | upstream.lift( 86 | TraceOperator( 87 | tracer, 88 | map, 89 | name, 90 | *tags 91 | ) 92 | ) 93 | } 94 | } 95 | 96 | fun traceAsChild(tracer: Tracer, name: String, vararg tags: Tag) 97 | : (SpanContext?) -> FlowableTransformer = 98 | { spanContext -> 99 | FlowableTransformer { upstream -> 100 | upstream.lift( 101 | if (spanContext == null) 102 | TraceOperator(tracer, null, name, *tags) 103 | else 104 | TraceOperator(tracer, null, spanContext, name, tags) 105 | ) 106 | } 107 | } 108 | 109 | private fun deserializeTracingMetadata( 110 | tracer: Tracer, metadata: Map 111 | ): SpanContext { 112 | val adapter = TextMapExtractAdapter(metadata) 113 | return tracer.extract(Format.Builtin.TEXT_MAP, adapter) 114 | } 115 | 116 | private fun requireUnsignedShort(i: Int): Int { 117 | if (i > UNSIGNED_SHORT_MAX_VALUE) { 118 | throw IllegalArgumentException( 119 | String.format("%d is larger than %d bits", i, UNSIGNED_SHORT_SIZE) 120 | ) 121 | } 122 | return i 123 | } 124 | 125 | private fun byteBufToMap(byteBuf: ByteBuf): Map { 126 | val map = HashMap() 127 | 128 | while (byteBuf.readableBytes() > 0) { 129 | val keyLength = byteBuf.readShort().toInt() 130 | val key = byteBuf.readCharSequence(keyLength, StandardCharsets.UTF_8) as String 131 | 132 | val valueLength = byteBuf.readShort().toInt() 133 | val value = byteBuf.readCharSequence(valueLength, StandardCharsets.UTF_8) as String 134 | 135 | map[key] = value 136 | } 137 | return map 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /rsocket-rpc-core/src/main/kotlin/io/rsocket/rpc/kotlin/util/StreamSplitter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.util 18 | 19 | import io.reactivex.Flowable 20 | import io.reactivex.processors.UnicastProcessor 21 | import io.rsocket.kotlin.DefaultPayload 22 | import io.rsocket.kotlin.Payload 23 | import org.reactivestreams.Publisher 24 | 25 | class StreamSplitter { 26 | 27 | companion object { 28 | 29 | @JvmStatic 30 | fun split(p: Publisher): Flowable { 31 | var first = true 32 | val rest = UnicastProcessor.create() 33 | 34 | return Flowable.fromPublisher(p) 35 | .doOnComplete { rest.onComplete() } 36 | .doOnError { rest.onError(it) } 37 | .map { payload -> 38 | if (first) { 39 | first = false 40 | Split(payload, rest) 41 | } else { 42 | rest.onNext(payload) 43 | noopSplit 44 | } 45 | }.filter { split -> split !== noopSplit } 46 | } 47 | 48 | private val noopSplit = Split(DefaultPayload("", ""), Flowable.empty()) 49 | } 50 | 51 | data class Split(val head: Payload, val tail: Flowable) 52 | } -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | plugins { 18 | id 'com.jfrog.artifactory' 19 | id 'com.jfrog.bintray' 20 | id 'maven-publish' 21 | id 'idea' 22 | } 23 | 24 | description = 'RSocket RPC Protobuf IDL' 25 | 26 | protobuf { 27 | generateProtoTasks { 28 | all().each { task -> 29 | task.enabled = false 30 | } 31 | } 32 | } 33 | 34 | idea { 35 | module { 36 | sourceDirs += file("src/main/proto") 37 | } 38 | } -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/gradle/dependency-locks/compile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/gradle/dependency-locks/compileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/gradle/dependency-locks/kotlinCompilerClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.intellij.deps:trove4j:1.0.20181211 5 | org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.50 6 | org.jetbrains.kotlin:kotlin-daemon-embeddable:1.3.50 7 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 8 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 9 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 11 | org.jetbrains:annotations:13.0 12 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/gradle/dependency-locks/protobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/gradle/dependency-locks/testCompile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/gradle/dependency-locks/testCompileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/gradle/dependency-locks/testProtobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf-idl/src/main/proto/rsocket/options.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | syntax = "proto3"; 18 | 19 | package io.rsocket.rpc; 20 | 21 | import "google/protobuf/descriptor.proto"; 22 | 23 | option java_package = "io.rsocket.rpc"; 24 | option java_outer_classname = "RSocketOptions"; 25 | option java_multiple_files = true; 26 | 27 | extend google.protobuf.MethodOptions { 28 | RSocketMethodOptions options = 1057; 29 | } 30 | 31 | message RSocketMethodOptions { 32 | bool fire_and_forget = 1; 33 | } -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | plugins { 18 | id 'cpp' 19 | id 'com.jfrog.artifactory' 20 | id 'com.jfrog.bintray' 21 | id 'maven-publish' 22 | } 23 | 24 | description = 'RSocket-kotlin RPC Protobuf Generator' 25 | 26 | def pluginPrefix = "rsocket-rpc-protobuf-${osdetector.os}-${osdetector.arch}" 27 | def pluginName = "${pluginPrefix}.exe" 28 | def artifactStagingPath = "$buildDir/artifacts" as File 29 | def pathToPlugin = "${artifactStagingPath.getPath()}/${pluginName}" 30 | 31 | // Adds space-delimited arguments from the environment variable env to the 32 | // argList. 33 | def addEnvArgs = { env, argList -> 34 | def value = System.getenv(env) 35 | if (value != null) { 36 | value.split(' +').each() { it -> argList.add(it) } 37 | } 38 | } 39 | 40 | // Adds corresponding "-l" option to the argList if libName is not found in 41 | // LDFLAGS. This is only used for Mac because when building for uploadArchives 42 | // artifacts, we add the ".a" files directly to LDFLAGS and without "-l" in 43 | // order to get statically linked, otherwise we add the libraries through "-l" 44 | // so that they can be searched for in default search paths. 45 | def addLibraryIfNotLinked = { libName, argList -> 46 | def ldflags = System.env.LDFLAGS 47 | if (ldflags == null || !ldflags.contains('lib' + libName + '.a')) { 48 | argList.add('-l' + libName) 49 | } 50 | } 51 | 52 | String arch = rootProject.hasProperty('targetArch') ? rootProject.targetArch : 53 | osdetector.arch 54 | boolean vcDisable = rootProject.hasProperty('vcDisable') ? rootProject.vcDisable : false 55 | 56 | model { 57 | toolChains { 58 | // If you have both VC and Gcc installed, VC will be selected, unless you 59 | // set 'vcDisable=true' 60 | if (!vcDisable) { 61 | visualCpp(VisualCpp) { 62 | // Prefer vcvars-provided environment over registry-discovered environment 63 | def String vsDir = System.getenv("VSINSTALLDIR") 64 | def String winDir = System.getenv("WindowsSdkDir") 65 | if (vsDir != null && winDir != null) { 66 | installDir = vsDir 67 | windowsSdkDir = winDir 68 | } 69 | } 70 | } 71 | gcc(Gcc) { 72 | target("ppcle_64") 73 | } 74 | clang(Clang) {} 75 | } 76 | 77 | platforms { 78 | x86_32 { 79 | architecture "x86" 80 | } 81 | x86_64 { 82 | architecture "x86_64" 83 | } 84 | ppcle_64 { 85 | architecture "ppcle_64" 86 | } 87 | } 88 | 89 | components { 90 | kotlin_plugin(NativeExecutableSpec) { 91 | if (arch in ['x86_32', 'x86_64', 'ppcle_64']) { 92 | // If arch is not within the defined platforms, we do not specify the 93 | // targetPlatform so that Gradle will choose what is appropriate. 94 | targetPlatform arch 95 | } 96 | baseName "$pluginPrefix" 97 | } 98 | } 99 | 100 | binaries { 101 | all { 102 | if (toolChain in Gcc || toolChain in Clang) { 103 | cppCompiler.define("RSOCKET_RPC_VERSION", version) 104 | cppCompiler.args "--std=c++0x" 105 | addEnvArgs("CXXFLAGS", cppCompiler.args) 106 | addEnvArgs("CPPFLAGS", cppCompiler.args) 107 | if (osdetector.os == "osx") { 108 | cppCompiler.args "-mmacosx-version-min=10.7", "-stdlib=libc++" 109 | addLibraryIfNotLinked('protoc', linker.args) 110 | addLibraryIfNotLinked('protobuf', linker.args) 111 | } 112 | else if (osdetector.os == "windows") { 113 | linker.args "-static", "-lprotoc", "-lprotobuf", "-static-libgcc", 114 | "-static-libstdc++", 115 | "-s" 116 | } 117 | else { 118 | // Link protoc, protobuf, libgcc and libstdc++ statically. 119 | // Link other (system) libraries dynamically. 120 | // Clang under OSX doesn't support these options. 121 | linker.args "-Wl,-Bstatic", "-lprotoc", "-lprotobuf", "-static-libgcc", 122 | "-static-libstdc++", 123 | "-Wl,-Bdynamic", "-lpthread", "-s" 124 | } 125 | addEnvArgs("LDFLAGS", linker.args) 126 | } 127 | else if (toolChain in VisualCpp) { 128 | cppCompiler.define("RSOCKET_RPC_VERSION", version) 129 | cppCompiler.args "/EHsc", "/MT" 130 | if (rootProject.hasProperty('vcProtobufInclude')) { 131 | cppCompiler.args "/I${rootProject.vcProtobufInclude}" 132 | } 133 | else { 134 | println 'You may need to add a propertry, vcProtobufInclude, pointing to protobuf include' 135 | } 136 | 137 | if (rootProject.hasProperty('vcProtobufLibs')) { 138 | linker.args "/LIBPATH:${rootProject.vcProtobufLibs}" 139 | } 140 | else { 141 | println 'You may need to add a propertry, vcProtobufLibs, pointing to protobuf lib' 142 | } 143 | 144 | linker.args "libprotobuf.lib", "libprotoc.lib" 145 | } 146 | } 147 | } 148 | } 149 | 150 | task buildArtifacts(type: Copy) { 151 | println 'generating artifacts' 152 | dependsOn 'kotlin_pluginExecutable' 153 | from("$buildDir/exe/kotlin_plugin") { 154 | if (osdetector.os != 'windows') { 155 | rename pluginPrefix, '$0.exe' 156 | } 157 | } 158 | into artifactStagingPath 159 | } 160 | 161 | compileJava.dependsOn ':rsocket-rpc-protobuf:buildArtifacts' 162 | 163 | artifacts { 164 | archives("$pathToPlugin" as File) { 165 | classifier osdetector.os + "-" + osdetector.arch 166 | type "exe" 167 | extension "exe" 168 | builtBy buildArtifacts 169 | } 170 | } 171 | 172 | apply from: '../gradle/publishing-compiler.gradle' -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/gradle/dependency-locks/compile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/gradle/dependency-locks/compileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/gradle/dependency-locks/kotlinCompilerClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.intellij.deps:trove4j:1.0.20181211 5 | org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.50 6 | org.jetbrains.kotlin:kotlin-daemon-embeddable:1.3.50 7 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 8 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 9 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 11 | org.jetbrains:annotations:13.0 12 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/gradle/dependency-locks/protobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/gradle/dependency-locks/protobufToolsLocator_protoc.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protoc:3.6.1 5 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/gradle/dependency-locks/testCompile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/gradle/dependency-locks/testCompileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/gradle/dependency-locks/testProtobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/src/kotlin_plugin/cpp/kotlin_generator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef RSOCKET_RPC_COMPILER_KOTLIN_GENERATOR_H_ 18 | #define RSOCKET_RPC_COMPILER_KOTLIN_GENERATOR_H_ 19 | 20 | #include // for abort() 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | class LogHelper { 28 | std::ostream* os; 29 | 30 | public: 31 | LogHelper(std::ostream* os) : os(os) {} 32 | ~LogHelper() { 33 | *os << std::endl; 34 | ::abort(); 35 | } 36 | std::ostream& get_os() { 37 | return *os; 38 | } 39 | }; 40 | 41 | // Abort the program after logging the mesage if the given condition is not 42 | // true. Otherwise, do nothing. 43 | #define RSOCKET_RPC_CODEGEN_CHECK(x) !(x) && LogHelper(&std::cerr).get_os() \ 44 | << "CHECK FAILED: " << __FILE__ << ":" \ 45 | << __LINE__ << ": " 46 | 47 | // Abort the program after logging the mesage. 48 | #define RSOCKET_RPC_CODEGEN_FAIL RSOCKET_RPC_CODEGEN_CHECK(false) 49 | 50 | using namespace std; 51 | 52 | namespace kotlin_rsocket_rpc_generator { 53 | 54 | enum ProtoFlavor { 55 | NORMAL, LITE 56 | }; 57 | 58 | // Returns the package name of the RSocket RPC services defined in the given file. 59 | string ServiceKotlinPackage(const google::protobuf::FileDescriptor* file); 60 | 61 | // Returns the name of the client class for the given service. 62 | string ClientClassName(const google::protobuf::ServiceDescriptor* service); 63 | 64 | // Returns the name of the client class for the given service. 65 | string ServerClassName(const google::protobuf::ServiceDescriptor* service); 66 | 67 | // Writes the generated interface into the given ZeroCopyOutputStream 68 | void GenerateInterface(const google::protobuf::ServiceDescriptor* service, 69 | google::protobuf::io::ZeroCopyOutputStream* out, 70 | ProtoFlavor flavor, 71 | bool disable_version); 72 | 73 | // Writes the generated client into the given ZeroCopyOutputStream 74 | void GenerateClient(const google::protobuf::ServiceDescriptor* service, 75 | google::protobuf::io::ZeroCopyOutputStream* out, 76 | ProtoFlavor flavor, 77 | bool disable_version); 78 | 79 | // Writes the generated server into the given ZeroCopyOutputStream 80 | void GenerateServer(const google::protobuf::ServiceDescriptor* service, 81 | google::protobuf::io::ZeroCopyOutputStream* out, 82 | ProtoFlavor flavor, 83 | bool disable_version); 84 | 85 | } // namespace kotlin_rsocket_rpc_generator 86 | 87 | #endif // RSOCKET_RPC_COMPILER_KOTLIN_GENERATOR_H_ 88 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/src/kotlin_plugin/cpp/kotlin_plugin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "kotlin_generator.h" 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | static string KotlinPackageToDir(const string& package_name) { 27 | string package_dir = package_name; 28 | for (size_t i = 0; i < package_dir.size(); ++i) { 29 | if (package_dir[i] == '.') { 30 | package_dir[i] = '/'; 31 | } 32 | } 33 | if (!package_dir.empty()) package_dir += "/"; 34 | return package_dir; 35 | } 36 | 37 | class KotlinRSocketRpcGenerator : public google::protobuf::compiler::CodeGenerator { 38 | public: 39 | KotlinRSocketRpcGenerator() {} 40 | virtual ~KotlinRSocketRpcGenerator() {} 41 | 42 | virtual bool Generate(const google::protobuf::FileDescriptor* file, 43 | const string& parameter, 44 | google::protobuf::compiler::GeneratorContext* context, 45 | string* error) const { 46 | return reactor(file, parameter, context, error); 47 | } 48 | 49 | virtual bool reactor(const google::protobuf::FileDescriptor* file, 50 | const string& parameter, 51 | google::protobuf::compiler::GeneratorContext* context, 52 | string* error) const { 53 | std::vector > options; 54 | google::protobuf::compiler::ParseGeneratorParameter(parameter, &options); 55 | 56 | kotlin_rsocket_rpc_generator::ProtoFlavor flavor = 57 | kotlin_rsocket_rpc_generator::ProtoFlavor::NORMAL; 58 | 59 | bool disable_version = false; 60 | for (size_t i = 0; i < options.size(); i++) { 61 | if (options[i].first == "lite") { 62 | flavor = kotlin_rsocket_rpc_generator::ProtoFlavor::LITE; 63 | } else if (options[i].first == "noversion") { 64 | disable_version = true; 65 | } 66 | } 67 | 68 | string package_name = kotlin_rsocket_rpc_generator::ServiceKotlinPackage(file); 69 | string package_filename = KotlinPackageToDir(package_name); 70 | for (int i = 0; i < file->service_count(); ++i) { 71 | const google::protobuf::ServiceDescriptor* service = file->service(i); 72 | 73 | string interface_filename = package_filename + service->name() + ".kt"; 74 | std::unique_ptr interface_file(context->Open(interface_filename)); 75 | kotlin_rsocket_rpc_generator::GenerateInterface(service, interface_file.get(), flavor, disable_version); 76 | 77 | string client_filename = package_filename + kotlin_rsocket_rpc_generator::ClientClassName(service) + ".kt"; 78 | std::unique_ptr client_file(context->Open(client_filename)); 79 | kotlin_rsocket_rpc_generator::GenerateClient(service, client_file.get(), flavor, disable_version); 80 | 81 | string server_filename = package_filename + kotlin_rsocket_rpc_generator::ServerClassName(service) + ".kt"; 82 | std::unique_ptr server_file(context->Open(server_filename)); 83 | kotlin_rsocket_rpc_generator::GenerateServer(service, server_file.get(), flavor, disable_version); 84 | } 85 | return true; 86 | } 87 | }; 88 | 89 | int main(int argc, char* argv[]) { 90 | KotlinRSocketRpcGenerator generator; 91 | return google::protobuf::compiler::PluginMain(argc, argv, &generator); 92 | } 93 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/src/kotlin_plugin/cpp/rsocket/options.pb.cc: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: rsocket/options.proto 3 | 4 | #include "options.pb.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | // This is a temporary google only hack 17 | #ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS 18 | #include "third_party/protobuf/version.h" 19 | #endif 20 | // @@protoc_insertion_point(includes) 21 | 22 | namespace protobuf_rsocket_2foptions_2eproto { 23 | extern PROTOBUF_INTERNAL_EXPORT_protobuf_rsocket_2foptions_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_RSocketMethodOptions; 24 | } // namespace protobuf_rsocket_2foptions_2eproto 25 | namespace io { 26 | namespace rsocket { 27 | namespace rpc { 28 | class RSocketMethodOptionsDefaultTypeInternal { 29 | public: 30 | ::google::protobuf::internal::ExplicitlyConstructed 31 | _instance; 32 | } _RSocketMethodOptions_default_instance_; 33 | } // namespace rpc 34 | } // namespace rsocket 35 | } // namespace io 36 | namespace protobuf_rsocket_2foptions_2eproto { 37 | static void InitDefaultsRSocketMethodOptions() { 38 | GOOGLE_PROTOBUF_VERIFY_VERSION; 39 | 40 | { 41 | void* ptr = &::io::rsocket::rpc::_RSocketMethodOptions_default_instance_; 42 | new (ptr) ::io::rsocket::rpc::RSocketMethodOptions(); 43 | ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); 44 | } 45 | ::io::rsocket::rpc::RSocketMethodOptions::InitAsDefaultInstance(); 46 | } 47 | 48 | ::google::protobuf::internal::SCCInfo<0> scc_info_RSocketMethodOptions = 49 | {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsRSocketMethodOptions}, {}}; 50 | 51 | void InitDefaults() { 52 | ::google::protobuf::internal::InitSCC(&scc_info_RSocketMethodOptions.base); 53 | } 54 | 55 | ::google::protobuf::Metadata file_level_metadata[1]; 56 | 57 | const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { 58 | ~0u, // no _has_bits_ 59 | GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::io::rsocket::rpc::RSocketMethodOptions, _internal_metadata_), 60 | ~0u, // no _extensions_ 61 | ~0u, // no _oneof_case_ 62 | ~0u, // no _weak_field_map_ 63 | GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::io::rsocket::rpc::RSocketMethodOptions, fire_and_forget_), 64 | }; 65 | static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { 66 | { 0, -1, sizeof(::io::rsocket::rpc::RSocketMethodOptions)}, 67 | }; 68 | 69 | static ::google::protobuf::Message const * const file_default_instances[] = { 70 | reinterpret_cast(&::io::rsocket::rpc::_RSocketMethodOptions_default_instance_), 71 | }; 72 | 73 | void protobuf_AssignDescriptors() { 74 | AddDescriptors(); 75 | AssignDescriptors( 76 | "rsocket/options.proto", schemas, file_default_instances, TableStruct::offsets, 77 | file_level_metadata, NULL, NULL); 78 | } 79 | 80 | void protobuf_AssignDescriptorsOnce() { 81 | static ::google::protobuf::internal::once_flag once; 82 | ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors); 83 | } 84 | 85 | void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD; 86 | void protobuf_RegisterTypes(const ::std::string&) { 87 | protobuf_AssignDescriptorsOnce(); 88 | ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); 89 | } 90 | 91 | void AddDescriptorsImpl() { 92 | InitDefaults(); 93 | static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { 94 | "\n\025rsocket/options.proto\022\016io.rsocket.rpc\032" 95 | " google/protobuf/descriptor.proto\"/\n\024RSo" 96 | "cketMethodOptions\022\027\n\017fire_and_forget\030\001 \001" 97 | "(\010:V\n\007options\022\036.google.protobuf.MethodOp" 98 | "tions\030\241\010 \001(\0132$.io.rsocket.rpc.RSocketMet" 99 | "hodOptionsB\"\n\016io.rsocket.rpcB\016RSocketOpt" 100 | "ionsP\001b\006proto3" 101 | }; 102 | ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( 103 | descriptor, 254); 104 | ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( 105 | "rsocket/options.proto", &protobuf_RegisterTypes); 106 | ::protobuf_google_2fprotobuf_2fdescriptor_2eproto::AddDescriptors(); 107 | } 108 | 109 | void AddDescriptors() { 110 | static ::google::protobuf::internal::once_flag once; 111 | ::google::protobuf::internal::call_once(once, AddDescriptorsImpl); 112 | } 113 | // Force AddDescriptors() to be called at dynamic initialization time. 114 | struct StaticDescriptorInitializer { 115 | StaticDescriptorInitializer() { 116 | AddDescriptors(); 117 | } 118 | } static_descriptor_initializer; 119 | } // namespace protobuf_rsocket_2foptions_2eproto 120 | namespace io { 121 | namespace rsocket { 122 | namespace rpc { 123 | 124 | // =================================================================== 125 | 126 | void RSocketMethodOptions::InitAsDefaultInstance() { 127 | } 128 | #if !defined(_MSC_VER) || _MSC_VER >= 1900 129 | const int RSocketMethodOptions::kFireAndForgetFieldNumber; 130 | #endif // !defined(_MSC_VER) || _MSC_VER >= 1900 131 | 132 | RSocketMethodOptions::RSocketMethodOptions() 133 | : ::google::protobuf::Message(), _internal_metadata_(NULL) { 134 | ::google::protobuf::internal::InitSCC( 135 | &protobuf_rsocket_2foptions_2eproto::scc_info_RSocketMethodOptions.base); 136 | SharedCtor(); 137 | // @@protoc_insertion_point(constructor:io.rsocket.rpc.RSocketMethodOptions) 138 | } 139 | RSocketMethodOptions::RSocketMethodOptions(const RSocketMethodOptions& from) 140 | : ::google::protobuf::Message(), 141 | _internal_metadata_(NULL) { 142 | _internal_metadata_.MergeFrom(from._internal_metadata_); 143 | fire_and_forget_ = from.fire_and_forget_; 144 | // @@protoc_insertion_point(copy_constructor:io.rsocket.rpc.RSocketMethodOptions) 145 | } 146 | 147 | void RSocketMethodOptions::SharedCtor() { 148 | fire_and_forget_ = false; 149 | } 150 | 151 | RSocketMethodOptions::~RSocketMethodOptions() { 152 | // @@protoc_insertion_point(destructor:io.rsocket.rpc.RSocketMethodOptions) 153 | SharedDtor(); 154 | } 155 | 156 | void RSocketMethodOptions::SharedDtor() { 157 | } 158 | 159 | void RSocketMethodOptions::SetCachedSize(int size) const { 160 | _cached_size_.Set(size); 161 | } 162 | const ::google::protobuf::Descriptor* RSocketMethodOptions::descriptor() { 163 | ::protobuf_rsocket_2foptions_2eproto::protobuf_AssignDescriptorsOnce(); 164 | return ::protobuf_rsocket_2foptions_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; 165 | } 166 | 167 | const RSocketMethodOptions& RSocketMethodOptions::default_instance() { 168 | ::google::protobuf::internal::InitSCC(&protobuf_rsocket_2foptions_2eproto::scc_info_RSocketMethodOptions.base); 169 | return *internal_default_instance(); 170 | } 171 | 172 | 173 | void RSocketMethodOptions::Clear() { 174 | // @@protoc_insertion_point(message_clear_start:io.rsocket.rpc.RSocketMethodOptions) 175 | ::google::protobuf::uint32 cached_has_bits = 0; 176 | // Prevent compiler warnings about cached_has_bits being unused 177 | (void) cached_has_bits; 178 | 179 | fire_and_forget_ = false; 180 | _internal_metadata_.Clear(); 181 | } 182 | 183 | bool RSocketMethodOptions::MergePartialFromCodedStream( 184 | ::google::protobuf::io::CodedInputStream* input) { 185 | #define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure 186 | ::google::protobuf::uint32 tag; 187 | // @@protoc_insertion_point(parse_start:io.rsocket.rpc.RSocketMethodOptions) 188 | for (;;) { 189 | ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); 190 | tag = p.first; 191 | if (!p.second) goto handle_unusual; 192 | switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { 193 | // bool fire_and_forget = 1; 194 | case 1: { 195 | if (static_cast< ::google::protobuf::uint8>(tag) == 196 | static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { 197 | 198 | DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< 199 | bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( 200 | input, &fire_and_forget_))); 201 | } else { 202 | goto handle_unusual; 203 | } 204 | break; 205 | } 206 | 207 | default: { 208 | handle_unusual: 209 | if (tag == 0) { 210 | goto success; 211 | } 212 | DO_(::google::protobuf::internal::WireFormat::SkipField( 213 | input, tag, _internal_metadata_.mutable_unknown_fields())); 214 | break; 215 | } 216 | } 217 | } 218 | success: 219 | // @@protoc_insertion_point(parse_success:io.rsocket.rpc.RSocketMethodOptions) 220 | return true; 221 | failure: 222 | // @@protoc_insertion_point(parse_failure:io.rsocket.rpc.RSocketMethodOptions) 223 | return false; 224 | #undef DO_ 225 | } 226 | 227 | void RSocketMethodOptions::SerializeWithCachedSizes( 228 | ::google::protobuf::io::CodedOutputStream* output) const { 229 | // @@protoc_insertion_point(serialize_start:io.rsocket.rpc.RSocketMethodOptions) 230 | ::google::protobuf::uint32 cached_has_bits = 0; 231 | (void) cached_has_bits; 232 | 233 | // bool fire_and_forget = 1; 234 | if (this->fire_and_forget() != 0) { 235 | ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->fire_and_forget(), output); 236 | } 237 | 238 | if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { 239 | ::google::protobuf::internal::WireFormat::SerializeUnknownFields( 240 | (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); 241 | } 242 | // @@protoc_insertion_point(serialize_end:io.rsocket.rpc.RSocketMethodOptions) 243 | } 244 | 245 | ::google::protobuf::uint8* RSocketMethodOptions::InternalSerializeWithCachedSizesToArray( 246 | bool deterministic, ::google::protobuf::uint8* target) const { 247 | (void)deterministic; // Unused 248 | // @@protoc_insertion_point(serialize_to_array_start:io.rsocket.rpc.RSocketMethodOptions) 249 | ::google::protobuf::uint32 cached_has_bits = 0; 250 | (void) cached_has_bits; 251 | 252 | // bool fire_and_forget = 1; 253 | if (this->fire_and_forget() != 0) { 254 | target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->fire_and_forget(), target); 255 | } 256 | 257 | if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { 258 | target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( 259 | (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); 260 | } 261 | // @@protoc_insertion_point(serialize_to_array_end:io.rsocket.rpc.RSocketMethodOptions) 262 | return target; 263 | } 264 | 265 | size_t RSocketMethodOptions::ByteSizeLong() const { 266 | // @@protoc_insertion_point(message_byte_size_start:io.rsocket.rpc.RSocketMethodOptions) 267 | size_t total_size = 0; 268 | 269 | if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { 270 | total_size += 271 | ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( 272 | (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); 273 | } 274 | // bool fire_and_forget = 1; 275 | if (this->fire_and_forget() != 0) { 276 | total_size += 1 + 1; 277 | } 278 | 279 | int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); 280 | SetCachedSize(cached_size); 281 | return total_size; 282 | } 283 | 284 | void RSocketMethodOptions::MergeFrom(const ::google::protobuf::Message& from) { 285 | // @@protoc_insertion_point(generalized_merge_from_start:io.rsocket.rpc.RSocketMethodOptions) 286 | GOOGLE_DCHECK_NE(&from, this); 287 | const RSocketMethodOptions* source = 288 | ::google::protobuf::internal::DynamicCastToGenerated( 289 | &from); 290 | if (source == NULL) { 291 | // @@protoc_insertion_point(generalized_merge_from_cast_fail:io.rsocket.rpc.RSocketMethodOptions) 292 | ::google::protobuf::internal::ReflectionOps::Merge(from, this); 293 | } else { 294 | // @@protoc_insertion_point(generalized_merge_from_cast_success:io.rsocket.rpc.RSocketMethodOptions) 295 | MergeFrom(*source); 296 | } 297 | } 298 | 299 | void RSocketMethodOptions::MergeFrom(const RSocketMethodOptions& from) { 300 | // @@protoc_insertion_point(class_specific_merge_from_start:io.rsocket.rpc.RSocketMethodOptions) 301 | GOOGLE_DCHECK_NE(&from, this); 302 | _internal_metadata_.MergeFrom(from._internal_metadata_); 303 | ::google::protobuf::uint32 cached_has_bits = 0; 304 | (void) cached_has_bits; 305 | 306 | if (from.fire_and_forget() != 0) { 307 | set_fire_and_forget(from.fire_and_forget()); 308 | } 309 | } 310 | 311 | void RSocketMethodOptions::CopyFrom(const ::google::protobuf::Message& from) { 312 | // @@protoc_insertion_point(generalized_copy_from_start:io.rsocket.rpc.RSocketMethodOptions) 313 | if (&from == this) return; 314 | Clear(); 315 | MergeFrom(from); 316 | } 317 | 318 | void RSocketMethodOptions::CopyFrom(const RSocketMethodOptions& from) { 319 | // @@protoc_insertion_point(class_specific_copy_from_start:io.rsocket.rpc.RSocketMethodOptions) 320 | if (&from == this) return; 321 | Clear(); 322 | MergeFrom(from); 323 | } 324 | 325 | bool RSocketMethodOptions::IsInitialized() const { 326 | return true; 327 | } 328 | 329 | void RSocketMethodOptions::Swap(RSocketMethodOptions* other) { 330 | if (other == this) return; 331 | InternalSwap(other); 332 | } 333 | void RSocketMethodOptions::InternalSwap(RSocketMethodOptions* other) { 334 | using std::swap; 335 | swap(fire_and_forget_, other->fire_and_forget_); 336 | _internal_metadata_.Swap(&other->_internal_metadata_); 337 | } 338 | 339 | ::google::protobuf::Metadata RSocketMethodOptions::GetMetadata() const { 340 | protobuf_rsocket_2foptions_2eproto::protobuf_AssignDescriptorsOnce(); 341 | return ::protobuf_rsocket_2foptions_2eproto::file_level_metadata[kIndexInFileMessages]; 342 | } 343 | 344 | ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::MethodOptions, 345 | ::google::protobuf::internal::MessageTypeTraits< ::io::rsocket::rpc::RSocketMethodOptions >, 11, false > 346 | options(kOptionsFieldNumber, *::io::rsocket::rpc::RSocketMethodOptions::internal_default_instance()); 347 | 348 | // @@protoc_insertion_point(namespace_scope) 349 | } // namespace rpc 350 | } // namespace rsocket 351 | } // namespace io 352 | namespace google { 353 | namespace protobuf { 354 | template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::io::rsocket::rpc::RSocketMethodOptions* Arena::CreateMaybeMessage< ::io::rsocket::rpc::RSocketMethodOptions >(Arena* arena) { 355 | return Arena::CreateInternal< ::io::rsocket::rpc::RSocketMethodOptions >(arena); 356 | } 357 | } // namespace protobuf 358 | } // namespace google 359 | 360 | // @@protoc_insertion_point(global_scope) 361 | -------------------------------------------------------------------------------- /rsocket-rpc-protobuf/src/kotlin_plugin/cpp/rsocket/options.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: rsocket/options.proto 3 | 4 | #ifndef PROTOBUF_INCLUDED_rsocket_2foptions_2eproto 5 | #define PROTOBUF_INCLUDED_rsocket_2foptions_2eproto 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include // IWYU pragma: export 20 | #include // IWYU pragma: export 21 | #include 22 | #include 23 | // @@protoc_insertion_point(includes) 24 | #define PROTOBUF_INTERNAL_EXPORT_protobuf_rsocket_2foptions_2eproto 25 | 26 | namespace protobuf_rsocket_2foptions_2eproto { 27 | // Internal implementation detail -- do not use these members. 28 | struct TableStruct { 29 | static const ::google::protobuf::internal::ParseTableField entries[]; 30 | static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; 31 | static const ::google::protobuf::internal::ParseTable schema[1]; 32 | static const ::google::protobuf::internal::FieldMetadata field_metadata[]; 33 | static const ::google::protobuf::internal::SerializationTable serialization_table[]; 34 | static const ::google::protobuf::uint32 offsets[]; 35 | }; 36 | void AddDescriptors(); 37 | } // namespace protobuf_rsocket_2foptions_2eproto 38 | namespace io { 39 | namespace rsocket { 40 | namespace rpc { 41 | class RSocketMethodOptions; 42 | class RSocketMethodOptionsDefaultTypeInternal; 43 | extern RSocketMethodOptionsDefaultTypeInternal _RSocketMethodOptions_default_instance_; 44 | } // namespace rpc 45 | } // namespace rsocket 46 | } // namespace io 47 | namespace google { 48 | namespace protobuf { 49 | template<> ::io::rsocket::rpc::RSocketMethodOptions* Arena::CreateMaybeMessage<::io::rsocket::rpc::RSocketMethodOptions>(Arena*); 50 | } // namespace protobuf 51 | } // namespace google 52 | namespace io { 53 | namespace rsocket { 54 | namespace rpc { 55 | 56 | // =================================================================== 57 | 58 | class RSocketMethodOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:io.rsocket.rpc.RSocketMethodOptions) */ { 59 | public: 60 | RSocketMethodOptions(); 61 | virtual ~RSocketMethodOptions(); 62 | 63 | RSocketMethodOptions(const RSocketMethodOptions& from); 64 | 65 | inline RSocketMethodOptions& operator=(const RSocketMethodOptions& from) { 66 | CopyFrom(from); 67 | return *this; 68 | } 69 | #if LANG_CXX11 70 | RSocketMethodOptions(RSocketMethodOptions&& from) noexcept 71 | : RSocketMethodOptions() { 72 | *this = ::std::move(from); 73 | } 74 | 75 | inline RSocketMethodOptions& operator=(RSocketMethodOptions&& from) noexcept { 76 | if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { 77 | if (this != &from) InternalSwap(&from); 78 | } else { 79 | CopyFrom(from); 80 | } 81 | return *this; 82 | } 83 | #endif 84 | static const ::google::protobuf::Descriptor* descriptor(); 85 | static const RSocketMethodOptions& default_instance(); 86 | 87 | static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY 88 | static inline const RSocketMethodOptions* internal_default_instance() { 89 | return reinterpret_cast( 90 | &_RSocketMethodOptions_default_instance_); 91 | } 92 | static constexpr int kIndexInFileMessages = 93 | 0; 94 | 95 | void Swap(RSocketMethodOptions* other); 96 | friend void swap(RSocketMethodOptions& a, RSocketMethodOptions& b) { 97 | a.Swap(&b); 98 | } 99 | 100 | // implements Message ---------------------------------------------- 101 | 102 | inline RSocketMethodOptions* New() const final { 103 | return CreateMaybeMessage(NULL); 104 | } 105 | 106 | RSocketMethodOptions* New(::google::protobuf::Arena* arena) const final { 107 | return CreateMaybeMessage(arena); 108 | } 109 | void CopyFrom(const ::google::protobuf::Message& from) final; 110 | void MergeFrom(const ::google::protobuf::Message& from) final; 111 | void CopyFrom(const RSocketMethodOptions& from); 112 | void MergeFrom(const RSocketMethodOptions& from); 113 | void Clear() final; 114 | bool IsInitialized() const final; 115 | 116 | size_t ByteSizeLong() const final; 117 | bool MergePartialFromCodedStream( 118 | ::google::protobuf::io::CodedInputStream* input) final; 119 | void SerializeWithCachedSizes( 120 | ::google::protobuf::io::CodedOutputStream* output) const final; 121 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 122 | bool deterministic, ::google::protobuf::uint8* target) const final; 123 | int GetCachedSize() const final { return _cached_size_.Get(); } 124 | 125 | private: 126 | void SharedCtor(); 127 | void SharedDtor(); 128 | void SetCachedSize(int size) const final; 129 | void InternalSwap(RSocketMethodOptions* other); 130 | private: 131 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 132 | return NULL; 133 | } 134 | inline void* MaybeArenaPtr() const { 135 | return NULL; 136 | } 137 | public: 138 | 139 | ::google::protobuf::Metadata GetMetadata() const final; 140 | 141 | // nested types ---------------------------------------------------- 142 | 143 | // accessors ------------------------------------------------------- 144 | 145 | // bool fire_and_forget = 1; 146 | void clear_fire_and_forget(); 147 | static const int kFireAndForgetFieldNumber = 1; 148 | bool fire_and_forget() const; 149 | void set_fire_and_forget(bool value); 150 | 151 | // @@protoc_insertion_point(class_scope:io.rsocket.rpc.RSocketMethodOptions) 152 | private: 153 | 154 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 155 | bool fire_and_forget_; 156 | mutable ::google::protobuf::internal::CachedSize _cached_size_; 157 | friend struct ::protobuf_rsocket_2foptions_2eproto::TableStruct; 158 | }; 159 | // =================================================================== 160 | 161 | static const int kOptionsFieldNumber = 1057; 162 | extern ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::MethodOptions, 163 | ::google::protobuf::internal::MessageTypeTraits< ::io::rsocket::rpc::RSocketMethodOptions >, 11, false > 164 | options; 165 | 166 | // =================================================================== 167 | 168 | #ifdef __GNUC__ 169 | #pragma GCC diagnostic push 170 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 171 | #endif // __GNUC__ 172 | // RSocketMethodOptions 173 | 174 | // bool fire_and_forget = 1; 175 | inline void RSocketMethodOptions::clear_fire_and_forget() { 176 | fire_and_forget_ = false; 177 | } 178 | inline bool RSocketMethodOptions::fire_and_forget() const { 179 | // @@protoc_insertion_point(field_get:io.rsocket.rpc.RSocketMethodOptions.fire_and_forget) 180 | return fire_and_forget_; 181 | } 182 | inline void RSocketMethodOptions::set_fire_and_forget(bool value) { 183 | 184 | fire_and_forget_ = value; 185 | // @@protoc_insertion_point(field_set:io.rsocket.rpc.RSocketMethodOptions.fire_and_forget) 186 | } 187 | 188 | #ifdef __GNUC__ 189 | #pragma GCC diagnostic pop 190 | #endif // __GNUC__ 191 | 192 | // @@protoc_insertion_point(namespace_scope) 193 | 194 | } // namespace rpc 195 | } // namespace rsocket 196 | } // namespace io 197 | 198 | // @@protoc_insertion_point(global_scope) 199 | 200 | #endif // PROTOBUF_INCLUDED_rsocket_2foptions_2eproto 201 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | pluginManagement { 18 | plugins { 19 | id 'com.google.osdetector' version "${osDetectorPluginVersion}" 20 | id 'com.gradle.build-scan' version "${buildScanPluginVersion}" 21 | id 'com.github.johnrengelman.shadow' version "${shadowPluginVersion}" 22 | id 'io.spring.dependency-management' version "${dependencyManagementPluginVersion}" 23 | id 'com.jfrog.bintray' version "${bintrayPluginVersion}" 24 | id 'com.jfrog.artifactory' version "${artifactoryPluginVersion}" 25 | id 'org.jetbrains.kotlin.jvm' version "${kotlinPluginVersion}" 26 | id "com.palantir.git-version" version "${gitPluginVersion}" 27 | id "com.google.protobuf" version "${protobufPluginVersion}" 28 | } 29 | } 30 | 31 | rootProject.name = 'rsocket-rpc-kotlin' 32 | include 'rsocket-rpc-protobuf-idl' 33 | include 'rsocket-rpc-protobuf' 34 | include 'rsocket-rpc-core' 35 | include 'example-idl' 36 | include 'example' 37 | include 'test' 38 | -------------------------------------------------------------------------------- /test/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import static org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS 18 | import static org.apache.tools.ant.taskdefs.condition.Os.isFamily 19 | 20 | plugins { 21 | id 'idea' 22 | } 23 | 24 | description = 'RSocket-kotlin RPC testing & internal websocket support' 25 | 26 | dependencies { 27 | api 'io.projectreactor.netty:reactor-netty' 28 | implementation project(":rsocket-rpc-core") 29 | 30 | testProtobuf project (':rsocket-rpc-protobuf-idl') 31 | 32 | testImplementation 'io.rsocket.kotlin:rsocket-transport-okhttp' 33 | testImplementation 'org.junit.jupiter:junit-jupiter-api' 34 | testImplementation 'org.junit.jupiter:junit-jupiter-engine' 35 | testImplementation 'org.junit.jupiter:junit-jupiter-params' 36 | } 37 | 38 | test { 39 | useJUnitPlatform() 40 | testLogging { 41 | events "passed", "skipped", "failed" 42 | } 43 | } 44 | 45 | def protocPluginBaseName = "rsocket-rpc-protobuf-${osdetector.os}-${osdetector.arch}" 46 | def kotlinPluginPath = "$rootDir/rsocket-rpc-protobuf/build/exe/kotlin_plugin/$protocPluginBaseName" 47 | 48 | if(isFamily(FAMILY_WINDOWS)){ 49 | kotlinPluginPath = kotlinPluginPath + ".exe" 50 | } 51 | 52 | protobuf { 53 | generatedFilesBaseDir = "${projectDir}/src/generated" 54 | 55 | protoc { 56 | artifact = "com.google.protobuf:protoc" 57 | } 58 | plugins { 59 | 60 | rsocketRpcKotlin { 61 | path = kotlinPluginPath 62 | } 63 | } 64 | generateProtoTasks { 65 | all().each { task -> 66 | task.dependsOn ':rsocket-rpc-protobuf:kotlin_pluginExecutable' 67 | // Recompile protos when the codegen has been changed 68 | task.inputs.file kotlinPluginPath 69 | // Recompile protos when build.gradle has been changed, because 70 | // it's possible the version of protoc has been changed. 71 | task.inputs.file "${rootProject.projectDir}/build.gradle" 72 | task.plugins { 73 | rsocketRpcKotlin {} 74 | } 75 | } 76 | } 77 | } 78 | 79 | clean { 80 | delete protobuf.generatedFilesBaseDir 81 | } 82 | 83 | idea { 84 | module { 85 | sourceDirs += file("src/generated/test/java") 86 | sourceDirs += file("src/generated/test/rsocketRpcKotlin") 87 | 88 | generatedSourceDirs += file("src/generated/test/java") 89 | generatedSourceDirs += file("src/generated/test/rsocketRpcKotlin") 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/compile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/compileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | io.netty:netty-buffer:4.1.37.Final 6 | io.netty:netty-codec-http2:4.1.36.Final 7 | io.netty:netty-codec-http:4.1.36.Final 8 | io.netty:netty-codec-socks:4.1.36.Final 9 | io.netty:netty-codec:4.1.36.Final 10 | io.netty:netty-common:4.1.37.Final 11 | io.netty:netty-handler-proxy:4.1.36.Final 12 | io.netty:netty-handler:4.1.36.Final 13 | io.netty:netty-resolver:4.1.36.Final 14 | io.netty:netty-transport-native-epoll:4.1.36.Final 15 | io.netty:netty-transport-native-unix-common:4.1.36.Final 16 | io.netty:netty-transport:4.1.36.Final 17 | io.opentracing:opentracing-api:0.31.0 18 | io.projectreactor.netty:reactor-netty:0.8.10.RELEASE 19 | io.projectreactor:reactor-core:3.2.10.RELEASE 20 | io.reactivex.rxjava2:rxjava:2.2.12 21 | io.rsocket.kotlin:rsocket-core:0.9.7 22 | javax.annotation:javax.annotation-api:1.3.2 23 | javax.inject:javax.inject:1 24 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 25 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 26 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 27 | org.jetbrains:annotations:13.0 28 | org.reactivestreams:reactive-streams:1.0.2 29 | org.slf4j:slf4j-api:1.7.28 30 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/kotlinCompilerClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.intellij.deps:trove4j:1.0.20181211 5 | org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.50 6 | org.jetbrains.kotlin:kotlin-daemon-embeddable:1.3.50 7 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 8 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 9 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 11 | org.jetbrains:annotations:13.0 12 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/kotlinCompilerPluginClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | org.jetbrains.kotlin:kotlin-reflect:1.3.50 5 | org.jetbrains.kotlin:kotlin-script-runtime:1.3.50 6 | org.jetbrains.kotlin:kotlin-scripting-common:1.3.50 7 | org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.3.50 8 | org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.3.50 9 | org.jetbrains.kotlin:kotlin-scripting-jvm:1.3.50 10 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 11 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 12 | org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1 13 | org.jetbrains:annotations:13.0 14 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/protobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/protobufToolsLocator_protoc.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protoc:3.6.1 5 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/testAnnotationProcessor.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/testCompile.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/testCompileClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | com.squareup.okhttp3:okhttp:3.14.2 6 | com.squareup.okio:okio:1.17.2 7 | io.netty:netty-buffer:4.1.37.Final 8 | io.netty:netty-codec-http2:4.1.36.Final 9 | io.netty:netty-codec-http:4.1.36.Final 10 | io.netty:netty-codec-socks:4.1.36.Final 11 | io.netty:netty-codec:4.1.36.Final 12 | io.netty:netty-common:4.1.37.Final 13 | io.netty:netty-handler-proxy:4.1.36.Final 14 | io.netty:netty-handler:4.1.36.Final 15 | io.netty:netty-resolver:4.1.36.Final 16 | io.netty:netty-transport-native-epoll:4.1.36.Final 17 | io.netty:netty-transport-native-unix-common:4.1.36.Final 18 | io.netty:netty-transport:4.1.36.Final 19 | io.opentracing:opentracing-api:0.31.0 20 | io.projectreactor.netty:reactor-netty:0.8.10.RELEASE 21 | io.projectreactor:reactor-core:3.2.10.RELEASE 22 | io.reactivex.rxjava2:rxjava:2.2.12 23 | io.rsocket.kotlin:rsocket-core:0.9.7 24 | io.rsocket.kotlin:rsocket-transport-okhttp:0.9.7 25 | javax.annotation:javax.annotation-api:1.3.2 26 | javax.inject:javax.inject:1 27 | org.apiguardian:apiguardian-api:1.1.0 28 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 29 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 30 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 31 | org.jetbrains:annotations:13.0 32 | org.junit.jupiter:junit-jupiter-api:5.5.1 33 | org.junit.jupiter:junit-jupiter-engine:5.5.1 34 | org.junit.jupiter:junit-jupiter-params:5.5.1 35 | org.junit.platform:junit-platform-commons:1.5.1 36 | org.junit.platform:junit-platform-engine:1.5.1 37 | org.opentest4j:opentest4j:1.2.0 38 | org.reactivestreams:reactive-streams:1.0.2 39 | org.slf4j:slf4j-api:1.7.28 40 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/testProtobuf.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | -------------------------------------------------------------------------------- /test/gradle/dependency-locks/testRuntimeClasspath.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | com.google.protobuf:protobuf-java:3.6.1 5 | com.squareup.okhttp3:okhttp:3.14.2 6 | com.squareup.okio:okio:1.17.2 7 | io.netty:netty-buffer:4.1.37.Final 8 | io.netty:netty-codec-http2:4.1.36.Final 9 | io.netty:netty-codec-http:4.1.36.Final 10 | io.netty:netty-codec-socks:4.1.36.Final 11 | io.netty:netty-codec:4.1.36.Final 12 | io.netty:netty-common:4.1.37.Final 13 | io.netty:netty-handler-proxy:4.1.36.Final 14 | io.netty:netty-handler:4.1.36.Final 15 | io.netty:netty-resolver:4.1.36.Final 16 | io.netty:netty-transport-native-epoll:4.1.36.Final 17 | io.netty:netty-transport-native-unix-common:4.1.36.Final 18 | io.netty:netty-transport:4.1.36.Final 19 | io.opentracing:opentracing-api:0.31.0 20 | io.projectreactor.netty:reactor-netty:0.8.10.RELEASE 21 | io.projectreactor:reactor-core:3.2.10.RELEASE 22 | io.reactivex.rxjava2:rxjava:2.2.12 23 | io.rsocket.kotlin:rsocket-core:0.9.7 24 | io.rsocket.kotlin:rsocket-transport-okhttp:0.9.7 25 | javax.annotation:javax.annotation-api:1.3.2 26 | javax.inject:javax.inject:1 27 | org.apiguardian:apiguardian-api:1.1.0 28 | org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50 29 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50 30 | org.jetbrains.kotlin:kotlin-stdlib:1.3.50 31 | org.jetbrains:annotations:13.0 32 | org.junit.jupiter:junit-jupiter-api:5.5.1 33 | org.junit.jupiter:junit-jupiter-engine:5.5.1 34 | org.junit.jupiter:junit-jupiter-params:5.5.1 35 | org.junit.platform:junit-platform-commons:1.5.1 36 | org.junit.platform:junit-platform-engine:1.5.1 37 | org.opentest4j:opentest4j:1.2.0 38 | org.reactivestreams:reactive-streams:1.0.2 39 | org.slf4j:slf4j-api:1.7.28 40 | -------------------------------------------------------------------------------- /test/src/main/kotlin/io/rsocket/rpc/kotlin/transport/internal/netty/Ext.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.transport.internal.netty 18 | 19 | import io.reactivex.Completable 20 | import io.reactivex.Flowable 21 | import io.reactivex.Single 22 | import reactor.core.publisher.Flux 23 | import reactor.core.publisher.Mono 24 | 25 | internal fun Flux.toFlowable(): Flowable = Flowable.fromPublisher(this) 26 | 27 | internal fun Mono.toCompletable(): Completable = Completable.fromPublisher(this) 28 | 29 | internal fun Mono.toSingle(): Single = Single.fromPublisher(this) 30 | 31 | internal const val frameLengthSize = 3 32 | 33 | internal const val frameLengthMask = 0xFFFFFF -------------------------------------------------------------------------------- /test/src/main/kotlin/io/rsocket/rpc/kotlin/transport/internal/netty/InternalWebsocketDuplexConnection.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.rsocket.rpc.kotlin.transport.internal.netty 17 | 18 | import io.netty.buffer.ByteBuf 19 | import io.netty.buffer.Unpooled.wrappedBuffer 20 | import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame 21 | import io.reactivex.Completable 22 | import io.reactivex.Flowable 23 | import io.rsocket.kotlin.DuplexConnection 24 | import io.rsocket.kotlin.Frame 25 | import org.reactivestreams.Publisher 26 | import reactor.netty.Connection 27 | 28 | class InternalWebsocketDuplexConnection(private val connection:Connection) : DuplexConnection { 29 | private val allocator = connection.channel().alloc() 30 | 31 | override fun send(frame: Publisher): Completable { 32 | return Flowable.fromPublisher(frame) 33 | .concatMap { sendOne(it).toFlowable() } 34 | .ignoreElements() 35 | } 36 | 37 | override fun sendOne(frame: Frame): Completable { 38 | return connection.outbound().sendObject( 39 | BinaryWebSocketFrame( 40 | frame.content().skipBytes(frameLengthSize))) 41 | .then() 42 | .toCompletable() 43 | } 44 | 45 | override fun receive(): Flowable { 46 | return connection.inbound().receive() 47 | .map { buf -> 48 | val composite = allocator.compositeBuffer() 49 | val lengthBuffer = wrappedBuffer(ByteArray(frameLengthSize)) 50 | encodeLength(lengthBuffer, 0, buf.readableBytes()) 51 | composite.addComponents(true, lengthBuffer, buf.retain()) 52 | Frame.from(composite) 53 | }.toFlowable() 54 | } 55 | 56 | override fun availability(): Double = if (connection.isDisposed) 0.0 else 1.0 57 | 58 | override fun close(): Completable = 59 | Completable.fromRunnable { 60 | if (!connection.isDisposed) { 61 | connection.channel().close() 62 | } 63 | } 64 | 65 | override fun onClose(): Completable = connection.onDispose().toCompletable() 66 | 67 | private fun encodeLength(byteBuf: ByteBuf, offset: Int, length: Int) { 68 | if (length and frameLengthMask.inv() != 0) { 69 | throw IllegalArgumentException("Length is larger than 24 bits") 70 | } 71 | byteBuf.setByte(offset, length shr 16) 72 | byteBuf.setByte(offset + 1, length shr 8) 73 | byteBuf.setByte(offset + 2, length) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /test/src/main/kotlin/io/rsocket/rpc/kotlin/transport/internal/netty/server/CloseableChannel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.transport.internal.netty.server 18 | 19 | import io.reactivex.Completable 20 | import io.rsocket.kotlin.Closeable 21 | import io.rsocket.rpc.kotlin.transport.internal.netty.toCompletable 22 | import reactor.netty.DisposableChannel 23 | import java.net.InetSocketAddress 24 | 25 | /** 26 | * A [Closeable] wrapping a [NettyContext], allowing for close and aware of its address. 27 | */ 28 | class CloseableChannel internal constructor(private val disposableChannel: DisposableChannel) 29 | : Closeable { 30 | override fun close(): Completable = 31 | Completable.fromRunnable { 32 | if (!disposableChannel.isDisposed) { 33 | disposableChannel.channel().close() 34 | } 35 | } 36 | 37 | override fun onClose(): Completable = disposableChannel.onDispose().toCompletable() 38 | 39 | /** 40 | * @return socket address. 41 | */ 42 | fun address(): InetSocketAddress = disposableChannel.address() 43 | } 44 | -------------------------------------------------------------------------------- /test/src/main/kotlin/io/rsocket/rpc/kotlin/transport/internal/netty/server/InternalWebsocketServerTransport.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.transport.internal.netty.server 18 | 19 | import io.reactivex.Single 20 | import io.rsocket.kotlin.transport.ServerTransport 21 | import io.rsocket.kotlin.transport.TransportHeaderAware 22 | import io.rsocket.rpc.kotlin.transport.internal.netty.InternalWebsocketDuplexConnection 23 | import io.rsocket.rpc.kotlin.transport.internal.netty.frameLengthMask 24 | import io.rsocket.rpc.kotlin.transport.internal.netty.toSingle 25 | import reactor.netty.Connection 26 | import reactor.netty.http.server.HttpServer 27 | 28 | class InternalWebsocketServerTransport private constructor(internal var server: HttpServer) 29 | : ServerTransport, TransportHeaderAware { 30 | private var transportHeaders: () -> Map = { emptyMap() } 31 | 32 | override fun start(acceptor: ServerTransport.ConnectionAcceptor) 33 | : Single { 34 | return server 35 | .handle { _, response -> 36 | transportHeaders() 37 | .forEach { (name, value) -> response.addHeader(name, value) } 38 | response.sendWebsocket(null, 39 | frameLengthMask 40 | ) { inbound, outbound -> 41 | val connection = 42 | InternalWebsocketDuplexConnection(inbound as Connection) 43 | acceptor(connection).andThen(outbound.neverComplete()) 44 | } 45 | }.bind().toSingle().map { CloseableChannel(it) } 46 | } 47 | 48 | override fun setTransportHeaders(transportHeaders: () -> Map) { 49 | this.transportHeaders = transportHeaders 50 | } 51 | 52 | companion object { 53 | 54 | fun create(bindAddress: String, port: Int): InternalWebsocketServerTransport { 55 | val httpServer = HttpServer.create().host(bindAddress).port(port) 56 | return create( 57 | httpServer 58 | ) 59 | } 60 | 61 | fun create(port: Int): InternalWebsocketServerTransport { 62 | val httpServer = HttpServer.create().port(port) 63 | return create( 64 | httpServer 65 | ) 66 | } 67 | 68 | fun create(server: HttpServer): InternalWebsocketServerTransport { 69 | return InternalWebsocketServerTransport(server) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/src/test/kotlin/io/rsocket/rpc/kotlin/InteractionsTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin 18 | 19 | import io.netty.buffer.ByteBuf 20 | import io.netty.buffer.Unpooled 21 | import io.netty.util.ResourceLeakDetector 22 | import io.reactivex.Completable 23 | import io.reactivex.Flowable 24 | import io.reactivex.Single 25 | import io.reactivex.processors.ReplayProcessor 26 | import io.reactivex.subscribers.TestSubscriber 27 | import io.rsocket.kotlin.Duration 28 | import io.rsocket.kotlin.RSocketFactory 29 | import io.rsocket.kotlin.exceptions.ApplicationException 30 | import io.rsocket.rpc.kotlin.rsocket.RequestHandlingRSocket 31 | import io.rsocket.rpc.kotlin.test.* 32 | import io.rsocket.rpc.kotlin.transport.internal.netty.server.CloseableChannel 33 | import io.rsocket.rpc.kotlin.transport.internal.netty.server.InternalWebsocketServerTransport 34 | import io.rsocket.rpc.kotlin.util.LongTest 35 | import io.rsocket.transport.okhttp.client.OkhttpWebsocketClientTransport 36 | import okhttp3.HttpUrl 37 | import org.junit.jupiter.api.AfterAll 38 | import org.junit.jupiter.api.Assertions 39 | import org.junit.jupiter.api.BeforeAll 40 | import org.junit.jupiter.api.Test 41 | import org.junit.jupiter.params.ParameterizedTest 42 | import org.junit.jupiter.params.provider.MethodSource 43 | import org.reactivestreams.Publisher 44 | import java.nio.charset.Charset 45 | import java.util.concurrent.TimeUnit 46 | 47 | 48 | class InteractionsTest { 49 | 50 | @Test 51 | fun fireAndForget() { 52 | val expected = "test" 53 | testClient.fireAndForget(request(expected)) 54 | .andThen(testClient.anotherFireAndForget(request(expected))) 55 | .timeout(5, TimeUnit.SECONDS) 56 | .blockingAwait() 57 | 58 | val fnfRequests = clientAcceptor 59 | .fnfRequests() 60 | .take(2) 61 | .toList() 62 | .timeout(5, TimeUnit.SECONDS) 63 | .blockingGet() 64 | fnfRequests.forEach { r -> Assertions.assertEquals(expectedMessage, r.message) } 65 | } 66 | 67 | @ParameterizedTest 68 | @MethodSource("requestResponseProvider") 69 | fun requestResponse(requestResponse: (Request) -> Single) { 70 | val expected = "test" 71 | val response = requestResponse(request(expected)) 72 | .timeout(5, TimeUnit.SECONDS) 73 | .blockingGet() 74 | 75 | Assertions.assertEquals(expected, response.message) 76 | } 77 | 78 | @ParameterizedTest 79 | @MethodSource("requestStreamProvider") 80 | fun requestStream(requestStream: (Request) -> Flowable) { 81 | val response = requestStream(request(expectedMessage)) 82 | .toList() 83 | .timeout(5, TimeUnit.SECONDS) 84 | .blockingGet() 85 | 86 | Assertions.assertEquals(expectedStreamCount, response.size) 87 | response.forEach { r -> Assertions.assertEquals(expectedMessage, r.message) } 88 | } 89 | 90 | @ParameterizedTest 91 | @MethodSource("streamRequestProvider") 92 | fun streamRequest(streamRequest: (Publisher) -> Single) { 93 | val response = streamRequest( 94 | streamRequest( 95 | expectedStreamCount, 96 | expectedMessage 97 | ) 98 | ) 99 | .timeout(5, TimeUnit.SECONDS) 100 | .blockingGet() 101 | 102 | Assertions.assertEquals(expectedMessage, response.message) 103 | } 104 | 105 | @ParameterizedTest 106 | @MethodSource("channelProvider") 107 | fun channel(requestResponse: (Publisher) -> Flowable) { 108 | val response = requestResponse( 109 | streamRequest( 110 | expectedStreamCount, 111 | expectedMessage 112 | ) 113 | ) 114 | .toList() 115 | .timeout(5, TimeUnit.SECONDS) 116 | .blockingGet() 117 | 118 | Assertions.assertEquals(expectedStreamCount, response.size) 119 | response.forEach { r -> Assertions.assertEquals(expectedMessage, r.message) } 120 | } 121 | 122 | @ParameterizedTest 123 | @MethodSource("defaultInteractionProvider") 124 | fun defaultInteractionIsError(interaction: (Flowable) -> Flowable) { 125 | val subs = TestSubscriber() 126 | interaction(Flowable.just(request("test"))) 127 | .timeout(5, TimeUnit.SECONDS) 128 | .blockingSubscribe(subs) 129 | 130 | subs.assertValueCount(0) 131 | subs.assertError { e -> e is ApplicationException && "not implemented" == e.message } 132 | } 133 | 134 | @LongTest 135 | fun responseLong() { 136 | Flowable.interval(1, TimeUnit.MILLISECONDS) 137 | .take(30, TimeUnit.SECONDS) 138 | .onBackpressureDrop() 139 | .flatMapSingle { 140 | testClient 141 | .requestResponse( 142 | request(expectedMessage), 143 | "foo".toByteBuf() 144 | ) 145 | } 146 | .rebatchRequests(128) 147 | .doOnNext { r -> Assertions.assertEquals(expectedMessage, r.message) } 148 | .timeout(5, TimeUnit.SECONDS) 149 | .lastOrError() 150 | .blockingGet() 151 | } 152 | 153 | @LongTest 154 | fun responseStreamLong() { 155 | Flowable.interval(1, TimeUnit.MILLISECONDS) 156 | .take(30, TimeUnit.SECONDS) 157 | .onBackpressureDrop() 158 | .flatMap { 159 | testClient 160 | .requestStream( 161 | request(expectedMessage), 162 | "foo".toByteBuf() 163 | ) 164 | } 165 | .rebatchRequests(128) 166 | .doOnNext { r -> Assertions.assertEquals(expectedMessage, r.message) } 167 | .timeout(5, TimeUnit.SECONDS) 168 | .lastOrError() 169 | .blockingGet() 170 | } 171 | 172 | @LongTest 173 | fun requestStreamLong() { 174 | Flowable.interval(1, TimeUnit.MILLISECONDS) 175 | .take(30, TimeUnit.SECONDS) 176 | .onBackpressureDrop() 177 | .flatMapSingle { 178 | testClient 179 | .streamRequest( 180 | streamRequest(16, expectedMessage), 181 | "foo".toByteBuf() 182 | ) 183 | } 184 | .rebatchRequests(128) 185 | .doOnNext { r -> Assertions.assertEquals(expectedMessage, r.message) } 186 | .timeout(5, TimeUnit.SECONDS) 187 | .lastOrError() 188 | .blockingGet() 189 | } 190 | 191 | @LongTest 192 | fun channelLong() { 193 | Flowable.interval(1, TimeUnit.MILLISECONDS) 194 | .take(30, TimeUnit.SECONDS) 195 | .onBackpressureDrop() 196 | .flatMap { 197 | testClient 198 | .channel( 199 | streamRequest( 200 | expectedStreamCount, 201 | expectedMessage 202 | ), "foo".toByteBuf() 203 | ) 204 | } 205 | .rebatchRequests(128) 206 | .doOnNext { r -> Assertions.assertEquals(expectedMessage, r.message) } 207 | .timeout(5, TimeUnit.SECONDS) 208 | .lastOrError() 209 | .blockingGet() 210 | } 211 | 212 | private fun String.toByteBuf(): ByteBuf { 213 | return Unpooled.wrappedBuffer(this.toByteArray(Charset.defaultCharset())) 214 | } 215 | 216 | private fun request(msg: String): Request { 217 | return Request 218 | .newBuilder() 219 | .setMessage(msg) 220 | .build() 221 | } 222 | 223 | private fun streamRequest(count: Int, msg: String): Flowable { 224 | return Flowable.range(0, count).map { request(msg) } 225 | } 226 | 227 | companion object { 228 | const val expectedStreamCount = 5 229 | const val expectedMessage = "test" 230 | 231 | lateinit var testClient: TestServiceClient 232 | private lateinit var server: CloseableChannel 233 | internal lateinit var clientAcceptor: ClientAcceptor 234 | 235 | @JvmStatic 236 | fun requestResponseProvider(): List<(Request) -> Single> = 237 | listOf(testClient::requestResponse, testClient::anotherRequestResponse) 238 | 239 | @JvmStatic 240 | fun requestStreamProvider(): List<(Request) -> Flowable> = 241 | listOf(testClient::requestStream, testClient::anotherRequestStream) 242 | 243 | @JvmStatic 244 | fun streamRequestProvider(): List<(Publisher) -> Single> = 245 | listOf(testClient::streamRequest, testClient::anotherStreamRequest) 246 | 247 | @JvmStatic 248 | fun channelProvider(): List<(Publisher) -> Flowable> = 249 | listOf(testClient::channel, testClient::anotherChannel) 250 | 251 | @JvmStatic 252 | fun defaultInteractionProvider(): List<(Flowable) -> Flowable> = 253 | listOf( 254 | { flowable -> flowable.flatMapSingle { r -> testClient.defaultRequestResponse(r) } }, 255 | { flowable -> flowable.flatMap { r -> testClient.defaultRequestStream(r) } }, 256 | { flowable -> testClient.defaultStreamRequest(flowable).toFlowable() }, 257 | { flowable -> testClient.defaultChannel(flowable) } 258 | ) 259 | 260 | @BeforeAll 261 | @JvmStatic 262 | internal fun setUp() { 263 | ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED) 264 | 265 | server = RSocketFactory.receive() 266 | .acceptor { 267 | { _, rSocket -> 268 | Single.just( 269 | TestServiceServer( 270 | ServerAcceptor(expectedStreamCount, TestServiceClient(rSocket)) 271 | ) 272 | ) 273 | } 274 | }.transport(InternalWebsocketServerTransport.create("localhost", 0)).start() 275 | .timeout(5, TimeUnit.SECONDS) 276 | .blockingGet() 277 | 278 | val address = server.address() 279 | 280 | val url = HttpUrl.Builder() 281 | .scheme("http") 282 | .host(address.hostName) 283 | .port(address.port) 284 | .build() 285 | 286 | clientAcceptor = ClientAcceptor() 287 | val rSocket = RSocketFactory 288 | .connect() 289 | .keepAlive { opts -> 290 | with(opts) { 291 | keepAliveInterval(Duration.ofSeconds(1)) 292 | keepAliveMaxLifeTime(Duration.ofMinutes(2)) 293 | } 294 | } 295 | .acceptor { { RequestHandlingRSocket(TestServiceServer(clientAcceptor)) } } 296 | .transport(OkhttpWebsocketClientTransport.create(url)) 297 | .start().timeout(5, TimeUnit.SECONDS) 298 | .blockingGet() 299 | 300 | testClient = TestServiceClient(rSocket) 301 | } 302 | 303 | @AfterAll 304 | @JvmStatic 305 | internal fun tearDown() { 306 | server 307 | .close() 308 | .blockingAwait(5, TimeUnit.SECONDS) 309 | } 310 | } 311 | } 312 | 313 | internal class ClientAcceptor : TestService { 314 | 315 | private val fnfProcessor = ReplayProcessor.create() 316 | 317 | fun fnfRequests(): Flowable = fnfProcessor 318 | 319 | override fun fireAndForget(message: Request, metadata: ByteBuf): Completable { 320 | fnfProcessor.onNext(message) 321 | return Completable.complete() 322 | } 323 | 324 | override fun anotherFireAndForget(message: Request, metadata: ByteBuf): Completable = 325 | fireAndForget(message, metadata) 326 | } 327 | 328 | private class ServerAcceptor( 329 | private val streamResponseCount: Int, 330 | private val serviceClient: TestServiceClient 331 | ) : TestService { 332 | override fun anotherFireAndForget(message: Request, metadata: ByteBuf): Completable = 333 | fireAndForget(message, metadata) 334 | 335 | override fun fireAndForget(message: Request, metadata: ByteBuf): Completable = 336 | serviceClient.fireAndForget(message) 337 | 338 | override fun anotherRequestResponse(message: Request, metadata: ByteBuf): Single = 339 | requestResponse(message, metadata) 340 | 341 | override fun anotherRequestStream(message: Request, metadata: ByteBuf): Flowable = 342 | requestStream(message, metadata) 343 | 344 | override fun anotherStreamRequest(message: Publisher, metadata: ByteBuf): Single = 345 | streamRequest(message, metadata) 346 | 347 | override fun anotherChannel(message: Publisher, metadata: ByteBuf): Flowable = 348 | channel(message, metadata) 349 | 350 | override fun requestResponse( 351 | message: Request, 352 | metadata: ByteBuf 353 | ): Single = 354 | Single.just(response(message)) 355 | 356 | override fun requestStream( 357 | message: Request, 358 | metadata: ByteBuf 359 | ): Flowable = 360 | response(message, streamResponseCount) 361 | 362 | override fun streamRequest( 363 | message: Publisher, 364 | metadata: ByteBuf 365 | ): Single = 366 | Flowable 367 | .fromPublisher(message) 368 | .lastOrError() 369 | .map { response(it) } 370 | 371 | override fun channel( 372 | message: Publisher, 373 | metadata: ByteBuf 374 | ): Flowable = 375 | Flowable 376 | .fromPublisher(message) 377 | .map { response(it) } 378 | 379 | private fun response(request: Request, count: Int) = 380 | Flowable.range(0, count) 381 | .map { response(request) } 382 | 383 | private fun response(request: Request) = 384 | Response 385 | .newBuilder() 386 | .setMessage(request.message) 387 | .build() 388 | } -------------------------------------------------------------------------------- /test/src/test/kotlin/io/rsocket/rpc/kotlin/util/LongTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.rsocket.rpc.kotlin.util 18 | 19 | import org.junit.jupiter.api.Test 20 | import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable 21 | 22 | @Target(allowedTargets = [AnnotationTarget.TYPE, AnnotationTarget.FUNCTION]) 23 | @Retention(AnnotationRetention.RUNTIME) 24 | @EnabledIfEnvironmentVariable(named = "RSOCKET_RPC_LONG_TEST_ENABLED", matches = "(?i)true") 25 | @Test 26 | annotation class LongTest -------------------------------------------------------------------------------- /test/src/test/proto/test.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | syntax = "proto3"; 18 | 19 | package io.rsocket.rpc.kotlin.test; 20 | 21 | import "google/protobuf/empty.proto"; 22 | import "rsocket/options.proto"; 23 | 24 | option java_package = "io.rsocket.rpc.kotlin.test"; 25 | option java_outer_classname = "Test"; 26 | option java_multiple_files = true; 27 | 28 | message Request { 29 | string message = 1; 30 | } 31 | 32 | message Response { 33 | string message = 1; 34 | } 35 | 36 | service TestService { 37 | 38 | rpc RequestResponse (Request) returns (Response) {} 39 | 40 | rpc AnotherRequestResponse (Request) returns (Response) {} 41 | 42 | rpc DefaultRequestResponse (Request) returns (Response) {} 43 | 44 | rpc RequestStream (Request) returns (stream Response) {} 45 | 46 | rpc AnotherRequestStream (Request) returns (stream Response) {} 47 | 48 | rpc DefaultRequestStream (Request) returns (stream Response) {} 49 | 50 | rpc StreamRequest (stream Request) returns (Response) {} 51 | 52 | rpc AnotherStreamRequest (stream Request) returns (Response) {} 53 | 54 | rpc DefaultStreamRequest (stream Request) returns (Response) {} 55 | 56 | rpc Channel (stream Request) returns (stream Response) {} 57 | 58 | rpc AnotherChannel (stream Request) returns (stream Response) {} 59 | 60 | rpc DefaultChannel (stream Request) returns (stream Response) {} 61 | 62 | rpc FireAndForget(Request) returns (google.protobuf.Empty) { 63 | option (options).fire_and_forget = true; 64 | } 65 | 66 | rpc AnotherFireAndForget(Request) returns (google.protobuf.Empty) { 67 | option (options).fire_and_forget = true; 68 | } 69 | 70 | rpc DefaultFireAndForget(Request) returns (google.protobuf.Empty) { 71 | option (options).fire_and_forget = true; 72 | } 73 | } 74 | --------------------------------------------------------------------------------