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'
|
if: matrix.cross_os != 'public_res'
|
||||||
run: |
|
run: |
|
||||||
go install github.com/golang/protobuf/protoc-gen-go@latest
|
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
|
- name: Build golang parts
|
||||||
if: steps.cache-common.outputs.cache-hit != 'true'
|
if: steps.cache-common.outputs.cache-hit != 'true'
|
||||||
shell: bash
|
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/quirc.c
|
||||||
3rdparty/quirc/version_db.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/dataStore/Database.cpp
|
||||||
src/stats/traffic/TrafficLooper.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";
|
syntax = "proto2";
|
||||||
|
|
||||||
package libcore;
|
package libcore;
|
||||||
option go_package = "grpc_server/gen";
|
option go_package = "./;gen";
|
||||||
option optimize_for = LITE_RUNTIME;
|
|
||||||
|
|
||||||
service LibcoreService {
|
service LibcoreService {
|
||||||
rpc Start(LoadConfigReq) returns (ErrorResp);
|
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
|
go 1.23.6
|
||||||
|
|
||||||
toolchain go1.24.4
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Mahdi-zarei/speedtest-go v1.7.12
|
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/dustin/go-humanize v1.0.1
|
||||||
github.com/gofrs/uuid/v5 v5.3.2
|
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/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1
|
github.com/oschwald/maxminddb-golang v1.13.1
|
||||||
github.com/sagernet/sing v0.6.11
|
github.com/sagernet/sing v0.6.11
|
||||||
@ -16,7 +16,6 @@ require (
|
|||||||
github.com/sagernet/sing-tun v0.6.9
|
github.com/sagernet/sing-tun v0.6.9
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.9.1
|
||||||
golang.org/x/sys v0.34.0
|
golang.org/x/sys v0.34.0
|
||||||
google.golang.org/grpc v1.74.2
|
|
||||||
google.golang.org/protobuf v1.36.6
|
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/sagernet/wireguard-go => github.com/throneproj/wireguard-go v0.0.1-beta.7.0.20250728063157-408bba78ad26
|
||||||
|
|
||||||
|
replace github.com/chai2010/protorpc => ../protorpc
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.6 // 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/time v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.28.0 // indirect
|
golang.org/x/tools v0.28.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // 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
|
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/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 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
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.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
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-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
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-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
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/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 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
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 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
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=
|
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/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 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
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 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
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.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 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
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-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
||||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
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 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
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=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@ -6,9 +6,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"google.golang.org/grpc"
|
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
runtimeDebug "runtime/debug"
|
runtimeDebug "runtime/debug"
|
||||||
@ -46,22 +44,12 @@ func RunCore() {
|
|||||||
}()
|
}()
|
||||||
boxmain.DisableColor()
|
boxmain.DisableColor()
|
||||||
|
|
||||||
// GRPC
|
// RPC
|
||||||
lis, err := net.Listen("tcp", "127.0.0.1:"+strconv.Itoa(*_port))
|
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 {
|
if err != nil {
|
||||||
log.Fatalf("failed to listen: %v", err)
|
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() {
|
func main() {
|
||||||
|
|||||||
@ -31,20 +31,17 @@ var systemProxyAddr metadata.Socksaddr
|
|||||||
var instanceCancel context.CancelFunc
|
var instanceCancel context.CancelFunc
|
||||||
var debug bool
|
var debug bool
|
||||||
|
|
||||||
type server struct {
|
type server int
|
||||||
gen.UnimplementedLibcoreServiceServer
|
|
||||||
}
|
|
||||||
|
|
||||||
// To returns a pointer to the given value.
|
// To returns a pointer to the given value.
|
||||||
func To[T any](v T) *T {
|
func To[T any](v T) *T {
|
||||||
return &v
|
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
|
var err error
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
out = &gen.ErrorResp{}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
out.Error = To(err.Error())
|
out.Error = To(err.Error())
|
||||||
boxInstance = nil
|
boxInstance = nil
|
||||||
@ -107,11 +104,10 @@ func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (out *gen.Err
|
|||||||
return
|
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
|
var err error
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
out = &gen.ErrorResp{}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
out.Error = To(err.Error())
|
out.Error = To(err.Error())
|
||||||
}
|
}
|
||||||
@ -140,35 +136,35 @@ func (s *server) Stop(ctx context.Context, in *gen.EmptyReq) (out *gen.ErrorResp
|
|||||||
return
|
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))
|
err := boxmain.Check([]byte(*in.CoreConfig))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &gen.ErrorResp{
|
out.Error = To(err.Error())
|
||||||
Error: To(err.Error()),
|
return nil
|
||||||
}, 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 testInstance *boxbox.Box
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
var err error
|
var err error
|
||||||
var twice = true
|
var twice = true
|
||||||
if *in.TestCurrent {
|
if *in.TestCurrent {
|
||||||
if boxInstance == nil {
|
if boxInstance == nil {
|
||||||
return &gen.TestResp{Results: []*gen.URLTestResp{{
|
out.Results = []*gen.URLTestResp{{
|
||||||
OutboundTag: To("proxy"),
|
OutboundTag: To("proxy"),
|
||||||
LatencyMs: To(int32(0)),
|
LatencyMs: To(int32(0)),
|
||||||
Error: To("Instance is not running"),
|
Error: To("Instance is not running"),
|
||||||
}}}, nil
|
}}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
testInstance = boxInstance
|
testInstance = boxInstance
|
||||||
twice = false
|
twice = false
|
||||||
} else {
|
} else {
|
||||||
testInstance, cancel, err = boxmain.Create([]byte(*in.Config))
|
testInstance, cancel, err = boxmain.Create([]byte(*in.Config))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
defer testInstance.Close()
|
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()
|
cancelTests()
|
||||||
testCtx, cancelTests = context.WithCancel(context.Background())
|
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()
|
results := URLReporter.Results()
|
||||||
resp := &gen.QueryURLTestResponse{}
|
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
errStr := ""
|
errStr := ""
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
errStr = r.Error.Error()
|
errStr = r.Error.Error()
|
||||||
}
|
}
|
||||||
resp.Results = append(resp.Results, &gen.URLTestResp{
|
out.Results = append(out.Results, &gen.URLTestResp{
|
||||||
OutboundTag: To(r.Tag),
|
OutboundTag: To(r.Tag),
|
||||||
LatencyMs: To(int32(r.Duration.Milliseconds())),
|
LatencyMs: To(int32(r.Duration.Milliseconds())),
|
||||||
Error: To(errStr),
|
Error: To(errStr),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return resp, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) QueryStats(ctx context.Context, _ *gen.EmptyReq) (*gen.QueryStatsResp, error) {
|
func (s *server) QueryStats(in *gen.EmptyReq, out *gen.QueryStatsResp) error {
|
||||||
resp := &gen.QueryStatsResp{
|
out.Ups = make(map[string]int64)
|
||||||
Ups: make(map[string]int64),
|
out.Downs = make(map[string]int64)
|
||||||
Downs: make(map[string]int64),
|
|
||||||
}
|
|
||||||
if boxInstance != nil {
|
if boxInstance != nil {
|
||||||
clash := service.FromContext[adapter.ClashServer](boxInstance.Context())
|
clash := service.FromContext[adapter.ClashServer](boxInstance.Context())
|
||||||
if clash != nil {
|
if clash != nil {
|
||||||
cApi, ok := clash.(*clashapi.Server)
|
cApi, ok := clash.(*clashapi.Server)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Println("Failed to assert clash server")
|
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())
|
outbounds := service.FromContext[adapter.OutboundManager](boxInstance.Context())
|
||||||
if outbounds == nil {
|
if outbounds == nil {
|
||||||
log.Println("Failed to get outbound manager")
|
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())
|
endpoints := service.FromContext[adapter.EndpointManager](boxInstance.Context())
|
||||||
if endpoints == nil {
|
if endpoints == nil {
|
||||||
log.Println("Failed to get endpoint manager")
|
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() {
|
for _, ob := range outbounds.Outbounds() {
|
||||||
u, d := cApi.TrafficManager().TotalOutbound(out.Tag())
|
u, d := cApi.TrafficManager().TotalOutbound(ob.Tag())
|
||||||
resp.Ups[out.Tag()] = u
|
out.Ups[ob.Tag()] = u
|
||||||
resp.Downs[out.Tag()] = d
|
out.Downs[ob.Tag()] = d
|
||||||
}
|
}
|
||||||
for _, ep := range endpoints.Endpoints() {
|
for _, ep := range endpoints.Endpoints() {
|
||||||
u, d := cApi.TrafficManager().TotalOutbound(ep.Tag())
|
u, d := cApi.TrafficManager().TotalOutbound(ep.Tag())
|
||||||
resp.Ups[ep.Tag()] = u
|
out.Ups[ep.Tag()] = u
|
||||||
resp.Downs[ep.Tag()] = d
|
out.Downs[ep.Tag()] = d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
return resp, 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 {
|
if boxInstance == nil {
|
||||||
return &gen.ListConnectionsResp{}, nil
|
return nil
|
||||||
}
|
}
|
||||||
if service.FromContext[adapter.ClashServer](boxInstance.Context()) == 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)
|
clash, ok := service.FromContext[adapter.ClashServer](boxInstance.Context()).(*clashapi.Server)
|
||||||
if !ok {
|
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()
|
connections := clash.TrafficManager().Connections()
|
||||||
|
|
||||||
@ -299,16 +292,14 @@ func (s *server) ListConnections(ctx context.Context, in *gen.EmptyReq) (*gen.Li
|
|||||||
}
|
}
|
||||||
res = append(res, r)
|
res = append(res, r)
|
||||||
}
|
}
|
||||||
out := &gen.ListConnectionsResp{
|
out.Connections = res
|
||||||
Connections: res,
|
return nil
|
||||||
}
|
|
||||||
return out, 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")
|
resp, err := boxmain.ListGeoip(*in.Path + string(os.PathSeparator) + "geoip.db")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
res := make([]string, 0)
|
res := make([]string, 0)
|
||||||
@ -317,13 +308,14 @@ func (s *server) GetGeoIPList(ctx context.Context, in *gen.GeoListRequest) (*gen
|
|||||||
res = append(res, r)
|
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")
|
resp, err := boxmain.GeositeList(*in.Path + string(os.PathSeparator) + "geosite.db")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
res := make([]string, 0)
|
res := make([]string, 0)
|
||||||
@ -332,42 +324,43 @@ func (s *server) GetGeoSiteList(ctx context.Context, in *gen.GeoListRequest) (*g
|
|||||||
res = append(res, r)
|
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")
|
category := strings.TrimSuffix(*in.Item, "_IP")
|
||||||
err := boxmain.CompileRuleSet(*in.Path+string(os.PathSeparator)+"geoip.db", category, boxmain.IpRuleSet, "./rule_sets/"+*in.Item+".srs")
|
err := boxmain.CompileRuleSet(*in.Path+string(os.PathSeparator)+"geoip.db", category, boxmain.IpRuleSet, "./rule_sets/"+*in.Item+".srs")
|
||||||
if err != nil {
|
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")
|
category := strings.TrimSuffix(*in.Item, "_SITE")
|
||||||
err := boxmain.CompileRuleSet(*in.Path+string(os.PathSeparator)+"geosite.db", category, boxmain.SiteRuleSet, "./rule_sets/"+*in.Item+".srs")
|
err := boxmain.CompileRuleSet(*in.Path+string(os.PathSeparator)+"geosite.db", category, boxmain.SiteRuleSet, "./rule_sets/"+*in.Item+".srs")
|
||||||
if err != nil {
|
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" {
|
if runtime.GOOS == "windows" {
|
||||||
return &gen.IsPrivilegedResponse{
|
out.HasPrivilege = To(false)
|
||||||
HasPrivilege: To(false),
|
return nil
|
||||||
}, 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 {
|
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 testInstance *boxbox.Box
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
@ -375,16 +368,17 @@ func (s *server) SpeedTest(ctx context.Context, in *gen.SpeedTestRequest) (*gen.
|
|||||||
var err error
|
var err error
|
||||||
if *in.TestCurrent {
|
if *in.TestCurrent {
|
||||||
if boxInstance == nil {
|
if boxInstance == nil {
|
||||||
return &gen.SpeedTestResponse{Results: []*gen.SpeedTestResult{{
|
out.Results = []*gen.SpeedTestResult{{
|
||||||
OutboundTag: To("proxy"),
|
OutboundTag: To("proxy"),
|
||||||
Error: To("Instance is not running"),
|
Error: To("Instance is not running"),
|
||||||
}}}, nil
|
}}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
testInstance = boxInstance
|
testInstance = boxInstance
|
||||||
} else {
|
} else {
|
||||||
testInstance, cancel, err = boxmain.Create([]byte(*in.Config))
|
testInstance, cancel, err = boxmain.Create([]byte(*in.Config))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
defer testInstance.Close()
|
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()
|
res, isRunning := SpTQuerier.Result()
|
||||||
errStr := ""
|
errStr := ""
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
errStr = res.Error.Error()
|
errStr = res.Error.Error()
|
||||||
}
|
}
|
||||||
return &gen.QuerySpeedTestResponse{
|
out.Result = &gen.SpeedTestResult{
|
||||||
Result: &gen.SpeedTestResult{
|
|
||||||
DlSpeed: To(res.DlSpeed),
|
DlSpeed: To(res.DlSpeed),
|
||||||
UlSpeed: To(res.UlSpeed),
|
UlSpeed: To(res.UlSpeed),
|
||||||
Latency: To(res.Latency),
|
Latency: To(res.Latency),
|
||||||
@ -434,7 +428,7 @@ func (s *server) QuerySpeedTest(context.Context, *gen.EmptyReq) (*gen.QuerySpeed
|
|||||||
ServerName: To(res.ServerName),
|
ServerName: To(res.ServerName),
|
||||||
ServerCountry: To(res.ServerCountry),
|
ServerCountry: To(res.ServerCountry),
|
||||||
Cancelled: To(res.Cancelled),
|
Cancelled: To(res.Cancelled),
|
||||||
},
|
}
|
||||||
IsRunning: To(isRunning),
|
out.IsRunning = To(isRunning)
|
||||||
}, nil
|
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 (
|
import (
|
||||||
"Core/gen"
|
"Core/gen"
|
||||||
"Core/internal/boxdns"
|
"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)
|
err := boxdns.DnsManagerInstance.SetSystemDNS(nil, *in.Clear)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gen.EmptyResp{}, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,17 +4,14 @@
|
|||||||
#include "libcore.pb.h"
|
#include "libcore.pb.h"
|
||||||
#endif
|
#endif
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include "3rdparty/protorpc/rpc_client.h"
|
||||||
namespace QtGrpc {
|
|
||||||
class Http2GrpcChannelPrivate;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace API {
|
namespace API {
|
||||||
enum GeoRuleSetType {ip, site};
|
enum GeoRuleSetType {ip, site};
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
public:
|
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
|
// QString returns is error string
|
||||||
|
|
||||||
@ -47,8 +44,7 @@ namespace API {
|
|||||||
libcore::QuerySpeedTestResponse QueryCurrentSpeedTests(bool *rpcOK);
|
libcore::QuerySpeedTestResponse QueryCurrentSpeedTests(bool *rpcOK);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<std::unique_ptr<QtGrpc::Http2GrpcChannelPrivate>()> make_grpc_channel;
|
std::function<std::unique_ptr<protorpc::Client>()> make_rpc_client;
|
||||||
std::unique_ptr<QtGrpc::Http2GrpcChannelPrivate> default_grpc_channel;
|
|
||||||
std::function<void(const QString &)> onError;
|
std::function<void(const QString &)> onError;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ popd
|
|||||||
#### Go: core ####
|
#### Go: core ####
|
||||||
pushd core/server
|
pushd core/server
|
||||||
pushd gen
|
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
|
popd
|
||||||
VERSION_SINGBOX=$(go list -m -f '{{.Version}}' github.com/sagernet/sing-box)
|
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"
|
$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/dataStore/Database.hpp"
|
||||||
#include "include/configs/proxy/includes.h"
|
#include "include/configs/proxy/includes.h"
|
||||||
#include "include/configs/proxy/Preset.hpp"
|
#include "include/configs/proxy/Preset.hpp"
|
||||||
#include "include/api/gRPC.h"
|
#include "include/api/RPC.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <include/api/gRPC.h>
|
#include <include/api/RPC.h>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include "include/sys/windows/guihelper.h"
|
#include "include/sys/windows/guihelper.h"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <libcore.pb.h>
|
#include <libcore.pb.h>
|
||||||
#include <include/api/gRPC.h>
|
#include <include/api/RPC.h>
|
||||||
#include "include/ui/mainwindow_interface.h"
|
#include "include/ui/mainwindow_interface.h"
|
||||||
#include <include/stats/connections/connectionLister.hpp>
|
#include <include/stats/connections/connectionLister.hpp>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include "include/stats/traffic/TrafficLooper.hpp"
|
#include "include/stats/traffic/TrafficLooper.hpp"
|
||||||
|
|
||||||
#include "include/api/gRPC.h"
|
#include "include/api/RPC.h"
|
||||||
#include "include/ui/mainwindow_interface.h"
|
#include "include/ui/mainwindow_interface.h"
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|||||||
@ -53,7 +53,6 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
#include <3rdparty/QHotkey/qhotkey.h>
|
#include <3rdparty/QHotkey/qhotkey.h>
|
||||||
#include <3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp>
|
#include <3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp>
|
||||||
#include <include/api/gRPC.h>
|
|
||||||
#include <include/global/HTTPRequestHelper.hpp>
|
#include <include/global/HTTPRequestHelper.hpp>
|
||||||
|
|
||||||
#include "include/sys/macos/MacOS.h"
|
#include "include/sys/macos/MacOS.h"
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
#include "include/dataStore/Database.hpp"
|
#include "include/dataStore/Database.hpp"
|
||||||
#include "include/configs/ConfigBuilder.hpp"
|
#include "include/configs/ConfigBuilder.hpp"
|
||||||
#include "include/stats/traffic/TrafficLooper.hpp"
|
#include "include/stats/traffic/TrafficLooper.hpp"
|
||||||
#include "include/api/gRPC.h"
|
#include "include/api/RPC.h"
|
||||||
#include "include/ui/utils//MessageBoxTimer.h"
|
#include "include/ui/utils//MessageBoxTimer.h"
|
||||||
#include "3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp"
|
#include "3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp"
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ void MainWindow::setup_grpc() {
|
|||||||
[=](const QString &errStr) {
|
[=](const QString &errStr) {
|
||||||
MW_show_log("[Error] Core: " + 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
|
// Looper
|
||||||
runOnNewThread([=] { Stats::trafficLooper->Loop(); });
|
runOnNewThread([=] { Stats::trafficLooper->Loop(); });
|
||||||
@ -64,7 +64,7 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
|
|||||||
{
|
{
|
||||||
int entid = -1;
|
int entid = -1;
|
||||||
if (!tag2entID.empty()) {
|
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) {
|
if (entid == -1) {
|
||||||
continue;
|
continue;
|
||||||
@ -76,11 +76,11 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
|
|||||||
if (res.error.value().empty()) {
|
if (res.error.value().empty()) {
|
||||||
ent->latency = res.latency_ms.value();
|
ent->latency = res.latency_ms.value();
|
||||||
} else {
|
} else {
|
||||||
if (QString(res.error.value().c_str()).contains("test aborted") ||
|
if (QString::fromStdString(res.error.value()).contains("test aborted") ||
|
||||||
QString(res.error.value().c_str()).contains("context canceled")) ent->latency=0;
|
QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0;
|
||||||
else {
|
else {
|
||||||
ent->latency = -1;
|
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();
|
ent->Save();
|
||||||
@ -104,7 +104,7 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
|
|||||||
|
|
||||||
for (const auto &res: result.results) {
|
for (const auto &res: result.results) {
|
||||||
if (!tag2entID.empty()) {
|
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) {
|
if (entID == -1) {
|
||||||
MW_show_log(tr("Something is very wrong, the subject ent cannot be found!"));
|
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()) {
|
if (res.error.value().empty()) {
|
||||||
ent->latency = res.latency_ms.value();
|
ent->latency = res.latency_ms.value();
|
||||||
} else {
|
} else {
|
||||||
if (QString(res.error.value().c_str()).contains("test aborted") ||
|
if (QString::fromStdString(res.error.value()).contains("test aborted") ||
|
||||||
QString(res.error.value().c_str()).contains("context canceled")) ent->latency=0;
|
QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0;
|
||||||
else {
|
else {
|
||||||
ent->latency = -1;
|
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();
|
ent->Save();
|
||||||
@ -212,7 +212,7 @@ void MainWindow::url_test_current() {
|
|||||||
|
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] {
|
||||||
if (!result.results[0].error.value().empty()) {
|
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) {
|
if (latency <= 0) {
|
||||||
ui->label_running->setText(tr("Test Result") + ": " + tr("Unavailable"));
|
ui->label_running->setText(tr("Test Result") + ": " + tr("Unavailable"));
|
||||||
@ -304,7 +304,7 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, bool testC
|
|||||||
{
|
{
|
||||||
continue;
|
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)
|
if (profile == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
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().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().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 = res.result.value().ul_speed.value().c_str();
|
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();
|
if (profile->latency <= 0 && res.result.value().latency.value() > 0) profile->latency = res.result.value().latency.value();
|
||||||
refresh_proxy_list(profile->id);
|
refresh_proxy_list(profile->id);
|
||||||
lastProxyListUpdate = QDateTime::currentDateTime();
|
lastProxyListUpdate = QDateTime::currentDateTime();
|
||||||
@ -343,7 +343,7 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, bool testC
|
|||||||
for (const auto &res: result.results) {
|
for (const auto &res: result.results) {
|
||||||
if (testCurrent) entID = running ? running->id : -1;
|
if (testCurrent) entID = running ? running->id : -1;
|
||||||
else {
|
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) {
|
if (entID == -1) {
|
||||||
MW_show_log(tr("Something is very wrong, the subject ent cannot be found!"));
|
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.cancelled.value()) continue;
|
||||||
|
|
||||||
if (res.error.value().empty()) {
|
if (res.error.value().empty()) {
|
||||||
ent->dl_speed = res.dl_speed.value().c_str();
|
ent->dl_speed = QString::fromStdString(res.dl_speed.value());
|
||||||
ent->ul_speed = res.ul_speed.value().c_str();
|
ent->ul_speed = QString::fromStdString(res.ul_speed.value());
|
||||||
if (ent->latency <= 0 && res.latency.value() > 0) ent->latency = res.latency.value();
|
if (ent->latency <= 0 && res.latency.value() > 0) ent->latency = res.latency.value();
|
||||||
} else {
|
} else {
|
||||||
ent->dl_speed = "N/A";
|
ent->dl_speed = "N/A";
|
||||||
ent->ul_speed = "N/A";
|
ent->ul_speed = "N/A";
|
||||||
ent->latency = -1;
|
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();
|
ent->Save();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include "include/ui/setting/RouteItem.h"
|
#include "include/ui/setting/RouteItem.h"
|
||||||
#include "include/dataStore/RouteEntity.h"
|
#include "include/dataStore/RouteEntity.h"
|
||||||
#include "include/dataStore/Database.hpp"
|
#include "include/dataStore/Database.hpp"
|
||||||
#include "include/api/gRPC.h"
|
#include "include/api/RPC.h"
|
||||||
|
|
||||||
void adjustComboBoxWidth(const QComboBox *comboBox) {
|
void adjustComboBoxWidth(const QComboBox *comboBox) {
|
||||||
int maxWidth = 0;
|
int maxWidth = 0;
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
#include <include/api/gRPC.h>
|
#include <include/api/RPC.h>
|
||||||
|
|
||||||
void DialogManageRoutes::reloadProfileItems() {
|
void DialogManageRoutes::reloadProfileItems() {
|
||||||
if (chainList.empty()) {
|
if (chainList.empty()) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user