├── .gitignore ├── CMakeLists.txt ├── Doxyfile ├── Makefile ├── README.md ├── bin ├── conf │ ├── fox_thread.yml │ ├── log.yml │ ├── redis.yml │ ├── server.yml │ ├── service.yml │ ├── system.yml │ └── worker.yml └── orm_conf │ └── user.xml ├── cmake ├── FindMySQL.cmake └── utils.cmake ├── examples ├── echo_server.cc ├── echo_server_udp.cc └── echo_udp_client.cc ├── generate.sh ├── samples └── my_http_server.cc ├── sylar ├── address.cc ├── address.h ├── application.cc ├── application.h ├── bytearray.cc ├── bytearray.h ├── config.cc ├── config.h ├── daemon.cc ├── daemon.h ├── db │ ├── db.h │ ├── fox_thread.cc │ ├── fox_thread.h │ ├── mysql.cc │ ├── mysql.h │ ├── redis.cc │ ├── redis.h │ ├── sqlite3.cc │ └── sqlite3.h ├── ds │ ├── array.h │ ├── bitmap.cc │ ├── bitmap.h │ ├── cache_status.h │ ├── dict.h │ ├── hash_map.h │ ├── hash_multimap.h │ ├── lru_cache.h │ ├── roaring.c │ ├── roaring.h │ ├── roaring.hh │ ├── roaring_bitmap.cc │ ├── roaring_bitmap.h │ ├── timed_cache.h │ ├── timed_lru_cache.h │ ├── util.cc │ └── util.h ├── email │ ├── email.cc │ ├── email.h │ ├── smtp.cc │ └── smtp.h ├── endian.h ├── env.cc ├── env.h ├── fd_manager.cc ├── fd_manager.h ├── fiber.cc ├── fiber.h ├── hook.cc ├── hook.h ├── http │ ├── http.cc │ ├── http.h │ ├── http11_common.h │ ├── http11_parser.h │ ├── http11_parser.rl │ ├── http_connection.cc │ ├── http_connection.h │ ├── http_parser.cc │ ├── http_parser.h │ ├── http_server.cc │ ├── http_server.h │ ├── http_session.cc │ ├── http_session.h │ ├── httpclient_parser.h │ ├── httpclient_parser.rl │ ├── servlet.cc │ ├── servlet.h │ ├── servlets │ │ ├── config_servlet.cc │ │ ├── config_servlet.h │ │ ├── status_servlet.cc │ │ └── status_servlet.h │ ├── session_data.cc │ ├── session_data.h │ ├── ws_connection.cc │ ├── ws_connection.h │ ├── ws_server.cc │ ├── ws_server.h │ ├── ws_servlet.cc │ ├── ws_servlet.h │ ├── ws_session.cc │ └── ws_session.h ├── iomanager.cc ├── iomanager.h ├── library.cc ├── library.h ├── log.cc ├── log.h ├── macro.h ├── main.cc ├── module.cc ├── module.h ├── mutex.cc ├── mutex.h ├── noncopyable.h ├── ns │ ├── name_server_module.cc │ ├── name_server_module.h │ ├── ns_client.cc │ ├── ns_client.h │ ├── ns_protobuf.proto │ ├── ns_protocol.cc │ └── ns_protocol.h ├── orm │ ├── column.cc │ ├── column.h │ ├── index.cc │ ├── index.h │ ├── orm.cc │ ├── table.cc │ ├── table.h │ ├── util.cc │ └── util.h ├── protocol.cc ├── protocol.h ├── rock │ ├── rock_protocol.cc │ ├── rock_protocol.h │ ├── rock_server.cc │ ├── rock_server.h │ ├── rock_stream.cc │ └── rock_stream.h ├── scheduler.cc ├── scheduler.h ├── singleton.h ├── socket.cc ├── socket.h ├── stream.cc ├── stream.h ├── streams │ ├── async_socket_stream.cc │ ├── async_socket_stream.h │ ├── load_balance.cc │ ├── load_balance.h │ ├── service_discovery.cc │ ├── service_discovery.h │ ├── socket_stream.cc │ ├── socket_stream.h │ ├── zlib_stream.cc │ └── zlib_stream.h ├── sylar.h ├── tcp_server.cc ├── tcp_server.h ├── test.proto ├── thread.cc ├── thread.h ├── timer.cc ├── timer.h ├── uri.h ├── uri.rl ├── util.cc ├── util.h ├── util │ ├── crypto_util.cc │ ├── crypto_util.h │ ├── hash_util.cc │ ├── hash_util.h │ ├── json_util.cc │ └── json_util.h ├── worker.cc ├── worker.h ├── zk_client.cc └── zk_client.h ├── template ├── CMakeLists.txt ├── bin │ └── conf │ │ ├── log.yml │ │ ├── server.yml │ │ ├── system.yml │ │ └── worker.yml ├── move.sh └── template │ ├── my_module.cc │ └── my_module.h └── tests ├── test.cc ├── test_address.cc ├── test_application.cc ├── test_array.cc ├── test_bitmap.cc ├── test_bytearray.cc ├── test_config.cc ├── test_crypto.cc ├── test_daemon.cc ├── test_dict.cc ├── test_email.cc ├── test_env.cc ├── test_fiber.cc ├── test_hashmap.cc ├── test_hashmultimap.cc ├── test_hook.cc ├── test_http.cc ├── test_http_connection.cc ├── test_http_parser.cc ├── test_http_server.cc ├── test_iomanager.cc ├── test_lru.cc ├── test_module.cc ├── test_mysql.cc ├── test_nameserver.cc ├── test_orm.cc ├── test_rock.cc ├── test_scheduler.cc ├── test_service_discovery.cc ├── test_socket.cc ├── test_sqlite3.cc ├── test_tcp_server.cc ├── test_thread.cc ├── test_timed_cache.cc ├── test_timed_lru_cache.cc ├── test_uri.cc ├── test_util.cc ├── test_ws_client.cc ├── test_ws_server.cc ├── test_zlib_stream.cc └── test_zookeeper.cc /.gitignore: -------------------------------------------------------------------------------- 1 | tags 2 | *.o 3 | *.sub 4 | *.guess 5 | ltmain.sh 6 | *.la 7 | *.a 8 | .deps 9 | .dirstamp 10 | .libs 11 | *.lo 12 | *.pb.h 13 | *.pb.cc 14 | *.rl.cc 15 | aclocal.m4 16 | autom4te.cache 17 | config.h.in 18 | config.log 19 | config.status 20 | configure 21 | config.h.in~ 22 | install-sh 23 | libtool 24 | Makefile 25 | Makefile.in 26 | missing 27 | stamp-h1 28 | *.pc 29 | depcomp 30 | *.xcodeproj 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: xx 2 | 3 | "": 4 | if [ -d "build" ]; then \ 5 | cd build && make -j4; \ 6 | else \ 7 | mkdir build; \ 8 | cd build && cmake -DCMAKE_CXX_COMPILER:FILEPATH=$(shell which g++) -DCMAKE_C_COMPILER:FILEPATH=$(shell which gcc) ..; \ 9 | fi 10 | 11 | %: 12 | if [ -d "build" ]; then \ 13 | cd build && make $@; \ 14 | else \ 15 | mkdir build; \ 16 | cd build && cmake -DCMAKE_CXX_COMPILER:FILEPATH=$(shell which g++) -DCMAKE_C_COMPILER:FILEPATH=$(shell which gcc) $@ ..; \ 17 | fi 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 视频地址 2 | [\[C++高级教程\]从零开始开发服务器框架(sylar)](https://www.bilibili.com/video/av53602631/?from=www.sylar.top "") 3 | # 视频教程内容: 4 | ## 1.日志模块 5 | 支持流式日志风格写日志和格式化风格写日志,支持日志格式自定义,日志级别,多日志分离等等功能 6 | 流式日志使用:SYLAR_LOG_INFO(g_logger) << "this is a log"; 7 | 格式化日志使用:SYLAR_LOG_FMT_INFO(g_logger, "%s", "this is a log"); 8 | 支持时间,线程id,线程名称,日志级别,日志名称,文件名,行号等内容的自由配置 9 | ## 2.配置模块 10 | 采用约定由于配置的思想。定义即可使用。不需要单独去解析。支持变更通知功能。使用YAML文件做为配置内容。支持级别格式的数据类型,支持STL容器(vector,list,set,map等等),支持自定义类型的支持(需要实现序列化和反序列化方法)使用方式如下: 11 | ```cpp 12 | static sylar::ConfigVar<int>::ptr g_tcp_connect_timeout = 13 | sylar::Config::Lookup("tcp.connect.timeout", 5000, "tcp connect timeout"); 14 | ``` 15 | 定义了一个tcp连接超时参数,可以直接使用 g_tcp_connect_timeout->getValue() 获取参数的值,当配置修改重新加载,该值自动更新 16 | 上述配置格式如下: 17 | ```sh 18 | tcp: 19 | connect: 20 | timeout: 10000 21 | ``` 22 | ## 3.线程模块 23 | 线程模块,封装了pthread里面的一些常用功能,Thread,Semaphore,Mutex,RWMutex,Spinlock等对象,可以方便开发中对线程日常使用 24 | 为什么不适用c++11里面的thread 25 | 本框架是使用C++11开发,不使用thread,是因为thread其实也是基于pthread实现的。并且C++11里面没有提供读写互斥量,RWMutex,Spinlock等,在高并发场景,这些对象是经常需要用到的。所以选择了自己封装pthread 26 | ## 4.协程模块 27 | 协程:用户态的线程,相当于线程中的线程,更轻量级。后续配置socket hook,可以把复杂的异步调用,封装成同步操作。降低业务逻辑的编写复杂度。 28 | 目前该协程是基于ucontext_t来实现的,后续将支持采用boost.context里面的fcontext_t的方式实现 29 | ## 5.协程调度模块 30 | 协程调度器,管理协程的调度,内部实现为一个线程池,支持协程在多线程中切换,也可以指定协程在固定的线程中执行。是一个N-M的协程调度模型,N个线程,M个协程。重复利用每一个线程。 31 | ## 6.IO协程调度模块 32 | 继承与协程调度器,封装了epoll(Linux),并支持定时器功能(使用epoll实现定时器,精度毫秒级),支持Socket读写时间的添加,删除,取消功能。支持一次性定时器,循环定时器,条件定时器等功能 33 | ## 7.Hook模块 34 | hook系统底层和socket相关的API,socket io相关的API,以及sleep系列的API。hook的开启控制是线程粒度的。可以自由选择。通过hook模块,可以使一些不具异步功能的API,展现出异步的性能。如(mysql) 35 | ## 8.Socket模块 36 | 封装了Socket类,提供所有socket API功能,统一封装了地址类,将IPv4,IPv6,Unix地址统一起来。并且提供域名,IP解析功能。 37 | ## 9.ByteArray序列化模块 38 | ByteArray二进制序列化模块,提供对二进制数据的常用操作。读写入基础类型int8_t,int16_t,int32_t,int64_t等,支持Varint,std::string的读写支持,支持字节序转化,支持序列化到文件,以及从文件反序列化等功能 39 | ## 10.TcpServer模块 40 | 基于Socket类,封装了一个通用的TcpServer的服务器类,提供简单的API,使用便捷,可以快速绑定一个或多个地址,启动服务,监听端口,accept连接,处理socket连接等功能。具体业务功能更的服务器实现,只需要继承该类就可以快速实现 41 | ## 11.Stream模块 42 | 封装流式的统一接口。将文件,socket封装成统一的接口。使用的时候,采用统一的风格操作。基于统一的风格,可以提供更灵活的扩展。目前实现了SocketStream 43 | ## 12.HTTP模块 44 | 采用Ragel(有限状态机,性能媲美汇编),实现了HTTP/1.1的简单协议实现和uri的解析。基于SocketStream实现了HttpConnection(HTTP的客户端)和HttpSession(HTTP服务器端的链接)。基于TcpServer实现了HttpServer。提供了完整的HTTP的客户端API请求功能,HTTP基础API服务器功能 45 | ## 13.Servlet模块 46 | 仿照java的servlet,实现了一套Servlet接口,实现了ServletDispatch,FunctionServlet。NotFoundServlet。支持uri的精准匹配,模糊匹配等功能。和HTTP模块,一起提供HTTP服务器功能 47 | ## 14.其他相关 48 | 联系方式: 49 | QQ:564628276 50 | 邮箱:564628276@qq.com 51 | 微信:sylar-yin 52 | QQ群:8151915(sylar技术群) 53 | 个人主页:www.sylar.top 54 | github:https://github.com/sylar-yin/sylar 55 | -------------------------------------------------------------------------------- /bin/conf/fox_thread.yml: -------------------------------------------------------------------------------- 1 | fox_thread: 2 | redis: 3 | name: redis 4 | num: 2 5 | advance: 0 6 | -------------------------------------------------------------------------------- /bin/conf/log.yml: -------------------------------------------------------------------------------- 1 | logs: 2 | - name: root 3 | level: info 4 | appenders: 5 | - type: FileLogAppender 6 | file: /apps/logs/sylar/root.txt 7 | - type: StdoutLogAppender 8 | - name: system 9 | level: info 10 | appenders: 11 | - type: FileLogAppender 12 | file: /apps/logs/sylar/system.txt 13 | - type: StdoutLogAppender 14 | -------------------------------------------------------------------------------- /bin/conf/redis.yml: -------------------------------------------------------------------------------- 1 | redis: 2 | config: 3 | local: 4 | host: 127.0.0.1:6379 5 | type: fox_redis 6 | pool: 2 7 | timeout: 100 8 | desc: "type: redis,redis_cluster,fox_redis,fox_redis_cluster" 9 | -------------------------------------------------------------------------------- /bin/conf/server.yml: -------------------------------------------------------------------------------- 1 | servers: 2 | - address: ["0.0.0.0:8090", "127.0.0.1:8091", "/tmp/test.sock"] 3 | keepalive: 1 4 | timeout: 1000 5 | name: sylar/1.1 6 | accept_worker: accept 7 | io_worker: http_io 8 | process_worker: http_io 9 | type: http 10 | - address: ["0.0.0.0:8062", "0.0.0.0:8061"] 11 | timeout: 1000 12 | name: sylar-rock/1.0 13 | accept_worker: accept 14 | io_worker: io 15 | process_worker: io 16 | type: rock 17 | -------------------------------------------------------------------------------- /bin/conf/service.yml: -------------------------------------------------------------------------------- 1 | service_discovery: 2 | zk: 127.0.0.1:21811 3 | rock_services: 4 | sylar.top: 5 | "all" : fair 6 | -------------------------------------------------------------------------------- /bin/conf/system.yml: -------------------------------------------------------------------------------- 1 | server: 2 | work_path: /apps/work/sylar 3 | pid_file: sylar.pid 4 | -------------------------------------------------------------------------------- /bin/conf/worker.yml: -------------------------------------------------------------------------------- 1 | workers: 2 | io: 3 | thread_num: 8 4 | http_io: 5 | thread_num: 1 6 | accept: 7 | thread_num: 2 8 | worker: 9 | thread_num: 8 10 | notify: 11 | thread_num: 8 12 | service_io: 13 | thread_num: 4 14 | -------------------------------------------------------------------------------- /bin/orm_conf/user.xml: -------------------------------------------------------------------------------- 1 | <table name="user" namespace="test.orm"> 2 | <columns> 3 | <column name="id" type="int64" desc="唯一主键" auto_increment="true"/> 4 | <column name="name" type="string" desc="名称" length="30"/> 5 | <column name="email" type="string" default="xx@xx.com"/> 6 | <column name="phone" type="string"/> 7 | <column name="status" type="int32" default="10"/> 8 | <column name="create_time" type="timestamp"/> 9 | <column name="update_time" type="timestamp" default="current_timestamp" update="current_timestamp"/> 10 | </columns> 11 | <indexs> 12 | <index name="pk" cols="id" type="pk" desc="主键"/> 13 | <index name="name" cols="name" type="uniq" desc="关联"/> 14 | <index name="email" cols="email" type="uniq" desc="关联"/> 15 | <index name="status" cols="status" type="index" desc="关联"/> 16 | </indexs> 17 | </table> 18 | -------------------------------------------------------------------------------- /cmake/utils.cmake: -------------------------------------------------------------------------------- 1 | function(force_redefine_file_macro_for_sources targetname) 2 | get_target_property(source_files "${targetname}" SOURCES) 3 | foreach(sourcefile ${source_files}) 4 | # Get source file's current list of compile definitions. 5 | get_property(defs SOURCE "${sourcefile}" 6 | PROPERTY COMPILE_DEFINITIONS) 7 | # Get the relative path of the source file in project directory 8 | get_filename_component(filepath "${sourcefile}" ABSOLUTE) 9 | string(REPLACE ${PROJECT_SOURCE_DIR}/ "" relpath ${filepath}) 10 | list(APPEND defs "__FILE__=\"${relpath}\"") 11 | # Set the updated compile definitions on the source file. 12 | set_property( 13 | SOURCE "${sourcefile}" 14 | PROPERTY COMPILE_DEFINITIONS ${defs} 15 | ) 16 | endforeach() 17 | endfunction() 18 | 19 | function(ragelmaker src_rl outputlist outputdir) 20 | #Create a custom build step that will call ragel on the provided src_rl file. 21 | #The output .cpp file will be appended to the variable name passed in outputlist. 22 | 23 | get_filename_component(src_file ${src_rl} NAME_WE) 24 | 25 | set(rl_out ${outputdir}/${src_file}.rl.cc) 26 | 27 | #adding to the list inside a function takes special care, we cannot use list(APPEND...) 28 | #because the results are local scope only 29 | set(${outputlist} ${${outputlist}} ${rl_out} PARENT_SCOPE) 30 | 31 | #Warning: The " -S -M -l -C -T0 --error-format=msvc" are added to match existing window invocation 32 | #we might want something different for mac and linux 33 | add_custom_command( 34 | OUTPUT ${rl_out} 35 | COMMAND cd ${outputdir} 36 | COMMAND ragel ${CMAKE_CURRENT_SOURCE_DIR}/${src_rl} -o ${rl_out} -l -C -G2 --error-format=msvc 37 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${src_rl} 38 | ) 39 | set_source_files_properties(${rl_out} PROPERTIES GENERATED TRUE) 40 | endfunction(ragelmaker) 41 | 42 | function(protobufmaker src_proto outputlist outputdir) 43 | #Create a custom build step that will call ragel on the provided src_rl file. 44 | #The output .cpp file will be appended to the variable name passed in outputlist. 45 | 46 | get_filename_component(src_file ${src_proto} NAME_WE) 47 | get_filename_component(src_path ${src_proto} PATH) 48 | 49 | set(protobuf_out ${outputdir}/${src_path}/${src_file}.pb.cc) 50 | 51 | #adding to the list inside a function takes special care, we cannot use list(APPEND...) 52 | #because the results are local scope only 53 | set(${outputlist} ${${outputlist}} ${protobuf_out} PARENT_SCOPE) 54 | 55 | add_custom_command( 56 | OUTPUT ${protobuf_out} 57 | COMMAND protoc --cpp_out=${outputdir} -I${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${src_proto} 58 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${src_proto} 59 | ) 60 | set_source_files_properties(${protobuf_out} PROPERTIES GENERATED TRUE) 61 | endfunction(protobufmaker) 62 | 63 | 64 | function(sylar_add_executable targetname srcs depends libs) 65 | add_executable(${targetname} ${srcs}) 66 | add_dependencies(${targetname} ${depends}) 67 | force_redefine_file_macro_for_sources(${targetname}) 68 | target_link_libraries(${targetname} ${libs}) 69 | endfunction() 70 | -------------------------------------------------------------------------------- /examples/echo_server.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/tcp_server.h" 2 | #include "sylar/log.h" 3 | #include "sylar/iomanager.h" 4 | #include "sylar/bytearray.h" 5 | #include "sylar/address.h" 6 | 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 8 | 9 | class EchoServer : public sylar::TcpServer { 10 | public: 11 | EchoServer(int type); 12 | void handleClient(sylar::Socket::ptr client); 13 | 14 | private: 15 | int m_type = 0; 16 | }; 17 | 18 | EchoServer::EchoServer(int type) 19 | :m_type(type) { 20 | } 21 | 22 | void EchoServer::handleClient(sylar::Socket::ptr client) { 23 | SYLAR_LOG_INFO(g_logger) << "handleClient " << *client; 24 | sylar::ByteArray::ptr ba(new sylar::ByteArray); 25 | while(true) { 26 | ba->clear(); 27 | std::vector<iovec> iovs; 28 | ba->getWriteBuffers(iovs, 1024); 29 | 30 | int rt = client->recv(&iovs[0], iovs.size()); 31 | if(rt == 0) { 32 | SYLAR_LOG_INFO(g_logger) << "client close: " << *client; 33 | break; 34 | } else if(rt < 0) { 35 | SYLAR_LOG_INFO(g_logger) << "client error rt=" << rt 36 | << " errno=" << errno << " errstr=" << strerror(errno); 37 | break; 38 | } 39 | ba->setPosition(ba->getPosition() + rt); 40 | ba->setPosition(0); 41 | //SYLAR_LOG_INFO(g_logger) << "recv rt=" << rt << " data=" << std::string((char*)iovs[0].iov_base, rt); 42 | if(m_type == 1) {//text 43 | std::cout << ba->toString();// << std::endl; 44 | } else { 45 | std::cout << ba->toHexString();// << std::endl; 46 | } 47 | std::cout.flush(); 48 | } 49 | } 50 | 51 | int type = 1; 52 | 53 | void run() { 54 | SYLAR_LOG_INFO(g_logger) << "server type=" << type; 55 | EchoServer::ptr es(new EchoServer(type)); 56 | auto addr = sylar::Address::LookupAny("0.0.0.0:8020"); 57 | while(!es->bind(addr)) { 58 | sleep(2); 59 | } 60 | es->start(); 61 | } 62 | 63 | int main(int argc, char** argv) { 64 | if(argc < 2) { 65 | SYLAR_LOG_INFO(g_logger) << "used as[" << argv[0] << " -t] or [" << argv[0] << " -b]"; 66 | return 0; 67 | } 68 | 69 | if(!strcmp(argv[1], "-b")) { 70 | type = 2; 71 | } 72 | 73 | sylar::IOManager iom(2); 74 | iom.schedule(run); 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /examples/echo_server_udp.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/socket.h" 2 | #include "sylar/log.h" 3 | #include "sylar/iomanager.h" 4 | 5 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 6 | 7 | void run() { 8 | sylar::IPAddress::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8050"); 9 | sylar::Socket::ptr sock = sylar::Socket::CreateUDP(addr); 10 | if(sock->bind(addr)) { 11 | SYLAR_LOG_INFO(g_logger) << "udp bind : " << *addr; 12 | } else { 13 | SYLAR_LOG_ERROR(g_logger) << "udp bind : " << *addr << " fail"; 14 | return; 15 | } 16 | while(true) { 17 | char buff[1024]; 18 | sylar::Address::ptr from(new sylar::IPv4Address); 19 | int len = sock->recvFrom(buff, 1024, from); 20 | if(len > 0) { 21 | buff[len] = '\0'; 22 | SYLAR_LOG_INFO(g_logger) << "recv: " << buff << " from: " << *from; 23 | len = sock->sendTo(buff, len, from); 24 | if(len < 0) { 25 | SYLAR_LOG_INFO(g_logger) << "send: " << buff << " to: " << *from 26 | << " error=" << len; 27 | } 28 | } 29 | } 30 | } 31 | 32 | int main(int argc, char** argv) { 33 | sylar::IOManager iom(1); 34 | iom.schedule(run); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /examples/echo_udp_client.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/socket.h" 2 | #include "sylar/iomanager.h" 3 | #include "sylar/log.h" 4 | #include <stdlib.h> 5 | 6 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 7 | 8 | const char* ip = nullptr; 9 | uint16_t port = 0; 10 | 11 | void run() { 12 | sylar::IPAddress::ptr addr = sylar::Address::LookupAnyIPAddress(ip); 13 | if(!addr) { 14 | SYLAR_LOG_ERROR(g_logger) << "invalid ip: " << ip; 15 | return; 16 | } 17 | addr->setPort(port); 18 | 19 | sylar::Socket::ptr sock = sylar::Socket::CreateUDP(addr); 20 | 21 | sylar::IOManager::GetThis()->schedule([sock](){ 22 | sylar::Address::ptr addr(new sylar::IPv4Address); 23 | SYLAR_LOG_INFO(g_logger) << "begin recv"; 24 | while(true) { 25 | char buff[1024]; 26 | int len = sock->recvFrom(buff, 1024, addr); 27 | if(len > 0) { 28 | std::cout << std::endl << "recv: " << std::string(buff, len) << " from: " << *addr << std::endl; 29 | } 30 | } 31 | }); 32 | sleep(1); 33 | while(true) { 34 | std::string line; 35 | std::cout << "input>"; 36 | std::getline(std::cin, line); 37 | if(!line.empty()) { 38 | int len = sock->sendTo(line.c_str(), line.size(), addr); 39 | if(len < 0) { 40 | int err = sock->getError(); 41 | SYLAR_LOG_ERROR(g_logger) << "send error err=" << err 42 | << " errstr=" << strerror(err) << " len=" << len 43 | << " addr=" << *addr 44 | << " sock=" << *sock; 45 | } else { 46 | SYLAR_LOG_INFO(g_logger) << "send " << line << " len:" << len; 47 | } 48 | } 49 | } 50 | } 51 | 52 | int main(int argc, char** argv) { 53 | if(argc < 3) { 54 | SYLAR_LOG_INFO(g_logger) << "use as[" << argv[0] << " ip port]"; 55 | return 0; 56 | } 57 | ip = argv[1]; 58 | port = atoi(argv[2]); 59 | sylar::IOManager iom(2); 60 | iom.schedule(run); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | command_error_exit() { 4 | $* 5 | if [ $? -ne 0 ] 6 | then 7 | exit 1 8 | fi 9 | } 10 | 11 | if [ $# -lt 2 ] 12 | then 13 | echo "use [$0 project_name namespace]" 14 | exit 0 15 | fi 16 | 17 | project_name=$1 18 | namespace=$2 19 | 20 | command_error_exit mkdir $project_name 21 | command_error_exit cd $project_name 22 | command_error_exit git clone https://github.com/sylar-yin/sylar.git 23 | command_error_exit cp sylar/Makefile . 24 | command_error_exit cp -rf sylar/template/* . 25 | command_error_exit cp -rf sylar/template/* . 26 | command_error_exit mv template ${namespace} 27 | command_error_exit sed -i "s/project_name/${project_name}/g" CMakeLists.txt 28 | command_error_exit sed -i "s/template/${namespace}/g" CMakeLists.txt 29 | command_error_exit sed -i "s/project_name/${project_name}/g" move.sh 30 | command_error_exit cd ${namespace} 31 | command_error_exit sed -i "s/name_space/${namespace}/g" `ls .` 32 | command_error_exit sed -i "s/project_name/${project_name}/g" `ls .` 33 | command_error_exit cd ../bin/conf 34 | command_error_exit sed -i "s/name_space/${namespace}/g" `ls .` 35 | command_error_exit sed -i "s/project_name/${project_name}/g" `ls .` 36 | 37 | echo "create module ${project_name} -- ${namespace} ok" 38 | -------------------------------------------------------------------------------- /samples/my_http_server.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/http/http_server.h" 2 | #include "sylar/log.h" 3 | 4 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | sylar::IOManager::ptr worker; 6 | void run() { 7 | g_logger->setLevel(sylar::LogLevel::INFO); 8 | sylar::Address::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8020"); 9 | if(!addr) { 10 | SYLAR_LOG_ERROR(g_logger) << "get address error"; 11 | return; 12 | } 13 | 14 | sylar::http::HttpServer::ptr http_server(new sylar::http::HttpServer(true, worker.get())); 15 | //sylar::http::HttpServer::ptr http_server(new sylar::http::HttpServer(true)); 16 | bool ssl = false; 17 | while(!http_server->bind(addr, ssl)) { 18 | SYLAR_LOG_ERROR(g_logger) << "bind " << *addr << " fail"; 19 | sleep(1); 20 | } 21 | 22 | if(ssl) { 23 | //http_server->loadCertificates("/home/apps/soft/sylar/keys/server.crt", "/home/apps/soft/sylar/keys/server.key"); 24 | } 25 | 26 | http_server->start(); 27 | } 28 | 29 | int main(int argc, char** argv) { 30 | sylar::IOManager iom(1); 31 | worker.reset(new sylar::IOManager(4, false)); 32 | iom.schedule(run); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /sylar/application.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_APPLICATION_H__ 2 | #define __SYLAR_APPLICATION_H__ 3 | 4 | #include "sylar/http/http_server.h" 5 | #include "sylar/streams/service_discovery.h" 6 | #include "sylar/rock/rock_stream.h" 7 | 8 | namespace sylar { 9 | 10 | class Application { 11 | public: 12 | Application(); 13 | 14 | static Application* GetInstance() { return s_instance;} 15 | bool init(int argc, char** argv); 16 | bool run(); 17 | 18 | bool getServer(const std::string& type, std::vector<TcpServer::ptr>& svrs); 19 | void listAllServer(std::map<std::string, std::vector<TcpServer::ptr> >& servers); 20 | 21 | ZKServiceDiscovery::ptr getServiceDiscovery() const { return m_serviceDiscovery;} 22 | RockSDLoadBalance::ptr getRockSDLoadBalance() const { return m_rockSDLoadBalance;} 23 | private: 24 | int main(int argc, char** argv); 25 | int run_fiber(); 26 | private: 27 | int m_argc = 0; 28 | char** m_argv = nullptr; 29 | 30 | //std::vector<sylar::http::HttpServer::ptr> m_httpservers; 31 | std::map<std::string, std::vector<TcpServer::ptr> > m_servers; 32 | IOManager::ptr m_mainIOManager; 33 | static Application* s_instance; 34 | 35 | ZKServiceDiscovery::ptr m_serviceDiscovery; 36 | RockSDLoadBalance::ptr m_rockSDLoadBalance; 37 | }; 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /sylar/config.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/config.h" 2 | #include "sylar/env.h" 3 | #include "sylar/util.h" 4 | #include <sys/types.h> 5 | #include <sys/stat.h> 6 | #include <unistd.h> 7 | 8 | namespace sylar { 9 | 10 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system"); 11 | 12 | ConfigVarBase::ptr Config::LookupBase(const std::string& name) { 13 | RWMutexType::ReadLock lock(GetMutex()); 14 | auto it = GetDatas().find(name); 15 | return it == GetDatas().end() ? nullptr : it->second; 16 | } 17 | 18 | //"A.B", 10 19 | //A: 20 | // B: 10 21 | // C: str 22 | 23 | static void ListAllMember(const std::string& prefix, 24 | const YAML::Node& node, 25 | std::list<std::pair<std::string, const YAML::Node> >& output) { 26 | if(prefix.find_first_not_of("abcdefghikjlmnopqrstuvwxyz._012345678") 27 | != std::string::npos) { 28 | SYLAR_LOG_ERROR(g_logger) << "Config invalid name: " << prefix << " : " << node; 29 | return; 30 | } 31 | output.push_back(std::make_pair(prefix, node)); 32 | if(node.IsMap()) { 33 | for(auto it = node.begin(); 34 | it != node.end(); ++it) { 35 | ListAllMember(prefix.empty() ? it->first.Scalar() 36 | : prefix + "." + it->first.Scalar(), it->second, output); 37 | } 38 | } 39 | } 40 | 41 | void Config::LoadFromYaml(const YAML::Node& root) { 42 | std::list<std::pair<std::string, const YAML::Node> > all_nodes; 43 | ListAllMember("", root, all_nodes); 44 | 45 | for(auto& i : all_nodes) { 46 | std::string key = i.first; 47 | if(key.empty()) { 48 | continue; 49 | } 50 | 51 | std::transform(key.begin(), key.end(), key.begin(), ::tolower); 52 | ConfigVarBase::ptr var = LookupBase(key); 53 | 54 | if(var) { 55 | if(i.second.IsScalar()) { 56 | var->fromString(i.second.Scalar()); 57 | } else { 58 | std::stringstream ss; 59 | ss << i.second; 60 | var->fromString(ss.str()); 61 | } 62 | } 63 | } 64 | } 65 | 66 | static std::map<std::string, uint64_t> s_file2modifytime; 67 | static sylar::Mutex s_mutex; 68 | 69 | void Config::LoadFromConfDir(const std::string& path, bool force) { 70 | std::string absoulte_path = sylar::EnvMgr::GetInstance()->getAbsolutePath(path); 71 | std::vector<std::string> files; 72 | FSUtil::ListAllFile(files, absoulte_path, ".yml"); 73 | 74 | for(auto& i : files) { 75 | { 76 | struct stat st; 77 | lstat(i.c_str(), &st); 78 | sylar::Mutex::Lock lock(s_mutex); 79 | if(!force && s_file2modifytime[i] == (uint64_t)st.st_mtime) { 80 | continue; 81 | } 82 | s_file2modifytime[i] = st.st_mtime; 83 | } 84 | try { 85 | YAML::Node root = YAML::LoadFile(i); 86 | LoadFromYaml(root); 87 | SYLAR_LOG_INFO(g_logger) << "LoadConfFile file=" 88 | << i << " ok"; 89 | } catch (...) { 90 | SYLAR_LOG_ERROR(g_logger) << "LoadConfFile file=" 91 | << i << " failed"; 92 | } 93 | } 94 | } 95 | 96 | void Config::Visit(std::function<void(ConfigVarBase::ptr)> cb) { 97 | RWMutexType::ReadLock lock(GetMutex()); 98 | ConfigVarMap& m = GetDatas(); 99 | for(auto it = m.begin(); 100 | it != m.end(); ++it) { 101 | cb(it->second); 102 | } 103 | 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /sylar/daemon.cc: -------------------------------------------------------------------------------- 1 | #include "daemon.h" 2 | #include "sylar/log.h" 3 | #include "sylar/config.h" 4 | #include <time.h> 5 | #include <string.h> 6 | #include <sys/types.h> 7 | #include <sys/wait.h> 8 | #include <unistd.h> 9 | 10 | namespace sylar { 11 | 12 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system"); 13 | static sylar::ConfigVar<uint32_t>::ptr g_daemon_restart_interval 14 | = sylar::Config::Lookup("daemon.restart_interval", (uint32_t)5, "daemon restart interval"); 15 | 16 | std::string ProcessInfo::toString() const { 17 | std::stringstream ss; 18 | ss << "[ProcessInfo parent_id=" << parent_id 19 | << " main_id=" << main_id 20 | << " parent_start_time=" << sylar::Time2Str(parent_start_time) 21 | << " main_start_time=" << sylar::Time2Str(main_start_time) 22 | << " restart_count=" << restart_count << "]"; 23 | return ss.str(); 24 | } 25 | 26 | static int real_start(int argc, char** argv, 27 | std::function<int(int argc, char** argv)> main_cb) { 28 | ProcessInfoMgr::GetInstance()->main_id = getpid(); 29 | ProcessInfoMgr::GetInstance()->main_start_time = time(0); 30 | return main_cb(argc, argv); 31 | } 32 | 33 | static int real_daemon(int argc, char** argv, 34 | std::function<int(int argc, char** argv)> main_cb) { 35 | daemon(1, 0); 36 | ProcessInfoMgr::GetInstance()->parent_id = getpid(); 37 | ProcessInfoMgr::GetInstance()->parent_start_time = time(0); 38 | while(true) { 39 | pid_t pid = fork(); 40 | if(pid == 0) { 41 | //子进程返回 42 | ProcessInfoMgr::GetInstance()->main_id = getpid(); 43 | ProcessInfoMgr::GetInstance()->main_start_time = time(0); 44 | SYLAR_LOG_INFO(g_logger) << "process start pid=" << getpid(); 45 | return real_start(argc, argv, main_cb); 46 | } else if(pid < 0) { 47 | SYLAR_LOG_ERROR(g_logger) << "fork fail return=" << pid 48 | << " errno=" << errno << " errstr=" << strerror(errno); 49 | return -1; 50 | } else { 51 | //父进程返回 52 | int status = 0; 53 | waitpid(pid, &status, 0); 54 | if(status) { 55 | if(status == 9) { 56 | SYLAR_LOG_INFO(g_logger) << "killed"; 57 | break; 58 | } else { 59 | SYLAR_LOG_ERROR(g_logger) << "child crash pid=" << pid 60 | << " status=" << status; 61 | } 62 | } else { 63 | SYLAR_LOG_INFO(g_logger) << "child finished pid=" << pid; 64 | break; 65 | } 66 | ProcessInfoMgr::GetInstance()->restart_count += 1; 67 | sleep(g_daemon_restart_interval->getValue()); 68 | } 69 | } 70 | return 0; 71 | } 72 | 73 | int start_daemon(int argc, char** argv 74 | , std::function<int(int argc, char** argv)> main_cb 75 | , bool is_daemon) { 76 | if(!is_daemon) { 77 | ProcessInfoMgr::GetInstance()->parent_id = getpid(); 78 | ProcessInfoMgr::GetInstance()->parent_start_time = time(0); 79 | return real_start(argc, argv, main_cb); 80 | } 81 | return real_daemon(argc, argv, main_cb); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /sylar/daemon.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_DAEMON_H__ 2 | #define __SYLAR_DAEMON_H__ 3 | 4 | #include <unistd.h> 5 | #include <functional> 6 | #include "sylar/singleton.h" 7 | 8 | namespace sylar { 9 | 10 | struct ProcessInfo { 11 | /// 父进程id 12 | pid_t parent_id = 0; 13 | /// 主进程id 14 | pid_t main_id = 0; 15 | /// 父进程启动时间 16 | uint64_t parent_start_time = 0; 17 | /// 主进程启动时间 18 | uint64_t main_start_time = 0; 19 | /// 主进程重启的次数 20 | uint32_t restart_count = 0; 21 | 22 | std::string toString() const; 23 | }; 24 | 25 | typedef sylar::Singleton<ProcessInfo> ProcessInfoMgr; 26 | 27 | /** 28 | * @brief 启动程序可以选择用守护进程的方式 29 | * @param[in] argc 参数个数 30 | * @param[in] argv 参数值数组 31 | * @param[in] main_cb 启动函数 32 | * @param[in] is_daemon 是否守护进程的方式 33 | * @return 返回程序的执行结果 34 | */ 35 | int start_daemon(int argc, char** argv 36 | , std::function<int(int argc, char** argv)> main_cb 37 | , bool is_daemon); 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /sylar/ds/cache_status.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_DS_CACHE_STATUS_H__ 2 | #define __SYLAR_DS_CACHE_STATUS_H__ 3 | 4 | #include <sstream> 5 | #include <string> 6 | #include <stdint.h> 7 | #include "sylar/util.h" 8 | 9 | namespace sylar { 10 | namespace ds { 11 | 12 | class CacheStatus { 13 | public: 14 | CacheStatus() {} 15 | 16 | int64_t incGet(int64_t v = 1) { return Atomic::addFetch(m_get, v);} 17 | int64_t incSet(int64_t v = 1) { return Atomic::addFetch(m_set, v);} 18 | int64_t incDel(int64_t v = 1) { return Atomic::addFetch(m_del, v);} 19 | int64_t incTimeout(int64_t v = 1) { return Atomic::addFetch(m_timeout, v);} 20 | int64_t incPrune(int64_t v = 1) { return Atomic::addFetch(m_prune, v);} 21 | int64_t incHit(int64_t v = 1) { return Atomic::addFetch(m_hit, v);} 22 | 23 | int64_t decGet(int64_t v = 1) { return Atomic::subFetch(m_get, v);} 24 | int64_t decSet(int64_t v = 1) { return Atomic::subFetch(m_set, v);} 25 | int64_t decDel(int64_t v = 1) { return Atomic::subFetch(m_del, v);} 26 | int64_t decTimeout(int64_t v = 1) { return Atomic::subFetch(m_timeout, v);} 27 | int64_t decPrune(int64_t v = 1) { return Atomic::subFetch(m_prune, v);} 28 | int64_t decHit(int64_t v = 1) { return Atomic::subFetch(m_hit, v);} 29 | 30 | int64_t getGet() const { return m_get;} 31 | int64_t getSet() const { return m_set;} 32 | int64_t getDel() const { return m_del;} 33 | int64_t getTimeout() const { return m_timeout;} 34 | int64_t getPrune() const { return m_prune;} 35 | int64_t getHit() const { return m_hit;} 36 | 37 | double getHitRate() const { 38 | return m_get ? (m_hit * 1.0 / m_get) : 0; 39 | } 40 | 41 | void merge(const CacheStatus& o) { 42 | m_get += o.m_get; 43 | m_set += o.m_set; 44 | m_del += o.m_del; 45 | m_timeout += o.m_timeout; 46 | m_prune += o.m_prune; 47 | m_hit += o.m_hit; 48 | } 49 | 50 | std::string toString() const { 51 | std::stringstream ss; 52 | ss << "get=" << m_get 53 | << " set=" << m_set 54 | << " del=" << m_del 55 | << " prune=" << m_prune 56 | << " timeout=" << m_timeout 57 | << " hit=" << m_hit 58 | << " hit_rate=" << (getHitRate() * 100.0) << "%"; 59 | return ss.str(); 60 | } 61 | private: 62 | int64_t m_get = 0; 63 | int64_t m_set = 0; 64 | int64_t m_del = 0; 65 | int64_t m_timeout = 0; 66 | int64_t m_prune = 0; 67 | int64_t m_hit = 0; 68 | }; 69 | 70 | } 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /sylar/ds/roaring_bitmap.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_DS_ROARING_BITMAP_H__ 2 | #define __SYLAR_DS_ROARING_BITMAP_H__ 3 | 4 | #include <stdint.h> 5 | #include <string> 6 | #include <vector> 7 | #include <memory> 8 | #include <functional> 9 | #include "sylar/bytearray.h" 10 | #include "roaring.hh" 11 | 12 | namespace sylar { 13 | namespace ds { 14 | 15 | class RoaringBitmap { 16 | public: 17 | typedef std::shared_ptr<RoaringBitmap> ptr; 18 | 19 | RoaringBitmap(); 20 | RoaringBitmap(uint32_t size); 21 | RoaringBitmap(const RoaringBitmap& b); 22 | ~RoaringBitmap(); 23 | 24 | RoaringBitmap& operator=(const RoaringBitmap& b); 25 | 26 | std::string toString() const; 27 | bool get(uint32_t idx) const; 28 | void set(uint32_t idx, bool v); 29 | 30 | void set(uint32_t from, uint32_t size, bool v); 31 | bool get(uint32_t from, uint32_t size, bool v) const; 32 | 33 | RoaringBitmap& operator&=(const RoaringBitmap& b); 34 | RoaringBitmap& operator|=(const RoaringBitmap& b); 35 | RoaringBitmap& operator-=(const RoaringBitmap& b); 36 | RoaringBitmap& operator^=(const RoaringBitmap& b); 37 | 38 | RoaringBitmap operator& (const RoaringBitmap& b); 39 | RoaringBitmap operator| (const RoaringBitmap& b); 40 | RoaringBitmap operator- (const RoaringBitmap& b); 41 | RoaringBitmap operator^ (const RoaringBitmap& b); 42 | 43 | //RoaringBitmap& operator~(); 44 | 45 | bool operator== (const RoaringBitmap& b) const; 46 | bool operator!= (const RoaringBitmap& b) const; 47 | 48 | RoaringBitmap::ptr compress() const; 49 | RoaringBitmap::ptr uncompress() const; 50 | 51 | bool any() const; 52 | 53 | void listPosAsc(std::vector<uint32_t>& pos); 54 | 55 | void foreach(std::function<bool(uint32_t)> cb); 56 | void rforeach(std::function<bool(uint32_t)> cb); 57 | 58 | void writeTo(sylar::ByteArray::ptr ba) const; 59 | bool readFrom(sylar::ByteArray::ptr ba); 60 | 61 | //uncompress to compress 62 | //uncompress to uncompress 63 | bool cross(const RoaringBitmap& b) const; 64 | 65 | float getCompressRate() const; 66 | 67 | uint32_t getCount() const; 68 | public: 69 | typedef RoaringSetBitForwardIterator iterator; 70 | typedef RoaringSetBitReverseIterator reverse_iterator; 71 | 72 | iterator begin() const { return m_bitmap.begin();} 73 | iterator end() const { return m_bitmap.end(); } 74 | 75 | reverse_iterator rbegin() const { return m_bitmap.rbegin();} 76 | reverse_iterator rend() const { return m_bitmap.rend();} 77 | 78 | private: 79 | RoaringBitmap(const Roaring& b); 80 | private: 81 | Roaring m_bitmap; 82 | }; 83 | 84 | } 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /sylar/email/email.cc: -------------------------------------------------------------------------------- 1 | #include "email.h" 2 | #include <fstream> 3 | #include <sstream> 4 | #include "sylar/util.h" 5 | 6 | namespace sylar { 7 | 8 | EMailEntity::ptr EMailEntity::CreateAttach(const std::string& filename) { 9 | std::ifstream ifs(filename, std::ios::binary); 10 | std::string buf; 11 | buf.resize(1024); 12 | EMailEntity::ptr entity(new EMailEntity); 13 | while(!ifs.eof()) { 14 | ifs.read(&buf[0], buf.size()); 15 | entity->m_content.append(buf.c_str(), ifs.gcount()); 16 | } 17 | entity->m_content = sylar::base64encode(entity->m_content); 18 | entity->addHeader("Content-Transfer-Encoding", "base64"); 19 | entity->addHeader("Content-Disposition", "attachment"); 20 | entity->addHeader("Content-Type", "application/octet-stream;name=" + sylar::FSUtil::Basename(filename)); 21 | return entity; 22 | } 23 | 24 | void EMailEntity::addHeader(const std::string& key, const std::string& val) { 25 | m_headers[key] = val; 26 | } 27 | 28 | std::string EMailEntity::getHeader(const std::string& key, const std::string& def) { 29 | auto it = m_headers.find(key); 30 | return it == m_headers.end() ? def : it->second; 31 | } 32 | 33 | std::string EMailEntity::toString() const { 34 | std::stringstream ss; 35 | for(auto& i : m_headers) { 36 | ss << i.first << ": " << i.second << "\r\n"; 37 | } 38 | ss << m_content << "\r\n"; 39 | return ss.str(); 40 | } 41 | 42 | EMail::ptr EMail::Create(const std::string& from_address, const std::string& from_passwd 43 | ,const std::string& title, const std::string& body 44 | ,const std::vector<std::string>& to_address 45 | ,const std::vector<std::string>& cc_address 46 | ,const std::vector<std::string>& bcc_address) { 47 | EMail::ptr email(new EMail); 48 | email->setFromEMailAddress(from_address); 49 | email->setFromEMailPasswd(from_passwd); 50 | email->setTitle(title); 51 | email->setBody(body); 52 | email->setToEMailAddress(to_address); 53 | email->setCcEMailAddress(cc_address); 54 | email->setBccEMailAddress(bcc_address); 55 | return email; 56 | } 57 | 58 | void EMail::addEntity(EMailEntity::ptr entity) { 59 | m_entitys.push_back(entity); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /sylar/email/email.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_EMAIL_EMAIL_H__ 2 | #define __SYLAR_EMAIL_EMAIL_H__ 3 | 4 | #include <memory> 5 | #include <string> 6 | #include <vector> 7 | #include <map> 8 | 9 | namespace sylar { 10 | 11 | class EMailEntity { 12 | public: 13 | typedef std::shared_ptr<EMailEntity> ptr; 14 | static EMailEntity::ptr CreateAttach(const std::string& filename); 15 | 16 | void addHeader(const std::string& key, const std::string& val); 17 | std::string getHeader(const std::string& key, const std::string& def = ""); 18 | 19 | const std::string& getContent() const { return m_content;} 20 | void setContent(const std::string& v) { m_content = v;} 21 | 22 | std::string toString() const; 23 | private: 24 | std::map<std::string, std::string> m_headers; 25 | std::string m_content; 26 | }; 27 | 28 | 29 | class EMail { 30 | public: 31 | typedef std::shared_ptr<EMail> ptr; 32 | static EMail::ptr Create(const std::string& from_address, const std::string& from_passwd 33 | ,const std::string& title, const std::string& body 34 | ,const std::vector<std::string>& to_address 35 | ,const std::vector<std::string>& cc_address = {} 36 | ,const std::vector<std::string>& bcc_address = {}); 37 | 38 | const std::string& getFromEMailAddress() const { return m_fromEMailAddress;} 39 | const std::string& getFromEMailPasswd() const { return m_fromEMailPasswd;} 40 | const std::string& getTitle() const { return m_title;} 41 | const std::string& getBody() const { return m_body;} 42 | 43 | void setFromEMailAddress(const std::string& v) { m_fromEMailAddress = v;} 44 | void setFromEMailPasswd(const std::string& v) { m_fromEMailPasswd = v;} 45 | void setTitle(const std::string& v) { m_title = v;} 46 | void setBody(const std::string& v) { m_body = v;} 47 | 48 | const std::vector<std::string>& getToEMailAddress() const { return m_toEMailAddress;} 49 | const std::vector<std::string>& getCcEMailAddress() const { return m_ccEMailAddress;} 50 | const std::vector<std::string>& getBccEMailAddress() const { return m_bccEMailAddress;} 51 | 52 | void setToEMailAddress(const std::vector<std::string>& v) { m_toEMailAddress = v;} 53 | void setCcEMailAddress(const std::vector<std::string>& v) { m_ccEMailAddress = v;} 54 | void setBccEMailAddress(const std::vector<std::string>& v) { m_bccEMailAddress = v;} 55 | 56 | void addEntity(EMailEntity::ptr entity); 57 | const std::vector<EMailEntity::ptr>& getEntitys() const { return m_entitys;} 58 | private: 59 | std::string m_fromEMailAddress; 60 | std::string m_fromEMailPasswd; 61 | std::string m_title; 62 | std::string m_body; 63 | std::vector<std::string> m_toEMailAddress; 64 | std::vector<std::string> m_ccEMailAddress; 65 | std::vector<std::string> m_bccEMailAddress; 66 | std::vector<EMailEntity::ptr> m_entitys; 67 | }; 68 | 69 | } 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /sylar/email/smtp.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_EMAIL_SMTP_H__ 2 | #define __SYLAR_EMAIL_SMTP_H__ 3 | 4 | #include "sylar/streams/socket_stream.h" 5 | #include "email.h" 6 | #include <sstream> 7 | 8 | namespace sylar { 9 | 10 | struct SmtpResult { 11 | typedef std::shared_ptr<SmtpResult> ptr; 12 | enum Result { 13 | OK = 0, 14 | IO_ERROR = -1 15 | }; 16 | 17 | SmtpResult(int r, const std::string& m) 18 | :result(r) 19 | ,msg(m) { 20 | } 21 | 22 | int result; 23 | std::string msg; 24 | }; 25 | 26 | class SmtpClient : public sylar::SocketStream { 27 | public: 28 | typedef std::shared_ptr<SmtpClient> ptr; 29 | static SmtpClient::ptr Create(const std::string& host, uint32_t port, bool ssl= false); 30 | SmtpResult::ptr send(EMail::ptr email, int64_t timeout_ms = 1000, bool debug = false); 31 | 32 | std::string getDebugInfo(); 33 | private: 34 | SmtpResult::ptr doCmd(const std::string& cmd, bool debug); 35 | private: 36 | SmtpClient(Socket::ptr sock); 37 | private: 38 | std::string m_host; 39 | std::stringstream m_ss; 40 | bool m_authed = false; 41 | }; 42 | 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /sylar/endian.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file endian.h 3 | * @brief 字节序操作函数(大端/小端) 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-06-01 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_ENDIAN_H__ 10 | #define __SYLAR_ENDIAN_H__ 11 | 12 | #define SYLAR_LITTLE_ENDIAN 1 13 | #define SYLAR_BIG_ENDIAN 2 14 | 15 | #include <byteswap.h> 16 | #include <stdint.h> 17 | 18 | namespace sylar { 19 | 20 | /** 21 | * @brief 8字节类型的字节序转化 22 | */ 23 | template<class T> 24 | typename std::enable_if<sizeof(T) == sizeof(uint64_t), T>::type 25 | byteswap(T value) { 26 | return (T)bswap_64((uint64_t)value); 27 | } 28 | 29 | /** 30 | * @brief 4字节类型的字节序转化 31 | */ 32 | template<class T> 33 | typename std::enable_if<sizeof(T) == sizeof(uint32_t), T>::type 34 | byteswap(T value) { 35 | return (T)bswap_32((uint32_t)value); 36 | } 37 | 38 | /** 39 | * @brief 2字节类型的字节序转化 40 | */ 41 | template<class T> 42 | typename std::enable_if<sizeof(T) == sizeof(uint16_t), T>::type 43 | byteswap(T value) { 44 | return (T)bswap_16((uint16_t)value); 45 | } 46 | 47 | #if BYTE_ORDER == BIG_ENDIAN 48 | #define SYLAR_BYTE_ORDER SYLAR_BIG_ENDIAN 49 | #else 50 | #define SYLAR_BYTE_ORDER SYLAR_LITTLE_ENDIAN 51 | #endif 52 | 53 | #if SYLAR_BYTE_ORDER == SYLAR_BIG_ENDIAN 54 | 55 | /** 56 | * @brief 只在小端机器上执行byteswap, 在大端机器上什么都不做 57 | */ 58 | template<class T> 59 | T byteswapOnLittleEndian(T t) { 60 | return t; 61 | } 62 | 63 | /** 64 | * @brief 只在大端机器上执行byteswap, 在小端机器上什么都不做 65 | */ 66 | template<class T> 67 | T byteswapOnBigEndian(T t) { 68 | return byteswap(t); 69 | } 70 | #else 71 | 72 | /** 73 | * @brief 只在小端机器上执行byteswap, 在大端机器上什么都不做 74 | */ 75 | template<class T> 76 | T byteswapOnLittleEndian(T t) { 77 | return byteswap(t); 78 | } 79 | 80 | /** 81 | * @brief 只在大端机器上执行byteswap, 在小端机器上什么都不做 82 | */ 83 | template<class T> 84 | T byteswapOnBigEndian(T t) { 85 | return t; 86 | } 87 | #endif 88 | 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /sylar/env.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_ENV_H__ 2 | #define __SYLAR_ENV_H__ 3 | 4 | #include "sylar/singleton.h" 5 | #include "sylar/thread.h" 6 | #include <map> 7 | #include <vector> 8 | 9 | namespace sylar { 10 | 11 | class Env { 12 | public: 13 | typedef RWMutex RWMutexType; 14 | bool init(int argc, char** argv); 15 | 16 | void add(const std::string& key, const std::string& val); 17 | bool has(const std::string& key); 18 | void del(const std::string& key); 19 | std::string get(const std::string& key, const std::string& default_value = ""); 20 | 21 | void addHelp(const std::string& key, const std::string& desc); 22 | void removeHelp(const std::string& key); 23 | void printHelp(); 24 | 25 | const std::string& getExe() const { return m_exe;} 26 | const std::string& getCwd() const { return m_cwd;} 27 | 28 | bool setEnv(const std::string& key, const std::string& val); 29 | std::string getEnv(const std::string& key, const std::string& default_value = ""); 30 | 31 | std::string getAbsolutePath(const std::string& path) const; 32 | std::string getAbsoluteWorkPath(const std::string& path) const; 33 | std::string getConfigPath(); 34 | private: 35 | RWMutexType m_mutex; 36 | std::map<std::string, std::string> m_args; 37 | std::vector<std::pair<std::string, std::string> > m_helps; 38 | 39 | std::string m_program; 40 | std::string m_exe; 41 | std::string m_cwd; 42 | }; 43 | 44 | typedef sylar::Singleton<Env> EnvMgr; 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /sylar/fd_manager.cc: -------------------------------------------------------------------------------- 1 | #include "fd_manager.h" 2 | #include "hook.h" 3 | #include <sys/types.h> 4 | #include <sys/stat.h> 5 | #include <unistd.h> 6 | 7 | namespace sylar { 8 | 9 | FdCtx::FdCtx(int fd) 10 | :m_isInit(false) 11 | ,m_isSocket(false) 12 | ,m_sysNonblock(false) 13 | ,m_userNonblock(false) 14 | ,m_isClosed(false) 15 | ,m_fd(fd) 16 | ,m_recvTimeout(-1) 17 | ,m_sendTimeout(-1) { 18 | init(); 19 | } 20 | 21 | FdCtx::~FdCtx() { 22 | } 23 | 24 | bool FdCtx::init() { 25 | if(m_isInit) { 26 | return true; 27 | } 28 | m_recvTimeout = -1; 29 | m_sendTimeout = -1; 30 | 31 | struct stat fd_stat; 32 | if(-1 == fstat(m_fd, &fd_stat)) { 33 | m_isInit = false; 34 | m_isSocket = false; 35 | } else { 36 | m_isInit = true; 37 | m_isSocket = S_ISSOCK(fd_stat.st_mode); 38 | } 39 | 40 | if(m_isSocket) { 41 | int flags = fcntl_f(m_fd, F_GETFL, 0); 42 | if(!(flags & O_NONBLOCK)) { 43 | fcntl_f(m_fd, F_SETFL, flags | O_NONBLOCK); 44 | } 45 | m_sysNonblock = true; 46 | } else { 47 | m_sysNonblock = false; 48 | } 49 | 50 | m_userNonblock = false; 51 | m_isClosed = false; 52 | return m_isInit; 53 | } 54 | 55 | void FdCtx::setTimeout(int type, uint64_t v) { 56 | if(type == SO_RCVTIMEO) { 57 | m_recvTimeout = v; 58 | } else { 59 | m_sendTimeout = v; 60 | } 61 | } 62 | 63 | uint64_t FdCtx::getTimeout(int type) { 64 | if(type == SO_RCVTIMEO) { 65 | return m_recvTimeout; 66 | } else { 67 | return m_sendTimeout; 68 | } 69 | } 70 | 71 | FdManager::FdManager() { 72 | m_datas.resize(64); 73 | } 74 | 75 | FdCtx::ptr FdManager::get(int fd, bool auto_create) { 76 | if(fd == -1) { 77 | return nullptr; 78 | } 79 | RWMutexType::ReadLock lock(m_mutex); 80 | if((int)m_datas.size() <= fd) { 81 | if(auto_create == false) { 82 | return nullptr; 83 | } 84 | } else { 85 | if(m_datas[fd] || !auto_create) { 86 | return m_datas[fd]; 87 | } 88 | } 89 | lock.unlock(); 90 | 91 | RWMutexType::WriteLock lock2(m_mutex); 92 | FdCtx::ptr ctx(new FdCtx(fd)); 93 | if(fd >= (int)m_datas.size()) { 94 | m_datas.resize(fd * 1.5); 95 | } 96 | m_datas[fd] = ctx; 97 | return ctx; 98 | } 99 | 100 | void FdManager::del(int fd) { 101 | RWMutexType::WriteLock lock(m_mutex); 102 | if((int)m_datas.size() <= fd) { 103 | return; 104 | } 105 | m_datas[fd].reset(); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /sylar/fd_manager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fd_manager.h 3 | * @brief 文件句柄管理类 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-05-30 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __FD_MANAGER_H__ 10 | #define __FD_MANAGER_H__ 11 | 12 | #include <memory> 13 | #include <vector> 14 | #include "thread.h" 15 | #include "singleton.h" 16 | 17 | namespace sylar { 18 | 19 | /** 20 | * @brief 文件句柄上下文类 21 | * @details 管理文件句柄类型(是否socket) 22 | * 是否阻塞,是否关闭,读/写超时时间 23 | */ 24 | class FdCtx : public std::enable_shared_from_this<FdCtx> { 25 | public: 26 | typedef std::shared_ptr<FdCtx> ptr; 27 | /** 28 | * @brief 通过文件句柄构造FdCtx 29 | */ 30 | FdCtx(int fd); 31 | /** 32 | * @brief 析构函数 33 | */ 34 | ~FdCtx(); 35 | 36 | /** 37 | * @brief 是否初始化完成 38 | */ 39 | bool isInit() const { return m_isInit;} 40 | 41 | /** 42 | * @brief 是否socket 43 | */ 44 | bool isSocket() const { return m_isSocket;} 45 | 46 | /** 47 | * @brief 是否已关闭 48 | */ 49 | bool isClose() const { return m_isClosed;} 50 | 51 | /** 52 | * @brief 设置用户主动设置非阻塞 53 | * @param[in] v 是否阻塞 54 | */ 55 | void setUserNonblock(bool v) { m_userNonblock = v;} 56 | 57 | /** 58 | * @brief 获取是否用户主动设置的非阻塞 59 | */ 60 | bool getUserNonblock() const { return m_userNonblock;} 61 | 62 | /** 63 | * @brief 设置系统非阻塞 64 | * @param[in] v 是否阻塞 65 | */ 66 | void setSysNonblock(bool v) { m_sysNonblock = v;} 67 | 68 | /** 69 | * @brief 获取系统非阻塞 70 | */ 71 | bool getSysNonblock() const { return m_sysNonblock;} 72 | 73 | /** 74 | * @brief 设置超时时间 75 | * @param[in] type 类型SO_RCVTIMEO(读超时), SO_SNDTIMEO(写超时) 76 | * @param[in] v 时间毫秒 77 | */ 78 | void setTimeout(int type, uint64_t v); 79 | 80 | /** 81 | * @brief 获取超时时间 82 | * @param[in] type 类型SO_RCVTIMEO(读超时), SO_SNDTIMEO(写超时) 83 | * @return 超时时间毫秒 84 | */ 85 | uint64_t getTimeout(int type); 86 | private: 87 | /** 88 | * @brief 初始化 89 | */ 90 | bool init(); 91 | private: 92 | /// 是否初始化 93 | bool m_isInit: 1; 94 | /// 是否socket 95 | bool m_isSocket: 1; 96 | /// 是否hook非阻塞 97 | bool m_sysNonblock: 1; 98 | /// 是否用户主动设置非阻塞 99 | bool m_userNonblock: 1; 100 | /// 是否关闭 101 | bool m_isClosed: 1; 102 | /// 文件句柄 103 | int m_fd; 104 | /// 读超时时间毫秒 105 | uint64_t m_recvTimeout; 106 | /// 写超时时间毫秒 107 | uint64_t m_sendTimeout; 108 | }; 109 | 110 | /** 111 | * @brief 文件句柄管理类 112 | */ 113 | class FdManager { 114 | public: 115 | typedef RWMutex RWMutexType; 116 | /** 117 | * @brief 无参构造函数 118 | */ 119 | FdManager(); 120 | 121 | /** 122 | * @brief 获取/创建文件句柄类FdCtx 123 | * @param[in] fd 文件句柄 124 | * @param[in] auto_create 是否自动创建 125 | * @return 返回对应文件句柄类FdCtx::ptr 126 | */ 127 | FdCtx::ptr get(int fd, bool auto_create = false); 128 | 129 | /** 130 | * @brief 删除文件句柄类 131 | * @param[in] fd 文件句柄 132 | */ 133 | void del(int fd); 134 | private: 135 | /// 读写锁 136 | RWMutexType m_mutex; 137 | /// 文件句柄集合 138 | std::vector<FdCtx::ptr> m_datas; 139 | }; 140 | 141 | /// 文件句柄单例 142 | typedef Singleton<FdManager> FdMgr; 143 | 144 | } 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /sylar/fiber.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file fiber.h 3 | * @brief 协程封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-05-24 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_FIBER_H__ 10 | #define __SYLAR_FIBER_H__ 11 | 12 | #include <memory> 13 | #include <functional> 14 | #include <ucontext.h> 15 | 16 | namespace sylar { 17 | 18 | class Scheduler; 19 | 20 | /** 21 | * @brief 协程类 22 | */ 23 | class Fiber : public std::enable_shared_from_this<Fiber> { 24 | friend class Scheduler; 25 | public: 26 | typedef std::shared_ptr<Fiber> ptr; 27 | 28 | /** 29 | * @brief 协程状态 30 | */ 31 | enum State { 32 | /// 初始化状态 33 | INIT, 34 | /// 暂停状态 35 | HOLD, 36 | /// 执行中状态 37 | EXEC, 38 | /// 结束状态 39 | TERM, 40 | /// 可执行状态 41 | READY, 42 | /// 异常状态 43 | EXCEPT 44 | }; 45 | private: 46 | /** 47 | * @brief 无参构造函数 48 | * @attention 每个线程第一个协程的构造 49 | */ 50 | Fiber(); 51 | 52 | public: 53 | /** 54 | * @brief 构造函数 55 | * @param[in] cb 协程执行的函数 56 | * @param[in] stacksize 协程栈大小 57 | * @param[in] use_caller 是否在MainFiber上调度 58 | */ 59 | Fiber(std::function<void()> cb, size_t stacksize = 0, bool use_caller = false); 60 | 61 | /** 62 | * @brief 析构函数 63 | */ 64 | ~Fiber(); 65 | 66 | /** 67 | * @brief 重置协程执行函数,并设置状态 68 | * @pre getState() 为 INIT, TERM, EXCEPT 69 | * @post getState() = INIT 70 | */ 71 | void reset(std::function<void()> cb); 72 | 73 | /** 74 | * @brief 将当前协程切换到运行状态 75 | * @pre getState() != EXEC 76 | * @post getState() = EXEC 77 | */ 78 | void swapIn(); 79 | 80 | /** 81 | * @brief 将当前协程切换到后台 82 | */ 83 | void swapOut(); 84 | 85 | /** 86 | * @brief 将当前线程切换到执行状态 87 | * @pre 执行的为当前线程的主协程 88 | */ 89 | void call(); 90 | 91 | /** 92 | * @brief 将当前线程切换到后台 93 | * @pre 执行的为该协程 94 | * @post 返回到线程的主协程 95 | */ 96 | void back(); 97 | 98 | /** 99 | * @brief 返回协程id 100 | */ 101 | uint64_t getId() const { return m_id;} 102 | 103 | /** 104 | * @brief 返回协程状态 105 | */ 106 | State getState() const { return m_state;} 107 | public: 108 | 109 | /** 110 | * @brief 设置当前线程的运行协程 111 | * @param[in] f 运行协程 112 | */ 113 | static void SetThis(Fiber* f); 114 | 115 | /** 116 | * @brief 返回当前所在的协程 117 | */ 118 | static Fiber::ptr GetThis(); 119 | 120 | /** 121 | * @brief 将当前协程切换到后台,并设置为READY状态 122 | * @post getState() = READY 123 | */ 124 | static void YieldToReady(); 125 | 126 | /** 127 | * @brief 将当前协程切换到后台,并设置为HOLD状态 128 | * @post getState() = HOLD 129 | */ 130 | static void YieldToHold(); 131 | 132 | /** 133 | * @brief 返回当前协程的总数量 134 | */ 135 | static uint64_t TotalFibers(); 136 | 137 | /** 138 | * @brief 协程执行函数 139 | * @post 执行完成返回到线程主协程 140 | */ 141 | static void MainFunc(); 142 | 143 | /** 144 | * @brief 协程执行函数 145 | * @post 执行完成返回到线程调度协程 146 | */ 147 | static void CallerMainFunc(); 148 | 149 | /** 150 | * @brief 获取当前协程的id 151 | */ 152 | static uint64_t GetFiberId(); 153 | private: 154 | /// 协程id 155 | uint64_t m_id = 0; 156 | /// 协程运行栈大小 157 | uint32_t m_stacksize = 0; 158 | /// 协程状态 159 | State m_state = INIT; 160 | /// 协程上下文 161 | ucontext_t m_ctx; 162 | /// 协程运行栈指针 163 | void* m_stack = nullptr; 164 | /// 协程运行函数 165 | std::function<void()> m_cb; 166 | }; 167 | 168 | } 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /sylar/hook.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hook.h 3 | * @brief hook函数封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-06-02 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | 10 | #ifndef __SYLAR_HOOK_H__ 11 | #define __SYLAR_HOOK_H__ 12 | 13 | #include <fcntl.h> 14 | #include <sys/ioctl.h> 15 | #include <sys/types.h> 16 | #include <sys/socket.h> 17 | #include <stdint.h> 18 | #include <time.h> 19 | #include <unistd.h> 20 | 21 | namespace sylar { 22 | /** 23 | * @brief 当前线程是否hook 24 | */ 25 | bool is_hook_enable(); 26 | /** 27 | * @brief 设置当前线程的hook状态 28 | */ 29 | void set_hook_enable(bool flag); 30 | } 31 | 32 | extern "C" { 33 | 34 | //sleep 35 | typedef unsigned int (*sleep_fun)(unsigned int seconds); 36 | extern sleep_fun sleep_f; 37 | 38 | typedef int (*usleep_fun)(useconds_t usec); 39 | extern usleep_fun usleep_f; 40 | 41 | typedef int (*nanosleep_fun)(const struct timespec *req, struct timespec *rem); 42 | extern nanosleep_fun nanosleep_f; 43 | 44 | //socket 45 | typedef int (*socket_fun)(int domain, int type, int protocol); 46 | extern socket_fun socket_f; 47 | 48 | typedef int (*connect_fun)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 49 | extern connect_fun connect_f; 50 | 51 | typedef int (*accept_fun)(int s, struct sockaddr *addr, socklen_t *addrlen); 52 | extern accept_fun accept_f; 53 | 54 | //read 55 | typedef ssize_t (*read_fun)(int fd, void *buf, size_t count); 56 | extern read_fun read_f; 57 | 58 | typedef ssize_t (*readv_fun)(int fd, const struct iovec *iov, int iovcnt); 59 | extern readv_fun readv_f; 60 | 61 | typedef ssize_t (*recv_fun)(int sockfd, void *buf, size_t len, int flags); 62 | extern recv_fun recv_f; 63 | 64 | typedef ssize_t (*recvfrom_fun)(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); 65 | extern recvfrom_fun recvfrom_f; 66 | 67 | typedef ssize_t (*recvmsg_fun)(int sockfd, struct msghdr *msg, int flags); 68 | extern recvmsg_fun recvmsg_f; 69 | 70 | //write 71 | typedef ssize_t (*write_fun)(int fd, const void *buf, size_t count); 72 | extern write_fun write_f; 73 | 74 | typedef ssize_t (*writev_fun)(int fd, const struct iovec *iov, int iovcnt); 75 | extern writev_fun writev_f; 76 | 77 | typedef ssize_t (*send_fun)(int s, const void *msg, size_t len, int flags); 78 | extern send_fun send_f; 79 | 80 | typedef ssize_t (*sendto_fun)(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); 81 | extern sendto_fun sendto_f; 82 | 83 | typedef ssize_t (*sendmsg_fun)(int s, const struct msghdr *msg, int flags); 84 | extern sendmsg_fun sendmsg_f; 85 | 86 | typedef int (*close_fun)(int fd); 87 | extern close_fun close_f; 88 | 89 | // 90 | typedef int (*fcntl_fun)(int fd, int cmd, ... /* arg */ ); 91 | extern fcntl_fun fcntl_f; 92 | 93 | typedef int (*ioctl_fun)(int d, unsigned long int request, ...); 94 | extern ioctl_fun ioctl_f; 95 | 96 | typedef int (*getsockopt_fun)(int sockfd, int level, int optname, void *optval, socklen_t *optlen); 97 | extern getsockopt_fun getsockopt_f; 98 | 99 | typedef int (*setsockopt_fun)(int sockfd, int level, int optname, const void *optval, socklen_t optlen); 100 | extern setsockopt_fun setsockopt_f; 101 | 102 | extern int connect_with_timeout(int fd, const struct sockaddr* addr, socklen_t addrlen, uint64_t timeout_ms); 103 | 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /sylar/http/http11_common.h: -------------------------------------------------------------------------------- 1 | #ifndef _http11_common_h 2 | #define _http11_common_h 3 | 4 | #include <sys/types.h> 5 | 6 | typedef void (*element_cb)(void *data, const char *at, size_t length); 7 | typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /sylar/http/http11_parser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file bytearray.h 3 | * @brief 二进制数组(序列化/反序列化) 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-06-03 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef http11_parser_h 10 | #define http11_parser_h 11 | 12 | #include "http11_common.h" 13 | 14 | typedef struct http_parser { 15 | int cs; 16 | size_t body_start; 17 | int content_len; 18 | size_t nread; 19 | size_t mark; 20 | size_t field_start; 21 | size_t field_len; 22 | size_t query_start; 23 | int xml_sent; 24 | int json_sent; 25 | 26 | void *data; 27 | 28 | int uri_relaxed; 29 | field_cb http_field; 30 | element_cb request_method; 31 | element_cb request_uri; 32 | element_cb fragment; 33 | element_cb request_path; 34 | element_cb query_string; 35 | element_cb http_version; 36 | element_cb header_done; 37 | 38 | } http_parser; 39 | 40 | int http_parser_init(http_parser *parser); 41 | int http_parser_finish(http_parser *parser); 42 | size_t http_parser_execute(http_parser *parser, const char *data, size_t len, size_t off); 43 | int http_parser_has_error(http_parser *parser); 44 | int http_parser_is_finished(http_parser *parser); 45 | 46 | #define http_parser_nread(parser) (parser)->nread 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /sylar/http/http_server.cc: -------------------------------------------------------------------------------- 1 | #include "http_server.h" 2 | #include "sylar/log.h" 3 | #include "sylar/http/servlets/config_servlet.h" 4 | #include "sylar/http/servlets/status_servlet.h" 5 | 6 | namespace sylar { 7 | namespace http { 8 | 9 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system"); 10 | 11 | HttpServer::HttpServer(bool keepalive 12 | ,sylar::IOManager* worker 13 | ,sylar::IOManager* io_worker 14 | ,sylar::IOManager* accept_worker) 15 | :TcpServer(worker, io_worker, accept_worker) 16 | ,m_isKeepalive(keepalive) { 17 | m_dispatch.reset(new ServletDispatch); 18 | 19 | m_type = "http"; 20 | m_dispatch->addServlet("/_/status", Servlet::ptr(new StatusServlet)); 21 | m_dispatch->addServlet("/_/config", Servlet::ptr(new ConfigServlet)); 22 | } 23 | 24 | void HttpServer::setName(const std::string& v) { 25 | TcpServer::setName(v); 26 | m_dispatch->setDefault(std::make_shared<NotFoundServlet>(v)); 27 | } 28 | 29 | void HttpServer::handleClient(Socket::ptr client) { 30 | SYLAR_LOG_DEBUG(g_logger) << "handleClient " << *client; 31 | HttpSession::ptr session(new HttpSession(client)); 32 | do { 33 | auto req = session->recvRequest(); 34 | if(!req) { 35 | SYLAR_LOG_DEBUG(g_logger) << "recv http request fail, errno=" 36 | << errno << " errstr=" << strerror(errno) 37 | << " cliet:" << *client << " keep_alive=" << m_isKeepalive; 38 | break; 39 | } 40 | 41 | HttpResponse::ptr rsp(new HttpResponse(req->getVersion() 42 | ,req->isClose() || !m_isKeepalive)); 43 | rsp->setHeader("Server", getName()); 44 | m_dispatch->handle(req, rsp, session); 45 | session->sendResponse(rsp); 46 | 47 | if(!m_isKeepalive || req->isClose()) { 48 | break; 49 | } 50 | } while(true); 51 | session->close(); 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /sylar/http/http_server.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file http_server.h 3 | * @brief HTTP服务器封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-06-09 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | 10 | #ifndef __SYLAR_HTTP_HTTP_SERVER_H__ 11 | #define __SYLAR_HTTP_HTTP_SERVER_H__ 12 | 13 | #include "sylar/tcp_server.h" 14 | #include "http_session.h" 15 | #include "servlet.h" 16 | 17 | namespace sylar { 18 | namespace http { 19 | 20 | /** 21 | * @brief HTTP服务器类 22 | */ 23 | class HttpServer : public TcpServer { 24 | public: 25 | /// 智能指针类型 26 | typedef std::shared_ptr<HttpServer> ptr; 27 | 28 | /** 29 | * @brief 构造函数 30 | * @param[in] keepalive 是否长连接 31 | * @param[in] worker 工作调度器 32 | * @param[in] accept_worker 接收连接调度器 33 | */ 34 | HttpServer(bool keepalive = false 35 | ,sylar::IOManager* worker = sylar::IOManager::GetThis() 36 | ,sylar::IOManager* io_worker = sylar::IOManager::GetThis() 37 | ,sylar::IOManager* accept_worker = sylar::IOManager::GetThis()); 38 | 39 | /** 40 | * @brief 获取ServletDispatch 41 | */ 42 | ServletDispatch::ptr getServletDispatch() const { return m_dispatch;} 43 | 44 | /** 45 | * @brief 设置ServletDispatch 46 | */ 47 | void setServletDispatch(ServletDispatch::ptr v) { m_dispatch = v;} 48 | 49 | virtual void setName(const std::string& v) override; 50 | protected: 51 | virtual void handleClient(Socket::ptr client) override; 52 | private: 53 | /// 是否支持长连接 54 | bool m_isKeepalive; 55 | /// Servlet分发器 56 | ServletDispatch::ptr m_dispatch; 57 | }; 58 | 59 | } 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /sylar/http/http_session.cc: -------------------------------------------------------------------------------- 1 | #include "http_session.h" 2 | #include "http_parser.h" 3 | 4 | namespace sylar { 5 | namespace http { 6 | 7 | HttpSession::HttpSession(Socket::ptr sock, bool owner) 8 | :SocketStream(sock, owner) { 9 | } 10 | 11 | HttpRequest::ptr HttpSession::recvRequest() { 12 | HttpRequestParser::ptr parser(new HttpRequestParser); 13 | uint64_t buff_size = HttpRequestParser::GetHttpRequestBufferSize(); 14 | //uint64_t buff_size = 100; 15 | std::shared_ptr<char> buffer( 16 | new char[buff_size], [](char* ptr){ 17 | delete[] ptr; 18 | }); 19 | char* data = buffer.get(); 20 | int offset = 0; 21 | do { 22 | int len = read(data + offset, buff_size - offset); 23 | if(len <= 0) { 24 | close(); 25 | return nullptr; 26 | } 27 | len += offset; 28 | size_t nparse = parser->execute(data, len); 29 | if(parser->hasError()) { 30 | close(); 31 | return nullptr; 32 | } 33 | offset = len - nparse; 34 | if(offset == (int)buff_size) { 35 | close(); 36 | return nullptr; 37 | } 38 | if(parser->isFinished()) { 39 | break; 40 | } 41 | } while(true); 42 | int64_t length = parser->getContentLength(); 43 | if(length > 0) { 44 | std::string body; 45 | body.resize(length); 46 | 47 | int len = 0; 48 | if(length >= offset) { 49 | memcpy(&body[0], data, offset); 50 | len = offset; 51 | } else { 52 | memcpy(&body[0], data, length); 53 | len = length; 54 | } 55 | length -= offset; 56 | if(length > 0) { 57 | if(readFixSize(&body[len], length) <= 0) { 58 | close(); 59 | return nullptr; 60 | } 61 | } 62 | parser->getData()->setBody(body); 63 | } 64 | 65 | parser->getData()->init(); 66 | return parser->getData(); 67 | } 68 | 69 | int HttpSession::sendResponse(HttpResponse::ptr rsp) { 70 | std::stringstream ss; 71 | ss << *rsp; 72 | std::string data = ss.str(); 73 | return writeFixSize(data.c_str(), data.size()); 74 | } 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /sylar/http/http_session.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file http_session.h 3 | * @brief HTTPSession封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-06-07 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | 10 | #ifndef __SYLAR_HTTP_SESSION_H__ 11 | #define __SYLAR_HTTP_SESSION_H__ 12 | 13 | #include "sylar/streams/socket_stream.h" 14 | #include "http.h" 15 | 16 | namespace sylar { 17 | namespace http { 18 | 19 | /** 20 | * @brief HTTPSession封装 21 | */ 22 | class HttpSession : public SocketStream { 23 | public: 24 | /// 智能指针类型定义 25 | typedef std::shared_ptr<HttpSession> ptr; 26 | 27 | /** 28 | * @brief 构造函数 29 | * @param[in] sock Socket类型 30 | * @param[in] owner 是否托管 31 | */ 32 | HttpSession(Socket::ptr sock, bool owner = true); 33 | 34 | /** 35 | * @brief 接收HTTP请求 36 | */ 37 | HttpRequest::ptr recvRequest(); 38 | 39 | /** 40 | * @brief 发送HTTP响应 41 | * @param[in] rsp HTTP响应 42 | * @return >0 发送成功 43 | * =0 对方关闭 44 | * <0 Socket异常 45 | */ 46 | int sendResponse(HttpResponse::ptr rsp); 47 | }; 48 | 49 | } 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /sylar/http/httpclient_parser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are 8 | * met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names 18 | * of its contributors may be used to endorse or promote products 19 | * derived from this software without specific prior written 20 | * permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 24 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef httpclient_parser_h 36 | #define httpclient_parser_h 37 | 38 | #include "http11_common.h" 39 | 40 | typedef struct httpclient_parser { 41 | int cs; 42 | size_t body_start; 43 | int content_len; 44 | int status; 45 | int chunked; 46 | int chunks_done; 47 | int close; 48 | size_t nread; 49 | size_t mark; 50 | size_t field_start; 51 | size_t field_len; 52 | 53 | void *data; 54 | 55 | field_cb http_field; 56 | element_cb reason_phrase; 57 | element_cb status_code; 58 | element_cb chunk_size; 59 | element_cb http_version; 60 | element_cb header_done; 61 | element_cb last_chunk; 62 | 63 | 64 | } httpclient_parser; 65 | 66 | int httpclient_parser_init(httpclient_parser *parser); 67 | int httpclient_parser_finish(httpclient_parser *parser); 68 | int httpclient_parser_execute(httpclient_parser *parser, const char *data, size_t len, size_t off); 69 | int httpclient_parser_has_error(httpclient_parser *parser); 70 | int httpclient_parser_is_finished(httpclient_parser *parser); 71 | 72 | #define httpclient_parser_nread(parser) (parser)->nread 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /sylar/http/servlets/config_servlet.cc: -------------------------------------------------------------------------------- 1 | #include "config_servlet.h" 2 | #include "sylar/config.h" 3 | 4 | namespace sylar { 5 | namespace http { 6 | 7 | ConfigServlet::ConfigServlet() 8 | :Servlet("ConfigServlet") { 9 | } 10 | 11 | int32_t ConfigServlet::handle(sylar::http::HttpRequest::ptr request 12 | ,sylar::http::HttpResponse::ptr response 13 | ,sylar::http::HttpSession::ptr session) { 14 | std::string type = request->getParam("type"); 15 | if(type == "json") { 16 | response->setHeader("Content-Type", "text/json charset=utf-8"); 17 | } else { 18 | response->setHeader("Content-Type", "text/yaml charset=utf-8"); 19 | } 20 | YAML::Node node; 21 | sylar::Config::Visit([&node](ConfigVarBase::ptr base) { 22 | YAML::Node n; 23 | try { 24 | n = YAML::Load(base->toString()); 25 | } catch(...) { 26 | return; 27 | } 28 | node[base->getName()] = n; 29 | node[base->getName() + "$description"] = base->getDescription(); 30 | }); 31 | if(type == "json") { 32 | Json::Value jvalue; 33 | if(YamlToJson(node, jvalue)) { 34 | response->setBody(JsonUtil::ToString(jvalue)); 35 | return 0; 36 | } 37 | } 38 | std::stringstream ss; 39 | ss << node; 40 | response->setBody(ss.str()); 41 | return 0; 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /sylar/http/servlets/config_servlet.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_HTTP_SERVLETS_CONFIG_SERVLET_H__ 2 | #define __SYLAR_HTTP_SERVLETS_CONFIG_SERVLET_H__ 3 | 4 | #include "sylar/http/servlet.h" 5 | 6 | namespace sylar { 7 | namespace http { 8 | 9 | class ConfigServlet : public Servlet { 10 | public: 11 | ConfigServlet(); 12 | virtual int32_t handle(sylar::http::HttpRequest::ptr request 13 | , sylar::http::HttpResponse::ptr response 14 | , sylar::http::HttpSession::ptr session) override; 15 | }; 16 | 17 | } 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /sylar/http/servlets/status_servlet.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_HTTP_SERVLETS_STATUS_SERVLET_H__ 2 | #define __SYLAR_HTTP_SERVLETS_STATUS_SERVLET_H__ 3 | 4 | #include "sylar/http/servlet.h" 5 | 6 | namespace sylar { 7 | namespace http { 8 | 9 | class StatusServlet : public Servlet { 10 | public: 11 | StatusServlet(); 12 | virtual int32_t handle(sylar::http::HttpRequest::ptr request 13 | , sylar::http::HttpResponse::ptr response 14 | , sylar::http::HttpSession::ptr session) override; 15 | }; 16 | 17 | } 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /sylar/http/session_data.cc: -------------------------------------------------------------------------------- 1 | #include "session_data.h" 2 | #include "sylar/util.h" 3 | 4 | namespace sylar { 5 | namespace http { 6 | 7 | SessionData::SessionData(bool auto_gen) 8 | :m_lastAccessTime(time(0)) { 9 | if(auto_gen) { 10 | std::stringstream ss; 11 | ss << sylar::GetCurrentUS() << "|" << rand() << "|" << rand() << "|" << rand(); 12 | m_id = sylar::md5(ss.str()); 13 | } 14 | } 15 | 16 | void SessionData::del(const std::string& key) { 17 | sylar::RWMutex::WriteLock lock(m_mutex); 18 | m_datas.erase(key); 19 | } 20 | 21 | bool SessionData::has(const std::string& key) { 22 | sylar::RWMutex::ReadLock lock(m_mutex); 23 | auto it = m_datas.find(key); 24 | return it != m_datas.end(); 25 | } 26 | 27 | void SessionDataManager::add(SessionData::ptr info) { 28 | sylar::RWMutex::WriteLock lock(m_mutex); 29 | m_datas[info->getId()] = info; 30 | } 31 | 32 | SessionData::ptr SessionDataManager::get(const std::string& id) { 33 | sylar::RWMutex::ReadLock lock(m_mutex); 34 | auto it = m_datas.find(id); 35 | if(it != m_datas.end()) { 36 | it->second->setLastAccessTime(time(0)); 37 | return it->second; 38 | } 39 | return nullptr; 40 | } 41 | 42 | void SessionDataManager::check(int64_t ts) { 43 | uint64_t now = time(0) - ts; 44 | std::vector<std::string> keys; 45 | sylar::RWMutex::ReadLock lock(m_mutex); 46 | for(auto& i : m_datas) { 47 | if(i.second->getLastAccessTime() < now) { 48 | keys.push_back(i.first); 49 | } 50 | } 51 | lock.unlock(); 52 | for(auto& i : keys) { 53 | del(i); 54 | } 55 | } 56 | 57 | void SessionDataManager::del(const std::string& id) { 58 | sylar::RWMutex::WriteLock lock(m_mutex); 59 | m_datas.erase(id); 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sylar/http/session_data.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_HTTP_SESSION_DATA_H__ 2 | #define __SYLAR_HTTP_SESSION_DATA_H__ 3 | 4 | #include "sylar/mutex.h" 5 | #include "sylar/singleton.h" 6 | #include <boost/any.hpp> 7 | #include <unordered_map> 8 | 9 | namespace sylar { 10 | namespace http { 11 | 12 | class SessionData { 13 | public: 14 | typedef std::shared_ptr<SessionData> ptr; 15 | SessionData(bool auto_gen = false); 16 | 17 | template<class T> 18 | void setData(const std::string& key, const T& v) { 19 | sylar::RWMutex::WriteLock lock(m_mutex); 20 | m_datas[key] = v; 21 | } 22 | 23 | template<class T> 24 | T getData(const std::string& key, const T& def = T()) { 25 | sylar::RWMutex::ReadLock lock(m_mutex); 26 | auto it = m_datas.find(key); 27 | if(it == m_datas.end()) { 28 | return def; 29 | } 30 | boost::any v = it->second; 31 | lock.unlock(); 32 | try { 33 | return boost::any_cast<T>(v); 34 | } catch (...) { 35 | } 36 | return def; 37 | } 38 | 39 | void del(const std::string& key); 40 | 41 | bool has(const std::string& key); 42 | uint64_t getLastAccessTime() const { return m_lastAccessTime;} 43 | void setLastAccessTime(uint64_t v) { m_lastAccessTime = v;} 44 | 45 | const std::string& getId() const { return m_id;} 46 | void setId(const std::string& val) { m_id = val;} 47 | private: 48 | sylar::RWMutex m_mutex; 49 | std::unordered_map<std::string, boost::any> m_datas; 50 | uint64_t m_lastAccessTime; 51 | std::string m_id; 52 | }; 53 | 54 | class SessionDataManager { 55 | public: 56 | void add(SessionData::ptr info); 57 | void del(const std::string& id); 58 | SessionData::ptr get(const std::string& id); 59 | void check(int64_t ts = 3600); 60 | private: 61 | sylar::RWMutex m_mutex; 62 | std::unordered_map<std::string, SessionData::ptr> m_datas; 63 | }; 64 | 65 | typedef sylar::Singleton<SessionDataManager> SessionDataMgr; 66 | 67 | } 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /sylar/http/ws_connection.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_HTTP_WS_CONNECTION_H__ 2 | #define __SYLAR_HTTP_WS_CONNECTION_H__ 3 | 4 | #include "sylar/http/http_connection.h" 5 | #include "sylar/http/ws_session.h" 6 | 7 | namespace sylar { 8 | namespace http { 9 | 10 | class WSConnection : public HttpConnection { 11 | public: 12 | typedef std::shared_ptr<WSConnection> ptr; 13 | WSConnection(Socket::ptr sock, bool owner = true); 14 | static std::pair<HttpResult::ptr, WSConnection::ptr> Create(const std::string& url 15 | ,uint64_t timeout_ms 16 | , const std::map<std::string, std::string>& headers = {}); 17 | static std::pair<HttpResult::ptr, WSConnection::ptr> Create(Uri::ptr uri 18 | ,uint64_t timeout_ms 19 | , const std::map<std::string, std::string>& headers = {}); 20 | WSFrameMessage::ptr recvMessage(); 21 | int32_t sendMessage(WSFrameMessage::ptr msg, bool fin = true); 22 | int32_t sendMessage(const std::string& msg, int32_t opcode = WSFrameHead::TEXT_FRAME, bool fin = true); 23 | int32_t ping(); 24 | int32_t pong(); 25 | }; 26 | 27 | } 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /sylar/http/ws_server.cc: -------------------------------------------------------------------------------- 1 | #include "ws_server.h" 2 | #include "sylar/log.h" 3 | 4 | namespace sylar { 5 | namespace http { 6 | 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system"); 8 | 9 | WSServer::WSServer(sylar::IOManager* worker, sylar::IOManager* io_worker, sylar::IOManager* accept_worker) 10 | :TcpServer(worker, io_worker, accept_worker) { 11 | m_dispatch.reset(new WSServletDispatch); 12 | m_type = "websocket_server"; 13 | } 14 | 15 | void WSServer::handleClient(Socket::ptr client) { 16 | SYLAR_LOG_DEBUG(g_logger) << "handleClient " << *client; 17 | WSSession::ptr session(new WSSession(client)); 18 | do { 19 | HttpRequest::ptr header = session->handleShake(); 20 | if(!header) { 21 | SYLAR_LOG_DEBUG(g_logger) << "handleShake error"; 22 | break; 23 | } 24 | WSServlet::ptr servlet = m_dispatch->getWSServlet(header->getPath()); 25 | if(!servlet) { 26 | SYLAR_LOG_DEBUG(g_logger) << "no match WSServlet"; 27 | break; 28 | } 29 | int rt = servlet->onConnect(header, session); 30 | if(rt) { 31 | SYLAR_LOG_DEBUG(g_logger) << "onConnect return " << rt; 32 | break; 33 | } 34 | while(true) { 35 | auto msg = session->recvMessage(); 36 | if(!msg) { 37 | break; 38 | } 39 | rt = servlet->handle(header, msg, session); 40 | if(rt) { 41 | SYLAR_LOG_DEBUG(g_logger) << "handle return " << rt; 42 | break; 43 | } 44 | } 45 | servlet->onClose(header, session); 46 | } while(0); 47 | session->close(); 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sylar/http/ws_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_HTTP_WS_SERVER_H__ 2 | #define __SYLAR_HTTP_WS_SERVER_H__ 3 | 4 | #include "sylar/tcp_server.h" 5 | #include "ws_session.h" 6 | #include "ws_servlet.h" 7 | 8 | namespace sylar { 9 | namespace http { 10 | 11 | class WSServer : public TcpServer { 12 | public: 13 | typedef std::shared_ptr<WSServer> ptr; 14 | 15 | WSServer(sylar::IOManager* worker = sylar::IOManager::GetThis() 16 | , sylar::IOManager* io_worker = sylar::IOManager::GetThis() 17 | , sylar::IOManager* accept_worker = sylar::IOManager::GetThis()); 18 | 19 | WSServletDispatch::ptr getWSServletDispatch() const { return m_dispatch;} 20 | void setWSServletDispatch(WSServletDispatch::ptr v) { m_dispatch = v;} 21 | protected: 22 | virtual void handleClient(Socket::ptr client) override; 23 | protected: 24 | WSServletDispatch::ptr m_dispatch; 25 | }; 26 | 27 | } 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /sylar/http/ws_servlet.cc: -------------------------------------------------------------------------------- 1 | #include "ws_servlet.h" 2 | 3 | namespace sylar { 4 | namespace http { 5 | 6 | FunctionWSServlet::FunctionWSServlet(callback cb 7 | ,on_connect_cb connect_cb 8 | ,on_close_cb close_cb) 9 | :WSServlet("FunctionWSServlet") 10 | ,m_callback(cb) 11 | ,m_onConnect(connect_cb) 12 | ,m_onClose(close_cb) { 13 | } 14 | 15 | int32_t FunctionWSServlet::onConnect(sylar::http::HttpRequest::ptr header 16 | ,sylar::http::WSSession::ptr session) { 17 | if(m_onConnect) { 18 | return m_onConnect(header, session); 19 | } 20 | return 0; 21 | } 22 | 23 | int32_t FunctionWSServlet::onClose(sylar::http::HttpRequest::ptr header 24 | ,sylar::http::WSSession::ptr session) { 25 | if(m_onClose) { 26 | return m_onClose(header, session); 27 | } 28 | return 0; 29 | } 30 | 31 | int32_t FunctionWSServlet::handle(sylar::http::HttpRequest::ptr header 32 | ,sylar::http::WSFrameMessage::ptr msg 33 | ,sylar::http::WSSession::ptr session) { 34 | if(m_callback) { 35 | return m_callback(header, msg, session); 36 | } 37 | return 0; 38 | } 39 | 40 | WSServletDispatch::WSServletDispatch() { 41 | m_name = "WSServletDispatch"; 42 | } 43 | 44 | void WSServletDispatch::addServlet(const std::string& uri 45 | ,FunctionWSServlet::callback cb 46 | ,FunctionWSServlet::on_connect_cb connect_cb 47 | ,FunctionWSServlet::on_close_cb close_cb) { 48 | ServletDispatch::addServlet(uri, std::make_shared<FunctionWSServlet>(cb, connect_cb, close_cb)); 49 | } 50 | 51 | void WSServletDispatch::addGlobServlet(const std::string& uri 52 | ,FunctionWSServlet::callback cb 53 | ,FunctionWSServlet::on_connect_cb connect_cb 54 | ,FunctionWSServlet::on_close_cb close_cb) { 55 | ServletDispatch::addGlobServlet(uri, std::make_shared<FunctionWSServlet>(cb, connect_cb, close_cb)); 56 | } 57 | 58 | WSServlet::ptr WSServletDispatch::getWSServlet(const std::string& uri) { 59 | auto slt = getMatchedServlet(uri); 60 | return std::dynamic_pointer_cast<WSServlet>(slt); 61 | } 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /sylar/http/ws_servlet.h: -------------------------------------------------------------------------------- 1 | #ifndef __HTTP_WS_SERVLET_H__ 2 | #define __HTTP_WS_SERVLET_H__ 3 | 4 | #include "ws_session.h" 5 | #include "sylar/thread.h" 6 | #include "servlet.h" 7 | 8 | namespace sylar { 9 | namespace http { 10 | 11 | class WSServlet : public Servlet { 12 | public: 13 | typedef std::shared_ptr<WSServlet> ptr; 14 | WSServlet(const std::string& name) 15 | :Servlet(name) { 16 | } 17 | virtual ~WSServlet() {} 18 | 19 | virtual int32_t handle(sylar::http::HttpRequest::ptr request 20 | , sylar::http::HttpResponse::ptr response 21 | , sylar::http::HttpSession::ptr session) override { 22 | return 0; 23 | } 24 | 25 | virtual int32_t onConnect(sylar::http::HttpRequest::ptr header 26 | ,sylar::http::WSSession::ptr session) = 0; 27 | virtual int32_t onClose(sylar::http::HttpRequest::ptr header 28 | ,sylar::http::WSSession::ptr session) = 0; 29 | virtual int32_t handle(sylar::http::HttpRequest::ptr header 30 | ,sylar::http::WSFrameMessage::ptr msg 31 | ,sylar::http::WSSession::ptr session) = 0; 32 | const std::string& getName() const { return m_name;} 33 | protected: 34 | std::string m_name; 35 | }; 36 | 37 | class FunctionWSServlet : public WSServlet { 38 | public: 39 | typedef std::shared_ptr<FunctionWSServlet> ptr; 40 | typedef std::function<int32_t (sylar::http::HttpRequest::ptr header 41 | ,sylar::http::WSSession::ptr session)> on_connect_cb; 42 | typedef std::function<int32_t (sylar::http::HttpRequest::ptr header 43 | ,sylar::http::WSSession::ptr session)> on_close_cb; 44 | typedef std::function<int32_t (sylar::http::HttpRequest::ptr header 45 | ,sylar::http::WSFrameMessage::ptr msg 46 | ,sylar::http::WSSession::ptr session)> callback; 47 | 48 | FunctionWSServlet(callback cb 49 | ,on_connect_cb connect_cb = nullptr 50 | ,on_close_cb close_cb = nullptr); 51 | 52 | virtual int32_t onConnect(sylar::http::HttpRequest::ptr header 53 | ,sylar::http::WSSession::ptr session) override; 54 | virtual int32_t onClose(sylar::http::HttpRequest::ptr header 55 | ,sylar::http::WSSession::ptr session) override; 56 | virtual int32_t handle(sylar::http::HttpRequest::ptr header 57 | ,sylar::http::WSFrameMessage::ptr msg 58 | ,sylar::http::WSSession::ptr session) override; 59 | protected: 60 | callback m_callback; 61 | on_connect_cb m_onConnect; 62 | on_close_cb m_onClose; 63 | }; 64 | 65 | class WSServletDispatch : public ServletDispatch { 66 | public: 67 | typedef std::shared_ptr<WSServletDispatch> ptr; 68 | typedef RWMutex RWMutexType; 69 | 70 | WSServletDispatch(); 71 | void addServlet(const std::string& uri 72 | ,FunctionWSServlet::callback cb 73 | ,FunctionWSServlet::on_connect_cb connect_cb = nullptr 74 | ,FunctionWSServlet::on_close_cb close_cb = nullptr); 75 | void addGlobServlet(const std::string& uri 76 | ,FunctionWSServlet::callback cb 77 | ,FunctionWSServlet::on_connect_cb connect_cb = nullptr 78 | ,FunctionWSServlet::on_close_cb close_cb = nullptr); 79 | WSServlet::ptr getWSServlet(const std::string& uri); 80 | }; 81 | 82 | } 83 | } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /sylar/http/ws_session.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_HTTP_WS_SESSION_H__ 2 | #define __SYLAR_HTTP_WS_SESSION_H__ 3 | 4 | #include "sylar/config.h" 5 | #include "sylar/http/http_session.h" 6 | #include <stdint.h> 7 | 8 | namespace sylar { 9 | namespace http { 10 | 11 | #pragma pack(1) 12 | struct WSFrameHead { 13 | enum OPCODE { 14 | /// 数据分片帧 15 | CONTINUE = 0, 16 | /// 文本帧 17 | TEXT_FRAME = 1, 18 | /// 二进制帧 19 | BIN_FRAME = 2, 20 | /// 断开连接 21 | CLOSE = 8, 22 | /// PING 23 | PING = 0x9, 24 | /// PONG 25 | PONG = 0xA 26 | }; 27 | uint32_t opcode: 4; 28 | bool rsv3: 1; 29 | bool rsv2: 1; 30 | bool rsv1: 1; 31 | bool fin: 1; 32 | uint32_t payload: 7; 33 | bool mask: 1; 34 | 35 | std::string toString() const; 36 | }; 37 | #pragma pack() 38 | 39 | class WSFrameMessage { 40 | public: 41 | typedef std::shared_ptr<WSFrameMessage> ptr; 42 | WSFrameMessage(int opcode = 0, const std::string& data = ""); 43 | 44 | int getOpcode() const { return m_opcode;} 45 | void setOpcode(int v) { m_opcode = v;} 46 | 47 | const std::string& getData() const { return m_data;} 48 | std::string& getData() { return m_data;} 49 | void setData(const std::string& v) { m_data = v;} 50 | private: 51 | int m_opcode; 52 | std::string m_data; 53 | }; 54 | 55 | class WSSession : public HttpSession { 56 | public: 57 | typedef std::shared_ptr<WSSession> ptr; 58 | WSSession(Socket::ptr sock, bool owner = true); 59 | 60 | /// server client 61 | HttpRequest::ptr handleShake(); 62 | 63 | WSFrameMessage::ptr recvMessage(); 64 | int32_t sendMessage(WSFrameMessage::ptr msg, bool fin = true); 65 | int32_t sendMessage(const std::string& msg, int32_t opcode = WSFrameHead::TEXT_FRAME, bool fin = true); 66 | int32_t ping(); 67 | int32_t pong(); 68 | private: 69 | bool handleServerShake(); 70 | bool handleClientShake(); 71 | }; 72 | 73 | extern sylar::ConfigVar<uint32_t>::ptr g_websocket_message_max_size; 74 | WSFrameMessage::ptr WSRecvMessage(Stream* stream, bool client); 75 | int32_t WSSendMessage(Stream* stream, WSFrameMessage::ptr msg, bool client, bool fin); 76 | int32_t WSPing(Stream* stream); 77 | int32_t WSPong(Stream* stream); 78 | 79 | } 80 | } 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /sylar/library.cc: -------------------------------------------------------------------------------- 1 | #include "library.h" 2 | 3 | #include <dlfcn.h> 4 | #include "sylar/config.h" 5 | #include "sylar/env.h" 6 | #include "sylar/log.h" 7 | 8 | namespace sylar { 9 | 10 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system"); 11 | 12 | typedef Module* (*create_module)(); 13 | typedef void (*destory_module)(Module*); 14 | 15 | class ModuleCloser { 16 | public: 17 | ModuleCloser(void* handle, destory_module d) 18 | :m_handle(handle) 19 | ,m_destory(d) { 20 | } 21 | 22 | void operator()(Module* module) { 23 | std::string name = module->getName(); 24 | std::string version = module->getVersion(); 25 | std::string path = module->getFilename(); 26 | m_destory(module); 27 | int rt = dlclose(m_handle); 28 | if(rt) { 29 | SYLAR_LOG_ERROR(g_logger) << "dlclose handle fail handle=" 30 | << m_handle << " name=" << name 31 | << " version=" << version 32 | << " path=" << path 33 | << " error=" << dlerror(); 34 | } else { 35 | SYLAR_LOG_INFO(g_logger) << "destory module=" << name 36 | << " version=" << version 37 | << " path=" << path 38 | << " handle=" << m_handle 39 | << " success"; 40 | } 41 | } 42 | private: 43 | void* m_handle; 44 | destory_module m_destory; 45 | }; 46 | 47 | Module::ptr Library::GetModule(const std::string& path) { 48 | void* handle = dlopen(path.c_str(), RTLD_NOW); 49 | if(!handle) { 50 | SYLAR_LOG_ERROR(g_logger) << "cannot load library path=" 51 | << path << " error=" << dlerror(); 52 | return nullptr; 53 | } 54 | 55 | create_module create = (create_module)dlsym(handle, "CreateModule"); 56 | if(!create) { 57 | SYLAR_LOG_ERROR(g_logger) << "cannot load symbol CreateModule in " 58 | << path << " error=" << dlerror(); 59 | dlclose(handle); 60 | return nullptr; 61 | } 62 | 63 | destory_module destory = (destory_module)dlsym(handle, "DestoryModule"); 64 | if(!destory) { 65 | SYLAR_LOG_ERROR(g_logger) << "cannot load symbol DestoryModule in " 66 | << path << " error=" << dlerror(); 67 | dlclose(handle); 68 | return nullptr; 69 | } 70 | 71 | Module::ptr module(create(), ModuleCloser(handle, destory)); 72 | module->setFilename(path); 73 | SYLAR_LOG_INFO(g_logger) << "load module name=" << module->getName() 74 | << " version=" << module->getVersion() 75 | << " path=" << module->getFilename() 76 | << " success"; 77 | Config::LoadFromConfDir(sylar::EnvMgr::GetInstance()->getConfigPath(), true); 78 | return module; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /sylar/library.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_LIBRARY_H__ 2 | #define __SYLAR_LIBRARY_H__ 3 | 4 | #include <memory> 5 | #include "module.h" 6 | 7 | namespace sylar { 8 | 9 | class Library { 10 | public: 11 | static Module::ptr GetModule(const std::string& path); 12 | }; 13 | 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /sylar/macro.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file macro.h 3 | * @brief 常用宏的封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-06-01 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_MACRO_H__ 10 | #define __SYLAR_MACRO_H__ 11 | 12 | #include <string.h> 13 | #include <assert.h> 14 | #include "log.h" 15 | #include "util.h" 16 | 17 | #if defined __GNUC__ || defined __llvm__ 18 | /// LIKCLY 宏的封装, 告诉编译器优化,条件大概率成立 19 | # define SYLAR_LIKELY(x) __builtin_expect(!!(x), 1) 20 | /// LIKCLY 宏的封装, 告诉编译器优化,条件大概率不成立 21 | # define SYLAR_UNLIKELY(x) __builtin_expect(!!(x), 0) 22 | #else 23 | # define SYLAR_LIKELY(x) (x) 24 | # define SYLAR_UNLIKELY(x) (x) 25 | #endif 26 | 27 | /// 断言宏封装 28 | #define SYLAR_ASSERT(x) \ 29 | if(SYLAR_UNLIKELY(!(x))) { \ 30 | SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "ASSERTION: " #x \ 31 | << "\nbacktrace:\n" \ 32 | << sylar::BacktraceToString(100, 2, " "); \ 33 | assert(x); \ 34 | } 35 | 36 | /// 断言宏封装 37 | #define SYLAR_ASSERT2(x, w) \ 38 | if(SYLAR_UNLIKELY(!(x))) { \ 39 | SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) << "ASSERTION: " #x \ 40 | << "\n" << w \ 41 | << "\nbacktrace:\n" \ 42 | << sylar::BacktraceToString(100, 2, " "); \ 43 | assert(x); \ 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /sylar/main.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/application.h" 2 | #include <stdlib.h> 3 | #include <time.h> 4 | 5 | int main(int argc, char** argv) { 6 | setenv("TZ", ":/etc/localtime", 1); 7 | tzset(); 8 | srand(time(0)); 9 | sylar::Application app; 10 | if(app.init(argc, argv)) { 11 | return app.run(); 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /sylar/mutex.cc: -------------------------------------------------------------------------------- 1 | #include "mutex.h" 2 | #include "macro.h" 3 | #include "scheduler.h" 4 | 5 | namespace sylar { 6 | 7 | Semaphore::Semaphore(uint32_t count) { 8 | if(sem_init(&m_semaphore, 0, count)) { 9 | throw std::logic_error("sem_init error"); 10 | } 11 | } 12 | 13 | Semaphore::~Semaphore() { 14 | sem_destroy(&m_semaphore); 15 | } 16 | 17 | void Semaphore::wait() { 18 | if(sem_wait(&m_semaphore)) { 19 | throw std::logic_error("sem_wait error"); 20 | } 21 | } 22 | 23 | void Semaphore::notify() { 24 | if(sem_post(&m_semaphore)) { 25 | throw std::logic_error("sem_post error"); 26 | } 27 | } 28 | 29 | FiberSemaphore::FiberSemaphore(size_t initial_concurrency) 30 | :m_concurrency(initial_concurrency) { 31 | } 32 | 33 | FiberSemaphore::~FiberSemaphore() { 34 | SYLAR_ASSERT(m_waiters.empty()); 35 | } 36 | 37 | bool FiberSemaphore::tryWait() { 38 | SYLAR_ASSERT(Scheduler::GetThis()); 39 | { 40 | MutexType::Lock lock(m_mutex); 41 | if(m_concurrency > 0u) { 42 | --m_concurrency; 43 | return true; 44 | } 45 | return false; 46 | } 47 | } 48 | 49 | void FiberSemaphore::wait() { 50 | SYLAR_ASSERT(Scheduler::GetThis()); 51 | { 52 | MutexType::Lock lock(m_mutex); 53 | if(m_concurrency > 0u) { 54 | --m_concurrency; 55 | return; 56 | } 57 | m_waiters.push_back(std::make_pair(Scheduler::GetThis(), Fiber::GetThis())); 58 | } 59 | Fiber::YieldToHold(); 60 | } 61 | 62 | void FiberSemaphore::notify() { 63 | MutexType::Lock lock(m_mutex); 64 | if(!m_waiters.empty()) { 65 | auto next = m_waiters.front(); 66 | m_waiters.pop_front(); 67 | next.first->schedule(next.second); 68 | } else { 69 | ++m_concurrency; 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /sylar/noncopyable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file noncopyable.h 3 | * @brief 不可拷贝对象封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-05-31 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_NONCOPYABLE_H__ 10 | #define __SYLAR_NONCOPYABLE_H__ 11 | 12 | namespace sylar { 13 | 14 | /** 15 | * @brief 对象无法拷贝,赋值 16 | */ 17 | class Noncopyable { 18 | public: 19 | /** 20 | * @brief 默认构造函数 21 | */ 22 | Noncopyable() = default; 23 | 24 | /** 25 | * @brief 默认析构函数 26 | */ 27 | ~Noncopyable() = default; 28 | 29 | /** 30 | * @brief 拷贝构造函数(禁用) 31 | */ 32 | Noncopyable(const Noncopyable&) = delete; 33 | 34 | /** 35 | * @brief 赋值函数(禁用) 36 | */ 37 | Noncopyable& operator=(const Noncopyable&) = delete; 38 | }; 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /sylar/ns/name_server_module.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_NS_NAME_SERVER_MODULE_H__ 2 | #define __SYLAR_NS_NAME_SERVER_MODULE_H__ 3 | 4 | #include "sylar/module.h" 5 | #include "ns_protocol.h" 6 | 7 | namespace sylar { 8 | namespace ns { 9 | 10 | class NameServerModule; 11 | class NSClientInfo { 12 | friend class NameServerModule; 13 | public: 14 | typedef std::shared_ptr<NSClientInfo> ptr; 15 | private: 16 | NSNode::ptr m_node; 17 | std::map<std::string, std::set<uint32_t> > m_domain2cmds; 18 | }; 19 | 20 | class NameServerModule : public RockModule { 21 | public: 22 | typedef std::shared_ptr<NameServerModule> ptr; 23 | NameServerModule(); 24 | 25 | virtual bool handleRockRequest(sylar::RockRequest::ptr request 26 | ,sylar::RockResponse::ptr response 27 | ,sylar::RockStream::ptr stream) override; 28 | virtual bool handleRockNotify(sylar::RockNotify::ptr notify 29 | ,sylar::RockStream::ptr stream) override; 30 | virtual bool onConnect(sylar::Stream::ptr stream) override; 31 | virtual bool onDisconnect(sylar::Stream::ptr stream) override; 32 | virtual std::string statusString() override; 33 | private: 34 | bool handleRegister(sylar::RockRequest::ptr request 35 | ,sylar::RockResponse::ptr response 36 | ,sylar::RockStream::ptr stream); 37 | bool handleQuery(sylar::RockRequest::ptr request 38 | ,sylar::RockResponse::ptr response 39 | ,sylar::RockStream::ptr stream); 40 | bool handleTick(sylar::RockRequest::ptr request 41 | ,sylar::RockResponse::ptr response 42 | ,sylar::RockStream::ptr stream); 43 | 44 | private: 45 | NSClientInfo::ptr get(sylar::RockStream::ptr rs); 46 | void set(sylar::RockStream::ptr rs, NSClientInfo::ptr info); 47 | 48 | void setQueryDomain(sylar::RockStream::ptr rs, const std::set<std::string>& ds); 49 | 50 | void doNotify(std::set<std::string>& domains, std::shared_ptr<NotifyMessage> nty); 51 | 52 | std::set<sylar::RockStream::ptr> getStreams(const std::string& domain); 53 | private: 54 | NSDomainSet::ptr m_domains; 55 | 56 | sylar::RWMutex m_mutex; 57 | std::map<sylar::RockStream::ptr, NSClientInfo::ptr> m_sessions; 58 | 59 | /// sessoin 关注的域名 60 | std::map<sylar::RockStream::ptr, std::set<std::string> > m_queryDomains; 61 | /// 域名对应关注的session 62 | std::map<std::string, std::set<sylar::RockStream::ptr> > m_domainToSessions; 63 | }; 64 | 65 | } 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /sylar/ns/ns_client.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_NS_NS_CLIENT_H__ 2 | #define __SYLAR_NS_NS_CLIENT_H__ 3 | 4 | #include "sylar/rock/rock_stream.h" 5 | #include "ns_protocol.h" 6 | 7 | namespace sylar { 8 | namespace ns { 9 | 10 | class NSClient : public RockConnection { 11 | public: 12 | typedef std::shared_ptr<NSClient> ptr; 13 | NSClient(); 14 | ~NSClient(); 15 | 16 | const std::set<std::string>& getQueryDomains(); 17 | void setQueryDomains(const std::set<std::string>& v); 18 | 19 | void addQueryDomain(const std::string& domain); 20 | void delQueryDomain(const std::string& domain); 21 | 22 | bool hasQueryDomain(const std::string& domain); 23 | 24 | RockResult::ptr query(); 25 | 26 | void init(); 27 | void uninit(); 28 | NSDomainSet::ptr getDomains() const { return m_domains;} 29 | private: 30 | void onQueryDomainChange(); 31 | bool onConnect(sylar::AsyncSocketStream::ptr stream); 32 | void onDisconnect(sylar::AsyncSocketStream::ptr stream); 33 | bool onNotify(sylar::RockNotify::ptr ,sylar::RockStream::ptr); 34 | 35 | void onTimer(); 36 | private: 37 | sylar::RWMutex m_mutex; 38 | std::set<std::string> m_queryDomains; 39 | NSDomainSet::ptr m_domains; 40 | uint32_t m_sn = 0; 41 | sylar::Timer::ptr m_timer; 42 | }; 43 | 44 | } 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /sylar/ns/ns_protobuf.proto: -------------------------------------------------------------------------------- 1 | package sylar.ns; 2 | 3 | message Node { 4 | optional string ip = 1; //ip地址 5 | optional uint32 port = 2; //端口号 6 | optional uint32 weight = 3; //权重 7 | } 8 | 9 | message RegisterInfo { 10 | optional string domain = 1; //域名 11 | repeated uint32 cmds = 2; //命令字 12 | optional Node node = 3; //节点信息 13 | } 14 | 15 | message RegisterRequest { 16 | repeated RegisterInfo infos = 1; //注册信息 17 | } 18 | 19 | message QueryRequest { 20 | repeated string domains = 1; //域名 21 | } 22 | 23 | message NodeInfo { 24 | optional string domain = 1; 25 | optional uint32 cmd = 2; 26 | repeated Node nodes = 3; 27 | } 28 | 29 | message QueryResponse { 30 | repeated NodeInfo infos = 1; 31 | } 32 | 33 | message NotifyMessage { 34 | repeated NodeInfo dels = 1; 35 | repeated NodeInfo updates = 2; 36 | } 37 | -------------------------------------------------------------------------------- /sylar/orm/column.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_ORM_COLUMN_H__ 2 | #define __SYLAR_ORM_COLUMN_H__ 3 | 4 | #include <memory> 5 | #include <string> 6 | #include "tinyxml2.h" 7 | 8 | namespace sylar { 9 | namespace orm { 10 | 11 | class Table; 12 | class Column { 13 | friend class Table; 14 | public: 15 | typedef std::shared_ptr<Column> ptr; 16 | enum Type { 17 | TYPE_NULL = 0, 18 | TYPE_INT8, 19 | TYPE_UINT8, 20 | TYPE_INT16, 21 | TYPE_UINT16, 22 | TYPE_INT32, 23 | TYPE_UINT32, 24 | TYPE_FLOAT, 25 | TYPE_DOUBLE, 26 | TYPE_INT64, 27 | TYPE_UINT64, 28 | TYPE_STRING, 29 | TYPE_TEXT, 30 | TYPE_BLOB, 31 | TYPE_TIMESTAMP 32 | }; 33 | 34 | const std::string& getName() const { return m_name;} 35 | const std::string& getType() const { return m_type;} 36 | const std::string& getDesc() const { return m_desc;} 37 | const std::string& getDefault() const { return m_default;} 38 | 39 | std::string getDefaultValueString(); 40 | std::string getSQLite3Default(); 41 | 42 | bool isAutoIncrement() const { return m_autoIncrement;} 43 | Type getDType() const { return m_dtype;} 44 | 45 | bool init(const tinyxml2::XMLElement& node); 46 | 47 | std::string getMemberDefine() const; 48 | std::string getGetFunDefine() const; 49 | std::string getSetFunDefine() const; 50 | std::string getSetFunImpl(const std::string& class_name, int idx) const; 51 | int getIndex() const { return m_index;} 52 | 53 | static Type ParseType(const std::string& v); 54 | static std::string TypeToString(Type type); 55 | 56 | std::string getDTypeString() { return TypeToString(m_dtype);} 57 | std::string getSQLite3TypeString(); 58 | std::string getMySQLTypeString(); 59 | 60 | std::string getBindString(); 61 | std::string getGetString(); 62 | const std::string& getUpdate() const { return m_update;} 63 | private: 64 | std::string m_name; 65 | std::string m_type; 66 | std::string m_default; 67 | std::string m_update; 68 | std::string m_desc; 69 | int m_index; 70 | 71 | bool m_autoIncrement; 72 | Type m_dtype; 73 | int m_length; 74 | }; 75 | 76 | } 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /sylar/orm/index.cc: -------------------------------------------------------------------------------- 1 | #include "index.h" 2 | #include "sylar/log.h" 3 | #include "sylar/util.h" 4 | 5 | namespace sylar { 6 | namespace orm { 7 | 8 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("orm"); 9 | 10 | Index::Type Index::ParseType(const std::string& v) { 11 | #define XX(a, b) \ 12 | if(v == b) {\ 13 | return a; \ 14 | } 15 | XX(TYPE_PK, "pk"); 16 | XX(TYPE_UNIQ, "uniq"); 17 | XX(TYPE_INDEX, "index"); 18 | #undef XX 19 | return TYPE_NULL; 20 | } 21 | 22 | std::string Index::TypeToString(Type v) { 23 | #define XX(a, b) \ 24 | if(v == a) { \ 25 | return b; \ 26 | } 27 | XX(TYPE_PK, "pk"); 28 | XX(TYPE_UNIQ, "uniq"); 29 | XX(TYPE_INDEX, "index"); 30 | #undef XX 31 | return ""; 32 | } 33 | 34 | bool Index::init(const tinyxml2::XMLElement& node) { 35 | if(!node.Attribute("name")) { 36 | SYLAR_LOG_ERROR(g_logger) << "index name not exists"; 37 | return false; 38 | } 39 | m_name = node.Attribute("name"); 40 | 41 | if(!node.Attribute("type")) { 42 | SYLAR_LOG_ERROR(g_logger) << "index name=" << m_name << " type is null"; 43 | return false; 44 | } 45 | 46 | m_type = node.Attribute("type"); 47 | m_dtype = ParseType(m_type); 48 | if(m_dtype == TYPE_NULL) { 49 | SYLAR_LOG_ERROR(g_logger) << "index name=" << m_name << " type=" << m_type 50 | << " invalid (pk, index, uniq)"; 51 | return false; 52 | } 53 | 54 | if(!node.Attribute("cols")) { 55 | SYLAR_LOG_ERROR(g_logger) << "index name=" << m_name << " cols is null"; 56 | } 57 | std::string tmp = node.Attribute("cols"); 58 | m_cols = sylar::split(tmp, ','); 59 | 60 | if(node.Attribute("desc")) { 61 | m_desc = node.Attribute("desc"); 62 | } 63 | return true; 64 | } 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sylar/orm/index.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_ORM_INDEX_H__ 2 | #define __SYLAR_ORM_INDEX_H__ 3 | 4 | #include <memory> 5 | #include <string> 6 | #include <vector> 7 | #include "tinyxml2.h" 8 | 9 | namespace sylar { 10 | namespace orm { 11 | 12 | class Index { 13 | public: 14 | enum Type { 15 | TYPE_NULL = 0, 16 | TYPE_PK, 17 | TYPE_UNIQ, 18 | TYPE_INDEX 19 | }; 20 | typedef std::shared_ptr<Index> ptr; 21 | const std::string& getName() const { return m_name;} 22 | const std::string& getType() const { return m_type;} 23 | const std::string& getDesc() const { return m_desc;} 24 | const std::vector<std::string>& getCols() const { return m_cols;} 25 | Type getDType() const { return m_dtype;} 26 | bool init(const tinyxml2::XMLElement& node); 27 | 28 | bool isPK() const { return m_type == "pk";} 29 | 30 | static Type ParseType(const std::string& v); 31 | static std::string TypeToString(Type v); 32 | private: 33 | std::string m_name; 34 | std::string m_type; 35 | std::string m_desc; 36 | std::vector<std::string> m_cols; 37 | 38 | Type m_dtype; 39 | }; 40 | 41 | } 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /sylar/orm/orm.cc: -------------------------------------------------------------------------------- 1 | #include "table.h" 2 | #include "sylar/util.h" 3 | #include "sylar/log.h" 4 | 5 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("orm"); 6 | 7 | void gen_cmake(const std::string& path, const std::map<std::string, sylar::orm::Table::ptr>& tbs) { 8 | std::ofstream ofs(path + "/CMakeLists.txt"); 9 | ofs << "cmake_minimum_required(VERSION 3.0)" << std::endl; 10 | ofs << "project(orm_data)" << std::endl; 11 | ofs << std::endl; 12 | ofs << "set(LIB_SRC" << std::endl; 13 | for(auto& i : tbs) { 14 | ofs << " " << sylar::replace(i.second->getNamespace(), ".", "/") 15 | << "/" << sylar::ToLower(i.second->getFilename()) << ".cc" << std::endl; 16 | } 17 | ofs << ")" << std::endl; 18 | ofs << "add_library(orm_data ${LIB_SRC})" << std::endl; 19 | ofs << "force_redefine_file_macro_for_sources(orm_data)" << std::endl; 20 | } 21 | 22 | 23 | int main(int argc, char** argv) { 24 | if(argc < 2) { 25 | std::cout << "use as[" << argv[0] << " orm_config_path orm_output_path]" << std::endl; 26 | } 27 | 28 | std::string out_path = "./orm_out"; 29 | std::string input_path = "bin/orm_conf"; 30 | if(argc > 1) { 31 | input_path = argv[1]; 32 | } 33 | if(argc > 2) { 34 | out_path = argv[2]; 35 | } 36 | std::vector<std::string> files; 37 | sylar::FSUtil::ListAllFile(files, input_path, ".xml"); 38 | std::vector<sylar::orm::Table::ptr> tbs; 39 | bool has_error = false; 40 | for(auto& i : files) { 41 | SYLAR_LOG_INFO(g_logger) << "init xml=" << i << " begin"; 42 | tinyxml2::XMLDocument doc; 43 | if(doc.LoadFile(i.c_str())) { 44 | SYLAR_LOG_ERROR(g_logger) << "error: " << doc.ErrorStr(); 45 | has_error = true; 46 | } else { 47 | sylar::orm::Table::ptr table(new sylar::orm::Table); 48 | if(!table->init(*doc.RootElement())) { 49 | SYLAR_LOG_ERROR(g_logger) << "table init error"; 50 | has_error = true; 51 | } else { 52 | tbs.push_back(table); 53 | } 54 | } 55 | SYLAR_LOG_INFO(g_logger) << "init xml=" << i << " end"; 56 | } 57 | if(has_error) { 58 | return 0; 59 | } 60 | 61 | std::map<std::string, sylar::orm::Table::ptr> orm_tbs; 62 | for(auto& i : tbs) { 63 | i->gen(out_path); 64 | orm_tbs[i->getName()] = i; 65 | } 66 | gen_cmake(out_path, orm_tbs); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /sylar/orm/table.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_ORM_TABLE_H__ 2 | #define __SYLAR_ORM_TABLE_H__ 3 | 4 | #include "column.h" 5 | #include "index.h" 6 | #include <fstream> 7 | 8 | namespace sylar { 9 | namespace orm { 10 | 11 | class Table { 12 | public: 13 | typedef std::shared_ptr<Table> ptr; 14 | const std::string& getName() const { return m_name;} 15 | const std::string& getNamespace() const { return m_namespace;} 16 | const std::string& getDesc() const { return m_desc;} 17 | 18 | const std::vector<Column::ptr>& getCols() const { return m_cols;} 19 | const std::vector<Index::ptr>& getIdxs() const { return m_idxs;} 20 | bool init(const tinyxml2::XMLElement& node); 21 | 22 | void gen(const std::string& path); 23 | 24 | std::string getFilename() const; 25 | private: 26 | void gen_inc(const std::string& path); 27 | void gen_src(const std::string& path); 28 | std::string genToStringInc(); 29 | std::string genToStringSrc(const std::string& class_name); 30 | std::string genToInsertSQL(const std::string& class_name); 31 | std::string genToUpdateSQL(const std::string& class_name); 32 | std::string genToDeleteSQL(const std::string& class_name); 33 | 34 | std::vector<Column::ptr> getPKs() const; 35 | Column::ptr getCol(const std::string& name) const; 36 | 37 | std::string genWhere() const; 38 | 39 | void gen_dao_inc(std::ofstream& ofs); 40 | void gen_dao_src(std::ofstream& ofs); 41 | 42 | enum DBType { 43 | TYPE_SQLITE3 = 1, 44 | TYPE_MYSQL = 2 45 | }; 46 | private: 47 | std::string m_name; 48 | std::string m_namespace; 49 | std::string m_desc; 50 | std::string m_subfix = "_info"; 51 | DBType m_type = TYPE_SQLITE3; 52 | std::string m_dbclass = "sylar::IDB"; 53 | std::string m_queryclass = "sylar::IDB"; 54 | std::string m_updateclass = "sylar::IDB"; 55 | std::vector<Column::ptr> m_cols; 56 | std::vector<Index::ptr> m_idxs; 57 | }; 58 | 59 | } 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /sylar/orm/util.cc: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include "sylar/util.h" 3 | 4 | namespace sylar { 5 | namespace orm { 6 | 7 | std::string GetAsVariable(const std::string& v) { 8 | return sylar::ToLower(v); 9 | } 10 | 11 | std::string GetAsClassName(const std::string& v) { 12 | auto vs = sylar::split(v, '_'); 13 | std::stringstream ss; 14 | for(auto& i : vs) { 15 | i[0] = toupper(i[0]); 16 | ss << i; 17 | } 18 | return ss.str(); 19 | } 20 | 21 | std::string GetAsMemberName(const std::string& v) { 22 | auto class_name = GetAsClassName(v); 23 | class_name[0] = tolower(class_name[0]); 24 | return "m_" + class_name; 25 | } 26 | 27 | std::string GetAsGetFunName(const std::string& v) { 28 | auto class_name = GetAsClassName(v); 29 | return "get" + class_name; 30 | } 31 | 32 | std::string GetAsSetFunName(const std::string& v) { 33 | auto class_name = GetAsClassName(v); 34 | return "set" + class_name; 35 | } 36 | 37 | std::string XmlToString(const tinyxml2::XMLNode& node) { 38 | return ""; 39 | } 40 | 41 | std::string GetAsDefineMacro(const std::string& v) { 42 | std::string tmp = sylar::replace(v, '.', '_'); 43 | tmp = sylar::ToUpper(tmp); 44 | return "__" + tmp + "__"; 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sylar/orm/util.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_ORM_UTIL_H__ 2 | #define __SYLAR_ORM_UTIL_H__ 3 | 4 | #include <tinyxml2.h> 5 | #include <string> 6 | 7 | namespace sylar { 8 | namespace orm { 9 | 10 | std::string GetAsVariable(const std::string& v); 11 | std::string GetAsClassName(const std::string& v); 12 | std::string GetAsMemberName(const std::string& v); 13 | std::string GetAsGetFunName(const std::string& v); 14 | std::string GetAsSetFunName(const std::string& v); 15 | std::string XmlToString(const tinyxml2::XMLNode& node); 16 | std::string GetAsDefineMacro(const std::string& v); 17 | 18 | } 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /sylar/protocol.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/protocol.h" 2 | #include "sylar/util.h" 3 | 4 | namespace sylar { 5 | 6 | ByteArray::ptr Message::toByteArray() { 7 | ByteArray::ptr ba(new ByteArray); 8 | if(serializeToByteArray(ba)) { 9 | return ba; 10 | } 11 | return nullptr; 12 | } 13 | 14 | Request::Request() 15 | :m_sn(0) 16 | ,m_cmd(0) { 17 | } 18 | 19 | bool Request::serializeToByteArray(ByteArray::ptr bytearray) { 20 | bytearray->writeFuint8(getType()); 21 | bytearray->writeUint32(m_sn); 22 | bytearray->writeUint32(m_cmd); 23 | return true; 24 | } 25 | 26 | bool Request::parseFromByteArray(ByteArray::ptr bytearray) { 27 | m_sn = bytearray->readUint32(); 28 | m_cmd = bytearray->readUint32(); 29 | return true; 30 | } 31 | 32 | Response::Response() 33 | :m_sn(0) 34 | ,m_cmd(0) 35 | ,m_result(404) 36 | ,m_resultStr("unhandle") { 37 | } 38 | 39 | bool Response::serializeToByteArray(ByteArray::ptr bytearray) { 40 | bytearray->writeFuint8(getType()); 41 | bytearray->writeUint32(m_sn); 42 | bytearray->writeUint32(m_cmd); 43 | bytearray->writeUint32(m_result); 44 | bytearray->writeStringVint(m_resultStr); 45 | return true; 46 | } 47 | 48 | bool Response::parseFromByteArray(ByteArray::ptr bytearray) { 49 | m_sn = bytearray->readUint32(); 50 | m_cmd = bytearray->readUint32(); 51 | m_result = bytearray->readUint32(); 52 | m_resultStr = bytearray->readStringVint(); 53 | return true; 54 | } 55 | 56 | Notify::Notify() 57 | :m_notify(0) { 58 | } 59 | 60 | bool Notify::serializeToByteArray(ByteArray::ptr bytearray) { 61 | bytearray->writeFuint8(getType()); 62 | bytearray->writeUint32(m_notify); 63 | return true; 64 | } 65 | 66 | bool Notify::parseFromByteArray(ByteArray::ptr bytearray) { 67 | m_notify = bytearray->readUint32(); 68 | return true; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /sylar/protocol.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file protocol.h 3 | * @brief 自定义协议 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-07-03 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_PROTOCOL_H__ 10 | #define __SYLAR_PROTOCOL_H__ 11 | 12 | #include <memory> 13 | #include "sylar/stream.h" 14 | #include "sylar/bytearray.h" 15 | 16 | namespace sylar { 17 | 18 | class Message { 19 | public: 20 | typedef std::shared_ptr<Message> ptr; 21 | enum MessageType { 22 | REQUEST = 1, 23 | RESPONSE = 2, 24 | NOTIFY = 3 25 | }; 26 | virtual ~Message() {} 27 | 28 | virtual ByteArray::ptr toByteArray(); 29 | virtual bool serializeToByteArray(ByteArray::ptr bytearray) = 0; 30 | virtual bool parseFromByteArray(ByteArray::ptr bytearray) = 0; 31 | 32 | virtual std::string toString() const = 0; 33 | virtual const std::string& getName() const = 0; 34 | virtual int32_t getType() const = 0; 35 | }; 36 | 37 | class MessageDecoder { 38 | public: 39 | typedef std::shared_ptr<MessageDecoder> ptr; 40 | 41 | virtual ~MessageDecoder() {} 42 | virtual Message::ptr parseFrom(Stream::ptr stream) = 0; 43 | virtual int32_t serializeTo(Stream::ptr stream, Message::ptr msg) = 0; 44 | }; 45 | 46 | class Request : public Message { 47 | public: 48 | typedef std::shared_ptr<Request> ptr; 49 | 50 | Request(); 51 | 52 | uint32_t getSn() const { return m_sn;} 53 | uint32_t getCmd() const { return m_cmd;} 54 | 55 | void setSn(uint32_t v) { m_sn = v;} 56 | void setCmd(uint32_t v) { m_cmd = v;} 57 | 58 | virtual bool serializeToByteArray(ByteArray::ptr bytearray) override; 59 | virtual bool parseFromByteArray(ByteArray::ptr bytearray) override; 60 | protected: 61 | uint32_t m_sn; 62 | uint32_t m_cmd; 63 | }; 64 | 65 | class Response : public Message { 66 | public: 67 | typedef std::shared_ptr<Response> ptr; 68 | 69 | Response(); 70 | 71 | uint32_t getSn() const { return m_sn;} 72 | uint32_t getCmd() const { return m_cmd;} 73 | uint32_t getResult() const { return m_result;} 74 | const std::string& getResultStr() const { return m_resultStr;} 75 | 76 | void setSn(uint32_t v) { m_sn = v;} 77 | void setCmd(uint32_t v) { m_cmd = v;} 78 | void setResult(uint32_t v) { m_result = v;} 79 | void setResultStr(const std::string& v) { m_resultStr = v;} 80 | 81 | virtual bool serializeToByteArray(ByteArray::ptr bytearray) override; 82 | virtual bool parseFromByteArray(ByteArray::ptr bytearray) override; 83 | protected: 84 | uint32_t m_sn; 85 | uint32_t m_cmd; 86 | uint32_t m_result; 87 | std::string m_resultStr; 88 | }; 89 | 90 | class Notify : public Message { 91 | public: 92 | typedef std::shared_ptr<Notify> ptr; 93 | Notify(); 94 | 95 | uint32_t getNotify() const { return m_notify;} 96 | void setNotify(uint32_t v) { m_notify = v;} 97 | 98 | virtual bool serializeToByteArray(ByteArray::ptr bytearray) override; 99 | virtual bool parseFromByteArray(ByteArray::ptr bytearray) override; 100 | protected: 101 | uint32_t m_notify; 102 | }; 103 | 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /sylar/rock/rock_protocol.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_ROCK_ROCK_PROTOCOL_H__ 2 | #define __SYLAR_ROCK_ROCK_PROTOCOL_H__ 3 | 4 | #include "sylar/protocol.h" 5 | #include "google/protobuf/message.h" 6 | 7 | namespace sylar { 8 | 9 | class RockBody { 10 | public: 11 | typedef std::shared_ptr<RockBody> ptr; 12 | virtual ~RockBody(){} 13 | 14 | void setBody(const std::string& v) { m_body = v;} 15 | const std::string& getBody() const { return m_body;} 16 | 17 | virtual bool serializeToByteArray(ByteArray::ptr bytearray); 18 | virtual bool parseFromByteArray(ByteArray::ptr bytearray); 19 | 20 | template<class T> 21 | std::shared_ptr<T> getAsPB() const { 22 | try { 23 | std::shared_ptr<T> data(new T); 24 | if(data->ParseFromString(m_body)) { 25 | return data; 26 | } 27 | } catch (...) { 28 | } 29 | return nullptr; 30 | } 31 | 32 | template<class T> 33 | bool setAsPB(const T& v) { 34 | try { 35 | return v.SerializeToString(&m_body); 36 | } catch (...) { 37 | } 38 | return false; 39 | } 40 | protected: 41 | std::string m_body; 42 | }; 43 | 44 | class RockResponse; 45 | class RockRequest : public Request, public RockBody { 46 | public: 47 | typedef std::shared_ptr<RockRequest> ptr; 48 | 49 | std::shared_ptr<RockResponse> createResponse(); 50 | 51 | virtual std::string toString() const override; 52 | virtual const std::string& getName() const override; 53 | virtual int32_t getType() const override; 54 | 55 | virtual bool serializeToByteArray(ByteArray::ptr bytearray) override; 56 | virtual bool parseFromByteArray(ByteArray::ptr bytearray) override; 57 | }; 58 | 59 | class RockResponse : public Response, public RockBody { 60 | public: 61 | typedef std::shared_ptr<RockResponse> ptr; 62 | 63 | virtual std::string toString() const override; 64 | virtual const std::string& getName() const override; 65 | virtual int32_t getType() const override; 66 | 67 | virtual bool serializeToByteArray(ByteArray::ptr bytearray) override; 68 | virtual bool parseFromByteArray(ByteArray::ptr bytearray) override; 69 | }; 70 | 71 | class RockNotify : public Notify, public RockBody { 72 | public: 73 | typedef std::shared_ptr<RockNotify> ptr; 74 | 75 | virtual std::string toString() const override; 76 | virtual const std::string& getName() const override; 77 | virtual int32_t getType() const override; 78 | 79 | virtual bool serializeToByteArray(ByteArray::ptr bytearray) override; 80 | virtual bool parseFromByteArray(ByteArray::ptr bytearray) override; 81 | }; 82 | 83 | struct RockMsgHeader { 84 | RockMsgHeader(); 85 | uint8_t magic[2]; 86 | uint8_t version; 87 | uint8_t flag; 88 | int32_t length; 89 | }; 90 | 91 | class RockMessageDecoder : public MessageDecoder { 92 | public: 93 | typedef std::shared_ptr<RockMessageDecoder> ptr; 94 | 95 | virtual Message::ptr parseFrom(Stream::ptr stream) override; 96 | virtual int32_t serializeTo(Stream::ptr stream, Message::ptr msg) override; 97 | }; 98 | 99 | } 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /sylar/rock/rock_server.cc: -------------------------------------------------------------------------------- 1 | #include "rock_server.h" 2 | #include "sylar/log.h" 3 | #include "sylar/module.h" 4 | 5 | namespace sylar { 6 | 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system"); 8 | 9 | RockServer::RockServer(const std::string& type 10 | ,sylar::IOManager* worker 11 | ,sylar::IOManager* io_worker 12 | ,sylar::IOManager* accept_worker) 13 | :TcpServer(worker, io_worker, accept_worker) { 14 | m_type = type; 15 | } 16 | 17 | void RockServer::handleClient(Socket::ptr client) { 18 | SYLAR_LOG_DEBUG(g_logger) << "handleClient " << *client; 19 | sylar::RockSession::ptr session(new sylar::RockSession(client)); 20 | session->setWorker(m_worker); 21 | ModuleMgr::GetInstance()->foreach(Module::ROCK, 22 | [session](Module::ptr m) { 23 | m->onConnect(session); 24 | }); 25 | session->setDisconnectCb( 26 | [](AsyncSocketStream::ptr stream) { 27 | ModuleMgr::GetInstance()->foreach(Module::ROCK, 28 | [stream](Module::ptr m) { 29 | m->onDisconnect(stream); 30 | }); 31 | } 32 | ); 33 | session->setRequestHandler( 34 | [](sylar::RockRequest::ptr req 35 | ,sylar::RockResponse::ptr rsp 36 | ,sylar::RockStream::ptr conn)->bool { 37 | //SYLAR_LOG_INFO(g_logger) << "handleReq " << req->toString() 38 | // << " body=" << req->getBody(); 39 | bool rt = false; 40 | ModuleMgr::GetInstance()->foreach(Module::ROCK, 41 | [&rt, req, rsp, conn](Module::ptr m) { 42 | if(rt) { 43 | return; 44 | } 45 | rt = m->handleRequest(req, rsp, conn); 46 | }); 47 | return rt; 48 | } 49 | ); 50 | session->setNotifyHandler( 51 | [](sylar::RockNotify::ptr nty 52 | ,sylar::RockStream::ptr conn)->bool { 53 | SYLAR_LOG_INFO(g_logger) << "handleNty " << nty->toString() 54 | << " body=" << nty->getBody(); 55 | bool rt = false; 56 | ModuleMgr::GetInstance()->foreach(Module::ROCK, 57 | [&rt, nty, conn](Module::ptr m) { 58 | if(rt) { 59 | return; 60 | } 61 | rt = m->handleNotify(nty, conn); 62 | }); 63 | return rt; 64 | } 65 | ); 66 | session->start(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /sylar/rock/rock_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_ROCK_SERVER_H__ 2 | #define __SYLAR_ROCK_SERVER_H__ 3 | 4 | #include "sylar/rock/rock_stream.h" 5 | #include "sylar/tcp_server.h" 6 | 7 | namespace sylar { 8 | 9 | class RockServer : public TcpServer { 10 | public: 11 | typedef std::shared_ptr<RockServer> ptr; 12 | RockServer(const std::string& type = "rock" 13 | ,sylar::IOManager* worker = sylar::IOManager::GetThis() 14 | ,sylar::IOManager* io_worker = sylar::IOManager::GetThis() 15 | ,sylar::IOManager* accept_worker = sylar::IOManager::GetThis()); 16 | 17 | protected: 18 | virtual void handleClient(Socket::ptr client) override; 19 | }; 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /sylar/singleton.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file singleton.h 3 | * @brief 单例模式封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-05-18 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_SINGLETON_H__ 10 | #define __SYLAR_SINGLETON_H__ 11 | 12 | #include <memory> 13 | 14 | namespace sylar { 15 | 16 | namespace { 17 | 18 | template<class T, class X, int N> 19 | T& GetInstanceX() { 20 | static T v; 21 | return v; 22 | } 23 | 24 | template<class T, class X, int N> 25 | std::shared_ptr<T> GetInstancePtr() { 26 | static std::shared_ptr<T> v(new T); 27 | return v; 28 | } 29 | 30 | 31 | } 32 | 33 | /** 34 | * @brief 单例模式封装类 35 | * @details T 类型 36 | * X 为了创造多个实例对应的Tag 37 | * N 同一个Tag创造多个实例索引 38 | */ 39 | template<class T, class X = void, int N = 0> 40 | class Singleton { 41 | public: 42 | /** 43 | * @brief 返回单例裸指针 44 | */ 45 | static T* GetInstance() { 46 | static T v; 47 | return &v; 48 | //return &GetInstanceX<T, X, N>(); 49 | } 50 | }; 51 | 52 | /** 53 | * @brief 单例模式智能指针封装类 54 | * @details T 类型 55 | * X 为了创造多个实例对应的Tag 56 | * N 同一个Tag创造多个实例索引 57 | */ 58 | template<class T, class X = void, int N = 0> 59 | class SingletonPtr { 60 | public: 61 | /** 62 | * @brief 返回单例智能指针 63 | */ 64 | static std::shared_ptr<T> GetInstance() { 65 | static std::shared_ptr<T> v(new T); 66 | return v; 67 | //return GetInstancePtr<T, X, N>(); 68 | } 69 | }; 70 | 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /sylar/stream.cc: -------------------------------------------------------------------------------- 1 | #include "stream.h" 2 | 3 | namespace sylar { 4 | 5 | int Stream::readFixSize(void* buffer, size_t length) { 6 | size_t offset = 0; 7 | int64_t left = length; 8 | while(left > 0) { 9 | int64_t len = read((char*)buffer + offset, left); 10 | if(len <= 0) { 11 | return len; 12 | } 13 | offset += len; 14 | left -= len; 15 | } 16 | return length; 17 | } 18 | 19 | int Stream::readFixSize(ByteArray::ptr ba, size_t length) { 20 | int64_t left = length; 21 | while(left > 0) { 22 | int64_t len = read(ba, left); 23 | if(len <= 0) { 24 | return len; 25 | } 26 | left -= len; 27 | } 28 | return length; 29 | } 30 | 31 | int Stream::writeFixSize(const void* buffer, size_t length) { 32 | size_t offset = 0; 33 | int64_t left = length; 34 | while(left > 0) { 35 | int64_t len = write((const char*)buffer + offset, left); 36 | if(len <= 0) { 37 | return len; 38 | } 39 | offset += len; 40 | left -= len; 41 | } 42 | return length; 43 | 44 | } 45 | 46 | int Stream::writeFixSize(ByteArray::ptr ba, size_t length) { 47 | int64_t left = length; 48 | while(left > 0) { 49 | int64_t len = write(ba, left); 50 | if(len <= 0) { 51 | return len; 52 | } 53 | left -= len; 54 | } 55 | return length; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /sylar/stream.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file stream.h 3 | * @brief 流接口 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-06-06 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_STREAM_H__ 10 | #define __SYLAR_STREAM_H__ 11 | 12 | #include <memory> 13 | #include "bytearray.h" 14 | 15 | namespace sylar { 16 | 17 | /** 18 | * @brief 流结构 19 | */ 20 | class Stream { 21 | public: 22 | typedef std::shared_ptr<Stream> ptr; 23 | /** 24 | * @brief 析构函数 25 | */ 26 | virtual ~Stream() {} 27 | 28 | /** 29 | * @brief 读数据 30 | * @param[out] buffer 接收数据的内存 31 | * @param[in] length 接收数据的内存大小 32 | * @return 33 | * @retval >0 返回接收到的数据的实际大小 34 | * @retval =0 被关闭 35 | * @retval <0 出现流错误 36 | */ 37 | virtual int read(void* buffer, size_t length) = 0; 38 | 39 | /** 40 | * @brief 读数据 41 | * @param[out] ba 接收数据的ByteArray 42 | * @param[in] length 接收数据的内存大小 43 | * @return 44 | * @retval >0 返回接收到的数据的实际大小 45 | * @retval =0 被关闭 46 | * @retval <0 出现流错误 47 | */ 48 | virtual int read(ByteArray::ptr ba, size_t length) = 0; 49 | 50 | /** 51 | * @brief 读固定长度的数据 52 | * @param[out] buffer 接收数据的内存 53 | * @param[in] length 接收数据的内存大小 54 | * @return 55 | * @retval >0 返回接收到的数据的实际大小 56 | * @retval =0 被关闭 57 | * @retval <0 出现流错误 58 | */ 59 | virtual int readFixSize(void* buffer, size_t length); 60 | 61 | /** 62 | * @brief 读固定长度的数据 63 | * @param[out] ba 接收数据的ByteArray 64 | * @param[in] length 接收数据的内存大小 65 | * @return 66 | * @retval >0 返回接收到的数据的实际大小 67 | * @retval =0 被关闭 68 | * @retval <0 出现流错误 69 | */ 70 | virtual int readFixSize(ByteArray::ptr ba, size_t length); 71 | 72 | /** 73 | * @brief 写数据 74 | * @param[in] buffer 写数据的内存 75 | * @param[in] length 写入数据的内存大小 76 | * @return 77 | * @retval >0 返回写入到的数据的实际大小 78 | * @retval =0 被关闭 79 | * @retval <0 出现流错误 80 | */ 81 | virtual int write(const void* buffer, size_t length) = 0; 82 | 83 | /** 84 | * @brief 写数据 85 | * @param[in] ba 写数据的ByteArray 86 | * @param[in] length 写入数据的内存大小 87 | * @return 88 | * @retval >0 返回写入到的数据的实际大小 89 | * @retval =0 被关闭 90 | * @retval <0 出现流错误 91 | */ 92 | virtual int write(ByteArray::ptr ba, size_t length) = 0; 93 | 94 | /** 95 | * @brief 写固定长度的数据 96 | * @param[in] buffer 写数据的内存 97 | * @param[in] length 写入数据的内存大小 98 | * @return 99 | * @retval >0 返回写入到的数据的实际大小 100 | * @retval =0 被关闭 101 | * @retval <0 出现流错误 102 | */ 103 | virtual int writeFixSize(const void* buffer, size_t length); 104 | 105 | /** 106 | * @brief 写固定长度的数据 107 | * @param[in] ba 写数据的ByteArray 108 | * @param[in] length 写入数据的内存大小 109 | * @return 110 | * @retval >0 返回写入到的数据的实际大小 111 | * @retval =0 被关闭 112 | * @retval <0 出现流错误 113 | */ 114 | virtual int writeFixSize(ByteArray::ptr ba, size_t length); 115 | 116 | /** 117 | * @brief 关闭流 118 | */ 119 | virtual void close() = 0; 120 | }; 121 | 122 | } 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /sylar/streams/socket_stream.cc: -------------------------------------------------------------------------------- 1 | #include "socket_stream.h" 2 | #include "sylar/util.h" 3 | 4 | namespace sylar { 5 | 6 | SocketStream::SocketStream(Socket::ptr sock, bool owner) 7 | :m_socket(sock) 8 | ,m_owner(owner) { 9 | } 10 | 11 | SocketStream::~SocketStream() { 12 | if(m_owner && m_socket) { 13 | m_socket->close(); 14 | } 15 | } 16 | 17 | bool SocketStream::isConnected() const { 18 | return m_socket && m_socket->isConnected(); 19 | } 20 | 21 | int SocketStream::read(void* buffer, size_t length) { 22 | if(!isConnected()) { 23 | return -1; 24 | } 25 | return m_socket->recv(buffer, length); 26 | } 27 | 28 | int SocketStream::read(ByteArray::ptr ba, size_t length) { 29 | if(!isConnected()) { 30 | return -1; 31 | } 32 | std::vector<iovec> iovs; 33 | ba->getWriteBuffers(iovs, length); 34 | int rt = m_socket->recv(&iovs[0], iovs.size()); 35 | if(rt > 0) { 36 | ba->setPosition(ba->getPosition() + rt); 37 | } 38 | return rt; 39 | } 40 | 41 | int SocketStream::write(const void* buffer, size_t length) { 42 | if(!isConnected()) { 43 | return -1; 44 | } 45 | return m_socket->send(buffer, length); 46 | } 47 | 48 | int SocketStream::write(ByteArray::ptr ba, size_t length) { 49 | if(!isConnected()) { 50 | return -1; 51 | } 52 | std::vector<iovec> iovs; 53 | ba->getReadBuffers(iovs, length); 54 | int rt = m_socket->send(&iovs[0], iovs.size()); 55 | if(rt > 0) { 56 | ba->setPosition(ba->getPosition() + rt); 57 | } 58 | return rt; 59 | } 60 | 61 | void SocketStream::close() { 62 | if(m_socket) { 63 | m_socket->close(); 64 | } 65 | } 66 | 67 | Address::ptr SocketStream::getRemoteAddress() { 68 | if(m_socket) { 69 | return m_socket->getRemoteAddress(); 70 | } 71 | return nullptr; 72 | } 73 | 74 | Address::ptr SocketStream::getLocalAddress() { 75 | if(m_socket) { 76 | return m_socket->getLocalAddress(); 77 | } 78 | return nullptr; 79 | } 80 | 81 | std::string SocketStream::getRemoteAddressString() { 82 | auto addr = getRemoteAddress(); 83 | if(addr) { 84 | return addr->toString(); 85 | } 86 | return ""; 87 | } 88 | 89 | std::string SocketStream::getLocalAddressString() { 90 | auto addr = getLocalAddress(); 91 | if(addr) { 92 | return addr->toString(); 93 | } 94 | return ""; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /sylar/streams/socket_stream.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file socket_stream.h 3 | * @brief Socket流式接口封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-06-06 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_SOCKET_STREAM_H__ 10 | #define __SYLAR_SOCKET_STREAM_H__ 11 | 12 | #include "sylar/stream.h" 13 | #include "sylar/socket.h" 14 | #include "sylar/mutex.h" 15 | #include "sylar/iomanager.h" 16 | 17 | namespace sylar { 18 | 19 | /** 20 | * @brief Socket流 21 | */ 22 | class SocketStream : public Stream { 23 | public: 24 | typedef std::shared_ptr<SocketStream> ptr; 25 | 26 | /** 27 | * @brief 构造函数 28 | * @param[in] sock Socket类 29 | * @param[in] owner 是否完全控制 30 | */ 31 | SocketStream(Socket::ptr sock, bool owner = true); 32 | 33 | /** 34 | * @brief 析构函数 35 | * @details 如果m_owner=true,则close 36 | */ 37 | ~SocketStream(); 38 | 39 | /** 40 | * @brief 读取数据 41 | * @param[out] buffer 待接收数据的内存 42 | * @param[in] length 待接收数据的内存长度 43 | * @return 44 | * @retval >0 返回实际接收到的数据长度 45 | * @retval =0 socket被远端关闭 46 | * @retval <0 socket错误 47 | */ 48 | virtual int read(void* buffer, size_t length) override; 49 | 50 | /** 51 | * @brief 读取数据 52 | * @param[out] ba 接收数据的ByteArray 53 | * @param[in] length 待接收数据的内存长度 54 | * @return 55 | * @retval >0 返回实际接收到的数据长度 56 | * @retval =0 socket被远端关闭 57 | * @retval <0 socket错误 58 | */ 59 | virtual int read(ByteArray::ptr ba, size_t length) override; 60 | 61 | /** 62 | * @brief 写入数据 63 | * @param[in] buffer 待发送数据的内存 64 | * @param[in] length 待发送数据的内存长度 65 | * @return 66 | * @retval >0 返回实际接收到的数据长度 67 | * @retval =0 socket被远端关闭 68 | * @retval <0 socket错误 69 | */ 70 | virtual int write(const void* buffer, size_t length) override; 71 | 72 | /** 73 | * @brief 写入数据 74 | * @param[in] ba 待发送数据的ByteArray 75 | * @param[in] length 待发送数据的内存长度 76 | * @return 77 | * @retval >0 返回实际接收到的数据长度 78 | * @retval =0 socket被远端关闭 79 | * @retval <0 socket错误 80 | */ 81 | virtual int write(ByteArray::ptr ba, size_t length) override; 82 | 83 | /** 84 | * @brief 关闭socket 85 | */ 86 | virtual void close() override; 87 | 88 | /** 89 | * @brief 返回Socket类 90 | */ 91 | Socket::ptr getSocket() const { return m_socket;} 92 | 93 | /** 94 | * @brief 返回是否连接 95 | */ 96 | bool isConnected() const; 97 | 98 | Address::ptr getRemoteAddress(); 99 | Address::ptr getLocalAddress(); 100 | std::string getRemoteAddressString(); 101 | std::string getLocalAddressString(); 102 | protected: 103 | /// Socket类 104 | Socket::ptr m_socket; 105 | /// 是否主控 106 | bool m_owner; 107 | }; 108 | 109 | } 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /sylar/streams/zlib_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_STREAMS_ZLIB_STREAM_H__ 2 | #define __SYLAR_STREAMS_ZLIB_STREAM_H__ 3 | 4 | #include "sylar/stream.h" 5 | #include <sys/uio.h> 6 | #include <zlib.h> 7 | #include <stdint.h> 8 | #include <vector> 9 | #include <string> 10 | #include <memory> 11 | 12 | namespace sylar { 13 | 14 | class ZlibStream : public Stream { 15 | public: 16 | typedef std::shared_ptr<ZlibStream> ptr; 17 | 18 | enum Type { 19 | ZLIB, 20 | DEFLATE, 21 | GZIP 22 | }; 23 | 24 | enum Strategy { 25 | DEFAULT = Z_DEFAULT_STRATEGY, 26 | FILTERED = Z_FILTERED, 27 | HUFFMAN = Z_HUFFMAN_ONLY, 28 | FIXED = Z_FIXED, 29 | RLE = Z_RLE 30 | }; 31 | 32 | enum CompressLevel { 33 | NO_COMPRESSION = Z_NO_COMPRESSION, 34 | BEST_SPEED = Z_BEST_SPEED, 35 | BEST_COMPRESSION = Z_BEST_COMPRESSION, 36 | DEFAULT_COMPRESSION = Z_DEFAULT_COMPRESSION 37 | }; 38 | 39 | static ZlibStream::ptr CreateGzip(bool encode, uint32_t buff_size = 4096); 40 | static ZlibStream::ptr CreateZlib(bool encode, uint32_t buff_size = 4096); 41 | static ZlibStream::ptr CreateDeflate(bool encode, uint32_t buff_size = 4096); 42 | static ZlibStream::ptr Create(bool encode, uint32_t buff_size = 4096, 43 | Type type = DEFLATE, int level = DEFAULT_COMPRESSION, int window_bits = 15 44 | ,int memlevel = 8, Strategy strategy = DEFAULT); 45 | 46 | ZlibStream(bool encode, uint32_t buff_size = 4096); 47 | ~ZlibStream(); 48 | 49 | virtual int read(void* buffer, size_t length) override; 50 | virtual int read(ByteArray::ptr ba, size_t length) override; 51 | virtual int write(const void* buffer, size_t length) override; 52 | virtual int write(ByteArray::ptr ba, size_t length) override; 53 | virtual void close() override; 54 | 55 | int flush(); 56 | 57 | bool isFree() const { return m_free;} 58 | void setFree(bool v) { m_free = v;} 59 | 60 | bool isEncode() const { return m_encode;} 61 | void setEndcode(bool v) { m_encode = v;} 62 | 63 | std::vector<iovec>& getBuffers() { return m_buffs;} 64 | std::string getResult() const; 65 | sylar::ByteArray::ptr getByteArray(); 66 | private: 67 | int init(Type type = DEFLATE, int level = DEFAULT_COMPRESSION 68 | ,int window_bits = 15, int memlevel = 8, Strategy strategy = DEFAULT); 69 | 70 | int encode(const iovec* v, const uint64_t& size, bool finish); 71 | int decode(const iovec* v, const uint64_t& size, bool finish); 72 | private: 73 | z_stream m_zstream; 74 | uint32_t m_buffSize; 75 | bool m_encode; 76 | bool m_free; 77 | std::vector<iovec> m_buffs; 78 | }; 79 | 80 | } 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /sylar/sylar.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sylar.h 3 | * @brief sylar头文件 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-05-24 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_SYLAR_H__ 10 | #define __SYLAR_SYLAR_H__ 11 | 12 | #include "address.h" 13 | #include "application.h" 14 | #include "bytearray.h" 15 | #include "config.h" 16 | #include "daemon.h" 17 | #include "endian.h" 18 | #include "env.h" 19 | #include "fd_manager.h" 20 | #include "fiber.h" 21 | #include "hook.h" 22 | #include "iomanager.h" 23 | #include "library.h" 24 | #include "log.h" 25 | #include "macro.h" 26 | #include "module.h" 27 | #include "mutex.h" 28 | #include "noncopyable.h" 29 | #include "protocol.h" 30 | #include "scheduler.h" 31 | #include "singleton.h" 32 | #include "socket.h" 33 | #include "stream.h" 34 | #include "tcp_server.h" 35 | #include "thread.h" 36 | #include "timer.h" 37 | #include "uri.h" 38 | #include "util.h" 39 | #include "worker.h" 40 | 41 | #include "db/db.h" 42 | #include "db/mysql.h" 43 | #include "db/sqlite3.h" 44 | 45 | #include "ds/cache_status.h" 46 | #include "ds/lru_cache.h" 47 | #include "ds/timed_cache.h" 48 | #include "ds/timed_lru_cache.h" 49 | 50 | #include "email/email.h" 51 | #include "email/smtp.h" 52 | 53 | #include "http/http.h" 54 | #include "http/http11_common.h" 55 | #include "http/http11_parser.h" 56 | #include "http/http_connection.h" 57 | #include "http/http_parser.h" 58 | #include "http/http_server.h" 59 | #include "http/http_session.h" 60 | #include "http/httpclient_parser.h" 61 | #include "http/servlet.h" 62 | #include "http/session_data.h" 63 | #include "http/ws_connection.h" 64 | #include "http/ws_server.h" 65 | #include "http/ws_servlet.h" 66 | #include "http/ws_session.h" 67 | 68 | #include "rock/rock_protocol.h" 69 | #include "rock/rock_server.h" 70 | #include "rock/rock_stream.h" 71 | 72 | #include "streams/async_socket_stream.h" 73 | #include "streams/load_balance.h" 74 | #include "streams/socket_stream.h" 75 | #include "streams/zlib_stream.h" 76 | 77 | #include "util/crypto_util.h" 78 | #include "util/hash_util.h" 79 | #include "util/json_util.h" 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /sylar/test.proto: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | message Hello { 4 | optional string name = 1; 5 | } 6 | -------------------------------------------------------------------------------- /sylar/thread.cc: -------------------------------------------------------------------------------- 1 | #include "thread.h" 2 | #include "log.h" 3 | #include "util.h" 4 | 5 | namespace sylar { 6 | 7 | static thread_local Thread* t_thread = nullptr; 8 | static thread_local std::string t_thread_name = "UNKNOW"; 9 | 10 | static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system"); 11 | 12 | Thread* Thread::GetThis() { 13 | return t_thread; 14 | } 15 | 16 | const std::string& Thread::GetName() { 17 | return t_thread_name; 18 | } 19 | 20 | void Thread::SetName(const std::string& name) { 21 | if(name.empty()) { 22 | return; 23 | } 24 | if(t_thread) { 25 | t_thread->m_name = name; 26 | } 27 | t_thread_name = name; 28 | } 29 | 30 | Thread::Thread(std::function<void()> cb, const std::string& name) 31 | :m_cb(cb) 32 | ,m_name(name) { 33 | if(name.empty()) { 34 | m_name = "UNKNOW"; 35 | } 36 | int rt = pthread_create(&m_thread, nullptr, &Thread::run, this); 37 | if(rt) { 38 | SYLAR_LOG_ERROR(g_logger) << "pthread_create thread fail, rt=" << rt 39 | << " name=" << name; 40 | throw std::logic_error("pthread_create error"); 41 | } 42 | m_semaphore.wait(); 43 | } 44 | 45 | Thread::~Thread() { 46 | if(m_thread) { 47 | pthread_detach(m_thread); 48 | } 49 | } 50 | 51 | void Thread::join() { 52 | if(m_thread) { 53 | int rt = pthread_join(m_thread, nullptr); 54 | if(rt) { 55 | SYLAR_LOG_ERROR(g_logger) << "pthread_join thread fail, rt=" << rt 56 | << " name=" << m_name; 57 | throw std::logic_error("pthread_join error"); 58 | } 59 | m_thread = 0; 60 | } 61 | } 62 | 63 | void* Thread::run(void* arg) { 64 | Thread* thread = (Thread*)arg; 65 | t_thread = thread; 66 | t_thread_name = thread->m_name; 67 | thread->m_id = sylar::GetThreadId(); 68 | pthread_setname_np(pthread_self(), thread->m_name.substr(0, 15).c_str()); 69 | 70 | std::function<void()> cb; 71 | cb.swap(thread->m_cb); 72 | 73 | thread->m_semaphore.notify(); 74 | 75 | cb(); 76 | return 0; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /sylar/thread.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file thread.h 3 | * @brief 线程相关的封装 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-05-31 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_THREAD_H__ 10 | #define __SYLAR_THREAD_H__ 11 | 12 | #include "mutex.h" 13 | 14 | namespace sylar { 15 | 16 | /** 17 | * @brief 线程类 18 | */ 19 | class Thread : Noncopyable { 20 | public: 21 | /// 线程智能指针类型 22 | typedef std::shared_ptr<Thread> ptr; 23 | 24 | /** 25 | * @brief 构造函数 26 | * @param[in] cb 线程执行函数 27 | * @param[in] name 线程名称 28 | */ 29 | Thread(std::function<void()> cb, const std::string& name); 30 | 31 | /** 32 | * @brief 析构函数 33 | */ 34 | ~Thread(); 35 | 36 | /** 37 | * @brief 线程ID 38 | */ 39 | pid_t getId() const { return m_id;} 40 | 41 | /** 42 | * @brief 线程名称 43 | */ 44 | const std::string& getName() const { return m_name;} 45 | 46 | /** 47 | * @brief 等待线程执行完成 48 | */ 49 | void join(); 50 | 51 | /** 52 | * @brief 获取当前的线程指针 53 | */ 54 | static Thread* GetThis(); 55 | 56 | /** 57 | * @brief 获取当前的线程名称 58 | */ 59 | static const std::string& GetName(); 60 | 61 | /** 62 | * @brief 设置当前线程名称 63 | * @param[in] name 线程名称 64 | */ 65 | static void SetName(const std::string& name); 66 | private: 67 | 68 | /** 69 | * @brief 线程执行函数 70 | */ 71 | static void* run(void* arg); 72 | private: 73 | /// 线程id 74 | pid_t m_id = -1; 75 | /// 线程结构 76 | pthread_t m_thread = 0; 77 | /// 线程执行函数 78 | std::function<void()> m_cb; 79 | /// 线程名称 80 | std::string m_name; 81 | /// 信号量 82 | Semaphore m_semaphore; 83 | }; 84 | 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /sylar/util/crypto_util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file crypto_util.h 3 | * @brief 加解密工具函数 4 | * @author sylar.yin 5 | * @email 564628276@qq.com 6 | * @date 2019-07-02 7 | * @copyright Copyright (c) 2019年 sylar.yin All rights reserved (www.sylar.top) 8 | */ 9 | #ifndef __SYLAR_UTIL_CRYPTO_UTIL_H__ 10 | #define __SYLAR_UTIL_CRYPTO_UTIL_H__ 11 | 12 | #include <openssl/ssl.h> 13 | #include <openssl/evp.h> 14 | #include <stdint.h> 15 | #include <memory> 16 | #include <string> 17 | 18 | namespace sylar { 19 | 20 | class CryptoUtil { 21 | public: 22 | //key 32字节 23 | static int32_t AES256Ecb(const void* key 24 | ,const void* in 25 | ,int32_t in_len 26 | ,void* out 27 | ,bool encode); 28 | 29 | //key 16字节 30 | static int32_t AES128Ecb(const void* key 31 | ,const void* in 32 | ,int32_t in_len 33 | ,void* out 34 | ,bool encode); 35 | 36 | //key 32字节 37 | //iv 16字节 38 | static int32_t AES256Cbc(const void* key, const void* iv 39 | ,const void* in, int32_t in_len 40 | ,void* out, bool encode); 41 | 42 | //key 16字节 43 | //iv 16字节 44 | static int32_t AES128Cbc(const void* key, const void* iv 45 | ,const void* in, int32_t in_len 46 | ,void* out, bool encode); 47 | 48 | static int32_t Crypto(const EVP_CIPHER* cipher, bool enc 49 | ,const void* key, const void* iv 50 | ,const void* in, int32_t in_len 51 | ,void* out, int32_t* out_len); 52 | }; 53 | 54 | 55 | class RSACipher { 56 | public: 57 | typedef std::shared_ptr<RSACipher> ptr; 58 | 59 | static int32_t GenerateKey(const std::string& pubkey_file 60 | ,const std::string& prikey_file 61 | ,uint32_t length = 1024); 62 | 63 | static RSACipher::ptr Create(const std::string& pubkey_file 64 | ,const std::string& prikey_file); 65 | 66 | RSACipher(); 67 | ~RSACipher(); 68 | 69 | int32_t privateEncrypt(const void* from, int flen, 70 | void* to, int padding = RSA_NO_PADDING); 71 | int32_t publicEncrypt(const void* from, int flen, 72 | void* to, int padding = RSA_NO_PADDING); 73 | int32_t privateDecrypt(const void* from, int flen, 74 | void* to, int padding = RSA_NO_PADDING); 75 | int32_t publicDecrypt(const void* from, int flen, 76 | void* to, int padding = RSA_NO_PADDING); 77 | int32_t privateEncrypt(const void* from, int flen, 78 | std::string& to, int padding = RSA_NO_PADDING); 79 | int32_t publicEncrypt(const void* from, int flen, 80 | std::string& to, int padding = RSA_NO_PADDING); 81 | int32_t privateDecrypt(const void* from, int flen, 82 | std::string& to, int padding = RSA_NO_PADDING); 83 | int32_t publicDecrypt(const void* from, int flen, 84 | std::string& to, int padding = RSA_NO_PADDING); 85 | 86 | 87 | const std::string& getPubkeyStr() const { return m_pubkeyStr;} 88 | const std::string& getPrikeyStr() const { return m_prikeyStr;} 89 | 90 | int32_t getPubRSASize(); 91 | int32_t getPriRSASize(); 92 | private: 93 | RSA* m_pubkey; 94 | RSA* m_prikey; 95 | std::string m_pubkeyStr; 96 | std::string m_prikeyStr; 97 | }; 98 | 99 | 100 | } 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /sylar/util/hash_util.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_UTIL_HASH_UTIL_H__ 2 | #define __SYLAR_UTIL_HASH_UTIL_H__ 3 | 4 | #include <stdint.h> 5 | #include <string> 6 | #include <vector> 7 | 8 | namespace sylar { 9 | 10 | uint32_t murmur3_hash(const char * str, const uint32_t & seed = 1060627423); 11 | uint64_t murmur3_hash64(const char * str, const uint32_t & seed = 1060627423, const uint32_t& seed2 = 1050126127); 12 | uint32_t murmur3_hash(const void* str, const uint32_t& size, const uint32_t & seed = 1060627423); 13 | uint64_t murmur3_hash64(const void* str, const uint32_t& size, const uint32_t & seed = 1060627423, const uint32_t& seed2 = 1050126127); 14 | uint32_t quick_hash(const char * str); 15 | uint32_t quick_hash(const void* str, uint32_t size); 16 | 17 | std::string base64decode(const std::string &src); 18 | std::string base64encode(const std::string &data); 19 | std::string base64encode(const void *data, size_t len); 20 | 21 | // Returns result in hex 22 | std::string md5(const std::string &data); 23 | std::string sha1(const std::string &data); 24 | // Returns result in blob 25 | std::string md5sum(const std::string &data); 26 | std::string md5sum(const void *data, size_t len); 27 | std::string sha0sum(const std::string &data); 28 | std::string sha0sum(const void *data, size_t len); 29 | std::string sha1sum(const std::string &data); 30 | std::string sha1sum(const void *data, size_t len); 31 | std::string hmac_md5(const std::string &text, const std::string &key); 32 | std::string hmac_sha1(const std::string &text, const std::string &key); 33 | std::string hmac_sha256(const std::string &text, const std::string &key); 34 | 35 | /// Output must be of size len * 2, and will *not* be null-terminated 36 | void hexstring_from_data(const void *data, size_t len, char *output); 37 | std::string hexstring_from_data(const void *data, size_t len); 38 | std::string hexstring_from_data(const std::string &data); 39 | 40 | /// Output must be of size length / 2, and will *not* be null-terminated 41 | /// std::invalid_argument will be thrown if hexstring is not hex 42 | void data_from_hexstring(const char *hexstring, size_t length, void *output); 43 | std::string data_from_hexstring(const char *hexstring, size_t length); 44 | std::string data_from_hexstring(const std::string &data); 45 | 46 | std::string replace(const std::string &str, char find, char replaceWith); 47 | std::string replace(const std::string &str, char find, const std::string &replaceWith); 48 | std::string replace(const std::string &str, const std::string &find, const std::string &replaceWith); 49 | 50 | std::vector<std::string> split(const std::string &str, char delim, size_t max = ~0); 51 | std::vector<std::string> split(const std::string &str, const char *delims, size_t max = ~0); 52 | 53 | std::string random_string(size_t len 54 | ,const std::string& chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /sylar/util/json_util.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_UTIL_JSON_UTIL_H__ 2 | #define __SYLAR_UTIL_JSON_UTIL_H__ 3 | 4 | #include <string> 5 | #include <iostream> 6 | #include <json/json.h> 7 | 8 | namespace sylar { 9 | 10 | class JsonUtil { 11 | public: 12 | static bool NeedEscape(const std::string& v); 13 | static std::string Escape(const std::string& v); 14 | static std::string GetString(const Json::Value& json 15 | ,const std::string& name 16 | ,const std::string& default_value = ""); 17 | static double GetDouble(const Json::Value& json 18 | ,const std::string& name 19 | ,double default_value = 0); 20 | static int32_t GetInt32(const Json::Value& json 21 | ,const std::string& name 22 | ,int32_t default_value = 0); 23 | static uint32_t GetUint32(const Json::Value& json 24 | ,const std::string& name 25 | ,uint32_t default_value = 0); 26 | static int64_t GetInt64(const Json::Value& json 27 | ,const std::string& name 28 | ,int64_t default_value = 0); 29 | static uint64_t GetUint64(const Json::Value& json 30 | ,const std::string& name 31 | ,uint64_t default_value = 0); 32 | static bool FromString(Json::Value& json, const std::string& v); 33 | static std::string ToString(const Json::Value& json); 34 | }; 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /sylar/worker.cc: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | #include "config.h" 3 | #include "util.h" 4 | 5 | namespace sylar { 6 | 7 | static sylar::ConfigVar<std::map<std::string, std::map<std::string, std::string> > >::ptr g_worker_config 8 | = sylar::Config::Lookup("workers", std::map<std::string, std::map<std::string, std::string> >(), "worker config"); 9 | 10 | WorkerGroup::WorkerGroup(uint32_t batch_size, sylar::Scheduler* s) 11 | :m_batchSize(batch_size) 12 | ,m_finish(false) 13 | ,m_scheduler(s) 14 | ,m_sem(batch_size) { 15 | } 16 | 17 | WorkerGroup::~WorkerGroup() { 18 | waitAll(); 19 | } 20 | 21 | void WorkerGroup::schedule(std::function<void()> cb, int thread) { 22 | m_sem.wait(); 23 | m_scheduler->schedule(std::bind(&WorkerGroup::doWork 24 | ,shared_from_this(), cb), thread); 25 | } 26 | 27 | void WorkerGroup::doWork(std::function<void()> cb) { 28 | cb(); 29 | m_sem.notify(); 30 | } 31 | 32 | void WorkerGroup::waitAll() { 33 | if(!m_finish) { 34 | m_finish = true; 35 | for(uint32_t i = 0; i < m_batchSize; ++i) { 36 | m_sem.wait(); 37 | } 38 | } 39 | } 40 | 41 | WorkerManager::WorkerManager() 42 | :m_stop(false) { 43 | } 44 | 45 | void WorkerManager::add(Scheduler::ptr s) { 46 | m_datas[s->getName()].push_back(s); 47 | } 48 | 49 | Scheduler::ptr WorkerManager::get(const std::string& name) { 50 | auto it = m_datas.find(name); 51 | if(it == m_datas.end()) { 52 | return nullptr; 53 | } 54 | if(it->second.size() == 1) { 55 | return it->second[0]; 56 | } 57 | return it->second[rand() % it->second.size()]; 58 | } 59 | 60 | IOManager::ptr WorkerManager::getAsIOManager(const std::string& name) { 61 | return std::dynamic_pointer_cast<IOManager>(get(name)); 62 | } 63 | 64 | bool WorkerManager::init(const std::map<std::string, std::map<std::string, std::string> >& v) { 65 | for(auto& i : v) { 66 | std::string name = i.first; 67 | int32_t thread_num = sylar::GetParamValue(i.second, "thread_num", 1); 68 | int32_t worker_num = sylar::GetParamValue(i.second, "worker_num", 1); 69 | 70 | for(int32_t x = 0; x < worker_num; ++x) { 71 | Scheduler::ptr s; 72 | if(!x) { 73 | s = std::make_shared<IOManager>(thread_num, false, name); 74 | } else { 75 | s = std::make_shared<IOManager>(thread_num, false, name + "-" + std::to_string(x)); 76 | } 77 | add(s); 78 | } 79 | } 80 | m_stop = m_datas.empty(); 81 | return true; 82 | } 83 | 84 | bool WorkerManager::init() { 85 | auto workers = g_worker_config->getValue(); 86 | return init(workers); 87 | } 88 | 89 | void WorkerManager::stop() { 90 | if(m_stop) { 91 | return; 92 | } 93 | for(auto& i : m_datas) { 94 | for(auto& n : i.second) { 95 | n->schedule([](){}); 96 | n->stop(); 97 | } 98 | } 99 | m_datas.clear(); 100 | m_stop = true; 101 | } 102 | 103 | uint32_t WorkerManager::getCount() { 104 | return m_datas.size(); 105 | } 106 | 107 | std::ostream& WorkerManager::dump(std::ostream& os) { 108 | for(auto& i : m_datas) { 109 | for(auto& n : i.second) { 110 | n->dump(os) << std::endl; 111 | } 112 | } 113 | return os; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /sylar/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_WORKER_H__ 2 | #define __SYLAR_WORKER_H__ 3 | 4 | #include "mutex.h" 5 | #include "singleton.h" 6 | #include "log.h" 7 | #include "iomanager.h" 8 | 9 | namespace sylar { 10 | 11 | class WorkerGroup : Noncopyable, public std::enable_shared_from_this<WorkerGroup> { 12 | public: 13 | typedef std::shared_ptr<WorkerGroup> ptr; 14 | static WorkerGroup::ptr Create(uint32_t batch_size, sylar::Scheduler* s = sylar::Scheduler::GetThis()) { 15 | return std::make_shared<WorkerGroup>(batch_size, s); 16 | } 17 | 18 | WorkerGroup(uint32_t batch_size, sylar::Scheduler* s = sylar::Scheduler::GetThis()); 19 | ~WorkerGroup(); 20 | 21 | void schedule(std::function<void()> cb, int thread = -1); 22 | void waitAll(); 23 | private: 24 | void doWork(std::function<void()> cb); 25 | private: 26 | uint32_t m_batchSize; 27 | bool m_finish; 28 | Scheduler* m_scheduler; 29 | FiberSemaphore m_sem; 30 | }; 31 | 32 | class WorkerManager { 33 | public: 34 | WorkerManager(); 35 | void add(Scheduler::ptr s); 36 | Scheduler::ptr get(const std::string& name); 37 | IOManager::ptr getAsIOManager(const std::string& name); 38 | 39 | template<class FiberOrCb> 40 | void schedule(const std::string& name, FiberOrCb fc, int thread = -1) { 41 | auto s = get(name); 42 | if(s) { 43 | s->schedule(fc, thread); 44 | } else { 45 | static sylar::Logger::ptr s_logger = SYLAR_LOG_NAME("system"); 46 | SYLAR_LOG_ERROR(s_logger) << "schedule name=" << name 47 | << " not exists"; 48 | } 49 | } 50 | 51 | template<class Iter> 52 | void schedule(const std::string& name, Iter begin, Iter end) { 53 | auto s = get(name); 54 | if(s) { 55 | s->schedule(begin, end); 56 | } else { 57 | static sylar::Logger::ptr s_logger = SYLAR_LOG_NAME("system"); 58 | SYLAR_LOG_ERROR(s_logger) << "schedule name=" << name 59 | << " not exists"; 60 | } 61 | } 62 | 63 | bool init(); 64 | bool init(const std::map<std::string, std::map<std::string, std::string> >& v); 65 | void stop(); 66 | 67 | bool isStoped() const { return m_stop;} 68 | std::ostream& dump(std::ostream& os); 69 | 70 | uint32_t getCount(); 71 | private: 72 | std::map<std::string, std::vector<Scheduler::ptr> > m_datas; 73 | bool m_stop; 74 | }; 75 | 76 | typedef sylar::Singleton<WorkerManager> WorkerMgr; 77 | 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /sylar/zk_client.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYLAR_ZK_CLIENT_H__ 2 | #define __SYLAR_ZK_CLIENT_H__ 3 | 4 | #include <memory> 5 | #include <functional> 6 | #include <string> 7 | #include <stdint.h> 8 | #include <vector> 9 | 10 | #ifndef THREADED 11 | #define THREADED 12 | #endif 13 | 14 | #include <zookeeper/zookeeper.h> 15 | 16 | namespace sylar { 17 | 18 | class ZKClient : public std::enable_shared_from_this<ZKClient> { 19 | public: 20 | class EventType { 21 | public: 22 | static const int CREATED; // = ZOO_CREATED_EVENT; 23 | static const int DELETED; // = ZOO_DELETED_EVENT; 24 | static const int CHANGED; // = ZOO_CHANGED_EVENT; 25 | static const int CHILD ; // = ZOO_CHILD_EVENT; 26 | static const int SESSION; // = ZOO_SESSION_EVENT; 27 | static const int NOWATCHING; // = ZOO_NOTWATCHING_EVENT; 28 | }; 29 | class FlagsType { 30 | public: 31 | static const int EPHEMERAL; // = ZOO_EPHEMERAL; 32 | static const int SEQUENCE; // = ZOO_SEQUENCE; 33 | static const int CONTAINER; // = ZOO_CONTAINER; 34 | }; 35 | class StateType { 36 | public: 37 | static const int EXPIRED_SESSION; // = ZOO_EXPIRED_SESSION_STATE; 38 | static const int AUTH_FAILED; // = ZOO_AUTH_FAILED_STATE; 39 | static const int CONNECTING; // = ZOO_CONNECTING_STATE; 40 | static const int ASSOCIATING; // = ZOO_ASSOCIATING_STATE; 41 | static const int CONNECTED; // = ZOO_CONNECTED_STATE; 42 | static const int READONLY; // = ZOO_READONLY_STATE; 43 | static const int NOTCONNECTED; // = ZOO_NOTCONNECTED_STATE; 44 | }; 45 | 46 | typedef std::shared_ptr<ZKClient> ptr; 47 | typedef std::function<void(int type, int stat, const std::string& path, ZKClient::ptr)> watcher_callback; 48 | typedef void(*log_callback)(const char *message); 49 | 50 | ZKClient(); 51 | ~ZKClient(); 52 | 53 | bool init(const std::string& hosts, int recv_timeout, watcher_callback cb, log_callback lcb = nullptr); 54 | int32_t setServers(const std::string& hosts); 55 | 56 | int32_t create(const std::string& path, const std::string& val, std::string& new_path 57 | , const struct ACL_vector* acl = &ZOO_OPEN_ACL_UNSAFE 58 | , int flags = 0); 59 | int32_t exists(const std::string& path, bool watch, Stat* stat = nullptr); 60 | int32_t del(const std::string& path, int version = -1); 61 | int32_t get(const std::string& path, std::string& val, bool watch, Stat* stat = nullptr); 62 | int32_t getConfig(std::string& val, bool watch, Stat* stat = nullptr); 63 | int32_t set(const std::string& path, const std::string& val, int version = -1, Stat* stat = nullptr); 64 | int32_t getChildren(const std::string& path, std::vector<std::string>& val, bool watch, Stat* stat = nullptr); 65 | int32_t close(); 66 | int32_t getState(); 67 | std::string getCurrentServer(); 68 | 69 | bool reconnect(); 70 | private: 71 | static void OnWatcher(zhandle_t *zh, int type, int stat, const char *path,void *watcherCtx); 72 | typedef std::function<void(int type, int stat, const std::string& path)> watcher_callback2; 73 | private: 74 | zhandle_t* m_handle; 75 | std::string m_hosts; 76 | watcher_callback2 m_watcherCb; 77 | log_callback m_logCb; 78 | int32_t m_recvTimeout; 79 | }; 80 | 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /template/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(project_name) 3 | 4 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sylar) 5 | 6 | include (sylar/cmake/utils.cmake) 7 | 8 | set(CMAKE_VERBOSE_MAKEFILE ON) 9 | set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -rdynamic -O0 -ggdb -std=c++11 -Wall -Wno-deprecated -Werror -Wno-unused-function -Wno-builtin-macro-redefined") 10 | 11 | include_directories(.) 12 | include_directories(/apps/sylar/include) 13 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar) 14 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar/thirdpart) 15 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar/thirdpart) 16 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar/thirdpart/yaml-cpp/include) 17 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/sylar/thirdpart/jsoncpp-1.8.4/include) 18 | link_directories(/apps/sylar/lib) 19 | 20 | find_package(Boost REQUIRED) 21 | if(Boost_FOUND) 22 | include_directories(${Boost_INCLUDE_DIRS}) 23 | endif() 24 | 25 | #find_package(Protobuf REQUIRED) 26 | #if(Protobuf_FOUND) 27 | # include_directories(${Protobuf_INCLUDE_DIRS}) 28 | #endif() 29 | find_package(OpenSSL REQUIRED) 30 | if(OPENSSL_FOUND) 31 | include_directories(${OPENSSL_INCLUDE_DIR}) 32 | endif() 33 | 34 | set(LIB_SRC 35 | template/my_module.cc 36 | ) 37 | 38 | #PROTOBUF_GENERATE_CPP(PB_SRCS PB_HDRS sylar/test.proto) 39 | #list(APPEND LIB_SRC ${PB_SRCS}) 40 | # 41 | #message(STATUS ${LIB_SRC}) 42 | 43 | add_library(project_name SHARED ${LIB_SRC}) 44 | force_redefine_file_macro_for_sources(project_name) 45 | 46 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 47 | SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) 48 | -------------------------------------------------------------------------------- /template/bin/conf/log.yml: -------------------------------------------------------------------------------- 1 | logs: 2 | - name: root 3 | level: info 4 | appenders: 5 | - type: FileLogAppender 6 | file: /apps/logs/project_name/root.log 7 | - type: StdoutLogAppender 8 | - name: system 9 | level: info 10 | appenders: 11 | - type: FileLogAppender 12 | file: /apps/logs/project_name/system.log 13 | - type: StdoutLogAppender 14 | -------------------------------------------------------------------------------- /template/bin/conf/server.yml: -------------------------------------------------------------------------------- 1 | servers: 2 | - address: ["0.0.0.0:8090", "127.0.0.1:0", "/tmp/test.sock"] 3 | keepalive: 1 4 | timeout: 1000 5 | name: sylar/1.1 6 | accept_worker: accept 7 | io_worker: io 8 | process_worker: io 9 | type: http 10 | - address: ["0.0.0.0:8062", "0.0.0.0:8061"] 11 | timeout: 1000 12 | name: sylar-rock/1.0 13 | accept_worker: accept 14 | io_worker: io 15 | process_worker: io 16 | type: rock 17 | -------------------------------------------------------------------------------- /template/bin/conf/system.yml: -------------------------------------------------------------------------------- 1 | server: 2 | work_path: /apps/work/project_name 3 | pid_file: project_name.pid 4 | -------------------------------------------------------------------------------- /template/bin/conf/worker.yml: -------------------------------------------------------------------------------- 1 | workers: 2 | io: 3 | thread_num: 4 4 | accept: 5 | thread_num: 1 6 | -------------------------------------------------------------------------------- /template/move.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -d bin/module ] 4 | then 5 | mkdir bin/module 6 | else 7 | unlink bin/project_name 8 | unlink bin/module/libproject_name.so 9 | fi 10 | 11 | cp sylar/bin/sylar bin/project_name 12 | cp lib/libproject_name.so bin/module/ 13 | -------------------------------------------------------------------------------- /template/template/my_module.cc: -------------------------------------------------------------------------------- 1 | #include "my_module.h" 2 | #include "sylar/config.h" 3 | #include "sylar/log.h" 4 | 5 | namespace name_space { 6 | 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 8 | 9 | MyModule::MyModule() 10 | :sylar::Module("project_name", "1.0", "") { 11 | } 12 | 13 | bool MyModule::onLoad() { 14 | SYLAR_LOG_INFO(g_logger) << "onLoad"; 15 | return true; 16 | } 17 | 18 | bool MyModule::onUnload() { 19 | SYLAR_LOG_INFO(g_logger) << "onUnload"; 20 | return true; 21 | } 22 | 23 | bool MyModule::onServerReady() { 24 | SYLAR_LOG_INFO(g_logger) << "onServerReady"; 25 | return true; 26 | } 27 | 28 | bool MyModule::onServerUp() { 29 | SYLAR_LOG_INFO(g_logger) << "onServerUp"; 30 | return true; 31 | } 32 | 33 | } 34 | 35 | extern "C" { 36 | 37 | sylar::Module* CreateModule() { 38 | sylar::Module* module = new name_space::MyModule; 39 | SYLAR_LOG_INFO(name_space::g_logger) << "CreateModule " << module; 40 | return module; 41 | } 42 | 43 | void DestoryModule(sylar::Module* module) { 44 | SYLAR_LOG_INFO(name_space::g_logger) << "CreateModule " << module; 45 | delete module; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /template/template/my_module.h: -------------------------------------------------------------------------------- 1 | #include "sylar/module.h" 2 | 3 | namespace name_space { 4 | 5 | class MyModule : public sylar::Module { 6 | public: 7 | typedef std::shared_ptr<MyModule> ptr; 8 | MyModule(); 9 | bool onLoad() override; 10 | bool onUnload() override; 11 | bool onServerReady() override; 12 | bool onServerUp() override; 13 | }; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /tests/test.cc: -------------------------------------------------------------------------------- 1 | #include <iostream> 2 | #include "sylar/log.h" 3 | #include "sylar/util.h" 4 | 5 | int main(int argc, char** argv) { 6 | sylar::Logger::ptr logger(new sylar::Logger); 7 | logger->addAppender(sylar::LogAppender::ptr(new sylar::StdoutLogAppender)); 8 | 9 | sylar::FileLogAppender::ptr file_appender(new sylar::FileLogAppender("./log.txt")); 10 | sylar::LogFormatter::ptr fmt(new sylar::LogFormatter("%d%T%p%T%m%n")); 11 | file_appender->setFormatter(fmt); 12 | file_appender->setLevel(sylar::LogLevel::ERROR); 13 | 14 | logger->addAppender(file_appender); 15 | 16 | //sylar::LogEvent::ptr event(new sylar::LogEvent(__FILE__, __LINE__, 0, sylar::GetThreadId(), sylar::GetFiberId(), time(0))); 17 | //event->getSS() << "hello sylar log"; 18 | //logger->log(sylar::LogLevel::DEBUG, event); 19 | std::cout << "hello sylar log" << std::endl; 20 | 21 | SYLAR_LOG_INFO(logger) << "test macro"; 22 | SYLAR_LOG_ERROR(logger) << "test macro error"; 23 | 24 | SYLAR_LOG_FMT_ERROR(logger, "test macro fmt error %s", "aa"); 25 | 26 | auto l = sylar::LoggerMgr::GetInstance()->getLogger("xx"); 27 | SYLAR_LOG_INFO(l) << "xxx"; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /tests/test_address.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/address.h" 2 | #include "sylar/log.h" 3 | 4 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | void test() { 7 | std::vector<sylar::Address::ptr> addrs; 8 | 9 | SYLAR_LOG_INFO(g_logger) << "begin"; 10 | bool v = sylar::Address::Lookup(addrs, "localhost:3080"); 11 | //bool v = sylar::Address::Lookup(addrs, "www.baidu.com", AF_INET); 12 | //bool v = sylar::Address::Lookup(addrs, "www.sylar.top", AF_INET); 13 | SYLAR_LOG_INFO(g_logger) << "end"; 14 | if(!v) { 15 | SYLAR_LOG_ERROR(g_logger) << "lookup fail"; 16 | return; 17 | } 18 | 19 | for(size_t i = 0; i < addrs.size(); ++i) { 20 | SYLAR_LOG_INFO(g_logger) << i << " - " << addrs[i]->toString(); 21 | } 22 | 23 | auto addr = sylar::Address::LookupAny("localhost:4080"); 24 | if(addr) { 25 | SYLAR_LOG_INFO(g_logger) << *addr; 26 | } else { 27 | SYLAR_LOG_ERROR(g_logger) << "error"; 28 | } 29 | } 30 | 31 | void test_iface() { 32 | std::multimap<std::string, std::pair<sylar::Address::ptr, uint32_t> > results; 33 | 34 | bool v = sylar::Address::GetInterfaceAddresses(results); 35 | if(!v) { 36 | SYLAR_LOG_ERROR(g_logger) << "GetInterfaceAddresses fail"; 37 | return; 38 | } 39 | 40 | for(auto& i: results) { 41 | SYLAR_LOG_INFO(g_logger) << i.first << " - " << i.second.first->toString() << " - " 42 | << i.second.second; 43 | } 44 | } 45 | 46 | void test_ipv4() { 47 | //auto addr = sylar::IPAddress::Create("www.sylar.top"); 48 | auto addr = sylar::IPAddress::Create("127.0.0.8"); 49 | if(addr) { 50 | SYLAR_LOG_INFO(g_logger) << addr->toString(); 51 | } 52 | } 53 | 54 | int main(int argc, char** argv) { 55 | //test_ipv4(); 56 | //test_iface(); 57 | test(); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /tests/test_application.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/application.h" 2 | 3 | int main(int argc, char** argv) { 4 | sylar::Application app; 5 | if(app.init(argc, argv)) { 6 | return app.run(); 7 | } 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /tests/test_array.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | #include "sylar/ds/array.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | struct PidVid { 7 | PidVid(uint32_t p = 0, uint32_t v = 0) 8 | :pid(p), vid(v) {} 9 | uint32_t pid; 10 | uint32_t vid; 11 | 12 | bool operator<(const PidVid& o) const { 13 | return memcmp(this, &o, sizeof(o)) < 0; 14 | } 15 | }; 16 | 17 | void gen() { 18 | sylar::ds::Array<int> tmp; 19 | std::vector<int> vs; 20 | for(int i = 0; i < 10000; ++i) { 21 | int v = rand(); 22 | tmp.insert(v); 23 | vs.push_back(v); 24 | SYLAR_ASSERT(tmp.isSorted()); 25 | } 26 | 27 | std::ofstream ofs("./array.data"); 28 | tmp.writeTo(ofs); 29 | 30 | for(auto& i : vs) { 31 | auto idx = tmp.exists(i); 32 | SYLAR_ASSERT(idx >= 0); 33 | tmp.erase(idx); 34 | SYLAR_ASSERT(tmp.isSorted()); 35 | } 36 | SYLAR_ASSERT(tmp.size() == 0); 37 | 38 | } 39 | 40 | void test() { 41 | for(int i = 0; i < 10000; ++i) { 42 | SYLAR_LOG_INFO(g_logger) << "i=" << i; 43 | std::ifstream ifs("./array.data"); 44 | sylar::ds::Array<int> tmp; 45 | if(!tmp.readFrom(ifs)) { 46 | SYLAR_LOG_INFO(g_logger) << "error"; 47 | } 48 | SYLAR_ASSERT(tmp.isSorted()); 49 | if(i % 100 == 0) { 50 | SYLAR_LOG_INFO(g_logger) << "over..." << (i + 1); 51 | } 52 | } 53 | } 54 | 55 | int main(int argc, char** argv) { 56 | gen(); 57 | test(); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /tests/test_bytearray.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/bytearray.h" 2 | #include "sylar/sylar.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | void test() { 6 | #define XX(type, len, write_fun, read_fun, base_len) {\ 7 | std::vector<type> vec; \ 8 | for(int i = 0; i < len; ++i) { \ 9 | vec.push_back(rand()); \ 10 | } \ 11 | sylar::ByteArray::ptr ba(new sylar::ByteArray(base_len)); \ 12 | for(auto& i : vec) { \ 13 | ba->write_fun(i); \ 14 | } \ 15 | ba->setPosition(0); \ 16 | for(size_t i = 0; i < vec.size(); ++i) { \ 17 | type v = ba->read_fun(); \ 18 | SYLAR_ASSERT(v == vec[i]); \ 19 | } \ 20 | SYLAR_ASSERT(ba->getReadSize() == 0); \ 21 | SYLAR_LOG_INFO(g_logger) << #write_fun "/" #read_fun \ 22 | " (" #type " ) len=" << len \ 23 | << " base_len=" << base_len \ 24 | << " size=" << ba->getSize(); \ 25 | } 26 | 27 | XX(int8_t, 100, writeFint8, readFint8, 1); 28 | XX(uint8_t, 100, writeFuint8, readFuint8, 1); 29 | XX(int16_t, 100, writeFint16, readFint16, 1); 30 | XX(uint16_t, 100, writeFuint16, readFuint16, 1); 31 | XX(int32_t, 100, writeFint32, readFint32, 1); 32 | XX(uint32_t, 100, writeFuint32, readFuint32, 1); 33 | XX(int64_t, 100, writeFint64, readFint64, 1); 34 | XX(uint64_t, 100, writeFuint64, readFuint64, 1); 35 | 36 | XX(int32_t, 100, writeInt32, readInt32, 1); 37 | XX(uint32_t, 100, writeUint32, readUint32, 1); 38 | XX(int64_t, 100, writeInt64, readInt64, 1); 39 | XX(uint64_t, 100, writeUint64, readUint64, 1); 40 | #undef XX 41 | 42 | #define XX(type, len, write_fun, read_fun, base_len) {\ 43 | std::vector<type> vec; \ 44 | for(int i = 0; i < len; ++i) { \ 45 | vec.push_back(rand()); \ 46 | } \ 47 | sylar::ByteArray::ptr ba(new sylar::ByteArray(base_len)); \ 48 | for(auto& i : vec) { \ 49 | ba->write_fun(i); \ 50 | } \ 51 | ba->setPosition(0); \ 52 | for(size_t i = 0; i < vec.size(); ++i) { \ 53 | type v = ba->read_fun(); \ 54 | SYLAR_ASSERT(v == vec[i]); \ 55 | } \ 56 | SYLAR_ASSERT(ba->getReadSize() == 0); \ 57 | SYLAR_LOG_INFO(g_logger) << #write_fun "/" #read_fun \ 58 | " (" #type " ) len=" << len \ 59 | << " base_len=" << base_len \ 60 | << " size=" << ba->getSize(); \ 61 | ba->setPosition(0); \ 62 | SYLAR_ASSERT(ba->writeToFile("/tmp/" #type "_" #len "-" #read_fun ".dat")); \ 63 | sylar::ByteArray::ptr ba2(new sylar::ByteArray(base_len * 2)); \ 64 | SYLAR_ASSERT(ba2->readFromFile("/tmp/" #type "_" #len "-" #read_fun ".dat")); \ 65 | ba2->setPosition(0); \ 66 | SYLAR_ASSERT(ba->toString() == ba2->toString()); \ 67 | SYLAR_ASSERT(ba->getPosition() == 0); \ 68 | SYLAR_ASSERT(ba2->getPosition() == 0); \ 69 | } 70 | XX(int8_t, 100, writeFint8, readFint8, 1); 71 | XX(uint8_t, 100, writeFuint8, readFuint8, 1); 72 | XX(int16_t, 100, writeFint16, readFint16, 1); 73 | XX(uint16_t, 100, writeFuint16, readFuint16, 1); 74 | XX(int32_t, 100, writeFint32, readFint32, 1); 75 | XX(uint32_t, 100, writeFuint32, readFuint32, 1); 76 | XX(int64_t, 100, writeFint64, readFint64, 1); 77 | XX(uint64_t, 100, writeFuint64, readFuint64, 1); 78 | 79 | XX(int32_t, 100, writeInt32, readInt32, 1); 80 | XX(uint32_t, 100, writeUint32, readUint32, 1); 81 | XX(int64_t, 100, writeInt64, readInt64, 1); 82 | XX(uint64_t, 100, writeUint64, readUint64, 1); 83 | 84 | #undef XX 85 | } 86 | 87 | int main(int argc, char** argv) { 88 | test(); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /tests/test_daemon.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/daemon.h" 2 | #include "sylar/iomanager.h" 3 | #include "sylar/log.h" 4 | 5 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 6 | 7 | sylar::Timer::ptr timer; 8 | int server_main(int argc, char** argv) { 9 | SYLAR_LOG_INFO(g_logger) << sylar::ProcessInfoMgr::GetInstance()->toString(); 10 | sylar::IOManager iom(1); 11 | timer = iom.addTimer(1000, [](){ 12 | SYLAR_LOG_INFO(g_logger) << "onTimer"; 13 | static int count = 0; 14 | if(++count > 10) { 15 | exit(1); 16 | } 17 | }, true); 18 | return 0; 19 | } 20 | 21 | int main(int argc, char** argv) { 22 | return sylar::start_daemon(argc, argv, server_main, argc != 1); 23 | } 24 | -------------------------------------------------------------------------------- /tests/test_dict.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | #include "sylar/ds/dict.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | struct PidVid { 7 | PidVid(uint32_t p = 0, uint32_t v = 0) 8 | :pid(p), vid(v) {} 9 | uint32_t pid; 10 | uint32_t vid; 11 | 12 | bool operator<(const PidVid& o) const { 13 | return memcmp(this, &o, sizeof(o)) < 0; 14 | } 15 | }; 16 | 17 | void gen() { 18 | sylar::ds::Dict<int, PidVid> tmp; 19 | for(int i = 0; i < 500000; ++i) { 20 | int32_t len = rand() % 10 + 5; 21 | int k = rand(); 22 | std::vector<PidVid> pvs; 23 | for(int n = 0; n < len; ++n) { 24 | pvs.push_back(PidVid(rand(), rand())); 25 | } 26 | tmp.insert(k, pvs.data(), pvs.size()); 27 | } 28 | 29 | std::ofstream ofs("./dict.data"); 30 | tmp.writeTo(ofs); 31 | } 32 | 33 | void test() { 34 | for(int i = 0; i < 10000; ++i) { 35 | SYLAR_LOG_INFO(g_logger) << "i=" << i; 36 | std::ifstream ifs("./dict.data"); 37 | sylar::ds::Dict<int, PidVid> tmp; 38 | if(!tmp.readFrom(ifs)) { 39 | SYLAR_LOG_INFO(g_logger) << "error"; 40 | } 41 | if(i % 100 == 0) { 42 | SYLAR_LOG_INFO(g_logger) << "over..." << (i + 1); 43 | } 44 | } 45 | } 46 | 47 | int main(int argc, char** argv) { 48 | gen(); 49 | test(); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /tests/test_email.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/email/email.h" 2 | #include "sylar/email/smtp.h" 3 | 4 | void test() { 5 | sylar::EMail::ptr email = sylar::EMail::Create( 6 | "user@163.com", "passwd", 7 | "hello world", "<B>hi xxx</B>hell world", {"564628276@qq.com"}); 8 | sylar::EMailEntity::ptr entity = sylar::EMailEntity::CreateAttach("sylar/sylar.h"); 9 | if(entity) { 10 | email->addEntity(entity); 11 | } 12 | 13 | entity = sylar::EMailEntity::CreateAttach("sylar/address.cc"); 14 | if(entity) { 15 | email->addEntity(entity); 16 | } 17 | 18 | auto client = sylar::SmtpClient::Create("smtp.163.com", 465, true); 19 | if(!client) { 20 | std::cout << "connect smtp.163.com:25 fail" << std::endl; 21 | return; 22 | } 23 | 24 | auto result = client->send(email, true); 25 | std::cout << "result=" << result->result << " msg=" << result->msg << std::endl; 26 | std::cout << client->getDebugInfo() << std::endl; 27 | //result = client->send(email, true); 28 | //std::cout << "result=" << result->result << " msg=" << result->msg << std::endl; 29 | //std::cout << client->getDebugInfo() << std::endl; 30 | } 31 | 32 | int main(int argc, char** argv) { 33 | sylar::IOManager iom(1); 34 | iom.schedule(test); 35 | iom.stop(); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/test_env.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/env.h" 2 | #include <unistd.h> 3 | #include <iostream> 4 | #include <fstream> 5 | 6 | struct A { 7 | A() { 8 | std::ifstream ifs("/proc/" + std::to_string(getpid()) + "/cmdline", std::ios::binary); 9 | std::string content; 10 | content.resize(4096); 11 | 12 | ifs.read(&content[0], content.size()); 13 | content.resize(ifs.gcount()); 14 | 15 | for(size_t i = 0; i < content.size(); ++i) { 16 | std::cout << i << " - " << content[i] << " - " << (int)content[i] << std::endl; 17 | } 18 | } 19 | }; 20 | 21 | A a; 22 | 23 | int main(int argc, char** argv) { 24 | std::cout << "argc=" << argc << std::endl; 25 | sylar::EnvMgr::GetInstance()->addHelp("s", "start with the terminal"); 26 | sylar::EnvMgr::GetInstance()->addHelp("d", "run as daemon"); 27 | sylar::EnvMgr::GetInstance()->addHelp("p", "print help"); 28 | if(!sylar::EnvMgr::GetInstance()->init(argc, argv)) { 29 | sylar::EnvMgr::GetInstance()->printHelp(); 30 | return 0; 31 | } 32 | 33 | std::cout << "exe=" << sylar::EnvMgr::GetInstance()->getExe() << std::endl; 34 | std::cout << "cwd=" << sylar::EnvMgr::GetInstance()->getCwd() << std::endl; 35 | 36 | std::cout << "path=" << sylar::EnvMgr::GetInstance()->getEnv("PATH", "xxx") << std::endl; 37 | std::cout << "test=" << sylar::EnvMgr::GetInstance()->getEnv("TEST", "") << std::endl; 38 | std::cout << "set env " << sylar::EnvMgr::GetInstance()->setEnv("TEST", "yy") << std::endl; 39 | std::cout << "test=" << sylar::EnvMgr::GetInstance()->getEnv("TEST", "") << std::endl; 40 | if(sylar::EnvMgr::GetInstance()->has("p")) { 41 | sylar::EnvMgr::GetInstance()->printHelp(); 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/test_fiber.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | 3 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 4 | 5 | void run_in_fiber() { 6 | SYLAR_LOG_INFO(g_logger) << "run_in_fiber begin"; 7 | sylar::Fiber::YieldToHold(); 8 | SYLAR_LOG_INFO(g_logger) << "run_in_fiber end"; 9 | sylar::Fiber::YieldToHold(); 10 | } 11 | 12 | void test_fiber() { 13 | SYLAR_LOG_INFO(g_logger) << "main begin -1"; 14 | { 15 | sylar::Fiber::GetThis(); 16 | SYLAR_LOG_INFO(g_logger) << "main begin"; 17 | sylar::Fiber::ptr fiber(new sylar::Fiber(run_in_fiber)); 18 | fiber->swapIn(); 19 | SYLAR_LOG_INFO(g_logger) << "main after swapIn"; 20 | fiber->swapIn(); 21 | SYLAR_LOG_INFO(g_logger) << "main after end"; 22 | fiber->swapIn(); 23 | } 24 | SYLAR_LOG_INFO(g_logger) << "main after end2"; 25 | } 26 | 27 | int main(int argc, char** argv) { 28 | sylar::Thread::SetName("main"); 29 | 30 | std::vector<sylar::Thread::ptr> thrs; 31 | for(int i = 0; i < 3; ++i) { 32 | thrs.push_back(sylar::Thread::ptr( 33 | new sylar::Thread(&test_fiber, "name_" + std::to_string(i)))); 34 | } 35 | for(auto i : thrs) { 36 | i->join(); 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /tests/test_hashmap.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | #include "sylar/ds/hash_map.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | struct PidVid { 7 | PidVid(uint32_t p = 0, uint32_t v = 0) 8 | :pid(p), vid(v) {} 9 | uint32_t pid; 10 | uint32_t vid; 11 | 12 | bool operator<(const PidVid& o) const { 13 | return memcmp(this, &o, sizeof(o)) < 0; 14 | } 15 | }; 16 | 17 | void gen() { 18 | sylar::ds::HashMap<int, PidVid> tmp; 19 | for(int i = 0; i < 500000; ++i) { 20 | int32_t len = rand() % 10 + 5; 21 | int k = rand(); 22 | for(int n = 0; n < len; ++n) { 23 | tmp.set(k, PidVid(rand(), rand())); 24 | } 25 | } 26 | 27 | std::ofstream ofs("./hashmap.data"); 28 | tmp.writeTo(ofs); 29 | } 30 | 31 | void test() { 32 | for(int i = 0; i < 10000; ++i) { 33 | SYLAR_LOG_INFO(g_logger) << "i=" << i; 34 | std::ifstream ifs("./hashmap.data"); 35 | sylar::ds::HashMap<int, PidVid> tmp; 36 | if(!tmp.readFrom(ifs)) { 37 | SYLAR_LOG_INFO(g_logger) << "error"; 38 | } 39 | if(i % 100 == 0) { 40 | SYLAR_LOG_INFO(g_logger) << "over..." << (i + 1); 41 | } 42 | } 43 | } 44 | 45 | int main(int argc, char** argv) { 46 | gen(); 47 | test(); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /tests/test_hashmultimap.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | #include "sylar/ds/hash_multimap.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | struct PidVid { 7 | PidVid(uint32_t p = 0, uint32_t v = 0) 8 | :pid(p), vid(v) {} 9 | uint32_t pid; 10 | uint32_t vid; 11 | 12 | bool operator<(const PidVid& o) const { 13 | return memcmp(this, &o, sizeof(o)) < 0; 14 | } 15 | }; 16 | 17 | void gen() { 18 | sylar::ds::HashMultimap<int, PidVid> tmp; 19 | for(int i = 0; i < 500000; ++i) { 20 | int32_t len = rand() % 10 + 5; 21 | int k = rand(); 22 | for(int n = 0; n < len; ++n) { 23 | tmp.insert(k, PidVid(rand(), rand())); 24 | } 25 | } 26 | 27 | std::ofstream ofs("./hashmultimap.data"); 28 | tmp.writeTo(ofs); 29 | } 30 | 31 | void test() { 32 | for(int i = 0; i < 10000; ++i) { 33 | SYLAR_LOG_INFO(g_logger) << "i=" << i; 34 | std::ifstream ifs("./hashmultimap.data"); 35 | sylar::ds::HashMultimap<int, PidVid> tmp; 36 | if(!tmp.readFrom(ifs)) { 37 | SYLAR_LOG_INFO(g_logger) << "error"; 38 | } 39 | if(i % 100 == 0) { 40 | SYLAR_LOG_INFO(g_logger) << "over..." << (i + 1); 41 | } 42 | } 43 | } 44 | 45 | int main(int argc, char** argv) { 46 | gen(); 47 | test(); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /tests/test_hook.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/hook.h" 2 | #include "sylar/log.h" 3 | #include "sylar/iomanager.h" 4 | #include <sys/types.h> 5 | #include <sys/socket.h> 6 | #include <arpa/inet.h> 7 | #include <unistd.h> 8 | #include <string.h> 9 | 10 | 11 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 12 | 13 | void test_sleep() { 14 | sylar::IOManager iom(1); 15 | iom.schedule([](){ 16 | sleep(2); 17 | SYLAR_LOG_INFO(g_logger) << "sleep 2"; 18 | }); 19 | 20 | iom.schedule([](){ 21 | sleep(3); 22 | SYLAR_LOG_INFO(g_logger) << "sleep 3"; 23 | }); 24 | SYLAR_LOG_INFO(g_logger) << "test_sleep"; 25 | } 26 | 27 | void test_sock() { 28 | int sock = socket(AF_INET, SOCK_STREAM, 0); 29 | 30 | sockaddr_in addr; 31 | memset(&addr, 0, sizeof(addr)); 32 | addr.sin_family = AF_INET; 33 | addr.sin_port = htons(80); 34 | inet_pton(AF_INET, "115.239.210.27", &addr.sin_addr.s_addr); 35 | 36 | SYLAR_LOG_INFO(g_logger) << "begin connect"; 37 | int rt = connect(sock, (const sockaddr*)&addr, sizeof(addr)); 38 | SYLAR_LOG_INFO(g_logger) << "connect rt=" << rt << " errno=" << errno; 39 | 40 | if(rt) { 41 | return; 42 | } 43 | 44 | const char data[] = "GET / HTTP/1.0\r\n\r\n"; 45 | rt = send(sock, data, sizeof(data), 0); 46 | SYLAR_LOG_INFO(g_logger) << "send rt=" << rt << " errno=" << errno; 47 | 48 | if(rt <= 0) { 49 | return; 50 | } 51 | 52 | std::string buff; 53 | buff.resize(4096); 54 | 55 | rt = recv(sock, &buff[0], buff.size(), 0); 56 | SYLAR_LOG_INFO(g_logger) << "recv rt=" << rt << " errno=" << errno; 57 | 58 | if(rt <= 0) { 59 | return; 60 | } 61 | 62 | buff.resize(rt); 63 | SYLAR_LOG_INFO(g_logger) << buff; 64 | } 65 | 66 | int main(int argc, char** argv) { 67 | //test_sleep(); 68 | sylar::IOManager iom; 69 | iom.schedule(test_sock); 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /tests/test_http.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/http/http.h" 2 | #include "sylar/log.h" 3 | 4 | void test_request() { 5 | sylar::http::HttpRequest::ptr req(new sylar::http::HttpRequest); 6 | req->setHeader("host" , "www.sylar.top"); 7 | req->setBody("hello sylar"); 8 | req->dump(std::cout) << std::endl; 9 | } 10 | 11 | void test_response() { 12 | sylar::http::HttpResponse::ptr rsp(new sylar::http::HttpResponse); 13 | rsp->setHeader("X-X", "sylar"); 14 | rsp->setBody("hello sylar"); 15 | rsp->setStatus((sylar::http::HttpStatus)400); 16 | rsp->setClose(false); 17 | 18 | rsp->dump(std::cout) << std::endl; 19 | } 20 | 21 | int main(int argc, char** argv) { 22 | test_request(); 23 | test_response(); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /tests/test_http_parser.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/http/http_parser.h" 2 | #include "sylar/log.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | const char test_request_data[] = "POST / HTTP/1.1\r\n" 7 | "Host: www.sylar.top\r\n" 8 | "Content-Length: 10\r\n\r\n" 9 | "1234567890"; 10 | 11 | void test_request() { 12 | sylar::http::HttpRequestParser parser; 13 | std::string tmp = test_request_data; 14 | size_t s = parser.execute(&tmp[0], tmp.size()); 15 | SYLAR_LOG_ERROR(g_logger) << "execute rt=" << s 16 | << "has_error=" << parser.hasError() 17 | << " is_finished=" << parser.isFinished() 18 | << " total=" << tmp.size() 19 | << " content_length=" << parser.getContentLength(); 20 | tmp.resize(tmp.size() - s); 21 | SYLAR_LOG_INFO(g_logger) << parser.getData()->toString(); 22 | SYLAR_LOG_INFO(g_logger) << tmp; 23 | } 24 | 25 | const char test_response_data[] = "HTTP/1.1 200 OK\r\n" 26 | "Date: Tue, 04 Jun 2019 15:43:56 GMT\r\n" 27 | "Server: Apache\r\n" 28 | "Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT\r\n" 29 | "ETag: \"51-47cf7e6ee8400\"\r\n" 30 | "Accept-Ranges: bytes\r\n" 31 | "Content-Length: 81\r\n" 32 | "Cache-Control: max-age=86400\r\n" 33 | "Expires: Wed, 05 Jun 2019 15:43:56 GMT\r\n" 34 | "Connection: Close\r\n" 35 | "Content-Type: text/html\r\n\r\n" 36 | "<html>\r\n" 37 | "<meta http-equiv=\"refresh\" content=\"0;url=http://www.baidu.com/\">\r\n" 38 | "</html>\r\n"; 39 | 40 | void test_response() { 41 | sylar::http::HttpResponseParser parser; 42 | std::string tmp = test_response_data; 43 | size_t s = parser.execute(&tmp[0], tmp.size(), true); 44 | SYLAR_LOG_ERROR(g_logger) << "execute rt=" << s 45 | << " has_error=" << parser.hasError() 46 | << " is_finished=" << parser.isFinished() 47 | << " total=" << tmp.size() 48 | << " content_length=" << parser.getContentLength() 49 | << " tmp[s]=" << tmp[s]; 50 | 51 | tmp.resize(tmp.size() - s); 52 | 53 | SYLAR_LOG_INFO(g_logger) << parser.getData()->toString(); 54 | SYLAR_LOG_INFO(g_logger) << tmp; 55 | } 56 | 57 | int main(int argc, char** argv) { 58 | test_request(); 59 | SYLAR_LOG_INFO(g_logger) << "--------------"; 60 | test_response(); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /tests/test_http_server.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/http/http_server.h" 2 | #include "sylar/log.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | #define XX(...) #__VA_ARGS__ 7 | 8 | 9 | sylar::IOManager::ptr worker; 10 | void run() { 11 | g_logger->setLevel(sylar::LogLevel::INFO); 12 | //sylar::http::HttpServer::ptr server(new sylar::http::HttpServer(true, worker.get(), sylar::IOManager::GetThis())); 13 | sylar::http::HttpServer::ptr server(new sylar::http::HttpServer(true)); 14 | sylar::Address::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8020"); 15 | while(!server->bind(addr)) { 16 | sleep(2); 17 | } 18 | auto sd = server->getServletDispatch(); 19 | sd->addServlet("/sylar/xx", [](sylar::http::HttpRequest::ptr req 20 | ,sylar::http::HttpResponse::ptr rsp 21 | ,sylar::http::HttpSession::ptr session) { 22 | rsp->setBody(req->toString()); 23 | return 0; 24 | }); 25 | 26 | sd->addGlobServlet("/sylar/*", [](sylar::http::HttpRequest::ptr req 27 | ,sylar::http::HttpResponse::ptr rsp 28 | ,sylar::http::HttpSession::ptr session) { 29 | rsp->setBody("Glob:\r\n" + req->toString()); 30 | return 0; 31 | }); 32 | 33 | sd->addGlobServlet("/sylarx/*", [](sylar::http::HttpRequest::ptr req 34 | ,sylar::http::HttpResponse::ptr rsp 35 | ,sylar::http::HttpSession::ptr session) { 36 | rsp->setBody(XX(<html> 37 | <head><title>404 Not Found</title></head> 38 | <body> 39 | <center><h1>404 Not Found</h1></center> 40 | <hr><center>nginx/1.16.0</center> 41 | </body> 42 | </html> 43 | <!-- a padding to disable MSIE and Chrome friendly error page --> 44 | <!-- a padding to disable MSIE and Chrome friendly error page --> 45 | <!-- a padding to disable MSIE and Chrome friendly error page --> 46 | <!-- a padding to disable MSIE and Chrome friendly error page --> 47 | <!-- a padding to disable MSIE and Chrome friendly error page --> 48 | <!-- a padding to disable MSIE and Chrome friendly error page --> 49 | )); 50 | return 0; 51 | }); 52 | 53 | server->start(); 54 | } 55 | 56 | int main(int argc, char** argv) { 57 | sylar::IOManager iom(1, true, "main"); 58 | worker.reset(new sylar::IOManager(3, false, "worker")); 59 | iom.schedule(run); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /tests/test_iomanager.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | #include "sylar/iomanager.h" 3 | #include <sys/types.h> 4 | #include <sys/socket.h> 5 | #include <arpa/inet.h> 6 | #include <unistd.h> 7 | #include <fcntl.h> 8 | #include <iostream> 9 | #include <sys/epoll.h> 10 | 11 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 12 | 13 | int sock = 0; 14 | 15 | void test_fiber() { 16 | SYLAR_LOG_INFO(g_logger) << "test_fiber sock=" << sock; 17 | 18 | //sleep(3); 19 | 20 | //close(sock); 21 | //sylar::IOManager::GetThis()->cancelAll(sock); 22 | 23 | sock = socket(AF_INET, SOCK_STREAM, 0); 24 | fcntl(sock, F_SETFL, O_NONBLOCK); 25 | 26 | sockaddr_in addr; 27 | memset(&addr, 0, sizeof(addr)); 28 | addr.sin_family = AF_INET; 29 | addr.sin_port = htons(80); 30 | inet_pton(AF_INET, "115.239.210.27", &addr.sin_addr.s_addr); 31 | 32 | if(!connect(sock, (const sockaddr*)&addr, sizeof(addr))) { 33 | } else if(errno == EINPROGRESS) { 34 | SYLAR_LOG_INFO(g_logger) << "add event errno=" << errno << " " << strerror(errno); 35 | sylar::IOManager::GetThis()->addEvent(sock, sylar::IOManager::READ, [](){ 36 | SYLAR_LOG_INFO(g_logger) << "read callback"; 37 | }); 38 | sylar::IOManager::GetThis()->addEvent(sock, sylar::IOManager::WRITE, [](){ 39 | SYLAR_LOG_INFO(g_logger) << "write callback"; 40 | //close(sock); 41 | sylar::IOManager::GetThis()->cancelEvent(sock, sylar::IOManager::READ); 42 | close(sock); 43 | }); 44 | } else { 45 | SYLAR_LOG_INFO(g_logger) << "else " << errno << " " << strerror(errno); 46 | } 47 | 48 | } 49 | 50 | void test1() { 51 | std::cout << "EPOLLIN=" << EPOLLIN 52 | << " EPOLLOUT=" << EPOLLOUT << std::endl; 53 | sylar::IOManager iom(2, false); 54 | iom.schedule(&test_fiber); 55 | } 56 | 57 | sylar::Timer::ptr s_timer; 58 | void test_timer() { 59 | sylar::IOManager iom(2); 60 | s_timer = iom.addTimer(1000, [](){ 61 | static int i = 0; 62 | SYLAR_LOG_INFO(g_logger) << "hello timer i=" << i; 63 | if(++i == 3) { 64 | s_timer->reset(2000, true); 65 | //s_timer->cancel(); 66 | } 67 | }, true); 68 | } 69 | 70 | int main(int argc, char** argv) { 71 | //test1(); 72 | test_timer(); 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /tests/test_lru.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/ds/lru_cache.h" 2 | 3 | void test_lru() { 4 | sylar::ds::LruCache<int, int> cache(30, 10); 5 | 6 | for(int i = 0; i < 105; ++i) { 7 | cache.set(i, i * 100); 8 | } 9 | 10 | for(int i = 0; i < 105; ++i) { 11 | int v; 12 | if(cache.get(i, v)) { 13 | std::cout << "get: " << i << " - " << v << std::endl; 14 | } 15 | } 16 | 17 | std::cout << cache.toStatusString() << std::endl; 18 | } 19 | 20 | void test_hash_lru() { 21 | sylar::ds::HashLruCache<int, int> cache(2, 30, 10); 22 | 23 | for(int i = 0; i < 105; ++i) { 24 | cache.set(i, i * 100); 25 | } 26 | 27 | for(int i = 0; i < 105; ++i) { 28 | int v; 29 | if(cache.get(i, v)) { 30 | std::cout << "get: " << i << " - " << v << std::endl; 31 | } 32 | } 33 | 34 | std::cout << cache.toStatusString() << std::endl; 35 | } 36 | 37 | int main(int argc, char** argv) { 38 | test_lru(); 39 | test_hash_lru(); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /tests/test_module.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/module.h" 2 | #include "sylar/singleton.h" 3 | #include <iostream> 4 | #include "sylar/log.h" 5 | #include "sylar/db/redis.h" 6 | 7 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 8 | 9 | class A { 10 | public: 11 | A() { 12 | std::cout << "A::A " << this << std::endl; 13 | } 14 | 15 | ~A() { 16 | std::cout << "A::~A " << this << std::endl; 17 | } 18 | 19 | }; 20 | 21 | class MyModule : public sylar::RockModule { 22 | public: 23 | MyModule() 24 | :RockModule("hello", "1.0", "") { 25 | //sylar::Singleton<A>::GetInstance(); 26 | } 27 | 28 | bool onLoad() override { 29 | sylar::Singleton<A>::GetInstance(); 30 | std::cout << "-----------onLoad------------" << std::endl; 31 | return true; 32 | } 33 | 34 | bool onUnload() override { 35 | sylar::Singleton<A>::GetInstance(); 36 | std::cout << "-----------onUnload------------" << std::endl; 37 | return true; 38 | } 39 | 40 | bool onServerReady() { 41 | registerService("rock", "sylar.top", "blog"); 42 | auto rpy = sylar::RedisUtil::Cmd("local", "get abc"); 43 | if(!rpy) { 44 | SYLAR_LOG_ERROR(g_logger) << "redis cmd get abc error"; 45 | } else { 46 | SYLAR_LOG_ERROR(g_logger) << "redis get abc: " 47 | << (rpy->str ? rpy->str : "(null)"); 48 | } 49 | return true; 50 | } 51 | 52 | bool handleRockRequest(sylar::RockRequest::ptr request 53 | ,sylar::RockResponse::ptr response 54 | ,sylar::RockStream::ptr stream) { 55 | //SYLAR_LOG_INFO(g_logger) << "handleRockRequest " << request->toString(); 56 | //sleep(1); 57 | response->setResult(0); 58 | response->setResultStr("ok"); 59 | response->setBody("echo: " + request->getBody()); 60 | 61 | usleep(100 * 1000); 62 | auto addr = stream->getLocalAddressString(); 63 | if(addr.find("8061") != std::string::npos) { 64 | if(rand() % 100 < 50) { 65 | usleep(10 * 1000); 66 | } else if(rand() % 100 < 10) { 67 | response->setResult(-1000); 68 | } 69 | } else { 70 | //if(rand() % 100 < 25) { 71 | // usleep(10 * 1000); 72 | //} else if(rand() % 100 < 10) { 73 | // response->setResult(-1000); 74 | //} 75 | } 76 | return true; 77 | //return rand() % 100 < 90; 78 | } 79 | 80 | bool handleRockNotify(sylar::RockNotify::ptr notify 81 | ,sylar::RockStream::ptr stream) { 82 | SYLAR_LOG_INFO(g_logger) << "handleRockNotify " << notify->toString(); 83 | return true; 84 | } 85 | 86 | }; 87 | 88 | extern "C" { 89 | 90 | sylar::Module* CreateModule() { 91 | sylar::Singleton<A>::GetInstance(); 92 | std::cout << "=============CreateModule=================" << std::endl; 93 | return new MyModule; 94 | } 95 | 96 | void DestoryModule(sylar::Module* ptr) { 97 | std::cout << "=============DestoryModule=================" << std::endl; 98 | delete ptr; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /tests/test_mysql.cc: -------------------------------------------------------------------------------- 1 | #include <iostream> 2 | #include "sylar/db/mysql.h" 3 | #include "sylar/iomanager.h" 4 | 5 | void run() { 6 | do { 7 | std::map<std::string, std::string> params; 8 | params["host"] = "127.0.0.1"; 9 | params["user"] = "sylar"; 10 | params["passwd"] = "blog123"; 11 | params["dbname"] = "blog"; 12 | 13 | sylar::MySQL::ptr mysql(new sylar::MySQL(params)); 14 | if(!mysql->connect()) { 15 | std::cout << "connect fail" << std::endl; 16 | return; 17 | } 18 | 19 | //auto stmt = mysql_stmt_init(mysql->getRaw()); 20 | //std::string sql = "select * from sylar where status >= ?"; 21 | //mysql_stmt_prepare(stmt, sql.c_str(), sql.size()); 22 | //MYSQL_BIND b; 23 | //int a = 0; 24 | //b.buffer_type = MYSQL_TYPE_LONG; 25 | //b.buffer = &a; 26 | //mysql_stmt_bind_param(m_ 27 | 28 | sylar::MySQLStmt::ptr stmt = sylar::MySQLStmt::Create(mysql, "update user set update_time = ? where id = 1"); 29 | stmt->bindString(1, "2018-01-01 10:10:10"); 30 | int rt = stmt->execute(); 31 | std::cout << "rt=" << rt << std::endl; 32 | 33 | //MYSQL_TIME mt; 34 | //sylar::time_t_to_mysql_time(time(0), mt); 35 | 36 | //int a = 0; 37 | ////auto stmt = mysql->prepare("select * from sylar where status >= ?"); 38 | ////stmt->bind(0, a); 39 | ////auto res = std::dynamic_pointer_cast<sylar::MySQLStmtRes>(stmt->query()); 40 | 41 | //auto res = std::dynamic_pointer_cast<sylar::MySQLStmtRes> 42 | // //(mysql->queryStmt("select * from sylar")); 43 | // (mysql->queryStmt("select *, 'hello' as xx from user where status >= ? and status <= ?" 44 | // , a, a)); 45 | // //(mysql->queryStmt("select id,name, keyword, creator as aa, last_update_time from sylar " 46 | // // " where last_update_time > ?", (time_t)0)); 47 | ////auto res = std::dynamic_pointer_cast<sylar::MySQLRes> 48 | //// (mysql->query("select * from search_brand")); 49 | //if(!res) { 50 | // std::cout << "invalid" << std::endl; 51 | // return; 52 | //} 53 | //if(res->getErrno()) { 54 | // std::cout << "errno=" << res->getErrno() 55 | // << " errstr=" << res->getErrStr() << std::endl; 56 | // return; 57 | //} 58 | 59 | //int i = 0; 60 | //while(res->next()) { 61 | // ++i; 62 | // std::cout << res->getInt64(0) 63 | // << " - " << res->getInt64(1) << std::endl; 64 | //} 65 | //std::cout << "===" << i << std::endl; 66 | } while(false); 67 | std::cout << "over" << std::endl; 68 | } 69 | 70 | int main(int argc, char** argv) { 71 | sylar::IOManager iom(1); 72 | //iom.schedule(run); 73 | iom.addTimer(1000, run, true); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /tests/test_orm.cc: -------------------------------------------------------------------------------- 1 | #include "orm_out/test/orm/user_info.h" 2 | #include "sylar/db/sqlite3.h" 3 | #include "sylar/db/mysql.h" 4 | 5 | int main(int argc, char** argv) { 6 | sylar::IDB::ptr db; 7 | if(argc == 1) { 8 | db = sylar::SQLite3::Create("abc.db"); 9 | std::cout << "create table: " << test::orm::UserInfoDao::CreateTableSQLite3(db) << std::endl; 10 | } else { 11 | std::map<std::string, std::string> params; 12 | params["host"] = "127.0.0.1"; 13 | params["user"] = "sylar"; 14 | params["passwd"] = "123456"; 15 | params["dbname"] = "sylar"; 16 | 17 | sylar::MySQL::ptr m(new sylar::MySQL(params)); 18 | m->connect(); 19 | db = m; 20 | std::cout << "create table: " << test::orm::UserInfoDao::CreateTableMySQL(db) << std::endl; 21 | } 22 | for(int i = 0; i < 10; ++i) { 23 | test::orm::UserInfo::ptr u(new test::orm::UserInfo); 24 | u->setName("name_a" + std::to_string(i)); 25 | u->setEmail("mail_a" + std::to_string(i)); 26 | u->setPhone("phone_a" + std::to_string(i)); 27 | u->setStatus(i % 2); 28 | 29 | std::cout << "i= " << i << " - " << test::orm::UserInfoDao::Insert(u, db); 30 | std::cout << " - " << u->toJsonString() 31 | << std::endl; 32 | } 33 | 34 | std::vector<test::orm::UserInfo::ptr> us; 35 | std::cout << "query_by_status: " << test::orm::UserInfoDao::QueryByStatus(us, 1, db) << std::endl; 36 | for(size_t i = 0; i < us.size(); ++i) { 37 | std::cout << "i=" << i << " - " << us[i]->toJsonString() << std::endl; 38 | us[i]->setName(us[i]->getName() + "_new"); 39 | test::orm::UserInfoDao::Update(us[i], db); 40 | } 41 | 42 | std::cout << "delete: " << test::orm::UserInfoDao::DeleteByStatus(1, db) << std::endl; 43 | us.clear(); 44 | std::cout << "query_by_status: " << test::orm::UserInfoDao::QueryByStatus(us, 0, db) << std::endl; 45 | for(size_t i = 0; i < us.size(); ++i) { 46 | std::cout << "i=" << i << " - " << us[i]->toJsonString() << std::endl; 47 | } 48 | 49 | us.clear(); 50 | std::cout << "query_all: " << test::orm::UserInfoDao::QueryAll(us, db) << std::endl; 51 | for(size_t i = 0; i < us.size(); ++i) { 52 | std::cout << "i=" << i << " - " << us[i]->toJsonString() << std::endl; 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /tests/test_rock.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | #include "sylar/rock/rock_stream.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | sylar::RockConnection::ptr conn(new sylar::RockConnection); 7 | void run() { 8 | conn->setAutoConnect(true); 9 | sylar::Address::ptr addr = sylar::Address::LookupAny("127.0.0.1:8061"); 10 | if(!conn->connect(addr)) { 11 | SYLAR_LOG_INFO(g_logger) << "connect " << *addr << " false"; 12 | } 13 | conn->start(); 14 | 15 | sylar::IOManager::GetThis()->addTimer(1000, [](){ 16 | sylar::RockRequest::ptr req(new sylar::RockRequest); 17 | static uint32_t s_sn = 0; 18 | req->setSn(++s_sn); 19 | req->setCmd(100); 20 | req->setBody("hello world sn=" + std::to_string(s_sn)); 21 | 22 | auto rsp = conn->request(req, 300); 23 | if(rsp->response) { 24 | SYLAR_LOG_INFO(g_logger) << rsp->response->toString(); 25 | } else { 26 | SYLAR_LOG_INFO(g_logger) << "error result=" << rsp->result; 27 | } 28 | }, true); 29 | } 30 | 31 | int main(int argc, char** argv) { 32 | sylar::IOManager iom(1); 33 | iom.schedule(run); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tests/test_scheduler.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | 3 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 4 | 5 | void test_fiber() { 6 | static int s_count = 5; 7 | SYLAR_LOG_INFO(g_logger) << "test in fiber s_count=" << s_count; 8 | 9 | sleep(1); 10 | if(--s_count >= 0) { 11 | sylar::Scheduler::GetThis()->schedule(&test_fiber, sylar::GetThreadId()); 12 | } 13 | } 14 | 15 | int main(int argc, char** argv) { 16 | SYLAR_LOG_INFO(g_logger) << "main"; 17 | sylar::Scheduler sc(3, false, "test"); 18 | sc.start(); 19 | sleep(2); 20 | SYLAR_LOG_INFO(g_logger) << "schedule"; 21 | sc.schedule(&test_fiber); 22 | sc.stop(); 23 | SYLAR_LOG_INFO(g_logger) << "over"; 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /tests/test_service_discovery.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/streams/service_discovery.h" 2 | #include "sylar/iomanager.h" 3 | #include "sylar/rock/rock_stream.h" 4 | #include "sylar/log.h" 5 | #include "sylar/worker.h" 6 | 7 | sylar::ZKServiceDiscovery::ptr zksd(new sylar::ZKServiceDiscovery("127.0.0.1:21812")); 8 | sylar::RockSDLoadBalance::ptr rsdlb(new sylar::RockSDLoadBalance(zksd)); 9 | 10 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 11 | 12 | std::atomic<uint32_t> s_id; 13 | void on_timer() { 14 | g_logger->setLevel(sylar::LogLevel::INFO); 15 | //SYLAR_LOG_INFO(g_logger) << "on_timer"; 16 | sylar::RockRequest::ptr req(new sylar::RockRequest); 17 | req->setSn(++s_id); 18 | req->setCmd(100); 19 | req->setBody("hello"); 20 | 21 | auto rt = rsdlb->request("sylar.top", "blog", req, 1000); 22 | if(!rt->response) { 23 | if(req->getSn() % 50 == 0) { 24 | SYLAR_LOG_ERROR(g_logger) << "invalid response: " << rt->toString(); 25 | } 26 | } else { 27 | if(req->getSn() % 1000 == 0) { 28 | SYLAR_LOG_INFO(g_logger) << rt->toString(); 29 | } 30 | } 31 | } 32 | 33 | void run() { 34 | zksd->setSelfInfo("127.0.0.1:2222"); 35 | zksd->setSelfData("aaaa"); 36 | 37 | std::unordered_map<std::string, std::unordered_map<std::string,std::string> > confs; 38 | confs["sylar.top"]["blog"] = "fair"; 39 | rsdlb->start(confs); 40 | //SYLAR_LOG_INFO(g_logger) << "on_timer---"; 41 | 42 | sylar::IOManager::GetThis()->addTimer(1, on_timer, true); 43 | } 44 | 45 | int main(int argc, char** argv) { 46 | sylar::WorkerMgr::GetInstance()->init({ 47 | {"service_io", { 48 | {"thread_num", "1"} 49 | }} 50 | }); 51 | sylar::IOManager iom(1); 52 | iom.addTimer(1000, [](){ 53 | std::cout << rsdlb->statusString() << std::endl; 54 | }, true); 55 | iom.schedule(run); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /tests/test_socket.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/socket.h" 2 | #include "sylar/sylar.h" 3 | #include "sylar/iomanager.h" 4 | 5 | static sylar::Logger::ptr g_looger = SYLAR_LOG_ROOT(); 6 | 7 | void test_socket() { 8 | //std::vector<sylar::Address::ptr> addrs; 9 | //sylar::Address::Lookup(addrs, "www.baidu.com", AF_INET); 10 | //sylar::IPAddress::ptr addr; 11 | //for(auto& i : addrs) { 12 | // SYLAR_LOG_INFO(g_looger) << i->toString(); 13 | // addr = std::dynamic_pointer_cast<sylar::IPAddress>(i); 14 | // if(addr) { 15 | // break; 16 | // } 17 | //} 18 | sylar::IPAddress::ptr addr = sylar::Address::LookupAnyIPAddress("www.baidu.com"); 19 | if(addr) { 20 | SYLAR_LOG_INFO(g_looger) << "get address: " << addr->toString(); 21 | } else { 22 | SYLAR_LOG_ERROR(g_looger) << "get address fail"; 23 | return; 24 | } 25 | 26 | sylar::Socket::ptr sock = sylar::Socket::CreateTCP(addr); 27 | addr->setPort(80); 28 | SYLAR_LOG_INFO(g_looger) << "addr=" << addr->toString(); 29 | if(!sock->connect(addr)) { 30 | SYLAR_LOG_ERROR(g_looger) << "connect " << addr->toString() << " fail"; 31 | return; 32 | } else { 33 | SYLAR_LOG_INFO(g_looger) << "connect " << addr->toString() << " connected"; 34 | } 35 | 36 | const char buff[] = "GET / HTTP/1.0\r\n\r\n"; 37 | int rt = sock->send(buff, sizeof(buff)); 38 | if(rt <= 0) { 39 | SYLAR_LOG_INFO(g_looger) << "send fail rt=" << rt; 40 | return; 41 | } 42 | 43 | std::string buffs; 44 | buffs.resize(4096); 45 | rt = sock->recv(&buffs[0], buffs.size()); 46 | 47 | if(rt <= 0) { 48 | SYLAR_LOG_INFO(g_looger) << "recv fail rt=" << rt; 49 | return; 50 | } 51 | 52 | buffs.resize(rt); 53 | SYLAR_LOG_INFO(g_looger) << buffs; 54 | } 55 | 56 | void test2() { 57 | sylar::IPAddress::ptr addr = sylar::Address::LookupAnyIPAddress("www.baidu.com:80"); 58 | if(addr) { 59 | SYLAR_LOG_INFO(g_looger) << "get address: " << addr->toString(); 60 | } else { 61 | SYLAR_LOG_ERROR(g_looger) << "get address fail"; 62 | return; 63 | } 64 | 65 | sylar::Socket::ptr sock = sylar::Socket::CreateTCP(addr); 66 | if(!sock->connect(addr)) { 67 | SYLAR_LOG_ERROR(g_looger) << "connect " << addr->toString() << " fail"; 68 | return; 69 | } else { 70 | SYLAR_LOG_INFO(g_looger) << "connect " << addr->toString() << " connected"; 71 | } 72 | 73 | uint64_t ts = sylar::GetCurrentUS(); 74 | for(size_t i = 0; i < 10000000000ul; ++i) { 75 | if(int err = sock->getError()) { 76 | SYLAR_LOG_INFO(g_looger) << "err=" << err << " errstr=" << strerror(err); 77 | break; 78 | } 79 | 80 | //struct tcp_info tcp_info; 81 | //if(!sock->getOption(IPPROTO_TCP, TCP_INFO, tcp_info)) { 82 | // SYLAR_LOG_INFO(g_looger) << "err"; 83 | // break; 84 | //} 85 | //if(tcp_info.tcpi_state != TCP_ESTABLISHED) { 86 | // SYLAR_LOG_INFO(g_looger) 87 | // << " state=" << (int)tcp_info.tcpi_state; 88 | // break; 89 | //} 90 | static int batch = 10000000; 91 | if(i && (i % batch) == 0) { 92 | uint64_t ts2 = sylar::GetCurrentUS(); 93 | SYLAR_LOG_INFO(g_looger) << "i=" << i << " used: " << ((ts2 - ts) * 1.0 / batch) << " us"; 94 | ts = ts2; 95 | } 96 | } 97 | } 98 | 99 | int main(int argc, char** argv) { 100 | sylar::IOManager iom; 101 | //iom.schedule(&test_socket); 102 | iom.schedule(&test2); 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /tests/test_tcp_server.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/tcp_server.h" 2 | #include "sylar/iomanager.h" 3 | #include "sylar/log.h" 4 | 5 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 6 | 7 | void run() { 8 | auto addr = sylar::Address::LookupAny("0.0.0.0:8033"); 9 | //auto addr2 = sylar::UnixAddress::ptr(new sylar::UnixAddress("/tmp/unix_addr")); 10 | std::vector<sylar::Address::ptr> addrs; 11 | addrs.push_back(addr); 12 | //addrs.push_back(addr2); 13 | 14 | sylar::TcpServer::ptr tcp_server(new sylar::TcpServer); 15 | std::vector<sylar::Address::ptr> fails; 16 | while(!tcp_server->bind(addrs, fails)) { 17 | sleep(2); 18 | } 19 | tcp_server->start(); 20 | 21 | } 22 | int main(int argc, char** argv) { 23 | sylar::IOManager iom(2); 24 | iom.schedule(run); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /tests/test_thread.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | #include <unistd.h> 3 | 4 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | int count = 0; 7 | //sylar::RWMutex s_mutex; 8 | sylar::Mutex s_mutex; 9 | 10 | void fun1() { 11 | SYLAR_LOG_INFO(g_logger) << "name: " << sylar::Thread::GetName() 12 | << " this.name: " << sylar::Thread::GetThis()->getName() 13 | << " id: " << sylar::GetThreadId() 14 | << " this.id: " << sylar::Thread::GetThis()->getId(); 15 | 16 | for(int i = 0; i < 100000; ++i) { 17 | //sylar::RWMutex::WriteLock lock(s_mutex); 18 | sylar::Mutex::Lock lock(s_mutex); 19 | ++count; 20 | } 21 | } 22 | 23 | void fun2() { 24 | while(true) { 25 | SYLAR_LOG_INFO(g_logger) << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 26 | } 27 | } 28 | 29 | void fun3() { 30 | while(true) { 31 | SYLAR_LOG_INFO(g_logger) << "========================================"; 32 | } 33 | } 34 | 35 | int main(int argc, char** argv) { 36 | SYLAR_LOG_INFO(g_logger) << "thread test begin"; 37 | YAML::Node root = YAML::LoadFile("/home/sylar/test/sylar/bin/conf/log2.yml"); 38 | sylar::Config::LoadFromYaml(root); 39 | 40 | std::vector<sylar::Thread::ptr> thrs; 41 | for(int i = 0; i < 1; ++i) { 42 | sylar::Thread::ptr thr(new sylar::Thread(&fun2, "name_" + std::to_string(i * 2))); 43 | //sylar::Thread::ptr thr2(new sylar::Thread(&fun3, "name_" + std::to_string(i * 2 + 1))); 44 | thrs.push_back(thr); 45 | //thrs.push_back(thr2); 46 | } 47 | 48 | for(size_t i = 0; i < thrs.size(); ++i) { 49 | thrs[i]->join(); 50 | } 51 | SYLAR_LOG_INFO(g_logger) << "thread test end"; 52 | SYLAR_LOG_INFO(g_logger) << "count=" << count; 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /tests/test_timed_cache.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/ds/timed_cache.h" 2 | 3 | void test_timed_cache() { 4 | sylar::ds::TimedCache<int, int> cache(30, 10); 5 | for(int i = 0; i < 105; ++i) { 6 | cache.set(i, i * 100, 1000); 7 | } 8 | 9 | for(int i = 0; i < 105; ++i) { 10 | int v; 11 | if(cache.get(i, v)) { 12 | std::cout << "get: " << i << " - " 13 | << v 14 | << " - " << cache.get(i) 15 | << std::endl; 16 | } 17 | } 18 | 19 | cache.set(1000, 11, 1000 * 10); 20 | //std::cout << "expired: " << cache.expired(100, 1000 * 10) << std::endl; 21 | std::cout << cache.toStatusString() << std::endl; 22 | sleep(2); 23 | std::cout << "check_timeout: " << cache.checkTimeout() << std::endl; 24 | std::cout << cache.toStatusString() << std::endl; 25 | } 26 | 27 | void test_hash_timed_cache() { 28 | sylar::ds::HashTimedCache<int, int> cache(2, 30, 10); 29 | 30 | for(int i = 0; i < 105; ++i) { 31 | cache.set(i, i * 100, -1000 * i); 32 | } 33 | 34 | for(int i = 0; i < 105; ++i) { 35 | int v; 36 | if(cache.get(i, v)) { 37 | std::cout << "get: " << i << " - " << v << std::endl; 38 | } 39 | } 40 | 41 | cache.expired(100, 1000 * 10); 42 | 43 | cache.set(1000, 11, 1000 * 10); 44 | std::cout << "expired: " << cache.expired(100, 1000 * 10) << std::endl; 45 | std::cout << cache.toStatusString() << std::endl; 46 | sleep(2); 47 | std::cout << "check_timeout: " << cache.checkTimeout() << std::endl; 48 | std::cout << cache.toStatusString() << std::endl; 49 | } 50 | 51 | int main(int argc, char** argv) { 52 | test_timed_cache(); 53 | test_hash_timed_cache(); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /tests/test_timed_lru_cache.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/ds/timed_lru_cache.h" 2 | 3 | void test_timed_lru_cache() { 4 | sylar::ds::TimedLruCache<int, int> cache(30, 10); 5 | for(int i = 0; i < 105; ++i) { 6 | cache.set(i, i * 100, 1000); 7 | } 8 | 9 | for(int i = 0; i < 105; ++i) { 10 | int v; 11 | if(cache.get(i, v)) { 12 | std::cout << "get: " << i << " - " 13 | << v 14 | << " - " << cache.get(i) 15 | << std::endl; 16 | } 17 | } 18 | 19 | cache.set(1000, 11, 1000 * 10); 20 | //std::cout << "expired: " << cache.expired(100, 1000 * 10) << std::endl; 21 | std::cout << cache.toStatusString() << std::endl; 22 | sleep(2); 23 | std::cout << "check_timeout: " << cache.checkTimeout() << std::endl; 24 | std::cout << cache.toStatusString() << std::endl; 25 | } 26 | 27 | void test_hash_timed_lru_cache() { 28 | sylar::ds::HashTimedLruCache<int, int> cache(2, 30, 10); 29 | for(int i = 0; i < 105; ++i) { 30 | cache.set(i, i * 100, 1000); 31 | } 32 | 33 | for(int i = 0; i < 105; ++i) { 34 | int v; 35 | if(cache.get(i, v)) { 36 | std::cout << "get: " << i << " - " 37 | << v 38 | << " - " << cache.get(i) 39 | << std::endl; 40 | } 41 | } 42 | 43 | cache.set(1000, 11, 1000 * 10); 44 | //std::cout << "expired: " << cache.expired(100, 1000 * 10) << std::endl; 45 | std::cout << cache.toStatusString() << std::endl; 46 | sleep(2); 47 | std::cout << "check_timeout: " << cache.checkTimeout() << std::endl; 48 | std::cout << cache.toStatusString() << std::endl; 49 | } 50 | 51 | int main(int argc, char** argv) { 52 | test_timed_lru_cache(); 53 | test_hash_timed_lru_cache(); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /tests/test_uri.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/uri.h" 2 | #include <iostream> 3 | 4 | int main(int argc, char** argv) { 5 | //sylar::Uri::ptr uri = sylar::Uri::Create("http://www.sylar.top/test/uri?id=100&name=sylar#frg"); 6 | //sylar::Uri::ptr uri = sylar::Uri::Create("http://admin@www.sylar.top/test/中文/uri?id=100&name=sylar&vv=中文#frg中文"); 7 | sylar::Uri::ptr uri = sylar::Uri::Create("http://admin@www.sylar.top"); 8 | //sylar::Uri::ptr uri = sylar::Uri::Create("http://www.sylar.top/test/uri"); 9 | std::cout << uri->toString() << std::endl; 10 | auto addr = uri->createAddress(); 11 | std::cout << *addr << std::endl; 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /tests/test_util.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/sylar.h" 2 | #include <assert.h> 3 | 4 | sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | void test_assert() { 7 | SYLAR_LOG_INFO(g_logger) << sylar::BacktraceToString(10); 8 | //SYLAR_ASSERT2(0 == 1, "abcdef xx"); 9 | } 10 | 11 | int main(int argc, char** argv) { 12 | test_assert(); 13 | 14 | int arr[] = {1,3,5,7,9,11}; 15 | 16 | SYLAR_LOG_INFO(g_logger) << sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 0); 17 | SYLAR_LOG_INFO(g_logger) << sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 1); 18 | SYLAR_LOG_INFO(g_logger) << sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 4); 19 | SYLAR_LOG_INFO(g_logger) << sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 13); 20 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 0) == -1); 21 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 1) == 0); 22 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 2) == -2); 23 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 3) == 1); 24 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 4) == -3); 25 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 5) == 2); 26 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 6) == -4); 27 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 7) == 3); 28 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 8) == -5); 29 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 9) == 4); 30 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 10) == -6); 31 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 11) == 5); 32 | SYLAR_ASSERT(sylar::BinarySearch(arr, sizeof(arr) / sizeof(arr[0]), 12) == -7); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /tests/test_ws_client.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/http/ws_connection.h" 2 | #include "sylar/iomanager.h" 3 | #include "sylar/util.h" 4 | 5 | void run() { 6 | auto rt = sylar::http::WSConnection::Create("http://127.0.0.1:8020/sylar", 1000); 7 | if(!rt.second) { 8 | std::cout << rt.first->toString() << std::endl; 9 | return; 10 | } 11 | 12 | auto conn = rt.second; 13 | while(true) { 14 | //for(int i = 0; i < 1100; ++i) { 15 | for(int i = 0; i < 1; ++i) { 16 | conn->sendMessage(sylar::random_string(60), sylar::http::WSFrameHead::TEXT_FRAME, false); 17 | } 18 | conn->sendMessage(sylar::random_string(65), sylar::http::WSFrameHead::TEXT_FRAME, true); 19 | auto msg = conn->recvMessage(); 20 | if(!msg) { 21 | break; 22 | } 23 | std::cout << "opcode=" << msg->getOpcode() 24 | << " data=" << msg->getData() << std::endl; 25 | 26 | sleep(10); 27 | } 28 | } 29 | 30 | int main(int argc, char** argv) { 31 | srand(time(0)); 32 | sylar::IOManager iom(1); 33 | iom.schedule(run); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tests/test_ws_server.cc: -------------------------------------------------------------------------------- 1 | #include "sylar/http/ws_server.h" 2 | #include "sylar/log.h" 3 | 4 | static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT(); 5 | 6 | void run() { 7 | sylar::http::WSServer::ptr server(new sylar::http::WSServer); 8 | sylar::Address::ptr addr = sylar::Address::LookupAnyIPAddress("0.0.0.0:8020"); 9 | if(!addr) { 10 | SYLAR_LOG_ERROR(g_logger) << "get address error"; 11 | return; 12 | } 13 | auto fun = [](sylar::http::HttpRequest::ptr header 14 | ,sylar::http::WSFrameMessage::ptr msg 15 | ,sylar::http::WSSession::ptr session) { 16 | session->sendMessage(msg); 17 | return 0; 18 | }; 19 | 20 | server->getWSServletDispatch()->addServlet("/sylar", fun); 21 | while(!server->bind(addr)) { 22 | SYLAR_LOG_ERROR(g_logger) << "bind " << *addr << " fail"; 23 | sleep(1); 24 | } 25 | server->start(); 26 | } 27 | 28 | int main(int argc, char** argv) { 29 | sylar::IOManager iom(2); 30 | iom.schedule(run); 31 | return 0; 32 | } 33 | --------------------------------------------------------------------------------