init
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								Gateway/gateway/.DS_Store
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Gateway/gateway/.DS_Store
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										62
									
								
								Gateway/gateway/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								Gateway/gateway/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| cmake_minimum_required (VERSION 2.8.12.2) | ||||
|  | ||||
| #项目名 | ||||
| project (gate) | ||||
| #cmake_policy(SET CMP0015 OLD)  | ||||
|  | ||||
| #头文件 | ||||
| include_directories( | ||||
| 	./ | ||||
| ) | ||||
|  | ||||
| # 源文件及头文件 | ||||
| file(GLOB_RECURSE Gate_CODELIST "${PROJECT_SOURCE_DIR}/*.cc" "${PROJECT_SOURCE_DIR}/*.h") | ||||
|  | ||||
| # 代码分组 | ||||
| #group_by_dir(${PROJECT_SOURCE_DIR}/gateway ${Gate_CODELIST}) | ||||
|  | ||||
| #链接库 | ||||
| link_directories( ${Libs_Dir} ) | ||||
|  | ||||
| if(MSVC) | ||||
| 	set(GAME_LIBRARIES | ||||
| 		ws2_32 | ||||
| 		srv | ||||
| 		Mswsock | ||||
| 		Dbghelp | ||||
| 		Winmm | ||||
| 		libmysql | ||||
| 		mysqlclient | ||||
| 		common | ||||
| 	) | ||||
| else() | ||||
| 	set(GAME_LIBRARIES | ||||
| 		rt | ||||
| 		pthread | ||||
| 		mysqlclient | ||||
| 		#lua | ||||
| 		srv | ||||
| 		common | ||||
| 	) | ||||
| endif(MSVC) | ||||
|  | ||||
| # Gate输出目录 | ||||
| SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/../../Exec/Gateway) | ||||
| SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/../../Exec/Gateway) | ||||
|  | ||||
| if ( ${CMAKE_BUILD_TYPE} STREQUAL "Release" ) | ||||
|    set( _DEBUG  0 ) | ||||
| else () | ||||
|    set( _DEBUG  1 ) | ||||
| endif() | ||||
|  | ||||
| if ( _DEBUG  ) | ||||
|   set( EXE_NAME gateway_d ) | ||||
| else() | ||||
|   set( EXE_NAME gateway_r ) | ||||
| endif() | ||||
|  | ||||
| add_executable(${EXE_NAME} ${Gate_CODELIST}) | ||||
| add_dependencies(${EXE_NAME} common) | ||||
| target_link_libraries(${EXE_NAME} ${GAME_LIBRARIES}) | ||||
|  | ||||
							
								
								
									
										2
									
								
								Gateway/gateway/StdAfx.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								Gateway/gateway/StdAfx.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| #include "StdAfx.h" | ||||
|  | ||||
							
								
								
									
										81
									
								
								Gateway/gateway/StdAfx.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								Gateway/gateway/StdAfx.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
|  | ||||
| #define USE_EPOLL false | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <math.h> | ||||
| #include "os_def.h" | ||||
| #include <_ast.h> | ||||
|  | ||||
| #ifndef _MSC_VER | ||||
| #include <netinet/in.h> | ||||
| #include <netdb.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/errno.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <netinet/in.h> | ||||
| #include <arpa/inet.h> | ||||
| #endif | ||||
|  | ||||
| #include <x_thread.h> | ||||
| #include <net/base_socket.h> | ||||
| #include <x_lock.h> | ||||
| #include <x_tick.h> | ||||
| #include <container/queue_list.h> | ||||
| #include "share_util.h" | ||||
| #include "memory/buffer_allocator.h" | ||||
| #include "memory/memory_container.hpp" | ||||
| #include "appitnmsg.h" | ||||
| #include "data_packet.hpp" | ||||
| #include "data_packet_reader.hpp" | ||||
| #include "net/send_packet_pool.h" | ||||
| #include "net/work_socket.h" | ||||
| #include "net/net_client.h" | ||||
| #include "net/server_socket.h" | ||||
| #include "server_def.h" | ||||
| #include "gate/gate_proto.h" | ||||
|  | ||||
| #include <stream.h> | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #include "statistic/time_stat.h" | ||||
| #endif | ||||
|  | ||||
| #include "encrypt/CRC.h" | ||||
| #include "encrypt/Encrypt.h" | ||||
| #include "flog/file_logger.h" | ||||
|  | ||||
| #include "second_time.h" | ||||
| #include "container/static_hash_table.h" | ||||
|  | ||||
| #include <ref_class.hpp> | ||||
| #include <ref_string.hpp> | ||||
| #include <time.h> | ||||
|  | ||||
| #include "encrypt/EDPass.h" | ||||
|  | ||||
| extern "C" | ||||
| { | ||||
| #include <lua.h> | ||||
| #include <lualib.h> | ||||
| #include <lauxlib.h> | ||||
| } | ||||
| #include "luabase/base_lua.h" | ||||
| #include "luabase/base_lua_config.h" | ||||
| #include "luabase/script_value.hpp" | ||||
| #include "luabase/script_value_list.h" | ||||
| #include "luabase/lua_pre_process.h" | ||||
| #include "luabase/vsp_def.h" | ||||
| #include "luabase/base_script.h" | ||||
|  | ||||
| #include "utils/fdop.h" | ||||
|  | ||||
| #include "gate_def.h" | ||||
| #include "srv/socket_srv.h" | ||||
| #include "gate_server.h" | ||||
| #include "config/ws_gate_config.h" | ||||
| #include "client/client.h" | ||||
| #include "srv/game_client_mgr.h" | ||||
| #include "gameworld/game_world_client.h" | ||||
							
								
								
									
										590
									
								
								Gateway/gateway/base/sha1.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										590
									
								
								Gateway/gateway/base/sha1.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,590 @@ | ||||
