LINUX.ORG.RU

Сообщения wolverin

 

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

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

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

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

Приветствую

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

Пробовал так

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

Приветствую

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

Вызов 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

Приветствую

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

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

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

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

 , ,

wolverin
()

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

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

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

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

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

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

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

 , ,

wolverin
()

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

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

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

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

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

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

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 адрес?

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

описание приходящей структуры 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
()

Либу traceroute/ping на C/C++

Засоветуйте? )

тот что православный из убунты/дебиана

этот не предлагать ) https://habr.com/ru/articles/726714/

 , ,

wolverin
()

std::string length возвращает 16777215

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

уже все проверил, вроде ничего память не переписывает

 

wolverin
()

Запись сырого h264

Для mjpeg потока с камеры реализовал круговую запись на носитель без файловой системы благодаря тому, что jpg это ключевой кадр и структура позволяет каждую минуту в поле «комментарии» ставить дополнительную информацию (временную метку, размер кадра и координату предыдущей минуты), при желании можно даже слить через dd данные и их как то проиграет vlc, словом все кроме передачи по ентернету происходит быстро.

Теперь пришли h264 камеры, а с этим потоком как известно все сложнее - начать просмотр можно только с И кадра, куча разнообразных блоков, в отличии от жпега представление внутренней структуры кадров на Хабре как то не нашлось )

Посоветуйте что нибудь разумное как можно аналогично реализовать круговую запись h264, в приблизительно в той же концепции что и mjpg???

ВАЖНО что выполняется это все на слабенькой ARMv7

Сам пока планирую засовывать как есть поток в минутный mp4 контейнер, но возникает вопрос будут ли пропуски между минутами и насколько ресурсоемко потом делать демукс-мукс в сетевой протокол передачи (сейчас пока использую «протокол» tcp из ffmpeg для передачи)

ЗЫ. звеняйте за многа букав

 

wolverin
()

Помогите с std::function

Приветствую

Суть задачи проста - получить параметры одного или всех сетевых интерфейсов, понятно что можно в векторе, например, вернуть, но можно как то вот хитрожопо сделать через std::function или что то иное есть??? Так чтобы снаружи вызова можно было построчно обработать.

код, в котором не догоняю как можно getIPs и getIP реализовать, чтобы потом их вызывать можно было???

std::string getSockToIP(const struct sockaddr * psa)
{
    uint8_t laddr = 0;
    char * addr = nullptr;
    std::string rt("");

    switch (psa->sa_family)
    {
        case AF_INET:
            addr = (char*)calloc(laddr = INET_ADDRSTRLEN, sizeof(char));
            break;
        case AF_INET6:
            addr = (char*)calloc(laddr = INET6_ADDRSTRLEN, sizeof(char));
            break;
    }

    if (laddr > 0)
    {
        inet_ntop(psa->sa_family, &((struct sockaddr_in*)(psa))->sin_addr, addr, laddr);
        rt.assign(addr);
        free(addr);
    }

    return rt;
}

std::string getIPAddr(const struct ifaddrs * pifa)
{
    std::string rt(pifa->ifa_name);
    if (pifa->ifa_addr)
        rt += " " + getSockToIP(pifa->ifa_addr);

    if (pifa->ifa_netmask)
        rt += " " + getSockToIP(pifa->ifa_netmask);

    return rt;
}

bool getIFAddrs(std::function<bool(struct ifaddrs * pifa)> cbFunc)
{
    struct ifaddrs * pifa = nullptr;
    if (getifaddrs(&pifa))
        return false;
    else
    {
        for (struct ifaddrs * p = pifa; !p; p = p->ifa_next)
            if (cbFunc(p))
                break;

        freeifaddrs(pifa);
        return true;
    }
}

void getIPs(std::function<std::string(void)> cbFunc)
{
    getIFAddrs([&](struct ifaddrs * pifa)
    {
//getIPAddr(pifa)
        return false;
    });
}

void getIP(const char * dev)
{
    getIFAddrs([&](struct ifaddrs * pifa)
    {
//getIPAddr(pifa)
        return !strcmp(pifa->ifa_name, dev);
    });
}

 

wolverin
()

av_read_frame отдает одинаковые кадры

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

В отсутствии носителя для записи локального видео архива решил делать снимки (пока по времени) с усб mjpeg камеры через библиотеку ffmpeg и столкнулся с проблемой - если захватывать с камеры кадры 1 раз в 10 минут, то они идентичны, при этом если с такой же периодичностью, но прочитать подряд 5 кадров и взять последний, то проблема уходит.

Так понимаю что камера отдает какой то буфер кадров за раз и ффмпег должен «вычитать» все, перед тем как получить новый!?

Или как можно победить проблему?

 ,

wolverin
()

Либу на С/C++ на анализ движения?

Посоветуйте, пожалста???

