summaryrefslogtreecommitdiffstats
path: root/src/CLI/ABRTSocket.cpp
blob: 1353134247959499ba6230a1a0e94f14bb930152 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "ABRTSocket.h"
#include "ABRTException.h"
#include "CrashTypesSocket.h"

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>

CABRTSocket::CABRTSocket() : m_nSocket(-1)
{}

CABRTSocket::~CABRTSocket()
{
    /* Paranoia. In C++, destructor will abort() if it was called while unwinding
     * the stack and it throws an exception.
     */
    try
    {
        Disconnect();
    }
    catch (...)
    {
        error_msg_and_die("Internal error");
    }
}

void CABRTSocket::Send(const std::string& pMessage)
{
    int ret = 0;
    int len = pMessage.length();
    int offset = 0;
    char* message = new char[len + 3];
    memcpy(message, pMessage.c_str(), len);
    message[len] = MESSAGE_END_MARKER;
    message[len + 1] = '\n';
    message[len + 2] = '\0';

    while (ret != strlen(message + offset))
    {
        offset += ret;
        ret = send(m_nSocket, message + offset, strlen(message + offset), 0);
        if (ret == -1)
        {
            throw CABRTException(EXCEP_FATAL, "CABRTSocket::Send(): Can not send data");
        }
    }
    delete[] message;
}

void CABRTSocket::Recv(std::string& pMessage)
{
    std::string message;
    bool receivingMessage = true;
    char buff[1];
    int ret;

    pMessage = "";
    while (receivingMessage)
    {
        ret = recv(m_nSocket, buff, 1, 0);
        if (ret == -1)
        {
            throw CABRTException(EXCEP_FATAL, "CABRTSocket::Recv(): Can not recv data");
        }
        else if (ret == 0)
        {
            throw CABRTException(EXCEP_FATAL, "CABRTSocket::Recv(): Connection closed by abrt server");
        }

        message += buff[0];

        if (message.length() > 2 &&
            message[message.length() - 2] == MESSAGE_END_MARKER &&
            message[message.length() - 1] == '\n')
        {
            receivingMessage = false;
            message = message.substr(0, message.length() - 2);
        }
    }
    pMessage = message;
}


void CABRTSocket::Connect(const std::string& pPath)
{
    int len;
    struct sockaddr_un remote;
    if ((m_nSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
    {
        throw CABRTException(EXCEP_FATAL, "CABRTSocket::Connect(): Can not create socket");
    }
    remote.sun_family = AF_UNIX;
    strcpy(remote.sun_path, pPath.c_str());
    len = strlen(remote.sun_path) + sizeof(remote.sun_family);
    if (connect(m_nSocket, (struct sockaddr *)&remote, len) == -1)
    {
        throw CABRTException(EXCEP_FATAL, "CABRTSocket::Connect(): Can not connect to remote");
    }
}

void CABRTSocket::Disconnect()
{
    if (m_nSocket != -1)
        close(m_nSocket);
}

vector_crash_infos_t CABRTSocket::GetCrashInfos()
{
    std::string message = MESSAGE_GET_CRASH_INFOS;
    Send(message);
    Recv(message);
    message.erase(0, sizeof(MESSAGE_GET_CRASH_INFOS) - 1);
    return string_to_crash_infos(message);
}

map_crash_report_t CABRTSocket::CreateReport(const std::string &pUUID)
{
    std::string message = MESSAGE_CREATE_REPORT + pUUID;
    Send(message);
    Recv(message);
    message.erase(0, sizeof(MESSAGE_CREATE_REPORT) - 1);
    return string_to_crash_report(message);
}

void CABRTSocket::Report(const map_crash_report_t& pReport)
{
    std::string message = MESSAGE_REPORT + crash_report_to_string(pReport);
    Send(message);
}

void CABRTSocket::DeleteDebugDump(const std::string& pUUID)
{
    std::string message = MESSAGE_DELETE_DEBUG_DUMP + pUUID;
    Send(message);
}