Line data Source code
1 : /*
2 : dyn_buffer.c
3 : Created by Danny Goossen, Gioxa Ltd on 8/3/17.
4 :
5 : MIT License
6 :
7 : Copyright (c) 2017 deployctl, Gioxa Ltd.
8 :
9 : Permission is hereby granted, free of charge, to any person obtaining a copy
10 : of this software and associated documentation files (the "Software"), to deal
11 : in the Software without restriction, including without limitation the rights
12 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 : copies of the Software, and to permit persons to whom the Software is
14 : furnished to do so, subject to the following conditions:
15 :
16 : The above copyright notice and this permission notice shall be included in all
17 : copies or substantial portions of the Software.
18 :
19 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 : SOFTWARE.
26 :
27 : */
28 :
29 : #include "deployd.h"
30 :
31 : const char * color_data[]={ANSI_BOLD_BLACK,ANSI_BOLD_RED,ANSI_BOLD_GREEN,ANSI_BOLD_YELLOW,ANSI_BOLD_BLUE,ANSI_BOLD_MAGENTA,ANSI_BOLD_CYAN,ANSI_BOLD_WHITE, \
32 : ANSI_BLACK,ANSI_RED,ANSI_GREEN,ANSI_YELLOW,ANSI_BLUE,ANSI_MAGENTA,ANSI_CYAN,ANSI_WHITE, \
33 : ANSI_CROSS_BLACK,ANSI_CROSS_RED,ANSI_CROSS_GREEN,ANSI_CROSS_YELLOW,ANSI_CROSS_BLUE,ANSI_CROSS_MAGENTA,ANSI_CROSS_CYAN,ANSI_CROSS_WHITE, \
34 : ANSI_RESET};
35 :
36 :
37 :
38 : /*------------------------------------------------------------------------
39 : * Helper function for Curl request
40 : *------------------------------------------------------------------------*/
41 6 : size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
42 : {
43 6 : size_t realsize = size * nmemb;
44 6 : struct MemoryStruct *mem = (struct MemoryStruct *)userp;
45 :
46 6 : void * tmp= realloc(mem->memory, mem->size + realsize + 1);
47 6 : if(tmp == NULL) {
48 : // LCOV_EXCL_START
49 : /* out of memory! */
50 : // error("not enough memory (realloc returned NULL)\n");
51 : return 0;
52 : // LCOV_EXCL_STOP
53 :
54 : }
55 : else
56 6 : mem->memory=tmp;
57 :
58 6 : memcpy(&(mem->memory[mem->size]), contents, realsize);
59 6 : mem->size += realsize;
60 6 : mem->memory[mem->size] = 0;
61 6 : return realsize;
62 : }
63 :
64 0 : void init_header_struct( void *userp)
65 : {
66 0 : struct headerStruct * s_header=(struct headerStruct*)userp;
67 0 : s_header->header=cJSON_CreateObject();
68 0 : }
69 0 : void free_header_struct( void *userp)
70 : {
71 0 : struct headerStruct * s_header=(struct headerStruct*)userp;
72 0 : if (s_header->header) cJSON_Delete(s_header->header);
73 0 : s_header->header=NULL;
74 0 : }
75 :
76 :
77 :
78 :
79 : /*------------------------------------------------------------------------
80 : * Helper function for Curl request
81 : *------------------------------------------------------------------------*/
82 0 : size_t WriteHeaderCallback(void *contents, size_t size, size_t nmemb, void *userp)
83 : {
84 0 : size_t realsize = size * nmemb;
85 0 : struct headerStruct * s_header=(struct headerStruct*)userp;
86 :
87 0 : char * e=contents;
88 0 : int len=(int)realsize;
89 0 : int pos = 0;
90 0 : while (*e++ != ':' && pos < len) pos++;
91 0 : if (pos != len && pos >1)
92 : {
93 :
94 0 : cJSON_AddItemToObject_n(s_header->header, contents, pos, cJSON_CreateString_n(contents+pos+2, len-pos-4));
95 :
96 : }
97 0 : return realsize;
98 : }
99 :
100 :
101 :
102 : /*------------------------------------------------------------------------
103 : * Helper function append string to dynamic trace
104 : *------------------------------------------------------------------------*/
105 16 : int init_dynamic_trace(void**userp, const char * token, const char * url, int job_id)
106 : {
107 16 : struct trace_Struct **trace_p = (struct trace_Struct **)userp;
108 16 : if (!trace_p || ! token || !url) return -1;
109 16 : if (*trace_p) free_dynamic_trace(userp);
110 16 : *trace_p=NULL;
111 :
112 16 : (*trace_p)=calloc(1, sizeof(struct trace_Struct));
113 16 : if (*trace_p)
114 : {
115 16 : (*trace_p)->url=strdup(url);
116 16 : (*trace_p)->job_id=job_id;
117 16 : (*trace_p)->params = cJSON_CreateObject();
118 16 : cJSON_AddStringToObject((*trace_p)->params, "state", "running");
119 16 : cJSON_AddStringToObject((*trace_p)->params, "token", token);
120 16 : cJSON * tmp=cJSON_CreateObject();
121 16 : tmp->valuestring=calloc(1,0x10000);
122 16 : if (tmp)
123 : {
124 16 : tmp->type=cJSON_String;
125 16 : cJSON_AddItemToObject((*trace_p)->params, "trace", tmp);
126 16 : (*trace_p)->trace_len=0;
127 16 : (*trace_p)->trace_buf_size=0x10000; // 64K initial buffer size
128 16 : (*trace_p)->curl=curl_easy_init();;
129 16 : (*trace_p)->tests=NULL;
130 16 : (*trace_p)->mark=0;
131 16 : (*trace_p)->min_trace_buf_increment=0x4000; //increment with minimun 16K
132 : }
133 : else
134 : {
135 0 : cJSON_Delete( (*trace_p)->params);
136 0 : if ((*trace_p)->url) free((*trace_p)->url);
137 0 : (*trace_p)->url=NULL;
138 0 : free(*trace_p);
139 0 : (*trace_p)=NULL;
140 : }
141 : }
142 16 : if (*trace_p) debug("trace->params ptr %p\n",(*trace_p)->params);
143 : return 0;
144 : }
145 :
146 5 : size_t Write_dynamic_trace_n(const void *contents,size_t n, void *userp)
147 : {
148 5 : struct trace_Struct *trace = (struct trace_Struct *)userp;
149 5 : if (contents && n>0)
150 : {
151 5 : cJSON * item=cJSON_GetObjectItem(trace->params, "trace" );
152 5 : if (item && item->valuestring)
153 : {
154 5 : if (trace->trace_len+1+n> trace->trace_buf_size)
155 : {
156 0 : size_t newsize=trace->trace_buf_size+ MAX(trace->min_trace_buf_increment, n);
157 0 : char * temp=realloc(item->valuestring,newsize);
158 0 : if (temp )
159 : {
160 0 : trace->trace_buf_size=newsize;
161 0 : if (temp!=item->valuestring)
162 : {
163 0 : item->valuestring=temp;
164 : }
165 : }
166 : else
167 : {
168 0 : error("Write_dyn_trace_n, no more mem");
169 0 : return -1;
170 : }
171 : }
172 5 : memcpy(item->valuestring+trace->trace_len, contents, n);
173 5 : trace->trace_len+=n;
174 5 : item->valuestring[trace->trace_len]=0;
175 : }
176 0 : else error("Write_dyn_trace_n, cjson trace problem\n");
177 : }
178 5 : return n;
179 : }
180 :
181 144 : size_t Write_dyn_trace(void *userp,enum term_color color, const char *message, ...)
182 : {
183 :
184 :
185 144 : if (!userp || !message|| strlen(message)==0) return -1;
186 : va_list varg;
187 144 : va_start (varg, message);
188 144 : struct trace_Struct *trace = (struct trace_Struct *)userp;
189 :
190 144 : size_t consten_buf_len=0;
191 144 : char * contents=NULL;
192 : // print into temp buffer and adjust buffer till content fits
193 :
194 144 : size_t cnt=0;
195 144 : int res=0;
196 : do {
197 144 : cnt++;
198 144 : if (contents) free(contents);
199 144 : contents=NULL;
200 144 : contents=(char *)calloc(cnt,trace->min_trace_buf_increment);
201 144 : res=-1;
202 144 : if (contents)
203 : {
204 144 : consten_buf_len=(size_t)(trace->min_trace_buf_increment * cnt);
205 144 : res=vsnprintf(contents,consten_buf_len ,message,varg);
206 : }
207 : else
208 : break;
209 144 : } while ((size_t)res >= consten_buf_len);
210 :
211 144 : va_end(varg);
212 :
213 144 : if (res<0)
214 : {
215 0 : error("Buffer error contents\n");
216 0 : if (contents) free (contents);
217 : contents=NULL;
218 : }
219 : size_t n;
220 : // with content and length, check if trace buffer needs to be increased
221 144 : if (contents)
222 : {
223 : // content ready, let's calculate the length
224 144 : if (color!= none)
225 111 : n= strlen(contents) + strlen(color_data[color]) + strlen(ANSI_RESET);
226 : else
227 33 : n= strlen(contents);
228 :
229 144 : cJSON * item=cJSON_GetObjectItem(trace->params, "trace" );
230 144 : if (item && item->valuestring)
231 : {
232 : // increase buffer if needed
233 144 : if (trace->trace_len+1+n> trace->trace_buf_size)
234 : {
235 0 : size_t newsize=trace->trace_buf_size+ MAX(trace->min_trace_buf_increment, n);
236 0 : char * temp=realloc(item->valuestring,newsize);
237 0 : if (temp )
238 : {
239 0 : trace->trace_buf_size=newsize;
240 0 : if (temp!=item->valuestring)
241 : {
242 0 : item->valuestring=temp;
243 : }
244 : }
245 : else
246 : {
247 0 : error("Write_dyn_trace_n, no more mem");
248 0 : if (contents) free(contents);
249 : return -1;
250 : }
251 : }
252 : // append contents
253 144 : if (color!= none)
254 111 : sprintf(item->valuestring+trace->trace_len,"%s%s%s",color_data[color],contents,ANSI_RESET);
255 : else
256 33 : memcpy(item->valuestring+trace->trace_len, contents, n);
257 144 : trace->trace_len+=n;
258 144 : item->valuestring[trace->trace_len]=0;
259 : }
260 0 : else error("Write_dyn_trace_n, cjson trace problem\n");
261 : }
262 144 : if (contents) free(contents);
263 144 : return n;
264 : }
265 :
266 :
267 78 : size_t Write_dyn_trace_pad(void *userp,enum term_color color, int len2pad,const char *message, ...)
268 : {
269 78 : if (!userp || !message|| strlen(message)==0) return -1;
270 :
271 78 : struct trace_Struct *trace = (struct trace_Struct *)userp;
272 :
273 78 : size_t consten_buf_len=0;
274 78 : char * contents=NULL;
275 : // print into temp buffer and adjust buffer till content fits
276 : va_list varg;
277 78 : va_start (varg, message);
278 78 : int cnt=0;
279 78 : int res=0;
280 : do {
281 78 : cnt++;
282 78 : consten_buf_len=trace->min_trace_buf_increment * cnt;
283 78 : if (contents) free(contents);
284 78 : contents=NULL;
285 78 : contents=calloc(1,consten_buf_len);
286 78 : res=-1;
287 78 : if (contents)
288 78 : res=vsnprintf(contents,consten_buf_len ,message,varg);
289 : else
290 : break;
291 78 : } while((size_t)res >= consten_buf_len);
292 78 : va_end(varg);
293 :
294 78 : if (res<0)
295 : {
296 0 : error("Buffer error contents\n");
297 0 : if (contents) free (contents);
298 : contents=NULL;
299 : }
300 78 : size_t realsize=-1;
301 : // with content and length, check if trace buffer needs to be increased
302 78 : if (contents)
303 : {
304 :
305 78 : realsize = strlen(contents);
306 78 : char pad[]=" ";
307 78 : if (realsize<=len2pad) pad[len2pad-realsize]=0;
308 : else
309 : { // trim contents
310 0 : contents[len2pad]=0;
311 0 : if (len2pad>2)
312 : {
313 0 : contents[len2pad-1]='.';
314 0 : contents[len2pad-2]='.';
315 : }
316 0 : pad[0]=0;
317 : }
318 : size_t n;
319 : // content ready, let's calculate the length
320 78 : if (color!= none)
321 4 : n= strlen(contents) + strlen(color_data[color]) + strlen(ANSI_RESET) + strlen(pad);
322 : else
323 74 : n= strlen(contents)+strlen(pad);
324 :
325 78 : cJSON * item=cJSON_GetObjectItem(trace->params, "trace" );
326 78 : if (item && item->valuestring)
327 : {
328 : // increase buffer if needed
329 78 : if (trace->trace_len+1+n> trace->trace_buf_size)
330 : {
331 0 : size_t newsize=trace->trace_buf_size+ MAX(trace->min_trace_buf_increment, n);
332 0 : char * temp=realloc(item->valuestring,newsize);
333 0 : if (temp )
334 : {
335 0 : trace->trace_buf_size=newsize;
336 0 : if (temp!=item->valuestring)
337 : {
338 0 : item->valuestring=temp;
339 : }
340 : }
341 : else
342 : {
343 0 : error("Write_dyn_trace_n, no more mem");
344 0 : if (contents) free(contents);
345 0 : return -1;
346 : }
347 : }
348 : // append contents with padding to the buffer
349 78 : if (color!= none)
350 4 : sprintf(item->valuestring+trace->trace_len,"%s%s%s%s",color_data[color],contents,ANSI_RESET,pad);
351 : else
352 74 : sprintf(item->valuestring+trace->trace_len,"%s%s",contents,pad);
353 78 : trace->trace_len+=n;
354 78 : item->valuestring[trace->trace_len]=0;
355 : }
356 0 : else error("Write_dyn_trace_n, cjson trace problem\n");
357 : }
358 78 : if (contents) free(contents);
359 78 : return realsize;
360 : }
361 :
362 0 : size_t Write_dynamic_trace_color(const void *contents,char * state, enum term_color color, void *userp)
363 : {
364 0 : if (!userp || !contents) return -1;
365 :
366 0 : struct trace_Struct *trace = (struct trace_Struct *)userp;
367 :
368 : size_t n;
369 0 : size_t realsize=-1;
370 0 : realsize=strlen(contents);
371 : // with content and length, check if trace buffer needs to be increased
372 0 : if (contents)
373 : {
374 : // content ready, let's calculate the length
375 0 : if (color!= none)
376 0 : n= strlen(contents) + strlen(color_data[color]) + strlen(ANSI_RESET);
377 : else
378 : n= strlen(contents);
379 :
380 0 : cJSON * item=cJSON_GetObjectItem(trace->params, "trace" );
381 0 : if (item && item->valuestring)
382 : {
383 : // increase buffer if needed
384 0 : if (trace->trace_len+1+n> trace->trace_buf_size)
385 : {
386 0 : size_t newsize=trace->trace_buf_size+ MAX(trace->min_trace_buf_increment, n);
387 0 : char * temp=realloc(item->valuestring,newsize);
388 0 : if (temp )
389 : {
390 0 : trace->trace_buf_size=newsize;
391 0 : if (temp!=item->valuestring)
392 : {
393 0 : item->valuestring=temp;
394 : }
395 : }
396 : else
397 : {
398 0 : error("Write_dyn_trace_n, no more mem");
399 0 : return -1;
400 : }
401 : }
402 : // append contents
403 0 : if (color!= none)
404 0 : sprintf(item->valuestring+trace->trace_len,"%s%s%s",color_data[color],contents,ANSI_RESET);
405 : else
406 0 : memcpy(item->valuestring+trace->trace_len, contents, n);
407 0 : trace->trace_len+=n;
408 0 : item->valuestring[trace->trace_len]=0;
409 : }
410 0 : else error("Write_dyn_trace_n, cjson trace problem\n");
411 : }
412 0 : if (state)
413 : {
414 0 : if (cJSON_get_key(trace->params, "state"))
415 0 : cJSON_ReplaceItemInObject(trace->params, "state", cJSON_CreateString(state));
416 : else
417 0 : cJSON_AddItemToObject(trace->params, "state", cJSON_CreateString(state));
418 : }
419 0 : return realsize;
420 : }
421 :
422 :
423 :
424 :
425 0 : size_t Write_dynamic_trace(const void *contents,char * state, void *userp)
426 : {
427 0 : size_t realsize = strlen(contents);
428 0 : return Write_dynamic_trace_n(contents, realsize, userp);
429 : }
430 :
431 :
432 : /*------------------------------------------------------------------------
433 : * Helper function get trace string
434 : *------------------------------------------------------------------------*/
435 9 : const char * get_dynamic_trace( void *userp)
436 : {
437 9 : struct trace_Struct *trace = (struct trace_Struct *)userp;
438 9 : return cJSON_get_key(trace->params, "trace");
439 : }
440 :
441 : /*------------------------------------------------------------------------
442 : * Helper function write string to dynamic buffer
443 : *------------------------------------------------------------------------*/
444 73 : size_t clear_dynamic_trace( void *userp)
445 : {
446 73 : struct trace_Struct *trace = (struct trace_Struct *)userp;
447 73 : cJSON * tmp=cJSON_GetObjectItem( trace->params, "trace");
448 73 : if (tmp)
449 : {
450 73 : tmp->valuestring[0]=0;
451 73 : trace->trace_len=0;
452 73 : trace->mark=-1;
453 : }
454 : else
455 0 : error("could not get trace\n");
456 73 : return 0;
457 : }
458 :
459 : /*------------------------------------------------------------------------
460 : * Helper function write string to dynamic buffer
461 : *------------------------------------------------------------------------*/
462 0 : void clear_till_mark_dynamic_trace( void *userp)
463 : {
464 0 : struct trace_Struct *trace = (struct trace_Struct *)userp;
465 0 : if (trace->mark!=-1 && trace->trace_len>0 && trace->trace_len>trace->mark)
466 : {
467 0 : cJSON * tmp=cJSON_GetObjectItem( trace->params, "trace");
468 0 : if (tmp)
469 : {
470 0 : tmp->valuestring[trace->mark]=0;
471 0 : trace->trace_len=trace->mark;
472 : }
473 : else
474 0 : error("could not get trace\n");
475 : }
476 0 : return;
477 : }
478 :
479 : /*------------------------------------------------------------------------
480 : * Helper function write string to dynamic buffer
481 : *------------------------------------------------------------------------*/
482 0 : void set_mark_dynamic_trace( void *userp)
483 : {
484 0 : struct trace_Struct *trace = (struct trace_Struct *)userp;
485 0 : trace->mark=trace->trace_len;
486 0 : return;
487 : }
488 : /*------------------------------------------------------------------------
489 : * Helper function write string to dynamic buffer
490 : *------------------------------------------------------------------------*/
491 0 : void clear_mark_dynamic_trace( void *userp)
492 : {
493 0 : struct trace_Struct *trace = (struct trace_Struct *)userp;
494 0 : trace->mark=-1;
495 0 : return;
496 : }
497 :
498 : /*------------------------------------------------------------------------
499 : * Helper function write string to dynamic buffer
500 : *------------------------------------------------------------------------*/
501 13 : void free_dynamic_trace(void **userp)
502 : {
503 13 : if (*userp)
504 : {
505 13 : struct trace_Struct **trace_p = (struct trace_Struct **)userp;
506 13 : if ((*trace_p)->params)cJSON_Delete( (*trace_p)->params);
507 13 : (*trace_p)->params=NULL;
508 13 : if ((*trace_p)->url) free((*trace_p)->url);
509 13 : (*trace_p)->url=NULL;
510 13 : if ((*trace_p)->curl) curl_easy_cleanup((*trace_p)->curl);
511 13 : (*trace_p)->curl=NULL;
512 13 : (*trace_p)->mark=-1;
513 13 : free (*trace_p);
514 13 : (*trace_p)=NULL;
515 : }
516 13 : return;
517 : }
518 :
519 :
520 : // START Dynbuffer
521 :
522 : /*------------------------------------------------------------------------
523 : * Helper function write string to dynamic buffer
524 : *------------------------------------------------------------------------*/
525 306 : size_t Writedynamicbuf(void *contents, void *userp)
526 : {
527 306 : size_t realsize = strlen(contents);
528 306 : struct MemoryStruct *mem = (struct MemoryStruct *)userp;
529 :
530 306 : void * tmp= realloc(mem->memory, mem->size + realsize + 1);
531 306 : if(tmp == NULL) {
532 : // LCOV_EXCL_START
533 : /* out of memory! */
534 : // error("not enough memory (realloc returned NULL)\n");
535 : return 0;
536 : // LCOV_EXCL_STOP
537 : }
538 : else
539 306 : mem->memory=tmp;
540 306 : memcpy(&(mem->memory[mem->size]), contents, realsize);
541 306 : mem->size += realsize;
542 306 : mem->memory[mem->size] = 0;
543 :
544 306 : return realsize;
545 : }
546 :
547 : /*------------------------------------------------------------------------
548 : * Helper function write non NULL string to dynamic buffer
549 : *------------------------------------------------------------------------*/
550 98 : size_t Writedynamicbuf_n(void *contents, size_t content_len, void *userp)
551 : {
552 98 : size_t realsize = content_len;
553 98 : struct MemoryStruct *mem = (struct MemoryStruct *)userp;
554 :
555 98 : void * tmp= realloc(mem->memory, mem->size + realsize + 1);
556 98 : if(tmp == NULL) {
557 : // LCOV_EXCL_START
558 : /* out of memory! */
559 : // error("not enough memory (realloc returned NULL)\n");
560 : return 0;
561 : // LCOV_EXCL_STOP
562 : }
563 : else
564 98 : mem->memory=tmp;
565 :
566 :
567 98 : memcpy(&(mem->memory[mem->size]), contents, realsize);
568 98 : mem->size += realsize;
569 98 : mem->memory[mem->size] = 0;
570 :
571 98 : return realsize;
572 : }
573 :
574 : /*------------------------------------------------------------------------
575 : * intializes the dynamic buff
576 : *------------------------------------------------------------------------*/
577 57 : size_t init_dynamicbuf( void *userp)
578 : {
579 57 : struct MemoryStruct *mem = (struct MemoryStruct *)userp;
580 :
581 57 : mem->memory = malloc( 1);
582 57 : mem->size=0;
583 57 : if(mem->memory == NULL) {
584 : // LCOV_EXCL_START
585 : /* out of memory! */
586 : // error("not enough memory (realloc returned NULL)\n");
587 : return -1;
588 : // LCOV_EXCL_STOP
589 : }
590 57 : mem->memory[mem->size] = 0;
591 57 : return 0;
592 : }
593 : /*------------------------------------------------------------------------
594 : * intializes the dynamic buff
595 : *------------------------------------------------------------------------*/
596 19 : void free_dynamicbuf( void *userp)
597 : {
598 19 : struct MemoryStruct *mem = (struct MemoryStruct *)userp;
599 :
600 19 : free(mem->memory);
601 19 : mem->memory=NULL;
602 19 : mem->size=-1;
603 19 : return ;
604 : }
|