This commit is contained in:
Michael Jerris 2014-06-11 12:48:46 -05:00
parent 94ab52cd01
commit 1ffb1ee0d0
22 changed files with 9203 additions and 0 deletions

View File

@ -83,6 +83,7 @@ dialplans/mod_dialplan_xml
#endpoints/mod_h323
#endpoints/mod_khomp
endpoints/mod_rtc
endpoints/mod_verto
endpoints/mod_loopback
#endpoints/mod_opal
#endpoints/mod_portaudio

View File

@ -1500,6 +1500,7 @@ AC_CONFIG_FILES([Makefile
src/mod/endpoints/mod_sofia/Makefile
src/mod/endpoints/mod_unicall/Makefile
src/mod/endpoints/mod_rtc/Makefile
src/mod/endpoints/mod_verto/Makefile
src/mod/event_handlers/mod_cdr_csv/Makefile
src/mod/event_handlers/mod_cdr_mongodb/Makefile
src/mod/event_handlers/mod_cdr_pg_csv/Makefile

View File

@ -0,0 +1,38 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_verto
mod_LTLIBRARIES = mod_verto.la
mod_verto_la_SOURCES = mod_verto.c ws.c mcast/mcast.c
mod_verto_la_CFLAGS = -D__EXTENSIONS__ -D_GNU_SOURCE $(AM_CFLAGS)
mod_verto_la_CPPFLAGS = -I. -Imcast
mod_verto_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_verto_la_LDFLAGS = -avoid-version -module -no-undefined -shared
if HAVE_PERL
perldir = $(PERL_SITEDIR)
perl_LTLIBRARIES = MCAST.la
MCAST_la_SOURCES = mcast/mcast_wrap.cpp mcast/perlxsi.c mcast/mcast.c mcast/mcast_cpp.cpp
MCAST_la_CFLAGS = $(CC_CFLAGS) $(CFLAGS) $(SWITCH_AM_CFLAGS) $(PERL_CFLAGS)
MCAST_la_CXXFLAGS = $(SWITCH_AM_CXXFLAGS) $(CXXFLAGS) -w $(PERL_INC)
MCAST_la_CPPFLAGS = -I$(switch_srcdir)/src/mod/endpoints/mod_verto/mcast
MCAST_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(PERL_LDFLAGS)
install-data-local: perlmod-install
perlmod-install: install-perlLTLIBRARIES
install -m 755 MCAST.pm $(PERL_SITEDIR)
endif
mcast/esl_wrap.cpp:
cd mcast && swig -module MCAST -shadow -perl5 -c++ -DMULTIPLICITY -I../src/include -o mcast_wrap.cpp ../MCAST.i
mcast/perlxsi.c:
$(PERL) -MExtUtils::Embed -e xsinit -- -o perlxsi.c
clean-data-local:
rm -f *.o *.so *~
swigclean:
rm -f mcast/mcast_wrap.* mcast/MCAST.so mcast/MCAST.pm mcast/perlxsi.*
reswig: swigclean mcast/mcast_wrap.cpp mcast/perlxsi.c

View File

@ -0,0 +1,2 @@
*.o
*.so

View File

@ -0,0 +1,24 @@
%{
#include "mcast.h"
#include "mcast_cpp.h"
%}
%newobject McastHANDLE::recv;
%include "mcast_cpp.h"
%perlcode %{
use constant {
MCAST_SEND => (1 << 0),
MCAST_RECV => (1 << 1),
MCAST_TTL_HOST => (1 << 2),
MCAST_TTL_SUBNET => (1 << 3),
MCAST_TTL_SITE => (1 << 4),
MCAST_TTL_REGION => (1 << 5),
MCAST_TTL_CONTINENT => (1 << 6),
MCAST_TTL_UNIVERSE => (1 << 7)
};
%}

View File

@ -0,0 +1,108 @@
# This file was automatically generated by SWIG (http://www.swig.org).
# Version 1.3.35
#
# Don't modify this file, modify the SWIG interface instead.
package MCAST;
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
package MCASTc;
bootstrap MCAST;
package MCAST;
@EXPORT = qw( );
# ---------- BASE METHODS -------------
package MCAST;
sub TIEHASH {
my ($classname,$obj) = @_;
return bless $obj, $classname;
}
sub CLEAR { }
sub FIRSTKEY { }
sub NEXTKEY { }
sub FETCH {
my ($self,$field) = @_;
my $member_func = "swig_${field}_get";
$self->$member_func();
}
sub STORE {
my ($self,$field,$newval) = @_;
my $member_func = "swig_${field}_set";
$self->$member_func($newval);
}
sub this {
my $ptr = shift;
return tied(%$ptr);
}
# ------- FUNCTION WRAPPERS --------
package MCAST;
############# Class : MCAST::McastHandle ##############
package MCAST::McastHandle;
use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
@ISA = qw( MCAST );
%OWNER = ();
%ITERATORS = ();
sub new {
my $pkg = shift;
my $self = MCASTc::new_McastHandle(@_);
bless $self, $pkg if defined($self);
}
sub DESTROY {
return unless $_[0]->isa('HASH');
my $self = tied(%{$_[0]});
return unless defined $self;
delete $ITERATORS{$self};
if (exists $OWNER{$self}) {
MCASTc::delete_McastHandle($self);
delete $OWNER{$self};
}
}
*send = *MCASTc::McastHandle_send;
*recv = *MCASTc::McastHandle_recv;
*fileno = *MCASTc::McastHandle_fileno;
sub DISOWN {
my $self = shift;
my $ptr = tied(%$self);
delete $OWNER{$ptr};
}
sub ACQUIRE {
my $self = shift;
my $ptr = tied(%$self);
$OWNER{$ptr} = 1;
}
# ------- VARIABLE STUBS --------
package MCAST;
use constant {
MCAST_SEND => (1 << 0),
MCAST_RECV => (1 << 1),
MCAST_TTL_HOST => (1 << 2),
MCAST_TTL_SUBNET => (1 << 3),
MCAST_TTL_SITE => (1 << 4),
MCAST_TTL_REGION => (1 << 5),
MCAST_TTL_CONTINENT => (1 << 6),
MCAST_TTL_UNIVERSE => (1 << 7)
};
1;

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2011, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h>
#include "mcast.h"
#include <poll.h>
int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle, mcast_flag_t flags)
{
uint32_t one = 1;
memset(handle, 0, sizeof(*handle));
if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || !(handle->sock = socket(AF_INET, SOCK_DGRAM, 0))) {
return -1;
}
handle->send_addr.sin_family = AF_INET;
handle->send_addr.sin_addr.s_addr = inet_addr(host);
handle->send_addr.sin_port = htons(port);
setsockopt(handle->sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if ((flags & MCAST_RECV)) {
struct ip_mreq mreq;
handle->recv_addr.sin_family = AF_INET;
handle->recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
handle->recv_addr.sin_port = htons(port);
mreq.imr_multiaddr.s_addr = inet_addr(host);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
close(handle->sock);
handle->sock = -1;
return -1;
}
if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr, sizeof(handle->recv_addr)) < 0) {
close(handle->sock);
handle->sock = -1;
return -1;
}
}
handle->ttl = 1;
if ((flags & MCAST_TTL_HOST)) {
handle->ttl = 0;
}
if ((flags & MCAST_TTL_SUBNET)) {
handle->ttl = 1;
}
if ((flags & MCAST_TTL_SITE)) {
handle->ttl = 32;
}
if ((flags & MCAST_TTL_REGION)) {
handle->ttl = 64;
}
if ((flags & MCAST_TTL_CONTINENT)) {
handle->ttl = 128;
}
if ((flags & MCAST_TTL_UNIVERSE)) {
handle->ttl = 255;
}
setsockopt(handle->sock, IPPROTO_IP, IP_MULTICAST_TTL, &handle->ttl, sizeof(handle->ttl));
handle->ready = 1;
return 0;
}
void mcast_socket_close(mcast_handle_t *handle)
{
if (handle->sock > -1) {
close(handle->sock);
handle->sock = -1;
}
}
ssize_t mcast_socket_send(mcast_handle_t *handle, void *data, size_t datalen)
{
if (handle->sock <= -1) {
return -1;
}
if (data == NULL || datalen == 0) {
data = handle->buffer;
datalen = sizeof(handle->buffer);
}
return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr, sizeof(handle->send_addr));
}
ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, int ms)
{
socklen_t addrlen = sizeof(handle->recv_addr);
int r;
if (data == NULL || datalen == 0) {
data = handle->buffer;
datalen = sizeof(handle->buffer);
}
if (ms > 0) {
struct pollfd pfds[1];
pfds[0].fd = handle->sock;
pfds[0].events = POLLIN|POLLERR;
if ((r = poll(pfds, 1, ms)) <= 0) {
return r;
}
if (pfds[0].revents & POLLERR) {
return -1;
}
}
return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr, &addrlen);
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2011, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __MCAST_H
#define __MCAST_H
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
#if EMACS_WORKS
}
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef struct {
int sock;
unsigned char ttl;
struct sockaddr_in send_addr;
struct sockaddr_in recv_addr;
unsigned char buffer[65536];
int ready;
} mcast_handle_t;
typedef enum {
MCAST_SEND = (1 << 0),
MCAST_RECV = (1 << 1),
MCAST_TTL_HOST = (1 << 2),
MCAST_TTL_SUBNET = (1 << 3),
MCAST_TTL_SITE = (1 << 4),
MCAST_TTL_REGION = (1 << 5),
MCAST_TTL_CONTINENT = (1 << 6),
MCAST_TTL_UNIVERSE = (1 << 7)
} mcast_flag_t;
int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle, mcast_flag_t flags);
void mcast_socket_close(mcast_handle_t *handle);
ssize_t mcast_socket_send(mcast_handle_t *handle, void *data, size_t datalen);
ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, int ms);
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
#endif

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2011, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mcast.h"
#include "mcast_cpp.h"
#include <string.h>
#include <poll.h>
McastHandle::McastHandle(const char *host, int port, int flags)
{
mcast_socket_create(host, port, &handle, (mcast_flag_t) flags);
}
McastHandle::~McastHandle()
{
mcast_socket_close(&handle);
}
int McastHandle::send(const char *data)
{
return (int) mcast_socket_send(&handle, (void *)data, strlen(data) + 1);
}
char *McastHandle::recv(int ms)
{
int r;
if ((r = mcast_socket_recv(&handle, NULL, 0, ms)) > 0) {
*((char *)handle.buffer + r) = '\0';
return (char *) handle.buffer;
}
return NULL;
}
int McastHandle::fileno(void)
{
return handle.sock;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2011, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __MCAST_CPP_H
#define __MCAST_CPP_H
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
#if EMACS_WORKS
}
#endif
class McastHandle {
private:
mcast_handle_t handle;
public:
McastHandle(const char *host, int port, int flags);
virtual ~McastHandle();
int send(const char *data);
char *recv(int ms = 0);
int fileno(void);
};
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
#include <EXTERN.h>
#include <perl.h>
EXTERN_C void xs_init (pTHX);
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
EXTERN_C void
xs_init(pTHX)
{
char *file = __FILE__;
dXSUB_SYS;
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
}

