nftables для FQDN
Приветствую.
Раз уж приходится переходить с iptables, которое сабж не умеет, на nftables появилась такая возможность?
Приветствую.
Раз уж приходится переходить с iptables, которое сабж не умеет, на nftables появилась такая возможность?
Приветствую.
Сначала написал многа букв в вопросе, но решил спросить просто кодом раз уж всегда требуют его - почему через обычный метод AutoCommit выполняется раньше всех и все работает, а через лямбду нет ибо порядок инициализации не соблюдается???
class CParamsTXT
{
private:
const bool bAutoCommit;
IBPP::Transaction tr;
IBPP::Statement st;
CDefFile * pCfg;
const string Typ, Section, id_bank;
bool getAutoCommit(IBPP::Transaction tr)
{
fprintf(stderr, "\n111 111\n");
const bool rt = !tr->Started();
if (rt) tr->Start();
return rt;
}
protected:
string GetParam(string & param, string Field, string Ident, string Default = "")
{ ... }
public:
const string DateFormat, DatePoint, DecPoint, codepage;
vector<string> svF;
const char cNote;
CParamsTXT(CDefFile * pCfg_, IBPP::Transaction tr_, IBPP::Statement st_, string Typ_, string Section_, string id_bank_, string DateFormat_, string DatePoint_, string DecPoint_, string codepage_, string Note_)
:
bAutoCommit([](IBPP::Transaction tr_){
fprintf(stderr, "\n111 222\n");
const bool rt = !tr_->Started();
if (rt) tr_->Start();
return rt;}),
// bAutoCommit(getAutoCommit(tr_)),
tr(tr_), st(st_), pCfg(pCfg_),
Typ(Typ_), Section(Section_), id_bank(id_bank_),
DateFormat(GetParam(DateFormat_, "date_format", "DateFormat", "d/m/y")),
DatePoint(GetParam(DatePoint_, "date_point", "DatePoint", "/")),
DecPoint(GetParam(DecPoint_, "dec_point", "DecPoint", ".")),
codepage(GetParam(codepage_, "codepage", "codepage", "DOS")),
cNote(GetParam(Note_, "note", "NoteTXT", "")[0])
{ }
Приветствую.
Очередная проблема после поднятия версии Debian c 8 до 10: isc-dhcp-server перестал обновлять локальную зону на шлюзе, из ошибок вижу такие сообщения
Nov 22 12:23:34 server dhcpd[]: DDNS: cleaning up lease pointer for a cancel cb=0x557dffa84800
Nov 22 12:23:34 server dhcpd[]: Unable to add forward map from имяхоста.имядомена.ru to 192.168.xxx.xxx: operation canceled
в бинде вообще тишина, никаких запросов нет
Делал конфиг когда то под Debian 6 конечно, но все работало пока не обновился
# grep -v ^# dhcpd.conf
ddns-update-style interim;
ddns-updates on;
ddns-domainname "имядомена.ru";
do-forward-updates on;
update-static-leases on;
ignore client-updates;
update-conflict-detection false;
include "/etc/dhcp/dhcpd.key";
zone имядомена.ru {
primary 192.168.xxx.2;
key DHCP_UPDATER;
}
zone xxx.168.192.in-addr.arpa {
primary 192.168.xxx.2;
key DHCP_UPDATER;
}
option domain-name "имядомена.ru";
option domain-name-servers 192.168.xxx.2;
option local-pac-server code 252 = text;
option local-pac-server "http://proxy/proxy.pac\000";
default-lease-time 36000; # 10h
max-lease-time 86400; # 24h
authoritative;
log-facility local7;
shared-network имясети {
subnet 192.168.xxx.0 netmask 255.255.255.0 {
range 192.168.xxx.10 192.168.xxx.250;
option broadcast-address 192.168.xxx.255;
option routers 192.168.xxx.2;
option ntp-servers 192.168.xxx.2;
filename "pxelinux.0";
next-server 192.168.xxx.1;
}
}
host имя1 {
hardware ethernet 52:54:00:8b:xx:xx;
fixed-address 192.168.xxx.xxx;
}
пока гуглеж не помогает, может кто сталкивался?
Приветствую.
После поднятия версии Debian c 8 до 10 перестали работать ключи, пытаюсь по новой их импортировать - пишет ошибку
$ gpg --import PUBRING.PGP
gpg: Всего обработано: 2
gpg: пропущено ключей PGP-2: 2
Тут конечно написаны такие ужасы
Some algorithms and parts of the protocols as used by the 20 years old PGP-2 software are meanwhile considered unsafe.
With GnuPG 2.1 all support for those keys has gone.
но что конкретно нужно сделать в этой ситуации не соображу, буду очень благодарен любой помощи.
Приветствую.
После поднятия версии Debian c 8 до 10 не запускается виртуалка с ошибкой
libvirtd[9019]: /usr/sbin/libvirtd: symbol lookup error: /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4: undefined symbol: libssh2_scp_recv2
либы стоят
# apt policy libssh2-1
libssh2-1:
Установлен: 1.8.0-2.1+deb10u1
Кандидат: 1.8.0-2.1+deb10u1
Таблица версий:
*** 1.8.0-2.1+deb10u1 500
500 http://security.debian.org buster/updates/main amd64 Packages
100 /var/lib/dpkg/status
1.8.0-2.1 500
500 http://mirror.yandex.ru/debian buster/main amd64 Packages
# apt policy libcurl3-gnutls
libcurl3-gnutls:
Установлен: 7.64.0-4+deb10u7
Кандидат: 7.64.0-4+deb10u7
Таблица версий:
*** 7.64.0-4+deb10u7 500
500 http://security.debian.org buster/updates/main amd64 Packages
100 /var/lib/dpkg/status
7.64.0-4+deb10u2 500
500 http://mirror.yandex.ru/debian buster/main amd64 Packages
гуглеж что то не помогает, подскажите в чем может быть проблема?
Приветствую.
Про определение о требовании выравнивания читал конечно. Но таки как выбирается аргумент??? чтобы получить кучи прироста производительности )
Т.е. я например объявляю объекты как
alignas(64) std::atomic<size_t> tail;
alignas(64) std::atomic<size_t> head;
на xeon прирост в 2 раза, а на виртуалке можно считать погрешностью, но при 16 уже на виртуалке хоть и маленький, но таки -5% времени выполнения, при этом на процессоре падение.
приветствую.
савчера вдрух mail.ru начал мозги делать доставкой писем по поводу SPF, DKIM, DMARC
вроде все сделал по их инструкции https://help.mail.ru/postmaster/technical-settings/notes
добавил в bind9 3 записи вида
@ IN TXT "v=spf1 a mx ~all"
@ IN TXT "v=DKIM1; k=rsa; p=ПУБЛИЧНЫЙКЛЮЧ"
@ IN TXT "v=DMARC1; p=none"
поставил opendkim, прописал там соответственно место приватного ключа, в postfix сконфигрурировал на использование opendkim
один фих они пишут мне в заголовке
Authentication-Results: mxs.mail.ru; spf=pass (mx324.i.mail.ru: domain of ДОМЕН designates IPадрес as permitted sender) smtp.mailfrom=wolverin@ДОМЕН smtp.helo=mail.ДОМЕН;
dkim=invalid reason=pubkey_unavailable header.d=ДОМЕН
Received-SPF: pass (mx324.i.mail.ru: domain of ДОМЕН designates IPадрес as permitted sender) client-ip=IPадрес; envelope-from=wolverin@ДОМЕН; helo=mail.ДОМЕН;
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=ДОМЕН; s=mail;
t=1698894939; bh=JjZLfQmoespEUwGKuwbvnkkjWozy3SgKdtKb0xyF/W4=;
h=Date:From:To:Subject:From;
b=o+dgSgqvHNSmHZaJgs+9T6ErJ8sM8CMYLiaMRVgIZ4ED3hqE4yb/Vxy3x2j8Xb7qz
03wTwz4AFtmAR/UrSXjKSvCYiusvtSomimsWbUfvq/fNHhWZxLfQntnGEGO+RLTL+T
izuF0e1ptd/ZjmvrzBI5m9OZjQtoeLkLleP1vNLY=
User-Agent: Roundcube Webmail/1.2.3
X-DKIM-FAIL: DKIM test failed: invalid (address=wolverin@ДОМЕН domain=ДОМЕН reason=pubkey_unavailable).
X-Mailru-Src: mx
X-4EC0790: 10
X-6b629377: 1
X-7564579A: 646B95376F6C166E
X-77F55803: E822A06ED42C499A7F63DA2F9F2A54461ED951AC22C7845A9D1D1EE593088C900BBDAAE39103F3638701F0628C4B95CB650AB02DA031907FC423C6D7DB1CDA95F7F2529DD7A3558E4DF7BC4678047644
X-7FA49CB5: A9FCD207E66530D8A18204E546F3947C6807E7B3823913D9AFB8EE5BB20AF148C8A9BA7A39EFB7663CFE1401686631C009758206774B3CD2D5E8D9A59859A8B61831C2A8CBD9F7CA71492C2D3FF63AF69449624AB7ADAF37FD314BCFCDE4A234277E793F4B08E8842DAF2A56518EC330CC198E72ECD316A4BD9CCCA9EDD067B1FF0C04525729832C4E1E7243831EC1F578DA827A17800CE786D80B7E7735AB376320D30F47244B793CFE1401686631C082BFA309970D60C2B287FD4696A6DC2F5F5C1EE8F4F765FC04C22ED69F47F2D8B287FD4696A6DC2FA8DF7F3B2552694A4E2F5AFA99E116B42401471946AA11AF176DF2183F8FC7C086614E11AFA257BF8F08D7030A58E5ADC58D69EE07B1408453DF159EA87357C20A6AB1C7CE11FEE32FFDA4F57982C5F4B289B51CCB092ABD5571747095F342E8C234C8B12C006B7AAEC4162A2AA392DA8DFF822C4FED0E964788BA5126CA40DB8EEF46B7454FC60B9742502CCDD46D0DEDCF5861DED71B2F389733CBF5DBD5E913377AFFFEAFD269176DF2183F8FC7C078FCF50C7EAF9C588941B15DA834481FCF19DD082D7633A0EF3E4896CB9E6436389733CBF5DBD5E9D5E8D9A59859A8B601F8F2FECC0250C8CC7F00164DA146DA6F5DAA56C3B73B23E7726E8460B7C23C
X-C1DE0DAB: 0D63561A33F958A52EF6A6EFBDB43C8BA0F06EF541F76ED3AC0764A0D20A0778F87CCE6106E1FC07E67D4AC08A07B9B0A6C7FFFE744CA7FB9C5DF10A05D560A950611B66E3DA6D700B0A020F03D25A09EDCF5861DED71B2FF32E08699F8F45A1CDFF422315505062BA7CCD254A1CF5E833629329AA2D25E5
X-C8649E89: 1C3962B70DF3F0AD26C0D434D75DEB27F22D334B9B612B432CCB5A6D6581D03D0776B5B2C279835F17BCBE6708A5A68D02015372BE9702A20F84C43FA2038CDE3DE146DE6857D72CDEB7323C50A52AFEAC8CE95F42CF61090966F1585594D6159B815B7972F6FBBE7894B9023F5C129066BFC862880C174652EE4E5D9E54FDA44C41F94D744909CECE91D1F769AC3F588EBB7F9845D5049F9CB4C0EABAFD0B4C37E69C174A41D00C
X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr59cQFxbtK52nlS5dXYHM/vGJPPyhnCcOsWxjvstlFwfLDmG3SyZat9J5NbkWIjxq932/b2BQGyWkRn3AgzCpU/iMtBVD51WbvH0GkMdp0FX1YB//7MgRjFKDtzAHcKfpojwMUFqnUrer
X-F696D7D5: 1DeD6lt5UnY/fUsKeIs0lzdPoFv7BEpSOG24EIKoYNjqMV5tCw+fwA==
tcp порт 53 до бинда тоже открыл, так то письма ходят, но подскажите что этому майлу может быть еще нужно???
Приветствую
В продолжении темы Рестартануть драйвер как?
нашел как из консоли бесконечно количество раз рестартить драйвер
systemctl stop ***.service
echo spi0.0 > /sys/bus/spi/drivers/flexfb/unbind
echo spi0.0 > /sys/bus/spi/drivers/flexfb/bind
systemctl start ***.service
делают тоже самое на сях как
static int setSPI(bool mode)
{
const char
* flexfb,
spi[] = "spi0.0";
if (mode)
{
flexfb = "/sys/bus/spi/drivers/flexfb/bind";
fputs("Start spi device\n", stderr);
}
else
{
flexfb = "/sys/bus/spi/drivers/flexfb/unbind";
fputs("Stop spi device\n", stdout);
}
int rt = -1;
int fd = open(flexfb, O_WRONLY);
if (fd > 0)
{
if ((rt = write(fd, spi, sizeof(spi))) <= 0)
fprintf(stderr, "ERROR set SPI: %d %s [%s]\n", errno, strerror(errno), flexfb);
close(fd);
}
else
fprintf(stderr, "ERROR open %s: %d %s\n", flexfb, errno, strerror(errno));
return rt;
}
уже без всяких systemctl просто запускаю и останавливаю приложение и в какой то момент на write(fd не снимаемая БЛОКИРОВКА
где может быть у меня косяк?
Приветствую
В продолжении темы Как рестартануть /dev/fb1 ???
как можно перезапустить из своего бинарника драйвер через ядро БЕЗ modprobe ???
Приветствую.
Через /dev/fb1 с одноплатника реализовано подключение lcd экрана, который зараза по необъяснимым причинам иногда белеет.
Может есть способ не ребутить убунту для «сброса» внешнего устройства? В идеале бы еще узнать текущее состояние конечно.
Полагаю оно прячется где то в прерываниях, но как найти с которым связано?
cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
16: 0 0 0 0 GICv2 25 Level vgic
17: 0 0 0 0 GICv2 50 Level /soc/timer@01c20c00
18: 0 0 0 0 GICv2 29 Level arch_timer
19: 90547909 139451125 142656932 143202842 GICv2 30 Level arch_timer
20: 0 0 0 0 GICv2 27 Level kvm guest timer
22: 0 0 0 0 GICv2 120 Level 1ee0000.hdmi, dw-hdmi-cec
24: 0 0 0 0 GICv2 118 Level 1c0c000.lcd-controller
25: 0 0 0 0 GICv2 82 Level 1c02000.dma-controller
26: 25 0 0 0 GICv2 92 Level sunxi-mmc
27: 79801 0 0 0 GICv2 94 Level sunxi-mmc
28: 1 0 0 0 GICv2 103 Level musb-hdrc.4.auto
29: 0 0 0 0 GICv2 104 Level ehci_hcd:usb1
30: 0 0 0 0 GICv2 105 Level ohci_hcd:usb2
31: 0 0 0 0 GICv2 106 Level ehci_hcd:usb3
32: 0 0 0 0 GICv2 107 Level ohci_hcd:usb6
33: 0 0 0 0 GICv2 108 Level ehci_hcd:usb4
34: 0 0 0 0 GICv2 109 Level ohci_hcd:usb7
35: 85647492 0 0 0 GICv2 110 Level ehci_hcd:usb5
36: 0 0 0 0 GICv2 111 Level ohci_hcd:usb8
39: 624264 0 0 0 GICv2 63 Level 1c25000.ths
41: 305355 0 0 0 GICv2 114 Level eth0
42: 3951995844 0 0 0 GICv2 97 Level sun6i-spi
45: 432 0 0 0 GICv2 32 Level ttyS0
46: 177618 0 0 0 GICv2 33 Level ttyS1
49: 0 0 0 0 GICv2 38 Level mv64xxx_i2c
50: 0 0 0 0 GICv2 39 Level mv64xxx_i2c
51: 0 0 0 0 GICv2 40 Level mv64xxx_i2c
52: 0 0 0 0 GICv2 72 Level 1f00000.rtc
106: 1 0 0 0 sunxi_pio_edge 44 Edge usb0-id-det
129: 1 0 0 0 sunxi_pio_edge 3 Edge k1
IPI0: 0 0 0 0 CPU wakeup interrupts
IPI1: 0 0 0 0 Timer broadcast interrupts
IPI2: 90852252 258982397 266588110 269015295 Rescheduling interrupts
IPI3: 760 582 624 629 Function call interrupts
IPI4: 0 0 0 0 CPU stop interrupts
IPI5: 88146 26774 27729 28640 IRQ work interrupts
IPI6: 0 0 0 0 completion interrupts
Err: 0
Приветствую.
Вынес кусок кода в отдельный hpp, который использую в разных проектах. Из этого куска передаю указатель на метод в методы разного функционала скомпилированные в разных объектниках как на Сях, так и на С++
Все работает, НО можно ли сделать внешнее связывание одновременно как для Си, так и для С++ в одном проекте???
Например, я объявляю метод в разном функционале
для С++ в hpp просто как
extern void func(void * ptr)
для Си в секции
#ifdef __cplusplus
extern "C" {
#endif
extern void func(void * ptr)
#ifdef __cplusplus
}
#endif
Куски конечно компилируются, но при попытке собрать все это дело
MQTT.h:12:13: error: conflicting declaration of ‘void func(void*)’ with ‘C’ linkage
extern void func(void * ptr);
^~~~~~~~~~~
In file included from IntercomIP.cpp:24:0:
SIP.hpp:36:13: note: previous declaration with ‘C++’ linkage
extern void func(void * ptr);
По всякому уже попробовал ) Собирается только если будет как объектник выделенного кода, так и сам код включен в компиляцию бинарника, выглядит конечно это бредово.
Приветствую.
В чужом решении с тысячами железок, которое переписываю, схема предоставление видео реализована через видео rtsp прокси сервер (rtsp-simple-server) + openvpn до каждой железки с ее rtsp сервером - само собой что такая архитектура обладает некоторой сложностью и как следствие не высокой надежностью.
Поскольку пока нет возможности выпилить видео прокси, есть частично проверенная идея на железках «перевернуть» сервер, используя если не сам ffmpeg, то его либы, выполняя с железки пуш rtsp подключение.
В прошлом году удалось втащить старый ffserver с новыми либами ффмпега в свой проект, что дало по быстрому реализовать свой rtsp сервер, в который видео передаю как раз с помощью пуша ртсп между своими же потоками через локальный интерфейс - проблем не замечено, но тут это будет не в единичном случае, а тысячи таких подключений через ентернет, хоть сам rtsp-simple-server такой способ и поддерживает как я проверил.
Это бы дало мне отказ он vpn и части php функционала на проксе. Или может есть другие более надежные способы выкинуть VPN в такой схеме ???
Приветствую.
В продолжении темы Вызов по указателю метода структуры вложенной в класс
Есть обработчик очереди класса в отдельном потоке
void CQueue::Handler(void)
{
auto Get = [this](cmd_t & cmd) {
std::unique_lock<std::mutex> ul(mtx);
do {
if (!abRun) return false;
} while (!cv.wait_for(ul, std::chrono::seconds(1), [this]{ return !pq.empty(); }));
cmd = pq.top();
pq.pop();
return true;
};
cmd_t cmd;
while (Get(cmd))
if (cmd.handle)
(this->*(cmd.handle))(cmd.id, cmd.msg);
}
В саму очередь засовываю подобным образом из другого потока поступающих команд
pQ->Put(id, std::string(msg, msgLen), &CQueue::handle_pass);
частично описание класса
class CQueue
{
private:
struct cmd_t {
int8_t pri;
std::string id, msg;
void (CQueue::*handle)(const std::string & id, std::string & msg);
};
std::function<bool (const cmd_t &, const cmd_t &)> cmp = [](const cmd_t & l, const cmd_t & r){ return l.pri > r.pri; };
std::priority_queue<cmd_t, std::vector<cmd_t>, decltype(cmp)> pq;
Все работает полагаю пока команды идут настолько «медленно», что CQueue::Handler успевает встать на условную переменную, но если удается за время вызова (this->(cmd.handle))(cmd.id, cmd.msg) засунуть в очередь несколько команд, то валится ошибка std::bad_function_call при вызове (this->(cmd.handle))
Разве нельзя одновременно передавать указатель на метод класса в другой поток и обращаться к нему???
Приветствую
Есть куча железок на убунте (может будет расбиан), которые могут быть физически стырены, необходимо зашифровать конфиги моего ПО на них, да так чтобы ключ-пароль сей не светился в самом бинарнике.
Ранее пользовал штатную библиотеку libgcrypt с алгоритмом AES в режиме CBC, поэтому из мыслей брать пароль и соль, например, mac и uuid диска, но кажется это тривиальным
Посоветуйте как можно решить подобную задачу, в идеале «штатными» средствами.
Приветствую.
Имеется класс вида
class CQueue
{
private:
struct cmd_t {
int8_t pri;
std::string id, msg;
void (CQueue::*handle)(const std::string & id, const std::string & msg);
};
....
public:
void handle_...(const std::string & id, const std::string & msg);
void handle_push(const std::string & id, const std::string & msg);
int Put(const std::string & id, const std::string & msg, void (CQueue::*handle)(const std::string & id, const std::string & msg), const int8_t pri = 0);
void Handler(void);
из метода не этого класса добавляю в эту очередь и GCC не возмущается как
pQ->Put(id, std::string(msg, msgLen), &CQueue::handle_push);
а как теперь обратиться к этому методу внутри этого же класса??? думал должно быть что то вроде
void CQueue::Handler(void)
{
.....
cmd_t cmd;
while (Get(cmd))
if (cmd.handle)
(cmd.*handle)(cmd.id, cmd.msg);
но компилятор против, говорит нет никакого handle
так тоже пробовал и тут типы не совпадают
(cmd.*cmd.handle)(cmd.id, cmd.msg)
или вообще все это не правильно и надо городить на std::function ???
Приветствую
Через однопоточный обработчик поступают mqtt команды и его никак нельзя тормозить ещё и их обработкой, при этом какие то типы команд могут быть быстро обработаны, какие то существенно медленней.
Если с самой очередью приоритотов вроде есть понимание в использовании std::priority_queue (или лучше мудрить с heap???), то как организовать раздельную обработку каждого приоритета, чтобы длинные низкоприоритетные задачи не тормозили более высокие пока не соображу.
Пока только 2 вида, но может в будущем будет больше и не хочется тупо делать количество очередей просто по количеству приоритотов.
На чем такое реализовать на плюсах???
И снова здравствуйте! )
Получилось ПОЧТИ что хотел - за одно подключение-рукопожатие при пиковом (за время полного цикла от подключения до записи в сокет) поступлении команд через mqtt удается отправить херову гору rest-запросов, затем происходит отключение и ожидание следующей порции.
Но вот что нормально НЕ работает, так это CPush::handle_read_status, получаю туда после первого нормального response какой то мусор с периодической ошибкой от буста Operation canceled
Описание
class CPush
{
private:
std::deque<std::string> dq;
std::mutex mtx;
std::condition_variable cv;
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> * psocket;
std::string request;
boost::asio::streambuf response;
bool verify_certificate(bool preverified, boost::asio::ssl::verify_context & ctx);
void handle_connect(const boost::system::error_code & error);
void handle_handshake(const boost::system::error_code & error);
void handle_write(const boost::system::error_code & error);
void handle_read_status(const boost::system::error_code & error);
void handle_read_header(const boost::system::error_code & error);
void handle_read_content(const boost::system::error_code & error);
void Write(void);
int Get(std::string & http);
public:
CPush(void) { std::cout << "PUSH client initialized" << std::endl; }
int Put(const std::string & tokens, const std::string & cmd);
bool Wait(void);
void Handler(void);
};
Частично реализация
void CPush::handle_handshake(const boost::system::error_code & error)
{
if (error)
std::cerr << "Handshake failed: " << error.message() << std::endl;
else
Write();
}
void CPush::handle_write(const boost::system::error_code & error)
{
if (error)
std::cerr << "Write failed: " << error.message() << std::endl;
else
{
std::cout << "Sending request OK!" << std::endl;
boost::asio::async_read_until(*psocket,
response, "\r\n",
boost::bind(&CPush::handle_read_status,
this,
boost::asio::placeholders::error));
Write();
}
}
void CPush::handle_read_status(const boost::system::error_code & error)
{
if (error)
std::cout << "Error read status: " << error.message() << std::endl;
else
{
std::cout << "!!!!!!!!!!!!!!!!!!!\n" << &response << "\n!!!!!!!!!!!!!!!!!!!\n" << std::flush;
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
std::cout << "Invalid response\n";
return;
}
if (status_code != 200)
{
std::cout << "Response returned with status code ";
std::cout << status_code << "\n";
// return;
}
/* // Read the response headers, which are terminated by a blank line.
boost::asio::async_read_until(*psocket,
response, "\r\n\r\n",
boost::bind(&CPush::handle_read_header,
this,
boost::asio::placeholders::error));
*/ }
}
int CPush::Get(std::string & http)
{
std::lock_guard<std::mutex> lock(mtx);
int rt = dq.size();
if (rt > 0)
{
http = dq.front();
dq.pop_front();
}
return rt;
}
void CPush::Write(void)
{
if (Get(request) > 0)
boost::asio::async_write(*psocket,
boost::asio::buffer(request),
boost::bind(&CPush::handle_write,
this,
boost::asio::placeholders::error));
}
int CPush::Put(const std::string & tokens, const std::string & cmd)
{
std::string json("{\"registration_ids\":[" + tokens + "],"
"\"notification\":null,"
....................
"\"priority\":\"high\","
"\"time_to_live\":15}");
mtx.lock();
dq.push_back("POST " + std::string(GOOGLE_API) + " HTTP/1.1\r\n"
"Host: " + GOOGLE_HOST + "\r\n" // << ":" << port
"Content-Type: application/json; charset=utf-8\r\n"
"Content-Length: " + std::to_string(json.size()) + "\r\n"
"Authorization: key=" + push_key + "\r\n\r\n" + json);
int rt = dq.size();
mtx.unlock();
cv.notify_one();
return rt;
}
bool CPush::Wait(void)
{
std::unique_lock<std::mutex> ul(mtx);
do {
if (!abRun) return false;
} while (!cv.wait_for(ul, std::chrono::seconds(1), [this]{ return dq.size() > 0; }));
return true;
}
void CPush::Handler(void)
{
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(GOOGLE_HOST, GOOGLE_PORT);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
context.set_default_verify_paths();
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service, context);
socket.set_verify_mode(boost::asio::ssl::context::verify_none);
socket.set_verify_callback(boost::bind(&CPush::verify_certificate, this, _1, _2));
psocket = &socket;
boost::asio::async_connect(psocket->lowest_layer(),
iterator,
boost::bind(&CPush::handle_connect,
this,
boost::asio::placeholders::error));
io_service.run();
std::cout << "00000000000000000000000000000000000" << std::endl;
}
запускаю все это дело из основного потока
std::thread ([](void){ while (pPush->Wait()) pPush->Handler(); }).detach();
и добавляю команды из другого потока по событию
pPush->Put(tokens_, cmd_);
Приветствую.
Даже спрашивать уже опасаюсь, опять отдельные личности с большим самомнением начнут объяснять какой я тупой, но все таки попробую, вдруг кому не сложно )
Код класс ниже, теста ради из одного потока все работало, пока не решил вызвать CPush::Send из другого и все упало. Думал сначала что дело в std::stringstream request, которая была локальная - поднял ее до класса и не помогло.
Хоть намек бы к пониманию, где косяк, заранее спасибо за не равнодушие )
class CPush
{
private:
std::stringstream request;
boost::asio::io_service * pio_service;
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> * psocket;
boost::asio::streambuf response;
bool verify_certificate(bool preverified, boost::asio::ssl::verify_context & ctx);
void handle_connect(const boost::system::error_code & error);
void handle_handshake(const boost::system::error_code & error);
void handle_write(const boost::system::error_code & error);//, size_t bytes_transferred
void handle_read_status(const boost::system::error_code & error);
void handle_read_header(const boost::system::error_code & error);
void handle_read_content(const boost::system::error_code & error);
public:
CPush(void){}
void LoopStart(void);
void LoopStop(void);
void Send(const std::string tokens, const std::string cmd);
};
Реализация
bool CPush::verify_certificate(bool preverified, boost::asio::ssl::verify_context & ctx)
{
char subject_name[256];
X509 * cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
std::cout << "Verifying " << subject_name << std::endl;
return preverified;
}
void CPush::handle_connect(const boost::system::error_code & error)
{
if (error)
std::cerr << "Connect failed: " << error.message() << std::endl;
else
{
// Support for Server Name Indication (SNI)
SSL_set_tlsext_host_name(psocket->native_handle(), GOOGLE_HOST);
psocket->async_handshake(boost::asio::ssl::stream_base::client,
boost::bind(&CPush::handle_handshake,
this,
boost::asio::placeholders::error));
std::cout << "Connection OK!" << std::endl;
}
}
void CPush::handle_handshake(const boost::system::error_code & error)
{
if (error)
std::cerr << "Handshake failed: " << error.message() << std::endl;
else
{ }
}
void CPush::handle_write(const boost::system::error_code & error)
{
if (error)
std::cerr << "Write failed: " << error.message() << std::endl;
else
{
boost::asio::async_read_until(*psocket,
response, "\r\n",
boost::bind(&CPush::handle_read_status,
this,
boost::asio::placeholders::error));
std::cout << "Sending request OK!" << std::endl;
}
}
void CPush::handle_read_status(const boost::system::error_code & error)
{
if (error)
std::cout << "Error read status: " << error.message() << std::endl;
else
{
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
std::cout << "Invalid response\n";
return;
}
if (status_code != 200)
{
std::cout << "Response returned with status code ";
std::cout << status_code << "\n";
// return;
}
// Read the response headers, which are terminated by a blank line.
boost::asio::async_read_until(*psocket,
response, "\r\n\r\n",
boost::bind(&CPush::handle_read_header,
this,
boost::asio::placeholders::error));
}
}
void CPush::handle_read_header(const boost::system::error_code & error)
{
if (error)
std::cout << "Error read header: " << error.message() << std::endl;
else
{
// Process the response headers.
std::istream response_stream(&response);
std::string header;
while (std::getline(response_stream, header) && header != "\r")
std::cout << header << "\n";
std::cout << "\n";
// Write whatever content we already have to output.
if (response.size() > 0)
std::cout << &response;
// Start reading remaining data until EOF.
boost::asio::async_read(*psocket,
response,
boost::asio::transfer_at_least(1),
boost::bind(&CPush::handle_read_content,
this,
boost::asio::placeholders::error));
}
}
void CPush::handle_read_content(const boost::system::error_code & error)
{
if (error)
{
if (error != boost::asio::error::eof)
std::cout << "Error read content: " << error.message() << std::endl;
}
else
{
// Write all of the data that has been read so far.
std::cout << &response;
// Continue reading remaining data until EOF.
boost::asio::async_read(*psocket,
response,
boost::asio::transfer_at_least(1),
boost::bind(&CPush::handle_read_content,
this,
boost::asio::placeholders::error));
}
}
void CPush::LoopStart(void)
{
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(GOOGLE_HOST, GOOGLE_PORT);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
context.set_default_verify_paths();
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service, context);
socket.set_verify_mode(boost::asio::ssl::context::verify_none);
socket.set_verify_callback(boost::bind(&CPush::verify_certificate, this, _1, _2));
psocket = &socket;
pio_service = &io_service;
boost::asio::async_connect(psocket->lowest_layer(),
iterator,
boost::bind(&CPush::handle_connect,
this,
boost::asio::placeholders::error));
io_service.run();
}
void CPush::Send(const std::string tokens, const std::string cmd)
{
std::string json("{\"registration_ids\":[" + tokens + "],"
"\"notification\":null,"
....
"\"priority\":\"high\","
"\"time_to_live\":15}");
request << "POST " << GOOGLE_API << " HTTP/1.1\r\n"
<< "Host: " << GOOGLE_HOST << "\r\n" // << ":" << port
<< "Content-Type: application/json; charset=utf-8\r\n"
<< "Content-Length: " << json.size() << "\r\n"
<< "Authorization: key=" << push_key << "\r\n"
<< "\r\n"
<< json;
std::cout << "Sending request...\n" << request.str() << std::endl;
boost::asio::async_write(*psocket,
boost::asio::buffer(request.str()),
boost::bind(&CPush::handle_write,
this,
boost::asio::placeholders::error));
}
void CPush::LoopStop(void)
{
if (!pio_service->stopped()) pio_service->stop();
}
Приветствую
Почему может не выполняться проверка сертификатов сервера???
Пробовал так
openssl s_client -connect fcm.googleapis.com:443
на одном дебиане выхлоп корректный
CONNECTED(00000003)
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
verify return:1
depth=0 CN = *.google.com
verify return:1
---
Certificate chain
0 s:/CN=*.google.com
i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1C3
1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1C3
i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
2 s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIPBzCCDe+gAwIBAgIQKuaFLS3w+z4K/anwgexsvTANBgkqhkiG9w0BAQsFADBG
MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMzA3MTcwODE2MzFaFw0yMzEwMDkw
ODE2MzBaMBcxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAMfBborGk6pXdukFvjev59Vz+nq4XsLmbYMMDQEtmSui
8wKv5LP9FxeOa4KyRJbGPajaCXFkV9wkMl5yrTY93bZ5uwMZDORRzUWylxwHlZxN
ks0/Jvjp/gUKtc+K0z5WxOnkq5V+rNpjMr6I6W0UAHHLqS+FjyKCV5b5qA2Jadz9
nvv3ddO6OuA1ozx/wGLY2j2k/27cl4ep6DbK8gDURrciy7zSzAsz1cFUBzAUEfpw
em2YppjmzCuey22gYHuFsXB5k4rzTSu9gwx3A6wooIsg54R+csY3dyNHvisWuC7w
2VlEQ87PeCshOWCfdoIxoSNeeQOmFAp5vhbo5DvDRD0CAwEAAaOCDB4wggwaMA4G
A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA
MB0GA1UdDgQWBBQZ48UsKZ0bzHsEYfPyvXkC+xbu1jAfBgNVHSMEGDAWgBSKdH+v
hc3ulc09nNDiRhTzcTUdJzBqBggrBgEFBQcBAQReMFwwJwYIKwYBBQUHMAGGG2h0
dHA6Ly9vY3NwLnBraS5nb29nL2d0czFjMzAxBggrBgEFBQcwAoYlaHR0cDovL3Br
aS5nb29nL3JlcG8vY2VydHMvZ3RzMWMzLmRlcjCCCc0GA1UdEQSCCcQwggnAggwq
Lmdvb2dsZS5jb22CFiouYXBwZW5naW5lLmdvb2dsZS5jb22CCSouYmRuLmRldoIV
Ki5vcmlnaW4tdGVzdC5iZG4uZGV2ghIqLmNsb3VkLmdvb2dsZS5jb22CGCouY3Jv
d2Rzb3VyY2UuZ29vZ2xlLmNvbYIYKi5kYXRhY29tcHV0ZS5nb29nbGUuY29tggsq
Lmdvb2dsZS5jYYILKi5nb29nbGUuY2yCDiouZ29vZ2xlLmNvLmlugg4qLmdvb2ds
ZS5jby5qcIIOKi5nb29nbGUuY28udWuCDyouZ29vZ2xlLmNvbS5hcoIPKi5nb29n
bGUuY29tLmF1gg8qLmdvb2dsZS5jb20uYnKCDyouZ29vZ2xlLmNvbS5jb4IPKi5n
b29nbGUuY29tLm14gg8qLmdvb2dsZS5jb20udHKCDyouZ29vZ2xlLmNvbS52boIL
Ki5nb29nbGUuZGWCCyouZ29vZ2xlLmVzggsqLmdvb2dsZS5mcoILKi5nb29nbGUu
aHWCCyouZ29vZ2xlLml0ggsqLmdvb2dsZS5ubIILKi5nb29nbGUucGyCCyouZ29v
Z2xlLnB0ghIqLmdvb2dsZWFkYXBpcy5jb22CDyouZ29vZ2xlYXBpcy5jboIRKi5n
b29nbGV2aWRlby5jb22CDCouZ3N0YXRpYy5jboIQKi5nc3RhdGljLWNuLmNvbYIP
Z29vZ2xlY25hcHBzLmNughEqLmdvb2dsZWNuYXBwcy5jboIRZ29vZ2xlYXBwcy1j
bi5jb22CEyouZ29vZ2xlYXBwcy1jbi5jb22CDGdrZWNuYXBwcy5jboIOKi5na2Vj
bmFwcHMuY26CEmdvb2dsZWRvd25sb2Fkcy5jboIUKi5nb29nbGVkb3dubG9hZHMu
Y26CEHJlY2FwdGNoYS5uZXQuY26CEioucmVjYXB0Y2hhLm5ldC5jboIQcmVjYXB0
Y2hhLWNuLm5ldIISKi5yZWNhcHRjaGEtY24ubmV0ggt3aWRldmluZS5jboINKi53
aWRldmluZS5jboIRYW1wcHJvamVjdC5vcmcuY26CEyouYW1wcHJvamVjdC5vcmcu
Y26CEWFtcHByb2plY3QubmV0LmNughMqLmFtcHByb2plY3QubmV0LmNughdnb29n
bGUtYW5hbHl0aWNzLWNuLmNvbYIZKi5nb29nbGUtYW5hbHl0aWNzLWNuLmNvbYIX
Z29vZ2xlYWRzZXJ2aWNlcy1jbi5jb22CGSouZ29vZ2xlYWRzZXJ2aWNlcy1jbi5j
b22CEWdvb2dsZXZhZHMtY24uY29tghMqLmdvb2dsZXZhZHMtY24uY29tghFnb29n
bGVhcGlzLWNuLmNvbYITKi5nb29nbGVhcGlzLWNuLmNvbYIVZ29vZ2xlb3B0aW1p
emUtY24uY29tghcqLmdvb2dsZW9wdGltaXplLWNuLmNvbYISZG91YmxlY2xpY2st
Y24ubmV0ghQqLmRvdWJsZWNsaWNrLWNuLm5ldIIYKi5mbHMuZG91YmxlY2xpY2st
Y24ubmV0ghYqLmcuZG91YmxlY2xpY2stY24ubmV0gg5kb3VibGVjbGljay5jboIQ
Ki5kb3VibGVjbGljay5jboIUKi5mbHMuZG91YmxlY2xpY2suY26CEiouZy5kb3Vi
bGVjbGljay5jboIRZGFydHNlYXJjaC1jbi5uZXSCEyouZGFydHNlYXJjaC1jbi5u
ZXSCHWdvb2dsZXRyYXZlbGFkc2VydmljZXMtY24uY29tgh8qLmdvb2dsZXRyYXZl
bGFkc2VydmljZXMtY24uY29tghhnb29nbGV0YWdzZXJ2aWNlcy1jbi5jb22CGiou
Z29vZ2xldGFnc2VydmljZXMtY24uY29tghdnb29nbGV0YWdtYW5hZ2VyLWNuLmNv
bYIZKi5nb29nbGV0YWdtYW5hZ2VyLWNuLmNvbYIYZ29vZ2xlc3luZGljYXRpb24t
Y24uY29tghoqLmdvb2dsZXN5bmRpY2F0aW9uLWNuLmNvbYIkKi5zYWZlZnJhbWUu
Z29vZ2xlc3luZGljYXRpb24tY24uY29tghZhcHAtbWVhc3VyZW1lbnQtY24uY29t
ghgqLmFwcC1tZWFzdXJlbWVudC1jbi5jb22CC2d2dDEtY24uY29tgg0qLmd2dDEt
Y24uY29tggtndnQyLWNuLmNvbYINKi5ndnQyLWNuLmNvbYILMm1kbi1jbi5uZXSC
DSouMm1kbi1jbi5uZXSCFGdvb2dsZWZsaWdodHMtY24ubmV0ghYqLmdvb2dsZWZs
aWdodHMtY24ubmV0ggxhZG1vYi1jbi5jb22CDiouYWRtb2ItY24uY29tghRnb29n
bGVzYW5kYm94LWNuLmNvbYIWKi5nb29nbGVzYW5kYm94LWNuLmNvbYIeKi5zYWZl
bnVwLmdvb2dsZXNhbmRib3gtY24uY29tgg0qLmdzdGF0aWMuY29tghQqLm1ldHJp
Yy5nc3RhdGljLmNvbYIKKi5ndnQxLmNvbYIRKi5nY3BjZG4uZ3Z0MS5jb22CCiou
Z3Z0Mi5jb22CDiouZ2NwLmd2dDIuY29tghAqLnVybC5nb29nbGUuY29tghYqLnlv
dXR1YmUtbm9jb29raWUuY29tggsqLnl0aW1nLmNvbYILYW5kcm9pZC5jb22CDSou
YW5kcm9pZC5jb22CEyouZmxhc2guYW5kcm9pZC5jb22CBGcuY26CBiouZy5jboIE
Zy5jb4IGKi5nLmNvggZnb28uZ2yCCnd3dy5nb28uZ2yCFGdvb2dsZS1hbmFseXRp
Y3MuY29tghYqLmdvb2dsZS1hbmFseXRpY3MuY29tggpnb29nbGUuY29tghJnb29n
bGVjb21tZXJjZS5jb22CFCouZ29vZ2xlY29tbWVyY2UuY29tgghnZ3BodC5jboIK
Ki5nZ3BodC5jboIKdXJjaGluLmNvbYIMKi51cmNoaW4uY29tggh5b3V0dS5iZYIL
eW91dHViZS5jb22CDSoueW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29t
ghYqLnlvdXR1YmVlZHVjYXRpb24uY29tgg95b3V0dWJla2lkcy5jb22CESoueW91
dHViZWtpZHMuY29tggV5dC5iZYIHKi55dC5iZYIaYW5kcm9pZC5jbGllbnRzLmdv
b2dsZS5jb22CG2RldmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVy
cy5hbmRyb2lkLmdvb2dsZS5jboIYc291cmNlLmFuZHJvaWQuZ29vZ2xlLmNuMCEG
A1UdIAQaMBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwPAYDVR0fBDUwMzAxoC+g
LYYraHR0cDovL2NybHMucGtpLmdvb2cvZ3RzMWMzL2ZWSnhiVi1LdG1rLmNybDCC
AQUGCisGAQQB1nkCBAIEgfYEgfMA8QB2AK33vvp8/xDIi509nB4+GGq0Zyldz7EM
JMqFhjTr3IKKAAABiWMjJUEAAAQDAEcwRQIgOupe5IIvifbm8xiVlqEyhOBpvXTC
Mkvs+996tP8raj8CIQCC+C7j+83WcIXUnzjdW8wwN/3P0uNF49pPBTmResO+tQB3
ALNzdwfhhFD4Y4bWBancEQlKeS2xZwwLh9zwAw55NqWaAAABiWMjJR8AAAQDAEgw
RgIhAO1LcKXKCSglGWIo/8XcwE5dKrcyqmyZzjcq1+ybZaL9AiEArfqI2WkZqy6M
eHLLDw1hPAmLc6DsJ13iUTkIEq6XvaUwDQYJKoZIhvcNAQELBQADggEBAHfeJw06
wBei3Xl0+77k+p0jn5wWWVXpEzDiRdaJZsJy/29lWzgGaNNDU8/kYDtoEFvOaaun
WqrrkJSDLHGooerEGWBuPo57trL7W6ZeRVn4BEogjk6lgz5w7As6IEdGiz2kZNEp
saJVgbfkdHpVIsiXJBAKSD9gXbI58bxHtIMFAYd9LwwvG4P3yFnPoYiRhKXMBuWl
i906cqjelyUG4kjB+AwDcD837QDZC78fGLDwW9NsdwYyKgY2kBdbleeRwyXtigvw
IabvTdvYKuTK8R0l+DSMz6oKS9F2IU2QDTyO1CXGPU1mYQPmtV714sdzq3r9gZmP
rktC22JuuTQfLVs=
-----END CERTIFICATE-----
subject=/CN=*.google.com
issuer=/C=US/O=Google Trust Services LLC/CN=GTS CA 1C3
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 7357 bytes and written 261 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-CHACHA20-POLY1305
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-CHACHA20-POLY1305
Session-ID: 6729DCD94FC7F482C061EBA85C6925EBBD3825F91A40308F66BE77408BDE82D3
Session-ID-ctx:
Master-Key: A6A142D3777B88391EF8FCDBF83251658DD54178E49FA90D4E19D940BBCC8976BEEFE8AEC4445BD65B9B1232258E91F9
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 100800 (seconds)
TLS session ticket:
0000 - 02 f4 dc 2a b0 9d 9e d3-84 56 19 15 ff 1c 8d eb ...*.....V......
0010 - 19 65 dc 84 fe c9 6a 7b-fe 89 44 6a e7 88 0f 20 .e....j{..Dj...
0020 - 6c fa 03 b3 3d b6 0c f0-85 09 2a 26 a5 99 9f 25 l...=.....*&...%
0030 - fa c3 0b 3d 56 58 96 95-1a 55 96 da 3b 90 07 bc ...=VX...U..;...
0040 - 66 54 e8 b7 ad 0d ef b6-9b ff 61 d4 34 f6 6e 03 fT........a.4.n.
0050 - 3c 19 36 f7 6a fd 77 cf-b1 86 48 93 15 88 d7 40 <.6.j.w...H....@
0060 - 7b 4d 5b 00 7f 44 ca c8-a9 d0 a3 31 5b e1 b7 2f {M[..D.....1[../
0070 - 5a 4e d9 8c e5 69 0b 18-ec 99 45 3a 54 16 f0 39 ZN...i....E:T..9
0080 - cf 89 de 8d d5 3d 11 0b-e4 04 4e 54 46 a5 fe f8 .....=....NTF...
0090 - db e9 57 49 c4 c1 b7 9a-84 fe 61 dc b5 bd 13 ed ..WI......a.....
00a0 - 2e 08 4e bb b0 f5 b7 d0-ec ae 63 59 1c 0b c7 96 ..N.......cY....
00b0 - 43 33 2c d3 9e a7 bb b9-5b 30 57 36 a5 c3 b6 12 C3,.....[0W6....
00c0 - 8e f1 e3 7a d0 fd f7 22-cc bf 1b c1 df f7 22 33 ...z..."......"3
00d0 - 10 83 e6 3e cc c6 28 b6-c8 d8 4c 50 50 32 52 0d ...>..(...LPP2R.
00e0 - 2f 4c 31 d3 14 /L1..
Start Time: 1691473119
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: yes
---
read:errno=0
на другом вижу только висящее
CONNECTED(00000003)
Приветствую
Подскажите где у меня косяк, а смотрю в документацию - вижу фигу
Вызов Send(), чернового варианта класса описанного ниже, выполняется только один раз, в чем косяк у меня, а то смотрю в документацию - вижу фигу.
class CPush
{
private:
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver::iterator iterator;
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> * psocket;
boost::asio::streambuf response;
bool verify_certificate(bool preverified, boost::asio::ssl::verify_context & ctx)
{
char subject_name[256];
X509 * cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
std::cout << "Verifying " << subject_name << std::endl;
return preverified;
}
void handle_connect(const boost::system::error_code & error)
{
if (error)
std::cerr << "Connect failed: " << error.message() << std::endl;
else
{
psocket->async_handshake(boost::asio::ssl::stream_base::client,
boost::bind(&CPush::handle_handshake,
this,
boost::asio::placeholders::error));
std::cout << "Connection OK!" << std::endl;
}
}
void handle_handshake(const boost::system::error_code & error)
{
if (error)
std::cerr << "Handshake failed: " << error.message() << std::endl;
else
{
std::string json("{\"registration_ids\":[\"" + token + "\"],"
+"\"notification\":null,"
.......
+"\"priority\":\"high\","
+"\"time_to_live\":15}");
std::stringstream request;
request << "POST " << GOOGLE_API << " HTTP/1.1\r\n"
<< "Host: " << GOOGLE_HOST << "\r\n" // << ":" << GOOGLE_PORT
<< "Content-Type: application/json; charset=utf-8\r\n"
<< "Content-Length: " << json.size() << "\r\n"
<< "Authorization: key=" << push_key << "\r\n"
<< "Connection: close\r\n"
<< "\r\n"
<< json << "\r\n\r\n";
std::cout << "Sending request...\n" << request.str();
boost::asio::async_write(*psocket,
boost::asio::buffer(request.str()),
boost::bind(&CPush::handle_write,
this,
boost::asio::placeholders::error));
}
}
void handle_write(const boost::system::error_code & error)
{
if (error)
std::cerr << "Write failed: " << error.message() << std::endl;
else
{
boost::asio::async_read_until(*psocket,
response, "\r\n",
boost::bind(&CPush::handle_read_status,
this,
boost::asio::placeholders::error));
std::cout << "Sending request OK!" << std::endl;
}
}
void handle_read_status(const boost::system::error_code & error)
{
if (error)
std::cout << "Error read status: " << error.message() << std::endl;
else
{
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
std::cout << "Invalid response\n";
return;
}
if (status_code != 200)
{
std::cout << "Response returned with status code ";
std::cout << status_code << "\n";
// return;
}
// Read the response headers, which are terminated by a blank line.
boost::asio::async_read_until(*psocket,
response, "\r\n\r\n",
boost::bind(&CPush::handle_read_header,
this,
boost::asio::placeholders::error));
}
}
void handle_read_header(const boost::system::error_code & error)
{
if (error)
std::cout << "Error read header: " << error.message() << std::endl;
else
{
// Process the response headers.
std::istream response_stream(&response);
std::string header;
while (std::getline(response_stream, header) && header != "\r")
std::cout << header << "\n";
std::cout << "\n";
// Write whatever content we already have to output.
if (response.size() > 0)
std::cout << &response;
// Start reading remaining data until EOF.
boost::asio::async_read(*psocket,
response,
boost::asio::transfer_at_least(1),
boost::bind(&CPush::handle_read_content,
this,
boost::asio::placeholders::error));
}
}
void handle_read_content(const boost::system::error_code & error)
{
if (error)
{
if (error != boost::asio::error::eof)
std::cout << "Error read content: " << error.message() << std::endl;
}
else
{
// Write all of the data that has been read so far.
std::cout << &response;
// Continue reading remaining data until EOF.
boost::asio::async_read(*psocket,
response,
boost::asio::transfer_at_least(1),
boost::bind(&CPush::handle_read_content,
this,
boost::asio::placeholders::error));
}
}
public:
CPush(void)
{
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(GOOGLE_HOST, GOOGLE_PORT);
iterator = resolver.resolve(query);
boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);
context.set_default_verify_paths();
psocket = new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(io_service, context);
psocket->set_verify_mode(boost::asio::ssl::context::verify_none);
psocket->set_verify_callback(boost::bind(&CPush::verify_certificate, this, _1, _2));
}
void Send(void)
{
boost::asio::async_connect(psocket->lowest_layer(),
iterator,
boost::bind(&CPush::handle_connect,
this,
boost::asio::placeholders::error));
io_service.run();
}
};
← предыдущие | следующие → |