├── .env-local ├── .github └── workflows │ └── build-and-push.yml ├── .gitignore ├── DESIGN.md ├── Dockerfile ├── README.md ├── cmake └── modules │ ├── FindSSL.cmake │ ├── Findhiredis.cmake │ ├── Findhiredis_ssl.cmake │ ├── Findjansson.cmake │ └── Findlibuv.cmake ├── code ├── CMakeLists.txt ├── FESL │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ └── server │ │ ├── FESLDriver.cpp │ │ ├── FESLDriver.h │ │ ├── FESLPeer.cpp │ │ ├── FESLPeer.h │ │ ├── FESLServer.cpp │ │ ├── FESLServer.h │ │ ├── commands │ │ ├── basic │ │ │ ├── handle_add_account.cpp │ │ │ ├── handle_add_sub_account.cpp │ │ │ ├── handle_disable_sub_account.cpp │ │ │ ├── handle_gamespy_preauth.cpp │ │ │ ├── handle_get_account.cpp │ │ │ ├── handle_get_country_list.cpp │ │ │ ├── handle_get_entitlement_by_bundle.cpp │ │ │ ├── handle_get_object_inventory.cpp │ │ │ ├── handle_get_subaccounts.cpp │ │ │ ├── handle_get_telemetry_token.cpp │ │ │ ├── handle_get_tos.cpp │ │ │ ├── handle_goodbye.cpp │ │ │ ├── handle_hello.cpp │ │ │ ├── handle_login.cpp │ │ │ ├── handle_login_sub_account.cpp │ │ │ ├── handle_memcheck.cpp │ │ │ ├── handle_ping.cpp │ │ │ ├── handle_register_game.cpp │ │ │ ├── handle_send_accountname.cpp │ │ │ ├── handle_send_password.cpp │ │ │ └── handle_update_account.cpp │ │ └── nu │ │ │ ├── handle_add_persona.cpp │ │ │ ├── handle_get_personas.cpp │ │ │ ├── handle_login.cpp │ │ │ └── handle_login_persona.cpp │ │ └── tasks │ │ ├── Perform_GetEntitledGameFeatures.cpp │ │ ├── Perform_GetObjectInventory.cpp │ │ ├── tasks.cpp │ │ └── tasks.h ├── GP │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ ├── server │ │ ├── GPDriver.cpp │ │ ├── GPDriver.h │ │ ├── GPPeer.cpp │ │ ├── GPPeer.h │ │ ├── GPServer.cpp │ │ ├── GPServer.h │ │ ├── ListHandler.cpp │ │ └── commands │ │ │ ├── handle_addblock.cpp │ │ │ ├── handle_addbuddy.cpp │ │ │ ├── handle_authadd.cpp │ │ │ ├── handle_bm.cpp │ │ │ ├── handle_delbuddy.cpp │ │ │ ├── handle_delprofile.cpp │ │ │ ├── handle_getprofile.cpp │ │ │ ├── handle_login.cpp │ │ │ ├── handle_newprofile.cpp │ │ │ ├── handle_newuser.cpp │ │ │ ├── handle_pinvite.cpp │ │ │ ├── handle_registercdkey.cpp │ │ │ ├── handle_registernick.cpp │ │ │ ├── handle_removeblock.cpp │ │ │ ├── handle_revoke.cpp │ │ │ ├── handle_status.cpp │ │ │ ├── handle_updatepro.cpp │ │ │ └── handle_updateui.cpp │ └── tasks │ │ ├── Auth_LoginTicket_GPHash.cpp │ │ ├── Auth_NickEMail_GPHash.cpp │ │ ├── Auth_PreAuth_Token_GPHash.cpp │ │ ├── Auth_Uniquenick_GPHash.cpp │ │ ├── BuddyRequest.cpp │ │ ├── PresenceMessageListener.cpp │ │ ├── SendBuddyMessage.cpp │ │ ├── SendGPBuddyStatus.cpp │ │ ├── SendLoginEvent.cpp │ │ ├── SetPresenceStatus.cpp │ │ ├── ToFromProfileAction.cpp │ │ ├── tasks.cpp │ │ └── tasks.h ├── SharedTasks │ ├── CMakeLists.txt │ └── src │ │ └── OS │ │ ├── Date.cpp │ │ ├── Date.h │ │ ├── GPShared.cpp │ │ ├── GPShared.h │ │ ├── Profile.cpp │ │ ├── Profile.h │ │ ├── SharedTasks │ │ ├── Account │ │ │ ├── AccountTasks.cpp │ │ │ ├── ProfileTasks.h │ │ │ ├── UserRegister.cpp │ │ │ ├── UserTasks.h │ │ │ └── tasks │ │ │ │ ├── BuddyLookup.cpp │ │ │ │ ├── UserSearch.cpp │ │ │ │ └── UserUpdate.cpp │ │ ├── Auth │ │ │ ├── AuthTasks.cpp │ │ │ ├── AuthTasks.h │ │ │ └── tasks │ │ │ │ ├── Auth_DeleteAuthSession.cpp │ │ │ │ ├── Auth_EmailPassword.cpp │ │ │ │ ├── Auth_MakeAuthSession.cpp │ │ │ │ ├── Auth_MakeAuthTicket.cpp │ │ │ │ ├── Auth_NickEmail.cpp │ │ │ │ ├── Auth_TestPreAuth.cpp │ │ │ │ └── Auth_UniqueNick_Password.cpp │ │ ├── CDKey │ │ │ ├── CDKeyTasks.cpp │ │ │ ├── CDKeyTasks.h │ │ │ └── tasks │ │ │ │ ├── CDKey_AssociateToProfile.cpp │ │ │ │ ├── CDKey_GetProfileByCDKey.cpp │ │ │ │ └── CDKey_TestCDKeyValid.cpp │ │ └── Geo │ │ │ ├── GeographyTasks.cpp │ │ │ ├── GeographyTasks.h │ │ │ └── tasks │ │ │ └── GetCountries.cpp │ │ ├── User.cpp │ │ ├── User.h │ │ ├── WebError.h │ │ ├── tasks.cpp │ │ └── tasks.h ├── cdkey │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ └── server │ │ ├── CDKeyDriver.cpp │ │ ├── CDKeyDriver.h │ │ ├── CDKeyServer.cpp │ │ ├── CDKeyServer.h │ │ └── handlers │ │ └── handle_auth.cpp ├── core │ ├── CMakeLists.txt │ ├── OS │ │ ├── Address.cpp │ │ ├── Buffer.cpp │ │ ├── Buffer.h │ │ ├── Config │ │ │ ├── Config.cpp │ │ │ └── Config.h │ │ ├── HTTP.cpp │ │ ├── HTTP.h │ │ ├── KVReader.cpp │ │ ├── KVReader.h │ │ ├── LinkedList.h │ │ ├── Logger.h │ │ ├── Logger │ │ │ ├── Unix │ │ │ │ ├── UnixLogger.cpp │ │ │ │ └── UnixLogger.h │ │ │ └── Win32 │ │ │ │ ├── Win32Logger.cpp │ │ │ │ └── Win32Logger.h │ │ ├── Net │ │ │ ├── NetDriver.cpp │ │ │ ├── NetDriver.h │ │ │ ├── NetPeer.cpp │ │ │ ├── NetPeer.h │ │ │ ├── NetProcessor.h │ │ │ ├── NetServer.cpp │ │ │ ├── NetServer.h │ │ │ ├── Processors │ │ │ │ ├── KVProcessor.cpp │ │ │ │ └── KVProcessor.h │ │ │ └── drivers │ │ │ │ ├── TCPDriver.cpp │ │ │ │ ├── TCPDriver.h │ │ │ │ ├── UDPDriver.cpp │ │ │ │ └── UDPDriver.h │ │ ├── OpenSpy.cpp │ │ ├── OpenSpy.h │ │ ├── Ref.h │ │ ├── gamespy │ │ │ ├── gamespy.cpp │ │ │ ├── gamespy.h │ │ │ ├── gsmsalg.cpp │ │ │ └── gsmsalg.h │ │ └── test │ │ │ ├── TestNetIOInterface.cpp │ │ │ └── TestNetIOInterface.h │ ├── SSL │ │ └── OpenSSL │ │ │ └── SSL │ │ │ ├── Base64.cpp │ │ │ ├── SSLPeer.cpp │ │ │ ├── SSLPeer.h │ │ │ ├── SSLTCPDriver.cpp │ │ │ ├── SSLTCPDriver.h │ │ │ ├── StringCrypter.cpp │ │ │ └── StringCrypter.h │ └── test │ │ ├── CMakeLists.txt │ │ ├── OS │ │ └── test_buffer.cpp │ │ └── common.h ├── gamestats │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ └── server │ │ ├── GSDriver.cpp │ │ ├── GSDriver.h │ │ ├── GSPeer.cpp │ │ ├── GSPeer.h │ │ ├── GSServer.cpp │ │ ├── GSServer.h │ │ ├── commands │ │ ├── handle_auth.cpp │ │ ├── handle_authp.cpp │ │ ├── handle_getpd.cpp │ │ ├── handle_getpid.cpp │ │ ├── handle_newgame.cpp │ │ ├── handle_setpd.cpp │ │ └── handle_updgame.cpp │ │ └── tasks │ │ ├── CDKeyAuth.cpp │ │ ├── GetGameInfo.cpp │ │ ├── GetProfileIDFromCD.cpp │ │ ├── GetUserData.cpp │ │ ├── GetUserKeyedData.cpp │ │ ├── NewGame.cpp │ │ ├── PreAuth.cpp │ │ ├── ProfileIDAuth.cpp │ │ ├── SetUserData.cpp │ │ ├── UpdateGame.cpp │ │ ├── tasks.cpp │ │ └── tasks.h ├── natneg │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ ├── server │ │ ├── NATMapper.cpp │ │ ├── NATMapper.h │ │ ├── NNDriver.cpp │ │ ├── NNDriver.h │ │ ├── NNServer.cpp │ │ ├── NNServer.h │ │ ├── handlers │ │ │ ├── handle_address_check.cpp │ │ │ ├── handle_connect_ack.cpp │ │ │ ├── handle_ert_ack.cpp │ │ │ ├── handle_init.cpp │ │ │ ├── handle_natify_request.cpp │ │ │ ├── handle_preinit.cpp │ │ │ └── handle_report.cpp │ │ └── structs.h │ └── tasks │ │ ├── SendMsgMessage.cpp │ │ ├── SubmitJson.cpp │ │ ├── tasks.cpp │ │ └── tasks.h ├── peerchat │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ ├── match.cpp │ ├── server │ │ ├── Driver.cpp │ │ ├── Driver.h │ │ ├── Peer.cpp │ │ ├── Peer.h │ │ ├── Server.cpp │ │ ├── Server.h │ │ ├── commands │ │ │ ├── handle_cdkey.cpp │ │ │ ├── handle_crypt.cpp │ │ │ ├── handle_delchanprops.cpp │ │ │ ├── handle_delusermode.cpp │ │ │ ├── handle_getchankey.cpp │ │ │ ├── handle_getckey.cpp │ │ │ ├── handle_getkey.cpp │ │ │ ├── handle_join.cpp │ │ │ ├── handle_kick.cpp │ │ │ ├── handle_kill.cpp │ │ │ ├── handle_list.cpp │ │ │ ├── handle_listchanprops.cpp │ │ │ ├── handle_listusermodes.cpp │ │ │ ├── handle_login.cpp │ │ │ ├── handle_lusers.cpp │ │ │ ├── handle_mode.cpp │ │ │ ├── handle_names.cpp │ │ │ ├── handle_nick.cpp │ │ │ ├── handle_oper.cpp │ │ │ ├── handle_part.cpp │ │ │ ├── handle_ping.cpp │ │ │ ├── handle_privmsg.cpp │ │ │ ├── handle_quit.cpp │ │ │ ├── handle_registernick.cpp │ │ │ ├── handle_setchankey.cpp │ │ │ ├── handle_setchanprops.cpp │ │ │ ├── handle_setckey.cpp │ │ │ ├── handle_setgroup.cpp │ │ │ ├── handle_setkey.cpp │ │ │ ├── handle_setusermode.cpp │ │ │ ├── handle_topic.cpp │ │ │ ├── handle_user.cpp │ │ │ ├── handle_userhost.cpp │ │ │ ├── handle_who.cpp │ │ │ └── handle_whois.cpp │ │ ├── gs_peerchat.cpp │ │ ├── gs_peerchat.h │ │ ├── irc_common.cpp │ │ └── irc_common.h │ └── tasks │ │ ├── Channel.cpp │ │ ├── Chanprops.cpp │ │ ├── Perform_CountServerUsers.cpp │ │ ├── Perform_DelChanProps.cpp │ │ ├── Perform_DeleteUser.cpp │ │ ├── Perform_DeleteUsermode.cpp │ │ ├── Perform_GetChannelKeys.cpp │ │ ├── Perform_GetChannelUserKeys.cpp │ │ ├── Perform_GetUserKeys.cpp │ │ ├── Perform_KeepaliveUser.cpp │ │ ├── Perform_ListChanProps.cpp │ │ ├── Perform_ListChannels.cpp │ │ ├── Perform_ListUsermodes.cpp │ │ ├── Perform_LookupChannelDetails.cpp │ │ ├── Perform_LookupGameInfo.cpp │ │ ├── Perform_LookupGlobalUsermode.cpp │ │ ├── Perform_LookupUserDetails.cpp │ │ ├── Perform_OperCheck.cpp │ │ ├── Perform_RemoteKill_ByName.cpp │ │ ├── Perform_SendMessageToTarget.cpp │ │ ├── Perform_SetBroadcastToVisibleUsers.cpp │ │ ├── Perform_SetChanProps.cpp │ │ ├── Perform_SetChannelKeys.cpp │ │ ├── Perform_SetChannelUserKeys.cpp │ │ ├── Perform_SetUserDetails.cpp │ │ ├── Perform_SetUserKeys.cpp │ │ ├── Perform_Setusermode.cpp │ │ ├── Perform_UpdateChannelModes.cpp │ │ ├── Perform_UpdateChannelModes_BanMask.cpp │ │ ├── Perform_UpdateUserModes.cpp │ │ ├── Perform_UserJoinChannel.cpp │ │ ├── Perform_UserJoinEvents.cpp │ │ ├── Perform_UserKickChannel.cpp │ │ ├── Perform_UserPartChannel.cpp │ │ ├── User.cpp │ │ ├── Usermode.cpp │ │ ├── tasks.cpp │ │ └── tasks.h ├── qr │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ ├── server │ │ ├── QRDriver.cpp │ │ ├── QRDriver.h │ │ ├── QRServer.cpp │ │ ├── QRServer.h │ │ ├── V1Handler.cpp │ │ ├── V2Handler.cpp │ │ ├── v1 │ │ │ ├── handle_echo.cpp │ │ │ ├── handle_heartbeat.cpp │ │ │ ├── handle_validate.cpp │ │ │ └── scan.cpp │ │ ├── v2.h │ │ └── v2 │ │ │ ├── handle_available.cpp │ │ │ ├── handle_challenge.cpp │ │ │ ├── handle_client_message_ack.cpp │ │ │ ├── handle_heartbeat.cpp │ │ │ └── handle_keepalive.cpp │ └── tasks │ │ ├── ClientMessageAck.cpp │ │ ├── GetGameInfo.cpp │ │ ├── Handle_QRMessage.cpp │ │ ├── Heartbeat.cpp │ │ ├── Keepalive.cpp │ │ ├── ValidateServer.cpp │ │ ├── shared.cpp │ │ ├── tasks.cpp │ │ └── tasks.h ├── search │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ └── server │ │ ├── SMDriver.cpp │ │ ├── SMDriver.h │ │ ├── SMPeer.cpp │ │ ├── SMPeer.h │ │ ├── SMServer.cpp │ │ ├── SMServer.h │ │ └── commands │ │ ├── handle_check.cpp │ │ ├── handle_newuser.cpp │ │ ├── handle_nicks.cpp │ │ ├── handle_others.cpp │ │ ├── handle_otherslist.cpp │ │ ├── handle_pmatch.cpp │ │ ├── handle_profilelist.cpp │ │ ├── handle_search.cpp │ │ ├── handle_searchunique.cpp │ │ ├── handle_uniquesearch.cpp │ │ └── handle_valid.cpp ├── serverbrowsing │ ├── CMakeLists.txt │ ├── filter │ │ ├── CToken.cpp │ │ ├── CToken.h │ │ ├── filter.cpp │ │ └── filter.h │ ├── main.cpp │ ├── main.h │ ├── server │ │ ├── SBDriver.cpp │ │ ├── SBDriver.h │ │ ├── SBPeer.cpp │ │ ├── SBPeer.h │ │ ├── SBServer.cpp │ │ ├── SBServer.h │ │ ├── V1Peer.cpp │ │ ├── V1Peer.h │ │ ├── V2Peer.cpp │ │ ├── V2Peer.h │ │ ├── enctype1_decoder.cpp │ │ ├── enctype1_encoder.cpp │ │ ├── enctype1_helper.cpp │ │ ├── enctype1_helper.h │ │ ├── enctype_shared.cpp │ │ ├── gutil.cpp │ │ ├── gutil.h │ │ ├── sb_crypt.cpp │ │ └── sb_crypt.h │ ├── tasks │ │ ├── GetGameInfoByGameName.cpp │ │ ├── GetGameInfoPairByGameName.cpp │ │ ├── GetGroups.cpp │ │ ├── GetServerByIP.cpp │ │ ├── GetServerByKey.cpp │ │ ├── GetServers.cpp │ │ ├── HandleServerEventMsg.cpp │ │ ├── SubmitData.cpp │ │ ├── tasks.cpp │ │ └── tasks.h │ └── test │ │ ├── CMakeLists.txt │ │ └── filter │ │ ├── CMakeLists.txt │ │ ├── filter_basic_test.cpp │ │ ├── filter_like_test.cpp │ │ └── filter_subtract_test.cpp ├── test │ ├── CMakeLists.txt │ └── serverbrowsing │ │ ├── CMakeLists.txt │ │ ├── V1 │ │ ├── CMakeLists.txt │ │ ├── common.h │ │ ├── test_common.cpp │ │ └── test_groups.cpp │ │ ├── V2 │ │ ├── CMakeLists.txt │ │ ├── common.h │ │ ├── test_common.cpp │ │ ├── test_groups.cpp │ │ ├── test_main.cpp │ │ └── test_server_message.cpp │ │ └── filter │ │ ├── CMakeLists.txt │ │ └── test_filter.cpp └── utmaster │ ├── CMakeLists.txt │ ├── main.cpp │ ├── main.h │ ├── server │ ├── UTDriver.cpp │ ├── UTDriver.h │ ├── UTPeer.cpp │ ├── UTPeer.h │ ├── UTServer.cpp │ ├── UTServer.h │ └── commands │ │ ├── handle_challenge.cpp │ │ ├── handle_community_data.cpp │ │ ├── handle_heartbeat.cpp │ │ ├── handle_motd.cpp │ │ ├── handle_packages_version.cpp │ │ ├── handle_serverlist.cpp │ │ ├── handle_stats_update.cpp │ │ └── handle_uplink_info.cpp │ └── tasks │ ├── PerformDeleteServer.cpp │ ├── PerformHeartbeat.cpp │ ├── PerformInternalLoadGameData.cpp │ ├── PerformListServers.cpp │ ├── tasks.cpp │ └── tasks.h ├── docker-compose.yaml ├── docker-support ├── fesl_tos.txt ├── motd-community.txt ├── motd.txt ├── password_key.pem ├── rsa_priv.pem ├── run.sh ├── utmaster.xml └── x509.pem ├── vcpkg-configuration.json └── vcpkg.json /.env-local: -------------------------------------------------------------------------------- 1 | OPENSPY_REDIS_ADDRESS=redis 2 | OPENSPY_REDIS_PORT=6379 3 | OPENSPY_REDIS_SSL=0 4 | OPENSPY_REDIS_SSL_NO_VERIFY=1 5 | OPENSPY_AMQP_ADDRESS=rabbit 6 | OPENSPY_AMQP_PORT=5672 7 | OPENSPY_AMQP_USER=rabbitmq 8 | OPENSPY_AMQP_PASSWORD=rabbitmq 9 | OPENSPY_WEBSERVICES_URL=http://core-web:8080 10 | OPENSPY_API_KEY=ELGAoKHyFPfsWhmWF5F/8uNz2YcdTrojCZbRfvlFwBKJIhDUdvMwM4bmljSsEBq57riyXRij8FoqmxWR8C2BQIEaGG68uFJKcQmJlLY2ntAFOYUloccRCr/eBW8sJZsTIGaIdVdsDeDOrRJR487tfFGNHW2Ezp+oVrZVsd3C9e0VobSE1fXdSFz3R5MIqH3bLprfcDLJL/U8gtvUBegOQI22Vviha24W0/76SQSo72Z7i6GrpU/OnrsjcHQSwyC6VeCTv5JjCP/BSsaCK0Zxw3OlzQsPAprQug9Pwm5MrH/pkkxhqLKcCxjsU25Zj+ipkKOzsO+rmqaIMsK6ILke6w== 11 | OPENSPY_NATNEG_BIND_ADDR=0.0.0.0 12 | OPENSPY_NATNEG_BIND_PORT=30695 13 | OPENSPY_QR_BIND_ADDR=0.0.0.0 14 | OPENSPY_QR_BIND_PORT=30694 15 | OPENSPY_SBV1_BIND_ADDR=0.0.0.0 16 | OPENSPY_SBV1_BIND_PORT=30692 17 | OPENSPY_SBV2_BIND_ADDR=0.0.0.0 18 | OPENSPY_SBV2_BIND_PORT=30693 19 | OPENSPY_GP_BIND_ADDR=0.0.0.0 20 | OPENSPY_GP_BIND_PORT=30974 21 | OPENSPY_GSTATS_BIND_ADDR=0.0.0.0 22 | OPENSPY_GSTATS_BIND_PORT=30836 23 | OPENSPY_SM_BIND_ADDR=0.0.0.0 24 | OPENSPY_SM_BIND_PORT=30734 25 | OPENSPY_CDKEY_BIND_ADDR=0.0.0.0 26 | OPENSPY_CDKEY_BIND_PORT=30694 27 | OPENSPY_PEERCHAT_BIND_ADDR=0.0.0.0 28 | OPENSPY_PEERCHAT_BIND_PORT=30838 29 | OPENSPY_UTMASTER_BIND_ADDR=0.0.0.0 30 | OPENSPY_UTMASTER_BIND_PORT=30839 31 | OPENSPY_UTMASTER_MAPPINGS_PATH=utmaster.xml 32 | UTMASTER_MOTD_DATA=VGhpcyBpcyB0aGUgdXRtYXN0ZXIgZGVmYXVsdCBkb2NrZXIgbW90ZA== 33 | UTMASTER_MOTD_COMMUNITY_DATA=VGhpcyBpcyB0aGUgdXRtYXN0ZXIgZGVmYXVsdCBkb2NrZXIgY29tbXVuaXR5IG1vdGQ= 34 | OPENSPY_FESL_TOS_PATH=fesl_tos.txt 35 | OPENSPY_SSL_CERT=ssl_cert.pem -------------------------------------------------------------------------------- /.github/workflows/build-and-push.yml: -------------------------------------------------------------------------------- 1 | name: build-and-push 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'master' 7 | 8 | jobs: 9 | build-and-push: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - 13 | name: Login to Docker Hub 14 | uses: docker/login-action@v3 15 | with: 16 | username: ${{ vars.DOCKERHUB_USERNAME }} 17 | password: ${{ secrets.DOCKERHUB_TOKEN }} 18 | - 19 | name: Set up QEMU 20 | uses: docker/setup-qemu-action@v3 21 | - 22 | name: Set up Docker Buildx 23 | uses: docker/setup-buildx-action@v3 24 | - 25 | name: Build and push 26 | uses: docker/build-push-action@v6 27 | with: 28 | push: true 29 | tags: chcniz/openspy-core:latest -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /cmake/modules/FindSSL.cmake: -------------------------------------------------------------------------------- 1 | find_package(OpenSSL) 2 | 3 | IF(OPENSSL_FOUND) 4 | SET(SSL_LIBS "${OPENSSL_LIBRARIES}") 5 | SET(SSL_OS_INC "${CMAKE_CURRENT_SOURCE_DIR}/../core/SSL/OpenSSL") 6 | SET(SSL_INCS "${OPENSSL_INCLUDE_DIR}") 7 | file (GLOB SSL_SRCS "SSL/OpenSSL/SSL/*.cpp") 8 | 9 | ELSE() 10 | message( FATAL_ERROR "OpenSSL not found!" ) 11 | ENDIF() 12 | 13 | # message(SSL_SRCS="${SSL_SRCS}") 14 | # message(SSL_LIBS="${SSL_LIBS}") 15 | # message(SSL_INCS="${SSL_INCS}") 16 | -------------------------------------------------------------------------------- /cmake/modules/Findhiredis.cmake: -------------------------------------------------------------------------------- 1 | find_path(HIREDIS_INCLUDE_DIR NAMES hiredis/hiredis.h PATHS ${HIREDIS_ROOT_DIR} ${HIREDIS_ROOT_DIR}/include) 2 | 3 | find_library(HIREDIS_LIBRARIES NAMES hiredis hiredisd PATHS ${HIREDIS_ROOT_DIR} ${HIREDIS_ROOT_DIR}/lib) 4 | 5 | if (HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARIES) 6 | if (NOT TARGET hiredis::hiredis) 7 | add_library(hiredis::hiredis UNKNOWN IMPORTED) 8 | set_target_properties(hiredis::hiredis PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${HIREDIS_INCLUDE_DIR} IMPORTED_LOCATION ${HIREDIS_LIBRARIES}) 9 | endif () 10 | endif () 11 | 12 | include(FindPackageHandleStandardArgs) 13 | find_package_handle_standard_args(hiredis REQUIRED_VARS HIREDIS_INCLUDE_DIR HIREDIS_LIBRARIES) 14 | 15 | if(HIREDIS_FOUND) 16 | message(STATUS "Found hiredis - (include: ${HIREDIS_INCLUDE_DIR}, library: ${HIREDIS_LIBRARIES})") 17 | mark_as_advanced(HIREDIS_INCLUDE_DIR HIREDIS_LIBRARIES) 18 | endif() 19 | -------------------------------------------------------------------------------- /cmake/modules/Findhiredis_ssl.cmake: -------------------------------------------------------------------------------- 1 | find_path(HIREDIS_SSL_INCLUDE_DIR NAMES hiredis/hiredis_ssl.h PATHS ${HIREDIS_SSL_ROOT_DIR} ${HIREDIS_SSL_ROOT_DIR}/include) 2 | 3 | find_library(HIREDIS_SSL_LIBRARIES NAMES hiredis_ssl hiredis_ssld PATHS ${HIREDIS_SSL_ROOT_DIR} ${HIREDIS_SSL_ROOT_DIR}/lib) 4 | 5 | if (HIREDIS_SSL_INCLUDE_DIR AND HIREDIS_SSL_LIBRARIES) 6 | if (NOT TARGET hiredis::hiredis_ssl) 7 | add_library(hiredis::hiredis_ssl UNKNOWN IMPORTED) 8 | set_target_properties(hiredis::hiredis_ssl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${HIREDIS_SSL_INCLUDE_DIR} IMPORTED_LOCATION ${HIREDIS_SSL_LIBRARIES}) 9 | endif () 10 | endif () 11 | 12 | include(FindPackageHandleStandardArgs) 13 | find_package_handle_standard_args(hiredis_ssl REQUIRED_VARS HIREDIS_SSL_INCLUDE_DIR HIREDIS_SSL_LIBRARIES) 14 | 15 | if(HIREDIS_SSL_FOUND) 16 | message(STATUS "Found hiredis_ssl - (include: ${HIREDIS_SSL_INCLUDE_DIR}, library: ${HIREDIS_SSL_LIBRARIES})") 17 | mark_as_advanced(HIREDIS_SSL_INCLUDE_DIR HIREDIS_SSL_LIBRARIES) 18 | endif() 19 | -------------------------------------------------------------------------------- /cmake/modules/Findjansson.cmake: -------------------------------------------------------------------------------- 1 | find_path(JANSSON_INCLUDE_DIR NAMES jansson.h PATHS ${JANSSON_ROOT_DIR}/include) 2 | 3 | find_library(JANSSON_LIBRARIES NAMES jansson PATHS ${JANSSON_ROOT_DIR}/lib) 4 | 5 | if (JANSSON_INCLUDE_DIR AND JANSSON_LIBRARIES) 6 | if (NOT TARGET jansson::jansson) 7 | add_library(jansson::jansson UNKNOWN IMPORTED) 8 | set_target_properties(jansson::jansson PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${JANSSON_INCLUDE_DIR} IMPORTED_LOCATION ${JANSSON_LIBRARIES}) 9 | endif () 10 | endif () 11 | 12 | include(FindPackageHandleStandardArgs) 13 | find_package_handle_standard_args(jansson REQUIRED_VARS JANSSON_INCLUDE_DIR JANSSON_LIBRARIES) 14 | 15 | if(JANSSON_FOUND) 16 | message(STATUS "Found jansson - (include: ${JANSSON_INCLUDE_DIR}, library: ${JANSSON_LIBRARIES})") 17 | mark_as_advanced(JANSSON_INCLUDE_DIR JANSSON_LIBRARIES) 18 | endif() 19 | -------------------------------------------------------------------------------- /cmake/modules/Findlibuv.cmake: -------------------------------------------------------------------------------- 1 | find_path(LIBUV_INCLUDE_DIR uv.h PATHS ${LIBUV_DIR} ${LIBUV_DIR}/include) 2 | 3 | find_library(LIBUV_LIBRARIES NAMES uv libuv PATHS ${LIBUV_DIR} ${LIBUV_DIR}/lib) 4 | 5 | if (LIBUV_INCLUDE_DIR AND LIBUV_LIBRARIES) 6 | if (NOT TARGET libuv::uv) 7 | add_library(libuv::uv UNKNOWN IMPORTED) 8 | set_target_properties(libuv::uv PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${LIBUV_INCLUDE_DIR} IMPORTED_LOCATION ${LIBUV_LIBRARIES}) 9 | endif () 10 | endif () 11 | 12 | include(FindPackageHandleStandardArgs) 13 | find_package_handle_standard_args(libuv REQUIRED_VARS LIBUV_LIBRARIES LIBUV_INCLUDE_DIR) 14 | 15 | if(LIBUV_FOUND) 16 | message(STATUS "Found libuv - (include: ${LIBUV_INCLUDE_DIR}, library: ${LIBUV_LIBRARIES})") 17 | mark_as_advanced(LIBUV_INCLUDE_DIR LIBUV_LIBRARIES) 18 | endif() 19 | -------------------------------------------------------------------------------- /code/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | #Where to find local cmake scripts 4 | set(OS_CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/../cmake/modules) 5 | message(OS_CMAKE_MODULE_PATH="${OS_CMAKE_MODULE_PATH}") 6 | set(CMAKE_MODULE_PATH ${OS_CMAKE_MODULE_PATH}) 7 | 8 | 9 | find_package(ZLIB REQUIRED) 10 | 11 | project(openspy) 12 | enable_testing() 13 | 14 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 15 | 16 | find_package(libuv REQUIRED) 17 | 18 | include_directories("core") 19 | 20 | 21 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/") 22 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/") 23 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/") 24 | 25 | 26 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/core/SSL/SSLNull ${CURL_INCLUDE_DIR}) 27 | 28 | if(UNIX) 29 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=gnu++0x -fpermissive") 30 | endif() 31 | 32 | add_subdirectory(core) 33 | add_subdirectory(SharedTasks) 34 | add_subdirectory(utmaster) 35 | add_subdirectory(serverbrowsing) 36 | add_subdirectory(qr) 37 | add_subdirectory(natneg) 38 | add_subdirectory(GP) 39 | add_subdirectory(gamestats) 40 | add_subdirectory(search) 41 | add_subdirectory(FESL) 42 | add_subdirectory(peerchat) 43 | add_subdirectory(cdkey) -------------------------------------------------------------------------------- /code/FESL/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/FESL/server/FESLDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPDRIVER_H 2 | #define _GPDRIVER_H 3 | #include 4 | #include "../main.h" 5 | #include 6 | #include 7 | #include "FESLPeer.h" 8 | 9 | #include 10 | #include 11 | #ifdef _WIN32 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | #define DRIVER_THREAD_TIME 1000 18 | 19 | namespace FESL { 20 | 21 | 22 | typedef struct { 23 | std::string domainPartition; 24 | std::string subDomain; 25 | std::string messagingHostname; 26 | uint16_t messagingPort; 27 | std::string theaterHostname; 28 | uint16_t theaterPort; 29 | std::string termsOfServiceData; 30 | int gameid; //OpenSpy gameid 31 | } PublicInfo; 32 | 33 | 34 | class Peer; 35 | 36 | class Driver : public OS::SSLTCPDriver { 37 | public: 38 | Driver(INetServer *server, const char *host, uint16_t port, PublicInfo public_info, std::string str_crypter_rsa_key, void *ssl_ctx); 39 | ~Driver(); 40 | 41 | PublicInfo GetServerInfo() { return m_server_info; }; 42 | 43 | OS::StringCrypter *getStringCrypter() const { return mp_string_crypter; }; 44 | 45 | void OnUserAuth(std::string session_key, int userid, int profileid); 46 | 47 | INetPeer *CreatePeer(uv_tcp_t *sd); 48 | private: 49 | PublicInfo m_server_info; 50 | 51 | OS::StringCrypter *mp_string_crypter; 52 | }; 53 | } 54 | #endif //_SBDRIVER_H -------------------------------------------------------------------------------- /code/FESL/server/FESLServer.cpp: -------------------------------------------------------------------------------- 1 | #include "FESLServer.h" 2 | #include "FESLDriver.h" 3 | #include "FESLPeer.h" 4 | 5 | namespace FESL { 6 | Server::Server() : INetServer() { 7 | } 8 | Server::~Server() { 9 | } 10 | void Server::init() { 11 | TaskShared::GeoRequest request; 12 | request.type = TaskShared::EGeoTaskType_GetCountries; 13 | request.extra = this; 14 | request.peer = NULL; 15 | request.callback = GetCountriesCallback; 16 | AddGeoTaskRequest(request); 17 | } 18 | void Server::GetCountriesCallback(TaskShared::GeoTaskData auth_data, void *extra, INetPeer *peer) { 19 | if (auth_data.error_details.response_code == TaskShared::WebErrorCode_Success) { 20 | Server *server = (Server *)extra; 21 | server->m_countries = auth_data.countries; 22 | } 23 | } 24 | void Server::tick() { 25 | std::vector::iterator it = m_net_drivers.begin(); 26 | while (it != m_net_drivers.end()) { 27 | INetDriver *driver = *it; 28 | driver->think(); 29 | it++; 30 | } 31 | NetworkTick(); 32 | } 33 | void Server::OnUserAuth(std::string session_key, int userid, int profileid) { 34 | std::vector::iterator it = m_net_drivers.begin(); 35 | while (it != m_net_drivers.end()) { 36 | FESL::Driver *driver = (FESL::Driver *) *it; 37 | driver->OnUserAuth(session_key, userid, profileid); 38 | it++; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /code/FESL/server/FESLServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _SMSERVER_H 2 | #define _SMSERVER_H 3 | #include 4 | #include 5 | #include 6 | 7 | namespace FESL { 8 | class FESLRequest; 9 | class Server : public INetServer { 10 | public: 11 | Server(); 12 | virtual ~Server(); 13 | void init(); 14 | void tick(); 15 | void OnUserAuth(std::string session_key, int userid, int profileid); 16 | std::vector GetCountries() { 17 | return m_countries; 18 | } 19 | private: 20 | std::vector m_countries; 21 | static void GetCountriesCallback(TaskShared::GeoTaskData auth_data, void *extra, INetPeer *peer); 22 | }; 23 | } 24 | #endif //_SMSERVER_H -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_gamespy_preauth.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | void Peer::m_create_auth_ticket(bool success, OS::User user, OS::Profile profile, TaskShared::AuthData auth_data, void *extra, INetPeer *peer) { 11 | std::ostringstream s; 12 | int tid = (int)(ptrdiff_t)extra; 13 | if (success) { 14 | s << "TXN=GameSpyPreAuth\n"; 15 | if(tid != -1) { 16 | s << "TID=" << tid << "\n"; 17 | } 18 | if(auth_data.response_proof.length()) 19 | s << "challenge=" << OS::url_encode(auth_data.response_proof) << "\n"; 20 | s << "ticket=" << OS::url_encode(auth_data.session_key) << "\n"; 21 | ((Peer *)peer)->SendPacket(FESL_TYPE_ACCOUNT, s.str()); 22 | } 23 | else { 24 | ((Peer *)peer)->SendError(FESL_TYPE_ACCOUNT, FESL_ERROR_AUTH_FAILURE, "GameSpyPreAuth", tid); 25 | } 26 | } 27 | bool Peer::m_acct_gamespy_preauth(OS::KVReader kv_list) { 28 | TaskShared::AuthRequest request; 29 | request.type = TaskShared::EAuthType_MakeAuthTicket; 30 | request.callback = m_create_auth_ticket; 31 | request.peer = this; 32 | int tid = -1; 33 | if(kv_list.HasKey("TID")) { 34 | tid = kv_list.GetValueInt("TID"); 35 | } 36 | request.extra = (void *)(ptrdiff_t)tid; 37 | IncRef(); 38 | if(m_profile.id != 0) { 39 | request.profile = m_profile; 40 | } else { 41 | request.profile = m_account_profile; 42 | } 43 | 44 | AddAuthTaskRequest(request); 45 | return true; 46 | } 47 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_get_entitlement_by_bundle.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_subs_get_entitlement_by_bundle(OS::KVReader kv_list) { 11 | std::ostringstream s; 12 | s << "TXN=GetEntitlementByBundle\n"; 13 | 14 | if(kv_list.HasKey("TID")) { 15 | s << "TID=" << kv_list.GetValueInt("TID") << "\n"; 16 | } 17 | s << "EntitlementByBundle.[]=0\n"; 18 | SendPacket(FESL_TYPE_SUBS, s.str()); 19 | return true; 20 | } 21 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_get_subaccounts.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | void Peer::send_subaccounts() { 11 | std::ostringstream s; 12 | uv_mutex_lock(&m_mutex); 13 | std::vector::iterator it = m_profiles.begin(); 14 | int i = 0; 15 | s << "TXN=GetSubAccounts\n"; 16 | if(m_last_profile_lookup_tid != -1) { 17 | s << "TID=" << m_last_profile_lookup_tid << "\n"; 18 | } 19 | s << "subAccounts.[]=" << m_profiles.size() << "\n"; 20 | while (it != m_profiles.end()) { 21 | OS::Profile profile = *it; 22 | s << "subAccounts." << i++ << "=\"" << profile.uniquenick << "\"\n"; 23 | it++; 24 | } 25 | 26 | uv_mutex_unlock(&m_mutex); 27 | SendPacket(FESL_TYPE_ACCOUNT, s.str()); 28 | } 29 | bool Peer::m_acct_get_sub_accounts(OS::KVReader kv_list) { 30 | if (!m_got_profiles) { 31 | m_pending_subaccounts = true; 32 | } 33 | else { 34 | int tid = -1; 35 | if(kv_list.HasKey("TID")) { 36 | tid = kv_list.GetValueInt("TID"); 37 | } 38 | m_last_profile_lookup_tid = tid; 39 | send_subaccounts(); 40 | } 41 | return true; 42 | } 43 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_get_telemetry_token.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_acct_get_telemetry_token(OS::KVReader kv_list) { 11 | std::ostringstream s; 12 | s << "TXN=GetTelemetryToken\n"; 13 | if(kv_list.HasKey("TID")) { 14 | s << "TID=" << kv_list.GetValueInt("TID") << "\n"; 15 | } 16 | s << "telemetryToken=\"teleToken\"\n"; 17 | s << "enabled=0\n"; 18 | s << "disabled=1\n"; 19 | SendPacket(FESL_TYPE_ACCOUNT, s.str()); 20 | return true; 21 | } 22 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_get_tos.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_acct_gettos_handler(OS::KVReader kv_list) { 11 | std::ostringstream s; 12 | s << "TXN=GetTos\n"; 13 | if(kv_list.HasKey("TID")) { 14 | s << "TID=" << kv_list.GetValueInt("TID") << "\n"; 15 | } 16 | s << "tos=\"" << ((FESL::Driver *)GetDriver())->GetServerInfo().termsOfServiceData << "\"\n"; 17 | 18 | SendPacket(FESL_TYPE_FSYS, s.str()); 19 | return true; 20 | } 21 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_goodbye.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_fsys_goodbye_handler(OS::KVReader kv_list) { 11 | Delete(); 12 | return true; 13 | } 14 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_fsys_hello_handler(OS::KVReader kv_list) { 11 | std::ostringstream ss; 12 | 13 | char timeBuff[128]; 14 | struct tm *newtime; 15 | time_t long_time; 16 | time(&long_time); 17 | newtime = gmtime(&long_time); 18 | 19 | strftime(timeBuff, sizeof(timeBuff), FESL_DATE_FORMAT, newtime); 20 | 21 | PublicInfo public_info = ((FESL::Driver *)mp_driver)->GetServerInfo(); 22 | ss << "TXN=Hello\n"; 23 | if(kv_list.HasKey("TID")) { 24 | ss << "TID=" << kv_list.GetValueInt("TID") << "\n"; 25 | } 26 | ss << "domainPartition.domain=" << public_info.domainPartition << "\n"; 27 | ss << "messengerIp=" << public_info.messagingHostname << "\n"; 28 | ss << "messengerPort=" << public_info.messagingPort << "\n"; 29 | ss << "domationPartition.subDomain=" << public_info.subDomain << "\n"; 30 | ss << "activityTimeoutSecs=" << FESL_PING_TIME * 2 << "\n"; 31 | ss << "curTime=\"" << OS::url_encode(timeBuff) << "\"\n"; 32 | ss << "theaterIp=" << public_info.theaterHostname << "\n"; 33 | ss << "theaterPort=" << public_info.theaterPort << "\n"; 34 | SendPacket(FESL_TYPE_FSYS, ss.str()); 35 | 36 | send_memcheck(0); 37 | return true; 38 | } 39 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_login_sub_account.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | void Peer::loginToSubAccount(std::string uniquenick, int tid) { 11 | std::ostringstream s; 12 | uv_mutex_lock(&m_mutex); 13 | bool loggedIn = false; 14 | std::vector::iterator it = m_profiles.begin(); 15 | while (it != m_profiles.end()) { 16 | OS::Profile profile = *it; 17 | if (profile.uniquenick.compare(uniquenick) == 0) { 18 | m_profile = profile; 19 | s << "TXN=LoginSubAccount\n"; 20 | if(tid != -1) { 21 | s << "TID=" << tid << "\n"; 22 | } 23 | s << "lkey=" << m_session_key << "\n"; 24 | s << "profileId=" << m_profile.id << "\n"; 25 | s << "userId=" << m_user.id << "\n"; 26 | SendPacket(FESL_TYPE_ACCOUNT, s.str()); 27 | loggedIn = true; 28 | break; 29 | } 30 | it++; 31 | } 32 | if (!loggedIn) { 33 | SendError(FESL_TYPE_ACCOUNT, FESL_ERROR_ACCOUNT_NOT_FOUND, "LoginSubAccount", tid); 34 | } 35 | uv_mutex_unlock(&m_mutex); 36 | } 37 | bool Peer::m_acct_login_sub_account(OS::KVReader kv_list) { 38 | int tid = -1; 39 | if(kv_list.HasKey("TID")) { 40 | tid = kv_list.GetValueInt("TID"); 41 | } 42 | loginToSubAccount(kv_list.GetValue("name"), tid); 43 | return true; 44 | } 45 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_memcheck.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_fsys_memcheck_handler(OS::KVReader kv_list) { 11 | //send_memcheck(0); 12 | return true; 13 | } 14 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_ping.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | void Peer::send_ping() { 11 | //check for timeout 12 | uv_timespec64_t current_time; 13 | uv_clock_gettime(UV_CLOCK_MONOTONIC, ¤t_time); 14 | if(current_time.tv_sec - m_last_ping.tv_sec > FESL_PING_TIME) { 15 | uv_clock_gettime(UV_CLOCK_MONOTONIC, &m_last_ping); 16 | std::ostringstream s; 17 | s << "TXN=Ping\n"; 18 | s << "TID=" << current_time.tv_sec << "\n"; 19 | SendPacket(FESL_TYPE_FSYS, s.str(), 1); 20 | } 21 | } 22 | bool Peer::m_fsys_ping_handler(OS::KVReader kv_list) { 23 | return true; 24 | } 25 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_register_game.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_acct_register_game_handler(OS::KVReader kv_list) { 11 | std::ostringstream s; 12 | s << "TXN=RegisterGame\n"; 13 | if(kv_list.HasKey("TID")) { 14 | s << "TID=" << kv_list.GetValueInt("TID") << "\n"; 15 | } 16 | SendPacket(FESL_TYPE_ACCOUNT, s.str()); 17 | return true; 18 | } 19 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_send_accountname.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_acct_send_account_name(OS::KVReader kv_list) { 11 | return true; 12 | } 13 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/basic/handle_send_password.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_acct_send_account_password(OS::KVReader kv_list) { 11 | return true; 12 | } 13 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/nu/handle_add_persona.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | bool Peer::m_acct_add_persona(OS::KVReader kv_list) { 11 | TaskShared::ProfileRequest request; 12 | std::string nick, oldnick; 13 | nick = kv_list.GetValue("name"); 14 | 15 | request.user_search_details.id = m_user.id; 16 | //request.profile_search_details.id = m_profile.id; 17 | request.profile_search_details.namespaceid = FESL_PROFILE_NAMESPACEID; 18 | request.profile_search_details.nick = nick; 19 | request.profile_search_details.uniquenick = nick; 20 | int tid = -1; 21 | if(kv_list.HasKey("TID")) { 22 | tid = kv_list.GetValueInt("TID"); 23 | } 24 | request.extra = (void *)(ptrdiff_t)tid; 25 | request.peer = this; 26 | request.peer->IncRef(); 27 | request.type = TaskShared::EProfileSearch_CreateProfile; 28 | request.callback = Peer::m_create_profile_callback; 29 | 30 | AddProfileTaskRequest(request); 31 | 32 | return true; 33 | } 34 | void Peer::m_create_nu_profile_callback(TaskShared::WebErrorDetails error_details, std::vector results, std::map result_users, void *extra, INetPeer *peer) { 35 | if (error_details.response_code == TaskShared::WebErrorCode_Success && results.size() > 0) { 36 | uv_mutex_lock(&((Peer *)peer)->m_mutex); 37 | ((Peer *)peer)->m_profiles.push_back(results.front()); 38 | uv_mutex_unlock(&((Peer *)peer)->m_mutex); 39 | ((Peer *)peer)->SendError(FESL_TYPE_ACCOUNT, FESL_ERROR_NO_ERROR, "NuAddPersona", (int)(ptrdiff_t)extra); 40 | } else { 41 | ((Peer *)peer)->handle_web_error(error_details, FESL_TYPE_ACCOUNT, "NuAddPersona", (int)(ptrdiff_t)extra); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/nu/handle_get_personas.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | void Peer::send_personas() { 11 | std::ostringstream s; 12 | uv_mutex_lock(&m_mutex); 13 | std::vector::iterator it = m_profiles.begin(); 14 | s << "TXN=NuGetPersonas\n"; 15 | if(m_last_profile_lookup_tid != -1) 16 | s << "TID=" << m_last_profile_lookup_tid << "\n"; 17 | s << "personas.[]=" << m_profiles.size() << "\n"; 18 | int i = 0; 19 | while (it != m_profiles.end()) { 20 | OS::Profile profile = *it; 21 | s << "personas." << i++ << "=\"" << profile.uniquenick << "\"\n"; 22 | it++; 23 | } 24 | uv_mutex_unlock(&m_mutex); 25 | SendPacket(FESL_TYPE_ACCOUNT, s.str()); 26 | } 27 | bool Peer::m_acct_get_personas(OS::KVReader kv_list) { 28 | int tid = -1; 29 | if(kv_list.HasKey("TID")) { 30 | tid = kv_list.GetValueInt("TID"); 31 | } 32 | m_last_profile_lookup_tid = tid; 33 | if (!m_got_profiles) { 34 | m_pending_nuget_personas= true; 35 | } 36 | else { 37 | send_personas(); 38 | } 39 | return true; 40 | } 41 | } -------------------------------------------------------------------------------- /code/FESL/server/commands/nu/handle_login_persona.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | namespace FESL { 10 | void Peer::loginToPersona(std::string uniquenick, int tid) { 11 | std::ostringstream s; 12 | uv_mutex_lock(&m_mutex); 13 | std::vector::iterator it = m_profiles.begin(); 14 | while (it != m_profiles.end()) { 15 | OS::Profile profile = *it; 16 | if (profile.uniquenick.compare(uniquenick) == 0) { 17 | m_profile = profile; 18 | s << "TXN=NuLoginPersona\n"; 19 | if(tid != -1) { 20 | s << "TID=" << tid << "\n"; 21 | } 22 | s << "lkey=" << m_session_key << "\n"; 23 | s << "profileId=" << m_profile.id << "\n"; 24 | s << "userId=" << m_user.id << "\n"; 25 | SendPacket(FESL_TYPE_ACCOUNT, s.str()); 26 | break; 27 | } 28 | it++; 29 | } 30 | uv_mutex_unlock(&m_mutex); 31 | } 32 | bool Peer::m_acct_login_persona(OS::KVReader kv_list) { 33 | std::ostringstream s; 34 | int tid = -1; 35 | if(kv_list.HasKey("TID")) { 36 | tid = kv_list.GetValueInt("TID"); 37 | } 38 | loginToPersona(kv_list.GetValue("name"), tid); 39 | return true; 40 | } 41 | } -------------------------------------------------------------------------------- /code/GP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(GP) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | file (GLOB MAIN_SRCS "*.cpp") 8 | file (GLOB MAIN_HDRS "*.h") 9 | file (GLOB SERVER_SRCS "server/*.cpp") 10 | file (GLOB SERVER_HDRS "server/*.h") 11 | file (GLOB SERVER_TASKS_SRCS "tasks/*.cpp") 12 | file (GLOB SERVER_TASKS_HDRS "tasks/*.h") 13 | file (GLOB SERVER_CMDS_SRCS "server/commands/*.cpp") 14 | file (GLOB SERVER_CMDS_HDRS "server/commands/*.h") 15 | 16 | 17 | set (ALL_SRCS ${MAIN_SRCS} ${MAIN_HDRS} ${SERVER_SRCS} ${SERVER_HDRS} ${SERVER_CMDS_SRCS} ${SERVER_CMDS_HDRS} ${SERVER_TASKS_SRCS} ${SERVER_TASKS_HDRS}) 18 | 19 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 20 | 21 | source_group("Sources" FILES ${MAIN_SRCS}) 22 | source_group("Sources\\Server" FILES ${SERVER_SRCS}) 23 | source_group("Sources\\Server\\Tasks" FILES ${SERVER_TASKS_SRCS}) 24 | source_group("Sources\\Server\\Commands" FILES ${SERVER_CMDS_SRCS}) 25 | 26 | source_group("Headers" FILES ${MAIN_HDRS}) 27 | source_group("Headers\\Server" FILES ${SERVER_HDRS}) 28 | source_group("Headers\\Server\\Tasks" FILES ${SERVER_TASKS_HDRS}) 29 | source_group("Headers\\Server\\Commands" FILES ${SERVER_CMDS_HDRS}) 30 | 31 | 32 | add_executable (GP ${ALL_SRCS}) 33 | 34 | IF(WIN32) 35 | target_link_libraries(GP openspy.lib SharedTasks ZLIB::ZLIB) 36 | ELSE() #unix 37 | target_link_libraries(GP openspy SharedTasks ZLIB::ZLIB) 38 | ENDIF() -------------------------------------------------------------------------------- /code/GP/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "server/GPServer.h" 7 | #include "server/GPDriver.h" 8 | #include "tasks/tasks.h" 9 | INetServer *g_gameserver = NULL; 10 | 11 | void tick_handler(uv_timer_t* handle) { 12 | g_gameserver->tick(); 13 | } 14 | 15 | int main() { 16 | uv_loop_t *loop = uv_default_loop(); 17 | uv_timer_t tick_timer; 18 | 19 | uv_timer_init(uv_default_loop(), &tick_timer); 20 | 21 | OS::Init("GP"); 22 | 23 | g_gameserver = new GP::Server(); 24 | 25 | 26 | char address_buff[256]; 27 | char port_buff[16]; 28 | size_t temp_env_sz = sizeof(address_buff); 29 | 30 | if(uv_os_getenv("OPENSPY_GP_BIND_ADDR", (char *)&address_buff, &temp_env_sz) != UV_ENOENT) { 31 | temp_env_sz = sizeof(port_buff); 32 | 33 | uint16_t port = 29900; 34 | if(uv_os_getenv("OPENSPY_GP_BIND_PORT", (char *)&port_buff, &temp_env_sz) != UV_ENOENT) { 35 | port = atoi(port_buff); 36 | } 37 | 38 | GP::Driver *driver = new GP::Driver(g_gameserver, address_buff, port); 39 | 40 | OS::LogText(OS::ELogLevel_Info, "Adding GP Driver: %s:%d\n", address_buff, port); 41 | g_gameserver->addNetworkDriver(driver); 42 | } else { 43 | OS::LogText(OS::ELogLevel_Warning, "Missing GP bind address environment variable"); 44 | } 45 | 46 | GP::InitTasks(); 47 | uv_timer_start(&tick_timer, tick_handler, 0, 250); 48 | 49 | uv_run(loop, UV_RUN_DEFAULT); 50 | 51 | uv_loop_close(loop); 52 | 53 | delete g_gameserver; 54 | 55 | OS::Shutdown(); 56 | return 0; 57 | } -------------------------------------------------------------------------------- /code/GP/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/GP/server/GPDriver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "GPDriver.h" 5 | #include "GPServer.h" 6 | #include "GPPeer.h" 7 | #include 8 | 9 | namespace GP { 10 | Driver::Driver(INetServer *server, const char *host, uint16_t port) : TCPDriver(server, host, port) { 11 | } 12 | 13 | Peer *Driver::FindPeerByProfileID(int profileid) { 14 | Peer* peer = (Peer*)GetPeerList()->GetHead(); 15 | if (peer != NULL) { 16 | do { 17 | if (peer->GetProfileID() == profileid) { 18 | return peer; 19 | } 20 | } while ((peer = (Peer*)peer->GetNext()) != NULL); 21 | } 22 | return NULL; 23 | } 24 | void Driver::InformStatusUpdate(int from_profileid, GPShared::GPStatus status) { 25 | Peer* peer = (Peer*)GetPeerList()->GetHead(); 26 | if (peer != NULL) { 27 | do { 28 | peer->inform_status_update(from_profileid, status); 29 | } while ((peer = (Peer*)peer->GetNext()) != NULL); 30 | } 31 | } 32 | INetPeer *Driver::CreatePeer(uv_tcp_t *socket) { 33 | return new Peer(this, socket); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /code/GP/server/GPDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPDRIVER_H 2 | #define _GPDRIVER_H 3 | #include 4 | #include "../main.h" 5 | #include 6 | 7 | #include "GPPeer.h" 8 | 9 | #include 10 | #include 11 | #ifdef _WIN32 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | #include 18 | 19 | #define GP_PING_TIME (60) 20 | 21 | namespace GP { 22 | class Peer; 23 | class Driver; 24 | class Driver : public OS::TCPDriver { 25 | public: 26 | Driver(INetServer *server, const char *host, uint16_t port); 27 | Peer *FindPeerByProfileID(int profileid); 28 | 29 | void InformStatusUpdate(int from_profileid, GPShared::GPStatus status); 30 | 31 | protected: 32 | virtual INetPeer *CreatePeer(uv_tcp_t *socket); 33 | }; 34 | } 35 | #endif //_SBDRIVER_H -------------------------------------------------------------------------------- /code/GP/server/GPServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "GPPeer.h" 3 | #include "GPServer.h" 4 | #include "GPDriver.h" 5 | namespace GP { 6 | Server::Server() : INetServer() { 7 | uv_loop_set_data(uv_default_loop(), this); 8 | } 9 | Server::~Server() { 10 | } 11 | void Server::tick() { 12 | std::vector::iterator it = m_net_drivers.begin(); 13 | while (it != m_net_drivers.end()) { 14 | INetDriver *driver = *it; 15 | driver->think(); 16 | it++; 17 | } 18 | NetworkTick(); 19 | } 20 | void Server::shutdown() { 21 | } 22 | INetPeer *Server::findPeerByProfile(int profile_id, bool inc_ref) { 23 | std::vector::iterator it = m_net_drivers.begin(); 24 | INetPeer *ret; 25 | GP::Driver *driver; 26 | while (it != m_net_drivers.end()) { 27 | driver = (GP::Driver *)*it; 28 | ret = driver->FindPeerByProfileID(profile_id); 29 | if (ret) { 30 | if (inc_ref) { 31 | ret->IncRef(); 32 | } 33 | return ret; 34 | } 35 | it++; 36 | } 37 | return NULL; 38 | } 39 | void Server::InformStatusUpdate(int from_profileid, GPShared::GPStatus status) { 40 | GP::Driver *driver; 41 | std::vector::iterator it = m_net_drivers.begin(); 42 | while (it != m_net_drivers.end()) { 43 | driver = (GP::Driver *)*it; 44 | driver->InformStatusUpdate(from_profileid, status); 45 | it++; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /code/GP/server/GPServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPSERVER_H 2 | #define _GPSERVER_H 3 | #include 4 | #include 5 | #include 6 | 7 | namespace GP { 8 | class Server : public INetServer { 9 | public: 10 | Server(); 11 | virtual ~Server(); 12 | void tick(); 13 | void shutdown(); 14 | INetPeer *findPeerByProfile(int profile_id, bool inc_ref = true); 15 | void InformStatusUpdate(int from_profileid, GPShared::GPStatus status); 16 | private: 17 | }; 18 | } 19 | #endif //_GPSERVER_H -------------------------------------------------------------------------------- /code/GP/server/commands/handle_addblock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "../../tasks/tasks.h" 15 | namespace GP { 16 | void Peer::handle_addblock(OS::KVReader data_parser) { 17 | if (data_parser.HasKey("profileid")) { 18 | int profileid = data_parser.GetValueInt("profileid"); 19 | if (std::find(m_blocks.begin(), m_blocks.end(), profileid) != m_blocks.end()) { 20 | send_error(GPShared::GP_ADDBLOCK_ALREADY_BLOCKED); 21 | return; 22 | } 23 | 24 | m_blocks.push_back(profileid); 25 | 26 | GPBackendRedisRequest req; 27 | req.type = EGPRedisRequestType_AddBlock; 28 | req.peer = this; 29 | req.peer->IncRef(); 30 | req.ToFromData.to_profileid = profileid; 31 | req.ToFromData.from_profileid = m_profile.id; 32 | AddGPTaskRequest(req); 33 | } else { 34 | send_error(GPShared::GP_PARSE); 35 | return; 36 | } 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /code/GP/server/commands/handle_delbuddy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace GP { 16 | void Peer::handle_delbuddy(OS::KVReader data_parser) { 17 | if (data_parser.HasKey("delprofileid")) { 18 | int delprofileid = data_parser.GetValueInt("delprofileid"); 19 | if (m_buddies.find(delprofileid) != m_buddies.end()) { 20 | GPBackendRedisRequest req; 21 | req.type = EGPRedisRequestType_DelBuddy; 22 | req.peer = (GP::Peer *)this; 23 | req.peer->IncRef(); 24 | req.ToFromData.from_profileid = m_profile.id; 25 | req.ToFromData.to_profileid = delprofileid; 26 | m_buddies.erase(delprofileid); 27 | AddGPTaskRequest(req); 28 | } 29 | else { 30 | send_error(GPShared::GP_DELBUDDY_NOT_BUDDY); 31 | } 32 | } 33 | else { 34 | send_error(GPShared::GP_PARSE); 35 | return; 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /code/GP/server/commands/handle_pinvite.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace GP { 16 | void Peer::handle_pinvite(OS::KVReader data_parser) { 17 | //profileid\10000\productid\1 18 | std::ostringstream s; 19 | //OS::KVReader data_parser = OS::KVReader(std::string(data)); 20 | int profileid = 0; 21 | if (data_parser.HasKey("profileid")) { 22 | profileid = data_parser.GetValueInt("profileid"); 23 | } 24 | int productid = 0; 25 | if (data_parser.HasKey("productid")) { 26 | productid = data_parser.GetValueInt("productid"); 27 | } 28 | 29 | s << "|p|" << productid; 30 | s << "|l|" << m_status.location_str; 31 | //s << "|signed|d41d8cd98f00b204e9800998ecf8427e"; //temp until calculation fixed 32 | //GPBackend::GPBackendRedisTask::SendMessage(this, profileid, GPI_BM_INVITE, s.str().c_str()); 33 | 34 | GPBackendRedisRequest req; 35 | req.type = EGPRedisRequestType_BuddyMessage; 36 | req.peer = this; 37 | req.peer->IncRef(); 38 | req.BuddyMessage.to_profileid = profileid; 39 | req.BuddyMessage.type = GPI_BM_INVITE; 40 | req.BuddyMessage.message = s.str(); 41 | 42 | 43 | AddGPTaskRequest(req); 44 | } 45 | } -------------------------------------------------------------------------------- /code/GP/server/commands/handle_removeblock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace GP { 16 | void Peer::handle_removeblock(OS::KVReader data_parser) { 17 | //OS::KVReader data_parser = OS::KVReader(std::string(data)); 18 | if (data_parser.HasKey("profileid")) { 19 | int profileid = data_parser.GetValueInt("profileid"); 20 | std::vector::iterator it = std::find(m_blocks.begin(), m_blocks.end(), profileid); 21 | if (it == m_blocks.end()) { 22 | send_error(GPShared::GP_REMOVEBLOCK_NOT_BLOCKED); 23 | return; 24 | } 25 | m_blocks.erase(it); 26 | 27 | GPBackendRedisRequest req; 28 | req.type = EGPRedisRequestType_DelBlock; 29 | req.peer = this; 30 | req.peer->IncRef(); 31 | req.ToFromData.to_profileid = profileid; 32 | req.ToFromData.from_profileid = m_profile.id; 33 | AddGPTaskRequest(req); 34 | } else { 35 | send_error(GPShared::GP_PARSE); 36 | return; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /code/GP/server/commands/handle_revoke.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace GP { 16 | void Peer::handle_revoke(OS::KVReader data_parser) { 17 | if (data_parser.HasKey("profileid")) { 18 | int delprofileid = data_parser.GetValueInt("profileid"); 19 | GPBackendRedisRequest req; 20 | req.type = EGPRedisRequestType_DelBuddy; 21 | req.peer = this; 22 | req.peer->IncRef(); 23 | req.ToFromData.to_profileid = m_profile.id; 24 | req.ToFromData.from_profileid = delprofileid; 25 | AddGPTaskRequest(req); 26 | } else { 27 | send_error(GPShared::GP_PARSE); 28 | return; 29 | } 30 | } 31 | void Peer::send_revoke_message(int from_profileid, int date_unix_timestamp) { 32 | m_buddies.erase(from_profileid); 33 | inform_status_update(from_profileid, GPShared::gp_default_status, true); 34 | 35 | std::ostringstream s; 36 | s << "\\bm\\" << GPI_BM_REVOKE; 37 | s << "\\f\\" << from_profileid; 38 | s << "\\msg\\I have revoked you from my list."; 39 | s << "|signed|d41d8cd98f00b204e9800998ecf8427e"; //temp until calculation fixed 40 | if(date_unix_timestamp != 0) 41 | s << "\\date\\" << date_unix_timestamp; 42 | SendPacket((const uint8_t *)s.str().c_str(),s.str().length()); 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /code/GP/tasks/BuddyRequest.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | namespace GP { 3 | bool Perform_BuddyRequest(GPBackendRedisRequest request, TaskThreadData *thread_data) { 4 | TaskShared::curl_data recv_data; 5 | //build json object 6 | json_t *send_obj = json_object(), *to_obj = json_object(), *from_obj = json_object(); 7 | 8 | json_object_set_new(send_obj, "addReason", json_string(request.BuddyRequest.reason.c_str())); 9 | 10 | json_object_set_new(send_obj, "sourceProfile", from_obj); 11 | json_object_set_new(send_obj, "targetProfile", to_obj); 12 | 13 | json_object_set_new(to_obj, "id", json_integer(request.BuddyRequest.to_profileid)); 14 | json_object_set_new(from_obj, "id", json_integer(request.BuddyRequest.from_profileid)); 15 | 16 | 17 | char *json_dump = json_dumps(send_obj, 0); 18 | 19 | CURL *curl = curl_easy_init(); 20 | CURLcode res; 21 | OS::Profile profile; 22 | OS::User user; 23 | user.id = 0; 24 | profile.id = 0; 25 | TaskShared::AuthData auth_data; 26 | 27 | 28 | if (curl) { 29 | struct curl_slist *chunk = NULL; 30 | GPReq_InitCurl(curl, json_dump, (void *)&recv_data, request, &chunk); 31 | 32 | res = curl_easy_perform(curl); 33 | 34 | if (res == CURLE_OK) { 35 | } 36 | curl_slist_free_all(chunk); 37 | curl_easy_cleanup(curl); 38 | } 39 | 40 | //no callback yet.. 41 | 42 | if (json_dump) { 43 | free((void *)json_dump); 44 | } 45 | json_decref(send_obj); 46 | 47 | if (request.peer) 48 | request.peer->DecRef(); 49 | return true; 50 | } 51 | } -------------------------------------------------------------------------------- /code/GP/tasks/SendBuddyMessage.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | namespace GP { 3 | bool Perform_SendBuddyMessage(GPBackendRedisRequest request, TaskThreadData *thread_data) { 4 | TaskShared::curl_data recv_data; 5 | //build json object 6 | json_t *send_obj = json_object(), *to_obj = json_object(), *from_obj = json_object(), *lookup_obj = json_object(); 7 | 8 | json_object_set_new(to_obj, "id", json_integer(request.BuddyMessage.to_profileid)); 9 | json_object_set_new(from_obj, "id", json_integer(request.peer->GetProfileID())); 10 | 11 | json_object_set_new(send_obj, "message", json_string(request.BuddyMessage.message.c_str())); 12 | 13 | json_object_set_new(lookup_obj, "sourceProfile", from_obj); 14 | json_object_set_new(lookup_obj, "targetProfile", to_obj); 15 | json_object_set_new(send_obj, "lookup", lookup_obj); 16 | 17 | json_object_set_new(send_obj, "type", json_integer(request.BuddyMessage.type)); 18 | 19 | 20 | char *json_dump = json_dumps(send_obj, 0); 21 | 22 | CURL *curl = curl_easy_init(); 23 | CURLcode res; 24 | OS::Profile profile; 25 | OS::User user; 26 | user.id = 0; 27 | profile.id = 0; 28 | TaskShared::AuthData auth_data; 29 | 30 | if (curl) { 31 | struct curl_slist *chunk = NULL; 32 | GPReq_InitCurl(curl, json_dump, (void *)&recv_data, request, &chunk); 33 | 34 | res = curl_easy_perform(curl); 35 | 36 | if (res == CURLE_OK) { 37 | //TODO: error handling 38 | } 39 | curl_slist_free_all(chunk); 40 | curl_easy_cleanup(curl); 41 | } 42 | if (json_dump) { 43 | free((void *)json_dump); 44 | } 45 | json_decref(send_obj); 46 | 47 | if(request.peer) 48 | request.peer->DecRef(); 49 | return true; 50 | } 51 | } -------------------------------------------------------------------------------- /code/GP/tasks/SendLoginEvent.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | namespace GP { 3 | bool Perform_SendLoginEvent(GPBackendRedisRequest request, TaskThreadData *thread_data) { 4 | 5 | if (request.peer) 6 | request.peer->DecRef(); 7 | return false; 8 | } 9 | } -------------------------------------------------------------------------------- /code/GP/tasks/ToFromProfileAction.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | namespace GP { 3 | bool Perform_ToFromProfileAction(GPBackendRedisRequest request, TaskThreadData *thread_data) { 4 | TaskShared::curl_data recv_data; 5 | //build json object 6 | json_t *send_obj = json_object(), *to_obj = json_object(), *from_obj = json_object(); 7 | 8 | 9 | json_object_set_new(send_obj, "sourceProfile", from_obj); 10 | json_object_set_new(send_obj, "targetProfile", to_obj); 11 | 12 | json_object_set_new(to_obj, "id", json_integer(request.ToFromData.to_profileid)); 13 | json_object_set_new(from_obj, "id", json_integer(request.ToFromData.from_profileid)); 14 | 15 | if (request.type == EGPRedisRequestType_DelBuddy) { 16 | //this might not be needed... 17 | json_object_set_new(send_obj, "silent", json_true()); 18 | } 19 | 20 | if (request.auth_token.length()) { 21 | json_object_set_new(send_obj, "addReason", json_string(request.auth_token.c_str())); 22 | } 23 | 24 | 25 | char *json_dump = json_dumps(send_obj, 0); 26 | 27 | CURL *curl = curl_easy_init(); 28 | CURLcode res; 29 | 30 | if (curl) { 31 | struct curl_slist *chunk = NULL; 32 | GPReq_InitCurl(curl, json_dump, (void *)&recv_data, request, &chunk); 33 | 34 | res = curl_easy_perform(curl); 35 | 36 | if (res == CURLE_OK) { 37 | } 38 | curl_slist_free_all(chunk); 39 | curl_easy_cleanup(curl); 40 | } 41 | 42 | if (json_dump) { 43 | free((void *)json_dump); 44 | } 45 | json_decref(send_obj); 46 | 47 | if (request.peer) 48 | request.peer->DecRef(); 49 | return true; 50 | } 51 | } -------------------------------------------------------------------------------- /code/SharedTasks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(openspy_SharedTasks) 4 | 5 | find_package(jansson REQUIRED) 6 | find_package(CURL REQUIRED) 7 | 8 | file(GLOB MAIN_SRCS "src/OS/*.cpp" "src/OS/SharedTasks/Account/*.cpp" "src/OS/SharedTasks/Account/tasks/*.cpp" "src/OS/SharedTasks/Auth/*.cpp" "src/OS/SharedTasks/Auth/tasks/*.cpp" "src/OS/SharedTasks/CDKey/*.cpp" "src/OS/SharedTasks/CDKey/tasks/*.cpp" "src/OS/SharedTasks/Geo/*.cpp" "src/OS/SharedTasks/Geo/tasks/*.cpp") 9 | 10 | SET(OPENSPY_SharedTasks_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${JANSSON_INCLUDE_DIRS} ${CURL_INCLUDE_DIR}) 11 | include_directories (${OPENSPY_SharedTasks_INCLUDE_DIRS}) 12 | 13 | 14 | add_library (SharedTasks SHARED ${MAIN_SRCS}) 15 | 16 | target_include_directories(SharedTasks PUBLIC "src/") 17 | target_link_libraries(SharedTasks openspy ${CURL_LIBRARIES} ${JANSSON_LIBRARIES}) 18 | INSTALL(TARGETS SharedTasks 19 | ARCHIVE DESTINATION lib 20 | LIBRARY DESTINATION lib 21 | COMPONENT library 22 | ) 23 | install(DIRECTORY "src/OS" DESTINATION include FILES_MATCHING PATTERN "*.h") 24 | -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/Date.cpp: -------------------------------------------------------------------------------- 1 | #include "Date.h" 2 | 3 | namespace OS { 4 | json_t *Date::GetJson() { 5 | json_t* obj = json_object(); 6 | 7 | json_object_set_new(obj, "day", json_integer(m_day)); 8 | json_object_set_new(obj, "month", json_integer(m_month)); 9 | json_object_set_new(obj, "year", json_integer(m_year)); 10 | 11 | return obj; 12 | } 13 | Date Date::GetDateFromJSON(json_t *object) { 14 | Date date; 15 | json_t *obj = json_object_get(object, "day"); 16 | date.m_day = (uint8_t)json_integer_value(obj); 17 | 18 | obj = json_object_get(object, "month"); 19 | date.m_month = (uint8_t)json_integer_value(obj); 20 | 21 | obj = json_object_get(object, "year"); 22 | date.m_year = (uint16_t)json_integer_value(obj); 23 | 24 | return date; 25 | } 26 | Date Date::GetDateFromGPValue(int value) { 27 | Date date; 28 | date.m_day = (value >> 24) & 0xFF; 29 | date.m_month = (value >> 16) & 0xFF; 30 | date.m_year = (value & 0xFFFF); 31 | return date; 32 | } 33 | 34 | int Date::GetGPDate() { 35 | int val = 0; 36 | val |= (m_day << 24); 37 | val |= (m_month << 16); 38 | val |= (m_year); 39 | return val; 40 | } 41 | } -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/Date.h: -------------------------------------------------------------------------------- 1 | #ifndef _N_DATE_H 2 | #define _N_DATE_H 3 | #include 4 | #include 5 | namespace OS { 6 | class Date { 7 | public: 8 | Date(uint16_t year, uint8_t month, uint8_t day) : m_year(year), m_month(month), m_day(day) { }; 9 | Date() : m_year(0), m_month(0), m_day(0) { }; 10 | 11 | json_t *GetJson(); 12 | 13 | static Date GetDateFromJSON(json_t *object); 14 | static Date GetDateFromGPValue(int value); 15 | int GetGPDate(); 16 | uint16_t GetYear() { return m_year; }; 17 | uint8_t GetMonth() { return m_month; }; 18 | uint8_t GetDay() { return m_day; }; 19 | private: 20 | uint16_t m_year; 21 | uint8_t m_month; 22 | uint8_t m_day; 23 | }; 24 | } 25 | #endif //_N_DATE_H -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/Profile.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_PROFILE_H 2 | #define _OS_PROFILE_H 3 | #include 4 | #include 5 | #include 6 | namespace OS { 7 | class Profile { 8 | public: 9 | Profile() { 10 | id = 0; 11 | userid = 0; 12 | namespaceid = -1; 13 | deleted = false; 14 | icquin = 0; 15 | zipcode = 0; 16 | sex = -1; 17 | pic = 0; 18 | ooc = 0; 19 | ind = 0; 20 | mar = 0; 21 | chc = 0; 22 | i1 = 0; 23 | birthday = Date(); 24 | lon = 0.0; 25 | lat = 0.0; 26 | }; 27 | int id; 28 | int userid; 29 | std::string nick; 30 | std::string uniquenick; 31 | int namespaceid; 32 | bool deleted; 33 | 34 | std::string firstname; 35 | std::string lastname; 36 | int icquin; 37 | int zipcode; 38 | int sex; 39 | int pic; //picture id 40 | int ooc; //occupation id 41 | int ind; //income id 42 | int mar; //marriage id 43 | int chc; //child count 44 | int i1; //interests 45 | OS::Date birthday; 46 | 47 | float lon; 48 | float lat; 49 | 50 | std::string homepage; 51 | std::string countrycode; 52 | std::string videocardstring[2]; 53 | std::string osstring; //operating system str 54 | std::string aim; 55 | }; 56 | 57 | json_t *ProfileToJson(Profile profile); 58 | Profile LoadProfileFromJson(json_t *obj); 59 | } 60 | #endif //_OS_PROFILE_H -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/SharedTasks/Account/UserTasks.h: -------------------------------------------------------------------------------- 1 | #ifndef OS_TASKS_USER_TASKS_H 2 | #define OS_TASKS_USER_TASKS_H 3 | #include 4 | #include 5 | #include 6 | #include "../../tasks.h" 7 | #include "../../WebError.h" 8 | namespace TaskShared { 9 | typedef void (*UserSearchCallback)(TaskShared::WebErrorDetails error_details, std::vector results, void *extra, INetPeer *peer); 10 | 11 | enum EUserRequestType { 12 | EUserRequestType_Create, 13 | EUserRequestType_Search, 14 | EUserRequestType_Update, 15 | EUserRequestType_Register, 16 | }; 17 | 18 | typedef struct { 19 | OS::GameData gamedata; 20 | OS::User user; 21 | OS::Profile profile; 22 | WebErrorDetails error_details; 23 | } UserRegisterData; 24 | 25 | typedef void(*RegisterCallback)(bool success, OS::User user, OS::Profile profile, TaskShared::UserRegisterData auth_data, void *extra, INetPeer *peer); 26 | 27 | typedef struct { 28 | OS::User search_params; 29 | OS::Profile profile_params; //used for register only 30 | int type; 31 | int skip; 32 | void *extra; 33 | UserSearchCallback callback; 34 | RegisterCallback registerCallback; 35 | INetPeer *peer; 36 | std::string gamename; 37 | } UserRequest; 38 | 39 | bool PerformUserRequest(UserRequest request, TaskThreadData *thread_data); 40 | bool PerformUserRegisterRequest(UserRequest request, TaskThreadData *thread_data); 41 | 42 | 43 | void PerformUserTaskWorkRequest(uv_work_t *req); 44 | void PerformUserTaskWorkRequestCleanup(uv_work_t *req, int status); 45 | void AddUserTaskRequest(UserRequest request); 46 | 47 | } 48 | #endif //_USER_TASKS_H -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/SharedTasks/Auth/tasks/Auth_DeleteAuthSession.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../AuthTasks.h" 3 | namespace TaskShared { 4 | bool PerformAuth_DeleteAuthSession(AuthRequest request, TaskThreadData *thread_data) { 5 | curl_data recv_data; 6 | //build json object 7 | json_t *send_obj = json_object(); 8 | json_object_set_new(send_obj, "sessionKey", json_string(request.gamename.c_str())); 9 | 10 | 11 | char *json_dump = json_dumps(send_obj, 0); 12 | 13 | CURL *curl = curl_easy_init(); 14 | CURLcode res; 15 | TaskShared::AuthData auth_data; 16 | 17 | bool success = false; 18 | if (curl) { 19 | struct curl_slist *chunk = NULL; 20 | AuthReq_InitCurl(curl, json_dump, (void *)&recv_data, request, &chunk); 21 | 22 | res = curl_easy_perform(curl); 23 | 24 | if (res == CURLE_OK) { 25 | json_t *json_data = json_loads(recv_data.buffer.c_str(), 0, NULL); 26 | if (Handle_WebError(json_data, auth_data.error_details)) { 27 | 28 | } else if (json_data) { 29 | json_t *success_obj = json_object_get(json_data, "success"); 30 | success = success_obj == json_true(); 31 | json_decref(json_data); 32 | } 33 | } 34 | curl_slist_free_all(chunk); 35 | curl_easy_cleanup(curl); 36 | } 37 | request.callback(success, OS::User(), OS::Profile(), auth_data, request.extra, request.peer); 38 | if (json_dump) { 39 | free((void *)json_dump); 40 | } 41 | json_decref(send_obj); 42 | 43 | if (request.peer) { 44 | request.peer->DecRef(); 45 | } 46 | return false; 47 | } 48 | } -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/SharedTasks/CDKey/CDKeyTasks.h: -------------------------------------------------------------------------------- 1 | #ifndef OS_TASKSHARED_CDKEY_H 2 | #define OS_TASKSHARED_CDKEY_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../../WebError.h" 11 | #include "../../tasks.h" 12 | namespace TaskShared { 13 | enum ECDKeyType { 14 | ECDKeyType_AssociateToProfile, 15 | ECDKeyType_GetProfileByCDKey, 16 | ECDKeyType_TestCDKeyValid, 17 | }; 18 | 19 | typedef struct { 20 | std::string cdkey; 21 | OS::Profile profile; 22 | OS::User user; 23 | OS::GameData gamedata; 24 | WebErrorDetails error_details; 25 | } CDKeyData; 26 | 27 | typedef void (*CDKeyCallback)(CDKeyData auth_data, void *extra, INetPeer *peer); 28 | 29 | class CDKeyRequest { 30 | public: 31 | CDKeyRequest() { 32 | extra = NULL; 33 | peer = NULL; 34 | callback = NULL; 35 | } 36 | int type; 37 | 38 | OS::Profile profile; 39 | CDKeyCallback callback; 40 | void *extra; 41 | 42 | INetPeer *peer; 43 | std::string gamename; 44 | int gameid; 45 | 46 | std::string cdkey; 47 | std::string cdkeyHash; 48 | }; 49 | 50 | void CDKeyReq_InitCurl(void *curl, char *post_data, void *write_data, CDKeyRequest request, struct curl_slist **out_list); 51 | 52 | bool PerformCDKey_AssociateToProfile(CDKeyRequest request, TaskThreadData *thread_data); 53 | bool PerformCDKey_GetProfileByCDKey(CDKeyRequest request, TaskThreadData *thread_data); 54 | bool PerformCDKey_TestCDKeyValid(CDKeyRequest request, TaskThreadData *thread_data); 55 | 56 | void AddCDKeyTaskRequest(CDKeyRequest request); 57 | } 58 | #endif //OS_TASKSHARED_AUTH_H -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/User.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_USER_H 2 | #define _OS_USER_H 3 | #include 4 | #include 5 | namespace OS { 6 | class User { 7 | public: 8 | User() { 9 | id = 0; 10 | partnercode = -1; 11 | videocard_ram[0] = 0; 12 | videocard_ram[1] = 0; 13 | cpu_speed = 0; 14 | cpu_brandid = 0; 15 | connectionspeed = 0; 16 | connectionid = 0; 17 | hasnetwork = false; 18 | email_verified = false; 19 | publicmask = 0; 20 | deleted = false; 21 | }; 22 | int id; 23 | std::string email; 24 | int partnercode; 25 | 26 | //below not searchable 27 | std::string password; 28 | int videocard_ram[2]; 29 | int cpu_speed; 30 | int cpu_brandid; 31 | int connectionspeed; 32 | int connectionid; 33 | bool hasnetwork; 34 | 35 | bool email_verified; 36 | int publicmask; //appears as user var in GP 37 | bool deleted; 38 | }; 39 | json_t *UserToJson(User user); 40 | User LoadUserFromJson(json_t *obj); 41 | } 42 | #endif //_OS_USER_H -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/WebError.h: -------------------------------------------------------------------------------- 1 | #ifndef _WEBERROR_H 2 | #define _WEBERROR_H 3 | #include 4 | namespace TaskShared { 5 | enum WebErrorCode { 6 | WebErrorCode_Success, 7 | WebErrorCode_AuthInvalidCredentials, 8 | WebErrorCode_AuthAccountBanned, 9 | WebErrorCode_AuthAccountDisabled, 10 | WebErrorCode_CannotDeleteLastProfile, 11 | WebErrorCode_NickInUse, 12 | WebErrorCode_NickInvalid, 13 | WebErrorCode_NoSuchUser, 14 | WebErrorCode_UniqueNickInUse, 15 | WebErrorCode_UniqueNickInvalid, 16 | WebErrorCode_UserExists, 17 | WebErrorCode_EmailInvalid, 18 | WebErrorCode_EmailInUse, 19 | WebErrorCode_BadCdKey, 20 | WebErrorCode_CdKeyAlreadyTaken, 21 | WebErrorCode_CdKeyAlreadySet, 22 | WebErrorCode_BackendError, //fallback error, generic comms problem, etc 23 | }; 24 | class WebErrorDetails { 25 | public: 26 | WebErrorDetails() { response_code = WebErrorCode_BackendError; userid = 0; profileid = 0; } 27 | WebErrorCode response_code; 28 | int profileid; 29 | int userid; 30 | } ; 31 | bool Handle_WebError(json_t *json_body, WebErrorDetails &error_info); //in AuthTasks.cpp 32 | } 33 | #endif //_WEBERROR_H -------------------------------------------------------------------------------- /code/SharedTasks/src/OS/tasks.h: -------------------------------------------------------------------------------- 1 | #ifndef _TASKS_SHARED_H 2 | #define _TASKS_SHARED_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace OS { 9 | class Address; 10 | } 11 | namespace TaskShared { 12 | class TaskThreadData { 13 | public: 14 | redisContext *mp_redis_connection; 15 | }; 16 | 17 | struct curl_data { 18 | std::string buffer; 19 | }; 20 | 21 | typedef struct _ListenerEventHandler{ 22 | const char *amqp_exchange; 23 | const char *amqp_routing_key; 24 | bool (*amqp_event_callback)(TaskThreadData *, std::string); 25 | } ListenerEventHandler; 26 | typedef struct { 27 | const struct _ListenerEventHandler *event_handlers; 28 | const size_t num_event_handlers; 29 | uv_thread_t amqp_authevent_consumer_thread; 30 | amqp_connection_state_t amqp_listener_conn; 31 | amqp_socket_t *amqp_socket; 32 | bool exit_flag; 33 | } ListenerArgs; 34 | 35 | size_t curl_callback(void *contents, size_t size, size_t nmemb, void *userp); 36 | 37 | amqp_connection_state_t getThreadLocalAmqpConnection(); 38 | redisContext *getThreadLocalRedisContext(); 39 | void sendAMQPMessage(const char *exchange, const char *routingkey, const char *messagebody, const OS::Address *peer_address = NULL); 40 | void setup_listener(ListenerArgs *args); 41 | void amqp_listenerargs_consume_thread(void *arg); 42 | 43 | } 44 | #endif //_TASKS_SHARED_H -------------------------------------------------------------------------------- /code/cdkey/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(cdkey) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | file (GLOB MAIN_SRCS "*.cpp") 8 | file (GLOB MAIN_HDRS "*.h") 9 | file (GLOB SERVER_SRCS "server/*.cpp") 10 | file (GLOB SERVER_HDRS "server/*.h") 11 | file (GLOB SERVER_HANDLERS_SRCS "server/handlers/*.cpp") 12 | file (GLOB SERVER_HANDLERS_HDRS "server/handlers/*.h") 13 | 14 | 15 | set (ALL_SRCS ${MAIN_SRCS} ${MAIN_HDRS} ${SERVER_SRCS} ${SERVER_HDRS} ${SERVER_HANDLERS_SRCS} ${SERVER_HANDLERS_HDRS}) 16 | 17 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 18 | 19 | source_group("Sources" FILES ${MAIN_SRCS}) 20 | source_group("Sources\\Server" FILES ${SERVER_SRCS}) 21 | source_group("Sources\\Server\\handlers" FILES ${SERVER_HANDLERS_SRCS}) 22 | 23 | source_group("Headers" FILES ${MAIN_HDRS}) 24 | source_group("Headers\\Server" FILES ${SERVER_HDRS}) 25 | source_group("Headers\\Server\\handlers" FILES ${SERVER_HANDLERS_HDRS}) 26 | 27 | 28 | add_executable (cdkey ${ALL_SRCS}) 29 | 30 | target_compile_features(cdkey PRIVATE cxx_unrestricted_unions) 31 | 32 | IF(WIN32) 33 | target_link_libraries(cdkey openspy.lib ZLIB::ZLIB) 34 | ELSE() #unix 35 | target_link_libraries(cdkey openspy ZLIB::ZLIB) 36 | ENDIF() -------------------------------------------------------------------------------- /code/cdkey/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "server/CDKeyServer.h" 7 | #include "server/CDKeyDriver.h" 8 | 9 | INetServer *g_gameserver = NULL; 10 | 11 | void tick_handler(uv_timer_t* handle) { 12 | g_gameserver->tick(); 13 | } 14 | 15 | int main() { 16 | uv_loop_t *loop = uv_default_loop(); 17 | uv_timer_t tick_timer; 18 | 19 | uv_timer_init(uv_default_loop(), &tick_timer); 20 | 21 | OS::Init("cdkey"); 22 | g_gameserver = new CDKey::Server(); 23 | 24 | char address_buff[256]; 25 | char port_buff[16]; 26 | size_t temp_env_sz = sizeof(address_buff); 27 | 28 | if(uv_os_getenv("OPENSPY_CDKEY_BIND_ADDR", (char *)&address_buff, &temp_env_sz) != UV_ENOENT) { 29 | temp_env_sz = sizeof(port_buff); 30 | 31 | uint16_t port = 29910; 32 | if(uv_os_getenv("OPENSPY_CDKEY_BIND_PORT", (char *)&port_buff, &temp_env_sz) != UV_ENOENT) { 33 | port = atoi(port_buff); 34 | } 35 | 36 | CDKey::Driver *driver = new CDKey::Driver(g_gameserver, address_buff, port); 37 | 38 | OS::LogText(OS::ELogLevel_Info, "Adding CDKey Driver: %s:%d\n", address_buff, port); 39 | g_gameserver->addNetworkDriver(driver); 40 | } else { 41 | OS::LogText(OS::ELogLevel_Warning, "Missing CDKey bind address environment variable"); 42 | } 43 | 44 | uv_timer_start(&tick_timer, tick_handler, 0, 250); 45 | uv_run(loop, UV_RUN_DEFAULT); 46 | 47 | uv_loop_close(loop); 48 | 49 | delete g_gameserver; 50 | 51 | OS::Shutdown(); 52 | return 0; 53 | } -------------------------------------------------------------------------------- /code/cdkey/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/cdkey/server/CDKeyDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _CDKEYDRIVER_H 2 | #define _CDKEYDRIVER_H 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #ifdef _WIN32 11 | #include 12 | #else 13 | #include 14 | #endif 15 | 16 | #include 17 | 18 | #define MAX_DATA_SIZE 1400 19 | #define DRIVER_THREAD_TIME 1000 20 | namespace CDKey { 21 | class Driver : public OS::UDPDriver { 22 | public: 23 | Driver(INetServer *server, const char *host, uint16_t port); 24 | ~Driver(); 25 | 26 | 27 | void handle_auth_packet(OS::Address from, OS::KVReader data_parser); 28 | void SendPacket(OS::Address to, std::string message); 29 | private: 30 | static void on_udp_read(uv_udp_t* handle, 31 | ssize_t nread, 32 | const uv_buf_t* buf, 33 | const struct sockaddr* addr, 34 | unsigned flags); 35 | 36 | uv_timespec64_t m_server_start; 37 | }; 38 | } 39 | #endif //_NNDRIVER_H -------------------------------------------------------------------------------- /code/cdkey/server/CDKeyServer.cpp: -------------------------------------------------------------------------------- 1 | #include "CDKeyServer.h" 2 | #include "CDKeyDriver.h" 3 | #include 4 | namespace CDKey { 5 | 6 | Server::Server() : INetServer() { 7 | uv_loop_set_data(uv_default_loop(), this); 8 | } 9 | Server::~Server() { 10 | } 11 | void Server::tick() { 12 | std::vector::iterator it = m_net_drivers.begin(); 13 | while (it != m_net_drivers.end()) { 14 | INetDriver *driver = *it; 15 | driver->think(); 16 | it++; 17 | } 18 | NetworkTick(); 19 | } 20 | void Server::shutdown() { 21 | 22 | } 23 | CDKey::Driver *Server::findDriverByAddress(OS::Address address) { 24 | std::vector::iterator it = m_net_drivers.begin(); 25 | while (it != m_net_drivers.end()) { 26 | INetDriver *driver = *it; 27 | if(OS::Address(driver->GetAddress()) == address) { 28 | return (CDKey::Driver *)driver; 29 | } 30 | it++; 31 | } 32 | return NULL; 33 | } 34 | } -------------------------------------------------------------------------------- /code/cdkey/server/CDKeyServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _CDKEYSERVER_H 2 | #define _CDKEYSERVER_H 3 | #include 4 | #include 5 | #include 6 | 7 | namespace CDKey { 8 | class Driver; 9 | class Server : public INetServer { 10 | public: 11 | Server(); 12 | virtual ~Server(); 13 | void tick(); 14 | void shutdown(); 15 | CDKey::Driver *findDriverByAddress(OS::Address address); 16 | private: 17 | }; 18 | } 19 | #endif //_CHCGAMESERVER_H -------------------------------------------------------------------------------- /code/cdkey/server/handlers/handle_auth.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../CDKeyServer.h" 5 | #include "../CDKeyDriver.h" 6 | #include 7 | 8 | namespace CDKey { 9 | void Driver::handle_auth_packet(OS::Address from, OS::KVReader data_parser) { 10 | std::ostringstream ss; 11 | std::string cdkey = data_parser.GetValue("resp"); 12 | if(cdkey.length() > 32) { 13 | cdkey = cdkey.substr(0, 32); 14 | } 15 | ss << "\\uok\\\\cd\\" << cdkey << "\\skey\\" << data_parser.GetValueInt("skey"); 16 | 17 | SendPacket(from, ss.str()); 18 | } 19 | } -------------------------------------------------------------------------------- /code/core/OS/Address.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | namespace OS { 4 | 5 | Address::Address(uint32_t ip, uint16_t port) { 6 | this->ip = ip; 7 | this->port = htons(port); 8 | } 9 | Address::Address(struct sockaddr_in addr) { 10 | ip = addr.sin_addr.s_addr; 11 | port = addr.sin_port; 12 | } 13 | Address::Address(std::string input) { 14 | std::string address; 15 | size_t offset = input.find(':'); 16 | if (offset != std::string::npos) { 17 | port = htons(atoi(input.substr(offset+1).c_str())); 18 | address = input.substr(0, offset); 19 | } 20 | else { 21 | address = input; 22 | } 23 | ip = inet_addr(address.c_str()); 24 | } 25 | Address::Address() { 26 | ip = 0; 27 | port = 0; 28 | } 29 | uint16_t Address::GetPort() const { 30 | return htons(port); 31 | } 32 | const struct sockaddr_in Address::GetInAddr() { 33 | struct sockaddr_in ret; 34 | ret.sin_family = AF_INET; 35 | memset(&ret.sin_zero, 0, sizeof(ret.sin_zero)); 36 | ret.sin_addr.s_addr = ip; 37 | ret.sin_port = port; 38 | return ret; 39 | 40 | } 41 | std::string Address::ToString(bool ip_only) const { 42 | struct sockaddr_in addr; 43 | addr.sin_port = (port); 44 | addr.sin_addr.s_addr = (ip); 45 | 46 | char ipinput[64]; 47 | memset(&ipinput, 0, sizeof(ipinput)); 48 | 49 | inet_ntop(AF_INET, &(addr.sin_addr), ipinput, sizeof(ipinput)); 50 | 51 | 52 | std::ostringstream s; 53 | s << ipinput; 54 | if (!ip_only) { 55 | s << ":" << htons(port); 56 | } 57 | return s.str(); 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /code/core/OS/HTTP.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_HTTP_H 2 | #define _OS_HTTP_H 3 | #include 4 | #include 5 | #include 6 | namespace OS { 7 | typedef struct { 8 | int status_code; 9 | std::string buffer; 10 | } HTTPResponse; 11 | class HTTPClient { 12 | public: 13 | HTTPClient(std::string url); 14 | ~HTTPClient(); 15 | //(GP_PERSIST_BACKEND_URL, GP_PERSIST_BACKEND_CRYPTKEY, send_json) 16 | HTTPResponse Post(std::string send, INetPeer *peer); //synchronous HTTP post 17 | HTTPResponse Put(std::string send, INetPeer *peer); //synchronous HTTP put 18 | HTTPResponse Delete(std::string send, INetPeer *peer); //synchronous HTTP delete 19 | 20 | private: 21 | HTTPResponse PerformMethod(std::string send, std::string method, INetPeer *peer); 22 | static size_t curl_callback (void *contents, size_t size, size_t nmemb, void *userp); 23 | std::string m_url; 24 | }; 25 | } 26 | #endif //_OS_HTTP_H -------------------------------------------------------------------------------- /code/core/OS/KVReader.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_KVREADER_H 2 | #define _OS_KVREADER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | /* 9 | This is not thread safe!! 10 | 11 | Because of: 12 | GetHead 13 | */ 14 | namespace OS { 15 | class KVReader { 16 | public: 17 | KVReader(); 18 | KVReader(std::string kv_pair, char delim = '\\', char line_delim=0, std::map data_map = std::map()); 19 | ~KVReader(); 20 | std::string GetKeyByIdx(int n); 21 | std::string GetValueByIdx(int n); 22 | int GetValueIntByIdx(int n); 23 | std::pair GetPairByIdx(int n); 24 | std::string GetValue(std::string key); 25 | int GetValueInt(std::string key); 26 | std::pair >::const_iterator, std::vector >::const_iterator> GetHead() const; 27 | bool HasKey(std::string name); 28 | size_t Size() { return m_kv_map.size(); }; 29 | std::map GetKVMap() const; 30 | 31 | std::string ToString(bool values_only = false) const; 32 | private: 33 | int GetIndex(int n); //map internal index to external index 34 | bool IsDataKey(std::string key); 35 | std::vector >::const_iterator FindKey(std::string key); 36 | std::vector >::const_iterator FindValue(std::string key); 37 | std::vector< std::pair > m_kv_map; 38 | char m_delimitor; 39 | char m_line_delimitor; 40 | std::map m_data_key_map; 41 | }; 42 | } 43 | #endif //_OS_KVREADER_H -------------------------------------------------------------------------------- /code/core/OS/Logger.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_LOGGER_H 2 | #define _OS_LOGGER_H 3 | #include 4 | /* 5 | The core logger for openspy 6 | 7 | Do not call this directly, call OS::Log instead 8 | 9 | There should only be 1 instance of this per process existing within openspy itself 10 | */ 11 | namespace OS { 12 | enum ELogLevel { 13 | ELogLevel_Debug, 14 | ELogLevel_Info, 15 | ELogLevel_Warning, 16 | ELogLevel_Critical, 17 | ELogLevel_Error, 18 | ELogLevel_Auth 19 | }; 20 | class Logger { 21 | public: 22 | Logger(const char *name) { mp_name = name; }; 23 | virtual ~Logger() {}; 24 | virtual void LogText(ELogLevel level, const char * format, va_list args) = 0; 25 | protected: 26 | const char *mp_name; 27 | }; 28 | } 29 | #endif //_OS_LOGGER_H -------------------------------------------------------------------------------- /code/core/OS/Logger/Unix/UnixLogger.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "UnixLogger.h" 5 | #include 6 | namespace OS { 7 | UnixLogger::UnixLogger(const char *name) : Logger(name) { 8 | openlog(name, LOG_PID|LOG_CONS, LOG_USER); 9 | } 10 | UnixLogger::~UnixLogger() { 11 | closelog(); 12 | } 13 | void UnixLogger::LogText(ELogLevel level, const char * format, va_list args) { 14 | int log_level = LOG_INFO; 15 | const char *level_str = "NA"; 16 | switch(level) { 17 | case ELogLevel_Debug: 18 | level_str = "DBG"; 19 | log_level = LOG_DEBUG; 20 | break; 21 | case ELogLevel_Warning: 22 | level_str = "WARN"; 23 | log_level = LOG_WARNING; 24 | break; 25 | case ELogLevel_Critical: 26 | level_str = "CRIT"; 27 | log_level = LOG_CRIT; 28 | break; 29 | case ELogLevel_Info: 30 | level_str = "INFO"; 31 | log_level = LOG_INFO; 32 | break; 33 | case ELogLevel_Error: 34 | level_str = "ERR"; 35 | log_level = LOG_ERR; 36 | break; 37 | case ELogLevel_Auth: 38 | level_str = "AUTH"; 39 | log_level = LOG_AUTH; 40 | break; 41 | } 42 | va_list va_cpy; 43 | va_copy(va_cpy,args); 44 | vsyslog(log_level, format, args); 45 | //fprintf(stderr, "[%s]:", level_str); 46 | //vfprintf(stderr, format, va_cpy); 47 | //fprintf(stderr, "\n"); 48 | va_end(va_cpy); 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /code/core/OS/Logger/Unix/UnixLogger.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_UNIXLOGGER_H 2 | #define _OS_UNIXLOGGER_H 3 | #include 4 | namespace OS { 5 | class UnixLogger : public Logger { 6 | public: 7 | UnixLogger(const char *name); 8 | ~UnixLogger(); 9 | void LogText(ELogLevel level, const char * format, va_list args); 10 | protected: 11 | const char *mp_name; 12 | }; 13 | } 14 | #endif //_OS_UNIXLOGGER_H -------------------------------------------------------------------------------- /code/core/OS/Logger/Win32/Win32Logger.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Win32Logger.h" 5 | #include 6 | namespace OS { 7 | Win32Logger::Win32Logger(const char *name) : Logger(name) { 8 | 9 | } 10 | Win32Logger::~Win32Logger() { 11 | 12 | } 13 | void Win32Logger::LogText(ELogLevel level, const char * format, va_list args) { 14 | vprintf(format, args); 15 | printf("\n"); 16 | } 17 | } -------------------------------------------------------------------------------- /code/core/OS/Logger/Win32/Win32Logger.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_WIN32LOGGER_H 2 | #define _OS_WIN32LOGGER_H 3 | #include 4 | namespace OS { 5 | class Win32Logger : public Logger { 6 | public: 7 | Win32Logger(const char *name); 8 | ~Win32Logger(); 9 | void LogText(ELogLevel level, const char * format, va_list args); 10 | protected: 11 | const char *mp_name; 12 | }; 13 | } 14 | #endif //_OS_UNIXLOGGER_H -------------------------------------------------------------------------------- /code/core/OS/Net/NetDriver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "NetDriver.h" 3 | #include "NetPeer.h" 4 | 5 | INetDriver::INetDriver(INetServer *server) { 6 | m_server = server; 7 | } 8 | INetDriver::~INetDriver() { 9 | } -------------------------------------------------------------------------------- /code/core/OS/Net/NetDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _NETDRIVER_H 2 | #define _NETDRIVER_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | class INetServer; 9 | class INetPeer; 10 | class INetDriver { 11 | public: 12 | INetDriver(INetServer *server); 13 | virtual ~INetDriver(); 14 | /* 15 | Check for incoming data, etc 16 | */ 17 | virtual void think() = 0; 18 | INetServer *getServer() { return m_server; } 19 | struct sockaddr_in GetAddress() { return m_recv_addr; }; 20 | protected: 21 | INetServer *m_server; 22 | struct sockaddr_in m_recv_addr; 23 | }; 24 | #endif //_NETDRIVER_H -------------------------------------------------------------------------------- /code/core/OS/Net/NetProcessor.h: -------------------------------------------------------------------------------- 1 | /* 2 | Generic application protocol dispatcher 3 | */ 4 | #ifndef _NETPROCESSOR_H 5 | #define _NETPROCESSOR_H 6 | #include 7 | #include 8 | #include 9 | template 10 | class INetProcessor { 11 | public: 12 | INetProcessor() { 13 | 14 | } 15 | virtual ~INetProcessor() { 16 | 17 | } 18 | bool ProcessIncoming(OS::Buffer &buffer, std::vector &output) { 19 | return deserialize_data(buffer, output); 20 | } 21 | bool SerializeData(O data, OS::Buffer &buffer) { 22 | return serialize_data(data, buffer); 23 | } 24 | protected: 25 | virtual bool deserialize_data(OS::Buffer &buffer, std::vector &output) = 0; 26 | virtual bool serialize_data(O &output, OS::Buffer &buffer) = 0; 27 | }; 28 | #endif //_NETPROCESSOR_H -------------------------------------------------------------------------------- /code/core/OS/Net/NetServer.cpp: -------------------------------------------------------------------------------- 1 | #include "NetServer.h" 2 | 3 | INetServer::INetServer() { 4 | } 5 | INetServer::~INetServer() { 6 | std::vector::iterator it = m_net_drivers.begin(); 7 | while (it != m_net_drivers.end()) { 8 | delete *it; 9 | it++; 10 | } 11 | } 12 | void INetServer::addNetworkDriver(INetDriver *driver) { 13 | m_net_drivers.push_back(driver); 14 | } 15 | void INetServer::tick() { 16 | } 17 | void INetServer::NetworkTick() { 18 | } -------------------------------------------------------------------------------- /code/core/OS/Net/NetServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _INETSERVER_H 2 | #define _INETSERVER_H 3 | #include 4 | #include 5 | #include "NetDriver.h" 6 | class INetServer { 7 | public: 8 | INetServer(); 9 | virtual ~INetServer(); 10 | virtual void tick(); 11 | /* 12 | Currently the driver is aware of what type of NetServer its connected to. 13 | */ 14 | void addNetworkDriver(INetDriver *driver); 15 | protected: 16 | void NetworkTick(); //fires the INetEventMgr 17 | //private: 18 | std::vector m_net_drivers; 19 | }; 20 | #endif //_IGAMESERVER_H -------------------------------------------------------------------------------- /code/core/OS/Net/Processors/KVProcessor.h: -------------------------------------------------------------------------------- 1 | #ifndef _KVPROCESSOR_H 2 | #define _KVPROCESSOR_H 3 | #include 4 | #include "../NetProcessor.h" 5 | #define MAX_UNPROCESSED_DATA 5000 6 | class KVProcessor : public INetProcessor { 7 | public: 8 | KVProcessor(); 9 | ~KVProcessor(); 10 | protected: 11 | bool deserialize_data(OS::Buffer &buffer, std::vector &output); 12 | bool serialize_data(OS::KVReader &output, OS::Buffer &buffer); 13 | private: 14 | std::string m_kv_accumulator; 15 | }; 16 | #endif //_KVPROCESSOR_H -------------------------------------------------------------------------------- /code/core/OS/Net/drivers/TCPDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _TCPDRIVER_H 2 | #define _TCPDRIVER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace OS { 8 | class TCPDriver : public INetDriver { 9 | public: 10 | TCPDriver(INetServer *server, const char *host, uint16_t port); 11 | virtual ~TCPDriver(); 12 | void think(); 13 | 14 | //Linked List iterators 15 | static bool LLIterator_DeleteAllClients(INetPeer* peer, TCPDriver* driver); 16 | static bool LLIterator_TickOrDeleteClient(INetPeer* peer, TCPDriver* driver); 17 | // 18 | OS::LinkedListHead* GetPeerList() { return mp_peers; }; 19 | protected: 20 | virtual INetPeer *CreatePeer(uv_tcp_t *socket) = 0; 21 | virtual void TickConnections(); 22 | void DeleteClients(); 23 | static void s_on_new_connection(uv_stream_t *server, int status); 24 | virtual INetPeer *on_new_connection(uv_stream_t *server, int status); 25 | OS::LinkedListHead* mp_peers; 26 | 27 | uv_tcp_t m_listener_socket; 28 | }; 29 | } 30 | #endif //_TCPDRIVER_H -------------------------------------------------------------------------------- /code/core/OS/Net/drivers/UDPDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _UDPDRIVER_H 2 | #define _UDPDRIVER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace OS { 8 | class UDPDriver : public INetDriver { 9 | public: 10 | UDPDriver(INetServer *server, const char *host, uint16_t port); 11 | virtual ~UDPDriver(); 12 | void think(); 13 | void SendUDPPacket(OS::Address to, OS::Buffer buffer); 14 | static void on_udp_send_callback(uv_udp_send_t* req, int status); 15 | protected: 16 | static void clear_send_buffer(uv_async_t *handle); 17 | 18 | uv_udp_t m_recv_udp_socket; 19 | uv_async_t m_udp_send_async_handler; 20 | std::stack> m_udp_send_buffer; 21 | uv_mutex_t m_udp_send_mutex; 22 | 23 | }; 24 | } 25 | #endif //_UDPDRIVER_H -------------------------------------------------------------------------------- /code/core/OS/Ref.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_REFCNT_H 2 | #define _OS_REFCNT_H 3 | #include 4 | namespace OS { 5 | class Ref { 6 | public: 7 | Ref() { m_ref_count.store(1); }; 8 | void DecRef() { m_ref_count--; }; 9 | void IncRef() { m_ref_count++; }; 10 | int GetRefCount() { return m_ref_count.load(); }; 11 | private: 12 | std::atomic m_ref_count; 13 | 14 | }; 15 | }; 16 | #endif //_OS_REFCNT_H 17 | -------------------------------------------------------------------------------- /code/core/OS/gamespy/gamespy.h: -------------------------------------------------------------------------------- 1 | #ifndef _OS_GAMESPY_H 2 | #define _OS_GAMESPY_H 3 | int gslame(int num); 4 | int gspassenc(uint8_t *pass, int passlen); 5 | uint8_t *base64_encode(uint8_t *data, int *size); 6 | uint8_t *base64_decode(uint8_t *data, int *size); 7 | void gamespyxor(char *data, int len); 8 | void gamespy3dxor(char *data, int len); 9 | #endif //_OS_GAMESPY_H -------------------------------------------------------------------------------- /code/core/OS/gamespy/gsmsalg.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifndef _GSMALG_INC 4 | #define _GSMALG_INC 5 | unsigned char gsvalfunc(int reg); 6 | unsigned char *gsseckey(unsigned char *dst, const char *src, const unsigned char *key, int enctype); 7 | #endif -------------------------------------------------------------------------------- /code/core/OS/test/TestNetIOInterface.cpp: -------------------------------------------------------------------------------- 1 | #include "TestNetIOInterface.h" 2 | 3 | namespace Test { 4 | template<> 5 | void TestNetIOInterface<>::fake_AddTCPConnection(INetIOSocket *socket) { 6 | m_TCPAccept_WaitList.push_back(socket); 7 | } 8 | template<> 9 | void TestNetIOInterface<>::fake_PushIncomingPacket(INetIOSocket *socket, OS::Buffer &buffer) { 10 | m_pending_packets[socket].push_back(buffer); 11 | } 12 | template<> 13 | void TestNetIOInterface<>::fake_SetSendCallback(bool (*SendCallback)(INetIOSocket *, OS::Buffer)) { 14 | mp_SendCallback = SendCallback; 15 | } 16 | template<> 17 | void TestNetIOInterface<>::fake_TCPDisconnect(INetIOSocket *socket) { 18 | m_pending_tcp_disconnects.push_back(socket); 19 | } 20 | template<> 21 | void TestNetIOInterface<>::fake_PushIncomingDatagram(INetIOSocket *socket, INetIODatagram dgram) { 22 | m_pending_datagrams[socket].push_back(dgram); 23 | } 24 | } -------------------------------------------------------------------------------- /code/core/SSL/OpenSSL/SSL/SSLPeer.h: -------------------------------------------------------------------------------- 1 | #ifndef _SSLPEER_H 2 | #define _SSLPEER_H 3 | #include 4 | #include 5 | namespace OS { 6 | class SSLNetPeer : public INetPeer { 7 | public: 8 | SSLNetPeer(INetDriver* driver, uv_tcp_t *sd); 9 | virtual ~SSLNetPeer(); 10 | void InitSSL(void *ssl); 11 | void stream_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); 12 | void clear_send_buffer(); 13 | void ssl_flush(); 14 | private: 15 | SSL *mp_ssl; 16 | BIO *mp_write_bio; 17 | BIO *mp_read_bio; 18 | }; 19 | } 20 | #endif //_SSLPEER_H -------------------------------------------------------------------------------- /code/core/SSL/OpenSSL/SSL/SSLTCPDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _SSLDRIVER_H 2 | #define _SSLDRIVER_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace OS { 9 | void *GetSSLContext(); //retrieves the configured SSL context (void* = SSL_CTX*) 10 | class SSLTCPDriver : public TCPDriver { 11 | public: 12 | SSLTCPDriver(INetServer *server, const char *host, uint16_t port, void *ssl_ctx); 13 | virtual ~SSLTCPDriver(); 14 | void think(); 15 | protected: 16 | INetPeer *on_new_connection(uv_stream_t *server, int status); 17 | SSL_CTX *mp_ctx; 18 | }; 19 | } 20 | #endif // _SSLDRIVER_H -------------------------------------------------------------------------------- /code/core/SSL/OpenSSL/SSL/StringCrypter.cpp: -------------------------------------------------------------------------------- 1 | #include "StringCrypter.h" 2 | #include 3 | #include 4 | namespace OS { 5 | StringCrypter::StringCrypter(std::string PEM_privateKey_Path, std::string pemPassword) { 6 | FILE *fd = fopen(PEM_privateKey_Path.c_str(), "r+"); 7 | mp_rsa_key = PEM_read_RSAPrivateKey(fd, NULL, NULL, (void *)pemPassword.c_str()); 8 | fclose(fd); 9 | } 10 | 11 | StringCrypter::~StringCrypter() { 12 | RSA_free(mp_rsa_key); 13 | } 14 | std::string StringCrypter::encryptString(std::string input) { 15 | std::string ret; 16 | int mem_len = RSA_size(mp_rsa_key); 17 | unsigned char *buf = (unsigned char *)malloc(mem_len); 18 | RSA_public_encrypt(input.length() + 1, (const unsigned char *)input.c_str(), buf, mp_rsa_key, RSA_PKCS1_PADDING); 19 | const char *b64_str = OS::BinToBase64Str(buf, mem_len); 20 | ret = std::string(b64_str); 21 | free((void *)b64_str); 22 | free((void *)buf); 23 | return ret; 24 | } 25 | std::string StringCrypter::decryptString(std::string input) { 26 | std::string ret; 27 | uint8_t *b64_out; 28 | size_t out_len = 0; 29 | 30 | int mem_len = RSA_size(mp_rsa_key); 31 | unsigned char *buf = (unsigned char *)malloc(mem_len); 32 | 33 | OS::Base64StrToBin(input.c_str(), &b64_out, out_len); 34 | RSA_private_decrypt(out_len, b64_out, buf, mp_rsa_key, RSA_PKCS1_PADDING); 35 | ret = std::string((char *)buf); 36 | if (b64_out) 37 | free((void *)b64_out); 38 | 39 | if (buf) { 40 | free((void *)buf); 41 | } 42 | return ret; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /code/core/SSL/OpenSSL/SSL/StringCrypter.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRINGCRYPTER_H 2 | #define _STRINGCRYPTER_H 3 | #include 4 | #include 5 | namespace OS { 6 | class StringCrypter { 7 | public: 8 | StringCrypter(std::string PEM_privateKey_Path, std::string pemPassword = ""); 9 | ~StringCrypter(); 10 | std::string encryptString(std::string input); 11 | std::string decryptString(std::string input); 12 | private: 13 | RSA *mp_rsa_key; 14 | }; 15 | }; 16 | #endif //_STRINGCRYPTER_H -------------------------------------------------------------------------------- /code/core/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(core_test) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 8 | 9 | 10 | add_executable (test_buffer ${ALL_SRCS} OS/test_buffer.cpp) 11 | add_test(NAME test_buffer COMMAND test_buffer WORKING_DIRECTORY .) 12 | 13 | target_link_libraries(test_buffer openspy) -------------------------------------------------------------------------------- /code/core/test/OS/test_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | void test_buffer_overwrite_memory_buffer() { 4 | OS::Buffer buffer(1); 5 | char test_buff_len = 999256; 6 | char *test_buff = (char *)malloc(test_buff_len); 7 | for(int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "server/GSServer.h" 7 | #include "server/GSDriver.h" 8 | #include "server/tasks/tasks.h" 9 | INetServer *g_gameserver = NULL; 10 | 11 | void tick_handler(uv_timer_t* handle) { 12 | g_gameserver->tick(); 13 | } 14 | 15 | int main() { 16 | uv_loop_t *loop = uv_default_loop(); 17 | uv_timer_t tick_timer; 18 | 19 | uv_timer_init(uv_default_loop(), &tick_timer); 20 | 21 | OS::Init("gstats"); 22 | g_gameserver = new GS::Server(); 23 | 24 | char address_buff[256]; 25 | char port_buff[16]; 26 | size_t temp_env_sz = sizeof(address_buff); 27 | 28 | if(uv_os_getenv("OPENSPY_GSTATS_BIND_ADDR", (char *)&address_buff, &temp_env_sz) != UV_ENOENT) { 29 | temp_env_sz = sizeof(port_buff); 30 | 31 | uint16_t port = 29920; 32 | if(uv_os_getenv("OPENSPY_GSTATS_BIND_PORT", (char *)&port_buff, &temp_env_sz) != UV_ENOENT) { 33 | port = atoi(port_buff); 34 | } 35 | 36 | GS::Driver *driver = new GS::Driver(g_gameserver, address_buff, port); 37 | 38 | OS::LogText(OS::ELogLevel_Info, "Adding gstats Driver: %s:%d\n", address_buff, port); 39 | g_gameserver->addNetworkDriver(driver); 40 | } else { 41 | OS::LogText(OS::ELogLevel_Warning, "Missing gstats bind address environment variable"); 42 | } 43 | 44 | GS::InitTasks(); 45 | uv_timer_start(&tick_timer, tick_handler, 0, 250); 46 | 47 | uv_run(loop, UV_RUN_DEFAULT); 48 | 49 | uv_loop_close(loop); 50 | 51 | delete g_gameserver; 52 | 53 | OS::Shutdown(); 54 | 55 | return 0; 56 | } -------------------------------------------------------------------------------- /code/gamestats/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/gamestats/server/GSDriver.cpp: -------------------------------------------------------------------------------- 1 | #include "GSDriver.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #include "GSServer.h" 7 | #include "GSPeer.h" 8 | 9 | #include 10 | 11 | namespace GS { 12 | Driver::Driver(INetServer *server, const char *host, uint16_t port) : TCPDriver(server, host, port) { 13 | } 14 | Peer *Driver::FindPeerByProfileID(int profileid) { 15 | Peer* peer = (Peer *)GetPeerList()->GetHead(); 16 | if (peer != NULL) { 17 | do { 18 | if (peer->GetProfileID() == profileid) { 19 | return peer; 20 | } 21 | } while ((peer = (Peer*)peer->GetNext()) != NULL); 22 | } 23 | return NULL; 24 | } 25 | INetPeer *Driver::CreatePeer(uv_tcp_t *sd) { 26 | return new Peer(this, sd); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /code/gamestats/server/GSDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPDRIVER_H 2 | #define _GPDRIVER_H 3 | #include 4 | #include "../main.h" 5 | #include 6 | 7 | #include "GSPeer.h" 8 | 9 | #include 10 | #include 11 | #ifdef _WIN32 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | #define GP_PING_TIME (600) 18 | 19 | namespace GS { 20 | class Peer; 21 | class Driver; 22 | class Driver : public OS::TCPDriver { 23 | public: 24 | Driver(INetServer *server, const char *host, uint16_t port); 25 | Peer *FindPeerByProfileID(int profileid); 26 | protected: 27 | virtual INetPeer *CreatePeer(uv_tcp_t *sd); 28 | }; 29 | } 30 | #endif //_SBDRIVER_H -------------------------------------------------------------------------------- /code/gamestats/server/GSServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "GSPeer.h" 3 | #include "GSServer.h" 4 | #include "GSDriver.h" 5 | 6 | #include "tasks/tasks.h" 7 | 8 | namespace GS { 9 | Server::Server() : INetServer() { 10 | uv_loop_set_data(uv_default_loop(), this); 11 | } 12 | Server::~Server() { 13 | } 14 | 15 | void Server::tick() { 16 | std::vector::iterator it = m_net_drivers.begin(); 17 | while (it != m_net_drivers.end()) { 18 | INetDriver *driver = *it; 19 | driver->think(); 20 | it++; 21 | } 22 | NetworkTick(); 23 | maybe_dispatch_responses(); 24 | } 25 | } -------------------------------------------------------------------------------- /code/gamestats/server/GSServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPSERVER_H 2 | #define _GPSERVER_H 3 | #include 4 | #include 5 | namespace GS { 6 | class Server : public INetServer { 7 | public: 8 | Server(); 9 | ~Server(); 10 | void tick(); 11 | private: 12 | }; 13 | } 14 | #endif //_GPSERVER_H -------------------------------------------------------------------------------- /code/gamestats/server/tasks/GetGameInfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tasks.h" 3 | 4 | namespace GS { 5 | bool Perform_GetGameInfo(PersistBackendRequest request, TaskThreadData *thread_data) { 6 | OS::GameData game_info; 7 | PersistBackendResponse resp_data; 8 | game_info = OS::GetGameByName(request.game_instance_identifier.c_str(), thread_data->mp_redis_connection); 9 | resp_data.gameData = game_info; 10 | callback_dispatch_later(game_info.secretkey[0] != 0, resp_data, request.mp_peer, request.mp_extra, request.callback); 11 | return true; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /code/gamestats/server/tasks/NewGame.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | #include 5 | namespace GS { 6 | bool Perform_NewGame(PersistBackendRequest request, TaskThreadData *thread_data) { 7 | json_t *send_json = json_object(), *profile_obj = json_object(), *game_obj = json_object(); 8 | 9 | json_object_set_new(profile_obj, "id", json_integer(request.profileid)); 10 | json_object_set_new(game_obj, "id", json_integer(request.mp_peer->GetGame().gameid)); 11 | 12 | json_object_set_new(send_json, "profileLookup", profile_obj); 13 | json_object_set_new(send_json, "gameLookup", game_obj); 14 | 15 | std::string url = std::string(OS::g_webServicesURL); 16 | 17 | url += "/v1/Persist/Storage/NewGame"; 18 | 19 | OS::HTTPClient client(url); 20 | PersistBackendResponse resp_data; 21 | 22 | char *json_data = json_dumps(send_json, 0); 23 | 24 | OS::HTTPResponse resp = client.Put(json_data, request.mp_peer); 25 | 26 | free(json_data); 27 | json_decref(send_json); 28 | 29 | send_json = json_loads(resp.buffer.c_str(), 0, NULL); 30 | 31 | bool success = false; 32 | 33 | json_t *success_obj = json_object_get(send_json, "_id"); 34 | if (success_obj) { 35 | success = true; 36 | resp_data.game_instance_identifier = json_string_value(success_obj); 37 | } 38 | callback_dispatch_later(success, resp_data, request.mp_peer, request.mp_extra, request.callback); 39 | 40 | json_decref(send_json); 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /code/gamestats/server/tasks/PreAuth.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | #include 5 | namespace GS { 6 | bool Perform_AuthTokenAuth(PersistBackendRequest request, TaskThreadData *thread_data) { 7 | json_t *send_json = json_object(); 8 | 9 | json_object_set_new(send_json, "client_response", json_string(request.game_instance_identifier.c_str())); 10 | json_object_set_new(send_json, "auth_token", json_string(request.auth_token.c_str())); 11 | 12 | json_object_set_new(send_json, "session_key", json_integer(request.modified_since)); 13 | 14 | std::string url = std::string(OS::g_webServicesURL) + "/v1/Persist/Auth/PreAuth"; 15 | 16 | OS::HTTPClient client(url); 17 | PersistBackendResponse resp_data; 18 | 19 | char *json_data = json_dumps(send_json, 0); 20 | 21 | OS::HTTPResponse resp = client.Post(json_data, request.mp_peer); 22 | 23 | free(json_data); 24 | json_decref(send_json); 25 | 26 | send_json = json_loads(resp.buffer.c_str(), 0, NULL); 27 | 28 | bool success = false; 29 | json_t *profile; 30 | OS::Profile auth_profile; 31 | OS::User auth_user; 32 | TaskShared::AuthData auth_data; 33 | if (TaskShared::Handle_WebError(send_json, auth_data.error_details)) { 34 | } 35 | else { 36 | success = true; 37 | profile = json_object_get(send_json, "profile"); 38 | if (profile) { 39 | auth_profile = OS::LoadProfileFromJson(profile); 40 | } 41 | 42 | profile = json_object_get(send_json, "user"); 43 | if (profile) { 44 | auth_user = OS::LoadUserFromJson(profile); 45 | } 46 | } 47 | authcallback_dispatch_later(success, auth_user, auth_profile, auth_data, request.mp_extra, request.mp_peer, request.authCallback); 48 | json_decref(send_json); 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /code/natneg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(natneg) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | file (GLOB MAIN_SRCS "*.cpp") 8 | file (GLOB MAIN_HDRS "*.h") 9 | file (GLOB SERVER_SRCS "server/*.cpp") 10 | file (GLOB SERVER_HDRS "server/*.h") 11 | 12 | file (GLOB TASKS_HDRS "tasks/*.h") 13 | file (GLOB TASKS_SRCS "tasks/*.cpp") 14 | 15 | file (GLOB HANDLERS_HDRS "server/handlers/*.h") 16 | file (GLOB HANDLERS_SRCS "server/handlers/*.cpp") 17 | 18 | 19 | set (ALL_SRCS ${MAIN_SRCS} ${MAIN_HDRS} ${SERVER_SRCS} ${SERVER_HDRS} ${TASKS_SRCS} ${TASKS_HDRS} ${HANDLERS_SRCS} ${HANDLERS_HDRS}) 20 | 21 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 22 | 23 | source_group("Sources" FILES ${MAIN_SRCS}) 24 | source_group("Sources\\Server" FILES ${SERVER_SRCS}) 25 | 26 | source_group("Headers" FILES ${MAIN_HDRS}) 27 | source_group("Headers\\Server" FILES ${SERVER_HDRS}) 28 | 29 | 30 | add_executable (natneg ${ALL_SRCS}) 31 | 32 | target_compile_features(natneg PRIVATE cxx_unrestricted_unions) 33 | 34 | IF(WIN32) 35 | target_link_libraries(natneg openspy.lib SharedTasks ZLIB::ZLIB) 36 | ELSE() #unix 37 | target_link_libraries(natneg openspy SharedTasks ZLIB::ZLIB) 38 | ENDIF() -------------------------------------------------------------------------------- /code/natneg/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "server/NNServer.h" 7 | #include "server/NNDriver.h" 8 | INetServer *g_gameserver = NULL; 9 | 10 | 11 | void tick_handler(uv_timer_t* handle) { 12 | g_gameserver->tick(); 13 | } 14 | 15 | int main() { 16 | uv_loop_t *loop = uv_default_loop(); 17 | uv_timer_t tick_timer; 18 | 19 | uv_timer_init(uv_default_loop(), &tick_timer); 20 | 21 | OS::Init("natneg"); 22 | 23 | g_gameserver = new NN::Server(); 24 | 25 | char address_buff[256]; 26 | char port_buff[16]; 27 | size_t temp_env_sz = sizeof(address_buff); 28 | 29 | if(uv_os_getenv("OPENSPY_NATNEG_BIND_ADDR", (char *)&address_buff, &temp_env_sz) != UV_ENOENT) { 30 | temp_env_sz = sizeof(port_buff); 31 | 32 | uint16_t port = 27901; 33 | if(uv_os_getenv("OPENSPY_NATNEG_BIND_PORT", (char *)&port_buff, &temp_env_sz) != UV_ENOENT) { 34 | port = atoi(port_buff); 35 | } 36 | 37 | NN::Driver *driver = new NN::Driver(g_gameserver, address_buff, port); 38 | 39 | OS::LogText(OS::ELogLevel_Info, "Adding natneg Driver: %s:%d\n", address_buff, port); 40 | g_gameserver->addNetworkDriver(driver); 41 | } else { 42 | OS::LogText(OS::ELogLevel_Warning, "Missing natneg bind address environment variable"); 43 | } 44 | 45 | uv_timer_start(&tick_timer, tick_handler, 0, 250); 46 | uv_run(loop, UV_RUN_DEFAULT); 47 | 48 | uv_loop_close(loop); 49 | 50 | delete g_gameserver; 51 | OS::Shutdown(); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /code/natneg/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/natneg/server/NATMapper.h: -------------------------------------------------------------------------------- 1 | #ifndef _NAT_MAPPER_H 2 | #define _NAT_MAPPER_H 3 | #include 4 | #include "structs.h" 5 | 6 | namespace NN { 7 | 8 | bool DetermineNatType(NAT &nat); 9 | void DetermineNextAddress(NAT &nat, OS::Address &next_public_address, OS::Address &next_private_address); 10 | void LoadSummaryIntoNAT(NN::ConnectionSummary summary, NAT &nat); 11 | const char *GetNatMappingSchemeString(NAT nat); 12 | } 13 | #endif //_NAT_MAPPER_H -------------------------------------------------------------------------------- /code/natneg/server/NNServer.cpp: -------------------------------------------------------------------------------- 1 | #include "NNServer.h" 2 | #include "NNDriver.h" 3 | #include 4 | #include 5 | namespace NN { 6 | 7 | Server::Server() : INetServer() { 8 | uv_loop_set_data(uv_default_loop(), this); 9 | InitTasks(); 10 | } 11 | Server::~Server() { 12 | } 13 | void Server::tick() { 14 | std::vector::iterator it = m_net_drivers.begin(); 15 | while (it != m_net_drivers.end()) { 16 | INetDriver *driver = *it; 17 | driver->think(); 18 | it++; 19 | } 20 | NetworkTick(); 21 | } 22 | NN::Driver *Server::findDriverByAddress(OS::Address address) { 23 | std::vector::iterator it = m_net_drivers.begin(); 24 | while (it != m_net_drivers.end()) { 25 | INetDriver *driver = *it; 26 | if(OS::Address(driver->GetAddress()) == address) { 27 | return (NN::Driver *)driver; 28 | } 29 | it++; 30 | } 31 | return NULL; 32 | } 33 | } -------------------------------------------------------------------------------- /code/natneg/server/NNServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _QRSERVER_H 2 | #define _QRSERVER_H 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "structs.h" 10 | 11 | #define NATNEG_PORT 27901 12 | namespace NN { 13 | class Driver; 14 | class Server : public INetServer { 15 | public: 16 | Server(); 17 | virtual ~Server(); 18 | void tick(); 19 | NN::Driver *findDriverByAddress(OS::Address address); 20 | private: 21 | }; 22 | } 23 | #endif //_CHCGAMESERVER_H -------------------------------------------------------------------------------- /code/natneg/server/handlers/handle_address_check.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../NNServer.h" 5 | #include "../../tasks/tasks.h" 6 | 7 | #include "../NNDriver.h" 8 | 9 | #include 10 | 11 | namespace NN { 12 | void Driver::handle_address_check_packet(OS::Address from, NatNegPacket *packet) { 13 | packet->packettype = NN_ADDRESS_REPLY; 14 | packet->Packet.Init.localip = from.GetInAddr().sin_addr.s_addr; 15 | packet->Packet.Init.localport = from.GetInAddr().sin_port; 16 | SendPacket(from, packet); 17 | OS::LogText(OS::ELogLevel_Info, "[%s] Got address check - version: %d, client idx: %d, cookie: %d, porttype: %d", from.ToString().c_str(), packet->version, packet->Packet.Init.clientindex, ntohl(packet->cookie), packet->Packet.Init.porttype); 18 | } 19 | } -------------------------------------------------------------------------------- /code/natneg/server/handlers/handle_preinit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../NNServer.h" 5 | #include "../../tasks/tasks.h" 6 | 7 | #include "../NNDriver.h" 8 | 9 | #include 10 | 11 | namespace NN { 12 | void Driver::handle_preinit_packet(OS::Address from, NatNegPacket *packet) { 13 | OS::Address private_address = OS::Address(packet->Packet.Init.localip, ntohs(packet->Packet.Init.localport)); 14 | OS::LogText(OS::ELogLevel_Info, "[%s] Got pre-init - version: %d, client idx: %d, cookie: %d, porttype: %d, use_gameport: %d, private: %s, game: %s", from.ToString().c_str(), packet->version, packet->Packet.Init.clientindex, ntohl(packet->cookie), packet->Packet.Init.porttype, packet->Packet.Init.usegameport, private_address.ToString().c_str()); 15 | packet->packettype = NN_PREINIT_ACK; 16 | packet->Packet.Preinit.state = NN_PREINIT_READY; 17 | SendPacket(from, packet); 18 | } 19 | 20 | void Driver::send_preinit_ack(OS::Address from, NatNegPacket *packet) { 21 | OS::LogText(OS::ELogLevel_Info, "[%s] Send Pre-init ack", from.ToString().c_str()); 22 | SendPacket(from, packet); 23 | } 24 | } -------------------------------------------------------------------------------- /code/natneg/server/handlers/handle_report.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../NNServer.h" 5 | #include "../../tasks/tasks.h" 6 | 7 | #include "../NNDriver.h" 8 | 9 | #include 10 | 11 | namespace NN { 12 | void Driver::handle_report_packet(OS::Address from, NatNegPacket *packet) { 13 | OS::LogText(OS::ELogLevel_Info, "[%s] Got report- client idx: %d, cookie: %d, game: %s, port type: %d, neg result: %d, neg type: %d, nat mapping scheme: %d", from.ToString().c_str(), packet->Packet.Report.clientindex, packet->cookie, packet->Packet.Report.gamename, packet->Packet.Report.porttype, packet->Packet.Report.negResult, packet->Packet.Report.natType, packet->Packet.Report.natMappingScheme); 14 | packet->packettype = NN_REPORT_ACK; 15 | SendPacket(from, packet); 16 | } 17 | void Driver::send_report_ack(OS::Address to_address, NatNegPacket *packet) { 18 | OS::LogText(OS::ELogLevel_Info, "[%s] Send Report ack", to_address.ToString().c_str()); 19 | SendPacket(to_address, packet); 20 | } 21 | } -------------------------------------------------------------------------------- /code/natneg/tasks/SubmitJson.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "tasks.h" 6 | 7 | #include 8 | 9 | namespace NN { 10 | bool PerformSubmitJson(NNRequestData request) { 11 | TaskShared::sendAMQPMessage(nn_channel_exchange, "natneg.core", request.send_string.c_str()); 12 | return true; 13 | } 14 | } -------------------------------------------------------------------------------- /code/natneg/tasks/tasks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "tasks.h" 7 | 8 | #include 9 | namespace NN { 10 | const char *nn_channel_exchange = "openspy.natneg", *nn_channel_routingkey="natneg.endpoint"; 11 | 12 | TaskShared::ListenerEventHandler nn_msg_handler = {nn_channel_exchange, nn_channel_routingkey, Handle_HandleRecvMessage}; 13 | TaskShared::ListenerEventHandler all_events[] = {nn_msg_handler}; 14 | TaskShared::ListenerArgs consume_nn_message = {all_events, sizeof(all_events) / sizeof(TaskShared::ListenerEventHandler)}; 15 | 16 | void InitTasks() { 17 | setup_listener(&consume_nn_message); 18 | } 19 | 20 | 21 | void PerformUVWorkRequest(uv_work_t *req) { 22 | NNRequestData *request = (NNRequestData *) uv_handle_get_data((uv_handle_t*) req); 23 | 24 | switch(request->type) { 25 | case ENNRequestType_SubmitJson: 26 | PerformSubmitJson(*request); 27 | break; 28 | } 29 | } 30 | void PerformUVWorkRequestCleanup(uv_work_t *req, int status) { 31 | NNRequestData *work_data = (NNRequestData *) uv_handle_get_data((uv_handle_t*) req); 32 | delete work_data; 33 | free((void *)req); 34 | } 35 | } -------------------------------------------------------------------------------- /code/natneg/tasks/tasks.h: -------------------------------------------------------------------------------- 1 | #ifndef _NN_TASKS_H 2 | #define _NN_TASKS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #define NN_REDIS_EXPIRE_TIME 500 12 | 13 | using namespace TaskShared; 14 | 15 | NN::ConnectionSummary LoadConnectionSummary(std::string redis_key); 16 | namespace NN { 17 | class Server; 18 | class Peer; 19 | enum ENNRequestType { 20 | ENNRequestType_SubmitJson 21 | }; 22 | class NNRequestData { 23 | public: 24 | std::string send_string; 25 | ENNRequestType type; 26 | }; 27 | extern const char *nn_channel_exchange; 28 | extern const char *nn_channel_routingkey; 29 | 30 | bool PerformSubmitJson(NNRequestData); 31 | 32 | void PerformUVWorkRequest(uv_work_t *req); 33 | void PerformUVWorkRequestCleanup(uv_work_t *req, int status); 34 | 35 | bool Handle_HandleRecvMessage(TaskShared::TaskThreadData *thread_data, std::string message); 36 | void InitTasks(); 37 | } 38 | #endif // _NN_TASKS_H 39 | -------------------------------------------------------------------------------- /code/peerchat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(peerchat) 4 | find_package(SSL) 5 | 6 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 7 | 8 | file (GLOB MAIN_SRCS "*.cpp") 9 | file (GLOB MAIN_HDRS "*.h") 10 | file (GLOB SERVER_SRCS "server/*.cpp") 11 | file (GLOB SERVER_HDRS "server/*.h") 12 | file (GLOB SERVER_TASKS_SRCS "tasks/*.cpp") 13 | file (GLOB SERVER_TASKS_HDRS "tasks/*.h") 14 | file (GLOB SERVER_CMDS_SRCS "server/commands/*.cpp") 15 | file (GLOB SERVER_CMDS_HDRS "server/commands/*.h") 16 | 17 | 18 | set (ALL_SRCS ${MAIN_SRCS} ${MAIN_HDRS} ${SERVER_SRCS} ${SERVER_HDRS} ${SERVER_CMDS_SRCS} ${SERVER_CMDS_HDRS} ${SERVER_TASKS_SRCS} ${SERVER_TASKS_HDRS}) 19 | 20 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${SSL_OS_INC} ${SSL_INCS}) 21 | 22 | source_group("Sources" FILES ${MAIN_SRCS}) 23 | source_group("Sources\\Server" FILES ${SERVER_SRCS}) 24 | source_group("Sources\\Server\\Tasks" FILES ${SERVER_TASKS_SRCS}) 25 | source_group("Sources\\Server\\Commands" FILES ${SERVER_CMDS_SRCS}) 26 | 27 | source_group("Headers" FILES ${MAIN_HDRS}) 28 | source_group("Headers\\Server" FILES ${SERVER_HDRS}) 29 | source_group("Headers\\Server\\Tasks" FILES ${SERVER_TASKS_HDRS}) 30 | source_group("Headers\\Server\\Commands" FILES ${SERVER_CMDS_HDRS}) 31 | 32 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 33 | 34 | 35 | add_executable (peerchat ${ALL_SRCS}) 36 | 37 | IF(WIN32) 38 | target_link_libraries(peerchat openspy.lib SharedTasks.lib ZLIB::ZLIB) 39 | ELSE() #unix 40 | target_link_libraries(peerchat openspy SharedTasks ZLIB::ZLIB) 41 | ENDIF() -------------------------------------------------------------------------------- /code/peerchat/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/peerchat/match.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int match2(const char *mask, const char *name) 4 | { 5 | const unsigned char *m = (unsigned char *)mask; 6 | const unsigned char *n = (unsigned char *)name; 7 | const unsigned char *ma = NULL; 8 | const unsigned char *na = (unsigned char *)name; 9 | 10 | while(1) 11 | { 12 | if (*m == '*') 13 | { 14 | while (*m == '*') /* collapse.. */ 15 | m++; 16 | ma = m; 17 | na = n; 18 | } 19 | 20 | if (!*m) 21 | { 22 | if (!*n) 23 | return 0; 24 | if (!ma) 25 | return 1; 26 | for (m--; (m > (const unsigned char *)mask) && (*m == '?'); m--); 27 | if (*m == '*') 28 | return 0; 29 | m = ma; 30 | n = ++na; 31 | } else 32 | if (!*n) 33 | { 34 | while (*m == '*') /* collapse.. */ 35 | m++; 36 | return (*m != 0); 37 | } 38 | 39 | if ((tolower(*m) != tolower(*n)) && !((*m == '_') && (*n == ' ')) && (*m != '?')) 40 | { 41 | if (!ma) 42 | return 1; 43 | m = ma; 44 | n = ++na; 45 | } else 46 | { 47 | m++; 48 | n++; 49 | } 50 | } 51 | return 1; 52 | } 53 | int match(const char *mask, const char *name) { 54 | if (mask[0] == '*' && mask[1] == '!') { 55 | mask += 2; 56 | while (*name != '!' && *name) 57 | name++; 58 | if (!*name) 59 | return 1; 60 | name++; 61 | } 62 | 63 | if (mask[0] == '*' && mask[1] == '@') { 64 | mask += 2; 65 | while (*name != '@' && *name) 66 | name++; 67 | if (!*name) 68 | return 1; 69 | name++; 70 | } 71 | return match2(mask,name); 72 | } -------------------------------------------------------------------------------- /code/peerchat/server/Server.h: -------------------------------------------------------------------------------- 1 | #ifndef _PEERCHATSERVER_H 2 | #define _PEERCHATSERVER_H 3 | #include 4 | #include 5 | #include 6 | 7 | int match(const char* mask, const char* name); 8 | int match2(const char* mask, const char* name); 9 | namespace Peerchat { 10 | class Server : public INetServer { 11 | public: 12 | Server(); 13 | ~Server(); 14 | void tick(); 15 | std::string getServerName() { return "s"; }; 16 | INetPeer *findPeerByProfile(int profile_id, bool inc_ref = true); 17 | 18 | void OnUserMessage(std::string type, UserSummary from, UserSummary to, std::string message); 19 | void OnChannelMessage(std::string type, ChannelUserSummary from, ChannelSummary channel, std::string message, ChannelUserSummary target, bool includeSelf, int requiredChanFlags, int requiredOperFlags, int onlyVisibleTo); 20 | 21 | //send 1 time message to anyone who is in a at least 1 channel with a user 22 | void OnChannelBroadcast(std::string type, UserSummary target, std::map channel_list, std::string message, bool includeSelf); 23 | void OnSetUserChannelKeys(ChannelSummary summary, UserSummary user_summary, OS::KVReader keys); 24 | void OnSetChannelKeys(ChannelSummary summary, OS::KVReader keys); 25 | 26 | void OnUpdateChanUsermode(int channel_id, UserSummary user_summary, int new_modeflags); 27 | 28 | void OnKillUser(UserSummary user_summary, std::string reason); 29 | 30 | private: 31 | }; 32 | } 33 | #endif //_GPSERVER_H -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_cdkey.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::handle_cdkey(std::vector data_parser) { 18 | std::ostringstream ss; 19 | ss << 1 << " Success"; 20 | send_numeric(706, ss.str(), true); 21 | } 22 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_delchanprops.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnDelChanProps(TaskResponse response_data, Peer* peer) { 18 | if (response_data.error_details.response_code != TaskShared::WebErrorCode_Success) { 19 | ((Peer*)peer)->send_message("PRIVMSG", "Failed to delete chanprops", *server_userSummary, ((Peer*)peer)->m_user_details.nick); 20 | return; 21 | } 22 | } 23 | 24 | void Peer::handle_delchanprops(std::vector data_parser) { 25 | std::string chanmask = data_parser.at(1); 26 | 27 | PeerchatBackendRequest req; 28 | 29 | req.type = EPeerchatRequestType_DeleteChanProps; 30 | 31 | req.peer = this; 32 | 33 | ChanpropsRecord chanpropsRecord; 34 | chanpropsRecord.channel_mask = chanmask; 35 | req.chanpropsRecord = chanpropsRecord; 36 | 37 | req.peer->IncRef(); 38 | req.callback = OnDelChanProps; 39 | AddTaskRequest(req); 40 | 41 | } 42 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_delusermode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnDeleteUserMode(TaskResponse response_data, Peer* peer) { 18 | if (response_data.error_details.response_code == TaskShared::WebErrorCode_Success) { 19 | ((Peer*)peer)->send_message("PRIVMSG", "Usermode deleted", *server_userSummary, ((Peer*)peer)->m_user_details.nick); 20 | } 21 | else { 22 | ((Peer*)peer)->send_message("PRIVMSG", "Failed to delete usermode", *server_userSummary, ((Peer*)peer)->m_user_details.nick); 23 | } 24 | } 25 | 26 | void Peer::handle_delusermode(std::vector data_parser) { 27 | std::string usermodeid_string = data_parser.at(1); 28 | 29 | PeerchatBackendRequest req; 30 | 31 | req.type = EPeerchatRequestType_DeleteUserMode; 32 | req.peer = this; 33 | 34 | UsermodeRecord usermodeRecord; 35 | usermodeRecord.usermodeid = atoi(usermodeid_string.c_str()); 36 | usermodeRecord.setByUserSummary = GetUserDetails(); 37 | req.usermodeRecord = usermodeRecord; 38 | 39 | req.peer->IncRef(); 40 | req.callback = OnDeleteUserMode; 41 | AddTaskRequest(req); 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_kick.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnKickCallback(TaskResponse response_data, Peer* peer) { 18 | if (response_data.error_details.response_code == TaskShared::WebErrorCode_NoSuchUser) { 19 | peer->send_no_such_target_error(response_data.summary.nick); 20 | } 21 | } 22 | /* 23 | -> s KICK #test CHC :hello there 24 | <- :CHC!CHC@* KICK #test CHC :hello there 25 | */ 26 | void Peer::handle_kick(std::vector data_parser) { 27 | 28 | std::string channel_target = data_parser.at(1); 29 | std::string user_target = data_parser.at(2); 30 | 31 | std::string message = ""; 32 | if (data_parser.size() > 4) { 33 | message = data_parser.at(3); 34 | bool do_combine = false; 35 | if (message[0] == ':') { 36 | do_combine = true; 37 | message = message.substr(1); 38 | } 39 | 40 | if (do_combine) { 41 | for (size_t i = 4; i < data_parser.size(); i++) { 42 | message = message.append(" ").append(data_parser.at(i)); 43 | } 44 | } 45 | } 46 | 47 | PeerchatBackendRequest req; 48 | req.type = EPeerchatRequestType_UserKickChannel; 49 | req.peer = this; 50 | req.channel_summary.channel_name = channel_target; 51 | req.summary = GetUserDetails(); 52 | req.message_target = user_target; 53 | req.message = message; 54 | req.peer->IncRef(); 55 | req.callback = OnKickCallback; 56 | AddTaskRequest(req); 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_kill.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnKillUser(TaskResponse response_data, Peer* peer) { 18 | if(response_data.summary.id == 0) { 19 | peer->send_no_such_target_error(response_data.profile.uniquenick); 20 | } 21 | 22 | } 23 | void Peer::handle_kill(std::vector data_parser) { 24 | std::string target = data_parser.at(1); 25 | 26 | std::string message = data_parser.at(2); 27 | 28 | bool do_combine = false; 29 | if(message[0] == ':') { 30 | do_combine = true; 31 | message = message.substr(1); 32 | } 33 | 34 | if (do_combine) { 35 | for (size_t i = 3; i < data_parser.size(); i++) { 36 | message = message.append(" ").append(data_parser.at(i)); 37 | } 38 | } 39 | 40 | std::string reason = "KILLED by " + GetUserDetails().nick + ": " + message; 41 | 42 | PeerchatBackendRequest req; 43 | req.type = EPeerchatRequestType_RemoteKill_ByName; 44 | req.peer = this; 45 | req.summary.username = target; 46 | 47 | req.usermodeRecord.comment = reason; 48 | 49 | req.peer->IncRef(); 50 | req.callback = OnKillUser; 51 | AddTaskRequest(req); 52 | } 53 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_lusers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnFetch_LUsers(TaskResponse response_data, Peer* peer) { 18 | std::ostringstream s; 19 | s << "There are " << response_data.usermode.usermodeid << " users"; 20 | peer->send_numeric(251, s.str()); 21 | } 22 | void Peer::handle_lusers(std::vector data_parser) { 23 | PeerchatBackendRequest req; 24 | req.type = EPeerchatRequestType_CountServerUsers; 25 | req.peer = this; 26 | req.peer->IncRef(); 27 | req.callback = OnFetch_LUsers; 28 | AddTaskRequest(req); 29 | } 30 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_ping.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::handle_ping(std::vector data_parser) { 18 | std::string end = ""; 19 | if (data_parser.size() > 1) { 20 | end = data_parser.at(1); 21 | if (end[0] == ':') { 22 | end = end.substr(1); 23 | } 24 | } 25 | uv_clock_gettime(UV_CLOCK_MONOTONIC, &m_last_sent_ping); 26 | send_message("PONG", end, UserSummary(), ((Peerchat::Server*)GetDriver()->getServer())->getServerName()); 27 | 28 | perform_keepalive(); 29 | } 30 | void Peer::handle_pong(std::vector data_parser) { 31 | perform_keepalive(); 32 | } 33 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_registernick.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | namespace Peerchat { 16 | void Peer::m_registernick_callback(TaskShared::WebErrorDetails error_details, std::vector results, std::map result_users, void *extra, INetPeer *peer) { 17 | std::ostringstream s; 18 | if (error_details.response_code == TaskShared::WebErrorCode_Success) { 19 | return; 20 | } 21 | s << 0 << " " << "\\"; //XXX: lookup suggestions, no suggestions currently 22 | ((Peer *)peer)->send_numeric(711, s.str()); 23 | 24 | } 25 | void Peer::handle_registernick(std::vector data_parser) { 26 | TaskShared::ProfileRequest request; 27 | 28 | std::string uniquenick = data_parser.at(2); 29 | int namespaceid = atoi(data_parser.at(1).c_str()); 30 | request.profile_search_details = m_profile; 31 | request.profile_search_details.uniquenick = uniquenick; 32 | request.profile_search_details.namespaceid = namespaceid; 33 | request.peer = this; 34 | request.peer->IncRef(); 35 | request.type = TaskShared::EProfileSearch_UpdateProfile; 36 | request.callback = Peer::m_registernick_callback; 37 | AddProfileTaskRequest(request); 38 | } 39 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_setchankey.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnSetChanKey(TaskResponse response_data, Peer* peer) { 18 | 19 | } 20 | 21 | //SETCHANKEY #GSP!godzilla2ps2!M411DDDD3M :\hostname\CDEMMNP|6\roomready\1\pwprivate\25 22 | 23 | void Peer::handle_setchankey(std::vector data_parser) { 24 | std::string channel_target = data_parser.at(1); 25 | 26 | std::string kv_string = data_parser.at(2); 27 | bool do_combine = false; 28 | if (kv_string.length() > 1 && kv_string[0] == ':') { 29 | kv_string = kv_string.substr(1); 30 | do_combine = true; 31 | } 32 | if (do_combine) { 33 | for (size_t i = 3; i < data_parser.size(); i++) { 34 | kv_string = kv_string.append(" ").append(data_parser.at(i)); 35 | } 36 | } 37 | 38 | PeerchatBackendRequest req; 39 | req.type = EPeerchatRequestType_SetChannelKeys; 40 | req.peer = this; 41 | req.channel_summary.channel_name = channel_target; 42 | req.channel_modify.kv_data = kv_string; 43 | 44 | req.peer->IncRef(); 45 | req.callback = OnSetChanKey; 46 | AddTaskRequest(req); 47 | 48 | } 49 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_setckey.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnSetCKey(TaskResponse response_data, Peer* peer) { 18 | } 19 | 20 | void Peer::handle_setckey(std::vector data_parser) { 21 | std::string channel_target = data_parser.at(1); 22 | std::string user_target = data_parser.at(2); 23 | 24 | std::string kv_string = data_parser.at(3); 25 | bool do_combine = false; 26 | if (kv_string.length() > 1 && kv_string[0] == ':') { 27 | kv_string = kv_string.substr(1); 28 | do_combine = true; 29 | } 30 | if (do_combine) { 31 | for (size_t i = 6; i < data_parser.size(); i++) { 32 | kv_string = kv_string.append(" ").append(data_parser.at(i)); 33 | } 34 | } 35 | 36 | PeerchatBackendRequest req; 37 | req.type = EPeerchatRequestType_SetChannelUserKeys; 38 | req.peer = this; 39 | req.channel_summary.channel_name = channel_target; 40 | req.summary.username = user_target; 41 | req.channel_modify.kv_data = kv_string; 42 | 43 | req.peer->IncRef(); 44 | req.callback = OnSetCKey; 45 | AddTaskRequest(req); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_setgroup.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnSetGroup(TaskResponse response_data, Peer* peer) { 18 | } 19 | 20 | void Peer::handle_setgroup(std::vector data_parser) { 21 | std::string channel_target = data_parser.at(1); 22 | std::string group = data_parser.at(2); 23 | 24 | std::ostringstream s; 25 | s << "\\groupname\\" << group; 26 | std::string kv_string = s.str(); 27 | 28 | PeerchatBackendRequest req; 29 | req.type = EPeerchatRequestType_SetChannelKeys; 30 | req.peer = this; 31 | req.channel_summary.channel_name = channel_target; 32 | req.channel_modify.kv_data = kv_string; 33 | 34 | req.peer->IncRef(); 35 | req.callback = OnSetGroup; 36 | AddTaskRequest(req); 37 | } 38 | } -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_setkey.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::OnSetKey(TaskResponse response_data, Peer* peer) { 18 | 19 | } 20 | 21 | //SETKEY :\test\1 22 | void Peer::handle_setkey(std::vector data_parser) { 23 | std::string kv_string = data_parser.at(1); 24 | if (kv_string.length() > 1 && kv_string[0] == ':') { 25 | kv_string = kv_string.substr(1); 26 | } 27 | 28 | PeerchatBackendRequest req; 29 | req.type = EPeerchatRequestType_SetUserKeys; 30 | req.peer = this; 31 | req.summary.username = GetUserDetails().nick; 32 | req.channel_modify.kv_data = kv_string; 33 | 34 | req.peer->IncRef(); 35 | req.callback = OnSetKey; 36 | AddTaskRequest(req); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /code/peerchat/server/commands/handle_user.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Peerchat { 17 | void Peer::handle_user(std::vector data_parser) { 18 | 19 | std::string username, realname; 20 | 21 | username = data_parser.at(1); 22 | realname = data_parser.at(4); 23 | if(realname.length() > 1 && realname.at(0) == ':') { 24 | realname = realname.substr(1); 25 | } 26 | 27 | if(is_nick_valid(username.c_str()) == 0) { 28 | send_numeric(468, "Erroneous User", false, username); 29 | return; 30 | } 31 | if(is_nick_valid(realname.c_str()) == 0) { 32 | send_numeric(468, "Erroneous Realname", false, realname); 33 | return; 34 | } 35 | 36 | m_user_details.username = username; 37 | m_user_details.realname = realname; 38 | 39 | OnUserMaybeRegistered(); 40 | } 41 | } -------------------------------------------------------------------------------- /code/peerchat/server/irc_common.h: -------------------------------------------------------------------------------- 1 | int is_nick_valid(const char *nick); 2 | int is_chan_valid(const char *nick); -------------------------------------------------------------------------------- /code/peerchat/tasks/Perform_CountServerUsers.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | namespace Peerchat { 8 | 9 | bool Perform_CountServerUsers(PeerchatBackendRequest request, TaskThreadData* thread_data) { 10 | TaskResponse response; 11 | response.usermode.usermodeid = CountServerUsers(thread_data); 12 | if (request.callback) { 13 | request.callback(response, request.peer); 14 | } 15 | 16 | if (request.peer) { 17 | request.peer->DecRef(); 18 | } 19 | return true; 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /code/peerchat/tasks/Perform_DelChanProps.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | namespace Peerchat { 8 | 9 | bool Perform_DelChanprops(PeerchatBackendRequest request, TaskThreadData* thread_data) { 10 | json_t* send_json = json_object(); 11 | json_object_set_new(send_json, "channelmask", json_string(request.chanpropsRecord.channel_mask.c_str())); 12 | 13 | std::string url = std::string(OS::g_webServicesURL) + "/v1/Chanprops"; 14 | 15 | OS::HTTPClient client(url); 16 | 17 | char* json_data = json_dumps(send_json, 0); 18 | 19 | OS::HTTPResponse resp = client.Delete(json_data, request.peer); 20 | 21 | free(json_data); 22 | json_decref(send_json); 23 | 24 | send_json = json_loads(resp.buffer.c_str(), 0, NULL); 25 | 26 | TaskResponse response; 27 | 28 | TaskShared::Handle_WebError(send_json, response.error_details); 29 | if (request.callback) { 30 | request.callback(response, request.peer); 31 | } 32 | 33 | if(send_json) { 34 | json_decref(send_json); 35 | } 36 | 37 | if (request.peer) { 38 | request.peer->DecRef(); 39 | } 40 | return true; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /code/peerchat/tasks/Perform_DeleteUsermode.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | #include 5 | namespace Peerchat { 6 | bool Perform_DeleteUsermode(PeerchatBackendRequest request, TaskThreadData* thread_data) { 7 | json_t* send_json = json_object(); 8 | json_object_set_new(send_json, "id", json_integer(request.usermodeRecord.usermodeid)); 9 | 10 | std::string url = std::string(OS::g_webServicesURL) + "/v1/Usermode"; 11 | 12 | OS::HTTPClient client(url); 13 | 14 | char* json_data = json_dumps(send_json, 0); 15 | 16 | OS::HTTPResponse resp = client.Delete(json_data, request.peer); 17 | 18 | free(json_data); 19 | json_decref(send_json); 20 | 21 | send_json = json_loads(resp.buffer.c_str(), 0, NULL); 22 | 23 | bool success = false; 24 | 25 | TaskResponse response; 26 | if (!TaskShared::Handle_WebError(send_json, response.error_details)) { 27 | if (send_json) { 28 | json_t* success_obj = json_object_get(send_json, "success"); 29 | if (success_obj) { 30 | success = success_obj == json_true(); 31 | } 32 | if (!success) { 33 | response.error_details.response_code = TaskShared::WebErrorCode_NoSuchUser; 34 | } 35 | } 36 | } 37 | 38 | if(send_json) 39 | json_decref(send_json); 40 | 41 | if (request.callback) 42 | request.callback(response, request.peer); 43 | 44 | if (request.peer) 45 | request.peer->DecRef(); 46 | return true; 47 | 48 | } 49 | } -------------------------------------------------------------------------------- /code/peerchat/tasks/Perform_LookupChannelDetails.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | 5 | namespace Peerchat { 6 | 7 | bool Perform_LookupChannelDetails(PeerchatBackendRequest request, TaskThreadData *thread_data) { 8 | TaskResponse response; 9 | ChannelSummary summary; 10 | if(request.channel_summary.channel_id != 0) { 11 | summary = LookupChannelById(thread_data, request.channel_summary.channel_id); 12 | } else { 13 | summary = GetChannelSummaryByName(thread_data, request.channel_summary.channel_name, false); 14 | } 15 | 16 | if (summary.channel_id != 0) { 17 | response.error_details.response_code = TaskShared::WebErrorCode_Success; 18 | } 19 | else { 20 | response.error_details.response_code = TaskShared::WebErrorCode_NoSuchUser; 21 | } 22 | 23 | response.profile.uniquenick = request.channel_summary.channel_name; 24 | response.channel_summary = summary; 25 | if (request.callback) { 26 | request.callback(response, request.peer); 27 | } 28 | if (request.peer) { 29 | request.peer->DecRef(); 30 | } 31 | return true; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /code/peerchat/tasks/Perform_LookupGameInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | 5 | namespace Peerchat { 6 | bool Perform_LookupGameInfo(PeerchatBackendRequest request, TaskThreadData* thread_data) { 7 | OS::GameData game_info; 8 | game_info = OS::GetGameByName(request.gamename.c_str(), thread_data->mp_redis_connection); 9 | 10 | 11 | TaskResponse response; 12 | response.game_data = game_info; 13 | 14 | if (request.callback) { 15 | request.callback(response, request.peer); 16 | } 17 | if (request.peer) { 18 | request.peer->DecRef(); 19 | } 20 | return true; 21 | } 22 | } -------------------------------------------------------------------------------- /code/peerchat/tasks/Perform_OperCheck.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | namespace Peerchat { 8 | 9 | bool Perform_OperCheck(PeerchatBackendRequest request, TaskThreadData* thread_data) { 10 | json_t* send_json = json_object(); 11 | json_object_set_new(send_json, "profileid", json_integer(request.profile.id)); 12 | 13 | std::string url = std::string(OS::g_webServicesURL) + "/v1/GlobalOpers/lookup"; 14 | 15 | OS::HTTPClient client(url); 16 | 17 | char* json_data = json_dumps(send_json, 0); 18 | 19 | OS::HTTPResponse resp = client.Post(json_data, request.peer); 20 | 21 | free(json_data); 22 | json_decref(send_json); 23 | 24 | send_json = json_loads(resp.buffer.c_str(), 0, NULL); 25 | 26 | TaskResponse response; 27 | 28 | if (TaskShared::Handle_WebError(send_json, response.error_details)) { 29 | if (request.callback) 30 | request.callback(response, request.peer); 31 | } 32 | else { 33 | int operflags = 0; 34 | int num_items = json_array_size(send_json); 35 | for (int i = 0; i < num_items; i++) { 36 | json_t* item = json_array_get(send_json, i); 37 | 38 | json_t *operflags_item = json_object_get(item, "operflags"); 39 | if(operflags_item != NULL) { 40 | operflags |= json_integer_value(operflags_item); 41 | } 42 | 43 | } 44 | 45 | response.channel_summary.basic_mode_flags = operflags; 46 | 47 | if (request.callback) 48 | request.callback(response, request.peer); 49 | 50 | } 51 | 52 | if(send_json) 53 | json_decref(send_json); 54 | 55 | if (request.peer) 56 | request.peer->DecRef(); 57 | return true; 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /code/peerchat/tasks/Perform_RemoteKill_ByName.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | #include 5 | namespace Peerchat { 6 | 7 | bool Perform_RemoteKill_ByName(PeerchatBackendRequest request, TaskThreadData* thread_data) { 8 | TaskResponse response; 9 | 10 | UserSummary summary = GetUserSummaryByName(thread_data, request.summary.username); 11 | response.summary = summary; 12 | 13 | const char* base64 = OS::BinToBase64Str((uint8_t*)request.usermodeRecord.comment.c_str(), request.usermodeRecord.comment.length()); 14 | 15 | std::ostringstream message; 16 | 17 | message << "\\type\\REMOTE_KILL\\user_id\\" << summary.id << "\\reason\\" << base64; 18 | 19 | free((void*)base64); 20 | sendAMQPMessage(peerchat_channel_exchange, peerchat_key_updates_routingkey, message.str().c_str()); 21 | 22 | response.profile.uniquenick = request.summary.username; 23 | response.error_details.response_code = TaskShared::WebErrorCode_Success; 24 | 25 | if (request.callback) 26 | request.callback(response, request.peer); 27 | if (request.peer) 28 | request.peer->DecRef(); 29 | return true; 30 | } 31 | } -------------------------------------------------------------------------------- /code/peerchat/tasks/Perform_UpdateUserModes.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | #include 3 | #include 4 | 5 | namespace Peerchat { 6 | bool Perform_UpdateUserModes(PeerchatBackendRequest request, TaskThreadData *thread_data) { 7 | TaskResponse response; 8 | UserSummary summary = LookupUserById(thread_data, request.peer->GetBackendId()); 9 | for (int i = 0; i < num_user_mode_flags; i++) { 10 | if (request.channel_modify.set_mode_flags & user_mode_flag_map[i].flag) { 11 | if (~summary.modeflags & user_mode_flag_map[i].flag) { 12 | summary.modeflags |= user_mode_flag_map[i].flag; 13 | } 14 | } 15 | if (request.channel_modify.unset_mode_flags & user_mode_flag_map[i].flag) { 16 | if (summary.modeflags & user_mode_flag_map[i].flag) { 17 | summary.modeflags &= ~user_mode_flag_map[i].flag; 18 | } 19 | } 20 | } 21 | 22 | void *reply; 23 | std::ostringstream ss; 24 | ss << "user_" << summary.id; 25 | std::string user_key = ss.str(); 26 | 27 | reply = redisCommand(thread_data->mp_redis_connection, "HSET %s modeflags %d", user_key.c_str(), summary.modeflags); 28 | 29 | freeReplyObject(reply); 30 | 31 | response.error_details.response_code = TaskShared::WebErrorCode_Success; 32 | 33 | response.summary = summary; 34 | 35 | if (request.callback) { 36 | request.callback(response, request.peer); 37 | } 38 | if (request.peer) { 39 | request.peer->DecRef(); 40 | } 41 | return true; 42 | } 43 | } -------------------------------------------------------------------------------- /code/qr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(qr) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | file (GLOB MAIN_SRCS "*.cpp") 8 | file (GLOB MAIN_HDRS "*.h") 9 | file (GLOB SERVER_SRCS "server/*.cpp") 10 | file (GLOB SERVER_HDRS "server/*.h") 11 | 12 | file (GLOB V2_SERVER_SRCS "server/v2/*.cpp") 13 | file (GLOB V2_SERVER_HDRS "server/v2/*.h") 14 | file (GLOB V1_SERVER_SRCS "server/v1/*.cpp") 15 | file (GLOB V1_SERVER_HDRS "server/v1/*.h") 16 | 17 | file (GLOB TASKS_SRCS "tasks/*.cpp") 18 | file (GLOB TASKS_HDRS "tasks/*.h") 19 | 20 | 21 | set (ALL_SRCS ${SERVER_SRCS} ${SERVER_HDRS} ${V2_SERVER_SRCS} ${V2_SERVER_HDRS} ${V1_SERVER_SRCS} ${V1_SERVER_HDRS} ${TASKS_SRCS}) 22 | 23 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 24 | 25 | source_group("Sources" FILES ${MAIN_SRCS}) 26 | source_group("Sources\\Server" FILES ${SERVER_SRCS}) 27 | source_group("Sources\\Tasks" FILES ${TASK_SRCS}) 28 | 29 | source_group("Headers" FILES ${MAIN_HDRS}) 30 | source_group("Headers\\Server" FILES ${SERVER_HDRS}) 31 | source_group("Headers\\Tasks" FILES ${TASK_HDRS}) 32 | 33 | add_executable (qr ${ALL_SRCS} ${MAIN_SRCS} ${MAIN_HDRS}) 34 | 35 | IF(WIN32) 36 | target_link_libraries(qr openspy.lib SharedTasks.lib ZLIB::ZLIB) 37 | ELSE() #unix 38 | target_link_libraries(qr openspy libuv::uv SharedTasks ZLIB::ZLIB) 39 | ENDIF() -------------------------------------------------------------------------------- /code/qr/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "server/QRServer.h" 8 | #include "server/QRDriver.h" 9 | #include "tasks/tasks.h" 10 | INetServer *g_gameserver = NULL; 11 | 12 | 13 | void tick_handler(uv_timer_t* handle) { 14 | g_gameserver->tick(); 15 | } 16 | 17 | int main() { 18 | uv_loop_t *loop = uv_default_loop(); 19 | uv_timer_t tick_timer; 20 | 21 | uv_timer_init(uv_default_loop(), &tick_timer); 22 | 23 | OS::Init("qr"); 24 | 25 | g_gameserver = new QR::Server(); 26 | 27 | char address_buff[256]; 28 | char port_buff[16]; 29 | size_t temp_env_sz = sizeof(address_buff); 30 | 31 | if(uv_os_getenv("OPENSPY_QR_BIND_ADDR", (char *)&address_buff, &temp_env_sz) != UV_ENOENT) { 32 | temp_env_sz = sizeof(port_buff); 33 | 34 | uint16_t port = 27900; 35 | if(uv_os_getenv("OPENSPY_QR_BIND_PORT", (char *)&port_buff, &temp_env_sz) != UV_ENOENT) { 36 | port = atoi(port_buff); 37 | } 38 | 39 | QR::Driver *driver = new QR::Driver(g_gameserver, address_buff, port); 40 | 41 | OS::LogText(OS::ELogLevel_Info, "Adding QR Driver: %s:%d\n", address_buff, port); 42 | g_gameserver->addNetworkDriver(driver); 43 | } else { 44 | OS::LogText(OS::ELogLevel_Warning, "Missing QR bind address environment variable"); 45 | } 46 | 47 | MM::InitTasks(); 48 | uv_timer_start(&tick_timer, tick_handler, 0, 250); 49 | uv_run(loop, UV_RUN_DEFAULT); 50 | 51 | uv_loop_close(loop); 52 | 53 | delete g_gameserver; 54 | OS::Shutdown(); 55 | return 0; 56 | } -------------------------------------------------------------------------------- /code/qr/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/qr/server/QRServer.cpp: -------------------------------------------------------------------------------- 1 | #include "QRServer.h" 2 | #include "QRDriver.h" 3 | #include 4 | 5 | namespace QR { 6 | 7 | Server::Server() : INetServer() { 8 | uv_loop_set_data(uv_default_loop(), this); 9 | } 10 | 11 | Server::~Server() { 12 | std::vector::iterator it = m_net_drivers.begin(); 13 | while (it != m_net_drivers.end()) { 14 | INetDriver *driver = *it; 15 | delete driver; 16 | it++; 17 | } 18 | } 19 | void Server::tick() { 20 | } 21 | QR::Driver *Server::findDriverByAddress(OS::Address address) { 22 | std::vector::iterator it = m_net_drivers.begin(); 23 | while (it != m_net_drivers.end()) { 24 | QR::Driver *driver = (QR::Driver *)*it; 25 | if(OS::Address(driver->GetAddress()) == address) { 26 | return (QR::Driver *)driver; 27 | } 28 | it++; 29 | } 30 | return NULL; 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /code/qr/server/QRServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _QRSERVER_H 2 | #define _QRSERVER_H 3 | #include 4 | #include 5 | 6 | #include 7 | #define MASTER_PORT 27900 8 | namespace MM { 9 | class MMPushTask; 10 | class MMPushRequest; 11 | } 12 | namespace QR { 13 | class Peer; 14 | class Server : public INetServer { 15 | public: 16 | Server(); 17 | ~Server(); 18 | void tick(); 19 | Driver *findDriverByAddress(OS::Address address); 20 | private: 21 | }; 22 | } 23 | #endif //_CHCGAMESERVER_H -------------------------------------------------------------------------------- /code/qr/server/V1Handler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "QRServer.h" 5 | #include "QRDriver.h" 6 | #include "v2.h" 7 | namespace QR { 8 | void Driver::handle_v1_packet(OS::Address address, OS::Buffer buffer) { 9 | std::string input = std::string((char *)buffer.GetHead(), buffer.readRemaining()); 10 | buffer.SetReadCursor(buffer.readRemaining()); 11 | 12 | OS::KVReader data_parser = input; 13 | 14 | 15 | std::string message_type = data_parser.GetKeyByIdx(0); 16 | 17 | if(message_type.compare("heartbeat") == 0) { 18 | handle_v1_heartbeat(address, data_parser); 19 | } else if(message_type.compare("validate") == 0) { 20 | handle_v1_validate(address, data_parser); 21 | } else if (message_type.compare("echo") == 0) { 22 | handle_v1_echo(address, data_parser); 23 | } else { 24 | //read heartbeat server info 25 | handle_v1_heartbeat_data(address, data_parser); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /code/qr/server/V2Handler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "QRServer.h" 5 | #include "QRDriver.h" 6 | #include "v2.h" 7 | namespace QR { 8 | void Driver::handle_v2_packet(OS::Address address, OS::Buffer buffer) { 9 | uint8_t type = buffer.ReadByte(); 10 | if(buffer.readRemaining() < REQUEST_KEY_LEN) { 11 | return; 12 | } 13 | 14 | uint8_t instance_key[REQUEST_KEY_LEN]; 15 | buffer.ReadBuffer(&instance_key, REQUEST_KEY_LEN); 16 | 17 | switch(type) { 18 | case PACKET_AVAILABLE: 19 | handle_v2_available(address, (uint8_t *)&instance_key, buffer); 20 | break; 21 | case PACKET_HEARTBEAT: 22 | handle_v2_heartbeat(address, (uint8_t *)&instance_key, buffer); 23 | break; 24 | case PACKET_CHALLENGE: 25 | handle_v2_challenge(address, (uint8_t *)&instance_key, buffer); 26 | break; 27 | case PACKET_KEEPALIVE: 28 | handle_v2_keepalive(address, (uint8_t *)&instance_key, buffer); 29 | break; 30 | case PACKET_CLIENT_MESSAGE_ACK: 31 | handle_v2_client_message_ack(address, (uint8_t *)&instance_key, buffer); 32 | break; 33 | default: 34 | OS::LogText(OS::ELogLevel_Info, "[%s] Got Unknown QR2 packet %d", address.ToString().c_str(), type); 35 | break; 36 | } 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /code/qr/server/v1/handle_echo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace QR { 10 | void Driver::on_v1_echo_processed(MM::MMTaskResponse response) { 11 | if(response.error_message != NULL) { 12 | //response.driver->send_v1_error(response.from_address, response.error_message); 13 | return; 14 | } 15 | std::stringstream ss; 16 | ss << "\\echo\\" << response.challenge; 17 | 18 | std::string message = ss.str(); 19 | 20 | OS::Buffer buffer; 21 | buffer.WriteBuffer(message.c_str(),message.length()); 22 | response.driver->SendUDPPacket(response.from_address, buffer); 23 | } 24 | void Driver::handle_v1_echo(OS::Address from_address, OS::KVReader reader) { 25 | OS::LogText(OS::ELogLevel_Info, "[%s] Got echo", from_address.ToString().c_str()); 26 | 27 | MM::MMPushRequest req; 28 | 29 | req.callback = on_v1_echo_processed; 30 | req.from_address = from_address; 31 | req.v2_instance_key = 0; 32 | req.driver = this; 33 | req.version = 1; 34 | req.gamename = reader.GetValueByIdx(0); //get echo string 35 | 36 | 37 | req.type = MM::EMMPushRequestType_Keepalive; 38 | AddRequest(req); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /code/qr/server/v1/handle_validate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | namespace QR { 11 | void Driver::on_v1_secure_processed(MM::MMTaskResponse response) { 12 | if(response.error_message != NULL) { 13 | response.driver->send_v1_error(response.from_address, response.error_message); 14 | return; 15 | } 16 | response.driver->perform_v1_key_scan(response.query_address); 17 | OS::LogText(OS::ELogLevel_Info, "[%s] Server Registered - %s", response.from_address.ToString().c_str(), response.challenge.c_str()); 18 | } 19 | void Driver::handle_v1_validate(OS::Address from_address, OS::KVReader reader) { 20 | std::string challenge = reader.GetValue("validate"); 21 | 22 | MM::MMPushRequest req; 23 | 24 | req.gamename = challenge; 25 | req.callback = on_v1_secure_processed; 26 | req.from_address = from_address; 27 | req.v2_instance_key = 0; 28 | req.driver = this; 29 | req.version = 1; 30 | 31 | OS::LogText(OS::ELogLevel_Info, "[%s] Got challenge response: %s", from_address.ToString().c_str(), challenge.c_str()); 32 | req.type = MM::EMMPushRequestType_ValidateServer; 33 | AddRequest(req); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /code/qr/server/v1/scan.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | namespace QR { 11 | void Driver::perform_v1_key_scan(OS::Address from_address) { 12 | std::stringstream ss; 13 | ss << "\\status\\"; 14 | 15 | std::string message = ss.str(); 16 | 17 | OS::Buffer buffer; 18 | buffer.WriteBuffer(message.c_str(),message.length()); 19 | SendUDPPacket(from_address, buffer); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /code/qr/server/v2.h: -------------------------------------------------------------------------------- 1 | #ifndef _V2_CONSTANTS 2 | #define _V2_CONSTANTS 3 | 4 | #define REQUEST_KEY_LEN 4 5 | #define QR2_PING_TIME 120 6 | 7 | #define QR2_RESEND_MSG_TIME 5 //resend every 5 seconds 8 | #define QR2_MAX_RESEND_COUNT 5 9 | 10 | #define PACKET_QUERY 0x00 //S -> C 11 | #define PACKET_CHALLENGE 0x01 //S -> C 12 | #define PACKET_ECHO 0x02 //S -> C (purpose..?) 13 | #define PACKET_ECHO_RESPONSE 0x05 // 0x05, not 0x03 (order) | C -> S 14 | #define PACKET_HEARTBEAT 0x03 //C -> S 15 | #define PACKET_ADDERROR 0x04 //S -> C 16 | #define PACKET_CLIENT_MESSAGE 0x06 //S -> C 17 | #define PACKET_CLIENT_MESSAGE_ACK 0x07 //C -> S 18 | #define PACKET_KEEPALIVE 0x08 //S -> C | C -> S 19 | #define PACKET_PREQUERY_IP_VERIFY 0x09 //S -> C 20 | #define PACKET_AVAILABLE 0x09 //C -> S 21 | #define PACKET_CLIENT_REGISTERED 0x0A //S -> C 22 | 23 | #define QR2_OPTION_USE_QUERY_CHALLENGE 128 //backend flag 24 | 25 | #define QR_MAGIC_1 0xFE 26 | #define QR_MAGIC_2 0xFD 27 | 28 | #define V2_CHALLENGE_LEN 20 29 | 30 | #endif //_V2_CONSTANTS -------------------------------------------------------------------------------- /code/qr/server/v2/handle_available.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace QR { 10 | void Driver::on_got_v2_available_data(MM::MMTaskResponse response) { 11 | OS::Buffer buffer; 12 | 13 | buffer.WriteByte(QR_MAGIC_1); 14 | buffer.WriteByte(QR_MAGIC_2); 15 | 16 | buffer.WriteByte(PACKET_AVAILABLE); 17 | buffer.WriteInt(htonl(response.game_data.disabled_services)); 18 | response.driver->SendUDPPacket(response.from_address, buffer); 19 | } 20 | 21 | void Driver::handle_v2_available(OS::Address from_address, uint8_t *instance_key, OS::Buffer &buffer) { 22 | std::string gamename = buffer.ReadNTS(); 23 | 24 | MM::MMPushRequest req; 25 | 26 | req.gamename = gamename; 27 | req.callback = on_got_v2_available_data; 28 | req.from_address = from_address; 29 | req.v2_instance_key = *(uint32_t *)instance_key; 30 | req.driver = this; 31 | req.version = 2; 32 | 33 | OS::LogText(OS::ELogLevel_Info, "[%s] Got available request: %s", from_address.ToString().c_str(), req.gamename.c_str()); 34 | req.type = MM::EMMPushRequestType_GetGameInfoByGameName; 35 | AddRequest(req); 36 | } 37 | } -------------------------------------------------------------------------------- /code/qr/server/v2/handle_challenge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace QR { 10 | void Driver::on_got_v2_challenge_response(MM::MMTaskResponse response) { 11 | if(response.error_message != NULL) { 12 | response.driver->send_v2_error(response.from_address, response.v2_instance_key, 1, response.error_message); 13 | return; 14 | } 15 | OS::Buffer buffer; 16 | buffer.WriteByte(QR_MAGIC_1); 17 | buffer.WriteByte(QR_MAGIC_2); 18 | 19 | buffer.WriteByte(PACKET_CLIENT_REGISTERED); 20 | buffer.WriteInt(response.v2_instance_key); 21 | response.driver->SendUDPPacket(response.from_address, buffer); 22 | OS::LogText(OS::ELogLevel_Info, "[%s] Server Registered - %s", response.from_address.ToString().c_str(), response.challenge.c_str()); 23 | } 24 | void Driver::handle_v2_challenge(OS::Address from_address, uint8_t *instance_key, OS::Buffer &buffer) { 25 | std::string challenge = buffer.ReadNTS(); 26 | 27 | MM::MMPushRequest req; 28 | 29 | req.gamename = challenge; 30 | req.callback = on_got_v2_challenge_response; 31 | req.from_address = from_address; 32 | req.v2_instance_key = *(uint32_t *)instance_key; 33 | req.driver = this; 34 | req.version = 2; 35 | 36 | req.type = MM::EMMPushRequestType_ValidateServer; 37 | AddRequest(req); 38 | } 39 | } -------------------------------------------------------------------------------- /code/qr/server/v2/handle_client_message_ack.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | namespace QR { 11 | void Driver::send_client_message(int version, OS::Address to_address, uint32_t instance_key, uint32_t message_key, OS::Buffer &message_buffer) { 12 | OS::Buffer buffer; 13 | 14 | OS::LogText(OS::ELogLevel_Info, "[%s] Send client message: %d - %d", to_address.ToString().c_str(), message_buffer.bytesWritten(), message_key); 15 | 16 | if(version == 2) { 17 | buffer.WriteByte(QR_MAGIC_1); 18 | buffer.WriteByte(QR_MAGIC_2); 19 | 20 | buffer.WriteByte(PACKET_CLIENT_MESSAGE); 21 | buffer.WriteInt(instance_key); 22 | 23 | buffer.WriteInt(message_key); 24 | buffer.WriteBuffer(message_buffer.GetHead(), message_buffer.bytesWritten()); 25 | SendUDPPacket(to_address, buffer); 26 | 27 | } 28 | } 29 | void Driver::handle_v2_client_message_ack(OS::Address from_address, uint8_t *instance_key, OS::Buffer &buffer) { 30 | uint32_t key = buffer.ReadInt(); 31 | 32 | MM::MMPushRequest req; 33 | 34 | req.callback = NULL; 35 | req.from_address = from_address; 36 | req.v2_instance_key = *(uint32_t *)instance_key; 37 | req.driver = this; 38 | req.version = 2; 39 | req.server.id = key; 40 | 41 | OS::LogText(OS::ELogLevel_Info, "[%s] Got client message ack %d", from_address.ToString().c_str(), key); 42 | 43 | 44 | req.type = MM::EMMPushRequestType_ClientMessageAck; 45 | AddRequest(req); 46 | } 47 | } -------------------------------------------------------------------------------- /code/qr/server/v2/handle_keepalive.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace QR { 10 | void Driver::on_v2_keepalive_processed(MM::MMTaskResponse response) { 11 | if(response.error_message != NULL) { 12 | //response.driver->send_v2_error(response.from_address, response.v2_instance_key, 1, response.error_message); 13 | return; 14 | } else { 15 | OS::Buffer send_buffer; 16 | uv_timespec64_t current_time; 17 | uv_clock_gettime(UV_CLOCK_REALTIME, ¤t_time); 18 | send_buffer.WriteByte(QR_MAGIC_1); 19 | send_buffer.WriteByte(QR_MAGIC_2); 20 | send_buffer.WriteByte(PACKET_KEEPALIVE); 21 | send_buffer.WriteInt(response.v2_instance_key); 22 | send_buffer.WriteInt(current_time.tv_sec); 23 | response.driver->SendUDPPacket(response.from_address, send_buffer); 24 | } 25 | } 26 | void Driver::handle_v2_keepalive(OS::Address from_address, uint8_t *instance_key, OS::Buffer &buffer) { 27 | //send response 28 | OS::LogText(OS::ELogLevel_Info, "[%s] Got keepalive", from_address.ToString().c_str()); 29 | 30 | MM::MMPushRequest req; 31 | 32 | req.callback = on_v2_keepalive_processed; 33 | req.from_address = from_address; 34 | req.v2_instance_key = *(uint32_t *)instance_key; 35 | req.driver = this; 36 | req.version = 2; 37 | 38 | 39 | req.type = MM::EMMPushRequestType_Keepalive; 40 | AddRequest(req); 41 | } 42 | } -------------------------------------------------------------------------------- /code/qr/tasks/ClientMessageAck.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../server/v2.h" 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace MM { 10 | bool PerformClientMessageAck(MMPushRequest request, TaskThreadData *thread_data) { 11 | MMTaskResponse response; 12 | response.v2_instance_key = request.v2_instance_key; 13 | response.driver = request.driver; 14 | response.from_address = request.from_address; 15 | 16 | json_t *send_obj = json_object(); 17 | 18 | json_object_set_new(send_obj, "instance_key", json_integer(request.v2_instance_key)); 19 | json_object_set_new(send_obj, "version", json_integer(2)); 20 | json_object_set_new(send_obj, "identifier", json_integer(request.server.id)); 21 | 22 | json_object_set_new(send_obj, "hostname", json_string(OS::g_hostName)); 23 | OS::Address address = request.driver->GetAddress(); 24 | json_object_set_new(send_obj, "driver_address", json_string(address.ToString().c_str())); 25 | json_object_set_new(send_obj, "from_address", json_string(request.from_address.ToString().c_str())); 26 | 27 | char *json_dump = json_dumps(send_obj, 0); 28 | 29 | 30 | TaskShared::sendAMQPMessage(mm_channel_exchange, mm_server_client_acks_routingkey, json_dump, &address); 31 | 32 | if (json_dump) { 33 | free((void *)json_dump); 34 | } 35 | 36 | json_decref(send_obj); 37 | 38 | if(request.callback) 39 | request.callback(response); 40 | 41 | return true; 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /code/qr/tasks/GetGameInfo.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | namespace MM { 4 | bool PerformGetGameInfo(MMPushRequest request, TaskThreadData *thread_data) { 5 | OS::GameData game_info; 6 | game_info = OS::GetGameByName(request.gamename.c_str(), thread_data->mp_redis_connection); 7 | selectQRRedisDB(thread_data); 8 | MMTaskResponse response; 9 | response.driver = request.driver; 10 | response.from_address = request.from_address; 11 | response.v2_instance_key = request.v2_instance_key; 12 | 13 | request.callback(response); 14 | 15 | return true; 16 | } 17 | } -------------------------------------------------------------------------------- /code/qr/tasks/Keepalive.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include 6 | #include "../server/v2.h" 7 | 8 | #include 9 | 10 | namespace MM { 11 | bool PerformKeepalive(MMPushRequest request, TaskThreadData *thread_data) { 12 | MMTaskResponse response; 13 | response.v2_instance_key = request.v2_instance_key; 14 | response.driver = request.driver; 15 | response.from_address = request.from_address; 16 | response.challenge = request.gamename; //copy echo key 17 | 18 | selectQRRedisDB(thread_data); 19 | 20 | std::string server_key = GetServerKey_FromRequest(request, thread_data); 21 | if(server_key.length() == 0) { 22 | response.error_message = "No server registered"; 23 | } else { 24 | WriteLastHeartbeatTime(thread_data, server_key, request.from_address, request.v2_instance_key, request.from_address); 25 | } 26 | 27 | request.callback(response); 28 | 29 | return true; 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /code/search/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(SM) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | file (GLOB MAIN_SRCS "*.cpp") 8 | file (GLOB MAIN_HDRS "*.h") 9 | file (GLOB SERVER_SRCS "server/*.cpp") 10 | file (GLOB SERVER_HDRS "server/*.h") 11 | file (GLOB SERVER_CMDS_SRCS "server/commands/*.cpp") 12 | file (GLOB SERVER_CMDS_HDRS "server/commands/*.h") 13 | 14 | 15 | set (ALL_SRCS ${MAIN_SRCS} ${MAIN_HDRS} ${SERVER_SRCS} ${SERVER_HDRS} ${SERVER_CMDS_SRCS}) 16 | 17 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} SharedTasks) 18 | 19 | source_group("Sources" FILES ${MAIN_SRCS}) 20 | source_group("Sources\\Server" FILES ${SERVER_SRCS}) 21 | source_group("Sources\\Commands\\Server" FILES ${SERVER_CMDS_SRCS}) 22 | 23 | source_group("Headers" FILES ${MAIN_HDRS}) 24 | source_group("Headers\\Server" FILES ${SERVER_HDRS}) 25 | source_group("Headers\\Commands\\Server" FILES ${SERVER_CMDS_HDRS}) 26 | 27 | add_executable (SM ${ALL_SRCS}) 28 | 29 | IF(WIN32) 30 | target_link_libraries(SM openspy.lib SharedTasks.lib ZLIB::ZLIB) 31 | ELSE() #unix 32 | target_link_libraries(SM openspy SharedTasks ZLIB::ZLIB) 33 | ENDIF() -------------------------------------------------------------------------------- /code/search/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "server/SMServer.h" 7 | #include "server/SMDriver.h" 8 | INetServer *g_gameserver = NULL; 9 | 10 | void tick_handler(uv_timer_t* handle) { 11 | g_gameserver->tick(); 12 | } 13 | 14 | int main() { 15 | uv_loop_t *loop = uv_default_loop(); 16 | uv_timer_t tick_timer; 17 | 18 | uv_timer_init(uv_default_loop(), &tick_timer); 19 | 20 | OS::Init("SM"); 21 | 22 | g_gameserver = new SM::Server(); 23 | 24 | char address_buff[256]; 25 | char port_buff[16]; 26 | size_t temp_env_sz = sizeof(address_buff); 27 | 28 | if(uv_os_getenv("OPENSPY_SM_BIND_ADDR", (char *)&address_buff, &temp_env_sz) != UV_ENOENT) { 29 | temp_env_sz = sizeof(port_buff); 30 | 31 | uint16_t port = 29901; 32 | if(uv_os_getenv("OPENSPY_SM_BIND_PORT", (char *)&port_buff, &temp_env_sz) != UV_ENOENT) { 33 | port = atoi(port_buff); 34 | } 35 | 36 | SM::Driver *driver = new SM::Driver(g_gameserver, address_buff, port); 37 | 38 | OS::LogText(OS::ELogLevel_Info, "Adding SM Driver: %s:%d\n", address_buff, port); 39 | g_gameserver->addNetworkDriver(driver); 40 | } else { 41 | OS::LogText(OS::ELogLevel_Warning, "Missing GP bind address environment variable"); 42 | } 43 | 44 | uv_timer_start(&tick_timer, tick_handler, 0, 250); 45 | 46 | uv_run(loop, UV_RUN_DEFAULT); 47 | 48 | uv_loop_close(loop); 49 | 50 | delete g_gameserver; 51 | 52 | OS::Shutdown(); 53 | return 0; 54 | } -------------------------------------------------------------------------------- /code/search/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/search/server/SMDriver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "SMServer.h" 5 | #include "SMPeer.h" 6 | #include "SMDriver.h" 7 | 8 | namespace SM { 9 | Driver::Driver(INetServer *server, const char *host, uint16_t port) : TCPDriver(server, host, port) { 10 | } 11 | INetPeer *Driver::CreatePeer(uv_tcp_t *sd) { 12 | return new Peer(this, sd); 13 | } 14 | } -------------------------------------------------------------------------------- /code/search/server/SMDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPDRIVER_H 2 | #define _GPDRIVER_H 3 | #include 4 | #include "../main.h" 5 | #include 6 | 7 | #include "SMPeer.h" 8 | 9 | #include 10 | #include 11 | #ifdef _WIN32 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | namespace SM { 18 | class Peer; 19 | 20 | class Driver : public OS::TCPDriver { 21 | public: 22 | Driver(INetServer *server, const char *host, uint16_t port); 23 | protected: 24 | virtual INetPeer *CreatePeer(uv_tcp_t *sd); 25 | }; 26 | } 27 | #endif //_SBDRIVER_H -------------------------------------------------------------------------------- /code/search/server/SMServer.cpp: -------------------------------------------------------------------------------- 1 | #include "SMPeer.h" 2 | #include "SMServer.h" 3 | #include "SMDriver.h" 4 | 5 | 6 | namespace SM { 7 | Server::Server() : INetServer(){ 8 | uv_loop_set_data(uv_default_loop(), this); 9 | } 10 | Server::~Server() { 11 | } 12 | void Server::tick() { 13 | std::vector::iterator it = m_net_drivers.begin(); 14 | while (it != m_net_drivers.end()) { 15 | INetDriver *driver = *it; 16 | driver->think(); 17 | it++; 18 | } 19 | NetworkTick(); 20 | } 21 | } -------------------------------------------------------------------------------- /code/search/server/SMServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _SMSERVER_H 2 | #define _SMSERVER_H 3 | #include 4 | #include 5 | 6 | namespace SM { 7 | class Server : public INetServer { 8 | public: 9 | Server(); 10 | virtual ~Server(); 11 | void tick(); 12 | private: 13 | }; 14 | } 15 | #endif //_SMSERVER_H -------------------------------------------------------------------------------- /code/search/server/commands/handle_pmatch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace SM { 16 | } -------------------------------------------------------------------------------- /code/search/server/commands/handle_profilelist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace SM { 16 | } -------------------------------------------------------------------------------- /code/search/server/commands/handle_uniquesearch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace SM { 16 | void Peer::m_uniquesearch_cb(TaskShared::WebErrorDetails error_details, std::vector results, std::map result_users, void *extra, INetPeer *peer) { 17 | std::ostringstream s; 18 | s << "\\us\\" << results.size(); 19 | std::vector::iterator it = results.begin(); 20 | while(it != results.end()) { 21 | OS::Profile p = *it; 22 | s << "\\nick\\" << p.uniquenick; 23 | it++; 24 | } 25 | s << "\\usdone\\"; 26 | ((Peer *)peer)->SendPacket(s.str().c_str()); 27 | 28 | ((Peer *)peer)->Delete(); 29 | } 30 | void Peer::handle_uniquesearch(OS::KVReader data_parser) { 31 | TaskShared::ProfileRequest request; 32 | request.type = TaskShared::EProfileSearch_SuggestUniquenick; 33 | if(data_parser.HasKey("preferrednick")) { 34 | request.profile_search_details.uniquenick = data_parser.GetValue("preferrednick"); 35 | } else { 36 | send_error(GPShared::GP_PARSE); 37 | return; 38 | } 39 | if(data_parser.HasKey("namespaceid")) { 40 | request.profile_search_details.namespaceid = data_parser.GetValueInt("namespaceid"); 41 | } 42 | 43 | request.extra = NULL; 44 | request.peer = this; 45 | IncRef(); 46 | request.callback = Peer::m_uniquesearch_cb; 47 | AddProfileTaskRequest(request); 48 | } 49 | } -------------------------------------------------------------------------------- /code/search/server/commands/handle_valid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace SM { 16 | void Peer::m_search_valid_callback(TaskShared::WebErrorDetails error_details, std::vector results, void *extra, INetPeer *peer) { 17 | std::ostringstream s; 18 | 19 | s << "\\vr\\" << ((results.size() > 0) ? 1 : 0); 20 | 21 | ((Peer *)peer)->SendPacket(s.str().c_str()); 22 | 23 | ((Peer *)peer)->Delete(); 24 | } 25 | void Peer::handle_valid(OS::KVReader data_parser) { 26 | TaskShared::UserRequest request; 27 | request.type = TaskShared::EUserRequestType_Search; 28 | if (data_parser.HasKey("userid")) { 29 | request.search_params.id = data_parser.GetValueInt("userid"); 30 | } 31 | 32 | if (data_parser.HasKey("partnercode")) { 33 | request.search_params.partnercode = data_parser.GetValueInt("partnercode"); 34 | } 35 | else if(data_parser.HasKey("partnerid")) { 36 | request.search_params.partnercode = data_parser.GetValueInt("partnerid"); 37 | } 38 | 39 | if(data_parser.HasKey("email")) { 40 | request.search_params.email = data_parser.GetValue("email"); 41 | } 42 | request.peer = this; 43 | IncRef(); 44 | request.callback = Peer::m_search_valid_callback; 45 | AddUserTaskRequest(request); 46 | } 47 | } -------------------------------------------------------------------------------- /code/serverbrowsing/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(serverbrowsing) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | file (GLOB MAIN_SRCS "*.cpp") 8 | file (GLOB MAIN_HDRS "*.h") 9 | file (GLOB SERVER_SRCS "server/*.cpp") 10 | file (GLOB SERVER_HDRS "server/*.h") 11 | file (GLOB FILTER_SRCS "filter/*.cpp") 12 | file (GLOB FILTER_HDRS "filter/*.h") 13 | file (GLOB TASKS_SRCS "tasks/*.cpp") 14 | file (GLOB TASKS_HDRS "tasks/*.h") 15 | 16 | 17 | set (ALL_SRCS ${SERVER_SRCS} ${SERVER_HDRS} ${FILTER_SRCS} ${FILTER_HDRS} ${TASKS_SRCS}) 18 | 19 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 20 | 21 | source_group("Sources" FILES ${MAIN_SRCS}) 22 | source_group("Sources\\Server" FILES ${SERVER_SRCS}) 23 | source_group("Sources\\Filter" FILES ${FILTER_SRCS}) 24 | source_group("Sources\\Tasks" FILES ${TASKS_SRCS}) 25 | 26 | source_group("Headers" FILES ${MAIN_HDRS}) 27 | source_group("Headers\\Server" FILES ${SERVER_HDRS}) 28 | source_group("Headers\\Filter" FILES ${FILTER_HDRS}) 29 | source_group("Headers\\Tasks" FILES ${TASKS_HDRS}) 30 | 31 | add_executable (serverbrowsing ${ALL_SRCS} ${MAIN_SRCS} ${MAIN_HDRS}) 32 | 33 | IF(WIN32) 34 | target_link_libraries(serverbrowsing openspy.lib SharedTasks.lib ZLIB::ZLIB) 35 | ELSE() #unix 36 | target_link_libraries(serverbrowsing openspy libuv::uv SharedTasks ZLIB::ZLIB) 37 | ENDIF() 38 | 39 | if(BUILD_TESTING) 40 | add_subdirectory(test) 41 | endif() 42 | -------------------------------------------------------------------------------- /code/serverbrowsing/filter/filter.cpp: -------------------------------------------------------------------------------- 1 | #include "filter.h" 2 | #include "CToken.h" 3 | 4 | bool filterMatches(std::vector token_list, std::map& kvList) { 5 | if (token_list.empty()) { 6 | return true; 7 | } 8 | return evaluate(token_list, kvList); 9 | } 10 | -------------------------------------------------------------------------------- /code/serverbrowsing/filter/filter.h: -------------------------------------------------------------------------------- 1 | #ifndef _FILTER_H 2 | #include 3 | #include 4 | 5 | #include "CToken.h" 6 | 7 | bool filterMatches(std::vector token_list, std::map& kvList); 8 | 9 | #endif //_FILTER_H 10 | -------------------------------------------------------------------------------- /code/serverbrowsing/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | 5 | //all those things that should be removed from the code base 6 | #define HACKER_PATCH_MSG_FORCE_NATNEG_ONLY 1 7 | #define HACKER_PATCH_MSG_SPAM_CHECKER 1 8 | #define HACKER_PATCH_MSG_SPAM_CHECKER_DUPLICATE 5 9 | #endif -------------------------------------------------------------------------------- /code/serverbrowsing/server/SBDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _SBDRIVER_H 2 | #define _SBDRIVER_H 3 | #include 4 | #include "../main.h" 5 | #include 6 | #include 7 | 8 | #include "SBPeer.h" 9 | #include "V2Peer.h" 10 | #include "V1Peer.h" 11 | #include 12 | 13 | #include 14 | #include 15 | #ifdef _WIN32 16 | #include 17 | #else 18 | #include 19 | #endif 20 | 21 | #define SB_PING_TIME 15 22 | #define DRIVER_THREAD_TIME 1000 23 | 24 | namespace SB { 25 | class Peer; 26 | 27 | class Driver : public OS::TCPDriver { 28 | public: 29 | Driver(INetServer *server, const char *host, uint16_t port, int version); 30 | ~Driver(); 31 | void SendDeleteServer(MM::Server *server); 32 | void SendNewServer(MM::Server *server); 33 | void SendUpdateServer(MM::Server *server); 34 | 35 | void AddDeleteServer(MM::Server serv); 36 | void AddNewServer(MM::Server serv); 37 | void AddUpdateServer(MM::Server serv); 38 | void TickConnections(); 39 | INetPeer *CreatePeer(uv_tcp_t *socket); 40 | private: 41 | int m_version; 42 | uv_mutex_t m_mutex; 43 | 44 | static bool LLIterator_SendDeleteServer(INetPeer* peer, MM::Server* server); 45 | static bool LLIterator_SendNewServer(INetPeer* peer, MM::Server* server); 46 | static bool LLIterator_SendUpdateServer(INetPeer* peer, MM::Server* server); 47 | 48 | //safe for now, until pointers one day get added 49 | std::queue m_server_delete_queue; 50 | std::queue m_server_new_queue; 51 | std::queue m_server_update_queue; 52 | }; 53 | } 54 | #endif //_SBDRIVER_H -------------------------------------------------------------------------------- /code/serverbrowsing/server/SBServer.cpp: -------------------------------------------------------------------------------- 1 | #include "SBPeer.h" 2 | #include "SBServer.h" 3 | #include "SBDriver.h" 4 | #include 5 | SBServer::SBServer() : INetServer() { 6 | uv_loop_set_data(uv_default_loop(), this); 7 | } 8 | SBServer::~SBServer() { 9 | } 10 | void SBServer::tick() { 11 | std::vector::iterator it = m_net_drivers.begin(); 12 | while (it != m_net_drivers.end()) { 13 | INetDriver *driver = *it; 14 | driver->think(); 15 | it++; 16 | } 17 | NetworkTick(); 18 | } 19 | void SBServer::OnNewServer(MM::Server server) { 20 | std::vector::iterator it = m_net_drivers.begin(); 21 | while (it != m_net_drivers.end()) { 22 | SB::Driver *driver = (SB::Driver *)*it; 23 | driver->AddNewServer(server); 24 | it++; 25 | } 26 | } 27 | void SBServer::OnUpdateServer(MM::Server server) { 28 | std::vector::iterator it = m_net_drivers.begin(); 29 | while (it != m_net_drivers.end()) { 30 | SB::Driver *driver = (SB::Driver *)*it; 31 | driver->AddUpdateServer(server); 32 | it++; 33 | } 34 | } 35 | void SBServer::OnDeleteServer(MM::Server server) { 36 | std::vector::iterator it = m_net_drivers.begin(); 37 | while (it != m_net_drivers.end()) { 38 | SB::Driver *driver = (SB::Driver *)*it; 39 | driver->AddDeleteServer(server); 40 | it++; 41 | } 42 | } -------------------------------------------------------------------------------- /code/serverbrowsing/server/SBServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _SBSERVER_H 2 | #define _SBSERVER_H 3 | #include 4 | #include 5 | #include 6 | 7 | class SBServer : public INetServer { 8 | public: 9 | SBServer(); 10 | ~SBServer(); 11 | void tick(); 12 | 13 | void OnNewServer(MM::Server server); 14 | void OnUpdateServer(MM::Server server); 15 | void OnDeleteServer(MM::Server server); 16 | private: 17 | }; 18 | #endif //_SBSERVER_H -------------------------------------------------------------------------------- /code/serverbrowsing/server/enctype1_encoder.cpp: -------------------------------------------------------------------------------- 1 | int enctype1_func7e(char v, unsigned char *enc1key) { 2 | unsigned char a, 3 | b, 4 | c; 5 | a = enc1key[256]; 6 | b = enc1key[257]; 7 | c = enc1key[a]; 8 | enc1key[256] = a + 1; 9 | enc1key[257] = b + c; 10 | a = enc1key[260]; 11 | b = enc1key[257]; 12 | b = enc1key[b]; 13 | c = enc1key[a]; 14 | enc1key[a] = b; 15 | a = enc1key[259]; 16 | b = enc1key[257]; 17 | a = enc1key[a]; 18 | enc1key[b] = a; 19 | a = enc1key[256]; 20 | b = enc1key[259]; 21 | a = enc1key[a]; 22 | enc1key[b] = a; 23 | a = enc1key[256]; 24 | enc1key[a] = c; 25 | b = enc1key[258]; 26 | a = enc1key[c]; 27 | c = enc1key[259]; 28 | b = b + a; 29 | enc1key[258] = b; 30 | a = b; 31 | 32 | c = enc1key[c]; 33 | b = enc1key[257]; 34 | b = enc1key[b]; 35 | a = enc1key[a]; 36 | c += b; 37 | b = enc1key[260]; 38 | b = enc1key[b]; 39 | c += b; 40 | 41 | b = enc1key[c]; 42 | c = enc1key[256]; 43 | c = enc1key[c]; 44 | a += c; 45 | 46 | c = enc1key[b]; 47 | b = enc1key[a]; 48 | 49 | c ^= b; 50 | c ^= v; 51 | 52 | enc1key[260] = c; 53 | enc1key[259] = v; 54 | return c; 55 | } 56 | 57 | 58 | void enctype1_func6e(unsigned char *data, int len, unsigned char *enc1key) { 59 | while(len--) { 60 | *data = enctype1_func7e(*data, enc1key); 61 | data++; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /code/serverbrowsing/server/enctype1_helper.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | despite being a stream cipher, gamespy seems to require enctype1 to be sent out as 1 continuous buffer, solely because the length is sent as the first 4 bytes 5 | 6 | its posible this is only required in the aluigi implementation, and not actually in gamespy 3d, however for now its a continuous buffer for this reason 7 | 8 | */ 9 | 10 | void create_enctype1_buffer(const char *validate_key, OS::Buffer input, OS::Buffer &output); -------------------------------------------------------------------------------- /code/serverbrowsing/server/gutil.h: -------------------------------------------------------------------------------- 1 | /****** 2 | gutil.h 3 | GameSpy C Engine SDK 4 | 5 | Copyright 1999-2001 GameSpy Industries, Inc 6 | 7 | 18002 Skypark Circle 8 | Irvine, California 92614 9 | 949.798.4200 (Tel) 10 | 949.798.4299 (Fax) 11 | devsupport@gamespy.com 12 | 13 | ****** 14 | 15 | Please see the GameSpy C Engine SDK documentation for more 16 | information 17 | 18 | ******/ 19 | #include 20 | typedef unsigned char uchar; 21 | 22 | 23 | void cengine_gs_encode ( uchar *ins, int size, uchar *result ); 24 | void cengine_gs_encrypt ( uchar *key, int key_len, uchar *buffer_ptr, int buffer_len ); 25 | 26 | 27 | 28 | #define CRYPT_HEIGHT 16 29 | #define CRYPT_TABLE_SIZE 256 30 | #define NUM_KEYSETUP_PASSES 2 31 | #define NWORDS 16 32 | 33 | typedef struct { 34 | uint32_t F[256]; 35 | uint32_t x_stack[CRYPT_HEIGHT]; 36 | uint32_t y_stack[CRYPT_HEIGHT]; 37 | uint32_t z_stack[CRYPT_HEIGHT]; 38 | int index; 39 | uint32_t x, y, z; 40 | uint32_t tree_num; 41 | uint32_t keydata[NWORDS]; 42 | unsigned char *keyptr; 43 | 44 | } crypt_key; 45 | 46 | void 47 | init_crypt_key(const unsigned char *key, 48 | unsigned int bytes_in_key, 49 | crypt_key *L); 50 | 51 | void 52 | crypt_encrypt(crypt_key *L, uint32_t *dest, int nodes); 53 | void crypt_docrypt(crypt_key *L, unsigned char *data, int datalen); 54 | -------------------------------------------------------------------------------- /code/serverbrowsing/server/sb_crypt.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // File: sb_crypt.h 3 | // SDK: GameSpy Server Browsing SDK 4 | // 5 | // Copyright Notice: This file is part of the GameSpy SDK designed and 6 | // developed by GameSpy Industries. Copyright (c) 2009 GameSpy Industries, Inc. 7 | 8 | #ifndef _SB_CRYPT_H 9 | #define _SB_CRYPT_H 10 | 11 | 12 | typedef struct _GOACryptState 13 | { 14 | unsigned char cards[256]; // A permutation of 0-255. 15 | unsigned char rotor; // Index that rotates smoothly 16 | unsigned char ratchet; // Index that moves erratically 17 | unsigned char avalanche; // Index heavily data dependent 18 | unsigned char last_plain; // Last plain text byte 19 | unsigned char last_cipher; // Last cipher text byte 20 | } GOACryptState; 21 | 22 | 23 | 24 | void GOACryptInit(GOACryptState *state, unsigned char *key, unsigned char keysize); 25 | void GOAHashInit(GOACryptState *state); 26 | unsigned char GOAEncryptByte(GOACryptState *state, unsigned char b); // Encrypt byte 27 | void GOAEncrypt(GOACryptState *state, unsigned char *bp, size_t len); // Encrypt byte array 28 | unsigned char GOADecryptByte(GOACryptState *state, unsigned char b); // Decrypt byte. 29 | void GOADecrypt(GOACryptState *state,unsigned char *bp, size_t len); // decrypt byte array 30 | void GOAHashFinal(GOACryptState *state, unsigned char *hash, unsigned char hashlength); // Hash length (16-32) 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /code/serverbrowsing/tasks/GetGameInfoByGameName.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | namespace MM { 4 | bool PerformGetGameInfoByGameName(MMQueryRequest request, TaskThreadData *thread_data) { 5 | OS::GameData game_info; 6 | game_info = OS::GetGameByName(request.gamenames[0].c_str(), thread_data->mp_redis_connection); 7 | if(request.peer) { 8 | request.peer->OnRecievedGameInfo(game_info, request.extra); 9 | request.peer->DecRef(); 10 | } 11 | return true; 12 | } 13 | } -------------------------------------------------------------------------------- /code/serverbrowsing/tasks/GetGameInfoPairByGameName.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | namespace MM { 4 | bool PerformGetGameInfoPairByGameName(MMQueryRequest request, TaskThreadData *thread_data) { 5 | OS::GameData games[2]; 6 | games[0] = OS::GetGameByName(request.gamenames[0].c_str(), thread_data->mp_redis_connection); 7 | games[1] = OS::GetGameByName(request.gamenames[1].c_str(), thread_data->mp_redis_connection); 8 | 9 | if(request.peer) { 10 | request.peer->OnRecievedGameInfoPair(games[0], games[1], request.extra); 11 | request.peer->DecRef(); 12 | } 13 | return true; 14 | } 15 | } -------------------------------------------------------------------------------- /code/serverbrowsing/tasks/GetServerByIP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | namespace MM { 6 | bool PerformGetServerByIP(MMQueryRequest request, TaskThreadData *thread_data) { 7 | ServerListQuery ret; 8 | Server *serv = GetServerByIP(thread_data, request.address, request.req.m_for_game, request.req.include_deleted, request.req.all_player_keys && request.req.all_team_keys); 9 | if(serv) 10 | ret.list.push_back(serv); 11 | 12 | if(request.peer) { 13 | request.peer->OnRetrievedServerInfo(request, ret, request.extra); 14 | request.peer->DecRef(); 15 | } 16 | 17 | 18 | FreeServerListQuery(&ret); 19 | return true; 20 | } 21 | Server *GetServerByIP(TaskThreadData *thread_data, OS::Address address, OS::GameData game, bool include_deleted, bool all_player_and_team_keys) { 22 | Server *server = NULL; 23 | 24 | std::ostringstream s; 25 | 26 | redisReply *reply = (redisReply *) redisCommand(thread_data->mp_redis_connection, "SELECT %d", OS::ERedisDB_QR); 27 | freeReplyObject(reply); 28 | 29 | s << "GET IPMAP_" << address.ToString(true) << "-" << address.GetPort(); 30 | std::string cmd = s.str(); 31 | 32 | reply = (redisReply *) redisCommand(thread_data->mp_redis_connection, cmd.c_str()); 33 | 34 | if(reply) { 35 | if(reply->type == REDIS_REPLY_STRING) { 36 | server = GetServerByKey(thread_data, reply->str, include_deleted, all_player_and_team_keys); 37 | } 38 | freeReplyObject(reply); 39 | } 40 | 41 | return server; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /code/serverbrowsing/tasks/GetServerByKey.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace MM { 8 | 9 | void AppendServerEntry_AllKeys(TaskThreadData* thread_data, std::string server_key, ServerListQuery* ret, bool include_deleted, bool all_player_and_team_keys) { 10 | sServerListReq req; 11 | req.all_keys = true; 12 | req.include_deleted = include_deleted; 13 | 14 | if (all_player_and_team_keys) { 15 | req.all_player_keys = true; 16 | req.all_team_keys = true; 17 | } 18 | 19 | std::vector keys; 20 | keys.push_back(server_key); 21 | 22 | AppendServerEntries_AllKeys(thread_data, keys, ret, &req); 23 | } 24 | 25 | bool PerformGetServerByKey(MMQueryRequest request, TaskThreadData *thread_data) { 26 | ServerListQuery ret; 27 | AppendServerEntry_AllKeys(thread_data, request.key, &ret, false, true); 28 | request.peer->OnRetrievedServerInfo(request, ret, request.extra); 29 | FreeServerListQuery(&ret); 30 | if(request.peer) 31 | request.peer->DecRef(); 32 | return true; 33 | } 34 | Server *GetServerByKey(TaskThreadData *thread_data, std::string key, bool include_deleted, bool include_player_and_team_keys) { 35 | ServerListQuery ret; 36 | AppendServerEntry_AllKeys(thread_data, key, &ret, include_deleted, include_player_and_team_keys); 37 | if(ret.list.size() < 1) 38 | return NULL; 39 | 40 | return ret.list[0]; 41 | } 42 | } -------------------------------------------------------------------------------- /code/serverbrowsing/tasks/HandleServerEventMsg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | namespace MM { 5 | 6 | //this event is handled by the "qr-service" project, which handles resending and other QR related logic 7 | bool Handle_ServerEventMsg(TaskThreadData *thread_data, std::string message) { 8 | SBServer *server = (SBServer *)uv_loop_get_data(uv_default_loop()); 9 | if(!server) return false; 10 | 11 | std::vector vec = OS::KeyStringToVector(message); 12 | if (vec.size() < 2) return false; 13 | std::string msg_type = vec.at(0); 14 | std::string server_key = vec.at(1); 15 | 16 | MM::Server *gameserver = GetServerByKey(thread_data, server_key, msg_type.compare("del") == 0); 17 | 18 | if(!gameserver) { 19 | return false; 20 | } 21 | 22 | if(msg_type.compare("del") == 0) { 23 | server->OnDeleteServer(*gameserver); 24 | } else if(msg_type.compare("new") == 0) { 25 | server->OnNewServer(*gameserver); 26 | } else if(msg_type.compare("update") == 0) { 27 | server->OnUpdateServer(*gameserver); 28 | } 29 | delete gameserver; 30 | return true; 31 | } 32 | } -------------------------------------------------------------------------------- /code/serverbrowsing/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(serverbrowsing_test) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 8 | 9 | 10 | add_subdirectory(filter) 11 | -------------------------------------------------------------------------------- /code/serverbrowsing/test/filter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(core_test) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 8 | 9 | 10 | add_executable (test_filter ${ALL_SRCS} filter_basic_test.cpp) 11 | add_test(NAME test_filter COMMAND test_filter WORKING_DIRECTORY .) 12 | target_link_libraries(test_filter openspy SharedTasks) 13 | 14 | 15 | add_executable (test_subtract ${ALL_SRCS} filter_subtract_test.cpp) 16 | add_test(NAME test_subtract COMMAND test_subtract WORKING_DIRECTORY .) 17 | target_link_libraries(test_subtract openspy SharedTasks) 18 | 19 | 20 | add_executable (test_like ${ALL_SRCS} filter_like_test.cpp) 21 | add_test(NAME test_like COMMAND test_like WORKING_DIRECTORY .) 22 | target_link_libraries(test_like openspy SharedTasks) -------------------------------------------------------------------------------- /code/serverbrowsing/test/filter/filter_basic_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void test_emptyserver_hasplayerscheck() { 5 | std::map kvList; 6 | kvList["numplayers"] = "0"; 7 | 8 | 9 | std::vector token_list = CToken::filterToTokenList("numplayers>0"); 10 | if(filterMatches(token_list, kvList)) { 11 | exit(1); 12 | } 13 | } 14 | 15 | void test_singleplayerserver_hasplayerscheck() { 16 | std::map kvList; 17 | kvList["numplayers"] = "1"; 18 | 19 | 20 | std::vector token_list = CToken::filterToTokenList("numplayers>0"); 21 | if(!filterMatches(token_list, kvList)) { 22 | exit(1); 23 | } 24 | } 25 | 26 | int main() { 27 | 28 | 29 | test_emptyserver_hasplayerscheck(); 30 | test_singleplayerserver_hasplayerscheck(); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /code/serverbrowsing/test/filter/filter_like_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void test_string_like_expectpass() { 5 | std::map kvList; 6 | kvList["hostname"] = "THE SERVER"; 7 | 8 | 9 | std::vector token_list = CToken::filterToTokenList("hostname LIKE '%SERVER%'"); 10 | if(!filterMatches(token_list, kvList)) { 11 | exit(1); 12 | } 13 | } 14 | 15 | void test_string_like_expectfail() { 16 | std::map kvList; 17 | kvList["hostname"] = "SOME NAME"; 18 | 19 | 20 | std::vector token_list = CToken::filterToTokenList("hostname LIKE '%SERVER%'"); 21 | if(filterMatches(token_list, kvList)) { 22 | exit(1); 23 | } 24 | } 25 | 26 | int main() { 27 | 28 | 29 | test_string_like_expectpass(); 30 | test_string_like_expectfail(); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /code/serverbrowsing/test/filter/filter_subtract_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void test_subtract_expectpass() { 5 | std::map kvList; 6 | 7 | kvList["maxplayers"] = "2"; 8 | kvList["numplayers"] = "1"; 9 | 10 | 11 | std::vector token_list = CToken::filterToTokenList("maxplayers-numplayers == 1"); 12 | if(!filterMatches(token_list, kvList)) { 13 | exit(1); 14 | } 15 | } 16 | 17 | void test_subtract_expectfail() { 18 | std::map kvList; 19 | 20 | kvList["maxplayers"] = "999"; 21 | kvList["numplayers"] = "1"; 22 | 23 | 24 | std::vector token_list = CToken::filterToTokenList("maxplayers-numplayers == 1"); 25 | if(filterMatches(token_list, kvList)) { 26 | exit(1); 27 | } 28 | } 29 | 30 | int main() { 31 | test_subtract_expectpass(); 32 | test_subtract_expectfail(); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /code/test/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openspy/openspy-core/24178c0f49bc540684b99f59127c0bb80ec162a9/code/test/CMakeLists.txt -------------------------------------------------------------------------------- /code/test/serverbrowsing/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(serverbrowsing_test) 4 | #add_subdirectory(filter) 5 | #add_subdirectory(V1) 6 | #add_subdirectory(V2) -------------------------------------------------------------------------------- /code/test/serverbrowsing/V1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(serverbrowsing_v1_test) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 8 | 9 | add_executable (test_sbv1_groups ${ALL_SRCS} test_common.cpp test_groups.cpp) 10 | add_test(NAME test_sbv1_groups COMMAND test_sbv1_groups WORKING_DIRECTORY .) 11 | IF(WIN32) 12 | target_link_libraries(test_sbv1_groups openspy.lib) 13 | ELSE() #unix 14 | target_link_libraries(test_sbv1_groups openspy) 15 | ENDIF() 16 | -------------------------------------------------------------------------------- /code/test/serverbrowsing/V1/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _TEST_COMMON 2 | #define _TEST_COMMON 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "server/SBPeer.h" 10 | #include "server/V1Peer.h" 11 | 12 | #define TEST_GAMENAME "gmtest" 13 | #define TEST_SECRETKEY "HA6zkS" 14 | 15 | extern INetServer *test_gameserver; 16 | extern Test::TestNetIOInterface<> *test_netio_iface; 17 | 18 | enum ETestType { 19 | ETestType_ListReq, 20 | ETestType_InfoReq, 21 | ETestType_SendMsgReq, 22 | }; 23 | enum EParseState { 24 | EParseState_ReadFields, 25 | EParseState_ReadList, 26 | }; 27 | 28 | typedef struct { 29 | INetIOSocket *socket; 30 | ETestType test_type; 31 | INetPeer *peer; 32 | INetDriver *driver; 33 | OS::Address address; 34 | 35 | std::string from_gamename; 36 | std::string from_secretkey; 37 | 38 | std::string validation; 39 | std::string server_challenge; 40 | 41 | 42 | bool sent_validation_response; 43 | 44 | EParseState parse_state; 45 | 46 | std::vector fields; 47 | } SBTestState; 48 | 49 | extern std::map m_test_connections; 50 | 51 | SBTestState *findTestStateByAddress(OS::Address address); 52 | void MapTestConnections(INetDriver *driver); 53 | SBTestState *Make_FakeConnection(INetDriver *driver, OS::Address source_address); 54 | 55 | 56 | void Send_ConnectionInitPacket(SBTestState *test_state); 57 | void Send_FakeServerGroupsReq(SBTestState *test_state, std::string gamename); 58 | 59 | #endif //_TEST_COMMON -------------------------------------------------------------------------------- /code/test/serverbrowsing/V2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(serverbrowsing_v2_test) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 8 | 9 | 10 | add_executable (test_sbv2_server_message ${ALL_SRCS} test_common.cpp test_server_message.cpp) 11 | add_test(NAME test_sbv2_server_message COMMAND test_sbv2_server_message WORKING_DIRECTORY .) 12 | 13 | add_executable (test_sbv2_groups ${ALL_SRCS} test_common.cpp test_groups.cpp) 14 | add_test(NAME test_sbv2_groups COMMAND test_sbv2_groups WORKING_DIRECTORY .) 15 | IF(WIN32) 16 | target_link_libraries(test_sbv2_server_message openspy.lib) 17 | target_link_libraries(test_sbv2_groups openspy.lib) 18 | ELSE() #unix 19 | target_link_libraries(test_sbv2_server_message openspy) 20 | target_link_libraries(test_sbv2_groups openspy) 21 | ENDIF() 22 | -------------------------------------------------------------------------------- /code/test/serverbrowsing/filter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(serverbrowsing_filter_test) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 8 | 9 | add_executable (test_filter ${ALL_SRCS} test_filter.cpp) 10 | add_test(NAME test_filter COMMAND test_sbv1_groups WORKING_DIRECTORY .) 11 | 12 | target_link_libraries(test_filter openspy) -------------------------------------------------------------------------------- /code/test/serverbrowsing/filter/test_filter.cpp: -------------------------------------------------------------------------------- 1 | 2 | int main() { 3 | asdasd 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /code/utmaster/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.22) 2 | 3 | project(utmaster) 4 | 5 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 6 | 7 | file (GLOB MAIN_SRCS "*.cpp") 8 | file (GLOB MAIN_HDRS "*.h") 9 | file (GLOB SERVER_SRCS "server/*.cpp") 10 | file (GLOB SERVER_HDRS "server/*.h") 11 | file (GLOB SERVER_CMDS_SRCS "server/commands/*.cpp") 12 | file (GLOB SERVER_CMDS_HDRS "server/commands/*.h") 13 | file (GLOB TASKS_SRCS "tasks/*.cpp") 14 | file (GLOB TASKS_HDRS "tasks/*.h") 15 | 16 | 17 | set (ALL_SRCS ${SERVER_SRCS} ${SERVER_HDRS} ${TASKS_SRCS} ${SERVER_CMDS_SRCS}) 18 | 19 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CURL_INCLUDE_DIR}) 20 | 21 | source_group("Sources" FILES ${MAIN_SRCS}) 22 | source_group("Sources\\Server" FILES ${SERVER_SRCS}) 23 | source_group("Sources\\Tasks" FILES ${TASKS_SRCS}) 24 | 25 | source_group("Headers" FILES ${MAIN_HDRS}) 26 | source_group("Headers\\Server" FILES ${SERVER_HDRS}) 27 | source_group("Headers\\Tasks" FILES ${TASKS_HDRS}) 28 | 29 | add_executable (utmaster ${ALL_SRCS} ${MAIN_SRCS} ${MAIN_HDRS}) 30 | 31 | IF(WIN32) 32 | target_link_libraries(utmaster openspy.lib SharedTasks.lib ZLIB::ZLIB) 33 | ELSE() #unix 34 | target_link_libraries(utmaster openspy SharedTasks ZLIB::ZLIB) 35 | ENDIF() -------------------------------------------------------------------------------- /code/utmaster/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | #endif -------------------------------------------------------------------------------- /code/utmaster/server/UTDriver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "UTServer.h" 4 | #include "UTPeer.h" 5 | #include "UTDriver.h" 6 | 7 | namespace UT { 8 | Driver::Driver(INetServer *server, const char *host, uint16_t port) : TCPDriver(server, host, port) { 9 | } 10 | INetPeer *Driver::CreatePeer(uv_tcp_t *socket) { 11 | return new UT::Peer(this, socket); 12 | } 13 | UT::Config *Driver::FindConfigByClientName(std::string clientName) { 14 | std::vector::iterator it = m_config.begin(); 15 | 16 | while(it != m_config.end()) { 17 | UT::Config *config = *it; 18 | if(config->clientName.compare(clientName) == 0) { 19 | return config; 20 | } 21 | it++; 22 | } 23 | return NULL; 24 | } 25 | void Driver::SetConfig(std::vector config) { 26 | m_config = config; 27 | 28 | /*std::vector::iterator it = config.begin(); 29 | while (it != config.end()) { 30 | UT::Config* cfg = *it; 31 | 32 | cfg->game_data = OS::GetGameByID(cfg->gameid); 33 | it++; 34 | }*/ 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /code/utmaster/server/UTDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPDRIVER_H 2 | #define _GPDRIVER_H 3 | #include 4 | #include "../main.h" 5 | #include 6 | 7 | #include "UTPeer.h" 8 | 9 | #include 10 | #include 11 | #ifdef _WIN32 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | namespace UT { 18 | class Peer; 19 | class PackageItem { 20 | public: 21 | std::string guid; 22 | std::string hash; 23 | int version; 24 | }; 25 | class MapItem { 26 | public: 27 | int version; 28 | std::string name; 29 | std::string description; 30 | std::string url; 31 | }; 32 | class Config { 33 | public: 34 | Config() { 35 | gameid = 0; 36 | is_server = 0; 37 | latest_client_version = 0; 38 | } 39 | std::string clientName; 40 | int gameid; 41 | OS::GameData game_data; 42 | std::string motd; 43 | bool is_server; 44 | int latest_client_version; 45 | std::vector packages; 46 | std::string community_motd; 47 | std::vector maps; 48 | }; 49 | 50 | class Driver : public OS::TCPDriver { 51 | public: 52 | Driver(INetServer *server, const char *host, uint16_t port); 53 | void SetConfig(std::vector config); 54 | UT::Config *FindConfigByClientName(std::string clientName); 55 | std::vector GetConfig() { return m_config; } 56 | protected: 57 | virtual INetPeer *CreatePeer(uv_tcp_t *socket); 58 | std::vector m_config; 59 | }; 60 | } 61 | #endif //_SBDRIVER_H 62 | -------------------------------------------------------------------------------- /code/utmaster/server/UTServer.cpp: -------------------------------------------------------------------------------- 1 | #include "UTPeer.h" 2 | #include "UTServer.h" 3 | #include "UTDriver.h" 4 | 5 | namespace UT { 6 | Server::Server() : INetServer(){ 7 | uv_loop_set_data(uv_default_loop(), this); 8 | } 9 | Server::~Server() { 10 | } 11 | void Server::tick() { 12 | std::vector::iterator it = m_net_drivers.begin(); 13 | while (it != m_net_drivers.end()) { 14 | INetDriver *driver = *it; 15 | driver->think(); 16 | it++; 17 | } 18 | NetworkTick(); 19 | } 20 | void Server::shutdown() { 21 | 22 | } 23 | 24 | void Server::doInternalLoadGameData(redisContext *ctx) { 25 | std::vector::iterator it = m_net_drivers.begin(); 26 | while (it != m_net_drivers.end()) { 27 | UT::Driver *driver = (UT::Driver *)*it; 28 | std::vector cfg_list = driver->GetConfig(); 29 | std::vector::iterator it2 = cfg_list.begin(); 30 | while(it2 != cfg_list.end()) { 31 | UT::Config *cfg = *it2; 32 | cfg->game_data = OS::GetGameByID(cfg->gameid, ctx); 33 | it2++; 34 | } 35 | it++; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /code/utmaster/server/UTServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _SMSERVER_H 2 | #define _SMSERVER_H 3 | #include 4 | #include 5 | namespace MM { 6 | class UTMasterRequest; 7 | } 8 | namespace UT { 9 | class Server : public INetServer { 10 | public: 11 | Server(); 12 | virtual ~Server(); 13 | void tick(); 14 | void shutdown(); 15 | void doInternalLoadGameData(redisContext *ctx); //called by async task on startup 16 | private: 17 | }; 18 | } 19 | #endif //_SMSERVER_H 20 | -------------------------------------------------------------------------------- /code/utmaster/server/commands/handle_community_data.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../UTPeer.h" 6 | #include "../UTDriver.h" 7 | #include "../UTServer.h" 8 | #include 9 | 10 | namespace UT { 11 | void Peer::send_community_motd() { 12 | OS::Buffer send_buffer; 13 | send_buffer.WriteByte(0); 14 | Write_FString(m_config->community_motd, send_buffer); 15 | send_packet(send_buffer); 16 | 17 | } 18 | void Peer::send_community_map(UT::MapItem data) { 19 | OS::Buffer send_buffer; 20 | send_buffer.WriteByte(1); 21 | send_buffer.WriteInt(0); 22 | send_buffer.WriteInt(data.version); 23 | Write_FString(data.name, send_buffer); 24 | 25 | send_buffer.WriteByte(1); 26 | send_buffer.WriteInt(1); 27 | send_buffer.WriteInt(data.version); 28 | Write_FString(data.description, send_buffer); 29 | 30 | send_buffer.WriteByte(1); 31 | send_buffer.WriteInt(2); 32 | send_buffer.WriteInt(data.version); 33 | Write_FString(data.url, send_buffer); 34 | 35 | send_packet(send_buffer); 36 | } 37 | void Peer::handle_community_data(OS::Buffer recv_buffer) { 38 | if (m_config->is_server) return; 39 | send_community_motd(); 40 | 41 | int version = recv_buffer.ReadInt(); 42 | 43 | std::vector::iterator it = m_config->maps.begin(); 44 | while (it != m_config->maps.end()) { 45 | if (it->version > version) { 46 | send_community_map(*it); 47 | } 48 | it++; 49 | } 50 | 51 | OS::Buffer send_buffer; 52 | send_buffer.WriteByte(2); 53 | send_packet(send_buffer); 54 | 55 | Delete(); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /code/utmaster/server/commands/handle_motd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../UTPeer.h" 6 | #include "../UTDriver.h" 7 | #include "../UTServer.h" 8 | #include 9 | 10 | namespace UT { 11 | void Peer::handle_motd(OS::Buffer recv_buffer) { 12 | send_motd(); 13 | } 14 | void Peer::send_motd() { 15 | if(m_config->is_server) return; 16 | OS::Buffer send_buffer; 17 | 18 | Write_FString(m_config->motd, send_buffer); 19 | 20 | if (m_client_version >= 3000) 21 | send_buffer.WriteInt(0); //some kind of status, non-zero = update button lickable 22 | send_packet(send_buffer); 23 | Delete(); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /code/utmaster/server/commands/handle_packages_version.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../UTPeer.h" 6 | #include "../UTDriver.h" 7 | #include "../UTServer.h" 8 | #include 9 | 10 | namespace UT { 11 | void Peer::send_packages_data(uint32_t version) { 12 | std::vector packages; 13 | 14 | //calculate packages data 15 | std::vector::iterator it = this->m_config->packages.begin(); 16 | while (it != this->m_config->packages.end()) { 17 | UT::PackageItem item = *it; 18 | 19 | if (item.version > version) { 20 | packages.push_back(item); 21 | } 22 | it++; 23 | } 24 | 25 | if (packages.empty()) { 26 | return; 27 | } 28 | 29 | //send packages data 30 | OS::Buffer buffer; 31 | buffer.WriteByte(EServerOutgoingRequest_PackagesData); 32 | Write_CompactInt(buffer, packages.size()); 33 | 34 | it = packages.begin(); 35 | while (it != packages.end()) { 36 | UT::PackageItem item = *it; 37 | Write_FString(item.guid, buffer); 38 | Write_FString(item.hash, buffer); 39 | buffer.WriteInt(item.version); 40 | it++; 41 | } 42 | 43 | send_packet(buffer); 44 | 45 | } 46 | void Peer::handle_packages_version(OS::Buffer recv_buffer) { 47 | uint32_t version = recv_buffer.ReadInt(); 48 | 49 | OS::LogText(OS::ELogLevel_Info, "[%s] Got packages version: %d", getAddress().ToString().c_str(), version); 50 | 51 | 52 | if(m_gamestats_id != 0xffffffff) { 53 | send_server_gamestatsid(m_gamestats_id); //init stats backend, generate match id, for now not needed 54 | } 55 | 56 | send_packages_data(version); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /code/utmaster/server/commands/handle_stats_update.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../UTPeer.h" 6 | #include "../UTDriver.h" 7 | #include "../UTServer.h" 8 | #include 9 | 10 | namespace UT { 11 | void Peer::handle_stats_update(OS::Buffer buffer) { 12 | std::string stats_data = Read_FString(buffer); 13 | 14 | OS::LogText(OS::ELogLevel_Info, "[%s] Stats Update: %s", getAddress().ToString().c_str(), stats_data.c_str()); 15 | } 16 | } -------------------------------------------------------------------------------- /code/utmaster/server/commands/handle_uplink_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../UTPeer.h" 6 | #include "../UTDriver.h" 7 | #include "../UTServer.h" 8 | #include 9 | 10 | namespace UT { 11 | void Peer::handle_uplink_info(OS::Buffer buffer) { 12 | //send_heartbeat_request(0, 1111); 13 | //send_heartbeat_request(1, 1111); 14 | //send_heartbeat_request(2, 1111); 15 | 16 | send_detected_ports(); 17 | 18 | uint32_t behind_nat = buffer.ReadInt(), gamespy_uplink = buffer.ReadInt(); 19 | 20 | OS::LogText(OS::ELogLevel_Info, "[%s] Behind NAT: %d, GameSpy Uplink: %d", getAddress().ToString().c_str(), behind_nat, gamespy_uplink); 21 | } 22 | void Peer::send_detected_ports() { 23 | //TODO: make this actually work 24 | 25 | uint16_t game_port = 7777; 26 | 27 | OS::Buffer send_data; 28 | send_data.WriteByte(EServerOutgoingRequest_DetectedPorts); 29 | 30 | if (m_client_version >= 3000) { 31 | send_data.WriteInt(120); //??? 32 | 33 | //ports are int32? maybe there is extra data here 34 | send_data.WriteInt(game_port + 1); //7778 35 | send_data.WriteInt(game_port); //7777 36 | send_data.WriteInt(game_port + 10); //7787 37 | } 38 | else { //UT2003 - this may not even be what it is 39 | send_data.WriteByte(0); //??? 40 | 41 | //ports are int32? maybe there is extra data here 42 | send_data.WriteInt(game_port); //7777 43 | } 44 | 45 | send_packet(send_data); 46 | } 47 | } -------------------------------------------------------------------------------- /code/utmaster/tasks/PerformDeleteServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tasks.h" 4 | #include 5 | 6 | namespace MM { 7 | bool PerformDeleteServer(UTMasterRequest request, TaskThreadData *thread_data) { 8 | 9 | MMTaskResponse response; 10 | response.peer = request.peer; 11 | 12 | selectQRRedisDB(thread_data); 13 | 14 | OS::GameData game_info = request.peer->GetGameData(); 15 | std::string server_key = GetServerKey_FromIPMap(request, thread_data, game_info); 16 | 17 | if(server_key.length() > 0) { 18 | //perform delete 19 | redisReply *reply = (redisReply *) redisCommand(thread_data->mp_redis_connection, "HSET %s deleted 1", server_key.c_str()); 20 | if(reply) { 21 | freeReplyObject(reply); 22 | } 23 | 24 | std::ostringstream s; 25 | s << "\\del\\" << server_key.c_str(); 26 | std::string str = s.str(); 27 | OS::Address address = request.peer->getAddress(); 28 | TaskShared::sendAMQPMessage(mm_channel_exchange, mm_server_event_routingkey, str.c_str(), &address); 29 | } 30 | 31 | if(request.peer) { 32 | request.peer->DecRef(); 33 | } 34 | if(request.callback) { 35 | request.callback(response); 36 | } 37 | 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /code/utmaster/tasks/PerformInternalLoadGameData.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tasks.h" 4 | #include 5 | 6 | extern INetServer *g_gameserver; 7 | 8 | namespace MM { 9 | bool PerformInternalLoadGameData(UTMasterRequest request, TaskThreadData *thread_data) { 10 | 11 | UT::Server *server = (UT::Server *)g_gameserver; 12 | 13 | server->doInternalLoadGameData(thread_data->mp_redis_connection); 14 | 15 | return true; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docker-support/fesl_tos.txt: -------------------------------------------------------------------------------- 1 | OpenSpy local test -------------------------------------------------------------------------------- /docker-support/motd-community.txt: -------------------------------------------------------------------------------- 1 | This is the utmaster default docker community motd -------------------------------------------------------------------------------- /docker-support/motd.txt: -------------------------------------------------------------------------------- 1 | This is the utmaster default docker motd -------------------------------------------------------------------------------- /docker-support/password_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQDUSzsvgw80/1aMB7yoK+K8IKWOOPDBC4Jt1joBtASY72WgRNFH 3 | AxrEJGV/bCiI6wR5LKA4zTCx2uVedo4GWilWDceVomqlA6L69y0Rlu2jqix+w7nz 4 | UjINm3Sho0fG5t1y3d8uunZtt2zRgVGEMltsii4ZmreVHN9RgKfKCHqvKQIDAQAB 5 | AoGBAJ3//+S0njTLdRZzC63+O5nYkl7vcf+7GS+2KSXrXSCVzAUkMr2vSdSBYikb 6 | zm9YutOUqwqbbIpyaBOOGNYRdIEEbPFCFKzM66KLyJeqxPoQrbgloa1wJoCUEo94 7 | mUqX0DQG8XjRzfqN6tkm7Kpqr7HNJzp6WnkLTjOL5ztnhPihAkEA6cEN5HDvhPga 8 | T/ew+4NnSDdpC3Oma/cTvDV/xpBKNZtw91iyVmiyva41d5UYlC6xlqvS4FC9AwoA 9 | FH++YGsKLwJBAOh/V2tP6nmgbOVKxef5+hibDvvzEHgeFaeN4gYnnrJgeG/L+iCV 10 | 38dJ7h1wlVCyL6bq6Xb8OBjJnAYcgKQnficCQEw0IIhJfPwXOdS6BdtosiHr1nXi 11 | RO3LhYaE1lvwLBEf1Ir+Ql1DEoododaTJ4kfU8uvxjZUe9nix7XnEzQxkQcCQQC0 12 | 8MXcImndFlkpabP0Abv+Ak77DgO3N9Kqf+Vz3MnJEQMqHpkfWwS5WHQUPVY3YzVq 13 | tk/T5h7SS7U9nFkRaBrpAkA5M8FT9QVUglprRPcTD14YUCH3TqobSlQKBsjg0mxE 14 | LU+2NIfkW2DkJrZu0VXVRP8bFpVCwiBP43AFKacoI23w 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /docker-support/rsa_priv.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICWwIBAAKBgQDF4z8tj5jCKu9x6kAhVD8IYpx7OSL92oAfIT6NaM+Oa3CYlSwe 3 | Tnk5RfWj2SBUhXk29Qi+oKYDgGAh1rze+O3ocwKWhMu0/3KJ9FZB9ij2a58MHeCb 4 | IcuGCN9rwYrWo1Iv+thaLIZSDXUt9hcRpxetwjvYD8+3KyyKxM0tlOQVdQIDAQAB 5 | AoGAWUVcEfSuyCFQZcZ0adS0ntbFmv06oOR6WhDIREjdIXWslNjuzzk9jK3X07O2 6 | 1wpjlXxTFpQocHnwZDOYfsozoJc4AekGm1wVPYmjQCpUsXkV8Xz9GMrfU0JsigvB 7 | GHDqfgBkB4Q38hv1KiLp1voDxn+qyKKjZyrT3a42R8FPE+ECQQDsYRG/zYcDpofJ 8 | Lx2AwXNfGed8uWd+SVi/q9g3KSJpeaQGzaxfnroSd/g+0moGtZDk+iOG/0EbEL7k 9 | nSl1fOZJAkEA1lBA/MlJrWlVx6NdUQVbQSvSWnT4FUkG8BpvfbZlF6Bk/3rWmVQN 10 | U5WfbEPeJxvpJBND1doihR2nVaVND15FzQJAUZJN5bqvVPsq8Kppq/0WK0NtNwVk 11 | SZhWIA7VVnPDhFKN4CspyPWlkKoF6OgD3rzZe6s2h2eeuBBXT91MaVbowQJAJwJa 12 | oeidoZPvyjPhM3MvJhCs7EwoL++n9KJLMu21PvSyDZK1ZxlWh6VPbGx6DlJVQHzF 13 | NzLKX8KDB+LbwPVe7QJAG4jzKY1r2zlMppZq12s1hd4cLD8Mjf/1weslPFZjqgPj 14 | ECSHmNRzYkpROwGa2nPyzda74z43sxnZgpEH39CpgA== 15 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /docker-support/run.sh: -------------------------------------------------------------------------------- 1 | RUN_FILE_BASEDIR=/opt/openspy/bin 2 | WORKDIR=/app-workdir 3 | FILE_TO_RUN=$RUN_FILE_BASEDIR/$RUN_FILE 4 | eval cd $WORKDIR 5 | eval bash -c $FILE_TO_RUN -------------------------------------------------------------------------------- /docker-support/x509.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDBzCCAnCgAwIBAgIJAIU6bgqkPGvsMA0GCSqGSIb3DQEBBQUAMGExCzAJBgNV 3 | BAYTAlVTMQswCQYDVQQIFAIiIjELMAkGA1UEBxQCIiIxCzAJBgNVBAoUAiIiMQsw 4 | CQYDVQQLFAIiIjELMAkGA1UEAxQCIiIxETAPBgkqhkiG9w0BCQEWAiIiMB4XDTA5 5 | MDEwNDAzMTQzM1oXDTEwMDEwNDAzMTQzM1owYTELMAkGA1UEBhMCVVMxCzAJBgNV 6 | BAgUAiIiMQswCQYDVQQHFAIiIjELMAkGA1UEChQCIiIxCzAJBgNVBAsUAiIiMQsw 7 | CQYDVQQDFAIiIjERMA8GCSqGSIb3DQEJARYCIiIwgZ8wDQYJKoZIhvcNAQEBBQAD 8 | gY0AMIGJAoGBAMXjPy2PmMIq73HqQCFUPwhinHs5Iv3agB8hPo1oz45rcJiVLB5O 9 | eTlF9aPZIFSFeTb1CL6gpgOAYCHWvN747ehzApaEy7T/con0VkH2KPZrnwwd4Jsh 10 | y4YI32vBitajUi/62FoshlINdS32FxGnF63CO9gPz7crLIrEzS2U5BV1AgMBAAGj 11 | gcYwgcMwHQYDVR0OBBYEFABrEqK5EJDk5ej/7FwkRO7twWa3MIGTBgNVHSMEgYsw 12 | gYiAFABrEqK5EJDk5ej/7FwkRO7twWa3oWWkYzBhMQswCQYDVQQGEwJVUzELMAkG 13 | A1UECBQCIiIxCzAJBgNVBAcUAiIiMQswCQYDVQQKFAIiIjELMAkGA1UECxQCIiIx 14 | CzAJBgNVBAMUAiIiMREwDwYJKoZIhvcNAQkBFgIiIoIJAIU6bgqkPGvsMAwGA1Ud 15 | EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAM7HQMQQXZ8pUcry3c1qPGyMlfcsj 16 | rhub0pKACV0gJNJzb+dar57Q3VBhlr98LaEKxIj34MbDBDVvrNXR/VWrbJnHZnK4 17 | cCLL04ynGBcuJS8zXFeCZw4p64F006NU+gi6h1AYq8UVac5KczvuEk0cYxGb302h 18 | OA22HfvWuFvCENk= 19 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /vcpkg-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "default-registry": { 3 | "kind": "git", 4 | "baseline": "b7601ed37e1e1ce11a4f61b4b94a23e39d465f1d", 5 | "repository": "https://github.com/microsoft/vcpkg" 6 | }, 7 | "registries": [ 8 | { 9 | "kind": "artifact", 10 | "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", 11 | "name": "microsoft" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | "curl", 4 | { 5 | "name": "hiredis", 6 | "features": [ 7 | "ssl" 8 | ] 9 | }, 10 | "jansson", 11 | "librabbitmq", 12 | "libuv", 13 | "openssl", 14 | "pugixml" 15 | ] 16 | } 17 | --------------------------------------------------------------------------------