├── tools ├── Makefile └── daeml.cpp ├── src ├── file_server │ ├── fileserver.conf │ ├── Makefile │ ├── FileConn.h │ └── file_server.cpp ├── route_server │ ├── routeserver.conf │ ├── Makefile │ ├── RouteFileHandler.h │ ├── RouteConn.h │ ├── route_server.cpp │ └── RouteFileHandler.cpp ├── msg_server │ ├── msgserv_app.cpp │ ├── msgserv_app.h │ ├── policy.xml │ ├── msgserver.conf │ ├── HttpQuery.h │ ├── FileHandler.h │ ├── LoginServConn.h │ ├── AttachData.cpp │ ├── FileServConn.h │ ├── HttpConn.h │ ├── RouteServConn.h │ ├── DBServConn.h │ ├── HttpParserWrapper.cpp │ ├── HttpParserWrapper.h │ ├── AttachData.h │ ├── Makefile │ ├── GroupChat.h │ ├── MsgConn.h │ ├── ImUser.h │ ├── LoginServConn.cpp │ ├── msg_server.cpp │ ├── HttpConn.cpp │ ├── FileHandler.cpp │ ├── FileServConn.cpp │ └── HttpQuery.cpp ├── login_server │ ├── loginserver.conf │ ├── Makefile │ ├── policy.xml │ ├── LoginConn.h │ └── login_server.cpp ├── base │ ├── impdu.h │ ├── ConfigFileReader.h │ ├── Makefile │ ├── netlib.h │ ├── ServInfo.cpp │ ├── EventDispatch.h │ ├── imconn.h │ ├── ostype.h │ ├── ServInfo.h │ ├── BaseSocket.h │ ├── ConfigFileReader.cpp │ ├── util.h │ ├── UtilPdu.h │ ├── netlib.cpp │ ├── imconn.cpp │ └── util.cpp ├── msfs │ ├── include │ │ ├── storage │ │ │ ├── Portable.h │ │ │ ├── FileLin.h │ │ │ └── FileManager.h │ │ ├── common │ │ │ ├── StringUtils.h │ │ │ ├── ConfigFileReader.h │ │ │ ├── CriticalSection.h │ │ │ ├── SimpleBuffer.h │ │ │ ├── netlib.h │ │ │ ├── ThreadPool.h │ │ │ ├── EventDispatch.h │ │ │ ├── BaseSocket.h │ │ │ ├── ostype.h │ │ │ └── util.h │ │ └── http │ │ │ └── HttpParserWrapper.h │ ├── Makefile │ ├── common │ │ ├── SimpleBuffer.cpp │ │ ├── StringUtils.cpp │ │ ├── ThreadPool.cpp │ │ ├── netlib.cpp │ │ └── ConfigFileReader.cpp │ ├── http │ │ └── HttpParserWrapper.cpp │ ├── HttpConn.h │ ├── storage │ │ ├── FileLin.cpp │ │ └── FileManager.cpp │ └── main.cpp ├── test_client │ ├── Makefile │ ├── ClientConn.h │ └── pressure_test.cpp └── build.sh └── README.md /tools/Makefile: -------------------------------------------------------------------------------- 1 | daeml: daeml.cpp 2 | g++ -Wall -o daeml daeml.cpp 3 | -------------------------------------------------------------------------------- /src/file_server/fileserver.conf: -------------------------------------------------------------------------------- 1 | ListenIP=0.0.0.0 # Listening IP 2 | ListenPort=9800 # Listening Port for client 3 | -------------------------------------------------------------------------------- /src/route_server/routeserver.conf: -------------------------------------------------------------------------------- 1 | ListenIP=0.0.0.0 # Listening IP 2 | ListenMsgPort=9200 # Listening Port for MsgServer 3 | -------------------------------------------------------------------------------- /src/msg_server/msgserv_app.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // msg_serv_app.cpp 3 | // public_TTServer 4 | // 5 | // Created by luoning on 14-7-17. 6 | // Copyright (c) 2014年 luoning. All rights reserved. 7 | // 8 | 9 | #include "msg_serv_app.h" 10 | -------------------------------------------------------------------------------- /src/login_server/loginserver.conf: -------------------------------------------------------------------------------- 1 | # config format spec 2 | # this is a commet 3 | 4 | ClientListenIP=0.0.0.0 # can use multiple ip, seperate by ';' 5 | ClientPort=8008 6 | MsgServerListenIP=0.0.0.0 # can use multiple ip, seperate by ';' 7 | MsgServerPort=9100 8 | -------------------------------------------------------------------------------- /src/msg_server/msgserv_app.h: -------------------------------------------------------------------------------- 1 | // 2 | // msg_serv_app.h 3 | // public_TTServer 4 | // 5 | // Created by luoning on 14-7-17. 6 | // Copyright (c) 2014年 luoning. All rights reserved. 7 | // 8 | 9 | #ifndef __public_TTServer__msg_serv_app__ 10 | #define __public_TTServer__msg_serv_app__ 11 | 12 | #include 13 | 14 | #endif /* defined(__public_TTServer__msg_serv_app__) */ 15 | -------------------------------------------------------------------------------- /src/base/impdu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * impdu.h 3 | * 4 | * packet data unit, packet encapsulation and parse 5 | * Created on: 2013-6-8 6 | * Author: ziteng@mogujie.com 7 | */ 8 | 9 | #ifndef IMPDU_H_ 10 | #define IMPDU_H_ 11 | 12 | 13 | #include "ImPduBase.h" 14 | #include "ImPduClient.h" 15 | #include "ImPduServer.h" 16 | #include "ImPduFile.h" 17 | #include "ImPduGroup.h" 18 | 19 | #endif /* IMPDU_H_ */ 20 | -------------------------------------------------------------------------------- /src/file_server/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | 3 | INC = ../base 4 | OPT = -Wall -Wno-deprecated -g 5 | 6 | OBJS = FileConn.o file_server.o ../base/libbase.a 7 | 8 | SERVER = file_server 9 | 10 | all: $(SERVER) 11 | 12 | $(SERVER): $(OBJS) 13 | $(CC) $(OPT) -o $@ $(OBJS) -lpthread 14 | 15 | FileConn.o: FileConn.cpp 16 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 17 | 18 | file_server.o: file_server.cpp 19 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 20 | 21 | clean: 22 | rm -f $(SERVER) *.o 23 | 24 | -------------------------------------------------------------------------------- /src/login_server/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | 3 | INC = ../base 4 | OPT = -Wall -Wno-deprecated -g 5 | 6 | OBJS = LoginConn.o login_server.o ../base/libbase.a 7 | 8 | SERVER = login_server 9 | 10 | all: $(SERVER) 11 | 12 | $(SERVER): $(OBJS) 13 | $(CC) $(OPT) -o $@ $(OBJS) -lpthread 14 | 15 | LoginConn.o: LoginConn.cpp 16 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 17 | 18 | login_server.o: login_server.cpp 19 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 20 | 21 | clean: 22 | rm -f $(SERVER) *.o 23 | 24 | -------------------------------------------------------------------------------- /src/route_server/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | 3 | INC = ../base 4 | OPT = -Wall -Wno-deprecated -g 5 | 6 | OBJS = RouteConn.o route_server.o ../base/libbase.a 7 | 8 | SERVER = route_server 9 | 10 | all: $(SERVER) 11 | 12 | $(SERVER): $(OBJS) 13 | $(CC) $(OPT) -o $@ $(OBJS) -lpthread 14 | 15 | 16 | RouteConn.o: RouteConn.cpp 17 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 18 | 19 | route_server.o: route_server.cpp 20 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 21 | 22 | clean: 23 | rm -f $(SERVER) *.o 24 | 25 | -------------------------------------------------------------------------------- /src/msfs/include/storage/Portable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 数据类型与一些可移植相关定义 3 | * 4 | */ 5 | 6 | #ifndef _PORTABLE_H_ 7 | #define _PORTABLE_H_ 8 | 9 | typedef signed char s8; 10 | typedef unsigned char u8; 11 | typedef signed short s16; 12 | typedef unsigned short u16; 13 | typedef signed int s32; 14 | typedef unsigned int u32; 15 | typedef long long s64; 16 | typedef unsigned long long u64; 17 | typedef unsigned int uint; 18 | typedef unsigned char byte; 19 | 20 | #ifndef LITTLE_ENDIAN 21 | #define LITTLE_ENDIAN 22 | #endif 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/login_server/policy.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/msg_server/policy.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/base/ConfigFileReader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ConfigFileReader.h 3 | * 4 | * Created on: 2013-7-2 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef CONFIGFILEREADER_H_ 9 | #define CONFIGFILEREADER_H_ 10 | 11 | #include "util.h" 12 | 13 | class CConfigFileReader 14 | { 15 | public: 16 | CConfigFileReader(const char* filename); 17 | ~CConfigFileReader(); 18 | 19 | char* GetConfigName(const char* name); 20 | private: 21 | void _LoadFile(const char* filename); 22 | void _ParseLine(char* line); 23 | char* _TrimSpace(char* name); 24 | 25 | bool m_load_ok; 26 | map* m_config_map; 27 | }; 28 | 29 | 30 | 31 | #endif /* CONFIGFILEREADER_H_ */ 32 | -------------------------------------------------------------------------------- /src/msg_server/msgserver.conf: -------------------------------------------------------------------------------- 1 | ListenIP=0.0.0.0 2 | ListenPort=9000 3 | 4 | HttpListenIP=0.0.0.0 5 | HttpListenPort=9200 6 | 7 | 8 | ConcurrentDBConnCnt=2 9 | DBServerIP1=10.0.0.52 10 | DBServerPort1=10200 11 | #DBServerIP2=10.0.0.237 12 | #DBServerPort2=10100 13 | 14 | LoginServerIP1=localhost 15 | LoginServerPort1=8100 16 | #LoginServerIP2=localhost 17 | #LoginServerPort2=8101 18 | 19 | RouteServerIP1=localhost 20 | RouteServerPort1=8200 21 | #RouteServerIP2=localhost 22 | #RouteServerPort2=8201 23 | 24 | FileServerIP1=localhost 25 | FileServerPort1=8300 26 | #FileServerIP2=localhost 27 | #FileServerPort2=8301 28 | 29 | IpAddr1=localhost #电信IP 30 | IpAddr2=localhost #网通IP 31 | MaxConnCnt=100000 32 | -------------------------------------------------------------------------------- /src/msfs/include/common/StringUtils.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace msfs { 4 | // Replaces all occurrences of "search" with "replace". 5 | void replace_substrs(const char *search, 6 | size_t search_len, 7 | const char *replace, 8 | size_t replace_len, 9 | std::string *s); 10 | 11 | // True iff s1 starts with s2. 12 | bool starts_with(const char *s1, const char *s2); 13 | 14 | // True iff s1 ends with s2. 15 | bool ends_with(const char *s1, const char *s2); 16 | 17 | // Remove leading and trailing whitespaces. 18 | std::string string_trim(const std::string& s); 19 | 20 | std::string string_prefix(const std::string& s, const char *sep = "."); 21 | std::string string_suffix(const std::string& s, const char *sep = "."); 22 | } 23 | -------------------------------------------------------------------------------- /src/msfs/include/common/ConfigFileReader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ConfigFileReader.h 3 | * 4 | * Created on: 2013-7-2 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef CONFIGFILEREADER_H_ 9 | #define CONFIGFILEREADER_H_ 10 | 11 | #include "util.h" 12 | 13 | class CConfigFileReader 14 | { 15 | public: 16 | CConfigFileReader(const char* filename); 17 | ~CConfigFileReader(); 18 | 19 | char* GetConfigName(const char* name); 20 | int SetConfigValue(const char* name, const char* value); 21 | private: 22 | void _LoadFile(const char* filename); 23 | int _WriteFIle(const char*filename = NULL); 24 | void _ParseLine(char* line); 25 | char* _TrimSpace(char* name); 26 | 27 | bool m_load_ok; 28 | map* m_config_map; 29 | string m_config_file; 30 | }; 31 | 32 | #endif /* CONFIGFILEREADER_H_ */ 33 | -------------------------------------------------------------------------------- /src/test_client/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | 3 | INC = ../base 4 | OPT = -Wall -Wno-deprecated -g 5 | 6 | OBJS = ClientConn.o ../base/libbase.a 7 | CLIENT_OBJS = test_client.o $(OBJS) 8 | PRESSURE_OBJS = pressure_test.o $(OBJS) 9 | 10 | CLIENT = test_client 11 | PRESSURE_TEST = pressure_test 12 | 13 | all: $(CLIENT) $(PRESSURE_TEST) $(TEST_DB) 14 | 15 | $(CLIENT): $(CLIENT_OBJS) 16 | $(CC) $(OPT) -o $@ $(CLIENT_OBJS) -lpthread 17 | 18 | $(PRESSURE_TEST) : $(PRESSURE_OBJS) 19 | $(CC) $(OPT) -o $@ $(PRESSURE_OBJS) -lpthread 20 | 21 | ClientConn.o: ClientConn.cpp 22 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 23 | 24 | test_client.o: test_client.cpp 25 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 26 | 27 | pressure_test.o: pressure_test.cpp 28 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 29 | 30 | clean: 31 | rm -f $(CLIENT) $(PRESSURE_TEST) $(TEST_DB) *.o 32 | 33 | -------------------------------------------------------------------------------- /src/msg_server/HttpQuery.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HttpQuery.h 3 | * 4 | * Created on: 2013-10-22 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef HTTPQUERY_H_ 9 | #define HTTPQUERY_H_ 10 | 11 | #include "HttpConn.h" 12 | #include "jsonxx.h" 13 | 14 | class CHttpQuery 15 | { 16 | public: 17 | virtual ~CHttpQuery() {} 18 | 19 | static CHttpQuery* GetInstance(); 20 | 21 | static void DispatchQuery(std::string& url, std::string& post_data, CHttpConn* pHttpConn); 22 | private: 23 | CHttpQuery() {} 24 | 25 | static void _QueryCreateNormalGroup(jsonxx::Object& post_json_obj, CHttpConn* pHttpConn); 26 | static void _QueryChangeMember(jsonxx::Object& post_json_obj, CHttpConn* pHttpConn); 27 | private: 28 | static CHttpQuery* m_query_instance; 29 | }; 30 | 31 | string PackSendOk(); 32 | string URLDecode(const string &sIn); 33 | #endif /* HTTPQUERY_H_ */ 34 | -------------------------------------------------------------------------------- /src/login_server/LoginConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LoginConn.h 3 | * 4 | * Created on: 2013-6-21 5 | * Author: jianqingdu 6 | */ 7 | 8 | #ifndef LOGINCONN_H_ 9 | #define LOGINCONN_H_ 10 | 11 | #include "imconn.h" 12 | 13 | enum { 14 | LOGIN_CONN_TYPE_CLIENT = 1, 15 | LOGIN_CONN_TYPE_MSG_SERV 16 | }; 17 | 18 | class CLoginConn : public CImConn 19 | { 20 | public: 21 | CLoginConn(); 22 | virtual ~CLoginConn(); 23 | 24 | virtual void Close(); 25 | 26 | void OnConnect2(net_handle_t handle, int conn_type); 27 | virtual void OnClose(); 28 | virtual void OnTimer(uint64_t curr_tick); 29 | 30 | virtual void HandlePdu(CImPdu* pPdu); 31 | private: 32 | void _HandleMsgServInfo(CImPduMsgServInfo* pPdu); 33 | void _HandleUserCntUpdate(CImPduUserCntUpdate* pPdu); 34 | void _HandleMsgServRequest(CImPduMsgServRequest* pPdu); 35 | void _HandleUserConnInfo(CImPduUserConnInfo* pPdu); 36 | private: 37 | int m_conn_type; 38 | }; 39 | 40 | void init_login_conn(); 41 | 42 | #endif /* LOGINCONN_H_ */ 43 | -------------------------------------------------------------------------------- /src/route_server/RouteFileHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RouteFileHandler.h 3 | * 4 | * Created on: 2013-12-18 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef ROUTEFILEHANDLER_H_ 9 | #define ROUTEFILEHANDLER_H_ 10 | 11 | #include "impdu.h" 12 | 13 | class CRouteConn; 14 | /* 15 | class CRouteFileHandler 16 | { 17 | public: 18 | virtual ~CRouteFileHandler() {} 19 | static CRouteFileHandler* getInstance(); 20 | 21 | void HandleFileRequest(CImPduFileRequest* pPdu, CRouteConn* pFromConn); 22 | void HandleFileResponse(CImPduFileResponse* pPdu); 23 | void HandleFileRecvReady(CImPduFileRecvReady* pPdu); 24 | void HandleFileAbout(CImPduFileAbort* pPdu); 25 | void HandleFileUploadOfflineNotify(CImPduFileUploadOfflineNotify* pPdu); 26 | void HandleFileDownloadOfflineNotify(CImPduFileDownloadOfflineNotify* pPdu); 27 | 28 | private: 29 | CRouteFileHandler() {} 30 | 31 | private: 32 | static CRouteFileHandler* s_handler_instance; 33 | }; 34 | */ 35 | 36 | #endif /* ROUTEFILEHANDLER_H_ */ 37 | -------------------------------------------------------------------------------- /src/msg_server/FileHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FileHandler.h 3 | * 4 | * Created on: 2013-12-17 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef FILEHANDLER_H_ 9 | #define FILEHANDLER_H_ 10 | 11 | #include "impdu.h" 12 | 13 | class CMsgConn; 14 | 15 | class CFileHandler 16 | { 17 | public: 18 | virtual ~CFileHandler() {} 19 | 20 | static CFileHandler* getInstance(); 21 | 22 | void HandleClientFileRequest(CMsgConn* pMsgConn, CImPduClientFileRequest* pPdu); 23 | void HandleClientFileHasOfflineReq(CMsgConn* pMsgConn, CImPduClientFileHasOfflineReq* pPdu); 24 | void HandleClientFileAddOfflineReq(CImPduClientFileAddOfflineReq* pPdu); 25 | void HandleClientFileDelOfflineReq(CImPduClientFileDelOfflineReq* pPdu); 26 | void HandleFileHasOfflineRes(CImPduFileHasOfflineRes* pPdu); 27 | void HandleFileNotify(CImPduFileNotify* pPdu); 28 | private: 29 | CFileHandler() {} 30 | 31 | private: 32 | static CFileHandler* s_handler_instance; 33 | }; 34 | 35 | 36 | #endif /* FILEHANDLER_H_ */ 37 | -------------------------------------------------------------------------------- /src/msfs/Makefile: -------------------------------------------------------------------------------- 1 | #基本 2 | CC = g++ 3 | CFLAGS=-Wall -Wno-deprecated -g -O2 4 | LDFLAGS= -lpthread 5 | LN=/bin/ln -s 6 | AR=ar 7 | CP=/bin/cp 8 | RM=-/bin/rm -rf 9 | ARCH=PC 10 | 11 | #链接库名 12 | LIB_NAME= 13 | #链接库版本 14 | LIB_VER=1.0.0 15 | 16 | # 二进制目标 17 | BIN=../run/msfs 18 | 19 | #源文件目录 20 | SrcDir= . common http storage 21 | #头文件目录 22 | IncDir= . include/common include/http include/storage 23 | #连接库目录 24 | LibDir= 25 | 26 | SRCS=$(foreach dir,$(SrcDir),$(wildcard $(dir)/*.cpp)) 27 | INCS=$(foreach dir,$(IncDir),$(addprefix -I,$(dir))) 28 | LINKS=$(foreach dir,$(LibDir),$(addprefix -L,$(dir))) 29 | CFLAGS := $(CFLAGS) $(INCS) 30 | LDFLAGS:= $(LINKS) $(LDFLAGS) 31 | 32 | OBJS = $(SRCS:%.cpp=%.o) 33 | .PHONY:all clean 34 | 35 | all:$(BIN) 36 | $(BIN):$(OBJS) 37 | $(CC) -o $(BIN) $(OBJS) $(LDFLAGS) 38 | @echo " OK!\tComplie $@ " 39 | 40 | %.o:%.cpp 41 | @echo "Compileing $@..." 42 | @$(CC) $(CFLAGS) -c $< -o $@ 43 | 44 | .PHONY: clean 45 | clean: 46 | @echo "Cleaning files..." 47 | @$(RM) $(OBJS) $(BIN) 48 | -------------------------------------------------------------------------------- /src/msfs/include/common/CriticalSection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * critical section by potian@mogujie.com 3 | */ 4 | #ifndef __CRITICALSECTION_H__ 5 | #define __CRITICALSECTION_H__ 6 | 7 | namespace msfs { 8 | 9 | class CriticalSection { 10 | public: 11 | CriticalSection() { 12 | pthread_mutexattr_t mutex_attribute; 13 | pthread_mutexattr_init(&mutex_attribute); 14 | pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE); 15 | pthread_mutex_init(&m_mutex, &mutex_attribute); 16 | pthread_mutexattr_destroy(&mutex_attribute); 17 | } 18 | ~CriticalSection() { 19 | pthread_mutex_destroy(&m_mutex); 20 | } 21 | void Enter() { 22 | pthread_mutex_lock(&m_mutex); 23 | } 24 | bool TryEnter() { 25 | if (pthread_mutex_trylock(&m_mutex) == 0) { 26 | return true; 27 | } 28 | return false; 29 | } 30 | void Leave() { 31 | pthread_mutex_unlock(&m_mutex); 32 | } 33 | 34 | private: 35 | pthread_mutex_t m_mutex; 36 | 37 | }; 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/msg_server/LoginServConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LoginServConn.h 3 | * 4 | * Created on: 2013-7-8 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef LOGINSERVCONN_H_ 9 | #define LOGINSERVCONN_H_ 10 | 11 | #include "imconn.h" 12 | #include "ServInfo.h" 13 | 14 | class CLoginServConn : public CImConn 15 | { 16 | public: 17 | CLoginServConn(); 18 | virtual ~CLoginServConn(); 19 | 20 | bool IsOpen() { return m_bOpen; } 21 | 22 | void Connect(const char* server_ip, uint16_t server_port, uint32_t serv_idx); 23 | virtual void Close(); 24 | 25 | virtual void OnConfirm(); 26 | virtual void OnClose(); 27 | virtual void OnTimer(uint64_t curr_tick); 28 | 29 | virtual void HandlePdu(CImPdu* pPdu); 30 | private: 31 | bool m_bOpen; 32 | uint32_t m_serv_idx; 33 | }; 34 | 35 | void init_login_serv_conn(serv_info_t* server_list, uint32_t server_count, const char* msg_server_ip_addr1, 36 | const char* msg_server_ip_addr2, uint16_t msg_server_port, uint32_t max_conn_cnt); 37 | bool is_login_server_available(); 38 | void send_to_all_login_server(CImPdu* pPdu); 39 | 40 | 41 | #endif /* MSGCONN_LS_H_ */ 42 | -------------------------------------------------------------------------------- /src/msfs/include/common/SimpleBuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIMPLEBUFFER_H_ 2 | #define _SIMPLEBUFFER_H_ 3 | 4 | #include "ostype.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | #ifdef WIN32 12 | #ifdef BUILD_PDU 13 | #define DLL_MODIFIER __declspec(dllexport) 14 | #else 15 | #define DLL_MODIFIER __declspec(dllimport) 16 | #endif 17 | #else 18 | #define DLL_MODIFIER 19 | #endif 20 | 21 | class DLL_MODIFIER CSimpleBuffer 22 | { 23 | public: 24 | CSimpleBuffer(); 25 | ~CSimpleBuffer(); 26 | uchar_t* GetBuffer() 27 | { 28 | return m_buffer; 29 | } 30 | uint32_t GetAllocSize() 31 | { 32 | return m_alloc_size; 33 | } 34 | uint32_t GetWriteOffset() 35 | { 36 | return m_write_offset; 37 | } 38 | void IncWriteOffset(uint32_t len) 39 | { 40 | m_write_offset += len; 41 | } 42 | 43 | void Extend(uint32_t len); 44 | uint32_t Write(void* buf, uint32_t len); 45 | uint32_t Read(void* buf, uint32_t len); 46 | private: 47 | uchar_t* m_buffer; 48 | uint32_t m_alloc_size; 49 | uint32_t m_write_offset; 50 | }; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/msg_server/AttachData.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AttachData.cpp 3 | * 4 | * Created on: 2014年4月16日 5 | * Author: ziteng 6 | */ 7 | 8 | 9 | #include "AttachData.h" 10 | 11 | CDbAttachData::CDbAttachData(uint32_t type, uint32_t handle, uint32_t service_type /* = 0 */) // 序列化 12 | { 13 | CByteStream os(&m_buf, 0); 14 | 15 | os << type; 16 | os << handle; 17 | os << service_type; 18 | } 19 | 20 | CDbAttachData::CDbAttachData(uchar_t* attach_data, uint32_t attach_len) // 反序列化 21 | { 22 | CByteStream is(attach_data, attach_len); 23 | 24 | is >> m_type; 25 | is >> m_handle; 26 | is >> m_service_type; 27 | } 28 | 29 | CPduAttachData::CPduAttachData(uint32_t type, uint32_t handle, uint32_t pduLength, uchar_t* pdu, uint32_t service_type) // 序列化 30 | { 31 | CByteStream os(&m_buf, 0); 32 | 33 | os << type; 34 | os << handle; 35 | os << service_type; 36 | os.WriteData(pdu, pduLength); 37 | } 38 | 39 | CPduAttachData::CPduAttachData(uchar_t* attach_data, uint32_t attach_len) // 反序列化 40 | { 41 | CByteStream is(attach_data, attach_len); 42 | 43 | is >> m_type; 44 | is >> m_handle; 45 | is >> m_service_type; 46 | m_pdu = is.ReadData(m_pduLength); 47 | } -------------------------------------------------------------------------------- /src/base/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | 3 | OPT = -Wall -Wno-deprecated -g 4 | 5 | OBJS = UtilPdu.o util.o ConfigFileReader.o BaseSocket.o EventDispatch.o netlib.o ImPduBase.o ImPduClient.o \ 6 | ImPduServer.o ImPduFile.o ImPduGroup.o imconn.o ServInfo.o 7 | 8 | LIBBASE = libbase.a 9 | 10 | all: $(LIBBASE) 11 | 12 | $(LIBBASE): $(OBJS) 13 | ar -r $@ $(OBJS) 14 | 15 | UtilPdu.o: UtilPdu.cpp 16 | $(CC) $(OPT) -c -o $@ $< 17 | 18 | util.o: util.cpp 19 | $(CC) $(OPT) -c -o $@ $< 20 | 21 | ConfigFileReader.o: ConfigFileReader.cpp 22 | $(CC) $(OPT) -c -o $@ $< 23 | 24 | BaseSocket.o: BaseSocket.cpp 25 | $(CC) $(OPT) -c -o $@ $< 26 | 27 | EventDispatch.o: EventDispatch.cpp 28 | $(CC) $(OPT) -c -o $@ $< 29 | 30 | netlib.o: netlib.cpp 31 | $(CC) $(OPT) -c -o $@ $< 32 | 33 | imconn.o: imconn.cpp 34 | $(CC) $(OPT) -c -o $@ $< 35 | 36 | ImPduBase.o: ImPduBase.cpp 37 | $(CC) $(OPT) -c -o $@ $< 38 | 39 | ImPduClient.o: ImPduClient.cpp 40 | $(CC) $(OPT) -c -o $@ $< 41 | 42 | ImPduServer.o: ImPduServer.cpp 43 | $(CC) $(OPT) -c -o $@ $< 44 | 45 | ImPduFile.o: ImPduFile.cpp 46 | $(CC) $(OPT) -c -o $@ $< 47 | 48 | ImPduGroup.o: ImPduGroup.cpp 49 | $(CC) $(OPT) -c -o $@ $< 50 | 51 | ServInfo.o: ServInfo.cpp 52 | $(CC) $(OPT) -c -o $@ $< 53 | 54 | 55 | clean: 56 | rm -f $(LIBBASE) *.o 57 | 58 | -------------------------------------------------------------------------------- /src/file_server/FileConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FileConn.h 3 | * 4 | * Created on: 2013-12-9 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef FILECONN_H_ 9 | #define FILECONN_H_ 10 | 11 | #include "imconn.h" 12 | #include "impdu.h" 13 | 14 | typedef struct { 15 | FILE* fp; 16 | string file_path; 17 | string save_path; 18 | string peer_user_id; 19 | uint32_t file_size; 20 | uint32_t transfer_size; 21 | } file_stat_t; 22 | 23 | typedef map FileMap_t; 24 | 25 | class CFileConn : public CImConn 26 | { 27 | public: 28 | CFileConn(); 29 | virtual ~CFileConn(); 30 | 31 | virtual void Close(); 32 | 33 | void OnConnect(net_handle_t handle); 34 | virtual void OnClose(); 35 | virtual void OnTimer(uint64_t curr_tick); 36 | 37 | virtual void OnWrite(); 38 | 39 | virtual void HandlePdu(CImPdu* pPdu); 40 | 41 | private: 42 | void _HandleClientFileLoginReq(CImPduClientFileLoginReq* pPdu); 43 | void _HandleClientFileData(CImPduClientFileData* pPdu); 44 | void _HandleClientFileGetOfflineReq(CImPduClientFileGetOfflineReq* pPdu); 45 | 46 | bool _IsAuth() { return m_bAuth; } 47 | void _TrySendFile(); 48 | 49 | private: 50 | bool m_bAuth; 51 | uint32_t m_user_id; 52 | string m_user_id_url; 53 | FileMap_t m_save_file_map; 54 | list m_send_file_list; 55 | }; 56 | 57 | void init_file_conn(); 58 | 59 | 60 | #endif /* FILECONN_H_ */ 61 | -------------------------------------------------------------------------------- /src/msg_server/FileServConn.h: -------------------------------------------------------------------------------- 1 | // 2 | // FileServConn.h 3 | // public_TTServer 4 | // 5 | // Created by luoning on 14-8-19. 6 | // Copyright (c) 2014年 luoning. All rights reserved. 7 | // 8 | 9 | #ifndef __FileServConn__ 10 | #define __FileServConn__ 11 | 12 | #include 13 | 14 | #include "imconn.h" 15 | #include "ServInfo.h" 16 | #include "BaseSocket.h" 17 | class CFileServConn : public CImConn 18 | { 19 | public: 20 | CFileServConn(); 21 | virtual ~CFileServConn(); 22 | 23 | bool IsOpen() { return m_bOpen; } 24 | 25 | void Connect(const char* server_ip, uint16_t server_port, uint32_t serv_idx); 26 | virtual void Close(); 27 | 28 | virtual void OnConfirm(); 29 | virtual void OnClose(); 30 | virtual void OnTimer(uint64_t curr_tick); 31 | 32 | virtual void HandlePdu(CImPdu* pPdu); 33 | 34 | const list* GetFileServerIPList() { return &m_ip_list; } 35 | 36 | private: 37 | void _HandleFileMsgTransRsp(CImPduMsgFileTransferRsp* pPdu); 38 | void _HandleFileServerIPRsp(CImPduFileServerIPRsp* pPdu); 39 | 40 | private: 41 | bool m_bOpen; 42 | uint32_t m_serv_idx; 43 | uint64_t m_connect_time; 44 | list m_ip_list; 45 | }; 46 | 47 | void init_file_serv_conn(serv_info_t* server_list, uint32_t server_count); 48 | bool is_file_server_available(); 49 | CFileServConn* get_random_file_serv_conn(); 50 | #endif /* defined(__FileServConn__) */ 51 | -------------------------------------------------------------------------------- /src/msg_server/HttpConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HttpConn.h 3 | * 4 | * Created on: 2013-9-29 5 | * Author: ziteng 6 | */ 7 | 8 | #ifndef __HTTP_CONN_H__ 9 | #define __HTTP_CONN_H__ 10 | 11 | #include "netlib.h" 12 | #include "util.h" 13 | 14 | #define HTTP_CONN_TIMEOUT 60000 15 | 16 | #define READ_BUF_SIZE 2048 17 | 18 | enum { 19 | CONN_STATE_IDLE, 20 | CONN_STATE_CONNECTED, 21 | CONN_STATE_OPEN, 22 | CONN_STATE_CLOSED, 23 | }; 24 | 25 | class CHttpConn : public CRefObject 26 | { 27 | public: 28 | CHttpConn(); 29 | virtual ~CHttpConn(); 30 | 31 | uint32_t GetConnHandle() { return m_conn_handle; } 32 | char* GetPeerIP() { return (char*)m_peer_ip.c_str(); } 33 | 34 | int Send(void* data, int len); 35 | 36 | void Close(); 37 | void OnConnect(net_handle_t handle); 38 | void OnRead(); 39 | void OnWrite(); 40 | void OnClose(); 41 | void OnTimer(uint64_t curr_tick); 42 | 43 | protected: 44 | net_handle_t m_sock_handle; 45 | uint32_t m_conn_handle; 46 | bool m_busy; 47 | 48 | uint32_t m_state; 49 | std::string m_peer_ip; 50 | uint16_t m_peer_port; 51 | CSimpleBuffer m_in_buf; 52 | CSimpleBuffer m_out_buf; 53 | 54 | uint64_t m_last_send_tick; 55 | uint64_t m_last_recv_tick; 56 | }; 57 | 58 | typedef hash_map HttpConnMap_t; 59 | 60 | CHttpConn* FindHttpConnByHandle(uint32_t handle); 61 | void init_http_conn(); 62 | 63 | #endif /* IMCONN_H_ */ 64 | -------------------------------------------------------------------------------- /src/base/netlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __NETLIB_H__ 2 | #define __NETLIB_H__ 3 | 4 | #include "ostype.h" 5 | 6 | #define NETLIB_OPT_SET_CALLBACK 1 7 | #define NETLIB_OPT_SET_CALLBACK_DATA 2 8 | #define NETLIB_OPT_GET_REMOTE_IP 3 9 | #define NETLIB_OPT_GET_REMOTE_PORT 4 10 | #define NETLIB_OPT_GET_LOCAL_IP 5 11 | #define NETLIB_OPT_GET_LOCAL_PORT 6 12 | #define NETLIB_OPT_SET_SEND_BUF_SIZE 7 13 | #define NETLIB_OPT_SET_RECV_BUF_SIZE 8 14 | 15 | #define NETLIB_MAX_SOCKET_BUF_SIZE (128 * 1024) 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | int netlib_init(); 22 | 23 | int netlib_destroy(); 24 | 25 | int netlib_listen( 26 | const char* server_ip, 27 | uint16_t port, 28 | callback_t callback, 29 | void* callback_data); 30 | 31 | net_handle_t netlib_connect( 32 | const char* server_ip, 33 | uint16_t port, 34 | callback_t callback, 35 | void* callback_data); 36 | 37 | int netlib_send(net_handle_t handle, void* buf, int len); 38 | 39 | int netlib_recv(net_handle_t handle, void* buf, int len); 40 | 41 | int netlib_close(net_handle_t handle); 42 | 43 | int netlib_option(net_handle_t handle, int opt, void* optval); 44 | 45 | int netlib_register_timer(callback_t callback, void* user_data, uint64_t interval); 46 | 47 | int netlib_delete_timer(callback_t callback, void* user_data); 48 | 49 | void netlib_eventloop(); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/msfs/include/common/netlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __NETLIB_H__ 2 | #define __NETLIB_H__ 3 | 4 | #include "ostype.h" 5 | 6 | #define NETLIB_OPT_SET_CALLBACK 1 7 | #define NETLIB_OPT_SET_CALLBACK_DATA 2 8 | #define NETLIB_OPT_GET_REMOTE_IP 3 9 | #define NETLIB_OPT_GET_REMOTE_PORT 4 10 | #define NETLIB_OPT_GET_LOCAL_IP 5 11 | #define NETLIB_OPT_GET_LOCAL_PORT 6 12 | 13 | #define NETLIB_MAX_SOCKET_BUF_SIZE (128 * 1024) 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | int netlib_init(); 20 | 21 | int netlib_destroy(); 22 | 23 | int netlib_listen( 24 | const char* server_ip, 25 | uint16_t port, 26 | callback_t callback, 27 | void* callback_data); 28 | 29 | net_handle_t netlib_connect( 30 | const char* server_ip, 31 | uint16_t port, 32 | callback_t callback, 33 | void* callback_data); 34 | 35 | int netlib_send(net_handle_t handle, void* buf, int len); 36 | 37 | int netlib_recv(net_handle_t handle, void* buf, int len); 38 | 39 | int netlib_close(net_handle_t handle); 40 | 41 | int netlib_option(net_handle_t handle, int opt, void* optval); 42 | 43 | int netlib_register_timer(callback_t callback, void* user_data, uint64_t interval); 44 | 45 | int netlib_delete_timer(callback_t callback, void* user_data); 46 | 47 | int netlib_add_loop(callback_t callback, void* user_data); 48 | 49 | void netlib_eventloop(uint32_t wait_timeout = 100); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/msfs/common/SimpleBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "SimpleBuffer.h" 2 | #include 3 | #include 4 | 5 | ///////////// CSimpleBuffer //////////////// 6 | CSimpleBuffer::CSimpleBuffer() 7 | { 8 | m_buffer = NULL; 9 | 10 | m_alloc_size = 0; 11 | m_write_offset = 0; 12 | } 13 | 14 | CSimpleBuffer::~CSimpleBuffer() 15 | { 16 | m_alloc_size = 0; 17 | m_write_offset = 0; 18 | if (m_buffer) 19 | { 20 | free(m_buffer); 21 | m_buffer = NULL; 22 | } 23 | } 24 | 25 | void CSimpleBuffer::Extend(uint32_t len) 26 | { 27 | m_alloc_size = m_write_offset + len; 28 | m_alloc_size += m_alloc_size >> 2; // increase by 1/4 allocate size 29 | uchar_t* new_buf = (uchar_t*) realloc(m_buffer, m_alloc_size); 30 | if(new_buf != NULL) 31 | { 32 | m_buffer = new_buf; 33 | } 34 | } 35 | 36 | uint32_t CSimpleBuffer::Write(void* buf, uint32_t len) 37 | { 38 | if (m_write_offset + len > m_alloc_size) 39 | { 40 | Extend(len); 41 | } 42 | 43 | if (buf) 44 | { 45 | memcpy(m_buffer + m_write_offset, buf, len); 46 | } 47 | 48 | m_write_offset += len; 49 | 50 | return len; 51 | } 52 | 53 | uint32_t CSimpleBuffer::Read(void* buf, uint32_t len) 54 | { 55 | if (len > m_write_offset) 56 | len = m_write_offset; 57 | 58 | if (buf) 59 | memcpy(buf, m_buffer, len); 60 | 61 | m_write_offset -= len; 62 | memmove(m_buffer, m_buffer + len, m_write_offset); 63 | return len; 64 | } 65 | -------------------------------------------------------------------------------- /src/base/ServInfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ServInfo.cpp 3 | * 4 | * Created on: 2013-8-8 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "ServInfo.h" 9 | 10 | serv_info_t* read_server_config(CConfigFileReader* config_file, const char* server_ip_format, 11 | const char* server_port_format, uint32_t& server_count) 12 | { 13 | char server_ip_key[64]; 14 | char server_port_key[64]; 15 | 16 | server_count = 0; 17 | 18 | // get server_count first; 19 | while (true) { 20 | sprintf(server_ip_key, "%s%d", server_ip_format, server_count + 1); 21 | sprintf(server_port_key, "%s%d", server_port_format, server_count + 1); 22 | char* server_ip_value = config_file->GetConfigName(server_ip_key); 23 | char* server_port_value = config_file->GetConfigName(server_port_key); 24 | if (!server_ip_value || !server_port_value) { 25 | break; 26 | } 27 | 28 | server_count++; 29 | } 30 | 31 | if (server_count == 0) { 32 | return NULL; 33 | } 34 | 35 | serv_info_t* server_list = new serv_info_t [server_count]; 36 | 37 | for (uint32_t i = 0; i < server_count; i++) { 38 | sprintf(server_ip_key, "%s%d", server_ip_format, i + 1); 39 | sprintf(server_port_key, "%s%d", server_port_format, i + 1); 40 | char* server_ip_value = config_file->GetConfigName(server_ip_key); 41 | char* server_port_value = config_file->GetConfigName(server_port_key); 42 | server_list[i].server_ip = server_ip_value; 43 | server_list[i].server_port = atoi(server_port_value); 44 | } 45 | 46 | return server_list; 47 | } 48 | -------------------------------------------------------------------------------- /src/base/EventDispatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * A socket event dispatcher, features include: 3 | * 1. portable: worked both on Windows, MAC OS X, LINUX platform 4 | * 2. a singleton pattern: only one instance of this class can exist 5 | */ 6 | #ifndef __EVENT_DISPATCH_H__ 7 | #define __EVENT_DISPATCH_H__ 8 | 9 | #include "ostype.h" 10 | #include "util.h" 11 | 12 | enum { 13 | SOCKET_READ = 0x1, 14 | SOCKET_WRITE = 0x2, 15 | SOCKET_EXCEP = 0x4, 16 | SOCKET_ALL = 0x7 17 | }; 18 | 19 | class CEventDispatch 20 | { 21 | public: 22 | virtual ~CEventDispatch(); 23 | 24 | void AddEvent(SOCKET fd, uint8_t socket_event); 25 | void RemoveEvent(SOCKET fd, uint8_t socket_event); 26 | 27 | void AddTimer(callback_t callback, void* user_data, uint64_t interval); 28 | void RemoveTimer(callback_t callback, void* user_data); 29 | 30 | void StartDispatch(); 31 | 32 | static CEventDispatch* Instance(); 33 | protected: 34 | CEventDispatch(); 35 | 36 | private: 37 | void _CheckTimer(); 38 | 39 | typedef struct { 40 | callback_t callback; 41 | void* user_data; 42 | uint64_t interval; 43 | uint64_t next_tick; 44 | } TimerItem; 45 | 46 | private: 47 | #ifdef _WIN32 48 | fd_set m_read_set; 49 | fd_set m_write_set; 50 | fd_set m_excep_set; 51 | #elif __APPLE__ 52 | int m_kqfd; 53 | #else 54 | int m_epfd; 55 | #endif 56 | CThreadLock m_lock; 57 | list m_timer_list; 58 | 59 | static CEventDispatch* m_pEventDispatch; 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/msfs/include/common/ThreadPool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ThreadPool.h 3 | * 4 | * Created on: 2014年7月21日 5 | * Author: ziteng 6 | */ 7 | 8 | #ifndef THREADPOOL_H_ 9 | #define THREADPOOL_H_ 10 | 11 | #include 12 | #include 13 | #include "ostype.h" 14 | using namespace std; 15 | 16 | class CThreadNotify 17 | { 18 | public: 19 | CThreadNotify(); 20 | ~CThreadNotify(); 21 | void Lock() { pthread_mutex_lock(&m_mutex); } 22 | void Unlock() { pthread_mutex_unlock(&m_mutex); } 23 | void Wait() { pthread_cond_wait(&m_cond, &m_mutex); } 24 | void Signal() { pthread_cond_signal(&m_cond); } 25 | private: 26 | pthread_mutex_t m_mutex; 27 | pthread_mutexattr_t m_mutexattr; 28 | 29 | pthread_cond_t m_cond; 30 | }; 31 | 32 | class CTask { 33 | public: 34 | CTask(); 35 | virtual ~CTask(); 36 | 37 | virtual void run() = 0; 38 | private: 39 | }; 40 | 41 | class CWorkerThread { 42 | public: 43 | CWorkerThread(); 44 | ~CWorkerThread(); 45 | 46 | static void* StartRoutine(void* arg); 47 | 48 | void Start(); 49 | void Execute(); 50 | void PushTask(CTask* pTask); 51 | 52 | void SetThreadIdx(uint32_t idx) { m_thread_idx = idx; } 53 | private: 54 | 55 | uint32_t m_thread_idx; 56 | uint32_t m_task_cnt; 57 | pthread_t m_thread_id; 58 | CThreadNotify m_thread_notify; 59 | list m_task_list; 60 | }; 61 | 62 | class CThreadPool { 63 | public: 64 | CThreadPool(); 65 | virtual ~CThreadPool(); 66 | 67 | int Init(uint32_t worker_size); 68 | void AddTask(CTask* pTask); 69 | private: 70 | uint32_t m_worker_size; 71 | CWorkerThread* m_worker_list; 72 | }; 73 | 74 | 75 | 76 | #endif /* THREADPOOL_H_ */ 77 | -------------------------------------------------------------------------------- /src/base/imconn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * imconn.h 3 | * 4 | * Created on: 2013-6-5 5 | * Author: ziteng 6 | */ 7 | 8 | #ifndef IMCONN_H_ 9 | #define IMCONN_H_ 10 | 11 | #include "netlib.h" 12 | #include "util.h" 13 | #include "impdu.h" 14 | 15 | #define SERVER_HEARTBEAT_INTERVAL 5000 16 | #define SERVER_TIMEOUT 30000 17 | #define CLIENT_HEARTBEAT_INTERVAL 5000 18 | #define CLIENT_TIMEOUT 30000 19 | 20 | #define READ_BUF_SIZE 2048 21 | 22 | class CImConn : public CRefObject 23 | { 24 | public: 25 | CImConn(); 26 | virtual ~CImConn(); 27 | 28 | bool IsBusy() { return m_busy; } 29 | int SendPdu(CImPdu* pPdu) { return Send(pPdu->GetBuffer(), pPdu->GetLength()); } 30 | int Send(void* data, int len); 31 | 32 | virtual void OnConnect(net_handle_t handle) { m_handle = handle; } 33 | virtual void OnConfirm() {} 34 | virtual void OnRead(); 35 | virtual void OnWrite(); 36 | virtual void OnClose() {} 37 | virtual void OnTimer(uint64_t curr_tick) {} 38 | 39 | virtual void HandlePdu(CImPdu* pPdu) {} 40 | 41 | protected: 42 | net_handle_t m_handle; 43 | bool m_busy; 44 | 45 | string m_peer_ip; 46 | uint16_t m_peer_port; 47 | CSimpleBuffer m_in_buf; 48 | CSimpleBuffer m_out_buf; 49 | 50 | bool m_policy_conn; 51 | uint32_t m_recv_bytes; 52 | uint64_t m_last_send_tick; 53 | uint64_t m_last_recv_tick; 54 | }; 55 | 56 | typedef hash_map ConnMap_t; 57 | typedef hash_map UserMap_t; 58 | typedef hash_map UserConnCntMap_t; 59 | 60 | void imconn_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam); 61 | void ReadPolicyFile(); 62 | 63 | #endif /* IMCONN_H_ */ 64 | -------------------------------------------------------------------------------- /src/route_server/RouteConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RouteConn.h 3 | * 4 | * Created on: 2013-7-4 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef ROUTECONN_H_ 9 | #define ROUTECONN_H_ 10 | 11 | #include "imconn.h" 12 | 13 | class CRouteConn : public CImConn 14 | { 15 | public: 16 | CRouteConn(); 17 | virtual ~CRouteConn(); 18 | 19 | virtual void Close(); 20 | 21 | virtual void OnConnect(net_handle_t handle); 22 | virtual void OnClose(); 23 | virtual void OnTimer(uint64_t curr_tick); 24 | 25 | virtual void HandlePdu(CImPdu* pPdu); 26 | 27 | private: 28 | void _HandleOnlineUserInfo(CImPduOnlineUserInfo* pPdu); 29 | void _HandleUserStatusUpdate(CImPduUserStatusUpdate* pPdu); 30 | void _HandleFriendStatusQuery(CImPduFriendStatusQuery* pPdu); 31 | void _HandleFriendStatusNotify(CImPduFriendStatusNotify* pPdu); 32 | void _HandleMsgData(CImPduMsgData* pPdu); 33 | void _HandleP2PMsg(CImPduP2PMsg* pPdu); 34 | void _HandleRoleSet(CImPduRoleSet* pPdu); 35 | void _HandleUserStatusRequest(CImPduUserStatusRequest* pPdu); 36 | void _HandleUsersStatusRequest(CImPduUsersStatusRequest* pPdu); 37 | void _HandleKickOut(CImPduServerKickUser* pPdu); 38 | void _HandleUserClientType(CImPduUserClientTypeRequest * pPdu); 39 | void _HandleFileNotify(CImPduFileNotify* pPdu); 40 | 41 | void _UpdateUserStatus(uint32_t user_id, uint32_t status, uint32_t client_type_flag); 42 | void _BroadcastMsg(CImPdu* pPdu); 43 | void _DeliverMsgData(uint32_t from_id, uint32_t to_id, CImPdu* pPdu); 44 | private: 45 | list m_notify_user_list; 46 | bool m_bMaster; 47 | }; 48 | 49 | void init_routeconn_timer_callback(); 50 | 51 | #endif /* ROUTECONN_H_ */ 52 | -------------------------------------------------------------------------------- /src/msfs/include/common/EventDispatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * A socket event dispatcher, features include: 3 | * 1. portable: worked both on Windows, MAC OS X, LINUX platform 4 | * 2. a singleton pattern: only one instance of this class can exist 5 | */ 6 | #ifndef __EVENT_DISPATCH_H__ 7 | #define __EVENT_DISPATCH_H__ 8 | 9 | #include "ostype.h" 10 | #include "util.h" 11 | 12 | enum { 13 | SOCKET_READ = 0x1, 14 | SOCKET_WRITE = 0x2, 15 | SOCKET_EXCEP = 0x4, 16 | SOCKET_ALL = 0x7 17 | }; 18 | 19 | class CEventDispatch 20 | { 21 | public: 22 | virtual ~CEventDispatch(); 23 | 24 | void AddEvent(SOCKET fd, uint8_t socket_event); 25 | void RemoveEvent(SOCKET fd, uint8_t socket_event); 26 | 27 | void AddTimer(callback_t callback, void* user_data, uint64_t interval); 28 | void RemoveTimer(callback_t callback, void* user_data); 29 | 30 | void AddLoop(callback_t callback, void* user_data); 31 | 32 | void StartDispatch(uint32_t wait_timeout = 100); 33 | 34 | static CEventDispatch* Instance(); 35 | protected: 36 | CEventDispatch(); 37 | 38 | private: 39 | void _CheckTimer(); 40 | void _CheckLoop(); 41 | 42 | typedef struct { 43 | callback_t callback; 44 | void* user_data; 45 | uint64_t interval; 46 | uint64_t next_tick; 47 | } TimerItem; 48 | 49 | private: 50 | #ifdef _WIN32 51 | fd_set m_read_set; 52 | fd_set m_write_set; 53 | fd_set m_excep_set; 54 | #elif __APPLE__ 55 | int m_kqfd; 56 | #else 57 | int m_epfd; 58 | #endif 59 | CThreadLock m_lock; 60 | list m_timer_list; 61 | list m_loop_list; 62 | 63 | static CEventDispatch* m_pEventDispatch; 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/build.sh: -------------------------------------------------------------------------------- 1 | build() { 2 | echo "#ifndef __VERSION_H__" > base/version.h 3 | echo "#define __VERSION_H__" >> base/version.h 4 | echo "#define VERSION \"$1\"" >> base/version.h 5 | echo "#endif" >> base/version.h 6 | 7 | cd base 8 | make 9 | cd ../login_server 10 | make 11 | cd ../route_server 12 | make 13 | cd ../msg_server 14 | make 15 | #cd ../file_server 16 | #make 17 | #cd ../test_client 18 | #make 19 | #cd ../tools 20 | #make 21 | 22 | cd ../ 23 | 24 | #copy executables to run/ dir 25 | cp login_server/login_server ../run/login_server/ 26 | cp route_server/route_server ../run/route_server/ 27 | cp msg_server/msg_server ../run/msg_server/ 28 | cp file_server/file_server ../run/file_server/ 29 | cp tools/daeml ../run/ 30 | 31 | build_name=im-server-$1.tar.gz 32 | if [ -e "$build_name" ]; then 33 | rm $build_name 34 | fi 35 | tar zcvf $build_name login_server/login_server route_server/route_server msg_server/msg_server 36 | # file_server/file_server 37 | } 38 | 39 | clean() { 40 | cd base 41 | make clean 42 | cd ../login_server 43 | make clean 44 | cd ../route_server 45 | make clean 46 | cd ../msg_server 47 | make clean 48 | cd ../file_server 49 | make clean 50 | cd ../test_client 51 | make clean 52 | } 53 | 54 | print_help() { 55 | echo "Usage: " 56 | echo " $0 clean --- clean all build" 57 | echo " $0 version version_str --- build a version" 58 | } 59 | 60 | case $1 in 61 | clean) 62 | echo "clean all build..." 63 | clean 64 | ;; 65 | version) 66 | if [ $# != 2 ]; then 67 | echo $# 68 | print_help 69 | exit 70 | fi 71 | 72 | echo $2 73 | echo "build..." 74 | build $2 75 | ;; 76 | *) 77 | print_help 78 | ;; 79 | esac 80 | -------------------------------------------------------------------------------- /src/msg_server/RouteServConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RouteServConn.h 3 | * 4 | * Created on: 2013-7-8 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef ROUTESERVCONN_H_ 9 | #define ROUTESERVCONN_H_ 10 | 11 | #include "imconn.h" 12 | #include "ServInfo.h" 13 | 14 | class CRouteServConn : public CImConn 15 | { 16 | public: 17 | CRouteServConn(); 18 | virtual ~CRouteServConn(); 19 | 20 | bool IsOpen() { return m_bOpen; } 21 | uint64_t GetConnectTime() { return m_connect_time; } 22 | 23 | void Connect(const char* server_ip, uint16_t server_port, uint32_t serv_idx); 24 | virtual void Close(); 25 | 26 | virtual void OnConfirm(); 27 | virtual void OnClose(); 28 | virtual void OnTimer(uint64_t curr_tick); 29 | 30 | virtual void HandlePdu(CImPdu* pPdu); 31 | private: 32 | void _HandleKickUser(CImPduServerKickUser* pPdu); 33 | void _HandleFriendStatusList(CImPduFriendStatusList* pPdu); 34 | void _HandleFriendStatusNotify(CImPduFriendStatusNotify* pPdu); 35 | void _HandleMsgData(CImPduMsgData* pPdu); 36 | void _HandleP2PMsg(CImPduP2PMsg* pPdu); 37 | void _HandleGroupP2PMsg(CImPduGroupP2PMessageResponse* pPdu); 38 | 39 | void _HandleUserStatusResponse(CImPduUserStatusResponse* pPdu); 40 | void _HandleUsersStatusResponse(CImPduUsersStatusResponse* pPdu); 41 | void _HandleUserClientTypeResponse(CImPduUserClientTypeResponse* pPdu); 42 | private: 43 | bool m_bOpen; 44 | uint32_t m_serv_idx; 45 | uint64_t m_connect_time; 46 | }; 47 | 48 | void init_route_serv_conn(serv_info_t* server_list, uint32_t server_count); 49 | bool is_route_server_available(); 50 | void send_to_all_route_server(CImPdu* pPdu); 51 | CRouteServConn* get_route_serv_conn(); 52 | 53 | 54 | #endif /* ROUTESERVCONN_H_ */ 55 | -------------------------------------------------------------------------------- /src/msg_server/DBServConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DBServConn.h 3 | * 4 | * Created on: 2013-7-8 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef DBSERVCONN_H_ 9 | #define DBSERVCONN_H_ 10 | 11 | #include "imconn.h" 12 | #include "ServInfo.h" 13 | #include "RouteServConn.h" 14 | 15 | class CDBServConn : public CImConn 16 | { 17 | public: 18 | CDBServConn(); 19 | virtual ~CDBServConn(); 20 | 21 | bool IsOpen() { return m_bOpen; } 22 | 23 | void Connect(const char* server_ip, uint16_t server_port, uint32_t serv_idx); 24 | virtual void Close(); 25 | 26 | virtual void OnConfirm(); 27 | virtual void OnClose(); 28 | virtual void OnTimer(uint64_t curr_tick); 29 | 30 | virtual void HandlePdu(CImPdu* pPdu); 31 | private: 32 | void _HandleValidateResponse(CImPduValidateResponse* pPdu); 33 | void _HandleFriendListResponse(CImPduFriendListResponse* pPdu); 34 | void _HandleUnreadMsgCountResponse(CImPduUnreadMsgCountResponse* pPdu); 35 | void _HandleMsgListResponse(CImPduMsgListResponse* pPdu); 36 | void _HandleDBWriteResponse(CImPduDBWriteResponse* pPdu); 37 | void _HandleUsersInfoResponse(CImPduUsersInfoResponse* pPdu); 38 | void _HandleStopReceivePacket(CImPduStopReceivePacket* pPdu); 39 | void _HandleDBQueryResponse(CImPduDBQueryResponse* pPdu); 40 | void _HandleRemoveSessionResponse(CImPduRemoveSessionResponse* pPdu); 41 | void _HandleDepartmentResponse(CImPduDepartmentResponse* pPdu); 42 | private: 43 | bool m_bOpen; 44 | uint32_t m_serv_idx; 45 | }; 46 | 47 | void init_db_serv_conn(serv_info_t* server_list, uint32_t server_count, uint32_t concur_conn_cnt); 48 | string create_uuid(); 49 | 50 | CDBServConn* get_db_serv_conn_for_login(); 51 | CDBServConn* get_db_serv_conn(); 52 | 53 | #endif /* DBSERVCONN_H_ */ 54 | -------------------------------------------------------------------------------- /src/file_server/file_server.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * file_server.cpp 3 | * 4 | * Created on: 2013-12-9 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "FileConn.h" 9 | #include "netlib.h" 10 | #include "ConfigFileReader.h" 11 | #include "version.h" 12 | 13 | void file_serv_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 14 | { 15 | if (msg == NETLIB_MSG_CONNECT) { 16 | CFileConn* pConn = new CFileConn(); 17 | pConn->OnConnect(handle); 18 | } else { 19 | log("!!!error msg: %d\n", msg); 20 | } 21 | } 22 | 23 | int main(int argc, char* argv[]) 24 | { 25 | if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { 26 | printf("Server Version: FileServer/%s\n", VERSION); 27 | printf("Server Build: %s %s\n", __DATE__, __TIME__); 28 | return 0; 29 | } 30 | 31 | signal(SIGPIPE, SIG_IGN); 32 | 33 | CConfigFileReader config_file("fileserver.conf"); 34 | 35 | char* listen_ip = config_file.GetConfigName("ListenIP"); 36 | char* str_listen_port = config_file.GetConfigName("ListenPort"); 37 | 38 | if (!listen_ip || !str_listen_port) { 39 | log("config item missing, exit...\n"); 40 | return -1; 41 | } 42 | 43 | uint16_t listen_port = atoi(str_listen_port); 44 | 45 | init_file_conn(); 46 | 47 | int ret = netlib_init(); 48 | 49 | if (ret == NETLIB_ERROR) 50 | return ret; 51 | 52 | CStrExplode listen_ip_list(listen_ip, ';'); 53 | for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) { 54 | ret = netlib_listen(listen_ip_list.GetItem(i), listen_port, file_serv_callback, NULL); 55 | if (ret == NETLIB_ERROR) 56 | return ret; 57 | } 58 | 59 | printf("server start listen on %s:%d\n", listen_ip, listen_port); 60 | printf("now enter the event loop...\n"); 61 | 62 | netlib_eventloop(); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /src/msg_server/HttpParserWrapper.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // HttpPdu.cpp 3 | // http_msg_server 4 | // 5 | // Created by jianqing.du on 13-9-29. 6 | // Copyright (c) 2013年 ziteng. All rights reserved. 7 | // 8 | 9 | #include "HttpParserWrapper.h" 10 | #include "http_parser.h" 11 | 12 | CHttpParserWrapper* CHttpParserWrapper::m_instance = NULL; 13 | 14 | CHttpParserWrapper::CHttpParserWrapper() 15 | { 16 | 17 | } 18 | 19 | CHttpParserWrapper* CHttpParserWrapper::GetInstance() 20 | { 21 | if (!m_instance) { 22 | m_instance = new CHttpParserWrapper(); 23 | } 24 | 25 | return m_instance; 26 | } 27 | 28 | void CHttpParserWrapper::ParseHttpContent(const char* buf, uint32_t len) 29 | { 30 | http_parser_init(&m_http_parser, HTTP_REQUEST); 31 | memset(&m_settings, 0, sizeof(m_settings)); 32 | m_settings.on_url = OnUrl; 33 | m_settings.on_headers_complete = OnHeadersComplete; 34 | m_settings.on_body = OnBody; 35 | m_settings.on_message_complete = OnMessageComplete; 36 | 37 | m_read_all = false; 38 | m_total_length = 0; 39 | m_url.clear(); 40 | m_body_content.clear(); 41 | 42 | http_parser_execute(&m_http_parser, &m_settings, buf, len); 43 | } 44 | 45 | int CHttpParserWrapper::OnUrl(http_parser* parser, const char *at, size_t length) 46 | { 47 | m_instance->SetUrl(at, length); 48 | return 0; 49 | } 50 | 51 | int CHttpParserWrapper::OnHeadersComplete (http_parser* parser) 52 | { 53 | m_instance->SetTotalLength(parser->nread + (uint32_t)parser->content_length); 54 | return 0; 55 | } 56 | 57 | int CHttpParserWrapper::OnBody (http_parser* parser, const char *at, size_t length) 58 | { 59 | m_instance->SetBodyContent(at, length); 60 | return 0; 61 | } 62 | 63 | int CHttpParserWrapper::OnMessageComplete (http_parser* parser) 64 | { 65 | m_instance->SetReadAll(); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /src/msg_server/HttpParserWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // HttpPdu.h 3 | // http_msg_server 4 | // 5 | // Created by jianqing.du on 13-9-29. 6 | // Copyright (c) 2013年 ziteng. All rights reserved. 7 | // 8 | 9 | #ifndef http_msg_server_HttpParserWrapper_h 10 | #define http_msg_server_HttpParserWrapper_h 11 | 12 | #include "util.h" 13 | #include "http_parser.h" 14 | 15 | // extract url and content body from an ajax request 16 | class CHttpParserWrapper { 17 | public: 18 | virtual ~CHttpParserWrapper() {} 19 | 20 | static CHttpParserWrapper* GetInstance(); 21 | 22 | void ParseHttpContent(const char* buf, uint32_t len); 23 | 24 | bool IsReadAll() { return m_read_all; } 25 | uint32_t GetTotalLength() { return m_total_length; } 26 | string& GetUrl() { return m_url; } 27 | string& GetBodyContent() { return m_body_content; } 28 | 29 | void SetUrl(const char* url, size_t length) { m_url.append(url, length); } 30 | void SetBodyContent(const char* content, size_t length) { m_body_content.append(content, length); } 31 | void SetTotalLength(uint32_t total_len) { m_total_length = total_len; } 32 | void SetReadAll() { m_read_all = true; } 33 | 34 | static int OnUrl(http_parser* parser, const char *at, size_t length); 35 | static int OnHeadersComplete (http_parser* parser); 36 | static int OnBody (http_parser* parser, const char *at, size_t length); 37 | static int OnMessageComplete (http_parser* parser); 38 | private: 39 | CHttpParserWrapper(); 40 | 41 | private: 42 | static CHttpParserWrapper* m_instance; 43 | 44 | http_parser m_http_parser; 45 | http_parser_settings m_settings; 46 | 47 | bool m_read_all; 48 | uint32_t m_total_length; 49 | string m_url; 50 | string m_body_content; 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/msg_server/AttachData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AttachData.h 3 | * 4 | * Created on: 2014年4月16日 5 | * Author: ziteng 6 | */ 7 | 8 | #ifndef ATTACHDATA_H_ 9 | #define ATTACHDATA_H_ 10 | 11 | #include "util.h" 12 | 13 | enum { 14 | ATTACH_TYPE_HANDLE = 1, 15 | ATTACH_TYPE_SHOP_ID = 2, 16 | ATTACH_TYPE_HANDLE_AND_PDU = 3, 17 | }; 18 | 19 | class CDbAttachData 20 | { 21 | public: 22 | CDbAttachData(uint32_t type, uint32_t handle, uint32_t service_type = 0); // 序列化 23 | CDbAttachData(uchar_t* attach_data, uint32_t attach_len); // 反序列化 24 | virtual ~CDbAttachData() {} 25 | 26 | uchar_t* GetBuffer() {return m_buf.GetBuffer(); } 27 | uint32_t GetLength() { return m_buf.GetWriteOffset(); } 28 | uint32_t GetType() { return m_type; } 29 | uint32_t GetHandle() { return m_handle; } 30 | uint32_t GetServiceType() { return m_service_type; } 31 | private: 32 | CSimpleBuffer m_buf; 33 | uint32_t m_type; 34 | uint32_t m_handle; 35 | uint32_t m_service_type; 36 | }; 37 | 38 | class CPduAttachData 39 | { 40 | public: 41 | CPduAttachData(uint32_t type, uint32_t handle, uint32_t pduLength, uchar_t* pdu, uint32_t service_type = 0); // 序列化 42 | CPduAttachData(uchar_t* attach_data, uint32_t attach_len); // 反序列化 43 | virtual ~CPduAttachData() {} 44 | 45 | uchar_t* GetBuffer() {return m_buf.GetBuffer(); } 46 | uint32_t GetLength() { return m_buf.GetWriteOffset(); } 47 | uint32_t GetType() { return m_type; } 48 | uint32_t GetHandle() { return m_handle; } 49 | uint32_t GetServiceType() { return m_service_type; } 50 | uint32_t GetPduLength() { return m_pduLength; } 51 | uchar_t* GetPdu() { return m_pdu; } 52 | private: 53 | CSimpleBuffer m_buf; 54 | uint32_t m_type; 55 | uint32_t m_handle; 56 | uint32_t m_service_type; 57 | uint32_t m_pduLength; 58 | uchar_t* m_pdu; 59 | }; 60 | 61 | #endif /* ATTACHDATA_H_ */ 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ###项目背景 2 | 随着蘑菇街由导购向电商转型,蘑菇街自己的IM也应运而生,IM起初只是用于商家和 3 | 买家之间沟通的工具。后面我们问自己,既然已经有了用于客服的IM,为什么不自己 4 | 做一个IM,用于公司内部的沟通工具,来替换RTX呢,然后就有了TT(TeamTalk) 5 | 的雏形,现在蘑菇街内部的IM工具都是TT来完成的。随着TT的逐渐完善,我们再次 6 | 决定把TT开源,来回馈开源社区,我们希望国内的中小企业都能用上免费开源的 7 | IM内部沟通工具。 8 | 9 | ###系统环境 10 | 服务端平台: Linux 11 | 客户端平台: Windows,Mac, iOS, Android 12 | 13 | ###子系统分类 14 | 各个子系统的详细说明请参考子系统的README文档 15 | 16 | -TTPhpServer 17 | TT的Web后台管理服务器 18 | 19 | -TTCppServer 20 | TT的服务器,包括登陆分配,长连接接入,消息路由,文件传输, 21 | 文件存储等功能的支持 22 | 23 | -TTJavaServer 24 | TT的服务器,主要是作为TT服务器操作MySQL和Redis的代理服务器 25 | 26 | -TTWinClient 27 | Window客户端 28 | 29 | -TTMacClient 30 | Mac系统客户端 31 | 32 | -TTIOSClient 33 | iOS客户端 34 | 35 | -TTAndroidClient 36 | Android客户端 37 | 38 | ###编译安装 39 | 详见各自子系统的INSTALL文件 40 | 41 | ###开发流程 42 | 43 | 开发者流程 44 | 45 | - 开发者是指现在TeamTalk的开发人员,或者以后我们信任的贡献者转化而成的开发人员。 46 | 47 | - 要成为开发者,需要在github上注册账号, 然后由管理者加入到相应项目的collaborators列表 48 | 49 | - 开发主要用到master和develop两个分支, 平时开发都在develop分支上,只有代码 50 | 达到一个milestone的stable状态,才把develop分支merge到master分支 51 | 52 | - 有时开发者可能想实现一个比较cool的feature,可以建立一个feature_x分支, 53 | 测试稳定后merge到master 54 | 55 | 贡献者流程 56 | 57 | - 贡献者是指非TeamTalk项目组成员,热爱开源且希望为开源项目贡献代码的开发人员 58 | 59 | - 贡献者可以在github上Fork一个子项目,然后在Fork的项目上提交代码, 60 | 再通过Pull Request把修改通知给项目开发者,由开发者code review后, 61 | 决定是否merge进入master分支, 具体可参考: [github协作流程](http://www.worldhello.net/gotgithub/04-work-with-others/010-fork-and-pull.html) 62 | 63 | ###版本迭代流程 64 | - 版本迭代周期暂定为3个月 65 | - 开发者和贡献者可以把想要实现的feature通过github的wiki功能提交上来 66 | - 开始迭代前讨论本期版本要实现哪些feature,然后把要在本次迭代实现的featue列表写入版本的TODO feature list列表 67 | - 制定大概的排期 68 | - 开发,内部测试 69 | - alpha版本发布,公测 70 | - 把develop分支代码merge到master分支,stable版本发布 71 | 72 | ###开源协议 73 | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) 74 | 75 | ###Remark 76 | ![](https://raw.githubusercontent.com/mogutt/TTiOSClient/develop/pic/we-need-you.png) 77 | -------------------------------------------------------------------------------- /src/msg_server/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | 3 | INC = ../base 4 | OPT = -Wall -Wno-deprecated -g 5 | 6 | OBJS = FileServConn.o HttpParserWrapper.o HttpQuery.o http_parser.o HttpConn.o jsonxx.o ImUser.o AttachData.o GroupChat.o FileHandler.o MsgConn.o LoginServConn.o RouteServConn.o DBServConn.o msg_server.o ../base/libbase.a 7 | 8 | OS_NAME = $(shell uname) 9 | LC_OS_NAME = $(shell echo $(OS_NAME) | tr '[A-Z]' '[a-z]') 10 | ifeq ($(LC_OS_NAME), darwin) 11 | LIBS = -lpthread 12 | else 13 | LIBS = -lpthread -luuid 14 | endif 15 | 16 | SERVER = msg_server 17 | 18 | all: $(SERVER) 19 | 20 | $(SERVER): $(OBJS) 21 | $(CC) $(OPT) -o $@ $(OBJS) $(LIBS) 22 | 23 | GroupChat.o: GroupChat.cpp 24 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 25 | 26 | FileHandler.o: FileHandler.cpp 27 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 28 | 29 | MsgConn.o: MsgConn.cpp 30 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 31 | 32 | LoginServConn.o: LoginServConn.cpp 33 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 34 | 35 | RouteServConn.o: RouteServConn.cpp 36 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 37 | 38 | DBServConn.o: DBServConn.cpp 39 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 40 | 41 | msg_server.o: msg_server.cpp 42 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 43 | 44 | ImUser.o: ImUser.cpp 45 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 46 | 47 | AttachData.o: AttachData.cpp 48 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 49 | 50 | HttpQuery.o: HttpQuery.cpp 51 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 52 | 53 | http_parser.o: http_parser.c 54 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 55 | 56 | HttpConn.o: HttpConn.cpp 57 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 58 | 59 | HttpParserWrapper.o: HttpParserWrapper.cpp 60 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 61 | 62 | jsonxx.o: jsonxx.cpp 63 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 64 | 65 | FileServConn.o: FileServConn.cpp 66 | $(CC) -I $(INC) $(OPT) -c -o $@ $< 67 | 68 | clean: 69 | rm -f $(SERVER) *.o 70 | checkos: 71 | @echo $(LC_OS_NAME) 72 | -------------------------------------------------------------------------------- /src/route_server/route_server.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * route_server.cpp 3 | * 4 | * Created on: 2013-7-4 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "RouteConn.h" 9 | #include "netlib.h" 10 | #include "ConfigFileReader.h" 11 | #include "version.h" 12 | 13 | // this callback will be replaced by imconn_callback() in OnConnect() 14 | void route_serv_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 15 | { 16 | if (msg == NETLIB_MSG_CONNECT) 17 | { 18 | CRouteConn* pConn = new CRouteConn(); 19 | pConn->OnConnect(handle); 20 | } 21 | else 22 | { 23 | log("!!!error msg: %d\n", msg); 24 | } 25 | } 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { 30 | printf("Server Version: RouteServer/%s\n", VERSION); 31 | printf("Server Build: %s %s\n", __DATE__, __TIME__); 32 | return 0; 33 | } 34 | 35 | signal(SIGPIPE, SIG_IGN); 36 | srand(time(NULL)); 37 | 38 | CConfigFileReader config_file("routeserver.conf"); 39 | 40 | char* listen_ip = config_file.GetConfigName("ListenIP"); 41 | char* str_listen_msg_port = config_file.GetConfigName("ListenMsgPort"); 42 | 43 | if (!listen_ip || !str_listen_msg_port) { 44 | log("config item missing, exit...\n"); 45 | return -1; 46 | } 47 | 48 | uint16_t listen_msg_port = atoi(str_listen_msg_port); 49 | 50 | int ret = netlib_init(); 51 | 52 | if (ret == NETLIB_ERROR) 53 | return ret; 54 | 55 | CStrExplode listen_ip_list(listen_ip, ';'); 56 | for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) { 57 | ret = netlib_listen(listen_ip_list.GetItem(i), listen_msg_port, route_serv_callback, NULL); 58 | if (ret == NETLIB_ERROR) 59 | return ret; 60 | } 61 | 62 | printf("server start listen on: %s:%d\n", listen_ip, listen_msg_port); 63 | 64 | init_routeconn_timer_callback(); 65 | 66 | printf("now enter the event loop...\n"); 67 | 68 | netlib_eventloop(); 69 | 70 | return 0; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /src/base/ostype.h: -------------------------------------------------------------------------------- 1 | // OS dependant type definition 2 | #ifndef __OS_TYPE_H__ 3 | #define __OS_TYPE_H__ 4 | 5 | #ifdef _WIN32 6 | #include 7 | #include 8 | #else 9 | #ifdef __APPLE__ 10 | #include 11 | #include 12 | #include // syscall(SYS_gettid) 13 | #else 14 | #include 15 | #endif 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include // define int8_t ... 28 | #include 29 | #define closesocket close 30 | #define ioctlsocket ioctl 31 | #endif 32 | 33 | #ifdef _WIN32 34 | #if (_MSC_VER >= 1800) 35 | //vs2013+ 36 | #include 37 | #else 38 | typedef char int8_t; 39 | typedef short int16_t; 40 | typedef int int32_t; 41 | typedef long long int64_t; 42 | typedef unsigned char uint8_t; 43 | typedef unsigned short uint16_t; 44 | typedef unsigned int uint32_t; 45 | typedef unsigned long long uint64_t; 46 | #endif 47 | typedef int socklen_t; 48 | #else 49 | typedef int SOCKET; 50 | typedef int BOOL; 51 | const int TRUE = 1; 52 | const int FALSE = 0; 53 | const int SOCKET_ERROR = -1; 54 | const int INVALID_SOCKET = -1; 55 | #endif 56 | 57 | typedef unsigned char uchar_t; 58 | typedef int net_handle_t; 59 | typedef int conn_handle_t; 60 | 61 | enum { 62 | NETLIB_OK = 0, 63 | NETLIB_ERROR = -1 64 | }; 65 | 66 | #define NETLIB_INVALID_HANDLE -1 67 | 68 | enum 69 | { 70 | NETLIB_MSG_CONNECT = 1, 71 | NETLIB_MSG_CONFIRM, 72 | NETLIB_MSG_READ, 73 | NETLIB_MSG_WRITE, 74 | NETLIB_MSG_CLOSE, 75 | NETLIB_MSG_TIMER 76 | }; 77 | 78 | typedef void (*callback_t)(void* callback_data, uint8_t msg, uint32_t handle, void* pParam); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/msfs/common/StringUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "StringUtils.h" 2 | #include 3 | 4 | namespace msfs { 5 | 6 | void replace_substrs(const char *search, 7 | size_t search_len, 8 | const char *replace, 9 | size_t replace_len, 10 | std::string *s) { 11 | size_t pos = 0; 12 | while ((pos = s->find(search, pos, search_len)) != std::string::npos) { 13 | s->replace(pos, search_len, replace, replace_len); 14 | pos += replace_len; 15 | } 16 | } 17 | 18 | bool starts_with(const char *s1, const char *s2) { 19 | return strncmp(s1, s2, strlen(s2)) == 0; 20 | } 21 | 22 | bool ends_with(const char *s1, const char *s2) { 23 | size_t s1_length = strlen(s1); 24 | size_t s2_length = strlen(s2); 25 | 26 | if (s2_length > s1_length) { 27 | return false; 28 | } 29 | 30 | const char* start = s1 + (s1_length - s2_length); 31 | return strncmp(start, s2, s2_length) == 0; 32 | } 33 | 34 | static const char kWhitespace[] = " \n\r\t"; 35 | 36 | std::string string_trim(const std::string& s) { 37 | std::string::size_type first = s.find_first_not_of(kWhitespace); 38 | std::string::size_type last = s.find_last_not_of(kWhitespace); 39 | 40 | if (first == std::string::npos || last == std::string::npos) { 41 | return std::string(""); 42 | } 43 | 44 | return s.substr(first, last - first + 1); 45 | } 46 | 47 | std::string string_prefix(const std::string& s, const char *sep) { 48 | std::string::size_type first = s.find_first_of(sep); 49 | if (first != std::string::npos) 50 | return s.substr(0, first); 51 | else 52 | return std::string(""); 53 | } 54 | 55 | 56 | std::string string_suffix(const std::string& s, const char *sep) { 57 | std::string::size_type last = s.find_last_of(sep); 58 | if (last != std::string::npos) 59 | return s.substr(last + 1); 60 | else 61 | return std::string(""); 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/base/ServInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ServInfo.h 3 | * 4 | * Created on: 2013-7-19 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef SERVINFO_H_ 9 | #define SERVINFO_H_ 10 | 11 | #include "util.h" 12 | #include "imconn.h" 13 | #include "ConfigFileReader.h" 14 | 15 | #define MAX_RECONNECT_CNT 64 16 | #define MIN_RECONNECT_CNT 4 17 | 18 | typedef struct { 19 | string server_ip; 20 | uint16_t server_port; 21 | uint32_t idle_cnt; 22 | uint32_t reconnect_cnt; 23 | CImConn* serv_conn; 24 | } serv_info_t; 25 | 26 | template 27 | void serv_init(serv_info_t* server_list, uint32_t server_count) 28 | { 29 | for (uint32_t i = 0; i < server_count; i++) { 30 | T* pConn = new T(); 31 | pConn->Connect(server_list[i].server_ip.c_str(), server_list[i].server_port, i); 32 | server_list[i].serv_conn = pConn; 33 | server_list[i].idle_cnt = 0; 34 | server_list[i].reconnect_cnt = MIN_RECONNECT_CNT / 2; 35 | } 36 | } 37 | 38 | template 39 | void serv_check_reconnect(serv_info_t* server_list, uint32_t server_count) 40 | { 41 | T* pConn; 42 | for (uint32_t i = 0; i < server_count; i++) { 43 | pConn = (T*)server_list[i].serv_conn; 44 | if (!pConn) { 45 | server_list[i].idle_cnt++; 46 | if (server_list[i].idle_cnt >= server_list[i].reconnect_cnt) { 47 | pConn = new T(); 48 | pConn->Connect(server_list[i].server_ip.c_str(), server_list[i].server_port, i); 49 | server_list[i].serv_conn = pConn; 50 | } 51 | } 52 | } 53 | } 54 | 55 | template 56 | void serv_reset(serv_info_t* server_list, uint32_t server_count, uint32_t serv_idx) 57 | { 58 | if (serv_idx >= server_count) { 59 | return; 60 | } 61 | 62 | server_list[serv_idx].serv_conn = NULL; 63 | server_list[serv_idx].idle_cnt = 0; 64 | server_list[serv_idx].reconnect_cnt *= 2; 65 | if (server_list[serv_idx].reconnect_cnt > MAX_RECONNECT_CNT) { 66 | server_list[serv_idx].reconnect_cnt = MIN_RECONNECT_CNT; 67 | } 68 | } 69 | 70 | serv_info_t* read_server_config(CConfigFileReader* config_file, const char* server_ip_format, 71 | const char* server_port_format, uint32_t& server_count); 72 | 73 | 74 | #endif /* SERVINFO_H_ */ 75 | -------------------------------------------------------------------------------- /src/test_client/ClientConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ClientConn.h 3 | * 4 | * Created on: 2013-6-21 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef CLIENTCONN_H_ 9 | #define CLIENTCONN_H_ 10 | 11 | #include "imconn.h" 12 | 13 | enum { 14 | CONN_TYPE_LOGIN_SERV = 1, 15 | CONN_TYPE_MSG_SERV 16 | }; 17 | 18 | class ClientConn : public CImConn 19 | { 20 | public: 21 | ClientConn(); 22 | virtual ~ClientConn(); 23 | 24 | bool IsOpen() { return m_bOpen; } 25 | 26 | void Connect(const char* server_ip, uint16_t server_port, const char* user_name, const char* password, uint32_t conn_type); 27 | 28 | virtual void Close(); 29 | 30 | virtual void OnConfirm(); 31 | virtual void OnClose(); 32 | virtual void OnTimer(uint64_t curr_tick); 33 | 34 | virtual void HandlePdu(CImPdu* pPdu); 35 | private: 36 | void _HandleMsgServResponse(CImPduMsgServResponse* pPdu); 37 | void _HandleLoginResponse(CImPduLoginResponse* pPdu); 38 | void _HandleClientFriendList(CImPduClientFriendList* pPdu); 39 | void _HandleClientOnlineFriendList(CImPduClientOnlineFriendList* pPdu); 40 | void _HandleClientFriendNotify(CImPduClientFriendNotify* pPdu); 41 | void _HandleClientMsgData(CImPduClientMsgData* pPdu); 42 | void _HandleClientUnreadMsgCntResponse(CImPduClientUnreadMsgCntResponse* pPdu); 43 | void _HandleClientMsgListResponse(CImPduClientMsgListResponse* pPdu); 44 | void _HandleClientP2PCmdMsg(CImPduClientP2PCmdMsg* pPdu); 45 | void _HandleClientUserInfoResponse(CImPduClientUserInfoResponse* pPdu); 46 | void _HandleClientMsgDataAck(CImPduClientMsgDataAck* pPdu); 47 | void _HandleKickUser(CImPduKickUser* pPdu); 48 | void _HandleClientGroupListResponse(CImPduClientGroupListResponse* pPdu); 49 | void _HandleClientGroupUserListResponse(CImPduClientGroupUserListResponse* pPdu); 50 | void _HandleClientDepartmentResponse(CImPduClientDepartmentResponse* pPdu); 51 | private: 52 | string m_user_name; 53 | string m_password; 54 | uint32_t m_user_id; 55 | string m_id_url; 56 | string m_uuid; 57 | int m_conn_type; 58 | bool m_bOpen; 59 | }; 60 | 61 | void init_client_conn(bool display_pkt_info = true); 62 | ClientConn* get_client_conn(uint32_t user_id); 63 | 64 | #endif /* CLIENTCONN_H_ */ 65 | -------------------------------------------------------------------------------- /src/msfs/include/common/BaseSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * a wrap for non-block socket class for Windows, LINUX and MacOS X platform 3 | */ 4 | 5 | #ifndef __SOCKET_H__ 6 | #define __SOCKET_H__ 7 | 8 | #include "ostype.h" 9 | #include "util.h" 10 | 11 | enum 12 | { 13 | SOCKET_STATE_IDLE, 14 | SOCKET_STATE_LISTENING, 15 | SOCKET_STATE_CONNECTING, 16 | SOCKET_STATE_CONNECTED, 17 | SOCKET_STATE_CLOSING 18 | }; 19 | 20 | class CBaseSocket : public CRefObject 21 | { 22 | public: 23 | CBaseSocket(); 24 | 25 | virtual ~CBaseSocket(); 26 | 27 | SOCKET GetSocket() { return m_socket; } 28 | void SetSocket(SOCKET fd) { m_socket = fd; } 29 | void SetState(uint8_t state) { m_state = state; } 30 | 31 | void SetCallback(callback_t callback) { m_callback = callback; } 32 | void SetCallbackData(void* data) { m_callback_data = data; } 33 | void SetRemoteIP(char* ip) { m_remote_ip = ip; } 34 | void SetRemotePort(uint16_t port) { m_remote_port = port; } 35 | 36 | const char* GetRemoteIP() { return m_remote_ip.c_str(); } 37 | uint16_t GetRemotePort() { return m_remote_port; } 38 | const char* GetLocalIP() { return m_local_ip.c_str(); } 39 | uint16_t GetLocalPort() { return m_local_port; } 40 | public: 41 | int Listen( 42 | const char* server_ip, 43 | uint16_t port, 44 | callback_t callback, 45 | void* callback_data); 46 | 47 | net_handle_t Connect( 48 | const char* server_ip, 49 | uint16_t port, 50 | callback_t callback, 51 | void* callback_data); 52 | 53 | int Send(void* buf, int len); 54 | 55 | int Recv(void* buf, int len); 56 | 57 | int Close(); 58 | 59 | public: 60 | void OnRead(); 61 | void OnWrite(); 62 | void OnClose(); 63 | 64 | private: 65 | int _GetErrorCode(); 66 | bool _IsBlock(int error_code); 67 | 68 | void _SetNonblock(SOCKET fd); 69 | void _SetReuseAddr(SOCKET fd); 70 | void _SetNoDelay(SOCKET fd); 71 | void _SetAddr(const char* ip, const uint16_t port, sockaddr_in* pAddr); 72 | 73 | void _AcceptNewSocket(); 74 | 75 | private: 76 | string m_remote_ip; 77 | uint16_t m_remote_port; 78 | string m_local_ip; 79 | uint16_t m_local_port; 80 | 81 | callback_t m_callback; 82 | void* m_callback_data; 83 | 84 | uint8_t m_state; 85 | SOCKET m_socket; 86 | }; 87 | 88 | CBaseSocket* FindBaseSocket(net_handle_t fd); 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/msfs/include/common/ostype.h: -------------------------------------------------------------------------------- 1 | // OS dependant type definition 2 | #ifndef __OS_TYPE_H__ 3 | #define __OS_TYPE_H__ 4 | 5 | #ifdef _WIN32 6 | #include 7 | #include 8 | #else 9 | #ifdef __APPLE__ 10 | #include 11 | #include 12 | #include // syscall(SYS_gettid) 13 | #else 14 | #include 15 | #endif 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include // define int8_t ... 28 | #include 29 | #define closesocket close 30 | #define ioctlsocket ioctl 31 | #endif 32 | 33 | #ifdef _WIN32 34 | typedef char int8_t; 35 | typedef short int16_t; 36 | typedef int int32_t; 37 | typedef long long int64_t; 38 | typedef unsigned char uint8_t; 39 | typedef unsigned short uint16_t; 40 | typedef unsigned int uint32_t; 41 | typedef unsigned long long uint64_t; 42 | typedef int socklen_t; 43 | #else 44 | #ifdef linux 45 | const int TRUE = 1; 46 | const int FALSE = 0; 47 | #endif 48 | typedef int SOCKET; 49 | typedef int BOOL; 50 | const int SOCKET_ERROR = -1; 51 | const int INVALID_SOCKET = -1; 52 | #endif 53 | 54 | typedef unsigned char uchar_t; 55 | typedef int net_handle_t; 56 | typedef int conn_handle_t; 57 | 58 | enum { 59 | NETLIB_OK = 0, 60 | NETLIB_ERROR = -1 61 | }; 62 | 63 | #define NETLIB_INVALID_HANDLE -1 64 | 65 | enum 66 | { 67 | NETLIB_MSG_CONNECT = 1, 68 | NETLIB_MSG_CONFIRM, 69 | NETLIB_MSG_READ, 70 | NETLIB_MSG_WRITE, 71 | NETLIB_MSG_CLOSE, 72 | NETLIB_MSG_TIMER, 73 | NETLIB_MSG_LOOP, 74 | }; 75 | 76 | typedef void (*callback_t)(void* callback_data, uint8_t msg, uint32_t handle, void* pParam); 77 | 78 | //windows 79 | #ifdef _WIN32 80 | #define MSFS_WIN 1 81 | #endif 82 | 83 | //linux 84 | #ifdef linux 85 | #define MSFS_LINUX 1 86 | #endif 87 | 88 | //freebsd 89 | #ifdef __FreeBSD__ 90 | #define MSFS_BSD 1 91 | #endif 92 | 93 | #ifdef __APPLE__ 94 | #define MSFS_BSD 1 95 | #endif 96 | //unix 97 | #ifdef _UNIX 98 | #define MSFS_UNIX 1 99 | #endif 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/base/BaseSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * a wrap for non-block socket class for Windows, LINUX and MacOS X platform 3 | */ 4 | 5 | #ifndef __SOCKET_H__ 6 | #define __SOCKET_H__ 7 | 8 | #include "ostype.h" 9 | #include "util.h" 10 | 11 | enum 12 | { 13 | SOCKET_STATE_IDLE, 14 | SOCKET_STATE_LISTENING, 15 | SOCKET_STATE_CONNECTING, 16 | SOCKET_STATE_CONNECTED, 17 | SOCKET_STATE_CLOSING 18 | }; 19 | 20 | class CBaseSocket : public CRefObject 21 | { 22 | public: 23 | CBaseSocket(); 24 | 25 | virtual ~CBaseSocket(); 26 | 27 | SOCKET GetSocket() { return m_socket; } 28 | void SetSocket(SOCKET fd) { m_socket = fd; } 29 | void SetState(uint8_t state) { m_state = state; } 30 | 31 | void SetCallback(callback_t callback) { m_callback = callback; } 32 | void SetCallbackData(void* data) { m_callback_data = data; } 33 | void SetRemoteIP(char* ip) { m_remote_ip = ip; } 34 | void SetRemotePort(uint16_t port) { m_remote_port = port; } 35 | void SetSendBufSize(uint32_t send_size); 36 | void SetRecvBufSize(uint32_t recv_size); 37 | 38 | const char* GetRemoteIP() { return m_remote_ip.c_str(); } 39 | uint16_t GetRemotePort() { return m_remote_port; } 40 | const char* GetLocalIP() { return m_local_ip.c_str(); } 41 | uint16_t GetLocalPort() { return m_local_port; } 42 | public: 43 | int Listen( 44 | const char* server_ip, 45 | uint16_t port, 46 | callback_t callback, 47 | void* callback_data); 48 | 49 | net_handle_t Connect( 50 | const char* server_ip, 51 | uint16_t port, 52 | callback_t callback, 53 | void* callback_data); 54 | 55 | int Send(void* buf, int len); 56 | 57 | int Recv(void* buf, int len); 58 | 59 | int Close(); 60 | 61 | public: 62 | void OnRead(); 63 | void OnWrite(); 64 | void OnClose(); 65 | 66 | private: 67 | int _GetErrorCode(); 68 | bool _IsBlock(int error_code); 69 | 70 | void _SetNonblock(SOCKET fd); 71 | void _SetReuseAddr(SOCKET fd); 72 | void _SetNoDelay(SOCKET fd); 73 | void _SetAddr(const char* ip, const uint16_t port, sockaddr_in* pAddr); 74 | 75 | void _AcceptNewSocket(); 76 | 77 | private: 78 | string m_remote_ip; 79 | uint16_t m_remote_port; 80 | string m_local_ip; 81 | uint16_t m_local_port; 82 | 83 | callback_t m_callback; 84 | void* m_callback_data; 85 | 86 | uint8_t m_state; 87 | SOCKET m_socket; 88 | }; 89 | 90 | CBaseSocket* FindBaseSocket(net_handle_t fd); 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /src/base/ConfigFileReader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ConfigFileReader.cpp 3 | * 4 | * Created on: 2013-7-2 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | 9 | #include "ConfigFileReader.h" 10 | 11 | CConfigFileReader::CConfigFileReader(const char* filename) 12 | { 13 | m_config_map = new map; 14 | _LoadFile(filename); 15 | } 16 | 17 | CConfigFileReader::~CConfigFileReader() 18 | { 19 | delete m_config_map; 20 | } 21 | 22 | char* CConfigFileReader::GetConfigName(const char* name) 23 | { 24 | if (!m_load_ok) 25 | return NULL; 26 | 27 | char* value = NULL; 28 | map::iterator it = m_config_map->begin(); 29 | for ( ; it != m_config_map->end(); it++) 30 | { 31 | const char* key = it->first.c_str(); 32 | if (strcmp(key, name) == 0) 33 | { 34 | value = (char*)it->second.c_str(); 35 | break; 36 | } 37 | } 38 | 39 | return value; 40 | } 41 | 42 | void CConfigFileReader::_LoadFile(const char* filename) 43 | { 44 | FILE* fp = fopen(filename, "r"); 45 | if (!fp) 46 | { 47 | log("can not open %s\n", filename); 48 | return; 49 | } 50 | 51 | char buf[256]; 52 | for (;;) 53 | { 54 | char* p = fgets(buf, 256, fp); 55 | if (!p) 56 | break; 57 | 58 | size_t len = strlen(buf); 59 | if (buf[len - 1] == '\n') 60 | buf[len - 1] = 0; // remove \n at the end 61 | 62 | char* ch = strchr(buf, '#'); // remove string start with # 63 | if (ch) 64 | *ch = 0; 65 | 66 | if (strlen(buf) == 0) 67 | continue; 68 | 69 | _ParseLine(buf); 70 | } 71 | 72 | fclose(fp); 73 | m_load_ok = true; 74 | } 75 | 76 | void CConfigFileReader::_ParseLine(char* line) 77 | { 78 | char* p = strchr(line, '='); 79 | if (p == NULL) 80 | return; 81 | 82 | *p = 0; 83 | char* key = _TrimSpace(line); 84 | char* value = _TrimSpace(p + 1); 85 | if (key && value) 86 | { 87 | m_config_map->insert(make_pair(key, value)); 88 | } 89 | } 90 | 91 | char* CConfigFileReader::_TrimSpace(char* name) 92 | { 93 | // remove starting space or tab 94 | char* start_pos = name; 95 | while ( (*start_pos == ' ') || (*start_pos == '\t') ) 96 | { 97 | start_pos++; 98 | } 99 | 100 | if (strlen(start_pos) == 0) 101 | return NULL; 102 | 103 | // remove ending space or tab 104 | char* end_pos = name + strlen(name) - 1; 105 | while ( (*end_pos == ' ') || (*end_pos == '\t') ) 106 | { 107 | *end_pos = 0; 108 | end_pos--; 109 | } 110 | 111 | int len = (int)(end_pos - start_pos) + 1; 112 | if (len <= 0) 113 | return NULL; 114 | 115 | return start_pos; 116 | } 117 | -------------------------------------------------------------------------------- /src/msfs/include/storage/FileLin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multimdia Small File Storage Sytem 3 | * File Operation In Linux System 4 | * @author potian@mogujie.com 5 | */ 6 | 7 | #ifndef _FILELIN_H_ 8 | #define _FILELIN_H_ 9 | 10 | #include "Portable.h" 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | namespace msfs { 18 | 19 | class File { 20 | public: 21 | File(const char *path); 22 | ~File(); 23 | const char* getPath() const { 24 | return m_path; 25 | } 26 | u64 create(bool directIo = false); 27 | u64 remove(); 28 | u64 open(bool directIo = false); 29 | u64 close(); 30 | 31 | u64 isExist(bool *exist); 32 | static bool isExist(const char *path) { 33 | bool exist = false; 34 | File(path).isExist(&exist); 35 | return exist; 36 | } 37 | 38 | static u64 mkdirNoRecursion(const char *path); 39 | u64 isDirectory(bool *isDir); 40 | 41 | u64 getFileNum(int *fileNum); 42 | int getFd() { return m_opened == false ? -1 : m_file;} 43 | u64 read(u64 offset, u32 size, void *buffer); 44 | u64 write(u64 offset,u32 size, const void *buffer); 45 | u64 sync(); 46 | 47 | static s64 getFileSize(const char *path); 48 | u64 getSize(u64 *size); 49 | u64 setSize(u64 size); 50 | 51 | static const char* explainErrno(u64 code) { 52 | switch ((u32)code) { 53 | case E_NO_ERROR: 54 | return "no error"; 55 | case E_NOT_EXIST: 56 | return "file not exist"; 57 | case E_PERM_ERR: 58 | return "permission deny"; 59 | case E_DISK_FULL: 60 | return "disk is full"; 61 | case E_EXISTS: 62 | return "file already exist"; 63 | case E_IN_USE: 64 | return "file is in use"; 65 | case E_READ: 66 | return "read failed"; 67 | case E_WRITE: 68 | return "write failed"; 69 | case E_EOF: 70 | return "end of file exceeded"; 71 | default: 72 | return "other reasons"; 73 | } 74 | } 75 | 76 | public: 77 | //error code 78 | static const u64 E_NO_ERROR = 0; 79 | static const u32 E_NOT_EXIST = 1; 80 | static const u64 E_PERM_ERR = 2; 81 | static const u64 E_DISK_FULL = 3; 82 | static const u64 E_EXISTS = 4; 83 | static const u64 E_IN_USE = 5; 84 | static const u64 E_EOF = 6; 85 | static const u64 E_READ = 7; 86 | static const u64 E_WRITE = 8; 87 | static const u64 E_NO_EMPTY = 9; 88 | static const u64 E_OTHER = 10; 89 | 90 | private: 91 | char *m_path; //file full path 92 | bool m_opened; //file has opened 93 | s64 m_size; //file size 94 | int m_file; //file fd, -1 while the file no exists or opened 95 | bool m_directIo;//file open with directIO no OS buffer 96 | }; 97 | 98 | } 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/route_server/RouteFileHandler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * RouteFileHandler.cpp 3 | * 4 | * Created on: 2013-12-18 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "RouteFileHandler.h" 9 | #include "RouteConn.h" 10 | 11 | /* 12 | CRouteFileHandler* CRouteFileHandler::s_handler_instance = NULL; 13 | 14 | CRouteFileHandler* CRouteFileHandler::getInstance() 15 | { 16 | if (!s_handler_instance) { 17 | s_handler_instance = new CRouteFileHandler(); 18 | } 19 | 20 | return s_handler_instance; 21 | } 22 | 23 | void CRouteFileHandler::HandleFileRequest(CImPduFileRequest* pPdu, CRouteConn* pFromConn) 24 | { 25 | uint32_t from_id = pPdu->GetFromId(); 26 | uint32_t to_id = pPdu->GetToId(); 27 | string file_name(pPdu->GetFileName(), pPdu->GetFileNameLen()); 28 | log("HandleFileRequest, %u->%u, fileName: %s\n", from_id, to_id, file_name.c_str()); 29 | 30 | CRouteConn* pToConn = get_route_conn(to_id); 31 | if (pToConn) { 32 | pToConn->SendPdu(pPdu); 33 | } 34 | } 35 | 36 | void CRouteFileHandler::HandleFileResponse(CImPduFileResponse* pPdu) 37 | { 38 | uint32_t from_id = pPdu->GetFromId(); 39 | uint32_t to_id = pPdu->GetToId(); 40 | string file_name(pPdu->GetFileName(), pPdu->GetFileNameLen()); 41 | log("HandleFileResponse, %u->%u, fileName: %s\n", from_id, to_id, file_name.c_str()); 42 | 43 | CRouteConn* pConn = get_route_conn(to_id); 44 | if (pConn) { 45 | pConn->SendPdu(pPdu); 46 | } 47 | } 48 | 49 | void CRouteFileHandler::HandleFileRecvReady(CImPduFileRecvReady* pPdu) 50 | { 51 | uint32_t from_id = pPdu->GetFromId(); 52 | uint32_t to_id = pPdu->GetToId(); 53 | log("HandleFileRecvReady, %u->%u\n", from_id, to_id); 54 | 55 | CRouteConn* pConn = get_route_conn(to_id); 56 | if (pConn) { 57 | pConn->SendPdu(pPdu); 58 | } 59 | } 60 | 61 | void CRouteFileHandler::HandleFileAbout(CImPduFileAbort* pPdu) 62 | { 63 | uint32_t from_id = pPdu->GetFromId(); 64 | uint32_t to_id = pPdu->GetToId(); 65 | log("HandleFileAbort, %u->%u\n", from_id, to_id); 66 | 67 | CRouteConn* pConn = get_route_conn(to_id); 68 | if (pConn) { 69 | pConn->SendPdu(pPdu); 70 | } 71 | } 72 | 73 | void CRouteFileHandler::HandleFileUploadOfflineNotify(CImPduFileUploadOfflineNotify* pPdu) 74 | { 75 | uint32_t from_id = pPdu->GetFromId(); 76 | uint32_t to_id = pPdu->GetToId(); 77 | log("HandleFileUploadOfflineNotify, %u->%u\n", from_id, to_id); 78 | 79 | CRouteConn* pConn = get_route_conn(to_id); 80 | if (pConn) { 81 | pConn->SendPdu(pPdu); 82 | } 83 | } 84 | 85 | void CRouteFileHandler::HandleFileDownloadOfflineNotify(CImPduFileDownloadOfflineNotify* pPdu) 86 | { 87 | uint32_t from_id = pPdu->GetFromId(); 88 | uint32_t to_id = pPdu->GetToId(); 89 | log("HandleFileDownloadOfflineNotify, %u->%u\n", from_id, to_id); 90 | 91 | CRouteConn* pConn = get_route_conn(to_id); 92 | if (pConn) { 93 | pConn->SendPdu(pPdu); 94 | } 95 | } 96 | */ 97 | -------------------------------------------------------------------------------- /src/login_server/login_server.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * login_server.cpp 3 | * 4 | * Created on: 2013-6-21 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "LoginConn.h" 9 | #include "netlib.h" 10 | #include "ConfigFileReader.h" 11 | #include "version.h" 12 | 13 | void client_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 14 | { 15 | if (msg == NETLIB_MSG_CONNECT) 16 | { 17 | CLoginConn* pConn = new CLoginConn(); 18 | pConn->OnConnect2(handle, LOGIN_CONN_TYPE_CLIENT); 19 | } 20 | else 21 | { 22 | log("!!!error msg: %d\n", msg); 23 | } 24 | } 25 | 26 | // this callback will be replaced by imconn_callback() in OnConnect() 27 | void msg_serv_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 28 | { 29 | if (msg == NETLIB_MSG_CONNECT) 30 | { 31 | CLoginConn* pConn = new CLoginConn(); 32 | pConn->OnConnect2(handle, LOGIN_CONN_TYPE_MSG_SERV); 33 | } 34 | else 35 | { 36 | log("!!!error msg: %d\n", msg); 37 | } 38 | } 39 | 40 | 41 | int main(int argc, char* argv[]) 42 | { 43 | if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { 44 | printf("Server Version: LoginServer/%s\n", VERSION); 45 | printf("Server Build: %s %s\n", __DATE__, __TIME__); 46 | return 0; 47 | } 48 | 49 | signal(SIGPIPE, SIG_IGN); 50 | 51 | CConfigFileReader config_file("loginserver.conf"); 52 | 53 | char* client_listen_ip = config_file.GetConfigName("ClientListenIP"); 54 | char* str_client_port = config_file.GetConfigName("ClientPort"); 55 | char* msg_server_listen_ip = config_file.GetConfigName("MsgServerListenIP"); 56 | char* str_msg_server_port = config_file.GetConfigName("MsgServerPort"); 57 | 58 | if (!client_listen_ip || !str_client_port || !msg_server_listen_ip || !str_msg_server_port) { 59 | log("config item missing, exit...\n"); 60 | return -1; 61 | } 62 | 63 | uint16_t client_port = atoi(str_client_port); 64 | uint16_t msg_server_port = atoi(str_msg_server_port); 65 | 66 | int ret = netlib_init(); 67 | 68 | if (ret == NETLIB_ERROR) 69 | return ret; 70 | 71 | CStrExplode client_listen_ip_list(client_listen_ip, ';'); 72 | for (uint32_t i = 0; i < client_listen_ip_list.GetItemCnt(); i++) { 73 | ret = netlib_listen(client_listen_ip_list.GetItem(i), client_port, client_callback, NULL); 74 | if (ret == NETLIB_ERROR) 75 | return ret; 76 | } 77 | 78 | CStrExplode msg_server_listen_ip_list(msg_server_listen_ip, ';'); 79 | for (uint32_t i = 0; i < msg_server_listen_ip_list.GetItemCnt(); i++) { 80 | ret = netlib_listen(msg_server_listen_ip_list.GetItem(i), msg_server_port, msg_serv_callback, NULL); 81 | if (ret == NETLIB_ERROR) 82 | return ret; 83 | } 84 | 85 | printf("server start listen on:\nFor client %s:%d\nFor MsgServer: %s:%d\n", 86 | client_listen_ip, client_port, msg_server_listen_ip, msg_server_port); 87 | 88 | init_login_conn(); 89 | 90 | printf("now enter the event loop...\n"); 91 | 92 | netlib_eventloop(); 93 | 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /src/msfs/common/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ThreadPool.cpp 3 | * 4 | * Created on: 2014年7月21日 5 | * Author: ziteng 6 | */ 7 | 8 | #include 9 | #include "util.h" 10 | #include "ThreadPool.h" 11 | 12 | CThreadNotify::CThreadNotify() 13 | { 14 | pthread_mutexattr_init(&m_mutexattr); 15 | pthread_mutexattr_settype(&m_mutexattr, PTHREAD_MUTEX_RECURSIVE); 16 | pthread_mutex_init(&m_mutex, &m_mutexattr); 17 | 18 | pthread_cond_init(&m_cond, NULL); 19 | } 20 | 21 | CThreadNotify::~CThreadNotify() 22 | { 23 | pthread_mutexattr_destroy(&m_mutexattr); 24 | pthread_mutex_destroy(&m_mutex); 25 | 26 | pthread_cond_destroy(&m_cond); 27 | } 28 | 29 | //////////////////// 30 | CTask::CTask() 31 | { 32 | } 33 | 34 | CTask::~CTask() 35 | { 36 | } 37 | 38 | void CTask::run() 39 | { 40 | } 41 | 42 | /////////// 43 | CWorkerThread::CWorkerThread() 44 | { 45 | m_task_cnt = 0; 46 | } 47 | 48 | CWorkerThread::~CWorkerThread() 49 | { 50 | 51 | } 52 | 53 | void* CWorkerThread::StartRoutine(void* arg) 54 | { 55 | CWorkerThread* pThread = (CWorkerThread*)arg; 56 | 57 | pThread->Execute(); 58 | 59 | return NULL; 60 | } 61 | 62 | void CWorkerThread::Start() 63 | { 64 | (void)pthread_create(&m_thread_id, NULL, StartRoutine, this); 65 | } 66 | 67 | void CWorkerThread::Execute() 68 | { 69 | while (true) { 70 | m_thread_notify.Lock(); 71 | 72 | // put wait in while cause there can be spurious wake up (due to signal/ENITR) 73 | while (m_task_list.empty()) { 74 | m_thread_notify.Wait(); 75 | } 76 | 77 | CTask* pTask = m_task_list.front(); 78 | m_task_list.pop_front(); 79 | m_thread_notify.Unlock(); 80 | 81 | pTask->run(); 82 | 83 | delete pTask; 84 | 85 | m_task_cnt++; 86 | log("%d have the execute %d task\n", m_thread_idx, m_task_cnt); 87 | } 88 | } 89 | 90 | void CWorkerThread::PushTask(CTask* pTask) 91 | { 92 | m_thread_notify.Lock(); 93 | m_task_list.push_back(pTask); 94 | m_thread_notify.Signal(); 95 | m_thread_notify.Unlock(); 96 | } 97 | 98 | ////////////// 99 | CThreadPool::CThreadPool() 100 | { 101 | m_worker_size = 0; 102 | m_worker_list = NULL; 103 | } 104 | 105 | CThreadPool::~CThreadPool() 106 | { 107 | 108 | } 109 | 110 | int CThreadPool::Init(uint32_t worker_size) 111 | { 112 | m_worker_size = worker_size; 113 | m_worker_list = new CWorkerThread [m_worker_size]; 114 | if (!m_worker_list) { 115 | return 1; 116 | } 117 | 118 | for (uint32_t i = 0; i < m_worker_size; i++) { 119 | m_worker_list[i].SetThreadIdx(i); 120 | m_worker_list[i].Start(); 121 | } 122 | 123 | return 0; 124 | } 125 | 126 | void CThreadPool::AddTask(CTask* pTask) 127 | { 128 | /* 129 | * select a random thread to push task 130 | * we can also select a thread that has less task to do 131 | * but that will scan the whole thread list and use thread lock to get each task size 132 | */ 133 | uint32_t thread_idx = random() % m_worker_size; 134 | m_worker_list[thread_idx].PushTask(pTask); 135 | } 136 | 137 | -------------------------------------------------------------------------------- /tools/daeml.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* closeall() -- close all FDs >= a specified value */ 10 | 11 | void closeall(int fd) 12 | { 13 | int fdlimit = sysconf(_SC_OPEN_MAX); 14 | 15 | while (fd < fdlimit) 16 | close(fd++); 17 | } 18 | 19 | 20 | /* daemon() - detach process from user and disappear into the background 21 | * returns -1 on failure, but you can't do much except exit in that case 22 | * since we may already have forked. This is based on the BSD version, 23 | * so the caller is responsible for things like the umask, etc. 24 | */ 25 | 26 | int daemon(int nochdir, int noclose, int asroot) 27 | { 28 | switch (fork()) 29 | { 30 | case 0: break; 31 | case -1: return -1; 32 | default: _exit(0); /* exit the original process */ 33 | } 34 | 35 | if (setsid() < 0) /* shoudn't fail */ 36 | return -1; 37 | 38 | if ( !asroot && (setuid(1) < 0) ) /* shoudn't fail */ 39 | return -1; 40 | 41 | /* dyke out this switch if you want to acquire a control tty in */ 42 | /* the future -- not normally advisable for daemons */ 43 | 44 | switch (fork()) 45 | { 46 | case 0: break; 47 | case -1: return -1; 48 | default: _exit(0); 49 | } 50 | 51 | if (!nochdir) 52 | chdir("/"); 53 | 54 | if (!noclose) 55 | { 56 | closeall(0); 57 | dup(0); dup(0); 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | #define TEXT(a) a 64 | void PrintUsage(char* name) 65 | { 66 | printf ( 67 | TEXT("\n ----- \n\n") 68 | TEXT("Usage:\n") 69 | TEXT(" %s program_name \n\n") 70 | TEXT("Where:\n") 71 | TEXT(" %s - Name of this Daemon loader.\n") 72 | TEXT(" program_name - Name (including path) of the program you want to load as daemon.\n\n") 73 | TEXT("Example:\n") 74 | TEXT(" %s ./atprcmgr - Launch program 'atprcmgr' in current directory as daemon. \n\n\n\n"), 75 | name, name, name 76 | ); 77 | } 78 | 79 | int main(int argc, char* argv[]) 80 | { 81 | printf( 82 | TEXT("\n") 83 | TEXT("Daemon loader\n") 84 | TEXT("- Launch specified program as daemon.\n") 85 | //TEXT("- Require root privilege to launch successfully.\n\n\n") 86 | ); 87 | 88 | if (argc < 2) 89 | { 90 | printf("* Missing parameter : daemon program name not specified!\n"); 91 | PrintUsage(argv[0]); 92 | exit(0); 93 | } 94 | 95 | printf("- Loading %s as daemon, please wait ......\n\n\n", argv[1]); 96 | 97 | if (daemon(1, 0, 1) >= 0) 98 | { 99 | signal(SIGCHLD, SIG_IGN); 100 | 101 | //execl(argv[1], argv[1], NULL); 102 | execv(argv[1], argv + 1); 103 | printf("! Excute daemon programm %s failed. \n", argv[1]); 104 | 105 | exit(0); 106 | } 107 | 108 | printf("! Create daemon error. Please check if you have 'root' privilege. \n"); 109 | return 0; 110 | } 111 | 112 | 113 | -------------------------------------------------------------------------------- /src/base/util.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTIL_H__ 2 | #define __UTIL_H__ 3 | 4 | #define _CRT_SECURE_NO_DEPRECATE // remove warning C4996, 5 | 6 | #include "ostype.h" 7 | #include "UtilPdu.h" 8 | #include 9 | #include 10 | #include 11 | 12 | #ifdef _WIN32 13 | #define snprintf sprintf_s 14 | #else 15 | #include 16 | #include 17 | #include 18 | #include 19 | #endif 20 | 21 | #ifdef _WIN32 22 | #include 23 | using namespace stdext; 24 | #else 25 | #include 26 | using namespace __gnu_cxx; 27 | #endif 28 | 29 | #define MAX_LOG_FILE_SIZE 0x4000000 // 64MB 30 | #define NOTUSED_ARG(v) ((void)v) // used this to remove warning C4100, unreferenced parameter 31 | 32 | class CThread 33 | { 34 | public: 35 | CThread(); 36 | virtual ~CThread(); 37 | 38 | #ifdef _WIN32 39 | static DWORD WINAPI StartRoutine(LPVOID lpParameter); 40 | #else 41 | static void* StartRoutine(void* arg); 42 | #endif 43 | 44 | virtual void StartThread(void); 45 | virtual void OnThreadRun(void) = 0; 46 | protected: 47 | #ifdef _WIN32 48 | DWORD m_thread_id; 49 | #else 50 | pthread_t m_thread_id; 51 | #endif 52 | }; 53 | 54 | class CEventThread : public CThread 55 | { 56 | public: 57 | CEventThread(); 58 | virtual ~CEventThread(); 59 | 60 | virtual void OnThreadTick(void) = 0; 61 | virtual void OnThreadRun(void); 62 | virtual void StartThread(); 63 | virtual void StopThread(); 64 | bool IsRunning() { return m_bRunning; } 65 | private: 66 | bool m_bRunning; 67 | }; 68 | 69 | class CThreadLock 70 | { 71 | public: 72 | CThreadLock(); 73 | ~CThreadLock(); 74 | void Lock(void); 75 | void Unlock(void); 76 | private: 77 | #ifdef _WIN32 78 | CRITICAL_SECTION m_critical_section; 79 | #else 80 | pthread_mutex_t m_mutex; 81 | pthread_mutexattr_t m_mutexattr; 82 | #endif 83 | }; 84 | 85 | class CFuncLock 86 | { 87 | public: 88 | CFuncLock(CThreadLock* lock) 89 | { 90 | m_lock = lock; 91 | if (m_lock) 92 | m_lock->Lock(); 93 | } 94 | 95 | ~CFuncLock() 96 | { 97 | if (m_lock) 98 | m_lock->Unlock(); 99 | } 100 | private: 101 | CThreadLock* m_lock; 102 | }; 103 | 104 | class CRefObject 105 | { 106 | public: 107 | CRefObject(); 108 | virtual ~CRefObject(); 109 | 110 | void SetLock(CThreadLock* lock) { m_lock = lock; } 111 | void AddRef(); 112 | void ReleaseRef(); 113 | private: 114 | int m_refCount; 115 | CThreadLock* m_lock; 116 | }; 117 | 118 | void log(const char* fmt, ...); 119 | 120 | uint64_t get_tick_count(); 121 | void util_sleep(uint32_t millisecond); 122 | 123 | 124 | class CStrExplode 125 | { 126 | public: 127 | CStrExplode(char* str, char seperator); 128 | virtual ~CStrExplode(); 129 | 130 | uint32_t GetItemCnt() { return m_item_cnt; } 131 | char* GetItem(uint32_t idx) { return m_item_list[idx]; } 132 | private: 133 | uint32_t m_item_cnt; 134 | char** m_item_list; 135 | }; 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/msg_server/GroupChat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GroupChat.h 3 | * 4 | * Created on: 2014-1-3 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef GROUPCHAT_H_ 9 | #define GROUPCHAT_H_ 10 | 11 | #include "impdu.h" 12 | 13 | typedef set group_member_t; 14 | typedef hash_map group_map_t; 15 | 16 | class CMsgConn; 17 | 18 | class CGroupChat 19 | { 20 | public: 21 | virtual ~CGroupChat() {} 22 | 23 | static CGroupChat* GetInstance(); 24 | 25 | void HandleClientGroupListRequest(CImPduClientGroupListRequest* pPdu, CMsgConn* pFromConn); 26 | void HandleGroupListResponse(CImPduGroupListResponse* pPdu); 27 | 28 | void HandleClientGroupUserListRequest(CImPduClientGroupUserListRequest* pPdu, CMsgConn* pFromConn); 29 | void HandleGroupUserListResponse(CImPduGroupUserListResponse* pPdu); 30 | 31 | void HandleClientGroupMessage(CImPduClientMsgData* pPdu, CMsgConn* pFromConn); 32 | void HandleGroupMessage(CImPduMsgData* pPdu); 33 | 34 | void HandleClientGroupUnreadMsgCntRequest(CImPduClientGroupUnreadMsgCntRequest* pPdu, CMsgConn* pFromConn); 35 | void HandleGroupUnreadMsgCntResponse(CImPduGroupUnreadMsgCntResponse* pPdu); 36 | 37 | void HandleClientGroupUnreadMsgRequest(CImPduClientGroupUnreadMsgRequest* pPdu, CMsgConn* pFromConn); 38 | void HandleClientGroupHistoryMsgRequest(CImPduClientGroupHistoryMsgRequest* pPdu, CMsgConn* pFromConn); 39 | void HandleGroupMsgListResponse(CImPduGroupMsgListResponse* pPdu); 40 | 41 | void HandleClientGroupMsgReadAck(CImPduClientGroupMsgReadAck* pPdu, CMsgConn* pFromConn); 42 | 43 | void HandleClientGroupCreateTmpGroupRequest(CImPduClientGroupCreateTmpGroupRequest* pPdu, CMsgConn* pFromConn); 44 | void HandleGroupCreateTmpGroupResponse(CImPduGroupCreateTmpGroupResponse* pPdu); 45 | void HandleGroupCreateTmpGroupBroadcast(CImPduGroupCreateTmpGroupResponse* pPdu); 46 | void HandleClientGroupChangeMemberRequest(CImPduClientGroupChangeMemberRequest* pPdu, CMsgConn* pFromConn); 47 | void HandleGroupChangeMemberResponse(CImPduGroupChangeMemberResponse* pPdu); 48 | void HandleGroupChangeMemberBroadcast(CImPduGroupChangeMemberResponse* pPdu); 49 | void HandleGroupCreateNormalGroupNotify(CImPduGroupCreateNormalGroupNotify* pdu); 50 | void HandleGroupChangeMemberNotify(CImPduGroupChangeMemberNotify* pdu); 51 | void HandleGroupCreateNormalGroupNotify(uint32_t group_id, const char* group_name, 52 | const char* group_avatar, uint32_t user_cnt, uint32_t* user_list); 53 | void HandleGroupChangeMemberNotify(uint32_t group_id, uint32_t user_cnt, uint32_t* user_list); 54 | 55 | private: 56 | CGroupChat() {} // for singleton; 57 | 58 | void _UpdateGroupMap(uint32_t group_id, list* user_list); 59 | void _UpdateGroupMap(uint32_t group_id, uint32_t user_cnt, uint32_t* user_list); 60 | group_member_t* _GetGroupMember(uint32_t group_id); 61 | void _JoinGroup(uint32_t group_id, uint32_t user_cnt, uint32_t* user_list); 62 | void _QuitGroup(uint32_t group_id, uint32_t user_cnt, uint32_t* user_list); 63 | void _SendPduToUser(CImPdu* pPdu, uint32_t user_id); 64 | private: 65 | 66 | static CGroupChat* s_group_chat_instance; 67 | 68 | group_map_t m_group_map; 69 | }; 70 | 71 | 72 | #endif /* GROUPCHAT_H_ */ 73 | -------------------------------------------------------------------------------- /src/msg_server/MsgConn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MsgConn.h 3 | * 4 | * Created on: 2013-7-5 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef MSGCONN_H_ 9 | #define MSGCONN_H_ 10 | 11 | #include "imconn.h" 12 | 13 | #define KICK_FROM_ROUTE_SERVER 1 14 | #define MAX_ONLINE_FRIEND_CNT 100 //通知好友状态通知的最多个数 15 | 16 | typedef struct { 17 | uint32_t seq_no; 18 | uint32_t from_id; 19 | uint64_t timestamp; 20 | } msg_ack_t; 21 | 22 | class CMsgConn : public CImConn 23 | { 24 | public: 25 | CMsgConn(); 26 | virtual ~CMsgConn(); 27 | 28 | string GetUserName() { return m_user_name; } 29 | uint32_t GetUserId(); 30 | uint32_t GetHandle() { return m_handle; } 31 | uint16_t GetPduVersion() { return m_pdu_version; } 32 | uint32_t GetClientType() { return m_client_type; } 33 | uint32_t GetClientTypeFlag(); 34 | void SetToken(string token) { m_token = token; } 35 | string GetToken() { return m_token; } 36 | void SetOpen() { m_bOpen = true; } 37 | bool IsOpen() { return m_bOpen; } 38 | void SendUserStatusUpdate(uint32_t user_status); 39 | 40 | virtual void Close(bool kick_user = false); 41 | 42 | virtual void OnConnect(net_handle_t handle); 43 | virtual void OnClose(); 44 | virtual inline void OnTimer(uint64_t curr_tick); 45 | 46 | virtual void HandlePdu(CImPdu* pPdu); 47 | 48 | void AddToSendList(uint32_t seq_no, uint32_t from_id); 49 | void DelFromSendList(uint32_t seq_no, uint32_t from_id); 50 | void SendUserActionLog(uint32_t action_type); 51 | private: 52 | void _HandleLoginRequest(CImPduLoginRequest* pPdu); 53 | void _HandleBuddyListRequest(CImPduClientBuddyListRequest* pPdu); 54 | void _HandleClientMsgData(CImPduClientMsgData* pPdu); 55 | void _HandleClientMsgDataAck(CImPduClientMsgDataAck* pPdu); 56 | void _HandleClientTimeRequest(CImPduClientTimeRequest* pPdu); 57 | void _HandleClientUnreadMsgCntRequest(CImPduClientUnreadMsgCntRequest* pPdu); 58 | void _HandleClientUnreadMsgRequest(CImPduClientUnreadMsgRequest* pPdu); 59 | void _HandleClientHistoryMsgRequest(CImPduClientHistoryMsgRequest* pPdu); 60 | void _HandleClientMsgReadAck(CImPduClientMsgReadAck* pPdu); 61 | void _HandleClientP2PCmdMsg(CImPduClientP2PCmdMsg* pPdu); 62 | void _HandleClientUserInfoRequest(CImPduClientUserInfoRequest* pPdu); 63 | void _HandleClientDBQueryRequest(CImPduClientDBQueryRequest* pPdu); 64 | 65 | void _HandleClientServiceSetting(CImPduClientServiceSetting* pPdu); 66 | void _HandleClientUserStatusRequest(CImPduClientUserStatusRequest* pPdu); 67 | void _HandleClientUsersStatusRequest(CImPduClientUsersStatusRequest* pPdu); 68 | 69 | void _HandleClientRemoveSessionRequest(CImPduClientRemoveSessionRequest* pPdu); 70 | void _HandleClientAllUserRequest(CImPduClientAllUserRequest* pPdu); 71 | 72 | void _HandleClientDepartmentRequest(CImPduClientDepartmentRequest* pPdu); 73 | private: 74 | string m_user_name; 75 | string m_token; 76 | bool m_bOpen; // only DB validate passed will be set to true; 77 | uint64_t m_login_time; 78 | 79 | uint32_t m_last_seq_no; 80 | 81 | uint16_t m_pdu_version; 82 | 83 | string m_client_version; // e.g MAC/2.2, or WIN/2.2 84 | 85 | list m_send_msg_list; 86 | 87 | uint32_t m_msg_cnt_per_sec; 88 | 89 | uint32_t m_client_type; //客户端登录方式 90 | }; 91 | 92 | void init_msg_conn(); 93 | 94 | #endif /* MSGCONN_H_ */ 95 | -------------------------------------------------------------------------------- /src/msfs/include/common/util.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTIL_H__ 2 | #define __UTIL_H__ 3 | 4 | #define _CRT_SECURE_NO_DEPRECATE // remove warning C4996, 5 | 6 | #include "ostype.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #ifdef _WIN32 13 | #define snprintf sprintf_s 14 | #else 15 | #include 16 | #include 17 | #include 18 | #include 19 | #endif 20 | 21 | #ifdef _WIN32 22 | #include 23 | using namespace stdext; 24 | #else 25 | #include 26 | using namespace __gnu_cxx; 27 | #endif 28 | 29 | using namespace std; 30 | 31 | #define MAX_LOG_FILE_SIZE 0x4000000 // 64MB 32 | #define NOTUSED_ARG(v) ((void)v) // used this to remove warning C4100, unreferenced parameter 33 | 34 | class CThread 35 | { 36 | public: 37 | CThread(); 38 | virtual ~CThread(); 39 | 40 | #ifdef _WIN32 41 | static DWORD WINAPI StartRoutine(LPVOID lpParameter); 42 | #else 43 | static void* StartRoutine(void* arg); 44 | #endif 45 | 46 | virtual void StartThread(void); 47 | virtual void OnThreadRun(void) = 0; 48 | protected: 49 | #ifdef _WIN32 50 | DWORD m_thread_id; 51 | #else 52 | pthread_t m_thread_id; 53 | #endif 54 | }; 55 | 56 | class CEventThread: public CThread 57 | { 58 | public: 59 | CEventThread(); 60 | virtual ~CEventThread(); 61 | 62 | virtual void OnThreadTick(void) = 0; 63 | virtual void OnThreadRun(void); 64 | virtual void StartThread(); 65 | virtual void StopThread(); 66 | bool IsRunning() 67 | { 68 | return m_bRunning; 69 | } 70 | private: 71 | bool m_bRunning; 72 | }; 73 | 74 | class CThreadLock 75 | { 76 | public: 77 | CThreadLock(); 78 | ~CThreadLock(); 79 | void Lock(void); 80 | void Unlock(void); 81 | private: 82 | #ifdef _WIN32 83 | CRITICAL_SECTION m_critical_section; 84 | #else 85 | pthread_mutex_t m_mutex; 86 | pthread_mutexattr_t m_mutexattr; 87 | #endif 88 | }; 89 | 90 | class CFuncLock 91 | { 92 | public: 93 | CFuncLock(CThreadLock* lock) 94 | { 95 | m_lock = lock; 96 | if (m_lock) 97 | m_lock->Lock(); 98 | } 99 | 100 | ~CFuncLock() 101 | { 102 | if (m_lock) 103 | m_lock->Unlock(); 104 | } 105 | private: 106 | CThreadLock* m_lock; 107 | }; 108 | 109 | class CRefObject 110 | { 111 | public: 112 | CRefObject(); 113 | virtual ~CRefObject(); 114 | 115 | void SetLock(CThreadLock* lock) 116 | { 117 | m_lock = lock; 118 | } 119 | void AddRef(); 120 | void ReleaseRef(); 121 | private: 122 | int m_refCount; 123 | CThreadLock* m_lock; 124 | }; 125 | 126 | void log(const char* fmt, ...); 127 | 128 | uint64_t get_tick_count(); 129 | void util_sleep(uint32_t millisecond); 130 | 131 | class CStrExplode 132 | { 133 | public: 134 | CStrExplode(char* str, char seperator); 135 | virtual ~CStrExplode(); 136 | 137 | uint32_t GetItemCnt() 138 | { 139 | return m_item_cnt; 140 | } 141 | char* GetItem(uint32_t idx) 142 | { 143 | return m_item_list[idx]; 144 | } 145 | private: 146 | uint32_t m_item_cnt; 147 | char** m_item_list; 148 | }; 149 | 150 | #include 151 | 152 | int64_t get_file_size(const char *path); 153 | const char* memfind(const char *src_str,size_t src_len, const char *sub_str, size_t sub_len, bool flag = true); 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /src/msg_server/ImUser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ImUser.h 3 | * 4 | * Created on: 2014年4月16日 5 | * Author: ziteng 6 | */ 7 | 8 | #ifndef IMUSER_H_ 9 | #define IMUSER_H_ 10 | 11 | #include "imconn.h" 12 | 13 | #define MAX_ONLINE_FRIEND_CNT 100 //通知好友状态通知的最多个数 14 | 15 | class CMsgConn; 16 | 17 | class CImUser 18 | { 19 | public: 20 | CImUser(string user_name); 21 | ~CImUser(); 22 | 23 | uint32_t GetUserId() { return m_user_id; } 24 | string GetUserName() { return m_name; } 25 | bool IsValidate() { return m_bValidate; } 26 | void SetValidated() { m_bValidate = true; } 27 | uint32_t GetIMOnlineStatus() { return m_online_status; } 28 | 29 | void AddOnlineFriend(uint32_t friend_id) { 30 | if (m_online_friend_set.size() < MAX_ONLINE_FRIEND_CNT) 31 | m_online_friend_set.insert(friend_id); 32 | } 33 | 34 | void RemoveOnlineFriend(uint32_t friend_id) { 35 | m_online_friend_set.erase(friend_id); 36 | } 37 | 38 | bool IsMsgConnEmpty() { return m_conn_map.empty(); } 39 | void AddMsgConn(string token, CMsgConn* pMsgConn) { m_conn_map[token] = pMsgConn; } 40 | void DelMsgConn(string token) { m_conn_map.erase(token); } 41 | CMsgConn* GetMsgConn(string token); 42 | CMsgConn* GetMsgConnByHandle(uint32_t handle); 43 | void ValidateMsgConn(string token, CMsgConn*); 44 | 45 | void AddUnValidateMsgConn(CMsgConn* pMsgConn) { m_unvalidate_conn_set.insert(pMsgConn); } 46 | void DelUnValidateMsgConn(CMsgConn* pMsgConn) { m_unvalidate_conn_set.erase(pMsgConn); } 47 | CMsgConn* GetUnValidateMsgConn(uint32_t handle); 48 | 49 | 50 | user_conn_t GetUserConn(); 51 | void SetIMOnlineStatus(uint32_t status) { m_online_status = status; } 52 | void SetUser(user_info_t* user); 53 | void BroadcastPdu(CImPdu* pPdu, CMsgConn* pFromConn = NULL); 54 | void BroadcastClientMsgData(CImPduClientMsgData* pPdu, CMsgConn* pFromConn, uint32_t from_id); 55 | void BroadcastData(void* buff, uint32_t len, CMsgConn* pFromConn = NULL); 56 | 57 | void SendStatusChangeToFriend(uint32_t online_status); 58 | 59 | void HandleKickUser(CMsgConn* pConn); 60 | 61 | bool KickOutSameClientType(uint32_t client_type, CMsgConn* pFromConn = NULL); 62 | 63 | uint32_t GetClientTypeFlag(); 64 | private: 65 | uint32_t m_user_id; 66 | string m_name; 67 | string m_user_id_url; 68 | bool m_user_updated; 69 | uint32_t m_online_status; // 1-online, 2-off-line, 3-leave 70 | 71 | bool m_bValidate; 72 | 73 | set m_online_friend_set; 74 | map m_conn_map; 75 | set m_unvalidate_conn_set; 76 | //map 77 | }; 78 | 79 | typedef map ImUserMap_t; 80 | typedef map ImUserMapByName_t; 81 | 82 | class CImUserManager 83 | { 84 | public: 85 | CImUserManager() {} 86 | ~CImUserManager(); 87 | 88 | static CImUserManager* GetInstance(); 89 | CImUser* GetImUserById(uint32_t user_id); 90 | CImUser* GetImUserByName(string user_name); 91 | 92 | CMsgConn* GetMsgConnByHandle(uint32_t user_id, uint32_t handle); 93 | bool AddImUserByName(string user_name, CImUser* pUser); 94 | void RemoveImUserByName(string user_name); 95 | 96 | bool AddImUserById(uint32_t user_id, CImUser* pUser); 97 | void RemoveImUserById(uint32_t user_id); 98 | 99 | void RemoveImUser(CImUser* pUser); 100 | 101 | void RemoveAll(); 102 | void GetOnlineUserInfo(list* online_user_info); 103 | void GetUserConnCnt(list* user_conn_list, uint32_t& total_conn_cnt); 104 | 105 | void BroadcastPdu(CImPdu* pdu); 106 | private: 107 | ImUserMap_t m_im_user_map; 108 | ImUserMapByName_t m_im_user_map_by_name; 109 | }; 110 | 111 | #endif /* IMUSER_H_ */ 112 | -------------------------------------------------------------------------------- /src/base/UtilPdu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * UtilPdu.h 3 | * 4 | * Created on: 2013-8-27 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #ifndef UTILPDU_H_ 9 | #define UTILPDU_H_ 10 | 11 | #include "ostype.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | #ifdef WIN32 19 | #ifdef BUILD_PDU 20 | #define DLL_MODIFIER __declspec(dllexport) 21 | #else 22 | #define DLL_MODIFIER __declspec(dllimport) 23 | #endif 24 | #else 25 | #define DLL_MODIFIER 26 | #endif 27 | 28 | class DLL_MODIFIER CSimpleBuffer 29 | { 30 | public: 31 | CSimpleBuffer(); 32 | ~CSimpleBuffer(); 33 | uchar_t* GetBuffer() { return m_buffer; } 34 | uint32_t GetAllocSize() { return m_alloc_size; } 35 | uint32_t GetWriteOffset() { return m_write_offset; } 36 | void IncWriteOffset(uint32_t len) { m_write_offset += len; } 37 | 38 | void Extend(uint32_t len); 39 | uint32_t Write(void* buf, uint32_t len); 40 | uint32_t Read(void* buf, uint32_t len); 41 | private: 42 | uchar_t* m_buffer; 43 | uint32_t m_alloc_size; 44 | uint32_t m_write_offset; 45 | }; 46 | 47 | class CByteStream 48 | { 49 | public: 50 | CByteStream(uchar_t* buf, uint32_t len); 51 | CByteStream(CSimpleBuffer* pSimpBuf, uint32_t pos); 52 | ~CByteStream() {} 53 | 54 | unsigned char* GetBuf() { return m_pSimpBuf ? m_pSimpBuf->GetBuffer() : m_pBuf; } 55 | uint32_t GetPos() { return m_pos; } 56 | uint32_t GetLen() { return m_len; } 57 | void Skip(uint32_t len) { m_pos += len; } 58 | 59 | static int16_t ReadInt16(uchar_t* buf); 60 | static uint16_t ReadUint16(uchar_t* buf); 61 | static int32_t ReadInt32(uchar_t* buf); 62 | static uint32_t ReadUint32(uchar_t* buf); 63 | static void WriteInt16(uchar_t* buf, int16_t data); 64 | static void WriteUint16(uchar_t* buf, uint16_t data); 65 | static void WriteInt32(uchar_t* buf, int32_t data); 66 | static void WriteUint32(uchar_t* buf, uint32_t data); 67 | 68 | void operator << (int8_t data); 69 | void operator << (uint8_t data); 70 | void operator << (int16_t data); 71 | void operator << (uint16_t data); 72 | void operator << (int32_t data); 73 | void operator << (uint32_t data); 74 | 75 | void operator >> (int8_t& data); 76 | void operator >> (uint8_t& data); 77 | void operator >> (int16_t& data); 78 | void operator >> (uint16_t& data); 79 | void operator >> (int32_t& data); 80 | void operator >> (uint32_t& data); 81 | 82 | void WriteString(const char* str); 83 | void WriteString(const char* str, uint32_t len); 84 | char* ReadString(uint32_t& len); 85 | 86 | void WriteData(uchar_t* data, uint32_t len); 87 | uchar_t* ReadData(uint32_t& len); 88 | private: 89 | void _WriteByte(void* buf, uint32_t len); 90 | void _ReadByte(void* buf, uint32_t len); 91 | private: 92 | CSimpleBuffer* m_pSimpBuf; 93 | uchar_t* m_pBuf; 94 | uint32_t m_len; 95 | uint32_t m_pos; 96 | }; 97 | 98 | #define ERROR_CODE_PARSE_FAILED 1 99 | #define ERROR_CODE_WRONG_SERVICE_ID 2 100 | #define ERROR_CODE_WRONG_COMMAND_ID 3 101 | #define ERROR_CODE_ALLOC_FAILED 4 102 | 103 | class CPduException { 104 | public: 105 | CPduException(uint32_t module_id, uint32_t command_id, uint32_t error_code, const char* error_msg) 106 | { 107 | m_module_id = module_id; 108 | m_command_id = command_id; 109 | m_error_code = error_code; 110 | m_error_msg = error_msg; 111 | } 112 | 113 | virtual ~CPduException() {} 114 | 115 | uint32_t GetModuleId() { return m_module_id; } 116 | uint32_t GetCommandId() { return m_command_id; } 117 | uint32_t GetErrorCode() { return m_error_code; } 118 | char* GetErrorMsg() { return (char*)m_error_msg.c_str(); } 119 | private: 120 | uint32_t m_module_id; 121 | uint32_t m_command_id; 122 | uint32_t m_error_code; 123 | string m_error_msg; 124 | }; 125 | 126 | char* idtourl(uint32_t id); 127 | uint32_t urltoid(const char* url); 128 | 129 | 130 | #endif /* UTILPDU_H_ */ 131 | -------------------------------------------------------------------------------- /src/msfs/include/storage/FileManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Multimedia Small File Storage System 3 | * FileManager Singleton to manager store or download file 4 | * author potian@mogujie.com 5 | */ 6 | 7 | #ifndef _FILEMANAGER_H_ 8 | #define _FILEMANAGER_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "FileLin.h" 20 | #include "CriticalSection.h" 21 | 22 | using namespace std; 23 | 24 | namespace msfs { 25 | class CriticalSection; 26 | class FileManager { 27 | private: 28 | FileManager() {} 29 | FileManager(const char *host, const char *disk, 30 | int totFiles, int filesPerDir) { 31 | m_host = new char[strlen(host) + 1]; 32 | m_disk = new char[strlen(disk) + 1]; 33 | m_host[strlen(host)] = '\0'; 34 | m_disk[strlen(disk)] = '\0'; 35 | strncpy(m_host, host, strlen(host)); 36 | strncpy(m_disk, disk, strlen(disk)); 37 | m_totFiles = totFiles; 38 | m_filesPerDir = filesPerDir; 39 | m_map.clear(); 40 | } 41 | ~FileManager() { 42 | if (m_host) 43 | delete [] m_host; 44 | m_host = NULL; 45 | if (m_disk) 46 | delete [] m_disk; 47 | m_disk = NULL; 48 | EntryMap::iterator it = m_map.begin(); 49 | while (it != m_map.end()) { 50 | delete it->second; 51 | m_map.erase(it++); 52 | } 53 | } 54 | 55 | FileManager(const FileManager &); 56 | FileManager operator=(const FileManager &); 57 | 58 | public: 59 | static FileManager* getInstance(const char *host, const char *disk, int totFiles, int filesPerDir) { 60 | return (m_instance) ? m_instance : \ 61 | (new FileManager(host, disk, totFiles, filesPerDir)); 62 | } 63 | 64 | static void destroyInstance() { 65 | if (m_instance) 66 | delete m_instance; 67 | m_instance = NULL; 68 | } 69 | 70 | int initDir(); 71 | u64 getFileCntCurr() {return m_totFiles;} 72 | int getFirstDir() {return (m_totFiles / (m_filesPerDir)) / (FIRST_DIR_MAX);} 73 | int getSecondDir() {return (m_totFiles % (m_filesPerDir * FIRST_DIR_MAX) ) / m_filesPerDir;} 74 | 75 | string createFileRelatePath(); 76 | int uploadFile(const char *type, const void *content, u32 size, char *url, char *ext = NULL); 77 | int downloadFileByUrl(char *urlEn, void *buf, u32 *size); 78 | int getRelatePathByUrl(const string &url, string &path); 79 | int getAbsPathByUrl(const string &url, string &path); 80 | 81 | protected: 82 | struct Entry { 83 | time_t m_lastAccess; 84 | size_t m_fileSize; 85 | u8* m_fileContent; 86 | Entry() { 87 | m_lastAccess = 0; 88 | m_fileSize = 0; 89 | m_fileContent = NULL; 90 | } 91 | ~Entry() { 92 | if (m_fileContent) 93 | delete [] m_fileContent; 94 | m_fileContent = NULL; 95 | } 96 | }; 97 | typedef std::map EntryMap; 98 | int insertEntry(const std::string& url, size_t filesize, 99 | const void* content); 100 | Entry* getEntry(const std::string& url) const { 101 | return const_cast(this)->getOrCreateEntry(url,false); 102 | } 103 | Entry* getOrCreateEntry(const std::string& url, bool create); 104 | void releaseFileCache(const std::string& url); 105 | void updateMapCache(); 106 | 107 | private: 108 | char *m_host; //msfs server ip or hostname 109 | char *m_disk; //storage directory of media files 110 | u64 m_totFiles; //total files has storaged 111 | CriticalSection m_filesCs; 112 | 113 | int m_filesPerDir; //mas file nums per dir eg. xxx/xxx 114 | static const u32 MAX_FILE_SIZE_PER_FILE = 5 * 1024 * 1024; 115 | static const int FIRST_DIR_MAX =255; 116 | static const int SECOND_DIR_MAX =255; 117 | static FileManager * m_instance; 118 | EntryMap m_map; 119 | static const u64 MAX_FILE_IN_MAP = 10000; 120 | CriticalSection m_cs; 121 | }; 122 | 123 | } 124 | 125 | #endif 126 | 127 | -------------------------------------------------------------------------------- /src/msfs/common/netlib.cpp: -------------------------------------------------------------------------------- 1 | #include "netlib.h" 2 | #include "BaseSocket.h" 3 | #include "EventDispatch.h" 4 | 5 | int netlib_init() 6 | { 7 | int ret = NETLIB_OK; 8 | #ifdef _WIN32 9 | WSADATA wsaData; 10 | WORD wReqest = MAKEWORD(1, 1); 11 | if (WSAStartup(wReqest, &wsaData) != 0) 12 | { 13 | ret = NETLIB_ERROR; 14 | } 15 | #endif 16 | 17 | return ret; 18 | } 19 | 20 | int netlib_destroy() 21 | { 22 | int ret = NETLIB_OK; 23 | #ifdef _WIN32 24 | if (WSACleanup() != 0) 25 | { 26 | ret = NETLIB_ERROR; 27 | } 28 | #endif 29 | 30 | return ret; 31 | } 32 | 33 | int netlib_listen( 34 | const char* server_ip, 35 | uint16_t port, 36 | callback_t callback, 37 | void* callback_data) 38 | { 39 | CBaseSocket* pSocket = new CBaseSocket(); 40 | if (!pSocket) 41 | return NETLIB_ERROR; 42 | 43 | int ret = pSocket->Listen(server_ip, port, callback, callback_data); 44 | if (ret == NETLIB_ERROR) 45 | delete pSocket; 46 | return ret; 47 | } 48 | 49 | net_handle_t netlib_connect( 50 | const char* server_ip, 51 | uint16_t port, 52 | callback_t callback, 53 | void* callback_data) 54 | { 55 | CBaseSocket* pSocket = new CBaseSocket(); 56 | if (!pSocket) 57 | return NETLIB_INVALID_HANDLE; 58 | 59 | net_handle_t handle = pSocket->Connect(server_ip, port, callback, callback_data); 60 | if (handle == NETLIB_INVALID_HANDLE) 61 | delete pSocket; 62 | return handle; 63 | } 64 | 65 | int netlib_send(net_handle_t handle, void* buf, int len) 66 | { 67 | CBaseSocket* pSocket = FindBaseSocket(handle); 68 | if (!pSocket) 69 | return NETLIB_ERROR; 70 | 71 | int ret = pSocket->Send(buf, len); 72 | pSocket->ReleaseRef(); 73 | return ret; 74 | } 75 | 76 | int netlib_recv(net_handle_t handle, void* buf, int len) 77 | { 78 | CBaseSocket* pSocket = FindBaseSocket(handle); 79 | if (!pSocket) 80 | return NETLIB_ERROR; 81 | 82 | int ret = pSocket->Recv(buf, len); 83 | pSocket->ReleaseRef(); 84 | return ret; 85 | } 86 | 87 | int netlib_close(net_handle_t handle) 88 | { 89 | CBaseSocket* pSocket = FindBaseSocket(handle); 90 | if (!pSocket) 91 | return NETLIB_ERROR; 92 | 93 | int ret = pSocket->Close(); 94 | pSocket->ReleaseRef(); 95 | return ret; 96 | } 97 | 98 | int netlib_option(net_handle_t handle, int opt, void* optval) 99 | { 100 | CBaseSocket* pSocket = FindBaseSocket(handle); 101 | if (!pSocket) 102 | return NETLIB_ERROR; 103 | 104 | if ((opt >= NETLIB_OPT_GET_REMOTE_IP) && !optval) 105 | return NETLIB_ERROR; 106 | 107 | switch (opt) 108 | { 109 | case NETLIB_OPT_SET_CALLBACK: 110 | pSocket->SetCallback((callback_t)optval); 111 | break; 112 | case NETLIB_OPT_SET_CALLBACK_DATA: 113 | pSocket->SetCallbackData(optval); 114 | break; 115 | case NETLIB_OPT_GET_REMOTE_IP: 116 | *(string*)optval = pSocket->GetRemoteIP(); 117 | break; 118 | case NETLIB_OPT_GET_REMOTE_PORT: 119 | *(uint16_t*)optval = pSocket->GetRemotePort(); 120 | break; 121 | case NETLIB_OPT_GET_LOCAL_IP: 122 | *(string*)optval = pSocket->GetLocalIP(); 123 | break; 124 | case NETLIB_OPT_GET_LOCAL_PORT: 125 | *(uint16_t*)optval = pSocket->GetLocalPort(); 126 | } 127 | 128 | pSocket->ReleaseRef(); 129 | return NETLIB_OK; 130 | } 131 | 132 | int netlib_register_timer(callback_t callback, void* user_data, uint64_t interval) 133 | { 134 | CEventDispatch::Instance()->AddTimer(callback, user_data, interval); 135 | return 0; 136 | } 137 | 138 | int netlib_delete_timer(callback_t callback, void* user_data) 139 | { 140 | CEventDispatch::Instance()->RemoveTimer(callback, user_data); 141 | return 0; 142 | } 143 | 144 | int netlib_add_loop(callback_t callback, void* user_data) 145 | { 146 | CEventDispatch::Instance()->AddLoop(callback, user_data); 147 | return 0; 148 | } 149 | 150 | void netlib_eventloop(uint32_t wait_timeout) 151 | { 152 | CEventDispatch::Instance()->StartDispatch(wait_timeout); 153 | } 154 | -------------------------------------------------------------------------------- /src/base/netlib.cpp: -------------------------------------------------------------------------------- 1 | #include "netlib.h" 2 | #include "BaseSocket.h" 3 | #include "EventDispatch.h" 4 | 5 | int netlib_init() 6 | { 7 | int ret = NETLIB_OK; 8 | #ifdef _WIN32 9 | WSADATA wsaData; 10 | WORD wReqest = MAKEWORD(1, 1); 11 | if (WSAStartup(wReqest, &wsaData) != 0) 12 | { 13 | ret = NETLIB_ERROR; 14 | } 15 | #endif 16 | 17 | return ret; 18 | } 19 | 20 | int netlib_destroy() 21 | { 22 | int ret = NETLIB_OK; 23 | #ifdef _WIN32 24 | if (WSACleanup() != 0) 25 | { 26 | ret = NETLIB_ERROR; 27 | } 28 | #endif 29 | 30 | return ret; 31 | } 32 | 33 | int netlib_listen( 34 | const char* server_ip, 35 | uint16_t port, 36 | callback_t callback, 37 | void* callback_data) 38 | { 39 | CBaseSocket* pSocket = new CBaseSocket(); 40 | if (!pSocket) 41 | return NETLIB_ERROR; 42 | 43 | int ret = pSocket->Listen(server_ip, port, callback, callback_data); 44 | if (ret == NETLIB_ERROR) 45 | delete pSocket; 46 | return ret; 47 | } 48 | 49 | net_handle_t netlib_connect( 50 | const char* server_ip, 51 | uint16_t port, 52 | callback_t callback, 53 | void* callback_data) 54 | { 55 | CBaseSocket* pSocket = new CBaseSocket(); 56 | if (!pSocket) 57 | return NETLIB_INVALID_HANDLE; 58 | 59 | net_handle_t handle = pSocket->Connect(server_ip, port, callback, callback_data); 60 | if (handle == NETLIB_INVALID_HANDLE) 61 | delete pSocket; 62 | return handle; 63 | } 64 | 65 | int netlib_send(net_handle_t handle, void* buf, int len) 66 | { 67 | CBaseSocket* pSocket = FindBaseSocket(handle); 68 | if (!pSocket) 69 | return NETLIB_ERROR; 70 | 71 | int ret = pSocket->Send(buf, len); 72 | pSocket->ReleaseRef(); 73 | return ret; 74 | } 75 | 76 | int netlib_recv(net_handle_t handle, void* buf, int len) 77 | { 78 | CBaseSocket* pSocket = FindBaseSocket(handle); 79 | if (!pSocket) 80 | return NETLIB_ERROR; 81 | 82 | int ret = pSocket->Recv(buf, len); 83 | pSocket->ReleaseRef(); 84 | return ret; 85 | } 86 | 87 | int netlib_close(net_handle_t handle) 88 | { 89 | CBaseSocket* pSocket = FindBaseSocket(handle); 90 | if (!pSocket) 91 | return NETLIB_ERROR; 92 | 93 | int ret = pSocket->Close(); 94 | pSocket->ReleaseRef(); 95 | return ret; 96 | } 97 | 98 | int netlib_option(net_handle_t handle, int opt, void* optval) 99 | { 100 | CBaseSocket* pSocket = FindBaseSocket(handle); 101 | if (!pSocket) 102 | return NETLIB_ERROR; 103 | 104 | if ((opt >= NETLIB_OPT_GET_REMOTE_IP) && !optval) 105 | return NETLIB_ERROR; 106 | 107 | switch (opt) 108 | { 109 | case NETLIB_OPT_SET_CALLBACK: 110 | pSocket->SetCallback((callback_t)optval); 111 | break; 112 | case NETLIB_OPT_SET_CALLBACK_DATA: 113 | pSocket->SetCallbackData(optval); 114 | break; 115 | case NETLIB_OPT_GET_REMOTE_IP: 116 | *(string*)optval = pSocket->GetRemoteIP(); 117 | break; 118 | case NETLIB_OPT_GET_REMOTE_PORT: 119 | *(uint16_t*)optval = pSocket->GetRemotePort(); 120 | break; 121 | case NETLIB_OPT_GET_LOCAL_IP: 122 | *(string*)optval = pSocket->GetLocalIP(); 123 | break; 124 | case NETLIB_OPT_GET_LOCAL_PORT: 125 | *(uint16_t*)optval = pSocket->GetLocalPort(); 126 | break; 127 | case NETLIB_OPT_SET_SEND_BUF_SIZE: 128 | pSocket->SetSendBufSize(*(uint32_t*)optval); 129 | break; 130 | case NETLIB_OPT_SET_RECV_BUF_SIZE: 131 | pSocket->SetRecvBufSize(*(uint32_t*)optval); 132 | break; 133 | } 134 | 135 | pSocket->ReleaseRef(); 136 | return NETLIB_OK; 137 | } 138 | 139 | int netlib_register_timer(callback_t callback, void* user_data, uint64_t interval) 140 | { 141 | CEventDispatch::Instance()->AddTimer(callback, user_data, interval); 142 | return 0; 143 | } 144 | 145 | int netlib_delete_timer(callback_t callback, void* user_data) 146 | { 147 | CEventDispatch::Instance()->RemoveTimer(callback, user_data); 148 | return 0; 149 | } 150 | 151 | void netlib_eventloop() 152 | { 153 | CEventDispatch::Instance()->StartDispatch(); 154 | } 155 | -------------------------------------------------------------------------------- /src/test_client/pressure_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * pressure_test.cpp 3 | * 4 | * Created on: 2013-7-11 5 | * Author: ziteng@mogujie.com 6 | */ 7 | #include "ClientConn.h" 8 | #include "netlib.h" 9 | #include "TokenValidator.h" 10 | #include 11 | 12 | #define MAX_BUF_SIZE 4096 13 | #define CONN_NUM_PER_TIMER 10 14 | #define MAX_ID_RANGE 1000 15 | 16 | #define AUTH_ENCRYPT_KEY "Mgj!@#123" 17 | 18 | uchar_t g_tmp_buf[MAX_BUF_SIZE]; 19 | char g_line_buf[256]; 20 | char g_curl_cmd_buf[256]; 21 | char g_test_uuid[256]; 22 | 23 | string g_server_ip; 24 | uint16_t g_server_port; 25 | uint32_t g_start_user_id; 26 | uint32_t g_stop_user_id; 27 | uint32_t g_request_id = 0; 28 | uint32_t g_pkt_per_second; 29 | uint32_t g_pkt_size; 30 | uint32_t g_current_user_id; 31 | 32 | uint32_t g_msg_user_id; 33 | 34 | void pressure_test_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 35 | { 36 | char token[64]; 37 | for (uint32_t i = 0; i < CONN_NUM_PER_TIMER && g_current_user_id <= g_stop_user_id; i++, g_current_user_id++) { 38 | genToken(g_current_user_id, 0, token); 39 | ClientConn* pConn = new ClientConn(); 40 | pConn->Connect(g_server_ip.c_str(), g_server_port, "", "", CONN_TYPE_LOGIN_SERV); 41 | printf("connnect %s:%d, user_id=%u, token=%s\n", g_server_ip.c_str(), g_server_port, 42 | g_current_user_id, token); 43 | } 44 | 45 | if (g_current_user_id >= g_stop_user_id) { 46 | for (uint32_t i = 0; i < CONN_NUM_PER_TIMER && g_msg_user_id <= g_stop_user_id; i++, g_msg_user_id++) { 47 | string from_id_url = idtourl(g_msg_user_id); 48 | string to_id_url = idtourl(24361096); 49 | 50 | ClientConn* pConn = get_client_conn(g_msg_user_id); 51 | if (pConn && pConn->IsOpen()) { 52 | CImPduClientMsgData pdu(0, from_id_url.c_str(), to_id_url.c_str(), get_tick_count(), 1, 0, 53 | 4, (uchar_t*)"test", 0, NULL); 54 | pConn->SendPdu(&pdu); 55 | printf("msg from %u->24361096\n", g_msg_user_id); 56 | } 57 | } 58 | } 59 | 60 | /*for (uint32_t i = 0; i < g_pkt_per_second / 10; i++) { 61 | // from_user_id and to_user_id is different by 1 or 2, this guarantee the send and receiver in the same PC 62 | // so we can calculate the time takes for the message packet from sender to receiver 63 | uint32_t from_user_id = rand() % (g_stop_user_id - g_start_user_id) + g_start_user_id; 64 | uint32_t to_user_id = 0; 65 | do { 66 | to_user_id = rand() % (g_stop_user_id - g_start_user_id) + g_start_user_id; 67 | } while (to_user_id == from_user_id); 68 | 69 | string from_id_url = idtourl(from_user_id); 70 | string to_id_url = idtourl(to_user_id); 71 | 72 | ClientConn* pConn = get_client_conn(from_user_id); 73 | if (pConn && pConn->IsOpen()) { 74 | CImPduClientMsgData pdu(0, from_id_url.c_str(), to_id_url.c_str(), get_tick_count(), 1, 0, 75 | g_pkt_size, g_tmp_buf, 0, NULL); 76 | pConn->SendPdu(&pdu); 77 | } 78 | }*/ 79 | } 80 | 81 | int main(int argc, char* argv[]) 82 | { 83 | if (argc != 7) { 84 | printf("Usage: ./pressure_test server_ip server_port start_user_id stop_user_id pkt_per_second pkt_size\n"); 85 | return -1; 86 | } 87 | 88 | for (int i = 0; i < MAX_BUF_SIZE; i += 8) { 89 | memcpy(g_tmp_buf + i, "test_msg", 8); 90 | } 91 | 92 | g_server_ip = argv[1]; 93 | g_server_port = (uint16_t)atoi(argv[2]); 94 | g_start_user_id = (uint32_t)atoi(argv[3]); 95 | g_stop_user_id = (uint32_t)atoi(argv[4]); 96 | g_pkt_per_second = (uint32_t)atoi(argv[5]); 97 | g_pkt_size = (uint32_t)atoi(argv[6]); 98 | 99 | g_current_user_id = g_start_user_id; 100 | g_msg_user_id = g_start_user_id; 101 | 102 | if (g_pkt_size > MAX_BUF_SIZE) { 103 | printf("packet size too big\n"); 104 | return -1; 105 | } 106 | 107 | signal(SIGPIPE, SIG_IGN); 108 | 109 | srand(time(NULL)); 110 | 111 | int ret = netlib_init(); 112 | 113 | if (ret == NETLIB_ERROR) 114 | return ret; 115 | 116 | init_client_conn(false); 117 | 118 | netlib_register_timer(pressure_test_callback, NULL, 100); 119 | 120 | netlib_eventloop(); 121 | 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /src/msfs/common/ConfigFileReader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ConfigFileReader.cpp 3 | * 4 | * Created on: 2013-7-2 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "ConfigFileReader.h" 9 | 10 | CConfigFileReader::CConfigFileReader(const char* filename) 11 | { 12 | m_config_map = new map; 13 | _LoadFile(filename); 14 | } 15 | 16 | CConfigFileReader::~CConfigFileReader() 17 | { 18 | delete m_config_map; 19 | } 20 | 21 | char* CConfigFileReader::GetConfigName(const char* name) 22 | { 23 | if (!m_load_ok) 24 | return NULL; 25 | 26 | char* value = NULL; 27 | map::iterator it = m_config_map->begin(); 28 | for (; it != m_config_map->end(); it++) 29 | { 30 | const char* key = it->first.c_str(); 31 | if (strcmp(key, name) == 0) 32 | { 33 | value = (char*) it->second.c_str(); 34 | break; 35 | } 36 | } 37 | 38 | return value; 39 | } 40 | 41 | int CConfigFileReader::SetConfigValue(const char* name, const char* value) 42 | { 43 | if(!m_load_ok) 44 | return -1; 45 | 46 | map::iterator it = m_config_map->find(name); 47 | if(it != m_config_map->end()) 48 | { 49 | it->second = value; 50 | } 51 | else 52 | { 53 | m_config_map->insert(make_pair(name, value)); 54 | } 55 | return _WriteFIle(); 56 | } 57 | void CConfigFileReader::_LoadFile(const char* filename) 58 | { 59 | m_config_file.clear(); 60 | m_config_file.append(filename); 61 | FILE* fp = fopen(filename, "r"); 62 | if (!fp) 63 | { 64 | log("can not open %s\n", filename); 65 | return; 66 | } 67 | 68 | char buf[256]; 69 | for (;;) 70 | { 71 | char* p = fgets(buf, 256, fp); 72 | if (!p) 73 | break; 74 | 75 | size_t len = strlen(buf); 76 | if (buf[len - 1] == '\n') 77 | buf[len - 1] = 0; // remove \n at the end 78 | 79 | char* ch = strchr(buf, '#'); // remove string start with # 80 | if (ch) 81 | *ch = 0; 82 | 83 | if (strlen(buf) == 0) 84 | continue; 85 | 86 | _ParseLine(buf); 87 | } 88 | 89 | fclose(fp); 90 | m_load_ok = true; 91 | } 92 | 93 | int CConfigFileReader::_WriteFIle(const char* filename) 94 | { 95 | FILE* fp = NULL; 96 | if(filename == NULL) 97 | { 98 | fp = fopen(m_config_file.c_str(), "w"); 99 | } 100 | else 101 | { 102 | fp = fopen(filename, "w"); 103 | } 104 | if(fp == NULL) 105 | { 106 | return -1; 107 | } 108 | 109 | char szPaire[128]; 110 | map::iterator it = m_config_map->begin(); 111 | for (; it != m_config_map->end(); it++) 112 | { 113 | memset(szPaire, 0, sizeof(szPaire)); 114 | snprintf(szPaire, sizeof(szPaire), "%s=%s\n", it->first.c_str(), it->second.c_str()); 115 | uint32_t ret = fwrite(szPaire, strlen(szPaire),1,fp); 116 | if(ret != 1) 117 | { 118 | fclose(fp); 119 | return -1; 120 | } 121 | } 122 | fclose(fp); 123 | return 0; 124 | } 125 | 126 | void CConfigFileReader::_ParseLine(char* line) 127 | { 128 | char* p = strchr(line, '='); 129 | if (p == NULL) 130 | return; 131 | 132 | *p = 0; 133 | char* key = _TrimSpace(line); 134 | char* value = _TrimSpace(p + 1); 135 | if (key && value) 136 | { 137 | m_config_map->insert(make_pair(key, value)); 138 | } 139 | } 140 | 141 | char* CConfigFileReader::_TrimSpace(char* name) 142 | { 143 | // remove starting space or tab 144 | char* start_pos = name; 145 | while ((*start_pos == ' ') || (*start_pos == '\t')) 146 | { 147 | start_pos++; 148 | } 149 | 150 | if (strlen(start_pos) == 0) 151 | return NULL; 152 | 153 | // remove ending space or tab 154 | char* end_pos = name + strlen(name) - 1; 155 | while ((*end_pos == ' ') || (*end_pos == '\t')) 156 | { 157 | *end_pos = 0; 158 | end_pos--; 159 | } 160 | 161 | int len = (int) (end_pos - start_pos) + 1; 162 | if (len <= 0) 163 | return NULL; 164 | 165 | return start_pos; 166 | } 167 | -------------------------------------------------------------------------------- /src/msg_server/LoginServConn.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * LoginServConn.cpp 3 | * 4 | * Created on: 2013-7-8 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | 9 | #include "LoginServConn.h" 10 | #include "MsgConn.h" 11 | #include "ImUser.h" 12 | 13 | static ConnMap_t g_login_server_conn_map; 14 | 15 | static serv_info_t* g_login_server_list; 16 | static uint32_t g_login_server_count; 17 | 18 | static string g_msg_server_ip_addr1; 19 | static string g_msg_server_ip_addr2; 20 | static uint16_t g_msg_server_port; 21 | static uint32_t g_max_conn_cnt; 22 | 23 | void login_server_conn_timer_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 24 | { 25 | ConnMap_t::iterator it_old; 26 | CLoginServConn* pConn = NULL; 27 | uint64_t cur_time = get_tick_count(); 28 | 29 | for (ConnMap_t::iterator it = g_login_server_conn_map.begin(); it != g_login_server_conn_map.end();) 30 | { 31 | it_old = it; 32 | it++; 33 | pConn = (CLoginServConn*)it_old->second; 34 | pConn->OnTimer(cur_time); 35 | } 36 | 37 | // reconnect LoginServer 38 | serv_check_reconnect(g_login_server_list, g_login_server_count); 39 | } 40 | 41 | void init_login_serv_conn(serv_info_t* server_list, uint32_t server_count, const char* msg_server_ip_addr1, 42 | const char* msg_server_ip_addr2, uint16_t msg_server_port, uint32_t max_conn_cnt) 43 | { 44 | g_login_server_list = server_list; 45 | g_login_server_count = server_count; 46 | 47 | serv_init(g_login_server_list, g_login_server_count); 48 | 49 | g_msg_server_ip_addr1 = msg_server_ip_addr1; 50 | g_msg_server_ip_addr2 = msg_server_ip_addr2; 51 | g_msg_server_port = msg_server_port; 52 | g_max_conn_cnt = max_conn_cnt; 53 | 54 | netlib_register_timer(login_server_conn_timer_callback, NULL, 1000); 55 | } 56 | 57 | // if there is one LoginServer available, return true 58 | bool is_login_server_available() 59 | { 60 | CLoginServConn* pConn = NULL; 61 | 62 | for (uint32_t i = 0; i < g_login_server_count; i++) { 63 | pConn = (CLoginServConn*)g_login_server_list[i].serv_conn; 64 | if (pConn && pConn->IsOpen()) { 65 | return true; 66 | } 67 | } 68 | 69 | return false; 70 | } 71 | 72 | void send_to_all_login_server(CImPdu* pPdu) 73 | { 74 | CLoginServConn* pConn = NULL; 75 | 76 | for (uint32_t i = 0; i < g_login_server_count; i++) { 77 | pConn = (CLoginServConn*)g_login_server_list[i].serv_conn; 78 | if (pConn && pConn->IsOpen()) { 79 | pConn->SendPdu(pPdu); 80 | } 81 | } 82 | } 83 | 84 | 85 | CLoginServConn::CLoginServConn() 86 | { 87 | m_bOpen = false; 88 | } 89 | 90 | CLoginServConn::~CLoginServConn() 91 | { 92 | 93 | } 94 | 95 | void CLoginServConn::Connect(const char* server_ip, uint16_t server_port, uint32_t serv_idx) 96 | { 97 | log("Connecting to LoginServer %s:%d\n", server_ip, server_port); 98 | 99 | m_serv_idx = serv_idx; 100 | m_handle = netlib_connect(server_ip, server_port, imconn_callback, (void*)&g_login_server_conn_map); 101 | 102 | if (m_handle != NETLIB_INVALID_HANDLE) { 103 | g_login_server_conn_map.insert(make_pair(m_handle, this)); 104 | } 105 | } 106 | 107 | void CLoginServConn::Close() 108 | { 109 | serv_reset(g_login_server_list, g_login_server_count, m_serv_idx); 110 | 111 | if (m_handle != NETLIB_INVALID_HANDLE) { 112 | netlib_close(m_handle); 113 | g_login_server_conn_map.erase(m_handle); 114 | } 115 | 116 | ReleaseRef(); 117 | } 118 | 119 | void CLoginServConn::OnConfirm() 120 | { 121 | log("connect to login server success\n"); 122 | m_bOpen = true; 123 | g_login_server_list[m_serv_idx].reconnect_cnt = MIN_RECONNECT_CNT / 2; 124 | 125 | uint32_t cur_conn_cnt = 0; 126 | list user_conn_list; 127 | CImUserManager::GetInstance()->GetUserConnCnt(&user_conn_list, cur_conn_cnt); 128 | char hostname[256] = {0}; 129 | gethostname(hostname, 256); 130 | CImPduMsgServInfo pdu(g_msg_server_ip_addr1.c_str(), g_msg_server_ip_addr2.c_str(), 131 | g_msg_server_port, g_max_conn_cnt, cur_conn_cnt, hostname, MSG_SERVER_TYPE_TCP); 132 | SendPdu(&pdu); 133 | 134 | if (!user_conn_list.empty()) { 135 | CImPduUserConnInfo pdu2(&user_conn_list); 136 | SendPdu(&pdu2); 137 | } 138 | } 139 | 140 | void CLoginServConn::OnClose() 141 | { 142 | log("login server conn onclose, from handle=%d\n", m_handle); 143 | Close(); 144 | } 145 | 146 | void CLoginServConn::OnTimer(uint64_t curr_tick) 147 | { 148 | if (curr_tick > m_last_send_tick + SERVER_HEARTBEAT_INTERVAL) { 149 | CImPduHeartbeat pdu; 150 | SendPdu(&pdu); 151 | } 152 | 153 | if (curr_tick > m_last_recv_tick + SERVER_TIMEOUT) { 154 | log("conn to login server timeout\n"); 155 | Close(); 156 | } 157 | } 158 | 159 | void CLoginServConn::HandlePdu(CImPdu* pPdu) 160 | { 161 | //printf("recv pdu_type=%d\n", pPdu->GetPduType()); 162 | } 163 | -------------------------------------------------------------------------------- /src/base/imconn.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * imconn.cpp 3 | * 4 | * Created on: 2013-6-5 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "imconn.h" 9 | 10 | #define POLICY_FILE_NAME "policy.xml" 11 | 12 | static char* g_policy_content = NULL; 13 | static uint32_t g_policy_len = 0; 14 | static uint32_t g_send_pkt_cnt = 0; // 发送数据包总数 15 | static uint32_t g_recv_pkt_cnt = 0; // 接收数据包总数 16 | 17 | static CImConn* FindImConn(ConnMap_t* imconn_map, net_handle_t handle) 18 | { 19 | CImConn* pConn = NULL; 20 | ConnMap_t::iterator iter = imconn_map->find(handle); 21 | if (iter != imconn_map->end()) 22 | { 23 | pConn = iter->second; 24 | pConn->AddRef(); 25 | } 26 | 27 | return pConn; 28 | } 29 | 30 | void imconn_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 31 | { 32 | NOTUSED_ARG(handle); 33 | NOTUSED_ARG(pParam); 34 | 35 | if (!callback_data) 36 | return; 37 | 38 | ConnMap_t* conn_map = (ConnMap_t*)callback_data; 39 | CImConn* pConn = FindImConn(conn_map, handle); 40 | if (!pConn) 41 | return; 42 | 43 | //log("msg=%d, handle=%d\n", msg, handle); 44 | 45 | switch (msg) 46 | { 47 | case NETLIB_MSG_CONFIRM: 48 | pConn->OnConfirm(); 49 | break; 50 | case NETLIB_MSG_READ: 51 | pConn->OnRead(); 52 | break; 53 | case NETLIB_MSG_WRITE: 54 | pConn->OnWrite(); 55 | break; 56 | case NETLIB_MSG_CLOSE: 57 | pConn->OnClose(); 58 | break; 59 | default: 60 | log("!!!imconn_callback error msg: %d\n", msg); 61 | break; 62 | } 63 | 64 | pConn->ReleaseRef(); 65 | } 66 | 67 | ////////////////////////// 68 | CImConn::CImConn() 69 | { 70 | //log("CImConn::CImConn\n"); 71 | 72 | m_busy = false; 73 | m_handle = NETLIB_INVALID_HANDLE; 74 | m_recv_bytes = 0; 75 | m_policy_conn = false; 76 | 77 | m_last_send_tick = m_last_recv_tick = get_tick_count(); 78 | } 79 | 80 | CImConn::~CImConn() 81 | { 82 | //log("CImConn::~CImConn, handle=%d\n", m_handle); 83 | } 84 | 85 | int CImConn::Send(void* data, int len) 86 | { 87 | m_last_send_tick = get_tick_count(); 88 | ++g_send_pkt_cnt; 89 | 90 | if (m_busy) 91 | { 92 | m_out_buf.Write(data, len); 93 | return len; 94 | } 95 | 96 | int offset = 0; 97 | int remain = len; 98 | while (remain > 0) { 99 | int send_size = remain; 100 | if (send_size > NETLIB_MAX_SOCKET_BUF_SIZE) { 101 | send_size = NETLIB_MAX_SOCKET_BUF_SIZE; 102 | } 103 | 104 | int ret = netlib_send(m_handle, (char*)data + offset , send_size); 105 | if (ret <= 0) { 106 | ret = 0; 107 | break; 108 | } 109 | 110 | offset += ret; 111 | remain -= ret; 112 | } 113 | 114 | if (remain > 0) 115 | { 116 | m_out_buf.Write((char*)data + offset, remain); 117 | m_busy = true; 118 | log("send busy, remain=%d\n", m_out_buf.GetWriteOffset()); 119 | } 120 | 121 | return len; 122 | } 123 | 124 | void CImConn::OnRead() 125 | { 126 | for (;;) 127 | { 128 | uint32_t free_buf_len = m_in_buf.GetAllocSize() - m_in_buf.GetWriteOffset(); 129 | if (free_buf_len < READ_BUF_SIZE) 130 | m_in_buf.Extend(READ_BUF_SIZE); 131 | 132 | int ret = netlib_recv(m_handle, m_in_buf.GetBuffer() + m_in_buf.GetWriteOffset(), READ_BUF_SIZE); 133 | if (ret <= 0) 134 | break; 135 | 136 | m_recv_bytes += ret; 137 | m_in_buf.IncWriteOffset(ret); 138 | 139 | m_last_recv_tick = get_tick_count(); 140 | } 141 | 142 | if (m_policy_conn) { 143 | return; 144 | } 145 | 146 | // no received data is read by ReadPdu(), check if this is a flash security policy request 147 | if (m_recv_bytes == m_in_buf.GetWriteOffset()) { 148 | if ( (m_in_buf.GetBuffer()[0] == '<') && (g_policy_content != NULL) ) { 149 | log("policy request, handle=%d\n", m_handle); 150 | m_policy_conn = true; 151 | Send(g_policy_content, g_policy_len); 152 | return; 153 | } 154 | } 155 | 156 | try { 157 | CImPdu* pPdu = NULL; 158 | while ( ( pPdu = CImPdu::ReadPdu(m_in_buf.GetBuffer(), m_in_buf.GetWriteOffset()) ) ) 159 | { 160 | uint32_t pdu_len = pPdu->GetLength(); 161 | 162 | HandlePdu(pPdu); 163 | 164 | m_in_buf.Read(NULL, pdu_len); 165 | delete pPdu; 166 | 167 | ++g_recv_pkt_cnt; 168 | } 169 | } catch (CPduException& ex) { 170 | log("!!!catch exception, sid=%u, cid=%u, err_code=%u, err_msg=%s, close the connection\n", 171 | ex.GetModuleId(), ex.GetCommandId(), ex.GetErrorCode(), ex.GetErrorMsg()); 172 | OnClose(); 173 | } 174 | } 175 | 176 | void CImConn::OnWrite() 177 | { 178 | if (!m_busy) 179 | return; 180 | 181 | while (m_out_buf.GetWriteOffset() > 0) { 182 | int send_size = m_out_buf.GetWriteOffset(); 183 | if (send_size > NETLIB_MAX_SOCKET_BUF_SIZE) { 184 | send_size = NETLIB_MAX_SOCKET_BUF_SIZE; 185 | } 186 | 187 | int ret = netlib_send(m_handle, m_out_buf.GetBuffer(), send_size); 188 | if (ret <= 0) { 189 | ret = 0; 190 | break; 191 | } 192 | 193 | m_out_buf.Read(NULL, ret); 194 | } 195 | 196 | if (m_out_buf.GetWriteOffset() == 0) { 197 | m_busy = false; 198 | } 199 | 200 | log("onWrite, remain=%d\n", m_out_buf.GetWriteOffset()); 201 | } 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /src/msg_server/msg_server.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * msg_server.cpp 3 | * 4 | * Created on: 2013-6-21 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "netlib.h" 9 | #include "ConfigFileReader.h" 10 | #include "MsgConn.h" 11 | #include "LoginServConn.h" 12 | #include "RouteServConn.h" 13 | #include "DBServConn.h" 14 | #include "HttpConn.h" 15 | #include "FileServConn.h" 16 | #include "version.h" 17 | 18 | #define DEFAULT_CONCURRENT_DB_CONN_CNT 10 19 | 20 | // for client connect in 21 | void msg_serv_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 22 | { 23 | if (msg == NETLIB_MSG_CONNECT) 24 | { 25 | CMsgConn* pConn = new CMsgConn(); 26 | pConn->OnConnect(handle); 27 | } 28 | else 29 | { 30 | log("!!!error msg: %d\n", msg); 31 | } 32 | } 33 | 34 | // for client connect in 35 | void http_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 36 | { 37 | if (msg == NETLIB_MSG_CONNECT) 38 | { 39 | CHttpConn* pConn = new CHttpConn(); 40 | pConn->OnConnect(handle); 41 | } 42 | else 43 | { 44 | log("!!!error msg: %d\n", msg); 45 | } 46 | } 47 | 48 | 49 | int main(int argc, char* argv[]) 50 | { 51 | if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { 52 | printf("Server Version: MsgServer/%s\n", VERSION); 53 | printf("Server Build: %s %s\n", __DATE__, __TIME__); 54 | return 0; 55 | } 56 | 57 | signal(SIGPIPE, SIG_IGN); 58 | srand(time(NULL)); 59 | 60 | log("MsgServer max files can open: %d\n", getdtablesize()); 61 | 62 | CConfigFileReader config_file("msgserver.conf"); 63 | 64 | char* listen_ip = config_file.GetConfigName("ListenIP"); 65 | char* str_listen_port = config_file.GetConfigName("ListenPort"); 66 | char* ip_addr1 = config_file.GetConfigName("IpAddr1"); // 电信IP 67 | char* ip_addr2 = config_file.GetConfigName("IpAddr2"); // 网通IP 68 | char* str_max_conn_cnt = config_file.GetConfigName("MaxConnCnt"); 69 | char* http_listen_ip = config_file.GetConfigName("HttpListenIP"); 70 | char* str_http_listen_port = config_file.GetConfigName("HttpListenPort"); 71 | 72 | uint32_t db_server_count = 0; 73 | serv_info_t* db_server_list = read_server_config(&config_file, "DBServerIP", "DBServerPort", db_server_count); 74 | 75 | uint32_t login_server_count = 0; 76 | serv_info_t* login_server_list = read_server_config(&config_file, "LoginServerIP", "LoginServerPort", login_server_count); 77 | 78 | uint32_t route_server_count = 0; 79 | serv_info_t* route_server_list = read_server_config(&config_file, "RouteServerIP", "RouteServerPort", route_server_count); 80 | 81 | uint32_t file_server_count = 0; 82 | serv_info_t* file_server_list = read_server_config(&config_file, "FileServerIP", 83 | "FileServerPort", file_server_count); 84 | // 必须至少配置2个BusinessServer实例, 一个用于用户登录业务,一个用于其他业务 85 | // 这样当其他业务量非常繁忙时,也不会影响客服端的登录验证 86 | // 建议配置4个实例,这样更新BusinessServer时,不会影响业务 87 | if (db_server_count < 2) { 88 | log("DBServerIP need 2 instance at lest\n"); 89 | return 1; 90 | } 91 | 92 | // 到BusinessServer的开多个并发的连接 93 | uint32_t concurrent_db_conn_cnt = DEFAULT_CONCURRENT_DB_CONN_CNT; 94 | uint32_t db_server_count2 = db_server_count * DEFAULT_CONCURRENT_DB_CONN_CNT; 95 | char* concurrent_db_conn = config_file.GetConfigName("ConcurrentDBConnCnt"); 96 | if (concurrent_db_conn) { 97 | concurrent_db_conn_cnt = atoi(concurrent_db_conn); 98 | db_server_count2 = db_server_count * concurrent_db_conn_cnt; 99 | } 100 | 101 | serv_info_t* db_server_list2 = new serv_info_t [ db_server_count2]; 102 | for (uint32_t i = 0; i < db_server_count2; i++) { 103 | db_server_list2[i].server_ip = db_server_list[i / concurrent_db_conn_cnt].server_ip.c_str(); 104 | db_server_list2[i].server_port = db_server_list[i / concurrent_db_conn_cnt].server_port; 105 | } 106 | 107 | if (!listen_ip || !str_listen_port || !ip_addr1 || !http_listen_ip || !str_http_listen_port) { 108 | log("config file miss, exit...\n"); 109 | return -1; 110 | } 111 | 112 | // 没有IP2,就用第一个IP 113 | if (!ip_addr2) { 114 | ip_addr2 = ip_addr1; 115 | } 116 | 117 | uint16_t listen_port = atoi(str_listen_port); 118 | uint32_t max_conn_cnt = atoi(str_max_conn_cnt); 119 | uint16_t http_listen_port = atoi(str_http_listen_port); 120 | 121 | int ret = netlib_init(); 122 | 123 | if (ret == NETLIB_ERROR) 124 | return ret; 125 | 126 | CStrExplode listen_ip_list(listen_ip, ';'); 127 | for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) { 128 | ret = netlib_listen(listen_ip_list.GetItem(i), listen_port, msg_serv_callback, NULL); 129 | if (ret == NETLIB_ERROR) 130 | return ret; 131 | } 132 | 133 | if (netlib_listen(http_listen_ip, http_listen_port, http_callback, NULL) == NETLIB_ERROR) 134 | { 135 | log("http listen failed, ip: %s, port:%u\n", http_listen_ip, http_listen_port); 136 | } 137 | 138 | printf("server start listen on: %s:%d\n", listen_ip, listen_port); 139 | 140 | init_msg_conn(); 141 | 142 | init_http_conn(); 143 | 144 | init_file_serv_conn(file_server_list, file_server_count); 145 | 146 | init_db_serv_conn(db_server_list2, db_server_count2, concurrent_db_conn_cnt); 147 | 148 | init_login_serv_conn(login_server_list, login_server_count, ip_addr1, ip_addr2, listen_port, max_conn_cnt); 149 | 150 | init_route_serv_conn(route_server_list, route_server_count); 151 | 152 | printf("now enter the event loop...\n"); 153 | 154 | netlib_eventloop(); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /src/msfs/http/HttpParserWrapper.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // HttpPdu.cpp 3 | // http_msg_server 4 | // 5 | // Created by jianqing.du on 13-9-29. 6 | // Copyright (c) 2013年 ziteng. All rights reserved. 7 | // 8 | 9 | #include "HttpParserWrapper.h" 10 | 11 | #define MAX_REFERER_LEN 32 12 | 13 | CHttpParserWrapper::CHttpParserWrapper() 14 | { 15 | 16 | } 17 | 18 | 19 | void CHttpParserWrapper::ParseHttpContent(const char* buf, uint32_t len) 20 | { 21 | http_parser_init(&m_http_parser, HTTP_REQUEST); 22 | memset(&m_settings, 0, sizeof(m_settings)); 23 | m_settings.on_url = OnUrl; 24 | m_settings.on_header_field = OnHeaderField; 25 | m_settings.on_header_value = OnHeaderValue; 26 | m_settings.on_headers_complete = OnHeadersComplete; 27 | m_settings.on_body = OnBody; 28 | m_settings.on_message_complete = OnMessageComplete; 29 | m_settings.object = this; 30 | 31 | m_read_all = false; 32 | m_read_referer = false; 33 | m_read_forward_ip = false; 34 | m_read_user_agent = false; 35 | m_read_content_type = false; 36 | m_read_content_len = false; 37 | m_read_host = false; 38 | m_total_length = 0; 39 | m_url.clear(); 40 | m_body_content.clear(); 41 | m_referer.clear(); 42 | m_forward_ip.clear(); 43 | m_user_agent.clear(); 44 | m_content_type.clear(); 45 | m_content_len = 0; 46 | m_host.clear(); 47 | 48 | http_parser_execute(&m_http_parser, &m_settings, buf, len); 49 | } 50 | 51 | int CHttpParserWrapper::OnUrl(http_parser* parser, const char *at, 52 | size_t length, void* obj) 53 | { 54 | ((CHttpParserWrapper*)obj)->SetUrl(at, length); 55 | return 0; 56 | } 57 | 58 | int CHttpParserWrapper::OnHeaderField(http_parser* parser, const char *at, 59 | size_t length, void* obj) 60 | { 61 | if (!((CHttpParserWrapper*)obj)->HasReadReferer()) 62 | { 63 | if (strncasecmp(at, "Referer", 7) == 0) 64 | { 65 | ((CHttpParserWrapper*)obj)->SetReadReferer(true); 66 | } 67 | } 68 | 69 | if (!((CHttpParserWrapper*)obj)->HasReadForwardIP()) 70 | { 71 | if (strncasecmp(at, "X-Forwarded-For", 15) == 0) 72 | { 73 | ((CHttpParserWrapper*)obj)->SetReadForwardIP(true); 74 | } 75 | } 76 | 77 | if (!((CHttpParserWrapper*)obj)->HasReadUserAgent()) 78 | { 79 | if (strncasecmp(at, "User-Agent", 10) == 0) 80 | { 81 | ((CHttpParserWrapper*)obj)->SetReadUserAgent(true); 82 | } 83 | } 84 | 85 | if (!((CHttpParserWrapper*)obj)->HasReadContentType()) 86 | { 87 | if (strncasecmp(at, "Content-Type", 12) == 0) 88 | { 89 | ((CHttpParserWrapper*)obj)->SetReadContentType(true); 90 | } 91 | } 92 | 93 | if(!((CHttpParserWrapper*)obj)->HasReadContentLen()) 94 | { 95 | if(strncasecmp(at, "Content-Length", 14) == 0) 96 | { 97 | ((CHttpParserWrapper*)obj)->SetReadContentLen(true); 98 | } 99 | } 100 | if(!((CHttpParserWrapper*)obj)->HasReadHost()) 101 | { 102 | if(strncasecmp(at, "Host", 4) == 0) 103 | { 104 | ((CHttpParserWrapper*)obj)->SetReadHost(true); 105 | } 106 | } 107 | return 0; 108 | } 109 | 110 | int CHttpParserWrapper::OnHeaderValue(http_parser* parser, const char *at, 111 | size_t length, void* obj) 112 | { 113 | if (((CHttpParserWrapper*)obj)->IsReadReferer()) 114 | { 115 | size_t referer_len = 116 | (length > MAX_REFERER_LEN) ? MAX_REFERER_LEN : length; 117 | ((CHttpParserWrapper*)obj)->SetReferer(at, referer_len); 118 | ((CHttpParserWrapper*)obj)->SetReadReferer(false); 119 | } 120 | 121 | if (((CHttpParserWrapper*)obj)->IsReadForwardIP()) 122 | { 123 | ((CHttpParserWrapper*)obj)->SetForwardIP(at, length); 124 | ((CHttpParserWrapper*)obj)->SetReadForwardIP(false); 125 | } 126 | 127 | if (((CHttpParserWrapper*)obj)->IsReadUserAgent()) 128 | { 129 | ((CHttpParserWrapper*)obj)->SetUserAgent(at, length); 130 | ((CHttpParserWrapper*)obj)->SetReadUserAgent(false); 131 | } 132 | 133 | if (((CHttpParserWrapper*)obj)->IsReadContentType()) 134 | { 135 | ((CHttpParserWrapper*)obj)->SetContentType(at, length); 136 | ((CHttpParserWrapper*)obj)->SetReadContentType(false); 137 | } 138 | 139 | if(((CHttpParserWrapper*)obj)->IsReadContentLen()) 140 | { 141 | string strContentLen(at, length); 142 | ((CHttpParserWrapper*)obj)->SetContentLen(atoi(strContentLen.c_str())); 143 | ((CHttpParserWrapper*)obj)->SetReadContentLen(false); 144 | } 145 | 146 | if(((CHttpParserWrapper*)obj)->IsReadHost()) 147 | { 148 | ((CHttpParserWrapper*)obj)->SetHost(at, length); 149 | ((CHttpParserWrapper*)obj)->SetReadHost(false); 150 | } 151 | return 0; 152 | } 153 | 154 | int CHttpParserWrapper::OnHeadersComplete(http_parser* parser, void* obj) 155 | { 156 | ((CHttpParserWrapper*)obj)->SetTotalLength( 157 | parser->nread + (uint32_t) parser->content_length); 158 | return 0; 159 | } 160 | 161 | int CHttpParserWrapper::OnBody(http_parser* parser, const char *at, 162 | size_t length, void* obj) 163 | { 164 | ((CHttpParserWrapper*)obj)->SetBodyContent(at, length); 165 | return 0; 166 | } 167 | 168 | int CHttpParserWrapper::OnMessageComplete(http_parser* parser, void* obj) 169 | { 170 | ((CHttpParserWrapper*)obj)->SetReadAll(); 171 | return 0; 172 | } 173 | -------------------------------------------------------------------------------- /src/msfs/HttpConn.h: -------------------------------------------------------------------------------- 1 | /*================================================================ 2 | * Copyright (C) 2014 All rights reserved. 3 | * 4 | * 文件名称:HttpConn.h 5 | * 创 建 者:Zhang Yuanhao 6 | * 邮 箱:bluefoxah@gmail.com 7 | * 创建日期:2014年07月29日 8 | * 描 述: 9 | * 10 | #pragma once 11 | ================================================================*/ 12 | #ifndef __HTTP_CONN_H__ 13 | #define __HTTP_CONN_H__ 14 | 15 | #include "util.h" 16 | #if (MSFS_LINUX) 17 | #include 18 | #elif (MSFS_BSD) 19 | #include 20 | #include 21 | #include 22 | #endif 23 | #include 24 | #include "netlib.h" 25 | #include "SimpleBuffer.h" 26 | #include "FileManager.h" 27 | #include "ConfigFileReader.h" 28 | #include "ThreadPool.h" 29 | #include "HttpParserWrapper.h" 30 | 31 | #define HTTP_CONN_TIMEOUT 30000 32 | #define HTTP_UPLOAD_MAX 0xA00000 //10M 33 | #define BOUNDARY_MARK "boundary=" 34 | #define HTTP_END_MARK "\r\n\r\n" 35 | #define CONTENT_TYPE "Content-Type:" 36 | #define CONTENT_DISPOSITION "Content-Disposition:" 37 | #define READ_BUF_SIZE 0x100000 //1M 38 | #define HTTP_RESPONSE_HEADER "HTTP/1.1 200 OK\r\n"\ 39 | "Connection:close\r\n"\ 40 | "Content-Length:%d\r\n"\ 41 | "Content-Type:multipart/form-data\r\n\r\n" 42 | #define HTTP_RESPONSE_EXTEND "HTTP/1.1 200 OK\r\n"\ 43 | "Connection:close\r\n"\ 44 | "Content-Length:%d\r\n"\ 45 | "Content-Type:multipart/form-data\r\n\r\n" 46 | #define HTTP_RESPONSE_HTML "HTTP/1.1 200 OK\r\n"\ 47 | "Connection:close\r\n"\ 48 | "Content-Length:%d\r\n"\ 49 | "Content-Type:text/html;charset=utf-8\r\n\r\n%s" 50 | #define HTTP_RESPONSE_HTML_MAX 1024 51 | #define HTTP_RESPONSE_403 "HTTP/1.1 403 Access Forbidden\r\n"\ 52 | "Content-Length: 0\r\n"\ 53 | "Connection: close\r\n"\ 54 | "Content-Type: text/html;charset=utf-8\r\n\r\n" 55 | #define HTTP_RESPONSE_403_LEN strlen(HTTP_RESPONSE_403) 56 | #define HTTP_RESPONSE_404 "HTTP/1.1 404 Not Found\r\n"\ 57 | "Content-Length: 0\r\n"\ 58 | "Connection: close\r\n"\ 59 | "Content-Type: text/html;charset=utf-8\r\n\r\n" 60 | #define HTTP_RESPONSE_404_LEN strlen(HTTP_RESPONSE_404) 61 | #define HTTP_RESPONSE_500 "HTTP/1.1 500 Internal Server Error\r\n"\ 62 | "Connection:close\r\n"\ 63 | "Content-Length:0\r\n"\ 64 | "Content-Type:text/html;charset=utf-8\r\n\r\n" 65 | #define HTTP_RESPONSE_500_LEN strlen(HTTP_RESPONSE_500) 66 | 67 | using namespace msfs; 68 | enum 69 | { 70 | CONN_STATE_IDLE, CONN_STATE_CONNECTED, CONN_STATE_OPEN, CONN_STATE_CLOSED, 71 | }; 72 | 73 | extern FileManager * g_fileManager; 74 | extern CConfigFileReader config_file; 75 | extern CThreadPool g_PostThreadPool; 76 | extern CThreadPool g_GetThreadPool; 77 | 78 | typedef struct { 79 | uint32_t conn_handle; 80 | int method; 81 | int nContentLen; 82 | string strAccessHost; 83 | char* pContent; 84 | string strUrl; 85 | string strContentType; 86 | }Request_t; 87 | 88 | typedef struct { 89 | uint32_t conn_handle; 90 | char* pContent; 91 | uint32_t content_len; 92 | } Response_t; 93 | 94 | class CHttpConn; 95 | class CHttpTask: public CTask 96 | { 97 | public: 98 | CHttpTask(Request_t request); 99 | virtual ~CHttpTask(); 100 | void run(); 101 | void OnUpload(); 102 | void OnDownload(); 103 | private: 104 | uint32_t m_ConnHandle; 105 | int m_nMethod; 106 | string m_strUrl; 107 | string m_strContentType; 108 | char* m_pContent; 109 | int m_nContentLen; 110 | string m_strAccessHost; 111 | }; 112 | 113 | class CHttpConn: public CRefObject 114 | { 115 | public: 116 | CHttpConn(); 117 | virtual ~CHttpConn(); 118 | 119 | uint32_t GetConnHandle() 120 | { 121 | return m_conn_handle; 122 | } 123 | char* GetPeerIP() 124 | { 125 | return (char*) m_peer_ip.c_str(); 126 | } 127 | 128 | int Send(void* data, int len); 129 | 130 | void Close(); 131 | void OnConnect(net_handle_t handle); 132 | void OnRead(); 133 | void OnWrite(); 134 | void OnClose(); 135 | void OnTimer(uint64_t curr_tick); 136 | void OnSendComplete(); 137 | 138 | static void AddResponsePdu(uint32_t conn_handle, char* pContent, int nLen); // 工作线程调用 139 | static void SendResponsePduList(); // 主线程调用 140 | protected: 141 | net_handle_t m_sock_handle; 142 | uint32_t m_conn_handle; 143 | bool m_busy; 144 | 145 | uint32_t m_state; 146 | string m_peer_ip; 147 | uint16_t m_peer_port; 148 | string m_access_host; 149 | CSimpleBuffer m_in_buf; 150 | CSimpleBuffer m_out_buf; 151 | uint64_t m_last_send_tick; 152 | uint64_t m_last_recv_tick; 153 | 154 | CHttpParserWrapper m_HttpParser; 155 | 156 | static CThreadLock s_list_lock; 157 | static list s_response_pdu_list; // 主线程发送回复消息 158 | }; 159 | 160 | typedef hash_map HttpConnMap_t; 161 | 162 | CHttpConn* FindHttpConnByHandle(uint32_t handle); 163 | void init_http_conn(); 164 | 165 | #endif 166 | -------------------------------------------------------------------------------- /src/msfs/storage/FileLin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multimedia Small File Storage System 3 | * File Operation API implement in Linux OS 4 | * @author potian@mogujie.com 5 | */ 6 | #ifndef WIN32 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "FileLin.h" 18 | 19 | namespace msfs { 20 | 21 | File::File(const char *path) { 22 | assert(path); 23 | m_path = new char[strlen(path) + 1]; 24 | strncpy(m_path, path, strlen(path)); 25 | m_path[strlen(path)] = '\0'; 26 | m_opened = false; 27 | m_file = -1; 28 | m_size = -1; 29 | } 30 | 31 | File::~File() { 32 | if (m_opened) 33 | close(); 34 | delete [] m_path; 35 | m_path = NULL; 36 | } 37 | 38 | u64 File::isExist(bool *exist) { 39 | *exist = access(m_path, 0) == 0; 40 | return 0; 41 | } 42 | 43 | u64 File::remove() { 44 | if (-1 == unlink(m_path)) 45 | return errno; 46 | return 0; 47 | } 48 | 49 | u64 File::create(bool directIo) { 50 | assert(!m_opened); 51 | int flags = O_RDWR | O_CREAT | O_EXCL; 52 | #if defined(__FREEBSD__) || defined (__APPLE__) 53 | m_file = ::open(m_path, flags, 00640); 54 | #elif defined(__LINUX__) || defined(__linux__) 55 | m_file = open64(m_path, flags, 00640); 56 | #endif 57 | if (-1 == m_file) 58 | return errno; 59 | #ifdef __LINUX__ 60 | if (directIo) 61 | if (-1 == fcntl(m_file, F_SETFL,O_DIRECT)) 62 | return errno; 63 | #endif 64 | m_opened = true; 65 | m_size = 0; 66 | m_directIo = directIo; 67 | return 0; 68 | } 69 | 70 | u64 File::open(bool directIo) { 71 | assert(!m_opened); 72 | int flags = O_RDWR; 73 | #ifdef __linux__ 74 | m_file = open64(m_path, flags); 75 | #elif defined(__FREEBSD__) || defined(__APPLE__) 76 | m_file = ::open(m_path, flags); 77 | #endif 78 | if(-1 == m_file) { 79 | return errno; 80 | } 81 | #ifdef __LINUX__ 82 | if (directIo) 83 | if (-1 == fcntl(m_file, F_SETFL, O_DIRECT)) 84 | return errno; 85 | #endif 86 | struct flock lock; 87 | lock.l_type = F_WRLCK; 88 | lock.l_start = 0; 89 | lock.l_whence = SEEK_SET; 90 | lock.l_len = 0; 91 | if(fcntl(m_file, F_SETLK, &lock) < 0) { 92 | ::close(m_file); 93 | return errno; 94 | } 95 | 96 | m_opened = true; 97 | u64 size = 0; 98 | u64 code = getSize(&size); 99 | if (code) { 100 | close(); 101 | return code; 102 | } 103 | m_size = size; 104 | m_directIo = directIo; 105 | return 0; 106 | } 107 | 108 | u64 File::close() { 109 | if (!m_opened) 110 | return 0; 111 | u64 err = sync(); 112 | if (err) 113 | return err; 114 | m_opened = false; 115 | if(0 != ::close(m_file)) 116 | return errno; 117 | return 0; 118 | } 119 | 120 | s64 File::getFileSize(const char *path) { 121 | s64 filesize = -1; 122 | struct stat statbuff; 123 | if(stat(path, &statbuff) < 0){ 124 | return filesize; 125 | } else { 126 | filesize = statbuff.st_size; 127 | } 128 | return filesize; 129 | } 130 | 131 | u64 File::getSize(u64 *size) { 132 | if (m_size > 0) { 133 | *size = m_size; 134 | return 0; 135 | } 136 | 137 | s64 sksize = lseek(m_file, 0, SEEK_END); 138 | if (-1 == sksize) 139 | return errno; 140 | else 141 | *size = (u64)sksize; 142 | m_size = *size; 143 | return 0; 144 | } 145 | 146 | u64 File::setSize(u64 size) { 147 | assert(m_opened); 148 | #ifdef __linux__ 149 | if (-1 == ftruncate64(m_file, size)) 150 | #elif defined(__FREEBSD__) || defined (__APPLE__) 151 | if (-1 == ftruncate(m_file, size)) 152 | #endif 153 | return errno; 154 | m_size = size; 155 | return 0; 156 | } 157 | 158 | u64 File::read(u64 offset, u32 size, void *buffer) { 159 | assert(m_opened); 160 | if (offset + size > (u64)m_size) 161 | return E_EOF; 162 | #ifdef __linux__ 163 | if (size != pread64(m_file, buffer, size, offset)) 164 | #elif defined(__FREEBSD__) || defined(__APPLE__) 165 | if (size != pread(m_file, buffer, size, offset)) 166 | #endif 167 | return errno; 168 | return 0; 169 | } 170 | 171 | u64 File::write(u64 offset, u32 size, const void *buffer) { 172 | assert(m_opened); 173 | setSize((u64)size); 174 | if (offset + size > (u64)m_size) 175 | return E_EOF; 176 | #ifdef __linux__ 177 | if(size != pwrite64(m_file, buffer, size, offset)) 178 | #elif defined(__FREEBSD__) || defined (__APPLE__) 179 | if(size != pwrite(m_file, buffer, size, offset)) 180 | #endif 181 | return errno; 182 | return 0; 183 | } 184 | 185 | u64 File::sync() { 186 | assert(m_opened); 187 | if (-1 == fsync(m_file)) { 188 | return errno; 189 | } 190 | return 0; 191 | } 192 | 193 | u64 File::mkdirNoRecursion(const char *path) { 194 | if (::mkdir(path, 0777) != 0) 195 | return errno; 196 | return 0; 197 | } 198 | 199 | u64 File::isDirectory(bool *isDir) { 200 | struct stat fileStat; 201 | if (stat(m_path, &fileStat) != 0) 202 | return errno; 203 | *isDir = S_ISDIR(fileStat.st_mode) != 0; 204 | return 0; 205 | } 206 | 207 | u64 File::getFileNum(int *fileNum) { 208 | DIR *dp; 209 | struct dirent *ep = NULL; 210 | string dir(m_path); 211 | if (dir[dir.length() - 1] != '/' && dir[dir.length() - 1] != '\\') 212 | dir += "/"; 213 | dp = opendir(m_path); 214 | if (!dp) 215 | return errno; 216 | int files = 0; 217 | ep = readdir(dp); 218 | while (ep) { 219 | string subPath = dir + ep->d_name; 220 | File subFile(subPath.c_str()); 221 | bool isDir = false; 222 | if (subFile.isDirectory(&isDir) != 0 || isDir) { 223 | closedir(dp); 224 | return errno; 225 | } else { 226 | if (strncmp(ep->d_name, ".", 1) != 0) 227 | files++; 228 | } 229 | ep = readdir(dp); 230 | } 231 | *fileNum = files; 232 | closedir(dp); 233 | return 0; 234 | } 235 | 236 | } 237 | #endif 238 | 239 | -------------------------------------------------------------------------------- /src/msg_server/HttpConn.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * HttpConn.cpp 3 | * 4 | * Created on: 2013-9-29 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "HttpParserWrapper.h" 9 | #include "HttpConn.h" 10 | #include "HttpQuery.h" 11 | 12 | static HttpConnMap_t g_http_conn_map; 13 | 14 | // conn_handle 从0开始递增,可以防止因socket handle重用引起的一些冲突 15 | static uint32_t g_conn_handle_generator = 0; 16 | 17 | CHttpConn* FindHttpConnByHandle(uint32_t conn_handle) 18 | { 19 | CHttpConn* pConn = NULL; 20 | HttpConnMap_t::iterator it = g_http_conn_map.find(conn_handle); 21 | if (it != g_http_conn_map.end()) { 22 | pConn = it->second; 23 | } 24 | 25 | return pConn; 26 | } 27 | 28 | void httpconn_callback(void* callback_data, uint8_t msg, uint32_t handle, uint32_t uParam, void* pParam) 29 | { 30 | NOTUSED_ARG(uParam); 31 | NOTUSED_ARG(pParam); 32 | 33 | // convert void* to uint32_t, oops 34 | uint32_t conn_handle = *((uint32_t*)(&callback_data)); 35 | CHttpConn* pConn = FindHttpConnByHandle(conn_handle); 36 | if (!pConn) { 37 | return; 38 | } 39 | 40 | switch (msg) 41 | { 42 | case NETLIB_MSG_READ: 43 | pConn->OnRead(); 44 | break; 45 | case NETLIB_MSG_WRITE: 46 | pConn->OnWrite(); 47 | break; 48 | case NETLIB_MSG_CLOSE: 49 | pConn->OnClose(); 50 | break; 51 | default: 52 | log("!!!httpconn_callback error msg: %d\n", msg); 53 | break; 54 | } 55 | } 56 | 57 | void http_conn_timer_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 58 | { 59 | CHttpConn* pConn = NULL; 60 | HttpConnMap_t::iterator it, it_old; 61 | uint64_t cur_time = get_tick_count(); 62 | 63 | for (it = g_http_conn_map.begin(); it != g_http_conn_map.end(); ) { 64 | it_old = it; 65 | it++; 66 | 67 | pConn = it_old->second; 68 | pConn->OnTimer(cur_time); 69 | } 70 | } 71 | 72 | void init_http_conn() 73 | { 74 | netlib_register_timer(http_conn_timer_callback, NULL, 1000); 75 | } 76 | 77 | ////////////////////////// 78 | CHttpConn::CHttpConn() 79 | { 80 | m_busy = false; 81 | m_sock_handle = NETLIB_INVALID_HANDLE; 82 | m_state = CONN_STATE_IDLE; 83 | 84 | m_last_send_tick = m_last_recv_tick = get_tick_count(); 85 | m_conn_handle = ++g_conn_handle_generator; 86 | if (m_conn_handle == 0) { 87 | m_conn_handle = ++g_conn_handle_generator; 88 | } 89 | 90 | //log("CHttpConn, handle=%u\n", m_conn_handle); 91 | } 92 | 93 | CHttpConn::~CHttpConn() 94 | { 95 | //log("~CHttpConn, handle=%u\n", m_conn_handle); 96 | } 97 | 98 | int CHttpConn::Send(void* data, int len) 99 | { 100 | m_last_send_tick = get_tick_count(); 101 | 102 | if (m_busy) 103 | { 104 | m_out_buf.Write(data, len); 105 | return len; 106 | } 107 | 108 | int ret = netlib_send(m_sock_handle, data, len); 109 | if (ret < 0) 110 | ret = 0; 111 | 112 | if (ret < len) 113 | { 114 | m_out_buf.Write((char*)data + ret, len - ret); 115 | m_busy = true; 116 | //log("not send all, remain=%d\n", m_out_buf.GetWriteOffset()); 117 | } 118 | 119 | return len; 120 | } 121 | 122 | void CHttpConn::Close() 123 | { 124 | m_state = CONN_STATE_CLOSED; 125 | 126 | g_http_conn_map.erase(m_conn_handle); 127 | netlib_close(m_sock_handle); 128 | 129 | ReleaseRef(); 130 | } 131 | 132 | void CHttpConn::OnConnect(net_handle_t handle) 133 | { 134 | //printf("OnConnect, handle=%d\n", handle); 135 | m_sock_handle = handle; 136 | m_state = CONN_STATE_CONNECTED; 137 | g_http_conn_map.insert(make_pair(m_conn_handle, this)); 138 | 139 | netlib_option(handle, NETLIB_OPT_SET_CALLBACK, (void*)httpconn_callback); 140 | netlib_option(handle, NETLIB_OPT_SET_CALLBACK_DATA, reinterpret_cast(m_conn_handle) ); 141 | netlib_option(handle, NETLIB_OPT_GET_REMOTE_IP, (void*)&m_peer_ip); 142 | } 143 | 144 | void CHttpConn::OnRead() 145 | { 146 | for (;;) 147 | { 148 | uint32_t free_buf_len = m_in_buf.GetAllocSize() - m_in_buf.GetWriteOffset(); 149 | if (free_buf_len < READ_BUF_SIZE + 1) 150 | m_in_buf.Extend(READ_BUF_SIZE + 1); 151 | 152 | int ret = netlib_recv(m_sock_handle, m_in_buf.GetBuffer() + m_in_buf.GetWriteOffset(), READ_BUF_SIZE); 153 | if (ret <= 0) 154 | break; 155 | 156 | m_in_buf.IncWriteOffset(ret); 157 | 158 | m_last_recv_tick = get_tick_count(); 159 | } 160 | 161 | // 每次请求对应一个HTTP连接,所以读完数据后,不用在同一个连接里面准备读取下个请求 162 | char* in_buf = (char*)m_in_buf.GetBuffer(); 163 | uint32_t buf_len = m_in_buf.GetWriteOffset(); 164 | in_buf[buf_len] = '\0'; 165 | 166 | //log("OnRead, buf_len=%u, conn_handle=%u\n", buf_len, m_conn_handle); // for debug 167 | 168 | CHttpParserWrapper* pHttpParser = CHttpParserWrapper::GetInstance(); 169 | pHttpParser->ParseHttpContent(in_buf, buf_len); 170 | 171 | if (pHttpParser->IsReadAll()) { 172 | string url = pHttpParser->GetUrl(); 173 | if (strncmp(url.c_str(), "/query/", 7) == 0) { 174 | string content = pHttpParser->GetBodyContent(); 175 | CHttpQuery* pQueryInstance = CHttpQuery::GetInstance(); 176 | pQueryInstance->DispatchQuery(url, content, this); 177 | } else { 178 | log("url unknown, url=%s\n", url.c_str()); 179 | Close(); 180 | } 181 | } 182 | } 183 | 184 | void CHttpConn::OnWrite() 185 | { 186 | if (!m_busy) 187 | return; 188 | 189 | int ret = netlib_send(m_sock_handle, m_out_buf.GetBuffer(), m_out_buf.GetWriteOffset()); 190 | if (ret < 0) 191 | ret = 0; 192 | 193 | int out_buf_size = (int)m_out_buf.GetWriteOffset(); 194 | 195 | m_out_buf.Read(NULL, ret); 196 | 197 | if (ret < out_buf_size) 198 | { 199 | m_busy = true; 200 | log("not send all, remain=%d\n", m_out_buf.GetWriteOffset()); 201 | } 202 | else 203 | { 204 | m_busy = false; 205 | } 206 | } 207 | 208 | void CHttpConn::OnClose() 209 | { 210 | Close(); 211 | } 212 | 213 | void CHttpConn::OnTimer(uint64_t curr_tick) 214 | { 215 | if (curr_tick > m_last_recv_tick + HTTP_CONN_TIMEOUT) { 216 | log("HttpConn timeout, handle=%d\n", m_conn_handle); 217 | Close(); 218 | } 219 | } 220 | 221 | 222 | -------------------------------------------------------------------------------- /src/msfs/main.cpp: -------------------------------------------------------------------------------- 1 | /*================================================================ 2 | * Copyright (C) 2014 All rights reserved. 3 | * 4 | * @ File : main.cpp 5 | * @ Author : Zhang Yuanhao 6 | * @ Email : bluefoxah@gmail.com 7 | * @ Date : 2014年7月29日 8 | * @ Version : 1.0 9 | * @ Description : 10 | * 11 | ================================================================*/ 12 | 13 | #include 14 | #include 15 | #include "netlib.h" 16 | #include "ConfigFileReader.h" 17 | #include "HttpConn.h" 18 | #include "FileManager.h" 19 | #include "ThreadPool.h" 20 | 21 | using namespace std; 22 | using namespace msfs; 23 | 24 | 25 | FileManager* FileManager::m_instance = NULL; 26 | FileManager* g_fileManager = NULL; 27 | CConfigFileReader config_file("msfs.conf"); 28 | CThreadPool g_PostThreadPool; 29 | CThreadPool g_GetThreadPool; 30 | 31 | void closeall(int fd) 32 | { 33 | int fdlimit = sysconf(_SC_OPEN_MAX); 34 | 35 | while (fd < fdlimit) 36 | close(fd++); 37 | } 38 | 39 | int daemon(int nochdir, int noclose, int asroot) 40 | { 41 | switch (fork()) 42 | { 43 | case 0: break; 44 | case -1: return -1; 45 | default: _exit(0); /* exit the original process */ 46 | } 47 | 48 | if (setsid() < 0) /* shoudn't fail */ 49 | return -1; 50 | 51 | if ( !asroot && (setuid(1) < 0) ) /* shoudn't fail */ 52 | return -1; 53 | 54 | /* dyke out this switch if you want to acquire a control tty in */ 55 | /* the future -- not normally advisable for daemons */ 56 | 57 | switch (fork()) 58 | { 59 | case 0: break; 60 | case -1: return -1; 61 | default: _exit(0); 62 | } 63 | 64 | if (!nochdir) 65 | chdir("/"); 66 | 67 | if (!noclose) 68 | { 69 | closeall(0); 70 | dup(0); dup(0); 71 | } 72 | 73 | return 0; 74 | } 75 | 76 | // for client connect in 77 | void http_callback(void* callback_data, uint8_t msg, uint32_t handle, 78 | void* pParam) 79 | { 80 | if (msg == NETLIB_MSG_CONNECT) 81 | { 82 | CHttpConn* pConn = new CHttpConn(); 83 | // CHttpTask* pTask = new CHttpTask(handle, pConn); 84 | // g_ThreadPool.AddTask(pTask); 85 | pConn->OnConnect(handle); 86 | } else 87 | { 88 | log("!!!error msg: %d\n", msg); 89 | } 90 | } 91 | 92 | void doQuitJob() 93 | { 94 | char fileCntBuf[20] = {0}; 95 | snprintf(fileCntBuf, 20, "%llu", g_fileManager->getFileCntCurr()); 96 | config_file.SetConfigValue("FileCnt", fileCntBuf); 97 | FileManager::destroyInstance(); 98 | netlib_destroy(); 99 | log("I'm ready quit...\n"); 100 | } 101 | void Stop(int signo) 102 | { 103 | switch(signo) 104 | { 105 | case SIGINT: 106 | case SIGTERM: 107 | case SIGHUP: 108 | case SIGQUIT: 109 | doQuitJob(); 110 | _exit(0); 111 | break; 112 | default: 113 | cout<< "unknown signal"<initDir(); 164 | if (ret) { 165 | printf("The BaseDir is set incorrectly :%s\n",base_dir); 166 | return ret; 167 | } 168 | ret = netlib_init(); 169 | if (ret == NETLIB_ERROR) 170 | return ret; 171 | 172 | CStrExplode listen_ip_list(listen_ip, ';'); 173 | for (uint32_t i = 0; i < listen_ip_list.GetItemCnt(); i++) 174 | { 175 | ret = netlib_listen(listen_ip_list.GetItem(i), listen_port, 176 | http_callback, NULL); 177 | if (ret == NETLIB_ERROR) 178 | return ret; 179 | } 180 | 181 | signal(SIGINT, Stop); 182 | signal (SIGTERM, Stop); 183 | signal (SIGHUP, Stop); 184 | signal (SIGQUIT, Stop); 185 | 186 | printf("server start listen on: %s:%d\n", listen_ip, listen_port); 187 | init_http_conn(); 188 | printf("now enter the event loop...\n"); 189 | 190 | netlib_eventloop(); 191 | return 0; 192 | } 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/msfs/include/http/HttpParserWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // HttpPdu.h 3 | // http_msg_server 4 | // 5 | // Created by jianqing.du on 13-9-29. 6 | // Copyright (c) 2013骞� ziteng. All rights reserved. 7 | // 8 | 9 | #ifndef http_msg_server_HttpParserWrapper_h 10 | #define http_msg_server_HttpParserWrapper_h 11 | 12 | #include "util.h" 13 | #include "HttpParser.h" 14 | 15 | // extract url and content body from an ajax request 16 | class CHttpParserWrapper 17 | { 18 | public: 19 | 20 | CHttpParserWrapper(); 21 | virtual ~CHttpParserWrapper() 22 | { 23 | } 24 | 25 | void ParseHttpContent(const char* buf, uint32_t len); 26 | 27 | bool IsReadAll() 28 | { 29 | return m_read_all; 30 | } 31 | bool IsReadReferer() 32 | { 33 | return m_read_referer; 34 | } 35 | bool HasReadReferer() 36 | { 37 | return m_referer.size() > 0; 38 | } 39 | bool IsReadForwardIP() 40 | { 41 | return m_read_forward_ip; 42 | } 43 | bool HasReadForwardIP() 44 | { 45 | return m_forward_ip.size() > 0; 46 | } 47 | bool IsReadUserAgent() 48 | { 49 | return m_read_user_agent; 50 | } 51 | bool HasReadUserAgent() 52 | { 53 | return m_user_agent.size() > 0; 54 | } 55 | bool IsReadContentType() 56 | { 57 | return m_read_content_type; 58 | } 59 | bool HasReadContentType() 60 | { 61 | return m_content_type.size() > 0; 62 | } 63 | bool IsReadContentLen() 64 | { 65 | return m_read_content_len; 66 | } 67 | bool HasReadContentLen() 68 | { 69 | return m_content_len != 0; 70 | } 71 | bool IsReadHost() 72 | { 73 | return m_read_host; 74 | } 75 | bool HasReadHost() 76 | { 77 | return m_read_host; 78 | } 79 | 80 | uint32_t GetTotalLength() 81 | { 82 | return m_total_length; 83 | } 84 | char* GetUrl() 85 | { 86 | return (char*) m_url.c_str(); 87 | } 88 | char* GetBodyContent() 89 | { 90 | return (char*) m_body_content.c_str(); 91 | } 92 | uint32_t GetBodyContentLen() 93 | { 94 | return m_body_content.length(); 95 | } 96 | char* GetReferer() 97 | { 98 | return (char*) m_referer.c_str(); 99 | } 100 | char* GetForwardIP() 101 | { 102 | return (char*)m_forward_ip .c_str(); 103 | } 104 | char* GetUserAgent() 105 | { 106 | return (char*) m_user_agent.c_str(); 107 | } 108 | char GetMethod() 109 | { 110 | return (char) m_http_parser.method; 111 | } 112 | char* GetContentType() 113 | { 114 | return (char*) m_content_type.c_str(); 115 | } 116 | uint32_t GetContentLen() 117 | { 118 | return m_content_len; 119 | } 120 | char* GetHost() 121 | { 122 | return (char*) m_host.c_str(); 123 | } 124 | 125 | void SetUrl(const char* url, size_t length) 126 | { 127 | m_url.append(url, length); 128 | } 129 | void SetReferer(const char* referer, size_t length) 130 | { 131 | m_referer.append(referer, length); 132 | } 133 | void SetForwardIP(const char* forward_ip, size_t length) 134 | { 135 | m_forward_ip.append(forward_ip, length); 136 | } 137 | void SetUserAgent(const char* user_agent, size_t length) 138 | { 139 | m_user_agent.append(user_agent, length); 140 | } 141 | void SetBodyContent(const char* content, size_t length) 142 | { 143 | m_body_content.append(content, length); 144 | } 145 | void SetContentType(const char* content_type, size_t length) 146 | { 147 | m_content_type.append(content_type, length); 148 | } 149 | void SetContentLen(uint32_t content_len) 150 | { 151 | m_content_len = content_len; 152 | } 153 | void SetTotalLength(uint32_t total_len) 154 | { 155 | m_total_length = total_len; 156 | } 157 | void SetHost(const char* host, size_t length) 158 | { 159 | m_host.append(host, length); 160 | } 161 | void SetReadAll() 162 | { 163 | m_read_all = true; 164 | } 165 | void SetReadReferer(bool read_referer) 166 | { 167 | m_read_referer = read_referer; 168 | } 169 | void SetReadForwardIP(bool read_forward_ip) 170 | { 171 | m_read_forward_ip = read_forward_ip; 172 | } 173 | void SetReadUserAgent(bool read_user_agent) 174 | { 175 | m_read_user_agent = read_user_agent; 176 | } 177 | void SetReadContentType(bool read_content_type) 178 | { 179 | m_read_content_type = read_content_type; 180 | } 181 | void SetReadContentLen(bool read_content_len) 182 | { 183 | m_read_content_len = read_content_len; 184 | } 185 | void SetReadHost(bool read_host) 186 | { 187 | m_read_host = read_host; 188 | } 189 | 190 | static int OnUrl(http_parser* parser, const char *at, size_t length, void* obj); 191 | static int OnHeaderField(http_parser* parser, const char *at, 192 | size_t length, void* obj); 193 | static int OnHeaderValue(http_parser* parser, const char *at, 194 | size_t length, void* obj); 195 | static int OnHeadersComplete(http_parser* parser, void* obj); 196 | static int OnBody(http_parser* parser, const char *at, size_t length, void* obj); 197 | static int OnMessageComplete(http_parser* parser, void* obj); 198 | 199 | private: 200 | 201 | private: 202 | 203 | http_parser m_http_parser; 204 | http_parser_settings m_settings; 205 | 206 | bool m_read_all; 207 | bool m_read_referer; 208 | bool m_read_forward_ip; 209 | bool m_read_user_agent; 210 | bool m_read_content_type; 211 | bool m_read_content_len; 212 | bool m_read_host; 213 | uint32_t m_total_length; 214 | string m_url; 215 | string m_body_content; 216 | string m_referer; 217 | string m_forward_ip; 218 | string m_user_agent; 219 | string m_content_type; 220 | uint32_t m_content_len; 221 | string m_host; 222 | }; 223 | 224 | #endif 225 | -------------------------------------------------------------------------------- /src/base/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | CThread::CThread() 4 | { 5 | m_thread_id = 0; 6 | } 7 | 8 | CThread::~CThread() 9 | { 10 | } 11 | 12 | #ifdef _WIN32 13 | DWORD WINAPI CThread::StartRoutine(LPVOID arg) 14 | #else 15 | void* CThread::StartRoutine(void* arg) 16 | #endif 17 | { 18 | CThread* pThread = (CThread*)arg; 19 | 20 | pThread->OnThreadRun(); 21 | 22 | #ifdef _WIN32 23 | return 0; 24 | #else 25 | return NULL; 26 | #endif 27 | } 28 | 29 | void CThread::StartThread() 30 | { 31 | #ifdef _WIN32 32 | (void)CreateThread(NULL, 0, StartRoutine, this, 0, &m_thread_id); 33 | #else 34 | (void)pthread_create(&m_thread_id, NULL, StartRoutine, this); 35 | #endif 36 | } 37 | 38 | CEventThread::CEventThread() 39 | { 40 | m_bRunning = false; 41 | } 42 | 43 | CEventThread::~CEventThread() 44 | { 45 | StopThread(); 46 | } 47 | 48 | void CEventThread::StartThread() 49 | { 50 | m_bRunning = true; 51 | CThread::StartThread(); 52 | } 53 | 54 | void CEventThread::StopThread() 55 | { 56 | m_bRunning = false; 57 | } 58 | 59 | void CEventThread::OnThreadRun() 60 | { 61 | while (m_bRunning) 62 | { 63 | OnThreadTick(); 64 | } 65 | } 66 | 67 | /////////// CThreadLock /////////// 68 | CThreadLock::CThreadLock() 69 | { 70 | #ifdef _WIN32 71 | InitializeCriticalSection(&m_critical_section); 72 | #else 73 | pthread_mutexattr_init(&m_mutexattr); 74 | pthread_mutexattr_settype(&m_mutexattr, PTHREAD_MUTEX_RECURSIVE); 75 | pthread_mutex_init(&m_mutex, &m_mutexattr); 76 | #endif 77 | } 78 | 79 | CThreadLock::~CThreadLock() 80 | { 81 | #ifdef _WIN32 82 | DeleteCriticalSection(&m_critical_section); 83 | #else 84 | pthread_mutexattr_destroy(&m_mutexattr); 85 | pthread_mutex_destroy(&m_mutex); 86 | #endif 87 | } 88 | 89 | void CThreadLock::Lock(void) 90 | { 91 | #ifdef _WIN32 92 | EnterCriticalSection(&m_critical_section); 93 | #else 94 | pthread_mutex_lock(&m_mutex); 95 | #endif 96 | } 97 | 98 | void CThreadLock::Unlock(void) 99 | { 100 | #ifdef _WIN32 101 | LeaveCriticalSection(&m_critical_section); 102 | #else 103 | pthread_mutex_unlock(&m_mutex); 104 | #endif 105 | } 106 | 107 | CRefObject::CRefObject() 108 | { 109 | m_lock = NULL; 110 | m_refCount = 1; 111 | } 112 | 113 | CRefObject::~CRefObject() 114 | { 115 | 116 | } 117 | 118 | void CRefObject::AddRef() 119 | { 120 | if (m_lock) 121 | { 122 | m_lock->Lock(); 123 | m_refCount++; 124 | m_lock->Unlock(); 125 | } 126 | else 127 | { 128 | m_refCount++; 129 | } 130 | } 131 | 132 | void CRefObject::ReleaseRef() 133 | { 134 | if (m_lock) 135 | { 136 | m_lock->Lock(); 137 | m_refCount--; 138 | if (m_refCount == 0) 139 | { 140 | delete this; 141 | return; 142 | } 143 | m_lock->Unlock(); 144 | } 145 | else 146 | { 147 | m_refCount--; 148 | if (m_refCount == 0) 149 | delete this; 150 | } 151 | } 152 | 153 | /* 154 | static void print_thread_id(FILE* fp) 155 | { 156 | uint16_t thread_id = 0; 157 | #ifdef _WIN32 158 | thread_id = (uint16_t)GetCurrentThreadId(); 159 | #elif __APPLE__ 160 | thread_id = syscall(SYS_gettid); 161 | #else 162 | thread_id = (uint16_t)pthread_self(); 163 | #endif 164 | fprintf(fp, "(tid=%d)", thread_id); 165 | } 166 | */ 167 | 168 | static void print_format_time(FILE* fp) 169 | { 170 | #ifdef _WIN32 171 | SYSTEMTIME systemTime; 172 | 173 | GetLocalTime(&systemTime); 174 | fprintf(fp, "%04d-%02d-%02d, %02d:%02d:%02d.%03d, ", systemTime.wYear, systemTime.wMonth, systemTime.wDay, 175 | systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds); 176 | #else 177 | struct timeval tval; 178 | struct tm* tm; 179 | time_t currTime; 180 | 181 | time(&currTime); 182 | tm = localtime(&currTime); 183 | gettimeofday(&tval, NULL); 184 | fprintf(fp, "%04d-%02d-%02d, %02d:%02d:%02d.%03d, ", 1900 + tm->tm_year, 1 + tm->tm_mon, 185 | tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tval.tv_usec / 1000); 186 | #endif 187 | } 188 | 189 | void log(const char* fmt, ...) 190 | { 191 | static int file_no = 1; 192 | static FILE* log_fp = NULL; 193 | if (log_fp == NULL) 194 | { 195 | char log_name[64]; 196 | uint32_t pid = 0; 197 | #ifdef _WIN32 198 | pid = (uint32_t)GetCurrentProcessId(); 199 | #else 200 | pid = (uint32_t)getpid(); 201 | #endif 202 | snprintf(log_name, 64, "log_%d_%d.txt", pid, file_no); 203 | log_fp = fopen(log_name, "w"); 204 | if (log_fp == NULL) 205 | return; 206 | } 207 | 208 | // single thread, so remove print_thread_id 209 | //print_thread_id(log_fp); 210 | 211 | print_format_time(log_fp); 212 | 213 | va_list ap; 214 | va_start(ap, fmt); 215 | vfprintf(log_fp, fmt, ap); 216 | va_end(ap); 217 | fflush(log_fp); 218 | 219 | if (ftell(log_fp) > MAX_LOG_FILE_SIZE) 220 | { 221 | fclose(log_fp); 222 | log_fp = NULL; 223 | file_no++; 224 | } 225 | } 226 | 227 | uint64_t get_tick_count() 228 | { 229 | #ifdef _WIN32 230 | LARGE_INTEGER liCounter; 231 | LARGE_INTEGER liCurrent; 232 | 233 | if (!QueryPerformanceFrequency(&liCounter)) 234 | return GetTickCount(); 235 | 236 | QueryPerformanceCounter(&liCurrent); 237 | return (uint64_t)(liCurrent.QuadPart * 1000 / liCounter.QuadPart); 238 | #else 239 | struct timeval tval; 240 | uint64_t ret_tick; 241 | 242 | gettimeofday(&tval, NULL); 243 | 244 | ret_tick = tval.tv_sec * 1000L + tval.tv_usec / 1000L; 245 | return ret_tick; 246 | #endif 247 | } 248 | 249 | void util_sleep(uint32_t millisecond) 250 | { 251 | #ifdef _WIN32 252 | Sleep(millisecond); 253 | #else 254 | usleep(millisecond * 1000); 255 | #endif 256 | } 257 | 258 | CStrExplode::CStrExplode(char* str, char seperator) 259 | { 260 | m_item_cnt = 1; 261 | char* pos = str; 262 | while (*pos) { 263 | if (*pos == seperator) { 264 | m_item_cnt++; 265 | } 266 | 267 | pos++; 268 | } 269 | 270 | m_item_list = new char* [m_item_cnt]; 271 | 272 | int idx = 0; 273 | char* start = pos = str; 274 | while (*pos) { 275 | if (*pos == seperator) { 276 | uint32_t len = pos - start; 277 | m_item_list[idx] = new char [len + 1]; 278 | strncpy(m_item_list[idx], start, len); 279 | m_item_list[idx][len] = '\0'; 280 | idx++; 281 | 282 | start = pos + 1; 283 | } 284 | 285 | pos++; 286 | } 287 | 288 | uint32_t len = pos - start; 289 | m_item_list[idx] = new char [len + 1]; 290 | strncpy(m_item_list[idx], start, len); 291 | m_item_list[idx][len] = '\0'; 292 | } 293 | 294 | CStrExplode::~CStrExplode() 295 | { 296 | for (uint32_t i = 0; i < m_item_cnt; i++) { 297 | delete [] m_item_list[i]; 298 | } 299 | 300 | delete [] m_item_list; 301 | } 302 | 303 | -------------------------------------------------------------------------------- /src/msg_server/FileHandler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * FileHandler.cpp 3 | * 4 | * Created on: 2013-12-17 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "FileHandler.h" 9 | #include "MsgConn.h" 10 | #include "RouteServConn.h" 11 | #include "DBServConn.h" 12 | #include "ImUser.h" 13 | #include "AttachData.h" 14 | #include "FileServConn.h" 15 | 16 | CFileHandler* CFileHandler::s_handler_instance = NULL; 17 | 18 | CFileHandler* CFileHandler::getInstance() 19 | { 20 | if (!s_handler_instance) { 21 | s_handler_instance = new CFileHandler(); 22 | } 23 | 24 | return s_handler_instance; 25 | } 26 | 27 | void CFileHandler::HandleClientFileRequest(CMsgConn* pMsgConn, CImPduClientFileRequest* pPdu) 28 | { 29 | string from_id_url(pPdu->GetFromId(), pPdu->GetFromIdLen()); 30 | uint32_t from_id = urltoid(from_id_url.c_str()); 31 | string to_id_url(pPdu->GetToId(), pPdu->GetToIdLen()); 32 | uint32_t to_id = urltoid(to_id_url.c_str()); 33 | string file_name(pPdu->GetFileName(), pPdu->GetFileNameLen()); 34 | uint32_t file_size = pPdu->GetFileSize(); 35 | log("HandleClientFileRequest, %u->%u, fileName: %s\n", from_id, to_id, file_name.c_str()); 36 | 37 | CPduAttachData attach(ATTACH_TYPE_HANDLE, pMsgConn->GetHandle(), 0, NULL, 0); 38 | 39 | CImUser* pUser = CImUserManager::GetInstance()->GetImUserById(to_id); 40 | if (pUser) 41 | { 42 | uint32_t client_type_flag = pUser->GetClientTypeFlag(); 43 | //to_user has pc_client in this msg_server 44 | if ((client_type_flag & CLIENT_TYPE_FLAG_BOTH) == CLIENT_TYPE_FLAG_PC) 45 | { 46 | CFileServConn* pFileConn = get_random_file_serv_conn(); 47 | if (pFileConn) 48 | { 49 | CImPduMsgFileTransferReq pdu(from_id, to_id, file_name.c_str(), file_size, 50 | FILE_TYPE_ONLINE, attach.GetLength(), attach.GetBuffer()); 51 | pdu.SetReserved(pPdu->GetReserved()); 52 | pFileConn->SendPdu(&pdu); 53 | } 54 | else 55 | { 56 | log("HandleClientFileRequest, no file server.\n"); 57 | CImPduClientFileResponse pdu2(REFUSE_REASON_NO_FILE_SERVER, from_id_url.c_str(), 58 | to_id_url.c_str(), file_name.c_str(), NULL, NULL, 0); 59 | pdu2.SetReserved(pPdu->GetReserved()); 60 | pMsgConn->SendPdu(&pdu2); 61 | } 62 | return; 63 | } 64 | } 65 | else 66 | { 67 | //no pc_client in this msg_server, check it from route_server 68 | CRouteServConn* pConn = get_route_serv_conn(); 69 | CPduAttachData pduAttachData(ATTACH_TYPE_HANDLE_AND_PDU, pMsgConn->GetHandle(), 70 | pPdu->GetLength(), pPdu->GetBuffer()); 71 | CImPduUserClientTypeRequest pdu3(to_id, pduAttachData.GetLength(), pduAttachData.GetBuffer()); 72 | pdu3.SetReserved(pPdu->GetReserved()); 73 | pConn->SendPdu(&pdu3); 74 | } 75 | } 76 | 77 | void CFileHandler::HandleClientFileHasOfflineReq(CMsgConn* pMsgConn, CImPduClientFileHasOfflineReq* pPdu) 78 | { 79 | uint32_t req_user_id = pMsgConn->GetUserId(); 80 | log("HandleClientFileHasOfflineReq, req_id=%u\n", req_user_id); 81 | 82 | CDbAttachData attach_data(ATTACH_TYPE_HANDLE, pMsgConn->GetHandle(), 0); 83 | CDBServConn* pDbConn = get_db_serv_conn(); 84 | if (pDbConn) { 85 | CImPduFileHasOfflineReq pdu(req_user_id, attach_data.GetLength(), attach_data.GetBuffer()); 86 | pdu.SetReserved(pPdu->GetReserved()); 87 | pDbConn->SendPdu(&pdu); 88 | } else { 89 | log("warning no DB connection available\n"); 90 | CImPduClientFileHasOfflineRes pdu; 91 | pdu.SetReserved(pPdu->GetReserved()); 92 | pMsgConn->SendPdu(&pdu); 93 | } 94 | } 95 | 96 | void CFileHandler::HandleClientFileAddOfflineReq(CImPduClientFileAddOfflineReq* pPdu) 97 | { 98 | string from_id_url(pPdu->GetFromId(), pPdu->GetFromIdLen()); 99 | string to_id_url(pPdu->GetToId(), pPdu->GetToIdLen()); 100 | string task_id(pPdu->GetTaskId(), pPdu->GetTaskIdLen()); 101 | string file_name(pPdu->GetFileName(), pPdu->GetFileNameLen()); 102 | uint32_t file_size = pPdu->GetFileSize(); 103 | uint32_t from_id = urltoid(from_id_url.c_str()); 104 | uint32_t to_id = urltoid(to_id_url.c_str()); 105 | log("HandleClientFileAddOfflineReq, %u->%u, task_id: %s, file_name: %s, size: %u \n", 106 | from_id, to_id, task_id.c_str(), file_name.c_str(), file_size); 107 | 108 | CDBServConn* pDbConn = get_db_serv_conn(); 109 | if (pDbConn) { 110 | CImPduFileAddOfflineReq pdu(from_id, from_id, to_id, task_id.c_str(), file_name.c_str(), file_size); 111 | pDbConn->SendPdu(&pdu); 112 | } 113 | } 114 | 115 | void CFileHandler::HandleClientFileDelOfflineReq(CImPduClientFileDelOfflineReq* pPdu) 116 | { 117 | string from_id_url(pPdu->GetFromId(), pPdu->GetFromIdLen()); 118 | string to_id_url(pPdu->GetToId(), pPdu->GetToIdLen()); 119 | uint32_t from_id = urltoid(from_id_url.c_str()); 120 | uint32_t to_id = urltoid(to_id_url.c_str()); 121 | string task_id(pPdu->GetTaskId(), pPdu->GetTaskIdLen()); 122 | log("HandleClientFileDelOfflineReq, %u->%u, task_id=%s\n", from_id, to_id, task_id.c_str()); 123 | 124 | CDBServConn* pDbConn = get_db_serv_conn(); 125 | if (pDbConn) { 126 | CImPduFileDelOfflineReq pdu(to_id, from_id, to_id, task_id.c_str()); 127 | pDbConn->SendPdu(&pdu); 128 | } 129 | } 130 | 131 | /////////// for server 132 | void CFileHandler::HandleFileHasOfflineRes(CImPduFileHasOfflineRes* pPdu) 133 | { 134 | uint32_t req_user_id = pPdu->GetReqUserId(); 135 | uint32_t file_cnt = pPdu->GetFileCnt(); 136 | offline_file_t* file_list = pPdu->GetFileList(); 137 | CDbAttachData attach(pPdu->GetAttachData(), pPdu->GetAttachLen()); 138 | log("HandleFileHasOfflineRes, req_id=%u, file_cnt=%u\n", req_user_id, file_cnt); 139 | 140 | CMsgConn* pConn = CImUserManager::GetInstance()->GetMsgConnByHandle(req_user_id, 141 | attach.GetHandle()); 142 | CFileServConn* pFileConn = get_random_file_serv_conn(); 143 | const list* ip_list = NULL; 144 | if (pFileConn) 145 | { 146 | ip_list = pFileConn->GetFileServerIPList(); 147 | } 148 | else 149 | { 150 | log("HandleFileHasOfflineRes, no file server.\n"); 151 | } 152 | if (pConn) { 153 | 154 | CImPduClientFileHasOfflineRes pdu(file_cnt, file_list, ip_list); 155 | pdu.SetReserved(pPdu->GetReserved()); 156 | pConn->SendPdu(&pdu); 157 | } 158 | } 159 | 160 | 161 | void CFileHandler::HandleFileNotify(CImPduFileNotify *pPdu) 162 | { 163 | uint32_t from_user_id = pPdu->GetFromId(); 164 | uint32_t to_user_id = pPdu->GetToId(); 165 | string file_name(pPdu->GetFileName(), pPdu->GetFileNameLen()); 166 | uint32_t file_size = pPdu->GetFileSize(); 167 | string task_id(pPdu->GetTaskId(), pPdu->GetTaskIdLen()); 168 | string listen_ip(pPdu->GetListenIp(), pPdu->GetListenIpLen()); 169 | uint32_t listen_port = pPdu->GetListenPort(); 170 | log("HandleFileNotify, from_id: %u, to_id: %u, file_name: %s, task_id: %s, file_server_ip: %s,\ 171 | file_server_port: %u.\n", from_user_id, to_user_id, file_name.c_str(), task_id.c_str(), 172 | listen_ip.c_str(), listen_port); 173 | CImUser* pUser = CImUserManager::GetInstance()->GetImUserById(to_user_id); 174 | if (pUser) { 175 | CImPduClientFileNotify pdu(idtourl(from_user_id), idtourl(to_user_id), file_name.c_str(), 176 | file_size, task_id.c_str(), listen_ip.c_str(), listen_port); 177 | pUser->BroadcastPdu(&pdu); 178 | } 179 | } 180 | 181 | -------------------------------------------------------------------------------- /src/msg_server/FileServConn.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // FileServConn.cpp 3 | // public_TTServer 4 | // 5 | // Created by luoning on 14-8-19. 6 | // Copyright (c) 2014年 luoning. All rights reserved. 7 | // 8 | 9 | #include "FileServConn.h" 10 | #include "FileHandler.h" 11 | #include "util.h" 12 | #include "ImUser.h" 13 | #include "AttachData.h" 14 | #include "RouteServConn.h" 15 | #include "MsgConn.h" 16 | static ConnMap_t g_file_server_conn_map; 17 | 18 | static serv_info_t* g_file_server_list; 19 | static uint32_t g_file_server_count; 20 | static CFileHandler* s_file_handler = NULL; 21 | 22 | void file_server_conn_timer_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 23 | { 24 | ConnMap_t::iterator it_old; 25 | CFileServConn* pConn = NULL; 26 | uint64_t cur_time = get_tick_count(); 27 | 28 | for (ConnMap_t::iterator it = g_file_server_conn_map.begin(); it != g_file_server_conn_map.end(); 29 | ) 30 | { 31 | it_old = it; 32 | it++; 33 | pConn = (CFileServConn*)it_old->second; 34 | pConn->OnTimer(cur_time); 35 | } 36 | 37 | // reconnect FileServer 38 | serv_check_reconnect(g_file_server_list, g_file_server_count); 39 | } 40 | 41 | void init_file_serv_conn(serv_info_t* server_list, uint32_t server_count) 42 | { 43 | g_file_server_list = server_list; 44 | g_file_server_count = server_count; 45 | 46 | serv_init(g_file_server_list, g_file_server_count); 47 | 48 | netlib_register_timer(file_server_conn_timer_callback, NULL, 1000); 49 | s_file_handler = CFileHandler::getInstance(); 50 | } 51 | 52 | bool is_file_server_available() 53 | { 54 | CFileServConn* pConn = NULL; 55 | 56 | for (uint32_t i = 0; i < g_file_server_count; i++) { 57 | pConn = (CFileServConn*)g_file_server_list[i].serv_conn; 58 | if (pConn && pConn->IsOpen()) { 59 | return true; 60 | } 61 | } 62 | return false; 63 | } 64 | 65 | // 66 | CFileServConn* get_random_file_serv_conn() 67 | { 68 | CFileServConn* pConn = NULL; 69 | CFileServConn* pConnTmp = NULL; 70 | if (0 == g_file_server_count) { 71 | return pConn; 72 | } 73 | int32_t random_num = rand() % g_file_server_count; 74 | pConnTmp = (CFileServConn*)g_file_server_list[random_num].serv_conn; 75 | if (pConnTmp && pConnTmp->IsOpen()) 76 | { 77 | pConn = pConnTmp; 78 | } 79 | else 80 | { 81 | for (uint32_t i = 0; i < g_file_server_count; i++) 82 | { 83 | int j = (random_num + 1) % g_file_server_count; 84 | pConnTmp = (CFileServConn*)g_file_server_list[j].serv_conn; 85 | if (pConnTmp && pConnTmp->IsOpen()) 86 | { 87 | pConn = pConnTmp; 88 | } 89 | } 90 | } 91 | return pConn; 92 | } 93 | 94 | 95 | CFileServConn::CFileServConn() 96 | { 97 | m_bOpen = false; 98 | m_serv_idx = 0; 99 | } 100 | 101 | CFileServConn::~CFileServConn() 102 | { 103 | 104 | } 105 | 106 | void CFileServConn::Connect(const char* server_ip, uint16_t server_port, uint32_t idx) 107 | { 108 | log("Connecting to FileServer %s:%d\n", server_ip, server_port); 109 | 110 | m_serv_idx = idx; 111 | m_handle = netlib_connect(server_ip, server_port, imconn_callback, (void*)&g_file_server_conn_map); 112 | 113 | if (m_handle != NETLIB_INVALID_HANDLE) { 114 | g_file_server_conn_map.insert(make_pair(m_handle, this)); 115 | } 116 | } 117 | 118 | void CFileServConn::Close() 119 | { 120 | serv_reset(g_file_server_list, g_file_server_count, m_serv_idx); 121 | 122 | m_bOpen = false; 123 | if (m_handle != NETLIB_INVALID_HANDLE) { 124 | netlib_close(m_handle); 125 | g_file_server_conn_map.erase(m_handle); 126 | } 127 | 128 | ReleaseRef(); 129 | } 130 | 131 | void CFileServConn::OnConfirm() 132 | { 133 | log("connect to file server success\n"); 134 | m_bOpen = true; 135 | m_connect_time = get_tick_count(); 136 | g_file_server_list[m_serv_idx].reconnect_cnt = MIN_RECONNECT_CNT / 2; 137 | 138 | CImPduFileServerIPReq pdu; 139 | //SendPdu(&pdu); 140 | } 141 | 142 | void CFileServConn::OnClose() 143 | { 144 | log("onclose from file server handle=%d\n", m_handle); 145 | Close(); 146 | } 147 | 148 | void CFileServConn::OnTimer(uint64_t curr_tick) 149 | { 150 | if (curr_tick > m_last_send_tick + SERVER_HEARTBEAT_INTERVAL) { 151 | CImPduHeartbeat pdu; 152 | SendPdu(&pdu); 153 | } 154 | 155 | if (curr_tick > m_last_recv_tick + SERVER_TIMEOUT) { 156 | log("conn to file server timeout\n"); 157 | Close(); 158 | } 159 | } 160 | 161 | void CFileServConn::HandlePdu(CImPdu* pPdu) 162 | { 163 | switch (pPdu->GetPduType()) { 164 | case IM_PDU_TYPE_HEARTBEAT: 165 | break; 166 | case IM_PDU_TYPE_MSG_FILE_TRANSFER_RSP: 167 | _HandleFileMsgTransRsp((CImPduMsgFileTransferRsp*) pPdu); 168 | break; 169 | case IM_PDU_TYPE_FILE_SERVER_IP_REQUEST: 170 | _HandleFileServerIPRsp((CImPduFileServerIPRsp*)pPdu); 171 | break; 172 | default: 173 | log("unknown pdu_type=%d\n", pPdu->GetPduType()); 174 | break; 175 | } 176 | } 177 | 178 | void CFileServConn::_HandleFileMsgTransRsp(CImPduMsgFileTransferRsp* pPdu) 179 | { 180 | uint32_t result = pPdu->GetResult(); 181 | uint32_t from_id = pPdu->GetFromId(); 182 | uint32_t to_id = pPdu->GetToId(); 183 | string file_name(pPdu->GetFileName(), pPdu->GetFileNameLength()); 184 | uint32_t file_size = pPdu->GetFileLength(); 185 | string listen_ip(pPdu->GetFileServerIp(), pPdu->GetFileServerIpLength()); 186 | uint16_t listen_port = pPdu->GetFileServerPort(); 187 | string task_id(pPdu->GetTaskId(), pPdu->GetTaskIdLen()); 188 | CPduAttachData attach(pPdu->GetAttachData(), pPdu->GetAttachLen()); 189 | CImPduClientFileResponse pdu(result, idtourl(from_id), idtourl(to_id), file_name.c_str(), 190 | task_id.c_str(), listen_ip.c_str(), listen_port); 191 | pdu.SetReserved(pPdu->GetReserved()); 192 | uint32_t handle = attach.GetHandle(); 193 | log("HandleFileMsgTransRsp, result: %u, from_user_id: %u, to_user_id: %u, file_name: %s, \ 194 | task_id: %s, listen_ip: %s, listen_port: %u.\n", result, from_id, to_id, file_name.c_str(), 195 | task_id.c_str(), listen_ip.c_str(), listen_port); 196 | 197 | CMsgConn* pFromConn = CImUserManager::GetInstance()->GetMsgConnByHandle(from_id, handle); 198 | if (pFromConn) 199 | { 200 | pFromConn->SendPdu(&pdu); 201 | } 202 | 203 | if (result == 0) 204 | { 205 | //send notify to target user 206 | CImUser* pToUser = CImUserManager::GetInstance()->GetImUserById(to_id); 207 | if (pToUser) 208 | { 209 | CImPduClientFileNotify pdu2(idtourl(from_id), idtourl(to_id), file_name.c_str(), file_size, 210 | task_id.c_str(), listen_ip.c_str(), listen_port); 211 | pToUser->BroadcastPdu(&pdu2); 212 | } 213 | 214 | //send to route server 215 | CRouteServConn* pRouteConn = get_route_serv_conn(); 216 | if (pRouteConn) { 217 | CImPduFileNotify pdu3(from_id, to_id, file_name.c_str(), file_size, task_id.c_str(), 218 | listen_ip.c_str(), listen_port); 219 | pRouteConn->SendPdu(&pdu3); 220 | } 221 | } 222 | } 223 | 224 | void CFileServConn::_HandleFileServerIPRsp(CImPduFileServerIPRsp* pPdu) 225 | { 226 | uint32_t ip_addr_cnt = pPdu->GetIPCnt(); 227 | ip_addr_t* ip_addr_list = pPdu->GetIPList(); 228 | 229 | for (uint32_t i = 0; i < ip_addr_cnt ; i++) { 230 | m_ip_list.push_back(ip_addr_list[i]); 231 | } 232 | } -------------------------------------------------------------------------------- /src/msg_server/HttpQuery.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * HttpQuery.cpp 3 | * 4 | * Created on: 2013-10-22 5 | * Author: ziteng@mogujie.com 6 | */ 7 | 8 | #include "HttpQuery.h" 9 | #include "RouteServConn.h" 10 | #include "DBServConn.h" 11 | #include "LoginServConn.h" 12 | #include "ImUser.h" 13 | #include "GroupChat.h" 14 | static uint32_t g_total_query = 0; 15 | static uint32_t g_last_year = 0; 16 | static uint32_t g_last_month = 0; 17 | static uint32_t g_last_mday = 0; 18 | 19 | #define HTTP_QUEYR_HEADER "HTTP/1.1 200 OK\r\n"\ 20 | "Cache-Control:no-cache\r\n"\ 21 | "Connection:close\r\n"\ 22 | "Content-Length:%d\r\n"\ 23 | "Content-Type:text/html;charset=utf-8\r\n\r\n%s" 24 | 25 | CHttpQuery* CHttpQuery::m_query_instance = NULL; 26 | 27 | string PackSendOk() 28 | { 29 | jsonxx::Object json_obj; 30 | 31 | json_obj << "result" << 0; 32 | 33 | std::string json_str = json_obj.json(); 34 | char szRes[512] = {0}; 35 | sprintf(szRes, HTTP_QUEYR_HEADER, json_str.size(), json_str.c_str()); 36 | string response = szRes; 37 | return response; 38 | } 39 | 40 | inline char fromHex(const char &x) 41 | { 42 | return isdigit(x) ? x-'0' : x-'A'+10; 43 | } 44 | 45 | string URLDecode(const string &sIn) 46 | { 47 | string sOut; 48 | for( size_t ix = 0; ix < sIn.size(); ix++ ) 49 | { 50 | char ch = 0; 51 | if(sIn[ix]=='%') 52 | { 53 | ch = (fromHex(sIn[ix+1])<<4); 54 | ch |= fromHex(sIn[ix+2]); 55 | ix += 2; 56 | } 57 | else if(sIn[ix] == '+') 58 | { 59 | ch = ' '; 60 | } 61 | else 62 | { 63 | ch = sIn[ix]; 64 | } 65 | sOut += (char)ch; 66 | } 67 | return sOut; 68 | } 69 | 70 | 71 | void http_query_timer_callback(void* callback_data, uint8_t msg, uint32_t handle, void* pParam) 72 | { 73 | struct tm* tm; 74 | time_t currTime; 75 | 76 | time(&currTime); 77 | tm = localtime(&currTime); 78 | 79 | uint32_t year = tm->tm_year + 1900; 80 | uint32_t mon = tm->tm_mon + 1; 81 | uint32_t mday = tm->tm_mday; 82 | if (year != g_last_year || mon != g_last_month || mday != g_last_mday) { 83 | // a new day begin, clear the count 84 | log("a new day begin, g_total_query=%u\n", g_total_query); 85 | g_total_query = 0; 86 | g_last_year = year; 87 | g_last_month = mon; 88 | g_last_mday = mday; 89 | } 90 | } 91 | 92 | CHttpQuery* CHttpQuery::GetInstance() 93 | { 94 | if (!m_query_instance) { 95 | m_query_instance = new CHttpQuery(); 96 | netlib_register_timer(http_query_timer_callback, NULL, 1000); 97 | } 98 | 99 | return m_query_instance; 100 | } 101 | 102 | void CHttpQuery::DispatchQuery(std::string& url, std::string& post_data, CHttpConn* pHttpConn) 103 | { 104 | ++g_total_query; 105 | log("DispatchQuery, url=%s, content=%s\n", url.c_str(), post_data.c_str()); 106 | jsonxx::Object json_obj; 107 | 108 | if ( !json_obj.parse(post_data) ) { 109 | log("json parse failed, post_data=%s\n", post_data.c_str()); 110 | pHttpConn->Close(); 111 | return; 112 | } 113 | 114 | // process post request with post content 115 | if (strcmp(url.c_str(), "/query/createNormalGroup") == 0) { 116 | _QueryCreateNormalGroup(json_obj, pHttpConn); 117 | } 118 | else if (strcmp(url.c_str(), "/query/changeMembers") == 0) { 119 | _QueryChangeMember(json_obj, pHttpConn); 120 | } 121 | else { 122 | log("url not support\n"); 123 | pHttpConn->Close(); 124 | return; 125 | } 126 | } 127 | 128 | void CHttpQuery::_QueryCreateNormalGroup(jsonxx::Object &post_json_obj, CHttpConn *pHttpConn) 129 | { 130 | CRouteServConn *pConn = get_route_serv_conn(); 131 | if (!pConn) { 132 | log("no connection to RouteServConn\n"); 133 | pHttpConn->Close(); 134 | return; 135 | } 136 | if ( !post_json_obj.has("group_id") ) { 137 | log("no group id\n"); 138 | pHttpConn->Close(); 139 | return; 140 | } 141 | 142 | if (!post_json_obj.has("group_name")) { 143 | log("no group name\n"); 144 | pHttpConn->Close(); 145 | return; 146 | } 147 | 148 | if (!post_json_obj.has("group_avatar")) { 149 | log("no group avatar\n"); 150 | pHttpConn->Close(); 151 | return; 152 | } 153 | 154 | if (!post_json_obj.has("user_list")) { 155 | log("no user list\n"); 156 | pHttpConn->Close(); 157 | return; 158 | } 159 | 160 | string response = PackSendOk(); 161 | pHttpConn->Send((void*)response.c_str(), response.length()); 162 | pHttpConn->Close(); 163 | 164 | uint32_t group_id = post_json_obj.get("group_id"); 165 | string group_name = post_json_obj.get("group_name"); 166 | string group_avatar = post_json_obj.get("group_avatar"); 167 | group_name = URLDecode(group_name); 168 | jsonxx::Array user_array = post_json_obj.get("user_list"); 169 | uint32_t user_cnt = user_array.size(); 170 | log("QueryCreateNormalGroup, group_id: %u, group_name: %s, user_cnt: %u.\n", group_id, 171 | group_name.c_str(), user_cnt); 172 | uint32_t* user_list = NULL; 173 | if (user_cnt > 0) { 174 | user_list = new uint32_t[user_cnt]; 175 | if (NULL == user_list) { 176 | log("_QueryCreateNormalGroup, alloced failed"); 177 | return; 178 | } 179 | for (uint32_t i = 0; i < user_array.size(); i++) { 180 | user_list[i] = user_array.get(i); 181 | } 182 | } 183 | 184 | CGroupChat::GetInstance()->HandleGroupCreateNormalGroupNotify(group_id, group_name.c_str(), 185 | group_avatar.c_str(), user_cnt, user_list); 186 | 187 | CImPduGroupCreateNormalGroupNotify pdu(group_id, group_name.c_str(), group_avatar.c_str(), 188 | user_cnt, user_list); 189 | pConn->SendPdu(&pdu); 190 | } 191 | 192 | void CHttpQuery::_QueryChangeMember(jsonxx::Object &post_json_obj, CHttpConn *pHttpConn) 193 | { 194 | CRouteServConn *pConn = get_route_serv_conn(); 195 | if (!pConn) { 196 | log("no connection to RouteServConn\n"); 197 | pHttpConn->Close(); 198 | return; 199 | } 200 | if ( !post_json_obj.has("group_id") ) { 201 | log("no group id\n"); 202 | pHttpConn->Close(); 203 | return; 204 | } 205 | 206 | if (!post_json_obj.has("user_list")) { 207 | log("no user list\n"); 208 | pHttpConn->Close(); 209 | return; 210 | } 211 | 212 | string response = PackSendOk(); 213 | pHttpConn->Send((void*)response.c_str(), response.length()); 214 | pHttpConn->Close(); 215 | 216 | uint32_t group_id = post_json_obj.get("group_id"); 217 | jsonxx::Array user_array = post_json_obj.get("user_list"); 218 | uint32_t user_cnt = user_array.size(); 219 | log("QueryChangeMember, group_id: %u, user_cnt: %u.\n", group_id, 220 | user_cnt); 221 | 222 | uint32_t* user_list = NULL; 223 | if (user_cnt > 0) { 224 | user_list = new uint32_t[user_cnt]; 225 | if (NULL == user_list) { 226 | log("_QueryCreateNormalGroup, alloced failed"); 227 | return; 228 | } 229 | for (uint32_t i = 0; i < user_array.size(); i++) { 230 | user_list[i] = user_array.get(i); 231 | } 232 | } 233 | CGroupChat::GetInstance()->HandleGroupChangeMemberNotify(group_id, user_cnt, 234 | user_list); 235 | 236 | CImPduGroupChangeMemberNotify pdu( group_id, user_cnt, user_list); 237 | pConn->SendPdu(&pdu); 238 | 239 | } 240 | 241 | -------------------------------------------------------------------------------- /src/msfs/storage/FileManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Multimedia Small File Storage System 3 | * File Manager Singleton implement to manage file store and download operation 4 | * author potian@mogujie.com 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "FileManager.h" 15 | #include "FileLin.h" 16 | #include "StringUtils.h" 17 | #include "util.h" 18 | 19 | using namespace std; 20 | 21 | namespace msfs { 22 | 23 | int FileManager::initDir() { 24 | bool isExist = File::isExist(m_disk); 25 | if (!isExist) { 26 | u64 ret = File::mkdirNoRecursion(m_disk); 27 | if (ret) { 28 | log("The dir[%s] set error for code[%d], \ 29 | its parent dir may no exists\n", m_disk, ret); 30 | return -1; 31 | } 32 | } 33 | 34 | //255 X 255 35 | char first[10] = {0}; 36 | char second[10] = {0}; 37 | for (int i = 0; i <= FIRST_DIR_MAX; i++) { 38 | snprintf(first, 5, "%03d", i); 39 | string tmp = string(m_disk) + "/" + string(first); 40 | int code = File::mkdirNoRecursion(tmp.c_str()); 41 | if (code && (errno != EEXIST)) { 42 | log("Create dir[%s] error[%d]\n", tmp.c_str(), errno); 43 | return -1; 44 | } 45 | for (int j = 0; j <= SECOND_DIR_MAX; j++) { 46 | snprintf(second, 5, "%03d", j); 47 | string tmp2 = tmp + "/" + string(second); 48 | code = File::mkdirNoRecursion(tmp2.c_str()); 49 | if (code && (errno != EEXIST)) { 50 | log("Create dir[%s] error[%d]\n", tmp2.c_str(), errno); 51 | return -1; 52 | } 53 | memset(second, 0x0, 10); 54 | } 55 | memset(first, 0x0, 10); 56 | } 57 | 58 | return 0; 59 | } 60 | 61 | string FileManager::createFileRelatePath() { 62 | char first[10] = {0}; 63 | char second[10] = {0}; 64 | m_cs.Enter(); 65 | snprintf(first, 5, "%03d", (int)getFirstDir()); 66 | snprintf(second, 5, "%03d", (int)getSecondDir()); 67 | m_cs.Leave(); 68 | 69 | struct timeval tv; 70 | gettimeofday(&tv,NULL); 71 | u64 usec = tv.tv_sec*1000000 + tv.tv_usec; 72 | u64 tid = (u64)pthread_self(); 73 | char unique[40]; 74 | snprintf(unique, 30, "%llu_%llu", usec, tid); 75 | string path = "/" + string(first) + "/" + string(second) 76 | + "/" + string(unique); 77 | return string(path); 78 | } 79 | 80 | int FileManager::uploadFile(const char *type, const void* content, u32 size, 81 | char *url, char *ext) { 82 | //check file size 83 | if (size > MAX_FILE_SIZE_PER_FILE) { 84 | log("File size[%d] should less than [%d]\n", size, 85 | MAX_FILE_SIZE_PER_FILE); 86 | return -1; 87 | } 88 | 89 | //append the type suffix 90 | string path = createFileRelatePath(); 91 | if (ext) 92 | path += "_" + string(ext); 93 | else 94 | path += "." + string(type); 95 | 96 | //construct url with group num 97 | string groups("g0"); 98 | string fullUrl = groups + path; 99 | strncpy(url, fullUrl.c_str(), strlen(fullUrl.c_str())); 100 | 101 | //insert map file cache 102 | m_cs.Enter(); 103 | insertEntry(fullUrl, (u64)size, content); 104 | updateMapCache(); 105 | m_cs.Leave(); 106 | 107 | //open and write file then close 108 | string absPath = string(m_disk) + path; 109 | File * tmpFile = new File(absPath.c_str()); 110 | tmpFile->create(); 111 | tmpFile->write(0, size, content); 112 | delete tmpFile; 113 | tmpFile = NULL; 114 | 115 | //increase total file sum 116 | m_filesCs.Enter(); 117 | m_totFiles++; 118 | m_filesCs.Leave(); 119 | 120 | return 0; 121 | } 122 | 123 | int FileManager::getRelatePathByUrl(const string &url, string &path) { 124 | string::size_type pos = url.find("/"); 125 | if (string::npos == pos) { 126 | log("Url [%s] format illegal.\n",url.c_str()); 127 | return -1; 128 | } 129 | path = url.substr(pos); 130 | return 0; 131 | } 132 | 133 | int FileManager::getAbsPathByUrl(const string &url, string &path) { 134 | string relate; 135 | if (getRelatePathByUrl(url, relate)) { 136 | log("Get path from url[%s] error\n", url.c_str()); 137 | return -1; 138 | } 139 | path = string(m_disk) + relate; 140 | return 0; 141 | } 142 | 143 | 144 | FileManager::Entry* 145 | FileManager::getOrCreateEntry(const std::string& url, bool create) { 146 | m_cs.Enter(); 147 | EntryMap::iterator it = m_map.find(url); 148 | if (it != m_map.end()) { 149 | log("the map has the file while url:%s\n", url.c_str()); 150 | m_cs.Leave(); 151 | return it->second; 152 | } 153 | if (!create) { 154 | m_cs.Leave(); 155 | return NULL; 156 | } 157 | 158 | string path; 159 | if (getAbsPathByUrl(url, path)) { 160 | log("Get abs path from url[%s] error\n", url.c_str()); 161 | m_cs.Leave(); 162 | return NULL; 163 | } 164 | 165 | Entry *e = new Entry(); 166 | u64 fileSize = File::getFileSize(path.c_str()); 167 | e->m_fileSize = fileSize; 168 | e->m_fileContent = new byte[fileSize]; 169 | memset(e->m_fileContent, 0x0, fileSize); 170 | e->m_lastAccess = time(NULL); 171 | File* tmpFile = new File(path.c_str()); 172 | tmpFile->open(); 173 | int ret = tmpFile->read(0, fileSize, e->m_fileContent); 174 | if (ret) { 175 | log("read file error while url:%s\n", url.c_str()); 176 | delete e; 177 | e = NULL; 178 | delete tmpFile; 179 | tmpFile = NULL; 180 | m_cs.Leave(); 181 | return NULL; 182 | } 183 | delete tmpFile; 184 | tmpFile = NULL; 185 | 186 | std::pair < map ::iterator, bool> result; 187 | result = m_map.insert(EntryMap::value_type(url, e)); 188 | if (result.second == false) { 189 | log("Insert url[%s] to file map error\n", url.c_str()); 190 | delete e; 191 | e = NULL; 192 | } 193 | updateMapCache(); 194 | m_cs.Leave(); 195 | return e; 196 | } 197 | 198 | int FileManager::downloadFileByUrl(char *url, void *buf, u32 *size) { 199 | Entry* en = getOrCreateEntry(url, true); 200 | if (!en) { 201 | log("download file error, while url:%s\n", url); 202 | return -1; 203 | } 204 | memcpy(buf, en->m_fileContent, en->m_fileSize); 205 | *size = (u32)en->m_fileSize; 206 | en->m_lastAccess = time(NULL);//todo:need prodect with mutex 207 | return 0; 208 | } 209 | 210 | void FileManager::updateMapCache() { 211 | size_t currSize = m_map.size(); 212 | if (currSize > MAX_FILE_IN_MAP) { 213 | EntryMap::iterator it = m_map.begin(); 214 | int times = MAX_FILE_IN_MAP - currSize; 215 | while (it != m_map.end() && times) { 216 | delete it->second; 217 | m_map.erase(it++); 218 | times--; 219 | } 220 | 221 | it = m_map.begin(); 222 | while (it != m_map.end() && times) { 223 | time_t currTime = time(NULL); 224 | if(currTime - it->second->m_lastAccess > 2*60*60) { 225 | delete it->second; 226 | m_map.erase(it++); 227 | } 228 | } 229 | } 230 | } 231 | 232 | int FileManager::insertEntry(const std::string& url, size_t fileSize, 233 | const void* content) { 234 | if (m_map.size()) { 235 | EntryMap::iterator it = m_map.find(url); 236 | if (it != m_map.end()) 237 | return -1; 238 | } 239 | Entry *e = new Entry(); 240 | e->m_fileSize = fileSize; 241 | e->m_fileContent = new byte[fileSize]; 242 | e->m_lastAccess = time(NULL); 243 | memcpy(e->m_fileContent, content, fileSize); 244 | 245 | m_cs.Enter(); 246 | pair< map::iterator, bool> ret; 247 | ret = m_map.insert(EntryMap::value_type(url, e)); 248 | if (ret.second == false) { 249 | delete e; 250 | e = NULL; 251 | } 252 | updateMapCache(); 253 | m_cs.Leave(); 254 | return 0; 255 | } 256 | 257 | void FileManager::releaseFileCache(const std::string& url) { 258 | m_cs.Enter(); 259 | const Entry* entry = getEntry(url); 260 | if (!entry) { 261 | log("map has not the url::%s\n", url.c_str()); 262 | return; 263 | } 264 | delete [] entry->m_fileContent; 265 | m_map.erase(url); 266 | m_cs.Leave(); 267 | return; 268 | } 269 | 270 | } 271 | 272 | --------------------------------------------------------------------------------