Broad patch from Dan Scott to move towards better memory management:
[OpenSRF.git] / src / libopensrf / osrf_message.c
1 #include <opensrf/osrf_message.h>
2
3 static char default_locale[17] = "en-US\0\0\0\0\0\0\0\0\0\0\0\0";
4 static char* current_locale = NULL;
5
6 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
7
8         osrf_message* msg                       = (osrf_message*) safe_malloc(sizeof(osrf_message));
9         msg->m_type                                     = type;
10         msg->thread_trace                       = thread_trace;
11         msg->protocol                           = protocol;
12         msg->next                                       = NULL;
13         msg->is_exception                       = 0;
14         msg->_params                            = NULL;
15         msg->_result_content            = NULL;
16         msg->sender_locale              = NULL;
17
18         return msg;
19 }
20
21
22 const char* osrf_message_get_last_locale() {
23         return current_locale;
24 }
25
26 char* osrf_message_set_locale( osrf_message* msg, const char* locale ) {
27         if( msg == NULL || locale == NULL ) return NULL;
28         return msg->sender_locale = strdup( locale );
29 }
30
31 const char* osrf_message_set_default_locale( const char* locale ) {
32         if( locale == NULL ) return NULL;
33         if( strlen(locale) > 16 ) return NULL;
34
35         memcpy( default_locale, locale, strlen(locale) );
36         default_locale[strlen(locale)] = '\0';
37         return (const char*) default_locale;
38 }
39
40 void osrf_message_set_method( osrf_message* msg, char* method_name ) {
41         if( msg == NULL || method_name == NULL ) return;
42         msg->method_name = strdup( method_name );
43 }
44
45
46 void osrf_message_add_object_param( osrf_message* msg, jsonObject* o ) {
47         if(!msg|| !o) return;
48         if(!msg->_params)
49                 msg->_params = jsonParseString("[]");
50         char* j = jsonObjectToJSON(o);
51         jsonObjectPush(msg->_params, jsonParseString(j));
52         free(j);
53 }
54
55 void osrf_message_set_params( osrf_message* msg, jsonObject* o ) {
56         if(!msg || !o) return;
57
58         if(o->type != JSON_ARRAY) {
59                 osrfLogDebug( OSRF_LOG_MARK, "passing non-array to osrf_message_set_params(), fixing...");
60                 jsonObject* clone = jsonObjectClone(o);
61                 o = jsonNewObject(NULL);
62                 jsonObjectPush(o, clone);
63                 if(msg->_params) jsonObjectFree(msg->_params);
64                 msg->_params = o;
65                 return;
66         }
67
68         if(msg->_params) jsonObjectFree(msg->_params);
69         msg->_params = jsonObjectClone(o);
70 }
71
72
73 /* only works if parse_json_params is false */
74 void osrf_message_add_param( osrf_message* msg, char* param_string ) {
75         if(msg == NULL || param_string == NULL) return;
76         if(!msg->_params) msg->_params = jsonParseString("[]");
77         jsonObjectPush(msg->_params, jsonParseString(param_string));
78 }
79
80
81 void osrf_message_set_status_info( 
82                 osrf_message* msg, char* status_name, char* status_text, int status_code ) {
83         if(!msg) return;
84
85         if( status_name != NULL ) 
86                 msg->status_name = strdup( status_name );
87
88         if( status_text != NULL )
89                 msg->status_text = strdup( status_text );
90
91         msg->status_code = status_code;
92 }
93
94
95 void osrf_message_set_result_content( osrf_message* msg, char* json_string ) {
96         if( msg == NULL || json_string == NULL) return;
97         msg->result_string =    strdup(json_string);
98         if(json_string) msg->_result_content = jsonParseString(json_string);
99 }
100
101
102
103 void osrfMessageFree( osrfMessage* msg ) {
104         osrf_message_free( msg );
105 }
106
107 void osrf_message_free( osrf_message* msg ) {
108         if( msg == NULL )
109                 return;
110
111         if( msg->status_name != NULL )
112                 free(msg->status_name);
113
114         if( msg->status_text != NULL )
115                 free(msg->status_text);
116
117         if( msg->_result_content != NULL )
118                 jsonObjectFree( msg->_result_content );
119
120         if( msg->result_string != NULL )
121                 free( msg->result_string);
122
123         if( msg->method_name != NULL )
124                 free(msg->method_name);
125
126         if( msg->sender_locale != NULL )
127                 free(msg->sender_locale);
128
129         if( msg->_params != NULL )
130                 jsonObjectFree(msg->_params);
131
132         free(msg);
133 }
134
135
136 char* osrfMessageSerializeBatch( osrfMessage* msgs [], int count ) {
137         if( !msgs ) return NULL;
138
139         char* j;
140         int i = 0;
141         osrfMessage* msg = NULL;
142         jsonObject* wrapper = jsonNewObject(NULL);
143
144         while( ((msg = msgs[i]) && (i++ < count)) ) 
145                 jsonObjectPush(wrapper, osrfMessageToJSON( msg ));
146
147         j = jsonObjectToJSON(wrapper);
148         jsonObjectFree(wrapper);
149
150         return j;       
151 }
152
153
154 char* osrf_message_serialize(osrf_message* msg) {
155
156         if( msg == NULL ) return NULL;
157         char* j = NULL;
158
159         jsonObject* json = osrfMessageToJSON( msg );
160
161         if(json) {
162                 jsonObject* wrapper = jsonNewObject(NULL);
163                 jsonObjectPush(wrapper, json);
164                 j = jsonObjectToJSON(wrapper);
165                 jsonObjectFree(wrapper);
166         }
167
168         return j;
169 }
170
171
172 jsonObject* osrfMessageToJSON( osrfMessage* msg ) {
173
174         jsonObject* json = jsonNewObject(NULL);
175         jsonObjectSetClass(json, "osrfMessage");
176         jsonObject* payload;
177         char sc[64];
178         memset(sc, 0, sizeof(sc));
179
180         char* str;
181
182         INT_TO_STRING(msg->thread_trace);
183         jsonObjectSetKey(json, "threadTrace", jsonNewObject(INTSTR));
184
185         if (msg->sender_locale != NULL) {
186                 jsonObjectSetKey(json, "locale", jsonNewObject(msg->sender_locale));
187         } else if (current_locale != NULL) {
188                 jsonObjectSetKey(json, "locale", jsonNewObject(current_locale));
189         } else {
190                 jsonObjectSetKey(json, "locale", jsonNewObject(default_locale));
191         }
192
193         switch(msg->m_type) {
194                 
195                 case CONNECT: 
196                         jsonObjectSetKey(json, "type", jsonNewObject("CONNECT"));
197                         break;
198
199                 case DISCONNECT: 
200                         jsonObjectSetKey(json, "type", jsonNewObject("DISCONNECT"));
201                         break;
202
203                 case STATUS:
204                         jsonObjectSetKey(json, "type", jsonNewObject("STATUS"));
205                         payload = jsonNewObject(NULL);
206                         jsonObjectSetClass(payload, msg->status_name);
207                         jsonObjectSetKey(payload, "status", jsonNewObject(msg->status_text));
208                         snprintf(sc, sizeof(sc), "%d", msg->status_code);
209                         jsonObjectSetKey(payload, "statusCode", jsonNewObject(sc));
210                         jsonObjectSetKey(json, "payload", payload);
211                         break;
212
213                 case REQUEST:
214                         jsonObjectSetKey(json, "type", jsonNewObject("REQUEST"));
215                         payload = jsonNewObject(NULL);
216                         jsonObjectSetClass(payload, "osrfMethod");
217                         jsonObjectSetKey(payload, "method", jsonNewObject(msg->method_name));
218                         str = jsonObjectToJSON(msg->_params);
219                         jsonObjectSetKey(payload, "params", jsonParseString(str));
220                         free(str);
221                         jsonObjectSetKey(json, "payload", payload);
222
223                         break;
224
225                 case RESULT:
226                         jsonObjectSetKey(json, "type", jsonNewObject("RESULT"));
227                         payload = jsonNewObject(NULL);
228                         jsonObjectSetClass(payload,"osrfResult");
229                         jsonObjectSetKey(payload, "status", jsonNewObject(msg->status_text));
230                         snprintf(sc, sizeof(sc), "%d", msg->status_code);
231                         jsonObjectSetKey(payload, "statusCode", jsonNewObject(sc));
232                         str = jsonObjectToJSON(msg->_result_content);
233                         jsonObjectSetKey(payload, "content", jsonParseString(str));
234                         free(str);
235                         jsonObjectSetKey(json, "payload", payload);
236                         break;
237         }
238
239         return json;
240 }
241
242
243 int osrf_message_deserialize(char* string, osrf_message* msgs[], int count) {
244
245         if(!string || !msgs || count <= 0) return 0;
246         int numparsed = 0;
247
248         jsonObject* json = jsonParseString(string);
249
250         if(!json) {
251                 osrfLogWarning( OSRF_LOG_MARK, 
252                         "osrf_message_deserialize() unable to parse data: \n%s\n", string);
253                 return 0;
254         }
255
256         int x;
257
258         for( x = 0; x < json->size && x < count; x++ ) {
259
260                 const jsonObject* message = jsonObjectGetIndex(json, x);
261
262                 if(message && message->type != JSON_NULL && 
263                         message->classname && !strcmp(message->classname, "osrfMessage")) {
264
265                         osrf_message* new_msg = safe_malloc(sizeof(osrf_message));
266
267                         const jsonObject* tmp = jsonObjectGetKeyConst(message, "type");
268
269                         const char* t;
270                         if( ( t = jsonObjectGetString(tmp)) ) {
271
272                                 if(!strcmp(t, "CONNECT"))               new_msg->m_type = CONNECT;
273                                 if(!strcmp(t, "DISCONNECT"))    new_msg->m_type = DISCONNECT;
274                                 if(!strcmp(t, "STATUS"))                new_msg->m_type = STATUS;
275                                 if(!strcmp(t, "REQUEST"))               new_msg->m_type = REQUEST;
276                                 if(!strcmp(t, "RESULT"))                new_msg->m_type = RESULT;
277                         }
278
279                         tmp = jsonObjectGetKeyConst(message, "threadTrace");
280                         if(tmp) {
281                                 char* tt = jsonObjectToSimpleString(tmp);
282                                 if(tt) {
283                                         new_msg->thread_trace = atoi(tt);
284                                         free(tt);
285                                 }
286                         }
287
288                         /* use the sender's locale, or the global default */
289                         if (current_locale)
290                                 free( current_locale );
291
292                         tmp = jsonObjectGetKeyConst(message, "locale");
293                         if(tmp) {
294                                 new_msg->sender_locale = jsonObjectToSimpleString(tmp);
295                                 current_locale = strdup( new_msg->sender_locale );
296                         } else {
297                                 current_locale = NULL;
298                         }
299
300                         tmp = jsonObjectGetKeyConst(message, "protocol");
301
302                         if(tmp) {
303                                 char* proto = jsonObjectToSimpleString(tmp);
304                                 if(proto) {
305                                         new_msg->protocol = atoi(proto);
306                                         free(proto);
307                                 }
308                         }
309
310                         tmp = jsonObjectGetKeyConst(message, "payload");
311                         if(tmp) {
312                                 if(tmp->classname)
313                                         new_msg->status_name = strdup(tmp->classname);
314
315                                 const jsonObject* tmp0 = jsonObjectGetKeyConst(tmp,"method");
316                                 if(jsonObjectGetString(tmp0))
317                                         new_msg->method_name = strdup(jsonObjectGetString(tmp0));
318
319                                 tmp0 = jsonObjectGetKeyConst(tmp,"params");
320                                 if(tmp0) {
321                                         char* s = jsonObjectToJSON(tmp0);
322                                         new_msg->_params = jsonParseString(s);
323                                         if(new_msg->_params && new_msg->_params->type == JSON_NULL) 
324                                                 new_msg->_params->type = JSON_ARRAY;
325                                         free(s);
326                                 }
327
328                                 tmp0 = jsonObjectGetKeyConst(tmp,"status");
329                                 if(jsonObjectGetString(tmp0))
330                                         new_msg->status_text = strdup(jsonObjectGetString(tmp0));
331
332                                 tmp0 = jsonObjectGetKeyConst(tmp,"statusCode");
333                                 if(tmp0) {
334                                         if(jsonObjectGetString(tmp0))
335                                                 new_msg->status_code = atoi(jsonObjectGetString(tmp0));
336                                         if(tmp0->type == JSON_NUMBER)
337                                                 new_msg->status_code = (int) jsonObjectGetNumber(tmp0);
338                                 }
339
340                                 tmp0 = jsonObjectGetKeyConst(tmp,"content");
341                                 if(tmp0) {
342                                         char* s = jsonObjectToJSON(tmp0);
343                                         new_msg->_result_content = jsonParseString(s);
344                                         free(s);
345                                 }
346
347                         }
348                         msgs[numparsed++] = new_msg;
349                 }
350         }
351
352         jsonObjectFree(json);
353         return numparsed;
354 }
355
356
357
358 jsonObject* osrfMessageGetResult( osrfMessage* msg ) {
359         if(msg) return msg->_result_content;
360         return NULL;
361 }
362