Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stream terminated by RST_STREAM with PROTOCOL_ERROR when listening on unix domain socket #742

Closed
BogdanIonesq opened this issue Aug 11, 2021 · 1 comment

Comments

@BogdanIonesq
Copy link

BogdanIonesq commented Aug 11, 2021

Bug Report

Version

tonic v0.5.2
tonic-build v0.5.2

Platform

Linux 5.13.9-arch1-1 x86_64 GNU/Linux

Description

I tried to keep the example as small as possible:
proto/hello.proto

syntax = "proto3";

package hello;

service HelloService {
  rpc SayHello(HelloRequest) returns (HelloResponse) {}
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string first_name = 1;
  string middle_name = 2;
  string last_name = 3;
}

Cargo.toml

...
[[bin]]
name = "server"
path = "src/server.rs"

[dependencies]
tonic = "0.5"
prost = "0.8"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
futures = "0.3.16"
async-stream = "0.3.2"

[build-dependencies]
tonic-build = "0.5"

src/server.rs

use tonic::{transport::Server, Request, Response, Status};
use hello::{HelloRequest, HelloResponse};
use hello::hello_service_server::{HelloService, HelloServiceServer};
use std::path::Path;
use tokio::net::{UnixListener};
use futures::TryFutureExt;
mod unix;

pub mod hello {
    tonic::include_proto!("hello");
}

#[derive(Debug, Default)]
pub struct MyGreeter {}

#[tonic::async_trait]
impl HelloService for MyGreeter {
    async fn say_hello(
        &self,
        request: Request<HelloRequest>,
    ) -> Result<Response<HelloResponse>, Status> {
        println!("Got a request: {:?}", request);

        let reply = HelloResponse {
            first_name: format!("first").into(),
            middle_name: format!("middle").into(),
            last_name: format!("last").into(),
        };

        Ok(Response::new(reply))
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Starting Greeter ...");

    let sock_path = Path::new("/tmp/example.sock");
    let greeter = MyGreeter::default();

    let incoming = {
        let uds = UnixListener::bind(sock_path)?;

        async_stream::stream! {
            while let item = uds.accept().map_ok(|(st, _)| unix::UnixStream(st)).await {
                yield item;
            }
        }
    };

    Server::builder()
        .add_service(HelloServiceServer::new(greeter))
        .serve_with_incoming(incoming)
        .await?;

    Ok(())
}

Along with the straightforward build.rs (compiling the proto/hello.proto) and the mod unix found in the uds example.

Running cargo run --bin server successfully starts the server. However, when executing a grpcurl call from the proto/ directory, the following error is encountered:

$ grpcurl -plaintext -proto hello.proto -d '{"greeting": "hello"}' -unix /tmp/example.sock hello.HelloService/SayHello
ERROR:
  Code: Internal
  Message: stream terminated by RST_STREAM with error code: PROTOCOL_ERROR

I have first encountered this error when executing a gRPC call from a Go client, so I do not think that it is an issue from grpcurl. It seems to be related to the unix domain socket listener, since listening on a random TCP port works:

$ grpcurl -plaintext -proto hello.proto -d '{"greeting": "hello"}' 127.0.0.1:4444 hello.HelloService/SayHello
{
  "firstName": "first",
  "middleName": "middle",
  "lastName": "last"
}

Any ideas how this can be fixed or what the root cause is?

@BogdanIonesq
Copy link
Author

I did some more digging and turns out this is an issue from h2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant