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