Есть мжпег камера, делаю с нее снимки ffmpeg либой, но хотелось бы иметь возможность проанализировать дельту движа между кадрами, в тупую сравнить по размеру кадры выходит не очень.

 ,

wolverin
()

Опять хитрая очередь для 2х потоков на C++

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

Сразу к сцути - пишет значит моя приблуда с 30 кадровой камеры мжпег кадры на SD карту на одноплатнике по кругу, для снижения нагрузки и получения некой равномерности делается это таким образом - меряю время в начале цикла записи, сравниваю после и оставшееся время либо сплю до частоты 10 фпс, либо пишу сразу следующий.

Все бы ничего, но иногда требуется как посмотреть текущее видео с камеры, которое перекодируется в х264 и отдается в ртсп, так и глянуть архив, которое хоть и не нагружает цпу у армки, но читает большие объемы с сд карты и шлет их активно в сеть по удп.

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

Но вот вопрос - как бы сделать так, чтобы на время записи-удаления из очереди И добавления в очередь - она НЕ БЛОКИРОВАЛАСЬ ??? Иба если блочить - очевидно опять будет неравномерность.

 ,

wolverin
()

Почему av_write_frame в FFmpeg такой медленный???

Читаю данные с SD карты на одноплатнике и отправляю их по сети через ффмпеговские либы, дамп на передающей стороне выглядит так

Output #0, mjpeg, to 'udp://192.168.1.1:5555':
  Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 1920x1080, q=2-31, 10 fps, 90k tbn

решил тут померить почему выдает нагрузку на сеть всего 4мбит/c и оказывается операция av_write_frame занимает в среднем 300-350 мс!!!

В чем может быть причина???

К слову за те же 300 мс с карты удается считать по 4Мбайта

 ,

wolverin
()

Форумы ака «поиск помощи» vs ChatGPT

Если с программированием еще сомнительно, т.к. сие действо больше творческий процесс, нежели тупое набивание букав, то похоже использование ЛЮБЫХ технических форумов аки места для поиска помощи у людей, кто ранее сталкивался с похожими проблемами в конечном итоге станет ненужным

Пришло тут мне в рассылке ffmpeg как человеку решение его проблемы подсказал ChatGPT, причем быстро и сразу точно http://ffmpeg.org/pipermail/libav-user/2023-April/013348.html

и реально, а почему не использовать более эффективный способ поиска решения???

 

wolverin
()

FFmpeg для клиент/серверной передачи

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

Необходимо передать видео через ентернеты (в общем случае через симметричные NATы с обоих сторон, т.е. это использование STUN + в моем случае сигнальный сервер MQTT, но пока для чистоты эксперимента на принимающей стороне белый ip).

Решение в лоб - отправить по запросу через mqtt с «клиента» rtp поток и получить его на «сервере» - натолкнулось естественно на ошибку об отсутствии SDP

[rtp @ 0x7f5d300008c0] Guessing on RTP content - if not received properly you need an SDP file describing it

Решением конкретно этой ошибки предлагается подгружать SDP файл в либы ffmpeg на стороне сервера, но такое не подходит иба белым сервер по итогу не будет. Конечно можно пересылать измененные параметры SDP через MQTT, создавать после этого файл на стороне сервера и грузить в avformat_open_input, но нет ли варианта попроще??? Ведь по сути разница только в IP адресе...

Так же не сочтите за наглость вопрос - в чем разница форматов у ffmpeg при стриме rtp, mpegts и rtp_mpegts, при этом исходящий (push) адрес может быть как rtp:// так и udp:// ???

Буду благодарен если кто то ткнет в конкретное место в документации и/или примере, сам пока не осилил похожее закодить https://www.programmersought.com/article/2920550131/

 , ,

wolverin
()

Самый распространенный видеоформат?

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

Накодил по своей старой теме чтение записанного архива Одновременное чтение и запись «файла»

теперь надо послать все это дело через ентернеты, планирую через ffmpeg, используя только rtp.

И вот вопрос возник - а во что лучше всего пожать видео, чтобы отправив такой ФАЙЛ хоть кому, он хоть где прочитался???

 

wolverin
()

Одновременное чтение и запись «файла»

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

Продолжаю мучать тему С++ vs прямая запись на флешку

Вроде пишется как хотел, НО теперь дошла очередь чтения записываемого видео архива, т.е. все надо делать ОДНОВРЕМЕННО.

Тем кому лень читать всякое мое старье - напомню что пишу на сырую флешку через Cишный stdio с кешем setvbuf(pf, NULL, _IOFBF, 256 * 1024) mjpeg кадры в разрешении 2мп.

Вопрос - что будет шустрее - еще раз открывать на чтение этот же диск-«файл» (как насчет недоступности для чтения того что в кеше?) или лучше все же устраивать «передергивание» позиции на уже открытом - чтение с нужной позиции, пока не приходит событие отдать «файл» на запись и т.д. ???

Критика идеи приветствуется )

 ,

wolverin
()

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