/**Executes the bytecode. */ static tsk_bool_t tcomp_udvm_runByteCode(tcomp_udvm_t *udvm) { uint16_t operand_1, operand_2, operand_3, operand_4, operand_5, operand_6, operand_7; tsk_bool_t excution_failed = tsk_false, end_message = tsk_false; if(!udvm->isOK) { TSK_DEBUG_ERROR("Cannot run()/execute() invalid bytecode"); return tsk_false; } // LOOP - EXCUTE all bytecode while( !excution_failed && !end_message ) { uint8_t udvm_instruction = * (TCOMP_UDVM_GET_BUFFER_AT(udvm->executionPointer)); udvm->last_memory_address_of_instruction = udvm->executionPointer; udvm->executionPointer++; /* Skip the 1-byte [INSTRUCTION]. */ switch(udvm_instruction) { case TCOMP_UDVM_INST__DECOMPRESSION_FAILURE: { TCOMP_UDVM_EXEC_INST__DECOMPRESSION_FAILURE(udvm); excution_failed = tsk_true; break; } case TCOMP_UDVM_INST__AND: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__AND(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__OR: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__OR(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__NOT: { operand_1 = tcomp_udvm_opget_reference_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__NOT(udvm, operand_1); break; } case TCOMP_UDVM_INST__LSHIFT: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__LSHIFT(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__RSHIFT: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__RSHIFT(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__ADD: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__ADD(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__SUBTRACT: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SUBTRACT(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__MULTIPLY: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__MULTIPLY(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__DIVIDE: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__DIVIDE(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__REMAINDER: { operand_1 = tcomp_udvm_opget_reference_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__REMAINDER(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__SORT_ASCENDING: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SORT_ASCENDING(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__SORT_DESCENDING: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SORT_DESCENDING(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__SHA_1: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SHA_1(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__LOAD: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__LOAD(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__MULTILOAD: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_literal_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__MULTILOAD(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__PUSH: { excution_failed = !TCOMP_UDVM_EXEC_INST__PUSH2(udvm); break; } case TCOMP_UDVM_INST__POP: { excution_failed = !TCOMP_UDVM_EXEC_INST__POP2(udvm); break; } case TCOMP_UDVM_INST__COPY: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__COPY(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__COPY_LITERAL: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_reference_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__COPY_LITERAL(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__COPY_OFFSET: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_reference_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__COPY_OFFSET(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__MEMSET: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__MEMSET(udvm, operand_1, operand_2, operand_3, operand_4); break; } case TCOMP_UDVM_INST__JUMP: { excution_failed = !TCOMP_UDVM_EXEC_INST__JUMP2(udvm); break; } case TCOMP_UDVM_INST__COMPARE: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); operand_4 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); operand_5 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); excution_failed = !TCOMP_UDVM_EXEC_INST__COMPARE(udvm, operand_1, operand_2, operand_3, operand_4, operand_5); break; } case TCOMP_UDVM_INST__CALL: { operand_1 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); excution_failed = !TCOMP_UDVM_EXEC_INST__CALL(udvm, operand_1); break; } case TCOMP_UDVM_INST__RETURN: { excution_failed = !TCOMP_UDVM_EXEC_INST__RETURN(udvm); break; } case TCOMP_UDVM_INST__SWITCH: { operand_1 = tcomp_udvm_opget_literal_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__SWITCH(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__CRC: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_reference_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__CRC(udvm, operand_1, operand_2, operand_3, operand_4); break; } case TCOMP_UDVM_INST__INPUT_BYTES: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); excution_failed = !TCOMP_UDVM_EXEC_INST__INPUT_BYTES(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__INPUT_BITS: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); excution_failed = !TCOMP_UDVM_EXEC_INST__INPUT_BITS(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__INPUT_HUFFMAN: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_address_param(udvm, udvm->last_memory_address_of_instruction); operand_3 = tcomp_udvm_opget_literal_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__INPUT_HUFFMAN(udvm, operand_1, operand_2, operand_3); break; } case TCOMP_UDVM_INST__STATE_ACCESS: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_multitype_param(udvm); operand_5 = tcomp_udvm_opget_multitype_param(udvm); operand_6 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__STATE_ACCESS(udvm, operand_1, operand_2, operand_3, operand_4, operand_5, operand_6); break; } case TCOMP_UDVM_INST__STATE_CREATE: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_multitype_param(udvm); operand_5 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__STATE_CREATE(udvm, operand_1, operand_2, operand_3, operand_4, operand_5); break; } case TCOMP_UDVM_INST__STATE_FREE: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__STATE_FREE(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__OUTPUT: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__OUTPUT(udvm, operand_1, operand_2); break; } case TCOMP_UDVM_INST__END_MESSAGE: { operand_1 = tcomp_udvm_opget_multitype_param(udvm); operand_2 = tcomp_udvm_opget_multitype_param(udvm); operand_3 = tcomp_udvm_opget_multitype_param(udvm); operand_4 = tcomp_udvm_opget_multitype_param(udvm); operand_5 = tcomp_udvm_opget_multitype_param(udvm); operand_6 = tcomp_udvm_opget_multitype_param(udvm); operand_7 = tcomp_udvm_opget_multitype_param(udvm); excution_failed = !TCOMP_UDVM_EXEC_INST__END_MESSAGE(udvm, operand_1, operand_2, operand_3, operand_4, operand_5, operand_6, operand_7); end_message = 1; break; } default: tcomp_udvm_createNackInfo2(udvm, NACK_INVALID_OPCODE); goto bail; } //TCOMP_UDVM_DEBUG_PRINT(200); } bail: udvm->lpResult->consumed_cycles = udvm->consumed_cycles; return (!excution_failed); }
int tipsec_run_command(TCHAR *args) { #define TIPSEC_PIPE_BUFFER 1024 DWORD bread=0,tid=0; int ret = -1; struct handleInfo hInfo; TCHAR _args[MAX_PATH]; HANDLE writePipe, readPipe, hThread; SECURITY_ATTRIBUTES secAttr = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; char buffer[TIPSEC_PIPE_BUFFER]; /* Create pipes */ if((ret = CreatePipe(&readPipe, &writePipe, &secAttr, 0)) == 0) { TSK_DEBUG_ERROR("CreatePipe failed with error code [%d].", GetLastError()); ret = -5; goto bail; } wsprintf(_args, TEXT("\"%s\" %s"), TEXT("ipsec6.exe"), args ); memset(buffer, 0, TIPSEC_PIPE_BUFFER); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = NULL; si.hStdOutput = writePipe; si.hStdError = NULL; /* Create process */ if (CreateProcess(NULL, _args, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi) == 0){ TSK_DEBUG_ERROR("CreateProcess failed with error code [%d].", GetLastError()); ret = -3; goto bail; } hInfo.process = pi.hProcess; hInfo.pipe = writePipe; /* Create thread */ if((hThread = CreateThread(NULL, 0, tipsec_waitForExit, &hInfo, 0, &tid)) == NULL) { TSK_DEBUG_ERROR("CreateThread failed with error code [%d].", GetLastError()); ret = -4; goto bail; } /* For debugging */ #if defined(DEBUG) || defined(_DEBUG) while (ReadFile(readPipe, buffer, TIPSEC_PIPE_BUFFER-2, &bread, NULL)) { if(bread > 0){ TSK_DEBUG_INFO("IPSEC6 ==> %s\n-------------\n", buffer); memset(buffer, 0, TIPSEC_PIPE_BUFFER); /* reset the buffer. */ } } #endif ret = 0; bail: return ret; }
/**@ingroup tmedia_codec_group * Initialize a Codec * @param self The codec to initialize. Could be any type of codec (e.g. @ref tmedia_codec_audio_t or @ref tmedia_codec_video_t). * @param type * @param name the name of the codec. e.g. "G.711u" or "G.711a" etc used in the sdp. * @param desc full description. * @param format the format. e.g. "0" for G.711.u or "8" for G.711a or "*" for MSRP. * @retval Zero if succeed and non-zero error code otherwise. */ int tmedia_codec_init(tmedia_codec_t* self, tmedia_type_t type, const char* name, const char* desc, const char* format) { if(!self || tsk_strnullORempty(name)) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } self->type = type; tsk_strupdate(&self->name, name); tsk_strupdate(&self->desc,desc); tsk_strupdate(&self->format, format); if(!self->bandwidth_max_upload) { self->bandwidth_max_upload = (type == tmedia_video ? tmedia_defaults_get_bandwidth_video_upload_max() : INT_MAX); // INT_MAX or <=0 means undefined } if(!self->bandwidth_max_download) { self->bandwidth_max_download = (type == tmedia_video ? tmedia_defaults_get_bandwidth_video_download_max() : INT_MAX); // INT_MAX or <=0 means undefined } if(!self->in.rate) { self->in.rate = self->plugin->rate; } if(!self->out.rate) { self->out.rate = self->plugin->rate; } if(type & tmedia_audio) { tmedia_codec_audio_t* audio = TMEDIA_CODEC_AUDIO(self); if(!audio->in.ptime) { audio->in.ptime = (self->plugin->audio.ptime ? self->plugin->audio.ptime : tmedia_defaults_get_audio_ptime()); } if(!audio->out.ptime) { audio->out.ptime = (self->plugin->audio.ptime ? self->plugin->audio.ptime : tmedia_defaults_get_audio_ptime()); } if(!audio->in.channels) { audio->in.channels = self->plugin->audio.channels; } if(!audio->out.channels) { audio->out.channels = self->plugin->audio.channels; } if(!audio->in.timestamp_multiplier) { audio->in.timestamp_multiplier = tmedia_codec_audio_get_timestamp_multiplier(self->id, self->in.rate); } if(!audio->out.timestamp_multiplier) { audio->out.timestamp_multiplier = tmedia_codec_audio_get_timestamp_multiplier(self->id, self->out.rate); } } // Video flipping: For backward compatibility we have to initialize the default values // according to the CFLAGS: 'FLIP_ENCODED_PICT' and 'FLIP_DECODED_PICT'. At any time you // can update thse values (e.g. when the device switch from landscape to portrait) using video_session->set(); else if(type & tmedia_video) { tmedia_codec_video_t* video = TMEDIA_CODEC_VIDEO(self); #if FLIP_ENCODED_PICT video->out.flip = tsk_true; #endif #if FLIP_DECODED_PICT video->in.flip = tsk_true; #endif if(!video->in.fps) { video->in.fps = self->plugin->video.fps ? self->plugin->video.fps : tmedia_defaults_get_video_fps(); } if(!video->out.fps) { video->out.fps = self->plugin->video.fps ? self->plugin->video.fps : tmedia_defaults_get_video_fps(); } if(video->in.chroma == tmedia_chroma_none) { video->in.chroma = tmedia_chroma_yuv420p; } if(video->out.chroma == tmedia_chroma_none) { video->out.chroma = tmedia_chroma_yuv420p; } if(0) { // @deprecated if(!video->in.width) { video->in.width = video->out.width = self->plugin->video.width; } if(!video->in.height) { video->in.height = video->out.height = self->plugin->video.height; } } else { int ret; unsigned width, height; video->pref_size = tmedia_defaults_get_pref_video_size(); if((ret = tmedia_video_get_size(video->pref_size, &width, &height)) != 0) { width = self->plugin->video.width; height = self->plugin->video.height; } if(!video->in.width) { video->in.width = video->out.width = width; } if(!video->in.height) { video->in.height = video->out.height = height; } } } return 0; }
int tmsrp_receiver_recv(tmsrp_receiver_t* self, const void* data, tsk_size_t size) { tmsrp_message_t* message; if(!self || !data || !size){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } // put the data tmsrp_data_in_put(self->data_in, data, size); // get msrp messages while((message = tmsrp_data_in_get(self->data_in))){ /* alert that we have received a message (Request or Response) */ _tmsrp_receiver_alert_user(self, tsk_false, message); // // REQUEST // if(TMSRP_MESSAGE_IS_REQUEST(message)){ /* ============= SEND =============== */ if(TMSRP_REQUEST_IS_SEND(message)){ tmsrp_response_t* r2xx; tmsrp_request_t* REPORT; // send 200 OK if((r2xx = tmsrp_create_response(message, 200, "OK"))){ if(tmsrp_message_serialize(r2xx, self->buffer) == 0 && self->buffer->data){ tnet_sockfd_send(self->fd, self->buffer->data, self->buffer->size, 0); } tsk_buffer_cleanup(self->buffer); TSK_OBJECT_SAFE_FREE(r2xx); } // send REPORT if(tmsrp_isReportRequired(message, tsk_false)){ if((REPORT = tmsrp_create_report(message, 200, "OK"))){ if(tmsrp_message_serialize(REPORT, self->buffer) == 0 && self->buffer->data){ tnet_sockfd_send(self->fd, self->buffer->data, self->buffer->size, 0); } tsk_buffer_cleanup(self->buffer); TSK_OBJECT_SAFE_FREE(REPORT); } } } /* ============= REPORT =============== */ if(TMSRP_REQUEST_IS_REPORT(message)){ tmsrp_response_t* r2xx; // send 200 OK if((r2xx = tmsrp_create_response(message, 200, "Report received"))){ if(tmsrp_message_serialize(r2xx, self->buffer) == 0 && self->buffer->data){ tnet_sockfd_send(self->fd, self->buffer->data, self->buffer->size, 0); } tsk_buffer_cleanup(self->buffer); TSK_OBJECT_SAFE_FREE(r2xx); } } /* ============= AUTH =============== */ /* ============= METHOD =============== */ } // // RESPONSE // else{ //short code = TMSRP_RESPONSE_CODE(message); //TSK_DEBUG_INFO("code=%u, tid=%s, phrase=%s", code, message->tid, TMSRP_RESPONSE_PHRASE(message)); } // alert user layer TSK_OBJECT_SAFE_FREE(message); } return 0; }
int tipsec_set_SPDs(tipsec_context_xp_t* ctx_xp) { int ret = -1; FILE* file = NULL; char* str = NULL; if(!ctx_xp){ goto bail; } if(TIPSEC_CONTEXT(ctx_xp)->state != state_full){ TSK_DEBUG_ERROR("IPSec context is in the wrong state."); ret = -3; goto bail; } if(!(file = fopen(TINYIPSEC_IPSEC6_FILE_SPD, "wb+"))){ TSK_DEBUG_ERROR("Failed to open file [%s].", TINYIPSEC_IPSEC6_FILE_SPD); ret = -4; goto bail; } tsk_sprintf(&str, TINYIPSEC_IPSEC6_TEMPLATE_POLICY, /* UC -> PS */ TINYIPSEC_IPSEC6_UCPS_POLICY, TIPSEC_CONTEXT(ctx_xp)->addr_remote, TIPSEC_CONTEXT(ctx_xp)->addr_local, TINYIPSEC_XP_GET_IPPROTO(TIPSEC_CONTEXT(ctx_xp)->ipproto), TIPSEC_CONTEXT(ctx_xp)->port_ps, TIPSEC_CONTEXT(ctx_xp)->port_uc, TINYIPSEC_XP_GET_PROTO(TIPSEC_CONTEXT(ctx_xp)->protocol), TINYIPSEC_XP_GET_MODE(TIPSEC_CONTEXT(ctx_xp)->mode), "*", /* RemoteGWIPAddr */ "NONE", /* SABundleIndex */ "BIDIRECT", /* Direction */ "APPLY", /* Action */ "0", /* InterfaceIndex */ /* US -> PC */ TINYIPSEC_IPSEC6_USPC_POLICY, TIPSEC_CONTEXT(ctx_xp)->addr_remote, TIPSEC_CONTEXT(ctx_xp)->addr_local, TINYIPSEC_XP_GET_IPPROTO(TIPSEC_CONTEXT(ctx_xp)->ipproto), TIPSEC_CONTEXT(ctx_xp)->port_pc, TIPSEC_CONTEXT(ctx_xp)->port_us, TINYIPSEC_XP_GET_PROTO(TIPSEC_CONTEXT(ctx_xp)->protocol), TINYIPSEC_XP_GET_MODE(TIPSEC_CONTEXT(ctx_xp)->mode), "*", /* RemoteGWIPAddr */ "NONE", /* SABundleIndex */ "BIDIRECT", /* Direction */ "APPLY", /* Action */ "0" /* InterfaceIndex */ ); fwrite(str, tsk_strlen(str), sizeof(uint8_t), file); ret = 0; bail: if(file){ fclose(file); } if(str){ TSK_FREE(str); } return ret; }
int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struct sockaddr_storage* remote_addr) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); return -1; #else tnet_dtls_socket_t *socket = handle; int ret = 0, len; void* out_data; if (!socket) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } tsk_safeobj_lock(socket); // update remote address even if handshaking is completed if (remote_addr) { socket->remote.addr = *remote_addr; } if (socket->handshake_completed) { TSK_DEBUG_INFO("Handshake completed"); ret = 0; goto bail; } if (!socket->handshake_started) { if ((ret = SSL_do_handshake(socket->ssl)) != 1) { switch ((ret = SSL_get_error(socket->ssl, ret))) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: case SSL_ERROR_NONE: break; default: TSK_DEBUG_ERROR("DTLS handshake failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_failed); ret = -2; goto bail; } } socket->handshake_started = (ret == SSL_ERROR_NONE); // TODO: reset for renegotiation } if ((len = (int)BIO_get_mem_data(socket->wbio, &out_data)) > 0 && out_data) { if (socket->handshake_storedata) { // e.g. when TURN is enabled we have to query handshaking data and sent it via the negotiated channel if ((int)socket->handshake_data.size < len) { if (!(socket->handshake_data.ptr = tsk_realloc(socket->handshake_data.ptr, len))) { socket->handshake_data.size = 0; socket->handshake_data.count = 0; ret = -5; goto bail; } socket->handshake_data.size = len; } socket->handshake_data.count = len; memcpy(socket->handshake_data.ptr, out_data, len); } else { int sentlen = 0; tnet_port_t port; tnet_ip_t ip; tsk_bool_t is_dgram = TNET_SOCKET_TYPE_IS_DGRAM(socket->wrapped_sock->type); const uint8_t *record_ptr, *records_ptr = out_data; tsk_size_t record_size; int records_len = len; tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port); TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, from(%.*s/%d) to(%.*s/%d)", len, (int)sizeof(socket->wrapped_sock->ip), socket->wrapped_sock->ip, socket->wrapped_sock->port, (int)sizeof(ip), ip, port); //!\ IP fragmentation issues must be avoided even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP while (records_len > 0 && (ret = tnet_dtls_socket_get_record_first(records_ptr, (tsk_size_t)records_len, &record_ptr, &record_size)) == 0) { if (is_dgram) { sentlen += tnet_sockfd_sendto(socket->wrapped_sock->fd, (const struct sockaddr *)&socket->remote.addr, record_ptr, record_size); } else { sentlen += tnet_socket_send_stream(socket->wrapped_sock, record_ptr, record_size); } records_len -= (int)record_size; records_ptr += record_size; } TSK_DEBUG_INFO("DTLS data handshake sent len = %d", sentlen); } } BIO_reset(socket->rbio); BIO_reset(socket->wbio); if ((socket->handshake_completed = SSL_is_init_finished(socket->ssl))) { TSK_DEBUG_INFO("DTLS handshake completed"); #if HAVE_OPENSSL_DTLS_SRTP if (socket->use_srtp){ #if !defined(SRTP_MAX_KEY_LEN) # define cipher_key_length (128 >> 3) // rfc5764 4.1.2. SRTP Protection Profiles # define cipher_salt_length (112 >> 3) // rfc5764 4.1.2. SRTP Protection Profiles // "cipher_key_length" is also equal to srtp_profile_get_master_key_length(srtp_profile_aes128_cm_sha1_80) // "cipher_salt_length" is also srtp_profile_get_master_salt_length(srtp_profile_aes128_cm_sha1_80) # define SRTP_MAX_KEY_LEN (cipher_key_length + cipher_salt_length) #endif /* SRTP_MAX_KEY_LEN */ #define EXTRACTOR_dtls_srtp_text "EXTRACTOR-dtls_srtp" #define EXTRACTOR_dtls_srtp_text_len 19 uint8_t keying_material[SRTP_MAX_KEY_LEN << 1]; static const tsk_size_t keying_material_size = sizeof(keying_material); /*if(socket->use_srtp)*/{ SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(socket->ssl); if (!p) { TSK_DEBUG_ERROR("SSL_get_selected_srtp_profile() returned null [%s]", ERR_error_string(ERR_get_error(), tsk_null)); ret = -2; goto bail; } // alert user _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_profile_selected, p->name, tsk_strlen(p->name)); memset(keying_material, 0, sizeof(keying_material)); // rfc5764 - 4.2. Key Derivation ret = SSL_export_keying_material(socket->ssl, keying_material, sizeof(keying_material), EXTRACTOR_dtls_srtp_text, EXTRACTOR_dtls_srtp_text_len, tsk_null, 0, 0); if (ret != 1) { // alert listener _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_error); TSK_DEBUG_ERROR("SSL_export_keying_material() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); ret = -2; goto bail; } } // alert listener _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_data, keying_material, keying_material_size); } #endif /* HAVE_OPENSSL_DTLS_SRTP */ _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_succeed); } ret = 0; // clear "ret", error will directly jump to "bail:" bail: tsk_safeobj_unlock(socket); return ret; #endif }
int tnet_transport_tls_set_certs(tnet_transport_handle_t *handle, const char* ca, const char* pbk, const char* pvk, tsk_bool_t verify) { tnet_transport_t *transport = handle; static const char* ssl_password = tsk_null; if(!transport){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } tsk_strupdate(&transport->tls.ca, ca); tsk_strupdate(&transport->tls.pvk, pvk); tsk_strupdate(&transport->tls.pbk, pbk); transport->tls.verify = verify; #if HAVE_OPENSSL { int32_t i, ret; SSL_CTX* contexts[3] = { tsk_null }; /* init DTLS/TLS contexts */ if((ret = _tnet_transport_ssl_init(transport))){ return ret; } if(transport->tls.enabled){ contexts[0] = transport->tls.ctx_client; contexts[1] = transport->tls.ctx_server; } if(transport->dtls.enabled){ contexts[2] = transport->dtls.ctx; /* Reset fingerprints */ memset(transport->dtls.fingerprints, 0, sizeof(transport->dtls.fingerprints)); } for(i = 0; i < sizeof(contexts)/sizeof(contexts[0]); ++i){ if(!contexts[i]){ continue; } SSL_CTX_set_verify(contexts[i], transport->tls.verify ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : SSL_VERIFY_NONE, tsk_null); if(!tsk_strnullORempty(transport->tls.pbk) || !tsk_strnullORempty(transport->tls.pvk) || !tsk_strnullORempty(transport->tls.ca)){ /* Sets Public key (cert) */ if(!tsk_strnullORempty(transport->tls.pbk) && (ret = SSL_CTX_use_certificate_file(contexts[i], transport->tls.pbk, SSL_FILETYPE_PEM)) != 1) { TSK_DEBUG_ERROR("SSL_CTX_use_certificate_file failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -3; } /*Sets the password of the private key*/ if(!tsk_strnullORempty(ssl_password)){ SSL_CTX_set_default_passwd_cb_userdata(contexts[i], (void*)ssl_password); } /* Sets Private key (cert) */ if (!tsk_strnullORempty(transport->tls.pvk) && (ret = SSL_CTX_use_PrivateKey_file(contexts[i], transport->tls.pvk, SSL_FILETYPE_PEM)) != 1) { TSK_DEBUG_ERROR("SSL_CTX_use_PrivateKey_file failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -4; } /* Checks private key */ if(!tsk_strnullORempty(transport->tls.pvk) && SSL_CTX_check_private_key(contexts[i]) == 0) { TSK_DEBUG_ERROR("SSL_CTX_check_private_key failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -5; } /* Sets trusted CAs and CA file */ if(!tsk_strnullORempty(transport->tls.ca) && (ret = SSL_CTX_load_verify_locations(contexts[i], transport->tls.ca, /*tlsdir_cas*/tsk_null)) != 1) { TSK_DEBUG_ERROR("SSL_CTX_load_verify_locations failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -5; } } } } #endif /* HAVE_OPENSSL */ return 0; }
tnet_fd_t tnet_transport_connectto_3(const tnet_transport_handle_t *handle, struct tnet_socket_s* socket, const char* host, tnet_port_t port, tnet_socket_type_t type) { tnet_transport_t *transport = (tnet_transport_t*)handle; struct sockaddr_storage to; int status = -1; tnet_fd_t fd = socket ? socket->fd : TNET_INVALID_FD; tnet_tls_socket_handle_t* tls_handle = tsk_null; tsk_bool_t owe_socket = socket ? tsk_false : tsk_true; tsk_bool_t use_proxy = TNET_SOCKET_TYPE_IS_STREAM(type); const char* to_host = host; tnet_port_t to_port = port; tnet_socket_type_t to_type = type; tnet_proxyinfo_t* proxy_info = tsk_null; if (!transport || !transport->master) { TSK_DEBUG_ERROR("Invalid transport handle"); goto bail; } if ((TNET_SOCKET_TYPE_IS_STREAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_STREAM(type)) || (TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_DGRAM(type))) { TSK_DEBUG_ERROR("Master/destination types mismatch [%u/%u]", transport->master->type, type); goto bail; } if (use_proxy) { // auto-detect the proxy if (transport->proxy.auto_detect) { char* url = tsk_null; // The proxy detection implementations are designed for a browser and expect a "http://" or "https://" schemes (will work with socks). tsk_sprintf(&url, "%s://%s:%d", TNET_SOCKET_TYPE_IS_TLS(to_type) ? "https" : "http", to_host, to_port); proxy_info = tnet_proxydetect_get_info_fast(url, to_type); TSK_FREE(url); } // fall-back to the hard proxy if auto-detection failed if (!tnet_proxyinfo_is_valid(proxy_info) && tnet_proxyinfo_is_valid(transport->proxy.info)) { proxy_info = tsk_object_ref(transport->proxy.info); } } use_proxy &= tnet_proxyinfo_is_valid(proxy_info); if (use_proxy) { if (tnet_proxy_node_is_nettransport_supported(proxy_info->type, type)) { to_host = proxy_info->hostname; to_port = proxy_info->port; // SOCKS still doesn't define RFC for SSL security (https://tools.ietf.org/html/draft-ietf-aft-socks-ssl-00) but Kerberos6 authentication is supported if (proxy_info->type == tnet_proxy_type_http || proxy_info->type == tnet_proxy_type_socks4 || proxy_info->type == tnet_proxy_type_socks4a || proxy_info->type == tnet_proxy_type_socks5) { // Send CONNET to the proxy using unsecure connection then begin SSL handshaking if needed TNET_SOCKET_TYPE_UNSET(to_type, TLS); // Make the type unsecure (will keep other flags-e.g. IP version-) TNET_SOCKET_TYPE_SET(to_type, TCP); // Use plain TCP } } else { // Not an error. TSK_DEBUG_INFO("No proxy plugin to handle network transport type = %d", type); use_proxy = tsk_false; } } TSK_DEBUG_INFO("tnet_transport_connectto_3(host=%s, port=%d, type=%d, fd=%d, use_proxy=%d, to_host=%s, to_port=%d, to_type=%d, proxy_type=%d)" , host, port, type, fd, use_proxy, to_host, to_port, to_type, proxy_info ? proxy_info->type : 0); /* Init destination sockaddr fields */ if ((status = tnet_sockaddr_init(to_host, to_port, to_type, &to))) { TSK_DEBUG_ERROR("Invalid HOST/PORT [%s/%u]", host, port); goto bail; } if (TNET_SOCKET_TYPE_IS_IPV46(type)) { /* Update the type (unambiguously) */ if (to.ss_family == AF_INET6) { TNET_SOCKET_TYPE_SET_IPV6Only(type); } else { TNET_SOCKET_TYPE_SET_IPV4Only(type); } } /* * STREAM ==> create new socket and connect it to the remote host. * DGRAM ==> connect the master to the remote host. */ if (fd == TNET_INVALID_FD) { // Create client socket descriptor. if ((status = tnet_sockfd_init(transport->local_host, TNET_SOCKET_PORT_ANY, to_type, &fd))) { TSK_DEBUG_ERROR("Failed to create new sockfd."); goto bail; } } if ((status = tnet_sockfd_connectto(fd, (const struct sockaddr_storage *)&to))) { if (fd != transport->master->fd) { tnet_sockfd_close(&fd); } goto bail; } else { static const tsk_bool_t __isClient = tsk_true; if (TNET_SOCKET_TYPE_IS_TLS(to_type) || TNET_SOCKET_TYPE_IS_WSS(to_type)) { #if HAVE_OPENSSL tls_handle = tnet_tls_socket_create(fd, transport->tls.ctx_client); if (socket) { TSK_OBJECT_SAFE_FREE(socket->tlshandle); socket->tlshandle = tsk_object_ref(tls_handle); } if ((status = tnet_tls_socket_connect(tls_handle))) { tnet_sockfd_close(&fd); goto bail; } #endif } /* Add the socket */ // socket must be added after connect() otherwise many Linux systems will return POLLHUP as the fd is not active yet if ((status = tnet_transport_add_socket_2(handle, fd, to_type, owe_socket, __isClient, tls_handle, host, port, proxy_info))) { TNET_PRINT_LAST_ERROR("Failed to add new socket"); tnet_sockfd_close(&fd); goto bail; } } bail: TSK_OBJECT_SAFE_FREE(tls_handle); TSK_OBJECT_SAFE_FREE(proxy_info); return status == 0 ? fd : TNET_INVALID_FD; }
/**@ingroup tnet_stun_group * Creates @ref tnet_stun_attribute_t from raw buffer. * @param data Raw buffer from which to create the STUN attribute.* * @param size The size of the eaw buffer. * @retval @ref tnet_stun_attribute_t object if succeed and NULL other wise. */ tnet_stun_attribute_t* tnet_stun_attribute_deserialize(const void* data, tsk_size_t size) { tnet_stun_attribute_t *attribute = 0; const uint8_t* dataPtr = data; tnet_stun_attribute_type_t type = (tnet_stun_attribute_type_t)tnet_ntohs_2(dataPtr); uint16_t length = tnet_ntohs_2(&dataPtr[2]); /* Check validity */ if(!data || size<=4/* Type(2-bytes) plus Length (2-bytes) */) { return 0; } dataPtr += (2 /* Type */+ 2/* Length */); /* Attribute Value */ switch(type) { /* RFC 5389 - 15.1. MAPPED-ADDRESS */ case stun_mapped_address: { attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_mapped_address_create(dataPtr, length); break; } /* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS*/ case stun_xor_mapped_address: { attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_xmapped_address_create(dataPtr, length); break; } /* RFC 5389 - 15.3. USERNAME*/ case stun_username: { attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_username_create(dataPtr, length); break; } /* RFC 5389 - MESSAGE-INTEGRITY*/ case stun_message_integrity: { if(length == TSK_SHA1_DIGEST_SIZE){ attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_integrity_create(dataPtr, length); } break; } /* RFC 5389 - 15.5. FINGERPRINT*/ case stun_fingerprint: { uint32_t fingerprint = tnet_htonl_2(dataPtr); attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_fingerprint_create(fingerprint); break; } /* RFC 5389 - 15.6. ERROR-CODE*/ case stun_error_code: { attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_errorcode_create(dataPtr, length); break; } /* RFC 5389 - 15.7. REALM*/ case stun_realm: { attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_realm_create(dataPtr, length); break; } /* RFC 5389 - 15.8. NONCE*/ case stun_nonce: { attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_nonce_create(dataPtr, length); break; } /* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES*/ case stun_unknown_attributes: { TSK_DEBUG_ERROR("DESERIALIZE:UNKNOWN-ATTRIBUTES ==> NOT IMPLEMENTED"); attribute = tnet_stun_attribute_create(); break; } /* RFC 5389 - 15.10. SOFTWARE */ case stun_software: { attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_software_create(dataPtr, length); break; } /* RFC 5389 - 15.11. ALTERNATE-SERVER */ case stun_alternate_server: { attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_altserver_create(dataPtr, length); break; } /* draft-ietf-behave-turn-16 subclause 14 */ case stun_channel_number: case stun_lifetime: case stun_reserved2: case stun_xor_peer_address: case stun_data: case stun_xor_relayed_address: case stun_even_port: case stun_requested_transport: case stun_dont_fragment: case stun_reserved3: case stun_reservation_token: { attribute = tnet_turn_attribute_deserialize(type, length, dataPtr, length); break; } default: //TSK_DEBUG_WARN("==> NOT IMPLEMENTED"); break; } if(!attribute){ /* Create default */ attribute = tnet_stun_attribute_create(); } /* Set common values (Do I need this ==> already set by the constructor). */ attribute->type = type; attribute->length = length; return attribute; }
static void tdav_codec_mp4ves_encap(tdav_codec_mp4ves_t* mp4v, const uint8_t* pdata, tsk_size_t size) { uint32_t scode; // start code if(size <= 4/*32bits: start code size*/){ TSK_DEBUG_ERROR("Too short"); return; } // first 32bits scode = tnet_htonl_2(pdata); /* RFC 3016 - 3.3 Examples of packetized MPEG-4 Visual bitstream VS= Visual Object Sequence VO= Visual Object VOL= Visual Object Layer VOP= Visual Object Plane GOV= Group of Visual Object Plane VP= Video Plane +------+------+------+------+ (a) | RTP | VS | VO | VOL | |header|header|header|header| +------+------+------+------+ +------+------+------+------+------------+ (b) | RTP | VS | VO | VOL |Video Packet| |header|header|header|header| | +------+------+------+------+------------+ +------+-----+------------------+ (c) | RTP | GOV |Video Object Plane| |header| | | +------+-----+------------------+ +------+------+------------+ +------+------+------------+ (d) | RTP | VOP |Video Packet| | RTP | VP |Video Packet| |header|header| (1) | |header|header| (2) | +------+------+------------+ +------+------+------------+ +------+------+------------+------+------------+------+------------+ (e) | RTP | VP |Video Packet| VP |Video Packet| VP |Video Packet| |header|header| (1) |header| (2) |header| (3) | +------+------+------------+------+------------+------+------------+ +------+------+------------+ +------+------------+ (f) | RTP | VOP |VOP fragment| | RTP |VOP fragment| |header|header| (1) | |header| (2) | ___ +------+------+------------+ +------+------------+ Figure 2 - Examples of RTP packetized MPEG-4 Visual bitstream */ /* RFC 3016 - 3.2 Fragmentation of MPEG-4 Visual bitstream A fragmented MPEG-4 Visual bitstream is mapped directly onto the RTP payload without any addition of extra header fields or any removal of Visual syntax elements. The Combined Configuration/Elementary streams mode is used. In the following, header means one of the following: - Configuration information (Visual Object Sequence Header, Visual Object Header and Video Object Layer Header) - visual_object_sequence_end_code - The header of the entry point function for an elementary stream (Group_of_VideoObjectPlane() or the header of VideoObjectPlane(), video_plane_with_short_header(), MeshObject() or FaceObject()) - The video packet header (video_packet_header() excluding next_resync_marker()) - The header of gob_layer() See 6.2.1 "Start codes" of ISO/IEC 14496-2 [2][9][4] for the definition of the configuration information and the entry point functions. */ switch(scode){ case visual_object_sequence_start_code: case visual_object_start_code: case user_data_start_code: case video_object_layer_start_code: case group_of_vop_start_code: case vop_start_code: { register uint32_t i, last_index = 0; int startcode = 0xffffffff; if(scode == visual_object_sequence_start_code && size >=5){ //uint8_t profile_and_level_indication = pdata[4]; /* IEC 14496-2: 6.3.2 Visual Object Sequence and Visual Object */ // TSK_DEBUG_INFO("profile_and_level_indication=%d", profile_and_level_indication); } if(size < MP4V_RTP_PAYLOAD_SIZE){ goto last; } for(i = 4; i<(size - 4); i++){ startcode = (startcode <<8) | pdata[i]; switch(startcode){ case visual_object_sequence_start_code: case group_of_vop_start_code: case vop_start_code: tdav_codec_mp4ves_rtp_callback(mp4v, pdata + last_index, (i - last_index), (last_index == size)); last_index = i; } } last: if(last_index < size){ tdav_codec_mp4ves_rtp_callback(mp4v, pdata + last_index, (size - last_index), tsk_true); } break; } default: TSK_DEBUG_ERROR("%x is an invalide start code", scode); break; } }
static int _tnet_transport_ssl_init(tnet_transport_t* transport) { if (!transport){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } #if HAVE_OPENSSL { tnet_socket_type_t type = tnet_transport_get_type(transport); tsk_bool_t is_tls = (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)); tsk_bool_t is_dtls = transport->dtls.enabled/* TNET_SOCKET_TYPE_IS_DTLS(type)*/; // DTLS-RTP, not raw DTLS if (is_dtls && !tnet_dtls_is_supported()){ TSK_DEBUG_ERROR("Requesting to create DTLS transport but source code not built with support for this feature"); return -1; } if (is_tls && !tnet_tls_is_supported()){ TSK_DEBUG_ERROR("Requesting to create TLS transport but source code not built with support for this feature"); return -1; } if ((transport->tls.enabled = is_tls)){ if (!transport->tls.ctx_client && !(transport->tls.ctx_client = SSL_CTX_new(SSLv23_client_method()))){ TSK_DEBUG_ERROR("Failed to create SSL client context"); return -2; } if (!transport->tls.ctx_server && !(transport->tls.ctx_server = SSL_CTX_new(SSLv23_server_method()))){ TSK_DEBUG_ERROR("Failed to create SSL server context"); return -3; } SSL_CTX_set_mode(transport->tls.ctx_client, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(transport->tls.ctx_server, SSL_MODE_AUTO_RETRY); SSL_CTX_set_verify(transport->tls.ctx_server, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs() SSL_CTX_set_verify(transport->tls.ctx_client, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs() if (SSL_CTX_set_cipher_list(transport->tls.ctx_client, TNET_CIPHER_LIST) <= 0 || SSL_CTX_set_cipher_list(transport->tls.ctx_server, TNET_CIPHER_LIST) <= 0){ TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); return -4; } } #if HAVE_OPENSSL_DTLS if ((transport->dtls.enabled = is_dtls)){ if (!transport->dtls.ctx && !(transport->dtls.ctx = SSL_CTX_new(DTLSv1_method()))){ TSK_DEBUG_ERROR("Failed to create DTLSv1 context"); TSK_OBJECT_SAFE_FREE(transport); return -5; } SSL_CTX_set_read_ahead(transport->dtls.ctx, 1); // SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_ALL); // SSL_CTX_set_mode(transport->dtls.ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_verify(transport->dtls.ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, tsk_null); // to be updated by tnet_transport_tls_set_certs() if (SSL_CTX_set_cipher_list(transport->dtls.ctx, TNET_CIPHER_LIST) <= 0){ TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); return -6; } //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP // Up to the DTLS socket to set the default MTU value SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_NO_QUERY_MTU); SSL_CTX_ctrl(transport->dtls.ctx, SSL_CTRL_SET_MTU, TNET_DTLS_MTU - 28, NULL); transport->dtls.activated = tsk_true; } #endif /* HAVE_OPENSSL_DTLS */ } #endif /* HAVE_OPENSSL */ return 0; }
/* ============ Internal functions ================= */ int tdav_codec_mp4ves_open_encoder(tdav_codec_mp4ves_t* self) { int ret, size; int32_t max_bw_kpbs; if(!self->encoder.codec && !(self->encoder.codec = avcodec_find_encoder(CODEC_ID_MPEG4))){ TSK_DEBUG_ERROR("Failed to find mp4v encoder"); return -1; } if(self->encoder.context){ TSK_DEBUG_ERROR("Encoder already opened"); return -1; } self->encoder.context = avcodec_alloc_context(); avcodec_get_context_defaults(self->encoder.context); self->encoder.context->pix_fmt = PIX_FMT_YUV420P; self->encoder.context->time_base.num = 1; self->encoder.context->time_base.den = TMEDIA_CODEC_VIDEO(self)->in.fps; self->encoder.context->width = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.height : TMEDIA_CODEC_VIDEO(self)->out.width; self->encoder.context->height = (self->encoder.rotation == 90 || self->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(self)->out.width : TMEDIA_CODEC_VIDEO(self)->out.height; self->encoder.context->mb_decision = FF_MB_DECISION_RD; self->encoder.context->noise_reduction = 250; self->encoder.context->flags |= CODEC_FLAG_QSCALE; self->encoder.context->global_quality = FF_QP2LAMBDA * self->encoder.quality; max_bw_kpbs = TSK_CLAMP( 0, tmedia_get_video_bandwidth_kbps_2(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, TMEDIA_CODEC_VIDEO(self)->out.fps), self->encoder.max_bw_kpbs ); self->encoder.context->bit_rate = (max_bw_kpbs * 1024);// bps self->encoder.context->rtp_payload_size = MP4V_RTP_PAYLOAD_SIZE; self->encoder.context->opaque = tsk_null; self->encoder.context->profile = self->profile>>4; self->encoder.context->level = self->profile & 0x0F; self->encoder.context->gop_size = (TMEDIA_CODEC_VIDEO(self)->in.fps * MP4V_GOP_SIZE_IN_SECONDS); self->encoder.context->max_b_frames = 0; self->encoder.context->b_frame_strategy = 1; self->encoder.context->flags |= CODEC_FLAG_AC_PRED; // Picture (YUV 420) if(!(self->encoder.picture = avcodec_alloc_frame())){ TSK_DEBUG_ERROR("Failed to create MP4V-ES encoder picture"); return -2; } avcodec_get_frame_defaults(self->encoder.picture); size = avpicture_get_size(PIX_FMT_YUV420P, self->encoder.context->width, self->encoder.context->height); if(!(self->encoder.buffer = tsk_calloc(size, sizeof(uint8_t)))){ TSK_DEBUG_ERROR("Failed to allocate MP4V-ES encoder buffer"); return -2; } // Open encoder if((ret = avcodec_open(self->encoder.context, self->encoder.codec)) < 0){ TSK_DEBUG_ERROR("Failed to open MP4V-ES encoder"); return ret; } TSK_DEBUG_INFO("[MP4V-ES] bitrate=%d bps", self->encoder.context->bit_rate); return ret; }
tsk_size_t tdav_codec_mp4ves_decode(tmedia_codec_t* _self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr) { tdav_codec_mp4ves_t* self = (tdav_codec_mp4ves_t*)_self; const trtp_rtp_header_t* rtp_hdr = proto_hdr; tsk_size_t xsize, retsize = 0; int got_picture_ptr; int ret; if(!self || !in_data || !in_size || !out_data || !self->decoder.context){ TSK_DEBUG_ERROR("Invalid parameter"); return 0; } // get expected size xsize = avpicture_get_size(self->decoder.context->pix_fmt, self->decoder.context->width, self->decoder.context->height); /* Packet lost? */ if(self->decoder.last_seq != (rtp_hdr->seq_num - 1) && self->decoder.last_seq){ if(self->decoder.last_seq == rtp_hdr->seq_num){ // Could happen on some stupid emulators TSK_DEBUG_INFO("Packet duplicated, seq_num=%d", rtp_hdr->seq_num); return 0; } TSK_DEBUG_INFO("Packet lost, seq_num=%d", rtp_hdr->seq_num); } self->decoder.last_seq = rtp_hdr->seq_num; if((self->decoder.accumulator_pos + in_size) <= xsize){ memcpy(&((uint8_t*)self->decoder.accumulator)[self->decoder.accumulator_pos], in_data, in_size); self->decoder.accumulator_pos += in_size; } else{ TSK_DEBUG_WARN("Buffer overflow"); self->decoder.accumulator_pos = 0; return 0; } if(rtp_hdr->marker){ AVPacket packet; /* allocate destination buffer */ if(*out_max_size <xsize){ if(!(*out_data = tsk_realloc(*out_data, xsize))){ TSK_DEBUG_ERROR("Failed to allocate new buffer"); self->decoder.accumulator_pos = 0; *out_max_size = 0; return 0; } *out_max_size = xsize; } av_init_packet(&packet); packet.size = (int)self->decoder.accumulator_pos; packet.data = self->decoder.accumulator; ret = avcodec_decode_video2(self->decoder.context, self->decoder.picture, &got_picture_ptr, &packet); if(ret < 0){ TSK_DEBUG_WARN("Failed to decode the buffer with error code = %d", ret); if(TMEDIA_CODEC_VIDEO(self)->in.callback){ TMEDIA_CODEC_VIDEO(self)->in.result.type = tmedia_video_decode_result_type_error; TMEDIA_CODEC_VIDEO(self)->in.result.proto_hdr = proto_hdr; TMEDIA_CODEC_VIDEO(self)->in.callback(&TMEDIA_CODEC_VIDEO(self)->in.result); } } else if(got_picture_ptr){ retsize = xsize; TMEDIA_CODEC_VIDEO(self)->in.width = self->decoder.context->width; TMEDIA_CODEC_VIDEO(self)->in.height = self->decoder.context->height; /* copy picture into a linear buffer */ avpicture_layout((AVPicture *)self->decoder.picture, self->decoder.context->pix_fmt, (int)self->decoder.context->width, (int)self->decoder.context->height, *out_data, (int)retsize); } /* in all cases: reset accumulator */ self->decoder.accumulator_pos = 0; } return retsize; }
static int tdav_speex_denoise_open(tmedia_denoise_t* self, uint32_t frame_size, uint32_t sampling_rate) { tdav_speex_denoise_t *denoiser = (tdav_speex_denoise_t *)self; float f; int i; if(!denoiser->echo_state && TMEDIA_DENOISE(denoiser)->echo_supp_enabled){ TSK_DEBUG_INFO("Init Aec frame_size[%u] filter_length[%u] SampleRate[%u]", (uint32_t)(frame_size* sizeof(spx_int16_t)),TMEDIA_DENOISE(denoiser)->echo_tail*frame_size,sampling_rate); if((denoiser->echo_state = speex_echo_state_init(frame_size, TMEDIA_DENOISE(denoiser)->echo_tail))){ speex_echo_ctl(denoiser->echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &sampling_rate); } } if(!denoiser->preprocess_state_record && !denoiser->preprocess_state_playback){ denoiser->frame_size = frame_size; if((denoiser->preprocess_state_record = speex_preprocess_state_init(frame_size, sampling_rate)) && (denoiser->preprocess_state_playback = speex_preprocess_state_init(frame_size, sampling_rate)) ){ // Echo suppression if(denoiser->echo_state){ int echo_supp , echo_supp_active = 0; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_ECHO_STATE, denoiser->echo_state); TSK_FREE(denoiser->echo_output_frame); denoiser->echo_output_frame = tsk_calloc(denoiser->frame_size, sizeof(spx_int16_t)); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS , &echo_supp ); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE , &echo_supp_active ); TSK_DEBUG_INFO("AEC echo_supp level [%d] echo_supp_active level[%d] ", echo_supp , echo_supp_active); echo_supp = -60 ; echo_supp_active = -60 ; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_ECHO_SUPPRESS , &echo_supp ); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE , &echo_supp_active ); // TRACES speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS , &echo_supp ); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE , &echo_supp_active ); TSK_DEBUG_INFO("New aec echo_supp level [%d] echo_supp_active level[%d] ", echo_supp , echo_supp_active); } // Noise suppression if(TMEDIA_DENOISE(denoiser)->noise_supp_enabled){ TSK_DEBUG_INFO("SpeexDSP: Noise supp enabled"); i = 1; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_DENOISE, &i); speex_preprocess_ctl(denoiser->preprocess_state_playback, SPEEX_PREPROCESS_SET_DENOISE, &i); i = TMEDIA_DENOISE(denoiser)->noise_supp_level; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i); speex_preprocess_ctl(denoiser->preprocess_state_playback, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i); } else{ i = 0; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_DENOISE, &i); speex_preprocess_ctl(denoiser->preprocess_state_playback, SPEEX_PREPROCESS_SET_DENOISE, &i); } // Automatic gain control if(TMEDIA_DENOISE(denoiser)->agc_enabled){ float agc_level = TMEDIA_DENOISE(denoiser)->agc_level; TSK_DEBUG_INFO("SpeexDSP: AGC enabled"); i = 1; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_AGC, &i); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_AGC_LEVEL, &agc_level); } else{ i = 0, f = 8000.0f; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_AGC, &i); speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f); } // Voice Activity detection i = TMEDIA_DENOISE(denoiser)->vad_enabled ? 1 : 0; speex_preprocess_ctl(denoiser->preprocess_state_record, SPEEX_PREPROCESS_SET_VAD, &i); return 0; } else{ TSK_DEBUG_ERROR("Failed to create Speex preprocessor state"); return -2; } } return 0; }
static int tdav_speex_jitterbuffer_set(tmedia_jitterbuffer_t *self, const tmedia_param_t* param) { TSK_DEBUG_ERROR("Not implemented"); return -2; }
/**@ingroup tnet_stun_group * Serializes a @ref tnet_stun_attribute_t objet in binary format. * @param attribute The STUN attribute to serialize. * @param output The output binary buffer. * @retval Zero if succeed and non-zero error code otherwise. */ int tnet_stun_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_buffer_t *output) { if(!attribute || !output){ return -1; } /* Attribute Type */ { uint16_t type = tnet_htons(attribute->type); tsk_buffer_append(output, &(type), 2); } /* Attribute Length */ { uint16_t length = tnet_htons(attribute->length); tsk_buffer_append(output, &(length), 2); } /* Attribute Value */ switch(attribute->type){ /* RFC 5389 - 15.1. MAPPED-ADDRESS */ case stun_mapped_address: { TSK_DEBUG_ERROR("NOT IMPLEMENTED"); return -3; } /* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS*/ case stun_xor_mapped_address: { TSK_DEBUG_ERROR("NOT IMPLEMENTED"); return -3; } /* RFC 5389 - 15.3. USERNAME*/ case stun_username: { tnet_stun_attribute_username_t *username = (tnet_stun_attribute_username_t*)attribute; tsk_buffer_append(output, username->value, tsk_strlen(username->value)); return 0; } /* RFC 5389 - MESSAGE-INTEGRITY*/ case stun_message_integrity: { tnet_stun_attribute_integrity_t *integrity = (tnet_stun_attribute_integrity_t*)attribute; tsk_buffer_append(output, integrity->sha1digest, TSK_SHA1_DIGEST_SIZE); return 0; } /* RFC 5389 - 15.5. FINGERPRINT*/ case stun_fingerprint: { uint32_t fingerprint = /*tnet_htonl*/(((tnet_stun_attribute_fingerprint_t*)attribute)->value); tsk_buffer_append(output, &fingerprint, 4); return 0; } /* RFC 5389 - 15.6. ERROR-CODE*/ case stun_error_code: { TSK_DEBUG_ERROR("NOT IMPLEMENTED"); return -3; } /* RFC 5389 - 15.7. REALM*/ case stun_realm: { tnet_stun_attribute_realm_t *realm = (tnet_stun_attribute_realm_t*)attribute; tsk_buffer_append(output, realm->value, tsk_strlen(realm->value)); return 0; } /* RFC 5389 - 15.8. NONCE*/ case stun_nonce: { tnet_stun_attribute_nonce_t *nonce = (tnet_stun_attribute_nonce_t*)attribute; tsk_buffer_append(output, nonce->value, tsk_strlen(nonce->value)); return 0; } /* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES*/ case stun_unknown_attributes: { TSK_DEBUG_ERROR("NOT IMPLEMENTED"); return -3; } /* RFC 5389 - 15.10. SOFTWARE */ case stun_software: { tnet_stun_attribute_software_t *software = (tnet_stun_attribute_software_t*)attribute; tsk_buffer_append(output, software->value, tsk_strlen(software->value)); return 0; } /* RFC 5389 - 15.11. ALTERNATE-SERVER */ case stun_alternate_server: { TSK_DEBUG_ERROR("NOT IMPLEMENTED"); return -3; } /* draft-ietf-behave-turn-16 - */ case stun_channel_number: case stun_lifetime: case stun_reserved2: case stun_xor_peer_address: case stun_data: case stun_xor_relayed_address: case stun_even_port: case stun_requested_transport: case stun_dont_fragment: case stun_reserved3: case stun_reservation_token: { return tnet_turn_attribute_serialize(attribute, output); } default: return -2; } }
static int tdav_speex_jitterbuffer_put(tmedia_jitterbuffer_t* self, void* data, tsk_size_t data_size, const tsk_object_t* proto_hdr) { tdav_speex_jitterbuffer_t *jb = (tdav_speex_jitterbuffer_t *)self; const trtp_rtp_header_t* rtp_hdr; JitterBufferPacket jb_packet; static uint16_t seq_num = 0; if(!data || !data_size || !proto_hdr){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(!jb->state){ TSK_DEBUG_ERROR("Invalid state"); return -2; } rtp_hdr = TRTP_RTP_HEADER(proto_hdr); jb_packet.user_data = 0; jb_packet.span = jb->frame_duration; jb_packet.len = jb->x_data_size; if(jb->x_data_size == data_size){ /* ptime match */ jb_packet.data = data; jb_packet.sequence = rtp_hdr->seq_num; jb_packet.timestamp = (rtp_hdr->seq_num * jb_packet.span); jitter_buffer_put(jb->state, &jb_packet); } else{ /* ptime mismatch */ tsk_size_t i; jb_packet.sequence = 0; // Ignore if((jb->buff.index + data_size) > jb->buff.size){ if(!(jb->buff.ptr = tsk_realloc(jb->buff.ptr, (jb->buff.index + data_size)))){ jb->buff.size = 0; jb->buff.index = 0; return 0; } jb->buff.size = (jb->buff.index + data_size); } memcpy(&jb->buff.ptr[jb->buff.index], data, data_size); jb->buff.index += data_size; if(jb->buff.index >= jb->x_data_size){ tsk_size_t copied = 0; for(i = 0; (i + jb->x_data_size) <= jb->buff.index; i += jb->x_data_size){ jb_packet.data = (char*)&jb->buff.ptr[i]; jb_packet.timestamp = (++jb->fake_seqnum * jb_packet.span);// reassembled pkt will have fake seqnum jitter_buffer_put(jb->state, &jb_packet); copied += jb->x_data_size; } if(copied == jb->buff.index){ // all copied jb->buff.index = 0; } else{ memmove(&jb->buff.ptr[0], &jb->buff.ptr[copied], (jb->buff.index - copied)); jb->buff.index -= copied; } } } return 0; }
static int tdav_consumer_audiounit_prepare(tmedia_consumer_t* self, const tmedia_codec_t* codec) { static UInt32 flagOne = 1; AudioStreamBasicDescription audioFormat; #define kOutputBus 0 tdav_consumer_audiounit_t* consumer = (tdav_consumer_audiounit_t*)self; OSStatus status = noErr; if(!consumer || !codec || !codec->plugin){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(!consumer->audioUnitHandle){ if(!(consumer->audioUnitHandle = tdav_audiounit_handle_create(TMEDIA_CONSUMER(consumer)->session_id))){ TSK_DEBUG_ERROR("Failed to get audio unit instance for session with id=%lld", TMEDIA_CONSUMER(consumer)->session_id); return -3; } } // enable status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(consumer->audioUnitHandle), kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flagOne, sizeof(flagOne)); if(status){ TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioOutputUnitProperty_EnableIO) failed with status=%d", (int32_t)status); return -4; } else { #if !TARGET_OS_IPHONE // strange: TARGET_OS_MAC is equal to '1' on Smulator UInt32 param; // disable input param = 0; status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(consumer->audioUnitHandle), kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, ¶m, sizeof(UInt32)); if(status != noErr){ TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioOutputUnitProperty_EnableIO) failed with status=%ld", (signed long)status); return -4; } // set default audio device param = sizeof(AudioDeviceID); AudioDeviceID outputDeviceID; status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, ¶m, &outputDeviceID); if(status != noErr){ TSK_DEBUG_ERROR("AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice) failed with status=%ld", (signed long)status); return -4; } // set the current device to the default input unit status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(consumer->audioUnitHandle), kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &outputDeviceID, sizeof(AudioDeviceID)); if(status != noErr){ TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioOutputUnitProperty_CurrentDevice) failed with status=%ld", (signed long)status); return -4; } #endif TMEDIA_CONSUMER(consumer)->audio.ptime = TMEDIA_CODEC_PTIME_AUDIO_DECODING(codec); TMEDIA_CONSUMER(consumer)->audio.in.channels = TMEDIA_CODEC_CHANNELS_AUDIO_DECODING(codec); TMEDIA_CONSUMER(consumer)->audio.in.rate = TMEDIA_CODEC_RATE_DECODING(codec); TSK_DEBUG_INFO("AudioUnit consumer: in.channels=%d, out.channles=%d, in.rate=%d, out.rate=%d, ptime=%d", TMEDIA_CONSUMER(consumer)->audio.in.channels, TMEDIA_CONSUMER(consumer)->audio.out.channels, TMEDIA_CONSUMER(consumer)->audio.in.rate, TMEDIA_CONSUMER(consumer)->audio.out.rate, TMEDIA_CONSUMER(consumer)->audio.ptime); audioFormat.mSampleRate = TMEDIA_CONSUMER(consumer)->audio.out.rate ? TMEDIA_CONSUMER(consumer)->audio.out.rate : TMEDIA_CONSUMER(consumer)->audio.in.rate; audioFormat.mFormatID = kAudioFormatLinearPCM; audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; audioFormat.mChannelsPerFrame = TMEDIA_CONSUMER(consumer)->audio.in.channels; audioFormat.mFramesPerPacket = 1; audioFormat.mBitsPerChannel = TMEDIA_CONSUMER(consumer)->audio.bits_per_sample; audioFormat.mBytesPerPacket = audioFormat.mBitsPerChannel / 8 * audioFormat.mChannelsPerFrame; audioFormat.mBytesPerFrame = audioFormat.mBytesPerPacket; audioFormat.mReserved = 0; status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(consumer->audioUnitHandle), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &audioFormat, sizeof(audioFormat)); if(status){ TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioUnitProperty_StreamFormat) failed with status=%ld", (signed long)status); return -5; } else { // configure if(tdav_audiounit_handle_configure(consumer->audioUnitHandle, tsk_true, TMEDIA_CONSUMER(consumer)->audio.ptime, &audioFormat)){ TSK_DEBUG_ERROR("tdav_audiounit_handle_set_rate(%d) failed", TMEDIA_CONSUMER(consumer)->audio.out.rate); return -4; } // set callback function AURenderCallbackStruct callback; callback.inputProc = __handle_output_buffer; callback.inputProcRefCon = consumer; status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(consumer->audioUnitHandle), kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback)); if(status){ TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioOutputUnitProperty_SetInputCallback) failed with status=%ld", (signed long)status); return -6; } } } // allocate the chunck buffer and create the ring consumer->ring.chunck.size = (TMEDIA_CONSUMER(consumer)->audio.ptime * audioFormat.mSampleRate * audioFormat.mBytesPerFrame) / 1000; consumer->ring.size = kRingPacketCount * consumer->ring.chunck.size; if(!(consumer->ring.chunck.buffer = tsk_realloc(consumer->ring.chunck.buffer, consumer->ring.chunck.size))){ TSK_DEBUG_ERROR("Failed to allocate new buffer"); return -7; } if(!consumer->ring.buffer){ consumer->ring.buffer = speex_buffer_init(consumer->ring.size); } else { int ret; if((ret = speex_buffer_resize(consumer->ring.buffer, consumer->ring.size)) < 0){ TSK_DEBUG_ERROR("speex_buffer_resize(%d) failed with error code=%d", consumer->ring.size, ret); return ret; } } if(!consumer->ring.buffer){ TSK_DEBUG_ERROR("Failed to create a new ring buffer with size = %d", consumer->ring.size); return -8; } if(!consumer->ring.mutex && !(consumer->ring.mutex = tsk_mutex_create_2(tsk_false))){ TSK_DEBUG_ERROR("Failed to create mutex"); return -9; } // set maximum frames per slice as buffer size //UInt32 numFrames = (UInt32)consumer->ring.chunck.size; //status = AudioUnitSetProperty(tdav_audiounit_handle_get_instance(consumer->audioUnitHandle), // kAudioUnitProperty_MaximumFramesPerSlice, // kAudioUnitScope_Global, // 0, // &numFrames, // sizeof(numFrames)); //if(status){ // TSK_DEBUG_ERROR("AudioUnitSetProperty(kAudioUnitProperty_MaximumFramesPerSlice, %u) failed with status=%d", (unsigned)numFrames, (int32_t)status); // return -6; //} TSK_DEBUG_INFO("AudioUnit consumer prepared"); return tdav_audiounit_handle_signal_consumer_prepared(consumer->audioUnitHandle); }
/* Handles DTLS data received over the network using standard functions (e.g. recvfrom()) @param handle @param data When "use_srtp" is enabled this must point to DTLS handshake data. @param size DTLS data size @returns 0 if succeed, non-zero error code otherwise */ int tnet_dtls_socket_handle_incoming_data(tnet_dtls_socket_handle_t* handle, const void* data, tsk_size_t size) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); return -200; #else tnet_dtls_socket_t *socket = handle; int ret = 0; if (!socket || !data || !size) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } tsk_safeobj_lock(socket); TSK_DEBUG_INFO("Receive DTLS data: %lu", (unsigned long)size); // BIO_reset(socket->rbio); // BIO_reset(socket->wbio); if (!socket->rbio || !socket->wbio) { TSK_DEBUG_ERROR("BIO not initialized yet"); ret = -2; goto bail; } if ((ret = _tnet_dtls_socket_do_handshake(socket))) { goto bail; } if ((ret = BIO_write(socket->rbio, data, (int)size)) != size) { ret = SSL_get_error(socket->ssl, ret); TSK_DEBUG_ERROR("BIO_write(rbio, %lu) failed [%s]", (unsigned long)size, ERR_error_string(ERR_get_error(), tsk_null)); ret = -1; goto bail; } /*if((ret = SSL_read(socket->ssl, (void*)data, size)) <= 0){ switch((ret = SSL_get_error(socket->ssl, ret))){ case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: case SSL_ERROR_NONE: break; default: { unsigned long sslErr = ERR_get_error(); const uint8_t* pData = (const uint8_t*)data; TSK_DEBUG_ERROR("%lu = SSL_read(rbio, %u) failed [%s]", sslErr, size, ERR_error_string(ret, tsk_null)); // try to understand what's going on // rfc6347 - 4.1. Record Layer // rfc6347 - 4.2.2. Handshake Message Format // rfc6347 - 4.3.2. Handshake Protocol if(size > 14 && pData[0] == 0x16){ // content-type=='Handshake' if(pData[13] == 0x01 && (socket->setup == tnet_dtls_setup_active || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='client Hello' TSK_DEBUG_INFO("DTLS engine was in client mode but we are receiving 'Client Hello' messages. This is a bug in the remote peer: Re-negotiating!"); tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_passive); break; } else if(pData[13] == 0x02 && (socket->setup == tnet_dtls_setup_passive || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='server Hello' TSK_DEBUG_INFO("DTLS engine was in server mode but we are receiving 'Server Hello' messages. This is a bug in the remote peer: Re-negotiating!"); tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_active); break; } } //return -1; break; } } }*/ ret = _tnet_dtls_socket_do_handshake(socket); bail: tsk_safeobj_unlock(socket); return ret; #endif }
/** internal fuction used to config a SIP action */ int _tsip_action_set(tsip_action_handle_t* self, va_list* app) { tsip_action_param_type_t curr; tsip_action_t* action = self; if(!action){ /* Nothing to do */ return 0; } while((curr = va_arg(*app, tsip_action_param_type_t)) != aptype_null){ switch(curr){ case aptype_header: { /* (const char*)NAME_STR, (const char*)VALUE_STR */ const char* name = va_arg(*app, const char *); const char* value = va_arg(*app, const char *); tsk_params_add_param(&action->headers, name, value); break; } case aptype_config: { /* (const tsip_action_handle_t*)ACTION_CONFIG_HANDLE */ const tsip_action_t* handle = va_arg(*app, const tsip_action_handle_t *); if(handle && handle->type == tsip_atype_config){ /* Copy headers */ if(!TSK_LIST_IS_EMPTY(handle->headers)){ tsk_list_pushback_list(action->headers, handle->headers); } /* Copy payload */ if(handle->payload && handle->payload->data && handle->payload->size){ TSK_OBJECT_SAFE_FREE(action->payload); action->payload = tsk_buffer_create(handle->payload->data, handle->payload->size); } /* Copy resp line */ action->line_resp.code = handle->line_resp.code; tsk_strupdate(&action->line_resp.phrase, handle->line_resp.phrase); /* Copy media params */ if(!TSK_LIST_IS_EMPTY(handle->media.params)){ if(!action->media.params){ action->media.params = tmedia_params_create(); } tsk_list_pushback_list(action->media.params, handle->media.params); } } else if(handle){ /* Only invalid type should cause error */ TSK_DEBUG_ERROR("Invalid action configuration handle."); return -2; } break; } case aptype_payload: { /* (const void*)PAY_PTR, (tsk_size_t)PAY_SIZE */ const void* payload = va_arg(*app, const void *); tsk_size_t size = va_arg(*app, tsk_size_t); if(payload && size){ TSK_OBJECT_SAFE_FREE(action->payload); action->payload = tsk_buffer_create(payload, size); } break; } case aptype_resp_line: { /* (int32_t)CODE_INT, (const char*)PHRASE_STR */ int32_t code = va_arg(*app, int32_t); const char* phrase = va_arg(*app, const void *); action->line_resp.code = (short)code; tsk_strupdate(&action->line_resp.phrase, phrase); break; } case aptype_media: { /* ... */ tmedia_params_L_t* params; if((params = tmedia_params_create_2(app))){ if(action->media.params){ tsk_list_pushback_list(action->media.params, params); } else{ action->media.params = tsk_object_ref(params); } TSK_OBJECT_SAFE_FREE(params); } break; } default: { /* va_list will be unsafe ==> exit */ TSK_DEBUG_ERROR("NOT SUPPORTED."); return -3; } } /* switch */ } /* while */ return 0; }
/** * Connects a socket. * @param handle The transport to use to connect() the socket. The new socket will be managed by this transport. * @param host The remote @a host to connect() to. * @param port The remote @a port to connect() to. * @param type The type of the socket to use to connect() to the remote @a host. * @retval The newly connected socket. For non-blocking sockets you should use @ref tnet_sockfd_waitUntilWritable to check * the socket for writability. * @sa tnet_sockfd_waitUntilWritable. */ tnet_fd_t tnet_transport_connectto(const tnet_transport_handle_t *handle, const char* host, tnet_port_t port, tnet_socket_type_t type) { tnet_transport_t *transport = (tnet_transport_t*)handle; struct sockaddr_storage to; int status = -1; tnet_fd_t fd = TNET_INVALID_FD; tnet_tls_socket_handle_t* tls_handle = tsk_null; if(!transport || !transport->master){ TSK_DEBUG_ERROR("Invalid transport handle"); goto bail; } if((TNET_SOCKET_TYPE_IS_STREAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_STREAM(type)) || (TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_DGRAM(type))){ TSK_DEBUG_ERROR("Master/destination types mismatch [%u/%u]", transport->master->type, type); goto bail; } /* Init destination sockaddr fields */ if((status = tnet_sockaddr_init(host, port, type, &to))){ TSK_DEBUG_ERROR("Invalid HOST/PORT [%s/%u]", host, port); goto bail; } else if(TNET_SOCKET_TYPE_IS_IPV46(type)){ /* Update the type (unambiguously) */ if(to.ss_family == AF_INET6){ TNET_SOCKET_TYPE_SET_IPV6Only(type); } else{ TNET_SOCKET_TYPE_SET_IPV4Only(type); } } /* * STREAM ==> create new socket and connect it to the remote host. * DGRAM ==> connect the master to the remote host. */ if(TNET_SOCKET_TYPE_IS_STREAM(type)){ /* Create client socket descriptor. */ if((status = tnet_sockfd_init(transport->local_host, TNET_SOCKET_PORT_ANY, type, &fd))){ TSK_DEBUG_ERROR("Failed to create new sockfd."); goto bail; } } else{ fd = transport->master->fd; } if((status = tnet_sockfd_connectto(fd, (const struct sockaddr_storage *)&to))){ if(fd != transport->master->fd){ tnet_sockfd_close(&fd); } goto bail; } else{ static const tsk_bool_t __isClient = tsk_true; static const tsk_bool_t __takeOwnership = tsk_true; if(TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)){ #if HAVE_OPENSSL tls_handle = tnet_tls_socket_create(fd, transport->tls.ctx_client); if((status = tnet_tls_socket_connect(tls_handle))){ tnet_sockfd_close(&fd); goto bail; } #endif } /* Add the socket */ // socket must be added after connect() otherwise many Linux systems when return POLLHUP as the fd is not active yet if((status = tnet_transport_add_socket(handle, fd, type, __takeOwnership, __isClient, tls_handle))){ TNET_PRINT_LAST_ERROR("Failed to add new socket"); tnet_sockfd_close(&fd); goto bail; } } bail: TSK_OBJECT_SAFE_FREE(tls_handle); return fd; }
int execute(const cmd_t* cmd) { int ret = 0; tsip_ssession_id_t sid; tsk_istr_t istr; if(!cmd){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } tsk_safeobj_lock(ctx); switch(cmd->type){ case cmd_audio: case cmd_audiovideo: { TSK_DEBUG_INFO("command=audio/video"); if((sid = invite_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){ if(cmd->sidparam){ tsk_itoa(sid, &istr); update_param(cmd->sidparam, istr); } } break; } case cmd_config_session: { TSK_DEBUG_INFO("command=config-session"); break; } case cmd_config_stack: { TSK_DEBUG_INFO("command=config-satck"); ret = stack_config(cmd->opts); break; } case cmd_dtmf: { const opt_t* opt; TSK_DEBUG_INFO("command=dtmf"); if(!(opt = opt_get_by_type(cmd->opts, opt_sid)) || tsk_strnullORempty(opt->value)){ /* --sid option */ TSK_DEBUG_ERROR("++dtmf command need --sid option"); break; } if(!(opt = opt_get_by_type(cmd->opts, opt_event)) || tsk_strnullORempty(opt->value)){ /* --event option */ TSK_DEBUG_ERROR("++dtmf command need --event option"); break; } invite_handle_cmd(cmd->type, cmd->opts); break; } case cmd_dump: { TSK_DEBUG_INFO("command=dump"); ret = stack_dump(); break; } case cmd_ect: { const opt_t* opt; TSK_DEBUG_INFO("command=ect"); if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)){ TSK_DEBUG_ERROR("++ect command need --sid option"); ret = -1; break; } if((opt = opt_get_by_type(cmd->opts, opt_to)) && !tsk_strnullORempty(opt->value)){ TSK_DEBUG_ERROR("++ect command need --to option"); ret = -1; break; } invite_handle_cmd(cmd->type, cmd->opts); break; } case cmd_exit: { TSK_DEBUG_INFO("command=exit"); goto bail; break; } case cmd_file: { const opt_t* opt; TSK_DEBUG_INFO("command=file"); if(!(opt = opt_get_by_type(cmd->opts, opt_path)) || tsk_strnullORempty(opt->value)){ TSK_DEBUG_ERROR("++file command need --path option"); break; } if((sid = invite_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){ if(cmd->sidparam){ tsk_itoa(sid, &istr); update_param(cmd->sidparam, istr); } } break; } case cmd_hangup: { const opt_t* opt; TSK_DEBUG_INFO("command=hangup"); if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)){ /* --sid option */ ret = session_hangup(tsk_atoll(opt->value)); } else{ TSK_DEBUG_ERROR("++hangup command need --sid option"); ret = -1; } break; } case cmd_help: { TSK_DEBUG_INFO("command=help"); cmd_print_help(); break; } case cmd_hold: { const opt_t* opt; TSK_DEBUG_INFO("command=hold"); if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)){ /* --sid option */ invite_handle_cmd(cmd->type, cmd->opts); } else{ TSK_DEBUG_ERROR("++hold command need --sid option"); ret = -1; } break; } case cmd_message: { TSK_DEBUG_INFO("command=message"); if((sid = message_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){ if(cmd->sidparam){ tsk_itoa(sid, &istr); update_param(cmd->sidparam, istr); } } break; } case cmd_options: { TSK_DEBUG_INFO("command=options"); if((sid = options_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){ if(cmd->sidparam){ tsk_itoa(sid, &istr); update_param(cmd->sidparam, istr); } } break; } case cmd_publish: { TSK_DEBUG_INFO("command=publish"); if((sid = publish_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){ if(cmd->sidparam){ tsk_itoa(sid, &istr); update_param(cmd->sidparam, istr); } } break; } case cmd_register: { TSK_DEBUG_INFO("command=register"); if((sid = register_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){ if(cmd->sidparam){ tsk_itoa(sid, &istr); update_param(cmd->sidparam, istr); } } break; } case cmd_resume: { const opt_t* opt; TSK_DEBUG_INFO("command=resume"); if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)){ /* --sid option */ invite_handle_cmd(cmd->type, cmd->opts); } else{ TSK_DEBUG_ERROR("++resume command need --sid option"); ret = -1; } break; } case cmd_run: { TSK_DEBUG_INFO("command=run"); ret = stack_run(cmd->opts); break; } case cmd_scenario: { TSK_DEBUG_INFO("command=scenario"); break; } case cmd_sleep: { const opt_t* opt; double seconds; tsk_safeobj_unlock(ctx); /* beacuse of callback function */ if((opt = opt_get_by_type(cmd->opts, opt_sec)) && !tsk_strnullORempty(opt->value)){ /* --sec option */ seconds = strtod(opt->value, tsk_null); /* strtod() is better than atof() */ if(seconds<=0){ printf("\n==== Press ENTER to continue...\n"); getchar(); } else{ TSK_DEBUG_INFO("Sleeping %f seconds", seconds); tsk_thread_sleep((uint64_t)(seconds * 1000)); } } else{ TSK_DEBUG_WARN("++sleep need --sec option."); } return 0; /* bail: will unlock again */ } case cmd_sms: { TSK_DEBUG_INFO("command=sms"); if((sid = message_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){ if(cmd->sidparam){ tsk_itoa(sid, &istr); update_param(cmd->sidparam, istr); } } break; } case cmd_stop: { TSK_DEBUG_INFO("command=stop"); tsip_stack_stop(ctx->stack); break; } case cmd_subscribe: { TSK_DEBUG_INFO("command=subscribe"); if((sid = subscribe_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){ if(cmd->sidparam){ tsk_itoa(sid, &istr); update_param(cmd->sidparam, istr); } } break; } case cmd_video: { TSK_DEBUG_INFO("command=video"); break; } default: { TSK_DEBUG_ERROR("%d not a valid command.", cmd); break; } } bail: tsk_safeobj_unlock(ctx); return ret; }
static int tdav_webrtc_denoise_open(tmedia_denoise_t* self, uint32_t frame_size, uint32_t sampling_rate) { tdav_webrtc_denoise_t *denoiser = (tdav_webrtc_denoise_t *)self; int ret; if(!denoiser){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(denoiser->AEC_inst || #if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER denoiser->SpeexDenoiser_proc #else denoiser->NS_inst #endif ){ TSK_DEBUG_ERROR("Denoiser already initialized"); return -2; } denoiser->echo_tail = TSK_CLAMP(WEBRTC_MIN_ECHO_TAIL, TMEDIA_DENOISE(denoiser)->echo_tail, WEBRTC_MAX_ECHO_TAIL); TSK_DEBUG_INFO("echo_tail=%d", denoiser->echo_tail); denoiser->echo_skew = TMEDIA_DENOISE(denoiser)->echo_skew; denoiser->frame_size = frame_size; denoiser->sampling_rate = sampling_rate; // // AEC instance // if((ret = TDAV_WebRtcAec_Create(&denoiser->AEC_inst))){ TSK_DEBUG_ERROR("WebRtcAec_Create failed with error code = %d", ret); return ret; } if((ret = TDAV_WebRtcAec_Init(denoiser->AEC_inst, denoiser->sampling_rate, denoiser->sampling_rate))){ TSK_DEBUG_ERROR("WebRtcAec_Init failed with error code = %d", ret); return ret; } #if WEBRTC_AEC_AGGRESSIVE { AecConfig aecConfig; aecConfig.nlpMode = kAecNlpAggressive; aecConfig.skewMode = kAecTrue; aecConfig.metricsMode = kAecFalse; aecConfig.delay_logging = kAecFalse; if((ret = WebRtcAec_set_config(denoiser->AEC_inst, aecConfig))){ TSK_DEBUG_ERROR("WebRtcAec_set_config failed with error code = %d", ret); } } #endif // // Noise Suppression instance // if(TMEDIA_DENOISE(denoiser)->noise_supp_enabled){ #if HAVE_SPEEX_DSP && PREFER_SPEEX_DENOISER if((denoiser->SpeexDenoiser_proc = speex_preprocess_state_init(denoiser->frame_size, denoiser->sampling_rate))){ int i = 1; speex_preprocess_ctl(denoiser->SpeexDenoiser_proc, SPEEX_PREPROCESS_SET_DENOISE, &i); i = TMEDIA_DENOISE(denoiser)->noise_supp_level; speex_preprocess_ctl(denoiser->SpeexDenoiser_proc, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i); } #else if((ret = TDAV_WebRtcNs_Create(&denoiser->NS_inst))){ TSK_DEBUG_ERROR("WebRtcNs_Create failed with error code = %d", ret); return ret; } if((ret = TDAV_WebRtcNs_Init(denoiser->NS_inst, denoiser->sampling_rate))){ TSK_DEBUG_ERROR("WebRtcNs_Init failed with error code = %d", ret); return ret; } #endif } // allocate temp buffer for record processing if(!(denoiser->temp_rec_out = tsk_realloc(denoiser->temp_rec_out, denoiser->frame_size * kSizeOfWord16))){ TSK_DEBUG_ERROR("Failed to allocate new buffer"); return -3; } TSK_DEBUG_INFO("WebRTC denoiser opened"); return ret; }
/* === entry point === */ int main(int argc, char** argv) { char cmdbuf[4096]; tsk_buffer_t* buffer = tsk_null; cmd_t* cmd = tsk_null; tsk_bool_t comment = tsk_false; int ret; int i, index; const char* start = tsk_null, *end = tsk_null; int a = 32 | 1 | 2; /* Copyright */ printf("Doubango Project (tinyDEMO)\nCopyright (C) 2009 - 2013 Mamadou Diop \n\n"); /* Initialize Network Layer ==> Mandatory */ tnet_startup(); /* Initialize Doubango Audio/Video Framework ==> will register all plugins(codecs and sessions) * Not mandatory if you have your own plugins*/ tdav_init(); /* Print Usage */ //cmd_print_help(); /* create user's ctx */ if(!(ctx = ctx_create()) || !ctx->stack){ TSK_DEBUG_ERROR("Failed to create user's ctx."); goto bail; } /* create new buffer */ if(!(buffer = tsk_buffer_create_null())){ TSK_DEBUG_ERROR("Failed to create new buffer."); goto bail; } /* initial args */ for(i=1 /* index zero contains the exe path */, index=0; i<argc && argv[i]; i++){ if(index){ tsk_buffer_append(buffer, " ", 1); } tsk_buffer_append(buffer, argv[i], tsk_strlen(argv[i])); } /* If initial args ==> parse it now */ if(buffer->size){ TSK_DEBUG_INFO("Initial command-line: %s", buffer->data); goto init_buffer; } /* always use fgets() instead of gets. gets() is considered to be unsafe.(Android and Mac OS X will warn) */ while(fgets(cmdbuf, sizeof(cmdbuf), stdin)){ TSK_DEBUG_INFO("Command-Line: %s", cmdbuf); tsk_buffer_cleanup(buffer); /* cannot read from console while executing scenario */ tsk_buffer_append(buffer, cmdbuf, tsk_strlen(cmdbuf)); init_buffer: start = buffer->data; //start = trim(start); end = start + buffer->size; if(start >= end){ TSK_DEBUG_INFO("Empty buffer"); continue; } parse_buffer: TSK_OBJECT_SAFE_FREE(cmd); /* Free old value */ cmd = cmd_parse(start, (end-start), &comment, ctx->params); if(cmd){ if(comment || cmd->type == cmd_none){ goto nex_line; } } else{ continue; } /* Load from scenario file? */ if(cmd->type == cmd_scenario){ FILE* file; const opt_t* opt; tsk_size_t read = 0; tsk_bool_t rm_lf = tsk_false; if((opt = opt_get_by_type(cmd->opts, opt_path)) && !tsk_strnullORempty(opt->value)){ /* --path option */ if((file = fopen(opt->value, "r"))){ memset(cmdbuf, '\0', sizeof(cmdbuf)), cmdbuf[0] = '\n'; read = fread(cmdbuf+1, sizeof(uint8_t), sizeof(cmdbuf)-1, file); fclose(file), file = tsk_null; if(read == 0){ TSK_DEBUG_ERROR("[%s] is empty.", opt->value); goto nex_line; } else if(read == sizeof(cmdbuf)-1){ TSK_DEBUG_ERROR("Buffer too short."); goto nex_line; } read++; /* \n */ /* repplace all '\' with spaces (easier than handling that in the ragel file) */ for(i=0; ((tsk_size_t)i)<read; i++){ if(cmdbuf[i] == '\\'){ cmdbuf[i] = ' '; rm_lf = tsk_true; } else if(rm_lf && cmdbuf[i] == '\n'){ cmdbuf[i] = ' '; rm_lf = tsk_false; } } cmdbuf[read] = '\n'; /* insert embedded scenario */ if((index = tsk_strindexOf(start, (end-start), "\n")) == -1){ /* ++sn line */ index = buffer->size; } else{ index += (start - ((const char*)buffer->data)); } if(tsk_buffer_insert(buffer, index, cmdbuf, read)){ continue; } else{ start = ((const char*)buffer->data) + index; // because insert use realloc() end = (((const char*)buffer->data) + buffer->size); goto nex_line; } } else{ TSK_DEBUG_ERROR("Failed to open scenario-file [%s].", opt->value); goto nex_line; } continue; } else{ TSK_DEBUG_ERROR("++scenario command must have --path option."); continue; } } /* execute current command */ switch(cmd->type){ case cmd_exit: TSK_DEBUG_INFO("Exit/Quit"); goto bail; default: ret = execute(cmd); break; } /* next line */ nex_line: if((index = tsk_strindexOf(start, (end - start), "\n")) !=-1){ start += index; while((start < end) && isspace(*start)){ start ++; } if((start + 2/*++*/) < end){ goto parse_buffer; /* next line */ } else{ continue; /* wait for new commands */ } } } /* while(buffer) */ bail: /* Free current command */ TSK_OBJECT_SAFE_FREE(cmd); /* Free buffer */ TSK_OBJECT_SAFE_FREE(buffer); /* Destroy the user's ctx */ TSK_OBJECT_SAFE_FREE(ctx); /* Deinitialize Doubango Audio/Video Framework ==> will unregister all plugins(codecs and sessions) * Not mandatory */ tdav_init(); /* Uninitilize Network Layer */ tnet_cleanup(); #if ANDROID exit(0); #endif return 0; }
int tipsec_set_SAs(tipsec_context_xp_t* ctx_xp) { int ret = -1; FILE* file = NULL; char* str = NULL; if(!ctx_xp){ goto bail; } if(TIPSEC_CONTEXT(ctx_xp)->state != state_full){ TSK_DEBUG_ERROR("IPSec context is in the wrong state."); ret = -3; goto bail; } if(!(file = fopen(TINYIPSEC_IPSEC6_FILE_SAD, "wb+"))){ TSK_DEBUG_ERROR("Failed to open file [%s].", TINYIPSEC_IPSEC6_FILE_SAD); ret = -4; goto bail; } tsk_sprintf(&str, TINYIPSEC_IPSEC6_TEMPLATE_SA, /* PC -> US */ "1", // SAEntry TIPSEC_CONTEXT(ctx_xp)->spi_us, // SPI TIPSEC_CONTEXT(ctx_xp)->addr_local, // SADestIPAddr "POLICY", // DestIPAddr "POLICY", // SrcIPAddr "POLICY", // Protocol "POLICY", // DestPort "POLICY", // SrcPort TINYIPSEC_XP_GET_ALGO(TIPSEC_CONTEXT(ctx_xp)->alg), // AuthAlg TINYIPSEC_IPSEC6_FILE_KEY, // KeyFile "INBOUND", // Direction "0", /* SecPolicyIndex */ /* US -> PC */ "2", // SAEntry TIPSEC_CONTEXT(ctx_xp)->spi_pc, // SPI TIPSEC_CONTEXT(ctx_xp)->addr_remote, // SADestIPAddr "POLICY", // DestIPAddr "POLICY", // SrcIPAddr "POLICY", // Protocol "POLICY", // DestPort "POLICY", // SrcPort TINYIPSEC_XP_GET_ALGO(TIPSEC_CONTEXT(ctx_xp)->alg), // AuthAlg TINYIPSEC_IPSEC6_FILE_KEY, // KeyFile "OUTBOUND", // Direction "0", /* SecPolicyIndex */ /* PS -> UC */ "3", // SAEntry TIPSEC_CONTEXT(ctx_xp)->spi_uc, // SPI TIPSEC_CONTEXT(ctx_xp)->addr_local, // SADestIPAddr "POLICY", // DestIPAddr "POLICY", // SrcIPAddr "POLICY", // Protocol "POLICY", // DestPort "POLICY", // SrcPort TINYIPSEC_XP_GET_ALGO(TIPSEC_CONTEXT(ctx_xp)->alg), // AuthAlg TINYIPSEC_IPSEC6_FILE_KEY, // KeyFile "INBOUND", // Direction "0", /* SecPolicyIndex */ /* UC -> PS */ "4", // SAEntry TIPSEC_CONTEXT(ctx_xp)->spi_ps, // SPI TIPSEC_CONTEXT(ctx_xp)->addr_remote, // SADestIPAddr "POLICY", // DestIPAddr "POLICY", // SrcIPAddr "POLICY", // Protocol "POLICY", // DestPort "POLICY", // SrcPort TINYIPSEC_XP_GET_ALGO(TIPSEC_CONTEXT(ctx_xp)->alg), // AuthAlg TINYIPSEC_IPSEC6_FILE_KEY, // KeyFile "OUTBOUND", // Direction "0" /* SecPolicyIndex */ ); fwrite(str, tsk_strlen(str), sizeof(uint8_t), file); ret = 0; bail: if(file){ fclose(file); } if(str){ TSK_FREE(str); } return ret; }
// @param str e.g. "1 1 udp 1 192.168.196.1 57806 typ host name video_rtcp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username StFEVThMK2DHThkv password qkhKUDr4WqKRwZTo generation 0" tnet_ice_candidate_t* tnet_ice_candidate_parse(const char* str) { char *v, *copy; int32_t k; tnet_ice_candidate_t* candidate; if(tsk_strnullORempty(str)){ TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } if(!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))){ TSK_DEBUG_ERROR("Failed to create candidate"); return tsk_null; } k = 0; copy = tsk_strdup(str); v = strtok(copy, " "); while(v){ switch(k){ case 0: { memcpy(candidate->foundation, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->foundation))); break; } case 1: { candidate->comp_id = atoi(v); break; } case 2: { candidate->transport_str = tsk_strdup(v); break; } case 3: { candidate->priority = atoi(v); break; } case 4: { memcpy(candidate->connection_addr, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->connection_addr))); break; } case 5: { tnet_family_t family; candidate->port = atoi(v); family = tnet_get_family(candidate->connection_addr, candidate->port); candidate->transport_e = _tnet_ice_candidate_get_transport_type((family == AF_INET6), candidate->transport_str); break; } case 6: { v = strtok(tsk_null, " "); tsk_strupdate(&candidate->cand_type_str, v); candidate->type_e = _tnet_ice_candtype_get_transport_type(v); break; } default: { const char* name = v; const char* value = (v = strtok(tsk_null, " ")); tsk_param_t* param = tsk_param_create(name, value); if(param){ tsk_list_push_back_data(candidate->extension_att_list, (void**)¶m); } break; } } ++k; v = strtok(tsk_null, " "); } if(k < 6){ TSK_DEBUG_ERROR("Failed to parse: %s", str); TSK_OBJECT_SAFE_FREE(candidate); } TSK_FREE(copy); return candidate; }
/**@ingroup tmedia_codec_group * Serialize a list of codecs to sdp (m= line) message.<br> * Will add: fmt, rtpmap and fmtp. * @param codecs The list of codecs to convert * @param m The destination * @retval Zero if succeed and non-zero error code otherwise */ int tmedia_codec_to_sdp(const tmedia_codecs_L_t* codecs, tsdp_header_M_t* m) { const tsk_list_item_t* item; const tmedia_codec_t* codec; char *fmtp, *rtpmap, *imageattr; tsk_bool_t is_audio, is_video, is_text; int ret; if(!m) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } is_audio = tsk_striequals(m->media, "audio"); is_video = tsk_striequals(m->media, "video"); is_text = tsk_striequals(m->media, "text"); tsk_list_foreach(item, codecs) { const char *neg_format; codec = item->data; /* add fmt */ neg_format = codec->neg_format? codec->neg_format : codec->format; if((ret = tsdp_header_M_add_fmt(m, neg_format))) { TSK_DEBUG_ERROR("Failed to add format"); return ret; } if(is_audio || is_video || is_text) { char* temp = tsk_null; /* add rtpmap attributes */ if((rtpmap = tmedia_codec_get_rtpmap(codec))) { tsdp_header_M_add_headers(m, TSDP_HEADER_A_VA_ARGS("rtpmap", rtpmap), tsk_null); TSK_FREE(rtpmap); } /* add 'imageattr' attributes */ if((imageattr = tmedia_codec_sdp_att_get(codec, "imageattr"))) { tsk_sprintf(&temp, "%s %s", neg_format, imageattr); tsdp_header_M_add_headers(m, TSDP_HEADER_A_VA_ARGS("imageattr", temp), tsk_null); TSK_FREE(temp); TSK_FREE(imageattr); } /* add fmtp attributes */ if((fmtp = tmedia_codec_sdp_att_get(codec, "fmtp"))) { if(is_video && tmedia_defaults_get_screen_x() > 0 && tmedia_defaults_get_screen_y() > 0) { tsk_sprintf(&temp, "%s %s;sx=%d;sy=%d", neg_format, fmtp, tmedia_defaults_get_screen_x(), tmedia_defaults_get_screen_y());//doubango clients } else { tsk_sprintf(&temp, "%s %s", neg_format, fmtp); } tsdp_header_M_add_headers(m, TSDP_HEADER_A_VA_ARGS("fmtp", temp), tsk_null); TSK_FREE(temp); TSK_FREE(fmtp); } /* special case for T.140 + red */ if(is_text && tsk_striequals(codec->format, TMEDIA_CODEC_FORMAT_RED)) { const tmedia_codec_t* codec_t140 = tsk_list_find_object_by_pred(codecs, __pred_find_codec_by_format, TMEDIA_CODEC_FORMAT_T140); if(codec_t140) { const char* neg_format_t140 = codec_t140->neg_format? codec_t140->neg_format : codec_t140->format; tsk_sprintf(&temp, "%s %s/%s/%s/%s", neg_format, neg_format_t140, neg_format_t140, neg_format_t140, neg_format_t140); tsdp_header_M_add_headers(m, TSDP_HEADER_A_VA_ARGS("fmtp", temp), tsk_null); TSK_FREE(temp); } } } } return 0; }
const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self) { const char* _transport_str; char __str[16]; // always allocated: bad idea :( if(!self){ TSK_DEBUG_ERROR("Invalid argument"); return tsk_null; } _transport_str = self->transport_str ? self->transport_str : _tnet_ice_candidate_get_transport_str(self->transport_e); if(self->is_ice_jingle){ tsk_size_t i, s = tsk_strlen(_transport_str); memset(__str, 0, sizeof(__str)); for(i = 0; i < s && i < sizeof(__str)/sizeof(__str[0]); ++i){ __str[i] = tolower(_transport_str[i]); } _transport_str = &__str[0]; } _tnet_ice_candidate_tostring( self->foundation, self->comp_id, _transport_str, self->priority, (tsk_strnullORempty(self->connection_addr) && self->socket) ? self->socket->ip : self->connection_addr, (self->port <= 0 && self->socket) ? self->socket->port : self->port, self->cand_type_str ? self->cand_type_str : _tnet_ice_candidate_get_candtype_str(self->type_e), self->extension_att_list, &self->tostring); /* <rel-addr> and <rel-port>: convey transport addresses related to the candidate, useful for diagnostics and other purposes. <rel-addr> and <rel-port> MUST be present for server reflexive, peer reflexive, and relayed candidates. */ switch(self->type_e){ case tnet_ice_cand_type_srflx: case tnet_ice_cand_type_prflx: case tnet_ice_cand_type_relay: { if(self->socket){ // when called from the browser(IE, Safari, Opera or Firefox) webrtc4all tsk_strcat_2(&self->tostring, " raddr %s rport %d", self->socket->ip, self->socket->port); } break; } } // WebRTC (Chrome) specific if(self->is_ice_jingle){ if(!tsk_params_have_param(self->extension_att_list, "name")){ tsk_strcat_2(&self->tostring, " name %s", self->is_rtp ? (self->is_video ? "video_rtp" : "rtp") : (self->is_video ? "video_rtcp" : "rtcp")); } if(!tsk_params_have_param(self->extension_att_list, "username")){ tsk_strcat_2(&self->tostring, " username %s", self->ufrag); } if(!tsk_params_have_param(self->extension_att_list, "password")){ tsk_strcat_2(&self->tostring, " password %s", self->pwd); } if(!tsk_params_have_param(self->extension_att_list, "network_name")){ tsk_strcat_2(&self->tostring, " network_name %s", "{9EBBE687-CCE6-42D3-87F5-B57BB30DEE23}"); } if(!tsk_params_have_param(self->extension_att_list, "generation")){ tsk_strcat_2(&self->tostring, " generation %s", "0"); } } return self->tostring; }
/**@ingroup tmedia_codec_group */ int tmedia_codec_parse_fmtp(const char* fmtp, unsigned* maxbr, unsigned* fps, unsigned *width, unsigned *height) { char *copy, *pch, *saveptr; tsk_bool_t found = tsk_false; if(tsk_strnullORempty(fmtp)) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } copy = tsk_strdup(fmtp); pch = tsk_strtok_r(copy, "; /", &saveptr); while(pch) { unsigned div = 0; if(sscanf(pch, "QCIF=%u", &div) == 1 && div) { *fps = 30/div; *width = 176; *height = 144; found = tsk_true; } else if(sscanf(pch, "CIF=%u", &div) == 1 && div) { *fps = 30/div; *width = 352; *height = 288; found = tsk_true; } else if(sscanf(pch, "SQCIF=%u", &div) == 1 && div) { *fps = 30/div; *width = 128; *height = 96; found = tsk_true; } else if(sscanf(pch, "QVGA=%u", &div) == 1 && div) { *fps = 30/div; *width = 320; *height = 240; found = tsk_true; } // to be continued if(found) { //found = tsk_false; pch = tsk_strtok_r(tsk_null, "; ", &saveptr); while(pch) { if(sscanf(pch, "MaxBR=%u", maxbr) == 1) { //found = tsk_true; break; } pch = tsk_strtok_r(tsk_null, "; /", &saveptr); } } if(found) { break; } pch = tsk_strtok_r(tsk_null, "; /", &saveptr); } TSK_FREE(copy); return found ? 0 : -2; }
/*=== Main thread */ void *tnet_transport_mainthread(void *param) { tnet_transport_t *transport = param; transport_context_t *context = transport->context; int i; /* check whether the transport is already prepared */ if (!transport->prepared) { TSK_DEBUG_ERROR("Transport must be prepared before strating."); goto bail; } TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d}...", transport->description, transport->master->ip, transport->master->port); // Set the RunLoop of the context context->cf_run_loop = CFRunLoopGetCurrent(); while(TSK_RUNNABLE(transport)->running) { // Check if new socket were added and wrap them. // We go backward as new socket are always added at the end. for(i = context->count - 1; i >= 0; i--) { if (tnet_transport_wrap(transport, i)) { break; } } // Give some time to process sources CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); if (!TSK_RUNNABLE(transport)->running) { goto bail; } } // Remove all the sockets, streams and sources from the run loop for(i = 0; i < context->count; i++) { transport_context_t *context = transport->context; transport_socket_t *sock = context->sockets[i]; if (sock) { continue; } if (sock->cf_run_loop_source) { CFRunLoopRemoveSource(context->cf_run_loop, sock->cf_run_loop_source, kCFRunLoopDefaultMode); } if (sock->cf_read_stream) { //CFReadStreamClose(sock->cf_read_stream); CFReadStreamUnscheduleFromRunLoop(sock->cf_read_stream, context->cf_run_loop, kCFRunLoopDefaultMode); } if (sock->cf_write_stream) { //CFWriteStreamClose(sock->cf_write_stream); CFWriteStreamUnscheduleFromRunLoop(sock->cf_write_stream, context->cf_run_loop, kCFRunLoopDefaultMode); } } bail: TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d}...", transport->description, transport->master->ip, transport->master->port); return 0; }