| /* | ||||
|  *  sha1.cpp | ||||
|  * | ||||
|  *  Copyright (C) 1998, 2009 | ||||
|  *  Paul E. Jones <paulej@packetizer.com> | ||||
|  *  All Rights Reserved. | ||||
|  * | ||||
|  ***************************************************************************** | ||||
|  *  $Id: sha1.cpp 12 2009-06-22 19:34:25Z paulej $ | ||||
|  ***************************************************************************** | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This class implements the Secure Hashing Standard as defined | ||||
|  *      in FIPS PUB 180-1 published April 17, 1995. | ||||
|  * | ||||
|  *      The Secure Hashing Standard, which uses the Secure Hashing | ||||
|  *      Algorithm (SHA), produces a 160-bit message digest for a | ||||
|  *      given data stream.  In theory, it is highly improbable that | ||||
|  *      two messages will produce the same message digest.  Therefore, | ||||
|  *      this algorithm can serve as a means of providing a "fingerprint" | ||||
|  *      for a message. | ||||
|  * | ||||
|  *  Portability Issues: | ||||
|  *      SHA-1 is defined in terms of 32-bit "words".  This code was | ||||
|  *      written with the expectation that the processor has at least | ||||
|  *      a 32-bit machine word size.  If the machine word size is larger, | ||||
|  *      the code should still function properly.  One caveat to that | ||||
|  *      is that the input functions taking characters and character arrays | ||||
|  *      assume that only 8 bits of information are stored in each character. | ||||
|  * | ||||
|  *  Caveats: | ||||
|  *      SHA-1 is designed to work with messages less than 2^64 bits long. | ||||
|  *      Although SHA-1 allows a message digest to be generated for | ||||
|  *      messages of any number of bits less than 2^64, this implementation | ||||
|  *      only works with messages with a length that is a multiple of 8 | ||||
|  *      bits. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include "sha1.h" | ||||
|  | ||||
|  | ||||
| /*   | ||||
|  *  SHA1 | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This is the constructor for the sha1 class. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      None. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| SHA1::SHA1() | ||||
| { | ||||
|     Reset(); | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  ~SHA1 | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This is the destructor for the sha1 class | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      None. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| SHA1::~SHA1() | ||||
| { | ||||
|     // The destructor does nothing | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  Reset | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function will initialize the sha1 class member variables | ||||
|  *      in preparation for computing a new message digest. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      None. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| void SHA1::Reset() | ||||
| { | ||||
|     Length_Low          = 0; | ||||
|     Length_High         = 0; | ||||
|     Message_Block_Index = 0; | ||||
|  | ||||
|     H[0]        = 0x67452301; | ||||
|     H[1]        = 0xEFCDAB89; | ||||
|     H[2]        = 0x98BADCFE; | ||||
|     H[3]        = 0x10325476; | ||||
|     H[4]        = 0xC3D2E1F0; | ||||
|  | ||||
|     Computed    = false; | ||||
|     Corrupted   = false; | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  Result | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function will return the 160-bit message digest into the | ||||
|  *      array provided. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_digest_array: [out] | ||||
|  *          This is an array of five unsigned integers which will be filled | ||||
|  *          with the message digest that has been computed. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      True if successful, false if it failed. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| bool SHA1::Result(unsigned *message_digest_array) | ||||
| { | ||||
|     int i;                                  // Counter | ||||
|  | ||||
|     if (Corrupted) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (!Computed) | ||||
|     { | ||||
|         PadMessage(); | ||||
|         Computed = true; | ||||
|     } | ||||
|  | ||||
|     for(i = 0; i < 5; i++) | ||||
|     { | ||||
|         message_digest_array[i] = H[i]; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  Input | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function accepts an array of octets as the next portion of | ||||
|  *      the message. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_array: [in] | ||||
|  *          An array of characters representing the next portion of the | ||||
|  *          message. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| void SHA1::Input(   const unsigned char *message_array, | ||||
|                     unsigned            length) | ||||
| { | ||||
|     if (!length) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (Computed || Corrupted) | ||||
|     { | ||||
|         Corrupted = true; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     while(length-- && !Corrupted) | ||||
|     { | ||||
|         Message_Block[Message_Block_Index++] = (*message_array & 0xFF); | ||||
|  | ||||
|         Length_Low += 8; | ||||
|         Length_Low &= 0xFFFFFFFF;               // Force it to 32 bits | ||||
|         if (Length_Low == 0) | ||||
|         { | ||||
|             Length_High++; | ||||
|             Length_High &= 0xFFFFFFFF;          // Force it to 32 bits | ||||
|             if (Length_High == 0) | ||||
|             { | ||||
|                 Corrupted = true;               // Message is too long | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (Message_Block_Index == 64) | ||||
|         { | ||||
|             ProcessMessageBlock(); | ||||
|         } | ||||
|  | ||||
|         message_array++; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  Input | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function accepts an array of octets as the next portion of | ||||
|  *      the message. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_array: [in] | ||||
|  *          An array of characters representing the next portion of the | ||||
|  *          message. | ||||
|  *      length: [in] | ||||
|  *          The length of the message_array | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| void SHA1::Input(   const char  *message_array, | ||||
|                     unsigned    length) | ||||
| { | ||||
|     Input((unsigned char *) message_array, length); | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  Input | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function accepts a single octets as the next message element. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_element: [in] | ||||
|  *          The next octet in the message. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| void SHA1::Input(unsigned char message_element) | ||||
| { | ||||
|     Input(&message_element, 1); | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  Input | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function accepts a single octet as the next message element. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_element: [in] | ||||
|  *          The next octet in the message. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| void SHA1::Input(char message_element) | ||||
| { | ||||
|     Input((unsigned char *) &message_element, 1); | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  operator<< | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This operator makes it convenient to provide character strings to | ||||
|  *      the SHA1 object for processing. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_array: [in] | ||||
|  *          The character array to take as input. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      A reference to the SHA1 object. | ||||
|  * | ||||
|  *  Comments: | ||||
|  *      Each character is assumed to hold 8 bits of information. | ||||
|  * | ||||
|  */ | ||||
| SHA1& SHA1::operator<<(const char *message_array) | ||||
| { | ||||
|     const char *p = message_array; | ||||
|  | ||||
|     while(*p) | ||||
|     { | ||||
|         Input(*p); | ||||
|         p++; | ||||
|     } | ||||
|  | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  operator<< | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This operator makes it convenient to provide character strings to | ||||
|  *      the SHA1 object for processing. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_array: [in] | ||||
|  *          The character array to take as input. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      A reference to the SHA1 object. | ||||
|  * | ||||
|  *  Comments: | ||||
|  *      Each character is assumed to hold 8 bits of information. | ||||
|  * | ||||
|  */ | ||||
| SHA1& SHA1::operator<<(const unsigned char *message_array) | ||||
| { | ||||
|     const unsigned char *p = message_array; | ||||
|  | ||||
|     while(*p) | ||||
|     { | ||||
|         Input(*p); | ||||
|         p++; | ||||
|     } | ||||
|  | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  operator<< | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function provides the next octet in the message. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_element: [in] | ||||
|  *          The next octet in the message | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      A reference to the SHA1 object. | ||||
|  * | ||||
|  *  Comments: | ||||
|  *      The character is assumed to hold 8 bits of information. | ||||
|  * | ||||
|  */ | ||||
| SHA1& SHA1::operator<<(const char message_element) | ||||
| { | ||||
|     Input((unsigned char *) &message_element, 1); | ||||
|  | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  operator<< | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function provides the next octet in the message. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      message_element: [in] | ||||
|  *          The next octet in the message | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      A reference to the SHA1 object. | ||||
|  * | ||||
|  *  Comments: | ||||
|  *      The character is assumed to hold 8 bits of information. | ||||
|  * | ||||
|  */ | ||||
| SHA1& SHA1::operator<<(const unsigned char message_element) | ||||
| { | ||||
|     Input(&message_element, 1); | ||||
|  | ||||
|     return *this; | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  ProcessMessageBlock | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This function will process the next 512 bits of the message | ||||
|  *      stored in the Message_Block array. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      None. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  *      Many of the variable names in this function, especially the single | ||||
|  *      character names, were used because those were the names used | ||||
|  *      in the publication. | ||||
|  * | ||||
|  */ | ||||
| void SHA1::ProcessMessageBlock() | ||||
| { | ||||
|     const unsigned K[] =    {               // Constants defined for SHA-1 | ||||
|                                 0x5A827999, | ||||
|                                 0x6ED9EBA1, | ||||
|                                 0x8F1BBCDC, | ||||
|                                 0xCA62C1D6 | ||||
|                             }; | ||||
|     int         t;                          // Loop counter | ||||
|     unsigned    temp;                       // Temporary word value | ||||
|     unsigned    W[80];                      // Word sequence | ||||
|     unsigned    A, B, C, D, E;              // Word buffers | ||||
|  | ||||
|     /* | ||||
|      *  Initialize the first 16 words in the array W | ||||
|      */ | ||||
|     for(t = 0; t < 16; t++) | ||||
|     { | ||||
|         W[t] = ((unsigned) Message_Block[t * 4]) << 24; | ||||
|         W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16; | ||||
|         W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8; | ||||
|         W[t] |= ((unsigned) Message_Block[t * 4 + 3]); | ||||
|     } | ||||
|  | ||||
|     for(t = 16; t < 80; t++) | ||||
|     { | ||||
|        W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); | ||||
|     } | ||||
|  | ||||
|     A = H[0]; | ||||
|     B = H[1]; | ||||
|     C = H[2]; | ||||
|     D = H[3]; | ||||
|     E = H[4]; | ||||
|  | ||||
|     for(t = 0; t < 20; t++) | ||||
|     { | ||||
|         temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; | ||||
|         temp &= 0xFFFFFFFF; | ||||
|         E = D; | ||||
|         D = C; | ||||
|         C = CircularShift(30,B); | ||||
|         B = A; | ||||
|         A = temp; | ||||
|     } | ||||
|  | ||||
|     for(t = 20; t < 40; t++) | ||||
|     { | ||||
|         temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; | ||||
|         temp &= 0xFFFFFFFF; | ||||
|         E = D; | ||||
|         D = C; | ||||
|         C = CircularShift(30,B); | ||||
|         B = A; | ||||
|         A = temp; | ||||
|     } | ||||
|  | ||||
|     for(t = 40; t < 60; t++) | ||||
|     { | ||||
|         temp = CircularShift(5,A) + | ||||
|                ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; | ||||
|         temp &= 0xFFFFFFFF; | ||||
|         E = D; | ||||
|         D = C; | ||||
|         C = CircularShift(30,B); | ||||
|         B = A; | ||||
|         A = temp; | ||||
|     } | ||||
|  | ||||
|     for(t = 60; t < 80; t++) | ||||
|     { | ||||
|         temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; | ||||
|         temp &= 0xFFFFFFFF; | ||||
|         E = D; | ||||
|         D = C; | ||||
|         C = CircularShift(30,B); | ||||
|         B = A; | ||||
|         A = temp; | ||||
|     } | ||||
|  | ||||
|     H[0] = (H[0] + A) & 0xFFFFFFFF; | ||||
|     H[1] = (H[1] + B) & 0xFFFFFFFF; | ||||
|     H[2] = (H[2] + C) & 0xFFFFFFFF; | ||||
|     H[3] = (H[3] + D) & 0xFFFFFFFF; | ||||
|     H[4] = (H[4] + E) & 0xFFFFFFFF; | ||||
|  | ||||
|     Message_Block_Index = 0; | ||||
| } | ||||
|  | ||||
| /*   | ||||
|  *  PadMessage | ||||
|  * | ||||
|  *  Description: | ||||
|  *      According to the standard, the message must be padded to an even | ||||
|  *      512 bits.  The first padding bit must be a '1'.  The last 64 bits | ||||
|  *      represent the length of the original message.  All bits in between | ||||
|  *      should be 0.  This function will pad the message according to those | ||||
|  *      rules by filling the message_block array accordingly.  It will also | ||||
|  *      call ProcessMessageBlock() appropriately.  When it returns, it | ||||
|  *      can be assumed that the message digest has been computed. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      None. | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      Nothing. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| void SHA1::PadMessage() | ||||
| { | ||||
|     /* | ||||
|      *  Check to see if the current message block is too small to hold | ||||
|      *  the initial padding bits and length.  If so, we will pad the | ||||
|      *  block, process it, and then continue padding into a second block. | ||||
|      */ | ||||
|     if (Message_Block_Index > 55) | ||||
|     { | ||||
|         Message_Block[Message_Block_Index++] = 0x80; | ||||
|         while(Message_Block_Index < 64) | ||||
|         { | ||||
|             Message_Block[Message_Block_Index++] = 0; | ||||
|         } | ||||
|  | ||||
|         ProcessMessageBlock(); | ||||
|  | ||||
|         while(Message_Block_Index < 56) | ||||
|         { | ||||
|             Message_Block[Message_Block_Index++] = 0; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         Message_Block[Message_Block_Index++] = 0x80; | ||||
|         while(Message_Block_Index < 56) | ||||
|         { | ||||
|             Message_Block[Message_Block_Index++] = 0; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      *  Store the message length as the last 8 octets | ||||
|      */ | ||||
|     Message_Block[56] = (Length_High >> 24) & 0xFF; | ||||
|     Message_Block[57] = (Length_High >> 16) & 0xFF; | ||||
|     Message_Block[58] = (Length_High >> 8) & 0xFF; | ||||
|     Message_Block[59] = (Length_High) & 0xFF; | ||||
|     Message_Block[60] = (Length_Low >> 24) & 0xFF; | ||||
|     Message_Block[61] = (Length_Low >> 16) & 0xFF; | ||||
|     Message_Block[62] = (Length_Low >> 8) & 0xFF; | ||||
|     Message_Block[63] = (Length_Low) & 0xFF; | ||||
|  | ||||
|     ProcessMessageBlock(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /*   | ||||
|  *  CircularShift | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This member function will perform a circular shifting operation. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      bits: [in] | ||||
|  *          The number of bits to shift (1-31) | ||||
|  *      word: [in] | ||||
|  *          The value to shift (assumes a 32-bit integer) | ||||
|  * | ||||
|  *  Returns: | ||||
|  *      The shifted value. | ||||
|  * | ||||
|  *  Comments: | ||||
|  * | ||||
|  */ | ||||
| unsigned SHA1::CircularShift(int bits, unsigned word) | ||||
| { | ||||
|     return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits)); | ||||
| } | ||||
							
								
								
									
										90
									
								
								Gateway/gateway/base/sha1.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								Gateway/gateway/base/sha1.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| /* | ||||
|  *  sha1.h | ||||
|  * | ||||
|  *  Copyright (C) 1998, 2009 | ||||
|  *  Paul E. Jones <paulej@packetizer.com> | ||||
|  *  All Rights Reserved. | ||||
|  * | ||||
|  ***************************************************************************** | ||||
|  *  $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $ | ||||
|  ***************************************************************************** | ||||
|  * | ||||
|  *  Description: | ||||
|  *      This class implements the Secure Hashing Standard as defined | ||||
|  *      in FIPS PUB 180-1 published April 17, 1995. | ||||
|  * | ||||
|  *      Many of the variable names in this class, especially the single | ||||
|  *      character names, were used because those were the names used | ||||
|  *      in the publication. | ||||
|  * | ||||
|  *      Please read the file sha1.cpp for more information. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef _SHA1_H_ | ||||
| #define _SHA1_H_ | ||||
|  | ||||
|  | ||||
| class SHA1 | ||||
| { | ||||
|     public: | ||||
|  | ||||
|         SHA1(); | ||||
|         virtual ~SHA1(); | ||||
|  | ||||
|         /* | ||||
|          *  Re-initialize the class | ||||
|          */ | ||||
|         void Reset(); | ||||
|  | ||||
|         /* | ||||
|          *  Returns the message digest | ||||
|          */ | ||||
|         bool Result(unsigned *message_digest_array); | ||||
|  | ||||
|         /* | ||||
|          *  Provide input to SHA1 | ||||
|          */ | ||||
|         void Input( const unsigned char *message_array, | ||||
|                     unsigned            length); | ||||
|         void Input( const char  *message_array, | ||||
|                     unsigned    length); | ||||
|         void Input(unsigned char message_element); | ||||
|         void Input(char message_element); | ||||
|         SHA1& operator<<(const char *message_array); | ||||
|         SHA1& operator<<(const unsigned char *message_array); | ||||
|         SHA1& operator<<(const char message_element); | ||||
|         SHA1& operator<<(const unsigned char message_element); | ||||
|  | ||||
|     private: | ||||
|  | ||||
|         /* | ||||
|          *  Process the next 512 bits of the message | ||||
|          */ | ||||
|         void ProcessMessageBlock(); | ||||
|  | ||||
|         /* | ||||
|          *  Pads the current message block to 512 bits | ||||
|          */ | ||||
|         void PadMessage(); | ||||
|  | ||||
|         /* | ||||
|          *  Performs a circular left shift operation | ||||
|          */ | ||||
|         inline unsigned CircularShift(int bits, unsigned word); | ||||
|  | ||||
|         unsigned H[5];                      // Message digest buffers | ||||
|  | ||||
|         unsigned Length_Low;                // Message length in bits | ||||
|         unsigned Length_High;               // Message length in bits | ||||
|  | ||||
|         unsigned char Message_Block[64];    // 512-bit message blocks | ||||
|         int Message_Block_Index;            // Index into message block array | ||||
|  | ||||
|         bool Computed;                      // Is the digest computed? | ||||
|         bool Corrupted;                     // Is the message digest corruped? | ||||
|      | ||||
| }; | ||||
|  | ||||
| 	 | ||||
| #endif // _SHA1_H_ | ||||
							
								
								
									
										8
									
								
								Gateway/gateway/build.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Gateway/gateway/build.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #!/bin/bash | ||||
| cd $(cd "$(dirname "$0")" && pwd) | ||||
| srcDIR=`pwd` | ||||
|  | ||||
| cd $srcDIR/build | ||||
| cmake .. | ||||
|  | ||||
| make -j2 | ||||
							
								
								
									
										399
									
								
								Gateway/gateway/client/client.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										399
									
								
								Gateway/gateway/client/client.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,399 @@ | ||||
| #include "StdAfx.h" | ||||
| #include "client.h" | ||||
| #include "base/sha1.h" | ||||
| #include "base64.h" | ||||
|  | ||||
| BaseAllocator Client::alloc("ClientAlloc"); | ||||
| Client::Client(GameClientMgr *cli_mgr, SOCKET s, sockaddr_in* addr) { | ||||
| 	shake_hands_ = false; | ||||
| 	fd_ = s; | ||||
| 	cli_mgr_ = cli_mgr; | ||||
| 	send_packet_ = new DataPacket(&alloc); | ||||
| 	send_packet_->reserve(SEND_PACKET_MAX); | ||||
| 	send_packet_->setLength(0); | ||||
| 	memcpy(&remote_addr_, addr, sizeof(sockaddr_in)); | ||||
| 	net_id_.socket_ = s; | ||||
| 	conn_status_ = ConnStatusDef::CS_CONNED; | ||||
| 	skey_ = 0; | ||||
| 	is_close_ = false; | ||||
| 	real_ip[0] = 0; | ||||
| } | ||||
|  | ||||
| Client ::~Client() { | ||||
| 	for (auto it : recv_list_) { | ||||
| 		SafeDelete(it); | ||||
| 	} | ||||
| 	SafeDelete(send_packet_); | ||||
| 	recv_list_.clear(); | ||||
| 	for (auto it : gw_recv_list_) { | ||||
| 		SafeDelete(it); | ||||
| 	} | ||||
| 	real_ip[0] = 0; | ||||
| } | ||||
|  | ||||
| int Client::SetBlockMode(const bool block) { | ||||
| 	unsigned long flag = block ? 0 : 1; | ||||
| #ifdef _MSC_VER | ||||
| 	return ioctlsocket(fd_, FIONBIO, &flag); | ||||
| #else | ||||
| 	return ioctl(fd_, FIONBIO, &flag);//改为非阻塞; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void Client::RecvData(void) { | ||||
| 	if (is_close_) return; | ||||
| 	static char buf[1024]; | ||||
| 	while (true) { | ||||
| 		int buflen = recv(fd_, buf, sizeof(buf), 0); | ||||
| 		if (buflen < 0) { | ||||
| 			// 由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可读 | ||||
| 			// 在这里就当作是该次事件已处理 | ||||
| #ifdef _MSC_VER | ||||
| 			if (WSAGetLastError() == WSAECONNABORTED) { | ||||
| 				Close(); | ||||
| 				return; | ||||
| 			} else if (WSAGetLastError() == WSAEWOULDBLOCK) { | ||||
| #else | ||||
| 			if (WSAGetLastError() == EINPROGRESS || WSAGetLastError() == EAGAIN) { | ||||
| #endif | ||||
| 				break; | ||||
| 			} else { | ||||
| 				MSG_ERR("not handle errno:[%d]%s", WSAGetLastError(), strerror(WSAGetLastError())); | ||||
| 				Close(); | ||||
| 				return; | ||||
| 			} | ||||
| 		} else if (buflen == 0) { | ||||
| 			// 这里表示对端的socket已正常关闭. | ||||
| 			Close(); | ||||
| 			return; | ||||
| 		} | ||||
| 		if (shake_hands_) { | ||||
| 			DataPacket* dp = new DataPacket(&alloc); | ||||
| 			dp->writeBuf(buf, buflen); | ||||
| 			dp->setPosition(0); | ||||
| 			recv_list_.push_back(dp); | ||||
| 		} else { | ||||
| 			//进行websocket握手 | ||||
| 			ShakeHandsHandle(buf, buflen); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| bool Client::SendData(void) { | ||||
| 	size_t splen = send_packet_->getAvaliableLength(); | ||||
| 	if (splen <= 0) { return true; } | ||||
| 	int lsed = send(fd_, send_packet_->getOffsetPtr(), (int)splen, 0); | ||||
| 	if(lsed <= 0) { return true; } | ||||
| 	if (lsed < splen) { | ||||
| 		send_packet_->setPosition(send_packet_->getPosition() + lsed); | ||||
| 		return false; | ||||
| 	} else { | ||||
| 		send_packet_->setLength(0); | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void Client::WriteEvent(void) { | ||||
| 	if (is_close_) return; | ||||
| 	DataPacket* dp = NULL; | ||||
| 	while (true) { | ||||
| 		if (gw_recv_list_.empty()) { break; } | ||||
| 		dp = *(gw_recv_list_.begin()); | ||||
| 		gw_recv_list_.pop_front(); | ||||
| 		FlushWsPack(dp->getOffsetPtr(), dp->getAvaliableLength()); | ||||
| 		SafeDelete(dp); | ||||
| 	} | ||||
| 	if(send_packet_->getAvaliableLength() > 0) { | ||||
| 		cli_mgr_->HaveData(this); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void Client::Flush(const char *buf, size_t len) { | ||||
| 	if (send_packet_->getAvaliableLength() + len > SEND_PACKET_MAX) { | ||||
| 		MSG_ERR("send packet is max, fd:%d", fd_); | ||||
| 		Close(); | ||||
| 		return; | ||||
| 	} else { | ||||
| 		size_t pos = send_packet_->getPosition(); | ||||
| 		send_packet_->setPosition(pos + send_packet_->getAvaliableLength()); | ||||
| 		send_packet_->writeBuf(buf, len); | ||||
| 		send_packet_->setPosition(pos); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void Client::SendNewSession(void) { | ||||
| 	static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient(); | ||||
| 	DataPacket &dp = wgc->AllocProtoPacket(GM_OPEN,net_id_.socket_,net_id_.index_,net_id_.gate_id_); | ||||
| 	if (real_ip[0] != 0) | ||||
| 		dp.writeBuf(real_ip, 32); | ||||
| 	else | ||||
| 		dp.writeBuf(inet_ntoa(remote_addr_.sin_addr), 32); | ||||
| 	wgc->flushProtoPacket(dp); | ||||
| 	OutputMsg(rmTip, _T("[Login] (2) 握手成功,通知LogicServer创建一个玩家Gate: gatekey(%d),socket(%lld),GateIdx(%d),LogicIdx(%d),CurrentThreadId(%d)。"), | ||||
| 		skey_, net_id_.socket_, net_id_.index_, net_id_.gate_id_, GetCurrentThreadId()); | ||||
| } | ||||
|  | ||||
| void Client::SendSessionClose(void) { | ||||
| 	static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient(); | ||||
| 	DataPacket &dp = wgc->AllocProtoPacket(GM_CLOSE,net_id_.socket_,net_id_.index_,net_id_.gate_id_); | ||||
| 	wgc->flushProtoPacket(dp); | ||||
| } | ||||
|  | ||||
| void Client::Close(void) { | ||||
| 	MSG_ERR("close client, fd:%d,index:%d", net_id_.socket_, net_id_.index_); | ||||
| 	cli_mgr_->CloseClient(this); | ||||
| 	SendSessionClose(); | ||||
| 	is_close_ = true; | ||||
| } | ||||
|  | ||||
| #define WEB_SOCKET_HANDS_RE "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n" | ||||
| #define MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" | ||||
| void Client::ShakeHandsHandle(const char* buf, int buflen) { | ||||
| 	char key[512]; memset(key, 0, 512); | ||||
| 	for (int i = 0; i < buflen; ++i) | ||||
| 	{ | ||||
| 		if (FindHttpParam("Sec-WebSocket-Key", buf+i)) { | ||||
| 			short k = i + 17, ki = 0; | ||||
| 			while(*(buf + k) != '\r' && *(buf + k) != '\n' && *(buf + k) != '\0') { | ||||
| 				if (*(buf + k) == ':' || *(buf + k) == ' '){ | ||||
| 					++k; continue; | ||||
| 				} else { | ||||
| 					key[ki++] = *(buf + k); | ||||
| 				} | ||||
| 				++k; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	memset(real_ip, 0, sizeof(real_ip)); | ||||
| 	for (int i = 0; i < buflen; ++i) | ||||
| 	{ | ||||
| 		if (FindHttpParam("X-Real-IP", buf+i)) { | ||||
| 			short k = i + 9, ki = 0; | ||||
| 			while(*(buf + k) != '\r' && *(buf + k) != '\n' && *(buf + k) != '\0') { | ||||
| 				if (*(buf + k) == ':' || *(buf + k) == ' '){ | ||||
| 					++k; continue; | ||||
| 				} else { | ||||
| 					real_ip[ki++] = *(buf + k); | ||||
| 				} | ||||
| 				++k; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	//MSG_LOG("key:%s...", key); | ||||
| 	memcpy(key + strlen(key), MAGIC_KEY, sizeof(MAGIC_KEY)); | ||||
| 	//MSG_LOG("megerkey:%s...", key); | ||||
| 	//求哈希1 | ||||
| 	SHA1 sha; | ||||
| 	unsigned int message_digest[5]; | ||||
| 	sha.Reset(); | ||||
| 	sha << key; | ||||
| 	sha.Result(message_digest); | ||||
| 	for (int i = 0; i < 5; i++) { | ||||
| 		message_digest[i] = htonl(message_digest[i]); | ||||
| 	} | ||||
|  | ||||
| 	memset(key, 0, 512); | ||||
| 	base64_encode(key, reinterpret_cast<const char*>(message_digest), 20); | ||||
| 	char http_res[512] = ""; | ||||
| 	sprintf(http_res, WEB_SOCKET_HANDS_RE, key); | ||||
| 	Flush(http_res, strlen(http_res)); | ||||
| 	//MSG_LOG("res:%s...",http_res);//fkYTdNEVkParesYkrM4S | ||||
| 	SendData(); | ||||
| 	shake_hands_ = true; | ||||
| 	SendNewSession();//发送到gameworld新增连接 | ||||
| } | ||||
|  | ||||
| void Client::PacketHandle(void) { | ||||
| 	if (is_close_) return; | ||||
| 	while (!recv_list_.empty()) { | ||||
| 		auto dpit = recv_list_.begin(); | ||||
| 		DataPacket* dp = *dpit; | ||||
| 		//读取websocket固定包头 | ||||
| 		if (!ws_head_.rh) { | ||||
| 			//这个包不够一个头部的大小 | ||||
| 			if (dp->getAvaliableLength() < 2) { | ||||
| 				if (MergePacketList(dpit)) continue; | ||||
| 				else break; | ||||
| 			} | ||||
| 			//读取 | ||||
| 			uint8_t head = 0; | ||||
| 			dp->readBuf(&head, 1); | ||||
| 			ws_head_.fin = head >> 7; | ||||
| 			ws_head_.opcode = head & 0xF; | ||||
| 			dp->readBuf(&head, 1); | ||||
| 			ws_head_.len = head & 0x7F; | ||||
| 			ws_head_.mask = head >> 7; | ||||
| 			ws_head_.rh = 1;//标记头部读取完成 | ||||
| 		} | ||||
| 		//读取长度 | ||||
| 		if (!ws_head_.rl) { | ||||
| 			uint8_t nsize = ws_head_.GetLenNeedByte(); | ||||
| 			if (nsize) { | ||||
| 				//这个包不够一个长度 | ||||
| 				if (dp->getAvaliableLength() < nsize) { | ||||
| 					if (MergePacketList(dpit)) continue; | ||||
| 					else break; | ||||
| 				} | ||||
| 				if (nsize == 2) { | ||||
| 					(*dp) >> ws_head_.ex_len.v16; | ||||
| 					ws_head_.ex_len.v16 = ntohs(ws_head_.ex_len.v16); | ||||
| 				} else { | ||||
| 					(*dp) >> ws_head_.ex_len.v32; | ||||
| 					ws_head_.ex_len.v32 = ntohl((u_long)ws_head_.ex_len.v32); | ||||
| 				} | ||||
| 			} | ||||
| 			ws_head_.rl = 1; | ||||
| 		} | ||||
| 		//读取MKEY | ||||
| 		if (!ws_head_.rk) { | ||||
| 			if (ws_head_.mask) { | ||||
| 				//这个包不够一个key | ||||
| 				if (dp->getAvaliableLength() < 4) { | ||||
| 					if (MergePacketList(dpit)) continue; | ||||
| 					else break; | ||||
| 				} | ||||
| 				(*dp) >> ws_head_.mkey[0]; | ||||
| 				(*dp) >> ws_head_.mkey[1]; | ||||
| 				(*dp) >> ws_head_.mkey[2]; | ||||
| 				(*dp) >> ws_head_.mkey[3]; | ||||
| 			} | ||||
| 			ws_head_.rk = 1; | ||||
| 		} | ||||
| 		//读取数据段 | ||||
| 		uint64_t data_len = ws_head_.GetLen(); | ||||
| 		if (dp->getAvaliableLength() < data_len) { | ||||
| 			if (MergePacketList(dpit)) continue; | ||||
| 			else break; | ||||
| 		} | ||||
|  | ||||
| 		if (ws_head_.mask) { | ||||
| 			char* dptr = dp->getOffsetPtr(); | ||||
| 			for (size_t i = 0; i < data_len; ++i) { | ||||
| 				dptr[i] = dptr[i] ^ ws_head_.mkey[i % 4]; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (!OnRecv(dp->getOffsetPtr(), data_len)) { | ||||
| 			return; | ||||
| 		} | ||||
| 		ws_head_.reset(); | ||||
| 		dp->adjustOffset(data_len); | ||||
| 		//这个包读取完了 | ||||
| 		if (dp->getAvaliableLength() <= 0) { | ||||
| 			recv_list_.pop_front(); | ||||
| 			SafeDelete(dp); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| bool Client::OnRecv(const char* buf, size_t size) { | ||||
|  | ||||
| 	if (conn_status_ == CS_COMMUNICATE) { | ||||
| 		if (ws_head_.opcode == OPCODE_CLR) { | ||||
| 			Close(); | ||||
| 			return false; | ||||
| 		} | ||||
| 		if (size < 4 + 2) { | ||||
| 			MSG_ERR("size is min"); | ||||
| 			return true; | ||||
| 		} | ||||
| 		 | ||||
| 		//截去key | ||||
| 		unsigned short tag = *((unsigned short*)buf); | ||||
| 		if (tag != skey_) { | ||||
| 			Close(); | ||||
| 			return false; | ||||
| 		} | ||||
| 		char* pdata = (char*)buf + sizeof(unsigned short); | ||||
| 		size -= 2; | ||||
|  | ||||
| 		//截去验证 | ||||
| 		uint32_t check = *((uint32_t*)pdata); | ||||
| 		pdata = pdata + sizeof(uint32_t); | ||||
| 		size -= 4; | ||||
|  | ||||
| 		//发送给游戏服 | ||||
| 		static GameWorldClient* wgc = cli_mgr_->GetGameWorldClient(); | ||||
| 		DataPacket &pack = wgc->AllocProtoPacket(GM_DATA,net_id_.socket_,net_id_.index_,net_id_.gate_id_); | ||||
| 		#ifdef _DEBUG | ||||
| 			const unsigned char* proto = pdata; | ||||
| 			OutputMsg(rmTip, "<[sock:%d,idx:%d] Recv(%d,%d)", fd_, GetSessionId(), *proto, *(proto+1)); | ||||
| 		#endif | ||||
| 		pack.writeBuf(pdata, size); | ||||
| 		wgc->flushProtoPacket(pack); | ||||
| 		//MSG_ERR("size is [%d + 4 + 2]", size); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	if (conn_status_ == CS_CONNED) { //刚连接上来 | ||||
| 		uint32_t tag = *((uint32_t*)buf); | ||||
| 		if (tag != DEFAULT_TAG) { | ||||
| 			Close(); | ||||
| 			return false; | ||||
| 		} | ||||
| 		skey_ = wrand(SHRT_MAX); | ||||
| 		FlushWsPack((char *)&skey_, 2); | ||||
| 		SendData(); | ||||
| 		conn_status_ = CS_COMMUNICATE; | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void Client::FlushWsPack(const char* buf, size_t size) { | ||||
| 	static DataPacket pack(&alloc); | ||||
| 	pack.setLength(0); | ||||
| 	pack << (uint8_t)0x82;//写头部 | ||||
| 	//写长度 | ||||
| 	if (size >= 126) {//7位放不下 | ||||
| 		if (size <= 0xFFFF) {//16位放 | ||||
| 			pack << (uint8_t)126; | ||||
| 			pack << (uint16_t)htons((u_short)size); | ||||
| 		} else {//64位放 | ||||
| 			pack << (uint8_t)127; | ||||
| 			pack << (uint64_t)OrderSwap64(size); | ||||
| 		} | ||||
| 	} else { | ||||
| 		pack << (uint8_t)size; | ||||
| 	} | ||||
| 	//写数据 | ||||
| 	pack.writeBuf(buf, size); | ||||
| 	pack.setPosition(0); | ||||
| 	Flush(pack.getOffsetPtr(), pack.getAvaliableLength()); | ||||
| } | ||||
|  | ||||
| void Client::OnGameWorldRecv(const char* buf, size_t size) { | ||||
| 	DataPacket *dp = new DataPacket(&alloc); | ||||
| 	(*dp) << (uint16_t)skey_; | ||||
| #ifdef _DEBUG | ||||
| 	const unsigned char* proto = buf; | ||||
| 	OutputMsg(rmTip, ">[sock:%d,idx:%d] Send(%d,%d)", fd_, GetSessionId(), *proto, *(proto+1)); | ||||
| #endif | ||||
| 	dp->writeBuf(buf, size); | ||||
| 	dp->setPosition(0); | ||||
| 	gw_recv_list_.push_back(dp); | ||||
| } | ||||
|  | ||||
| bool Client::MergePacketList(std::list<DataPacket*>::iterator &dpit) { | ||||
| 	auto sdpit = dpit++; | ||||
| 	if (dpit == recv_list_.end()) return false; | ||||
| 	DataPacket* sdp = *sdpit; | ||||
| 	//合并第二个到第一个 | ||||
| 	sdp->writeBuf((*dpit)->getOffsetPtr(), (*dpit)->getAvaliableLength()); | ||||
| 	SafeDelete((*dpit)); | ||||
| 	recv_list_.erase(dpit); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| bool Client::FindHttpParam(const char * param, const char * buf) { | ||||
| 	while (*param == *buf) { | ||||
| 		if (*(param + 1) == '\0') return true; | ||||
| 		++param; ++buf; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
							
								
								
									
										106
									
								
								Gateway/gateway/client/client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								Gateway/gateway/client/client.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | ||||
| #pragma once | ||||
| #include <list> | ||||
|  | ||||
| #define SEND_PACKET_MAX 1024*1024*8 | ||||
| #define DEFAULT_TAG 0xCA0FFFFF | ||||
|  | ||||
| enum WebSocketOpcode { //操作码定义类型 | ||||
| 	OPCODE_MID = 0x0,//标识一个中间数据包 | ||||
| 	OPCODE_TXT = 0x1,//标识一个text类型数据包 | ||||
| 	OPCODE_BIN = 0x2,//标识一个binary类型数据包 | ||||
| 	//0x3 - 7:保留 | ||||
| 	OPCODE_CLR = 0x8,//标识一个断开连接类型数据包 | ||||
| 	OPCODE_PIN = 0x9,//标识一个ping类型数据包 | ||||
| 	OPCODE_PON = 0xA,//表示一个pong类型数据包 | ||||
| }; | ||||
|  | ||||
| #pragma pack(push,1) | ||||
| struct WebSocketHead { | ||||
| 	uint8_t fin : 1;//标识是否为此消息的最后一个数据包 | ||||
| 	uint8_t rsv1 : 1;//保留位1 | ||||
| 	uint8_t rsv2 : 1;//保留位2 | ||||
| 	uint8_t rsv3 : 1;//保留位3 | ||||
| 	uint8_t opcode : 4;//操作码 | ||||
|  | ||||
| 	uint8_t mask : 1; //是否需要掩码 | ||||
| 	uint8_t len : 7;//长度 | ||||
| 	union { | ||||
| 		uint16_t v16;//长度为126时 | ||||
| 		uint32_t v32;//长度为127时 | ||||
| 	} ex_len; | ||||
| 	uint8_t mkey[4]; | ||||
| 	uint8_t rh : 1;//head读取完成 | ||||
| 	uint8_t rl : 1;//len读取完成 | ||||
| 	uint8_t rk : 1;//mkey读取完成 | ||||
| 	uint8_t rs : 5;//扩展保留 | ||||
| 	WebSocketHead(void) { reset(); } | ||||
| 	void reset(void) { memset(this,0,sizeof(WebSocketHead)); } | ||||
| 	inline uint32_t GetLen(void) { | ||||
| 		if (len == 126) { | ||||
| 			return ex_len.v16; | ||||
| 		} else if (len == 127) { | ||||
| 			return ex_len.v32; | ||||
| 		} | ||||
| 		return len; | ||||
| 	} | ||||
| 	inline uint8_t GetLenNeedByte(void) { | ||||
| 		if (len == 126) { | ||||
| 			return 2; | ||||
| 		} else if (len == 127) { | ||||
| 			return 8; | ||||
| 		}  | ||||
| 		return 0; | ||||
| 	} | ||||
| }; | ||||
| #pragma pack(pop) | ||||
|  | ||||
| enum ConnStatusDef { | ||||
| 	CS_CONNED,//连接上 | ||||
| 	CS_COMMUNICATE,//通信状态 | ||||
| }; | ||||
| typedef std::list<DataPacket*> DataPacketList; | ||||
| class Client { | ||||
| public: | ||||
| 	Client(GameClientMgr *cli_mgr, SOCKET s, sockaddr_in* addr); | ||||
| 	~Client(); | ||||
|  | ||||
| 	//设置阻塞模式。true表示阻塞,false表示非阻塞,返回值为socket错误号,0表示成功 | ||||
| 	int SetBlockMode(const bool block); | ||||
| 	void SetSessionId(const uint16_t sid) { net_id_.index_ = sid; } | ||||
| 	uint16_t GetSessionId(void) { return net_id_.index_; } | ||||
| 	NetId &GetNetId(void) { return net_id_; } | ||||
| 	void RecvData(void); | ||||
| 	bool SendData(void); | ||||
| 	void WriteEvent(void); | ||||
| 	void Flush(const char *buf, size_t len); | ||||
| 	void SendNewSession(void); | ||||
| 	void SendSessionClose(void); | ||||
| 	void Close(void); | ||||
| 	bool OnRecv(const char* buf, size_t size); | ||||
| 	void FlushWsPack(const char* buf, size_t size); | ||||
| 	void OnGameWorldRecv(const char* buf, size_t size); | ||||
| 	inline SOCKET GetFd(void) { return fd_; } | ||||
| 	inline bool IsClose(void) { return is_close_; } | ||||
| 	void PacketHandle(void); | ||||
| 	uint16_t GetSKey() { return skey_; } | ||||
| protected: | ||||
| 	void ShakeHandsHandle(const char* buf, int buflen); | ||||
| private: | ||||
| 	inline bool MergePacketList(std::list<DataPacket*>::iterator &dpit); | ||||
| 	bool FindHttpParam(const char* param, const char* buf); | ||||
|  | ||||
| 	bool shake_hands_;//是否已经握手 | ||||
| 	SOCKET fd_;		 //套接字 | ||||
| 	bool is_close_;	//是否已经关闭连接 | ||||
| 	sockaddr_in	remote_addr_;//远程地址 | ||||
| 	DataPacketList recv_list_;//收到的包列表 | ||||
| 	DataPacket* send_packet_;//需要发包的缓冲区 | ||||
| 	DataPacketList gw_recv_list_;//从游戏服收到的包列表 | ||||
| 	WebSocketHead ws_head_;//包头 | ||||
| 	NetId net_id_; | ||||
| 	uint8_t conn_status_;//连接状态 | ||||
| 	uint16_t skey_;//服务端KEY | ||||
| 	static BaseAllocator alloc; | ||||
| 	GameClientMgr* cli_mgr_; | ||||
| 	char real_ip[64]; | ||||
| }; | ||||
							
								
								
									
										67
									
								
								Gateway/gateway/client/client_obj_mgr.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								Gateway/gateway/client/client_obj_mgr.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| #include "StdAfx.h" | ||||
| #include "client_obj_mgr.h" | ||||
| #include <map> | ||||
|  | ||||
| ClientObjMgr::ClientObjMgr() { | ||||
| 	cur_idx_ = 0; | ||||
| 	max_session_ = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| ClientObjMgr::~ClientObjMgr() { | ||||
| 	flush(); | ||||
| 	for (auto cli:client_list_) { | ||||
| 		SafeDelete(cli.second); | ||||
| 	} | ||||
| 	client_list_.clear(); | ||||
| } | ||||
|  | ||||
| void ClientObjMgr::SetMaxSession(int max_session) { | ||||
| 	max_session_ = max_session; | ||||
| } | ||||
|  | ||||
| bool ClientObjMgr::setNewClient(Client *cli) { | ||||
| 	client_lock_.Lock(); | ||||
| 	if (max_session_ <= cur_idx_) return false; | ||||
| 	uint16_t index = 0; | ||||
| 	if (free_cli_idx_.empty()) { | ||||
| 		index = cur_idx_++; | ||||
| 	} else { | ||||
| 		index = free_cli_idx_.front(); | ||||
| 		free_cli_idx_.pop_front(); | ||||
| 	} | ||||
| 	cli->SetSessionId(index); | ||||
| 	client_append_list_.push_back(cli); | ||||
| 	client_lock_.Unlock(); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void ClientObjMgr::flush(void) { | ||||
| 	client_lock_.Lock(); | ||||
| 	for (auto it:client_append_list_) { | ||||
| 		client_list_.insert(std::make_pair(it->GetSessionId(), it)); | ||||
| 	} | ||||
| 	client_append_list_.clear(); | ||||
| 	client_lock_.Unlock(); | ||||
| } | ||||
|  | ||||
| Client* ClientObjMgr::get(uint16_t index) { | ||||
| 	auto it = client_list_.find(index); | ||||
| 	if (it == client_list_.end()) return NULL; | ||||
| 	return it->second; | ||||
| } | ||||
|  | ||||
| Client * ClientObjMgr::remove(uint16_t index) { | ||||
| 	auto it = client_list_.find(index); | ||||
| 	if (it == client_list_.end()) return NULL; | ||||
| 	Client *cli = it->second; | ||||
| 	client_list_.erase(it); | ||||
| 	client_lock_.Lock(); | ||||
| 	if (index == cur_idx_ - 1) { | ||||
| 		--cur_idx_; | ||||
| 	} else { | ||||
| 		free_cli_idx_.push_back(index); | ||||
| 	} | ||||
| 	client_lock_.Unlock(); | ||||
| 	return cli; | ||||
| } | ||||
							
								
								
									
										24
									
								
								Gateway/gateway/client/client_obj_mgr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Gateway/gateway/client/client_obj_mgr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| #pragma once | ||||
| #include <map> | ||||
| class ClientObjMgr { | ||||
| public: | ||||
| 	ClientObjMgr(); | ||||
| 	~ClientObjMgr(); | ||||
|  | ||||
| 	void SetMaxSession(int max_session); | ||||
| 	bool setNewClient(Client *cli); | ||||
| 	void flush(void); | ||||
| 	std::map<uint16_t, Client*> &getClientMap(void) { | ||||
| 		return client_list_; | ||||
| 	} | ||||
| 	Client* get(uint16_t index); | ||||
| 	Client* remove(uint16_t index); | ||||
| private: | ||||
| 	uint16_t max_session_;//<2F><><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ||||
| 	uint16_t cur_idx_; | ||||
| 	std::list<uint16_t> free_cli_idx_;//<2F><><EFBFBD>еĿͻ<C4BF><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ||||
| 	std::vector<Client*> client_append_list_; | ||||
| 	Mutex client_lock_;		//<2F>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>append_list<73><74> | ||||
| 	std::map<uint16_t, Client*> client_list_; | ||||
| }; | ||||
|  | ||||
							
								
								
									
										78
									
								
								Gateway/gateway/config/ws_gate_config.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								Gateway/gateway/config/ws_gate_config.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| #include "StdAfx.h" | ||||
| #include "ws_gate_config.h" | ||||
|  | ||||
| const char WsGateConfig::ConfigFileName[] = ("GateWay.txt"); | ||||
|  | ||||
| WsGateConfig::WsGateConfig(){ | ||||
| } | ||||
|  | ||||
|  | ||||
| WsGateConfig::~WsGateConfig() { | ||||
|  | ||||
| } | ||||
|  | ||||
| void WsGateConfig::showError(const char* err) { | ||||
| 	SetErrDesc(err); | ||||
| 	RefString s = ("[Config Error]"); | ||||
| 	s += err; | ||||
| 	throw s; | ||||
| } | ||||
|  | ||||
| bool WsGateConfig::loadServerConfig(GateServer * gate_srv) | ||||
| { | ||||
| 	using namespace stream; | ||||
|  | ||||
| 	MemoryStream ms(NULL); | ||||
|  | ||||
| 	try	{ | ||||
| 		if (ms.loadFromFile(ConfigFileName) <= 0) { | ||||
| 			showError("unable to load config from file GateWay.txt"); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (!setScript((const char*)ms.getMemory())) { | ||||
| 			showError("parse config script failed"); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (openGlobalTable("GateServer")) { | ||||
| 			if (enumTableFirst()) { | ||||
| 				char str[32]; | ||||
| 				GameClientMgr* gcmgr = NULL; | ||||
| 				do { | ||||
| 					if (openFieldTable("LocalService")) { | ||||
| 						 | ||||
| 						getFieldStringBuffer(("ServerName"), str, sizeof(str)); | ||||
| 						gcmgr = gate_srv->AddGameClientMgr(str); | ||||
| 						 | ||||
| 						getFieldStringBuffer(("Address"), str, sizeof(str)); | ||||
| 						gcmgr->SetServiceHost(str); | ||||
|  | ||||
| 						int port = getFieldInt("Port"); | ||||
| 						gcmgr->SetServicePort(port); | ||||
| 						gcmgr->SetMaxSession(getFieldInt("MaxSession")); | ||||
|  | ||||
| 						closeTable(); | ||||
| 					} | ||||
|  | ||||
| 					if (gcmgr && openFieldTable("BackServer")) { | ||||
| 						getFieldStringBuffer(("Host"), str, sizeof(str)); | ||||
| 						int port = getFieldInt("Port"); | ||||
|  | ||||
| 						gcmgr->InitGameWorldClient(str, port); | ||||
| 						closeTable(); | ||||
| 					} | ||||
|  | ||||
| 				} while (enumTableNext()); | ||||
| 			} | ||||
|  | ||||
| 			closeTable(); | ||||
| 		} | ||||
| 	} catch (RefString& s) { | ||||
| 		OutputMsg(rmNormal, s.rawStr()); | ||||
| 	} catch (...) { | ||||
| 		MSG_ERR("unexpected error on load config"); | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
							
								
								
									
										18
									
								
								Gateway/gateway/config/ws_gate_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Gateway/gateway/config/ws_gate_config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| #pragma once | ||||
|  | ||||
| class BaseLuaConfig; | ||||
|  | ||||
| class WsGateConfig : | ||||
| 	public BaseLuaConfig { | ||||
| public: | ||||
| 	WsGateConfig(); | ||||
| 	~WsGateConfig(); | ||||
| 	static const char ConfigFileName[];	//定义配置文件名称 | ||||
|  | ||||
| 	//加载并读取服务器服务配置 | ||||
| 	bool loadServerConfig(GateServer *gate_srv); | ||||
|  | ||||
| protected: | ||||
| 	void showError(const char* err); | ||||
| }; | ||||
|  | ||||
							
								
								
									
										18
									
								
								Gateway/gateway/event/base_event.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Gateway/gateway/event/base_event.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| #include "StdAfx.h" | ||||
| #include "base_event.h" | ||||
|  | ||||
| BaseEvent::BaseEvent(GameClientMgr* cli_mgr) | ||||
| :cli_mgr_(cli_mgr) { | ||||
| } | ||||
|  | ||||
| BaseEvent::~BaseEvent() | ||||
| { | ||||
| } | ||||
|  | ||||
| bool BaseEvent::init(void) { | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void BaseEvent::RunOne(void) { | ||||
| 	 | ||||
| } | ||||
							
								
								
									
										16
									
								
								Gateway/gateway/event/base_event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Gateway/gateway/event/base_event.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| #pragma once | ||||
| class BaseEvent | ||||
| { | ||||
| public: | ||||
| 	BaseEvent(GameClientMgr* cli_mgr); | ||||
| 	~BaseEvent(); | ||||
| 	virtual bool init(void); | ||||
| 	virtual void RunOne(void); | ||||
| 	virtual void AddReadFd(SOCKET fd, void *ptr = NULL) {} | ||||
| 	virtual void DelFd(SOCKET fd, void *ptr = NULL) {} | ||||
| 	virtual void AddWriteFd(SOCKET fd, void *ptr = NULL) {} | ||||
|  | ||||
| protected: | ||||
| 	GameClientMgr* cli_mgr_; | ||||
| }; | ||||
|  | ||||
							
								
								
									
										52
									
								
								Gateway/gateway/event/epoll_event.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								Gateway/gateway/event/epoll_event.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| #include "StdAfx.h" | ||||
| #include "epoll_event.h" | ||||
|  | ||||
| #ifndef _MSC_VER | ||||
| EpollEvent::EpollEvent(GameClientMgr* cli_mgr) : BaseEvent(cli_mgr) { | ||||
| 	epollfd_ = 0; | ||||
| 	listen_fd_ = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| EpollEvent::~EpollEvent() { | ||||
| 	if (epollfd_) { | ||||
| 		close(epollfd_); | ||||
| 	} | ||||
| } | ||||
| bool EpollEvent::init(void) { | ||||
| 	epollfd_ = epoll_create(EPOLLEVENTS); | ||||
| 	return true; | ||||
| } | ||||
| void EpollEvent::RunOne(void) { | ||||
| 	int ret = epoll_wait(epollfd_, events_, EPOLLEVENTS, 0); | ||||
| 	for (int i = 0; i < ret; i++) { | ||||
| 		if (Client *ptr = (Client*)events_[i].data.ptr) | ||||
| 		{ | ||||
| 			if (events_[i].events & EPOLLIN) { | ||||
| 				cli_mgr_->HandleReadEvent(ptr->GetFd(), ptr); | ||||
| 			} else if (events_[i].events & EPOLLOUT) { | ||||
| 				cli_mgr_->HandleWriteEvent(ptr->GetFd(), ptr); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void EpollEvent::AddReadFd(SOCKET fd, void *ptr) { | ||||
| 	struct epoll_event ev; | ||||
| 	ev.events = EPOLLIN; | ||||
| 	ev.data.ptr = ptr; | ||||
| 	epoll_ctl(epollfd_, EPOLL_CTL_ADD, fd, &ev); | ||||
| } | ||||
|  | ||||
| void EpollEvent::DelFd(SOCKET fd, void *ptr) { | ||||
| 	epoll_ctl(epollfd_, EPOLL_CTL_DEL, fd, NULL); | ||||
| } | ||||
|  | ||||
| void EpollEvent::AddWriteFd(SOCKET fd, void *ptr) { | ||||
| 	struct epoll_event ev; | ||||
| 	ev.events = EPOLLIN | EPOLLOUT; | ||||
| 	ev.data.ptr = ptr; | ||||
| 	epoll_ctl(epollfd_, EPOLL_CTL_MOD, fd, &ev); | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										22
									
								
								Gateway/gateway/event/epoll_event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Gateway/gateway/event/epoll_event.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #pragma once | ||||
| #ifndef _MSC_VER | ||||
| #include "base_event.h" | ||||
| #include <sys/epoll.h> | ||||
|  | ||||
| #define EPOLLEVENTS 1024 | ||||
| class EpollEvent : | ||||
| 	public BaseEvent { | ||||
| public: | ||||
| 	EpollEvent(GameClientMgr* cli_mgr); | ||||
| 	~EpollEvent(); | ||||
| 	virtual bool init(void); | ||||
| 	virtual void RunOne(void); | ||||
| 	virtual void AddReadFd(SOCKET fd, void *ptr = NULL); | ||||
| 	virtual void DelFd(SOCKET fd, void *ptr = NULL); | ||||
| 	virtual void AddWriteFd(SOCKET fd, void *ptr = NULL); | ||||
| private: | ||||
| 	SOCKET epollfd_; | ||||
| 	SOCKET listen_fd_; | ||||
| 	struct epoll_event events_[EPOLLEVENTS]; | ||||
| }; | ||||
| #endif | ||||
							
								
								
									
										13
									
								
								Gateway/gateway/event/select_event.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Gateway/gateway/event/select_event.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| #include "StdAfx.h" | ||||
| #include "select_event.h" | ||||
| SelectEvent::SelectEvent(GameClientMgr* cli_mgr) : BaseEvent(cli_mgr){ | ||||
|  | ||||
| } | ||||
|  | ||||
| SelectEvent::~SelectEvent() { | ||||
|  | ||||
| } | ||||
|  | ||||
| void SelectEvent::RunOne(void) { | ||||
| 	cli_mgr_->ProssClient(); | ||||
| } | ||||
							
								
								
									
										11
									
								
								Gateway/gateway/event/select_event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Gateway/gateway/event/select_event.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| #pragma once | ||||
| #include "base_event.h" | ||||
| #include <map> | ||||
|  | ||||
| class SelectEvent :	public BaseEvent { | ||||
| public: | ||||
| 	typedef std::map<SOCKET, void*> FdPtrMap; | ||||
| 	SelectEvent(GameClientMgr* cli_mgr); | ||||
| 	~SelectEvent(); | ||||
| 	virtual void RunOne(void); | ||||
| }; | ||||
							
								
								
									
										144
									
								
								Gateway/gateway/gameworld/game_world_client.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								Gateway/gateway/gameworld/game_world_client.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| #include "StdAfx.h" | ||||
| #include "game_world_client.h" | ||||
|  | ||||
| GameWorldClient::GameWorldClient(GateServer* serv, GameClientMgr* gcmgr, const char* name) : | ||||
| NetClient(name), | ||||
| serv_(serv), | ||||
| gcmgr_(gcmgr) { | ||||
| 	SetClientName(name); | ||||
| 	free_.setLock(&lock_); | ||||
| } | ||||
|  | ||||
|  | ||||
| GameWorldClient::~GameWorldClient() { | ||||
| 	free_.flush(); | ||||
|  | ||||
| 	for (int i = 0; i < free_.count(); i++) | ||||
| 	{ | ||||
| 		DataPacket* dp = free_[i]; | ||||
| 		dp->setPosition(0); | ||||
| 		Flush(*dp); | ||||
| 	} | ||||
|  | ||||
| 	free_.clear(); | ||||
| } | ||||
|  | ||||
| void GameWorldClient::OnRecv(const uint16_t cmd, char * buf, int size) | ||||
| { | ||||
| 	GATEMSGHDR* hdr = (GATEMSGHDR*)buf; | ||||
| 	buf = (char*)(hdr + 1); | ||||
|  | ||||
| 	switch (cmd) { | ||||
| 	case GM_DATA: { | ||||
| 		//NetId net_id; | ||||
| 		//net_id.socket_ = hdr->nSocket; | ||||
| 		//net_id.index_ = hdr->wSessionIdx; | ||||
| 		//net_id.gate_id_ = hdr->wServerIdx; | ||||
| 		DataPacket *dp = AllocPostPacket(); | ||||
| 		dp->writeBuf(buf , size); | ||||
| 		dp->setPosition(0); | ||||
| 		GateInterMsg msg; | ||||
| 		msg.msg_id_ = gcGWData; | ||||
| 		msg.data_.index_ = hdr->wSessionIdx; | ||||
| 		msg.data_.packet_ = dp; | ||||
| 		gcmgr_->PostMsg(msg); | ||||
| 		break; | ||||
| 	} | ||||
| 	case GM_CLOSE: { | ||||
| 		GateInterMsg msg; | ||||
| 		msg.msg_id_ = gcGWClose; | ||||
| 		msg.data_.index_ = hdr->wSessionIdx; | ||||
| 		gcmgr_->PostMsg(msg); | ||||
| 		break; | ||||
| 	} | ||||
| 	case GM_SERVERUSERINDEX: { | ||||
| 		GateInterMsg msg; | ||||
| 		msg.msg_id_ = gcServerIdx; | ||||
| 		msg.data_.idx_ = hdr->wSessionIdx; | ||||
| 		msg.data_.para_ = hdr->wServerIdx; | ||||
| 		gcmgr_->PostMsg(msg); | ||||
| 		break; | ||||
| 	} | ||||
| 	case GM_CHECKCLIENT: { | ||||
| 		break; | ||||
| 	} | ||||
| 	default: | ||||
| 		MSG_LOG("not handle gameword cmd:%d", cmd); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void GameWorldClient::OnChannelMsg(char* buf, int size) { | ||||
| 	Channel info = *((Channel*)buf); | ||||
| 	switch (info.type) { | ||||
| 	case ccBroadCast: { | ||||
| 		uint8_t nsize = sizeof(Channel); | ||||
| 		DataPacket *dp = AllocPostPacket(); | ||||
| 		dp->writeBuf(buf + nsize, size - nsize); | ||||
| 		dp->setPosition(0); | ||||
| 		GateInterMsg msg; | ||||
| 		msg.msg_id_ = gcChBro; | ||||
| 		msg.data_.b_channel_ = info.channelId; | ||||
| 		msg.data_.b_para_ = info.para; | ||||
| 		msg.data_.dp_ = dp; | ||||
| 		gcmgr_->PostMsg(msg); | ||||
| 		break; | ||||
| 	} | ||||
| 	case ccAddUser: { | ||||
| 		GateInterMsg msg; | ||||
| 		msg.msg_id_ = gcChAdd; | ||||
| 		msg.data_.channel_ = info.channelId; | ||||
| 		msg.data_.para_ = info.para; | ||||
| 		msg.data_.idx_ = info.index_; | ||||
| 		gcmgr_->PostMsg(msg); | ||||
| 		break; | ||||
| 	} | ||||
| 	case ccDelUser: { | ||||
| 		GateInterMsg msg; | ||||
| 		msg.msg_id_ = gcChDel; | ||||
| 		msg.data_.channel_ = info.channelId; | ||||
| 		msg.data_.para_ = info.para; | ||||
| 		msg.data_.idx_ = info.index_; | ||||
| 		gcmgr_->PostMsg(msg); | ||||
| 		break; | ||||
| 	} | ||||
| 	default: | ||||
| 		MSG_LOG("not handle channel type:%d", info.type); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int GameWorldClient::GetLocalServerType() { | ||||
| 	return SrvDef::GateServer; | ||||
| } | ||||
|  | ||||
| const char * GameWorldClient::GetLocalServerName() { | ||||
| 	return gcmgr_->GetServiceName(); | ||||
| } | ||||
|  | ||||
| void GameWorldClient::OnDisconnected() { | ||||
| 	GateInterMsg msg; | ||||
| 	msg.msg_id_ = gcGWDisconn; | ||||
| 	gcmgr_->PostMsg(msg); | ||||
| } | ||||
|  | ||||
| void GameWorldClient::FreeBackUserDataPacket(DataPacket* pack) { | ||||
| 	free_.append(pack); | ||||
| } | ||||
|  | ||||
| DataPacket* GameWorldClient::AllocPostPacket() | ||||
| { | ||||
| 	if (free_.count() <= 0) | ||||
| 	{ | ||||
| 		free_.flush(); | ||||
| 	} | ||||
|  | ||||
| 	if (free_.count() <= 0) | ||||
| 	{ | ||||
| 		AllocSendPack(&free_, 512); | ||||
| 	} | ||||
|  | ||||
| 	DataPacket* dp = free_.pop();//<2F>õ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Datapacket | ||||
| 	dp->setLength(0); | ||||
| 	return dp; | ||||
| } | ||||
							
								
								
									
										34
									
								
								Gateway/gateway/gameworld/game_world_client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Gateway/gateway/gameworld/game_world_client.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| #pragma once | ||||
| struct Channel { | ||||
| 	int type;// == 0 ? ccAddUser : ccDelUser; | ||||
| 	int channelId; | ||||
| 	int para; | ||||
| 	int index_; | ||||
| }; | ||||
|  | ||||
| class GameWorldClient : | ||||
| 	public NetClient | ||||
| { | ||||
| public: | ||||
| 	GameWorldClient(GateServer* serv, GameClientMgr* gcmgr, const char* name); | ||||
| 	~GameWorldClient(); | ||||
| 	// 回收空闲的CDataPacket类 | ||||
| 	void FreeBackUserDataPacket(DataPacket* pack); | ||||
| protected: | ||||
| 	// 以下是实现基类的虚函数 | ||||
| 	virtual void OnRecv(const uint16_t cmd, char* buf, int size); | ||||
| 	void OnChannelMsg(char* buf, int size); | ||||
| 	virtual int GetLocalServerType(); | ||||
| 	/* 查询本地服务器的名称,以便正确的发送注册数据 */ | ||||
| 	virtual const char* GetLocalServerName(); | ||||
| 	virtual void OnDisconnected(); | ||||
| private: | ||||
| 	// 分配一个包,这个包传递给游戏主逻辑处理 | ||||
| 	DataPacket* AllocPostPacket(); | ||||
| private: | ||||
| 	QueueList<DataPacket*>			free_;	//用来存放空闲的数据包 | ||||
| 	Mutex							lock_; | ||||
| 	GateServer* serv_; | ||||
| 	GameClientMgr* gcmgr_; | ||||
| }; | ||||
|  | ||||
							
								
								
									
										12
									
								
								Gateway/gateway/gate_def.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Gateway/gateway/gate_def.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| #pragma once | ||||
| #include <syscall.h> | ||||
| #define GetCurrentThreadId() syscall(SYS_gettid) | ||||
|  | ||||
| #define MSG_LOG(format, ...) OutputMsg(rmNormal, "[%s:%d %s] "#format, __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__); | ||||
| #define MSG_WAR(format, ...) OutputMsg(rmWarning, "[%s:%d %s] "#format, __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__); | ||||
| #define MSG_TIP(format, ...) OutputMsg(rmTip, "[%s:%d %s] "#format, __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__); | ||||
| #define MSG_ERR(format, ...) OutputMsg(rmError, "[%s:%d %s] "#format, __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__); | ||||
|  | ||||
| #define OrderSwap16(A) (((uint16_t)(A) >> 8) | ((uint16_t)(A & 0xFF) << 8)) | ||||
| #define OrderSwap32(A) (OrderSwap16((uint32_t)(A) >> 16) | ((uint32_t)(OrderSwap16(A)) << 16)) | ||||
| #define OrderSwap64(A) (OrderSwap32((uint64_t)(A) >> 32) | ((uint64_t)(OrderSwap32(A)) << 32)); | ||||
							
								
								
									
										38
									
								
								Gateway/gateway/gate_server.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Gateway/gateway/gate_server.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| #include "StdAfx.h" | ||||
|  | ||||
| GateServer::GateServer() { | ||||
| 	GateServer::Instance = this; | ||||
| 	GetSystemTime(cur_sys_time_); | ||||
| 	now_sec_.encode(cur_sys_time_); | ||||
| } | ||||
|  | ||||
| GateServer::~GateServer() { | ||||
| 	for (auto gcmgr : game_client_mgr_) { | ||||
| 		SafeDelete(gcmgr); | ||||
| 	} | ||||
| 	game_client_mgr_.clear(); | ||||
| } | ||||
|  | ||||
| bool GateServer::StartServer() { | ||||
| 	MSG_LOG("start server..................."); | ||||
| 	for (auto gcmgr : game_client_mgr_) { | ||||
| 		gcmgr->Startup(); | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void GateServer::StopServer() { | ||||
| 	MSG_LOG("stop server................... start"); | ||||
| 	for (auto gcmgr : game_client_mgr_) { | ||||
| 		gcmgr->Stop(); | ||||
| 	} | ||||
| 	MSG_LOG("stop server................... ok"); | ||||
| } | ||||
|  | ||||
| GameClientMgr* GateServer::AddGameClientMgr(const char *name) | ||||
| { | ||||
| 	GameClientMgr* gcmgr = new GameClientMgr(name, this); | ||||
| 	gcmgr->SetServiceName(name); | ||||
| 	game_client_mgr_.push_back(gcmgr); | ||||
| 	return gcmgr; | ||||
| } | ||||
							
								
								
									
										31
									
								
								Gateway/gateway/gate_server.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Gateway/gateway/gate_server.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| #pragma once | ||||
|  | ||||
| class GameClientMgr; | ||||
|  | ||||
| class GateServer { | ||||
| public: | ||||
| 	GateServer(); | ||||
| 	~GateServer(); | ||||
|  | ||||
| 	//启动服务器 | ||||
| 	bool StartServer(); | ||||
| 	//停止服务器 | ||||
| 	void StopServer(); | ||||
|  | ||||
| 	//获取同步的逻辑短日期时间值 | ||||
| 	inline unsigned int getMiniDateTime() { | ||||
| 		GetSystemTime(cur_sys_time_); | ||||
| 		now_sec_.encode(cur_sys_time_);  | ||||
| 		return now_sec_; | ||||
| 	} | ||||
| 	 | ||||
| 	GameClientMgr* AddGameClientMgr(const char *name); | ||||
|  | ||||
| public: | ||||
| 	static GateServer* Instance; | ||||
|  | ||||
| private: | ||||
| 	std::vector<GameClientMgr*> game_client_mgr_;//游戏客户端管理类 | ||||
| 	SYSTEMTIME cur_sys_time_; | ||||
| 	SecondTime now_sec_; //当前短日期时间 | ||||
| }; | ||||
							
								
								
									
										148
									
								
								Gateway/gateway/main.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								Gateway/gateway/main.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| #include "StdAfx.h" | ||||
| #include <signal.h> | ||||
|  | ||||
| void Exit() { | ||||
| #ifdef	_MLIB_DUMP_MEMORY_LEAKS_ | ||||
| 	_CrtDumpMemoryLeaks(); | ||||
| #endif | ||||
| } | ||||
| #ifdef _MSC_VER | ||||
| const char szExceptionDumpFile[] = ".\\wsgate.dmp"; | ||||
| #endif | ||||
| bool SetupLogicServerConfig(GateServer* gate_srv); | ||||
| void ServerMain(); | ||||
|  | ||||
| GateServer* GateServer::Instance = NULL; | ||||
|  | ||||
| void sighup_handler(int) { | ||||
| 	MSG_TIP("log the perfermance "); | ||||
| 	MemoryCounter::getSingleton().logToFile(); | ||||
| } | ||||
|  | ||||
| bool runing = false; | ||||
| void sigterm_handler(int arg) { | ||||
| 	sighup_handler(arg); | ||||
| 	runing = false; | ||||
| } | ||||
|  | ||||
| int main(int argc, char** argv) { | ||||
| 	winitseed((unsigned int)time(NULL)); | ||||
| #ifdef _MSC_VER | ||||
| 	//初始化网络库 | ||||
| 	int err = WorkSocket::InitSocketLib(); | ||||
| 	if (err) { | ||||
| 		MSG_ERR("initialize inet library failure"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	SetMiniDumpFlag(MiniDumpWithFullMemory, szExceptionDumpFile); | ||||
| 	SetUnhandledExceptionFilter(DefaultUnHandleExceptionFilter); | ||||
| #else | ||||
| 	//改为正确的启动目录 | ||||
| 	const int MAX_PATH = 256; | ||||
| 	char startDir[MAX_PATH]; | ||||
| 	FDOP::ExtractFileDirectory(argv[1], startDir, MAX_PATH - 1); | ||||
| 	//merge | ||||
| 	char dir[MAX_PATH]; | ||||
| 	if (startDir[0] == '/')	{ | ||||
| 		SNPRINTFA(dir, MAX_PATH - 1, "%s", startDir); | ||||
| 	} else { | ||||
| 		char p[MAX_PATH]; | ||||
| 		getcwd(p, MAX_PATH - 1); | ||||
| 		SNPRINTFA(dir, MAX_PATH - 1, "%s/%s", p, startDir); | ||||
| 	} | ||||
| 	int err = chdir(dir); | ||||
| 	printf("chdir:%s, ret:%d\n", dir, err); | ||||
|  | ||||
| 	//daemon(1, 0); | ||||
| #endif | ||||
|  | ||||
| 	InitDefMsgOut(); | ||||
| #ifdef _MSC_VER | ||||
| 	TimeProfMgr::getSingleton().InitMgr(); | ||||
| #endif | ||||
|  | ||||
| 	ServerMain(); | ||||
|  | ||||
| 	MemoryCounter::getSingleton().logToFile(); | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| 	TimeProfMgr::getSingleton().clear(); | ||||
| 	WorkSocket::UnintSocketLib(); | ||||
| #endif | ||||
|  | ||||
| 	MemoryCounter::getSingleton().clear(); | ||||
| 	UninitDefMsgOut(); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| void ServerMain() { | ||||
| 	//设置窗口标题 | ||||
| #ifdef _MSC_VER | ||||
| 	SetConsoleTitle("gateway"); | ||||
| #endif | ||||
| 	char logpath[256] = "./log/"; | ||||
|  | ||||
| 	if (!FDOP::FileExists(logpath)) { | ||||
| 		FDOP::DeepCreateDirectory(logpath); | ||||
| 	} | ||||
| 	FileLogger flog(("./log/gateway")); | ||||
|  | ||||
| 	GateServer::Instance = new GateServer(); | ||||
|  | ||||
| 	if (SetupLogicServerConfig(GateServer::Instance))	{ | ||||
| 		if (GateServer::Instance->StartServer()) { | ||||
| 			MSG_TIP("==========================="); | ||||
| 			MSG_TIP("gateway start ok"); | ||||
| 			MSG_TIP("quit:stop server and exit"); | ||||
| 			MSG_TIP("==========================="); | ||||
| #ifndef _MSC_VER		 | ||||
| 			runing = true; | ||||
| 			signal(SIGTERM, sigterm_handler); | ||||
| 			signal(SIGPIPE, SIG_IGN); | ||||
| 			signal(SIGHUP, sighup_handler); | ||||
| #endif | ||||
| 			while (true) { | ||||
| #ifdef _MSC_VER | ||||
| 				char cmd_buf[512]; | ||||
| 				//gets(cmd_buf); | ||||
| 				scanf("%s", cmd_buf); | ||||
|  | ||||
| 				if (cmd_buf == NULL || *cmd_buf == 0) { | ||||
| 					Sleep(500); | ||||
| 					continue; | ||||
| 				} | ||||
| 				if (strncmp(cmd_buf, ("\\q"), 2) == 0 | ||||
| 					|| strncmp(cmd_buf, ("exit"), 4) == 0 | ||||
| 					|| strncmp(cmd_buf, ("quit"), 4) == 0) { | ||||
| 					sighup_handler(0); | ||||
| 					MSG_TIP("stop gate..."); | ||||
| 					break; | ||||
| 				} else if (strncmp(cmd_buf, "spf", 3) == 0) { | ||||
| 					sighup_handler(0); | ||||
| 				} else if (strncmp(cmd_buf, "dmp", 3) == 0) { | ||||
| 					DebugBreak(); | ||||
| 				} | ||||
| #else | ||||
| 				if (!runing) break; | ||||
| #endif | ||||
| 				Sleep(10); | ||||
| 			} | ||||
|  | ||||
| 			GateServer::Instance->StopServer(); | ||||
| 		} else { | ||||
| 			MSG_ERR("Press Any Key To Exit...\n"); | ||||
| 			getc(stdin); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	delete GateServer::Instance; | ||||
| 	MSG_LOG("delete GateServer::Instance"); | ||||
| } | ||||
|  | ||||
| bool SetupLogicServerConfig(GateServer* gate_srv) { | ||||
| 	WsGateConfig config; | ||||
| 	return config.loadServerConfig(gate_srv); | ||||
| } | ||||
|  | ||||
							
								
								
									
										235
									
								
								Gateway/gateway/srv/game_client_mgr.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								Gateway/gateway/srv/game_client_mgr.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,235 @@ | ||||
| #include "StdAfx.h" | ||||
| #include <map> | ||||
| #include "client/client_obj_mgr.h" | ||||
| #include "event/select_event.h" | ||||
| #include "event/epoll_event.h" | ||||
|  | ||||
| GameClientMgr::GameClientMgr(const char *name, GateServer *srv) { | ||||
| 	srv_ = srv; | ||||
| 	gw_cli_ = new GameWorldClient(srv, this, name); | ||||
| 	cli_obj_mgr_ = new ClientObjMgr(); | ||||
| 	inner_msg_list_.setLock(&inner_msg_lock_); | ||||
| #if USE_EPOLL | ||||
| 	event_ = new EpollEvent(this); | ||||
| #else | ||||
| 	event_ = new SelectEvent(this); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| GameClientMgr::~GameClientMgr() { | ||||
| 	cli_obj_mgr_->flush(); | ||||
| 	SafeDelete(cli_obj_mgr_); | ||||
| 	inner_msg_list_.flush(); | ||||
| 	inner_msg_list_.clear(); | ||||
| 	SafeDelete(gw_cli_); | ||||
| } | ||||
|  | ||||
| void GameClientMgr::SetMaxSession(int max_session) { | ||||
| 	cli_obj_mgr_->SetMaxSession(max_session); | ||||
| } | ||||
|  | ||||
| void GameClientMgr::InitGameWorldClient(const char * ip, int port) { | ||||
| 	gw_cli_ = new GameWorldClient(srv_, this, GetServiceName()); | ||||
| 	gw_cli_->UseBaseAlloc(true); | ||||
| 	gw_cli_->SetHost(ip); | ||||
| 	gw_cli_->SetPort(port); | ||||
| } | ||||
|  | ||||
| bool GameClientMgr::onConnect(SOCKET nSocket, sockaddr_in * pAddrIn) { | ||||
| 	if (!gw_cli_->connected()) return false; | ||||
|  | ||||
| 	Client *cli = new Client(this, nSocket, pAddrIn); | ||||
| 	cli_obj_mgr_->setNewClient(cli); | ||||
| 	cli_obj_mgr_->flush(); | ||||
| 	cli->SetBlockMode(false); | ||||
| 	GateInterMsg msg; | ||||
| 	msg.msg_id_ = gcAddClient; | ||||
| 	msg.data_.fd_ = nSocket; | ||||
| 	msg.data_.sessidx_ = cli->GetSessionId(); | ||||
| 	PostMsg(msg); | ||||
| 	OutputMsg(rmTip, _T("[Login] (1) 客户端连接上来: gatekey(%d),socket(%lld),GateIdx(%d),LogicIdx(%d),CurrentThreadId(%d)。"), | ||||
| 		cli->GetSKey(), nSocket, cli->GetNetId().index_, cli->GetNetId().gate_id_, GetCurrentThreadId()); | ||||
| 	//MSG_TIP("new client connect fd:%d, sid:%d", cli->GetFd(), cli->GetSessionId()); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| int GameClientMgr::Run() { | ||||
| 	inner_msg_list_.flush(); | ||||
| 	int count = inner_msg_list_.count(); | ||||
| 	for (int i = 0; i < count; ++i) | ||||
| 	{ | ||||
| 		GateInterMsg& msg = inner_msg_list_[i]; | ||||
| 		OnRecvSysMsg(msg); | ||||
| 	} | ||||
| 	inner_msg_list_.clear(); | ||||
| 	event_->RunOne(); | ||||
| 	return count; | ||||
| } | ||||
|  | ||||
| void GameClientMgr::OnStart() { | ||||
| 	MSG_LOG("GameClientMgr::OnStart"); | ||||
| 	event_->init(); | ||||
| } | ||||
|  | ||||
| void GameClientMgr::OnStop() { | ||||
| 	MSG_LOG("GameClientMgr::OnStop"); | ||||
| } | ||||
|  | ||||
| void GameClientMgr::Stop() { | ||||
| 	MSG_LOG("%s, start", GetServiceName()); | ||||
| 	while (gw_cli_->GetPacketCount()) {//这里还有包没发完,导致一致没法停止 | ||||
| 		gw_cli_->SingleRun(); | ||||
| 		Sleep(1); | ||||
| 	} | ||||
| 	gw_cli_->Stop(); | ||||
| 	Inherited::Stop(); | ||||
| 	MSG_LOG("%s, ok", GetServiceName()); | ||||
| } | ||||
|  | ||||
| void GameClientMgr::OnRecvSysMsg(GateInterMsg & msg) | ||||
| { | ||||
| 	switch (msg.msg_id_) | ||||
| 	{ | ||||
| 		case gcAddClient: | ||||
| 		{ | ||||
| 			event_->AddReadFd(msg.data_.fd_, cli_obj_mgr_->get(msg.data_.sessidx_)); | ||||
| 			break; | ||||
| 		} | ||||
| 		case gcServerIdx: | ||||
| 		{ | ||||
| 			Client* cli = cli_obj_mgr_->get(msg.data_.idx_); | ||||
| 			if (cli) { | ||||
| 				cli->GetNetId().gate_id_ = msg.data_.para_; | ||||
| 				OutputMsg(rmTip, _T("[Login] (5) LogicServer已成功添加玩家Gate: gatekey(%d),socket(%lld),GateIdx(%d),LogicIdx(%d),CurrentThreadId(%d)。"), | ||||
| 					cli->GetSKey(), cli->GetNetId().socket_, cli->GetNetId().index_, cli->GetNetId().gate_id_, GetCurrentThreadId()); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		case gcGWData: | ||||
| 		{ | ||||
| 			Client* cli = cli_obj_mgr_->get(msg.data_.index_); | ||||
| 			if (cli) { | ||||
| 				auto dp = msg.data_.packet_; | ||||
| 				cli->OnGameWorldRecv(dp->getOffsetPtr(), dp->getAvaliableLength()); | ||||
| 			} | ||||
| 			gw_cli_->FreeBackUserDataPacket(msg.data_.packet_); | ||||
| 			break; | ||||
| 		} | ||||
| 		case gcGWClose: | ||||
| 		{ | ||||
| 			Client* cli = cli_obj_mgr_->get(msg.data_.index_); | ||||
| 			if (cli) { | ||||
| 				cli->Close(); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		case gcChAdd: | ||||
| 		{ | ||||
| 			uint64_t key = MAKEINT64(msg.data_.channel_, msg.data_.para_); | ||||
| 			channel_indexs_map_[key].insert(msg.data_.idx_); | ||||
| 			break; | ||||
| 		} | ||||
| 		case gcChDel: | ||||
| 		{ | ||||
| 			uint64_t key = MAKEINT64(msg.data_.channel_, msg.data_.para_); | ||||
| 			channel_indexs_map_[key].erase(msg.data_.idx_); | ||||
| 			break; | ||||
| 		} | ||||
| 		case gcChBro: | ||||
| 		{ | ||||
| 			uint64_t key = MAKEINT64(msg.data_.b_channel_, msg.data_.b_para_); | ||||
| 			auto &list = channel_indexs_map_[key]; | ||||
| 			for (auto idx:list) { | ||||
| 				Client* cli = cli_obj_mgr_->get(idx); | ||||
| 				if (cli) { | ||||
| 					auto dp = msg.data_.packet_; | ||||
| 					cli->OnGameWorldRecv(dp->getOffsetPtr(), dp->getAvaliableLength()); | ||||
| 				} | ||||
| 			} | ||||
| 			gw_cli_->FreeBackUserDataPacket(msg.data_.dp_); | ||||
| 			break; | ||||
| 		} | ||||
| 		case gcGWDisconn: | ||||
| 		{ | ||||
| 			CloseAllClient(); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void GameClientMgr::ProssClient(void) { | ||||
| 	//cli_obj_mgr_->flush(); | ||||
| 	auto &list = cli_obj_mgr_->getClientMap(); | ||||
| 	std::vector<uint16_t> remove_list; | ||||
| 	for (auto it:list)	{ | ||||
| 		Client *cli = it.second; | ||||
| 		if(cli) | ||||
| 		{ | ||||
| 			if (cli->IsClose()) { | ||||
| 				remove_list.push_back(cli->GetSessionId()); | ||||
| 				continue; | ||||
| 			} | ||||
| 			cli->RecvData(); | ||||
| 			cli->PacketHandle(); | ||||
| 			cli->WriteEvent(); | ||||
| 			cli->SendData(); | ||||
| 		} | ||||
| 	} | ||||
| 	for (auto idx: remove_list) { | ||||
| 		Client *cli = cli_obj_mgr_->remove(idx); | ||||
| 		SafeDelete(cli); | ||||
| 	} | ||||
| 	remove_list.clear(); | ||||
| } | ||||
|  | ||||
| void GameClientMgr::HandleReadEvent(SOCKET fd, Client * cli) { | ||||
| 	if (cli) { | ||||
| 		cli->RecvData(); | ||||
| 		cli->PacketHandle(); | ||||
| 		event_->AddWriteFd(fd, cli); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void GameClientMgr::HandleWriteEvent(SOCKET fd, Client * cli) { | ||||
| 	if (cli) { | ||||
| 		cli->WriteEvent(); | ||||
| 		if (!cli->SendData()) { | ||||
| 			event_->AddWriteFd(fd, cli); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void GameClientMgr::CloseAllClient() { | ||||
| 	cli_obj_mgr_->flush(); | ||||
| 	auto &list = cli_obj_mgr_->getClientMap(); | ||||
| 	std::vector<uint16_t> remove_list; | ||||
| 	for (auto it : list) { | ||||
| 		Client *cli = it.second; | ||||
| 		cli->Close(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void GameClientMgr::HaveData(Client * cli) { | ||||
| 	if(cli) { | ||||
| 		event_->AddWriteFd(cli->GetFd(), cli); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void GameClientMgr::CloseClient(Client * cli) { | ||||
| 	event_->DelFd(cli->GetFd()); | ||||
| 	closesocket(cli->GetFd()); | ||||
| 	if (cli_obj_mgr_->get(cli->GetSessionId())) | ||||
| 	{ | ||||
| 		cli_obj_mgr_->remove(cli->GetSessionId()); | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
|  | ||||
| bool GameClientMgr::Startup() { | ||||
| 	if (!Inherited::Startup()) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	// 创建发送线程 | ||||
| 	 | ||||
| 	return gw_cli_->Startup(); | ||||
| } | ||||
							
								
								
									
										95
									
								
								Gateway/gateway/srv/game_client_mgr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								Gateway/gateway/srv/game_client_mgr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <map> | ||||
| #include <set> | ||||
|  | ||||
| typedef union GateInterMsgData { | ||||
| 	struct { | ||||
| 		uint32_t b_channel_; | ||||
| 		uint32_t b_para_; | ||||
| 		DataPacket* dp_; | ||||
| 	}; | ||||
| 	struct { | ||||
| 		uint32_t index_; | ||||
| 		DataPacket* packet_; | ||||
| 	}; | ||||
| 	struct { | ||||
| 		uint32_t idx_; | ||||
| 		uint32_t para_; | ||||
| 		uint32_t channel_; | ||||
| 	}; | ||||
| 	struct { | ||||
| 		uint32_t sessidx_; | ||||
| 		SOCKET fd_; | ||||
| 	}; | ||||
| } tagGateInterMsgData; | ||||
|  | ||||
| typedef struct GateInterMsg | ||||
| { | ||||
| 	int	msg_id_; | ||||
| 	GateInterMsgData data_; | ||||
| } tagGateInterMsg; | ||||
|  | ||||
| class GameWorldClient; | ||||
| class BaseEvent; | ||||
| class SocketSrv; | ||||
| class ClientObjMgr; | ||||
|  | ||||
| enum { | ||||
| 	gcAddClient = 1,	//增加一个新的客户端连接 | ||||
| 	gcGWData = 2, //游戏服给客户端发消息 | ||||
| 	gcGWClose = 3,	//游戏服主动关闭客户端 | ||||
| 	gcChBro = 4,//频道广播消息 | ||||
| 	gcChAdd = 5,//频道信息增加 | ||||
| 	gcChDel = 6,//频道信息删除 | ||||
| 	gcGWDisconn = 7,//游戏服断开连接 | ||||
| 	gcServerIdx = 8,//游戏服的玩家对应gateid | ||||
| }; | ||||
|  | ||||
| class GameClientMgr : public SocketSrv { | ||||
| public: | ||||
| 	typedef SocketSrv Inherited; | ||||
| 	GameClientMgr(const char *name, GateServer *srv); | ||||
| 	~GameClientMgr(); | ||||
|  | ||||
| 	void SetMaxSession(int max_session); | ||||
|  | ||||
| 	bool Startup(); | ||||
| 	void InitGameWorldClient(const char *ip, int port); | ||||
| 	GameWorldClient* GetGameWorldClient(void) { return gw_cli_; } | ||||
| 	virtual bool onConnect(SOCKET nSocket, sockaddr_in* pAddrIn); | ||||
| 	 | ||||
| 	//单次逻辑处理 | ||||
| 	virtual int Run(); | ||||
| 	virtual void OnStart(); | ||||
| 	virtual void OnStop(); | ||||
| 	virtual void Stop(); | ||||
|  | ||||
| 	void PostMsg(GateInterMsg& msg) { | ||||
| 		inner_msg_list_.append(msg); | ||||
| 	} | ||||
|  | ||||
| 	void OnRecvSysMsg(GateInterMsg& msg); | ||||
|  | ||||
| 	//select模式使用 | ||||
| 	void ProssClient(void); | ||||
| 	//epoll模式使用 | ||||
| 	void HandleReadEvent(SOCKET fd, Client* cli); | ||||
| 	void HandleWriteEvent(SOCKET fd, Client* cli); | ||||
| 	//断开所有客户端连接 | ||||
| 	void CloseAllClient(); | ||||
| 	void HaveData(Client* cli); | ||||
| 	 | ||||
| 	void CloseClient(Client *cli); | ||||
|  | ||||
| protected: | ||||
|  | ||||
| 	GateServer *srv_; | ||||
| 	GameWorldClient *gw_cli_; | ||||
| 	ClientObjMgr *cli_obj_mgr_; | ||||
| 	std::map<uint64_t, std::set<int> > channel_indexs_map_; | ||||
|  | ||||
| 	QueueList<GateInterMsg> inner_msg_list_;//内部消息列表 | ||||
| 	Mutex				 inner_msg_lock_;//内部消息列表锁 | ||||
| 	BaseEvent			*event_;//事件处理 | ||||
| }; | ||||
							
								
								
									
										148
									
								
								Gateway/gateway/srv/socket_srv.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								Gateway/gateway/srv/socket_srv.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| #ifdef _MSC_VER | ||||
| #include <Windows.h>   | ||||
| #include <process.h>   | ||||
| #else   | ||||
| #include <pthread.h>   | ||||
| #endif   | ||||
| #include "StdAfx.h" | ||||
| #include "socket_srv.h" | ||||
|  | ||||
|  | ||||
| SocketSrv::SocketSrv() { | ||||
| 	srv_stoped_ = true; | ||||
| 	memset(server_name_, 0, sizeof(server_name_)); | ||||
| #ifdef _MSC_VER   | ||||
| 	accept_thread_ = NULL; | ||||
| #else   | ||||
| 	accept_thread_ = 0; | ||||
| #endif   | ||||
| 	accept_exit_ = true; | ||||
| } | ||||
|  | ||||
|  | ||||
| SocketSrv::~SocketSrv() | ||||
| { | ||||
| #ifdef _MSC_VER   | ||||
| 	if (NULL != accept_thread_)	{ | ||||
| 		CloseHandle(accept_thread_); | ||||
| 	} | ||||
| 	accept_thread_ = NULL; | ||||
| #else   | ||||
| 	accept_thread_ = 0; | ||||
| #endif   | ||||
| } | ||||
| #ifdef _MSC_VER | ||||
| void STDCALL SocketSrv::ServerSocketAcceptThreadRoutine(void* arg) { | ||||
| #else | ||||
| void * SocketSrv::ServerSocketAcceptThreadRoutine(void * arg) { | ||||
| #endif | ||||
| 	SocketSrv *srv = (SocketSrv*)arg; | ||||
| 	struct sockaddr_in server_addr; | ||||
| 	SOCKET listen_fd_ = 0; | ||||
| 	if ((listen_fd_ = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) { | ||||
| 		MSG_ERR("create socket error:%d",errno); | ||||
| 		assert(false); | ||||
| 	} | ||||
| #ifdef _MSC_VER | ||||
| 	char optval = 1; | ||||
| #else | ||||
| 	int optval = 1; | ||||
| #endif | ||||
| 	if (setsockopt(listen_fd_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == SOCKET_ERROR) { | ||||
| 		MSG_ERR("setsockopt"); | ||||
| 		assert(false); | ||||
| 	} | ||||
| 	server_addr.sin_family = AF_INET; | ||||
| 	server_addr.sin_port = htons(srv->GetServicePort()); | ||||
| 	server_addr.sin_addr.s_addr = inet_addr(srv->GetServiceHost()); | ||||
| 	memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero)); | ||||
|  | ||||
| 	if (::bind(listen_fd_, (struct sockaddr *)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) { | ||||
| 		MSG_ERR("bind error"); | ||||
| 		assert(false); | ||||
| 	} | ||||
| 	if (listen(listen_fd_, 5) == SOCKET_ERROR) { | ||||
| 		MSG_ERR("listen error"); | ||||
| 		assert(false); | ||||
| 	} | ||||
| 	socklen_t len = sizeof(sockaddr); | ||||
| 	do { | ||||
| 		sockaddr_in cli_addr; | ||||
| 		SOCKET nSocket = accept(listen_fd_, (sockaddr*)&cli_addr, &len); | ||||
| 		if (srv->Started() && !srv->onConnect(nSocket, &cli_addr)) { | ||||
| 			closesocket(nSocket); | ||||
| 		} | ||||
| 	} while (srv->Started()); | ||||
| 	closesocket(listen_fd_); | ||||
| 	srv->accept_exit_ = true; | ||||
| #ifdef _MSC_VER | ||||
| 	ExitThread(0);//设置线程退出返回值 | ||||
| #else | ||||
| 	return NULL; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void SocketSrv::SetServiceName(const char * sName) | ||||
| { | ||||
| 	_STRNCPY_A(server_name_, sName); | ||||
| } | ||||
|  | ||||
| void SocketSrv::SetServiceHost(const char * sHost) | ||||
| { | ||||
| 	_STRNCPY_A(host_, sHost); | ||||
| } | ||||
|  | ||||
| void SocketSrv::SetServicePort(const int nPort) { | ||||
| 	port_ = nPort; | ||||
| } | ||||
|  | ||||
| bool SocketSrv::Startup() { | ||||
| 	Inherited:Start(); | ||||
| 	bool ret = true; | ||||
| 	int err = 0; | ||||
| 	srv_stoped_ = false; | ||||
| #ifdef _MSC_VER | ||||
| 	accept_thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ServerSocketAcceptThreadRoutine, this, 0, NULL); | ||||
| 	if (!accept_thread_) { | ||||
| 		err = GetLastError(); | ||||
| 		ret = false; | ||||
| 	} | ||||
| #else | ||||
|  | ||||
| 	if (pthread_create(&accept_thread_, NULL, ServerSocketAcceptThreadRoutine, this)) { | ||||
| 		err = errno; | ||||
| 		ret = false; | ||||
| 	} | ||||
|  | ||||
| #endif | ||||
|  | ||||
| 	if (!ret)  { | ||||
| 		MSG_ERR("create listen thread error %d", err); | ||||
| 		return false; | ||||
| 	} | ||||
| 	accept_exit_ = false; | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void SocketSrv::Stop() { | ||||
| 	if (srv_stoped_) return; | ||||
| 	MSG_LOG("start"); | ||||
| 	srv_stoped_ = true; | ||||
| //	while (!accept_exit_) { | ||||
| //		Sleep(1); | ||||
| //	} | ||||
| //#ifdef _MSC_VER | ||||
| //	CloseThread(accept_thread_); | ||||
| //#endif | ||||
| 	Inherited::Stop(); | ||||
| 	MSG_LOG("ok"); | ||||
| } | ||||
|  | ||||
| void SocketSrv::OnRoutine() { | ||||
| 	OnStart(); | ||||
| 	while (!terminated()) { | ||||
| 		if (Run() <= 0) | ||||
| 			Sleep(1); | ||||
| 	} | ||||
| 	OnStop(); | ||||
| } | ||||
							
								
								
									
										55
									
								
								Gateway/gateway/srv/socket_srv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								Gateway/gateway/srv/socket_srv.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| #pragma once | ||||
| class SocketSrv : public thread::BaseThread { | ||||
| public: | ||||
| 	typedef thread::BaseThread Inherited; | ||||
| 	SocketSrv(); | ||||
| 	~SocketSrv(); | ||||
| #ifdef _MSC_VER | ||||
| 	static void STDCALL ServerSocketAcceptThreadRoutine(void* srv); | ||||
| #else | ||||
| 	static void* ServerSocketAcceptThreadRoutine(void* arg); | ||||
| #endif | ||||
| 	virtual bool onConnect(SOCKET nSocket, sockaddr_in* pAddrIn) = 0; | ||||
| 	virtual void OnRoutine(); | ||||
| 	//单次逻辑处理 | ||||
| 	virtual int Run() = 0; | ||||
| 	virtual void OnStart() = 0; | ||||
| 	virtual void OnStop() = 0; | ||||
|  | ||||
| 	inline const char* GetServiceName() | ||||
| 	{ | ||||
| 		return server_name_; | ||||
| 	} | ||||
| 	inline const char* GetServiceHost() | ||||
| 	{ | ||||
| 		return host_; | ||||
| 	} | ||||
| 	inline int GetServicePort() | ||||
| 	{ | ||||
| 		return port_; | ||||
| 	} | ||||
| 	inline bool Started() | ||||
| 	{ | ||||
| 		return !srv_stoped_; | ||||
| 	} | ||||
| 	void SetServiceName(const char* sName); | ||||
| 	void SetServiceHost(const char* sHost); | ||||
| 	void SetServicePort(const int nPort); | ||||
| 	bool Startup(); | ||||
| 	virtual void Stop(); | ||||
|  | ||||
| private: | ||||
| #ifdef _MSC_VER | ||||
| 	HANDLE						accept_thread_;		//接受客户端连接线程 | ||||
| #else | ||||
| 	pthread_t					accept_thread_; | ||||
| #endif | ||||
|  | ||||
| 	bool						srv_stoped_;				//是否停止工作线程 | ||||
| 	bool						accept_exit_; //监听线程完整退出 | ||||
|  | ||||
| 	char						server_name_[256];	//服务名称 | ||||
| 	char						host_[256];		//服务绑定地址 | ||||
| 	int							port_;			//服务绑定端口 | ||||
| }; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user