LINUX.ORG.RU

Сообщения wolverin

 

Для чего alignas?

Форум — Development

Приветствую.

Про определение о требовании выравнивания читал конечно. Но таки как выбирается аргумент??? чтобы получить кучи прироста производительности )

Т.е. я например объявляю объекты как

alignas(64) std::atomic<size_t> tail;
alignas(64) std::atomic<size_t> head;

на xeon прирост в 2 раза, а на виртуалке можно считать погрешностью, но при 16 уже на виртуалке хоть и маленький, но таки -5% времени выполнения, при этом на процессоре падение.

 ,

wolverin
()

dkim pubkey_unavailable

Форум — Admin

приветствую.

савчера вдрух 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 до бинда тоже открыл, так то письма ходят, но подскажите что этому майлу может быть еще нужно???

 

wolverin
()

Почему write(fd,..) висит?

Форум — Development

Приветствую

В продолжении темы Рестартануть драйвер как?

нашел как из консоли бесконечно количество раз рестартить драйвер

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 не снимаемая БЛОКИРОВКА

где может быть у меня косяк?

 , ,

wolverin
()

Рестартануть драйвер как?

Форум — Development

Приветствую

В продолжении темы Как рестартануть /dev/fb1 ???

как можно перезапустить из своего бинарника драйвер через ядро БЕЗ modprobe ???

 ,

wolverin
()

Как рестартануть /dev/fb1 ???

Форум — Linux-hardware

Приветствую.

Через /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

 ,

wolverin
()

Линковка extern вместо передачи указателя в C и С++?

Форум — Development

Приветствую.

Вынес кусок кода в отдельный 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);

По всякому уже попробовал ) Собирается только если будет как объектник выделенного кода, так и сам код включен в компиляцию бинарника, выглядит конечно это бредово.

 , , ,

wolverin
()

RTSP публикация надежна?

Форум — Development

Приветствую.

В чужом решении с тысячами железок, которое переписываю, схема предоставление видео реализована через видео rtsp прокси сервер (rtsp-simple-server) + openvpn до каждой железки с ее rtsp сервером - само собой что такая архитектура обладает некоторой сложностью и как следствие не высокой надежностью.

Поскольку пока нет возможности выпилить видео прокси, есть частично проверенная идея на железках «перевернуть» сервер, используя если не сам ffmpeg, то его либы, выполняя с железки пуш rtsp подключение.

В прошлом году удалось втащить старый ffserver с новыми либами ффмпега в свой проект, что дало по быстрому реализовать свой rtsp сервер, в который видео передаю как раз с помощью пуша ртсп между своими же потоками через локальный интерфейс - проблем не замечено, но тут это будет не в единичном случае, а тысячи таких подключений через ентернет, хоть сам rtsp-simple-server такой способ и поддерживает как я проверил.

Это бы дало мне отказ он vpn и части php функционала на проксе. Или может есть другие более надежные способы выкинуть VPN в такой схеме ???

 ,

wolverin
()

std::bad_function_call на указатель метода класса

Форум — Development

Приветствую.

В продолжении темы Вызов по указателю метода структуры вложенной в класс

Есть обработчик очереди класса в отдельном потоке

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))

Разве нельзя одновременно передавать указатель на метод класса в другой поток и обращаться к нему???

 

wolverin
()

«без ключевое» шифрование конфига

Форум — Development

Приветствую

Есть куча железок на убунте (может будет расбиан), которые могут быть физически стырены, необходимо зашифровать конфиги моего ПО на них, да так чтобы ключ-пароль сей не светился в самом бинарнике.

Ранее пользовал штатную библиотеку libgcrypt с алгоритмом AES в режиме CBC, поэтому из мыслей брать пароль и соль, например, mac и uuid диска, но кажется это тривиальным

Посоветуйте как можно решить подобную задачу, в идеале «штатными» средствами.

 ,

wolverin
()

Вызов по указателю метода структуры вложенной в класс

Форум — Development

Приветствую.

