diff options
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp index 6cb7353..2be9c54 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -106,6 +106,8 @@ string strPoolName = "Bitflash Pool"; | |||
| 106 | string strPoolDashboardUrl; | 106 | string strPoolDashboardUrl; |
| 107 | string strPoolStatusFile; | 107 | string strPoolStatusFile; |
| 108 | double dPoolFeePercent = 0.0; | 108 | double dPoolFeePercent = 0.0; |
| 109 | bool fStratumBridge = false; | ||
| 110 | int nStratumBridgePort = 3333; | ||
| 109 | 111 | ||
| 110 | static std::atomic<uint64> gParticipantSharesSent{0}; | 112 | static std::atomic<uint64> gParticipantSharesSent{0}; |
| 111 | static std::atomic<uint64> gParticipantSharesAccepted{0}; | 113 | static std::atomic<uint64> gParticipantSharesAccepted{0}; |
| @@ -3873,6 +3875,190 @@ static bool PoolParticipantMiner() | |||
| 3873 | return true; | 3875 | return true; |
| 3874 | } | 3876 | } |
| 3875 | 3877 | ||
| 3878 | // --------------------------------------------------------------------------- | ||
| 3879 | // Local Stratum bridge -- lets external miners speak plain Stratum to | ||
| 3880 | // 127.0.0.1 while Bitflash opens the .btf tunnel to the selected pool. | ||
| 3881 | // --------------------------------------------------------------------------- | ||
| 3882 | |||
| 3883 | struct StratumBridgeClientCtx | ||
| 3884 | { | ||
| 3885 | SOCKET miner; | ||
| 3886 | std::string pool; | ||
| 3887 | }; | ||
| 3888 | |||
| 3889 | static bool BridgeSendAll(SOCKET s, const char* p, int n) | ||
| 3890 | { | ||
| 3891 | int off = 0; | ||
| 3892 | while (off < n) | ||
| 3893 | { | ||
| 3894 | int r = send(s, p + off, n - off, 0); | ||
| 3895 | if (r <= 0) | ||
| 3896 | return false; | ||
| 3897 | off += r; | ||
| 3898 | } | ||
| 3899 | return true; | ||
| 3900 | } | ||
| 3901 | |||
| 3902 | static void BridgePump(SOCKET a, SOCKET b) | ||
| 3903 | { | ||
| 3904 | char buf[8192]; | ||
| 3905 | while (!fShutdown) | ||
| 3906 | { | ||
| 3907 | fd_set rd; | ||
| 3908 | FD_ZERO(&rd); | ||
| 3909 | FD_SET(a, &rd); | ||
| 3910 | FD_SET(b, &rd); | ||
| 3911 | SOCKET maxfd = a > b ? a : b; | ||
| 3912 | struct timeval tv = {1, 0}; | ||
| 3913 | int r = select((int)maxfd + 1, &rd, NULL, NULL, &tv); | ||
| 3914 | if (r <= 0) | ||
| 3915 | continue; | ||
| 3916 | |||
| 3917 | if (FD_ISSET(a, &rd)) | ||
| 3918 | { | ||
| 3919 | int n = recv(a, buf, sizeof(buf), 0); | ||
| 3920 | if (n <= 0 || !BridgeSendAll(b, buf, n)) | ||
| 3921 | break; | ||
| 3922 | } | ||
| 3923 | if (FD_ISSET(b, &rd)) | ||
| 3924 | { | ||
| 3925 | int n = recv(b, buf, sizeof(buf), 0); | ||
| 3926 | if (n <= 0 || !BridgeSendAll(a, buf, n)) | ||
| 3927 | break; | ||
| 3928 | } | ||
| 3929 | } | ||
| 3930 | } | ||
| 3931 | |||
| 3932 | static void ThreadStratumBridgeClient(void* arg) | ||
| 3933 | { | ||
| 3934 | StratumBridgeClientCtx* ctx = (StratumBridgeClientCtx*)arg; | ||
| 3935 | SOCKET miner = ctx->miner; | ||
| 3936 | std::string pool = ctx->pool; | ||
| 3937 | delete ctx; | ||
| 3938 | |||
| 3939 | unsigned char target_pubkey[32]; | ||
| 3940 | if (!btf::ParseAddress(pool, target_pubkey)) | ||
| 3941 | { | ||
| 3942 | LogPrint("worker", "[bridge] invalid pool .btf address: %s\n", pool.c_str()); | ||
| 3943 | BtfCloseSocket(miner); | ||
| 3944 | return; | ||
| 3945 | } | ||
| 3946 | |||
| 3947 | std::string meetingHostPort; | ||
| 3948 | unsigned char service_enc_pub[32]; | ||
| 3949 | if (!BtfResolve(pool, meetingHostPort, service_enc_pub)) | ||
| 3950 | { | ||
| 3951 | LogPrint("worker", "[bridge] failed to resolve pool %s\n", pool.c_str()); | ||
| 3952 | BtfCloseSocket(miner); | ||
| 3953 | return; | ||
| 3954 | } | ||
| 3955 | |||
| 3956 | size_t colon = meetingHostPort.rfind(':'); | ||
| 3957 | if (colon == std::string::npos) | ||
| 3958 | { | ||
| 3959 | LogPrint("worker", "[bridge] bad pool endpoint '%s'\n", meetingHostPort.c_str()); | ||
| 3960 | BtfCloseSocket(miner); | ||
| 3961 | return; | ||
| 3962 | } | ||
| 3963 | std::string host = meetingHostPort.substr(0, colon); | ||
| 3964 | int port = atoi(meetingHostPort.substr(colon + 1).c_str()); | ||
| 3965 | if (port <= 0 || port > 65535) | ||
| 3966 | { | ||
| 3967 | LogPrint("worker", "[bridge] bad pool port in '%s'\n", meetingHostPort.c_str()); | ||
| 3968 | BtfCloseSocket(miner); | ||
| 3969 | return; | ||
| 3970 | } | ||
| 3971 | |||
| 3972 | SOCKET poolSock = btf::BtfClientTunnel(host.c_str(), (unsigned short)port, | ||
| 3973 | target_pubkey, service_enc_pub); | ||
| 3974 | if (poolSock == INVALID_SOCKET) | ||
| 3975 | { | ||
| 3976 | LogPrint("worker", "[bridge] tunnel connect failed for pool %s via %s\n", | ||
| 3977 | pool.c_str(), meetingHostPort.c_str()); | ||
| 3978 | BtfCloseSocket(miner); | ||
| 3979 | return; | ||
| 3980 | } | ||
| 3981 | |||
| 3982 | LogPrint("worker", "[bridge] miner connected to pool %s via %s\n", | ||
| 3983 | pool.c_str(), meetingHostPort.c_str()); | ||
| 3984 | BridgePump(miner, poolSock); | ||
| 3985 | BtfCloseSocket(poolSock); | ||
| 3986 | BtfCloseSocket(miner); | ||
| 3987 | LogPrint("worker", "[bridge] miner disconnected from pool %s\n", pool.c_str()); | ||
| 3988 | } | ||
| 3989 | |||
| 3990 | void ThreadStratumBridge(void*) | ||
| 3991 | { | ||
| 3992 | if (strParticipantPool.empty()) | ||
| 3993 | { | ||
| 3994 | printf("Stratum bridge: no pool selected. Use /stratumbridge=POOL_BTF_ADDRESS\n"); | ||
| 3995 | return; | ||
| 3996 | } | ||
| 3997 | |||
| 3998 | SOCKET listener = BtfSocketTag(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP), | ||
| 3999 | SOCK_STRATUM_BRIDGE); | ||
| 4000 | if (listener == INVALID_SOCKET) | ||
| 4001 | { | ||
| 4002 | printf("Stratum bridge: could not create listen socket\n"); | ||
| 4003 | return; | ||
| 4004 | } | ||
| 4005 | |||
| 4006 | int yes = 1; | ||
| 4007 | setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); | ||
| 4008 | |||
| 4009 | sockaddr_in addr; | ||
| 4010 | memset(&addr, 0, sizeof(addr)); | ||
| 4011 | addr.sin_family = AF_INET; | ||
| 4012 | addr.sin_addr.s_addr = htonl(0x7f000001); | ||
| 4013 | addr.sin_port = htons((unsigned short)nStratumBridgePort); | ||
| 4014 | |||
| 4015 | if (bind(listener, (sockaddr*)&addr, sizeof(addr)) != 0 || | ||
| 4016 | listen(listener, 16) != 0) | ||
| 4017 | { | ||
| 4018 | printf("Stratum bridge: could not listen on 127.0.0.1:%d\n", | ||
| 4019 | nStratumBridgePort); | ||
| 4020 | BtfCloseSocket(listener); | ||
| 4021 | return; | ||
| 4022 | } | ||
| 4023 | |||
| 4024 | printf("Stratum bridge: listening on 127.0.0.1:%d for pool %s\n", | ||
| 4025 | nStratumBridgePort, strParticipantPool.c_str()); | ||
| 4026 | |||
| 4027 | while (!fShutdown) | ||
| 4028 | { | ||
| 4029 | fd_set rd; | ||
| 4030 | FD_ZERO(&rd); | ||
| 4031 | FD_SET(listener, &rd); | ||
| 4032 | struct timeval tv = {1, 0}; | ||
| 4033 | if (select((int)listener + 1, &rd, NULL, NULL, &tv) <= 0) | ||
| 4034 | continue; | ||
| 4035 | |||
| 4036 | sockaddr_in cli; | ||
| 4037 | #ifdef _WIN32 | ||
| 4038 | int len = sizeof(cli); | ||
| 4039 | #else | ||
| 4040 | socklen_t len = sizeof(cli); | ||
| 4041 | #endif | ||
| 4042 | SOCKET miner = BtfSocketTag(accept(listener, (sockaddr*)&cli, &len), | ||
| 4043 | SOCK_STRATUM_BRIDGE); | ||
| 4044 | if (miner == INVALID_SOCKET) | ||
| 4045 | continue; | ||
| 4046 | |||
| 4047 | StratumBridgeClientCtx* ctx = new StratumBridgeClientCtx(); | ||
| 4048 | ctx->miner = miner; | ||
| 4049 | ctx->pool = strParticipantPool; | ||
| 4050 | if (_beginthread(ThreadStratumBridgeClient, 0, ctx) == (uintptr_t)-1) | ||
| 4051 | { | ||
| 4052 | delete ctx; | ||
| 4053 | BtfCloseSocket(miner); | ||
| 4054 | LogPrint("worker", "[bridge] failed to spawn client thread\n"); | ||
| 4055 | } | ||
| 4056 | } | ||
| 4057 | |||
| 4058 | BtfCloseSocket(listener); | ||
| 4059 | printf("Stratum bridge: stopped\n"); | ||
| 4060 | } | ||
| 4061 | |||
| 3876 | bool BitcoinMiner(int nThreadId) | 4062 | bool BitcoinMiner(int nThreadId) |
| 3877 | { | 4063 | { |
| 3878 | // Relay mode: never mines, just relays/syncs. (Shouldn't normally get here | 4064 | // Relay mode: never mines, just relays/syncs. (Shouldn't normally get here |