Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
bb5d283e
提交
bb5d283e
authored
11月 06, 2013
作者:
Chris Rienzo
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
mod_rayo: <receivefax> component added. No support for HTTP(S) yet.
上级
90f0fdb9
显示空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
464 行增加
和
5 行删除
+464
-5
rayo.conf.xml
conf/rayo/autoload_configs/rayo.conf.xml
+7
-0
Makefile
src/mod/event_handlers/mod_rayo/Makefile
+2
-0
rayo.conf.xml
...ent_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml
+7
-0
mod_rayo.c
src/mod/event_handlers/mod_rayo/mod_rayo.c
+46
-4
mod_rayo.h
src/mod/event_handlers/mod_rayo/mod_rayo.h
+3
-0
rayo_components.c
src/mod/event_handlers/mod_rayo/rayo_components.c
+3
-1
rayo_components.h
src/mod/event_handlers/mod_rayo/rayo_components.h
+5
-0
rayo_elements.c
src/mod/event_handlers/mod_rayo/rayo_elements.c
+12
-0
rayo_elements.h
src/mod/event_handlers/mod_rayo/rayo_elements.h
+1
-0
rayo_receivefax_component.c
src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c
+378
-0
没有找到文件。
conf/rayo/autoload_configs/rayo.conf.xml
浏览文件 @
bb5d283e
...
...
@@ -16,6 +16,12 @@
<param
name=
"default-recognizer"
value=
"pocketsphinx"
/>
</input>
<!-- receivefax component params -->
<receivefax>
<!-- where to store incoming faxes -->
<param
name=
"file-prefix"
value=
"/tmp/"
/>
</receivefax>
<!-- XMPP server domain -->
<domain
name=
"$${rayo_domain_name}"
shared-secret=
"ClueCon"
>
<!-- use this instead if you want secure XMPP client to server connections. Put .crt and .key file in freeswitch/certs -->
...
...
@@ -65,6 +71,7 @@
<alias
name=
"speed-down"
target=
"output"
>
<![CDATA[<speed-down xmlns="urn:xmpp:rayo:output:1"/>]]>
</alias>
<alias
name=
"volume-up"
target=
"output"
>
<![CDATA[<volume-up xmlns="urn:xmpp:rayo:output:1"/>]]>
</alias>
<alias
name=
"volume-down"
target=
"output"
>
<![CDATA[<volume-down xmlns="urn:xmpp:rayo:output:1"/>]]>
</alias>
<alias
name=
"receivefax"
target=
"call"
>
<![CDATA[<receivefax xmlns="urn:xmpp:rayo:fax:1"/>]]>
</alias>
<alias
name=
"record"
target=
"call"
>
<![CDATA[<record xmlns="urn:xmpp:rayo:record:1"/>]]>
</alias>
<alias
name=
"record_pause"
target=
"record"
>
<![CDATA[<pause xmlns="urn:xmpp:rayo:record:1"/>]]>
</alias>
<alias
name=
"record_resume"
target=
"record"
>
<![CDATA[<resume xmlns="urn:xmpp:rayo:record:1"/>]]>
</alias>
...
...
src/mod/event_handlers/mod_rayo/Makefile
浏览文件 @
bb5d283e
...
...
@@ -14,6 +14,7 @@ LOCAL_OBJS= $(IKS_LA) \
rayo_input_component.o
\
rayo_output_component.o
\
rayo_prompt_component.o
\
rayo_receivefax_component.o
\
rayo_record_component.o
\
sasl.o
\
srgs.o
\
...
...
@@ -27,6 +28,7 @@ LOCAL_SOURCES= \
rayo_output_component.c
\
rayo_prompt_component.c
\
rayo_record_component.c
\
rayo_receivefax_component.c
\
sasl.c
\
srgs.c
\
xmpp_streams.c
...
...
src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml
浏览文件 @
bb5d283e
...
...
@@ -16,6 +16,12 @@
<param
name=
"default-recognizer"
value=
"pocketsphinx"
/>
</input>
<!-- receivefax component params -->
<receivefax>
<!-- where to store incoming faxes -->
<param
name=
"file-prefix"
value=
"/tmp/"
/>
</receivefax>
<!-- XMPP server domain -->
<domain
name=
"$${rayo_domain_name}"
shared-secret=
"ClueCon"
>
<!-- use this instead if you want secure XMPP client to server connections. Put .crt and .key file in freeswitch/certs -->
...
...
@@ -65,6 +71,7 @@
<alias
name=
"speed-down"
target=
"output"
>
<![CDATA[<speed-down xmlns="urn:xmpp:rayo:output:1"/>]]>
</alias>
<alias
name=
"volume-up"
target=
"output"
>
<![CDATA[<volume-up xmlns="urn:xmpp:rayo:output:1"/>]]>
</alias>
<alias
name=
"volume-down"
target=
"output"
>
<![CDATA[<volume-down xmlns="urn:xmpp:rayo:output:1"/>]]>
</alias>
<alias
name=
"receivefax"
target=
"call"
>
<![CDATA[<receivefax xmlns="urn:xmpp:rayo:fax:1"/>]]>
</alias>
<alias
name=
"record"
target=
"call"
>
<![CDATA[<record xmlns="urn:xmpp:rayo:record:1"/>]]>
</alias>
<alias
name=
"record_pause"
target=
"record"
>
<![CDATA[<pause xmlns="urn:xmpp:rayo:record:1"/>]]>
</alias>
<alias
name=
"record_resume"
target=
"record"
>
<![CDATA[<resume xmlns="urn:xmpp:rayo:record:1"/>]]>
</alias>
...
...
src/mod/event_handlers/mod_rayo/mod_rayo.c
浏览文件 @
bb5d283e
...
...
@@ -126,6 +126,8 @@ struct rayo_call {
switch_hash_t
*
pcps
;
/** current idle start time */
switch_time_t
idle_start_time
;
/** true if fax is in progress */
int
faxing
;
/** 1 if joined to call, 2 if joined to mixer */
int
joined
;
/** pending join */
...
...
@@ -963,11 +965,35 @@ const char *rayo_call_get_dcp_jid(struct rayo_call *call)
/**
* @param call the Rayo call
* @return true if joined
* @return true if joined
(or a join is in progress)
*/
static
int
rayo_call_is_joined
(
struct
rayo_call
*
call
)
int
rayo_call_is_joined
(
struct
rayo_call
*
call
)
{
return
call
->
joined
;
return
call
->
joined
||
call
->
pending_join_request
;
}
/**
* @param call to check if faxing
* @return true if faxing is in progress
*/
int
rayo_call_is_faxing
(
struct
rayo_call
*
call
)
{
return
call
->
faxing
;
}
/**
* Set faxing flag if faxing is not in progress
* @param call the call to flag
* @param faxing true if faxing is in progress
* @return true if set, false if can't set because faxing is already in progress. Reset always succeeds.
*/
int
rayo_call_set_faxing
(
struct
rayo_call
*
call
,
int
faxing
)
{
if
(
!
faxing
||
(
faxing
&&
!
call
->
faxing
))
{
call
->
faxing
=
faxing
;
return
1
;
}
return
0
;
}
#define RAYO_MIXER_LOCATE(mixer_name) rayo_mixer_locate(mixer_name, __FILE__, __LINE__)
...
...
@@ -1942,6 +1968,12 @@ static iks *on_rayo_join(struct rayo_actor *call, struct rayo_message *msg, void
goto
done
;
}
if
(
rayo_call_is_faxing
(
RAYO_CALL
(
call
)))
{
/* can't join a call while it's faxing */
response
=
iks_new_error_detailed
(
msg
->
payload
,
STANZA_ERROR_UNEXPECTED_REQUEST
,
"fax is in progress"
);
goto
done
;
}
if
(
RAYO_CALL
(
call
)
->
pending_join_request
)
{
/* don't allow concurrent join requests */
response
=
iks_new_error_detailed
(
msg
->
payload
,
STANZA_ERROR_UNEXPECTED_REQUEST
,
"(un)join request is pending"
);
...
...
@@ -3074,12 +3106,22 @@ static switch_status_t rayo_call_on_read_frame(switch_core_session_t *session, s
switch_time_t
idle_start
=
call
->
idle_start_time
;
int
idle_duration_ms
=
(
now
-
idle_start
)
/
1000
;
/* detect idle session (rayo-client has stopped controlling call) and terminate call */
if
(
rayo_call_is_joined
(
call
))
{
if
(
rayo_call_is_joined
(
call
)
||
rayo_call_is_faxing
(
call
)
)
{
call
->
idle_start_time
=
now
;
}
else
if
(
idle_duration_ms
>
globals
.
max_idle_ms
)
{
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_WARNING
,
"Ending abandoned call. idle_duration_ms = %i ms
\n
"
,
idle_duration_ms
);
switch_channel_hangup
(
channel
,
RAYO_CAUSE_HANGUP
);
}
/* check for break request */
{
const
char
*
break_jid
=
switch_channel_get_variable
(
channel
,
"rayo_read_frame_interrupt"
);
struct
rayo_actor
*
actor
;
if
(
break_jid
&&
(
actor
=
RAYO_LOCATE
(
break_jid
)))
{
RAYO_UNLOCK
(
actor
);
return
SWITCH_STATUS_FALSE
;
}
}
}
return
SWITCH_STATUS_SUCCESS
;
}
...
...
src/mod/event_handlers/mod_rayo/mod_rayo.h
浏览文件 @
bb5d283e
...
...
@@ -153,6 +153,9 @@ extern void rayo_actor_destroy(struct rayo_actor *actor, const char *file, int l
#define RAYO_DESTROY(x) rayo_actor_destroy(RAYO_ACTOR(x), __FILE__, __LINE__)
#define RAYO_SEQ_NEXT(x) rayo_actor_seq_next(RAYO_ACTOR(x))
extern
int
rayo_call_is_joined
(
struct
rayo_call
*
call
);
extern
int
rayo_call_is_faxing
(
struct
rayo_call
*
call
);
extern
int
rayo_call_set_faxing
(
struct
rayo_call
*
call
,
int
faxing
);
extern
const
char
*
rayo_call_get_dcp_jid
(
struct
rayo_call
*
call
);
#define rayo_mixer_get_name(mixer) RAYO_ID(mixer)
...
...
src/mod/event_handlers/mod_rayo/rayo_components.c
浏览文件 @
bb5d283e
...
...
@@ -226,7 +226,8 @@ switch_status_t rayo_components_load(switch_loadable_module_interface_t **module
if
(
rayo_input_component_load
(
module_interface
,
pool
,
config_file
)
!=
SWITCH_STATUS_SUCCESS
||
rayo_output_component_load
(
module_interface
,
pool
,
config_file
)
!=
SWITCH_STATUS_SUCCESS
||
rayo_prompt_component_load
(
module_interface
,
pool
,
config_file
)
!=
SWITCH_STATUS_SUCCESS
||
rayo_record_component_load
(
module_interface
,
pool
,
config_file
)
!=
SWITCH_STATUS_SUCCESS
)
{
rayo_record_component_load
(
module_interface
,
pool
,
config_file
)
!=
SWITCH_STATUS_SUCCESS
||
rayo_receivefax_component_load
(
module_interface
,
pool
,
config_file
)
!=
SWITCH_STATUS_SUCCESS
)
{
return
SWITCH_STATUS_TERM
;
}
return
SWITCH_STATUS_SUCCESS
;
...
...
@@ -241,6 +242,7 @@ switch_status_t rayo_components_shutdown(void)
rayo_output_component_shutdown
();
rayo_prompt_component_shutdown
();
rayo_record_component_shutdown
();
rayo_receivefax_component_shutdown
();
return
SWITCH_STATUS_SUCCESS
;
}
...
...
src/mod/event_handlers/mod_rayo/rayo_components.h
浏览文件 @
bb5d283e
...
...
@@ -49,6 +49,9 @@
#define RAYO_PROMPT_NS RAYO_BASE "prompt:" RAYO_VERSION
#define RAYO_PROMPT_COMPLETE_NS RAYO_BASE "prompt:complete:" RAYO_VERSION
#define RAYO_FAX_NS RAYO_BASE "fax:" RAYO_VERSION
#define RAYO_FAX_COMPLETE_NS RAYO_BASE "fax:complete:" RAYO_VERSION
#define COMPONENT_COMPLETE_STOP "stop", RAYO_EXT_COMPLETE_NS
#define COMPONENT_COMPLETE_ERROR "error", RAYO_EXT_COMPLETE_NS
#define COMPONENT_COMPLETE_HANGUP "hangup", RAYO_EXT_COMPLETE_NS
...
...
@@ -58,12 +61,14 @@ extern switch_status_t rayo_input_component_load(switch_loadable_module_interfac
extern
switch_status_t
rayo_output_component_load
(
switch_loadable_module_interface_t
**
module_interface
,
switch_memory_pool_t
*
pool
,
const
char
*
config_file
);
extern
switch_status_t
rayo_prompt_component_load
(
switch_loadable_module_interface_t
**
module_interface
,
switch_memory_pool_t
*
pool
,
const
char
*
config_file
);
extern
switch_status_t
rayo_record_component_load
(
switch_loadable_module_interface_t
**
module_interface
,
switch_memory_pool_t
*
pool
,
const
char
*
config_file
);
extern
switch_status_t
rayo_receivefax_component_load
(
switch_loadable_module_interface_t
**
module_interface
,
switch_memory_pool_t
*
pool
,
const
char
*
config_file
);
extern
switch_status_t
rayo_components_shutdown
(
void
);
extern
switch_status_t
rayo_input_component_shutdown
(
void
);
extern
switch_status_t
rayo_output_component_shutdown
(
void
);
extern
switch_status_t
rayo_prompt_component_shutdown
(
void
);
extern
switch_status_t
rayo_record_component_shutdown
(
void
);
extern
switch_status_t
rayo_receivefax_component_shutdown
(
void
);
extern
void
rayo_component_send_start
(
struct
rayo_component
*
component
,
iks
*
iq
);
extern
void
rayo_component_send_iq_error
(
struct
rayo_component
*
component
,
iks
*
iq
,
const
char
*
error_name
,
const
char
*
error_type
);
...
...
src/mod/event_handlers/mod_rayo/rayo_elements.c
浏览文件 @
bb5d283e
...
...
@@ -32,6 +32,7 @@
* <input> component validation
*/
ELEMENT
(
RAYO_INPUT
)
ATTRIB
(
xmlns
,,
any
)
STRING_ATTRIB
(
mode
,
any
,
"any,dtmf,voice"
)
OPTIONAL_ATTRIB
(
terminator
,,
dtmf_digit
)
ATTRIB
(
recognizer
,,
any
)
...
...
@@ -52,6 +53,7 @@ ELEMENT_END
* <output> component validation
*/
ELEMENT
(
RAYO_OUTPUT
)
ATTRIB
(
xmlns
,,
any
)
ATTRIB
(
start
-
offset
,
0
,
not_negative
)
ATTRIB
(
start
-
paused
,
false
,
bool
)
ATTRIB
(
repeat
-
interval
,
0
,
not_negative
)
...
...
@@ -65,6 +67,7 @@ ELEMENT_END
* <output><seek> validation
*/
ELEMENT
(
RAYO_OUTPUT_SEEK
)
ATTRIB
(
xmlns
,,
any
)
STRING_ATTRIB
(
direction
,,
"forward,back"
)
ATTRIB
(
amount
,
-
1
,
positive
)
ELEMENT_END
...
...
@@ -73,6 +76,7 @@ ELEMENT_END
* <prompt> component validation
*/
ELEMENT
(
RAYO_PROMPT
)
ATTRIB
(
xmlns
,,
any
)
ATTRIB
(
barge
-
in
,
true
,
bool
)
ELEMENT_END
...
...
@@ -80,6 +84,7 @@ ELEMENT_END
* <record> component validation
*/
ELEMENT
(
RAYO_RECORD
)
ATTRIB
(
xmlns
,,
any
)
ATTRIB
(
format
,
wav
,
any
)
ATTRIB
(
start
-
beep
,
false
,
bool
)
ATTRIB
(
stop
-
beep
,
false
,
bool
)
...
...
@@ -95,12 +100,19 @@ ELEMENT_END
* <join> command validation
*/
ELEMENT
(
RAYO_JOIN
)
ATTRIB
(
xmlns
,,
any
)
STRING_ATTRIB
(
direction
,
duplex
,
"send,recv,duplex"
)
STRING_ATTRIB
(
media
,
bridge
,
"bridge,direct"
)
ATTRIB
(
call
-
uri
,,
any
)
ATTRIB
(
mixer
-
name
,,
any
)
ELEMENT_END
/**
* <receivefax> command validation
*/
ELEMENT
(
RAYO_RECEIVEFAX
)
ATTRIB
(
xmlns
,,
any
)
ELEMENT_END
/* For Emacs:
* Local Variables:
...
...
src/mod/event_handlers/mod_rayo/rayo_elements.h
浏览文件 @
bb5d283e
...
...
@@ -37,6 +37,7 @@ ELEMENT_DECL(RAYO_OUTPUT_SEEK)
ELEMENT_DECL
(
RAYO_PROMPT
)
ELEMENT_DECL
(
RAYO_RECORD
)
ELEMENT_DECL
(
RAYO_JOIN
)
ELEMENT_DECL
(
RAYO_RECEIVEFAX
)
#endif
...
...
src/mod/event_handlers/mod_rayo/rayo_receivefax_component.c
0 → 100644
浏览文件 @
bb5d283e
/*
* mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013, Grasshopper
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is Grasshopper
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chris Rienzo <chris.rienzo@grasshopper.com>
*
* rayo_receivefax_component.c -- Rayo receivefax component implementation
*
*/
#include "rayo_components.h"
#include "rayo_elements.h"
/**
* settings
*/
static
struct
{
const
char
*
file_prefix
;
}
globals
;
struct
receivefax_component
{
/** component base class */
struct
rayo_component
base
;
/** true if HTTP PUT needs to be done after fax is received */
int
http_put_after_receive
;
/** fax stored on local filesystem */
const
char
*
local_filename
;
/** fax final target (may be same as local filename) */
const
char
*
filename
;
/** Flag to stop fax */
int
stop
;
};
#define RECEIVEFAX_FINISH "finish", RAYO_FAX_COMPLETE_NS
#define RECEIVEFAX_COMPONENT(x) ((struct receivefax_component *)x)
/**
* 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_set_faxing
(
RAYO_CALL
(
call
),
1
))
{
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"
,
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
;
}
else
{
/* assume file.. */
receivefax_component
->
local_filename
=
receivefax_component
->
filename
;
}
/* 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
);
/* 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
);
switch_event_add_header_string
(
execute_event
,
SWITCH_STACK_BOTTOM
,
"event-lock"
,
"true"
);
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_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_UNLOCK
(
receivefax_component
);
}
return
response
;
}
/**
* Stop execution of receivefax component
*/
static
iks
*
stop_receivefax_component
(
struct
rayo_actor
*
component
,
struct
rayo_message
*
msg
,
void
*
data
)
{
iks
*
iq
=
msg
->
payload
;
switch_core_session_t
*
session
=
switch_core_session_locate
(
RAYO_COMPONENT
(
component
)
->
parent
->
id
);
if
(
session
)
{
/* fail on read frame until component is destroyed */
switch_channel_set_variable
(
switch_core_session_get_channel
(
session
),
"rayo_read_frame_interrupt"
,
RAYO_JID
(
component
));
switch_core_session_rwunlock
(
session
);
}
RECEIVEFAX_COMPONENT
(
component
)
->
stop
=
1
;
return
iks_new_iq_result
(
iq
);
}
/**
* Add fax metadata to result
* @param event source of metadata
* @param name of metadata
* @param result to add metadata to
*/
static
void
insert_fax_metadata
(
switch_event_t
*
event
,
const
char
*
name
,
iks
*
result
)
{
char
actual_name
[
256
];
const
char
*
value
;
snprintf
(
actual_name
,
sizeof
(
actual_name
),
"variable_%s"
,
name
);
actual_name
[
sizeof
(
actual_name
)
-
1
]
=
'\0'
;
value
=
switch_event_get_header
(
event
,
actual_name
);
if
(
!
zstr
(
value
))
{
iks
*
metadata
=
iks_insert
(
result
,
"metadata"
);
iks_insert_attrib
(
metadata
,
"xmlns"
,
RAYO_FAX_COMPLETE_NS
);
iks_insert_attrib
(
metadata
,
"name"
,
name
);
iks_insert_attrib
(
metadata
,
"value"
,
value
);
}
}
/**
* Handle rxfax execute event
* @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns.
*/
static
void
on_execute_event
(
switch_event_t
*
event
)
{
const
char
*
application
=
switch_event_get_header
(
event
,
"Application"
);
if
(
!
zstr
(
application
)
&&
!
strcmp
(
application
,
"rxfax"
))
{
/* TODO */
}
}
/**
* Handle rxfax 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"
))
{
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
)))
{
const
char
*
url
=
RECEIVEFAX_COMPONENT
(
component
)
->
filename
;
iks
*
result
;
iks
*
complete
;
iks
*
fax
;
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
);
}
/* flag faxing as done */
rayo_call_set_faxing
(
RAYO_CALL
(
RAYO_COMPONENT
(
component
)
->
parent
),
0
);
/* successful fax? */
if
(
switch_true
(
switch_event_get_header
(
event
,
"variable_fax_success"
)))
{
result
=
rayo_component_create_complete_event
(
RAYO_COMPONENT
(
component
),
RECEIVEFAX_FINISH
);
}
else
if
(
RECEIVEFAX_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"
);
/* add fax document information */
{
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
(
strlen
(
url
)
>
strlen
(
SWITCH_PATH_SEPARATOR
)
&&
!
strncmp
(
url
,
SWITCH_PATH_SEPARATOR
,
strlen
(
SWITCH_PATH_SEPARATOR
)))
{
/* convert absolute path to file:// URI */
iks_insert_attrib_printf
(
fax
,
"url"
,
"file://%s"
,
url
);
}
else
{
/* is already a URI (hopefully) */
iks_insert_attrib
(
fax
,
"url"
,
url
);
}
if
(
!
zstr
(
resolution
))
{
iks_insert_attrib
(
fax
,
"resolution"
,
resolution
);
}
if
(
!
zstr
(
size
))
{
iks_insert_attrib
(
fax
,
"size"
,
size
);
}
iks_insert_attrib
(
fax
,
"pages"
,
pages
);
}
/* TODO transfer HTTP document and delete local copy */
}
/* 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
);
rayo_component_send_complete_event
(
RAYO_COMPONENT
(
component
),
result
);
RAYO_UNLOCK
(
component
);
}
}
}
/**
* Process module XML configuration
* @param pool memory pool to allocate from
* @param config_file to use
* @return SWITCH_STATUS_SUCCESS on successful configuration
*/
static
switch_status_t
do_config
(
switch_memory_pool_t
*
pool
,
const
char
*
config_file
)
{
switch_xml_t
cfg
,
xml
;
/* set defaults */
globals
.
file_prefix
=
switch_core_sprintf
(
pool
,
"%s%s"
,
SWITCH_GLOBAL_dirs
.
recordings_dir
,
SWITCH_PATH_SEPARATOR
);
if
(
!
(
xml
=
switch_xml_open_cfg
(
config_file
,
&
cfg
,
NULL
)))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"open of %s failed
\n
"
,
config_file
);
return
SWITCH_STATUS_TERM
;
}
/* get params */
{
switch_xml_t
settings
=
switch_xml_child
(
cfg
,
"receivefax"
);
if
(
settings
)
{
switch_xml_t
param
;
for
(
param
=
switch_xml_child
(
settings
,
"param"
);
param
;
param
=
param
->
next
)
{
const
char
*
var
=
switch_xml_attr_soft
(
param
,
"name"
);
const
char
*
val
=
switch_xml_attr_soft
(
param
,
"value"
);
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"param: %s = %s
\n
"
,
var
,
val
);
if
(
!
strcasecmp
(
var
,
"file-prefix"
))
{
if
(
!
zstr
(
val
))
{
globals
.
file_prefix
=
switch_core_strdup
(
pool
,
val
);
}
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_WARNING
,
"Unsupported param: %s
\n
"
,
var
);
}
}
}
}
switch_xml_free
(
xml
);
return
SWITCH_STATUS_SUCCESS
;
}
/**
* Initialize receivefax component
* @param module_interface
* @param pool memory pool to allocate from
* @param config_file to use
* @return SWITCH_STATUS_SUCCESS if successful
*/
switch_status_t
rayo_receivefax_component_load
(
switch_loadable_module_interface_t
**
module_interface
,
switch_memory_pool_t
*
pool
,
const
char
*
config_file
)
{
if
(
do_config
(
pool
,
config_file
)
!=
SWITCH_STATUS_SUCCESS
)
{
return
SWITCH_STATUS_TERM
;
}
switch_event_bind
(
"rayo_receivefax_component"
,
SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE
,
NULL
,
on_execute_complete_event
,
NULL
);
switch_event_bind
(
"rayo_receivefax_component"
,
SWITCH_EVENT_CHANNEL_EXECUTE
,
NULL
,
on_execute_event
,
NULL
);
rayo_actor_command_handler_add
(
RAT_CALL
,
""
,
"set:"
RAYO_FAX_NS
":receivefax"
,
start_receivefax_component
);
rayo_actor_command_handler_add
(
RAT_CALL_COMPONENT
,
"receivefax"
,
"set:"
RAYO_EXT_NS
":stop"
,
stop_receivefax_component
);
return
SWITCH_STATUS_SUCCESS
;
}
/**
* Shutdown receivefax component
* @return SWITCH_STATUS_SUCCESS if successful
*/
switch_status_t
rayo_receivefax_component_shutdown
(
void
)
{
switch_event_unbind_callback
(
on_execute_event
);
switch_event_unbind_callback
(
on_execute_complete_event
);
return
SWITCH_STATUS_SUCCESS
;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
*/
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论