View File

@ -0,0 +1,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "mcast.h"
int main(int argc, char *argv[])
{
mcast_handle_t handle;
if (argc < 2) {
printf("WTF\n");
exit(-1);
}
mcast_socket_create("231.3.3.7", 1337, &handle, MCAST_SEND | MCAST_RECV | MCAST_TTL_HOST);
perror("create");
if (!strcmp(argv[1], "send")) {
mcast_socket_send(&handle, argv[2], strlen(argv[2]));
exit(0);
}
for(;;) {
int r = mcast_socket_recv(&handle, NULL, 0);
printf("RECV %d [%s]\n", r, (char *)handle.buffer);
}
}

View File

@ -0,0 +1,19 @@
use MCAST;
my $s = new MCAST::McastHandle("231.3.3.7", 1337, MCAST_SEND | MCAST_RECV | MCAST_TTL_HOST);
my $action = shift;
if ($action eq "send") {
$s->send("W00t from Perl " . shift);
exit;
}
for(;;) {
my $foo = $s->recv(100);
if ($foo) {
print "RECV [$foo]\n";
} else {
print "PING\n";
}
}

View File

@ -0,0 +1,23 @@
use MCAST;
my $action = shift;
if ($action eq "send") {
my $s = new MCAST::McastHandle("224.1.1.1", 1337, MCAST::MCAST_SEND | MCAST::MCAST_TTL_HOST);
$s->send(shift);
print "Sending message";
exit;
}
my $s = new MCAST::McastHandle("224.1.1.1", 1338, MCAST::MCAST_RECV | MCAST::MCAST_TTL_HOST);
for(;;) {
my $foo = $s->recv();
if ($foo) {
print "RECV [$foo]\n";
} else {
print "PING\n";
}
}