Имеется класс вида

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 ???

 

wolverin
()

Приоритетная очередь

Форум — Development

Приветствую

Через однопоточный обработчик поступают mqtt команды и его никак нельзя тормозить ещё и их обработкой, при этом какие то типы команд могут быть быстро обработаны, какие то существенно медленней.

Если с самой очередью приоритотов вроде есть понимание в использовании std::priority_queue (или лучше мудрить с heap???), то как организовать раздельную обработку каждого приоритета, чтобы длинные низкоприоритетные задачи не тормозили более высокие пока не соображу.

Пока только 2 вида, но может в будущем будет больше и не хочется тупо делать количество очередей просто по количеству приоритотов.

На чем такое реализовать на плюсах???

 

wolverin
()

Boost.Asio и несколько async_write/async_read за раз

Форум — Development

И снова здравствуйте! )

Получилось ПОЧТИ что хотел - за одно подключение-рукопожатие при пиковом (за время полного цикла от подключения до записи в сокет) поступлении команд через 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_);

 , ,

wolverin
()

boost::asio::async_write вызывает Segmentation fault

Форум — Development

Приветствую.

Даже спрашивать уже опасаюсь, опять отдельные личности с большим самомнением начнут объяснять какой я тупой, но все таки попробую, вдруг кому не сложно )

Код класс ниже, теста ради из одного потока все работало, пока не решил вызвать 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();
}

 , ,

wolverin
()

openssl не выполняет рукопожатие

Форум — Admin

Приветствую

Почему может не выполняться проверка сертификатов сервера???

Пробовал так

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)

 

wolverin
()

REST через Boost.Asio

Форум — Development

Приветствую

Подскажите где у меня косяк, а смотрю в документацию - вижу фигу

Вызов 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();
}
};

 , ,

wolverin
()

libcurl vs Boost.Asio

Форум — Development

Приветствую

Надо из кода на плюсах слать PUSH на андройд через REST запросы POST на ихний https сервер.

Что быстрее будет из этих двух работать???

Курл конечно много проще, но это ж надо еще либу эту поддерживать отдельно в проекте, бууст почти как стд вроде как, хотя вопрос конечно больше в эффективности.

ЗЫ. количество посылок в секунду пока хз сколько )

 , ,

wolverin
()

Чем заменить HTTP клиента?

Форум — Development

Опять очень нуждаюсь в идеи )

Есть большой парк (несколько тысяч) простых железок, часть функционала в которых реализована через HTTP, другая часть это SIP и MQTT.

Есть непреодолимое желание выпилить функционал на HTTP именно с самих железок, который причем использует одновременно 2 сервера и служащий для того, чтобы железка после событий пришедших из SIP или MQTT (к слову находящихся сейчас физически там же где и HTTP) что то сделала, например, полазила в БД или отправила push на андройд и тд.

Есть мысль уж коли приходит что то в mqtt, то и ответить надо туда же, а уж на стороне сервера эта перенесенная часть функционала будет слушать и делать то же самое, что делает множество железок, НО возникает момент, что это может стать узким местом в алгоритме из-за однопоточности обработки очереди сообщений из mqtt.

Как бы Вы поступили???

ЗЫ. цель выпиливания - упрощение и увеличение надежности работы самих железок, а так же появится простая возможность обернуть железки в простое api

 , ,

wolverin
()

template с параметром по умолчанию

Форум — Development

Очень хотелось бы (для сокращения написанного кода) в зависимости от параметра шаблона, который в общем случае может быть задан по дефолту в описании шаблона, получать НЕМНОГО отличающиеся по реализации классы

сцуть тривиального шаблона который компилируется (правда на выполнение не проверял)

using guard = unique_lock<mutex>;

template <typename Cmd_t> class TQueue
{
private:
    const uint8_t maxQ;

    deque<Cmd_t> dqQ;

    mutex mtx;
public:

    TQueue(uint8_t lQueue)
    : maxQ(lQueue)
    { }

    ~TQueue()
    {
        if (!dqQ.empty())
            dqQ.clear();
    }

    uint8_t Put(Cmd_t cmd);
    uint8_t Get(Cmd_t & cmd);
};

