/** * Execute function for each subscriber */ static void subscriber_execute(const char *uuid, const char *signal_type, subscriber_execute_fn callback, void *user_data) { switch_event_t *subscriber_list = NULL; switch_event_header_t *subscriber = NULL; /* fetch list of subscribers */ char *key = switch_mprintf("%s:%s", uuid, signal_type); switch_event_create_subclass(&subscriber_list, SWITCH_EVENT_CLONE, NULL); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Subscriber execute %s\n", signal_type); switch_mutex_lock(globals.subscribers_mutex); { switch_hash_index_t *hi = NULL; switch_hash_t *signal_subscribers = switch_core_hash_find(globals.subscribers, key); if (signal_subscribers) { for (hi = switch_core_hash_first(signal_subscribers); hi; hi = switch_core_hash_next(hi)) { const void *jid; void *dont_care; switch_core_hash_this(hi, &jid, NULL, &dont_care); switch_event_add_header_string(subscriber_list, SWITCH_STACK_BOTTOM, "execute", (const char *)jid); } } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "No subscribers for %s\n", signal_type); } } switch_mutex_unlock(globals.subscribers_mutex); switch_safe_free(key); /* execute function for each subscriber */ for (subscriber = subscriber_list->headers; subscriber; subscriber = subscriber->next) { callback(subscriber->value, user_data); } switch_event_destroy(&subscriber_list); }
/** * Process a tag */ static int tag_hook(void *user_data, char *name, char **atts, int type) { int result = IKS_OK; struct nlsml_parser *parser = (struct nlsml_parser *)user_data; if (type == IKS_OPEN || type == IKS_SINGLE) { struct nlsml_node *child_node = malloc(sizeof(*child_node)); child_node->name = name; child_node->tag_def = switch_core_hash_find(globals.tag_defs, name); if (!child_node->tag_def) { child_node->tag_def = switch_core_hash_find(globals.tag_defs, "ANY"); } child_node->parent = parser->cur; parser->cur = child_node; switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_DEBUG1, "<%s>\n", name); result = process_tag(parser, name, atts); } if (type == IKS_CLOSE || type == IKS_SINGLE) { struct nlsml_node *node = parser->cur; parser->cur = node->parent; free(node); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_DEBUG1, "</%s>\n", name); } return result; }
/** * Parse the result, looking for noinput/nomatch/match * @param result the NLSML result to parse * @param uuid optional UUID for logging * @return true if successful */ enum nlsml_match_type nlsml_parse(const char *result, const char *uuid) { struct nlsml_parser parser = { 0 }; parser.uuid = uuid; if (!zstr(result)) { iksparser *p = iks_sax_new(&parser, tag_hook, cdata_hook); if (iks_parse(p, result, 0, 1) == IKS_OK) { /* check result */ if (parser.match) { return NMT_MATCH; } if (parser.nomatch) { return NMT_NOMATCH; } if (parser.noinput) { return NMT_NOINPUT; } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser.uuid), SWITCH_LOG_INFO, "NLSML result does not have match/noinput/nomatch!\n"); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser.uuid), SWITCH_LOG_INFO, "Failed to parse NLSML!\n"); } iks_parser_delete(p); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser.uuid), SWITCH_LOG_INFO, "Missing NLSML result\n"); } return NMT_BAD_XML; }
bool WSClientParser::Login() { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_INFO, "WSClientParser::Login( " "this : %p, " "user : '******', " "domain : '%s', " "site : '%s', " "custom : '%s' " ") \n", this, mpUser, mpDomain, mpSite, mpCustom ); bool bFlag = true; // 暂时不做PHP验证 switch_event_t *locate_params; switch_xml_t xml = NULL; switch_event_create(&locate_params, SWITCH_EVENT_GENERAL); switch_assert(locate_params); switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "source", "mod_ws"); switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "site", mpSite); switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "custom", mpCustom); /* Locate user */ if (switch_xml_locate_user_merged("id", mpUser, mpDomain, NULL, &xml, locate_params) != SWITCH_STATUS_SUCCESS) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_ERROR, "WSClientParser::Login( " "[Fail], " "this : %p, " "user : '******', " "domain : '%s' ", this, mpUser, mpDomain ); bFlag = false; } switch_event_destroy(&locate_params); // 发送登录成功事件 ws_login(); return bFlag; }
/** * Forward CPA signal to client */ static void rayo_cpa_detector_event(const char *jid, void *user_data) { struct rayo_actor *component = RAYO_LOCATE(jid); if (component) { if (CPA_COMPONENT(component)->ready) { switch_event_t *event = (switch_event_t *)user_data; const char *signal_type = switch_event_get_header(event, "signal-type"); struct cpa_signal *cpa_signal = switch_core_hash_find(CPA_COMPONENT(component)->signals, signal_type); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_COMPONENT(component)->parent->id), SWITCH_LOG_DEBUG, "Handling CPA event\n"); if (cpa_signal) { const char *value = switch_event_get_header(event, "value"); const char *duration = switch_event_get_header(event, "duration"); if (cpa_signal->terminate) { iks *complete_event; iks *signal_xml; stop_cpa_detectors(CPA_COMPONENT(component)); /* send complete event to client */ complete_event = rayo_component_create_complete_event(RAYO_COMPONENT(component), "signal", RAYO_CPA_NS); signal_xml = iks_find(complete_event, "complete"); signal_xml = iks_find(signal_xml, "signal"); iks_insert_attrib(signal_xml, "type", signal_type); if (!zstr(value)) { iks_insert_attrib(signal_xml, "value", value); } if (!zstr(duration)) { iks_insert_attrib(signal_xml, "duration", duration); } rayo_component_send_complete_event(RAYO_COMPONENT(component), complete_event); } else { /* send event to client */ iks *signal_event = iks_new_presence("signal", RAYO_CPA_NS, RAYO_JID(component), RAYO_COMPONENT(component)->client_jid); iks *signal_xml = iks_find(signal_event, "signal"); iks_insert_attrib(signal_xml, "type", signal_type); if (!zstr(value)) { iks_insert_attrib(signal_xml, "value", value); } if (!zstr(duration)) { iks_insert_attrib(signal_xml, "duration", duration); } RAYO_SEND_REPLY(component, RAYO_COMPONENT(component)->client_jid, signal_event); } } } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(RAYO_COMPONENT(component)->parent->id), SWITCH_LOG_DEBUG, "Skipping CPA event\n"); } RAYO_UNLOCK(component); } }
WSChannel* WSClientParser::CreateChannel(switch_core_session_t *session) { WSChannel *wsChannel = NULL; // 创建channel // switch_memory_pool_t *pool = switch_core_session_get_pool(session); wsChannel = (WSChannel *)switch_core_alloc(mpPool, sizeof(WSChannel)); wsChannel->session = session; wsChannel->parser = this; wsChannel->uuid_str = switch_core_strdup(mpPool, switch_core_session_get_uuid(session)); switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::CreateChannel( " "this : %p, " "wsChannel : %p " ") \n", this, wsChannel ); if( InitChannel(wsChannel) ) { mpChannel = wsChannel; } else { DestroyChannel(wsChannel); } return wsChannel; }
bool WSClientParser::ws_disconnect() { switch_status_t status = SWITCH_STATUS_FALSE; switch_event_t *event; if ( (status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, WS_EVENT_MAINT)) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "User", mpUser); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Domain", mpDomain); status = switch_event_fire(&event); } if( status != SWITCH_STATUS_SUCCESS ) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_ERROR, "WSClientParser::ws_disconnect( " "[Send event Fail], " "this : %p, " "user : '******', " "domain : '%s' " ") \n", this, mpUser, mpDomain ); } return status == SWITCH_STATUS_SUCCESS; }
/** * Request signals */ static void subscribe(const char *uuid, const char *signal_type, const char *jid) { char *key = switch_mprintf("%s:%s", uuid, signal_type); switch_mutex_lock(globals.subscribers_mutex); { switch_hash_t *signal_subscribers = switch_core_hash_find(globals.subscribers, key); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Subscribe %s => %s\n", signal_type, jid); if (!signal_subscribers) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Create %s subscriber hash\n", signal_type); switch_core_hash_init(&signal_subscribers); switch_core_hash_insert(globals.subscribers, key, signal_subscribers); } switch_core_hash_insert(signal_subscribers, jid, "1"); } switch_mutex_unlock(globals.subscribers_mutex); switch_safe_free(key); }
/** * Seek file */ static switch_status_t fileman_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence) { struct fileman_file_context *context = handle->private_info; if (!handle->seekable) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "File is not seekable\n"); return SWITCH_STATUS_NOTIMPL; } return switch_core_file_seek(&context->fh, cur_sample, samples, whence); }
/** * Handle CDATA that is not allowed * @param parser the parser * @param data the CDATA * @param len the CDATA length * @return IKS_BADXML if any printable characters */ static int process_cdata_bad(struct nlsml_parser *parser, char *data, size_t len) { int i; for (i = 0; i < len; i++) { if (isgraph(data[i])) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "Unexpected CDATA for <%s>\n", parser->cur->name); return IKS_BADXML; } } return IKS_OK; }
/** * Stop receiving signals */ static void unsubscribe(const char *uuid, const char *signal_type, const char *jid) { char *key = switch_mprintf("%s:%s", uuid, signal_type); switch_mutex_lock(globals.subscribers_mutex); { switch_hash_t *signal_subscribers = switch_core_hash_find(globals.subscribers, key); if (signal_subscribers) { switch_core_hash_delete(signal_subscribers, jid); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Unsubscribe %s => %s\n", signal_type, jid); /* clean up hash if empty */ if (!switch_core_hash_first(signal_subscribers)) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Destroy %s subscriber hash\n", signal_type); switch_core_hash_destroy(&signal_subscribers); switch_core_hash_delete(globals.subscribers, key); } } } switch_mutex_unlock(globals.subscribers_mutex); switch_safe_free(key); }
/** * Handle tag attributes * @param parser the parser * @param name the tag name * @param atts the attributes * @return IKS_OK if OK IKS_BADXML on parse failure */ static int process_tag(struct nlsml_parser *parser, const char *name, char **atts) { struct nlsml_node *cur = parser->cur; if (cur->tag_def->is_root && cur->parent == NULL) { /* no parent for ROOT tags */ return cur->tag_def->attribs_fn(parser, atts); } else if (!cur->tag_def->is_root && cur->parent) { /* check if this child is allowed by parent node */ struct tag_def *parent_def = cur->parent->tag_def; if (switch_core_hash_find(parent_def->children_tags, "ANY") || switch_core_hash_find(parent_def->children_tags, name)) { return cur->tag_def->attribs_fn(parser, atts); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "<%s> cannot be a child of <%s>\n", name, cur->parent->name); } } else if (cur->tag_def->is_root && cur->parent != NULL) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "<%s> must be the root element\n", name); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "<%s> cannot be a root element\n", name); } return IKS_BADXML; }
/** * Notify completion of record component */ static void complete_record(struct rayo_component *component, const char *reason, const char *reason_namespace) { switch_core_session_t *session = NULL; const char *uuid = component->parent->id; char *uri = switch_mprintf("file://%s", RECORD_COMPONENT(component)->local_file_path); iks *recording; switch_size_t file_size = 0; /* TODO this doesn't work with HTTP */ #if 0 switch_file_t *file; if (switch_file_open(&file, RECORD_COMPONENT(component)->local_file_path, SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD, RAYO_POOL(component)) == SWITCH_STATUS_SUCCESS) { file_size = switch_file_get_size(file); switch_file_close(file); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_INFO, "Failed to open %s.\n", RECORD_COMPONENT(component)->local_file_path); } #endif switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Recording %s done.\n", RECORD_COMPONENT(component)->local_file_path); if (RECORD_COMPONENT(component)->stop_beep && (session = switch_core_session_locate(uuid))) { switch_ivr_displace_session(session, RECORD_BEEP, 0, ""); switch_core_session_rwunlock(session); } /* send complete event to client */ recording = iks_new("recording"); iks_insert_attrib(recording, "xmlns", RAYO_RECORD_COMPLETE_NS); iks_insert_attrib(recording, "uri", uri); iks_insert_attrib_printf(recording, "duration", "%i", RECORD_COMPONENT(component)->duration_ms); iks_insert_attrib_printf(recording, "size", "%"SWITCH_SIZE_T_FMT, file_size); rayo_component_send_complete_with_metadata(component, reason, reason_namespace, recording, 1); iks_delete(recording); RAYO_UNLOCK(component); switch_safe_free(uri); }
static switch_status_t rtmp_tcp_write(rtmp_session_t *rsession, const unsigned char *buf, switch_size_t *len) { //rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io; rtmp_tcp_io_private_t *io_pvt = rsession->io_private; switch_status_t status; switch_size_t orig_len = *len; #ifdef RTMP_DEBUG_IO { int i; fprintf(rsession->io_debug_out, "SEND %"SWITCH_SIZE_T_FMT" bytes\n> ", *len); for (i = 0; i < *len; i++) { fprintf(rsession->io_debug_out, "%02X ", (uint8_t)buf[i]); if (i != 0 && i % 32 == 0) { fprintf(rsession->io_debug_out, "\n> "); } } fprintf(rsession->io_debug_out, "\n\n "); fflush(rsession->io_debug_out); } #endif if (io_pvt->sendq && switch_buffer_inuse(io_pvt->sendq) > 0) { /* We already have queued data, append it to the sendq */ switch_buffer_write(io_pvt->sendq, buf, *len); return SWITCH_STATUS_SUCCESS; } status = switch_socket_send_nonblock(io_pvt->socket, (char*)buf, len); if (*len > 0 && *len < orig_len) { if (rsession->state >= RS_DESTROY) { return SWITCH_STATUS_FALSE; } /* We didnt send it all... add it to the sendq*/ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "%"SWITCH_SIZE_T_FMT" bytes added to sendq.\n", (orig_len - *len)); switch_buffer_write(io_pvt->sendq, (buf + *len), orig_len - *len); /* Make sure we poll-write */ rtmp_tcp_alter_pollfd(rsession, SWITCH_TRUE); } return status; }
void WSClientParser::DestroyChannel(WSChannel* wsChannel) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::DestroyChannel( " "this : %p, " "wsChannel : %p " ") \n", this, mpChannel ); if( wsChannel ) { // Audio if (switch_core_codec_ready(&wsChannel->read_codec)) { switch_core_codec_destroy(&wsChannel->read_codec); } if (switch_core_codec_ready(&wsChannel->write_codec)) { switch_core_codec_destroy(&wsChannel->write_codec); } // Video if (switch_core_codec_ready(&wsChannel->video_read_codec)) { switch_core_codec_destroy(&wsChannel->video_read_codec); } if (switch_core_codec_ready(&wsChannel->video_write_codec)) { switch_core_codec_destroy(&wsChannel->video_write_codec); } if( wsChannel->video_readbuf_mutex ) { switch_mutex_destroy(wsChannel->video_readbuf_mutex); wsChannel->video_readbuf_mutex = NULL; } if( wsChannel->session ) { switch_media_handle_destroy(wsChannel->session); wsChannel->session = NULL; } if( wsChannel->video_readbuf ) { switch_buffer_destroy(&wsChannel->video_readbuf); wsChannel->video_readbuf = NULL; } } }
void WSClientParser::DestroyCall() { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::DestroyCall( " "this : %p, " "mpChannel : %p " ") \n", this, mpChannel ); if( mpChannel ) { DestroyChannel(mpChannel); mpChannel = NULL; } }
/** * Process cdata * @param user_data the parser * @param data the CDATA * @param len the CDATA length * @return IKS_OK */ static int cdata_hook(void *user_data, char *data, size_t len) { struct nlsml_parser *parser = (struct nlsml_parser *)user_data; if (!parser) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing parser\n"); return IKS_BADXML; } if (parser->cur) { struct tag_def *def = parser->cur->tag_def; if (def) { return def->cdata_fn(parser, data, len); } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(parser->uuid), SWITCH_LOG_INFO, "Missing definition for <%s>\n", parser->cur->name); return IKS_BADXML; } return IKS_OK; }
bool WSClientParser::GetHandShakeRespond(char** buffer, int& len) { if( mState == WSClientState_Handshake ) { mState = WSClientState_Data; char input[256] = ""; unsigned char output[SHA1_HASH_SIZE] = ""; char b64[256] = ""; snprintf(input, sizeof(input), "%s%s", mWebSocketKey, WEBSOCKET_GUID); sha1_digest(output, input); b64encode((unsigned char *)output, SHA1_HASH_SIZE, (unsigned char *)b64, sizeof(b64)); char* temp = switch_core_sprintf( mpPool, "HTTP/1.1 101 Switching Protocols\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: %s\r\n" "\r\n", b64 ); *buffer = temp; len = strlen(temp); switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_INFO, "WSClientParser::GetHandShakeRespond( " "this : %p, " "len : %d, " "buffer : \n%s\n" ") \n", this, len, *buffer ); return true; } return false; }
static void rtmp_tcp_alter_pollfd(rtmp_session_t *rsession, switch_bool_t pollout) { rtmp_tcp_io_private_t *io_pvt = rsession->io_private; rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io; if (pollout && (io_pvt->pollfd->reqevents & SWITCH_POLLOUT)) { return; } else if (!pollout && !(io_pvt->pollfd->reqevents & SWITCH_POLLOUT)) { return; } switch_pollset_remove(io->pollset, io_pvt->pollfd); io_pvt->pollfd->reqevents = SWITCH_POLLIN | SWITCH_POLLERR; if (pollout) { io_pvt->pollfd->reqevents |= SWITCH_POLLOUT; } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_NOTICE, "Pollout: %s\n", pollout ? "true" : "false"); switch_pollset_add(io->pollset, io_pvt->pollfd); }
/** * Wraps file with interface that can be controlled by fileman flags * @param handle * @param path the file to play * @return SWITCH_STATUS_SUCCESS if opened */ static switch_status_t fileman_file_open(switch_file_handle_t *handle, const char *path) { int start_offset_ms = 0; switch_status_t status = SWITCH_STATUS_FALSE; struct fileman_file_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context)); handle->private_info = context; if (handle->params) { const char *id = switch_event_get_header(handle->params, "id"); const char *uuid = switch_event_get_header(handle->params, "session"); const char *start_offset_ms_str = switch_event_get_header(handle->params, "start_offset_ms"); if (!zstr(id)) { context->id = switch_core_strdup(handle->memory_pool, id); } if (!zstr(uuid)) { context->uuid = switch_core_strdup(handle->memory_pool, uuid); } if (!zstr(start_offset_ms_str) && switch_is_number(start_offset_ms_str)) { start_offset_ms = atoi(start_offset_ms_str); if (start_offset_ms < 0) { start_offset_ms = 0; } } } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Got path %s\n", path); if ((status = switch_core_file_open(&context->fh, path, handle->channels, handle->samplerate, handle->flags, NULL)) != SWITCH_STATUS_SUCCESS) { return status; } /* set up handle for external control */ if (!context->id) { /* use filename as ID */ context->id = switch_core_strdup(handle->memory_pool, path); } switch_mutex_lock(fileman_globals.mutex); if (!switch_core_hash_find(fileman_globals.hash, context->id)) { switch_core_hash_insert(fileman_globals.hash, context->id, handle); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "Duplicate fileman ID: %s\n", context->id); return SWITCH_STATUS_FALSE; } switch_mutex_unlock(fileman_globals.mutex); context->max_frame_len = (handle->samplerate / 1000 * SWITCH_MAX_INTERVAL); switch_zmalloc(context->abuf, FILE_STARTBYTES * sizeof(*context->abuf)); if (!context->fh.audio_buffer) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Create audio buffer\n"); switch_buffer_create_dynamic(&context->fh.audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0); switch_assert(context->fh.audio_buffer); } handle->samples = context->fh.samples; handle->format = context->fh.format; handle->sections = context->fh.sections; handle->seekable = context->fh.seekable; handle->speed = context->fh.speed; handle->vol = context->fh.vol; handle->offset_pos = context->fh.offset_pos; handle->interval = context->fh.interval; if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) { switch_set_flag(handle, SWITCH_FILE_NATIVE); } else { switch_clear_flag(handle, SWITCH_FILE_NATIVE); } if (handle->params && switch_true(switch_event_get_header(handle->params, "pause"))) { switch_set_flag(handle, SWITCH_FILE_PAUSE); } if (handle->seekable && start_offset_ms) { unsigned int pos = 0; int32_t target = start_offset_ms * (handle->samplerate / 1000); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(&context->fh, &pos, target, SEEK_SET); } return status; }
WSChannel* WSClientParser::CreateCall( switch_core_session_t *session, const char *profileName, const char *profileContext, const char *profileDialplan, const char* ip ) { WSChannel *wsChannel = NULL; switch_memory_pool_t *pool = NULL; switch_channel_t* channel = NULL; switch_caller_profile_t *caller_profile = NULL; char *user = mpUser; char *domain = mpDomain; const char *destNumber = mpDestNumber; const char *context = NULL; const char *dialplan = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::CreateCall( " "this : %p, " "profileName : '%s', " "profileContext : '%s', " "profileDialplan : '%s', " "ip : '%s' " ") \n", this, profileName, profileContext, profileDialplan, ip ); // 参数不能为空 if ( !user || !domain || !destNumber ) { status = SWITCH_STATUS_FALSE; } // 不允许一个连接创建多个会话 if( status == SWITCH_STATUS_SUCCESS && mpChannel ) { status = SWITCH_STATUS_FALSE; } if( status == SWITCH_STATUS_SUCCESS ) { pool = switch_core_session_get_pool(session); channel = switch_core_session_get_channel(session); switch_channel_set_name( channel, switch_core_session_sprintf(session, "ws/%s/%s/%s", profileName, user, destNumber) ); } // if ( status == SWITCH_STATUS_SUCCESS && !zstr(user) && !zstr(domain)) { // // 拨号不做验证 // const char *ivrUser = switch_core_session_sprintf(session, "%s@%s", user, domain); // status = switch_ivr_set_user(session, ivrUser); // } if( status == SWITCH_STATUS_SUCCESS ) { if (!(context = switch_channel_get_variable(channel, "user_context"))) { if (!(context = profileContext)) { context = "public"; } } if (!(dialplan = switch_channel_get_variable(channel, "inbound_dialplan"))) { if (!(dialplan = profileDialplan)) { dialplan = "LUA"; } } // switch_log_printf( // SWITCH_CHANNEL_SESSION_LOG(session), // SWITCH_LOG_NOTICE, // "WSClientParser::CreateCall( " // "context : %s, " // "dialplan : %s " // ") \n", // context, // dialplan // ); // 设置主叫 caller_profile = switch_caller_profile_new( pool, switch_str_nil(user), dialplan, SWITCH_DEFAULT_CLID_NAME, !zstr(user) ? user : SWITCH_DEFAULT_CLID_NUMBER, ip /* net addr */, NULL /* ani */, NULL /* anii */, NULL /* rdnis */, "mod_ws", context, destNumber ); switch_channel_set_caller_profile(channel, caller_profile); switch_core_session_add_stream(session, NULL); switch_channel_set_variable(channel, "caller", user); switch_channel_set_state(channel, CS_INIT); wsChannel = CreateChannel(session); } if( wsChannel ) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::CreateCall( " "[Success], " "this : %p, " "wsChannel : %p, " "profileName : '%s', " "profileContext : '%s', " "profileDialplan : '%s', " "ip : '%s' " ") \n", this, wsChannel, profileName, profileContext, profileDialplan, ip ); } else { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_ERROR, "WSClientParser::CreateCall( " "[Fail], " "this : %p " ") \n", this, profileName, profileContext, profileDialplan, ip ); } return wsChannel; }
/** * Process fileman command */ static switch_status_t fileman_process_cmd(const char *cmd, switch_file_handle_t *fhp) { if (zstr(cmd)) { return SWITCH_STATUS_SUCCESS; } if (fhp) { struct fileman_file_context *context = (struct fileman_file_context *)fhp->private_info; if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { return SWITCH_STATUS_FALSE; } if (!strncasecmp(cmd, "speed", 5)) { char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { if (*p == '+') { step = 1; } else { step = -1; } } fhp->speed += step; } else { int speed = atoi(p); fhp->speed = speed; } return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; } else if (!strncasecmp(cmd, "volume", 6)) { char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { if (*p == '+') { step = 1; } else { step = -1; } } fhp->vol += step; } else { int vol = atoi(p); fhp->vol = vol; } return SWITCH_STATUS_SUCCESS; } if (fhp->vol) { switch_normalize_volume(fhp->vol); } return SWITCH_STATUS_FALSE; } else if (!strcasecmp(cmd, "pause")) { switch_set_flag(fhp, SWITCH_FILE_PAUSE); return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(cmd, "resume")) { switch_clear_flag(fhp, SWITCH_FILE_PAUSE); return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(cmd, "stop")) { switch_set_flag(fhp, SWITCH_FILE_DONE); return SWITCH_STATUS_FALSE; } else if (!strcasecmp(cmd, "truncate")) { switch_core_file_truncate(fhp, 0); } else if (!strcasecmp(cmd, "restart")) { unsigned int pos = 0; fhp->speed = 0; switch_core_file_seek(fhp, &pos, 0, SEEK_SET); return SWITCH_STATUS_SUCCESS; } else if (!strncasecmp(cmd, "seek", 4)) { unsigned int samps = 0; unsigned int pos = 0; char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; int32_t target; if (!(step = atoi(p))) { if (*p == '+') { step = 1000; } else { step = -1000; } } samps = step * (fhp->samplerate / 1000); target = (int32_t)fhp->pos + samps; if (target < 0) { target = 0; } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(fhp, &pos, target, SEEK_SET); } else { samps = switch_atoui(p) * (fhp->samplerate / 1000); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); switch_core_file_seek(fhp, &pos, samps, SEEK_SET); } } return SWITCH_STATUS_SUCCESS; } } if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) { return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
bool WSClientParser::HangupCall() { switch_core_session_t* session = NULL; if( mpChannel ) { // 挂断会话 char* uuid = mpChannel->uuid_str; switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::HangupCall( " "[Start], " "this : %p, " "wsChannel : %p, " "session : '%s' " ") \n", this, mpChannel, uuid ); if( uuid ) { // 挂断会话 session = switch_core_session_locate(uuid); if ( session != NULL ) { switch_channel_t* channel = switch_core_session_get_channel(session); if( channel ) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::HangupCall( " "[Channel hang up], " "this : %p, " "wsChannel : %p, " "session : '%s' " ") \n", this, mpChannel, switch_core_session_get_uuid(session) ); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); } else { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::HangupCall( " "[No channel to hang up], " "this : %p, " "wsChannel : %p, " "session : '%s' " ") \n", this, mpChannel, switch_core_session_get_uuid(session) ); } switch_core_session_rwunlock(session); } } switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::HangupCall( " "[Success], " "this : %p, " "wsChannel : %p, " "session : '%s' " ") \n", this, mpChannel, uuid ); } return (session != NULL); }
bool WSClientParser::ParseFirstLine(char* line) { bool bFlag = false; // Get Param char* p = line; char* delim = " "; char decodeUrl[HTTP_URL_MAX_PATH] = {0}; char *array[HTTP_URL_FIRSTLINE_PARAM_MAX_COUNT]; if( switch_separate_string_string(p, delim, array, HTTP_URL_FIRSTLINE_PARAM_MAX_COUNT) >= HTTP_URL_FIRSTLINE_PARAM_COUNT ) { Arithmetic ac; ac.decode_url(array[1], strlen(array[1]), decodeUrl); switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_INFO, "WSClientParser::ParseFirstLine( " "this : %p, " "decodeUrl : '%s' " ") \n", this, decodeUrl ); if( strlen(decodeUrl) > 0 ) { // p = decodeUrl; p = switch_core_strdup(mpPool, decodeUrl); delim = "/"; if( *p == *delim ) { p++; } char *array2[HTTP_URL_PATH_PARAM_MAX_COUNT]; if( switch_separate_string_string(p, delim, array2, HTTP_URL_PATH_PARAM_MAX_COUNT) >= HTTP_URL_PATH_PARAM_COUNT ) { mpUser = switch_core_strdup(mpPool, array2[0]); mpDomain = switch_core_strdup(mpPool, array2[1]); mpDestNumber = switch_core_strdup(mpPool, array2[2]); // 暂时不做PHP验证 mpSite = switch_core_strdup(mpPool, array2[3]); mpCustom = switch_core_strdup(mpPool, array2[4]); // mpSite = switch_core_strdup(mpPool, ""); // mpCustom = switch_core_strdup(mpPool, ""); switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_INFO, "WSClientParser::ParseFirstLine( " "this : %p, " "user : '******', " "domain : '%s', " "destnumber : '%s', " "site : '%s', " "custom : '%s' " ") \n", this, mpUser, mpDomain, mpDestNumber, mpSite, mpCustom ); bFlag = true; } } } if( !bFlag ) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_ERROR, "WSClientParser::ParseFirstLine( " "[Fail], " "this : %p, " "decodeUrl : '%s' " ") \n", this, decodeUrl ); } return bFlag; }
/** * Handle fax completion event from FreeSWITCH core * @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns. */ static void on_execute_complete_event(switch_event_t *event) { const char *application = switch_event_get_header(event, "Application"); if (!zstr(application) && (!strcmp(application, "rxfax") || !strcmp(application, "txfax"))) { int is_rxfax = !strcmp(application, "rxfax"); const char *uuid = switch_event_get_header(event, "Unique-ID"); const char *fax_jid = switch_event_get_header(event, "variable_rayo_fax_jid"); struct rayo_actor *component; if (!zstr(fax_jid) && (component = RAYO_LOCATE(fax_jid))) { iks *result; iks *complete; iks *fax; int have_fax_document = 1; switch_core_session_t *session; switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Got result for %s\n", fax_jid); /* clean up channel */ session = switch_core_session_locate(uuid); if (session) { switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); switch_core_session_rwunlock(session); } /* RX only: transfer HTTP document and delete local copy */ if (is_rxfax && RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)) == SWITCH_STATUS_SUCCESS) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename); switch_api_execute("http_put", RECEIVEFAX_COMPONENT(component)->filename, NULL, &stream); /* check if successful */ if (!zstr(stream.data) && strncmp(stream.data, "+OK", 3)) { /* PUT failed */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s failed: %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename, (char *)stream.data); have_fax_document = 0; } switch_safe_free(stream.data) switch_file_remove(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)); } /* successful fax? */ if (have_fax_document && switch_true(switch_event_get_header(event, "variable_fax_success"))) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), FAX_FINISH); } else if (have_fax_document && FAX_COMPONENT(component)->stop) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_STOP); } else { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_ERROR); } complete = iks_find(result, "complete"); /* RX only: add fax document information */ if (is_rxfax && have_fax_document) { const char *pages = switch_event_get_header(event, "variable_fax_document_transferred_pages"); if (!zstr(pages) && switch_is_number(pages) && atoi(pages) > 0) { const char *resolution = switch_event_get_header(event, "variable_fax_file_image_resolution"); const char *size = switch_event_get_header(event, "variable_fax_image_size"); fax = iks_insert(complete, "fax"); iks_insert_attrib(fax, "xmlns", RAYO_FAX_COMPLETE_NS); if (RECEIVEFAX_COMPONENT(component)->http_put_after_receive) { iks_insert_attrib(fax, "url", RECEIVEFAX_COMPONENT(component)->filename); } else { /* convert absolute path to file:// URI */ iks_insert_attrib_printf(fax, "url", "file://%s", RECEIVEFAX_COMPONENT(component)->filename); } if (!zstr(resolution)) { iks_insert_attrib(fax, "resolution", resolution); } if (!zstr(size)) { iks_insert_attrib(fax, "size", size); } iks_insert_attrib(fax, "pages", pages); } } /* add metadata from event */ insert_fax_metadata(event, "fax_success", complete); insert_fax_metadata(event, "fax_result_code", complete); insert_fax_metadata(event, "fax_result_text", complete); insert_fax_metadata(event, "fax_document_transferred_pages", complete); insert_fax_metadata(event, "fax_document_total_pages", complete); insert_fax_metadata(event, "fax_image_resolution", complete); insert_fax_metadata(event, "fax_image_size", complete); insert_fax_metadata(event, "fax_bad_rows", complete); insert_fax_metadata(event, "fax_transfer_rate", complete); insert_fax_metadata(event, "fax_ecm_used", complete); insert_fax_metadata(event, "fax_local_station_id", complete); insert_fax_metadata(event, "fax_remote_station_id", complete); /* flag faxing as done */ rayo_call_set_faxing(RAYO_CALL(RAYO_COMPONENT(component)->parent), 0); rayo_component_send_complete_event(RAYO_COMPONENT(component), result); RAYO_UNLOCK(component); } } }
void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj) { rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)obj; io->base.running = 1; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: I/O Thread starting\n", io->base.profile->name); while(io->base.running) { const switch_pollfd_t *fds; int32_t numfds; int32_t i; switch_status_t status; switch_mutex_lock(io->mutex); status = switch_pollset_poll(io->pollset, 500000, &numfds, &fds); switch_mutex_unlock(io->mutex); if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_TIMEOUT) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n"); continue; } else if (status == SWITCH_STATUS_TIMEOUT) { switch_cond_next(); } for (i = 0; i < numfds; i++) { if (!fds[i].client_data) { switch_socket_t *newsocket; if (switch_socket_accept(&newsocket, io->listen_socket, io->base.pool) != SWITCH_STATUS_SUCCESS) { if (io->base.running) { /* Don't spam the logs if we are shutting down */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno)); } else { return NULL; } } else { rtmp_session_t *rsession; if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n"); } if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n"); } if (rtmp_session_request(io->base.profile, &rsession) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP session request failed\n"); switch_socket_close(newsocket); } else { switch_sockaddr_t *addr = NULL; char ipbuf[200]; /* Create out private data and attach it to the rtmp session structure */ rtmp_tcp_io_private_t *pvt = switch_core_alloc(rsession->pool, sizeof(*pvt)); rsession->io_private = pvt; pvt->socket = newsocket; switch_socket_create_pollfd(&pvt->pollfd, newsocket, SWITCH_POLLIN | SWITCH_POLLERR, rsession, rsession->pool); switch_pollset_add(io->pollset, pvt->pollfd); switch_buffer_create_dynamic(&pvt->sendq, 512, 1024, 0); /* Get the remote address/port info */ switch_socket_addr_get(&addr, SWITCH_TRUE, newsocket); switch_get_addr(ipbuf, sizeof(ipbuf), addr); rsession->remote_address = switch_core_strdup(rsession->pool, ipbuf); rsession->remote_port = switch_sockaddr_get_port(addr); switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "Rtmp connection from %s:%i\n", rsession->remote_address, rsession->remote_port); } } } else { rtmp_session_t *rsession = (rtmp_session_t*)fds[i].client_data; rtmp_tcp_io_private_t *io_pvt = (rtmp_tcp_io_private_t*)rsession->io_private; if (fds[i].rtnevents & SWITCH_POLLOUT && switch_buffer_inuse(io_pvt->sendq) > 0) { /* Send as much remaining data as possible */ switch_size_t sendlen; const void *ptr; sendlen = switch_buffer_peek_zerocopy(io_pvt->sendq, &ptr); switch_socket_send_nonblock(io_pvt->socket, ptr, &sendlen); switch_buffer_toss(io_pvt->sendq, sendlen); if (switch_buffer_inuse(io_pvt->sendq) == 0) { /* Remove our fd from OUT polling */ rtmp_tcp_alter_pollfd(rsession, SWITCH_FALSE); } } else if (fds[i].rtnevents & SWITCH_POLLIN && rtmp_handle_data(rsession) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "Closing socket\n"); switch_mutex_lock(io->mutex); switch_pollset_remove(io->pollset, io_pvt->pollfd); switch_mutex_unlock(io->mutex); switch_socket_close(io_pvt->socket); io_pvt->socket = NULL; rtmp_session_destroy(&rsession); } } } } io->base.running = -1; switch_socket_close(io->listen_socket); return NULL; }
int WSClientParser::ParseData(char* buffer, int len) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_DEBUG, "WSClientParser::ParseData( " "this : %p, " "len : %d " // "buffer : \n%s\n" ") \n", this, len // buffer ); int ret = 0; // DataParser::ParseData(NULL, len); Lock(); switch( mState ) { case WSClientState_UnKnow:{ int lineNumber = 0; char line[HTTP_URL_MAX_PATH]; int lineLen = 0; const char* header = buffer; const char* sepHeader = strstr(buffer, HTTP_HEADER_SEP); const char* sep = NULL; if( sepHeader ) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->uuid), SWITCH_LOG_INFO, "WSClientParser::ParseData( " "[HandShake], " "this : %p, " "len : %d, " "buffer : \n%s\n" ") \n", this, len, buffer ); // Parse HTTP header separator ret = sepHeader - buffer + strlen(HTTP_HEADER_SEP); // Parse HTTP header line separator while( true ) { if( (sep = strstr(header, HTTP_LINE_SEP)) && sep != sepHeader ) { lineLen = sep - header; if( lineLen < sizeof(line) - 1 ) { memcpy(line, header, lineLen); line[lineLen] = '\0'; if( lineNumber == 0 ) { // Get First Line if( !ParseFirstLine(line) ) { break; } } else { ParseHeader(line); if( CheckHandShake() ) { break; } } } header += lineLen + strlen(HTTP_LINE_SEP); lineNumber++; } else { break; } } } if( mState == WSClientState_Handshake ) { if( mpCallback ) { mpCallback->OnWSClientParserHandshake(this); } } else { if( mpCallback ) { mpCallback->OnWSClientDisconected(this); } } }break; case WSClientState_Handshake:{ } case WSClientState_Data:{ // char temp[4096] = {0}; // char *p = temp; // unsigned char c; // for(int i = 0; i< len; i++) { // c = buffer[i]; // sprintf(p, "%c%c,", hex[c >> 4], hex[c & (16 - 1)]); // p += 3; // } // switch_log_printf( // SWITCH_CHANNEL_UUID_LOG(this->uuid), // SWITCH_LOG_INFO, // "WSClientParser::ParseData( " // "parser : %p, " // "hex : \n%s\n" // ") \n", // this, // temp // ); WSPacket* packet = (WSPacket *)buffer; // switch_log_printf( // SWITCH_CHANNEL_UUID_LOG(this->uuid), // SWITCH_LOG_INFO, // "WSClientParser::ParseData( " // "parser : %p, " // "packet->Fin : %s, " // "packet->RSV : %u, " // "packet->Opcode : %u, " // "packet->Mask : %s, " // "packet->Playload Length : %u, " // "packet->Extend Playload Length : %llu, " // "packet->Mask Key : %s " // ") \n", // this, // packet->baseHeader.IsFin()?"true":"false", // packet->baseHeader.GetRSVType(), // packet->baseHeader.GetOpcode(), // packet->baseHeader.IsMask()?"true":"false", // packet->baseHeader.GetPlayloadLength(), // packet->GetPlayloadLength(), // packet->GetMaskKey() // ); const char* data = (const char*)packet->GetData();//buffer;//packet->GetData(); int playloadLength = packet->GetPlayloadLength();//len;//packet->GetPlayloadLength(); ret = packet->GetHeaderLength() + playloadLength; if( mpCallback) { mpCallback->OnWSClientParserData(this, data, playloadLength); } }break; case WSClientState_Disconnected:{ ret = len; }break; default:{ break; } } Unlock(); return ret; }