//================================================================================================= // HTTP action object definition // static tsk_object_t* thttp_action_ctor(tsk_object_t * self, va_list * app) { thttp_action_t *action = self; if(action){ va_list* app_2; thttp_action_param_type_t curr; action->type = va_arg(*app, thttp_action_type_t); action->url = tsk_strdup(va_arg(*app, const char*)); action->method = tsk_strdup(va_arg(*app, const char*)); app_2 = va_arg(*app, va_list*); action->options = tsk_list_create(); action->headers = tsk_list_create(); if(!app_2){ /* XCAP stack will pass null va_list */ goto bail; } while((curr = va_arg(*app_2, thttp_action_param_type_t)) != thttp_aptype_null){ switch(curr){ case thttp_aptype_option: { /* (thttp_action_option_t)ID_ENUM, (const char*)VALUE_STR */ thttp_action_option_t id = va_arg(*app_2, thttp_action_option_t); const char* value = va_arg(*app_2, const char *); tsk_options_add_option(&action->options, id, value); break; } case thttp_aptype_header: { /* (const char*)NAME_STR, (const char*)VALUE_STR */ const char* name = va_arg(*app_2, const char *); const char* value = va_arg(*app_2, const char *); tsk_params_add_param(&action->headers, name, value); break; } case thttp_aptype_payload: { /* (const void*)PAY_PTR, (tsk_size_t)PAY_SIZE */ const void* payload = va_arg(*app_2, const void *); tsk_size_t size = va_arg(*app_2, tsk_size_t); if(payload && size){ TSK_OBJECT_SAFE_FREE(action->payload); action->payload = tsk_buffer_create(payload, size); } break; } default: { /* va_list will be unsafe ==> exit */ TSK_DEBUG_ERROR("NOT SUPPORTED."); goto bail; } } /* switch */ } /* while */ } bail: return self; }
static tsk_object_t* tdav_video_jb_ctor(tsk_object_t * self, va_list * app) { tdav_video_jb_t *jb = self; if(jb){ if(!(jb->frames = tsk_list_create())){ TSK_DEBUG_ERROR("Failed to create list"); return tsk_null; } if(!(jb->decode_thread_cond = tsk_condwait_create())){ TSK_DEBUG_ERROR("Failed to create condition var"); return tsk_null; } jb->cb_data_fdd.type = tdav_video_jb_cb_data_type_fdd; jb->cb_data_rtp.type = tdav_video_jb_cb_data_type_rtp; jb->decode_last_seq_num_with_mark = -1; jb->fps = TDAV_VIDEO_JB_FPS_MAX; jb->rate = TDAV_VIDEO_JB_RATE; jb->latency_min = TDAV_VIDEO_JB_LATENCY_MIN; jb->latency_max = TDAV_VIDEO_JB_LATENCY_MAX; tsk_safeobj_init(jb); } return self; }
static const tsdp_header_M_t* tmedia_session_ghost_get_lo(tmedia_session_t* self) { tmedia_session_ghost_t* ghost; ghost = (tmedia_session_ghost_t*)self; if(self->M.lo){ return self->M.lo; } else if(!(self->M.lo = tsdp_header_M_create(ghost->media, 0, ghost->proto ? ghost->proto: "RTP/AVP"))){ TSK_DEBUG_ERROR("Failed to create lo"); return tsk_null; } // add format if(!tsk_strnullORempty(ghost->first_format)){ tsk_string_t* fmt = tsk_string_create(ghost->first_format); if(!self->M.lo->FMTs){ self->M.lo->FMTs = tsk_list_create(); } tsk_list_push_back_data(self->M.lo->FMTs, (void**)&fmt); TSK_OBJECT_SAFE_FREE(fmt); } return self->M.lo; }
/** Initialze the list of auids with default values from __txcap_auids * auids must be null; */ int txcap_auids_init(txcap_auids_L_t** auids) { size_t i; size_t count; if(!auids){ TSK_DEBUG_ERROR("invalid parameter."); return -1; } else if(*auids){ TSK_DEBUG_WARN("auids already initialized."); } else{ *auids = tsk_list_create(); } count = sizeof(__txcap_auids)/sizeof(auid_t); for(i = 0; i<count; i++){ txcap_auid_t* auid = txcap_auid_create(__txcap_auids[i].type, __txcap_auids[i].id, __txcap_auids[i].mime_type, __txcap_auids[i].ns, __txcap_auids[i].document_name, __txcap_auids[i].global); tsk_list_push_back_data(*auids, (void**)&auid); } return 0; }
//======================================================== // XCAP stack object definition // static tsk_object_t* _txcap_stack_create(tsk_object_t * self, va_list * app) { txcap_stack_t *stack = self; if(stack){ thttp_stack_callback_f callback; tsk_safeobj_init(stack); callback = va_arg(*app, thttp_stack_callback_f); stack->xui = tsk_strdup( va_arg(*app, const char*) ); stack->password = tsk_strdup( va_arg(*app, const char*) ); stack->xcap_root = tsk_strdup( va_arg(*app, const char*) ); /* HTTP/HTTPS stack and session */ stack->http_stack = thttp_stack_create(callback, THTTP_STACK_SET_NULL()); stack->http_session = thttp_session_create(stack->http_stack , THTTP_SESSION_SET_NULL()); /* Options */ stack->options = tsk_list_create(); /* AUIDs */ txcap_auids_init(&stack->auids); } return self; }
static tsk_object_t* tnet_ice_candidate_ctor(tsk_object_t * self, va_list * app) { tnet_ice_candidate_t *candidate = self; if(candidate){ candidate->extension_att_list = tsk_list_create(); } return self; }
//================================================================================================= // SIP action object definition // static tsk_object_t* tsip_action_ctor(tsk_object_t * self, va_list * app) { tsip_action_t *action = self; if(action){ action->headers = tsk_list_create(); action->media.type = tmedia_none; } return self; }
// // [[DHCP OPTION - RFC 2132 3.8. Domain Name Server Option]] object definition // static tsk_object_t* tnet_dhcp_option_dns_ctor(tsk_object_t * self, va_list * app) { tnet_dhcp_option_dns_t *option = self; if(option){ const void* payload = va_arg(*app, const void*); tsk_size_t payload_size = va_arg(*app, tsk_size_t); const uint8_t* payloadPtr = (const uint8_t*)payload; const uint8_t* payloadEnd = (payloadPtr + payload_size); /* init base */ tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_Domain_Server); option->servers = tsk_list_create(); if(payload_size<4 || payload_size%4){ TSK_DEBUG_ERROR("DHCP - The minimum length for this option is 4 octets, and the length MUST always be a multiple of 4."); } else{ tsk_size_t i; char* ip4 = 0; uint32_t address; tsk_string_t* addrstring; for(i=0; i<payload_size && (payloadPtr< payloadEnd); i+=4){ /* Code Len Address 1 Address 2 +-----+-----+-----+-----+-----+-----+-----+-----+-- | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... +-----+-----+-----+-----+-----+-----+-----+-----+-- */ address = (uint32_t)tnet_htonl_2(payloadPtr); tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); addrstring = tsk_string_create(ip4); tsk_list_push_back_data(option->servers, (void*)&addrstring); TSK_FREE(ip4); payloadPtr+= 4; } } } return self; }
static tsk_object_t* tdav_video_jb_ctor(tsk_object_t * self, va_list * app) { tdav_video_jb_t *jb = self; if(jb) { if(!(jb->frames = tsk_list_create())) { TSK_DEBUG_ERROR("Failed to create list"); return tsk_null; } if(!(jb->decode_thread_cond = tsk_condwait_create())) { TSK_DEBUG_ERROR("Failed to create condition var"); return tsk_null; } jb->cb_data_fdd.type = tdav_video_jb_cb_data_type_fdd; jb->cb_data_rtp.type = tdav_video_jb_cb_data_type_rtp; tsk_safeobj_init(jb); } return self; }
/**@ingroup tsk_params_group * Adds a parameter to the list of parameters. If the parameter already exist(case-insensitive), then it's value will be updated. * @param self The destination list. * @param name The name of the parameter to add. * @param value The value of the parameter to add. * @retval Zero if succeed and -1 otherwise. */ int tsk_params_add_param(tsk_params_L_t **self, const char* name, const char* value) { tsk_param_t *param; if(!self || !name) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(!*self){ *self = tsk_list_create(); } if((param = (tsk_param_t*)tsk_params_get_param_by_name(*self, name))){ tsk_strupdate(¶m->value, value); /* Already exist ==> update the value. */ } else{ param = tsk_param_create(name, value); tsk_list_push_back_data(*self, (void**)¶m); } return 0; }
/**@ingroup tnet_nat_group * Creates new NAT context. */ struct tnet_nat_ctx_s* tnet_nat_context_create(tnet_socket_type_t socket_type, const char* pc_username, const char* pc_password) { extern const tsk_object_def_t *tnet_nat_context_def_t; struct tnet_nat_ctx_s* p_ctx; if (!(p_ctx = tsk_object_new(tnet_nat_context_def_t)) || !(p_ctx->stun_bindings = tsk_list_create())) { TSK_OBJECT_SAFE_FREE(p_ctx); TSK_DEBUG_ERROR("Failed to create NAT context"); return tsk_null; } p_ctx->socket_type = socket_type; p_ctx->username = tsk_strdup(pc_username); p_ctx->password = tsk_strdup(pc_password); p_ctx->server_port = kStunPortDefaultTcpUdp; /* 7.2.1. Sending over UDP In fixed-line access links, a value of 500 ms is RECOMMENDED. */ p_ctx->RTO = kStunRTO; /* 7.2.1. Sending over UDP Rc SHOULD be configurable and SHOULD have a default of 7. */ p_ctx->Rc = kStunRC; return p_ctx; }
// // [[DHCP SIP4]] object definition // static tsk_object_t* tnet_dhcp_option_sip_ctor(tsk_object_t * self, va_list * app) { tnet_dhcp_option_sip_t *option = self; if(option){ const void* payload = va_arg(*app, const void*); tsk_size_t payload_size = va_arg(*app, tsk_size_t); const uint8_t* payloadPtr = (const uint8_t*)payload; const uint8_t* payloadEnd = (payloadPtr + payload_size); /* init base */ tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_SIP_Servers_DHCP_Option); option->servers = tsk_list_create(); /* Set values as per RFC 3361. */ if(*payloadPtr == 0){ /* enc=0 */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ |120|27 | 0 | 7 |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'c'|'o'|'m'| 0 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+ | 7 |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'n'|'e'|'t'| 0 | +---+---+--- +---+---+---+---+---+---+---+---+---+---+ */ tsk_size_t offset = 1; char* server = 0; payloadPtr++; while((payloadPtr < payloadEnd) && !tnet_dns_rr_qname_deserialize(payload, &server, &offset)){ tsk_string_t* string = tsk_string_create(server); tsk_list_push_back_data(option->servers, (void*)&string); TSK_FREE(server); payloadPtr += offset; } } else{ /* Code Len enc Address 1 Address 2 +-----+-----+-----+-----+-----+-----+-----+-----+-- | 120 | n | 1 | a1 | a2 | a3 | a4 | a1 | ... +-----+-----+-----+-----+-----+-----+-----+-----+-- */ uint32_t address; tsk_string_t* addrstring; char* ip4 = 0; while(payloadPtr < payloadEnd){ ++payloadPtr; address = tnet_htonl_2(payloadPtr); tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); addrstring = tsk_string_create(ip4); tsk_list_push_back_data(option->servers, (void*)&addrstring); TSK_FREE(ip4); payloadPtr+= 4; } } } return self; }
tdav_audiounit_handle_t* tdav_audiounit_handle_create(uint64_t session_id) { tdav_audiounit_instance_t* inst = tsk_null; // create audio unit component if(!__audioSystem){ AudioComponentDescription audioDescription; audioDescription.componentType = kAudioUnitType_Output; audioDescription.componentSubType = kDoubangoAudioUnitSubType; audioDescription.componentManufacturer = kAudioUnitManufacturer_Apple; audioDescription.componentFlags = 0; audioDescription.componentFlagsMask = 0; if((__audioSystem = AudioComponentFindNext(NULL, &audioDescription))){ // leave blank } else { TSK_DEBUG_ERROR("Failed to find new audio component"); goto done; } } // create list used to hold instances if(!__audioUnitInstances && !(__audioUnitInstances = tsk_list_create())){ TSK_DEBUG_ERROR("Failed to create new list"); goto done; } //= lock the list tsk_list_lock(__audioUnitInstances); // For iOS we are using full-duplex AudioUnit and to keep it unique for both // the consumer and producer we use the session id. #if TARGET_OS_IPHONE // find the instance from the list const tsk_list_item_t* item; tsk_list_foreach(item,__audioUnitInstances){ if(((tdav_audiounit_instance_t*)item->data)->session_id == session_id){ inst = tsk_object_ref(item->data); goto done; } } #endif // create instance object and put it into the list if((inst = tsk_object_new(tdav_audiounit_instance_def_t))){ OSStatus status = noErr; tdav_audiounit_instance_t* _inst; // create new instance if((status= AudioComponentInstanceNew(__audioSystem, &inst->audioUnit)) != noErr){ TSK_DEBUG_ERROR("AudioComponentInstanceNew() failed with status=%ld", (signed long)status); TSK_OBJECT_SAFE_FREE(inst); goto done; } _inst = inst, _inst->session_id = session_id; tsk_list_push_back_data(__audioUnitInstances, (void**)&_inst); } done: //= unlock the list tsk_list_unlock(__audioUnitInstances); return (tdav_audiounit_handle_t*)inst; }
/* context is only used if list is NULL, else list is used. */ uint8_t tsk_list_add(void *context, TSK_LIST ** list, uint64_t key) { TSK_LIST *tmp; /* If the head is NULL, then create an entry */ if (*list == NULL) { TSK_LIST *ent; if (tsk_verbose) fprintf(stderr, "entry %" PRIu64 " is first on list\n", key); if ((ent = tsk_list_create(context, key)) == NULL) return 1; *list = ent; return 0; } /* If the new key is larger than the head, make it the head */ if (key > (*list)->key) { if (tsk_verbose) fprintf(stderr, "entry %" PRIu64 " added to head before %" PRIu64 "\n", key, (*list)->key); // If we can, update the length of the existing list entry if (key == (*list)->key + 1) { (*list)->key++; (*list)->len++; } else { TSK_LIST *ent; if ((ent = tsk_list_create(*list, key)) == NULL) return 1; ent->next = *list; *list = ent; } return 0; } // get rid of duplicates else if (key == (*list)->key) { return 0; } /* At the start of this loop each time, we know that the key to add * is smaller than the entry being considered (tmp) */ tmp = *list; while (tmp != NULL) { /* First check if this is a duplicate and contained in tmp */ if (key > (tmp->key - tmp->len)) { return 0; } /* Can we append it to the end of tmp? */ else if (key == (tmp->key - tmp->len)) { // do a sanity check on the next entry if ((tmp->next) && (tmp->next->key == key)) { // @@@ We could fix this situation and remove the next entry... return 0; } tmp->len++; return 0; } /* The key is less than the current bucket and can't be added to it. * check if we are at the end of the list yet */ else if (tmp->next == NULL) { TSK_LIST *ent; if (tsk_verbose) fprintf(stderr, "entry %" PRIu64 " added to tail\n", key); if ((ent = tsk_list_create(*list, key)) == NULL) return 1; tmp->next = ent; return 0; } // can we prepend it to the next bucket? else if (key == tmp->next->key + 1) { tmp->next->key++; tmp->next->len++; } // do we need a new bucket in between? else if (key > tmp->next->key) { TSK_LIST *ent; if (tsk_verbose) fprintf(stderr, "entry %" PRIu64 " added before %" PRIu64 "\n", key, tmp->next->key); if ((ent = tsk_list_create(*list, key)) == NULL) return 1; ent->next = tmp->next; tmp->next = ent; return 0; } else if (key == tmp->next->key) { return 0; } tmp = tmp->next; } return 0; }