static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; int headerlength; if (ei_decode_string_or_binary(buf->buff, &buf->index, SWITCH_UUID_FORMATTED_LENGTH, uuid) || ei_decode_list_header(buf->buff, &buf->index, &headerlength)) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { switch_core_session_t *session; if (!zstr_buf(uuid) && (session = switch_core_session_locate(uuid))) { switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_SEND_MESSAGE) == SWITCH_STATUS_SUCCESS) { char key[1024]; char value[1024]; int i = 0; switch_bool_t fail = SWITCH_FALSE; while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) { fail = SWITCH_TRUE; break; } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value); } if (headerlength != i || fail) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { if (switch_core_session_queue_private_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badmem"); } } } /* release the lock returned by session locate */ switch_core_session_rwunlock(session); } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "nosession"); } } return SWITCH_STATUS_SUCCESS; }
/** * Start execution of call sendfax component * @param call the call to send fax to * @param msg the original request * @param session_data the call's session */ static iks *start_sendfax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { iks *iq = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; struct fax_component *sendfax_component = NULL; iks *sendfax = iks_find(iq, "sendfax"); iks *response = NULL; switch_event_t *execute_event = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_memory_pool_t *pool; iks *document; const char *fax_document; const char *fax_header; const char *fax_identity; const char *pages; /* validate attributes */ if (!VALIDATE_RAYO_SENDFAX(sendfax)) { return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); } /* fax is only allowed if the call is not currently joined */ if (rayo_call_is_joined(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't send fax on a joined call"); } if (rayo_call_is_faxing(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); } /* get fax document */ document = iks_find(sendfax, "document"); if (!document) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "missing document"); } fax_document = iks_find_attrib_soft(document, "url"); if (zstr(fax_document)) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "missing document url"); } /* is valid URL type? */ if (!strncasecmp(fax_document, "http://", 7) || !strncasecmp(fax_document, "https://", 8)) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); /* need to fetch document from server... */ switch_api_execute("http_get", fax_document, session, &stream); if (!zstr(stream.data) && !strncmp(fax_document, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { fax_document = switch_core_session_strdup(session, stream.data); } else { switch_safe_free(stream.data); return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to fetch document"); } switch_safe_free(stream.data); } else if (!strncasecmp(fax_document, "file://", 7)) { fax_document = fax_document + 7; if (zstr(fax_document)) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid file:// url"); } } else if (strncasecmp(fax_document, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "unsupported url type"); } /* does document exist? */ if (switch_file_exists(fax_document, pool) != SWITCH_STATUS_SUCCESS) { return iks_new_error_detailed_printf(iq, STANZA_ERROR_BAD_REQUEST, "file not found: %s", fax_document); } /* get fax identity and header */ fax_identity = iks_find_attrib_soft(document, "identity"); if (!zstr(fax_identity)) { switch_channel_set_variable(channel, "fax_ident", fax_identity); } else { switch_channel_set_variable(channel, "fax_ident", NULL); } fax_header = iks_find_attrib_soft(document, "header"); if (!zstr(fax_header)) { switch_channel_set_variable(channel, "fax_header", fax_header); } else { switch_channel_set_variable(channel, "fax_header", NULL); } /* get pages to send */ pages = iks_find_attrib_soft(document, "pages"); if (!zstr(pages)) { if (switch_regex_match(pages, "[1-9][0-9]*(-[1-9][0-9]*)?") == SWITCH_STATUS_FALSE) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid pages value"); } else { int start = 0; int end = 0; char *pages_dup = switch_core_session_strdup(session, pages); char *sep = strchr(pages_dup, '-'); if (sep) { *sep = '\0'; sep++; end = atoi(sep); } start = atoi(pages_dup); if (end && end < start) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid pages value"); } switch_channel_set_variable(channel, "fax_start_page", pages_dup); switch_channel_set_variable(channel, "fax_end_page", sep); } } else { switch_channel_set_variable(channel, "fax_start_page", NULL); switch_channel_set_variable(channel, "fax_end_page", NULL); } /* create sendfax component */ switch_core_new_memory_pool(&pool); sendfax_component = switch_core_alloc(pool, sizeof(*sendfax_component)); rayo_component_init((struct rayo_component *)sendfax_component, pool, RAT_CALL_COMPONENT, "sendfax", NULL, call, iks_find_attrib(iq, "from")); /* add channel variable so that fax component can be located from fax events */ switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(sendfax_component)); /* clear fax result variables */ switch_channel_set_variable(channel, "fax_success", NULL); switch_channel_set_variable(channel, "fax_result_code", NULL); switch_channel_set_variable(channel, "fax_result_text", NULL); switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); switch_channel_set_variable(channel, "fax_document_total_pages", NULL); switch_channel_set_variable(channel, "fax_image_resolution", NULL); switch_channel_set_variable(channel, "fax_image_size", NULL); switch_channel_set_variable(channel, "fax_bad_rows", NULL); switch_channel_set_variable(channel, "fax_transfer_rate", NULL); switch_channel_set_variable(channel, "fax_ecm_used", NULL); switch_channel_set_variable(channel, "fax_local_station_id", NULL); switch_channel_set_variable(channel, "fax_remote_station_id", NULL); /* clear fax interrupt variable */ switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); rayo_call_set_faxing(RAYO_CALL(call), 1); /* execute txfax APP */ if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "txfax"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", fax_document); if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); } if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to txfax (queue event failed)"); if (execute_event) { switch_event_destroy(&execute_event); } rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(sendfax_component); } else { /* component starting... */ rayo_component_send_start(RAYO_COMPONENT(sendfax_component), iq); } } else { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create txfax event"); rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(sendfax_component); } return response; }
/** * Start execution of call receivefax component * @param call the call to receive fax from * @param msg the original request * @param session_data the call's session */ static iks *start_receivefax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { iks *iq = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; struct receivefax_component *receivefax_component = NULL; iks *receivefax = iks_find(iq, "receivefax"); iks *response = NULL; switch_event_t *execute_event = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_memory_pool_t *pool; int file_no; /* validate attributes */ if (!VALIDATE_RAYO_RECEIVEFAX(receivefax)) { return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); } /* fax is only allowed if the call is not currently joined */ if (rayo_call_is_joined(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't receive fax on a joined call"); } if (rayo_call_is_faxing(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); } /* create receivefax component */ switch_core_new_memory_pool(&pool); receivefax_component = switch_core_alloc(pool, sizeof(*receivefax_component)); rayo_component_init((struct rayo_component *)receivefax_component, pool, RAT_CALL_COMPONENT, "receivefax", NULL, call, iks_find_attrib(iq, "from")); file_no = rayo_actor_seq_next(call); receivefax_component->filename = switch_core_sprintf(pool, "%s%s%s-%d.tif", globals.file_prefix, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); if (!strncmp(receivefax_component->filename, "http://", 7) || !strncmp(receivefax_component->filename, "https://", 8)) { /* This is an HTTP URL, need to PUT after fax is received */ receivefax_component->local_filename = switch_core_sprintf(pool, "%s%s%s-%d", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); receivefax_component->http_put_after_receive = 1; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to HTTP URL\n", RAYO_JID(receivefax_component)); } else { /* assume file.. */ receivefax_component->local_filename = receivefax_component->filename; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to local file\n", RAYO_JID(receivefax_component)); } /* add channel variable so that fax component can be located from fax events */ switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(receivefax_component)); /* clear fax result variables */ switch_channel_set_variable(channel, "fax_success", NULL); switch_channel_set_variable(channel, "fax_result_code", NULL); switch_channel_set_variable(channel, "fax_result_text", NULL); switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); switch_channel_set_variable(channel, "fax_document_total_pages", NULL); switch_channel_set_variable(channel, "fax_image_resolution", NULL); switch_channel_set_variable(channel, "fax_image_size", NULL); switch_channel_set_variable(channel, "fax_bad_rows", NULL); switch_channel_set_variable(channel, "fax_transfer_rate", NULL); switch_channel_set_variable(channel, "fax_ecm_used", NULL); switch_channel_set_variable(channel, "fax_local_station_id", NULL); switch_channel_set_variable(channel, "fax_remote_station_id", NULL); /* clear fax interrupt variable */ switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); rayo_call_set_faxing(RAYO_CALL(call), 1); /* execute rxfax APP */ if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "rxfax"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", receivefax_component->local_filename); if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); } if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to rxfax (queue event failed)"); if (execute_event) { switch_event_destroy(&execute_event); } rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(receivefax_component); } else { /* component starting... */ rayo_component_send_start(RAYO_COMPONENT(receivefax_component), iq); } } else { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create rxfax event"); rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(receivefax_component); } return response; }