View File

@ -0,0 +1,287 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="mod_verto"
ProjectGUID="{11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}"
RootNamespace="mod_verto"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\mod_verto.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mod_verto</ProjectName>
<ProjectGuid>{11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}</ProjectGuid>
<RootNamespace>mod_verto</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_verto.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>mod_verto</ProjectName>
<ProjectGuid>{11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}</ProjectGuid>
<RootNamespace>mod_verto</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\w32\module_debug.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_verto.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2012.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,272 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* 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 FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
* mod_html.h -- HTML 5 interface
*
*/
#ifndef MOD_VERTO_H
#define MOD_VERTO_H
#include <switch.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <stdarg.h>
#include <netinet/tcp.h>
#include <sys/un.h>
#include <assert.h>
#include <errno.h>
#include <pwd.h>
#include <netdb.h>
#include <openssl/ssl.h>
#include "mcast.h"
#define MAXPENDING 10000
#define STACK_SIZE 80 * 1024
#define VERTO_CHAT_PROTO "verto"
#define copy_string(x,y,z) strncpy(x, y, z - 1)
#define set_string(x,y) strncpy(x, y, sizeof(x)-1)
#define CODE_INVALID -32600
#define CODE_AUTH_REQUIRED -32000
#define CODE_AUTH_FAILED -32001
#define CODE_SESSION_ERROR -32002
typedef enum {
PTYPE_CLIENT = (1 << 0),
PTYPE_CLIENT_SSL = (1 << 1)
} jsock_type_t;
typedef enum {
JPFLAG_INIT = (1 << 0),
JPFLAG_AUTHED = (1 << 1),
JPFLAG_CHECK_ATTACH = (1 << 2)
} jpflag_t;
struct verto_profile_s;
struct jsock_s {
int client_socket;
switch_memory_pool_t *pool;
switch_thread_t *thread;
wsh_t ws;
unsigned char buf[65535];
char *name;
jsock_type_t ptype;
struct sockaddr_in local_addr;
struct sockaddr_in remote_addr;
struct sockaddr_in send_addr;
struct ucred credentials;
struct passwd pw;
int drop;
int local_sock;
SSL *ssl;
jpflag_t flags;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
switch_event_t *allowed_methods;
switch_event_t *allowed_jsapi;
switch_event_t *allowed_fsapi;
switch_event_t *allowed_event_channels;
char *id;
char *domain;
char *uid;
char *dialplan;
char *context;
struct verto_profile_s *profile;
switch_thread_rwlock_t *rwlock;
switch_mutex_t *write_mutex;
switch_event_t *params;
switch_event_t *vars;
struct jsock_s *next;
};
typedef struct jsock_s jsock_t;
#define MAX_BIND 25
#define MAX_RTPIP 25
struct ips {
char local_ip[256];
in_addr_t local_ip_addr;
int local_port;
int secure;
};
typedef enum {
TFLAG_SENT_MEDIA = (1 << 0),
TFLAG_ATTACH_REQ = (1 << 1)
} tflag_t;
typedef struct verto_pvt_s {
char *jsock_uuid;
char *call_id;
char *r_sdp;
tflag_t flags;
switch_core_session_t *session;
switch_channel_t *channel;
switch_media_handle_t *smh;
switch_core_media_params_t *mparams;
switch_call_cause_t remote_hangup_cause;
time_t detach_time;
struct verto_pvt_s *next;
} verto_pvt_t;
struct verto_profile_s {
char *name;
switch_mutex_t *mutex;
switch_memory_pool_t *pool;
switch_thread_rwlock_t *rwlock;
struct ips ip[MAX_BIND];
int i;
const SSL_METHOD *ssl_method;
SSL_CTX *ssl_ctx;
char cert[512];
char key[512];
char chain[512];
jsock_t *jsock_head;
int jsock_count;
int server_socket[MAX_BIND];
int running;
int ssl_ready;
int ready;
int debug;
int in_thread;
char *userauth;
char *root_passwd;
char *context;
char *dialplan;
char *mcast_ip;
switch_port_t mcast_port;
mcast_handle_t mcast_sub;
mcast_handle_t mcast_pub;
char *extrtpip;
char *rtpip[MAX_RTPIP];
int rtpip_index;
int rtpip_cur;
char *cand_acl[SWITCH_MAX_CAND_ACL];
uint32_t cand_acl_count;
char *inbound_codec_string;
char *outbound_codec_string;
char *timer_name;
char *local_network;
struct verto_profile_s *next;
};
typedef struct verto_profile_s verto_profile_t;
struct globals_s {
switch_mutex_t *mutex;
switch_memory_pool_t *pool;
int profile_count;
verto_profile_t *profile_head;
int sig;
int running;
switch_hash_t *method_hash;
switch_mutex_t *method_mutex;
switch_hash_t *event_channel_hash;
switch_thread_rwlock_t *event_channel_rwlock;
int debug;
int ready;
int profile_threads;
int enable_presence;
switch_hash_t *jsock_hash;
switch_mutex_t *jsock_mutex;
verto_pvt_t *tech_head;
switch_thread_rwlock_t *tech_rwlock;
switch_thread_cond_t *detach_cond;
switch_mutex_t *detach_mutex;
switch_mutex_t *detach2_mutex;
uint32_t detached;
uint32_t detach_timeout;
switch_event_channel_id_t event_channel_id;
};
extern struct globals_s globals;
typedef switch_bool_t (*jrpc_func_t)(const char *method, cJSON *params, jsock_t *jsock, cJSON **response);
void set_log_path(const char *path);
/** @} */
#endif
/* 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:
*/

View File

@ -0,0 +1,879 @@
#include "ws.h"
#include <pthread.h>
#ifndef _MSC_VER
#include <fcntl.h>
#endif
#ifndef _MSC_VER
#define ms_sleep(x) usleep( x * 1000);
#else
#define ms_sleep(x) Sleep( x );
#endif
#define WS_BLOCK 1
#define WS_NOBLOCK 0
#define SHA1_HASH_SIZE 20
struct ws_globals_s ws_globals;
#ifndef WSS_STANDALONE
void init_ssl(void)
{
SSL_library_init();
}
void deinit_ssl(void)
{
return;
}
#else
static unsigned long pthreads_thread_id(void);
static void pthreads_locking_callback(int mode, int type, const char *file, int line);
static pthread_mutex_t *lock_cs;
static long *lock_count;
static void thread_setup(void)
{
int i;
lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
for (i = 0; i < CRYPTO_num_locks(); i++) {
lock_count[i] = 0;
pthread_mutex_init(&(lock_cs[i]), NULL);
}
CRYPTO_set_id_callback(pthreads_thread_id);
CRYPTO_set_locking_callback(pthreads_locking_callback);
}
static void thread_cleanup(void)
{
int i;
CRYPTO_set_locking_callback(NULL);
for (i=0; i<CRYPTO_num_locks(); i++) {
pthread_mutex_destroy(&(lock_cs[i]));
}
OPENSSL_free(lock_cs);
OPENSSL_free(lock_count);
}
static void pthreads_locking_callback(int mode, int type, const char *file, int line)
{
if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(&(lock_cs[type]));
lock_count[type]++;
} else {
pthread_mutex_unlock(&(lock_cs[type]));
}
}
static unsigned long pthreads_thread_id(void)
{
return (unsigned long) pthread_self();
}
void init_ssl(void) {
SSL_library_init();
OpenSSL_add_all_algorithms(); /* load & register cryptos */
SSL_load_error_strings(); /* load all error messages */
ws_globals.ssl_method = TLSv1_server_method(); /* create server instance */
ws_globals.ssl_ctx = SSL_CTX_new(ws_globals.ssl_method); /* create context */
assert(ws_globals.ssl_ctx);
/* set the local certificate from CertFile */
SSL_CTX_use_certificate_file(ws_globals.ssl_ctx, ws_globals.cert, SSL_FILETYPE_PEM);
/* set the private key from KeyFile */
SSL_CTX_use_PrivateKey_file(ws_globals.ssl_ctx, ws_globals.key, SSL_FILETYPE_PEM);
/* verify private key */
if ( !SSL_CTX_check_private_key(ws_globals.ssl_ctx) ) {
abort();
}
SSL_CTX_set_cipher_list(ws_globals.ssl_ctx, "HIGH:!DSS:!aNULL@STRENGTH");
thread_setup();
}
void deinit_ssl(void) {
thread_cleanup();
}
#endif
static const char c64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int cheezy_get_var(char *data, char *name, char *buf, size_t buflen)
{
char *p=data;
/* the old way didnt make sure that variable values were used for the name hunt
* and didnt ensure that only a full match of the variable name was used
*/
do {
if(!strncmp(p,name,strlen(name)) && *(p+strlen(name))==':') break;
} while((p = (strstr(p,"\n")+1))!=(char *)1);
if (p != (char *)1 && *p!='\0') {
char *v, *e = 0;
v = strchr(p, ':');
if (v) {
v++;
while(v && *v == ' ') {
v++;
}
if (v) {
e = strchr(v, '\r');
if (!e) {
e = strchr(v, '\n');
}
}
if (v && e) {
int cplen;
size_t len = e - v;
if (len > buflen - 1) {
cplen = buflen -1;
} else {
cplen = len;
}
strncpy(buf, v, cplen);
*(buf+cplen) = '\0';
return 1;
}
}
}
return 0;
}
static int b64encode(unsigned char *in, size_t ilen, unsigned char *out, size_t olen)
{
int y=0,bytes=0;
size_t x=0;
unsigned int b=0,l=0;
if(olen) {
}
for(x=0;x<ilen;x++) {
b = (b<<8) + in[x];
l += 8;
while (l >= 6) {
out[bytes++] = c64[(b>>(l-=6))%64];
if(++y!=72) {
continue;
}
//out[bytes++] = '\n';
y=0;
}
}
if (l > 0) {
out[bytes++] = c64[((b%16)<<(6-l))%64];
}
if (l != 0) while (l < 6) {
out[bytes++] = '=', l += 2;
}
return 0;
}
#ifdef NO_OPENSSL
static void sha1_digest(char *digest, unsigned char *in)
{
SHA1Context sha;
char *p;
int x;
SHA1Init(&sha);
SHA1Update(&sha, in, strlen(in));
SHA1Final(&sha, digest);
}
#else
static void sha1_digest(unsigned char *digest, char *in)
{
SHA_CTX sha;
SHA1_Init(&sha);
SHA1_Update(&sha, in, strlen(in));
SHA1_Final(digest, &sha);
}
#endif
int ws_handshake(wsh_t *wsh)
{
char key[256] = "";
char version[5] = "";
char proto[256] = "";
char proto_buf[384] = "";
char uri[256] = "";
char input[256] = "";
unsigned char output[SHA1_HASH_SIZE] = "";
char b64[256] = "";
char respond[512] = "";
ssize_t bytes;
char *p, *e = 0;
if (wsh->sock == ws_sock_invalid) {
return -3;
}
while((bytes = ws_raw_read(wsh, wsh->buffer + wsh->datalen, wsh->buflen - wsh->datalen, WS_BLOCK)) > 0) {
wsh->datalen += bytes;
if (strstr(wsh->buffer, "\r\n\r\n") || strstr(wsh->buffer, "\n\n")) {
break;
}
}
if (bytes > sizeof(wsh->buffer) -1) {
goto err;
}
*(wsh->buffer+bytes) = '\0';
if (strncasecmp(wsh->buffer, "GET ", 4)) {
goto err;
}
p = wsh->buffer + 4;
e = strchr(p, ' ');
if (!e) {
goto err;
}
strncpy(uri, p, e-p);
cheezy_get_var(wsh->buffer, "Sec-WebSocket-Key", key, sizeof(key));
cheezy_get_var(wsh->buffer, "Sec-WebSocket-Version", version, sizeof(version));
cheezy_get_var(wsh->buffer, "Sec-WebSocket-Protocol", proto, sizeof(proto));
if (!*key) {
goto err;
}
snprintf(input, sizeof(input), "%s%s", key, WEBSOCKET_GUID);
sha1_digest(output, input);
b64encode((unsigned char *)output, SHA1_HASH_SIZE, (unsigned char *)b64, sizeof(b64));
if (*proto) {
snprintf(proto_buf, sizeof(proto_buf), "Sec-WebSocket-Protocol: %s\r\n", proto);
}
snprintf(respond, sizeof(respond),
"HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: %s\r\n"
"%s\r\n",
b64,
proto_buf);
ws_raw_write(wsh, respond, strlen(respond));
wsh->handshake = 1;
return 0;
err:
snprintf(respond, sizeof(respond), "HTTP/1.1 400 Bad Request\r\n"
"Sec-WebSocket-Version: 13\r\n\r\n");
//printf("ERR:\n%s\n", respond);
ws_raw_write(wsh, respond, strlen(respond));
ws_close(wsh, WS_NONE);
return -1;
}
ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
{
ssize_t r;
int err = 0;
if (wsh->ssl) {
do {
r = SSL_read(wsh->ssl, data, bytes);
ms_sleep(10);
if (r == -1) {
err = SSL_get_error(wsh->ssl, r);
if (!block && err == SSL_ERROR_WANT_READ) {
r = -2;
goto end;
}
}
} while (r == -1 && err == SSL_ERROR_WANT_READ && wsh->x < 100);
goto end;
}
do {
r = recv(wsh->sock, data, bytes, 0);
ms_sleep(10);
} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 100);
if (wsh->x >= 100) {
r = -1;
}
end:
if (r > 0) {
*((char *)data + r) = '\0';
}
if (r >= 0) {
wsh->x = 0;
}
return r;
}
ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
{
size_t r;
if (wsh->ssl) {
do {
r = SSL_write(wsh->ssl, data, bytes);
} while (r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_WRITE);
return r;
}
do {
r = send(wsh->sock, data, bytes, 0);
} while (r == -1 && xp_is_blocking(xp_errno()));
//if (r<0) {
//printf("wRITE FAIL: %s\n", strerror(errno));
//}
return r;
}
#ifdef _MSC_VER
static int setup_socket(ws_socket_t sock)
{
unsigned long v = 1;
if (ioctlsocket(sock, FIONBIO, &v) == SOCKET_ERROR) {
return -1;
}
return 0;
}
static int restore_socket(ws_socket_t sock)
{
unsigned long v = 0;
if (ioctlsocket(sock, FIONBIO, &v) == SOCKET_ERROR) {
return -1;
}
return 0;
}
#else
static int setup_socket(ws_socket_t sock)
{
int flags = fcntl(sock, F_GETFL, 0);
return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}
static int restore_socket(ws_socket_t sock)
{
int flags = fcntl(sock, F_GETFL, 0);
flags &= ~O_NONBLOCK;
return fcntl(sock, F_SETFL, flags);
}
#endif
static int establish_logical_layer(wsh_t *wsh)
{
if (!wsh->sanity) {
return -1;
}
if (wsh->logical_established) {
return 0;
}
if (wsh->secure && !wsh->secure_established) {
int code;
if (!wsh->ssl) {
wsh->ssl = SSL_new(wsh->ssl_ctx);
assert(wsh->ssl);
SSL_set_fd(wsh->ssl, wsh->sock);
}
do {
code = SSL_accept(wsh->ssl);
if (code == 1) {
wsh->secure_established = 1;
break;
}
if (code == 0) {
return -1;
}
if (code < 0) {
if (code == -1 && SSL_get_error(wsh->ssl, code) != SSL_ERROR_WANT_READ) {
return -1;
}
}
if (wsh->block) {
ms_sleep(10);
} else {
ms_sleep(1);
}
wsh->sanity--;
if (!wsh->block) {
return -2;
}
} while (wsh->sanity > 0);
if (!wsh->sanity) {
return -1;
}
}
while (!wsh->down && !wsh->handshake) {
int r = ws_handshake(wsh);
if (r < 0) {
wsh->down = 1;
return -1;
}
if (!wsh->handshake && !wsh->block) {
return -2;
}
}
wsh->logical_established = 1;
return 0;
}
int ws_init(wsh_t *wsh, ws_socket_t sock, SSL_CTX *ssl_ctx, int close_sock, int block)
{
memset(wsh, 0, sizeof(*wsh));
wsh->sock = sock;
wsh->block = block;
wsh->sanity = 5000;
wsh->ssl_ctx = ssl_ctx;
if (!ssl_ctx) {
ssl_ctx = ws_globals.ssl_ctx;
}
if (close_sock) {
wsh->close_sock = 1;
}
wsh->buflen = sizeof(wsh->buffer);
wsh->secure = ssl_ctx ? 1 : 0;
setup_socket(sock);
if (establish_logical_layer(wsh) == -1) {
return -1;
}
if (wsh->down) {
return -1;
}
return 0;
}
void ws_destroy(wsh_t *wsh)
{
if (!wsh) {
return;
}
if (!wsh->down) {
ws_close(wsh, WS_NONE);
}
if (wsh->down > 1) {
return;
}
wsh->down = 2;
if (wsh->ssl) {
int code;
do {
code = SSL_shutdown(wsh->ssl);
} while (code == -1 && SSL_get_error(wsh->ssl, code) == SSL_ERROR_WANT_READ);
SSL_free(wsh->ssl);
wsh->ssl = NULL;
}
}
ssize_t ws_close(wsh_t *wsh, int16_t reason)
{
if (wsh->down) {
return -1;
}
wsh->down = 1;
if (reason && wsh->sock != ws_sock_invalid) {
uint16_t *u16;
uint8_t fr[4] = {WSOC_CLOSE | 0x80, 2, 0};
u16 = (uint16_t *) &fr[2];
*u16 = htons((int16_t)reason);
ws_raw_write(wsh, fr, 4);
}
restore_socket(wsh->sock);
if (wsh->close_sock && wsh->sock != ws_sock_invalid) {
close(wsh->sock);
}
wsh->sock = ws_sock_invalid;
return reason * -1;
}
ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
{
ssize_t need = 2;
char *maskp;
int ll = 0;
again:
need = 2;
maskp = NULL;
*data = NULL;
ll = establish_logical_layer(wsh);
if (ll < 0) {
return ll;
}
if (wsh->down) {
return -1;
}
if (!wsh->handshake) {
return ws_close(wsh, WS_PROTO_ERR);
}
if ((wsh->datalen = ws_raw_read(wsh, wsh->buffer, 9, wsh->block)) < 0) {
if (wsh->datalen == -2) {
return -2;
}
return ws_close(wsh, WS_PROTO_ERR);
}
if (wsh->datalen < need) {
if ((wsh->datalen += ws_raw_read(wsh, wsh->buffer + wsh->datalen, 9 - wsh->datalen, WS_BLOCK)) < need) {
/* too small - protocol err */
return ws_close(wsh, WS_PROTO_ERR);
}
}
*oc = *wsh->buffer & 0xf;
switch(*oc) {
case WSOC_CLOSE:
{
wsh->plen = wsh->buffer[1] & 0x7f;
*data = (uint8_t *) &wsh->buffer[2];
return ws_close(wsh, 1000);
}
break;
case WSOC_CONTINUATION:
case WSOC_TEXT:
case WSOC_BINARY:
case WSOC_PING:
case WSOC_PONG:
{
//int fin = (wsh->buffer[0] >> 7) & 1;
int mask = (wsh->buffer[1] >> 7) & 1;
if (mask) {
need += 4;
if (need > wsh->datalen) {
/* too small - protocol err */
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_PROTO_ERR);
}
}
wsh->plen = wsh->buffer[1] & 0x7f;
wsh->payload = &wsh->buffer[2];
if (wsh->plen == 127) {
uint64_t *u64;
need += 8;
if (need > wsh->datalen) {
/* too small - protocol err */
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_PROTO_ERR);
}
u64 = (uint64_t *) wsh->payload;
wsh->payload += 8;
wsh->plen = ntohl((u_long)*u64);
} else if (wsh->plen == 126) {
uint16_t *u16;
need += 2;
if (need > wsh->datalen) {
/* too small - protocol err */
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_PROTO_ERR);
}
u16 = (uint16_t *) wsh->payload;
wsh->payload += 2;
wsh->plen = ntohs(*u16);
}
if (mask) {
maskp = (char *)wsh->payload;
wsh->payload += 4;
}
need = (wsh->plen - (wsh->datalen - need));
if (need < 0) {
/* invalid read - protocol err .. */
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_PROTO_ERR);
}
if ((need + wsh->datalen) > (ssize_t)wsh->buflen) {
/* too big - Ain't nobody got time fo' dat */
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_DATA_TOO_BIG);
}
wsh->rplen = wsh->plen - need;
while(need) {
ssize_t r = ws_raw_read(wsh, wsh->payload + wsh->rplen, need, WS_BLOCK);
if (r < 1) {
/* invalid read - protocol err .. */
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_PROTO_ERR);
}
wsh->datalen += r;
wsh->rplen += r;
need -= r;
}
if (mask && maskp) {
ssize_t i;
for (i = 0; i < wsh->datalen; i++) {
wsh->payload[i] ^= maskp[i % 4];
}
}
if (*oc == WSOC_PING) {
ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen);
goto again;
}
*(wsh->payload+wsh->rplen) = '\0';
*data = (uint8_t *)wsh->payload;
//printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->rplen, *oc, (char *)*data);
return wsh->rplen;
}
break;
default:
{
/* invalid op code - protocol err .. */
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_PROTO_ERR);
}
break;
}
}
ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes)
{
if (bytes + wsh->wdatalen > wsh->buflen) {
return -1;
}
memcpy(wsh->wbuffer + wsh->wdatalen, data, bytes);
wsh->wdatalen += bytes;
return bytes;
}
ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc)
{
ssize_t r = 0;
if (!wsh->wdatalen) {
return -1;
}
r = ws_write_frame(wsh, oc, wsh->wbuffer, wsh->wdatalen);
wsh->wdatalen = 0;
return r;
}
ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
{
uint8_t hdr[14] = { 0 };
size_t hlen = 2;
if (wsh->down) {
return -1;
}
//printf("WRITE[%ld]-----------------------------:\n[%s]\n-----------------------------------\n", bytes, (char *) data);
hdr[0] = (uint8_t)(oc | 0x80);
if (bytes < 126) {
hdr[1] = (uint8_t)bytes;
} else if (bytes < 0x10000) {
uint16_t *u16;
hdr[1] = 126;
hlen += 2;
u16 = (uint16_t *) &hdr[2];
*u16 = htons((uint16_t) bytes);
} else {
uint64_t *u64;
hdr[1] = 127;
hlen += 8;
u64 = (uint64_t *) &hdr[2];
*u64 = htonl(bytes);
}
if (ws_raw_write(wsh, (void *) &hdr[0], hlen) != (ssize_t)hlen) {
return -1;
}
if (ws_raw_write(wsh, data, bytes) != (ssize_t)bytes) {
return -2;
}
return bytes;
}
#ifdef _MSC_VER
int xp_errno(void)
{
return WSAGetLastError();
}
int xp_is_blocking(int errcode)
{
return errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS;
}
#else
int xp_errno(void)
{
return errno;
}
int xp_is_blocking(int errcode)
{
return errcode == EAGAIN || errcode == EWOULDBLOCK || errcode == EINPROGRESS || errcode == EINTR || errcode == ETIMEDOUT;
}
#endif

