提交 9c79c2a3 authored 作者: Anthony Minessale's avatar Anthony Minessale

Add mod_event_socket remote client module and sample client.

To Test:

uncomment or add from modules.conf
make installall again to compile it
uncomment the load line from freeswitch.xml

the default values are to bind to 127.0.0.1 port 8021

telnet to port 8021
enter "auth ClueCon" to authenticate

from here you can do the following:
*) events [xml|plain] <list of events to log or all for all>
*) noevents 
*) log <level> // same as the console.conf values
*) nolog
*) api <command> <arg>
*) exit

there is a perl client in scripts/socket called fs.pl

with the module up and loaded:
cd scripts/socket
perl fs.pl <optional log level>

you can enter a few api commands like "show or status"




git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2047 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 7a5bc3b7
......@@ -21,7 +21,8 @@
<!-- <load module="mod_event_test"/> -->
<!-- <load module="mod_zeroconf"/> -->
<!-- <load module="mod_xmpp_event"/> -->
<!-- <load module="mod_event_socket"/> -->
<!-- Directory Interfaces -->
<!-- <load module="mod_ldap"/> -->
......@@ -72,7 +73,15 @@
</modules>
</configuration>
<configuration name="event_socket.conf" description="Socket Client">
<settings>
<param name="listen-ip" value="127.0.0.1"/>
<param name="listen-port" value="8021"/>
<param name="password" value="ClueCon"/>
</settings>
</configuration>
<configuration name="iax.conf" description="IAX Configuration">
<settings>
<param name="debug" value="0"/>
......
......@@ -29,6 +29,7 @@ endpoints/mod_woomera
#event_handlers/mod_event_test
event_handlers/mod_xmpp_event
#event_handlers/mod_zeroconf
#event_handlers/mod_event_socket
formats/mod_sndfile
#languages/mod_perl
#languages/mod_spidermonkey
......
package FreeSWITCH::Client;
$|=1;
use IO::Socket::INET;
use IO::Select;
use Data::Dumper;
sub init($;$) {
my $proto = shift;
my $args = shift;
my $class = ref($proto) || $proto;
$self->{_host} = $args->{-host} || "localhost";
$self->{_port} = $args->{-port} || 8021;
$self->{_password} = $args->{-password} || undef;
my $me = bless $self,$class;
if ($me->connect()) {
return $me;
} else {
return undef;
}
}
sub input($;$) {
my ($self,$to) = @_;
my $i;
my @r;
my $s = $self->{_sock};
my $x = 0;
my $done = 0;
my $start = time;
while(!$done) {
if ($to and time - $start > $to) {
last;
}
@ready = $self->{_sel}->can_read($to);
if (@ready) {
$x=0;
foreach my $s (@ready) {
while ($i = <$s>) {
$x++;
return @r if($i eq "\n");
$i =~ s/[\n]+$//g;
push @r,$i;
}
unless($x) {
return ("SocketError: yes");
}
}
}
}
return @r;
}
sub readhash($$) {
my $self = shift;
my $arg = shift;
my @r = $self->input($arg);
my $data = join "\n", @r;
my %h = $data =~ /^([^:]+)\s*:\s*([^\n]*)/mg;
foreach (keys %h) {
my $new = lc $_;
$h{$new} = $h{$_};
delete $h{$_};
}
if ($h{'content-length'}) {
my $s = $self->{_sock};
read $s, $h{body}, $h{'content-length'};
}
return \%h;
}
sub error($$) {
my($self,$error) = @_;
die $error;
}
sub output($$) {
my ($self,$data) = @_;
my $s = $self->{_sock};
print $s $data;
}
sub cmd($$$) {
my $self = shift;
my $cmd = shift;
my $to = shift;
$self->output($cmd);
my $h = $self->readhash($to);
$h;
}
sub connect($) {
my $self = shift;
$self->{_sock} = new IO::Socket::INET( Proto => 'tcp',
PeerAddr => $self->{_host},
PeerPort => $self->{_port}
) or return $self->error("Connection refused $self->{_host} port $self->{_port}");
$self->{_sock}->autoflush(1);
#$self->{_sock}->blocking(0);
$self->{_sel} = new IO::Select( $self->{_sock} );
my $h = $self->readhash(undef);
if ($h->{"content-type"} eq "auth/request") {
my $pass = $self->{"_password"};
$self->output("auth $pass");
$h = $self->readhash(undef);
}
if ($h->{'reply-text'} =~ "OK") {
return 1;
}
return 0;
}
1;
use FreeSWITCH::Client;
use Data::Dumper;
use Term::ReadLine;
my $password = "ClueCon";
my $fs = init FreeSWITCH::Client {-password => $password} or die "Error $@";
my $term = new Term::ReadLine ?FreeSWITCH CLI?;
my $prompt = "FS>";
my $OUT = $term->OUT .. \*STDOUT;
my $log = shift;
if ($log) {
$pid = fork;
if (!$pid) {
my $fs2 = init FreeSWITCH::Client {-password => $password} or die "Error $@";
$fs2->cmd("log $log");
while (1) {
my $reply = $fs2->readhash(undef);
if ($reply->{body}) {
print $reply->{body} . "\n";
} elsif ($reply->{'reply-text'}) {
print $reply->{'reply-text'} . "\n";
}
}
}
}
while ( defined ($_ = $term->readline($prompt)) ) {
my $reply;
if ($_) {
if ($_ =~ /^alog|^anolog/) {
$reply = $fs2->cmd($_);
} else {
$reply = $fs->cmd("api $_");
}
if ($reply->{body}) {
print $reply->{body};
} elsif ($reply->{'reply-text'}) {
print $reply->{'reply-text'};
}
print "\n";
if ($_ =~ /exit/) {
last;
}
}
$term->addhistory($_) if /\S/;
}
......@@ -208,6 +208,14 @@ SWITCH_DECLARE(switch_status_t) switch_event_bind(char *id, switch_event_types_t
*/
SWITCH_DECLARE(char *) switch_event_name(switch_event_types_t event);
/*!
\brief return the event id that matches a given event name
\param name the name of the event
\param type the event id to return
\return SWITCH_STATUS_SUCCESS if there was a match
*/
SWITCH_DECLARE(switch_status_t) switch_name_event(char *name, switch_event_types_t *type);
/*!
\brief Reserve a subclass name for private use with a custom event
\param owner the owner of the event name
......
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="mod_event_test"
ProjectGUID="{3A2A7795-C216-4FFF-B8EF-4D17A84BACCC}"
RootNamespace="mod_event_test"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\include&quot;;&quot;$(InputDir)include&quot;;&quot;$(InputDir)..\..\..\..\libs\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\..\..\w32\vsnet\$(OutDir)/mod/mod_event_test.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\..\w32\vsnet\$(OutDir)"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/mod_event_test.pdb"
SubSystem="2"
ImportLibrary="$(OutDir)/mod_event_test.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(InputDir)..\..\..\include&quot;;&quot;$(InputDir)include&quot;;&quot;$(InputDir)..\..\..\..\libs\include&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\..\..\w32\vsnet\$(OutDir)/mod/mod_event_test.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\..\w32\vsnet\$(OutDir)"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
ImportLibrary="$(OutDir)/mod_event_test.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\mod_event_test.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
......@@ -566,7 +566,16 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c
if (state < CS_HANGUP) {
switch_event_t *event;
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
if (state == CS_RING) {
switch_channel_event_set_data(channel, event);
} else {
char state_num[25];
snprintf(state_num, sizeof(state_num), "%d", channel->state);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State", (char *) switch_channel_state_name(channel->state));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", (char *) state_num);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Name", switch_channel_get_name(channel));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(channel->session));
}
switch_event_fire(&event);
}
}
......
......@@ -248,6 +248,23 @@ SWITCH_DECLARE(char *) switch_event_name(switch_event_types_t event)
return EVENT_NAMES[event];
}
SWITCH_DECLARE(switch_status_t) switch_name_event(char *name, switch_event_types_t *type)
{
switch_event_types_t x;
assert(BLOCK != NULL);
assert(RUNTIME_POOL != NULL);
for (x = 0; x <= SWITCH_EVENT_ALL; x++) {
if (!strcasecmp(name, EVENT_NAMES[x])) {
*type = x;
return SWITCH_STATUS_SUCCESS;
}
}
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_event_reserve_subclass_detailed(char *owner, char *subclass_name)
{
......@@ -454,9 +471,9 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_event_t *todup)
{
switch_event_header_t *header, *hp, *hp2;
switch_event_header_t *header, *hp, *hp2, *last = NULL;
if (switch_event_create_subclass(event, todup->event_id, todup->subclass->name) != SWITCH_STATUS_SUCCESS) {
if (switch_event_create_subclass(event, todup->event_id, todup->subclass ? todup->subclass->name : NULL) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_GENERR;
}
......@@ -464,7 +481,9 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_
(*event)->event_user_data = todup->event_user_data;
(*event)->bind_user_data = todup->bind_user_data;
for (hp = todup->headers; hp && hp->next;) {
hp2 = (*event)->headers;
for (hp = todup->headers; hp; hp = hp->next) {
if ((header = ALLOC(sizeof(*header))) == 0) {
return SWITCH_STATUS_MEMERR;
}
......@@ -474,13 +493,17 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_
header->name = DUP(hp->name);
header->value = DUP(hp->value);
for (hp2 = todup->headers; hp2 && hp2->next; hp2 = hp2->next);
if (hp2) {
hp2->next = header;
if (last) {
last->next = header;
} else {
(*event)->headers = header;
}
last = header;
}
if (todup->body) {
(*event)->body = DUP(todup->body);
}
return SWITCH_STATUS_SUCCESS;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论