Telegrambot для слежения за майнером
![](http://istarik.ru/uploads/images/00/00/01/2017/10/04/8ce340.png)
Здравствуйте.
В сети встречается уже не мало программ для управления майнерами через мессенджер
В качестве доп. функций, умеет показывать курсы криптовалют.
![](http://istarik.ru/uploads/images/00/00/01/2017/10/21/11ad44.png)
Сервер teleminerstd написан
Работает следующим образом: в конфигурационный файл программы вписываете команду запуска Вашего майнера
![](http://istarik.ru/uploads/images/00/00/01/2017/10/05/c3ce09.png)
Открываете приложение Telegram на вашем смартфоне, отправляете боту команду
![](http://istarik.ru/uploads/images/00/00/01/2017/10/05/60e6ce.png)
Далее подробно обо всём…
Установите приложение
Теперь нужно создать Телеграмбота, подготовить ssl-сертификат и установить Webhook. Весь этот несложный процесс я подробно описал в соседней статье, начиная отсюда и до фразы — «Всё что касается Telegram мы сделали…».
Наконец пришло время заняться программой teleminerstd. В домашней папке создайте папку teleminer и перейдите в неё:
mkdir teleminer && cd teleminer
Скачайте программу и конфиг-файл:
wget https://istarik.ru/file/teleminerstd
wget https://istarik.ru/file/teleminerstd.conf
А так же крохотную библиотеку:
wget https://istarik.ru/file/line_buffer.so
Дайте программе все права:
sudo chmod 777 ./teleminerstd
И наконец, скопируйте в эту же папку созданный Вами файл cert.pem.
В итоге, в папке teleminer у Вас будут четыре файла — teleminerstd, teleminerstd.conf, line_buffer.so, cert.pem.
Наглядный конфиг-файл
port=8443
token=703562402:AAEoqwe5ghP9_ccbXreHsDD1n1m56Nwer1P
pminer=/home/dima/miner/miner --server zec.suprnova.cc --user Dimon.dimka --pass wor789rtyu --port 2142 --pec
globchatid=
data_on=vkldat
data_off=otkldat
all_off=otklall
count_dat=20
reb_komp=KfErEstDim41g
off_komp=zSDimErPst35F
rest_mainer=AsDaErEsSfW
comamd_info=rEsSfWKfErQ
port=впишите порт, который указывали при установке Webhook'а. Не забудьте пробросить его на роутере.
token=Ваш токен.
pminer=путь к майнеру вместе с аргументами.
Если запускаете nheqminer или Claymore's, тогда в конце команды впишите такую конструкцию — 2>&1
globchatid= — пока ничего не пишите.
data_on=команда включающая отправку всех сообщений от майнера в Телеграм.
data_off=команда отключающая отправку сообщений от майнера, кроме сообщений сигнализирующих об ошибках.
all_off=команда отключающая вообще все сообщения от майнера. Отменяется командой vkldat.
Команды можете придумать любые (желательно посложнее), но только английскими буквами и не больше 14 символов.
count_dat=количество сообщений, которые будут отправлены после команды vkldat. Можно вписать любое число. Если хотите чтоб сообщения отсылались постоянно, то впишите 99000000, однако мне кажется это излишним
![](http://istarik.ru/uploads/images/00/00/01/2017/10/05/48e83d.png)
Тем более, как было замечено, если заваливать
reb_komp=это команда для перезагрузки компьютера/фермы, поэтому нужно обязательно придумать какую-нибудь хитрую и длинную
off_komp=эта команда выключает компьютер/ферму (команда должна быть хитрая и длинная).
rest_mainer=эта команда служит для рестарта майнера, на тот случай если он «упадёт (опять же, команда должна быть хитрая и длинная).
comamd_info=эта команда тоже должна быть секретная, она выводит список всех команд. Так что нужно запоминать только её.
![](http://istarik.ru/uploads/images/00/00/01/2017/10/26/bd56b5.png)
После заполнения конфиг-файла можно запустить teleminerstd
sudo ./teleminerstd
Для остановки сервера используйте только —
После старта программа покажет то, что прочитала из конфига, а потом побегут строки майнера:
![](http://istarik.ru/uploads/images/00/00/01/2017/10/05/8b02fd.png)
Теперь в Телеграме кликните своего бота, нажмите START и отправьте букву t. Если всё работает, то в ответ Вы получите слово TEST.
![](http://istarik.ru/uploads/images/00/00/01/2017/10/05/7bcf2a.png)
В терминале среди прочих строк будет Chat_id:617455910 (у вас будет другое число):
![](http://istarik.ru/uploads/images/00/00/01/2017/10/13/e84df8.png)
Это ID Вашего клиента. Его нужно вписать в конфиг-файл — globchatid=
Тут требуется небольшое пояснение: когда Вы посылаете какую-либо команду, вместе с командой сервер получает id клиента, которому нужно отправить данные. Однако предположим, что если teleminerstd добавлен в автозагрузку, то после ребута фермы он не будет знать кому отправлять данные. Вот тут то и понадобится id вашего клиента записанный конфиге.
Если в процессе работы Вы будете отправлять команды с разных клиентов, тогда id будет меняться внутри программы.
Теперь при старте, в
![](http://istarik.ru/uploads/images/00/00/01/2017/10/08/8a2314.png)
… а следом побегут строки от майнера:
![](http://istarik.ru/uploads/images/00/00/01/2017/10/22/c2740f.png)
Строк будет выведено столько, сколько указано в конфиге (count_dat). Зачастую строки идут не по порядку, но это происходит тогда, когда единовременно отправляется много данных.
Далее попробуйте командами vkldat и otkldat включать и отключать вывод данных в
![](http://istarik.ru/uploads/images/00/00/01/2017/10/05/e05890.png)
Если не посылать команду otkldat, то (как уже выше написано) будет выведено столько строк, сколько указано в конфиге.
Теперь намеренно сделайте ошибку в конфиге, в адресе пула (zec.prnova.cc) и перезапустите teleminerstd:
![](http://istarik.ru/uploads/images/00/00/01/2017/10/20/a5af5b.png)
Майнер будет запущен, но выдав ошибку тут же „самоубьется“
![](http://istarik.ru/uploads/images/00/00/01/2017/10/22/dded47.png)
Разные майнеры по разному и с разной частотой выдают ошибки и варнинги, могут выдать одну ошибку и остановиться или продолжать нормальную работу, а могут работать и сыпать ошибки непрерывно. Поскольку сообщения об ошибках отправляются автоматически, (то есть даже при „otkldat“), это может принести дискомфорт. Для этого у программы есть счётчик ошибок, который при превышений числа 10, останавливает отправку и пишет „END MSG ERROR“.
![](http://istarik.ru/uploads/images/00/00/01/2017/10/09/73e37a.png)
После этого, если счётчик не будет обнулён, то запустится таймер, который будет отправлять по одной ошибке с интервалом не менее 10 минут.
Чтобы обнулить счётчик ошибок, нужно послать ту же команду, что и для отправки всех сообщений (»vkldat"), а если хотите отключить вообще любые сообщения, тогда отправьте команду («otklall»).
На все полученные команды, teleminerstd отвечает соответствующими сообщениями.
Свои ошибки teleminerstd пишет в файл — Errteleminerstd.log, который создаётся в папке вместе с программой и очищается при превышении 4Кб.
Помимо ошибок, в этот файл записываются некоторые ответственные действия, например команды выключения или перезагрузки
Дополнительные функции
С помощью команды rate,coin можно узнать курс какой-либо криптовалюты. После слова rate,, через запятую и без пробелов, впишите название интересующей монеты.
Например bitcoin или ethereum:
![](http://istarik.ru/uploads/images/00/00/01/2017/10/26/aaf515.png)
Ссылка ведёт на сайт с графиками.
В терминале это тоже отобразится:
![](http://istarik.ru/uploads/images/00/00/01/2017/10/26/f36414.png)
Как видно из картинки, инфа берётся с сайта coinmarketcap.com, они предоставляют API, поэтому удобно.
Под спойлером список валют, взятый отсюда.
названия крипты
Вначале идёт популярная. Ешё болше названий смотрите по ссылке выше.
bitcoin, ethereum, ripple, litecoin, ethereum-classic, nem, dash, iota, bitshares, monero,
stratis, zcash, golem-network-tokens, siacoin, steem, waves, bytecoin-bcn, iconomi, antshares,
bitconnect, stellar, dogecoin, augur, lisk, gamecredits, factom, gnosis-gno, ardor,
maidsafecoin, byteball, decred, veritaseum, digibyte, komodo, digixdao, nxt,
basic-attention-token, tether, firstblood, mobilego, bancor, singulardtv, syscoin, pivx,
bitcoindark, mcap, aragon, round, emercoin, peercoin, ubiq, lykke, numeraire, cloakcoin,
ark, rlc, leocoin, reddcoin, quantum-resistant-ledger, storjcoin-x, asch, melon, nexus, synereo,
library-credit, bitbay, peerplays-ppy, wings, edgeless, verge, omni, namecoin, counterparty,
mysterium, gulden, monacoin, blackcoin, obits, elastic, xaurum, zcoin, burst, viacoin, vslice,
ion, vertcoin, earthcoin, humaniq, cofound-it, ybcoin, blocknet, nav-coin, etheroll, trust,
gridcoin, potcoin, mooncoin, luckchain, expanse, e-dinar-coin, tokencard, quantum, guppy, taas,
radium, shift, neoscoin, bitcoin-plus, iocoin, skycoin, crown, digitalnote, energycoin, novacoin,
nexium, bcap, worldcoin, dnotes, databits, unity-ingot, monetaryunit, lomocoin, primecoin,
swarm-city, chronobank, heat-ledger, mergecoin, foldingcoin, infinitecoin, patientory, feathercoin,
quark, einsteinium, voxels, vpncoin, e-coin, espers, vericoin, rubycoin, golos, faircoin,
bitcrystals, firstcoin, clams, agoras-tokens, sibcoin, pluton, pepe-cash, bitcny, florincoin, megacoin,
salus, xtrabytes, waves-community-token, belacoin, cryptonite, pascal-coin, eccoin, bankcoin,
gambit, zencash, safe-exchange-coin, aeon, bitshares-music, dubaicoin-dbix, circuits-of-value,
solarcoin, sphere, zccoin, bitland, pinkcoin, lunyr, okcash, maxcoin, spreadcoin, bitbean,
blitzcash, spectrecoin, unobtanium, bitusd, creditbit, applebyte, ethereum-movie-venture,
zetacoin, musicoin, raiblocks, vcash, digitalcoin, diamond, nautiluscoin, myriad,
roulettetoken, groestlcoin, darcrus, riecoin, global-currency-reserve, atmos, boostcoin,
rise, sequence, steem-dollars, curecoin, apx, incent, icash, auroracoin, janus, ico-openledger,
putincoin, zeitcoin, korecoin, bitmark, goldcoin, synergy, project-decorum, triggers, bitsend,
zclassic, breakout-stake, cannabiscoin, huntercoin, idice, anoncoin, altcoin-alt,
mediterraneancoin, legends-room, bata, fedoracoin, boolberry, zennies, breakout,
veriumreserve, xcurrency, stealthcoin, tickets, mintcoin, securecoin, minereum,
tagcoin, creativecoin, qwark, vtorrent, bitswift, blockpay, insanecoin, inpay,
transfercoin, dimecoin, dopecoin, 1337, cryptocarbon, startcoin, hush, 2give, geocoin,
Исходники
teleminerstd.c
line_buffer.c
#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <unistd.h>
#include <openssl/err.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <resolv.h>
#include <netdb.h>
#include <time.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/stat.h>
#define BREADSIZE 2048
#define COMANDSIZE 16
#define TOKENSIZE 64
#define IDSIZE 16
#define PMINERSIZE 512
#define YES 1
#define NO 0
int fd;
int counter = 0;
int count_error = 0;
int port = 0;
char token[TOKENSIZE] = {0,};
char glob_chat_id[IDSIZE] = {0,};
char res_pminer[PMINERSIZE] = {0,};
char vkl_data = 'A';
char data_on[COMANDSIZE] = {0,};
char data_off[COMANDSIZE] = {0,};
char all_off[COMANDSIZE] = {0,};
int count_dat = 0;
char reb_komp[COMANDSIZE] = {0,};
char off_komp[COMANDSIZE] = {0,};
char rest_mainer[COMANDSIZE] = {0,};
char comamd_info[COMANDSIZE] = {0,};
int work_miner = NO;
/////////////////////////////////////////////////// error_log ///////////////////////////////////////////////////////
void error_log(char *my_error)
{
time_t t;
time(&t);
FILE *f;
struct stat st;
stat("Errteleminerstd.log",&st);
if(st.st_size < 4096) f = fopen("Errteleminerstd.log", "a");
else f = fopen("Errteleminerstd.log", "w");
if(f == NULL)
{
printf("Error open Errteleminerstd.log.\n");
exit(0);
}
fprintf(f, "%s", ctime( &t));
fprintf(f, "Error: %s\n\n", my_error);
printf("Error: %s Write to Errteleminerstd.log.\n", my_error);
fclose(f);
if(my_error[strlen(my_error) - 1] == '!') exit(0);
}
/////////////////////////////////////////////////// read_conf ///////////////////////////////////////////////////////
void read_conf()
{
FILE *mf;
mf = fopen ("teleminerstd.conf","r");
if(mf == NULL) error_log("config-file!");
printf ("Open config file.\n");
while(1)
{
char *restr = NULL;
char str[300] = {0,};
restr = fgets(str, 299, mf);
if(restr == NULL)
{
if(feof(mf) != 0) break;
else error_log("read from config file!");
}
if(strstr(str,"port=") != NULL)
{
port = atoi(str + 5);
printf("Port=%d\n", port);
}
else if(strstr(str, "token=") != NULL)
{
strncpy(token, str + 6, (int)strlen(str) - 7);
printf("Token=%s\n", token);
}
else if(strstr(str, "pminer=") != NULL)
{
char *pminer = (char*)malloc((int)strlen(str));
strncpy(pminer, str + 7, (int)strlen(str) - 8);
snprintf(res_pminer, 29 + strlen(pminer), "LD_PRELOAD=./line_buffer.so %s", pminer);
printf("Pminer=%s\n", pminer);
free(pminer);
}
else if(strstr(str, "globchatid=") != NULL)
{
strncpy(glob_chat_id, str + 11, (int)strlen(str) - 12);
printf("Globchatid=%s\n", glob_chat_id);
}
else if(strstr(str, "data_on=") != NULL)
{
strncpy(data_on, str + 8, (int)strlen(str) - 9);
printf("Data_on=%s\n", data_on);
}
else if(strstr(str, "data_off=") != NULL)
{
strncpy(data_off, str + 9, (int)strlen(str) - 10);
printf("Data_off=%s\n", data_off);
}
else if(strstr(str, "all_off=") != NULL)
{
strncpy(all_off, str + 8, (int)strlen(str) - 9);
printf("All_off=%s\n", all_off);
}
else if(strstr(str,"count_dat=") != NULL)
{
count_dat = atoi(str + 10);
printf("Count_dat=%d\n", count_dat);
}
else if(strstr(str, "reb_komp=") != NULL)
{
strncpy(reb_komp, str + 9, (int)strlen(str) - 10);
printf("Reb_komp=%s\n", reb_komp);
}
else if(strstr(str, "off_komp=") != NULL)
{
strncpy(off_komp, str + 9, (int)strlen(str) - 10);
printf("Off_komp=%s\n", off_komp);
}
else if(strstr(str, "rest_mainer=") != NULL)
{
strncpy(rest_mainer, str + 12, (int)strlen(str) - 13);
printf("Rest_mainer=%s\n", rest_mainer);
}
else if(strstr(str, "comamd_info=") != NULL)
{
strncpy(comamd_info, str + 12, (int)strlen(str) - 13);
printf("Comamd_info=%s\n", comamd_info);
}
else break;
} // END while
if(fclose(mf) == EOF) error_log("mf EOF!");
printf ("Close config file.\n");
} // END read_conf
/////////////////////////////////////////////////// child_kill ///////////////////////////////////////////////////////
void child_kill() { wait(NULL); }
void child_kill2() { wait(NULL); }
/////////////////////////////////////////////////// time count ///////////////////////////////////////////////////////
void * timecount_func()
{
for(;;)
{
if(count_error == 10)
{
counter++;
printf("Timer=%dsec\n", counter);
if(counter > 599)
{
printf("Timer=10 min\n");
counter = 0;
count_error = 9;
}
}
sleep(1);
}
pthread_exit(NULL);
}
/////////////////////////////////////////////////// SendMessage ///////////////////////////////////////////////////////
void SendMessage(char *chat_id, char *send_text)
{
pid_t smpid;
signal(SIGCHLD, child_kill2);
smpid = fork();
if(smpid == 0)
{
char str[1024] = {0,};
int lenstr = 95;
char json_str[256] = {0,};
snprintf(json_str, 1 + 11 + (int)strlen(chat_id) + 9 + (int)strlen(send_text) + 2, "{\"chat_id\":%s,\"text\":\"%s\"}", chat_id, send_text);
int lenjson = (int)strlen(json_str);
snprintf(str, 1 + 9 + (int)strlen(token) + lenstr + 3 + 23 + lenjson, "POST /bot%s/sendMessage HTTP/1.1\r\nHost: api.telegram.org\r\nContent-Type: application/json\r\nContent-Length: %d\r\nConnection: close\r\n\r\n%s", token, lenjson, json_str);
//////////////////////////////////// client ///////////////////////////////////////////
struct sockaddr_in serv_addr;
int sd = 0;
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) error_log("socket in SM!");
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if(setsockopt (sd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) error_log("setsockopt.");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("149.154.167.198");
serv_addr.sin_port = htons(443);
if(connect(sd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
{
error_log("connect.");
if(close(sd) == -1) error_log("close sd in SendMessage!");
exit(0);
}
/////////////////////////////////// ssl client ////////////////////////////////////////
SSL_CTX * sslctx = SSL_CTX_new(TLSv1_2_client_method());
SSL * cSSL = SSL_new(sslctx);
if(SSL_set_fd(cSSL, sd) == 0) error_log("SSL_set_fd in SM!");
if(SSL_connect(cSSL) == 0) error_log("SSL_connect in SM!");
/////////////////////////////////// send mesg ////////////////////////////////////////
int vsm = SSL_write(cSSL, str, (int)strlen(str));
if(vsm <= 0)
{
SSL_free(cSSL);
if(close(sd) == -1) error_log("close sd in SM!");
error_log("vsm = SSL_write in SM!");
}
memset(str, 0, 1024);
/////////////////////////////////// read response ////////////////////////////////////
int n = SSL_read(cSSL, str, 1023);
if(n <= 0)
{
SSL_free(cSSL);
if(close(sd) == -1) error_log("close client_3!");
error_log("Err SSL_read in SM.");
}
/////////////////////////////////// close connect ////////////////////////////////////
SSL_free(cSSL);
SSL_CTX_free(sslctx);
if(close(sd) == -1) error_log("close sd in SendMessage!");
exit(0);
} // END FORK
} // END SendMessage
////////////////////////////////////////////////// miner_thread_func ///////////////////////////////////////////////////////
void * miner_thread_func()
{
FILE *prog_miner;
char buff[256] = {0,};
char res_buff[256] = {0,};
int count = 0;
prog_miner = popen(res_pminer, "r");
if(prog_miner == NULL) error_log("popen miner!");
work_miner = YES;
printf("START MINER AND WAIT DATA.\n\n");
while(fgets(buff, 255, prog_miner) != NULL)
{
printf("DATA: %s", buff);
int buff_len = (int)strlen(buff);
int indexin = 0, indexout = 0;
while(indexin < buff_len)
{
if(buff[indexin] == '\x1b')
{
for(; indexin < buff_len; indexin++)
{
if(buff[indexin] == 'm')
{
buff[indexin] = ' ';
break;
}
}
}
res_buff[indexout] = buff[indexin];
if(res_buff[indexout] == '\n')
{
res_buff[indexout] = 0;
if(vkl_data == 'A')
{
SendMessage(glob_chat_id, res_buff);
count++;
if(count >= count_dat)
{
count = 0;
vkl_data = 'Z';
sleep(1);
SendMessage(glob_chat_id, "DATA OFF");
}
}
else if(vkl_data == 'Z')
{
count = 0;
if(count_error < 10 && (strstr(res_buff, "ERROR") != NULL || strstr(res_buff, "Host not found") != NULL || strstr(res_buff, "Worker not authorized") != NULL || strstr(res_buff, "WARNING") != NULL || strstr(res_buff, "Could not connect") != NULL))
{
if(count_error == 0)
{
SendMessage(glob_chat_id, "START ERROR MSG");
sleep(1);
}
printf("SEND ERROR: %d %s\n", count_error, res_buff);
SendMessage(glob_chat_id, res_buff);
if(count_error == 9)
{
sleep(1);
SendMessage(glob_chat_id, "STOP ERROR MSG");
}
count_error++;
}
}
break;
}
indexin++;
indexout++;
}
}
SendMessage(glob_chat_id, "MINER CRASH");
printf("MINER CRASH\n");
work_miner = NO;
if(pclose(prog_miner) == -1) error_log("pclose.");
pthread_exit(NULL);
} // END miner_thread
////////////////////////////////// miner_thread ///////////////////////////////////
void start_miner_thread()
{
pthread_t miner_thread;
int min_result = pthread_create(&miner_thread, NULL, &miner_thread_func, NULL);
if(min_result != 0) error_log("creating miner_thread!");
pthread_detach(miner_thread);
}
//////////////////////////////////// rate ///////////////////////////////////////
void rate_coin(char *coin)
{
FILE *rat_coi;
int coin_len = (int)strlen(coin);
char *buff = (char*)malloc(59 + coin_len);
snprintf(buff, 59 + coin_len, "curl https://api.coinmarketcap.com/v1/ticker/%s/ 2>/dev/null", coin);
printf("\nCoinmarketcap: %s\n", buff);
rat_coi = popen(buff, "r");
if(rat_coi == NULL) error_log("rat_coi!");
char *trans_rate = (char*)malloc(160);
int count = 0;
strcpy(trans_rate, "RATE COIN\n");
while(fgets(buff, 58, rat_coi) != NULL)
{
count++;
if(count > 8) break;
if(count == 4 || count == 7 || count == 8)
{
char *pch = strtok(buff, " ,\"");
while(pch != NULL)
{
char *ptr = strchr(pch, ':');
if(ptr != NULL) *ptr = ' ';
strcat(trans_rate, pch);
pch = strtok(NULL, " ,\"");
}
}
}
snprintf(buff, 47 + coin_len, "\nhttps://coinmarketcap.com/currencies/%s/#charts", coin);
strcat(trans_rate, buff);
free(buff);
SendMessage(glob_chat_id, trans_rate);
printf("\n%s\n\n", trans_rate);
free(trans_rate);
}
//////////////////////////////////////////// MAIN ///////////////////////////////////////////
int main()
{
printf("\nDONATE TeleminerstD\n");
printf("BTC - 1F7tctXBtjnSJEMwPEQc4P4GZGDqEZHVP1\n");
printf("ZEC - t1XwmdEZkKKwtQVgF2jvxBTAWheYDVLrUMX\n");
printf("Thanks )))\n\n");
sleep(2);
read_conf();
start_miner_thread();
////////////////////////////// timecount_func ////////////////////////////////////
pthread_t counterr_thread;
int result2 = pthread_create(&counterr_thread, NULL, &timecount_func, NULL);
if(result2 != 0) error_log("creating timecount_func!");
pthread_detach(counterr_thread);
//////////////////////////////////// ssl //////////////////////////////////////////
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();
SSL_CTX * sslctx = SSL_CTX_new(TLSv1_2_server_method());
///////////////////////////// read certificate ////////////////////////////////////
if(SSL_CTX_use_certificate_file(sslctx, "cert.pem", SSL_FILETYPE_PEM) <= 0) error_log("use_certificate_file!");
if(SSL_CTX_use_PrivateKey_file(sslctx, "cert.pem", SSL_FILETYPE_PEM) <= 0) error_log("use_PrivateKey_file!");
if(!SSL_CTX_check_private_key(sslctx)) error_log("check_private_key!");
/////////////////////////////////// server ////////////////////////////////////////
int sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) error_log("descriptor socket!");
int one = 1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
struct sockaddr_in s_addr;
s_addr.sin_family = AF_INET;
s_addr.sin_addr.s_addr = INADDR_ANY;
s_addr.sin_port = htons(port);
if(bind(sd, (struct sockaddr *)&s_addr, sizeof(s_addr)) < 0) error_log("binding!");
if(listen(sd, 5) == -1)
{
close(sd);
error_log("listen!");
}
char read_buffer[BREADSIZE] = {0,};
SendMessage(glob_chat_id, "START SYSTEM");
while(1)
{
printf("WAIT CONNECTION.\n\n");
memset(read_buffer, 0, BREADSIZE);
int client = accept(sd, NULL, NULL);
if(client == -1)
{
error_log("Not cl accept.");
if(close(client) == -1) error_log("close client_1!");
continue;
}
///////////////////////////// ssl socket //////////////////////////////
SSL *ssl = SSL_new(sslctx);
if(SSL_set_fd(ssl, client) == 0) error_log("SSL_set_fd!");
int acc = SSL_accept(ssl);
if(acc <= 0)
{
SSL_free(ssl);
if(close(client) == -1) error_log("close client_2!");
error_log("Not SSL_accept.");
continue;
}
///////////////////////////// creat pipe ///////////////////////////////
int pip_fd[2];
int size;
if(pipe(pip_fd) < 0) error_log("create pipe!");
/////////////////////////////// fork ///////////////////////////////////
pid_t fpid;
signal(SIGCHLD, child_kill);
fpid = fork();
//////////////////////// parent read pipe //////////////////////////////
if(fpid > 0)
{
if(close(pip_fd[1]) < 0) error_log("close parent pip_fd[1]!");
size = read(pip_fd[0], glob_chat_id, IDSIZE - 2);
if(size < 0) error_log("read chat_id from child!");
if(close(pip_fd[0]) < 0) error_log("close parent pip_fd[0]!");
if(glob_chat_id[strlen(glob_chat_id) - 1] == 'A') // switch on msg from pipe
{
counter = 0;
count_error = 0;
vkl_data = glob_chat_id[strlen(glob_chat_id) - 1];
glob_chat_id[strlen(glob_chat_id) - 1] = 0;
}
else if(glob_chat_id[strlen(glob_chat_id) - 1] == 'Z') // switch off msg from pipe
{
vkl_data = glob_chat_id[strlen(glob_chat_id) - 1];
glob_chat_id[strlen(glob_chat_id) - 1] = 0;
}
else if(glob_chat_id[strlen(glob_chat_id) - 1] == 'S') // off all msg from pipe
{
vkl_data = glob_chat_id[strlen(glob_chat_id) - 1];
glob_chat_id[strlen(glob_chat_id) - 1] = 0;
}
else if(glob_chat_id[strlen(glob_chat_id) - 1] == 'R') // restart miner from pipe
{
glob_chat_id[strlen(glob_chat_id) - 1] = 0;
if(work_miner == NO)
{
counter = 0;
count_error = 0;
vkl_data = 'A';
SendMessage(glob_chat_id, "RESTART MINER");
start_miner_thread();
error_log("Not error, hand restart miner.");
}
else SendMessage(glob_chat_id, "MINER WORKING");
}
else if(glob_chat_id[strlen(glob_chat_id) - 1] == 'I')
{
glob_chat_id[strlen(glob_chat_id) - 1] = 0;
int len_help_str = strlen(data_on) + strlen(data_off) + strlen(all_off) + strlen(reb_komp) + strlen(off_komp) + strlen(rest_mainer) + 74;
char *help_str = (char*)malloc(len_help_str);
snprintf(help_str, len_help_str, "HELP COMANDS\nData_on=%s\nData_off=%s\nAll_off=%s\nReb_komp=%s\nOff_komp=%s\nRest_mainer=%s", data_on, data_off, all_off, reb_komp, off_komp, rest_mainer);
SendMessage(glob_chat_id, help_str);
printf("%s\n", help_str);
free(help_str);
}
}
/////////////////////////// start child ////////////////////////////////
if(fpid != 0)
{
SSL_free(ssl);
if(close(client) == -1) error_log("close client_pid!");
continue;
}
////////////////////// read header from telegram ///////////////////////
int n = SSL_read(ssl, read_buffer, BREADSIZE - 2); // first SSL_read
if(n <= 0)
{
SSL_free(ssl);
if(close(client) == -1) error_log("close client_3!");
printf("Disconnection:%d\n", n);
exit(0);
}
/////////////////////// verification token ////////////////////////////
char *r_buf = read_buffer;
char res_token[64] = {0,};
int rb = 0;
if(*r_buf != '\0')
{
for(;rb < 10; r_buf++, rb++)
{
if(*r_buf == '/')
{
r_buf++;
break;
}
}
for(rb = 0; *r_buf != ' '; r_buf++, rb++)
{
res_token[rb] = *r_buf;
if(rb > 63) break;
}
}
if(strcmp(res_token, token) != 0)
{
SSL_free(ssl);
if(close(client) == -1) error_log("close client_4!");
error_log("Not valid POST!");
}
/////////////////////// chek content-type ////////////////////////////
if(strstr(read_buffer, "Content-Type: application/json") == NULL)
{
SSL_free(ssl);
if(close(client) == -1) error_log("close client_5!");
error_log("Not json!");
}
/////////////////////////// read jons data /////////////////////////////
memset(read_buffer, 0, BREADSIZE);
int m = SSL_read(ssl, read_buffer, BREADSIZE - 2);
if(m <= 0)
{
SSL_free(ssl);
if(close(client) == -1) error_log("close client_8!");
}
/////////////////////////// read chat_id ///////////////////////////////
char *p = NULL;
char chat_id[IDSIZE] = {0,};
if((p = strstr(read_buffer, "chat\":{\"id\":")) != NULL)
{
memccpy(chat_id, p + 12, ',', IDSIZE - 1);
chat_id[strlen(chat_id) - 1] = 0;
printf("Chat_id: %s\n", chat_id);
}
//////////////////////////// read msag ////////////////////////////////
char msg_text[64] = {0,};
if((p = strstr(read_buffer, "text\":\"")) != NULL)
{
memccpy(msg_text, p + 7, '"', 63);
msg_text[strlen(msg_text) - 1] = 0;
printf("Msg_text: %s\n", msg_text);
}
//////////////////////////// telegram reply //////////////////////////////
int v = SSL_write(ssl, "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", 38);
if(v <= 0)
{
SSL_free(ssl);
if(close(client) == -1) error_log("v = SSL_write!");
}
SSL_free(ssl);
if(close(client) == -1) error_log("close client_6!");
///////////////////////////// my functions ////////////////////////////////
if(msg_text[0] == 't' && msg_text[1] == 0) // test
{
SendMessage(chat_id, "TEST OK");
}
else if(strcmp(msg_text, data_on) == 0) // vkldat
{
vkl_data = 'A';
SendMessage(chat_id, "DATA ON");
chat_id[strlen(chat_id)] = vkl_data;
}
else if(strcmp(msg_text, data_off) == 0) // otkldat
{
vkl_data = 'Z';
SendMessage(chat_id, "DATA OFF");
chat_id[strlen(chat_id)] = vkl_data;
}
else if(strcmp(msg_text, all_off) == 0) // otkl all dat
{
vkl_data = 'S';
SendMessage(chat_id, "ALL OFF");
chat_id[strlen(chat_id)] = vkl_data;
}
else if(strcmp(msg_text, reb_komp) == 0) // reboot
{
error_log("Not error, received command REBOOT.");
SendMessage(chat_id, "REBOOT");
system("reboot");
}
else if(strcmp(msg_text, off_komp) == 0) // poweroff
{
error_log("Not error, received command SHUTDOWN.");
SendMessage(chat_id, "SHUTDOWN");
system("shutdown -h now");
}
else if(strcmp(msg_text, rest_mainer) == 0) // restart miner to pipe
{
chat_id[strlen(chat_id)] = 'R';
}
else if(strcmp(msg_text, comamd_info) == 0) // info to pipe
{
chat_id[strlen(chat_id)] = 'I';
}
else if(strstr(msg_text, "rate,") != NULL)
{
char rate_text[16] = {0,};
strncpy(rate_text, msg_text + 5, (int)strlen(msg_text) - 5);
rate_coin(rate_text);
}
if(close(pip_fd[0]) < 0) error_log("close child pip_fd[0]!");
size = write(pip_fd[1], chat_id, (int)strlen(chat_id)); // write to pipe
if(size != (int)strlen(chat_id)) error_log("write chat_id!");
if(close(pip_fd[1]) < 0) error_log("close child pip_fd[1]!");
exit(0);
} // END while(1)
if(close(sd) == -1) error_log("close sd client_7!");
}
// gcc -Wall -Wextra teleminerstd.c -o teleminerstd -lcrypto -lssl -pthread
// ./teleminerstd
line_buffer.c
#include <stdio.h>
__attribute__((constructor)) void f()
{
setvbuf(stdout,NULL,_IONBF,0);
}
// gcc -fPIC -shared -Wall -o line_buffer.so line_buffer.c
![](http://istarik.ru/uploads/images/00/00/01/2017/10/10/a2b7dc.png)
Автозагрузка осуществляется традиционным способом: поместите в файл /etc/rc.local (до exit 0) следующую строку…
(cd /home/dima/teleminer && ./teleminerstd)&
Имя юзера поменяйте на своё.
Это beta версия, в дальнейшем планируется развитие функционала и анигиляция багов).
Пробуйте и отписывайтесь в комментах.
На этом пока всё…
Z
Буду очень благодарен любым пожертвованиям!
![](http://istarik.ru/uploads/images/thnd.png)
- +31
- stD
8816
Поддержать автора
Комментарии (0)