1 /*
2 	belle-sip - SIP (RFC3261) library.
3     Copyright (C) 2014  Belledonne Communications SARL
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "belle_sip_internal.h"
20 #include "bctoolbox/vfs.h"
21 
22 #ifdef HAVE_ZLIB
23 #include "zlib.h"
24 #endif
25 
26 /*
27  * Body handler base class implementation
28  */
29 
30 struct belle_sip_body_handler{
31 	belle_sip_object_t base;
32 	belle_sip_body_handler_progress_callback_t progress_cb;
33 	size_t expected_size; /* 0 if unknown*/
34 	size_t transfered_size;
35 	belle_sip_list_t *headers; /**> used when this body is part of a multipart message to store the header of this part */
36 	char *headerStringBuffer; /**> buffer populated with a string created from marshaling the headers */
37 	void *user_data;
38 };
39 
belle_sip_body_handler_clone(belle_sip_body_handler_t * obj,const belle_sip_body_handler_t * orig)40 static void belle_sip_body_handler_clone(belle_sip_body_handler_t *obj, const belle_sip_body_handler_t *orig){
41 	obj->progress_cb=orig->progress_cb;
42 	obj->user_data=orig->user_data;
43 	obj->expected_size=orig->expected_size;
44 	obj->transfered_size=orig->transfered_size;
45 	obj->headers=belle_sip_list_copy_with_data(orig->headers,(void *(*)(void*))belle_sip_object_clone_and_ref);
46 	if (orig->headerStringBuffer!=NULL) {
47 		obj->headerStringBuffer = strdup(orig->headerStringBuffer);
48 	}
49 }
50 
belle_sip_body_handler_destroy(belle_sip_body_handler_t * obj)51 static void belle_sip_body_handler_destroy(belle_sip_body_handler_t *obj){
52 	belle_sip_list_free_with_data(obj->headers,belle_sip_object_unref);
53 	belle_sip_free(obj->headerStringBuffer);
54 }
55 
belle_sip_body_handler_marshal(belle_sip_body_handler_t * obj,char * buff,size_t buff_size,size_t * offset)56 static belle_sip_error_code belle_sip_body_handler_marshal(belle_sip_body_handler_t *obj, char *buff, size_t buff_size, size_t *offset) {
57 	int ret;
58 	size_t len;
59 	if (*offset == 0) belle_sip_body_handler_begin_send_transfer(obj);
60 	do {
61 		len = buff_size - *offset;
62 		ret = belle_sip_body_handler_send_chunk(obj, NULL, (uint8_t*)buff + *offset, &len);
63 		*offset += len;
64 	} while ((ret == BELLE_SIP_CONTINUE) && (len > 0));
65 	if ((ret == BELLE_SIP_CONTINUE) || (ret == BELLE_SIP_BUFFER_OVERFLOW)) return BELLE_SIP_BUFFER_OVERFLOW;
66 	if (ret == BELLE_SIP_STOP) belle_sip_body_handler_end_transfer(obj);
67 	return BELLE_SIP_OK;
68 }
69 
70 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_body_handler_t);
71 
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_body_handler_t)72 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_body_handler_t)
73 	{
74 		BELLE_SIP_VPTR_INIT(belle_sip_body_handler_t,belle_sip_object_t,TRUE),
75 		(belle_sip_object_destroy_t) belle_sip_body_handler_destroy,
76 		(belle_sip_object_clone_t) belle_sip_body_handler_clone,
77 		(belle_sip_object_marshal_t) belle_sip_body_handler_marshal,
78 		BELLE_SIP_DEFAULT_BUFSIZE_HINT
79 	},
80 	NULL, /* begin_recv_transfer */
81 	NULL, /* begin_send_transfer */
82 	NULL, /* end_transfer */
83 	NULL, /*chunk_recv*/
84 	NULL /*chunk_send*/
85 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
86 
87 void belle_sip_body_handler_init(belle_sip_body_handler_t *obj, belle_sip_body_handler_progress_callback_t progress_cb, void *user_data){
88 	obj->user_data=user_data;
89 	obj->progress_cb=progress_cb;
90 	obj->headers = NULL; /* header is not used in most of the case, set it using a dedicated function if needed */
91 	obj->headerStringBuffer = NULL; /* header string buffer is set when adding a body handler to a multipart body handler */
92 }
93 
belle_sip_body_handler_add_header(belle_sip_body_handler_t * obj,belle_sip_header_t * header)94 void belle_sip_body_handler_add_header(belle_sip_body_handler_t *obj, belle_sip_header_t *header) {
95 	if (header != NULL) {
96 		obj->headers=belle_sip_list_append(obj->headers,belle_sip_object_ref(header));
97 	}
98 }
99 
belle_sip_body_handler_remove_header_from_ptr(belle_sip_body_handler_t * obj,belle_sip_header_t * header)100 void belle_sip_body_handler_remove_header_from_ptr(belle_sip_body_handler_t *obj, belle_sip_header_t* header) {
101 	belle_sip_list_t* it = belle_sip_list_find(obj->headers, header);
102 	if (it) {
103 		belle_sip_object_unref(header);
104 		obj->headers = belle_sip_list_delete_link(obj->headers, it);
105 	}
106 }
107 
belle_sip_body_handler_get_headers(const belle_sip_body_handler_t * obj)108 const belle_sip_list_t* belle_sip_body_handler_get_headers(const belle_sip_body_handler_t *obj) {
109 	return obj->headers;
110 }
111 
belle_sip_body_handler_get_size(const belle_sip_body_handler_t * obj)112 size_t belle_sip_body_handler_get_size(const belle_sip_body_handler_t *obj){
113 	return obj->expected_size;
114 }
115 
belle_sip_body_handler_set_size(belle_sip_body_handler_t * obj,size_t size)116 void belle_sip_body_handler_set_size(belle_sip_body_handler_t *obj, size_t size){
117 	obj->expected_size=size;
118 }
119 
belle_sip_body_handler_get_transfered_size(const belle_sip_body_handler_t * obj)120 size_t belle_sip_body_handler_get_transfered_size(const belle_sip_body_handler_t *obj){
121 	return obj->transfered_size;
122 }
123 
update_progress(belle_sip_body_handler_t * obj,belle_sip_message_t * msg)124 static void update_progress(belle_sip_body_handler_t *obj, belle_sip_message_t *msg){
125 	if (obj->progress_cb)
126 		obj->progress_cb(obj,msg,obj->user_data,obj->transfered_size,obj->expected_size);
127 }
128 
belle_sip_body_handler_begin_recv_transfer(belle_sip_body_handler_t * obj)129 void belle_sip_body_handler_begin_recv_transfer(belle_sip_body_handler_t *obj){
130 	BELLE_SIP_OBJECT_VPTR_TYPE(belle_sip_body_handler_t) *vptr = BELLE_SIP_OBJECT_VPTR(obj, belle_sip_body_handler_t);
131 	if (vptr->begin_recv_transfer != NULL) {
132 		vptr->begin_recv_transfer(obj);
133 	}
134 	obj->transfered_size=0;
135 }
136 
belle_sip_body_handler_begin_send_transfer(belle_sip_body_handler_t * obj)137 void belle_sip_body_handler_begin_send_transfer(belle_sip_body_handler_t *obj) {
138 	BELLE_SIP_OBJECT_VPTR_TYPE(belle_sip_body_handler_t) *vptr = BELLE_SIP_OBJECT_VPTR(obj, belle_sip_body_handler_t);
139 	if (vptr->begin_send_transfer != NULL) {
140 		vptr->begin_send_transfer(obj);
141 	}
142 	obj->transfered_size = 0;
143 }
144 
belle_sip_body_handler_recv_chunk(belle_sip_body_handler_t * obj,belle_sip_message_t * msg,uint8_t * buf,size_t size)145 void belle_sip_body_handler_recv_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, uint8_t *buf, size_t size){
146 	BELLE_SIP_OBJECT_VPTR(obj,belle_sip_body_handler_t)->chunk_recv(obj,msg,(off_t)obj->transfered_size,buf,size);
147 	obj->transfered_size+=size;
148 	update_progress(obj,msg);
149 }
150 
belle_sip_body_handler_send_chunk(belle_sip_body_handler_t * obj,belle_sip_message_t * msg,uint8_t * buf,size_t * size)151 int belle_sip_body_handler_send_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, uint8_t *buf, size_t *size){
152 	int ret;
153 	size_t to_send = *size;
154 	if (obj->expected_size!=0){
155 		to_send=MIN(*size,obj->expected_size-obj->transfered_size);
156 	}
157 	if (to_send==0 && obj->transfered_size==obj->expected_size) {
158 		// An eWouldBlock error added a call to the function, nothing to send so return
159 		// In some case to_send=0 because not buffer is available but sendings not finished.
160 		belle_sip_message("body handler [%p] : Nothing to send",obj);
161 		*size=0;
162 		return BELLE_SIP_STOP;
163 	}
164 	ret=BELLE_SIP_OBJECT_VPTR(obj,belle_sip_body_handler_t)->chunk_send(obj,msg,(off_t)obj->transfered_size,buf,&to_send);
165 	obj->transfered_size+=to_send;
166 	*size=to_send;
167 	update_progress(obj,msg);
168 	if (obj->expected_size!=0){
169 		if (obj->transfered_size==obj->expected_size) {
170 			return BELLE_SIP_STOP;
171 		}
172 		if (ret==BELLE_SIP_STOP && obj->transfered_size<obj->expected_size){
173 			belle_sip_error("body handler [%p] transfered only [%i] bytes while [%i] were expected",obj,
174 					(int)obj->transfered_size,(int)obj->expected_size);
175 		}
176 	}
177 	return ret;
178 }
179 
belle_sip_body_handler_end_transfer(belle_sip_body_handler_t * obj)180 void belle_sip_body_handler_end_transfer(belle_sip_body_handler_t *obj){
181 	BELLE_SIP_OBJECT_VPTR_TYPE(belle_sip_body_handler_t) *vptr = BELLE_SIP_OBJECT_VPTR(obj, belle_sip_body_handler_t);
182 	if (vptr->end_transfer != NULL) {
183 		vptr->end_transfer(obj);
184 	}
185 	if (obj->expected_size==0)
186 		obj->expected_size=obj->transfered_size;
187 }
188 
189 /*
190  * memory body handler implementation.
191 **/
192 
193 struct belle_sip_memory_body_handler{
194 	belle_sip_body_handler_t base;
195 	uint8_t *buffer;
196 	uint8_t encoding_applied;
197 };
198 
belle_sip_memory_body_handler_destroy(belle_sip_memory_body_handler_t * obj)199 static void belle_sip_memory_body_handler_destroy(belle_sip_memory_body_handler_t *obj){
200 	if (obj->buffer) belle_sip_free(obj->buffer);
201 }
202 
belle_sip_memory_body_handler_clone(belle_sip_memory_body_handler_t * obj,const belle_sip_memory_body_handler_t * orig)203 static void belle_sip_memory_body_handler_clone(belle_sip_memory_body_handler_t *obj, const belle_sip_memory_body_handler_t *orig){
204 	if (orig->buffer) {
205 		obj->buffer=belle_sip_malloc(orig->base.expected_size+1);
206 		memcpy(obj->buffer,orig->buffer,orig->base.expected_size);
207 		obj->buffer[orig->base.expected_size]='\0';
208 	}
209 	obj->encoding_applied = orig->encoding_applied;
210 }
211 
belle_sip_memory_body_handler_recv_chunk(belle_sip_body_handler_t * base,belle_sip_message_t * msg,off_t offset,uint8_t * buf,size_t size)212 static void belle_sip_memory_body_handler_recv_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, off_t offset, uint8_t *buf, size_t size){
213 	belle_sip_memory_body_handler_t *obj=(belle_sip_memory_body_handler_t*)base;
214 	obj->buffer=belle_sip_realloc(obj->buffer,offset+size+1);
215 	memcpy(obj->buffer+offset,buf,size);
216 	obj->buffer[offset+size]='\0';
217 }
218 
belle_sip_memory_body_handler_send_chunk(belle_sip_body_handler_t * base,belle_sip_message_t * msg,off_t offset,uint8_t * buf,size_t * size)219 static int belle_sip_memory_body_handler_send_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, off_t offset, uint8_t *buf, size_t *size){
220 	belle_sip_memory_body_handler_t *obj=(belle_sip_memory_body_handler_t*)base;
221 	size_t to_send=MIN(*size,obj->base.expected_size-offset);
222 	if (obj->buffer == NULL) return BELLE_SIP_STOP;
223 	memcpy(buf,obj->buffer+offset,to_send);
224 	*size=to_send;
225 	return (obj->base.expected_size-offset==*size) ? BELLE_SIP_STOP : BELLE_SIP_CONTINUE;
226 }
227 
228 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_memory_body_handler_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_memory_body_handler_t)229 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_memory_body_handler_t)
230 	{
231 		{
232 			BELLE_SIP_VPTR_INIT(belle_sip_memory_body_handler_t,belle_sip_body_handler_t,TRUE),
233 			(belle_sip_object_destroy_t) belle_sip_memory_body_handler_destroy,
234 			(belle_sip_object_clone_t)belle_sip_memory_body_handler_clone,
235 			NULL,
236 			BELLE_SIP_DEFAULT_BUFSIZE_HINT
237 		},
238 		NULL,
239 		NULL,
240 		NULL,
241 		belle_sip_memory_body_handler_recv_chunk,
242 		belle_sip_memory_body_handler_send_chunk
243 	}
244 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
245 
belle_sip_memory_body_handler_get_buffer(const belle_sip_memory_body_handler_t * obj)246 void *belle_sip_memory_body_handler_get_buffer(const belle_sip_memory_body_handler_t *obj){
247 	return obj->buffer;
248 }
249 
belle_sip_memory_body_handler_set_buffer(belle_sip_memory_body_handler_t * obj,void * buffer)250 void belle_sip_memory_body_handler_set_buffer(belle_sip_memory_body_handler_t *obj, void *buffer) {
251 	if (obj->buffer != NULL) belle_sip_free(obj->buffer);
252 	obj->buffer = (uint8_t *)buffer;
253 }
254 
255 #define BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_INITIAL_SIZE 2048
256 
belle_sip_memory_body_handler_apply_encoding(belle_sip_memory_body_handler_t * obj,const char * encoding)257 void belle_sip_memory_body_handler_apply_encoding(belle_sip_memory_body_handler_t *obj, const char *encoding) {
258 	if ((obj->buffer == NULL) || (obj->encoding_applied == TRUE)) return;
259 
260 #ifdef HAVE_ZLIB
261 	if (strcmp(encoding, "deflate") == 0) {
262 		z_stream strm;
263 		size_t initial_size = belle_sip_body_handler_get_size(BELLE_SIP_BODY_HANDLER(obj));
264 		size_t final_size;
265 		unsigned int avail_out = BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_INITIAL_SIZE;
266 		unsigned int outbuf_size = avail_out;
267 		unsigned char *outbuf = belle_sip_malloc(outbuf_size);
268 		unsigned char *outbuf_ptr = outbuf;
269 		int ret;
270 
271 		strm.zalloc = Z_NULL;
272 		strm.zfree = Z_NULL;
273 		strm.opaque = Z_NULL;
274 		ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
275 		if (ret != Z_OK) return;
276 		strm.avail_in = (uInt)initial_size;
277 		strm.next_in = obj->buffer;
278 		do {
279 			if (avail_out < BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_INITIAL_SIZE) {
280 				unsigned int cursize = (unsigned int)(outbuf_ptr - outbuf);
281 				outbuf_size *= 2;
282 				outbuf = belle_sip_realloc(outbuf, outbuf_size);
283 				outbuf_ptr = outbuf + cursize;
284 			}
285 			strm.avail_out = avail_out;
286 			strm.next_out = outbuf_ptr;
287 			deflate(&strm, Z_FINISH);
288 			outbuf_ptr += avail_out - strm.avail_out;
289 			avail_out = outbuf_size - (unsigned int)(outbuf_ptr - outbuf);
290 		} while (strm.avail_out == 0);
291 		deflateEnd(&strm);
292 		final_size = outbuf_ptr - outbuf;
293 		belle_sip_message("Body has been compressed: %u->%u:\n%s", (unsigned int)initial_size, (unsigned int)final_size, obj->buffer);
294 		belle_sip_free(obj->buffer);
295 		obj->buffer = outbuf;
296 		belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(obj), final_size);
297 		obj->encoding_applied = TRUE;
298 	} else
299 #endif
300 	{
301 		belle_sip_warning("%s: unknown encoding '%s'", __FUNCTION__, encoding);
302 	}
303 }
304 
belle_sip_memory_body_handler_unapply_encoding(belle_sip_memory_body_handler_t * obj,const char * encoding)305 int belle_sip_memory_body_handler_unapply_encoding(belle_sip_memory_body_handler_t *obj, const char *encoding) {
306 	if (obj->buffer == NULL) return -1;
307 
308 #ifdef HAVE_ZLIB
309 	if (strcmp(encoding, "deflate") == 0) {
310 		z_stream strm;
311 		size_t initial_size = belle_sip_body_handler_get_size(BELLE_SIP_BODY_HANDLER(obj));
312 		size_t final_size;
313 		unsigned int avail_out = BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_INITIAL_SIZE;
314 		unsigned int outbuf_size = avail_out;
315 		unsigned char *outbuf = belle_sip_malloc(outbuf_size);
316 		unsigned char *outbuf_ptr = outbuf;
317 		bool_t outbuf_too_small = FALSE;
318 		int ret;
319 
320 		strm.zalloc = Z_NULL;
321 		strm.zfree = Z_NULL;
322 		strm.opaque = Z_NULL;
323 		strm.avail_in = 0;
324 		strm.next_in = Z_NULL;
325 		ret = inflateInit(&strm);
326 		if (ret != Z_OK) return -1;
327 		strm.avail_in = (uInt)initial_size;
328 		strm.next_in = obj->buffer;
329 		do {
330 			if ((avail_out < BELLE_SIP_MEMORY_BODY_HANDLER_ZLIB_INITIAL_SIZE) || (outbuf_too_small == TRUE)) {
331 				unsigned int cursize = (unsigned int)(outbuf_ptr - outbuf);
332 				unsigned int increase = outbuf_size;
333 				outbuf_size *= 2;
334 				outbuf = belle_sip_realloc(outbuf, outbuf_size);
335 				outbuf_ptr = outbuf + cursize;
336 				avail_out += increase;
337 			}
338 			outbuf_too_small = FALSE;
339 			strm.avail_out = avail_out;
340 			strm.next_out = outbuf_ptr;
341 			ret = inflate(&strm, Z_NO_FLUSH);
342 			switch (ret) {
343 				case Z_OK:
344 					/* Error handling for truncated input buffer. Z_STREAM_END is not returned but there is no further input content */
345 					if (strm.avail_out > 0) {
346 						belle_sip_error("%s: truncated compressed body. Cannot uncompress it...", __FUNCTION__);
347 						return -1;
348 					}
349 					break;
350 				case Z_STREAM_END:
351 					// Everything is ok, continue
352 					break;
353 				case Z_BUF_ERROR:
354 					// Ask for more output space
355 					outbuf_too_small = TRUE;
356 					break;
357 				case Z_NEED_DICT:
358 				case Z_DATA_ERROR:
359 				case Z_STREAM_ERROR:
360 				case Z_MEM_ERROR:
361 				default:
362 					inflateEnd(&strm);
363 					belle_sip_free(outbuf);
364 					return -1;
365 			}
366 			outbuf_ptr += avail_out - strm.avail_out;
367 			avail_out = outbuf_size - (unsigned int)(outbuf_ptr - outbuf);
368 		} while (ret != Z_STREAM_END);
369 		inflateEnd(&strm);
370 		final_size = outbuf_ptr - outbuf;
371 		if (final_size == outbuf_size) {
372 			/* If not enough space get it to be able to put the final NULL character. */
373 			outbuf = belle_sip_realloc(outbuf, outbuf_size + 1);
374 			outbuf_ptr = outbuf + final_size;
375 		}
376 		*outbuf_ptr = '\0';
377 		belle_sip_message("Body has been uncompressed: %u->%u:\n%s", (unsigned int)initial_size, (unsigned int)final_size, outbuf);
378 		belle_sip_free(obj->buffer);
379 		obj->buffer = outbuf;
380 		belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(obj), final_size);
381 		return 0;
382 	} else
383 #endif
384 	{
385 		belle_sip_warning("%s: unknown encoding '%s'", __FUNCTION__, encoding);
386 		return -1;
387 	}
388 }
389 
belle_sip_memory_body_handler_new(belle_sip_body_handler_progress_callback_t cb,void * user_data)390 belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_new(belle_sip_body_handler_progress_callback_t cb, void *user_data){
391 	belle_sip_memory_body_handler_t *obj=belle_sip_object_new(belle_sip_memory_body_handler_t);
392 	belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,cb,user_data);
393 	return obj;
394 }
395 
belle_sip_memory_body_handler_new_from_buffer(void * buffer,size_t bufsize,belle_sip_body_handler_progress_callback_t cb,void * user_data)396 belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_new_from_buffer(void *buffer, size_t bufsize, belle_sip_body_handler_progress_callback_t cb, void *user_data){
397 	belle_sip_memory_body_handler_t *obj=belle_sip_object_new(belle_sip_memory_body_handler_t);
398 	belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,cb,user_data);
399 	obj->buffer=(uint8_t*)buffer;
400 	obj->base.expected_size=bufsize;
401 	return obj;
402 }
403 
belle_sip_memory_body_handler_new_copy_from_buffer(const void * buffer,size_t bufsize,belle_sip_body_handler_progress_callback_t cb,void * user_data)404 belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_new_copy_from_buffer(const void *buffer, size_t bufsize, belle_sip_body_handler_progress_callback_t cb, void *user_data){
405 	belle_sip_memory_body_handler_t *obj=belle_sip_object_new(belle_sip_memory_body_handler_t);
406 	belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,cb,user_data);
407 	obj->buffer=(uint8_t*)belle_sip_malloc(bufsize+1);
408 	obj->buffer[bufsize]='\0';
409 	obj->base.expected_size=bufsize;
410 	memcpy(obj->buffer,buffer,bufsize);
411 	return obj;
412 }
413 
414 /*
415  * User body handler implementation
416  */
417 
418 struct belle_sip_user_body_handler{
419 	belle_sip_body_handler_t base;
420 	belle_sip_user_body_handler_start_callback_t start_cb;
421 	belle_sip_user_body_handler_recv_callback_t recv_cb;
422 	belle_sip_user_body_handler_send_callback_t send_cb;
423 	belle_sip_user_body_handler_stop_callback_t stop_cb;
424 };
425 
belle_sip_user_body_handler_begin_transfer(belle_sip_body_handler_t * base)426 static void belle_sip_user_body_handler_begin_transfer(belle_sip_body_handler_t *base) {
427 	belle_sip_user_body_handler_t *obj = (belle_sip_user_body_handler_t *)base;
428 	if (obj->start_cb)
429 		obj->start_cb((belle_sip_user_body_handler_t*)base, base->user_data);
430 }
431 
belle_sip_user_body_handler_end_transfer(belle_sip_body_handler_t * base)432 static void belle_sip_user_body_handler_end_transfer(belle_sip_body_handler_t *base) {
433 	belle_sip_user_body_handler_t *obj = (belle_sip_user_body_handler_t *)base;
434 	if (obj->stop_cb)
435 		obj->stop_cb((belle_sip_user_body_handler_t*)base, base->user_data);
436 }
437 
belle_sip_user_body_handler_recv_chunk(belle_sip_body_handler_t * base,belle_sip_message_t * msg,off_t offset,uint8_t * buf,size_t size)438 static void belle_sip_user_body_handler_recv_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, off_t offset, uint8_t *buf, size_t size){
439 	belle_sip_user_body_handler_t *obj=(belle_sip_user_body_handler_t*)base;
440 	if (obj->recv_cb)
441 		obj->recv_cb((belle_sip_user_body_handler_t*)base, msg, base->user_data, offset, buf, size);
442 	else belle_sip_warning("belle_sip_user_body_handler_t ignoring received chunk.");
443 }
444 
belle_sip_user_body_handler_send_chunk(belle_sip_body_handler_t * base,belle_sip_message_t * msg,off_t offset,uint8_t * buf,size_t * size)445 static int belle_sip_user_body_handler_send_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, off_t offset, uint8_t *buf, size_t *size){
446 	belle_sip_user_body_handler_t *obj=(belle_sip_user_body_handler_t*)base;
447 	if (obj->send_cb)
448 		return obj->send_cb((belle_sip_user_body_handler_t*)base, msg, base->user_data, offset, buf, size);
449 	else belle_sip_warning("belle_sip_user_body_handler_t ignoring send chunk.");
450 	*size=0;
451 	return BELLE_SIP_STOP;
452 }
453 
belle_sip_user_body_handler_clone(belle_sip_user_body_handler_t * obj,const belle_sip_user_body_handler_t * orig)454 static void belle_sip_user_body_handler_clone(belle_sip_user_body_handler_t *obj, const belle_sip_user_body_handler_t *orig){
455 	obj->start_cb=orig->start_cb;
456 	obj->recv_cb=orig->recv_cb;
457 	obj->send_cb=orig->send_cb;
458 	obj->stop_cb=orig->stop_cb;
459 }
460 
461 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_user_body_handler_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_user_body_handler_t)462 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_user_body_handler_t)
463 	{
464 		{
465 			BELLE_SIP_VPTR_INIT(belle_sip_user_body_handler_t,belle_sip_body_handler_t,TRUE),
466 			(belle_sip_object_destroy_t) NULL,
467 			(belle_sip_object_clone_t)belle_sip_user_body_handler_clone,
468 			NULL,
469 			BELLE_SIP_DEFAULT_BUFSIZE_HINT
470 		},
471 		belle_sip_user_body_handler_begin_transfer,
472 		belle_sip_user_body_handler_begin_transfer,
473 		belle_sip_user_body_handler_end_transfer,
474 		belle_sip_user_body_handler_recv_chunk,
475 		belle_sip_user_body_handler_send_chunk
476 	}
477 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
478 
belle_sip_user_body_handler_new(size_t total_size,belle_sip_body_handler_progress_callback_t progress_cb,belle_sip_user_body_handler_start_callback_t start_cb,belle_sip_user_body_handler_recv_callback_t recv_cb,belle_sip_user_body_handler_send_callback_t send_cb,belle_sip_user_body_handler_stop_callback_t stop_cb,void * data)479 belle_sip_user_body_handler_t *belle_sip_user_body_handler_new(
480 	size_t total_size,
481 	belle_sip_body_handler_progress_callback_t progress_cb,
482 	belle_sip_user_body_handler_start_callback_t start_cb,
483 	belle_sip_user_body_handler_recv_callback_t recv_cb,
484 	belle_sip_user_body_handler_send_callback_t send_cb,
485 	belle_sip_user_body_handler_stop_callback_t stop_cb,
486 	void *data){
487 	belle_sip_user_body_handler_t * obj=belle_sip_object_new(belle_sip_user_body_handler_t);
488 	belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,progress_cb,data);
489 	obj->base.expected_size=total_size;
490 	obj->start_cb=start_cb;
491 	obj->recv_cb=recv_cb;
492 	obj->send_cb=send_cb;
493 	obj->stop_cb=stop_cb;
494 	return obj;
495 }
496 
497 
498 /**
499  * File body handler implementation
500 **/
501 
502 struct belle_sip_file_body_handler{
503 	belle_sip_body_handler_t base;
504 	char *filepath;
505 	bctbx_vfs_file_t *file;
506 	belle_sip_user_body_handler_t *user_bh;
507 };
508 
belle_sip_file_body_handler_destroy(belle_sip_file_body_handler_t * obj)509 static void belle_sip_file_body_handler_destroy(belle_sip_file_body_handler_t *obj) {
510 	if (obj->filepath) belle_sip_free(obj->filepath);
511 	if (obj->file) {
512 		ssize_t ret;
513 		ret = bctbx_file_close(obj->file);
514 		if (ret == BCTBX_VFS_ERROR) {
515 			bctbx_error("Can't close file %s", obj->filepath);
516 		}
517 		obj->file = NULL;
518 	}
519 	if (obj->user_bh) {
520 		belle_sip_object_unref(obj->user_bh);
521 		obj->user_bh = NULL;
522 	}
523 }
524 
belle_sip_file_body_handler_clone(belle_sip_file_body_handler_t * obj,const belle_sip_file_body_handler_t * orig)525 static void belle_sip_file_body_handler_clone(belle_sip_file_body_handler_t *obj, const belle_sip_file_body_handler_t *orig) {
526 	obj->filepath = belle_sip_strdup(orig->filepath);
527 	obj->file = orig->file;
528 	obj->user_bh = orig->user_bh;
529 	if (obj->user_bh) {
530 		belle_sip_object_ref(obj->user_bh);
531 	}
532 }
533 
belle_sip_file_body_handler_begin_recv_transfer(belle_sip_body_handler_t * base)534 static void belle_sip_file_body_handler_begin_recv_transfer(belle_sip_body_handler_t *base) {
535 	belle_sip_file_body_handler_t *obj = (belle_sip_file_body_handler_t *)base;
536 	bctbx_vfs_t *vfs = bctbx_vfs_get_default();
537 
538 	if (obj->filepath == NULL) return;
539 	obj->file = bctbx_file_open(vfs, obj->filepath, "r+");
540 	if (!obj->file) {
541 		bctbx_error("Can't open file %s", obj->filepath);
542 	}
543 
544 	if (obj->user_bh && obj->user_bh->start_cb) {
545 		obj->user_bh->start_cb((belle_sip_user_body_handler_t*)&(obj->user_bh->base), obj->user_bh->base.user_data);
546 	}
547 }
548 
belle_sip_file_body_handler_begin_send_transfer(belle_sip_body_handler_t * base)549 static void belle_sip_file_body_handler_begin_send_transfer(belle_sip_body_handler_t *base) {
550 	belle_sip_file_body_handler_t *obj = (belle_sip_file_body_handler_t *)base;
551 	bctbx_vfs_t *vfs = bctbx_vfs_get_default();
552 
553 	if (obj->filepath == NULL) return;
554 	obj->file = bctbx_file_open(vfs, obj->filepath, "r");
555 	if (!obj->file) {
556 		bctbx_error("Can't open file %s", obj->filepath);
557 	}
558 
559 	if (obj->user_bh && obj->user_bh->start_cb) {
560 		obj->user_bh->start_cb((belle_sip_user_body_handler_t*)&(obj->user_bh->base), obj->user_bh->base.user_data);
561 	}
562 }
563 
belle_sip_file_body_handler_end_transfer(belle_sip_body_handler_t * base)564 static void belle_sip_file_body_handler_end_transfer(belle_sip_body_handler_t *base) {
565 	belle_sip_file_body_handler_t *obj = (belle_sip_file_body_handler_t *)base;
566 
567 	if (obj->user_bh && obj->user_bh->stop_cb) {
568 		obj->user_bh->stop_cb((belle_sip_user_body_handler_t*)&(obj->user_bh->base), obj->user_bh->base.user_data);
569 	}
570 
571 	if (obj->file) {
572 		ssize_t ret;
573 		ret = bctbx_file_close(obj->file);
574 		if (ret == BCTBX_VFS_ERROR) {
575 			bctbx_error("Can't close file %s", obj->filepath);
576 		}
577 		obj->file = NULL;
578 	}
579 }
580 
belle_sip_file_body_handler_recv_chunk(belle_sip_body_handler_t * base,belle_sip_message_t * msg,off_t offset,uint8_t * buf,size_t size)581 static void belle_sip_file_body_handler_recv_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, off_t offset, uint8_t *buf, size_t size) {
582 	belle_sip_file_body_handler_t *obj = (belle_sip_file_body_handler_t *)base;
583 	ssize_t ret;
584 
585 	if (obj->file == NULL) return;
586 
587 	if (obj->user_bh && obj->user_bh->recv_cb) {
588 		obj->user_bh->recv_cb((belle_sip_user_body_handler_t*)&(obj->user_bh->base), msg, obj->user_bh->base.user_data, offset, buf, size);
589 	}
590 
591 	ret = bctbx_file_write(obj->file, buf, size, offset);
592 	if (ret == BCTBX_VFS_ERROR) {
593 		bctbx_error("File body handler recv write error at offset %lu", (unsigned long)offset);
594 	}
595 }
596 
belle_sip_file_body_handler_send_chunk(belle_sip_body_handler_t * base,belle_sip_message_t * msg,off_t offset,uint8_t * buf,size_t * size)597 static int belle_sip_file_body_handler_send_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, off_t offset, uint8_t *buf, size_t *size) {
598 	belle_sip_file_body_handler_t *obj = (belle_sip_file_body_handler_t *)base;
599 	ssize_t size_t_ret;
600 	size_t to_send = MIN(*size, obj->base.expected_size - offset);
601 
602 	if (obj->file == NULL) return BELLE_SIP_STOP;
603 	size_t_ret = bctbx_file_read(obj->file, buf, to_send, offset);
604 	if (size_t_ret == BCTBX_VFS_ERROR) {
605 		bctbx_error("File body handler send read error at offset %lu", (unsigned long)offset);
606 		return BELLE_SIP_STOP;
607 	}
608 	*size = (size_t)size_t_ret;
609 
610 	if (obj->user_bh && obj->user_bh->send_cb) {
611 		int result = obj->user_bh->send_cb((belle_sip_user_body_handler_t*)&(obj->user_bh->base), msg, obj->user_bh->base.user_data, offset, buf, size);
612 		if (result == BELLE_SIP_STOP) return result;
613 	}
614 
615 	return (((obj->base.expected_size - offset) == (size_t)size_t_ret) || (*size == 0)) ? BELLE_SIP_STOP : BELLE_SIP_CONTINUE;
616 }
617 
618 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_file_body_handler_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_file_body_handler_t)619 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_file_body_handler_t)
620 	{
621 		{
622 			BELLE_SIP_VPTR_INIT(belle_sip_file_body_handler_t,belle_sip_body_handler_t,TRUE),
623 			(belle_sip_object_destroy_t) belle_sip_file_body_handler_destroy,
624 			(belle_sip_object_clone_t)belle_sip_file_body_handler_clone,
625 			NULL,
626 			BELLE_SIP_DEFAULT_BUFSIZE_HINT
627 		},
628 		belle_sip_file_body_handler_begin_recv_transfer,
629 		belle_sip_file_body_handler_begin_send_transfer,
630 		belle_sip_file_body_handler_end_transfer,
631 		belle_sip_file_body_handler_recv_chunk,
632 		belle_sip_file_body_handler_send_chunk
633 	}
634 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
635 
belle_sip_file_body_handler_new(const char * filepath,belle_sip_body_handler_progress_callback_t progress_cb,void * data)636 belle_sip_file_body_handler_t *belle_sip_file_body_handler_new(const char *filepath, belle_sip_body_handler_progress_callback_t progress_cb, void *data) {
637 	struct stat statbuf;
638 	belle_sip_file_body_handler_t *obj = belle_sip_object_new(belle_sip_file_body_handler_t);
639 	belle_sip_body_handler_init((belle_sip_body_handler_t*)obj, progress_cb, data);
640 	obj->filepath = belle_sip_strdup(filepath);
641 	obj->user_bh = NULL;
642 	if (stat(obj->filepath, &statbuf) == 0) {
643 		obj->base.expected_size = statbuf.st_size;
644 	}
645 	return obj;
646 }
647 
belle_sip_file_body_handler_get_file_size(belle_sip_file_body_handler_t * file_bh)648 size_t belle_sip_file_body_handler_get_file_size(belle_sip_file_body_handler_t *file_bh) {
649 	return file_bh->base.expected_size;
650 }
651 
belle_sip_file_body_handler_set_user_body_handler(belle_sip_file_body_handler_t * file_bh,belle_sip_user_body_handler_t * user_bh)652 void belle_sip_file_body_handler_set_user_body_handler(belle_sip_file_body_handler_t *file_bh, belle_sip_user_body_handler_t *user_bh) {
653 	if (file_bh) {
654 		file_bh->user_bh = user_bh;
655 		belle_sip_object_ref(file_bh->user_bh);
656 	}
657 }
658 
659 /*
660  * Multipart body handler implementation
661  * TODO
662 **/
663 
664 struct belle_sip_multipart_body_handler{
665 	belle_sip_body_handler_t base;
666 	belle_sip_list_t *parts;
667 	belle_sip_list_t *transfer_current_part;
668 	char *boundary;
669 	uint8_t *buffer;
670 	unsigned int related;
671 };
672 GET_SET_BOOL(belle_sip_multipart_body_handler,related,is);
673 
belle_sip_multipart_body_handler_destroy(belle_sip_multipart_body_handler_t * obj)674 static void belle_sip_multipart_body_handler_destroy(belle_sip_multipart_body_handler_t *obj){
675 	belle_sip_list_free_with_data(obj->parts,belle_sip_object_unref);
676 	if (obj->buffer != NULL) belle_sip_free(obj->buffer);
677 	if (obj->boundary != NULL) belle_sip_free(obj->boundary);
678 }
679 
belle_sip_multipart_body_handler_clone(belle_sip_multipart_body_handler_t * obj)680 static void belle_sip_multipart_body_handler_clone(belle_sip_multipart_body_handler_t *obj){
681 	obj->parts=belle_sip_list_copy_with_data(obj->parts,(void *(*)(void*))belle_sip_object_clone_and_ref);
682 }
683 
belle_sip_multipart_body_handler_begin_recv_transfer(belle_sip_body_handler_t * obj)684 static void belle_sip_multipart_body_handler_begin_recv_transfer(belle_sip_body_handler_t *obj) {
685 	const belle_sip_list_t *it;
686 	belle_sip_multipart_body_handler_t *obj_multipart = (belle_sip_multipart_body_handler_t *)obj;
687 	for (it = obj_multipart->parts; it != NULL; it = it->next) {
688 		belle_sip_body_handler_t *bh = BELLE_SIP_BODY_HANDLER(it->data);
689 		belle_sip_body_handler_begin_recv_transfer(bh);
690 	}
691 	obj_multipart->transfer_current_part = obj_multipart->parts;
692 }
693 
belle_sip_multipart_body_handler_begin_send_transfer(belle_sip_body_handler_t * obj)694 static void belle_sip_multipart_body_handler_begin_send_transfer(belle_sip_body_handler_t *obj) {
695 	const belle_sip_list_t *it;
696 	belle_sip_multipart_body_handler_t *obj_multipart = (belle_sip_multipart_body_handler_t *)obj;
697 	for (it = obj_multipart->parts; it != NULL; it = it->next) {
698 		belle_sip_body_handler_t *bh = BELLE_SIP_BODY_HANDLER(it->data);
699 		belle_sip_body_handler_begin_send_transfer(bh);
700 	}
701 	obj_multipart->transfer_current_part = obj_multipart->parts;
702 }
703 
belle_sip_multipart_body_handler_end_transfer(belle_sip_body_handler_t * obj)704 static void belle_sip_multipart_body_handler_end_transfer(belle_sip_body_handler_t *obj) {
705 	const belle_sip_list_t *it;
706 	belle_sip_multipart_body_handler_t *obj_multipart = (belle_sip_multipart_body_handler_t *)obj;
707 	for (it = obj_multipart->parts; it != NULL; it = it->next) {
708 		belle_sip_body_handler_t *bh = BELLE_SIP_BODY_HANDLER(it->data);
709 		belle_sip_body_handler_end_transfer(bh);
710 	}
711 	obj_multipart->transfer_current_part = NULL;
712 }
713 
belle_sip_multipart_body_handler_recv_chunk(belle_sip_body_handler_t * obj,belle_sip_message_t * msg,off_t offset,uint8_t * buffer,size_t size)714 static void belle_sip_multipart_body_handler_recv_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, off_t offset,
715 							uint8_t *buffer, size_t size){
716 	/* Store the whole buffer, the parts will be split when belle_sip_multipart_body_handler_progress_cb() is called with transfered size equal to expected size. */
717 	belle_sip_multipart_body_handler_t *obj_multipart = (belle_sip_multipart_body_handler_t *)obj;
718 	obj_multipart->buffer = belle_sip_realloc(obj_multipart->buffer,offset + size + 1);
719 	memcpy(obj_multipart->buffer + offset, buffer, size);
720 	obj_multipart->buffer[offset + size] = '\0';
721 }
722 
belle_sip_multipart_body_handler_send_chunk(belle_sip_body_handler_t * obj,belle_sip_message_t * msg,off_t offset,uint8_t * buffer,size_t * size)723 static int belle_sip_multipart_body_handler_send_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, off_t offset,
724 							uint8_t *buffer, size_t *size){
725 	belle_sip_multipart_body_handler_t *obj_multipart=(belle_sip_multipart_body_handler_t*)obj;
726 
727 	if (obj_multipart->transfer_current_part->data) { /* we have a part, get its content from handler */
728 		int retval = BELLE_SIP_STOP;
729 		size_t offsetSize = 0; /* used to store size of data added by this function and not given by the body handler of current part */
730 		size_t boundary_len = strlen(obj_multipart->boundary);
731 		belle_sip_body_handler_t *current_part = (belle_sip_body_handler_t *)obj_multipart->transfer_current_part->data;
732 		*size -= strlen(obj_multipart->boundary) + 8; /* just in case it will be the end of the message, ask for less characters than possible in order to be able to add the multipart message termination. 8 is for "\r\n--" and "--\r\n" */
733 
734 		if (current_part->transfered_size == 0) { /* Nothing transfered yet on this part, include a separator and the header if exists */
735 			size_t headersSize = 0;
736 			offsetSize = strlen(obj_multipart->boundary) + 4; /* 4 is for "--" and "\r\n" */
737 
738 			if (current_part->headerStringBuffer != NULL) {
739 				headersSize = strlen(current_part->headerStringBuffer);
740 			}
741 
742 			/* check if buffer is large enough to get the whole header + separtor and at least a byte of data */
743 			if (*size < headersSize+offsetSize+1) {
744 				return BELLE_SIP_BUFFER_OVERFLOW;
745 			}
746 
747 			/* insert separator */
748 			memcpy(buffer, "--", 2);
749 			memcpy(buffer + 2, obj_multipart->boundary, boundary_len);
750 			memcpy(buffer + 2 + boundary_len, "\r\n", 2);
751 			offsetSize = boundary_len + 4;
752 			/* insert part header */
753 			if (headersSize!=0) {
754 				memcpy(buffer+offsetSize, current_part->headerStringBuffer, headersSize);
755 				offsetSize += headersSize;
756 			}
757 
758 			*size -=offsetSize; /* decrease data length requested to the current part handler */
759 		}
760 
761 		retval = belle_sip_body_handler_send_chunk(current_part, msg, buffer+offsetSize, size); /* add offsetSize to the buffer address in order to point at the begining of free space (after header if included) */
762 		*size +=offsetSize; /* restore total of data given including potential separator and header */
763 
764 
765 		if (retval == BELLE_SIP_CONTINUE) {
766 			return BELLE_SIP_CONTINUE; /* there is still data to be sent, continue */
767 		} else { /* this part has reach the end, pass to next one if there is one */
768 			if (obj_multipart->transfer_current_part->next!=NULL) { /* there is an other part to be sent */
769 				obj_multipart->transfer_current_part = belle_sip_list_next(obj_multipart->transfer_current_part);
770 				return BELLE_SIP_CONTINUE;
771 			} else { /* there is nothing else, close the message and return STOP */
772 				size_t boundary_len = strlen(obj_multipart->boundary);
773 				memcpy(buffer + *size, "\r\n--", 4);
774 				memcpy(buffer + *size + 4, obj_multipart->boundary, boundary_len);
775 				memcpy(buffer + *size + 4 + boundary_len, "--\r\n", 4);
776 				*size+=boundary_len + 8;
777 				return BELLE_SIP_STOP;
778 			}
779 		}
780 	}
781 	return BELLE_SIP_STOP;
782 }
783 
784 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_multipart_body_handler_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_multipart_body_handler_t)785 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_multipart_body_handler_t)
786 	{
787 		{
788 			BELLE_SIP_VPTR_INIT(belle_sip_multipart_body_handler_t,belle_sip_body_handler_t,TRUE),
789 			(belle_sip_object_destroy_t) belle_sip_multipart_body_handler_destroy,
790 			(belle_sip_object_clone_t)belle_sip_multipart_body_handler_clone,
791 			NULL,
792 			BELLE_SIP_DEFAULT_BUFSIZE_HINT
793 		},
794 		belle_sip_multipart_body_handler_begin_recv_transfer,
795 		belle_sip_multipart_body_handler_begin_send_transfer,
796 		belle_sip_multipart_body_handler_end_transfer,
797 		belle_sip_multipart_body_handler_recv_chunk,
798 		belle_sip_multipart_body_handler_send_chunk
799 	}
800 BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
801 
belle_sip_multipart_body_handler_set_boundary(belle_sip_multipart_body_handler_t * obj,const char * boundary)802 static void belle_sip_multipart_body_handler_set_boundary(belle_sip_multipart_body_handler_t *obj, const char *boundary) {
803 	if (obj->boundary != NULL) {
804 		belle_sip_free(obj->boundary);
805 	}
806 	if (boundary != NULL) {
807 		obj->boundary = belle_sip_strdup(boundary);
808 	} else {
809 		obj->boundary = belle_sip_strdup(BELLESIP_MULTIPART_BOUNDARY);
810 	}
811 }
812 
belle_sip_multipart_body_handler_new(belle_sip_body_handler_progress_callback_t progress_cb,void * data,belle_sip_body_handler_t * first_part,const char * boundary)813 belle_sip_multipart_body_handler_t *belle_sip_multipart_body_handler_new(belle_sip_body_handler_progress_callback_t progress_cb, void *data,
814 									 belle_sip_body_handler_t *first_part, const char *boundary){
815 	belle_sip_multipart_body_handler_t *obj=belle_sip_object_new(belle_sip_multipart_body_handler_t);
816 	belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,progress_cb,data);
817 	belle_sip_multipart_body_handler_set_boundary(obj, boundary);
818 	obj->base.expected_size = strlen(obj->boundary) + 8; /* body's length will be part length(including boundary) + multipart end. 8 is for "\r\n--" and "--\r\n" */
819 	if (first_part) belle_sip_multipart_body_handler_add_part(obj,first_part);
820 	return obj;
821 }
822 
belle_sip_multipart_body_handler_new_from_buffer(void * buffer,size_t bufsize,const char * boundary)823 belle_sip_multipart_body_handler_t *belle_sip_multipart_body_handler_new_from_buffer(void *buffer, size_t bufsize, const char *boundary) {
824 	belle_sip_multipart_body_handler_t *obj_multipart = belle_sip_object_new(belle_sip_multipart_body_handler_t);
825 	belle_sip_body_handler_t *obj = (belle_sip_body_handler_t *)obj_multipart;
826 	belle_sip_body_handler_init((belle_sip_body_handler_t *)obj, belle_sip_multipart_body_handler_progress_cb, NULL);
827 	belle_sip_multipart_body_handler_set_boundary(obj_multipart, boundary);
828 	obj_multipart->base.expected_size = bufsize;
829 	belle_sip_body_handler_begin_recv_transfer(obj);
830 	belle_sip_body_handler_recv_chunk(obj, NULL, (uint8_t *)buffer, bufsize);
831 	belle_sip_body_handler_end_transfer(obj);
832 	return obj_multipart;
833 }
834 
835 #define DEFAULT_HEADER_STRING_SIZE 512
belle_sip_multipart_body_handler_add_part(belle_sip_multipart_body_handler_t * obj,belle_sip_body_handler_t * part)836 void belle_sip_multipart_body_handler_add_part(belle_sip_multipart_body_handler_t *obj, belle_sip_body_handler_t *part){
837 	obj->base.expected_size+=part->expected_size+strlen(obj->boundary) + 4; /* add the separator length to the body length as each part start with a separator. 4 is for "--" and "\r\n" */
838 	if (part->headers != NULL) { /* there is a declared header for this part, add its length to the expected total length */
839 		size_t headerStringBufferSize = DEFAULT_HEADER_STRING_SIZE;
840 		size_t offset = 0;
841 		belle_sip_list_t *headerList = part->headers;
842 		part->headerStringBuffer = (char *)belle_sip_malloc(DEFAULT_HEADER_STRING_SIZE);
843 
844 		while (headerList != NULL) {
845 			size_t offsetBackup=offset; /* we must backup the offset as it will be messed up by the marshal function in case of failure */
846 			belle_sip_error_code returnCode = belle_sip_object_marshal(headerList->data, part->headerStringBuffer, headerStringBufferSize-5, &offset); /* -5 to leave room for carriage returns */
847 			if (returnCode == BELLE_SIP_BUFFER_OVERFLOW) { /* increase buffer size */
848 				offset=offsetBackup; /* restore the offset, no data were written to the buffer */
849 				headerStringBufferSize+=DEFAULT_HEADER_STRING_SIZE;
850 				part->headerStringBuffer = (char *)belle_sip_realloc(part->headerStringBuffer, headerStringBufferSize);
851 			} else if (returnCode == BELLE_SIP_OK) { /* add the carriage return chars */
852 				part->headerStringBuffer[offset++]='\r';
853 				part->headerStringBuffer[offset++]='\n';
854 				headerList = belle_sip_list_next(headerList);
855 			}
856 		}
857 		part->headerStringBuffer[offset++]='\r';
858 		part->headerStringBuffer[offset++]='\n';
859 		obj->base.expected_size += offset;
860 		part->headerStringBuffer[offset++]='\0'; /* null terminate the buffer in order to be able to get it length later using strlen */
861 	}
862 	obj->parts=belle_sip_list_append(obj->parts,belle_sip_object_ref(part));
863 }
belle_sip_multipart_body_handler_get_parts(const belle_sip_multipart_body_handler_t * obj)864 const belle_sip_list_t* belle_sip_multipart_body_handler_get_parts(const belle_sip_multipart_body_handler_t *obj) {
865 	return obj->parts;
866 }
867 
belle_sip_multipart_body_handler_progress_cb(belle_sip_body_handler_t * obj,belle_sip_message_t * msg,void * user_data,size_t transfered,size_t expected_total)868 void belle_sip_multipart_body_handler_progress_cb(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, void *user_data, size_t transfered, size_t expected_total) {
869 	if (transfered == expected_total) {
870 		/* The full multipart body has been received, we can now parse it and split the different parts,
871 		 * creating a belle_sip_memory_body_handler for each part and adding them to the belle_sip_multipart_body_handler
872 		 * parts list. */
873 		belle_sip_multipart_body_handler_t *obj_multipart = (belle_sip_multipart_body_handler_t *)obj;
874 		belle_sip_memory_body_handler_t *memorypart;
875 		belle_sip_header_t *header;
876 		uint8_t *end_part_cursor;
877 		uint8_t *end_headers_cursor;
878 		uint8_t *end_header_cursor;
879 		uint8_t *cursor = obj_multipart->buffer;
880 		char *boundary = belle_sip_strdup_printf("--%s", obj_multipart->boundary);
881 		if (strncmp((char *)cursor, boundary, strlen(boundary))) {
882 			belle_sip_warning("belle_sip_multipart_body_handler [%p]: body not starting by specified boundary '%s'", obj_multipart, obj_multipart->boundary);
883 			belle_sip_free(boundary);
884 			return;
885 		}
886 		cursor += strlen(boundary);
887 		do {
888 			if (strncmp((char *)cursor, "\r\n", 2)) {
889 				belle_sip_warning("belle_sip_multipart_body_handler [%p]: no new-line after boundary", obj_multipart);
890 				return;
891 			}
892 			cursor += 2;
893 			end_part_cursor = (uint8_t *)strstr((char *)cursor, boundary);
894 			if (end_part_cursor == NULL) {
895 				belle_sip_warning("belle_sip_multipart_body_handler [%p]: cannot find next boundary", obj_multipart);
896 				return;
897 			} else {
898 				*end_part_cursor = 0;
899 				end_headers_cursor = (uint8_t *)strstr((char *)cursor, "\r\n\r\n");
900 				if (end_headers_cursor == NULL) {
901 					memorypart = belle_sip_memory_body_handler_new_copy_from_buffer(cursor, strlen((char *)cursor), NULL, NULL);
902 				} else {
903 					uint8_t *begin_body_cursor = end_headers_cursor + 4;
904 					memorypart = belle_sip_memory_body_handler_new_copy_from_buffer(begin_body_cursor, strlen((char *)begin_body_cursor), NULL, NULL);
905 					do {
906 						end_header_cursor = (uint8_t *)strstr((char *)cursor, "\r\n");
907 						*end_header_cursor = 0;
908 						header = belle_sip_header_parse((char *)cursor);
909 						if (header != NULL) {
910 							belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(memorypart), header);
911 						}
912 						cursor = end_header_cursor + 2;
913 					} while (end_header_cursor != end_headers_cursor);
914 				}
915 				belle_sip_multipart_body_handler_add_part(obj_multipart, BELLE_SIP_BODY_HANDLER(memorypart));
916 				cursor = end_part_cursor + strlen(boundary);
917 			}
918 		} while (strcmp((char *)cursor, "--\r\n"));
919 		belle_sip_free(boundary);
920 	}
921 }
922