mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2025-12-18 20:50:09 +08:00
Migrate to protorpc (#598)
* refactor: migrate from grpc to protorpc * fix * fix * fix * cleanup * Update mainwindow_grpc.cpp * Update RPC.cpp * fix --------- Co-authored-by: parhelia512 <0011d3@gmail.com>
This commit is contained in:
parent
792dad2bc1
commit
2dde7dbb2e
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -72,7 +72,7 @@ jobs:
|
||||
if: matrix.cross_os != 'public_res'
|
||||
run: |
|
||||
go install github.com/golang/protobuf/protoc-gen-go@latest
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
go install github.com/chai2010/protorpc/protoc-gen-protorpc@latest
|
||||
- name: Build golang parts
|
||||
if: steps.cache-common.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
|
||||
97
3rdparty/protorpc/rpc_client.cc
vendored
Normal file
97
3rdparty/protorpc/rpc_client.cc
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "3rdparty/protorpc/rpc_client.h"
|
||||
#include "3rdparty/protorpc/rpc_wire.h"
|
||||
|
||||
namespace protorpc {
|
||||
|
||||
Client::Client(const char* host, int port):
|
||||
conn_(0), host_(host), port_(port), seq_(0) {
|
||||
//
|
||||
}
|
||||
Client::~Client() {
|
||||
Close();
|
||||
}
|
||||
|
||||
const ::protorpc::Error Client::CallMethod(
|
||||
const std::string& method,
|
||||
const ::std::string* request,
|
||||
::std::string* response
|
||||
) {
|
||||
if(!checkMothdValid(method, request, response)) {
|
||||
return ::protorpc::Error::New(
|
||||
std::string("protorpc.Client.CallMethod: Invalid method, method: ") + method
|
||||
);
|
||||
}
|
||||
return callMethod(method, request, response);
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
void Client::Close() {
|
||||
conn_.Close();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
const ::protorpc::Error Client::callMethod(
|
||||
const std::string& method,
|
||||
const ::std::string* request,
|
||||
::std::string* response
|
||||
) {
|
||||
if(!conn_.IsValid()) {
|
||||
if(!conn_.DialTCP(host_.c_str(), port_)) {
|
||||
return ::protorpc::Error::New(
|
||||
std::string("protorpc.Client.callMethod: DialTCP fail, ") +
|
||||
std::string("host: ") + host_ + std::string(":") + std::to_string(static_cast<long long>(port_))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Error err;
|
||||
|
||||
uint64_t id = seq_++;
|
||||
wire::ResponseHeader respHeader;
|
||||
|
||||
// send request
|
||||
err = wire::SendRequest(&conn_, id, method, request);
|
||||
if(!err.IsNil()) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// recv response hdr
|
||||
err = wire::RecvResponseHeader(&conn_, &respHeader);
|
||||
if(!err.IsNil()) {
|
||||
return err;
|
||||
}
|
||||
// recv response body
|
||||
err = wire::RecvResponseBody(&conn_, &respHeader, response);
|
||||
if(!err.IsNil()) {
|
||||
return err;
|
||||
}
|
||||
if(respHeader.id != id) {
|
||||
return Error::New("protorpc.Client.callMethod: unexpected call id.");
|
||||
}
|
||||
if(!respHeader.error.empty()) {
|
||||
return Error::New(respHeader.error);
|
||||
}
|
||||
|
||||
return Error::Nil();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
bool Client::checkMothdValid(
|
||||
const std::string& method,
|
||||
const ::std::string* request,
|
||||
::std::string* response
|
||||
) const {
|
||||
if(method.empty()) return false;
|
||||
if(!request) return false;
|
||||
if(!response) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace protorpc
|
||||
|
||||
53
3rdparty/protorpc/rpc_client.h
vendored
Normal file
53
3rdparty/protorpc/rpc_client.h
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef PROTORPC_CLIENT_H__
|
||||
#define PROTORPC_CLIENT_H__
|
||||
|
||||
#include "3rdparty/protorpc/rpc_conn.h"
|
||||
#include "3rdparty/protorpc/rpc_error.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace protorpc {
|
||||
|
||||
class Client {
|
||||
public:
|
||||
Client(const char* host, int port);
|
||||
~Client();
|
||||
|
||||
const ::protorpc::Error CallMethod(
|
||||
const std::string& method,
|
||||
const ::std::string* request,
|
||||
::std::string* response
|
||||
);
|
||||
|
||||
// Close the connection
|
||||
void Close();
|
||||
|
||||
private:
|
||||
const ::protorpc::Error callMethod(
|
||||
const std::string& method,
|
||||
const ::std::string* request,
|
||||
::std::string* response
|
||||
);
|
||||
|
||||
bool checkMothdValid(
|
||||
const std::string& method,
|
||||
const ::std::string* request,
|
||||
::std::string* response
|
||||
) const;
|
||||
|
||||
std::string host_;
|
||||
int port_;
|
||||
Conn conn_;
|
||||
uint64_t seq_;
|
||||
};
|
||||
|
||||
} // namespace protorpc
|
||||
|
||||
#endif // PROTORPC_CLIENT_H__
|
||||
98
3rdparty/protorpc/rpc_conn.cc
vendored
Normal file
98
3rdparty/protorpc/rpc_conn.cc
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "3rdparty/protorpc/rpc_conn.h"
|
||||
|
||||
#if (defined(_WIN32) || defined(_WIN64))
|
||||
# include "./rpc_conn_windows.cc"
|
||||
#else
|
||||
# include "./rpc_conn_posix.cc"
|
||||
#endif
|
||||
|
||||
namespace protorpc {
|
||||
|
||||
// MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.
|
||||
static const int maxVarintLen16 = 3;
|
||||
static const int maxVarintLen32 = 5;
|
||||
static const int maxVarintLen64 = 10;
|
||||
|
||||
// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
|
||||
// If the buffer is too small, PutUvarint will panic.
|
||||
static int putUvarint(uint8_t buf[], uint64_t x) {
|
||||
auto i = 0;
|
||||
while(x >= 0x80) {
|
||||
buf[i] = uint8_t(x) | 0x80;
|
||||
x >>= 7;
|
||||
i++;
|
||||
}
|
||||
buf[i] = uint8_t(x);
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
// ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
|
||||
bool Conn::ReadUvarint(uint64_t* rx) {
|
||||
uint64_t x;
|
||||
uint8_t s, b;
|
||||
|
||||
*rx = 0;
|
||||
x = 0;
|
||||
s = 0;
|
||||
|
||||
for(int i = 0; ; i++) {
|
||||
if(!Read(&b, 1)) {
|
||||
return false;
|
||||
}
|
||||
if(b < 0x80) {
|
||||
if(i > 9 || i == 9 && b > 1){
|
||||
printf("protorpc.Conn.ReadUvarint: varint overflows a 64-bit integer\n");
|
||||
return false;
|
||||
}
|
||||
*rx = (x | uint64_t(b)<<s);
|
||||
return true;
|
||||
}
|
||||
x |= (uint64_t(b&0x7f) << s);
|
||||
s += 7;
|
||||
}
|
||||
printf("not reachable!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
|
||||
// If the buffer is too small, PutUvarint will panic.
|
||||
bool Conn::WriteUvarint(uint64_t x) {
|
||||
uint8_t buf[maxVarintLen64];
|
||||
int n = putUvarint(buf, x);
|
||||
return Write(buf, n);
|
||||
}
|
||||
|
||||
bool Conn::RecvFrame(::std::string* data) {
|
||||
uint64_t size;
|
||||
if(!ReadUvarint(&size)) {
|
||||
return false;
|
||||
}
|
||||
if(size != 0) {
|
||||
data->resize(size_t(size));
|
||||
if(!Read((void*)data->data(), int(size))) {
|
||||
data->clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Conn::SendFrame(const ::std::string* data) {
|
||||
if(data == NULL) {
|
||||
return WriteUvarint(uint64_t(0));
|
||||
}
|
||||
|
||||
if(!WriteUvarint(uint64_t(data->size()))) {
|
||||
return false;
|
||||
}
|
||||
if(!Write((void*)data->data(), data->size())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace protorpc
|
||||
49
3rdparty/protorpc/rpc_conn.h
vendored
Normal file
49
3rdparty/protorpc/rpc_conn.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef PROTORPC_CONN_H__
|
||||
#define PROTORPC_CONN_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace protorpc {
|
||||
|
||||
// Initialize socket services
|
||||
bool InitSocket();
|
||||
|
||||
// Stream-oriented network connection.
|
||||
class Conn {
|
||||
public:
|
||||
Conn(int fd=0): sock_(fd) { InitSocket(); }
|
||||
~Conn() {}
|
||||
|
||||
bool IsValid() const;
|
||||
bool DialTCP(const char* host, int port);
|
||||
bool ListenTCP(int port, int backlog=5);
|
||||
void Close();
|
||||
|
||||
Conn* Accept();
|
||||
|
||||
bool Read(void* buf, int len);
|
||||
bool Write(void* buf, int len);
|
||||
|
||||
bool ReadUvarint(uint64_t* x);
|
||||
bool WriteUvarint(uint64_t x);
|
||||
|
||||
bool RecvFrame(::std::string* data);
|
||||
bool SendFrame(const ::std::string* data);
|
||||
|
||||
private:
|
||||
|
||||
int sock_;
|
||||
};
|
||||
|
||||
} // namespace protorpc
|
||||
|
||||
#endif // PROTORPC_CONN_H__
|
||||
|
||||
145
3rdparty/protorpc/rpc_conn_posix.cc
vendored
Normal file
145
3rdparty/protorpc/rpc_conn_posix.cc
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "3rdparty/protorpc/rpc_conn.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__APPLE__) && !defined(MSG_NOSIGNAL)
|
||||
# define MSG_NOSIGNAL 0x4000
|
||||
#endif
|
||||
|
||||
#ifndef NI_MAXSERV
|
||||
# define NI_MAXSERV 32
|
||||
#endif
|
||||
|
||||
namespace protorpc {
|
||||
|
||||
// [static]
|
||||
// Initialize socket services
|
||||
bool InitSocket() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Conn::IsValid() const {
|
||||
return sock_ != 0;
|
||||
}
|
||||
|
||||
bool Conn::DialTCP(const char* host, int port) {
|
||||
struct sockaddr_in sa;
|
||||
int status, len;
|
||||
|
||||
if(IsValid()) Close();
|
||||
if((sock_ = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
printf("protorpc.Conn.DialTCP: socket failed.\n");
|
||||
sock_ = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(sa.sin_zero, 0 , sizeof(sa.sin_zero));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_addr.s_addr = inet_addr(host);
|
||||
size_t addressSize = sizeof(sa);
|
||||
|
||||
if(connect(sock_, (struct sockaddr*)&sa, addressSize) == -1) {
|
||||
printf("protorpc.Conn.DialTCP: connect failed.\n");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
int flag = 1;
|
||||
setsockopt(sock_, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(flag));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Conn::ListenTCP(int port, int backlog) {
|
||||
if(IsValid()) Close();
|
||||
if((sock_ = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
printf("protorpc.Conn.ListenTCP: socket failed.\n");
|
||||
sock_ = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in saddr;
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
saddr.sin_port = htons((u_short) port);
|
||||
|
||||
if(bind(sock_, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
|
||||
printf("protorpc.Conn.ListenTCP: bind failed.\n");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
if(::listen(sock_, backlog) != 0) {
|
||||
printf("protorpc.Conn.ListenTCP: listen failed.\n");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
int flag = 1;
|
||||
setsockopt(sock_, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(flag));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Conn::Close() {
|
||||
if(IsValid()) {
|
||||
::close(sock_);
|
||||
sock_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Conn* Conn::Accept() {
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int sock = ::accept(sock_, (struct sockaddr*)&addr, &addrlen);
|
||||
if(sock == 0) {
|
||||
printf("protorpc.Conn.Accept: failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
return new Conn(sock);
|
||||
}
|
||||
|
||||
bool Conn::Read (void* buf, int len) {
|
||||
char *cbuf = (char*)buf;
|
||||
while(len > 0) {
|
||||
int sent = recv(sock_, cbuf, len, 0);
|
||||
if(sent == 0 || sent == -1) {
|
||||
printf("protorpc.Conn.Read: IO error, err = %d.\n", errno);
|
||||
return false;
|
||||
}
|
||||
cbuf += sent;
|
||||
len -= sent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Conn::Write(void* buf, int len) {
|
||||
const char *cbuf = (char*)buf;
|
||||
int flags = MSG_NOSIGNAL;
|
||||
|
||||
while(len > 0) {
|
||||
int sent = send(sock_, cbuf, len, flags);
|
||||
if(sent == -1) {
|
||||
printf("protorpc.Conn.Write: IO error, err = %d.\n", errno);
|
||||
return false;
|
||||
}
|
||||
cbuf += sent;
|
||||
len -= sent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace protorpc
|
||||
150
3rdparty/protorpc/rpc_conn_windows.cc
vendored
Normal file
150
3rdparty/protorpc/rpc_conn_windows.cc
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "3rdparty/protorpc/rpc_conn.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <ws2tcpip.h> /* send,recv,socklen_t etc */
|
||||
# include <wspiapi.h> /* addrinfo */
|
||||
# pragma comment(lib, "ws2_32.lib")
|
||||
#else
|
||||
# include <ws2tcpip.h> /* send,recv,socklen_t etc */
|
||||
# include <winsock2.h>
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
#ifndef NI_MAXSERV
|
||||
# define NI_MAXSERV 32
|
||||
#endif
|
||||
|
||||
namespace protorpc {
|
||||
|
||||
// [static]
|
||||
// Initialize socket services
|
||||
bool InitSocket() {
|
||||
WSADATA wsaData;
|
||||
WORD wVers;
|
||||
static bool called_once = false;
|
||||
static bool retval = false;
|
||||
|
||||
if(called_once) return retval;
|
||||
|
||||
called_once = true;
|
||||
wVers = MAKEWORD(1, 1);
|
||||
retval = (WSAStartup(wVers, &wsaData) == 0);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool Conn::IsValid() const {
|
||||
return sock_ != 0;
|
||||
}
|
||||
|
||||
bool Conn::DialTCP(const char* host, int port) {
|
||||
if(IsValid()) Close();
|
||||
if((sock_ = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
printf("protorpc.Conn.DialTCP: socket failed.\n");
|
||||
sock_ = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in sa;
|
||||
socklen_t addressSize;
|
||||
memset(sa.sin_zero, 0 , sizeof(sa.sin_zero));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_addr.s_addr = inet_addr(host);
|
||||
addressSize = sizeof(sa);
|
||||
|
||||
if(connect(sock_, ( struct sockaddr*)&sa, addressSize) == -1 ) {
|
||||
printf("protorpc.Conn.DialTCP: connect failed.\n");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
int flag = 1;
|
||||
setsockopt(sock_, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(flag));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Conn::ListenTCP(int port, int backlog) {
|
||||
if(IsValid()) Close();
|
||||
if((sock_ = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
printf("protorpc.Conn.ListenTCP: socket failed.\n");
|
||||
sock_ = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in saddr;
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
saddr.sin_port = htons((u_short) port);
|
||||
|
||||
if(bind(sock_, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
|
||||
printf("protorpc.Conn.ListenTCP: bind failed.\n");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
if(::listen(sock_, backlog) != 0) {
|
||||
printf("protorpc.Conn.ListenTCP: listen failed.\n");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
int flag = 1;
|
||||
setsockopt(sock_, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(flag));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Conn::Close() {
|
||||
if(IsValid()) {
|
||||
::closesocket(sock_);
|
||||
sock_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Conn* Conn::Accept() {
|
||||
struct sockaddr_in addr;
|
||||
int addrlen = sizeof(addr);
|
||||
int sock = ::accept(sock_, (struct sockaddr*)&addr, &addrlen);
|
||||
if(sock == 0) {
|
||||
printf("protorpc.Conn.Accept: failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
return new Conn(sock);
|
||||
}
|
||||
|
||||
bool Conn::Read (void* buf, int len) {
|
||||
char *cbuf = (char*)buf;
|
||||
while(len > 0) {
|
||||
int sent = recv(sock_, cbuf, len, 0);
|
||||
if(sent == 0 || sent == -1) {
|
||||
printf("protorpc.Conn.Read: IO error, err = %d.\n", WSAGetLastError());
|
||||
return false;
|
||||
}
|
||||
cbuf += sent;
|
||||
len -= sent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Conn::Write(void* buf, int len) {
|
||||
const char *cbuf = (char*)buf;
|
||||
int flags = 0;
|
||||
|
||||
while(len > 0) {
|
||||
int sent = send(sock_, cbuf, len, flags );
|
||||
if(sent == -1) {
|
||||
printf("protorpc.Conn.Write: IO error, err = %d.\n", WSAGetLastError());
|
||||
return false;
|
||||
}
|
||||
cbuf += sent;
|
||||
len -= sent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace protorpc
|
||||
32
3rdparty/protorpc/rpc_error.h
vendored
Normal file
32
3rdparty/protorpc/rpc_error.h
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef PROTORPC_ERROR_H__
|
||||
#define PROTORPC_ERROR_H__
|
||||
|
||||
namespace protorpc {
|
||||
|
||||
// Error
|
||||
class Error {
|
||||
public:
|
||||
Error(){}
|
||||
Error(const std::string& err): err_text_(err) {}
|
||||
Error(const Error& err): err_text_(err.err_text_) {}
|
||||
~Error(){}
|
||||
|
||||
static Error Nil() { return Error(); }
|
||||
static Error New(const std::string& err) { return Error(err); }
|
||||
|
||||
bool IsNil()const { return err_text_.empty(); }
|
||||
const std::string& String()const { return err_text_; }
|
||||
|
||||
private:
|
||||
std::string err_text_;
|
||||
};
|
||||
|
||||
} // namespace protorpc
|
||||
|
||||
#endif // PROTORPC_ERROR_H__
|
||||
158
3rdparty/protorpc/rpc_wire.cc
vendored
Normal file
158
3rdparty/protorpc/rpc_wire.cc
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "3rdparty/protorpc/rpc_wire.h"
|
||||
|
||||
namespace protorpc {
|
||||
namespace wire {
|
||||
|
||||
Error SendRequest(Conn* conn,
|
||||
uint64_t id, const std::string& serviceMethod,
|
||||
const ::std::string* request
|
||||
) {
|
||||
// marshal request
|
||||
std::string pbRequest;
|
||||
if(request != NULL) {
|
||||
pbRequest = *request;
|
||||
}
|
||||
|
||||
// generate header
|
||||
RequestHeader header;
|
||||
|
||||
header.id = id;
|
||||
header.method = serviceMethod;
|
||||
|
||||
header.raw_request_len = pbRequest.size();
|
||||
|
||||
// check header size
|
||||
std::string pbHeader = spb::pb::serialize<std::string>(header);
|
||||
if(pbHeader.size() > (unsigned int)protorpc::wire::Const::MAX_REQUEST_HEADER_LEN) {
|
||||
return Error::New("protorpc.SendRequest: header larger than max_header_len.");
|
||||
}
|
||||
|
||||
// send header
|
||||
if(!conn->SendFrame(&pbHeader)) {
|
||||
return Error::New("protorpc.SendRequest: SendFrame header failed.");
|
||||
}
|
||||
|
||||
// send body
|
||||
if(!conn->SendFrame(&pbRequest)) {
|
||||
return Error::New("protorpc.SendRequest: SendFrame body failed.");
|
||||
}
|
||||
|
||||
return Error::Nil();
|
||||
}
|
||||
|
||||
Error RecvRequestHeader(Conn* conn,
|
||||
RequestHeader* header
|
||||
) {
|
||||
// recv header
|
||||
std::string pbHeader;
|
||||
if(!conn->RecvFrame(&pbHeader)) {
|
||||
return Error::New("protorpc.RecvRequestHeader: RecvFrame failed.");
|
||||
}
|
||||
if(pbHeader.size() > (unsigned int)protorpc::wire::Const::MAX_REQUEST_HEADER_LEN) {
|
||||
return Error::New("protorpc.RecvRequestHeader: RecvFrame larger than max_header_len.");
|
||||
}
|
||||
|
||||
// Marshal Header
|
||||
*header = spb::pb::deserialize<RequestHeader>(pbHeader);
|
||||
|
||||
return Error::Nil();
|
||||
}
|
||||
|
||||
Error RecvRequestBody(Conn* conn,
|
||||
const RequestHeader* header,
|
||||
::std::string* request
|
||||
) {
|
||||
// recv body
|
||||
std::string pbRequest;
|
||||
if(!conn->RecvFrame(&pbRequest)) {
|
||||
return Error::New("protorpc.RecvRequestBody: RecvFrame failed.");
|
||||
}
|
||||
|
||||
// check wire header: rawMsgLen
|
||||
if(pbRequest.size() != header->raw_request_len) {
|
||||
return Error::New("protorpc.RecvRequestBody: Unexcpeted raw msg len.");
|
||||
}
|
||||
|
||||
// marshal request
|
||||
*request = pbRequest;
|
||||
|
||||
return Error::Nil();
|
||||
}
|
||||
|
||||
Error SendResponse(Conn* conn,
|
||||
uint64_t id, const std::string& error,
|
||||
const ::std::string* response
|
||||
) {
|
||||
// marshal response
|
||||
std::string pbResponse;
|
||||
if(response != NULL) {
|
||||
pbResponse = *response;
|
||||
}
|
||||
|
||||
// generate header
|
||||
ResponseHeader header;
|
||||
|
||||
header.id = id;
|
||||
header.error = error;
|
||||
|
||||
header.raw_response_len = pbResponse.size();
|
||||
|
||||
// check header size
|
||||
std::string pbHeader = spb::pb::serialize<std::string>(header);
|
||||
|
||||
|
||||
// send header
|
||||
if(!conn->SendFrame(&pbHeader)) {
|
||||
return Error::New("protorpc.SendResponse: SendFrame header failed.");
|
||||
}
|
||||
|
||||
// send body
|
||||
if(!conn->SendFrame(&pbResponse)) {
|
||||
return Error::New("protorpc.SendResponse: SendFrame body failed.");
|
||||
}
|
||||
|
||||
return Error::Nil();
|
||||
}
|
||||
|
||||
Error RecvResponseHeader(Conn* conn,
|
||||
ResponseHeader* header
|
||||
) {
|
||||
// recv header
|
||||
std::string pbHeader;
|
||||
if(!conn->RecvFrame(&pbHeader)) {
|
||||
return Error::New("protorpc.RecvResponseHeader: RecvFrame failed.");
|
||||
}
|
||||
|
||||
// Marshal Header
|
||||
*header = spb::pb::deserialize<ResponseHeader>(pbHeader);
|
||||
|
||||
return Error::Nil();
|
||||
}
|
||||
|
||||
Error RecvResponseBody(Conn* conn,
|
||||
const ResponseHeader* header,
|
||||
::std::string* response
|
||||
) {
|
||||
// recv body
|
||||
std::string pbResponse;
|
||||
if(!conn->RecvFrame(&pbResponse)) {
|
||||
return Error::New("protorpc.RecvResponseBody: RecvFrame failed.");
|
||||
}
|
||||
|
||||
// check wire header: rawMsgLen
|
||||
if(pbResponse.size() != header->raw_response_len) {
|
||||
return Error::New("protorpc.RecvResponseBody: Unexcpeted raw msg len.");
|
||||
}
|
||||
|
||||
// marshal response
|
||||
*response = pbResponse;
|
||||
|
||||
return Error::Nil();
|
||||
}
|
||||
|
||||
} // namespace wire
|
||||
} // namespace protorpc
|
||||
48
3rdparty/protorpc/rpc_wire.h
vendored
Normal file
48
3rdparty/protorpc/rpc_wire.h
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef PROTORPC_WIRE_H__
|
||||
#define PROTORPC_WIRE_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "3rdparty/protorpc/wire.pb/wire.pb.h"
|
||||
#include "3rdparty/protorpc/rpc_error.h"
|
||||
#include "3rdparty/protorpc/rpc_conn.h"
|
||||
|
||||
namespace protorpc {
|
||||
namespace wire {
|
||||
|
||||
Error SendRequest(Conn* conn,
|
||||
uint64_t id, const std::string& serviceMethod,
|
||||
const ::std::string* request
|
||||
);
|
||||
Error RecvRequestHeader(Conn* conn,
|
||||
RequestHeader* header
|
||||
);
|
||||
Error RecvRequestBody(Conn* conn,
|
||||
const RequestHeader* header,
|
||||
::std::string* request
|
||||
);
|
||||
|
||||
Error SendResponse(Conn* conn,
|
||||
uint64_t id, const std::string& error,
|
||||
const ::std::string* response
|
||||
);
|
||||
Error RecvResponseHeader(Conn* conn,
|
||||
ResponseHeader* header
|
||||
);
|
||||
Error RecvResponseBody(Conn* conn,
|
||||
const ResponseHeader* header,
|
||||
::std::string* request
|
||||
);
|
||||
|
||||
} // namespace wire
|
||||
} // namespace protorpc
|
||||
|
||||
#endif // PROTORPC_WIRE_H__
|
||||
|
||||
197
3rdparty/protorpc/wire.pb/wire.pb.cc
vendored
Normal file
197
3rdparty/protorpc/wire.pb/wire.pb.cc
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
#include "wire.pb.h"
|
||||
#include <spb/json.hpp>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
|
||||
namespace spb::json
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
void serialize_value( detail::ostream & stream, const ::protorpc::wire::Const & value )
|
||||
{
|
||||
switch( value )
|
||||
{
|
||||
case ::protorpc::wire::Const::ZERO:
|
||||
return stream.serialize( "ZERO"sv);
|
||||
case ::protorpc::wire::Const::MAX_REQUEST_HEADER_LEN:
|
||||
return stream.serialize( "MAX_REQUEST_HEADER_LEN"sv);
|
||||
default:
|
||||
throw std::system_error( std::make_error_code( std::errc::invalid_argument ) );
|
||||
}
|
||||
}
|
||||
|
||||
void deserialize_value( detail::istream & stream, ::protorpc::wire::Const & value )
|
||||
{
|
||||
auto enum_value = stream.deserialize_string_or_int( 4, 22 );
|
||||
std::visit( detail::overloaded{
|
||||
[&]( std::string_view enum_str )
|
||||
{
|
||||
const auto enum_hash = djb2_hash( enum_str );
|
||||
switch( enum_hash )
|
||||
{
|
||||
case detail::djb2_hash( "ZERO"sv ):
|
||||
if( enum_str == "ZERO"sv ){
|
||||
value = ::protorpc::wire::Const::ZERO;
|
||||
return ; }
|
||||
break ;
|
||||
case detail::djb2_hash( "MAX_REQUEST_HEADER_LEN"sv ):
|
||||
if( enum_str == "MAX_REQUEST_HEADER_LEN"sv ){
|
||||
value = ::protorpc::wire::Const::MAX_REQUEST_HEADER_LEN;
|
||||
return ; }
|
||||
break ;
|
||||
}
|
||||
throw std::system_error( std::make_error_code( std::errc::invalid_argument ) );
|
||||
},
|
||||
[&]( int32_t enum_int )
|
||||
{
|
||||
switch( ::protorpc::wire::Const( enum_int ) )
|
||||
{
|
||||
case ::protorpc::wire::Const::ZERO:
|
||||
case ::protorpc::wire::Const::MAX_REQUEST_HEADER_LEN:
|
||||
value = ::protorpc::wire::Const( enum_int );
|
||||
return ;
|
||||
}
|
||||
throw std::system_error( std::make_error_code( std::errc::invalid_argument ) );
|
||||
}
|
||||
}, enum_value );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
namespace detail
|
||||
{
|
||||
void serialize_value( detail::ostream & stream, const ::protorpc::wire::RequestHeader & value )
|
||||
{
|
||||
stream.serialize( "id"sv, value.id );
|
||||
stream.serialize( "method"sv, value.method );
|
||||
stream.serialize( "raw_request_len"sv, value.raw_request_len );
|
||||
}
|
||||
void deserialize_value( detail::istream & stream, ::protorpc::wire::RequestHeader & value )
|
||||
{
|
||||
auto key = stream.deserialize_key( 2, 15 );
|
||||
switch( djb2_hash( key ) )
|
||||
{
|
||||
case detail::djb2_hash( "id"sv ):
|
||||
if( key == "id"sv )
|
||||
{
|
||||
return stream.deserialize( value.id );
|
||||
}
|
||||
break;
|
||||
case detail::djb2_hash( "method"sv ):
|
||||
if( key == "method"sv )
|
||||
{
|
||||
return stream.deserialize( value.method );
|
||||
}
|
||||
break;
|
||||
case detail::djb2_hash( "raw_request_len"sv ):
|
||||
if( key == "raw_request_len"sv )
|
||||
{
|
||||
return stream.deserialize( value.raw_request_len );
|
||||
}
|
||||
break;
|
||||
case detail::djb2_hash( "rawRequestLen"sv ):
|
||||
if( key == "rawRequestLen"sv )
|
||||
{
|
||||
return stream.deserialize( value.raw_request_len );
|
||||
}
|
||||
break;
|
||||
}
|
||||
return stream.skip_value( );
|
||||
}
|
||||
} // namespace detail
|
||||
namespace detail
|
||||
{
|
||||
void serialize_value( detail::ostream & stream, const ::protorpc::wire::ResponseHeader & value )
|
||||
{
|
||||
stream.serialize( "id"sv, value.id );
|
||||
stream.serialize( "error"sv, value.error );
|
||||
stream.serialize( "raw_response_len"sv, value.raw_response_len );
|
||||
}
|
||||
void deserialize_value( detail::istream & stream, ::protorpc::wire::ResponseHeader & value )
|
||||
{
|
||||
auto key = stream.deserialize_key( 2, 16 );
|
||||
switch( djb2_hash( key ) )
|
||||
{
|
||||
case detail::djb2_hash( "id"sv ):
|
||||
if( key == "id"sv )
|
||||
{
|
||||
return stream.deserialize( value.id );
|
||||
}
|
||||
break;
|
||||
case detail::djb2_hash( "error"sv ):
|
||||
if( key == "error"sv )
|
||||
{
|
||||
return stream.deserialize( value.error );
|
||||
}
|
||||
break;
|
||||
case detail::djb2_hash( "rawResponseLen"sv ):
|
||||
if( key == "rawResponseLen"sv )
|
||||
{
|
||||
return stream.deserialize( value.raw_response_len );
|
||||
}
|
||||
break;
|
||||
case detail::djb2_hash( "raw_response_len"sv ):
|
||||
if( key == "raw_response_len"sv )
|
||||
{
|
||||
return stream.deserialize( value.raw_response_len );
|
||||
}
|
||||
break;
|
||||
}
|
||||
return stream.skip_value( );
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace spb::json
|
||||
#include "wire.pb.h"
|
||||
#include <spb/pb.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace spb::pb
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
void serialize( detail::ostream & stream, const ::protorpc::wire::RequestHeader & value )
|
||||
{
|
||||
stream.serialize_as<scalar_encoder::varint>( 1, value.id );
|
||||
stream.serialize( 2, value.method );
|
||||
stream.serialize_as<scalar_encoder::varint>( 3, value.raw_request_len );
|
||||
}
|
||||
void deserialize_value( detail::istream & stream, ::protorpc::wire::RequestHeader & value, uint32_t tag )
|
||||
{
|
||||
switch( field_from_tag( tag ) )
|
||||
{
|
||||
case 1:
|
||||
return stream.deserialize_as<scalar_encoder::varint>( value.id, tag );
|
||||
case 2:
|
||||
return stream.deserialize( value.method, tag );
|
||||
case 3:
|
||||
return stream.deserialize_as<scalar_encoder::varint>( value.raw_request_len, tag );
|
||||
default:
|
||||
return stream.skip( tag );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
namespace detail
|
||||
{
|
||||
void serialize( detail::ostream & stream, const ::protorpc::wire::ResponseHeader & value )
|
||||
{
|
||||
stream.serialize_as<scalar_encoder::varint>( 1, value.id );
|
||||
stream.serialize( 2, value.error );
|
||||
stream.serialize_as<scalar_encoder::varint>( 3, value.raw_response_len );
|
||||
}
|
||||
void deserialize_value( detail::istream & stream, ::protorpc::wire::ResponseHeader & value, uint32_t tag )
|
||||
{
|
||||
switch( field_from_tag( tag ) )
|
||||
{
|
||||
case 1:
|
||||
return stream.deserialize_as<scalar_encoder::varint>( value.id, tag );
|
||||
case 2:
|
||||
return stream.deserialize( value.error, tag );
|
||||
case 3:
|
||||
return stream.deserialize_as<scalar_encoder::varint>( value.raw_response_len, tag );
|
||||
default:
|
||||
return stream.skip( tag );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace spb::pb
|
||||
85
3rdparty/protorpc/wire.pb/wire.pb.h
vendored
Normal file
85
3rdparty/protorpc/wire.pb/wire.pb.h
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <spb/json.hpp>
|
||||
#include <spb/pb.hpp>
|
||||
#include <string>
|
||||
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
// protorpc wire format wrapper
|
||||
//
|
||||
// 0. Frame Format
|
||||
// len : uvarint64
|
||||
// data: byte[len]
|
||||
//
|
||||
// 1. Client Send Request
|
||||
// Send RequestHeader: sendFrame(zsock, hdr, len(hdr))
|
||||
// Send Request: sendFrame(zsock, body, hdr.snappy_compressed_request_len)
|
||||
//
|
||||
// 2. Server Recv Request
|
||||
// Recv RequestHeader: recvFrame(zsock, hdr, max_hdr_len, 0)
|
||||
// Recv Request: recvFrame(zsock, body, hdr.snappy_compressed_request_len, 0)
|
||||
//
|
||||
// 3. Server Send Response
|
||||
// Send ResponseHeader: sendFrame(zsock, hdr, len(hdr))
|
||||
// Send Response: sendFrame(zsock, body, hdr.snappy_compressed_response_len)
|
||||
//
|
||||
// 4. Client Recv Response
|
||||
// Recv ResponseHeader: recvFrame(zsock, hdr, max_hdr_len, 0)
|
||||
// Recv Response: recvFrame(zsock, body, hdr.snappy_compressed_response_len, 0)
|
||||
//
|
||||
namespace protorpc::wire
|
||||
{
|
||||
enum class Const : int32_t
|
||||
{
|
||||
ZERO = 0,
|
||||
MAX_REQUEST_HEADER_LEN = 1024,
|
||||
};
|
||||
struct RequestHeader
|
||||
{
|
||||
uint64_t id;
|
||||
std::string method;
|
||||
uint32_t raw_request_len;
|
||||
};
|
||||
struct ResponseHeader
|
||||
{
|
||||
uint64_t id;
|
||||
std::string error;
|
||||
uint32_t raw_response_len;
|
||||
};
|
||||
}// namespace protorpc::wire
|
||||
|
||||
namespace spb::json::detail
|
||||
{
|
||||
struct ostream;
|
||||
struct istream;
|
||||
|
||||
void serialize_value( ostream & stream, const protorpc::wire::RequestHeader & value );
|
||||
void deserialize_value( istream & stream, protorpc::wire::RequestHeader & value );
|
||||
|
||||
|
||||
void serialize_value( ostream & stream, const protorpc::wire::ResponseHeader & value );
|
||||
void deserialize_value( istream & stream, protorpc::wire::ResponseHeader & value );
|
||||
|
||||
|
||||
void serialize_value( ostream & stream, const protorpc::wire::Const & value );
|
||||
void deserialize_value( istream & stream, protorpc::wire::Const & value );
|
||||
|
||||
} // namespace spb::json::detail
|
||||
namespace spb::pb::detail
|
||||
{
|
||||
struct ostream;
|
||||
struct istream;
|
||||
|
||||
void serialize( ostream & stream, const protorpc::wire::RequestHeader & value );
|
||||
void deserialize_value( istream & stream, protorpc::wire::RequestHeader & value, uint32_t tag );
|
||||
|
||||
|
||||
void serialize( ostream & stream, const protorpc::wire::ResponseHeader & value );
|
||||
void deserialize_value( istream & stream, protorpc::wire::ResponseHeader & value, uint32_t tag );
|
||||
|
||||
} // namespace spb::pb::detail
|
||||
50
3rdparty/protorpc/wire.pb/wire.proto
vendored
Normal file
50
3rdparty/protorpc/wire.pb/wire.proto
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
//
|
||||
// protorpc wire format wrapper
|
||||
//
|
||||
// 0. Frame Format
|
||||
// len : uvarint64
|
||||
// data: byte[len]
|
||||
//
|
||||
// 1. Client Send Request
|
||||
// Send RequestHeader: sendFrame(zsock, hdr, len(hdr))
|
||||
// Send Request: sendFrame(zsock, body, hdr.snappy_compressed_request_len)
|
||||
//
|
||||
// 2. Server Recv Request
|
||||
// Recv RequestHeader: recvFrame(zsock, hdr, max_hdr_len, 0)
|
||||
// Recv Request: recvFrame(zsock, body, hdr.snappy_compressed_request_len, 0)
|
||||
//
|
||||
// 3. Server Send Response
|
||||
// Send ResponseHeader: sendFrame(zsock, hdr, len(hdr))
|
||||
// Send Response: sendFrame(zsock, body, hdr.snappy_compressed_response_len)
|
||||
//
|
||||
// 4. Client Recv Response
|
||||
// Recv ResponseHeader: recvFrame(zsock, hdr, max_hdr_len, 0)
|
||||
// Recv Response: recvFrame(zsock, body, hdr.snappy_compressed_response_len, 0)
|
||||
//
|
||||
package protorpc.wire;
|
||||
option go_package = "protorpc.wire";
|
||||
|
||||
enum Const {
|
||||
ZERO = 0;
|
||||
MAX_REQUEST_HEADER_LEN = 1024;
|
||||
}
|
||||
|
||||
message RequestHeader {
|
||||
required uint64 id = 1;
|
||||
required string method = 2;
|
||||
|
||||
required uint32 raw_request_len = 3;
|
||||
}
|
||||
|
||||
message ResponseHeader {
|
||||
required uint64 id = 1;
|
||||
required string error = 2;
|
||||
|
||||
required uint32 raw_response_len = 3;
|
||||
}
|
||||
@ -85,7 +85,12 @@ set(PROJECT_SOURCES
|
||||
3rdparty/quirc/quirc.c
|
||||
3rdparty/quirc/version_db.c
|
||||
|
||||
src/api/gRPC.cpp
|
||||
3rdparty/protorpc/rpc_client.cc
|
||||
3rdparty/protorpc/rpc_conn.cc
|
||||
3rdparty/protorpc/rpc_wire.cc
|
||||
3rdparty/protorpc/wire.pb/wire.pb.cc
|
||||
|
||||
src/api/RPC.cpp
|
||||
|
||||
src/dataStore/Database.cpp
|
||||
src/stats/traffic/TrafficLooper.cpp
|
||||
|
||||
29
core/protorpc/.editorconfig
Normal file
29
core/protorpc/.editorconfig
Normal file
@ -0,0 +1,29 @@
|
||||
# Copyright 2018 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
# http://editorconfig.org/
|
||||
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
|
||||
[*.{go,proto}]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
tab_width = 4
|
||||
|
||||
# Matches the exact files either package.json or .travis.yml
|
||||
[{package.json,.travis.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
12
core/protorpc/.travis.yml
Normal file
12
core/protorpc/.travis.yml
Normal file
@ -0,0 +1,12 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.13
|
||||
- 1.14
|
||||
- 1.15
|
||||
- 1.16
|
||||
- tip
|
||||
|
||||
before_script:
|
||||
- go get github.com/golang/snappy
|
||||
- go get github.com/golang/protobuf/proto
|
||||
24
core/protorpc/Dockerfile
Normal file
24
core/protorpc/Dockerfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright 2018 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
FROM golang:1.9.2-alpine3.6 as builder
|
||||
|
||||
RUN apk add --no-cache git curl openssl
|
||||
|
||||
RUN go get github.com/golang/protobuf/protoc-gen-go
|
||||
RUN go get github.com/chai2010/protorpc/protoc-gen-protorpc
|
||||
RUN go get github.com/chai2010/protorpc/protoc-gen-stdrpc
|
||||
|
||||
# the protoc can't run on alpine,
|
||||
# we only need the protobuf's stdarnd library in the `/protoc/include`.
|
||||
RUN mkdir -p /protoc && cd /protoc \
|
||||
&& wget https://github.com/google/protobuf/releases/download/v3.5.0/protoc-3.5.0-linux-x86_64.zip \
|
||||
&& unzip protoc-3.5.0-linux-x86_64.zip
|
||||
|
||||
FROM golang:1.9.2-alpine3.6
|
||||
|
||||
RUN apk add --no-cache git protobuf make curl openssl
|
||||
|
||||
COPY --from=builder /protoc/include /usr/local/include
|
||||
COPY --from=builder /go/bin /go/bin
|
||||
27
core/protorpc/LICENSE
Normal file
27
core/protorpc/LICENSE
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2014, chai2010
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the {organization} nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
173
core/protorpc/README.md
Normal file
173
core/protorpc/README.md
Normal file
@ -0,0 +1,173 @@
|
||||
- *Go语言QQ群: 102319854, 1055927514*
|
||||
- *凹语言(凹读音“Wa”)(The Wa Programming Language): https://github.com/wa-lang/wa*
|
||||
|
||||
----
|
||||
|
||||
# protorpc
|
||||
|
||||
```
|
||||
██████╗ ██████╗ ██████╗ ████████╗ ██████╗ ██████╗ ██████╗ ██████╗
|
||||
██╔══██╗██╔══██╗██╔═══██╗╚══██╔══╝██╔═══██╗ ██╔══██╗██╔══██╗██╔════╝
|
||||
██████╔╝██████╔╝██║ ██║ ██║ ██║ ██║█████╗██████╔╝██████╔╝██║
|
||||
██╔═══╝ ██╔══██╗██║ ██║ ██║ ██║ ██║╚════╝██╔══██╗██╔═══╝ ██║
|
||||
██║ ██║ ██║╚██████╔╝ ██║ ╚██████╔╝ ██║ ██║██║ ╚██████╗
|
||||
╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═════╝
|
||||
```
|
||||
|
||||
[](https://travis-ci.org/chai2010/protorpc)
|
||||
[](https://godoc.org/github.com/chai2010/protorpc)
|
||||
|
||||
- C++ Version(Proto2): [https://github.com/chai2010/protorpc.cxx](https://github.com/chai2010/protorpc.cxx)
|
||||
- C++ Version(Proto3): [https://github.com/chai2010/protorpc3-cxx](https://github.com/chai2010/protorpc3-cxx)
|
||||
- Talks: [Go/C++语言Protobuf-RPC简介](http://go-talks.appspot.com/github.com/chai2010/talks/chai2010-protorpc-intro.slide)
|
||||
|
||||
# Install
|
||||
|
||||
Install `protorpc` package:
|
||||
|
||||
1. `go install github.com/golang/protobuf/protoc-gen-go`
|
||||
1. `go get github.com/chai2010/protorpc`
|
||||
1. `go run hello.go`
|
||||
|
||||
Install `protoc-gen-go` plugin:
|
||||
|
||||
1. install `protoc` at first: http://github.com/google/protobuf/releases
|
||||
1. `go get github.com/golang/protobuf/protoc-gen-go`
|
||||
1. `go get github.com/chai2010/protorpc/protoc-gen-protorpc`
|
||||
1. `go generate github.com/chai2010/protorpc/examples/service.pb`
|
||||
1. `go test github.com/chai2010/protorpc/examples/service.pb`
|
||||
|
||||
|
||||
# Examples
|
||||
|
||||
First, create [echo.proto](examples/service.pb/echo.proto):
|
||||
|
||||
```Proto
|
||||
syntax = "proto3";
|
||||
|
||||
package service;
|
||||
|
||||
message EchoRequest {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
message EchoResponse {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
service EchoService {
|
||||
rpc Echo (EchoRequest) returns (EchoResponse);
|
||||
rpc EchoTwice (EchoRequest) returns (EchoResponse);
|
||||
}
|
||||
```
|
||||
|
||||
Second, generate [echo.pb.go](examples/service.pb/echo.pb.go) and [echo.pb.protorpc.go](examples/service.pb/echo.pb.protorpc.go)
|
||||
from [echo.proto](examples/service.pb/echo.proto) (we can use `go generate` to invoke this command, see [proto.go](examples/service.pb/proto.go)).
|
||||
|
||||
protoc --go_out=. echo.proto
|
||||
protoc --protorpc_out=. echo.proto
|
||||
|
||||
|
||||
Now, we can use the stub code like this:
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/chai2010/protorpc"
|
||||
service "github.com/chai2010/protorpc/examples/service.pb"
|
||||
)
|
||||
|
||||
type Echo int
|
||||
|
||||
func (t *Echo) Echo(args *service.EchoRequest, reply *service.EchoResponse) error {
|
||||
reply.Msg = args.Msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Echo) EchoTwice(args *service.EchoRequest, reply *service.EchoResponse) error {
|
||||
reply.Msg = args.Msg + args.Msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
go service.ListenAndServeEchoService("tcp", `127.0.0.1:9527`, new(Echo))
|
||||
}
|
||||
|
||||
func main() {
|
||||
echoClient, err := service.DialEchoService("tcp", `127.0.0.1:9527`)
|
||||
if err != nil {
|
||||
log.Fatalf("service.DialEchoService: %v", err)
|
||||
}
|
||||
defer echoClient.Close()
|
||||
|
||||
args := &service.EchoRequest{Msg: "你好, 世界!"}
|
||||
reply, err := echoClient.EchoTwice(args)
|
||||
if err != nil {
|
||||
log.Fatalf("echoClient.EchoTwice: %v", err)
|
||||
}
|
||||
fmt.Println(reply.Msg)
|
||||
|
||||
// or use normal client
|
||||
client, err := protorpc.Dial("tcp", `127.0.0.1:9527`)
|
||||
if err != nil {
|
||||
log.Fatalf("protorpc.Dial: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
echoClient1 := &service.EchoServiceClient{client}
|
||||
echoClient2 := &service.EchoServiceClient{client}
|
||||
reply, err = echoClient1.EchoTwice(args)
|
||||
reply, err = echoClient2.EchoTwice(args)
|
||||
_, _ = reply, err
|
||||
|
||||
// Output:
|
||||
// 你好, 世界!你好, 世界!
|
||||
}
|
||||
```
|
||||
|
||||
[More examples](examples).
|
||||
|
||||
# standard net/rpc
|
||||
|
||||
First, create [echo.proto](examples/stdrpc.pb/echo.proto):
|
||||
|
||||
```Proto
|
||||
syntax = "proto3";
|
||||
|
||||
package service;
|
||||
|
||||
message EchoRequest {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
message EchoResponse {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
service EchoService {
|
||||
rpc Echo (EchoRequest) returns (EchoResponse);
|
||||
rpc EchoTwice (EchoRequest) returns (EchoResponse);
|
||||
}
|
||||
```
|
||||
|
||||
Second, generate [echo.pb.go](examples/stdrpc.pb/echo.pb.go) from [echo.proto](examples/stdrpc.pb/echo.proto) with `protoc-gen-stdrpc` plugin.
|
||||
|
||||
protoc --stdrpc_out=. echo.proto
|
||||
|
||||
The stdrpc plugin generated code do not depends **protorpc** package, it use gob as the default rpc encoding.
|
||||
|
||||
# Add prefix
|
||||
|
||||
```
|
||||
$ ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX=abc protoc --protorpc_out=. x.proto
|
||||
```
|
||||
|
||||
# BUGS
|
||||
|
||||
Report bugs to <chaishushan@gmail.com>.
|
||||
|
||||
Thanks!
|
||||
23
core/protorpc/changelog.md
Normal file
23
core/protorpc/changelog.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Changelogs
|
||||
|
||||
## 1.1.3 - 2021.7.12
|
||||
|
||||
- fix `readRequestHeader` maxSize, response error maybe very long
|
||||
|
||||
## 1.1.2 - 2021.7.6
|
||||
|
||||
- fix `UseSnappy` typo
|
||||
|
||||
## 1.1.1 - 2021.7.4
|
||||
|
||||
- protoc-gen-plugin: ignore format error
|
||||
|
||||
## 1.1.0 - 2021.7.4
|
||||
|
||||
- add `UseSappy` and `UseCrc32ChecksumIEEE`
|
||||
- add `ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX` env flag
|
||||
- fix frame size overflow panic (issue12)
|
||||
|
||||
## 1.0.0 - go mod version (2018)
|
||||
|
||||
- init version
|
||||
135
core/protorpc/client.go
Normal file
135
core/protorpc/client.go
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protorpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
wire "github.com/chai2010/protorpc/wire.pb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
type clientCodec struct {
|
||||
r io.Reader
|
||||
w io.Writer
|
||||
c io.Closer
|
||||
|
||||
// temporary work space
|
||||
respHeader wire.ResponseHeader
|
||||
|
||||
// Protobuf-RPC responses include the request id but not the request method.
|
||||
// Package rpc expects both.
|
||||
// We save the request method in pending when sending a request
|
||||
// and then look it up by request ID when filling out the rpc Response.
|
||||
mutex sync.Mutex // protects pending
|
||||
pending map[uint64]string // map request id to method name
|
||||
}
|
||||
|
||||
// NewClientCodec returns a new rpc.ClientCodec using Protobuf-RPC on conn.
|
||||
func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec {
|
||||
return &clientCodec{
|
||||
r: conn,
|
||||
w: conn,
|
||||
c: conn,
|
||||
pending: make(map[uint64]string),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) error {
|
||||
c.mutex.Lock()
|
||||
c.pending[r.Seq] = r.ServiceMethod
|
||||
c.mutex.Unlock()
|
||||
|
||||
var request proto.Message
|
||||
if param != nil {
|
||||
var ok bool
|
||||
if request, ok = param.(proto.Message); !ok {
|
||||
return fmt.Errorf(
|
||||
"protorpc.ClientCodec.WriteRequest: %T does not implement proto.Message",
|
||||
param,
|
||||
)
|
||||
}
|
||||
}
|
||||
err := writeRequest(c.w, r.Seq, r.ServiceMethod, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *clientCodec) ReadResponseHeader(r *rpc.Response) error {
|
||||
header := wire.ResponseHeader{}
|
||||
err := readResponseHeader(c.r, &header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.mutex.Lock()
|
||||
r.Seq = *header.Id
|
||||
r.Error = *header.Error
|
||||
r.ServiceMethod = c.pending[r.Seq]
|
||||
delete(c.pending, r.Seq)
|
||||
c.mutex.Unlock()
|
||||
|
||||
c.respHeader = header
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *clientCodec) ReadResponseBody(x interface{}) error {
|
||||
var response proto.Message
|
||||
if x != nil {
|
||||
var ok bool
|
||||
response, ok = x.(proto.Message)
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
"protorpc.ClientCodec.ReadResponseBody: %T does not implement proto.Message",
|
||||
x,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
err := readResponseBody(c.r, &c.respHeader, response)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.respHeader = wire.ResponseHeader{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close closes the underlying connection.
|
||||
func (c *clientCodec) Close() error {
|
||||
return c.c.Close()
|
||||
}
|
||||
|
||||
// NewClient returns a new rpc.Client to handle requests to the
|
||||
// set of services at the other end of the connection.
|
||||
func NewClient(conn io.ReadWriteCloser) *rpc.Client {
|
||||
return rpc.NewClientWithCodec(NewClientCodec(conn))
|
||||
}
|
||||
|
||||
// Dial connects to a Protobuf-RPC server at the specified network address.
|
||||
func Dial(network, address string) (*rpc.Client, error) {
|
||||
conn, err := net.Dial(network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewClient(conn), err
|
||||
}
|
||||
|
||||
// DialTimeout connects to a Protobuf-RPC server at the specified network address.
|
||||
func DialTimeout(network, address string, timeout time.Duration) (*rpc.Client, error) {
|
||||
conn, err := net.DialTimeout(network, address, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewClient(conn), err
|
||||
}
|
||||
117
core/protorpc/conn.go
Normal file
117
core/protorpc/conn.go
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protorpc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
func sendFrame(w io.Writer, data []byte) (err error) {
|
||||
// Allocate enough space for the biggest uvarint
|
||||
var size [binary.MaxVarintLen64]byte
|
||||
|
||||
if data == nil || len(data) == 0 {
|
||||
n := binary.PutUvarint(size[:], uint64(0))
|
||||
if err = write(w, size[:n], false); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Write the size and data
|
||||
n := binary.PutUvarint(size[:], uint64(len(data)))
|
||||
if err = write(w, size[:n], false); err != nil {
|
||||
return
|
||||
}
|
||||
if err = write(w, data, false); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func recvFrame(r io.Reader, maxSize int) (data []byte, err error) {
|
||||
size, err := readUvarint(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if maxSize > 0 {
|
||||
if int(size) > maxSize {
|
||||
return nil, fmt.Errorf("protorpc: varint overflows maxSize(%d)", maxSize)
|
||||
}
|
||||
}
|
||||
if size != 0 {
|
||||
data = make([]byte, size)
|
||||
if err = read(r, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
|
||||
func readUvarint(r io.Reader) (uint64, error) {
|
||||
var x uint64
|
||||
var s uint
|
||||
for i := 0; ; i++ {
|
||||
var b byte
|
||||
b, err := readByte(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if b < 0x80 {
|
||||
if i > 9 || i == 9 && b > 1 {
|
||||
return x, errors.New("protorpc: varint overflows a 64-bit integer")
|
||||
}
|
||||
return x | uint64(b)<<s, nil
|
||||
}
|
||||
x |= uint64(b&0x7f) << s
|
||||
s += 7
|
||||
}
|
||||
}
|
||||
|
||||
func write(w io.Writer, data []byte, onePacket bool) error {
|
||||
if onePacket {
|
||||
if _, err := w.Write(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
for index := 0; index < len(data); {
|
||||
n, err := w.Write(data[index:])
|
||||
if err != nil {
|
||||
if nerr, ok := err.(net.Error); !ok || !nerr.Temporary() {
|
||||
return err
|
||||
}
|
||||
}
|
||||
index += n
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func read(r io.Reader, data []byte) error {
|
||||
for index := 0; index < len(data); {
|
||||
n, err := r.Read(data[index:])
|
||||
if err != nil {
|
||||
if nerr, ok := err.(net.Error); !ok || !nerr.Temporary() {
|
||||
return err
|
||||
}
|
||||
}
|
||||
index += n
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readByte(r io.Reader) (c byte, err error) {
|
||||
data := make([]byte, 1)
|
||||
if err = read(r, data); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
c = data[0]
|
||||
return
|
||||
}
|
||||
111
core/protorpc/doc.go
Normal file
111
core/protorpc/doc.go
Normal file
@ -0,0 +1,111 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package protorpc implements a Protobuf-RPC ClientCodec and ServerCodec
|
||||
for the rpc package.
|
||||
|
||||
To install it, you must first have Go (version 1) installed
|
||||
(see http://golang.org/doc/install). Next, install the standard
|
||||
protocol buffer implementation from http://github.com/google/protobuf/;
|
||||
you must be running version 2.3 or higher.
|
||||
|
||||
Finally run
|
||||
|
||||
go get github.com/chai2010/protorpc
|
||||
go get github.com/chai2010/protorpc/protoc-gen-protorpc
|
||||
|
||||
to install the support library and protocol compiler.
|
||||
|
||||
Here is a simple proto file("arith.pb/arith.proto"):
|
||||
|
||||
package arith;
|
||||
|
||||
message ArithRequest {
|
||||
optional int32 a = 1;
|
||||
optional int32 b = 2;
|
||||
}
|
||||
|
||||
message ArithResponse {
|
||||
optional int32 val = 1;
|
||||
optional int32 quo = 2;
|
||||
optional int32 rem = 3;
|
||||
}
|
||||
|
||||
service ArithService {
|
||||
rpc multiply (ArithRequest) returns (ArithResponse);
|
||||
rpc divide (ArithRequest) returns (ArithResponse);
|
||||
}
|
||||
|
||||
Then use "protoc-gen-go" to generate "arith.pb.go" file:
|
||||
|
||||
cd arith.pb && protoc --go_out=. arith.proto
|
||||
|
||||
|
||||
Use "protoc-gen-protorpc" to generate "arith.pb.protorpc.go" file (include stub code):
|
||||
|
||||
cd arith.pb && protoc --protorpc_out=. arith.proto
|
||||
|
||||
The server calls (for TCP service):
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"./arith.pb"
|
||||
)
|
||||
|
||||
type Arith int
|
||||
|
||||
func (t *Arith) Multiply(args *arith.ArithRequest, reply *arith.ArithResponse) error {
|
||||
reply.Val = proto.Int32(args.GetA() * args.GetB())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Arith) Divide(args *arith.ArithRequest, reply *arith.ArithResponse) error {
|
||||
if args.GetB() == 0 {
|
||||
return errors.New("divide by zero")
|
||||
}
|
||||
reply.Quo = proto.Int32(args.GetA() / args.GetB())
|
||||
reply.Rem = proto.Int32(args.GetA() % args.GetB())
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
arith.ListenAndServeArithService("tcp", ":1984", new(Arith))
|
||||
}
|
||||
|
||||
At this point, clients can see a service "Arith" with methods "ArithService.Multiply" and
|
||||
"ArithService.Divide". To invoke one, a client first dials the server:
|
||||
|
||||
stub, err := arith.DialArithService("tcp", "127.0.0.1:1984")
|
||||
if err != nil {
|
||||
log.Fatal(`arith.DialArithService("tcp", "127.0.0.1:1984"):`, err)
|
||||
}
|
||||
defer stub.Close()
|
||||
|
||||
Then it can make a remote call with stub:
|
||||
|
||||
var args ArithRequest
|
||||
|
||||
args.A = proto.Int32(7)
|
||||
args.B = proto.Int32(8)
|
||||
reply, err := stub.Multiply(&args, &reply)
|
||||
if err != nil {
|
||||
log.Fatal("arith error:", err)
|
||||
}
|
||||
fmt.Printf("Arith: %d*%d=%d", args.GetA(), args.GetB(), reply.GetVal())
|
||||
|
||||
More example:
|
||||
|
||||
go test github.com/chai2010/protorpc/internal/service.pb
|
||||
|
||||
Report bugs to <chaishushan@gmail.com>.
|
||||
|
||||
Thanks!
|
||||
*/
|
||||
package protorpc // import "github.com/chai2010/protorpc"
|
||||
90
core/protorpc/examples/message.pb/arith.pb.go
Normal file
90
core/protorpc/examples/message.pb/arith.pb.go
Normal file
@ -0,0 +1,90 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: arith.proto
|
||||
|
||||
/*
|
||||
Package message is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
arith.proto
|
||||
echo.proto
|
||||
|
||||
It has these top-level messages:
|
||||
ArithRequest
|
||||
ArithResponse
|
||||
EchoRequest
|
||||
EchoResponse
|
||||
*/
|
||||
package message
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type ArithRequest struct {
|
||||
A int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"`
|
||||
B int32 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ArithRequest) Reset() { *m = ArithRequest{} }
|
||||
func (m *ArithRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ArithRequest) ProtoMessage() {}
|
||||
func (*ArithRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *ArithRequest) GetA() int32 {
|
||||
if m != nil {
|
||||
return m.A
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ArithRequest) GetB() int32 {
|
||||
if m != nil {
|
||||
return m.B
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ArithResponse struct {
|
||||
C int32 `protobuf:"varint,1,opt,name=c" json:"c,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ArithResponse) Reset() { *m = ArithResponse{} }
|
||||
func (m *ArithResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ArithResponse) ProtoMessage() {}
|
||||
func (*ArithResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *ArithResponse) GetC() int32 {
|
||||
if m != nil {
|
||||
return m.C
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*ArithRequest)(nil), "message.ArithRequest")
|
||||
proto.RegisterType((*ArithResponse)(nil), "message.ArithResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("arith.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 104 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0x2c, 0xca, 0x2c,
|
||||
0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xcf, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f,
|
||||
0x55, 0xd2, 0xe2, 0xe2, 0x71, 0x04, 0x89, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0xf1,
|
||||
0x70, 0x31, 0x26, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0x31, 0x26, 0x82, 0x78, 0x49, 0x12,
|
||||
0x4c, 0x10, 0x5e, 0x92, 0x92, 0x2c, 0x17, 0x2f, 0x54, 0x6d, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0x2a,
|
||||
0x48, 0x3a, 0x19, 0xa6, 0x38, 0x39, 0x89, 0x0d, 0x6c, 0xb4, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff,
|
||||
0x61, 0x27, 0x57, 0x32, 0x69, 0x00, 0x00, 0x00,
|
||||
}
|
||||
16
core/protorpc/examples/message.pb/arith.proto
Normal file
16
core/protorpc/examples/message.pb/arith.proto
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package message;
|
||||
|
||||
message ArithRequest {
|
||||
int32 a = 1;
|
||||
int32 b = 2;
|
||||
}
|
||||
|
||||
message ArithResponse {
|
||||
int32 c = 1;
|
||||
}
|
||||
62
core/protorpc/examples/message.pb/echo.pb.go
Normal file
62
core/protorpc/examples/message.pb/echo.pb.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: echo.proto
|
||||
|
||||
package message
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type EchoRequest struct {
|
||||
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EchoRequest) Reset() { *m = EchoRequest{} }
|
||||
func (m *EchoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*EchoRequest) ProtoMessage() {}
|
||||
func (*EchoRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
|
||||
|
||||
func (m *EchoRequest) GetMsg() string {
|
||||
if m != nil {
|
||||
return m.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EchoResponse struct {
|
||||
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EchoResponse) Reset() { *m = EchoResponse{} }
|
||||
func (m *EchoResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*EchoResponse) ProtoMessage() {}
|
||||
func (*EchoResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
|
||||
|
||||
func (m *EchoResponse) GetMsg() string {
|
||||
if m != nil {
|
||||
return m.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*EchoRequest)(nil), "message.EchoRequest")
|
||||
proto.RegisterType((*EchoResponse)(nil), "message.EchoResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("echo.proto", fileDescriptor1) }
|
||||
|
||||
var fileDescriptor1 = []byte{
|
||||
// 95 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8,
|
||||
0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xcf, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 0x55,
|
||||
0x92, 0xe7, 0xe2, 0x76, 0x4d, 0xce, 0xc8, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12,
|
||||
0xe0, 0x62, 0xce, 0x2d, 0x4e, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x95, 0x14,
|
||||
0xb8, 0x78, 0x20, 0x0a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x31, 0x55, 0x24, 0xb1, 0x81, 0x8d,
|
||||
0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xcb, 0xea, 0xe4, 0xa6, 0x60, 0x00, 0x00, 0x00,
|
||||
}
|
||||
15
core/protorpc/examples/message.pb/echo.proto
Normal file
15
core/protorpc/examples/message.pb/echo.proto
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package message;
|
||||
|
||||
message EchoRequest {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
message EchoResponse {
|
||||
string msg = 1;
|
||||
}
|
||||
7
core/protorpc/examples/message.pb/proto.go
Normal file
7
core/protorpc/examples/message.pb/proto.go
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate protoc --go_out=. arith.proto echo.proto
|
||||
|
||||
package message
|
||||
14
core/protorpc/examples/proto3.pb/Makefile
Normal file
14
core/protorpc/examples/proto3.pb/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
PROTO_FILES=$(sort $(wildcard ./*.proto))
|
||||
|
||||
default: $(PROTO_FILES) Makefile
|
||||
go install github.com/golang/protobuf/protoc-gen-go
|
||||
go install github.com/chai2010/protorpc/protoc-gen-protorpc
|
||||
protoc --go_out=. ${PROTO_FILES}
|
||||
protoc --protorpc_out=. ${PROTO_FILES}
|
||||
go test
|
||||
|
||||
clean:
|
||||
8
core/protorpc/examples/proto3.pb/proto.go
Normal file
8
core/protorpc/examples/proto3.pb/proto.go
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate protoc --go_out=. proto3.proto
|
||||
//go:generate protoc --protorpc_out=. proto3.proto
|
||||
|
||||
package proto3_proto
|
||||
220
core/protorpc/examples/proto3.pb/proto3.pb.go
Normal file
220
core/protorpc/examples/proto3.pb/proto3.pb.go
Normal file
@ -0,0 +1,220 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: proto3.proto
|
||||
|
||||
/*
|
||||
Package proto3_proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
proto3.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Message
|
||||
Nested
|
||||
MessageWithMap
|
||||
*/
|
||||
package proto3_proto
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Message_Humour int32
|
||||
|
||||
const (
|
||||
Message_UNKNOWN Message_Humour = 0
|
||||
Message_PUNS Message_Humour = 1
|
||||
Message_SLAPSTICK Message_Humour = 2
|
||||
Message_BILL_BAILEY Message_Humour = 3
|
||||
)
|
||||
|
||||
var Message_Humour_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "PUNS",
|
||||
2: "SLAPSTICK",
|
||||
3: "BILL_BAILEY",
|
||||
}
|
||||
var Message_Humour_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"PUNS": 1,
|
||||
"SLAPSTICK": 2,
|
||||
"BILL_BAILEY": 3,
|
||||
}
|
||||
|
||||
func (x Message_Humour) String() string {
|
||||
return proto.EnumName(Message_Humour_name, int32(x))
|
||||
}
|
||||
func (Message_Humour) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
|
||||
|
||||
type Message struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
|
||||
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm" json:"height_in_cm,omitempty"`
|
||||
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
|
||||
ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount" json:"result_count,omitempty"`
|
||||
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman" json:"true_scotsman,omitempty"`
|
||||
Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"`
|
||||
Key []uint64 `protobuf:"varint,5,rep,packed,name=key" json:"key,omitempty"`
|
||||
Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
|
||||
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
}
|
||||
|
||||
func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Message) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Message) GetHilarity() Message_Humour {
|
||||
if m != nil {
|
||||
return m.Hilarity
|
||||
}
|
||||
return Message_UNKNOWN
|
||||
}
|
||||
|
||||
func (m *Message) GetHeightInCm() uint32 {
|
||||
if m != nil {
|
||||
return m.HeightInCm
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Message) GetData() []byte {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetResultCount() int64 {
|
||||
if m != nil {
|
||||
return m.ResultCount
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Message) GetTrueScotsman() bool {
|
||||
if m != nil {
|
||||
return m.TrueScotsman
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Message) GetScore() float32 {
|
||||
if m != nil {
|
||||
return m.Score
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Message) GetKey() []uint64 {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetNested() *Nested {
|
||||
if m != nil {
|
||||
return m.Nested
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetTerrain() map[string]*Nested {
|
||||
if m != nil {
|
||||
return m.Terrain
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Nested struct {
|
||||
Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Nested) Reset() { *m = Nested{} }
|
||||
func (m *Nested) String() string { return proto.CompactTextString(m) }
|
||||
func (*Nested) ProtoMessage() {}
|
||||
func (*Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Nested) GetBunny() string {
|
||||
if m != nil {
|
||||
return m.Bunny
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type MessageWithMap struct {
|
||||
ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
|
||||
func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
|
||||
func (*MessageWithMap) ProtoMessage() {}
|
||||
func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
|
||||
if m != nil {
|
||||
return m.ByteMapping
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Message)(nil), "proto3_proto.Message")
|
||||
proto.RegisterType((*Nested)(nil), "proto3_proto.Nested")
|
||||
proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap")
|
||||
proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("proto3.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 473 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0x5f, 0x8b, 0xd3, 0x40,
|
||||
0x14, 0xc5, 0x9d, 0xa6, 0xdb, 0x3f, 0x37, 0xe9, 0x1a, 0x86, 0x0a, 0x43, 0x11, 0x19, 0xeb, 0xcb,
|
||||
0x20, 0xda, 0x87, 0xea, 0xc3, 0x22, 0xa2, 0x6c, 0x4b, 0xc1, 0xb2, 0x6d, 0x2d, 0xd3, 0x5d, 0x16,
|
||||
0x9f, 0xc2, 0x34, 0x3b, 0xb4, 0xc1, 0x66, 0x52, 0x26, 0x93, 0x85, 0x7c, 0x1d, 0x3f, 0xa7, 0x0f,
|
||||
0x92, 0x4c, 0xaa, 0x51, 0xea, 0xd3, 0xdc, 0x7b, 0xe6, 0xdc, 0x99, 0x73, 0x7f, 0xe0, 0x1d, 0x75,
|
||||
0x62, 0x92, 0x77, 0xa3, 0xf2, 0xc0, 0x55, 0x17, 0x94, 0xc7, 0xf0, 0xa7, 0x03, 0xed, 0xa5, 0x4c,
|
||||
0x53, 0xb1, 0x93, 0x18, 0x43, 0x53, 0x89, 0x58, 0x12, 0x44, 0x11, 0xeb, 0xf2, 0xb2, 0xc6, 0x57,
|
||||
0xd0, 0xd9, 0x47, 0x07, 0xa1, 0x23, 0x93, 0x93, 0x06, 0x45, 0xec, 0x72, 0xfc, 0x7c, 0x54, 0x7f,
|
||||
0x60, 0x54, 0x0d, 0x8f, 0xbe, 0x64, 0x71, 0x92, 0x69, 0xfe, 0xdb, 0x8d, 0x29, 0x78, 0x7b, 0x19,
|
||||
0xed, 0xf6, 0x26, 0x88, 0x54, 0x10, 0xc6, 0xc4, 0xa1, 0x88, 0xf5, 0x38, 0x58, 0x6d, 0xae, 0xa6,
|
||||
0x71, 0xf1, 0xdf, 0x83, 0x30, 0x82, 0x34, 0x29, 0x62, 0x1e, 0x2f, 0x6b, 0xfc, 0x12, 0x3c, 0x2d,
|
||||
0xd3, 0xec, 0x60, 0x82, 0x30, 0xc9, 0x94, 0x21, 0x6d, 0x8a, 0x98, 0xc3, 0x5d, 0xab, 0x4d, 0x0b,
|
||||
0x09, 0xbf, 0x82, 0x9e, 0xd1, 0x99, 0x0c, 0xd2, 0x30, 0x31, 0x69, 0x2c, 0x14, 0xe9, 0x50, 0xc4,
|
||||
0x3a, 0xdc, 0x2b, 0xc4, 0x4d, 0xa5, 0xe1, 0x3e, 0x5c, 0xa4, 0x61, 0xa2, 0x25, 0xe9, 0x52, 0xc4,
|
||||
0x1a, 0xdc, 0x36, 0xd8, 0x07, 0xe7, 0xbb, 0xcc, 0xc9, 0x05, 0x75, 0x58, 0x93, 0x17, 0x25, 0x7e,
|
||||
0x03, 0x2d, 0x25, 0x53, 0x23, 0x1f, 0x48, 0x8b, 0x22, 0xe6, 0x8e, 0xfb, 0x7f, 0x6f, 0xb7, 0x2a,
|
||||
0xef, 0x78, 0xe5, 0xc1, 0x1f, 0xa1, 0x6d, 0xa4, 0xd6, 0x22, 0x52, 0x04, 0xa8, 0xc3, 0xdc, 0xf1,
|
||||
0xf0, 0x3c, 0x8c, 0x5b, 0x6b, 0x9a, 0x29, 0xa3, 0x73, 0x7e, 0x1a, 0x19, 0xac, 0xc1, 0xab, 0x5f,
|
||||
0x9c, 0xd2, 0x58, 0xdc, 0x65, 0x9a, 0xd7, 0x70, 0xf1, 0x28, 0x0e, 0x99, 0x2c, 0x51, 0xff, 0x2f,
|
||||
0x8c, 0xb5, 0x7c, 0x68, 0x5c, 0xa1, 0xe1, 0x67, 0x68, 0x59, 0xee, 0xd8, 0x85, 0xf6, 0xdd, 0xea,
|
||||
0x66, 0xf5, 0xf5, 0x7e, 0xe5, 0x3f, 0xc1, 0x1d, 0x68, 0xae, 0xef, 0x56, 0x1b, 0x1f, 0xe1, 0x1e,
|
||||
0x74, 0x37, 0x8b, 0xeb, 0xf5, 0xe6, 0x76, 0x3e, 0xbd, 0xf1, 0x1b, 0xf8, 0x29, 0xb8, 0x93, 0xf9,
|
||||
0x62, 0x11, 0x4c, 0xae, 0xe7, 0x8b, 0xd9, 0x37, 0xdf, 0x19, 0xbe, 0x80, 0x96, 0x7d, 0xb5, 0x00,
|
||||
0xb6, 0xcd, 0x94, 0x3a, 0xc5, 0xb1, 0xcd, 0xf0, 0x07, 0x82, 0xcb, 0x6a, 0xa9, 0xfb, 0xc8, 0xec,
|
||||
0x97, 0xe2, 0x88, 0xd7, 0xe0, 0x6d, 0x73, 0x23, 0x83, 0x58, 0x1c, 0x8f, 0x91, 0xda, 0x11, 0x54,
|
||||
0x82, 0x78, 0x7b, 0x16, 0x44, 0x35, 0x33, 0x9a, 0xe4, 0x46, 0x2e, 0xad, 0xdf, 0x32, 0x71, 0xb7,
|
||||
0x7f, 0x94, 0xc1, 0x27, 0xf0, 0xff, 0x35, 0xd4, 0xd9, 0x74, 0x2c, 0x9b, 0x7e, 0x9d, 0x8d, 0x57,
|
||||
0xa3, 0x30, 0x9e, 0x82, 0x3b, 0x0b, 0xf7, 0xc9, 0x46, 0xea, 0xc7, 0x28, 0x94, 0xf8, 0x3d, 0x34,
|
||||
0x8b, 0x16, 0x3f, 0x3b, 0x1b, 0x69, 0x70, 0x5e, 0xde, 0xb6, 0xac, 0xfa, 0x2b, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xc1, 0x87, 0xd6, 0x2d, 0x03, 0x00, 0x00,
|
||||
}
|
||||
171
core/protorpc/examples/proto3.pb/proto3.pb.protorpc.go
Normal file
171
core/protorpc/examples/proto3.pb/proto3.pb.protorpc.go
Normal file
@ -0,0 +1,171 @@
|
||||
// Code generated by protoc-gen-protorpc. DO NOT EDIT.
|
||||
//
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-protorpc
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-plugin-common
|
||||
//
|
||||
// source: proto3.proto
|
||||
|
||||
package proto3_proto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"time"
|
||||
|
||||
"github.com/chai2010/protorpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = fmt.Sprint
|
||||
_ = io.Reader(nil)
|
||||
_ = log.Print
|
||||
_ = net.Addr(nil)
|
||||
_ = rpc.Call{}
|
||||
_ = time.Second
|
||||
|
||||
_ = proto.String
|
||||
_ = protorpc.Dial
|
||||
)
|
||||
|
||||
type EchoService interface {
|
||||
Echo(in *Message, out *Message) error
|
||||
}
|
||||
|
||||
// AcceptEchoServiceClient accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func AcceptEchoServiceClient(lis net.Listener, x EchoService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterEchoService publish the given EchoService implementation on the server.
|
||||
func RegisterEchoService(srv *rpc.Server, x EchoService) error {
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewEchoServiceServer returns a new EchoService Server.
|
||||
func NewEchoServiceServer(x EchoService) *rpc.Server {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// ListenAndServeEchoService listen announces on the local network address laddr
|
||||
// and serves the given EchoService implementation.
|
||||
func ListenAndServeEchoService(network, addr string, x EchoService) error {
|
||||
lis, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}
|
||||
|
||||
// ServeEchoService serves the given EchoService implementation.
|
||||
func ServeEchoService(conn io.ReadWriteCloser, x EchoService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
|
||||
type EchoServiceClient struct {
|
||||
*rpc.Client
|
||||
}
|
||||
|
||||
// NewEchoServiceClient returns a EchoService stub to handle
|
||||
// requests to the set of EchoService at the other end of the connection.
|
||||
func NewEchoServiceClient(conn io.ReadWriteCloser) *EchoServiceClient {
|
||||
c := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn))
|
||||
return &EchoServiceClient{c}
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) Echo(in *Message) (out *Message, err error) {
|
||||
if in == nil {
|
||||
in = new(Message)
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new(Message)
|
||||
if err = c.Call("EchoService.Echo", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) AsyncEcho(in *Message, out *Message, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(Message)
|
||||
}
|
||||
return c.Go(
|
||||
"EchoService.Echo",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
// DialEchoService connects to an EchoService at the specified network address.
|
||||
func DialEchoService(network, addr string) (*EchoServiceClient, error) {
|
||||
c, err := protorpc.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EchoServiceClient{c}, nil
|
||||
}
|
||||
|
||||
// DialEchoServiceTimeout connects to an EchoService at the specified network address.
|
||||
func DialEchoServiceTimeout(network, addr string, timeout time.Duration) (*EchoServiceClient, error) {
|
||||
c, err := protorpc.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EchoServiceClient{c}, nil
|
||||
}
|
||||
41
core/protorpc/examples/proto3.pb/proto3.proto
Normal file
41
core/protorpc/examples/proto3.pb/proto3.proto
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2015 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package proto3_proto;
|
||||
|
||||
message Message {
|
||||
enum Humour {
|
||||
UNKNOWN = 0;
|
||||
PUNS = 1;
|
||||
SLAPSTICK = 2;
|
||||
BILL_BAILEY = 3;
|
||||
}
|
||||
|
||||
string name = 1;
|
||||
Humour hilarity = 2;
|
||||
uint32 height_in_cm = 3;
|
||||
bytes data = 4;
|
||||
int64 result_count = 7;
|
||||
bool true_scotsman = 8;
|
||||
float score = 9;
|
||||
|
||||
repeated uint64 key = 5;
|
||||
Nested nested = 6;
|
||||
|
||||
map<string, Nested> terrain = 10;
|
||||
}
|
||||
|
||||
message Nested {
|
||||
string bunny = 1;
|
||||
}
|
||||
|
||||
message MessageWithMap {
|
||||
map<bool, bytes> byte_mapping = 1;
|
||||
}
|
||||
|
||||
service EchoService {
|
||||
rpc Echo(Message) returns (Message);
|
||||
}
|
||||
72
core/protorpc/examples/proto3.pb/proto3_proto_test.go
Normal file
72
core/protorpc/examples/proto3.pb/proto3_proto_test.go
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright 2015 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto3_proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type tEchoService struct {
|
||||
private int
|
||||
}
|
||||
|
||||
func (p *tEchoService) Echo(in *Message, out *Message) error {
|
||||
var buf bytes.Buffer
|
||||
if err := gob.NewEncoder(&buf).Encode(in); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(out); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
go func() {
|
||||
if err := ListenAndServeEchoService("tcp", "127.0.0.1:3000", new(tEchoService)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
time.Sleep(time.Second * 3) // wait for start the server
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestEchoService(t *testing.T) {
|
||||
c, err := DialEchoService("tcp", "127.0.0.1:3000")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
in := Message{
|
||||
Name: "github.com/chai2010/protorpc",
|
||||
Hilarity: Message_PUNS,
|
||||
HeightInCm: 13,
|
||||
Data: []byte("bin data"),
|
||||
ResultCount: 2<<35 + 1,
|
||||
TrueScotsman: true,
|
||||
Score: 3.14,
|
||||
Key: []uint64{1, 1001},
|
||||
Nested: &Nested{Bunny: "{{Bunny}}"},
|
||||
Terrain: map[string]*Nested{
|
||||
"A": &Nested{Bunny: "{{A}}"},
|
||||
"B": &Nested{Bunny: "{{B}}"},
|
||||
},
|
||||
}
|
||||
|
||||
out, err := c.Echo(&in)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(&in, out) {
|
||||
t.Fatalf("not euqal, got = %v\n", &out)
|
||||
}
|
||||
}
|
||||
14
core/protorpc/examples/service.pb/Makefile
Normal file
14
core/protorpc/examples/service.pb/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
PROTO_FILES=$(sort $(wildcard ./*.proto))
|
||||
|
||||
default: $(PROTO_FILES) Makefile
|
||||
go install github.com/golang/protobuf/protoc-gen-go
|
||||
go install github.com/chai2010/protorpc/protoc-gen-protorpc
|
||||
protoc --go_out=. ${PROTO_FILES}
|
||||
ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX= protoc --protorpc_out=. ${PROTO_FILES}
|
||||
go test
|
||||
|
||||
clean:
|
||||
193
core/protorpc/examples/service.pb/all_test.go
Normal file
193
core/protorpc/examples/service.pb/all_test.go
Normal file
@ -0,0 +1,193 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"testing"
|
||||
|
||||
"github.com/chai2010/protorpc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
err := listenAndServeArithAndEchoService("tcp", "127.0.0.1:1984")
|
||||
if err != nil {
|
||||
log.Fatalf("listenAndServeArithAndEchoService: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
conn, err := net.Dial("tcp", "127.0.0.1:1984")
|
||||
if err != nil {
|
||||
t.Fatalf(`net.Dial("tcp", "127.0.0.1:1984"): %v`, err)
|
||||
}
|
||||
client := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn))
|
||||
defer client.Close()
|
||||
|
||||
testArithClient(t, client)
|
||||
testEchoClient(t, client)
|
||||
|
||||
arithStub := &ArithServiceClient{client}
|
||||
echoStub := &EchoServiceClient{client}
|
||||
|
||||
testArithStub(t, arithStub)
|
||||
testEchoStub(t, echoStub)
|
||||
}
|
||||
|
||||
func listenAndServeArithAndEchoService(network, addr string) error {
|
||||
clients, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv := rpc.NewServer()
|
||||
if err := RegisterArithService(srv, new(Arith)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := RegisterEchoService(srv, new(Echo)); err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
conn, err := clients.Accept()
|
||||
if err != nil {
|
||||
log.Printf("clients.Accept(): %v\n", err)
|
||||
continue
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func testArithClient(t *testing.T, client *rpc.Client) {
|
||||
var args ArithRequest
|
||||
var reply ArithResponse
|
||||
var err error
|
||||
|
||||
// Add
|
||||
args.A = 1
|
||||
args.B = 2
|
||||
if err = client.Call("ArithService.Add", &args, &reply); err != nil {
|
||||
t.Fatalf(`arith.Add: %v`, err)
|
||||
}
|
||||
if reply.C != 3 {
|
||||
t.Fatalf(`arith.Add: expected = %d, got = %d`, 3, reply.C)
|
||||
}
|
||||
|
||||
// Mul
|
||||
args.A = 2
|
||||
args.B = 3
|
||||
if err = client.Call("ArithService.Mul", &args, &reply); err != nil {
|
||||
t.Fatalf(`arith.Mul: %v`, err)
|
||||
}
|
||||
if reply.C != 6 {
|
||||
t.Fatalf(`arith.Mul: expected = %d, got = %d`, 6, reply.C)
|
||||
}
|
||||
|
||||
// Div
|
||||
args.A = 13
|
||||
args.B = 5
|
||||
if err = client.Call("ArithService.Div", &args, &reply); err != nil {
|
||||
t.Fatalf(`arith.Div: %v`, err)
|
||||
}
|
||||
if reply.C != 2 {
|
||||
t.Fatalf(`arith.Div: expected = %d, got = %d`, 2, reply.C)
|
||||
}
|
||||
|
||||
// Div zero
|
||||
args.A = 1
|
||||
args.B = 0
|
||||
if err = client.Call("ArithService.Div", &args, &reply); err.Error() != "divide by zero" {
|
||||
t.Fatalf(`arith.Div: expected = "%s", got = "%s"`, "divide by zero", err.Error())
|
||||
}
|
||||
|
||||
// Error
|
||||
args.A = 1
|
||||
args.B = 2
|
||||
if err = client.Call("ArithService.Error", &args, &reply); err.Error() != "ArithError" {
|
||||
t.Fatalf(`arith.Error: expected = "%s", got = "%s"`, "ArithError", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func testEchoClient(t *testing.T, client *rpc.Client) {
|
||||
var args EchoRequest
|
||||
var reply EchoResponse
|
||||
var err error
|
||||
|
||||
// EchoService.Echo
|
||||
args.Msg = "Hello, Protobuf-RPC"
|
||||
if err = client.Call("EchoService.Echo", &args, &reply); err != nil {
|
||||
t.Fatalf(`echo.Echo: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg {
|
||||
t.Fatalf(`echo.Echo: expected = "%s", got = "%s"`, args.Msg, reply.Msg)
|
||||
}
|
||||
}
|
||||
|
||||
func testArithStub(t *testing.T, stub *ArithServiceClient) {
|
||||
var args ArithRequest
|
||||
var reply *ArithResponse
|
||||
var err error
|
||||
|
||||
// Add
|
||||
args.A = 1
|
||||
args.B = 2
|
||||
if reply, err = stub.Add(&args); err != nil {
|
||||
t.Fatalf(`stub.Add: %v`, err)
|
||||
}
|
||||
if reply.C != 3 {
|
||||
t.Fatalf(`stub.Add: expected = %d, got = %d`, 3, reply.C)
|
||||
}
|
||||
|
||||
// Mul
|
||||
args.A = 2
|
||||
args.B = 3
|
||||
if reply, err = stub.Mul(&args); err != nil {
|
||||
t.Fatalf(`stub.Mul: %v`, err)
|
||||
}
|
||||
if reply.C != 6 {
|
||||
t.Fatalf(`stub.Mul: expected = %d, got = %d`, 6, reply.C)
|
||||
}
|
||||
|
||||
// Div
|
||||
args.A = 13
|
||||
args.B = 5
|
||||
if reply, err = stub.Div(&args); err != nil {
|
||||
t.Fatalf(`stub.Div: %v`, err)
|
||||
}
|
||||
if reply.C != 2 {
|
||||
t.Fatalf(`stub.Div: expected = %d, got = %d`, 2, reply.C)
|
||||
}
|
||||
|
||||
// Div zero
|
||||
args.A = 1
|
||||
args.B = 0
|
||||
if reply, err = stub.Div(&args); err.Error() != "divide by zero" {
|
||||
t.Fatalf(`stub.Div: expected = "%s", got = "%s"`, "divide by zero", err.Error())
|
||||
}
|
||||
|
||||
// Error
|
||||
args.A = 1
|
||||
args.B = 2
|
||||
if reply, err = stub.Error(&args); err.Error() != "ArithError" {
|
||||
t.Fatalf(`stub.Error: expected = "%s", got = "%s"`, "ArithError", err.Error())
|
||||
}
|
||||
}
|
||||
func testEchoStub(t *testing.T, stub *EchoServiceClient) {
|
||||
var args EchoRequest
|
||||
var reply *EchoResponse
|
||||
var err error
|
||||
|
||||
// EchoService.Echo
|
||||
args.Msg = "Hello, Protobuf-RPC"
|
||||
if reply, err = stub.Echo(&args); err != nil {
|
||||
t.Fatalf(`stub.Echo: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg {
|
||||
t.Fatalf(`stub.Echo: expected = "%s", got = "%s"`, args.Msg, reply.Msg)
|
||||
}
|
||||
}
|
||||
33
core/protorpc/examples/service.pb/arith.go
Normal file
33
core/protorpc/examples/service.pb/arith.go
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Arith int
|
||||
|
||||
func (t *Arith) Add(args *ArithRequest, reply *ArithResponse) error {
|
||||
reply.C = args.A + args.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Arith) Mul(args *ArithRequest, reply *ArithResponse) error {
|
||||
reply.C = args.A * args.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Arith) Div(args *ArithRequest, reply *ArithResponse) error {
|
||||
if args.B == 0 {
|
||||
return errors.New("divide by zero")
|
||||
}
|
||||
reply.C = args.A / args.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Arith) Error(args *ArithRequest, reply *ArithResponse) error {
|
||||
return errors.New("ArithError")
|
||||
}
|
||||
93
core/protorpc/examples/service.pb/arith.pb.go
Normal file
93
core/protorpc/examples/service.pb/arith.pb.go
Normal file
@ -0,0 +1,93 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: arith.proto
|
||||
|
||||
/*
|
||||
Package service is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
arith.proto
|
||||
echo.proto
|
||||
|
||||
It has these top-level messages:
|
||||
ArithRequest
|
||||
ArithResponse
|
||||
EchoRequest
|
||||
EchoResponse
|
||||
*/
|
||||
package service
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type ArithRequest struct {
|
||||
A int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"`
|
||||
B int32 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ArithRequest) Reset() { *m = ArithRequest{} }
|
||||
func (m *ArithRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ArithRequest) ProtoMessage() {}
|
||||
func (*ArithRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *ArithRequest) GetA() int32 {
|
||||
if m != nil {
|
||||
return m.A
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ArithRequest) GetB() int32 {
|
||||
if m != nil {
|
||||
return m.B
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ArithResponse struct {
|
||||
C int32 `protobuf:"varint,1,opt,name=c" json:"c,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ArithResponse) Reset() { *m = ArithResponse{} }
|
||||
func (m *ArithResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ArithResponse) ProtoMessage() {}
|
||||
func (*ArithResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *ArithResponse) GetC() int32 {
|
||||
if m != nil {
|
||||
return m.C
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*ArithRequest)(nil), "service.ArithRequest")
|
||||
proto.RegisterType((*ArithResponse)(nil), "service.ArithResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("arith.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 159 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0x2c, 0xca, 0x2c,
|
||||
0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e,
|
||||
0x55, 0xd2, 0xe2, 0xe2, 0x71, 0x04, 0x89, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0xf1,
|
||||
0x70, 0x31, 0x26, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0x31, 0x26, 0x82, 0x78, 0x49, 0x12,
|
||||
0x4c, 0x10, 0x5e, 0x92, 0x92, 0x2c, 0x17, 0x2f, 0x54, 0x6d, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0x2a,
|
||||
0x48, 0x3a, 0x19, 0xa6, 0x38, 0xd9, 0xe8, 0x05, 0x23, 0xd4, 0xac, 0x60, 0x88, 0xd9, 0x42, 0x26,
|
||||
0x5c, 0xcc, 0x89, 0x29, 0x29, 0x42, 0xa2, 0x7a, 0x50, 0xcb, 0xf4, 0x90, 0x6d, 0x92, 0x12, 0x43,
|
||||
0x17, 0x86, 0x1a, 0x6a, 0xc2, 0xc5, 0x9c, 0x5b, 0x9a, 0x43, 0x86, 0xae, 0x94, 0xcc, 0x32, 0x52,
|
||||
0x75, 0x99, 0x71, 0xb1, 0xa6, 0x16, 0x15, 0xe5, 0x17, 0x91, 0xa8, 0x2f, 0x89, 0x0d, 0x1c, 0x8a,
|
||||
0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x62, 0xfd, 0xbd, 0x54, 0x01, 0x00, 0x00,
|
||||
}
|
||||
291
core/protorpc/examples/service.pb/arith.pb.protorpc.go
Normal file
291
core/protorpc/examples/service.pb/arith.pb.protorpc.go
Normal file
@ -0,0 +1,291 @@
|
||||
// Code generated by protoc-gen-protorpc. DO NOT EDIT.
|
||||
//
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-plugin
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-protorpc
|
||||
//
|
||||
// source: arith.proto
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"time"
|
||||
|
||||
"github.com/chai2010/protorpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = fmt.Sprint
|
||||
_ = io.Reader(nil)
|
||||
_ = log.Print
|
||||
_ = net.Addr(nil)
|
||||
_ = rpc.Call{}
|
||||
_ = time.Second
|
||||
|
||||
_ = proto.String
|
||||
_ = protorpc.Dial
|
||||
)
|
||||
|
||||
type ArithService interface {
|
||||
Add(in *ArithRequest, out *ArithResponse) error
|
||||
Mul(in *ArithRequest, out *ArithResponse) error
|
||||
Div(in *ArithRequest, out *ArithResponse) error
|
||||
Error(in *ArithRequest, out *ArithResponse) error
|
||||
}
|
||||
|
||||
// AcceptArithServiceClient accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func AcceptArithServiceClient(lis net.Listener, x ArithService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("ArithService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterArithService publish the given ArithService implementation on the server.
|
||||
func RegisterArithService(srv *rpc.Server, x ArithService) error {
|
||||
if err := srv.RegisterName("ArithService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewArithServiceServer returns a new ArithService Server.
|
||||
func NewArithServiceServer(x ArithService) *rpc.Server {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("ArithService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// ListenAndServeArithService listen announces on the local network address laddr
|
||||
// and serves the given ArithService implementation.
|
||||
func ListenAndServeArithService(network, addr string, x ArithService) error {
|
||||
lis, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("ArithService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}
|
||||
|
||||
// ServeArithService serves the given ArithService implementation.
|
||||
func ServeArithService(conn io.ReadWriteCloser, x ArithService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("ArithService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
|
||||
type ArithServiceClient struct {
|
||||
*rpc.Client
|
||||
}
|
||||
|
||||
// NewArithServiceClient returns a ArithService stub to handle
|
||||
// requests to the set of ArithService at the other end of the connection.
|
||||
func NewArithServiceClient(conn io.ReadWriteCloser) *ArithServiceClient {
|
||||
c := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn))
|
||||
return &ArithServiceClient{c}
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) Add(in *ArithRequest) (out *ArithResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new(ArithResponse)
|
||||
if err = c.Call("ArithService.Add", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) AsyncAdd(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"ArithService.Add",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) Mul(in *ArithRequest) (out *ArithResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new(ArithResponse)
|
||||
if err = c.Call("ArithService.Mul", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) AsyncMul(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"ArithService.Mul",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) Div(in *ArithRequest) (out *ArithResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new(ArithResponse)
|
||||
if err = c.Call("ArithService.Div", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) AsyncDiv(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"ArithService.Div",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) Error(in *ArithRequest) (out *ArithResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new(ArithResponse)
|
||||
if err = c.Call("ArithService.Error", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) AsyncError(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"ArithService.Error",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
// DialArithService connects to an ArithService at the specified network address.
|
||||
func DialArithService(network, addr string) (*ArithServiceClient, error) {
|
||||
c, err := protorpc.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ArithServiceClient{c}, nil
|
||||
}
|
||||
|
||||
// DialArithServiceTimeout connects to an ArithService at the specified network address.
|
||||
func DialArithServiceTimeout(network, addr string, timeout time.Duration) (*ArithServiceClient, error) {
|
||||
c, err := protorpc.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ArithServiceClient{c}, nil
|
||||
}
|
||||
23
core/protorpc/examples/service.pb/arith.proto
Normal file
23
core/protorpc/examples/service.pb/arith.proto
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package service;
|
||||
|
||||
message ArithRequest {
|
||||
int32 a = 1;
|
||||
int32 b = 2;
|
||||
}
|
||||
|
||||
message ArithResponse {
|
||||
int32 c = 1;
|
||||
}
|
||||
|
||||
service ArithService {
|
||||
rpc add (ArithRequest) returns (ArithResponse);
|
||||
rpc mul (ArithRequest) returns (ArithResponse);
|
||||
rpc div (ArithRequest) returns (ArithResponse);
|
||||
rpc error (ArithRequest) returns (ArithResponse);
|
||||
}
|
||||
34
core/protorpc/examples/service.pb/arith_test.go
Normal file
34
core/protorpc/examples/service.pb/arith_test.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
arithHost = "127.0.0.1"
|
||||
arithPort = 2010
|
||||
|
||||
onceArith sync.Once
|
||||
)
|
||||
|
||||
func setupArithServer() {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
defer wg.Wait()
|
||||
|
||||
go func() {
|
||||
wg.Done()
|
||||
|
||||
addr := fmt.Sprintf("127.0.0.1:%d", arithPort)
|
||||
err := ListenAndServeArithService("tcp", addr, new(Arith))
|
||||
if err != nil {
|
||||
log.Fatalf("ListenAndServeArithService: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
17
core/protorpc/examples/service.pb/echo.go
Normal file
17
core/protorpc/examples/service.pb/echo.go
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package service
|
||||
|
||||
type Echo int
|
||||
|
||||
func (t *Echo) Echo(args *EchoRequest, reply *EchoResponse) error {
|
||||
reply.Msg = args.Msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Echo) EchoTwice(args *EchoRequest, reply *EchoResponse) error {
|
||||
reply.Msg = args.Msg + args.Msg
|
||||
return nil
|
||||
}
|
||||
65
core/protorpc/examples/service.pb/echo.pb.go
Normal file
65
core/protorpc/examples/service.pb/echo.pb.go
Normal file
@ -0,0 +1,65 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: echo.proto
|
||||
|
||||
package service
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type EchoRequest struct {
|
||||
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EchoRequest) Reset() { *m = EchoRequest{} }
|
||||
func (m *EchoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*EchoRequest) ProtoMessage() {}
|
||||
func (*EchoRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
|
||||
|
||||
func (m *EchoRequest) GetMsg() string {
|
||||
if m != nil {
|
||||
return m.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EchoResponse struct {
|
||||
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EchoResponse) Reset() { *m = EchoResponse{} }
|
||||
func (m *EchoResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*EchoResponse) ProtoMessage() {}
|
||||
func (*EchoResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
|
||||
|
||||
func (m *EchoResponse) GetMsg() string {
|
||||
if m != nil {
|
||||
return m.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*EchoRequest)(nil), "service.EchoRequest")
|
||||
proto.RegisterType((*EchoResponse)(nil), "service.EchoResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("echo.proto", fileDescriptor1) }
|
||||
|
||||
var fileDescriptor1 = []byte{
|
||||
// 134 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8,
|
||||
0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x55,
|
||||
0x92, 0xe7, 0xe2, 0x76, 0x4d, 0xce, 0xc8, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12,
|
||||
0xe0, 0x62, 0xce, 0x2d, 0x4e, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x95, 0x14,
|
||||
0xb8, 0x78, 0x20, 0x0a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x31, 0x55, 0x18, 0xd5, 0x40, 0x8c,
|
||||
0x08, 0x86, 0x98, 0x28, 0x64, 0xcc, 0xc5, 0x02, 0xe2, 0x0a, 0x89, 0xe8, 0x41, 0xed, 0xd0, 0x43,
|
||||
0xb2, 0x40, 0x4a, 0x14, 0x4d, 0x14, 0x6a, 0xaa, 0x05, 0x17, 0x27, 0x88, 0x1f, 0x52, 0x0e, 0x32,
|
||||
0x81, 0x14, 0x9d, 0x49, 0x6c, 0x60, 0x0f, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc1,
|
||||
0xd4, 0xbd, 0xde, 0x00, 0x00, 0x00,
|
||||
}
|
||||
211
core/protorpc/examples/service.pb/echo.pb.protorpc.go
Normal file
211
core/protorpc/examples/service.pb/echo.pb.protorpc.go
Normal file
@ -0,0 +1,211 @@
|
||||
// Code generated by protoc-gen-protorpc. DO NOT EDIT.
|
||||
//
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-plugin
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-protorpc
|
||||
//
|
||||
// source: echo.proto
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"time"
|
||||
|
||||
"github.com/chai2010/protorpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = fmt.Sprint
|
||||
_ = io.Reader(nil)
|
||||
_ = log.Print
|
||||
_ = net.Addr(nil)
|
||||
_ = rpc.Call{}
|
||||
_ = time.Second
|
||||
|
||||
_ = proto.String
|
||||
_ = protorpc.Dial
|
||||
)
|
||||
|
||||
type EchoService interface {
|
||||
Echo(in *EchoRequest, out *EchoResponse) error
|
||||
EchoTwice(in *EchoRequest, out *EchoResponse) error
|
||||
}
|
||||
|
||||
// AcceptEchoServiceClient accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func AcceptEchoServiceClient(lis net.Listener, x EchoService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterEchoService publish the given EchoService implementation on the server.
|
||||
func RegisterEchoService(srv *rpc.Server, x EchoService) error {
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewEchoServiceServer returns a new EchoService Server.
|
||||
func NewEchoServiceServer(x EchoService) *rpc.Server {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// ListenAndServeEchoService listen announces on the local network address laddr
|
||||
// and serves the given EchoService implementation.
|
||||
func ListenAndServeEchoService(network, addr string, x EchoService) error {
|
||||
lis, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}
|
||||
|
||||
// ServeEchoService serves the given EchoService implementation.
|
||||
func ServeEchoService(conn io.ReadWriteCloser, x EchoService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
|
||||
type EchoServiceClient struct {
|
||||
*rpc.Client
|
||||
}
|
||||
|
||||
// NewEchoServiceClient returns a EchoService stub to handle
|
||||
// requests to the set of EchoService at the other end of the connection.
|
||||
func NewEchoServiceClient(conn io.ReadWriteCloser) *EchoServiceClient {
|
||||
c := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn))
|
||||
return &EchoServiceClient{c}
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) Echo(in *EchoRequest) (out *EchoResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(EchoRequest)
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new(EchoResponse)
|
||||
if err = c.Call("EchoService.Echo", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) AsyncEcho(in *EchoRequest, out *EchoResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(EchoRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"EchoService.Echo",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) EchoTwice(in *EchoRequest) (out *EchoResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(EchoRequest)
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new(EchoResponse)
|
||||
if err = c.Call("EchoService.EchoTwice", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) AsyncEchoTwice(in *EchoRequest, out *EchoResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(EchoRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"EchoService.EchoTwice",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
// DialEchoService connects to an EchoService at the specified network address.
|
||||
func DialEchoService(network, addr string) (*EchoServiceClient, error) {
|
||||
c, err := protorpc.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EchoServiceClient{c}, nil
|
||||
}
|
||||
|
||||
// DialEchoServiceTimeout connects to an EchoService at the specified network address.
|
||||
func DialEchoServiceTimeout(network, addr string, timeout time.Duration) (*EchoServiceClient, error) {
|
||||
c, err := protorpc.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EchoServiceClient{c}, nil
|
||||
}
|
||||
20
core/protorpc/examples/service.pb/echo.proto
Normal file
20
core/protorpc/examples/service.pb/echo.proto
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package service;
|
||||
|
||||
message EchoRequest {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
message EchoResponse {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
service EchoService {
|
||||
rpc Echo (EchoRequest) returns (EchoResponse);
|
||||
rpc EchoTwice (EchoRequest) returns (EchoResponse);
|
||||
}
|
||||
698
core/protorpc/examples/service.pb/echo_test.go
Normal file
698
core/protorpc/examples/service.pb/echo_test.go
Normal file
@ -0,0 +1,698 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/rpc"
|
||||
"sync"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var (
|
||||
echoHost = "127.0.0.1"
|
||||
echoPort = 2015
|
||||
|
||||
echoRequest = "Hello, new gopher!"
|
||||
echoResponse = echoRequest + echoRequest
|
||||
echoMassiveRequest = makeMassive("Hello, 世界.")
|
||||
echoMassiveResponse = echoMassiveRequest + echoMassiveRequest
|
||||
|
||||
onceEcho sync.Once
|
||||
)
|
||||
|
||||
func makeMassive(args string) string {
|
||||
runeLen := utf8.RuneCountInString(args)
|
||||
runeBuf := make([]rune, runeLen*1024*100)
|
||||
for i := 0; i < 1024*100; i++ {
|
||||
offset := i * runeLen
|
||||
j := 0
|
||||
for _, r := range args {
|
||||
runeBuf[offset+j] = r
|
||||
j++
|
||||
}
|
||||
}
|
||||
return string(runeBuf)
|
||||
}
|
||||
|
||||
func setupEchoServer() {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
defer wg.Wait()
|
||||
|
||||
go func() {
|
||||
wg.Done()
|
||||
|
||||
addr := fmt.Sprintf("127.0.0.1:%d", echoPort)
|
||||
err := ListenAndServeEchoService("tcp", addr, new(Echo))
|
||||
if err != nil {
|
||||
log.Fatalf("ListenAndServeEchoService: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func TestEchoService(t *testing.T) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
c, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
t.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
testEchoService(t, c.Client)
|
||||
}
|
||||
|
||||
func testEchoService(t *testing.T, client *rpc.Client) {
|
||||
var args EchoRequest
|
||||
var reply EchoResponse
|
||||
var err error
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = echoRequest
|
||||
err = client.Call("EchoService.EchoTwice", &args, &reply)
|
||||
if err != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != echoResponse {
|
||||
t.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
echoResponse, reply.Msg,
|
||||
)
|
||||
}
|
||||
|
||||
// EchoService.EchoTwice (Massive)
|
||||
args.Msg = echoMassiveRequest
|
||||
err = client.Call("EchoService.EchoTwice", &args, &reply)
|
||||
if err != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != echoMassiveResponse {
|
||||
got := reply.Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(reply.Msg), got,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientSyncEcho(t *testing.T) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
echoClient, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
t.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer echoClient.Close()
|
||||
|
||||
var args EchoRequest
|
||||
var reply *EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = "abc"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
t.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args.Msg+args.Msg, reply.Msg,
|
||||
)
|
||||
}
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = "你好, 世界"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
t.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args.Msg+args.Msg, reply.Msg,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientSyncMassive(t *testing.T) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
echoClient, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
t.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer echoClient.Close()
|
||||
|
||||
var args EchoRequest
|
||||
var reply *EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = echoMassiveRequest + "abc"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
got := reply.Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(reply.Msg), got,
|
||||
)
|
||||
}
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = echoMassiveRequest + "你好, 世界"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
got := reply.Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(reply.Msg), got,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientAsyncEcho(t *testing.T) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
client, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
t.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
var args EchoRequest
|
||||
var reply EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = echoRequest
|
||||
call := client.Go("EchoService.EchoTwice", &args, &reply, nil)
|
||||
|
||||
call = <-call.Done
|
||||
if call.Error != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, call.Error)
|
||||
}
|
||||
if call.Reply.(*EchoResponse).Msg != echoResponse {
|
||||
t.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
echoResponse, call.Reply.(*EchoResponse).Msg,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientAsyncEchoBatches(t *testing.T) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
client, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
t.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
var args1 EchoRequest
|
||||
var reply1 EchoResponse
|
||||
var args2 EchoRequest
|
||||
var reply2 EchoResponse
|
||||
var args3 EchoRequest
|
||||
var reply3 EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args1.Msg = "abc"
|
||||
call1 := client.Go("EchoService.EchoTwice", &args1, &reply1, nil)
|
||||
args2.Msg = "你好, 世界"
|
||||
call2 := client.Go("EchoService.EchoTwice", &args2, &reply2, nil)
|
||||
args3.Msg = "Hello, 世界"
|
||||
call3 := client.Go("EchoService.EchoTwice", &args3, &reply3, nil)
|
||||
|
||||
call1 = <-call1.Done
|
||||
call2 = <-call2.Done
|
||||
call3 = <-call3.Done
|
||||
|
||||
// call1
|
||||
if call1.Error != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, call1.Error)
|
||||
}
|
||||
if call1.Reply.(*EchoResponse).Msg != args1.Msg+args1.Msg {
|
||||
t.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args1.Msg+args1.Msg,
|
||||
call1.Reply.(*EchoResponse).Msg,
|
||||
)
|
||||
}
|
||||
|
||||
// call2
|
||||
if call2.Error != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, call2.Error)
|
||||
}
|
||||
if call2.Reply.(*EchoResponse).Msg != args2.Msg+args2.Msg {
|
||||
t.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args2.Msg+args2.Msg,
|
||||
call2.Reply.(*EchoResponse).Msg,
|
||||
)
|
||||
}
|
||||
|
||||
// call3
|
||||
if call3.Error != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, call3.Error)
|
||||
}
|
||||
if call3.Reply.(*EchoResponse).Msg != args3.Msg+args3.Msg {
|
||||
t.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args3.Msg+args3.Msg,
|
||||
call3.Reply.(*EchoResponse).Msg,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientAsyncMassive(t *testing.T) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
client, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
t.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
var args EchoRequest
|
||||
var reply EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = echoMassiveRequest
|
||||
call := client.Go("EchoService.EchoTwice", &args, &reply, nil)
|
||||
|
||||
call = <-call.Done
|
||||
if call.Error != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, call.Error)
|
||||
}
|
||||
if call.Reply.(*EchoResponse).Msg != echoMassiveResponse {
|
||||
got := call.Reply.(*EchoResponse).Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(call.Reply.(*EchoResponse).Msg), got,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientAsyncMassiveBatches(t *testing.T) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
client, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
t.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
var args1 EchoRequest
|
||||
var reply1 EchoResponse
|
||||
var args2 EchoRequest
|
||||
var reply2 EchoResponse
|
||||
var args3 EchoRequest
|
||||
var reply3 EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args1.Msg = echoMassiveRequest + "abc"
|
||||
call1 := client.Go("EchoService.EchoTwice", &args1, &reply1, nil)
|
||||
args2.Msg = echoMassiveRequest + "你好, 世界"
|
||||
call2 := client.Go("EchoService.EchoTwice", &args2, &reply2, nil)
|
||||
args3.Msg = echoMassiveRequest + "Hello, 世界"
|
||||
call3 := client.Go("EchoService.EchoTwice", &args3, &reply3, nil)
|
||||
|
||||
call1 = <-call1.Done
|
||||
call2 = <-call2.Done
|
||||
call3 = <-call3.Done
|
||||
|
||||
// call1
|
||||
if call1.Error != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, call1.Error)
|
||||
}
|
||||
if call1.Reply.(*EchoResponse).Msg != args1.Msg+args1.Msg {
|
||||
got := call1.Reply.(*EchoResponse).Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(call1.Reply.(*EchoResponse).Msg), got,
|
||||
)
|
||||
}
|
||||
|
||||
// call2
|
||||
if call2.Error != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, call2.Error)
|
||||
}
|
||||
if call2.Reply.(*EchoResponse).Msg != args2.Msg+args2.Msg {
|
||||
got := call2.Reply.(*EchoResponse).Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(call2.Reply.(*EchoResponse).Msg), got,
|
||||
)
|
||||
}
|
||||
|
||||
// call3
|
||||
if call3.Error != nil {
|
||||
t.Fatalf(`EchoService.EchoTwice: %v`, call3.Error)
|
||||
}
|
||||
if call3.Reply.(*EchoResponse).Msg != args3.Msg+args3.Msg {
|
||||
got := call3.Reply.(*EchoResponse).Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
t.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(call3.Reply.(*EchoResponse).Msg), got,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSyncEcho(b *testing.B) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
echoClient, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
b.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer echoClient.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var args EchoRequest
|
||||
var reply *EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = "abc"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
b.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args.Msg+args.Msg, reply.Msg,
|
||||
)
|
||||
}
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = "你好, 世界"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
b.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args.Msg+args.Msg, reply.Msg,
|
||||
)
|
||||
}
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = "Hello, 世界"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
b.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args.Msg+args.Msg, reply.Msg,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSyncMassive(b *testing.B) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
echoClient, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
b.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer echoClient.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var args EchoRequest
|
||||
var reply *EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = echoMassiveRequest + "abc"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
got := reply.Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(reply.Msg), got,
|
||||
)
|
||||
}
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = echoMassiveRequest + "你好, 世界"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
got := reply.Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(reply.Msg), got,
|
||||
)
|
||||
}
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args.Msg = echoMassiveRequest + "Hello, 世界"
|
||||
reply, err = echoClient.EchoTwice(&args)
|
||||
if err != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg+args.Msg {
|
||||
got := reply.Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(reply.Msg), got,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAsyncEcho(b *testing.B) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
client, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
b.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var args1 EchoRequest
|
||||
var reply1 EchoResponse
|
||||
var args2 EchoRequest
|
||||
var reply2 EchoResponse
|
||||
var args3 EchoRequest
|
||||
var reply3 EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args1.Msg = "abc"
|
||||
call1 := client.Go("EchoService.EchoTwice", &args1, &reply1, nil)
|
||||
args2.Msg = "你好, 世界"
|
||||
call2 := client.Go("EchoService.EchoTwice", &args2, &reply2, nil)
|
||||
args3.Msg = "Hello, 世界"
|
||||
call3 := client.Go("EchoService.EchoTwice", &args3, &reply3, nil)
|
||||
|
||||
call1 = <-call1.Done
|
||||
call2 = <-call2.Done
|
||||
call3 = <-call3.Done
|
||||
|
||||
// call1
|
||||
if call1.Error != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, call1.Error)
|
||||
}
|
||||
if call1.Reply.(*EchoResponse).Msg != args1.Msg+args1.Msg {
|
||||
b.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args1.Msg+args1.Msg,
|
||||
call1.Reply.(*EchoResponse).Msg,
|
||||
)
|
||||
}
|
||||
|
||||
// call2
|
||||
if call2.Error != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, call2.Error)
|
||||
}
|
||||
if call2.Reply.(*EchoResponse).Msg != args2.Msg+args2.Msg {
|
||||
b.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args2.Msg+args2.Msg,
|
||||
call2.Reply.(*EchoResponse).Msg,
|
||||
)
|
||||
}
|
||||
|
||||
// call3
|
||||
if call3.Error != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, call3.Error)
|
||||
}
|
||||
if call3.Reply.(*EchoResponse).Msg != args3.Msg+args3.Msg {
|
||||
b.Fatalf(
|
||||
`EchoService.EchoTwice: expected = "%s", got = "%s"`,
|
||||
args3.Msg+args3.Msg,
|
||||
call3.Reply.(*EchoResponse).Msg,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAsyncMassive(b *testing.B) {
|
||||
onceEcho.Do(setupEchoServer)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", echoHost, echoPort)
|
||||
client, err := DialEchoService("tcp", addr)
|
||||
if err != nil {
|
||||
b.Fatalf(
|
||||
`net.Dial("tcp", "%s:%d"): %v`,
|
||||
echoHost, echoPort,
|
||||
err,
|
||||
)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var args1 EchoRequest
|
||||
var reply1 EchoResponse
|
||||
var args2 EchoRequest
|
||||
var reply2 EchoResponse
|
||||
var args3 EchoRequest
|
||||
var reply3 EchoResponse
|
||||
|
||||
// EchoService.EchoTwice
|
||||
args1.Msg = echoMassiveRequest + "abc"
|
||||
call1 := client.Go("EchoService.EchoTwice", &args1, &reply1, nil)
|
||||
args2.Msg = echoMassiveRequest + "你好, 世界"
|
||||
call2 := client.Go("EchoService.EchoTwice", &args2, &reply2, nil)
|
||||
args3.Msg = echoMassiveRequest + "Hello, 世界"
|
||||
call3 := client.Go("EchoService.EchoTwice", &args3, &reply3, nil)
|
||||
|
||||
call1 = <-call1.Done
|
||||
call2 = <-call2.Done
|
||||
call3 = <-call3.Done
|
||||
|
||||
// call1
|
||||
if call1.Error != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, call1.Error)
|
||||
}
|
||||
if call1.Reply.(*EchoResponse).Msg != args1.Msg+args1.Msg {
|
||||
got := call1.Reply.(*EchoResponse).Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(call1.Reply.(*EchoResponse).Msg), got,
|
||||
)
|
||||
}
|
||||
|
||||
// call2
|
||||
if call2.Error != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, call2.Error)
|
||||
}
|
||||
if call2.Reply.(*EchoResponse).Msg != args2.Msg+args2.Msg {
|
||||
got := call2.Reply.(*EchoResponse).Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(call2.Reply.(*EchoResponse).Msg), got,
|
||||
)
|
||||
}
|
||||
|
||||
// call3
|
||||
if call3.Error != nil {
|
||||
b.Fatalf(`EchoService.EchoTwice: %v`, call3.Error)
|
||||
}
|
||||
if call3.Reply.(*EchoResponse).Msg != args3.Msg+args3.Msg {
|
||||
got := call3.Reply.(*EchoResponse).Msg
|
||||
if len(got) > 8 {
|
||||
got = got[:8] + "..."
|
||||
}
|
||||
b.Fatalf(`EchoService.EchoTwice: len = %d, got = %v`,
|
||||
len(call3.Reply.(*EchoResponse).Msg), got,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
8
core/protorpc/examples/service.pb/proto.go
Normal file
8
core/protorpc/examples/service.pb/proto.go
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate protoc --go_out=. arith.proto echo.proto
|
||||
//go:generate protoc --protorpc_out=. arith.proto echo.proto
|
||||
|
||||
package service
|
||||
13
core/protorpc/examples/stdrpc.pb/Makefile
Normal file
13
core/protorpc/examples/stdrpc.pb/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
PROTO_FILES=$(sort $(wildcard ./*.proto))
|
||||
|
||||
default: $(PROTO_FILES) Makefile
|
||||
go install github.com/golang/protobuf/protoc-gen-go
|
||||
go install github.com/chai2010/protorpc/protoc-gen-stdrpc
|
||||
protoc --stdrpc_out=. ${PROTO_FILES}
|
||||
go test
|
||||
|
||||
clean:
|
||||
401
core/protorpc/examples/stdrpc.pb/arith.pb.go
Normal file
401
core/protorpc/examples/stdrpc.pb/arith.pb.go
Normal file
@ -0,0 +1,401 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: arith.proto
|
||||
|
||||
/*
|
||||
Package service is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
arith.proto
|
||||
echo.proto
|
||||
|
||||
It has these top-level messages:
|
||||
ArithRequest
|
||||
ArithResponse
|
||||
EchoRequest
|
||||
EchoResponse
|
||||
*/
|
||||
package service
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import "bufio"
|
||||
import "crypto/tls"
|
||||
import "errors"
|
||||
import "io"
|
||||
import "log"
|
||||
import "net"
|
||||
import "net/http"
|
||||
import "net/rpc"
|
||||
import "time"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type ArithRequest struct {
|
||||
A int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"`
|
||||
B int32 `protobuf:"varint,2,opt,name=b" json:"b,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ArithRequest) Reset() { *m = ArithRequest{} }
|
||||
func (m *ArithRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ArithRequest) ProtoMessage() {}
|
||||
func (*ArithRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *ArithRequest) GetA() int32 {
|
||||
if m != nil {
|
||||
return m.A
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *ArithRequest) GetB() int32 {
|
||||
if m != nil {
|
||||
return m.B
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ArithResponse struct {
|
||||
C int32 `protobuf:"varint,1,opt,name=c" json:"c,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ArithResponse) Reset() { *m = ArithResponse{} }
|
||||
func (m *ArithResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ArithResponse) ProtoMessage() {}
|
||||
func (*ArithResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *ArithResponse) GetC() int32 {
|
||||
if m != nil {
|
||||
return m.C
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*ArithRequest)(nil), "service.ArithRequest")
|
||||
proto.RegisterType((*ArithResponse)(nil), "service.ArithResponse")
|
||||
}
|
||||
|
||||
type ArithService interface {
|
||||
Add(in *ArithRequest, out *ArithResponse) error
|
||||
Mul(in *ArithRequest, out *ArithResponse) error
|
||||
Div(in *ArithRequest, out *ArithResponse) error
|
||||
Error(in *ArithRequest, out *ArithResponse) error
|
||||
}
|
||||
|
||||
// AcceptArithServiceClient accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func AcceptArithServiceClient(lis net.Listener, x ArithService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("service.ArithService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterArithService publish the given ArithService implementation on the server.
|
||||
func RegisterArithService(srv *rpc.Server, x ArithService) error {
|
||||
if err := srv.RegisterName("service.ArithService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewArithServiceServer returns a new ArithService Server.
|
||||
func NewArithServiceServer(x ArithService) *rpc.Server {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("service.ArithService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// ListenAndServeArithService listen announces on the local network address laddr
|
||||
// and serves the given ArithService implementation.
|
||||
func ListenAndServeArithService(network, addr string, x ArithService) error {
|
||||
lis, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("service.ArithService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// ServeArithService serves the given ArithService implementation.
|
||||
func ServeArithService(conn io.ReadWriteCloser, x ArithService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("service.ArithService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv.ServeConn(conn)
|
||||
}
|
||||
|
||||
type ArithServiceClient struct {
|
||||
*rpc.Client
|
||||
}
|
||||
|
||||
// NewArithServiceClient returns a ArithService stub to handle
|
||||
// requests to the set of ArithService at the other end of the connection.
|
||||
func NewArithServiceClient(conn io.ReadWriteCloser) *ArithServiceClient {
|
||||
c := rpc.NewClient(conn)
|
||||
return &ArithServiceClient{c}
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) Add(in *ArithRequest) (out *ArithResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out = new(ArithResponse)
|
||||
if err = c.Call("service.ArithService.Add", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) AsyncAdd(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"service.ArithService.Add",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) Mul(in *ArithRequest) (out *ArithResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out = new(ArithResponse)
|
||||
if err = c.Call("service.ArithService.Mul", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) AsyncMul(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"service.ArithService.Mul",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) Div(in *ArithRequest) (out *ArithResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out = new(ArithResponse)
|
||||
if err = c.Call("service.ArithService.Div", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) AsyncDiv(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"service.ArithService.Div",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) Error(in *ArithRequest) (out *ArithResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out = new(ArithResponse)
|
||||
if err = c.Call("service.ArithService.Error", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ArithServiceClient) AsyncError(in *ArithRequest, out *ArithResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(ArithRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"service.ArithService.Error",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
// DialArithService connects to an ArithService at the specified network address.
|
||||
func DialArithService(network, addr string) (*ArithServiceClient, error) {
|
||||
c, err := rpc.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ArithServiceClient{c}, nil
|
||||
}
|
||||
|
||||
// DialArithServiceTimeout connects to an ArithService at the specified network address.
|
||||
func DialArithServiceTimeout(network, addr string, timeout time.Duration) (*ArithServiceClient, error) {
|
||||
conn, err := net.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ArithServiceClient{rpc.NewClient(conn)}, nil
|
||||
}
|
||||
|
||||
// DialArithServiceHTTP connects to an HTTP RPC server at the specified network address
|
||||
// listening on the default HTTP RPC path.
|
||||
func DialArithServiceHTTP(network, address string) (*ArithServiceClient, error) {
|
||||
return DialArithServiceHTTPPath(network, address, rpc.DefaultRPCPath)
|
||||
}
|
||||
|
||||
// DialArithServiceHTTPPath connects to an HTTP RPC server
|
||||
// at the specified network address and path.
|
||||
func DialArithServiceHTTPPath(network, address, path string) (*ArithServiceClient, error) {
|
||||
conn, err := net.Dial(network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialArithServicePath(network, address, path, conn)
|
||||
}
|
||||
|
||||
// DialArithServiceHTTPS connects to an HTTPS RPC server at the specified network address
|
||||
// listening on the default HTTP RPC path.
|
||||
func DialArithServiceHTTPS(network, address string, tlsConfig *tls.Config) (*ArithServiceClient, error) {
|
||||
return DialArithServiceHTTPSPath(network, address, rpc.DefaultRPCPath, tlsConfig)
|
||||
}
|
||||
|
||||
// DialArithServiceHTTPSPath connects to an HTTPS RPC server
|
||||
// at the specified network address and path.
|
||||
func DialArithServiceHTTPSPath(network, address, path string, tlsConfig *tls.Config) (*ArithServiceClient, error) {
|
||||
conn, err := tls.Dial(network, address, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialArithServicePath(network, address, path, conn)
|
||||
}
|
||||
|
||||
func dialArithServicePath(network, address, path string, conn net.Conn) (*ArithServiceClient, error) {
|
||||
const net_rpc_connected = "200 Connected to Go RPC"
|
||||
|
||||
io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n")
|
||||
|
||||
// Require successful HTTP response
|
||||
// before switching to RPC protocol.
|
||||
resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
|
||||
if err == nil && resp.Status == net_rpc_connected {
|
||||
return &ArithServiceClient{rpc.NewClient(conn)}, nil
|
||||
}
|
||||
if err == nil {
|
||||
err = errors.New("unexpected HTTP response: " + resp.Status)
|
||||
}
|
||||
conn.Close()
|
||||
return nil, &net.OpError{
|
||||
Op: "dial-http",
|
||||
Net: network + " " + address,
|
||||
Addr: nil,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("arith.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 159 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4e, 0x2c, 0xca, 0x2c,
|
||||
0xc9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e,
|
||||
0x55, 0xd2, 0xe2, 0xe2, 0x71, 0x04, 0x89, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0xf1,
|
||||
0x70, 0x31, 0x26, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0x31, 0x26, 0x82, 0x78, 0x49, 0x12,
|
||||
0x4c, 0x10, 0x5e, 0x92, 0x92, 0x2c, 0x17, 0x2f, 0x54, 0x6d, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0x2a,
|
||||
0x48, 0x3a, 0x19, 0xa6, 0x38, 0xd9, 0xe8, 0x05, 0x23, 0xd4, 0xac, 0x60, 0x88, 0xd9, 0x42, 0x26,
|
||||
0x5c, 0xcc, 0x89, 0x29, 0x29, 0x42, 0xa2, 0x7a, 0x50, 0xcb, 0xf4, 0x90, 0x6d, 0x92, 0x12, 0x43,
|
||||
0x17, 0x86, 0x1a, 0x6a, 0xc2, 0xc5, 0x9c, 0x5b, 0x9a, 0x43, 0x86, 0xae, 0x94, 0xcc, 0x32, 0x52,
|
||||
0x75, 0x99, 0x71, 0xb1, 0xa6, 0x16, 0x15, 0xe5, 0x17, 0x91, 0xa8, 0x2f, 0x89, 0x0d, 0x1c, 0x8a,
|
||||
0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x62, 0xfd, 0xbd, 0x54, 0x01, 0x00, 0x00,
|
||||
}
|
||||
23
core/protorpc/examples/stdrpc.pb/arith.proto
Normal file
23
core/protorpc/examples/stdrpc.pb/arith.proto
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package service;
|
||||
|
||||
message ArithRequest {
|
||||
int32 a = 1;
|
||||
int32 b = 2;
|
||||
}
|
||||
|
||||
message ArithResponse {
|
||||
int32 c = 1;
|
||||
}
|
||||
|
||||
service ArithService {
|
||||
rpc add (ArithRequest) returns (ArithResponse);
|
||||
rpc mul (ArithRequest) returns (ArithResponse);
|
||||
rpc div (ArithRequest) returns (ArithResponse);
|
||||
rpc error (ArithRequest) returns (ArithResponse);
|
||||
}
|
||||
301
core/protorpc/examples/stdrpc.pb/echo.pb.go
Normal file
301
core/protorpc/examples/stdrpc.pb/echo.pb.go
Normal file
@ -0,0 +1,301 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: echo.proto
|
||||
|
||||
package service
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import "bufio"
|
||||
import "crypto/tls"
|
||||
import "errors"
|
||||
import "io"
|
||||
import "log"
|
||||
import "net"
|
||||
import "net/http"
|
||||
import "net/rpc"
|
||||
import "time"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type EchoRequest struct {
|
||||
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EchoRequest) Reset() { *m = EchoRequest{} }
|
||||
func (m *EchoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*EchoRequest) ProtoMessage() {}
|
||||
func (*EchoRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
|
||||
|
||||
func (m *EchoRequest) GetMsg() string {
|
||||
if m != nil {
|
||||
return m.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EchoResponse struct {
|
||||
Msg string `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EchoResponse) Reset() { *m = EchoResponse{} }
|
||||
func (m *EchoResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*EchoResponse) ProtoMessage() {}
|
||||
func (*EchoResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
|
||||
|
||||
func (m *EchoResponse) GetMsg() string {
|
||||
if m != nil {
|
||||
return m.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*EchoRequest)(nil), "service.EchoRequest")
|
||||
proto.RegisterType((*EchoResponse)(nil), "service.EchoResponse")
|
||||
}
|
||||
|
||||
type EchoService interface {
|
||||
Echo(in *EchoRequest, out *EchoResponse) error
|
||||
EchoTwice(in *EchoRequest, out *EchoResponse) error
|
||||
}
|
||||
|
||||
// AcceptEchoServiceClient accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func AcceptEchoServiceClient(lis net.Listener, x EchoService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("service.EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterEchoService publish the given EchoService implementation on the server.
|
||||
func RegisterEchoService(srv *rpc.Server, x EchoService) error {
|
||||
if err := srv.RegisterName("service.EchoService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewEchoServiceServer returns a new EchoService Server.
|
||||
func NewEchoServiceServer(x EchoService) *rpc.Server {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("service.EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// ListenAndServeEchoService listen announces on the local network address laddr
|
||||
// and serves the given EchoService implementation.
|
||||
func ListenAndServeEchoService(network, addr string, x EchoService) error {
|
||||
lis, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("service.EchoService", x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// ServeEchoService serves the given EchoService implementation.
|
||||
func ServeEchoService(conn io.ReadWriteCloser, x EchoService) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("service.EchoService", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv.ServeConn(conn)
|
||||
}
|
||||
|
||||
type EchoServiceClient struct {
|
||||
*rpc.Client
|
||||
}
|
||||
|
||||
// NewEchoServiceClient returns a EchoService stub to handle
|
||||
// requests to the set of EchoService at the other end of the connection.
|
||||
func NewEchoServiceClient(conn io.ReadWriteCloser) *EchoServiceClient {
|
||||
c := rpc.NewClient(conn)
|
||||
return &EchoServiceClient{c}
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) Echo(in *EchoRequest) (out *EchoResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(EchoRequest)
|
||||
}
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out = new(EchoResponse)
|
||||
if err = c.Call("service.EchoService.Echo", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) AsyncEcho(in *EchoRequest, out *EchoResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(EchoRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"service.EchoService.Echo",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) EchoTwice(in *EchoRequest) (out *EchoResponse, err error) {
|
||||
if in == nil {
|
||||
in = new(EchoRequest)
|
||||
}
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out = new(EchoResponse)
|
||||
if err = c.Call("service.EchoService.EchoTwice", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *EchoServiceClient) AsyncEchoTwice(in *EchoRequest, out *EchoResponse, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new(EchoRequest)
|
||||
}
|
||||
return c.Go(
|
||||
"service.EchoService.EchoTwice",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
|
||||
// DialEchoService connects to an EchoService at the specified network address.
|
||||
func DialEchoService(network, addr string) (*EchoServiceClient, error) {
|
||||
c, err := rpc.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EchoServiceClient{c}, nil
|
||||
}
|
||||
|
||||
// DialEchoServiceTimeout connects to an EchoService at the specified network address.
|
||||
func DialEchoServiceTimeout(network, addr string, timeout time.Duration) (*EchoServiceClient, error) {
|
||||
conn, err := net.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EchoServiceClient{rpc.NewClient(conn)}, nil
|
||||
}
|
||||
|
||||
// DialEchoServiceHTTP connects to an HTTP RPC server at the specified network address
|
||||
// listening on the default HTTP RPC path.
|
||||
func DialEchoServiceHTTP(network, address string) (*EchoServiceClient, error) {
|
||||
return DialEchoServiceHTTPPath(network, address, rpc.DefaultRPCPath)
|
||||
}
|
||||
|
||||
// DialEchoServiceHTTPPath connects to an HTTP RPC server
|
||||
// at the specified network address and path.
|
||||
func DialEchoServiceHTTPPath(network, address, path string) (*EchoServiceClient, error) {
|
||||
conn, err := net.Dial(network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialEchoServicePath(network, address, path, conn)
|
||||
}
|
||||
|
||||
// DialEchoServiceHTTPS connects to an HTTPS RPC server at the specified network address
|
||||
// listening on the default HTTP RPC path.
|
||||
func DialEchoServiceHTTPS(network, address string, tlsConfig *tls.Config) (*EchoServiceClient, error) {
|
||||
return DialEchoServiceHTTPSPath(network, address, rpc.DefaultRPCPath, tlsConfig)
|
||||
}
|
||||
|
||||
// DialEchoServiceHTTPSPath connects to an HTTPS RPC server
|
||||
// at the specified network address and path.
|
||||
func DialEchoServiceHTTPSPath(network, address, path string, tlsConfig *tls.Config) (*EchoServiceClient, error) {
|
||||
conn, err := tls.Dial(network, address, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialEchoServicePath(network, address, path, conn)
|
||||
}
|
||||
|
||||
func dialEchoServicePath(network, address, path string, conn net.Conn) (*EchoServiceClient, error) {
|
||||
const net_rpc_connected = "200 Connected to Go RPC"
|
||||
|
||||
io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n")
|
||||
|
||||
// Require successful HTTP response
|
||||
// before switching to RPC protocol.
|
||||
resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
|
||||
if err == nil && resp.Status == net_rpc_connected {
|
||||
return &EchoServiceClient{rpc.NewClient(conn)}, nil
|
||||
}
|
||||
if err == nil {
|
||||
err = errors.New("unexpected HTTP response: " + resp.Status)
|
||||
}
|
||||
conn.Close()
|
||||
return nil, &net.OpError{
|
||||
Op: "dial-http",
|
||||
Net: network + " " + address,
|
||||
Addr: nil,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("echo.proto", fileDescriptor1) }
|
||||
|
||||
var fileDescriptor1 = []byte{
|
||||
// 134 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8,
|
||||
0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x55,
|
||||
0x92, 0xe7, 0xe2, 0x76, 0x4d, 0xce, 0xc8, 0x0f, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12,
|
||||
0xe0, 0x62, 0xce, 0x2d, 0x4e, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x95, 0x14,
|
||||
0xb8, 0x78, 0x20, 0x0a, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x31, 0x55, 0x18, 0xd5, 0x40, 0x8c,
|
||||
0x08, 0x86, 0x98, 0x28, 0x64, 0xcc, 0xc5, 0x02, 0xe2, 0x0a, 0x89, 0xe8, 0x41, 0xed, 0xd0, 0x43,
|
||||
0xb2, 0x40, 0x4a, 0x14, 0x4d, 0x14, 0x6a, 0xaa, 0x05, 0x17, 0x27, 0x88, 0x1f, 0x52, 0x0e, 0x32,
|
||||
0x81, 0x14, 0x9d, 0x49, 0x6c, 0x60, 0x0f, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc1,
|
||||
0xd4, 0xbd, 0xde, 0x00, 0x00, 0x00,
|
||||
}
|
||||
20
core/protorpc/examples/stdrpc.pb/echo.proto
Normal file
20
core/protorpc/examples/stdrpc.pb/echo.proto
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package service;
|
||||
|
||||
message EchoRequest {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
message EchoResponse {
|
||||
string msg = 1;
|
||||
}
|
||||
|
||||
service EchoService {
|
||||
rpc Echo (EchoRequest) returns (EchoResponse);
|
||||
rpc EchoTwice (EchoRequest) returns (EchoResponse);
|
||||
}
|
||||
11
core/protorpc/go.mod
Normal file
11
core/protorpc/go.mod
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2021 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
module github.com/chai2010/protorpc
|
||||
|
||||
go 1.23
|
||||
|
||||
require github.com/golang/protobuf v1.5.4
|
||||
|
||||
require google.golang.org/protobuf v1.36.6 // indirect
|
||||
62
core/protorpc/hello.go
Normal file
62
core/protorpc/hello.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ingore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/chai2010/protorpc"
|
||||
service "github.com/chai2010/protorpc/examples/service.pb"
|
||||
)
|
||||
|
||||
type Echo int
|
||||
|
||||
func (t *Echo) Echo(args *service.EchoRequest, reply *service.EchoResponse) error {
|
||||
reply.Msg = args.Msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Echo) EchoTwice(args *service.EchoRequest, reply *service.EchoResponse) error {
|
||||
reply.Msg = args.Msg + args.Msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
go service.ListenAndServeEchoService("tcp", `127.0.0.1:9527`, new(Echo))
|
||||
}
|
||||
|
||||
func main() {
|
||||
echoClient, err := service.DialEchoService("tcp", `127.0.0.1:9527`)
|
||||
if err != nil {
|
||||
log.Fatalf("service.DialEchoService: %v", err)
|
||||
}
|
||||
defer echoClient.Close()
|
||||
|
||||
args := &service.EchoRequest{Msg: "你好, 世界!"}
|
||||
reply, err := echoClient.EchoTwice(args)
|
||||
if err != nil {
|
||||
log.Fatalf("echoClient.EchoTwice: %v", err)
|
||||
}
|
||||
fmt.Println(reply.Msg)
|
||||
|
||||
// or use normal client
|
||||
client, err := protorpc.Dial("tcp", `127.0.0.1:9527`)
|
||||
if err != nil {
|
||||
log.Fatalf("protorpc.Dial: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
echoClient1 := &service.EchoServiceClient{client}
|
||||
echoClient2 := &service.EchoServiceClient{client}
|
||||
reply, err = echoClient1.EchoTwice(args)
|
||||
reply, err = echoClient2.EchoTwice(args)
|
||||
_, _ = reply, err
|
||||
|
||||
// Output:
|
||||
// 你好, 世界!你好, 世界!
|
||||
}
|
||||
65
core/protorpc/hello2.go
Normal file
65
core/protorpc/hello2.go
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ingore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/rpc"
|
||||
"time"
|
||||
|
||||
stdrpc "github.com/chai2010/protorpc/examples/stdrpc.pb"
|
||||
)
|
||||
|
||||
type Echo int
|
||||
|
||||
func (t *Echo) Echo(args *stdrpc.EchoRequest, reply *stdrpc.EchoResponse) error {
|
||||
reply.Msg = args.Msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Echo) EchoTwice(args *stdrpc.EchoRequest, reply *stdrpc.EchoResponse) error {
|
||||
reply.Msg = args.Msg + args.Msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
go stdrpc.ListenAndServeEchoService("tcp", `127.0.0.1:9527`, new(Echo))
|
||||
}
|
||||
|
||||
func main() {
|
||||
time.Sleep(time.Second)
|
||||
|
||||
echoClient, err := stdrpc.DialEchoService("tcp", `127.0.0.1:9527`)
|
||||
if err != nil {
|
||||
log.Fatalf("stdrpc.DialEchoService: %v", err)
|
||||
}
|
||||
defer echoClient.Close()
|
||||
|
||||
args := &stdrpc.EchoRequest{Msg: "你好, 世界!"}
|
||||
reply, err := echoClient.EchoTwice(args)
|
||||
if err != nil {
|
||||
log.Fatalf("echoClient.EchoTwice: %v", err)
|
||||
}
|
||||
fmt.Println(reply.Msg)
|
||||
|
||||
// or use normal client
|
||||
client, err := rpc.Dial("tcp", `127.0.0.1:9527`)
|
||||
if err != nil {
|
||||
log.Fatalf("rpc.Dial: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
echoClient1 := &stdrpc.EchoServiceClient{client}
|
||||
echoClient2 := &stdrpc.EchoServiceClient{client}
|
||||
reply, err = echoClient1.EchoTwice(args)
|
||||
reply, err = echoClient2.EchoTwice(args)
|
||||
_, _ = reply, err
|
||||
|
||||
// Output:
|
||||
// 你好, 世界!你好, 世界!
|
||||
}
|
||||
52
core/protorpc/protoc-gen-plugin/generator.go
Normal file
52
core/protorpc/protoc-gen-plugin/generator.go
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2017 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a Apache
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
)
|
||||
|
||||
var pkgCodeGeneratorList []CodeGenerator
|
||||
|
||||
type CodeGenerator interface {
|
||||
Name() string
|
||||
FileNameExt() string
|
||||
|
||||
HeaderCode(g *generator.Generator, file *generator.FileDescriptor) string
|
||||
ServiceCode(g *generator.Generator, file *generator.FileDescriptor, svc *descriptor.ServiceDescriptorProto) string
|
||||
MessageCode(g *generator.Generator, file *generator.FileDescriptor, msg *descriptor.DescriptorProto) string
|
||||
}
|
||||
|
||||
func RegisterCodeGenerator(g CodeGenerator) {
|
||||
pkgCodeGeneratorList = append(pkgCodeGeneratorList, g)
|
||||
}
|
||||
|
||||
func getAllCodeGenerator() []CodeGenerator {
|
||||
return pkgCodeGeneratorList
|
||||
}
|
||||
|
||||
func getAllServiceGeneratorNames() (names []string) {
|
||||
for _, g := range pkgCodeGeneratorList {
|
||||
names = append(names, g.Name())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getFirstServiceGeneratorName() string {
|
||||
if len(pkgCodeGeneratorList) > 0 {
|
||||
return pkgCodeGeneratorList[0].Name()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getCodeGenerator(name string) CodeGenerator {
|
||||
for _, g := range pkgCodeGeneratorList {
|
||||
if g.Name() == name {
|
||||
return g
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
115
core/protorpc/protoc-gen-plugin/main.go
Normal file
115
core/protorpc/protoc-gen-plugin/main.go
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright 2017 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a Apache
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
)
|
||||
|
||||
func Main() {
|
||||
mainPlugin := new(mainPlugin)
|
||||
generator.RegisterPlugin(mainPlugin)
|
||||
|
||||
// Begin by allocating a generator. The request and response structures are stored there
|
||||
// so we can do error handling easily - the response structure contains the field to
|
||||
// report failure.
|
||||
g := generator.New()
|
||||
if len(getAllCodeGenerator()) == 0 {
|
||||
g.Fail("no code generator plugin")
|
||||
}
|
||||
|
||||
pkgReadRequetFromStdin(g)
|
||||
pkgGenerateAllFiles(g, mainPlugin)
|
||||
pkgWriteResponseToStdout(g)
|
||||
}
|
||||
|
||||
func pkgGenerateAllFiles(g *generator.Generator, plugin *mainPlugin) {
|
||||
// set default plugins
|
||||
// protoc --xxx_out=. x.proto
|
||||
plugin.InitService(pkgGetUserPlugin(g))
|
||||
|
||||
// parse command line parameters
|
||||
g.CommandLineParameters("plugins=" + plugin.Name())
|
||||
|
||||
// Create a wrapped version of the Descriptors and EnumDescriptors that
|
||||
// point to the file that defines them.
|
||||
g.WrapTypes()
|
||||
|
||||
g.SetPackageNames()
|
||||
g.BuildTypeNameMap()
|
||||
|
||||
g.GenerateAllFiles()
|
||||
|
||||
// skip non *.pb.xxx.go
|
||||
respFileList := g.Response.File[:0]
|
||||
for _, file := range g.Response.File {
|
||||
fileName := file.GetName()
|
||||
extName := plugin.FileNameExt()
|
||||
|
||||
if strings.HasSuffix(fileName, extName) {
|
||||
respFileList = append(respFileList, file)
|
||||
}
|
||||
}
|
||||
g.Response.File = respFileList
|
||||
}
|
||||
|
||||
func pkgReadRequetFromStdin(g *generator.Generator) {
|
||||
data, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
g.Error(err, "reading input")
|
||||
}
|
||||
|
||||
if err := proto.Unmarshal(data, g.Request); err != nil {
|
||||
g.Error(err, "parsing input proto")
|
||||
}
|
||||
|
||||
if len(g.Request.FileToGenerate) == 0 {
|
||||
g.Fail("no files to generate")
|
||||
}
|
||||
}
|
||||
|
||||
func pkgWriteResponseToStdout(g *generator.Generator) {
|
||||
data, err := proto.Marshal(g.Response)
|
||||
if err != nil {
|
||||
g.Error(err, "failed to marshal output proto")
|
||||
}
|
||||
_, err = os.Stdout.Write(data)
|
||||
if err != nil {
|
||||
g.Error(err, "failed to write output proto")
|
||||
}
|
||||
}
|
||||
|
||||
func pkgGetUserPlugin(g *generator.Generator) CodeGenerator {
|
||||
args := g.Request.GetParameter()
|
||||
userPluginName := pkgGetParameterValue(args, "plugin")
|
||||
if userPluginName == "" {
|
||||
userPluginName = getFirstServiceGeneratorName()
|
||||
}
|
||||
|
||||
userPlugin := getCodeGenerator(userPluginName)
|
||||
if userPlugin == nil {
|
||||
log.Print("protoc-gen-plugin: registor plugins:", getAllServiceGeneratorNames())
|
||||
g.Fail("invalid plugin option:", userPluginName)
|
||||
}
|
||||
|
||||
return userPlugin
|
||||
}
|
||||
|
||||
func pkgGetParameterValue(parameter, key string) string {
|
||||
for _, p := range strings.Split(parameter, ",") {
|
||||
if i := strings.Index(p, "="); i > 0 {
|
||||
if p[0:i] == key {
|
||||
return p[i+1:]
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
119
core/protorpc/protoc-gen-plugin/main_plugin.go
Normal file
119
core/protorpc/protoc-gen-plugin/main_plugin.go
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright 2017 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a Apache
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||
)
|
||||
|
||||
// mainPlugin produce the Service interface.
|
||||
type mainPlugin struct {
|
||||
*generator.Generator
|
||||
CodeGenerator
|
||||
}
|
||||
|
||||
// Name returns the name of the plugin.
|
||||
func (p *mainPlugin) Name() string { return "main-plugin" }
|
||||
|
||||
// Init is called once after data structures are built but before
|
||||
// code generation begins.
|
||||
func (p *mainPlugin) Init(g *generator.Generator) {
|
||||
p.Generator = g
|
||||
}
|
||||
|
||||
func (p *mainPlugin) InitService(g CodeGenerator) {
|
||||
p.CodeGenerator = g
|
||||
}
|
||||
|
||||
// Generate produces the code generated by the plugin for this file.
|
||||
func (p *mainPlugin) GenerateImports(file *generator.FileDescriptor) {
|
||||
// skip
|
||||
}
|
||||
|
||||
// Generate generates the Service interface.
|
||||
// rpc service can't handle other proto message!!!
|
||||
func (p *mainPlugin) Generate(file *generator.FileDescriptor) {
|
||||
if !p.isFileNeedGenerate(file) {
|
||||
return
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintln(&buf, p.HeaderCode(p.Generator, file))
|
||||
|
||||
for _, msg := range file.MessageType {
|
||||
fmt.Fprintln(&buf, p.MessageCode(p.Generator, file, msg))
|
||||
}
|
||||
|
||||
for _, svc := range file.Service {
|
||||
fmt.Fprintln(&buf, p.ServiceCode(p.Generator, file, svc))
|
||||
}
|
||||
|
||||
fileContent := buf.String()
|
||||
if code, err := format.Source(buf.Bytes()); err == nil {
|
||||
fileContent = string(code)
|
||||
}
|
||||
|
||||
p.Generator.Response.File = append(p.Generator.Response.File, &plugin.CodeGeneratorResponse_File{
|
||||
Name: proto.String(p.goFileName(file)),
|
||||
Content: proto.String(fileContent),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *mainPlugin) isFileNeedGenerate(file *generator.FileDescriptor) bool {
|
||||
for _, v := range p.Generator.Request.FileToGenerate {
|
||||
if v == file.GetName() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *mainPlugin) goFileName(file *generator.FileDescriptor) string {
|
||||
name := *file.Name
|
||||
if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
|
||||
name = name[:len(name)-len(ext)]
|
||||
}
|
||||
name += p.FileNameExt()
|
||||
|
||||
// Does the file have a "go_package" option?
|
||||
// If it does, it may override the filename.
|
||||
if impPath, _, ok := p.goPackageOption(file); ok && impPath != "" {
|
||||
// Replace the existing dirname with the declared import path.
|
||||
_, name = path.Split(name)
|
||||
name = path.Join(impPath, name)
|
||||
return name
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func (p *mainPlugin) goPackageOption(file *generator.FileDescriptor) (impPath, pkg string, ok bool) {
|
||||
pkg = file.GetOptions().GetGoPackage()
|
||||
if pkg == "" {
|
||||
return
|
||||
}
|
||||
ok = true
|
||||
// The presence of a slash implies there's an import path.
|
||||
slash := strings.LastIndex(pkg, "/")
|
||||
if slash < 0 {
|
||||
return
|
||||
}
|
||||
impPath, pkg = pkg, pkg[slash+1:]
|
||||
// A semicolon-delimited suffix overrides the package name.
|
||||
sc := strings.IndexByte(impPath, ';')
|
||||
if sc < 0 {
|
||||
return
|
||||
}
|
||||
impPath, pkg = impPath[:sc], impPath[sc+1:]
|
||||
return
|
||||
}
|
||||
7
core/protorpc/protoc-gen-protorpc/env.go
Normal file
7
core/protorpc/protoc-gen-protorpc/env.go
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
const ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX = "ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX"
|
||||
381
core/protorpc/protoc-gen-protorpc/main.go
Normal file
381
core/protorpc/protoc-gen-protorpc/main.go
Normal file
@ -0,0 +1,381 @@
|
||||
// Copyright 2018 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
plugin "github.com/chai2010/protorpc/protoc-gen-plugin"
|
||||
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
)
|
||||
|
||||
var flagPrefix = os.Getenv(ENV_PROTOC_GEN_PROTORPC_FLAG_PREFIX)
|
||||
|
||||
func main() {
|
||||
plugin.Main()
|
||||
}
|
||||
|
||||
func init() {
|
||||
plugin.RegisterCodeGenerator(new(protorpcPlugin))
|
||||
}
|
||||
|
||||
type protorpcPlugin struct{}
|
||||
|
||||
func (p *protorpcPlugin) Name() string { return "protorpc-go" }
|
||||
func (p *protorpcPlugin) FileNameExt() string { return ".pb.protorpc.go" }
|
||||
|
||||
func (p *protorpcPlugin) HeaderCode(g *generator.Generator, file *generator.FileDescriptor) string {
|
||||
const tmpl = `
|
||||
{{- $G := .G -}}
|
||||
{{- $File := .File -}}
|
||||
|
||||
// Code generated by protoc-gen-protorpc. DO NOT EDIT.
|
||||
//
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-plugin
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-protorpc
|
||||
//
|
||||
// source: {{$File.GetName}}
|
||||
|
||||
package {{$File.PackageName}}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"time"
|
||||
|
||||
"github.com/chai2010/protorpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = fmt.Sprint
|
||||
_ = io.Reader(nil)
|
||||
_ = log.Print
|
||||
_ = net.Addr(nil)
|
||||
_ = rpc.Call{}
|
||||
_ = time.Second
|
||||
|
||||
_ = proto.String
|
||||
_ = protorpc.Dial
|
||||
)
|
||||
`
|
||||
var buf bytes.Buffer
|
||||
t := template.Must(template.New("").Parse(tmpl))
|
||||
err := t.Execute(&buf,
|
||||
struct {
|
||||
G *generator.Generator
|
||||
File *generator.FileDescriptor
|
||||
Prefix string
|
||||
}{
|
||||
G: g,
|
||||
File: file,
|
||||
Prefix: flagPrefix,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) ServiceCode(g *generator.Generator, file *generator.FileDescriptor, svc *descriptor.ServiceDescriptorProto) string {
|
||||
var code string
|
||||
code += p.genServiceInterface(g, file, svc)
|
||||
code += p.genServiceServer(g, file, svc)
|
||||
code += p.genServiceClient(g, file, svc)
|
||||
return code
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) MessageCode(g *generator.Generator, file *generator.FileDescriptor, msg *descriptor.DescriptorProto) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) genServiceInterface(
|
||||
g *generator.Generator,
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) string {
|
||||
const serviceInterfaceTmpl = `
|
||||
type {{.Prefix}}{{.ServiceName}} interface {
|
||||
{{.CallMethodList}}
|
||||
}
|
||||
`
|
||||
const callMethodTmpl = `
|
||||
{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}) error`
|
||||
|
||||
// gen call method list
|
||||
var callMethodList string
|
||||
for _, m := range svc.Method {
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(callMethodTmpl))
|
||||
t.Execute(out, &struct {
|
||||
Prefix string
|
||||
ServiceName string
|
||||
MethodName string
|
||||
ArgsType string
|
||||
ReplyType string
|
||||
}{
|
||||
Prefix: flagPrefix,
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
MethodName: generator.CamelCase(m.GetName()),
|
||||
ArgsType: g.TypeName(g.ObjectNamed(m.GetInputType())),
|
||||
ReplyType: g.TypeName(g.ObjectNamed(m.GetOutputType())),
|
||||
})
|
||||
callMethodList += out.String()
|
||||
|
||||
g.RecordTypeUse(m.GetInputType())
|
||||
g.RecordTypeUse(m.GetOutputType())
|
||||
}
|
||||
|
||||
// gen all interface code
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(serviceInterfaceTmpl))
|
||||
t.Execute(out, &struct {
|
||||
Prefix string
|
||||
ServiceName string
|
||||
CallMethodList string
|
||||
}{
|
||||
Prefix: flagPrefix,
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
CallMethodList: callMethodList,
|
||||
})
|
||||
|
||||
return out.String()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) genServiceServer(
|
||||
g *generator.Generator,
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) string {
|
||||
const serviceHelperFunTmpl = `
|
||||
// {{.Prefix}}Accept{{.ServiceName}}Client accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func {{.Prefix}}Accept{{.ServiceName}}Client(lis net.Listener, x {{.Prefix}}{{.ServiceName}}) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}
|
||||
|
||||
// {{.Prefix}}Register{{.ServiceName}} publish the given {{.Prefix}}{{.ServiceName}} implementation on the server.
|
||||
func {{.Prefix}}Register{{.ServiceName}}(srv *rpc.Server, x {{.Prefix}}{{.ServiceName}}) error {
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// {{.Prefix}}New{{.ServiceName}}Server returns a new {{.Prefix}}{{.ServiceName}} Server.
|
||||
func {{.Prefix}}New{{.ServiceName}}Server(x {{.Prefix}}{{.ServiceName}}) *rpc.Server {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// {{.Prefix}}ListenAndServe{{.ServiceName}} listen announces on the local network address laddr
|
||||
// and serves the given {{.ServiceName}} implementation.
|
||||
func {{.Prefix}}ListenAndServe{{.ServiceName}}(network, addr string, x {{.Prefix}}{{.ServiceName}}) error {
|
||||
lis, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}
|
||||
|
||||
// {{.Prefix}}Serve{{.ServiceName}} serves the given {{.Prefix}}{{.ServiceName}} implementation.
|
||||
func {{.Prefix}}Serve{{.ServiceName}}(conn io.ReadWriteCloser, x {{.Prefix}}{{.ServiceName}}) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
`
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(serviceHelperFunTmpl))
|
||||
t.Execute(out, &struct {
|
||||
Prefix string
|
||||
PackageName string
|
||||
ServiceName string
|
||||
ServiceRegisterName string
|
||||
}{
|
||||
Prefix: flagPrefix,
|
||||
PackageName: file.GetPackage(),
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
ServiceRegisterName: p.makeServiceRegisterName(
|
||||
file, file.GetPackage(), generator.CamelCase(svc.GetName()),
|
||||
),
|
||||
})
|
||||
|
||||
return out.String()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) genServiceClient(
|
||||
g *generator.Generator,
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) string {
|
||||
const clientHelperFuncTmpl = `
|
||||
type {{.Prefix}}{{.ServiceName}}Client struct {
|
||||
*rpc.Client
|
||||
}
|
||||
|
||||
// {{.Prefix}}New{{.ServiceName}}Client returns a {{.Prefix}}{{.ServiceName}} stub to handle
|
||||
// requests to the set of {{.Prefix}}{{.ServiceName}} at the other end of the connection.
|
||||
func {{.Prefix}}New{{.ServiceName}}Client(conn io.ReadWriteCloser) (*{{.Prefix}}{{.ServiceName}}Client) {
|
||||
c := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn))
|
||||
return &{{.Prefix}}{{.ServiceName}}Client{c}
|
||||
}
|
||||
|
||||
{{.MethodList}}
|
||||
|
||||
// {{.Prefix}}Dial{{.ServiceName}} connects to an {{.Prefix}}{{.ServiceName}} at the specified network address.
|
||||
func {{.Prefix}}Dial{{.ServiceName}}(network, addr string) (*{{.Prefix}}{{.ServiceName}}Client, error) {
|
||||
c, err := protorpc.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &{{.Prefix}}{{.ServiceName}}Client{c}, nil
|
||||
}
|
||||
|
||||
// {{.Prefix}}Dial{{.ServiceName}}Timeout connects to an {{.Prefix}}{{.ServiceName}} at the specified network address.
|
||||
func {{.Prefix}}Dial{{.ServiceName}}Timeout(network, addr string, timeout time.Duration) (*{{.Prefix}}{{.ServiceName}}Client, error) {
|
||||
c, err := protorpc.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &{{.Prefix}}{{.ServiceName}}Client{c}, nil
|
||||
}
|
||||
`
|
||||
const clientMethodTmpl = `
|
||||
func (c *{{.Prefix}}{{.ServiceName}}Client) {{.MethodName}}(in *{{.ArgsType}}) (out *{{.ReplyType}}, err error) {
|
||||
if in == nil {
|
||||
in = new({{.ArgsType}})
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new({{.ReplyType}})
|
||||
if err = c.Call("{{.ServiceRegisterName}}.{{.MethodName}}", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *{{.Prefix}}{{.ServiceName}}Client) Async{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new({{.ArgsType}})
|
||||
}
|
||||
return c.Go(
|
||||
"{{.ServiceRegisterName}}.{{.MethodName}}",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
`
|
||||
|
||||
// gen client method list
|
||||
var methodList string
|
||||
for _, m := range svc.Method {
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(clientMethodTmpl))
|
||||
t.Execute(out, &struct {
|
||||
Prefix string
|
||||
ServiceName string
|
||||
ServiceRegisterName string
|
||||
MethodName string
|
||||
ArgsType string
|
||||
ReplyType string
|
||||
}{
|
||||
Prefix: flagPrefix,
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
ServiceRegisterName: p.makeServiceRegisterName(
|
||||
file, file.GetPackage(), generator.CamelCase(svc.GetName()),
|
||||
),
|
||||
MethodName: generator.CamelCase(m.GetName()),
|
||||
ArgsType: g.TypeName(g.ObjectNamed(m.GetInputType())),
|
||||
ReplyType: g.TypeName(g.ObjectNamed(m.GetOutputType())),
|
||||
})
|
||||
methodList += out.String()
|
||||
}
|
||||
|
||||
// gen all client code
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(clientHelperFuncTmpl))
|
||||
t.Execute(out, &struct {
|
||||
Prefix string
|
||||
PackageName string
|
||||
ServiceName string
|
||||
MethodList string
|
||||
}{
|
||||
Prefix: flagPrefix,
|
||||
PackageName: file.GetPackage(),
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
MethodList: methodList,
|
||||
})
|
||||
|
||||
return out.String()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) makeServiceRegisterName(
|
||||
file *generator.FileDescriptor,
|
||||
packageName, serviceName string,
|
||||
) string {
|
||||
// return packageName + "." + serviceName
|
||||
return serviceName
|
||||
}
|
||||
342
core/protorpc/protoc-gen-stdrpc/_main-ignore.go
Normal file
342
core/protorpc/protoc-gen-stdrpc/_main-ignore.go
Normal file
@ -0,0 +1,342 @@
|
||||
// Copyright 2018 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"text/template"
|
||||
|
||||
plugin "github.com/chai2010/protorpc/protoc-gen-plugin"
|
||||
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plugin.Main()
|
||||
}
|
||||
|
||||
func init() {
|
||||
plugin.RegisterCodeGenerator(new(protorpcPlugin))
|
||||
}
|
||||
|
||||
type protorpcPlugin struct{}
|
||||
|
||||
func (p *protorpcPlugin) Name() string { return "stdrpc-go" }
|
||||
func (p *protorpcPlugin) FileNameExt() string { return ".pb.stdrpc.go" }
|
||||
|
||||
func (p *protorpcPlugin) HeaderCode(g *generator.Generator, file *generator.FileDescriptor) string {
|
||||
const tmpl = `
|
||||
{{- $G := .G -}}
|
||||
{{- $File := .File -}}
|
||||
|
||||
// Code generated by protoc-gen-stdrpc. DO NOT EDIT.
|
||||
//
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-plugin
|
||||
// plugin: https://github.com/chai2010/protorpc/tree/master/protoc-gen-stdrpc
|
||||
//
|
||||
// source: {{$File.GetName}}
|
||||
|
||||
package {{$File.PackageName}}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = fmt.Sprint
|
||||
_ = io.Reader(nil)
|
||||
_ = log.Print
|
||||
_ = net.Addr(nil)
|
||||
_ = rpc.Call{}
|
||||
_ = time.Second
|
||||
|
||||
_ = proto.String
|
||||
)
|
||||
`
|
||||
var buf bytes.Buffer
|
||||
t := template.Must(template.New("").Parse(tmpl))
|
||||
err := t.Execute(&buf,
|
||||
struct {
|
||||
G *generator.Generator
|
||||
File *generator.FileDescriptor
|
||||
}{
|
||||
G: g,
|
||||
File: file,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) ServiceCode(g *generator.Generator, file *generator.FileDescriptor, svc *descriptor.ServiceDescriptorProto) string {
|
||||
var code string
|
||||
code += p.genServiceInterface(g, file, svc)
|
||||
code += p.genServiceServer(g, file, svc)
|
||||
code += p.genServiceClient(g, file, svc)
|
||||
return code
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) MessageCode(g *generator.Generator, file *generator.FileDescriptor, msg *descriptor.DescriptorProto) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) genServiceInterface(
|
||||
g *generator.Generator,
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) string {
|
||||
const serviceInterfaceTmpl = `
|
||||
type {{.ServiceName}} interface {
|
||||
{{.CallMethodList}}
|
||||
}
|
||||
`
|
||||
const callMethodTmpl = `
|
||||
{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}) error`
|
||||
|
||||
// gen call method list
|
||||
var callMethodList string
|
||||
for _, m := range svc.Method {
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(callMethodTmpl))
|
||||
t.Execute(out, &struct{ ServiceName, MethodName, ArgsType, ReplyType string }{
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
MethodName: generator.CamelCase(m.GetName()),
|
||||
ArgsType: g.TypeName(g.ObjectNamed(m.GetInputType())),
|
||||
ReplyType: g.TypeName(g.ObjectNamed(m.GetOutputType())),
|
||||
})
|
||||
callMethodList += out.String()
|
||||
|
||||
g.RecordTypeUse(m.GetInputType())
|
||||
g.RecordTypeUse(m.GetOutputType())
|
||||
}
|
||||
|
||||
// gen all interface code
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(serviceInterfaceTmpl))
|
||||
t.Execute(out, &struct{ ServiceName, CallMethodList string }{
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
CallMethodList: callMethodList,
|
||||
})
|
||||
|
||||
return out.String()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) genServiceServer(
|
||||
g *generator.Generator,
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) string {
|
||||
const serviceHelperFunTmpl = `
|
||||
// Accept{{.ServiceName}}Client accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func Accept{{.ServiceName}}Client(lis net.Listener, x {{.ServiceName}}) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// Register{{.ServiceName}} publish the given {{.ServiceName}} implementation on the server.
|
||||
func Register{{.ServiceName}}(srv *rpc.Server, x {{.ServiceName}}) error {
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// New{{.ServiceName}}Server returns a new {{.ServiceName}} Server.
|
||||
func New{{.ServiceName}}Server(x {{.ServiceName}}) *rpc.Server {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// ListenAndServe{{.ServiceName}} listen announces on the local network address laddr
|
||||
// and serves the given {{.ServiceName}} implementation.
|
||||
func ListenAndServe{{.ServiceName}}(network, addr string, x {{.ServiceName}}) error {
|
||||
lis, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// Serve{{.ServiceName}} serves the given {{.ServiceName}} implementation.
|
||||
func Serve{{.ServiceName}}(conn io.ReadWriteCloser, x {{.ServiceName}}) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv.ServeConn(conn)
|
||||
}
|
||||
`
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(serviceHelperFunTmpl))
|
||||
t.Execute(out, &struct{ PackageName, ServiceName, ServiceRegisterName string }{
|
||||
PackageName: file.GetPackage(),
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
ServiceRegisterName: p.makeServiceRegisterName(
|
||||
file, file.GetPackage(), generator.CamelCase(svc.GetName()),
|
||||
),
|
||||
})
|
||||
|
||||
return out.String()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) genServiceClient(
|
||||
g *generator.Generator,
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) string {
|
||||
const clientHelperFuncTmpl = `
|
||||
type {{.ServiceName}}Client struct {
|
||||
*rpc.Client
|
||||
}
|
||||
|
||||
// New{{.ServiceName}}Client returns a {{.ServiceName}} stub to handle
|
||||
// requests to the set of {{.ServiceName}} at the other end of the connection.
|
||||
func New{{.ServiceName}}Client(conn io.ReadWriteCloser) (*{{.ServiceName}}Client) {
|
||||
c := rpc.NewClient(conn)
|
||||
return &{{.ServiceName}}Client{c}
|
||||
}
|
||||
|
||||
{{.MethodList}}
|
||||
|
||||
// Dial{{.ServiceName}} connects to an {{.ServiceName}} at the specified network address.
|
||||
func Dial{{.ServiceName}}(network, addr string) (*{{.ServiceName}}Client, error) {
|
||||
c, err := rpc.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &{{.ServiceName}}Client{c}, nil
|
||||
}
|
||||
|
||||
// Dial{{.ServiceName}}Timeout connects to an {{.ServiceName}} at the specified network address.
|
||||
func Dial{{.ServiceName}}Timeout(network, addr string, timeout time.Duration) (*{{.ServiceName}}Client, error) {
|
||||
conn, err := net.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &{{.ServiceName}}Client{rpc.NewClient(conn)}, nil
|
||||
}
|
||||
`
|
||||
const clientMethodTmpl = `
|
||||
func (c *{{.ServiceName}}Client) {{.MethodName}}(in *{{.ArgsType}}) (out *{{.ReplyType}}, err error) {
|
||||
if in == nil {
|
||||
in = new({{.ArgsType}})
|
||||
}
|
||||
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out = new({{.ReplyType}})
|
||||
if err = c.Call("{{.ServiceRegisterName}}.{{.MethodName}}", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *{{.ServiceName}}Client) Async{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new({{.ArgsType}})
|
||||
}
|
||||
return c.Go(
|
||||
"{{.ServiceRegisterName}}.{{.MethodName}}",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
`
|
||||
|
||||
// gen client method list
|
||||
var methodList string
|
||||
for _, m := range svc.Method {
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(clientMethodTmpl))
|
||||
t.Execute(out, &struct{ ServiceName, ServiceRegisterName, MethodName, ArgsType, ReplyType string }{
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
ServiceRegisterName: p.makeServiceRegisterName(
|
||||
file, file.GetPackage(), generator.CamelCase(svc.GetName()),
|
||||
),
|
||||
MethodName: generator.CamelCase(m.GetName()),
|
||||
ArgsType: g.TypeName(g.ObjectNamed(m.GetInputType())),
|
||||
ReplyType: g.TypeName(g.ObjectNamed(m.GetOutputType())),
|
||||
})
|
||||
methodList += out.String()
|
||||
}
|
||||
|
||||
// gen all client code
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(clientHelperFuncTmpl))
|
||||
t.Execute(out, &struct{ PackageName, ServiceName, MethodList string }{
|
||||
PackageName: file.GetPackage(),
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
MethodList: methodList,
|
||||
})
|
||||
|
||||
return out.String()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *protorpcPlugin) makeServiceRegisterName(
|
||||
file *generator.FileDescriptor,
|
||||
packageName, serviceName string,
|
||||
) string {
|
||||
// return packageName + "." + serviceName
|
||||
return serviceName
|
||||
}
|
||||
103
core/protorpc/protoc-gen-stdrpc/main.go
Normal file
103
core/protorpc/protoc-gen-stdrpc/main.go
Normal file
@ -0,0 +1,103 @@
|
||||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate
|
||||
// Go code. Run it by building this program and putting it in your path with
|
||||
// the name
|
||||
// protoc-gen-go
|
||||
// That word 'go' at the end becomes part of the option string set for the
|
||||
// protocol compiler, so once the protocol compiler (protoc) is installed
|
||||
// you can run
|
||||
// protoc --go_out=output_directory input_directory/file.proto
|
||||
// to generate Go bindings for the protocol defined by file.proto.
|
||||
// With that input, the output will be written to
|
||||
// output_directory/file.pb.go
|
||||
//
|
||||
// The generated code is documented in the package comment for
|
||||
// the library.
|
||||
//
|
||||
// See the README and documentation for protocol buffers to learn more:
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Begin by allocating a generator. The request and response structures are stored there
|
||||
// so we can do error handling easily - the response structure contains the field to
|
||||
// report failure.
|
||||
g := generator.New()
|
||||
|
||||
data, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
g.Error(err, "reading input")
|
||||
}
|
||||
|
||||
if err := proto.Unmarshal(data, g.Request); err != nil {
|
||||
g.Error(err, "parsing input proto")
|
||||
}
|
||||
|
||||
if len(g.Request.FileToGenerate) == 0 {
|
||||
g.Fail("no files to generate")
|
||||
}
|
||||
|
||||
parameter := g.Request.GetParameter()
|
||||
if !strings.Contains(parameter, "plugins=") {
|
||||
parameter += ",plugins=" + netrpcPluginName
|
||||
}
|
||||
g.CommandLineParameters(parameter)
|
||||
|
||||
// Create a wrapped version of the Descriptors and EnumDescriptors that
|
||||
// point to the file that defines them.
|
||||
g.WrapTypes()
|
||||
|
||||
g.SetPackageNames()
|
||||
g.BuildTypeNameMap()
|
||||
|
||||
g.GenerateAllFiles()
|
||||
|
||||
// Send back the results.
|
||||
data, err = proto.Marshal(g.Response)
|
||||
if err != nil {
|
||||
g.Error(err, "failed to marshal output proto")
|
||||
}
|
||||
_, err = os.Stdout.Write(data)
|
||||
if err != nil {
|
||||
g.Error(err, "failed to write output proto")
|
||||
}
|
||||
}
|
||||
350
core/protorpc/protoc-gen-stdrpc/netrpc.go
Normal file
350
core/protorpc/protoc-gen-stdrpc/netrpc.go
Normal file
@ -0,0 +1,350 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
|
||||
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
)
|
||||
|
||||
const netrpcPluginName = "netrpc"
|
||||
|
||||
// netrpcPlugin produce the Service interface.
|
||||
type netrpcPlugin struct {
|
||||
*generator.Generator
|
||||
}
|
||||
|
||||
// Name returns the name of the plugin.
|
||||
func (p *netrpcPlugin) Name() string { return netrpcPluginName }
|
||||
|
||||
// Init is called once after data structures are built but before
|
||||
// code generation begins.
|
||||
func (p *netrpcPlugin) Init(g *generator.Generator) {
|
||||
p.Generator = g
|
||||
}
|
||||
|
||||
// Generate produces the code generated by the plugin for this file.
|
||||
func (p *netrpcPlugin) GenerateImports(file *generator.FileDescriptor) {
|
||||
if len(file.Service) > 0 {
|
||||
p.P(`import "bufio"`)
|
||||
p.P(`import "crypto/tls"`)
|
||||
p.P(`import "errors"`)
|
||||
p.P(`import "io"`)
|
||||
p.P(`import "log"`)
|
||||
p.P(`import "net"`)
|
||||
p.P(`import "net/http"`)
|
||||
p.P(`import "net/rpc"`)
|
||||
p.P(`import "time"`)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate generates the Service interface.
|
||||
// rpc service can't handle other proto message!!!
|
||||
func (p *netrpcPlugin) Generate(file *generator.FileDescriptor) {
|
||||
for _, svc := range file.Service {
|
||||
p.genServiceInterface(file, svc)
|
||||
p.genServiceServer(file, svc)
|
||||
p.genServiceClient(file, svc)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *netrpcPlugin) genServiceInterface(
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) {
|
||||
const serviceInterfaceTmpl = `
|
||||
type {{.ServiceName}} interface {
|
||||
{{.CallMethodList}}
|
||||
}
|
||||
`
|
||||
const callMethodTmpl = `
|
||||
{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}) error`
|
||||
|
||||
// gen call method list
|
||||
var callMethodList string
|
||||
for _, m := range svc.Method {
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(callMethodTmpl))
|
||||
t.Execute(out, &struct{ ServiceName, MethodName, ArgsType, ReplyType string }{
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
MethodName: generator.CamelCase(m.GetName()),
|
||||
ArgsType: p.TypeName(p.ObjectNamed(m.GetInputType())),
|
||||
ReplyType: p.TypeName(p.ObjectNamed(m.GetOutputType())),
|
||||
})
|
||||
callMethodList += out.String()
|
||||
|
||||
p.RecordTypeUse(m.GetInputType())
|
||||
p.RecordTypeUse(m.GetOutputType())
|
||||
}
|
||||
|
||||
// gen all interface code
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(serviceInterfaceTmpl))
|
||||
t.Execute(out, &struct{ ServiceName, CallMethodList string }{
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
CallMethodList: callMethodList,
|
||||
})
|
||||
p.P(out.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *netrpcPlugin) genServiceServer(
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) {
|
||||
const serviceHelperFunTmpl = `
|
||||
// Accept{{.ServiceName}}Client accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
// invokes it in a go statement.
|
||||
func Accept{{.ServiceName}}Client(lis net.Listener, x {{.ServiceName}}) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// Register{{.ServiceName}} publish the given {{.ServiceName}} implementation on the server.
|
||||
func Register{{.ServiceName}}(srv *rpc.Server, x {{.ServiceName}}) error {
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// New{{.ServiceName}}Server returns a new {{.ServiceName}} Server.
|
||||
func New{{.ServiceName}}Server(x {{.ServiceName}}) *rpc.Server {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// ListenAndServe{{.ServiceName}} listen announces on the local network address laddr
|
||||
// and serves the given {{.ServiceName}} implementation.
|
||||
func ListenAndServe{{.ServiceName}}(network, addr string, x {{.ServiceName}}) error {
|
||||
lis, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := lis.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("lis.Accept(): %v\n", err)
|
||||
}
|
||||
go srv.ServeConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// Serve{{.ServiceName}} serves the given {{.ServiceName}} implementation.
|
||||
func Serve{{.ServiceName}}(conn io.ReadWriteCloser, x {{.ServiceName}}) {
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("{{.ServiceRegisterName}}", x); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv.ServeConn(conn)
|
||||
}
|
||||
`
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(serviceHelperFunTmpl))
|
||||
t.Execute(out, &struct{ PackageName, ServiceName, ServiceRegisterName string }{
|
||||
PackageName: file.GetPackage(),
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
ServiceRegisterName: p.makeServiceRegisterName(
|
||||
file, file.GetPackage(), generator.CamelCase(svc.GetName()),
|
||||
),
|
||||
})
|
||||
p.P(out.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *netrpcPlugin) genServiceClient(
|
||||
file *generator.FileDescriptor,
|
||||
svc *descriptor.ServiceDescriptorProto,
|
||||
) {
|
||||
const clientHelperFuncTmpl = `
|
||||
type {{.ServiceName}}Client struct {
|
||||
*rpc.Client
|
||||
}
|
||||
|
||||
// New{{.ServiceName}}Client returns a {{.ServiceName}} stub to handle
|
||||
// requests to the set of {{.ServiceName}} at the other end of the connection.
|
||||
func New{{.ServiceName}}Client(conn io.ReadWriteCloser) (*{{.ServiceName}}Client) {
|
||||
c := rpc.NewClient(conn)
|
||||
return &{{.ServiceName}}Client{c}
|
||||
}
|
||||
|
||||
{{.MethodList}}
|
||||
|
||||
// Dial{{.ServiceName}} connects to an {{.ServiceName}} at the specified network address.
|
||||
func Dial{{.ServiceName}}(network, addr string) (*{{.ServiceName}}Client, error) {
|
||||
c, err := rpc.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &{{.ServiceName}}Client{c}, nil
|
||||
}
|
||||
|
||||
// Dial{{.ServiceName}}Timeout connects to an {{.ServiceName}} at the specified network address.
|
||||
func Dial{{.ServiceName}}Timeout(network, addr string, timeout time.Duration) (*{{.ServiceName}}Client, error) {
|
||||
conn, err := net.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &{{.ServiceName}}Client{rpc.NewClient(conn)}, nil
|
||||
}
|
||||
|
||||
// Dial{{.ServiceName}}HTTP connects to an HTTP RPC server at the specified network address
|
||||
// listening on the default HTTP RPC path.
|
||||
func Dial{{.ServiceName}}HTTP(network, address string) (*{{.ServiceName}}Client, error) {
|
||||
return Dial{{.ServiceName}}HTTPPath(network, address, rpc.DefaultRPCPath)
|
||||
}
|
||||
|
||||
// Dial{{.ServiceName}}HTTPPath connects to an HTTP RPC server
|
||||
// at the specified network address and path.
|
||||
func Dial{{.ServiceName}}HTTPPath(network, address, path string) (*{{.ServiceName}}Client, error) {
|
||||
conn, err := net.Dial(network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dial{{.ServiceName}}Path(network, address, path, conn)
|
||||
}
|
||||
|
||||
// Dial{{.ServiceName}}HTTPS connects to an HTTPS RPC server at the specified network address
|
||||
// listening on the default HTTP RPC path.
|
||||
func Dial{{.ServiceName}}HTTPS(network, address string, tlsConfig *tls.Config) (*{{.ServiceName}}Client, error) {
|
||||
return Dial{{.ServiceName}}HTTPSPath(network, address, rpc.DefaultRPCPath, tlsConfig)
|
||||
}
|
||||
|
||||
// Dial{{.ServiceName}}HTTPSPath connects to an HTTPS RPC server
|
||||
// at the specified network address and path.
|
||||
func Dial{{.ServiceName}}HTTPSPath(network, address, path string, tlsConfig *tls.Config) (*{{.ServiceName}}Client, error) {
|
||||
conn, err := tls.Dial(network, address, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dial{{.ServiceName}}Path(network, address, path, conn)
|
||||
}
|
||||
|
||||
func dial{{.ServiceName}}Path(network, address, path string, conn net.Conn) (*{{.ServiceName}}Client, error) {
|
||||
const net_rpc_connected = "200 Connected to Go RPC"
|
||||
|
||||
io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n")
|
||||
|
||||
// Require successful HTTP response
|
||||
// before switching to RPC protocol.
|
||||
resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
|
||||
if err == nil && resp.Status == net_rpc_connected {
|
||||
return &{{.ServiceName}}Client{rpc.NewClient(conn)}, nil
|
||||
}
|
||||
if err == nil {
|
||||
err = errors.New("unexpected HTTP response: " + resp.Status)
|
||||
}
|
||||
conn.Close()
|
||||
return nil, &net.OpError{
|
||||
Op: "dial-http",
|
||||
Net: network + " " + address,
|
||||
Addr: nil,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
`
|
||||
const clientMethodTmpl = `
|
||||
func (c *{{.ServiceName}}Client) {{.MethodName}}(in *{{.ArgsType}}) (out *{{.ReplyType}}, err error) {
|
||||
if in == nil {
|
||||
in = new({{.ArgsType}})
|
||||
}
|
||||
type Validator interface {
|
||||
Validate() error
|
||||
}
|
||||
if x, ok := proto.Message(in).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out = new({{.ReplyType}})
|
||||
if err = c.Call("{{.ServiceRegisterName}}.{{.MethodName}}", in, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if x, ok := proto.Message(out).(Validator); ok {
|
||||
if err := x.Validate(); err != nil {
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *{{.ServiceName}}Client) Async{{.MethodName}}(in *{{.ArgsType}}, out *{{.ReplyType}}, done chan *rpc.Call) *rpc.Call {
|
||||
if in == nil {
|
||||
in = new({{.ArgsType}})
|
||||
}
|
||||
return c.Go(
|
||||
"{{.ServiceRegisterName}}.{{.MethodName}}",
|
||||
in, out,
|
||||
done,
|
||||
)
|
||||
}
|
||||
`
|
||||
|
||||
// gen client method list
|
||||
var methodList string
|
||||
for _, m := range svc.Method {
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(clientMethodTmpl))
|
||||
t.Execute(out, &struct{ ServiceName, ServiceRegisterName, MethodName, ArgsType, ReplyType string }{
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
ServiceRegisterName: p.makeServiceRegisterName(
|
||||
file, file.GetPackage(), generator.CamelCase(svc.GetName()),
|
||||
),
|
||||
MethodName: generator.CamelCase(m.GetName()),
|
||||
ArgsType: p.TypeName(p.ObjectNamed(m.GetInputType())),
|
||||
ReplyType: p.TypeName(p.ObjectNamed(m.GetOutputType())),
|
||||
})
|
||||
methodList += out.String()
|
||||
}
|
||||
|
||||
// gen all client code
|
||||
{
|
||||
out := bytes.NewBuffer([]byte{})
|
||||
t := template.Must(template.New("").Parse(clientHelperFuncTmpl))
|
||||
t.Execute(out, &struct{ PackageName, ServiceName, MethodList string }{
|
||||
PackageName: file.GetPackage(),
|
||||
ServiceName: generator.CamelCase(svc.GetName()),
|
||||
MethodList: methodList,
|
||||
})
|
||||
p.P(out.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *netrpcPlugin) makeServiceRegisterName(
|
||||
file *generator.FileDescriptor,
|
||||
packageName, serviceName string,
|
||||
) string {
|
||||
return packageName + "." + serviceName
|
||||
}
|
||||
|
||||
func init() {
|
||||
generator.RegisterPlugin(new(netrpcPlugin))
|
||||
}
|
||||
256
core/protorpc/rpc_test.go
Normal file
256
core/protorpc/rpc_test.go
Normal file
@ -0,0 +1,256 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protorpc_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/chai2010/protorpc"
|
||||
msg "github.com/chai2010/protorpc/examples/message.pb"
|
||||
)
|
||||
|
||||
type Arith int
|
||||
|
||||
func (t *Arith) Add(args *msg.ArithRequest, reply *msg.ArithResponse) error {
|
||||
reply.C = args.A + args.B
|
||||
log.Printf("Arith.Add(%v, %v): %v", args.A, args.B, reply.C)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Arith) Mul(args *msg.ArithRequest, reply *msg.ArithResponse) error {
|
||||
reply.C = args.A * args.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Arith) Div(args *msg.ArithRequest, reply *msg.ArithResponse) error {
|
||||
if args.B == 0 {
|
||||
return errors.New("divide by zero")
|
||||
}
|
||||
reply.C = args.A / args.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Arith) Error(args *msg.ArithRequest, reply *msg.ArithResponse) error {
|
||||
return errors.New("ArithError")
|
||||
}
|
||||
|
||||
type Echo int
|
||||
|
||||
func (t *Echo) Echo(args *msg.EchoRequest, reply *msg.EchoResponse) error {
|
||||
reply.Msg = args.Msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestInternalMessagePkg(t *testing.T) {
|
||||
err := listenAndServeArithAndEchoService("tcp", "127.0.0.1:1414")
|
||||
if err != nil {
|
||||
log.Fatalf("listenAndServeArithAndEchoService: %v", err)
|
||||
}
|
||||
|
||||
conn, err := net.Dial("tcp", "127.0.0.1:1414")
|
||||
if err != nil {
|
||||
t.Fatalf(`net.Dial("tcp", "127.0.0.1:1414"): %v`, err)
|
||||
}
|
||||
client := rpc.NewClientWithCodec(protorpc.NewClientCodec(conn))
|
||||
defer client.Close()
|
||||
|
||||
testArithClient(t, client)
|
||||
testEchoClient(t, client)
|
||||
|
||||
testArithClientAsync(t, client)
|
||||
testEchoClientAsync(t, client)
|
||||
}
|
||||
|
||||
func listenAndServeArithAndEchoService(network, addr string) error {
|
||||
clients, err := net.Listen(network, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv := rpc.NewServer()
|
||||
if err := srv.RegisterName("ArithService", new(Arith)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := srv.RegisterName("EchoService", new(Echo)); err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
conn, err := clients.Accept()
|
||||
if err != nil {
|
||||
log.Printf("clients.Accept(): %v\n", err)
|
||||
continue
|
||||
}
|
||||
go srv.ServeCodec(protorpc.NewServerCodec(conn))
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func testArithClient(t *testing.T, client *rpc.Client) {
|
||||
var args msg.ArithRequest
|
||||
var reply msg.ArithResponse
|
||||
var err error
|
||||
|
||||
// Add
|
||||
args.A = 1
|
||||
args.B = 2
|
||||
if err = client.Call("ArithService.Add", &args, &reply); err != nil {
|
||||
t.Fatalf(`arith.Add: %v`, err)
|
||||
}
|
||||
if reply.C != 3 {
|
||||
t.Fatalf(`arith.Add: expected = %d, got = %d`, 3, reply.C)
|
||||
}
|
||||
|
||||
// Mul
|
||||
args.A = 2
|
||||
args.B = 3
|
||||
if err = client.Call("ArithService.Mul", &args, &reply); err != nil {
|
||||
t.Fatalf(`arith.Mul: %v`, err)
|
||||
}
|
||||
if reply.C != 6 {
|
||||
t.Fatalf(`arith.Mul: expected = %d, got = %d`, 6, reply.C)
|
||||
}
|
||||
|
||||
// Div
|
||||
args.A = 13
|
||||
args.B = 5
|
||||
if err = client.Call("ArithService.Div", &args, &reply); err != nil {
|
||||
t.Fatalf(`arith.Div: %v`, err)
|
||||
}
|
||||
if reply.C != 2 {
|
||||
t.Fatalf(`arith.Div: expected = %d, got = %d`, 2, reply.C)
|
||||
}
|
||||
|
||||
// Div zero
|
||||
args.A = 1
|
||||
args.B = 0
|
||||
if err = client.Call("ArithService.Div", &args, &reply); err.Error() != "divide by zero" {
|
||||
t.Fatalf(`arith.Error: expected = "%s", got = "%s"`, "divide by zero", err.Error())
|
||||
}
|
||||
|
||||
// Error
|
||||
args.A = 1
|
||||
args.B = 2
|
||||
if err = client.Call("ArithService.Error", &args, &reply); err.Error() != "ArithError" {
|
||||
t.Fatalf(`arith.Error: expected = "%s", got = "%s"`, "ArithError", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func testArithClientAsync(t *testing.T, client *rpc.Client) {
|
||||
done := make(chan *rpc.Call, 16)
|
||||
callInfoList := []struct {
|
||||
method string
|
||||
args *msg.ArithRequest
|
||||
reply *msg.ArithResponse
|
||||
err error
|
||||
}{
|
||||
{
|
||||
"ArithService.Add",
|
||||
&msg.ArithRequest{A: 1, B: 2},
|
||||
&msg.ArithResponse{C: 3},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"ArithService.Mul",
|
||||
&msg.ArithRequest{A: 2, B: 3},
|
||||
&msg.ArithResponse{C: 6},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"ArithService.Div",
|
||||
&msg.ArithRequest{A: 13, B: 5},
|
||||
&msg.ArithResponse{C: 2},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"ArithService.Div",
|
||||
&msg.ArithRequest{A: 1, B: 0},
|
||||
&msg.ArithResponse{},
|
||||
errors.New("divide by zero"),
|
||||
},
|
||||
{
|
||||
"ArithService.Error",
|
||||
&msg.ArithRequest{A: 1, B: 2},
|
||||
&msg.ArithResponse{},
|
||||
errors.New("ArithError"),
|
||||
},
|
||||
}
|
||||
|
||||
// GoCall list
|
||||
calls := make([]*rpc.Call, len(callInfoList))
|
||||
for i := 0; i < len(calls); i++ {
|
||||
calls[i] = client.Go(callInfoList[i].method,
|
||||
callInfoList[i].args, callInfoList[i].reply,
|
||||
done,
|
||||
)
|
||||
}
|
||||
for i := 0; i < len(calls); i++ {
|
||||
<-calls[i].Done
|
||||
}
|
||||
|
||||
// check result
|
||||
for i := 0; i < len(calls); i++ {
|
||||
if callInfoList[i].err != nil {
|
||||
if calls[i].Error.Error() != callInfoList[i].err.Error() {
|
||||
t.Fatalf(`%s: expected %v, Got = %v`,
|
||||
callInfoList[i].method,
|
||||
callInfoList[i].err,
|
||||
calls[i].Error,
|
||||
)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
got := calls[i].Reply.(*msg.ArithResponse).C
|
||||
expected := callInfoList[i].reply.C
|
||||
if got != expected {
|
||||
t.Fatalf(`%v: expected %v, Got = %v`,
|
||||
callInfoList[i].method, got, expected,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testEchoClient(t *testing.T, client *rpc.Client) {
|
||||
var args msg.EchoRequest
|
||||
var reply msg.EchoResponse
|
||||
var err error
|
||||
|
||||
// EchoService.Echo
|
||||
args.Msg = "Hello, Protobuf-RPC"
|
||||
if err = client.Call("EchoService.Echo", &args, &reply); err != nil {
|
||||
t.Fatalf(`EchoService.Echo: %v`, err)
|
||||
}
|
||||
if reply.Msg != args.Msg {
|
||||
t.Fatalf(`EchoService.Echo: expected = "%s", got = "%s"`, args.Msg, reply.Msg)
|
||||
}
|
||||
}
|
||||
|
||||
func testEchoClientAsync(t *testing.T, client *rpc.Client) {
|
||||
// EchoService.Echo
|
||||
args := &msg.EchoRequest{Msg: "Hello, Protobuf-RPC"}
|
||||
reply := &msg.EchoResponse{}
|
||||
echoCall := client.Go("EchoService.Echo", args, reply, nil)
|
||||
|
||||
// sleep 1s
|
||||
time.Sleep(time.Second)
|
||||
|
||||
// EchoService.Echo reply
|
||||
echoCall = <-echoCall.Done
|
||||
if echoCall.Error != nil {
|
||||
t.Fatalf(`EchoService.Echo: %v`, echoCall.Error)
|
||||
}
|
||||
if echoCall.Reply.(*msg.EchoResponse).Msg != args.Msg {
|
||||
t.Fatalf(`EchoService.Echo: expected = "%s", got = "%s"`,
|
||||
args.Msg,
|
||||
echoCall.Reply.(*msg.EchoResponse).Msg,
|
||||
)
|
||||
}
|
||||
}
|
||||
134
core/protorpc/server.go
Normal file
134
core/protorpc/server.go
Normal file
@ -0,0 +1,134 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protorpc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/rpc"
|
||||
"sync"
|
||||
|
||||
wire "github.com/chai2010/protorpc/wire.pb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
type serverCodec struct {
|
||||
r io.Reader
|
||||
w io.Writer
|
||||
c io.Closer
|
||||
|
||||
// temporary work space
|
||||
reqHeader wire.RequestHeader
|
||||
|
||||
// Package rpc expects uint64 request IDs.
|
||||
// We assign uint64 sequence numbers to incoming requests
|
||||
// but save the original request ID in the pending map.
|
||||
// When rpc responds, we use the sequence number in
|
||||
// the response to find the original request ID.
|
||||
mutex sync.Mutex // protects seq, pending
|
||||
seq uint64
|
||||
pending map[uint64]uint64
|
||||
}
|
||||
|
||||
// NewServerCodec returns a serverCodec that communicates with the ClientCodec
|
||||
// on the other end of the given conn.
|
||||
func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {
|
||||
return &serverCodec{
|
||||
r: conn,
|
||||
w: conn,
|
||||
c: conn,
|
||||
pending: make(map[uint64]uint64),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error {
|
||||
header := wire.RequestHeader{}
|
||||
err := readRequestHeader(c.r, &header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.mutex.Lock()
|
||||
c.seq++
|
||||
c.pending[c.seq] = *header.Id
|
||||
r.ServiceMethod = *header.Method
|
||||
r.Seq = c.seq
|
||||
c.mutex.Unlock()
|
||||
|
||||
c.reqHeader = header
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *serverCodec) ReadRequestBody(x interface{}) error {
|
||||
if x == nil {
|
||||
return nil
|
||||
}
|
||||
request, ok := x.(proto.Message)
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
"protorpc.ServerCodec.ReadRequestBody: %T does not implement proto.Message",
|
||||
x,
|
||||
)
|
||||
}
|
||||
|
||||
err := readRequestBody(c.r, &c.reqHeader, request)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.reqHeader = wire.RequestHeader{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A value sent as a placeholder for the server's response value when the server
|
||||
// receives an invalid request. It is never decoded by the client since the Response
|
||||
// contains an error when it is used.
|
||||
var invalidRequest = struct{}{}
|
||||
|
||||
func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error {
|
||||
var response proto.Message
|
||||
if x != nil {
|
||||
var ok bool
|
||||
if response, ok = x.(proto.Message); !ok {
|
||||
if _, ok = x.(struct{}); !ok {
|
||||
c.mutex.Lock()
|
||||
delete(c.pending, r.Seq)
|
||||
c.mutex.Unlock()
|
||||
return fmt.Errorf(
|
||||
"protorpc.ServerCodec.WriteResponse: %T does not implement proto.Message",
|
||||
x,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.mutex.Lock()
|
||||
id, ok := c.pending[r.Seq]
|
||||
if !ok {
|
||||
c.mutex.Unlock()
|
||||
return errors.New("protorpc: invalid sequence number in response")
|
||||
}
|
||||
delete(c.pending, r.Seq)
|
||||
c.mutex.Unlock()
|
||||
|
||||
err := writeResponse(c.w, id, r.Error, response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *serverCodec) Close() error {
|
||||
return s.c.Close()
|
||||
}
|
||||
|
||||
// ServeConn runs the Protobuf-RPC server on a single connection.
|
||||
// ServeConn blocks, serving the connection until the client hangs up.
|
||||
// The caller typically invokes ServeConn in a go statement.
|
||||
func ServeConn(conn io.ReadWriteCloser) {
|
||||
rpc.ServeCodec(NewServerCodec(conn))
|
||||
}
|
||||
173
core/protorpc/wire.go
Normal file
173
core/protorpc/wire.go
Normal file
@ -0,0 +1,173 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protorpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
wire "github.com/chai2010/protorpc/wire.pb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
func To[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
func maxUint32(a, b uint32) uint32 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func writeRequest(w io.Writer, id uint64, method string, request proto.Message) error {
|
||||
// marshal request
|
||||
pbRequest := []byte{}
|
||||
if request != nil {
|
||||
var err error
|
||||
pbRequest, err = proto.Marshal(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// generate header
|
||||
header := &wire.RequestHeader{
|
||||
Id: To(id),
|
||||
Method: To(method),
|
||||
RawRequestLen: To(uint32(len(pbRequest))),
|
||||
}
|
||||
|
||||
// check header size
|
||||
pbHeader, err := proto.Marshal(header)
|
||||
if err != err {
|
||||
return err
|
||||
}
|
||||
if len(pbHeader) > int(wire.Const_MAX_REQUEST_HEADER_LEN) {
|
||||
return fmt.Errorf("protorpc.writeRequest: header larger than max_header_len: %d.", len(pbHeader))
|
||||
}
|
||||
|
||||
// send header (more)
|
||||
if err := sendFrame(w, pbHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// send body (end)
|
||||
if err := sendFrame(w, pbRequest); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readRequestHeader(r io.Reader, header *wire.RequestHeader) (err error) {
|
||||
// recv header (more)
|
||||
pbHeader, err := recvFrame(r, int(wire.Const_MAX_REQUEST_HEADER_LEN))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Marshal Header
|
||||
err = proto.Unmarshal(pbHeader, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readRequestBody(r io.Reader, header *wire.RequestHeader, request proto.Message) error {
|
||||
// recv body (end)
|
||||
pbRequest, err := recvFrame(r, int(*header.RawRequestLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Unmarshal to proto message
|
||||
if request != nil {
|
||||
err = proto.Unmarshal(pbRequest, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeResponse(w io.Writer, id uint64, serr string, response proto.Message) (err error) {
|
||||
// clean response if error
|
||||
if serr != "" {
|
||||
response = nil
|
||||
}
|
||||
|
||||
// marshal response
|
||||
pbResponse := []byte{}
|
||||
if response != nil {
|
||||
pbResponse, err = proto.Marshal(response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// generate header
|
||||
header := &wire.ResponseHeader{
|
||||
Id: To(id),
|
||||
Error: To(serr),
|
||||
RawResponseLen: To(uint32(len(pbResponse))),
|
||||
}
|
||||
|
||||
// check header size
|
||||
pbHeader, err := proto.Marshal(header)
|
||||
if err != err {
|
||||
return
|
||||
}
|
||||
|
||||
// send header (more)
|
||||
if err = sendFrame(w, pbHeader); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// send body (end)
|
||||
if err = sendFrame(w, pbResponse); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readResponseHeader(r io.Reader, header *wire.ResponseHeader) error {
|
||||
// recv header (more)
|
||||
pbHeader, err := recvFrame(r, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Marshal Header
|
||||
err = proto.Unmarshal(pbHeader, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readResponseBody(r io.Reader, header *wire.ResponseHeader, response proto.Message) error {
|
||||
// recv body (end)
|
||||
pbResponse, err := recvFrame(r, int(*header.RawResponseLen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Unmarshal to proto message
|
||||
if response != nil {
|
||||
err = proto.Unmarshal(pbResponse, response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
7
core/protorpc/wire.pb/proto.go
Normal file
7
core/protorpc/wire.pb/proto.go
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate protoc --go_out=. wire.proto
|
||||
|
||||
package protorpc_wire
|
||||
296
core/protorpc/wire.pb/wire.pb.go
Normal file
296
core/protorpc/wire.pb/wire.pb.go
Normal file
@ -0,0 +1,296 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v6.31.0
|
||||
// source: wire.proto
|
||||
|
||||
//
|
||||
// protorpc wire format wrapper
|
||||
//
|
||||
// 0. Frame Format
|
||||
// len : uvarint64
|
||||
// data: byte[len]
|
||||
//
|
||||
// 1. Client Send Request
|
||||
// Send RequestHeader: sendFrame(zsock, hdr, len(hdr))
|
||||
// Send Request: sendFrame(zsock, body, hdr.snappy_compressed_request_len)
|
||||
//
|
||||
// 2. Server Recv Request
|
||||
// Recv RequestHeader: recvFrame(zsock, hdr, max_hdr_len, 0)
|
||||
// Recv Request: recvFrame(zsock, body, hdr.snappy_compressed_request_len, 0)
|
||||
//
|
||||
// 3. Server Send Response
|
||||
// Send ResponseHeader: sendFrame(zsock, hdr, len(hdr))
|
||||
// Send Response: sendFrame(zsock, body, hdr.snappy_compressed_response_len)
|
||||
//
|
||||
// 4. Client Recv Response
|
||||
// Recv ResponseHeader: recvFrame(zsock, hdr, max_hdr_len, 0)
|
||||
// Recv Response: recvFrame(zsock, body, hdr.snappy_compressed_response_len, 0)
|
||||
//
|
||||
|
||||
package protorpc_wire
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Const int32
|
||||
|
||||
const (
|
||||
Const_ZERO Const = 0
|
||||
Const_MAX_REQUEST_HEADER_LEN Const = 1024
|
||||
)
|
||||
|
||||
// Enum value maps for Const.
|
||||
var (
|
||||
Const_name = map[int32]string{
|
||||
0: "ZERO",
|
||||
1024: "MAX_REQUEST_HEADER_LEN",
|
||||
}
|
||||
Const_value = map[string]int32{
|
||||
"ZERO": 0,
|
||||
"MAX_REQUEST_HEADER_LEN": 1024,
|
||||
}
|
||||
)
|
||||
|
||||
func (x Const) Enum() *Const {
|
||||
p := new(Const)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x Const) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (Const) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_wire_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (Const) Type() protoreflect.EnumType {
|
||||
return &file_wire_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x Const) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func (x *Const) UnmarshalJSON(b []byte) error {
|
||||
num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = Const(num)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated: Use Const.Descriptor instead.
|
||||
func (Const) EnumDescriptor() ([]byte, []int) {
|
||||
return file_wire_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type RequestHeader struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id *uint64 `protobuf:"varint,1,req,name=id" json:"id,omitempty"`
|
||||
Method *string `protobuf:"bytes,2,req,name=method" json:"method,omitempty"`
|
||||
RawRequestLen *uint32 `protobuf:"varint,3,req,name=raw_request_len,json=rawRequestLen" json:"raw_request_len,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RequestHeader) Reset() {
|
||||
*x = RequestHeader{}
|
||||
mi := &file_wire_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RequestHeader) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RequestHeader) ProtoMessage() {}
|
||||
|
||||
func (x *RequestHeader) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_wire_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RequestHeader.ProtoReflect.Descriptor instead.
|
||||
func (*RequestHeader) Descriptor() ([]byte, []int) {
|
||||
return file_wire_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *RequestHeader) GetId() uint64 {
|
||||
if x != nil && x.Id != nil {
|
||||
return *x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RequestHeader) GetMethod() string {
|
||||
if x != nil && x.Method != nil {
|
||||
return *x.Method
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RequestHeader) GetRawRequestLen() uint32 {
|
||||
if x != nil && x.RawRequestLen != nil {
|
||||
return *x.RawRequestLen
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ResponseHeader struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id *uint64 `protobuf:"varint,1,req,name=id" json:"id,omitempty"`
|
||||
Error *string `protobuf:"bytes,2,req,name=error" json:"error,omitempty"`
|
||||
RawResponseLen *uint32 `protobuf:"varint,3,req,name=raw_response_len,json=rawResponseLen" json:"raw_response_len,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ResponseHeader) Reset() {
|
||||
*x = ResponseHeader{}
|
||||
mi := &file_wire_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ResponseHeader) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ResponseHeader) ProtoMessage() {}
|
||||
|
||||
func (x *ResponseHeader) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_wire_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ResponseHeader.ProtoReflect.Descriptor instead.
|
||||
func (*ResponseHeader) Descriptor() ([]byte, []int) {
|
||||
return file_wire_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ResponseHeader) GetId() uint64 {
|
||||
if x != nil && x.Id != nil {
|
||||
return *x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ResponseHeader) GetError() string {
|
||||
if x != nil && x.Error != nil {
|
||||
return *x.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ResponseHeader) GetRawResponseLen() uint32 {
|
||||
if x != nil && x.RawResponseLen != nil {
|
||||
return *x.RawResponseLen
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_wire_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_wire_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"wire.proto\x12\rprotorpc.wire\"_\n" +
|
||||
"\rRequestHeader\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x02(\x04R\x02id\x12\x16\n" +
|
||||
"\x06method\x18\x02 \x02(\tR\x06method\x12&\n" +
|
||||
"\x0fraw_request_len\x18\x03 \x02(\rR\rrawRequestLen\"`\n" +
|
||||
"\x0eResponseHeader\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x02(\x04R\x02id\x12\x14\n" +
|
||||
"\x05error\x18\x02 \x02(\tR\x05error\x12(\n" +
|
||||
"\x10raw_response_len\x18\x03 \x02(\rR\x0erawResponseLen*.\n" +
|
||||
"\x05Const\x12\b\n" +
|
||||
"\x04ZERO\x10\x00\x12\x1b\n" +
|
||||
"\x16MAX_REQUEST_HEADER_LEN\x10\x80\bB\x0fZ\rprotorpc.wire"
|
||||
|
||||
var (
|
||||
file_wire_proto_rawDescOnce sync.Once
|
||||
file_wire_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_wire_proto_rawDescGZIP() []byte {
|
||||
file_wire_proto_rawDescOnce.Do(func() {
|
||||
file_wire_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_wire_proto_rawDesc), len(file_wire_proto_rawDesc)))
|
||||
})
|
||||
return file_wire_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_wire_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_wire_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_wire_proto_goTypes = []any{
|
||||
(Const)(0), // 0: protorpc.wire.Const
|
||||
(*RequestHeader)(nil), // 1: protorpc.wire.RequestHeader
|
||||
(*ResponseHeader)(nil), // 2: protorpc.wire.ResponseHeader
|
||||
}
|
||||
var file_wire_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_wire_proto_init() }
|
||||
func file_wire_proto_init() {
|
||||
if File_wire_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_wire_proto_rawDesc), len(file_wire_proto_rawDesc)),
|
||||
NumEnums: 1,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_wire_proto_goTypes,
|
||||
DependencyIndexes: file_wire_proto_depIdxs,
|
||||
EnumInfos: file_wire_proto_enumTypes,
|
||||
MessageInfos: file_wire_proto_msgTypes,
|
||||
}.Build()
|
||||
File_wire_proto = out.File
|
||||
file_wire_proto_goTypes = nil
|
||||
file_wire_proto_depIdxs = nil
|
||||
}
|
||||
50
core/protorpc/wire.pb/wire.proto
Normal file
50
core/protorpc/wire.pb/wire.proto
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
//
|
||||
// protorpc wire format wrapper
|
||||
//
|
||||
// 0. Frame Format
|
||||
// len : uvarint64
|
||||
// data: byte[len]
|
||||
//
|
||||
// 1. Client Send Request
|
||||
// Send RequestHeader: sendFrame(zsock, hdr, len(hdr))
|
||||
// Send Request: sendFrame(zsock, body, hdr.snappy_compressed_request_len)
|
||||
//
|
||||
// 2. Server Recv Request
|
||||
// Recv RequestHeader: recvFrame(zsock, hdr, max_hdr_len, 0)
|
||||
// Recv Request: recvFrame(zsock, body, hdr.snappy_compressed_request_len, 0)
|
||||
//
|
||||
// 3. Server Send Response
|
||||
// Send ResponseHeader: sendFrame(zsock, hdr, len(hdr))
|
||||
// Send Response: sendFrame(zsock, body, hdr.snappy_compressed_response_len)
|
||||
//
|
||||
// 4. Client Recv Response
|
||||
// Recv ResponseHeader: recvFrame(zsock, hdr, max_hdr_len, 0)
|
||||
// Recv Response: recvFrame(zsock, body, hdr.snappy_compressed_response_len, 0)
|
||||
//
|
||||
package protorpc.wire;
|
||||
option go_package = "protorpc.wire";
|
||||
|
||||
enum Const {
|
||||
ZERO = 0;
|
||||
MAX_REQUEST_HEADER_LEN = 1024;
|
||||
}
|
||||
|
||||
message RequestHeader {
|
||||
required uint64 id = 1;
|
||||
required string method = 2;
|
||||
|
||||
required uint32 raw_request_len = 3;
|
||||
}
|
||||
|
||||
message ResponseHeader {
|
||||
required uint64 id = 1;
|
||||
required string error = 2;
|
||||
|
||||
required uint32 raw_response_len = 3;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,7 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package libcore;
|
||||
option go_package = "grpc_server/gen";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option go_package = "./;gen";
|
||||
|
||||
service LibcoreService {
|
||||
rpc Start(LoadConfigReq) returns (ErrorResp);
|
||||
|
||||
@ -1,691 +0,0 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.29.3
|
||||
// source: libcore.proto
|
||||
|
||||
package gen
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
LibcoreService_Start_FullMethodName = "/libcore.LibcoreService/Start"
|
||||
LibcoreService_Stop_FullMethodName = "/libcore.LibcoreService/Stop"
|
||||
LibcoreService_CheckConfig_FullMethodName = "/libcore.LibcoreService/CheckConfig"
|
||||
LibcoreService_Test_FullMethodName = "/libcore.LibcoreService/Test"
|
||||
LibcoreService_StopTest_FullMethodName = "/libcore.LibcoreService/StopTest"
|
||||
LibcoreService_QueryURLTest_FullMethodName = "/libcore.LibcoreService/QueryURLTest"
|
||||
LibcoreService_QueryStats_FullMethodName = "/libcore.LibcoreService/QueryStats"
|
||||
LibcoreService_ListConnections_FullMethodName = "/libcore.LibcoreService/ListConnections"
|
||||
LibcoreService_GetGeoIPList_FullMethodName = "/libcore.LibcoreService/GetGeoIPList"
|
||||
LibcoreService_GetGeoSiteList_FullMethodName = "/libcore.LibcoreService/GetGeoSiteList"
|
||||
LibcoreService_CompileGeoIPToSrs_FullMethodName = "/libcore.LibcoreService/CompileGeoIPToSrs"
|
||||
LibcoreService_CompileGeoSiteToSrs_FullMethodName = "/libcore.LibcoreService/CompileGeoSiteToSrs"
|
||||
LibcoreService_SetSystemDNS_FullMethodName = "/libcore.LibcoreService/SetSystemDNS"
|
||||
LibcoreService_IsPrivileged_FullMethodName = "/libcore.LibcoreService/IsPrivileged"
|
||||
LibcoreService_SpeedTest_FullMethodName = "/libcore.LibcoreService/SpeedTest"
|
||||
LibcoreService_QuerySpeedTest_FullMethodName = "/libcore.LibcoreService/QuerySpeedTest"
|
||||
)
|
||||
|
||||
// LibcoreServiceClient is the client API for LibcoreService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type LibcoreServiceClient interface {
|
||||
Start(ctx context.Context, in *LoadConfigReq, opts ...grpc.CallOption) (*ErrorResp, error)
|
||||
Stop(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*ErrorResp, error)
|
||||
CheckConfig(ctx context.Context, in *LoadConfigReq, opts ...grpc.CallOption) (*ErrorResp, error)
|
||||
Test(ctx context.Context, in *TestReq, opts ...grpc.CallOption) (*TestResp, error)
|
||||
StopTest(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*EmptyResp, error)
|
||||
QueryURLTest(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*QueryURLTestResponse, error)
|
||||
QueryStats(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*QueryStatsResp, error)
|
||||
ListConnections(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*ListConnectionsResp, error)
|
||||
GetGeoIPList(ctx context.Context, in *GeoListRequest, opts ...grpc.CallOption) (*GetGeoIPListResponse, error)
|
||||
GetGeoSiteList(ctx context.Context, in *GeoListRequest, opts ...grpc.CallOption) (*GetGeoSiteListResponse, error)
|
||||
CompileGeoIPToSrs(ctx context.Context, in *CompileGeoIPToSrsRequest, opts ...grpc.CallOption) (*EmptyResp, error)
|
||||
CompileGeoSiteToSrs(ctx context.Context, in *CompileGeoSiteToSrsRequest, opts ...grpc.CallOption) (*EmptyResp, error)
|
||||
SetSystemDNS(ctx context.Context, in *SetSystemDNSRequest, opts ...grpc.CallOption) (*EmptyResp, error)
|
||||
IsPrivileged(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*IsPrivilegedResponse, error)
|
||||
SpeedTest(ctx context.Context, in *SpeedTestRequest, opts ...grpc.CallOption) (*SpeedTestResponse, error)
|
||||
QuerySpeedTest(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*QuerySpeedTestResponse, error)
|
||||
}
|
||||
|
||||
type libcoreServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewLibcoreServiceClient(cc grpc.ClientConnInterface) LibcoreServiceClient {
|
||||
return &libcoreServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) Start(ctx context.Context, in *LoadConfigReq, opts ...grpc.CallOption) (*ErrorResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ErrorResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_Start_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) Stop(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*ErrorResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ErrorResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_Stop_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) CheckConfig(ctx context.Context, in *LoadConfigReq, opts ...grpc.CallOption) (*ErrorResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ErrorResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_CheckConfig_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) Test(ctx context.Context, in *TestReq, opts ...grpc.CallOption) (*TestResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(TestResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_Test_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) StopTest(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*EmptyResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(EmptyResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_StopTest_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) QueryURLTest(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*QueryURLTestResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryURLTestResponse)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_QueryURLTest_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) QueryStats(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*QueryStatsResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QueryStatsResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_QueryStats_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) ListConnections(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*ListConnectionsResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListConnectionsResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_ListConnections_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) GetGeoIPList(ctx context.Context, in *GeoListRequest, opts ...grpc.CallOption) (*GetGeoIPListResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetGeoIPListResponse)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_GetGeoIPList_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) GetGeoSiteList(ctx context.Context, in *GeoListRequest, opts ...grpc.CallOption) (*GetGeoSiteListResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetGeoSiteListResponse)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_GetGeoSiteList_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) CompileGeoIPToSrs(ctx context.Context, in *CompileGeoIPToSrsRequest, opts ...grpc.CallOption) (*EmptyResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(EmptyResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_CompileGeoIPToSrs_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) CompileGeoSiteToSrs(ctx context.Context, in *CompileGeoSiteToSrsRequest, opts ...grpc.CallOption) (*EmptyResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(EmptyResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_CompileGeoSiteToSrs_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) SetSystemDNS(ctx context.Context, in *SetSystemDNSRequest, opts ...grpc.CallOption) (*EmptyResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(EmptyResp)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_SetSystemDNS_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) IsPrivileged(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*IsPrivilegedResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(IsPrivilegedResponse)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_IsPrivileged_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) SpeedTest(ctx context.Context, in *SpeedTestRequest, opts ...grpc.CallOption) (*SpeedTestResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(SpeedTestResponse)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_SpeedTest_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *libcoreServiceClient) QuerySpeedTest(ctx context.Context, in *EmptyReq, opts ...grpc.CallOption) (*QuerySpeedTestResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(QuerySpeedTestResponse)
|
||||
err := c.cc.Invoke(ctx, LibcoreService_QuerySpeedTest_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// LibcoreServiceServer is the server API for LibcoreService service.
|
||||
// All implementations must embed UnimplementedLibcoreServiceServer
|
||||
// for forward compatibility.
|
||||
type LibcoreServiceServer interface {
|
||||
Start(context.Context, *LoadConfigReq) (*ErrorResp, error)
|
||||
Stop(context.Context, *EmptyReq) (*ErrorResp, error)
|
||||
CheckConfig(context.Context, *LoadConfigReq) (*ErrorResp, error)
|
||||
Test(context.Context, *TestReq) (*TestResp, error)
|
||||
StopTest(context.Context, *EmptyReq) (*EmptyResp, error)
|
||||
QueryURLTest(context.Context, *EmptyReq) (*QueryURLTestResponse, error)
|
||||
QueryStats(context.Context, *EmptyReq) (*QueryStatsResp, error)
|
||||
ListConnections(context.Context, *EmptyReq) (*ListConnectionsResp, error)
|
||||
GetGeoIPList(context.Context, *GeoListRequest) (*GetGeoIPListResponse, error)
|
||||
GetGeoSiteList(context.Context, *GeoListRequest) (*GetGeoSiteListResponse, error)
|
||||
CompileGeoIPToSrs(context.Context, *CompileGeoIPToSrsRequest) (*EmptyResp, error)
|
||||
CompileGeoSiteToSrs(context.Context, *CompileGeoSiteToSrsRequest) (*EmptyResp, error)
|
||||
SetSystemDNS(context.Context, *SetSystemDNSRequest) (*EmptyResp, error)
|
||||
IsPrivileged(context.Context, *EmptyReq) (*IsPrivilegedResponse, error)
|
||||
SpeedTest(context.Context, *SpeedTestRequest) (*SpeedTestResponse, error)
|
||||
QuerySpeedTest(context.Context, *EmptyReq) (*QuerySpeedTestResponse, error)
|
||||
mustEmbedUnimplementedLibcoreServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedLibcoreServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedLibcoreServiceServer struct{}
|
||||
|
||||
func (UnimplementedLibcoreServiceServer) Start(context.Context, *LoadConfigReq) (*ErrorResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Start not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) Stop(context.Context, *EmptyReq) (*ErrorResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Stop not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) CheckConfig(context.Context, *LoadConfigReq) (*ErrorResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CheckConfig not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) Test(context.Context, *TestReq) (*TestResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Test not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) StopTest(context.Context, *EmptyReq) (*EmptyResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method StopTest not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) QueryURLTest(context.Context, *EmptyReq) (*QueryURLTestResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method QueryURLTest not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) QueryStats(context.Context, *EmptyReq) (*QueryStatsResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method QueryStats not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) ListConnections(context.Context, *EmptyReq) (*ListConnectionsResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListConnections not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) GetGeoIPList(context.Context, *GeoListRequest) (*GetGeoIPListResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetGeoIPList not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) GetGeoSiteList(context.Context, *GeoListRequest) (*GetGeoSiteListResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetGeoSiteList not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) CompileGeoIPToSrs(context.Context, *CompileGeoIPToSrsRequest) (*EmptyResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CompileGeoIPToSrs not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) CompileGeoSiteToSrs(context.Context, *CompileGeoSiteToSrsRequest) (*EmptyResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CompileGeoSiteToSrs not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) SetSystemDNS(context.Context, *SetSystemDNSRequest) (*EmptyResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetSystemDNS not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) IsPrivileged(context.Context, *EmptyReq) (*IsPrivilegedResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method IsPrivileged not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) SpeedTest(context.Context, *SpeedTestRequest) (*SpeedTestResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SpeedTest not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) QuerySpeedTest(context.Context, *EmptyReq) (*QuerySpeedTestResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method QuerySpeedTest not implemented")
|
||||
}
|
||||
func (UnimplementedLibcoreServiceServer) mustEmbedUnimplementedLibcoreServiceServer() {}
|
||||
func (UnimplementedLibcoreServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeLibcoreServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to LibcoreServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeLibcoreServiceServer interface {
|
||||
mustEmbedUnimplementedLibcoreServiceServer()
|
||||
}
|
||||
|
||||
func RegisterLibcoreServiceServer(s grpc.ServiceRegistrar, srv LibcoreServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedLibcoreServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&LibcoreService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _LibcoreService_Start_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(LoadConfigReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).Start(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_Start_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).Start(ctx, req.(*LoadConfigReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_Stop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).Stop(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_Stop_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).Stop(ctx, req.(*EmptyReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_CheckConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(LoadConfigReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).CheckConfig(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_CheckConfig_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).CheckConfig(ctx, req.(*LoadConfigReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_Test_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TestReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).Test(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_Test_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).Test(ctx, req.(*TestReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_StopTest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).StopTest(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_StopTest_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).StopTest(ctx, req.(*EmptyReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_QueryURLTest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).QueryURLTest(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_QueryURLTest_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).QueryURLTest(ctx, req.(*EmptyReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_QueryStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).QueryStats(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_QueryStats_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).QueryStats(ctx, req.(*EmptyReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_ListConnections_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).ListConnections(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_ListConnections_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).ListConnections(ctx, req.(*EmptyReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_GetGeoIPList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GeoListRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).GetGeoIPList(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_GetGeoIPList_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).GetGeoIPList(ctx, req.(*GeoListRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_GetGeoSiteList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GeoListRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).GetGeoSiteList(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_GetGeoSiteList_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).GetGeoSiteList(ctx, req.(*GeoListRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_CompileGeoIPToSrs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CompileGeoIPToSrsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).CompileGeoIPToSrs(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_CompileGeoIPToSrs_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).CompileGeoIPToSrs(ctx, req.(*CompileGeoIPToSrsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_CompileGeoSiteToSrs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CompileGeoSiteToSrsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).CompileGeoSiteToSrs(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_CompileGeoSiteToSrs_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).CompileGeoSiteToSrs(ctx, req.(*CompileGeoSiteToSrsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_SetSystemDNS_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SetSystemDNSRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).SetSystemDNS(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_SetSystemDNS_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).SetSystemDNS(ctx, req.(*SetSystemDNSRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_IsPrivileged_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).IsPrivileged(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_IsPrivileged_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).IsPrivileged(ctx, req.(*EmptyReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_SpeedTest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SpeedTestRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).SpeedTest(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_SpeedTest_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).SpeedTest(ctx, req.(*SpeedTestRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _LibcoreService_QuerySpeedTest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(LibcoreServiceServer).QuerySpeedTest(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: LibcoreService_QuerySpeedTest_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(LibcoreServiceServer).QuerySpeedTest(ctx, req.(*EmptyReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// LibcoreService_ServiceDesc is the grpc.ServiceDesc for LibcoreService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var LibcoreService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "libcore.LibcoreService",
|
||||
HandlerType: (*LibcoreServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Start",
|
||||
Handler: _LibcoreService_Start_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Stop",
|
||||
Handler: _LibcoreService_Stop_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CheckConfig",
|
||||
Handler: _LibcoreService_CheckConfig_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Test",
|
||||
Handler: _LibcoreService_Test_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "StopTest",
|
||||
Handler: _LibcoreService_StopTest_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "QueryURLTest",
|
||||
Handler: _LibcoreService_QueryURLTest_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "QueryStats",
|
||||
Handler: _LibcoreService_QueryStats_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListConnections",
|
||||
Handler: _LibcoreService_ListConnections_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetGeoIPList",
|
||||
Handler: _LibcoreService_GetGeoIPList_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetGeoSiteList",
|
||||
Handler: _LibcoreService_GetGeoSiteList_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CompileGeoIPToSrs",
|
||||
Handler: _LibcoreService_CompileGeoIPToSrs_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CompileGeoSiteToSrs",
|
||||
Handler: _LibcoreService_CompileGeoSiteToSrs_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SetSystemDNS",
|
||||
Handler: _LibcoreService_SetSystemDNS_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "IsPrivileged",
|
||||
Handler: _LibcoreService_IsPrivileged_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SpeedTest",
|
||||
Handler: _LibcoreService_SpeedTest_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "QuerySpeedTest",
|
||||
Handler: _LibcoreService_QuerySpeedTest_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "libcore.proto",
|
||||
}
|
||||
@ -2,12 +2,12 @@ module Core
|
||||
|
||||
go 1.23.6
|
||||
|
||||
toolchain go1.24.4
|
||||
|
||||
require (
|
||||
github.com/Mahdi-zarei/speedtest-go v1.7.12
|
||||
github.com/chai2010/protorpc v1.1.4
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/gofrs/uuid/v5 v5.3.2
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/oschwald/maxminddb-golang v1.13.1
|
||||
github.com/sagernet/sing v0.6.11
|
||||
@ -16,7 +16,6 @@ require (
|
||||
github.com/sagernet/sing-tun v0.6.9
|
||||
github.com/spf13/cobra v1.9.1
|
||||
golang.org/x/sys v0.34.0
|
||||
google.golang.org/grpc v1.74.2
|
||||
google.golang.org/protobuf v1.36.6
|
||||
)
|
||||
|
||||
@ -26,6 +25,8 @@ replace github.com/sagernet/sing-dns => github.com/Mahdi-zarei/sing-dns v0.3.0-b
|
||||
|
||||
replace github.com/sagernet/wireguard-go => github.com/throneproj/wireguard-go v0.0.1-beta.7.0.20250728063157-408bba78ad26
|
||||
|
||||
replace github.com/chai2010/protorpc => ../protorpc
|
||||
|
||||
require (
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||
@ -97,6 +98,7 @@ require (
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.28.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/grpc v1.63.2 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
)
|
||||
|
||||
@ -24,10 +24,8 @@ github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
||||
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
@ -48,8 +46,6 @@ github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5X
|
||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
@ -171,18 +167,6 @@ github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@ -227,10 +211,10 @@ golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
|
||||
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
||||
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@ -6,9 +6,7 @@ import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"google.golang.org/grpc"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
runtimeDebug "runtime/debug"
|
||||
@ -46,22 +44,12 @@ func RunCore() {
|
||||
}()
|
||||
boxmain.DisableColor()
|
||||
|
||||
// GRPC
|
||||
lis, err := net.Listen("tcp", "127.0.0.1:"+strconv.Itoa(*_port))
|
||||
// RPC
|
||||
fmt.Printf("Core listening at %v\n", "127.0.0.1:"+strconv.Itoa(*_port))
|
||||
err := gen.ListenAndServeLibcoreService("tcp", "127.0.0.1:"+strconv.Itoa(*_port), new(server))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
}
|
||||
|
||||
s := grpc.NewServer(
|
||||
grpc.MaxRecvMsgSize(1024*1024*1024), // 1 gigaByte
|
||||
grpc.MaxSendMsgSize(1024*1024*1024), // 1 gigaByte
|
||||
)
|
||||
gen.RegisterLibcoreServiceServer(s, &server{})
|
||||
|
||||
fmt.Printf("Core listening at %v\n", lis.Addr())
|
||||
if err := s.Serve(lis); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
@ -31,20 +31,17 @@ var systemProxyAddr metadata.Socksaddr
|
||||
var instanceCancel context.CancelFunc
|
||||
var debug bool
|
||||
|
||||
type server struct {
|
||||
gen.UnimplementedLibcoreServiceServer
|
||||
}
|
||||
type server int
|
||||
|
||||
// To returns a pointer to the given value.
|
||||
func To[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (out *gen.ErrorResp, _ error) {
|
||||
func (s *server) Start(in *gen.LoadConfigReq, out *gen.ErrorResp) (_ error) {
|
||||
var err error
|
||||
|
||||
defer func() {
|
||||
out = &gen.ErrorResp{}
|
||||
if err != nil {
|
||||
out.Error = To(err.Error())
|
||||
boxInstance = nil
|
||||
@ -107,11 +104,10 @@ func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (out *gen.Err
|
||||
return
|
||||
}
|
||||
|
||||
func (s *server) Stop(ctx context.Context, in *gen.EmptyReq) (out *gen.ErrorResp, _ error) {
|
||||
func (s *server) Stop(in *gen.EmptyReq, out *gen.ErrorResp) (_ error) {
|
||||
var err error
|
||||
|
||||
defer func() {
|
||||
out = &gen.ErrorResp{}
|
||||
if err != nil {
|
||||
out.Error = To(err.Error())
|
||||
}
|
||||
@ -140,35 +136,35 @@ func (s *server) Stop(ctx context.Context, in *gen.EmptyReq) (out *gen.ErrorResp
|
||||
return
|
||||
}
|
||||
|
||||
func (s *server) CheckConfig(ctx context.Context, in *gen.LoadConfigReq) (*gen.ErrorResp, error) {
|
||||
func (s *server) CheckConfig(in *gen.LoadConfigReq, out *gen.ErrorResp) error {
|
||||
err := boxmain.Check([]byte(*in.CoreConfig))
|
||||
if err != nil {
|
||||
return &gen.ErrorResp{
|
||||
Error: To(err.Error()),
|
||||
}, nil
|
||||
out.Error = To(err.Error())
|
||||
return nil
|
||||
}
|
||||
return &gen.ErrorResp{}, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) Test(ctx context.Context, in *gen.TestReq) (*gen.TestResp, error) {
|
||||
func (s *server) Test(in *gen.TestReq, out *gen.TestResp) error {
|
||||
var testInstance *boxbox.Box
|
||||
var cancel context.CancelFunc
|
||||
var err error
|
||||
var twice = true
|
||||
if *in.TestCurrent {
|
||||
if boxInstance == nil {
|
||||
return &gen.TestResp{Results: []*gen.URLTestResp{{
|
||||
out.Results = []*gen.URLTestResp{{
|
||||
OutboundTag: To("proxy"),
|
||||
LatencyMs: To(int32(0)),
|
||||
Error: To("Instance is not running"),
|
||||
}}}, nil
|
||||
}}
|
||||
return nil
|
||||
}
|
||||
testInstance = boxInstance
|
||||
twice = false
|
||||
} else {
|
||||
testInstance, cancel, err = boxmain.Create([]byte(*in.Config))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
defer testInstance.Close()
|
||||
@ -199,82 +195,79 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (*gen.TestResp, erro
|
||||
})
|
||||
}
|
||||
|
||||
return &gen.TestResp{Results: res}, nil
|
||||
out.Results = res
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) StopTest(ctx context.Context, in *gen.EmptyReq) (*gen.EmptyResp, error) {
|
||||
func (s *server) StopTest(in *gen.EmptyReq, out *gen.EmptyResp) error {
|
||||
cancelTests()
|
||||
testCtx, cancelTests = context.WithCancel(context.Background())
|
||||
|
||||
return &gen.EmptyResp{}, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) QueryURLTest(ctx context.Context, in *gen.EmptyReq) (*gen.QueryURLTestResponse, error) {
|
||||
func (s *server) QueryURLTest(in *gen.EmptyReq, out *gen.QueryURLTestResponse) error {
|
||||
results := URLReporter.Results()
|
||||
resp := &gen.QueryURLTestResponse{}
|
||||
for _, r := range results {
|
||||
errStr := ""
|
||||
if r.Error != nil {
|
||||
errStr = r.Error.Error()
|
||||
}
|
||||
resp.Results = append(resp.Results, &gen.URLTestResp{
|
||||
out.Results = append(out.Results, &gen.URLTestResp{
|
||||
OutboundTag: To(r.Tag),
|
||||
LatencyMs: To(int32(r.Duration.Milliseconds())),
|
||||
Error: To(errStr),
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) QueryStats(ctx context.Context, _ *gen.EmptyReq) (*gen.QueryStatsResp, error) {
|
||||
resp := &gen.QueryStatsResp{
|
||||
Ups: make(map[string]int64),
|
||||
Downs: make(map[string]int64),
|
||||
}
|
||||
func (s *server) QueryStats(in *gen.EmptyReq, out *gen.QueryStatsResp) error {
|
||||
out.Ups = make(map[string]int64)
|
||||
out.Downs = make(map[string]int64)
|
||||
if boxInstance != nil {
|
||||
clash := service.FromContext[adapter.ClashServer](boxInstance.Context())
|
||||
if clash != nil {
|
||||
cApi, ok := clash.(*clashapi.Server)
|
||||
if !ok {
|
||||
log.Println("Failed to assert clash server")
|
||||
return nil, E.New("invalid clash server type")
|
||||
return E.New("invalid clash server type")
|
||||
}
|
||||
outbounds := service.FromContext[adapter.OutboundManager](boxInstance.Context())
|
||||
if outbounds == nil {
|
||||
log.Println("Failed to get outbound manager")
|
||||
return nil, E.New("nil outbound manager")
|
||||
return E.New("nil outbound manager")
|
||||
}
|
||||
endpoints := service.FromContext[adapter.EndpointManager](boxInstance.Context())
|
||||
if endpoints == nil {
|
||||
log.Println("Failed to get endpoint manager")
|
||||
return nil, E.New("nil endpoint manager")
|
||||
return E.New("nil endpoint manager")
|
||||
}
|
||||
for _, out := range outbounds.Outbounds() {
|
||||
u, d := cApi.TrafficManager().TotalOutbound(out.Tag())
|
||||
resp.Ups[out.Tag()] = u
|
||||
resp.Downs[out.Tag()] = d
|
||||
for _, ob := range outbounds.Outbounds() {
|
||||
u, d := cApi.TrafficManager().TotalOutbound(ob.Tag())
|
||||
out.Ups[ob.Tag()] = u
|
||||
out.Downs[ob.Tag()] = d
|
||||
}
|
||||
for _, ep := range endpoints.Endpoints() {
|
||||
u, d := cApi.TrafficManager().TotalOutbound(ep.Tag())
|
||||
resp.Ups[ep.Tag()] = u
|
||||
resp.Downs[ep.Tag()] = d
|
||||
out.Ups[ep.Tag()] = u
|
||||
out.Downs[ep.Tag()] = d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) ListConnections(ctx context.Context, in *gen.EmptyReq) (*gen.ListConnectionsResp, error) {
|
||||
func (s *server) ListConnections(in *gen.EmptyReq, out *gen.ListConnectionsResp) error {
|
||||
if boxInstance == nil {
|
||||
return &gen.ListConnectionsResp{}, nil
|
||||
return nil
|
||||
}
|
||||
if service.FromContext[adapter.ClashServer](boxInstance.Context()) == nil {
|
||||
return nil, errors.New("no clash server found")
|
||||
return errors.New("no clash server found")
|
||||
}
|
||||
clash, ok := service.FromContext[adapter.ClashServer](boxInstance.Context()).(*clashapi.Server)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid state, should not be here")
|
||||
return errors.New("invalid state, should not be here")
|
||||
}
|
||||
connections := clash.TrafficManager().Connections()
|
||||
|
||||
@ -299,16 +292,14 @@ func (s *server) ListConnections(ctx context.Context, in *gen.EmptyReq) (*gen.Li
|
||||
}
|
||||
res = append(res, r)
|
||||
}
|
||||
out := &gen.ListConnectionsResp{
|
||||
Connections: res,
|
||||
}
|
||||
return out, nil
|
||||
out.Connections = res
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) GetGeoIPList(ctx context.Context, in *gen.GeoListRequest) (*gen.GetGeoIPListResponse, error) {
|
||||
func (s *server) GetGeoIPList(in *gen.GeoListRequest, out *gen.GetGeoIPListResponse) error {
|
||||
resp, err := boxmain.ListGeoip(*in.Path + string(os.PathSeparator) + "geoip.db")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
res := make([]string, 0)
|
||||
@ -317,13 +308,14 @@ func (s *server) GetGeoIPList(ctx context.Context, in *gen.GeoListRequest) (*gen
|
||||
res = append(res, r)
|
||||
}
|
||||
|
||||
return &gen.GetGeoIPListResponse{Items: res}, nil
|
||||
out.Items = res
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) GetGeoSiteList(ctx context.Context, in *gen.GeoListRequest) (*gen.GetGeoSiteListResponse, error) {
|
||||
func (s *server) GetGeoSiteList(in *gen.GeoListRequest, out *gen.GetGeoSiteListResponse) error {
|
||||
resp, err := boxmain.GeositeList(*in.Path + string(os.PathSeparator) + "geosite.db")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
res := make([]string, 0)
|
||||
@ -332,42 +324,43 @@ func (s *server) GetGeoSiteList(ctx context.Context, in *gen.GeoListRequest) (*g
|
||||
res = append(res, r)
|
||||
}
|
||||
|
||||
return &gen.GetGeoSiteListResponse{Items: res}, nil
|
||||
out.Items = res
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) CompileGeoIPToSrs(ctx context.Context, in *gen.CompileGeoIPToSrsRequest) (*gen.EmptyResp, error) {
|
||||
func (s *server) CompileGeoIPToSrs(in *gen.CompileGeoIPToSrsRequest, out *gen.EmptyResp) error {
|
||||
category := strings.TrimSuffix(*in.Item, "_IP")
|
||||
err := boxmain.CompileRuleSet(*in.Path+string(os.PathSeparator)+"geoip.db", category, boxmain.IpRuleSet, "./rule_sets/"+*in.Item+".srs")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
return &gen.EmptyResp{}, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) CompileGeoSiteToSrs(ctx context.Context, in *gen.CompileGeoSiteToSrsRequest) (*gen.EmptyResp, error) {
|
||||
func (s *server) CompileGeoSiteToSrs(in *gen.CompileGeoSiteToSrsRequest, out *gen.EmptyResp) error {
|
||||
category := strings.TrimSuffix(*in.Item, "_SITE")
|
||||
err := boxmain.CompileRuleSet(*in.Path+string(os.PathSeparator)+"geosite.db", category, boxmain.SiteRuleSet, "./rule_sets/"+*in.Item+".srs")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
return &gen.EmptyResp{}, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) IsPrivileged(ctx context.Context, _ *gen.EmptyReq) (*gen.IsPrivilegedResponse, error) {
|
||||
func (s *server) IsPrivileged(in *gen.EmptyReq, out *gen.IsPrivilegedResponse) error {
|
||||
if runtime.GOOS == "windows" {
|
||||
return &gen.IsPrivilegedResponse{
|
||||
HasPrivilege: To(false),
|
||||
}, nil
|
||||
out.HasPrivilege = To(false)
|
||||
return nil
|
||||
}
|
||||
|
||||
return &gen.IsPrivilegedResponse{HasPrivilege: To(os.Geteuid() == 0)}, nil
|
||||
out.HasPrivilege = To(os.Geteuid() == 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) SpeedTest(ctx context.Context, in *gen.SpeedTestRequest) (*gen.SpeedTestResponse, error) {
|
||||
func (s *server) SpeedTest(in *gen.SpeedTestRequest, out *gen.SpeedTestResponse) error {
|
||||
if !*in.TestDownload && !*in.TestUpload && !*in.SimpleDownload {
|
||||
return nil, errors.New("cannot run empty test")
|
||||
return errors.New("cannot run empty test")
|
||||
}
|
||||
var testInstance *boxbox.Box
|
||||
var cancel context.CancelFunc
|
||||
@ -375,16 +368,17 @@ func (s *server) SpeedTest(ctx context.Context, in *gen.SpeedTestRequest) (*gen.
|
||||
var err error
|
||||
if *in.TestCurrent {
|
||||
if boxInstance == nil {
|
||||
return &gen.SpeedTestResponse{Results: []*gen.SpeedTestResult{{
|
||||
out.Results = []*gen.SpeedTestResult{{
|
||||
OutboundTag: To("proxy"),
|
||||
Error: To("Instance is not running"),
|
||||
}}}, nil
|
||||
}}
|
||||
return nil
|
||||
}
|
||||
testInstance = boxInstance
|
||||
} else {
|
||||
testInstance, cancel, err = boxmain.Create([]byte(*in.Config))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
defer testInstance.Close()
|
||||
@ -415,17 +409,17 @@ func (s *server) SpeedTest(ctx context.Context, in *gen.SpeedTestRequest) (*gen.
|
||||
})
|
||||
}
|
||||
|
||||
return &gen.SpeedTestResponse{Results: res}, nil
|
||||
out.Results = res
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) QuerySpeedTest(context.Context, *gen.EmptyReq) (*gen.QuerySpeedTestResponse, error) {
|
||||
func (s *server) QuerySpeedTest(in *gen.EmptyReq, out *gen.QuerySpeedTestResponse) error {
|
||||
res, isRunning := SpTQuerier.Result()
|
||||
errStr := ""
|
||||
if res.Error != nil {
|
||||
errStr = res.Error.Error()
|
||||
}
|
||||
return &gen.QuerySpeedTestResponse{
|
||||
Result: &gen.SpeedTestResult{
|
||||
out.Result = &gen.SpeedTestResult{
|
||||
DlSpeed: To(res.DlSpeed),
|
||||
UlSpeed: To(res.UlSpeed),
|
||||
Latency: To(res.Latency),
|
||||
@ -434,7 +428,7 @@ func (s *server) QuerySpeedTest(context.Context, *gen.EmptyReq) (*gen.QuerySpeed
|
||||
ServerName: To(res.ServerName),
|
||||
ServerCountry: To(res.ServerCountry),
|
||||
Cancelled: To(res.Cancelled),
|
||||
},
|
||||
IsRunning: To(isRunning),
|
||||
}, nil
|
||||
}
|
||||
out.IsRunning = To(isRunning)
|
||||
return nil
|
||||
}
|
||||
|
||||
9
core/server/server_darwin.go
Normal file
9
core/server/server_darwin.go
Normal file
@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"Core/gen"
|
||||
)
|
||||
|
||||
func (s *server) SetSystemDNS(in *gen.SetSystemDNSRequest, out *gen.EmptyResp) error {
|
||||
return nil
|
||||
}
|
||||
9
core/server/server_linux.go
Normal file
9
core/server/server_linux.go
Normal file
@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"Core/gen"
|
||||
)
|
||||
|
||||
func (s *server) SetSystemDNS(in *gen.SetSystemDNSRequest, out *gen.EmptyResp) error {
|
||||
return nil
|
||||
}
|
||||
@ -3,14 +3,13 @@ package main
|
||||
import (
|
||||
"Core/gen"
|
||||
"Core/internal/boxdns"
|
||||
"context"
|
||||
)
|
||||
|
||||
func (s *server) SetSystemDNS(ctx context.Context, in *gen.SetSystemDNSRequest) (*gen.EmptyResp, error) {
|
||||
func (s *server) SetSystemDNS(in *gen.SetSystemDNSRequest, out *gen.EmptyResp) error {
|
||||
err := boxdns.DnsManagerInstance.SetSystemDNS(nil, *in.Clear)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
return &gen.EmptyResp{}, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -4,17 +4,14 @@
|
||||
#include "libcore.pb.h"
|
||||
#endif
|
||||
#include <QString>
|
||||
|
||||
namespace QtGrpc {
|
||||
class Http2GrpcChannelPrivate;
|
||||
}
|
||||
#include "3rdparty/protorpc/rpc_client.h"
|
||||
|
||||
namespace API {
|
||||
enum GeoRuleSetType {ip, site};
|
||||
|
||||
class Client {
|
||||
public:
|
||||
explicit Client(std::function<void(const QString &)> onError, const QString &target);
|
||||
explicit Client(std::function<void(const QString &)> onError, const QString &host, int port);
|
||||
|
||||
// QString returns is error string
|
||||
|
||||
@ -47,8 +44,7 @@ namespace API {
|
||||
libcore::QuerySpeedTestResponse QueryCurrentSpeedTests(bool *rpcOK);
|
||||
|
||||
private:
|
||||
std::function<std::unique_ptr<QtGrpc::Http2GrpcChannelPrivate>()> make_grpc_channel;
|
||||
std::unique_ptr<QtGrpc::Http2GrpcChannelPrivate> default_grpc_channel;
|
||||
std::function<std::unique_ptr<protorpc::Client>()> make_rpc_client;
|
||||
std::function<void(const QString &)> onError;
|
||||
};
|
||||
|
||||
@ -39,7 +39,7 @@ popd
|
||||
#### Go: core ####
|
||||
pushd core/server
|
||||
pushd gen
|
||||
protoc -I . --go_out=. --go_opt paths=source_relative --go-grpc_out=. --go-grpc_opt paths=source_relative libcore.proto
|
||||
protoc -I . --go_out=. --protorpc_out=. libcore.proto
|
||||
popd
|
||||
VERSION_SINGBOX=$(go list -m -f '{{.Version}}' github.com/sagernet/sing-box)
|
||||
$GOCMD build -v -o $DEST -trimpath -ldflags "-w -s -X 'github.com/sagernet/sing-box/constant.Version=${VERSION_SINGBOX}'" -tags "with_clash_api,with_gvisor,with_quic,with_wireguard,with_utls,with_ech,with_dhcp"
|
||||
|
||||
295
src/api/RPC.cpp
Normal file
295
src/api/RPC.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
#include "include/api/RPC.h"
|
||||
|
||||
#include "include/global/Configs.hpp"
|
||||
|
||||
namespace API {
|
||||
|
||||
Client::Client(std::function<void(const QString &)> onError, const QString &host, int port) {
|
||||
this->make_rpc_client = [=]() { return std::make_unique<protorpc::Client>(host.toStdString().c_str(), port); };
|
||||
this->onError = std::move(onError);
|
||||
}
|
||||
|
||||
#define NOT_OK \
|
||||
*rpcOK = false; \
|
||||
onError(QString("LibcoreService error: %1\n").arg(QString::fromStdString(err.String())));
|
||||
|
||||
QString Client::Start(bool *rpcOK, const libcore::LoadConfigReq &request) {
|
||||
libcore::ErrorResp reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.Start", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
reply = spb::pb::deserialize< libcore::ErrorResp >(resp);
|
||||
*rpcOK = true;
|
||||
return QString::fromStdString(reply.error.value());
|
||||
} else {
|
||||
NOT_OK
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
QString Client::Stop(bool *rpcOK) {
|
||||
libcore::EmptyReq request;
|
||||
libcore::ErrorResp reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.Stop", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
reply = spb::pb::deserialize< libcore::ErrorResp >( resp );
|
||||
*rpcOK = true;
|
||||
return QString::fromStdString(reply.error.value());
|
||||
} else {
|
||||
NOT_OK
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
libcore::QueryStatsResp Client::QueryStats() {
|
||||
libcore::EmptyReq request;
|
||||
libcore::QueryStatsResp reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.QueryStats", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
reply = spb::pb::deserialize< libcore::QueryStatsResp >( resp );
|
||||
return reply;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
libcore::TestResp Client::Test(bool *rpcOK, const libcore::TestReq &request) {
|
||||
libcore::TestResp reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.Test", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
reply = spb::pb::deserialize< libcore::TestResp >( resp );
|
||||
*rpcOK = true;
|
||||
return reply;
|
||||
} else {
|
||||
NOT_OK
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
void Client::StopTests(bool *rpcOK) {
|
||||
const libcore::EmptyReq request;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.StopTest", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
*rpcOK = true;
|
||||
} else {
|
||||
NOT_OK
|
||||
}
|
||||
}
|
||||
|
||||
libcore::QueryURLTestResponse Client::QueryURLTest(bool *rpcOK)
|
||||
{
|
||||
libcore::EmptyReq request;
|
||||
libcore::QueryURLTestResponse reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.QueryURLTest", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
reply = spb::pb::deserialize< libcore::QueryURLTestResponse >( resp );
|
||||
*rpcOK = true;
|
||||
return reply;
|
||||
} else {
|
||||
NOT_OK
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList Client::GetGeoList(bool *rpcOK, GeoRuleSetType mode, const QString& basePath) {
|
||||
switch (mode) {
|
||||
case GeoRuleSetType::ip: {
|
||||
libcore::GeoListRequest request;
|
||||
libcore::GetGeoIPListResponse reply;
|
||||
request.path = basePath.toStdString();
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.GetGeoIPList", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
QStringList res;
|
||||
reply = spb::pb::deserialize< libcore::GetGeoIPListResponse >( resp );
|
||||
for (const auto & i : reply.items) {
|
||||
res.append(QString::fromStdString(i));
|
||||
}
|
||||
*rpcOK = true;
|
||||
return res;
|
||||
} else {
|
||||
NOT_OK
|
||||
return {};
|
||||
}
|
||||
}
|
||||
case GeoRuleSetType::site: {
|
||||
libcore::GeoListRequest request;
|
||||
libcore::GetGeoSiteListResponse reply;
|
||||
request.path = basePath.toStdString();
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.GetGeoSiteList", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
QStringList res;
|
||||
reply = spb::pb::deserialize< libcore::GetGeoSiteListResponse >( resp );
|
||||
for (const auto & i : reply.items) {
|
||||
res.append(QString::fromStdString(i));
|
||||
}
|
||||
*rpcOK = true;
|
||||
return res;
|
||||
} else {
|
||||
NOT_OK
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QString Client::CompileGeoSet(bool *rpcOK, GeoRuleSetType mode, std::string category, const QString& basePath) {
|
||||
switch (mode) {
|
||||
case ip: {
|
||||
libcore::CompileGeoIPToSrsRequest request;
|
||||
libcore::EmptyResp reply;
|
||||
request.item = category;
|
||||
request.path = basePath.toStdString();
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.CompileGeoIPToSrs", &req, &resp);
|
||||
if(err.IsNil()) {
|
||||
*rpcOK = true;
|
||||
return "";
|
||||
} else {
|
||||
NOT_OK
|
||||
return QString::fromStdString(err.String());
|
||||
}
|
||||
}
|
||||
case site: {
|
||||
libcore::CompileGeoSiteToSrsRequest request;
|
||||
libcore::EmptyResp reply;
|
||||
request.item = category;
|
||||
request.path = basePath.toStdString();
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.CompileGeoSiteToSrs", &req, &resp);
|
||||
if(err.IsNil()) {
|
||||
*rpcOK = true;
|
||||
return "";
|
||||
} else {
|
||||
NOT_OK
|
||||
return QString::fromStdString(err.String());
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
QString Client::SetSystemDNS(bool *rpcOK, const bool clear) const {
|
||||
libcore::SetSystemDNSRequest request;
|
||||
request.clear = clear;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.SetSystemDNS", &req, &resp);
|
||||
if(err.IsNil()) {
|
||||
*rpcOK = true;
|
||||
return "";
|
||||
} else {
|
||||
NOT_OK
|
||||
return QString::fromStdString(err.String());
|
||||
}
|
||||
}
|
||||
|
||||
libcore::ListConnectionsResp Client::ListConnections(bool* rpcOK) const
|
||||
{
|
||||
libcore::EmptyReq request;
|
||||
libcore::ListConnectionsResp reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.ListConnections", &req, &resp);
|
||||
if(err.IsNil()) {
|
||||
reply = spb::pb::deserialize< libcore::ListConnectionsResp >( resp );
|
||||
*rpcOK = true;
|
||||
return reply;
|
||||
} else {
|
||||
NOT_OK
|
||||
MW_show_log(QString("Failed to list connections: ") + QString::fromStdString(err.String()));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
QString Client::CheckConfig(bool* rpcOK, const QString& config) const
|
||||
{
|
||||
libcore::LoadConfigReq request;
|
||||
libcore::ErrorResp reply;
|
||||
request.core_config = config.toStdString();
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.CheckConfig", &req, &resp);
|
||||
|
||||
if(err.IsNil())
|
||||
{
|
||||
reply = spb::pb::deserialize< libcore::ErrorResp >( resp );
|
||||
*rpcOK = true;
|
||||
return QString::fromStdString(reply.error.value());
|
||||
} else
|
||||
{
|
||||
NOT_OK
|
||||
return QString::fromStdString(err.String());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Client::IsPrivileged(bool* rpcOK) const
|
||||
{
|
||||
libcore::EmptyReq request;
|
||||
libcore::IsPrivilegedResponse reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.IsPrivileged", &req, &resp);
|
||||
|
||||
if(err.IsNil())
|
||||
{
|
||||
reply = spb::pb::deserialize< libcore::IsPrivilegedResponse >( resp );
|
||||
*rpcOK = true;
|
||||
return reply.has_privilege.value();
|
||||
} else
|
||||
{
|
||||
NOT_OK
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
libcore::SpeedTestResponse Client::SpeedTest(bool *rpcOK, const libcore::SpeedTestRequest &request)
|
||||
{
|
||||
libcore::SpeedTestResponse reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.SpeedTest", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
reply = spb::pb::deserialize< libcore::SpeedTestResponse >( resp );
|
||||
*rpcOK = true;
|
||||
return reply;
|
||||
} else {
|
||||
NOT_OK
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
libcore::QuerySpeedTestResponse Client::QueryCurrentSpeedTests(bool *rpcOK)
|
||||
{
|
||||
const libcore::EmptyReq request;
|
||||
libcore::QuerySpeedTestResponse reply;
|
||||
std::string resp, req = spb::pb::serialize<std::string>(request);
|
||||
auto err = make_rpc_client()->CallMethod("LibcoreService.QuerySpeedTest", &req, &resp);
|
||||
|
||||
if(err.IsNil()) {
|
||||
reply = spb::pb::deserialize< libcore::QuerySpeedTestResponse >( resp );
|
||||
*rpcOK = true;
|
||||
return reply;
|
||||
} else {
|
||||
NOT_OK
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace API
|
||||
474
src/api/gRPC.cpp
474
src/api/gRPC.cpp
@ -1,474 +0,0 @@
|
||||
#include "include/api/gRPC.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "include/global/Configs.hpp"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QNetworkReply>
|
||||
#include <QTimer>
|
||||
#include <QtEndian>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QAbstractNetworkCache>
|
||||
|
||||
namespace QtGrpc {
|
||||
const char *GrpcAcceptEncodingHeader = "grpc-accept-encoding";
|
||||
const char *AcceptEncodingHeader = "accept-encoding";
|
||||
const char *TEHeader = "te";
|
||||
const char *GrpcStatusHeader = "grpc-status";
|
||||
const char *GrpcStatusMessage = "grpc-message";
|
||||
const int GrpcMessageSizeHeaderSize = 5;
|
||||
|
||||
class NoCache : public QAbstractNetworkCache {
|
||||
public:
|
||||
QNetworkCacheMetaData metaData(const QUrl &url) override {
|
||||
return {};
|
||||
}
|
||||
void updateMetaData(const QNetworkCacheMetaData &metaData) override {
|
||||
}
|
||||
QIODevice *data(const QUrl &url) override {
|
||||
return nullptr;
|
||||
}
|
||||
bool remove(const QUrl &url) override {
|
||||
return false;
|
||||
}
|
||||
[[nodiscard]] qint64 cacheSize() const override {
|
||||
return 0;
|
||||
}
|
||||
QIODevice *prepare(const QNetworkCacheMetaData &metaData) override {
|
||||
return nullptr;
|
||||
}
|
||||
void insert(QIODevice *device) override {
|
||||
}
|
||||
void clear() override {
|
||||
}
|
||||
};
|
||||
|
||||
class Http2GrpcChannelPrivate {
|
||||
private:
|
||||
QThread *thread;
|
||||
QNetworkAccessManager *nm;
|
||||
|
||||
QString url_base;
|
||||
QString serviceName;
|
||||
|
||||
// async
|
||||
QNetworkReply *post(const QString &method, const QString &service, const QByteArray &args) {
|
||||
QUrl callUrl = url_base + "/" + service + "/" + method;
|
||||
|
||||
QNetworkRequest request(callUrl);
|
||||
request.setAttribute(QNetworkRequest::Http2DirectAttribute, true);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String{"application/grpc"});
|
||||
request.setRawHeader("Cache-Control", "no-store");
|
||||
request.setRawHeader(GrpcAcceptEncodingHeader, QByteArray{"identity,deflate,gzip"});
|
||||
request.setRawHeader(AcceptEncodingHeader, QByteArray{"identity,gzip"});
|
||||
request.setRawHeader(TEHeader, QByteArray{"trailers"});
|
||||
|
||||
QByteArray msg(GrpcMessageSizeHeaderSize, '\0');
|
||||
*reinterpret_cast<int *>(msg.data() + 1) = qToBigEndian((int) args.size());
|
||||
msg += args;
|
||||
|
||||
QNetworkReply *networkReply = nm->post(request, msg);
|
||||
return networkReply;
|
||||
}
|
||||
|
||||
static QByteArray processReply(QNetworkReply *networkReply, QNetworkReply::NetworkError &statusCode) {
|
||||
// Check if no network error occured
|
||||
if (networkReply->error() != QNetworkReply::NoError) {
|
||||
statusCode = networkReply->error();
|
||||
return {};
|
||||
}
|
||||
|
||||
// Check if server answer with error
|
||||
auto errCode = networkReply->rawHeader(GrpcStatusHeader).toInt();
|
||||
if (errCode != 0) {
|
||||
QStringList errstr;
|
||||
errstr << "grpc-status error code:" << Int2String(errCode) << ", error msg:"
|
||||
<< QLatin1String(networkReply->rawHeader(GrpcStatusMessage));
|
||||
MW_show_log(errstr.join(" "));
|
||||
statusCode = QNetworkReply::NetworkError::ProtocolUnknownError;
|
||||
return {};
|
||||
}
|
||||
statusCode = QNetworkReply::NetworkError::NoError;
|
||||
return networkReply->readAll().mid(GrpcMessageSizeHeaderSize);
|
||||
}
|
||||
|
||||
QNetworkReply::NetworkError call(const QString &method, const QString &service, const QByteArray &args, QByteArray &qByteArray, int timeout_ms) {
|
||||
QNetworkReply *networkReply = post(method, service, args);
|
||||
|
||||
QTimer *abortTimer = nullptr;
|
||||
if (timeout_ms > 0) {
|
||||
abortTimer = new QTimer;
|
||||
abortTimer->setSingleShot(true);
|
||||
abortTimer->setInterval(timeout_ms);
|
||||
QObject::connect(abortTimer, &QTimer::timeout, networkReply, &QNetworkReply::abort);
|
||||
abortTimer->start();
|
||||
}
|
||||
|
||||
{
|
||||
QEventLoop loop;
|
||||
QObject::connect(networkReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
}
|
||||
|
||||
if (abortTimer != nullptr) {
|
||||
abortTimer->stop();
|
||||
abortTimer->deleteLater();
|
||||
}
|
||||
|
||||
auto grpcStatus = QNetworkReply::NetworkError::ProtocolUnknownError;
|
||||
qByteArray = processReply(networkReply, grpcStatus);
|
||||
|
||||
networkReply->deleteLater();
|
||||
return grpcStatus;
|
||||
}
|
||||
|
||||
public:
|
||||
Http2GrpcChannelPrivate(const QString &url_, const QString &serviceName_) {
|
||||
url_base = "http://" + url_;
|
||||
serviceName = serviceName_;
|
||||
//
|
||||
thread = new QThread;
|
||||
nm = new QNetworkAccessManager();
|
||||
nm->setCache(new NoCache);
|
||||
nm->moveToThread(thread);
|
||||
thread->start();
|
||||
}
|
||||
|
||||
~Http2GrpcChannelPrivate() {
|
||||
nm->deleteLater();
|
||||
thread->quit();
|
||||
thread->wait();
|
||||
thread->deleteLater();
|
||||
}
|
||||
|
||||
QNetworkReply::NetworkError Call(const QString &methodName,
|
||||
const std::string req, std::vector<uint8_t> &rsp,
|
||||
int timeout_ms = 0) {
|
||||
if (!Configs::dataStore->core_running) return QNetworkReply::NetworkError(-1919);
|
||||
|
||||
auto requestArray = QByteArray::fromStdString(req);
|
||||
|
||||
QByteArray responseArray;
|
||||
QNetworkReply::NetworkError err;
|
||||
QMutex lock;
|
||||
lock.lock();
|
||||
|
||||
runOnThread(
|
||||
[&] {
|
||||
err = call(methodName, serviceName, requestArray, responseArray, timeout_ms);
|
||||
lock.unlock();
|
||||
},
|
||||
nm);
|
||||
|
||||
lock.lock();
|
||||
lock.unlock();
|
||||
// qDebug() << "rsp err" << err;
|
||||
// qDebug() << "rsp array" << responseArray;
|
||||
|
||||
if (err != QNetworkReply::NetworkError::NoError) {
|
||||
return err;
|
||||
}
|
||||
rsp.assign(responseArray.begin(), responseArray.end());
|
||||
return QNetworkReply::NetworkError::NoError;
|
||||
}
|
||||
};
|
||||
} // namespace QtGrpc
|
||||
|
||||
namespace API {
|
||||
|
||||
Client::Client(std::function<void(const QString &)> onError, const QString &target) {
|
||||
this->make_grpc_channel = [=]() { return std::make_unique<QtGrpc::Http2GrpcChannelPrivate>(target, "libcore.LibcoreService"); };
|
||||
this->default_grpc_channel = make_grpc_channel();
|
||||
this->onError = std::move(onError);
|
||||
}
|
||||
|
||||
#define NOT_OK \
|
||||
*rpcOK = false; \
|
||||
onError(QString("QNetworkReply::NetworkError code: %1\n").arg(status));
|
||||
|
||||
QString Client::Start(bool *rpcOK, const libcore::LoadConfigReq &request) {
|
||||
libcore::ErrorResp reply;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = default_grpc_channel->Call("Start", spb::pb::serialize< std::string >( request ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
reply = spb::pb::deserialize< libcore::ErrorResp >( rsp );
|
||||
*rpcOK = true;
|
||||
return {reply.error.value().c_str()};
|
||||
} else {
|
||||
NOT_OK
|
||||
return reply.error.value().c_str();
|
||||
}
|
||||
}
|
||||
|
||||
QString Client::Stop(bool *rpcOK) {
|
||||
libcore::EmptyReq request;
|
||||
libcore::ErrorResp reply;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = default_grpc_channel->Call("Stop", spb::pb::serialize< std::string >( request ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
reply = spb::pb::deserialize< libcore::ErrorResp >( rsp );
|
||||
*rpcOK = true;
|
||||
return {reply.error.value().c_str()};
|
||||
} else {
|
||||
NOT_OK
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
libcore::QueryStatsResp Client::QueryStats() {
|
||||
libcore::EmptyReq request;
|
||||
libcore::QueryStatsResp reply;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = default_grpc_channel->Call("QueryStats", spb::pb::serialize< std::string >( request ), rsp, 500);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
reply = spb::pb::deserialize< libcore::QueryStatsResp >( rsp );
|
||||
return reply;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
libcore::TestResp Client::Test(bool *rpcOK, const libcore::TestReq &request) {
|
||||
libcore::TestResp reply;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = make_grpc_channel()->Call("Test", spb::pb::serialize< std::string >( request ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
reply = spb::pb::deserialize< libcore::TestResp >( rsp );
|
||||
*rpcOK = true;
|
||||
return reply;
|
||||
} else {
|
||||
NOT_OK
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
void Client::StopTests(bool *rpcOK) {
|
||||
const libcore::EmptyReq req;
|
||||
libcore::EmptyResp resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = make_grpc_channel()->Call("StopTest", spb::pb::serialize< std::string >( req ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
*rpcOK = true;
|
||||
} else {
|
||||
NOT_OK
|
||||
}
|
||||
}
|
||||
|
||||
libcore::QueryURLTestResponse Client::QueryURLTest(bool *rpcOK)
|
||||
{
|
||||
libcore::EmptyReq request;
|
||||
libcore::QueryURLTestResponse resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = make_grpc_channel()->Call("QueryURLTest", spb::pb::serialize< std::string >( request ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
resp = spb::pb::deserialize< libcore::QueryURLTestResponse >( rsp );
|
||||
*rpcOK = true;
|
||||
return resp;
|
||||
} else {
|
||||
NOT_OK
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList Client::GetGeoList(bool *rpcOK, GeoRuleSetType mode, const QString& basePath) {
|
||||
switch (mode) {
|
||||
case GeoRuleSetType::ip: {
|
||||
libcore::GeoListRequest req;
|
||||
libcore::GetGeoIPListResponse resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
req.path = basePath.toStdString();
|
||||
|
||||
auto status = default_grpc_channel->Call("GetGeoIPList", spb::pb::serialize< std::string >( req ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
QStringList res;
|
||||
resp = spb::pb::deserialize< libcore::GetGeoIPListResponse >( rsp );
|
||||
for (const auto & i : resp.items) {
|
||||
res.append(QString::fromStdString(i));
|
||||
}
|
||||
*rpcOK = true;
|
||||
return res;
|
||||
} else {
|
||||
NOT_OK
|
||||
return {};
|
||||
}
|
||||
}
|
||||
case GeoRuleSetType::site: {
|
||||
libcore::GeoListRequest req;
|
||||
libcore::GetGeoSiteListResponse resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
req.path = basePath.toStdString();
|
||||
|
||||
auto status = default_grpc_channel->Call("GetGeoSiteList", spb::pb::serialize< std::string >( req ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
QStringList res;
|
||||
resp = spb::pb::deserialize< libcore::GetGeoSiteListResponse >( rsp );
|
||||
for (const auto & i : resp.items) {
|
||||
res.append(QString::fromStdString(i));
|
||||
}
|
||||
*rpcOK = true;
|
||||
return res;
|
||||
} else {
|
||||
NOT_OK
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QString Client::CompileGeoSet(bool *rpcOK, GeoRuleSetType mode, std::string category, const QString& basePath) {
|
||||
switch (mode) {
|
||||
case ip: {
|
||||
libcore::CompileGeoIPToSrsRequest req;
|
||||
libcore::EmptyResp resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
req.item = category;
|
||||
req.path = basePath.toStdString();
|
||||
|
||||
auto status = default_grpc_channel->Call("CompileGeoIPToSrs", spb::pb::serialize< std::string >( req ), rsp);
|
||||
if (status == QNetworkReply::NoError) {
|
||||
*rpcOK = true;
|
||||
return "";
|
||||
} else {
|
||||
NOT_OK
|
||||
return qt_error_string(status);
|
||||
}
|
||||
}
|
||||
case site: {
|
||||
libcore::CompileGeoSiteToSrsRequest req;
|
||||
libcore::EmptyResp resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
req.item = category;
|
||||
req.path = basePath.toStdString();
|
||||
|
||||
auto status = default_grpc_channel->Call("CompileGeoSiteToSrs", spb::pb::serialize< std::string >( req ), rsp);
|
||||
if (status == QNetworkReply::NoError) {
|
||||
*rpcOK = true;
|
||||
return "";
|
||||
} else {
|
||||
NOT_OK
|
||||
return qt_error_string(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
QString Client::SetSystemDNS(bool *rpcOK, const bool clear) const {
|
||||
libcore::SetSystemDNSRequest req;
|
||||
libcore::EmptyResp resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
req.clear = clear;
|
||||
|
||||
auto status = default_grpc_channel->Call("SetSystemDNS", spb::pb::serialize< std::string >( req ), rsp);
|
||||
if (status == QNetworkReply::NoError) {
|
||||
*rpcOK = true;
|
||||
return "";
|
||||
} else {
|
||||
NOT_OK
|
||||
return qt_error_string(status);
|
||||
}
|
||||
}
|
||||
|
||||
libcore::ListConnectionsResp Client::ListConnections(bool* rpcOK) const
|
||||
{
|
||||
libcore::EmptyReq req;
|
||||
libcore::ListConnectionsResp resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = default_grpc_channel->Call("ListConnections", spb::pb::serialize< std::string >( req ), rsp);
|
||||
if (status == QNetworkReply::NoError) {
|
||||
resp = spb::pb::deserialize< libcore::ListConnectionsResp >( rsp );
|
||||
*rpcOK = true;
|
||||
return resp;
|
||||
} else {
|
||||
NOT_OK
|
||||
MW_show_log(QString("Failed to list connections: " + qt_error_string(status)));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
QString Client::CheckConfig(bool* rpcOK, const QString& config) const
|
||||
{
|
||||
libcore::LoadConfigReq req;
|
||||
libcore::ErrorResp resp;
|
||||
std::vector<uint8_t> rsp;
|
||||
req.core_config = config.toStdString();
|
||||
auto status = default_grpc_channel->Call("CheckConfig", spb::pb::serialize< std::string >( req ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError)
|
||||
{
|
||||
resp = spb::pb::deserialize< libcore::ErrorResp >( rsp );
|
||||
*rpcOK = true;
|
||||
return {resp.error.value().c_str()};
|
||||
} else
|
||||
{
|
||||
NOT_OK
|
||||
return qt_error_string(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Client::IsPrivileged(bool* rpcOK) const
|
||||
{
|
||||
auto req = libcore::EmptyReq();
|
||||
auto resp = libcore::IsPrivilegedResponse();
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = default_grpc_channel->Call("IsPrivileged", spb::pb::serialize< std::string >( req ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError)
|
||||
{
|
||||
resp = spb::pb::deserialize< libcore::IsPrivilegedResponse >( rsp );
|
||||
*rpcOK = true;
|
||||
return resp.has_privilege.value();
|
||||
} else
|
||||
{
|
||||
NOT_OK
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
libcore::SpeedTestResponse Client::SpeedTest(bool *rpcOK, const libcore::SpeedTestRequest &request)
|
||||
{
|
||||
libcore::SpeedTestResponse reply;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = make_grpc_channel()->Call("SpeedTest", spb::pb::serialize< std::string >( request ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
reply = spb::pb::deserialize< libcore::SpeedTestResponse >( rsp );
|
||||
*rpcOK = true;
|
||||
return reply;
|
||||
} else {
|
||||
NOT_OK
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
libcore::QuerySpeedTestResponse Client::QueryCurrentSpeedTests(bool *rpcOK)
|
||||
{
|
||||
const libcore::EmptyReq req;
|
||||
libcore::QuerySpeedTestResponse reply;
|
||||
std::vector<uint8_t> rsp;
|
||||
auto status = make_grpc_channel()->Call("QuerySpeedTest", spb::pb::serialize< std::string >( req ), rsp);
|
||||
|
||||
if (status == QNetworkReply::NoError) {
|
||||
reply = spb::pb::deserialize< libcore::QuerySpeedTestResponse >( rsp );
|
||||
*rpcOK = true;
|
||||
return reply;
|
||||
} else {
|
||||
NOT_OK
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace API
|
||||
@ -2,7 +2,7 @@
|
||||
#include "include/dataStore/Database.hpp"
|
||||
#include "include/configs/proxy/includes.h"
|
||||
#include "include/configs/proxy/Preset.hpp"
|
||||
#include "include/api/gRPC.h"
|
||||
#include "include/api/RPC.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QStandardPaths>
|
||||
#include <include/api/gRPC.h>
|
||||
#include <include/api/RPC.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "include/sys/windows/guihelper.h"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include <QThread>
|
||||
#include <libcore.pb.h>
|
||||
#include <include/api/gRPC.h>
|
||||
#include <include/api/RPC.h>
|
||||
#include "include/ui/mainwindow_interface.h"
|
||||
#include <include/stats/connections/connectionLister.hpp>
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "include/stats/traffic/TrafficLooper.hpp"
|
||||
|
||||
#include "include/api/gRPC.h"
|
||||
#include "include/api/RPC.h"
|
||||
#include "include/ui/mainwindow_interface.h"
|
||||
|
||||
#include <QThread>
|
||||
|
||||
@ -53,7 +53,6 @@
|
||||
#include <random>
|
||||
#include <3rdparty/QHotkey/qhotkey.h>
|
||||
#include <3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp>
|
||||
#include <include/api/gRPC.h>
|
||||
#include <include/global/HTTPRequestHelper.hpp>
|
||||
|
||||
#include "include/sys/macos/MacOS.h"
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include "include/dataStore/Database.hpp"
|
||||
#include "include/configs/ConfigBuilder.hpp"
|
||||
#include "include/stats/traffic/TrafficLooper.hpp"
|
||||
#include "include/api/gRPC.h"
|
||||
#include "include/api/RPC.h"
|
||||
#include "include/ui/utils//MessageBoxTimer.h"
|
||||
#include "3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp"
|
||||
|
||||
@ -22,7 +22,7 @@ void MainWindow::setup_grpc() {
|
||||
[=](const QString &errStr) {
|
||||
MW_show_log("[Error] Core: " + errStr);
|
||||
},
|
||||
"127.0.0.1:" + Int2String(Configs::dataStore->core_port));
|
||||
"127.0.0.1", Configs::dataStore->core_port);
|
||||
|
||||
// Looper
|
||||
runOnNewThread([=] { Stats::trafficLooper->Loop(); });
|
||||
@ -64,7 +64,7 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
|
||||
{
|
||||
int entid = -1;
|
||||
if (!tag2entID.empty()) {
|
||||
entid = tag2entID.count(QString(res.outbound_tag.value().c_str())) == 0 ? -1 : tag2entID[QString(res.outbound_tag.value().c_str())];
|
||||
entid = tag2entID.count(QString::fromStdString(res.outbound_tag.value())) == 0 ? -1 : tag2entID[QString::fromStdString(res.outbound_tag.value())];
|
||||
}
|
||||
if (entid == -1) {
|
||||
continue;
|
||||
@ -76,11 +76,11 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
|
||||
if (res.error.value().empty()) {
|
||||
ent->latency = res.latency_ms.value();
|
||||
} else {
|
||||
if (QString(res.error.value().c_str()).contains("test aborted") ||
|
||||
QString(res.error.value().c_str()).contains("context canceled")) ent->latency=0;
|
||||
if (QString::fromStdString(res.error.value()).contains("test aborted") ||
|
||||
QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0;
|
||||
else {
|
||||
ent->latency = -1;
|
||||
MW_show_log(tr("[%1] test error: %2").arg(ent->bean->DisplayTypeAndName(), res.error.value().c_str()));
|
||||
MW_show_log(tr("[%1] test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
|
||||
}
|
||||
}
|
||||
ent->Save();
|
||||
@ -104,7 +104,7 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
|
||||
|
||||
for (const auto &res: result.results) {
|
||||
if (!tag2entID.empty()) {
|
||||
entID = tag2entID.count(QString(res.outbound_tag.value().c_str())) == 0 ? -1 : tag2entID[QString(res.outbound_tag.value().c_str())];
|
||||
entID = tag2entID.count(QString::fromStdString(res.outbound_tag.value())) == 0 ? -1 : tag2entID[QString::fromStdString(res.outbound_tag.value())];
|
||||
}
|
||||
if (entID == -1) {
|
||||
MW_show_log(tr("Something is very wrong, the subject ent cannot be found!"));
|
||||
@ -120,11 +120,11 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
|
||||
if (res.error.value().empty()) {
|
||||
ent->latency = res.latency_ms.value();
|
||||
} else {
|
||||
if (QString(res.error.value().c_str()).contains("test aborted") ||
|
||||
QString(res.error.value().c_str()).contains("context canceled")) ent->latency=0;
|
||||
if (QString::fromStdString(res.error.value()).contains("test aborted") ||
|
||||
QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0;
|
||||
else {
|
||||
ent->latency = -1;
|
||||
MW_show_log(tr("[%1] test error: %2").arg(ent->bean->DisplayTypeAndName(), res.error.value().c_str()));
|
||||
MW_show_log(tr("[%1] test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
|
||||
}
|
||||
}
|
||||
ent->Save();
|
||||
@ -212,7 +212,7 @@ void MainWindow::url_test_current() {
|
||||
|
||||
runOnUiThread([=] {
|
||||
if (!result.results[0].error.value().empty()) {
|
||||
MW_show_log(QString("UrlTest error: %1").arg(result.results[0].error.value().c_str()));
|
||||
MW_show_log(QString("UrlTest error: %1").arg(QString::fromStdString(result.results[0].error.value())));
|
||||
}
|
||||
if (latency <= 0) {
|
||||
ui->label_running->setText(tr("Test Result") + ": " + tr("Unavailable"));
|
||||
@ -304,7 +304,7 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, bool testC
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto profile = testCurrent ? running : Configs::profileManager->GetProfile(tag2entID[res.result.value().outbound_tag.value().c_str()]);
|
||||
auto profile = testCurrent ? running : Configs::profileManager->GetProfile(tag2entID[QString::fromStdString(res.result.value().outbound_tag.value())]);
|
||||
if (profile == nullptr)
|
||||
{
|
||||
continue;
|
||||
@ -318,8 +318,8 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, bool testC
|
||||
|
||||
if (res.result.value().error.value().empty() && !res.result.value().cancelled.value() && lastProxyListUpdate.msecsTo(QDateTime::currentDateTime()) >= 500)
|
||||
{
|
||||
if (!res.result.value().dl_speed.value().empty()) profile->dl_speed = res.result.value().dl_speed.value().c_str();
|
||||
if (!res.result.value().ul_speed.value().empty()) profile->ul_speed = res.result.value().ul_speed.value().c_str();
|
||||
if (!res.result.value().dl_speed.value().empty()) profile->dl_speed = QString::fromStdString(res.result.value().dl_speed.value());
|
||||
if (!res.result.value().ul_speed.value().empty()) profile->ul_speed = QString::fromStdString(res.result.value().ul_speed.value());
|
||||
if (profile->latency <= 0 && res.result.value().latency.value() > 0) profile->latency = res.result.value().latency.value();
|
||||
refresh_proxy_list(profile->id);
|
||||
lastProxyListUpdate = QDateTime::currentDateTime();
|
||||
@ -343,7 +343,7 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, bool testC
|
||||
for (const auto &res: result.results) {
|
||||
if (testCurrent) entID = running ? running->id : -1;
|
||||
else {
|
||||
entID = tag2entID.count(QString(res.outbound_tag.value().c_str())) == 0 ? -1 : tag2entID[QString(res.outbound_tag.value().c_str())];
|
||||
entID = tag2entID.count(QString::fromStdString(res.outbound_tag.value())) == 0 ? -1 : tag2entID[QString::fromStdString(res.outbound_tag.value())];
|
||||
}
|
||||
if (entID == -1) {
|
||||
MW_show_log(tr("Something is very wrong, the subject ent cannot be found!"));
|
||||
@ -359,14 +359,14 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, bool testC
|
||||
if (res.cancelled.value()) continue;
|
||||
|
||||
if (res.error.value().empty()) {
|
||||
ent->dl_speed = res.dl_speed.value().c_str();
|
||||
ent->ul_speed = res.ul_speed.value().c_str();
|
||||
ent->dl_speed = QString::fromStdString(res.dl_speed.value());
|
||||
ent->ul_speed = QString::fromStdString(res.ul_speed.value());
|
||||
if (ent->latency <= 0 && res.latency.value() > 0) ent->latency = res.latency.value();
|
||||
} else {
|
||||
ent->dl_speed = "N/A";
|
||||
ent->ul_speed = "N/A";
|
||||
ent->latency = -1;
|
||||
MW_show_log(tr("[%1] speed test error: %2").arg(ent->bean->DisplayTypeAndName(), res.error.value().c_str()));
|
||||
MW_show_log(tr("[%1] speed test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
|
||||
}
|
||||
ent->Save();
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include "include/ui/setting/RouteItem.h"
|
||||
#include "include/dataStore/RouteEntity.h"
|
||||
#include "include/dataStore/Database.hpp"
|
||||
#include "include/api/gRPC.h"
|
||||
#include "include/api/RPC.h"
|
||||
|
||||
void adjustComboBoxWidth(const QComboBox *comboBox) {
|
||||
int maxWidth = 0;
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
#include <QShortcut>
|
||||
#include <QTimer>
|
||||
#include <QToolTip>
|
||||
#include <include/api/gRPC.h>
|
||||
#include <include/api/RPC.h>
|
||||
|
||||
void DialogManageRoutes::reloadProfileItems() {
|
||||
if (chainList.empty()) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user