Merge 7ae9a737ab
into 531c657b64
This commit is contained in:
commit
7e6ce53b18
6 changed files with 212 additions and 127 deletions
|
@ -27,6 +27,8 @@
|
|||
#include <string.h>
|
||||
#include <utility>
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "interfaces/IClientListener.h"
|
||||
#include "log/Log.h"
|
||||
|
@ -55,6 +57,8 @@ int64_t Client::m_sequence = 1;
|
|||
|
||||
Client::Client(int id, const char *agent, IClientListener *listener) :
|
||||
m_quiet(false),
|
||||
m_keystream(),
|
||||
m_encrypted(false),
|
||||
m_agent(agent),
|
||||
m_listener(listener),
|
||||
m_id(id),
|
||||
|
@ -68,6 +72,7 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
|
|||
{
|
||||
memset(m_ip, 0, sizeof(m_ip));
|
||||
memset(&m_hints, 0, sizeof(m_hints));
|
||||
memset(m_keystream, 0, sizeof(m_keystream));
|
||||
|
||||
m_resolver.data = this;
|
||||
|
||||
|
@ -128,6 +133,16 @@ void Client::setUrl(const Url *url)
|
|||
return;
|
||||
}
|
||||
|
||||
if (url->hasKeystream())
|
||||
{
|
||||
url->copyKeystream(m_keystream, sizeof(m_keystream));
|
||||
m_encrypted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_encrypted = false;
|
||||
}
|
||||
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
|
@ -271,14 +286,30 @@ int Client::resolve(const char *host)
|
|||
}
|
||||
|
||||
|
||||
int64_t Client::send(size_t size)
|
||||
int64_t Client::send(size_t size, const bool encrypted)
|
||||
{
|
||||
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf);
|
||||
if (state() != ConnectedState || !uv_is_writable(m_stream)) {
|
||||
if ((state() != ConnectedState && state() != ProxingState) || !uv_is_writable(m_stream)) {
|
||||
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(encrypted && m_encrypted)
|
||||
{
|
||||
// Encrypt
|
||||
for(size_t i = 0; i < std::min(size, sizeof(m_keystream)); ++i)
|
||||
{
|
||||
m_sendBuf[i] ^= m_keystream[i];
|
||||
}
|
||||
|
||||
char * send_encr_hex = static_cast<char*>(malloc(size * 2 + 1));
|
||||
memset(send_encr_hex, 0, size * 2 + 1);
|
||||
Job::toHex((const unsigned char*)m_sendBuf, size, send_encr_hex);
|
||||
send_encr_hex[size * 2] = '\0';
|
||||
LOG_DEBUG("[%s:%u] send encr. (%d bytes): \"0x%s\"", m_url.host(), m_url.port(), size, send_encr_hex);
|
||||
free(send_encr_hex);
|
||||
}
|
||||
|
||||
uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size);
|
||||
|
||||
if (uv_try_write(m_stream, &buf, 1) < 0) {
|
||||
|
@ -328,6 +359,27 @@ void Client::connect(struct sockaddr *addr)
|
|||
uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect);
|
||||
}
|
||||
|
||||
void Client::prelogin()
|
||||
{
|
||||
if (m_url.proxyHost())
|
||||
{
|
||||
setState (ProxingState);
|
||||
const std::string buffer = std::string ("CONNECT ") + m_url.finalHost() + ":" + std::to_string(m_url.finalPort()) + " HTTP/1.1\n";
|
||||
|
||||
const size_t size = buffer.size();
|
||||
memcpy (m_sendBuf, buffer.c_str(), size);
|
||||
m_sendBuf[size] = '\n';
|
||||
m_sendBuf[size + 1] = '\0';
|
||||
|
||||
LOG_DEBUG("Prelogin send (%d bytes): \"%s\"", size, m_sendBuf);
|
||||
send (size + 1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
setState (ConnectedState);
|
||||
login();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::login()
|
||||
{
|
||||
|
@ -565,12 +617,11 @@ void Client::onConnect(uv_connect_t *req, int status)
|
|||
|
||||
client->m_stream = static_cast<uv_stream_t*>(req->handle);
|
||||
client->m_stream->data = req->data;
|
||||
client->setState(ConnectedState);
|
||||
|
||||
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
|
||||
delete req;
|
||||
|
||||
client->login();
|
||||
client->prelogin();
|
||||
}
|
||||
|
||||
|
||||
|
@ -589,12 +640,43 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
|
|||
return client->close();
|
||||
}
|
||||
|
||||
if (client->state() == ProxingState)
|
||||
{
|
||||
const char* const content = buf->base;
|
||||
LOG_DEBUG("[%s:%u] received from proxy (%d bytes): \"%s\"",
|
||||
client->m_url.host(), client->m_url.port(),
|
||||
nread, content);
|
||||
|
||||
if(content == strstr(content, "HTTP/1.1 200"))
|
||||
{
|
||||
LOG_INFO("[%s:%u] Proxy connected to %s:%u!", client->m_url.host(), client->m_url.port(), client->m_url.finalHost(), client->m_url.finalPort());
|
||||
client->setState(ConnectedState);
|
||||
client->login();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
client->m_recvBufPos += nread;
|
||||
|
||||
char* end;
|
||||
char* start = buf->base;
|
||||
size_t remaining = client->m_recvBufPos;
|
||||
|
||||
if(client->m_encrypted)
|
||||
{
|
||||
char * read_encr_hex = static_cast<char*>(malloc(nread * 2 + 1));
|
||||
memset(read_encr_hex, 0, nread * 2 + 1);
|
||||
Job::toHex((const unsigned char*)start, nread, read_encr_hex);
|
||||
LOG_DEBUG("[%s] read encr. (%d bytes): \"0x%s\"", client->m_ip, nread, read_encr_hex);
|
||||
free(read_encr_hex);
|
||||
|
||||
// DeEncrypt
|
||||
for(int i = 0; i < (int)nread; ++i)
|
||||
{
|
||||
start[i] ^= client->m_keystream[i];
|
||||
}
|
||||
}
|
||||
|
||||
while ((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr) {
|
||||
end++;
|
||||
size_t len = end - start;
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
UnconnectedState,
|
||||
HostLookupState,
|
||||
ConnectingState,
|
||||
ProxingState,
|
||||
ConnectedState,
|
||||
ClosingState
|
||||
};
|
||||
|
@ -78,9 +79,10 @@ private:
|
|||
bool parseJob(const rapidjson::Value ¶ms, int *code);
|
||||
bool parseLogin(const rapidjson::Value &result, int *code);
|
||||
int resolve(const char *host);
|
||||
int64_t send(size_t size);
|
||||
int64_t send(size_t size, const bool encrypted = true);
|
||||
void close();
|
||||
void connect(struct sockaddr *addr);
|
||||
void prelogin();
|
||||
void login();
|
||||
void parse(char *line, size_t len);
|
||||
void parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error);
|
||||
|
@ -104,6 +106,8 @@ private:
|
|||
char m_ip[17];
|
||||
char m_rpcId[64];
|
||||
char m_sendBuf[768];
|
||||
char m_keystream[sizeof(m_sendBuf)];
|
||||
bool m_encrypted;
|
||||
const char *m_agent;
|
||||
IClientListener *m_listener;
|
||||
int m_id;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
#include "net/Url.h"
|
||||
|
@ -41,7 +42,10 @@ Url::Url() :
|
|||
m_host(nullptr),
|
||||
m_password(nullptr),
|
||||
m_user(nullptr),
|
||||
m_port(kDefaultPort)
|
||||
m_port(kDefaultPort),
|
||||
m_proxy_host(nullptr),
|
||||
m_proxy_port(kDefaultProxyPort),
|
||||
m_keystream(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -63,7 +67,10 @@ Url::Url(const char *url) :
|
|||
m_host(nullptr),
|
||||
m_password(nullptr),
|
||||
m_user(nullptr),
|
||||
m_port(kDefaultPort)
|
||||
m_port(kDefaultPort),
|
||||
m_proxy_host(nullptr),
|
||||
m_proxy_port(kDefaultProxyPort),
|
||||
m_keystream(nullptr)
|
||||
{
|
||||
parse(url);
|
||||
}
|
||||
|
@ -74,7 +81,10 @@ Url::Url(const char *host, uint16_t port, const char *user, const char *password
|
|||
m_nicehash(nicehash),
|
||||
m_password(password ? strdup(password) : nullptr),
|
||||
m_user(user ? strdup(user) : nullptr),
|
||||
m_port(port)
|
||||
m_port(port),
|
||||
m_proxy_host(nullptr),
|
||||
m_proxy_port(kDefaultProxyPort),
|
||||
m_keystream(nullptr)
|
||||
{
|
||||
m_host = strdup(host);
|
||||
}
|
||||
|
@ -85,9 +95,10 @@ Url::~Url()
|
|||
free(m_host);
|
||||
free(m_password);
|
||||
free(m_user);
|
||||
free(m_proxy_host);
|
||||
free(m_keystream);
|
||||
}
|
||||
|
||||
|
||||
bool Url::parse(const char *url)
|
||||
{
|
||||
const char *p = strstr(url, "://");
|
||||
|
@ -116,7 +127,44 @@ bool Url::parse(const char *url)
|
|||
memcpy(m_host, base, size - 1);
|
||||
m_host[size - 1] = '\0';
|
||||
|
||||
const char* proxy = strchr(port, '@');
|
||||
const char* keystream = strchr(port, '#');
|
||||
if(keystream)
|
||||
{
|
||||
++keystream;
|
||||
if(!proxy)
|
||||
{
|
||||
m_keystream = strdup(keystream);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t keystreamsize = proxy - keystream;
|
||||
m_keystream = static_cast<char*>(malloc (keystreamsize + 1));
|
||||
m_keystream[keystreamsize] = '\0';
|
||||
memcpy(m_keystream, keystream, keystreamsize);
|
||||
}
|
||||
}
|
||||
|
||||
m_port = (uint16_t) strtol(port, nullptr, 10);
|
||||
if (!proxy) {
|
||||
m_port = (uint16_t) strtol(port, nullptr, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
++proxy;
|
||||
|
||||
const char* proxyport = strchr(proxy, ':');
|
||||
if (!port) {
|
||||
m_proxy_host = strdup(proxy);
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t proxysize = proxyport++ - proxy + 1;
|
||||
m_proxy_host = static_cast<char*>(malloc (proxysize));
|
||||
memcpy(m_proxy_host, proxy, proxysize - 1);
|
||||
m_proxy_host[proxysize - 1] = '\0';
|
||||
m_proxy_port = (uint16_t) strtol(proxyport, nullptr, 10);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -177,18 +225,46 @@ void Url::setUser(const char *user)
|
|||
m_user = strdup(user);
|
||||
}
|
||||
|
||||
void Url::copyKeystream(char *keystreamDest, const size_t keystreamLen) const
|
||||
{
|
||||
if(hasKeystream())
|
||||
{
|
||||
memset(keystreamDest, 1, keystreamLen);
|
||||
memcpy(keystreamDest, m_keystream, std::min(keystreamLen, strlen(m_keystream)));
|
||||
}
|
||||
}
|
||||
|
||||
Url &Url::operator=(const Url *other)
|
||||
{
|
||||
m_keepAlive = other->m_keepAlive;
|
||||
m_nicehash = other->m_nicehash;
|
||||
m_port = other->m_port;
|
||||
m_proxy_port = other->m_proxy_port;
|
||||
|
||||
free(m_host);
|
||||
m_host = strdup(other->m_host);
|
||||
|
||||
free (m_proxy_host);
|
||||
if(other->m_proxy_host)
|
||||
{
|
||||
m_proxy_host = strdup (other->m_proxy_host);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_proxy_host = nullptr;
|
||||
}
|
||||
|
||||
setPassword(other->m_password);
|
||||
setUser(other->m_user);
|
||||
|
||||
free (m_keystream);
|
||||
if(other->m_keystream)
|
||||
{
|
||||
m_keystream = strdup (other->m_keystream);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_keystream = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
constexpr static const char *kDefaultPassword = "x";
|
||||
constexpr static const char *kDefaultUser = "x";
|
||||
constexpr static uint16_t kDefaultPort = 3333;
|
||||
constexpr static uint16_t kDefaultProxyPort = 8080;
|
||||
|
||||
Url();
|
||||
Url(const char *url);
|
||||
|
@ -43,10 +44,16 @@ public:
|
|||
inline bool isKeepAlive() const { return m_keepAlive; }
|
||||
inline bool isNicehash() const { return m_nicehash; }
|
||||
inline bool isValid() const { return m_host && m_port > 0; }
|
||||
inline const char *host() const { return m_host; }
|
||||
inline bool hasKeystream() const { return m_keystream; }
|
||||
inline const char *host() const { return isProxyed() ? proxyHost() : finalHost(); }
|
||||
inline const char *password() const { return m_password ? m_password : kDefaultPassword; }
|
||||
inline const char *user() const { return m_user ? m_user : kDefaultUser; }
|
||||
inline uint16_t port() const { return m_port; }
|
||||
inline uint16_t port() const { return isProxyed() ? proxyPort() : finalPort(); }
|
||||
inline bool isProxyed() const { return proxyHost(); }
|
||||
inline const char* finalHost() const { return m_host; }
|
||||
inline uint16_t finalPort() const { return m_port; }
|
||||
inline const char* proxyHost() const { return m_proxy_host; }
|
||||
inline uint16_t proxyPort() const { return m_proxy_port; }
|
||||
inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; }
|
||||
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
|
||||
|
||||
|
@ -55,6 +62,7 @@ public:
|
|||
void applyExceptions();
|
||||
void setPassword(const char *password);
|
||||
void setUser(const char *user);
|
||||
void copyKeystream(char *keystreamDest, const size_t keystreamLen) const;
|
||||
|
||||
Url &operator=(const Url *other);
|
||||
|
||||
|
@ -65,6 +73,9 @@ private:
|
|||
char *m_password;
|
||||
char *m_user;
|
||||
uint16_t m_port;
|
||||
char* m_proxy_host;
|
||||
uint16_t m_proxy_port;
|
||||
char* m_keystream;
|
||||
};
|
||||
|
||||
#endif /* __URL_H__ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue