Internal change.

PiperOrigin-RevId: 310213705
This commit is contained in:
gVisor bot 2020-05-06 13:12:06 -07:00
parent 591ff0e424
commit 4631de620a
3 changed files with 133 additions and 191 deletions

View File

@ -174,41 +174,41 @@ class PosixImpl final : public posix_server::Posix::Service {
grpc_impl::ServerContext *context,
const ::posix_server::GetSockOptRequest *request,
::posix_server::GetSockOptResponse *response) override {
socklen_t optlen = request->optlen();
std::vector<char> buf(optlen);
response->set_ret(::getsockopt(request->sockfd(), request->level(),
request->optname(), buf.data(), &optlen));
response->set_errno_(errno);
if (optlen >= 0) {
response->set_optval(buf.data(), optlen);
switch (request->type()) {
case ::posix_server::GetSockOptRequest::BYTES: {
socklen_t optlen = request->optlen();
std::vector<char> buf(optlen);
response->set_ret(::getsockopt(request->sockfd(), request->level(),
request->optname(), buf.data(),
&optlen));
if (optlen >= 0) {
response->mutable_optval()->set_bytesval(buf.data(), optlen);
}
break;
}
case ::posix_server::GetSockOptRequest::INT: {
int intval = 0;
socklen_t optlen = sizeof(intval);
response->set_ret(::getsockopt(request->sockfd(), request->level(),
request->optname(), &intval, &optlen));
response->mutable_optval()->set_intval(intval);
break;
}
case ::posix_server::GetSockOptRequest::TIME: {
timeval tv;
socklen_t optlen = sizeof(tv);
response->set_ret(::getsockopt(request->sockfd(), request->level(),
request->optname(), &tv, &optlen));
response->mutable_optval()->mutable_timeval()->set_seconds(tv.tv_sec);
response->mutable_optval()->mutable_timeval()->set_microseconds(
tv.tv_usec);
break;
}
default:
return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
"Unknown SockOpt Type");
}
return ::grpc::Status::OK;
}
::grpc::Status GetSockOptInt(
::grpc::ServerContext *context,
const ::posix_server::GetSockOptIntRequest *request,
::posix_server::GetSockOptIntResponse *response) override {
int opt = 0;
socklen_t optlen = sizeof(opt);
response->set_ret(::getsockopt(request->sockfd(), request->level(),
request->optname(), &opt, &optlen));
response->set_errno_(errno);
response->set_intval(opt);
return ::grpc::Status::OK;
}
::grpc::Status GetSockOptTimeval(
::grpc::ServerContext *context,
const ::posix_server::GetSockOptTimevalRequest *request,
::posix_server::GetSockOptTimevalResponse *response) override {
timeval tv;
socklen_t optlen = sizeof(tv);
response->set_ret(::getsockopt(request->sockfd(), request->level(),
request->optname(), &tv, &optlen));
response->set_errno_(errno);
response->mutable_timeval()->set_seconds(tv.tv_sec);
response->mutable_timeval()->set_microseconds(tv.tv_usec);
return ::grpc::Status::OK;
}
@ -253,33 +253,32 @@ class PosixImpl final : public posix_server::Posix::Service {
grpc_impl::ServerContext *context,
const ::posix_server::SetSockOptRequest *request,
::posix_server::SetSockOptResponse *response) override {
response->set_ret(setsockopt(request->sockfd(), request->level(),
request->optname(), request->optval().c_str(),
request->optval().size()));
response->set_errno_(errno);
return ::grpc::Status::OK;
}
::grpc::Status SetSockOptInt(
::grpc::ServerContext *context,
const ::posix_server::SetSockOptIntRequest *request,
::posix_server::SetSockOptIntResponse *response) override {
int opt = request->intval();
response->set_ret(::setsockopt(request->sockfd(), request->level(),
request->optname(), &opt, sizeof(opt)));
response->set_errno_(errno);
return ::grpc::Status::OK;
}
::grpc::Status SetSockOptTimeval(
::grpc::ServerContext *context,
const ::posix_server::SetSockOptTimevalRequest *request,
::posix_server::SetSockOptTimevalResponse *response) override {
timeval tv = {.tv_sec = static_cast<__time_t>(request->timeval().seconds()),
.tv_usec = static_cast<__suseconds_t>(
request->timeval().microseconds())};
response->set_ret(setsockopt(request->sockfd(), request->level(),
request->optname(), &tv, sizeof(tv)));
switch (request->optval().val_case()) {
case ::posix_server::SockOptVal::kBytesval:
response->set_ret(setsockopt(request->sockfd(), request->level(),
request->optname(),
request->optval().bytesval().c_str(),
request->optval().bytesval().size()));
break;
case ::posix_server::SockOptVal::kIntval: {
int opt = request->optval().intval();
response->set_ret(::setsockopt(request->sockfd(), request->level(),
request->optname(), &opt, sizeof(opt)));
break;
}
case ::posix_server::SockOptVal::kTimeval: {
timeval tv = {.tv_sec = static_cast<__time_t>(
request->optval().timeval().seconds()),
.tv_usec = static_cast<__suseconds_t>(
request->optval().timeval().microseconds())};
response->set_ret(setsockopt(request->sockfd(), request->level(),
request->optname(), &tv, sizeof(tv)));
break;
}
default:
return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
"Unknown SockOpt Type");
}
response->set_errno_(errno);
return ::grpc::Status::OK;
}