template <typename Cmd_t> uint8_t TQueue<Cmd_t>::Put(const Cmd_t cmd)
{
    uint8_t rt = 0;
    {
        guard g(mtx);

        rt = dqQ.size();
        if (rt < maxQ)
        {
            dqQ.push_back(cmd);
            rt++;
        }
    }

    return rt;
}

пытаюсь что то эдакое туда засунуть

template <typename Cmd_t, sem_t * psem = NULL> class TQueue

gcc ругается

error: could not convert template argument ‘0l’ to ‘sem_t*’

а еще как бы в реализации Put проверить пришедший параметр psem на нулл и если нет, то вставить соответственно туда sem_post(), чтобы он был только в нужно месте, а не во всех классах ествественно.

премного буду благодарен за любую помощь )

 ,

wolverin
()

Как обратиться к std::shared_ptr<void> ???

Форум — Development

Подскажите как правильно тип привести, чтобы подсчет ссылок не поломался?

Чтобы не усложнять линковку при компиляции решил в заголовочном файле в классе сделать замену

std::shared_ptr<linphone::Core> core >>> std::shared_ptr<void> core

проинициализировалось

auto factory = linphone::Factory::get();
core = factory->createCoreWithConfig(config, nullptr);

Как теперь здесь обратиться корректно???

...core...->addListener(std::make_shared<ClientCoreListener>())

 

wolverin
()

Как из сокета прочитанного recvmsg вытащить IP адрес?

Форум — Development

Мучаю тут тему с приклеиванием трассировки к библиотеки пинга

описание приходящей структуры msghdr и вытаскиваемой макросами из нее cmsghdr посмотрел, но как из них получить IP адрес отправителя ICMP пакета что то не догоняю

подскажите если не затруднит куда искать, на что смотреть???

на всякий случай дублирую то место в коде liboping.c где происходит чтение

payload_buffer_len = recvmsg (fd, &msghdr, /* flags = */ 0);
        if (payload_buffer_len < 0)
        {
#if WITH_DEBUG
                char errbuf[PING_ERRMSG_LEN];
                dprintf ("recvfrom: %s\n",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
#endif
                return (-1);
        }
        dprintf ("Read %zi bytes from fd = %i\n", payload_buffer_len, fd);

        /* Iterate over all auxiliary data in msghdr */
        recv_ttl = -1;
        recv_qos = 0;
        for (cmsg = CMSG_FIRSTHDR (&msghdr); /* {{{ */
                        cmsg != NULL;
                        cmsg = CMSG_NXTHDR (&msghdr, cmsg))
        {
                if (cmsg->cmsg_level == SOL_SOCKET)
                {
#ifdef SO_TIMESTAMP
                        if (cmsg->cmsg_type == SO_TIMESTAMP)
                                memcpy (&pkt_now, CMSG_DATA (cmsg), sizeof (pkt_now));
#endif /* SO_TIMESTAMP */
                }
                else if (addrfam == AF_INET) /* {{{ */
                {
                        if (cmsg->cmsg_level != IPPROTO_IP)
                                continue;

                        if (cmsg->cmsg_type == IP_TOS)
                        {
                                memcpy (&recv_qos, CMSG_DATA (cmsg),
                                                sizeof (recv_qos));
                                dprintf ("TOSv4 = 0x%02"PRIx8";\n", recv_qos);
                        } else
                        if (cmsg->cmsg_type == IP_TTL)
                        {
                                memcpy (&recv_ttl, CMSG_DATA (cmsg),
                                                sizeof (recv_ttl));
                                dprintf ("TTLv4 = %i;\n", recv_ttl);
                        }
                        else
                        {
                                dprintf ("Not handling option %i.\n",
                                                cmsg->cmsg_type);
                        }
                } /* }}} */

 ,

wolverin
()

RSS подписка на новые темы