]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/smux/utils.cpp
Improved handling errors got from server.
[stg.git] / projects / stargazer / plugins / other / smux / utils.cpp
1 #include <unistd.h> // write
2
3 #include <cstring> // memset
4 #include <cerrno>
5
6 #include "stg/common.h"
7
8 #include "stg/OpenPDU.h"
9 #include "stg/ClosePDU.h"
10 #include "stg/RReqPDU.h"
11 #include "stg/ber_decoder.h"
12 #include "stg/der_encoder.h"
13
14 #include "pen.h"
15 #include "utils.h"
16
17 bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi)
18 {
19 size_t left = 0, pos = 0, arcPos = 0;
20 int arcs[1024];
21 pos = str.find_first_of('.', left);
22 if (pos == 0)
23     {
24     left = 1;
25     pos = str.find_first_of('.', left);
26     }
27 while (pos != std::string::npos)
28     {
29     int arc = 0;
30     if (str2x(str.substr(left, left - pos), arc))
31         {
32         return false;
33         }
34     arcs[arcPos++] = arc;
35     left = pos + 1;
36     pos = str.find_first_of('.', left);
37     }
38 if (left < str.length())
39     {
40     int arc = 0;
41     if (str2x(str.substr(left, left - pos), arc))
42         {
43         return false;
44         }
45     arcs[arcPos++] = arc;
46     }
47 OBJECT_IDENTIFIER_set_arcs(oi, arcs, sizeof(arcs[0]), static_cast<unsigned int>(arcPos));
48 return true;
49 }
50
51 std::string OI2String(OBJECT_IDENTIFIER_t * oi)
52 {
53 std::string res;
54
55 int arcs[1024];
56 int count = OBJECT_IDENTIFIER_get_arcs(oi, arcs, sizeof(arcs[0]), 1024);
57
58 if (count > 1024)
59     return "";
60
61 for (int i = 0; i < count; ++i)
62     {
63     res += ".";
64     std::string arc;
65     strprintf(&arc, "%d", arcs[i]);
66     res += arc;
67     }
68
69 return res;
70 }
71
72 bool SendOpenPDU(int fd)
73 {
74 const char * description = "Stg SMUX Plugin";
75 asn_enc_rval_t error;
76 OpenPDU_t msg;
77
78 memset(&msg, 0, sizeof(msg));
79
80 msg.present = OpenPDU_PR_simple;
81 asn_long2INTEGER(&msg.choice.simple.version, SimpleOpen__version_version_1);
82 if (!String2OI(PEN_PREFIX, &msg.choice.simple.identity))
83     {
84     printfd(__FILE__,
85             "SendOpenPDU() - failed to convert string to OBJECT_IDENTIFIER\n");
86     return false;
87     }
88 OCTET_STRING_fromString(&msg.choice.simple.description, description);
89 OCTET_STRING_fromString(&msg.choice.simple.password, "");
90
91 char buffer[1024];
92 error = der_encode_to_buffer(&asn_DEF_OpenPDU, &msg, buffer, sizeof(buffer));
93
94 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OpenPDU, &msg);
95
96 if (error.encoded == -1)
97     {
98     printfd(__FILE__, "Could not encode OpenPDU (at %s)\n",
99             error.failed_type ? error.failed_type->name : "unknown");
100     return false;
101     }
102 else
103     {
104     if (write(fd, buffer, error.encoded) < 0)
105         {
106         printfd(__FILE__, "Failed to send OpenPDU: %s\n", strerror(errno));
107         return false;
108         }
109     }
110 return true;
111 }
112
113 bool SendClosePDU(int fd)
114 {
115 ClosePDU_t msg;
116
117 memset(&msg, 0, sizeof(msg));
118
119 asn_long2INTEGER(&msg, ClosePDU_goingDown);
120
121 char buffer[1024];
122 asn_enc_rval_t error;
123 error = der_encode_to_buffer(&asn_DEF_ClosePDU, &msg, buffer, sizeof(buffer));
124
125 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_ClosePDU, &msg);
126
127 if (error.encoded == -1)
128     {
129     printfd(__FILE__, "Could not encode ClosePDU (at %s)\n",
130             error.failed_type ? error.failed_type->name : "unknown");
131     return false;
132     }
133 else
134     {
135     if (write(fd, buffer, error.encoded) < 0)
136         {
137         printfd(__FILE__, "Failed to send ClosePDU: %s\n", strerror(errno));
138         return false;
139         }
140     }
141 return true;
142 }
143
144 bool SendRReqPDU(int fd)
145 {
146 int oid[] = {1, 3, 6, 1, 4, 1, 38313, 1};
147 asn_enc_rval_t error;
148 RReqPDU_t msg;
149
150 memset(&msg, 0, sizeof(msg));
151
152 msg.priority = 0;
153 asn_long2INTEGER(&msg.operation, RReqPDU__operation_readOnly);
154 OBJECT_IDENTIFIER_set_arcs(&msg.subtree,
155                            oid,
156                            sizeof(oid[0]),
157                            8);
158
159 char buffer[1024];
160 error = der_encode_to_buffer(&asn_DEF_RReqPDU, &msg, buffer, sizeof(buffer));
161
162 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RReqPDU, &msg);
163
164 if (error.encoded == -1)
165     {
166     printfd(__FILE__, "Could not encode RReqPDU (at %s)\n",
167             error.failed_type ? error.failed_type->name : "unknown");
168     return false;
169     }
170 else
171     {
172     if (write(fd, buffer, error.encoded) < 0)
173         {
174         printfd(__FILE__, "Failed to send RReqPDU: %s\n", strerror(errno));
175         return false;
176         }
177     }
178 return true;
179 }
180
181 SMUX_PDUs_t * RecvSMUXPDUs(int fd)
182 {
183 char buffer[1024];
184 SMUX_PDUs_t * pdus = NULL;
185
186 memset(buffer, 0, sizeof(buffer));
187
188 size_t length = read(fd, buffer, sizeof(buffer));
189 if (length < 1)
190     return NULL;
191 asn_dec_rval_t error;
192 error = ber_decode(0, &asn_DEF_SMUX_PDUs, (void **)&pdus, buffer, length);
193
194 if(error.code != RC_OK)
195     {
196     printfd(__FILE__, "Failed to decode PDUs at byte %ld\n",
197             (long)error.consumed);
198     return NULL;
199     }
200 return pdus;
201 }
202
203 bool SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse)
204 {
205 asn_enc_rval_t error;
206
207 char buffer[1024];
208 error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, getResponse, buffer,
209                              sizeof(buffer));
210
211 if (error.encoded == -1)
212     {
213     printfd(__FILE__, "Could not encode GetResponsePDU (at %s)\n",
214             error.failed_type ? error.failed_type->name : "unknown");
215     return false;
216     }
217 else
218     {
219     if (write(fd, buffer, error.encoded) < 0)
220         {
221         printfd(__FILE__, "Failed to send GetResponsePDU: %s\n", strerror(errno));
222         return false;
223         }
224     }
225 return true;
226 }
227
228 bool SendGetResponseErrorPDU(int fd,
229                              const PDU_t * getRequest,
230                              int errorStatus,
231                              int errorIndex)
232 {
233 asn_enc_rval_t error;
234 GetResponse_PDU_t msg;
235
236 memset(&msg, 0, sizeof(msg));
237
238 long id = 0;
239 asn_INTEGER2long(&getRequest->request_id, &id);
240 asn_long2INTEGER(&msg.request_id, id);
241 asn_long2INTEGER(&msg.error_status, errorStatus);
242 asn_long2INTEGER(&msg.error_index, errorIndex);
243
244 char buffer[1024];
245 error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, &msg, buffer,
246                              sizeof(buffer));
247
248 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_GetResponse_PDU, &msg);
249
250 if (error.encoded == -1)
251     {
252     printfd(__FILE__, "Could not encode GetResponsePDU for error (at %s)\n",
253             error.failed_type ? error.failed_type->name : "unknown");
254     return false;
255     }
256 else
257     {
258     if (write(fd, buffer, error.encoded) < 0)
259         {
260         printfd(__FILE__, "Failed to send GetResponseErrorPDU: %s\n", strerror(errno));
261         return false;
262         }
263     }
264 return true;
265 }