LIBSSDP
 All Classes Files Functions Variables Typedefs Macros
ssdp_cache_output_format.c
Go to the documentation of this file.
1 
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include "common_definitions.h"
11 #include "log.h"
13 #include "ssdp_message.h"
14 
15 #define SSDP_CUSTOM_FIELD_SERIALNUMBER "serialNumber"
16 #define SSDP_CUSTOM_FIELD_FRIENDLYNAME "friendlyName"
17 #define ONELINE_ANSI_COLOR_GREEN "\x1b[1;32m"
18 #define ONELINE_ANSI_COLOR_GREEN_SIZE 10
19 #define ONELINE_ANSI_COLOR_RESET "\x1b[0m"
20 #define ONELINE_ANSI_COLOR_RESET_SIZE 7
21 
22 unsigned int cache_to_json(ssdp_cache_s *ssdp_cache, char *json_buffer,
23  unsigned int json_buffer_size) {
24  unsigned int used_buffer = 0;
25 
26  /* Point at the beginning */
27  ssdp_cache = ssdp_cache->first;
28 
29  /* For every element in the ssdp cache */
30  used_buffer = snprintf(json_buffer, json_buffer_size, "root {\n");
31 
32  while(ssdp_cache) {
33  used_buffer += to_json(ssdp_cache->ssdp_message, FALSE,
34  (json_buffer + used_buffer), (json_buffer_size - used_buffer));
35  ssdp_cache = ssdp_cache->next;
36  }
37  used_buffer += snprintf((json_buffer + used_buffer),
38  (json_buffer_size - used_buffer), "}\n");
39 
40  return used_buffer;
41 }
42 
43 unsigned int cache_to_xml(ssdp_cache_s *ssdp_cache, char *xml_buffer,
44  unsigned int xml_buffer_size) {
45  unsigned int used_buffer = 0;
46 
47  if(NULL == ssdp_cache) {
48  PRINT_ERROR("No valid SSDP cache given (NULL)");
49  return 0;
50  }
51 
52  /* Point at the beginning */
53  ssdp_cache = ssdp_cache->first;
54 
55  /* For every element in the ssdp cache */
56  used_buffer = snprintf(xml_buffer, xml_buffer_size,
57  "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n");
58 
59  while(ssdp_cache) {
60  PRINT_DEBUG("cache_to_xml(): buffer used: %d; left: %d", used_buffer,
61  xml_buffer_size - used_buffer);
62  PRINT_DEBUG("start with with '%s'", ssdp_cache->ssdp_message->ip);
63  used_buffer += to_xml(ssdp_cache->ssdp_message, FALSE,
64  (xml_buffer + used_buffer), (xml_buffer_size - used_buffer));
65  PRINT_DEBUG("done with '%s'", ssdp_cache->ssdp_message->ip);
66  ssdp_cache = ssdp_cache->next;
67  }
68  used_buffer += snprintf((xml_buffer + used_buffer),
69  (xml_buffer_size - used_buffer), "</root>\n");
70 
71  return used_buffer;
72 }
73 
74 unsigned int to_json(const ssdp_message_s *ssdp_message, BOOL full_json,
75  char *json_buffer, int json_buffer_size) {
76  int used_length = 0;
77 
78  // TODO: write it!
79 
80  return used_length;
81 }
82 
83 unsigned int to_xml(const ssdp_message_s *ssdp_message, BOOL full_xml,
84  char *xml_buffer, int xml_buffer_size) {
85  int used_length = 0;
86 
87  if (!xml_buffer) {
88  PRINT_ERROR("to_xml(): No XML message buffer specified");
89  return -1;
90  } else if (ssdp_message == NULL) {
91  PRINT_ERROR("to_xml(): No SSDP message specified");
92  return -1;
93  }
94 
95  memset(xml_buffer, '\0', sizeof(char) * xml_buffer_size);
96  if (full_xml) {
97  used_length = snprintf(xml_buffer, xml_buffer_size,
98  "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n");
99  }
100 
101  PRINT_DEBUG("Setting upnp xml-fields");
102  used_length += snprintf(xml_buffer + used_length,
103  xml_buffer_size - used_length, "\t<message length=\"%d\">\n",
104  ssdp_message->message_length);
105  used_length += snprintf(xml_buffer + used_length,
106  xml_buffer_size - used_length, "\t\t<mac>\n\t\t\t%s\n\t\t</mac>\n",
107  ssdp_message->mac);
108  used_length += snprintf(xml_buffer + used_length,
109  xml_buffer_size - used_length, "\t\t<ip>\n\t\t\t%s\n\t\t</ip>\n",
110  ssdp_message->ip);
111  used_length += snprintf(xml_buffer + used_length, xml_buffer_size - used_length,
112  "\t\t<request protocol=\"%s\">\n\t\t\t%s\n\t\t</request>\n",
113  ssdp_message->protocol, ssdp_message->request);
114  used_length += snprintf(xml_buffer + used_length,
115  xml_buffer_size - used_length,
116  "\t\t<datetime>\n\t\t\t%s\n\t\t</datetime>\n", ssdp_message->datetime);
117 
118  if (ssdp_message->custom_fields) {
119 
120  ssdp_custom_field_s *cf = ssdp_message->custom_fields->first;
121 
122  /*
123  * The whole needed size is calculated as:
124  * leading headers string: +29
125  * each header constant string +50
126  * each header name string +X
127  * each header contents string +Y
128  * tailing header tailing string +19
129  */
130 
131  /* Leading (29) and tailing (13) string sizes combined */
132  int needed_size = 48;
133 
134  PRINT_DEBUG("Setting custom xml-fields");
135  /* Calculate needed buffer size */
136  while (cf) {
137 
138  /* Each header combined (46 + X + Y + 18) string size */
139  needed_size += strlen(cf->name) + strlen(cf->contents) + 50;
140  cf = cf->next;
141  PRINT_DEBUG("Done calculating buffer");
142 
143  }
144  cf = ssdp_message->custom_fields->first;
145 
146  /* Check if buffer has enought room */
147  PRINT_DEBUG("to_xml(): XML custom fields buffer left: %d, buffer_needed: "
148  "%d", (xml_buffer_size - used_length), needed_size);
149  if ((xml_buffer_size - used_length) < needed_size) {
150  PRINT_ERROR("to_xml(): Not enought buffer space left to convert the "
151  "SSDP message custom fields to XML, skipping\n");
152  } else {
153 
154  /* Convert to XML format */
155  used_length += snprintf(xml_buffer + used_length, xml_buffer_size - used_length,
156  "\t\t<custom_fields count=\"%d\">\n", ssdp_message->custom_field_count);
157 
158  while (cf) {
159  PRINT_DEBUG("Setting:");
160  PRINT_DEBUG("'%s'", cf->name);
161  used_length += snprintf(xml_buffer + used_length,
162  xml_buffer_size - used_length,
163  "\t\t\t<custom_field name=\"%s\">\n\t\t\t\t%s\n\t\t\t</custom_field>\n",
164  cf->name,
165  cf->contents);
166  cf = cf->next;
167  PRINT_DEBUG("Done with this one");
168  }
169 
170  cf = NULL;
171  used_length += snprintf(xml_buffer + used_length,
172  xml_buffer_size - used_length,
173  "\t\t</custom_fields>\n");
174  PRINT_DEBUG("to_xml(): XML custom-fields bytes used: %d",
175  (int)strlen(xml_buffer));
176  }
177 
178  }
179 
180  if (ssdp_message->headers) {
181 
182  ssdp_header_s *h = ssdp_message->headers->first;
183 
184  /*
185  * The whole needed size is calculated as:
186  * leading headers string: +23
187  * each header leading string +46
188  * each header type as two digits
189  * each header type as string +X
190  * each header contents string +Y
191  * each header tailing string +18
192  * tailing header tailing string +13
193  */
194 
195  /* Leading (23) and tailing (13) string sizes combined */
196  int needed_size = 36;
197 
198  /* Calculate needed buffer size */
199  while (h) {
200 
201  /* Each header combined (46 + X + Y + 18) string size */
202  needed_size += (h->unknown_type ?
203  strlen(h->unknown_type) :
204  strlen(get_header_string(h->type, h))) + strlen(h->contents) + 64;
205  h = h->next;
206 
207  }
208  h = ssdp_message->headers->first;
209 
210  /* Check if buffer has enought space */
211  PRINT_DEBUG("buffer left: %d, buffer needed: %d",
212  (xml_buffer_size - used_length), needed_size);
213  if ((xml_buffer_size - used_length) < needed_size) {
214  PRINT_ERROR("to_xml(): Not enought buffer space left to convert the "
215  "SSDP message headers to XML, skipping\n");
216  } else {
217 
218  used_length += snprintf(xml_buffer + used_length,
219  xml_buffer_size - used_length, "\t\t<headers count=\"%d\">\n",
220  (unsigned int)ssdp_message->header_count);
221 
222  while (h) {
223  used_length += snprintf(xml_buffer + used_length,
224  xml_buffer_size - used_length,
225  "\t\t\t<header typeInt=\"%d\" typeStr=\"%s\">\n", h->type,
226  get_header_string(h->type, h));
227  used_length += snprintf(xml_buffer + used_length,
228  xml_buffer_size - used_length, "\t\t\t\t%s\n\t\t\t</header>\n",
229  h->contents);
230  h = h->next;
231  }
232  h = NULL;
233 
234  used_length += snprintf(xml_buffer + used_length,
235  xml_buffer_size - used_length, "\t\t</headers>\n");
236  }
237 
238  }
239 
240  used_length += snprintf(xml_buffer + used_length,
241  xml_buffer_size - used_length, "\t</message>\n");
242 
243  if (full_xml) {
244  used_length += snprintf(xml_buffer + used_length,
245  xml_buffer_size - used_length, "</root>\n");
246  }
247 
248  return used_length;
249 }
250 
251 char *to_oneline(const ssdp_message_s *message, BOOL monochrome) {
252  const ssdp_custom_field_s *custom_field_id = NULL;
253  const ssdp_custom_field_s *custom_field_model = NULL;
254  char *oneline = NULL;
255 
256  if (!message)
257  return NULL;
258 
259  custom_field_id = get_custom_field(message, SSDP_CUSTOM_FIELD_SERIALNUMBER);
260  /* 7 is the needed characters for "(no id)" in the sprintf() below */
261  int id_size =
262  custom_field_id ? strlen(custom_field_id->contents) : 7;
263 
264  /* 8 is the needed characters for "(no MAC)" in the sprintf() below */
265  int mac_size = message->mac ? strlen(message->mac) : 8;
266 
267  custom_field_model = get_custom_field(message,
268  SSDP_CUSTOM_FIELD_FRIENDLYNAME);
269  /* 10 is the needed characters for "(no model)" in the sprintf() below */
270  int model_size =
271  custom_field_model ? strlen(custom_field_model->contents) : 10;
272 
273  /* Set color control-codes */
274  const char* start_color = monochrome ? "" : ONELINE_ANSI_COLOR_GREEN;
275  const char* end_color = monochrome ? "" : ONELINE_ANSI_COLOR_RESET;
276  int start_color_size = monochrome ? 0 : ONELINE_ANSI_COLOR_GREEN_SIZE;
277  int end_color_size = monochrome ? 0 : ONELINE_ANSI_COLOR_RESET_SIZE;
278 
279  /* 10 is the extra characters in the sprintf() below plus a null-term */
280  int oneline_size = start_color_size + id_size + end_color_size +
281  strlen(message->ip) + mac_size + model_size + 10;
282  oneline = malloc(oneline_size + 1);
283 
284  sprintf(oneline, "%s%s%s - %s - %s - %s", start_color,
285  custom_field_id ? custom_field_id->contents : "(no ID)",
286  end_color, message->ip, message->mac ? message->mac : "(no MAC)",
287  custom_field_model ? custom_field_model->contents :
288  "(no model)");
289 
290  return oneline;
291 }
const char * get_header_string(const unsigned int header_type, const ssdp_header_s *header)
Definition: ssdp_message.c:402
ssdp_custom_field_s * get_custom_field(const ssdp_message_s *ssdp_message, const char *custom_field)
Definition: ssdp_message.c:134
unsigned char header_count
Definition: ssdp_message.h:106
struct ssdp_custom_field_struct * custom_fields
Definition: ssdp_message.h:112
unsigned char type
Definition: ssdp_message.h:58
struct ssdp_header_struct * next
Definition: ssdp_message.h:66
struct ssdp_header_struct * headers
Definition: ssdp_message.h:108
unsigned int cache_to_xml(ssdp_cache_s *ssdp_cache, char *xml_buffer, unsigned int xml_buffer_size)
struct ssdp_cache_struct * next
Definition: ssdp_cache.h:27
#define FALSE
unsigned int to_xml(const ssdp_message_s *ssdp_message, BOOL full_xml, char *xml_buffer, int xml_buffer_size)
unsigned char custom_field_count
Definition: ssdp_message.h:110
unsigned int to_json(const ssdp_message_s *ssdp_message, BOOL full_json, char *json_buffer, int json_buffer_size)
struct ssdp_custom_field_struct * first
Definition: ssdp_message.h:76
unsigned int cache_to_json(ssdp_cache_s *ssdp_cache, char *json_buffer, unsigned int json_buffer_size)
struct ssdp_cache_struct * first
Definition: ssdp_cache.h:23
struct ssdp_header_struct * first
Definition: ssdp_message.h:64
ssdp_message_s * ssdp_message
Definition: ssdp_cache.h:25
int BOOL
char * to_oneline(const ssdp_message_s *message, BOOL monochrome)
struct ssdp_custom_field_struct * next
Definition: ssdp_message.h:78