Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : /*
6 : * sandesh.c
7 : *
8 : * Sandesh C Library
9 : */
10 :
11 : #include "sandesh.h"
12 :
13 : /**
14 : * Extract sandesh information corresponding to sandesh name
15 : *
16 : * Returns sandesh info on success, NULL otherwise
17 : */
18 : sandesh_info_t *
19 13872 : sandesh_find_info (sandesh_info_t *infos, const char *name) {
20 13872 : int sidx = 0;
21 104676 : while (infos[sidx].name != NULL) {
22 104676 : if (strcmp(infos[sidx].name, name) == 0) {
23 13872 : return &infos[sidx];
24 : }
25 90804 : sidx++;
26 : }
27 0 : return NULL;
28 : }
29 :
30 : /**
31 : * Decode a sandesh from the buffer and call the sandesh handler function
32 : *
33 : * Returns the number of bytes processed, -1 on error and sets error
34 : */
35 : static int32_t
36 6593 : sandesh_decode_one (u_int8_t *buf, u_int32_t buf_len, sandesh_find_info_fn sinfo_find_fn,
37 : int *error) {
38 6593 : int32_t rxfer = 0, ret, sread_len = 0;
39 6593 : char *sname = NULL;
40 : sandesh_info_t *sinfo;
41 : void *sandesh;
42 : union {
43 : void * b[4];
44 : int32_t all;
45 : } bytes4;
46 :
47 : /* Read the sandesh name */
48 6593 : if (buf_len < (uint32_t)(rxfer + 4)) {
49 0 : os_log(OS_LOG_ERR, "Read sandesh begin FAILED");
50 0 : ret = -1;
51 0 : goto exit;
52 : }
53 6593 : memcpy(bytes4.b, buf + rxfer, 4);
54 6593 : rxfer += 4;
55 6593 : sread_len = ntohl(bytes4.all);
56 6593 : if (sread_len > 0) {
57 6593 : if (buf_len < (uint32_t)(rxfer + sread_len)) {
58 0 : os_log(OS_LOG_ERR, "Read sandesh begin: Length(%d) FAILED",
59 : sread_len);
60 0 : ret = -1;
61 0 : goto exit;
62 : }
63 6593 : sname = os_malloc(sread_len + 1);
64 6593 : memcpy(sname, buf + rxfer, sread_len);
65 6593 : sname[sread_len] = 0;
66 6593 : rxfer += sread_len;
67 : } else {
68 0 : os_log(OS_LOG_ERR, "Read sandesh begin: Length(%d) INVALID",
69 : sread_len);
70 0 : ret = -1;
71 0 : goto exit;
72 : }
73 :
74 : /* Find the corresponding sandesh information */
75 6593 : sinfo = sinfo_find_fn(sname);
76 6593 : if (sinfo == NULL) {
77 0 : os_log(OS_LOG_ERR, "No information for sandesh %s", sname);
78 0 : *error = EINVAL;
79 0 : ret = -1;
80 0 : goto exit;
81 : }
82 :
83 6593 : sandesh = os_zalloc(sinfo->size);
84 6593 : if (sandesh == NULL) {
85 0 : os_log(OS_LOG_ERR, "Allocation of sandesh %s : %d bytes FAILED",
86 : sname, sinfo->size);
87 0 : *error = ENOMEM;
88 0 : ret = -1;
89 0 : goto exit;
90 : }
91 :
92 : /* Now, read the sandesh */
93 6593 : rxfer = sinfo->read_binary_from_buffer(sandesh, buf, buf_len, error);
94 6593 : if (rxfer < 0) {
95 0 : os_log(OS_LOG_ERR, "%s read FAILED (%d)", sname, *error);
96 0 : sinfo->free(sandesh);
97 0 : os_free(sandesh);
98 0 : sandesh = NULL;
99 0 : ret = -1;
100 0 : goto exit;
101 : }
102 6593 : ret = rxfer;
103 :
104 : /* Process the sandesh */
105 6593 : sinfo->process(sandesh);
106 :
107 : /* Release the sandesh */
108 6593 : sinfo->free(sandesh);
109 6593 : os_free(sandesh);
110 6593 : sandesh = NULL;
111 :
112 6593 : exit:
113 6593 : if (sname) {
114 6593 : os_free(sname);
115 6593 : sname = NULL;
116 : }
117 6593 : return ret;
118 : }
119 :
120 : /**
121 : * Decode sandeshs from the buffer and calls the sandesh handler function
122 : * for each decoded sandesh
123 : *
124 : * Returns the number of bytes processed, -1 on error and sets error
125 : */
126 : int32_t
127 5725 : sandesh_decode (u_int8_t *buf, u_int32_t buf_len, sandesh_find_info_fn sinfo_find_fn,
128 : int *error) {
129 5725 : u_int32_t xfer = 0;
130 : int32_t ret;
131 :
132 12318 : while (xfer < buf_len) {
133 6593 : ret = sandesh_decode_one(buf + xfer, buf_len - xfer, sinfo_find_fn, error);
134 6593 : if (ret < 0) {
135 0 : os_log(OS_LOG_ERR, "Sandesh read from %d bytes, at offset %d "
136 : "FAILED (%d)", buf_len, xfer, ret);
137 0 : return ret;
138 : }
139 6593 : xfer += ret;
140 : }
141 5725 : return xfer;
142 : }
143 :
144 : /*
145 : * Encode a sandesh into the buffer
146 : *
147 : * Returns the length of the encoded sandesh, -1 on error and set error
148 : */
149 : int32_t
150 6593 : sandesh_encode (void *sandesh, const char *sname,
151 : sandesh_find_info_fn sinfo_find_fn, u_int8_t *buf,
152 : u_int32_t buf_len, int *error) {
153 : sandesh_info_t *sinfo;
154 : int32_t wxfer;
155 :
156 : /* First find the corresponding sandesh information */
157 6593 : sinfo = sinfo_find_fn(sname);
158 6593 : if (sinfo == NULL) {
159 0 : os_log(OS_LOG_ERR, "Write: No information for sandesh %s", sname);
160 0 : *error = EINVAL;
161 0 : return -1;
162 : }
163 :
164 : /* Now, write the sandesh */
165 6593 : wxfer = sinfo->write_binary_to_buffer(sandesh, buf, buf_len, error);
166 6593 : if (wxfer < 0) {
167 : #ifdef __KERNEL__
168 : if (vrouter_dbg) {
169 : os_log(OS_LOG_DEBUG, "Write: Encode sandesh %s FAILED(%d)",
170 : sname, *error);
171 : }
172 : #elif (!defined(SANDESH_QUIET))
173 0 : os_log(OS_LOG_DEBUG, "Write: Encode sandesh %s FAILED(%d)", sname, *error);
174 : #endif
175 0 : return -1;
176 : }
177 :
178 6593 : return wxfer;
179 : }
180 :
181 : /*
182 : * Get the encoded length of a sandesh
183 : *
184 : * Returns the encoded length of a sandesh, -1 on error and set error
185 : */
186 : int32_t
187 0 : sandesh_get_encoded_length (void *sandesh, const char *sname,
188 : sandesh_find_info_fn sinfo_find_fn, int *error) {
189 : ThriftBinaryProtocol protocol;
190 : ThriftFakeTransport transport;
191 : sandesh_info_t *sinfo;
192 : int32_t wxfer;
193 :
194 : /* First find the corresponding sandesh information */
195 0 : sinfo = sinfo_find_fn(sname);
196 0 : if (sinfo == NULL) {
197 0 : os_log(OS_LOG_ERR, "Encode: No information for sandesh %s", sname);
198 0 : *error = EINVAL;
199 0 : return -1;
200 : }
201 :
202 : /* Initialize the transport and protocol */
203 0 : thrift_fake_transport_init(&transport);
204 0 : thrift_protocol_init(&protocol, T_PROTOCOL_BINARY, (ThriftTransport *)&transport);
205 :
206 : /* Now, write the sandesh into the fake transport to get the encoded length */
207 0 : wxfer = sinfo->write(sandesh, &protocol, error);
208 0 : if (wxfer < 0) {
209 0 : os_log(OS_LOG_ERR, "Encode: Encode sandesh %s FAILED(%d)", sname, *error);
210 0 : return -1;
211 : }
212 :
213 0 : return wxfer;
214 : }
|