toxcore/toxmsi/toxmsi_header.c
2013-10-13 16:16:47 +02:00

182 lines
4.6 KiB
C

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "toxmsi_message.h"
#include <string.h>
#include "../toxrtp/toxrtp_helper.h"
#include <assert.h>
#include "../toxcore/Lossless_UDP.h"
#define ALLOC_ADD_DATA(_tempval, _hdrlist, _fielddef, _msgvar, _alloctype) \
_tempval = msi_search_field(_hdrlist, (const uint8_t*)_fielddef); \
if ( _tempval ){ \
_msgvar = calloc(sizeof(_alloctype), 1); \
assert(_msgvar); \
_msgvar->_header_value = _tempval; \
}
uint8_t* msi_search_field ( msi_header_t* _list, const uint8_t* _field )
{
assert(_list);
assert(_field);
msi_header_t* _iterator;
for ( _iterator = _list;
_iterator && strcmp((const char*)_iterator->_header_field, (const char*)_field) != 0;
_iterator = _iterator->next );
if ( _iterator ){
return t_strallcpy(_iterator->_header_value);
} else return NULL;
}
int msi_parse_headers ( msi_msg_t* _msg )
{
assert(_msg);
if ( !_msg->_headers )
return FAILURE;
msi_header_t* _list = _msg->_headers;
uint8_t* _field_current;
ALLOC_ADD_DATA(_field_current, _list, _CALL_ID_FIELD, _msg->_call_id, msi_header_call_id_t)
ALLOC_ADD_DATA(_field_current, _list, _VERSION_FIELD, _msg->_version, msi_header_version_t)
ALLOC_ADD_DATA(_field_current, _list, _REQUEST_FIELD, _msg->_request, msi_header_request_t)
ALLOC_ADD_DATA(_field_current, _list, _RESPONSE_FIELD, _msg->_response, msi_header_response_t)
ALLOC_ADD_DATA(_field_current, _list, _FRIENDID_FIELD, _msg->_friend_id, msi_header_friendid_t)
ALLOC_ADD_DATA(_field_current, _list, _CALLTYPE_FIELD, _msg->_call_type, msi_header_call_type_t)
ALLOC_ADD_DATA(_field_current, _list, _USERAGENT_FIELD, _msg->_user_agent, msi_header_user_agent_t)
ALLOC_ADD_DATA(_field_current, _list, _INFO_FIELD, _msg->_info, msi_header_info_t)
ALLOC_ADD_DATA(_field_current, _list, _REASON_FIELD, _msg->_reason, msi_header_reason_t)
/* Since we don't need the raw header anymore remove it */
msi_header_t* _temp;
while ( _list ){
_temp = _list->next;
free(_list->_header_field);
free(_list->_header_value);
free(_list);
_list = _temp;
}
_msg->_headers = NULL;
return SUCCESS;
}
/*
* If you find better way of parsing values let me know
*/
msi_header_t* msi_add_new_header ( uint8_t* _value )
{
if ( !_value )
return NULL;
size_t _length = t_memlen(_value);
if ( !_length ) {
return NULL;
}
size_t _first_len = t_strfind(_value, (const uint8_t*)" ");
if ( !_first_len ){
return NULL;
}
size_t _second_len = (_length - _first_len);
if ( !_second_len ){
return NULL;
}
uint8_t* _identifier = calloc(sizeof (uint8_t), (_first_len + 1) );
uint8_t* _data = calloc(sizeof (uint8_t), (_second_len + 1) );
assert(_identifier);
assert(_data);
uint8_t* _p_it = _value;
size_t _num_it;
for ( _num_it = 0; *_p_it != ' '; _num_it++ ){
_identifier[_num_it] = *_p_it;
++_p_it;
}
_identifier[_num_it] = '\0';
++_p_it;
for ( _num_it = 0; *_p_it != '\r'; _num_it++ ){
_data[_num_it] = *_p_it;
++_p_it;
}
_data[_num_it] = '\r';
_data[_num_it + 1] = '\0';
msi_header_t* _retu = calloc(sizeof(msi_header_t), 1);
assert(_retu);
_retu->_header_field = _identifier;
_retu->_header_value = _data;
_retu->next = NULL;
return _retu;
}
msi_header_t* msi_parse_raw_data ( const uint8_t* _data )
{
assert(_data);
uint8_t* _header_string;
_header_string = (uint8_t*) strtok ((char*)_data, _RAW_TERMINATOR);
msi_header_t* _head = msi_add_new_header(_header_string);
msi_header_t* _it = _head;
while ( _header_string && _it ){
_header_string = (uint8_t*) strtok (NULL, _RAW_TERMINATOR);
_it->next = msi_add_new_header(_header_string);
if ( _it->next ){
_it = _it->next;
}
}
/* Iterate through list and remove all fault headers if any */
msi_header_t* _tmp = _it;
for ( _it = _head; _it; _it = _it->next ){
if ( !_it->_header_value || !_it->_header_field ) {
_tmp ->next = _it->next;
if ( _it->_header_field )
free(_it->_header_field);
if ( _it->_header_value )
free(_it->_header_value);
if ( _it == _head ){
_head = _head->next;
}
free(_it);
_it = _tmp;
} else
_tmp = _it;
}
return _head;
}