commit fd6441d247937eeca4128cef644002c1c544936a Author: yangzuhao Date: Wed Dec 14 19:05:52 2022 +0800 编译mac版brpc静态库 diff --git a/README.md b/README.md new file mode 100644 index 0000000..60da39f --- /dev/null +++ b/README.md @@ -0,0 +1,148 @@ +# 测试demo cmakelist + +```cmakelist +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +cmake_minimum_required(VERSION 2.8.10) +project(echo_c++ C CXX) + +option(LINK_SO "Whether examples are linked dynamically" OFF) + +execute_process( + COMMAND bash -c "find ${PROJECT_SOURCE_DIR}/../.. -type d -regex \".*output/include$\" | head -n1 | xargs dirname | tr -d '\n'" + OUTPUT_VARIABLE OUTPUT_PATH +) + +set(CMAKE_PREFIX_PATH ${OUTPUT_PATH}) + +include(FindThreads) +include(FindProtobuf) +protobuf_generate_cpp(PROTO_SRC PROTO_HEADER echo.proto) +# include PROTO_HEADER +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Search for libthrift* by best effort. If it is not found and brpc is +# compiled with thrift protocol enabled, a link error would be reported. +find_library(THRIFT_LIB NAMES thrift) +if (NOT THRIFT_LIB) + set(THRIFT_LIB "") +endif() +find_library(THRIFTNB_LIB NAMES thriftnb) +if (NOT THRIFTNB_LIB) + set(THRIFTNB_LIB "") +endif() + +find_path(BRPC_INCLUDE_PATH NAMES brpc/server.h) +if(LINK_SO) + find_library(BRPC_LIB NAMES brpc) +else() + find_library(BRPC_LIB NAMES libbrpc.a brpc) +endif() +if((NOT BRPC_INCLUDE_PATH) OR (NOT BRPC_LIB)) + message(FATAL_ERROR "Fail to find brpc") +endif() +include_directories(${BRPC_INCLUDE_PATH}) + +find_path(GFLAGS_INCLUDE_PATH gflags/gflags.h) +find_library(GFLAGS_LIBRARY NAMES gflags libgflags) +if((NOT GFLAGS_INCLUDE_PATH) OR (NOT GFLAGS_LIBRARY)) + message(FATAL_ERROR "Fail to find gflags") +endif() +include_directories(${GFLAGS_INCLUDE_PATH}) + +execute_process( + COMMAND bash -c "grep \"namespace [_A-Za-z0-9]\\+ {\" ${GFLAGS_INCLUDE_PATH}/gflags/gflags_declare.h | head -1 | awk '{print $2}' | tr -d '\n'" + OUTPUT_VARIABLE GFLAGS_NS +) +if(${GFLAGS_NS} STREQUAL "GFLAGS_NAMESPACE") + execute_process( + COMMAND bash -c "grep \"#define GFLAGS_NAMESPACE [_A-Za-z0-9]\\+\" ${GFLAGS_INCLUDE_PATH}/gflags/gflags_declare.h | head -1 | awk '{print $3}' | tr -d '\n'" + OUTPUT_VARIABLE GFLAGS_NS + ) +endif() +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + include(CheckFunctionExists) + CHECK_FUNCTION_EXISTS(clock_gettime HAVE_CLOCK_GETTIME) + if(NOT HAVE_CLOCK_GETTIME) + set(DEFINE_CLOCK_GETTIME "-DNO_CLOCK_GETTIME_IN_MAC") + endif() +endif() + +set(CMAKE_CPP_FLAGS "${DEFINE_CLOCK_GETTIME} -DGFLAGS_NS=${GFLAGS_NS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CPP_FLAGS} -DNDEBUG -O2 -D__const__=__unused__ -pipe -W -Wall -Wno-unused-parameter -fPIC -fno-omit-frame-pointer") + +if(CMAKE_VERSION VERSION_LESS "3.1.3") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() +else() + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() + +find_path(LEVELDB_INCLUDE_PATH NAMES leveldb/db.h) +find_library(LEVELDB_LIB NAMES leveldb) +if ((NOT LEVELDB_INCLUDE_PATH) OR (NOT LEVELDB_LIB)) + message(FATAL_ERROR "Fail to find leveldb") +endif() +include_directories(${LEVELDB_INCLUDE_PATH}) + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(OPENSSL_ROOT_DIR + "/usr/local/opt/openssl" # Homebrew installed OpenSSL + ) +endif() + +find_package(OpenSSL) +include_directories(${OPENSSL_INCLUDE_DIR}) + +set(DYNAMIC_LIB + ${CMAKE_THREAD_LIBS_INIT} + ${GFLAGS_LIBRARY} + ${PROTOBUF_LIBRARIES} + ${LEVELDB_LIB} + ${OPENSSL_CRYPTO_LIBRARY} + ${OPENSSL_SSL_LIBRARY} + ${THRIFT_LIB} + ${THRIFTNB_LIB} + dl + ) + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(DYNAMIC_LIB ${DYNAMIC_LIB} + pthread + "-framework CoreFoundation" + "-framework CoreGraphics" + "-framework CoreData" + "-framework CoreText" + "-framework Security" + "-framework Foundation" + "-Wl,-U,_MallocExtension_ReleaseFreeMemory" + "-Wl,-U,_ProfilerStart" + "-Wl,-U,_ProfilerStop") +endif() + +add_executable(echo_client client.cpp ${PROTO_SRC} ${PROTO_HEADER}) +add_executable(echo_server server.cpp ${PROTO_SRC} ${PROTO_HEADER}) + +target_link_libraries(echo_client ${BRPC_LIB} ${DYNAMIC_LIB}) +target_link_libraries(echo_server ${BRPC_LIB} ${DYNAMIC_LIB}) +``` diff --git a/bin/protoc-gen-mcpack b/bin/protoc-gen-mcpack new file mode 100755 index 0000000..305f4af Binary files /dev/null and b/bin/protoc-gen-mcpack differ diff --git a/include/brpc/acceptor.h b/include/brpc/acceptor.h new file mode 100644 index 0000000..c442a60 --- /dev/null +++ b/include/brpc/acceptor.h @@ -0,0 +1,118 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#ifndef BRPC_ACCEPTOR_H +#define BRPC_ACCEPTOR_H + +#include "bthread/bthread.h" // bthread_t +#include "butil/synchronization/condition_variable.h" +#include "butil/containers/flat_map.h" +#include "brpc/input_messenger.h" + + +namespace brpc { + +struct ConnectStatistics { +}; + +// Accept connections from a specific port and then +// process messages from which it reads +class Acceptor : public InputMessenger { +friend class Server; +public: + typedef butil::FlatMap SocketMap; + + enum Status { + UNINITIALIZED = 0, + READY = 1, + RUNNING = 2, + STOPPING = 3, + }; + +public: + explicit Acceptor(bthread_keytable_pool_t* pool = NULL); + ~Acceptor(); + + // [thread-safe] Accept connections from `listened_fd'. Ownership of + // `listened_fd' is also transferred to `Acceptor'. Can be called + // multiple times if the last `StartAccept' has been completely stopped + // by calling `StopAccept' and `Join'. Connections that has no data + // transmission for `idle_timeout_sec' will be closed automatically iff + // `idle_timeout_sec' > 0 + // Return 0 on success, -1 otherwise. + int StartAccept(int listened_fd, int idle_timeout_sec, + const std::shared_ptr& ssl_ctx); + + // [thread-safe] Stop accepting connections. + // `closewait_ms' is not used anymore. + void StopAccept(int /*closewait_ms*/); + + // Wait until all existing Sockets(defined in socket.h) are recycled. + void Join(); + + // The parameter to StartAccept. Negative when acceptor is stopped. + int listened_fd() const { return _listened_fd; } + + // Get number of existing connections. + size_t ConnectionCount() const; + + // Clear `conn_list' and append all connections into it. + void ListConnections(std::vector* conn_list); + + // Clear `conn_list' and append all most `max_copied' connections into it. + void ListConnections(std::vector* conn_list, size_t max_copied); + + Status status() const { return _status; } + +private: + // Accept connections. + static void OnNewConnectionsUntilEAGAIN(Socket* m); + static void OnNewConnections(Socket* m); + + static void* CloseIdleConnections(void* arg); + + // Initialize internal structure. + int Initialize(); + + // Remove the accepted socket `sock' from inside + void BeforeRecycle(Socket* sock) override; + + bthread_keytable_pool_t* _keytable_pool; // owned by Server + Status _status; + int _idle_timeout_sec; + bthread_t _close_idle_tid; + + int _listened_fd; + // The Socket tso accept connections. + SocketId _acception_id; + + butil::Mutex _map_mutex; + butil::ConditionVariable _empty_cond; + + // The map containing all the accepted sockets + SocketMap _socket_map; + + std::shared_ptr _ssl_ctx; + + // Whether to use rdma or not + bool _use_rdma; +}; + +} // namespace brpc + + +#endif // BRPC_ACCEPTOR_H diff --git a/include/brpc/adaptive_connection_type.h b/include/brpc/adaptive_connection_type.h new file mode 100644 index 0000000..36a4954 --- /dev/null +++ b/include/brpc/adaptive_connection_type.h @@ -0,0 +1,70 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +#ifndef BRPC_ADAPTIVE_CONNECTION_TYPE_H +#define BRPC_ADAPTIVE_CONNECTION_TYPE_H + +// To brpc developers: This is a header included by user, don't depend +// on internal structures, use opaque pointers instead. + +#include "butil/strings/string_piece.h" +#include "brpc/options.pb.h" + +namespace brpc { + +// Convert a case-insensitive string to corresponding ConnectionType +// Possible options are: short, pooled, single +// Returns: CONNECTION_TYPE_UNKNOWN on error. +ConnectionType StringToConnectionType(const butil::StringPiece& type, + bool print_log_on_unknown); +inline ConnectionType StringToConnectionType(const butil::StringPiece& type) +{ return StringToConnectionType(type, true); } + +// Convert a ConnectionType to a c-style string. +const char* ConnectionTypeToString(ConnectionType); + +// Assignable by both ConnectionType and names. +class AdaptiveConnectionType { +public: + AdaptiveConnectionType() : _type(CONNECTION_TYPE_UNKNOWN), _error(false) {} + AdaptiveConnectionType(ConnectionType type) : _type(type), _error(false) {} + ~AdaptiveConnectionType() {} + + void operator=(ConnectionType type) { + _type = type; + _error = false; + } + void operator=(const butil::StringPiece& name); + + operator ConnectionType() const { return _type; } + const char* name() const { return ConnectionTypeToString(_type); } + bool has_error() const { return _error; } + +private: + ConnectionType _type; + // Since this structure occupies 8 bytes in 64-bit machines anyway, + // we add a field to mark if last operator=(name) failed so that + // channel can print a error log before re-selecting a valid + // ConnectionType for user. + bool _error; +}; + +} // namespace brpc + + +#endif // BRPC_ADAPTIVE_CONNECTION_TYPE_H diff --git a/include/brpc/adaptive_max_concurrency.h b/include/brpc/adaptive_max_concurrency.h new file mode 100644 index 0000000..46af414 --- /dev/null +++ b/include/brpc/adaptive_max_concurrency.h @@ -0,0 +1,92 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#ifndef BRPC_ADAPTIVE_MAX_CONCURRENCY_H +#define BRPC_ADAPTIVE_MAX_CONCURRENCY_H + +// To brpc developers: This is a header included by user, don't depend +// on internal structures, use opaque pointers instead. + +#include "butil/strings/string_piece.h" +#include "brpc/options.pb.h" + +namespace brpc { + +class AdaptiveMaxConcurrency{ +public: + explicit AdaptiveMaxConcurrency(); + explicit AdaptiveMaxConcurrency(int max_concurrency); + explicit AdaptiveMaxConcurrency(const butil::StringPiece& value); + + // Non-trivial destructor to prevent AdaptiveMaxConcurrency from being + // passed to variadic arguments without explicit type conversion. + // eg: + // printf("%d", options.max_concurrency) // compile error + // printf("%s", options.max_concurrency.value().c_str()) // ok + ~AdaptiveMaxConcurrency() {} + + void operator=(int max_concurrency); + void operator=(const butil::StringPiece& value); + + // 0 for type="unlimited" + // >0 for type="constant" + // <0 for type="user-defined" + operator int() const { return _max_concurrency; } + + // "unlimited" for type="unlimited" + // "10" "20" "30" for type="constant" + // "user-defined" for type="user-defined" + const std::string& value() const { return _value; } + + // "unlimited", "constant" or "user-defined" + const std::string& type() const; + + // Get strings filled with "unlimited" and "constant" + static const std::string& UNLIMITED(); + static const std::string& CONSTANT(); + +private: + std::string _value; + int _max_concurrency; +}; + +inline std::ostream& operator<<(std::ostream& os, const AdaptiveMaxConcurrency& amc) { + return os << amc.value(); +} + +bool operator==(const AdaptiveMaxConcurrency& adaptive_concurrency, + const butil::StringPiece& concurrency); + +inline bool operator==(const butil::StringPiece& concurrency, + const AdaptiveMaxConcurrency& adaptive_concurrency) { + return adaptive_concurrency == concurrency; +} + +inline bool operator!=(const AdaptiveMaxConcurrency& adaptive_concurrency, + const butil::StringPiece& concurrency) { + return !(adaptive_concurrency == concurrency); +} + +inline bool operator!=(const butil::StringPiece& concurrency, + const AdaptiveMaxConcurrency& adaptive_concurrency) { + return !(adaptive_concurrency == concurrency); +} + +} // namespace brpc + + +#endif // BRPC_ADAPTIVE_MAX_CONCURRENCY_H diff --git a/include/brpc/adaptive_protocol_type.h b/include/brpc/adaptive_protocol_type.h new file mode 100644 index 0000000..666654e --- /dev/null +++ b/include/brpc/adaptive_protocol_type.h @@ -0,0 +1,92 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#ifndef BRPC_ADAPTIVE_PROTOCOL_TYPE_H +#define BRPC_ADAPTIVE_PROTOCOL_TYPE_H + +// To brpc developers: This is a header included by user, don't depend +// on internal structures, use opaque pointers instead. + +#include "butil/strings/string_piece.h" +#include "brpc/options.pb.h" + +namespace brpc { + +// NOTE: impl. are in brpc/protocol.cpp + +// Convert a case-insensitive string to corresponding ProtocolType which is +// defined in src/brpc/options.proto +// Returns: PROTOCOL_UNKNOWN on error. +ProtocolType StringToProtocolType(const butil::StringPiece& type, + bool print_log_on_unknown); +inline ProtocolType StringToProtocolType(const butil::StringPiece& type) +{ return StringToProtocolType(type, true); } + +// Convert a ProtocolType to a c-style string. +const char* ProtocolTypeToString(ProtocolType); + +// Assignable by both ProtocolType and names. +class AdaptiveProtocolType { +public: + explicit AdaptiveProtocolType() : _type(PROTOCOL_UNKNOWN) {} + explicit AdaptiveProtocolType(ProtocolType type) : _type(type) {} + ~AdaptiveProtocolType() {} + + void operator=(ProtocolType type) { + _type = type; + _name.clear(); + _param.clear(); + } + + void operator=(butil::StringPiece name) { + butil::StringPiece param; + const size_t pos = name.find(':'); + if (pos != butil::StringPiece::npos) { + param = name.substr(pos + 1); + name.remove_suffix(name.size() - pos); + } + _type = StringToProtocolType(name); + if (_type == PROTOCOL_UNKNOWN) { + _name.assign(name.data(), name.size()); + } else { + _name.clear(); + } + if (!param.empty()) { + _param.assign(param.data(), param.size()); + } else { + _param.clear(); + } + }; + + operator ProtocolType() const { return _type; } + + const char* name() const { + return _name.empty() ? ProtocolTypeToString(_type) : _name.c_str(); + } + + bool has_param() const { return !_param.empty(); } + const std::string& param() const { return _param; } + +private: + ProtocolType _type; + std::string _name; + std::string _param; +}; + +} // namespace brpc + +#endif // BRPC_ADAPTIVE_PROTOCOL_TYPE_H diff --git a/include/brpc/amf.h b/include/brpc/amf.h new file mode 100644 index 0000000..e9777e8 --- /dev/null +++ b/include/brpc/amf.h @@ -0,0 +1,304 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +#ifndef BRPC_AMF_H +#define BRPC_AMF_H + +#include +#include +#include +#include +#include "butil/sys_byteorder.h" +#include "butil/strings/string_piece.h" + + +namespace brpc { + +// For parsing and serializing Action Message Format used throughout RTMP. + +// Buffer ZeroCopyInputStream as efficient input of parsing AMF. +class AMFInputStream { +public: + AMFInputStream(google::protobuf::io::ZeroCopyInputStream* stream) + : _good(true) + , _size(0) + , _data(NULL) + , _zc_stream(stream) + , _popped_bytes(0) + {} + + ~AMFInputStream() { } + + // Cut off at-most n bytes from front side and copy to `out'. + // Returns bytes cut. + size_t cutn(void* out, size_t n); + + size_t cut_u8(uint8_t* u16); + size_t cut_u16(uint16_t* u16); + size_t cut_u32(uint32_t* u32); + size_t cut_u64(uint64_t* u64); + + // Returns bytes popped and cut since creation of this stream. + size_t popped_bytes() const { return _popped_bytes; } + + // Returns false if error occurred in other consuming functions. + bool good() const { return _good; } + + // If the error prevents parsing from going on, call this method. + // This method is also called in other functions in this class. + void set_bad() { _good = false; } + + // Return true if the stream is empty. Notice that this function + // may update _data and _size. + bool check_emptiness(); + +private: + bool _good; + int _size; + const void* _data; + google::protobuf::io::ZeroCopyInputStream* _zc_stream; + size_t _popped_bytes; +}; + +// Buffer serialize data of AMF to ZeroCopyOutputStream +class AMFOutputStream { +public: + AMFOutputStream(google::protobuf::io::ZeroCopyOutputStream* stream) + : _good(true) + , _size(0) + , _data(NULL) + , _zc_stream(stream) + , _pushed_bytes(0) + {} + + ~AMFOutputStream() { done(); } + + // Append n bytes. + void putn(const void* data, int n); + + void put_u8(uint8_t u16); + void put_u16(uint16_t u16); + void put_u32(uint32_t u32); + void put_u64(uint64_t u64); + + // Returns bytes pushed and cut since creation of this stream. + size_t pushed_bytes() const { return _pushed_bytes; } + + // Returns false if error occurred during serialization. + bool good() { return _good; } + + void set_bad() { _good = false; } + + // Optionally called to backup buffered bytes to zero-copy stream. + void done(); + +private: + bool _good; + int _size; + void* _data; + google::protobuf::io::ZeroCopyOutputStream* _zc_stream; + size_t _pushed_bytes; +}; + +// There are 16 core type markers in AMF 0. A type marker is one byte in +// length and describes the kind of encoded data that may follow. +enum AMFMarker { + AMF_MARKER_NUMBER = 0x00, + AMF_MARKER_BOOLEAN = 0x01, + AMF_MARKER_STRING = 0x02, + AMF_MARKER_OBJECT = 0x03, + AMF_MARKER_MOVIECLIP = 0x04, + AMF_MARKER_NULL = 0x05, + AMF_MARKER_UNDEFINED = 0x06, + AMF_MARKER_REFERENCE = 0x07, + AMF_MARKER_ECMA_ARRAY = 0x08, + AMF_MARKER_OBJECT_END = 0x09, + AMF_MARKER_STRICT_ARRAY = 0x0A, + AMF_MARKER_DATE = 0x0B, + AMF_MARKER_LONG_STRING = 0x0C, + AMF_MARKER_UNSUPPORTED = 0x0D, + AMF_MARKER_RECORDSET = 0x0E, + AMF_MARKER_XML_DOCUMENT = 0x0F, + AMF_MARKER_TYPED_OBJECT = 0x10, + AMF_MARKER_AVMPLUS_OBJECT = 0x11 +}; + +const char* marker2str(AMFMarker marker); +const char* marker2str(uint8_t marker); + +class AMFObject; +class AMFArray; + +// A field inside a AMF object. +class AMFField { +friend class AMFObject; +public: + static const size_t SSO_LIMIT = 8; + + AMFField(); + AMFField(const AMFField&); + AMFField& operator=(const AMFField&); + ~AMFField() { Clear(); } + void Clear() { if (_type != AMF_MARKER_UNDEFINED) { SlowerClear(); } } + + AMFMarker type() const { return (AMFMarker)_type; } + + bool IsString() const + { return _type == AMF_MARKER_STRING || _type == AMF_MARKER_LONG_STRING; } + bool IsBool() const { return _type == AMF_MARKER_BOOLEAN; } + bool IsNumber() const { return _type == AMF_MARKER_NUMBER; } + bool IsObject() const + { return _type == AMF_MARKER_OBJECT || _type == AMF_MARKER_ECMA_ARRAY; } + bool IsArray() const { return _type == AMF_MARKER_STRICT_ARRAY; } + + butil::StringPiece AsString() const + { return butil::StringPiece((_is_shortstr ? _shortstr : _str), _strsize); } + bool AsBool() const { return _b; } + double AsNumber() const { return _num; } + const AMFObject& AsObject() const { return *_obj; } + const AMFArray& AsArray() const { return *_arr; } + + void SetString(const butil::StringPiece& str); + void SetBool(bool val); + void SetNumber(double val); + void SetNull(); + void SetUndefined(); + void SetUnsupported(); + AMFObject* MutableObject(); + AMFArray* MutableArray(); + +private: + void SlowerClear(); + + uint8_t _type; + bool _is_shortstr; + uint32_t _strsize; + union { + double _num; + char* _str; + char _shortstr[SSO_LIMIT]; // SSO + bool _b; + AMFObject* _obj; + AMFArray* _arr; + }; +}; +std::ostream& operator<<(std::ostream& os, const AMFField& field); + +// A general AMF object. +class AMFObject { +public: + typedef std::map::iterator iterator; + typedef std::map::const_iterator const_iterator; + + const AMFField* Find(const char* name) const; + void Remove(const std::string& name) { _fields.erase(name); } + void Clear() { _fields.clear(); } + + void SetString(const std::string& name, const butil::StringPiece& val); + void SetBool(const std::string& name, bool val); + void SetNumber(const std::string& name, double val); + void SetNull(const std::string& name); + void SetUndefined(const std::string& name); + void SetUnsupported(const std::string& name); + AMFObject* MutableObject(const std::string& name); + AMFArray* MutableArray(const std::string& name); + + iterator begin() { return _fields.begin(); } + const_iterator begin() const { return _fields.begin(); } + iterator end() { return _fields.end(); } + const_iterator end() const { return _fields.end(); } + +private: + std::map _fields; +}; +std::ostream& operator<<(std::ostream& os, const AMFObject&); + +// An AMF strict array (not ecma array) +class AMFArray { +public: + AMFArray(); + AMFArray(const AMFArray&); + AMFArray& operator=(const AMFArray&); + ~AMFArray() { Clear(); } + void Clear(); + + const AMFField& operator[](size_t index) const; + AMFField& operator[](size_t index); + size_t size() const { return _size; } + + void AddString(const butil::StringPiece& val) { AddField()->SetString(val); } + void AddBool(bool val) { AddField()->SetBool(val); } + void AddNumber(double val) { AddField()->SetNumber(val); } + void AddNull() { AddField()->SetNull(); } + void AddUndefined() { AddField()->SetUndefined(); } + void AddUnsupported() { AddField()->SetUnsupported(); } + AMFObject* AddObject() { return AddField()->MutableObject(); } + AMFArray* AddArray() { return AddField()->MutableArray(); } + +private: + AMFField* AddField(); + void RemoveLastField(); + + uint32_t _size; + AMFField _fields[4]; + std::deque _morefields; +}; +std::ostream& operator<<(std::ostream& os, const AMFArray&); + +inline const AMFField& AMFArray::operator[](size_t index) const { + return (index < arraysize(_fields) ? _fields[index] : + _morefields[index - arraysize(_fields)]); +} +inline AMFField& AMFArray::operator[](size_t index) { + return (index < arraysize(_fields) ? _fields[index] : + _morefields[index - arraysize(_fields)]); +} + +// Parse types of the stream. +bool ReadAMFString(std::string* val, AMFInputStream* stream); +bool ReadAMFBool(bool* val, AMFInputStream* stream); +bool ReadAMFNumber(double* val, AMFInputStream* stream); +bool ReadAMFUint32(uint32_t* val, AMFInputStream* stream); +bool ReadAMFNull(AMFInputStream* stream); +bool ReadAMFUndefined(AMFInputStream* stream); +bool ReadAMFUnsupported(AMFInputStream* stream); +// The pb version just loads known fields (defined in proto) +bool ReadAMFObject(google::protobuf::Message* msg, AMFInputStream* stream); +bool ReadAMFObject(AMFObject* obj, AMFInputStream* stream); +bool ReadAMFArray(AMFArray* arr, AMFInputStream* stream); + +// Serialize types into the stream. +// Check stream->good() for successfulness after one or multiple WriteAMFxxx. +void WriteAMFString(const butil::StringPiece& val, AMFOutputStream* stream); +void WriteAMFBool(bool val, AMFOutputStream* stream); +void WriteAMFNumber(double val, AMFOutputStream* stream); +void WriteAMFUint32(uint32_t val, AMFOutputStream* stream); +void WriteAMFNull(AMFOutputStream* stream); +void WriteAMFUndefined(AMFOutputStream* stream); +void WriteAMFUnsupported(AMFOutputStream* stream); +void WriteAMFObject(const google::protobuf::Message& msg, + AMFOutputStream* stream); +void WriteAMFObject(const AMFObject& obj, AMFOutputStream* stream); +void WriteAMFArray(const AMFArray& arr, AMFOutputStream* stream); + +} // namespace brpc + + +#include "brpc/amf_inl.h" + +#endif // BRPC_AMF_H diff --git a/include/brpc/amf_inl.h b/include/brpc/amf_inl.h new file mode 100644 index 0000000..d9d3a56 --- /dev/null +++ b/include/brpc/amf_inl.h @@ -0,0 +1,171 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +#ifndef BRPC_AMF_INL_H +#define BRPC_AMF_INL_H + +void* fast_memcpy(void *__restrict dest, const void *__restrict src, size_t n); + + +namespace brpc { + +inline size_t AMFInputStream::cutn(void* out, size_t n) { + const size_t saved_n = n; + do { + if (_size >= (int64_t)n) { + memcpy(out, _data, n); + _data = (const char*)_data + n; + _size -= n; + _popped_bytes += saved_n; + return saved_n; + } + if (_size) { + memcpy(out, _data, _size); + out = (char*)out + _size; + n -= _size; + } + } while (_zc_stream->Next(&_data, &_size)); + _data = NULL; + _size = 0; + _popped_bytes += saved_n - n; + return saved_n - n; +} + +inline bool AMFInputStream::check_emptiness() { + return _size == 0 && !_zc_stream->Next(&_data, &_size); +} + +inline size_t AMFInputStream::cut_u8(uint8_t* val) { + if (_size >= 1) { + *val = *(uint8_t*)_data; + _data = (const char*)_data + 1; + _size -= 1; + _popped_bytes += 1; + return 1; + } + return cutn(val, 1); +} + +inline size_t AMFInputStream::cut_u16(uint16_t* val) { + if (_size >= 2) { + const uint16_t netval = *(uint16_t*)_data; + *val = butil::NetToHost16(netval); + _data = (const char*)_data + 2; + _size -= 2; + _popped_bytes += 2; + return 2; + } + uint16_t netval = 0; + const size_t ret = cutn(&netval, 2); + *val = butil::NetToHost16(netval); + return ret; +} + +inline size_t AMFInputStream::cut_u32(uint32_t* val) { + if (_size >= 4) { + const uint32_t netval = *(uint32_t*)_data; + *val = butil::NetToHost32(netval); + _data = (const char*)_data + 4; + _size -= 4; + _popped_bytes += 4; + return 4; + } + uint32_t netval = 0; + const size_t ret = cutn(&netval, 4); + *val = butil::NetToHost32(netval); + return ret; +} + +inline size_t AMFInputStream::cut_u64(uint64_t* val) { + if (_size >= 8) { + const uint64_t netval = *(uint64_t*)_data; + *val = butil::NetToHost64(netval); + _data = (const char*)_data + 8; + _size -= 8; + _popped_bytes += 8; + return 8; + } + uint64_t netval = 0; + const size_t ret = cutn(&netval, 8); + *val = butil::NetToHost64(netval); + return ret; +} + +inline void AMFOutputStream::done() { + if (_good && _size) { + _zc_stream->BackUp(_size); + _size = 0; + } +} + +inline void AMFOutputStream::putn(const void* data, int n) { + const int saved_n = n; + do { + if (n <= _size) { + fast_memcpy(_data, data, n); + _data = (char*)_data + n; + _size -= n; + _pushed_bytes += saved_n; + return; + } + fast_memcpy(_data, data, _size); + data = (const char*)data + _size; + n -= _size; + } while (_zc_stream->Next(&_data, &_size)); + _data = NULL; + _size = 0; + _pushed_bytes += (saved_n - n); + if (n) { + set_bad(); + } +} + +inline void AMFOutputStream::put_u8(uint8_t val) { + do { + if (_size > 0) { + *(uint8_t*)_data = val; + _data = (char*)_data + 1; + --_size; + ++_pushed_bytes; + return; + } + } while (_zc_stream->Next(&_data, &_size)); + _data = NULL; + _size = 0; + set_bad(); +} + +inline void AMFOutputStream::put_u16(uint16_t val) { + uint16_t netval = butil::HostToNet16(val); + return putn(&netval, sizeof(netval)); +} + +inline void AMFOutputStream::put_u32(uint32_t val) { + uint32_t netval = butil::HostToNet32(val); + return putn(&netval, sizeof(netval)); +} + +inline void AMFOutputStream::put_u64(uint64_t val) { + uint64_t netval = butil::HostToNet64(val); + return putn(&netval, sizeof(netval)); +} + +} // namespace brpc + + +#endif // BRPC_AMF_INL_H diff --git a/include/brpc/authenticator.h b/include/brpc/authenticator.h new file mode 100644 index 0000000..501e427 --- /dev/null +++ b/include/brpc/authenticator.h @@ -0,0 +1,91 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +#ifndef BRPC_AUTHENTICATOR_H +#define BRPC_AUTHENTICATOR_H + +#include +#include "butil/endpoint.h" // butil::EndPoint +#include "butil/macros.h" // BAIDU_CONCAT +#include "brpc/extension.h" // Extension + + +namespace brpc { + +class AuthContext { +public: + AuthContext() : _is_service(false) {} + ~AuthContext() {} + + const std::string& user() const { return _user; } + void set_user(const std::string& user) { _user = user; } + + const std::string& group() const { return _group; } + void set_group(const std::string& group) { _group = group; } + + const std::string& roles() const { return _roles; } + void set_roles(const std::string& roles) { _roles = roles; } + + const std::string& starter() const { return _starter; } + void set_starter(const std::string& starter) { _starter = starter; } + + bool is_service() const { return _is_service; } + void set_is_service(bool is_service) { _is_service = is_service; } + +private: + bool _is_service; + std::string _user; + std::string _group; + std::string _roles; + std::string _starter; +}; + +class Authenticator { +public: + virtual ~Authenticator() {} + + // Implement this method to generate credential information + // into `auth_str' which will be sent to `VerifyCredential' + // at server side. This method will be called on client side. + // Returns 0 on success, error code otherwise + virtual int GenerateCredential(std::string* auth_str) const = 0; + + // Implement this method to verify credential information + // `auth_str' from `client_addr'. You can fill credential + // context (result) into `*out_ctx' and later fetch this + // pointer from `Controller'. + // Returns 0 on success, error code otherwise + virtual int VerifyCredential(const std::string& auth_str, + const butil::EndPoint& client_addr, + AuthContext* out_ctx) const = 0; + +}; + +inline std::ostream& operator<<(std::ostream& os, const AuthContext& ctx) { + return os << "[name=" << ctx.user() << " [This is a " + << (ctx.is_service() ? "service" : "user") + << "], group=" << ctx.group() << ", roles=" << ctx.roles() + << ", starter=" << ctx.starter() << "]"; +} + + +} // namespace brpc + + + +#endif // BRPC_AUTHENTICATOR_H diff --git a/include/brpc/builtin/bad_method_service.h b/include/brpc/builtin/bad_method_service.h new file mode 100644 index 0000000..a127f62 --- /dev/null +++ b/include/brpc/builtin/bad_method_service.h @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +#ifndef BRPC_BADMETHOD_SERVICE_H +#define BRPC_BADMETHOD_SERVICE_H + +#include "brpc/builtin_service.pb.h" + + +namespace brpc { + +class BadMethodService : public badmethod { +public: + void no_method(::google::protobuf::RpcController* cntl_base, + const ::brpc::BadMethodRequest* request, + ::brpc::BadMethodResponse* response, + ::google::protobuf::Closure* done); +}; + +} // namespace brpc + + + +#endif // BRPC_BADMETHOD_SERVICE_H diff --git a/include/brpc/builtin/bthreads_service.h b/include/brpc/builtin/bthreads_service.h new file mode 100644 index 0000000..813a3a0 --- /dev/null +++ b/include/brpc/builtin/bthreads_service.h @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +#ifndef BRPC_BTHREADS_SERVICE_H +#define BRPC_BTHREADS_SERVICE_H + +#include "brpc/builtin_service.pb.h" + + +namespace brpc { + +class BthreadsService : public bthreads { +public: + void default_method(::google::protobuf::RpcController* cntl_base, + const ::brpc::BthreadsRequest* request, + ::brpc::BthreadsResponse* response, + ::google::protobuf::Closure* done); +}; + +} // namespace brpc + + +#endif // BRPC_BTHREADS_SERVICE_H diff --git a/include/brpc/builtin/common.h b/include/brpc/builtin/common.h new file mode 100644 index 0000000..f4d6962 --- /dev/null +++ b/include/brpc/builtin/common.h @@ -0,0 +1,146 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +#ifndef BRPC_BUILTIN_COMMON_H +#define BRPC_BUILTIN_COMMON_H + +#include // std::vector +#include +#include "butil/endpoint.h" +#include "brpc/http_header.h" + + +namespace brpc { + +class Controller; + +// These static strings are referenced more than once in brpc. +// Don't turn them to std::strings whose constructing sequences are undefined. +const char* const UNKNOWN_METHOD_STR = "unknown_method"; +const char* const TRACE_ID_STR = "trace"; +const char* const SPAN_ID_STR = "span"; +const char* const TIME_STR = "time"; +const char* const MAX_SCAN_STR = "max_scan"; +const char* const MIN_LATENCY_STR = "min_latency"; +const char* const MIN_REQUEST_SIZE_STR = "min_request_size"; +const char* const MIN_RESPONSE_SIZE_STR = "min_response_size"; +const char* const LOG_ID_STR = "log_id"; +const char* const ERROR_CODE_STR = "error_code"; +const char* const CONSOLE_STR = "console"; +const char* const USER_AGENT_STR = "user-agent"; +const char* const SETVALUE_STR = "setvalue"; + +const size_t MAX_READ = 1024 * 1024; + +enum ProfilingType { + PROFILING_CPU = 0, + PROFILING_HEAP = 1, + PROFILING_GROWTH = 2, + PROFILING_CONTENTION = 3, +}; + +DECLARE_string(rpc_profiling_dir); + +bool UseHTML(const HttpHeader& header); +bool MatchAnyWildcard(const std::string& name, + const std::vector& wildcards); + +void PrintRealDateTime(std::ostream& os, int64_t tm); +void PrintRealDateTime(std::ostream& os, int64_t tm, bool ignore_microseconds); + +struct PrintedAsDateTime { + PrintedAsDateTime(int64_t realtime2) : realtime(realtime2) {} + int64_t realtime; +}; +std::ostream& operator<<(std::ostream& os, const PrintedAsDateTime&); + +struct Path { + static const butil::EndPoint *LOCAL; + Path(const char* uri2, const butil::EndPoint* html_addr2) + : uri(uri2), html_addr(html_addr2), text(NULL) {} + + Path(const char* uri2, const butil::EndPoint* html_addr2, const char* text2) + : uri(uri2), html_addr(html_addr2), text(text2) {} + + const char* uri; + const butil::EndPoint* html_addr; + const char* text; +}; +std::ostream& operator<<(std::ostream& os, const Path& link); + +// Append `filename' to `dir' according to unix directory rules: +// "foo/bar" + ".." -> "foo" +// "foo/bar/." + ".." -> "foo" +// "foo" + "." -> "foo" +// "foo/" + ".." -> "" +// "foo/../" + ".." -> ".." +// "/foo/../" + ".." -> "/" +// "foo/./" + ".." -> "" +void AppendFileName(std::string* dir, const std::string& filename); + +// style of class=gridtable, wrapped with