View File

@ -42,6 +42,14 @@ message Timeval {
int64 microseconds = 2;
}
message SockOptVal {
oneof val {
bytes bytesval = 1;
int32 intval = 2;
Timeval timeval = 3;
}
}
// Request and Response pairs for each Posix service RPC call, sorted.
message AcceptRequest {
@ -98,36 +106,19 @@ message GetSockOptRequest {
int32 level = 2;
int32 optname = 3;
int32 optlen = 4;
enum SockOptType {
UNSPECIFIED = 0;
BYTES = 1;
INT = 2;
TIME = 3;
}
SockOptType type = 5;
}
message GetSockOptResponse {
int32 ret = 1;
int32 errno_ = 2; // "errno" may fail to compile in c++.
bytes optval = 3;
}
message GetSockOptIntRequest {
int32 sockfd = 1;
int32 level = 2;
int32 optname = 3;
}
message GetSockOptIntResponse {
int32 ret = 1;
int32 errno_ = 2; // "errno" may fail to compile in c++.
int32 intval = 3;
}
message GetSockOptTimevalRequest {
int32 sockfd = 1;
int32 level = 2;
int32 optname = 3;
}
message GetSockOptTimevalResponse {
int32 ret = 1;
int32 errno_ = 2; // "errno" may fail to compile in c++.
Timeval timeval = 3;
SockOptVal optval = 3;
}
message ListenRequest {
@ -167,7 +158,7 @@ message SetSockOptRequest {
int32 sockfd = 1;
int32 level = 2;
int32 optname = 3;
bytes optval = 4;
SockOptVal optval = 4;
}
message SetSockOptResponse {
@ -175,30 +166,6 @@ message SetSockOptResponse {
int32 errno_ = 2; // "errno" may fail to compile in c++.
}
message SetSockOptIntRequest {
int32 sockfd = 1;
int32 level = 2;
int32 optname = 3;
int32 intval = 4;
}
message SetSockOptIntResponse {
int32 ret = 1;
int32 errno_ = 2;
}
message SetSockOptTimevalRequest {
int32 sockfd = 1;
int32 level = 2;
int32 optname = 3;
Timeval timeval = 4;
}
message SetSockOptTimevalResponse {
int32 ret = 1;
int32 errno_ = 2; // "errno" may fail to compile in c++.
}
message SocketRequest {
int32 domain = 1;
int32 type = 2;
@ -233,32 +200,16 @@ service Posix {
rpc Connect(ConnectRequest) returns (ConnectResponse);
// Call getsockname() on the DUT.
rpc GetSockName(GetSockNameRequest) returns (GetSockNameResponse);
// Call getsockopt() on the DUT. You should prefer one of the other
// GetSockOpt* functions with a more structured optval or else you may get the
// encoding wrong, such as making a bad assumption about the server's word
// sizes or endianness.
// Call getsockopt() on the DUT.
rpc GetSockOpt(GetSockOptRequest) returns (GetSockOptResponse);
// Call getsockopt() on the DUT with an int optval.
rpc GetSockOptInt(GetSockOptIntRequest) returns (GetSockOptIntResponse);
// Call getsockopt() on the DUT with a Timeval optval.
rpc GetSockOptTimeval(GetSockOptTimevalRequest)
returns (GetSockOptTimevalResponse);
// Call listen() on the DUT.
rpc Listen(ListenRequest) returns (ListenResponse);
// Call send() on the DUT.
rpc Send(SendRequest) returns (SendResponse);
// Call sendto() on the DUT.
rpc SendTo(SendToRequest) returns (SendToResponse);
// Call setsockopt() on the DUT. You should prefer one of the other
// SetSockOpt* functions with a more structured optval or else you may get the
// encoding wrong, such as making a bad assumption about the server's word
// sizes or endianness.
// Call setsockopt() on the DUT.
rpc SetSockOpt(SetSockOptRequest) returns (SetSockOptResponse);
// Call setsockopt() on the DUT with an int optval.
rpc SetSockOptInt(SetSockOptIntRequest) returns (SetSockOptIntResponse);
// Call setsockopt() on the DUT with a Timeval optval.
rpc SetSockOptTimeval(SetSockOptTimevalRequest)
returns (SetSockOptTimevalResponse);
// Call socket() on the DUT.
rpc Socket(SocketRequest) returns (SocketResponse);
// Call recv() on the DUT.

View File

@ -291,6 +291,26 @@ func (dut *DUT) GetSockNameWithErrno(ctx context.Context, sockfd int32) (int32,
return resp.GetRet(), dut.protoToSockaddr(resp.GetAddr()), syscall.Errno(resp.GetErrno_())
}
func (dut *DUT) getSockOpt(ctx context.Context, sockfd, level, optname, optlen int32, typ pb.GetSockOptRequest_SockOptType) (int32, *pb.SockOptVal, error) {
dut.t.Helper()
req := pb.GetSockOptRequest{
Sockfd: sockfd,
Level: level,
Optname: optname,
Optlen: optlen,
Type: typ,
}
resp, err := dut.posixServer.GetSockOpt(ctx, &req)
if err != nil {
dut.t.Fatalf("failed to call GetSockOpt: %s", err)
}
optval := resp.GetOptval()
if optval == nil {
dut.t.Fatalf("GetSockOpt response does not contain a value")
}
return resp.GetRet(), optval, syscall.Errno(resp.GetErrno_())
}
// GetSockOpt calls getsockopt on the DUT and causes a fatal test failure if it
// doesn't succeed. If more control over the timeout or error handling is
// needed, use GetSockOptWithErrno. Because endianess and the width of values
@ -312,17 +332,12 @@ func (dut *DUT) GetSockOpt(sockfd, level, optname, optlen int32) []byte {
// prefer to use a more specific GetSockOptXxxWithErrno function.
func (dut *DUT) GetSockOptWithErrno(ctx context.Context, sockfd, level, optname, optlen int32) (int32, []byte, error) {
dut.t.Helper()
req := pb.GetSockOptRequest{
Sockfd: sockfd,
Level: level,
Optname: optname,
Optlen: optlen,
ret, optval, errno := dut.getSockOpt(ctx, sockfd, level, optname, optlen, pb.GetSockOptRequest_BYTES)
bytesval, ok := optval.Val.(*pb.SockOptVal_Bytesval)
if !ok {
dut.t.Fatalf("GetSockOpt got value type: %T, want bytes", optval)
}
resp, err := dut.posixServer.GetSockOpt(ctx, &req)
if err != nil {
dut.t.Fatalf("failed to call GetSockOpt: %s", err)
}
return resp.GetRet(), resp.GetOptval(), syscall.Errno(resp.GetErrno_())
return ret, bytesval.Bytesval, errno
}
// GetSockOptInt calls getsockopt on the DUT and causes a fatal test failure
@ -342,16 +357,12 @@ func (dut *DUT) GetSockOptInt(sockfd, level, optname int32) int32 {
// GetSockOptIntWithErrno calls getsockopt with an integer optval.
func (dut *DUT) GetSockOptIntWithErrno(ctx context.Context, sockfd, level, optname int32) (int32, int32, error) {
dut.t.Helper()
req := pb.GetSockOptIntRequest{
Sockfd: sockfd,
Level: level,
Optname: optname,
ret, optval, errno := dut.getSockOpt(ctx, sockfd, level, optname, 0, pb.GetSockOptRequest_INT)
intval, ok := optval.Val.(*pb.SockOptVal_Intval)
if !ok {
dut.t.Fatalf("GetSockOpt got value type: %T, want int", optval)
}
resp, err := dut.posixServer.GetSockOptInt(ctx, &req)
if err != nil {
dut.t.Fatalf("failed to call GetSockOptInt: %s", err)
}
return resp.GetRet(), resp.GetIntval(), syscall.Errno(resp.GetErrno_())
return ret, intval.Intval, errno
}
// GetSockOptTimeval calls getsockopt on the DUT and causes a fatal test failure
@ -371,20 +382,16 @@ func (dut *DUT) GetSockOptTimeval(sockfd, level, optname int32) unix.Timeval {
// GetSockOptTimevalWithErrno calls getsockopt and returns a timeval.
func (dut *DUT) GetSockOptTimevalWithErrno(ctx context.Context, sockfd, level, optname int32) (int32, unix.Timeval, error) {
dut.t.Helper()
req := pb.GetSockOptTimevalRequest{
Sockfd: sockfd,
Level: level,
Optname: optname,
}
resp, err := dut.posixServer.GetSockOptTimeval(ctx, &req)
if err != nil {
dut.t.Fatalf("failed to call GetSockOptTimeval: %s", err)
ret, optval, errno := dut.getSockOpt(ctx, sockfd, level, optname, 0, pb.GetSockOptRequest_TIME)
tv, ok := optval.Val.(*pb.SockOptVal_Timeval)
if !ok {
dut.t.Fatalf("GetSockOpt got value type: %T, want timeval", optval)
}
timeval := unix.Timeval{
Sec: resp.GetTimeval().Seconds,
Usec: resp.GetTimeval().Microseconds,
Sec: tv.Timeval.Seconds,
Usec: tv.Timeval.Microseconds,
}
return resp.GetRet(), timeval, syscall.Errno(resp.GetErrno_())
return ret, timeval, errno
}
// Listen calls listen on the DUT and causes a fatal test failure if it doesn't
@ -473,6 +480,21 @@ func (dut *DUT) SendToWithErrno(ctx context.Context, sockfd int32, buf []byte, f
return resp.GetRet(), syscall.Errno(resp.GetErrno_())
}
func (dut *DUT) setSockOpt(ctx context.Context, sockfd, level, optname int32, optval *pb.SockOptVal) (int32, error) {
dut.t.Helper()
req := pb.SetSockOptRequest{
Sockfd: sockfd,
Level: level,
Optname: optname,
Optval: optval,
}
resp, err := dut.posixServer.SetSockOpt(ctx, &req)
if err != nil {
dut.t.Fatalf("failed to call SetSockOpt: %s", err)
}
return resp.GetRet(), syscall.Errno(resp.GetErrno_())
}
// SetSockOpt calls setsockopt on the DUT and causes a fatal test failure if it
// doesn't succeed. If more control over the timeout or error handling is
// needed, use SetSockOptWithErrno. Because endianess and the width of values
@ -493,17 +515,7 @@ func (dut *DUT) SetSockOpt(sockfd, level, optname int32, optval []byte) {
// prefer to use a more specific SetSockOptXxxWithErrno function.
func (dut *DUT) SetSockOptWithErrno(ctx context.Context, sockfd, level, optname int32, optval []byte) (int32, error) {
dut.t.Helper()
req := pb.SetSockOptRequest{
Sockfd: sockfd,
Level: level,
Optname: optname,
Optval: optval,
}
resp, err := dut.posixServer.SetSockOpt(ctx, &req)
if err != nil {
dut.t.Fatalf("failed to call SetSockOpt: %s", err)
}
return resp.GetRet(), syscall.Errno(resp.GetErrno_())
return dut.setSockOpt(ctx, sockfd, level, optname, &pb.SockOptVal{Val: &pb.SockOptVal_Bytesval{optval}})
}
// SetSockOptInt calls setsockopt on the DUT and causes a fatal test failure
@ -522,17 +534,7 @@ func (dut *DUT) SetSockOptInt(sockfd, level, optname, optval int32) {
// SetSockOptIntWithErrno calls setsockopt with an integer optval.
func (dut *DUT) SetSockOptIntWithErrno(ctx context.Context, sockfd, level, optname, optval int32) (int32, error) {
dut.t.Helper()
req := pb.SetSockOptIntRequest{
Sockfd: sockfd,
Level: level,
Optname: optname,
Intval: optval,
}
resp, err := dut.posixServer.SetSockOptInt(ctx, &req)
if err != nil {
dut.t.Fatalf("failed to call SetSockOptInt: %s", err)
}
return resp.GetRet(), syscall.Errno(resp.GetErrno_())
return dut.setSockOpt(ctx, sockfd, level, optname, &pb.SockOptVal{Val: &pb.SockOptVal_Intval{optval}})
}
// SetSockOptTimeval calls setsockopt on the DUT and causes a fatal test failure
@ -556,17 +558,7 @@ func (dut *DUT) SetSockOptTimevalWithErrno(ctx context.Context, sockfd, level, o
Seconds: int64(tv.Sec),
Microseconds: int64(tv.Usec),
}
req := pb.SetSockOptTimevalRequest{
Sockfd: sockfd,
Level: level,
Optname: optname,
Timeval: &timeval,
}
resp, err := dut.posixServer.SetSockOptTimeval(ctx, &req)
if err != nil {
dut.t.Fatalf("failed to call SetSockOptTimeval: %s", err)
}
return resp.GetRet(), syscall.Errno(resp.GetErrno_())
return dut.setSockOpt(ctx, sockfd, level, optname, &pb.SockOptVal{Val: &pb.SockOptVal_Timeval{&timeval}})
}
// Socket calls socket on the DUT and returns the file descriptor. If socket