View File

@ -0,0 +1,120 @@
#ifndef _WS_H
#define _WS_H
//#define WSS_STANDALONE 1
#define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
#define B64BUFFLEN 1024
#include <sys/types.h>
#ifndef _MSC_VER
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/socket.h>
#else
#pragma warning(disable:4996)
#endif
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
//#include "sha1.h"
#include <openssl/ssl.h>
#ifdef _MSC_VER
#define strncasecmp _strnicmp
#define snprintf _snprintf
#ifdef _WIN64
#define WS_SSIZE_T __int64
#elif _MSC_VER >= 1400
#define WS_SSIZE_T __int32 __w64
#else
#define WS_SSIZE_T __int32
#endif
typedef WS_SSIZE_T ssize_t;
#endif
struct ws_globals_s {
const SSL_METHOD *ssl_method;
SSL_CTX *ssl_ctx;
char cert[512];
char key[512];
};
extern struct ws_globals_s ws_globals;
typedef int ws_socket_t;
#define ws_sock_invalid -1
typedef enum {
WS_NONE = 0,
WS_NORMAL = 1000,
WS_PROTO_ERR = 1002,
WS_DATA_TOO_BIG = 1009
} ws_cause_t;
typedef enum {
WSOC_CONTINUATION = 0x0,
WSOC_TEXT = 0x1,
WSOC_BINARY = 0x2,
WSOC_CLOSE = 0x8,
WSOC_PING = 0x9,
WSOC_PONG = 0xA
} ws_opcode_t;
typedef struct wsh_s {
ws_socket_t sock;
char buffer[65536];
char wbuffer[65536];
size_t buflen;
ssize_t datalen;
ssize_t wdatalen;
char *payload;
ssize_t plen;
ssize_t rplen;
SSL *ssl;
int handshake;
uint8_t down;
int secure;
uint8_t close_sock;
SSL_CTX *ssl_ctx;
int block;
int sanity;
int secure_established;
int logical_established;
int x;
} wsh_t;
ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc);
ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes);
ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block);
ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes);
ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data);
ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes);
int ws_init(wsh_t *wsh, ws_socket_t sock, SSL_CTX *ssl_ctx, int close_sock, int block);
ssize_t ws_close(wsh_t *wsh, int16_t reason);
void ws_destroy(wsh_t *wsh);
void init_ssl(void);
void deinit_ssl(void);
int xp_errno(void);
int xp_is_blocking(int errcode);
#ifndef _MSC_VER
static inline uint64_t get_unaligned_uint64(const void *p)
{
const struct { uint64_t d; } __attribute__((packed)) *pp = p;
return pp->d;
}
#endif
#endif