- switch to latest resiprocate

This commit is contained in:
2023-05-11 15:34:13 +03:00
parent 55445f6630
commit 95fbaf5379
10736 changed files with 2057171 additions and 38694 deletions

View File

@@ -0,0 +1,9 @@
/Makefile.in
/Makefile
/.deps
/.libs
/.dirstamp
/ichat-gw

View File

@@ -0,0 +1,216 @@
#include "rutil/Logger.hxx"
#include "rutil/ParseBuffer.hxx"
#include "AppSubsystem.hxx"
#include "AddressTranslator.hxx"
#include "rutil/WinLeakCheck.hxx"
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
using namespace gateway;
using namespace resip;
using namespace std;
namespace gateway
{
AddressTranslator::AddressTranslator()
{
}
AddressTranslator::~AddressTranslator()
{
// Destroy all of the filters
for(FilterOpList::iterator it = mFilterOperators.begin(); it != mFilterOperators.end(); it++)
{
if ( it->preq )
{
regfree ( it->preq );
delete it->preq;
it->preq = 0;
}
}
mFilterOperators.clear();
}
void
AddressTranslator::addTranslation(const resip::Data& matchingPattern,
const resip::Data& rewriteExpression)
{
InfoLog( << "Add translation " << matchingPattern << " -> " << rewriteExpression);
FilterOp filter;
filter.mMatchingPattern = matchingPattern;
filter.mRewriteExpression = rewriteExpression;
if( !filter.mMatchingPattern.empty() )
{
int flags = REG_EXTENDED;
if( filter.mRewriteExpression.find("$") == Data::npos )
{
flags |= REG_NOSUB;
}
filter.preq = new regex_t;
int ret = regcomp( filter.preq, filter.mMatchingPattern.c_str(), flags );
if( ret != 0 )
{
delete filter.preq;
ErrLog( << "Translation has invalid match expression: "
<< filter.mMatchingPattern );
filter.preq = 0;
}
}
mFilterOperators.push_back( filter );
}
void
AddressTranslator::removeTranslation(const resip::Data& matchingPattern )
{
FilterOpList::iterator it = mFilterOperators.begin();
while ( it != mFilterOperators.end() )
{
if ( it->mMatchingPattern == matchingPattern )
{
FilterOpList::iterator i = it;
it++;
if ( i->preq )
{
regfree ( i->preq );
delete i->preq;
i->preq = 0;
}
mFilterOperators.erase(i);
}
else
{
it++;
}
}
}
bool
AddressTranslator::translate(const resip::Data& address, resip::Data& translation, bool failIfNoRule)
{
bool rc=false;
DebugLog( << "Translating "<< address);
for (FilterOpList::iterator it = mFilterOperators.begin();
it != mFilterOperators.end(); it++)
{
Data rewrite = it->mRewriteExpression;
Data& match = it->mMatchingPattern;
if ( it->preq )
{
int ret;
const int nmatch=10;
regmatch_t pmatch[nmatch];
ret = regexec(it->preq, address.c_str(), nmatch, pmatch, 0/*eflags*/);
if ( ret != 0 )
{
// did not match
DebugLog( << " Skipped translation "<< address << " did not match " << match );
continue;
}
DebugLog( << " Matched translation "<< address << " matched " << match );
translation = rewrite;
rc=true;
if ( rewrite.find("$") != Data::npos )
{
for ( int i=1; i<nmatch; i++)
{
if ( pmatch[i].rm_so != -1 )
{
Data subExp(address.substr(pmatch[i].rm_so,
pmatch[i].rm_eo-pmatch[i].rm_so));
DebugLog( << " subExpression[" <<i <<"]="<< subExp );
Data result;
{
DataStream s(result);
ParseBuffer pb(translation);
while (true)
{
const char* a = pb.position();
pb.skipToChars( Data("$") + char('0'+i) );
if ( pb.eof() )
{
s << pb.data(a);
break;
}
else
{
s << pb.data(a);
pb.skipN(2);
s << subExp;
}
}
s.flush();
}
translation = result;
}
}
}
else
{
translation = rewrite;
rc = true;
}
break;
}
}
// If we didn't find a translation and we are not suppossed to fail, then just return address
if(!rc && !failIfNoRule)
{
rc = true;
translation = address;
}
InfoLog( << "Translated "<< address << " to " << translation);
return rc;
}
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,79 @@
#if !defined(AddressTranslator_hxx)
#define AddressTranslator_hxx
#include <list>
#ifdef WIN32
#include <pcreposix.h>
#else
#include <regex.h>
#endif
#include "rutil/Data.hxx"
namespace gateway
{
class AddressTranslator
{
public:
AddressTranslator();
~AddressTranslator();
void addTranslation(const resip::Data& matchingPattern,
const resip::Data& rewriteExpression);
void removeTranslation(const resip::Data& matchingPattern);
bool translate(const resip::Data& address, resip::Data& translation, bool failIfNoRule=false);
private:
class FilterOp
{
public:
resip::Data mMatchingPattern;
resip::Data mRewriteExpression;
regex_t *preq;
};
typedef std::list<FilterOp> FilterOpList;
FilterOpList mFilterOperators;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,38 @@
#include "AppSubsystem.hxx"
AppSubsystem AppSubsystem::GATEWAY("GATEWAY");
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,61 @@
#if !defined(AppSubsystem_hxx)
#define AppSubsystem_hxx
#include <iostream>
#include <rutil/Subsystem.hxx>
/**
This class is used in the logging subsystem to identify
logging messages generated from the iChat Gateway.
Author: Scott Godin (sgodin AT SipSpectrum DOT com)
*/
class AppSubsystem : public resip::Subsystem
{
public:
// Add new systems below
static AppSubsystem GATEWAY;
private:
explicit AppSubsystem(const char* rhs) : resip::Subsystem(rhs) {};
explicit AppSubsystem(const resip::Data& rhs);
AppSubsystem& operator=(const resip::Data& rhs);
};
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,175 @@
#if !defined(B2BSession_hxx)
#define B2BSession_hxx
#include <rutil/Log.hxx>
#include <rutil/SharedPtr.hxx>
#include <resip/dum/DialogUsageManager.hxx>
#include <resip/dum/InviteSessionHandler.hxx>
#include <resip/dum/DialogSetHandler.hxx>
#include <resip/dum/AppDialogSet.hxx>
namespace gateway
{
class Server;
class IChatIPPortData;
typedef unsigned int B2BSessionHandle;
class B2BSession : public resip::AppDialogSet
{
public:
B2BSession(Server& server, bool hasDialogSet=true);
virtual ~B2BSession();
virtual void end();
void setPeer(B2BSession* peer);
B2BSession* getPeer();
void stealPeer(B2BSession* victimSession);
B2BSessionHandle getB2BSessionHandle() const { return mHandle; }
void initiateIChatCallRequest(const std::string& to, const std::string& from);
bool createNewPeer(const resip::Uri& destinationUri, const resip::NameAddr& from, const resip::SdpContents *sdp);
void startIChatCall(const resip::Uri& destinationUri, const resip::NameAddr& from, const resip::SdpContents *sdp);
void startSIPCall(const resip::Uri& destinationUri, const resip::NameAddr& from, const resip::SdpContents *sdp);
bool checkIChatCallMatch(const resip::SipMessage& msg);
// iChat call notifications from Jabber Component
void notifyIChatCallCancelled();
void notifyIChatCallProceeding(const std::string& to);
void notifyIChatCallFailed(unsigned int statusCode);
void continueIChatCall(const std::string& remoteIPPortListBlob);
void timeoutIChatCall();
// IPC messages for Jabber Component
void initiateIChatCall();
void cancelIChatCall();
void proceedingIChatCall();
void acceptIChatCall();
void rejectIChatCall();
protected:
friend class Server;
virtual resip::SharedPtr<resip::UserProfile> selectUASUserProfile(const resip::SipMessage& msg);
// Invite Session Handler /////////////////////////////////////////////////////
virtual void onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
virtual void onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
virtual void onFailure(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&);
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
virtual void onConnected(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onStaleCallTimeout(resip::ClientInviteSessionHandle);
virtual void onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* msg);
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&);
virtual void onOffer(resip::InviteSessionHandle handle, const resip::SipMessage& msg, const resip::SdpContents& offer);
virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg);
virtual void onOfferRequestRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onRemoteSdpChanged(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents& sdp);
virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg);
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual bool doReferNoSub(const resip::SipMessage& msg);
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onForkDestroyed(resip::ClientInviteSessionHandle);
// DialogSetHandler //////////////////////////////////////////////
virtual void onTrying(resip::AppDialogSetHandle, const resip::SipMessage& msg);
virtual void onNonDialogCreatingProvisional(resip::AppDialogSetHandle, const resip::SipMessage& msg);
// ClientSubscriptionHandler ///////////////////////////////////////////////////
virtual void onUpdatePending(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
virtual void onUpdateActive(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
virtual void onUpdateExtension(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder);
virtual void onTerminated(resip::ClientSubscriptionHandle h, const resip::SipMessage* notify);
virtual void onNewSubscription(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify);
virtual int onRequestRetry(resip::ClientSubscriptionHandle h, int retryMinimum, const resip::SipMessage& notify);
private:
bool buildLocalOffer(resip::SdpContents& sdp);
bool buildLocalAnswer(resip::SdpContents& sdp);
bool provideLocalAnswer(void);
void endPeer();
bool isUACConnected();
bool isStaleFork(const resip::DialogId& dialogId);
void fixupSdp(const resip::SdpContents& origSdp, resip::SdpContents& fixedSdp);
unsigned int mapRejectionCodeForIChat(unsigned int statusCode);
Server& mServer;
bool mHasDialogSet;
resip::DialogUsageManager& mDum;
B2BSession* mPeer;
resip::InviteSessionHandle mInviteSessionHandle;
B2BSessionHandle mHandle;
resip::AppDialogSetHandle mReferringAppDialogSet;
// State information
resip::DialogId mUACConnectedDialogId;
bool mWaitingOfferFromPeer;
bool mWaitingAnswerFromPeer;
bool mWaitingNitAnswerFromPeer;
bool mAnchorMedia;
unsigned short mMediaRelayPort;
// IChat specific endpoint info
bool mIChatEndpoint;
bool mIChatWaitingToAccept;
bool mIChatWaitingToProceed;
bool mIChatWaitingToContinue;
resip::Uri mIChatDestination;
resip::NameAddr mIChatFrom;
resip::SdpContents* mIChatSdp;
std::string mIChatCallToJID;
std::string mIChatCallFromJID;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,443 @@
#include "ConfigParser.hxx"
#include "Server.hxx"
#include "AppSubsystem.hxx"
#include <iostream>
#include <fstream>
#include <iterator>
#include <rutil/DnsUtil.hxx>
#include <rutil/Log.hxx>
#include <rutil/Logger.hxx>
#include <rutil/WinLeakCheck.hxx>
using namespace gateway;
using namespace resip;
using namespace std;
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
namespace gateway
{
ConfigParser::ConfigParser(int argc, char** argv) :
// Defaults
mSipPort(5070),
mTlsPort(5071),
mTlsDomain(DnsUtil::getLocalHostName()),
mRegistrationTime(3600),
mRegistrationRetryTime(120),
mKeepAlives(true),
mLogLevel("INFO"),
mLogFilename("ichat-gw.log"),
mLogFileMaxLines(50000), // 50000 is about 5M size
mGatewayIPCPort(2078),
mJabberConnectorIPCPort(2079),
mHttpPort(5090),
mHttpAuth(false),
mHttpAuthPwd("admin"),
mIChatProceedingTimeout(5000),
mAlwaysRelayIChatMedia(true),
mPreferIPv6(false),
mSkipFirstIChatAddress(false),
mMediaRelayPortRangeMin(8000),
mMediaRelayPortRangeMax(9999),
mJabberComponentPort(5275),
mJabberServerPingDuration(60) // 1 min
{
// Parse config file first
parseConfigFile("ichat-gw.config");
// Parse command line options
// Note: command line overrides config file setting
parseCommandLine(argc, argv);
}
ConfigParser::~ConfigParser()
{
}
void
ConfigParser::parseCommandLine(int argc, char** argv)
{
// Loop through command line arguments and process them
for(int i = 1; i < argc; i++)
{
Data commandName(argv[i]);
// Process all commandNames that don't take values
if(isEqualNoCase(commandName, "-?") ||
isEqualNoCase(commandName, "--?") ||
isEqualNoCase(commandName, "--help") ||
isEqualNoCase(commandName, "/?"))
{
cout << "Command line options are:" << endl;
cout << " -a <IP Address> - bind SIP transports to this IP address" << endl;
cout << " -d <DNS servers> - comma seperated list of DNS servers, overrides OS detected list" << endl;
cout << " -gi <Gateway identity> - used in From header of click-to-call requests to initiator" << endl;
cout << " -sp <port num> - local port number to use for SIP messaging (UDP/TCP)" << endl;
cout << " -tp <port num> - local port number to use for TLS SIP messaging" << endl;
cout << " -td <domain name> - domain name to use for TLS server connections" << endl;
cout << " -nk - no keepalives, set this to disable sending of keepalives" << endl;
cout << " -op <SIP URI> - URI of a proxy server to use a SIP outbound proxy" << endl;
cout << " -l <NONE|CRIT|ERR|WARNING|INFO|DEBUG|STACK> - logging level" << endl;
cout << endl;
cout << "Sample Command line:" << endl;
cout << "ichat-gw -a 192.168.1.100 -l DEBUG" << endl;
exit(0);
}
else if(isEqualNoCase(commandName, "-nk"))
{
mKeepAlives = false;
}
else if(commandName.at(0) == '-')
{
commandName = commandName.substr(1); // Remove -
// Process commands that have values
Data commandValue(i+1 < argc ? argv[i+1] : Data::Empty);
if(commandValue.empty() || commandValue.at(0) == '-')
{
cerr << "Invalid command line parameters!" << endl;
exit(-1);
}
i++; // increment argument
//cout << "Command Line Name='" << commandName << "' value='" << commandValue << "'" << endl;
if(!processOption(commandName.lowercase(), commandValue))
{
cerr << "Invalid command line parameters!" << endl;
exit(-1);
}
}
else
{
cerr << "Invalid command line parameters!" << endl;
exit(-1);
}
}
}
void
ConfigParser::parseConfigFile(const Data& filename)
{
ifstream configFile(filename.c_str());
string sline;
while(getline(configFile, sline))
{
Data line(sline);
Data name;
Data value;
ParseBuffer pb(line);
pb.skipWhitespace();
const char * anchor = pb.position();
if(pb.eof() || *anchor == '#') continue; // if line is a comment or blank then skip it
// Look for =
pb.skipToOneOf("= \t");
if(!pb.eof())
{
pb.data(name,anchor);
if(*pb.position()!='=')
{
pb.skipToChar('=');
}
pb.skipChar('=');
pb.skipWhitespace();
anchor = pb.position();
if(!pb.eof())
{
pb.skipToEnd();
pb.data(value, anchor);
}
//cout << "Config file Name='" << name << "' value='" << value << "'" << endl;
processOption(name.lowercase(), value);
}
}
}
bool
ConfigParser::assignOnOffSetting(const Data& value, bool& setting)
{
if(value == "1" || value == "true" || value == "on" || value == "enable")
{
setting = true;
return true;
}
else if(value == "0" || value == "false" || value == "off" || value == "disable")
{
setting = false;
return true;
}
return false;
}
bool
ConfigParser::processOption(const Data& name, const Data& value)
{
bool result = true;
if(name == "a" || name == "ipaddress")
{
mAddress = value;
}
else if(name == "d" || name == "dnsservers")
{
if(!value.empty()) mDnsServers.clear(); // allow command line to override config file, since list is added to
// DNS Servers
ParseBuffer pb(value);
Data dnsServer;
while(!value.empty() && !pb.eof())
{
pb.skipWhitespace();
const char *start = pb.position();
pb.skipToOneOf(ParseBuffer::Whitespace, ";,"); // allow white space
pb.data(dnsServer, start);
if(DnsUtil::isIpV4Address(dnsServer))
{
mDnsServers.push_back(Tuple(dnsServer, 0, UNKNOWN_TRANSPORT).toGenericIPAddress());
}
else
{
cerr << "Tried to add dns server, but invalid format: " << value << endl;
result = false;
}
if(!pb.eof())
{
pb.skipChar();
}
}
}
else if(name == "gi" || name == "sipgatewayidentity")
{
result = assignNameAddr("sip gateway identity", value, mGatewayIdentity);
}
else if(name == "sp" || name == "udptcpport")
{
mSipPort = (unsigned short)value.convertUnsignedLong();
}
else if(name == "tp" || name == "tlsport")
{
mTlsPort = (unsigned short)value.convertUnsignedLong();
}
else if(name == "td" || name == "tlsdomain")
{
mTlsDomain = value;
}
else if(name == "keepalives")
{
assignOnOffSetting(value, mKeepAlives);
}
else if(name == "op" || name == "outboundproxy")
{
result = assignNameAddr("outbound proxy", value, mOutboundProxy);
}
else if(name == "registrationtime")
{
mRegistrationTime = value.convertUnsignedLong();
}
else if(name == "registrationretrytime")
{
mRegistrationRetryTime = value.convertUnsignedLong();
}
else if(name == "l" || name == "loglevel")
{
mLogLevel = value;
}
else if(name == "logfilename")
{
mLogFilename = value;
}
else if(name == "logfilemaxlines")
{
mLogFileMaxLines = value.convertUnsignedLong();
}
else if(name == "gatewayipcport")
{
mGatewayIPCPort = (unsigned short)value.convertUnsignedLong();
}
else if(name == "jabberconnectoripcport")
{
mJabberConnectorIPCPort = (unsigned short)value.convertUnsignedLong();
}
else if(name == "httpport")
{
mHttpPort = (unsigned short)value.convertUnsignedLong();
}
else if(name == "httpauth")
{
assignOnOffSetting(value, mHttpAuth);
}
else if(name == "httpauthpwd")
{
mHttpAuthPwd = value;
}
else if(name == "ichatproceedingtimeout")
{
mIChatProceedingTimeout = value.convertUnsignedLong();
}
else if(name == "alwaysrelayichatmedia")
{
assignOnOffSetting(value, mAlwaysRelayIChatMedia);
}
else if(name == "preferipv6")
{
assignOnOffSetting(value, mPreferIPv6);
}
else if(name == "skipfirstichataddress")
{
assignOnOffSetting(value, mSkipFirstIChatAddress);
}
else if(name == "codecidfilterlist")
{
ParseBuffer pb(value);
Data codecId;
while(!value.empty() && !pb.eof())
{
pb.skipWhitespace();
const char *start = pb.position();
pb.skipToOneOf(ParseBuffer::Whitespace, ";,"); // allow white space
pb.data(codecId, start);
mCodecIdFilterList.insert((unsigned short)codecId.convertUnsignedLong());
if(!pb.eof())
{
pb.skipChar();
}
}
}
else if(name == "mediarelayportrangemin")
{
mMediaRelayPortRangeMin = (unsigned short)value.convertUnsignedLong();
}
else if(name == "mediarelayportrangemax")
{
mMediaRelayPortRangeMax = (unsigned short)value.convertUnsignedLong();
}
else if(name == "translationpattern")
{
mAddressTranslations.push_back(std::make_pair(value, Data::Empty));
}
else if(name == "translationoutput")
{
if(!mAddressTranslations.empty())
{
mAddressTranslations.back().second = value;
}
}
else if(name == "jabberserver")
{
mJabberServer = value;
}
else if(name == "jabbercomponentname")
{
mJabberComponentName = value;
}
else if(name == "jabbercomponentpassword")
{
mJabberComponentPassword = value;
}
else if(name == "jabbercomponentport")
{
mJabberComponentPort = (unsigned short)value.convertUnsignedLong();
}
else if(name == "jabberserverpingduration")
{
mJabberServerPingDuration = value.convertUnsignedLong();
}
else if(name == "jabbercontrolusername")
{
mJabberControlUsername = value;
}
else if(name == "tlsdhparamsfilename")
{
mTLSDHParamsFilename = value;
}
else if(name == "tlscertificate")
{
mTLSCertificate = value;
}
else if(name == "tlsprivateKey")
{
mTLSPrivateKey = value;
}
else if(name == "tlsprivatekeypassphrase")
{
mTLSPrivateKeyPassPhrase = value;
}
else if(name == "ichatjabberconnectorpath")
{
mIchatJabberConnectorPath = value;
}
else
{
result = false;
}
return result;
}
bool
ConfigParser::assignNameAddr(const Data& settingName, const Data& settingValue, NameAddr& nameAddr)
{
try
{
if(!settingValue.empty())
{
NameAddr tempNameAddr(settingValue);
nameAddr = tempNameAddr;
}
}
catch(resip::BaseException& e)
{
// Try adding sip: to address to see if it will be valid
try
{
NameAddr tempNameAddr(Data("sip:" + settingValue));
nameAddr = tempNameAddr;
}
catch(resip::BaseException&)
{
cerr << "Invalid " << settingName << " NameAddr format=" << settingValue << ": " << e << endl;
return false;
}
}
return true;
}
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,111 @@
#if !defined(ConfigParser_hxx)
#define ConfigParser_hxx
#include <list>
#include <resip/dum/MasterProfile.hxx>
#include <rutil/dns/DnsStub.hxx>
#include <rutil/Log.hxx>
#include <rutil/SharedPtr.hxx>
namespace gateway
{
class ConfigParser
{
public:
ConfigParser(int argc, char** argv);
virtual ~ConfigParser();
resip::Data mAddress;
resip::DnsStub::NameserverList mDnsServers;
resip::NameAddr mGatewayIdentity;
unsigned short mSipPort;
unsigned short mTlsPort;
resip::Data mTlsDomain;
resip::NameAddr mOutboundProxy;
unsigned int mRegistrationTime;
unsigned int mRegistrationRetryTime;
bool mKeepAlives;
resip::Data mLogLevel;
resip::Data mLogFilename;
unsigned int mLogFileMaxLines;
unsigned short mGatewayIPCPort;
unsigned short mJabberConnectorIPCPort;
unsigned short mHttpPort;
bool mHttpAuth;
resip::Data mHttpAuthPwd;
unsigned int mIChatProceedingTimeout;
bool mAlwaysRelayIChatMedia;
bool mPreferIPv6;
bool mSkipFirstIChatAddress; // (for testing): skipping the first IPV4 NAT mapped address (on systems with one interface) causes the local address to be used
typedef std::set<unsigned short> CodecIdList;
CodecIdList mCodecIdFilterList;
unsigned short mMediaRelayPortRangeMin;
unsigned short mMediaRelayPortRangeMax;
typedef std::list<std::pair<resip::Data,resip::Data> > TranslationList;
TranslationList mAddressTranslations;
// Jabber specific settings
resip::Data mJabberServer;
resip::Data mJabberComponentName;
resip::Data mJabberComponentPassword;
unsigned short mJabberComponentPort;
unsigned int mJabberServerPingDuration;
resip::Data mJabberControlUsername;
// TLS specific settings
resip::Data mTLSDHParamsFilename;
resip::Data mTLSCertificate;
resip::Data mTLSPrivateKey;
resip::Data mTLSPrivateKeyPassPhrase;
// iChat Jabber Connector file path
resip::Data mIchatJabberConnectorPath;
private:
void parseCommandLine(int argc, char** argv);
void parseConfigFile(const resip::Data& filename);
bool processOption(const resip::Data& name, const resip::Data& value);
bool assignNameAddr(const resip::Data& settingName, const resip::Data& settingValue, resip::NameAddr& nameAddr);
bool assignOnOffSetting(const resip::Data& value, bool& setting);
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,182 @@
#if !defined(IChatGatewayCmds_hxx)
#define IChatGatewayCmds_hxx
#include <resip/dum/DumCommand.hxx>
#include "Server.hxx"
#include "B2BSession.hxx"
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
namespace gateway
{
/**
The classes defined here are used to pass commands from the
application thread to the DUM thread (process loop).
This ensures thread safety of the external Server methods.
Author: Scott Godin (sgodin AT SipSpectrum DOT com)
*/
class NotifyIChatCallRequestCmd : public resip::DumCommand
{
public:
NotifyIChatCallRequestCmd(Server& server, const std::string& to, const std::string& from)
: mServer(server), mTo(to), mFrom(from) {}
virtual void executeCommand()
{
mServer.notifyIChatCallRequestImpl(mTo, mFrom);
}
resip::Message* clone() const { resip_assert(0); return 0; }
EncodeStream& encode(EncodeStream& strm) const { strm << " NotifyIChatCallRequestCmd: "; return strm; }
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
private:
Server& mServer;
std::string mTo;
std::string mFrom;
};
class NotifyIChatCallCancelledCmd : public resip::DumCommand
{
public:
NotifyIChatCallCancelledCmd(Server& server, const B2BSessionHandle& handle)
: mServer(server), mHandle(handle) {}
virtual void executeCommand()
{
mServer.notifyIChatCallCancelledImpl(mHandle);
}
resip::Message* clone() const { resip_assert(0); return 0; }
EncodeStream& encode(EncodeStream& strm) const { strm << " NotifyIChatCallCancelledCmd: "; return strm; }
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
private:
Server& mServer;
B2BSessionHandle mHandle;
};
class NotifyIChatCallProceedingCmd : public resip::DumCommand
{
public:
NotifyIChatCallProceedingCmd(Server& server, const B2BSessionHandle& handle, const std::string& to)
: mServer(server), mHandle(handle), mTo(to) {}
virtual void executeCommand()
{
mServer.notifyIChatCallProceedingImpl(mHandle, mTo);
}
resip::Message* clone() const { resip_assert(0); return 0; }
EncodeStream& encode(EncodeStream& strm) const { strm << " NotifyIChatCallProceedingCmd: "; return strm; }
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
private:
Server& mServer;
B2BSessionHandle mHandle;
std::string mTo;
};
class NotifyIChatCallFailedCmd : public resip::DumCommand
{
public:
NotifyIChatCallFailedCmd(Server& server, const B2BSessionHandle& handle, unsigned int statusCode)
: mServer(server), mHandle(handle), mStatusCode(statusCode) {}
virtual void executeCommand()
{
mServer.notifyIChatCallFailedImpl(mHandle, mStatusCode);
}
resip::Message* clone() const { resip_assert(0); return 0; }
EncodeStream& encode(EncodeStream& strm) const { strm << " NotifyIChatCallFailedCmd: "; return strm; }
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
private:
Server& mServer;
B2BSessionHandle mHandle;
unsigned int mStatusCode;
};
class ContinueIChatCallCmd : public resip::DumCommand
{
public:
ContinueIChatCallCmd(Server& server, const B2BSessionHandle& handle, const std::string& remoteIPPortListBlob)
: mServer(server), mHandle(handle), mRemoteIPPortListBlob(remoteIPPortListBlob) {}
virtual void executeCommand()
{
mServer.continueIChatCallImpl(mHandle, mRemoteIPPortListBlob);
}
resip::Message* clone() const { resip_assert(0); return 0; }
EncodeStream& encode(EncodeStream& strm) const { strm << " ContinueIChatCallCmd: "; return strm; }
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
private:
Server& mServer;
B2BSessionHandle mHandle;
std::string mRemoteIPPortListBlob;
};
class SipRegisterJabberUserCmd : public resip::DumCommand
{
public:
SipRegisterJabberUserCmd(Server& server, const std::string& jidToRegister)
: mServer(server), mJidToRegister(jidToRegister) {}
virtual void executeCommand()
{
mServer.sipRegisterJabberUserImpl(mJidToRegister);
}
resip::Message* clone() const { resip_assert(0); return 0; }
EncodeStream& encode(EncodeStream& strm) const { strm << " SipRegisterJabberUserCmd: "; return strm; }
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
private:
Server& mServer;
std::string mJidToRegister;
};
class SipUnregisterJabberUserCmd : public resip::DumCommand
{
public:
SipUnregisterJabberUserCmd(Server& server, const std::string& jidToUnregister)
: mServer(server), mJidToUnregister(jidToUnregister) {}
virtual void executeCommand()
{
mServer.sipUnregisterJabberUserImpl(mJidToUnregister);
}
resip::Message* clone() const { resip_assert(0); return 0; }
EncodeStream& encode(EncodeStream& strm) const { strm << " SipUnregisterJabberUserCmd: "; return strm; }
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
private:
Server& mServer;
std::string mJidToUnregister;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,169 @@
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <rutil/Logger.hxx>
#include <resip/stack/Helper.hxx>
#include "AppSubsystem.hxx"
#include "IChatIPPortData.hxx"
#include <rutil/WinLeakCheck.hxx>
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
using namespace gateway;
using namespace resip;
using namespace std;
namespace gateway
{
typedef struct
{
unsigned short initialPad;
unsigned short family;
char interfaceName[16];
char ipAddress[16];
unsigned short port;
unsigned short finalPad;
} IPPortDataBlob;
IChatIPPortData::IChatIPPortData()
{
}
IChatIPPortData::IChatIPPortData(const std::string& hexblob) : mHexBlob(hexblob)
{
unsigned int pad = 0;
// Note: gloox passes us an initial line feed, so be tollerant of this
if(hexblob.at(0) == 0xa)
{
pad = 1;
}
// Convert hexblob to binary blob
if(((hexblob.size()-pad) % 40) != 0)
{
ErrLog(<< "Data size provided for IChatIPPortData is not correct, size=" << hexblob.size());
return;
}
Data blob((unsigned int)hexblob.size()-1 / 2, Data::Preallocate);
for(unsigned int i = pad; i < hexblob.size(); i=i+8)
{
unsigned int block = ntohl(Helper::hex2integer(&hexblob.at(i)));
blob.append((const char*)&block, 4);
}
for(unsigned int j = 0; j < blob.size(); j=j+40)
{
IPPortDataBlob* ipPortDataBlob = (IPPortDataBlob*)(blob.data()+j);
if(ipPortDataBlob->family == V4)
{
in_addr addr;
memcpy(&addr, ipPortDataBlob->ipAddress, 4);
addIPPortData(Data(ipPortDataBlob->interfaceName), Tuple(addr,ntohs(ipPortDataBlob->port),UDP));
}
else
{
#ifdef USE_IPV6
in6_addr addr;
memcpy(&addr, ipPortDataBlob->ipAddress, 16);
addIPPortData(Data(ipPortDataBlob->interfaceName), Tuple(addr,ntohs(ipPortDataBlob->port),UDP));
#else
ErrLog(<< "IPv6 support not enabled at compile time.");
resip_assert(0);
#endif
}
InfoLog(<< "IChatIPPortData: name=" << mIPPortDataList.back().first << " addr=" << mIPPortDataList.back().second);
}
}
void
IChatIPPortData::addIPPortData(const Data& name, const Tuple& ipPortData)
{
mIPPortDataList.push_back(std::make_pair(name, ipPortData));
mHexBlob.clear(); // clear any existing blob string - it will now need to be re-generated if requested
}
std::string&
IChatIPPortData::hexBlob()
{
if(mHexBlob.empty())
{
Data dataBlob((int)mIPPortDataList.size() * sizeof(IPPortDataBlob), Data::Preallocate);
IPPortDataList::const_iterator it;
for(it = mIPPortDataList.begin(); it != mIPPortDataList.end(); it++)
{
IPPortDataBlob ipPortDataBlob;
memset(&ipPortDataBlob, 0, sizeof(ipPortDataBlob));
memcpy(ipPortDataBlob.interfaceName, it->first.data(), it->first.size() < 16 ? it->first.size() : 16);
ipPortDataBlob.port = htons(it->second.getPort());
if(it->second.ipVersion() == V4)
{
ipPortDataBlob.family = V4;
memcpy(ipPortDataBlob.ipAddress, &reinterpret_cast<const sockaddr_in&>(it->second.getSockaddr()).sin_addr, 4);
}
else
{
ipPortDataBlob.family = V6;
memcpy(ipPortDataBlob.ipAddress, &reinterpret_cast<const sockaddr_in6&>(it->second.getSockaddr()).sin6_addr, 16);
}
dataBlob.append((const char*)&ipPortDataBlob, sizeof(ipPortDataBlob));
}
// Hexify
for(unsigned int i = 0; i < dataBlob.size(); i=i+4)
{
unsigned int block;
memcpy(&block, dataBlob.data()+i, 4);
char hexBlock[8];
Helper::integer2hex(hexBlock, htonl(block));
mHexBlob.append(hexBlock, 8);
}
}
return mHexBlob;
}
const IChatIPPortData::IPPortDataList&
IChatIPPortData::getIPPortDataList() const
{
return mIPPortDataList;
}
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,66 @@
#if !defined(IChatIPPortData_hxx)
#define IChatIPPortData_hxx
#include <list>
#include <string>
#include "rutil/Data.hxx"
#include "resip/stack/Tuple.hxx"
namespace gateway
{
class IChatIPPortData
{
public:
typedef std::list<std::pair<resip::Data,resip::Tuple> > IPPortDataList;
IChatIPPortData();
IChatIPPortData(const std::string& hexblob);
void addIPPortData(const resip::Data& name, const resip::Tuple& ipPortData);
std::string& hexBlob();
const IPPortDataList& getIPPortDataList() const;
private:
IPPortDataList mIPPortDataList;
std::string mHexBlob;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,281 @@
#include "rutil/ResipAssert.h"
#include <iostream>
#include <sstream>
#include <string.h>
#ifdef WIN32
#include <WS2tcpip.h>
#else
#include <sys/fcntl.h>
#include <unistd.h>
#endif
#include "IPCThread.hxx"
using namespace gateway;
using namespace std;
#ifdef WIN32
#define EADDRINUSE WSAEADDRINUSE
#define EWOULDBLOCK WSAEWOULDBLOCK
#define sleepMs(t) Sleep(t)
#else
#define sleepMs(t) usleep(t*1000)
#endif
IPCThread::IPCThread(unsigned short localPort, unsigned short remotePort, IPCHandler* handler, IPCMutex* mutex) :
mLocalPort(localPort),
mRemotePort(remotePort),
mHandler(handler),
mMutex(mutex)
{
resip_assert(handler!=0);
mSocket = createIPCSocket("127.0.0.1",mLocalPort);
if(mSocket == INVALID_SOCKET)
{
cerr << "IPCThread::IPCThread - could not create IPC udp socket on port=" << mLocalPort << endl;
}
else
{
// Set RemoteSockaddr to be same as local but with remote port
memcpy(&mRemoteSockaddr, &mLocalSockaddr, sizeof(mRemoteSockaddr));
sockaddr_in* anonv4 = (sockaddr_in*)&mRemoteSockaddr;
anonv4->sin_port = htons(remotePort);
cout << "IPCThread::IPCThread: local port=" << mLocalPort << ", remote port=" << remotePort << endl;
}
}
IPCThread::~IPCThread()
{
#if defined(WIN32)
closesocket(mSocket);
#else
close(mSocket);
#endif
}
void
IPCThread::sendIPCMsg(IPCMsg& msg)
{
std::ostringstream oss;
msg.encode(oss);
mMutex->lock();
mDataToSend.push(oss.str());
mMutex->unlock();
}
Socket
IPCThread::createIPCSocket(const std::string& printableAddr, unsigned int port)
{
Socket fd;
sockaddr_in* anonv4 = (sockaddr_in*)&mLocalSockaddr;
fd = ::socket(PF_INET, SOCK_DGRAM, 0);
if ( fd == INVALID_SOCKET )
{
int e = getErrno();
cerr << "IPCThread::createIPCSocket - Failed to create socket: error=" << e << endl;
return INVALID_SOCKET;
}
memset(anonv4, 0, sizeof(anonv4));
anonv4->sin_family = AF_INET;
anonv4->sin_port = htons(port);
if (printableAddr.empty())
{
anonv4->sin_addr.s_addr = htonl(INADDR_ANY);
}
else
{
anonv4->sin_addr.s_addr = inet_addr(printableAddr.c_str());
}
//cout << "IPCThread::createIPCSocket - Creating fd=" << (int)fd
// << ", Binding to " << printableAddr << ":" << port << endl;
if ( ::bind( fd, &mLocalSockaddr, sizeof(mLocalSockaddr)) == SOCKET_ERROR )
{
int e = getErrno();
if ( e == EADDRINUSE )
{
cerr << "IPCThread::createIPCSocket - " << printableAddr << ":" << port << " already in use" << endl;
}
else
{
cerr << "IPCThread::createIPCSocket - Could not bind to " << printableAddr << ":" << port << ", error=" << e << endl;
}
return INVALID_SOCKET;
}
if(port == 0)
{
// If we used port 0, then query what port the OS allocated for us
socklen_t len = sizeof(mLocalSockaddr);
if(::getsockname(fd, &mLocalSockaddr, &len) == SOCKET_ERROR)
{
int e = getErrno();
cerr <<"IPCThread::createIPCSocket - getsockname failed, error=" << e << endl;
return INVALID_SOCKET;
}
}
#if defined(WIN32)
unsigned long noBlock = 1;
int errNoBlock = ioctlsocket( fd, FIONBIO , &noBlock );
if ( errNoBlock != 0 )
{
cerr << "IPCThread::createIPCSocket - Could not make socket non-blocking" << endl;
return INVALID_SOCKET;
}
#else
int flags = fcntl( fd, F_GETFL, 0);
int errNoBlock = fcntl(fd, F_SETFL, flags | O_NONBLOCK );
if ( errNoBlock != 0 )
{
cerr << "IPCThread::createIPCSocket - Could not make socket non-blocking" << endl;
return INVALID_SOCKET;
}
#endif
return fd;
}
void
IPCThread::thread()
{
fd_set read;
fd_set write;
fd_set except;
struct timeval tv;
if(mSocket == INVALID_SOCKET) return;
while (!isShutdown())
{
tv.tv_sec = 1; // Note: calling select on linux based systems can cause the contents of the passed in timeval struct to be modified, so we need to reset the time on each loop iteration
tv.tv_usec = 0;
FD_ZERO(&read);
FD_ZERO(&write);
FD_ZERO(&except);
FD_SET(mSocket, &read);
FD_SET(mSocket, &except);
if(!mDataToSend.empty())
{
FD_SET(mSocket, &write);
}
int ret = ::select(mSocket+1, &read, &write, &except, &tv);
if (ret > 0)
{
process(read, write);
}
}
cout << "IPCThread::thread - IPCThread shutdown." << endl;
}
void
IPCThread::process(fd_set& read_fdset, fd_set& write_fdset)
{
// If data to send and write has signalled
if(!mDataToSend.empty() && (FD_ISSET(mSocket, &write_fdset) != 0))
{
int count;
mMutex->lock();
std::string& dataToSend = mDataToSend.front();
count = sendto(mSocket,
dataToSend.data(),
dataToSend.size(),
0, // flags
&mRemoteSockaddr, sizeof(mRemoteSockaddr));
mDataToSend.pop();
mMutex->unlock();
if ( count == SOCKET_ERROR )
{
int e = getErrno();
cerr << "IPCThread::process - Failed (" << e << ") sending." << endl;
}
}
if((FD_ISSET(mSocket, &read_fdset) != 0))
{
sockaddr readAddr;
bool success = true;
socklen_t slen = sizeof(readAddr);
int len = recvfrom(mSocket,
mReadBuffer,
UDP_IPC_BUFFER_SIZE,
0 /*flags */,
&readAddr,
&slen);
if ( len == SOCKET_ERROR )
{
int err = getErrno();
if ( err != EWOULDBLOCK )
{
cerr << "IPCThread::process - Error calling recvfrom: " << err << endl;
success = false;
}
}
if (len == 0 || len == SOCKET_ERROR)
{
cerr << "IPCThread::process - No data calling recvfrom: len=" << len << endl;
success = false;
}
if (len+1 >= UDP_IPC_BUFFER_SIZE)
{
cerr << "IPCThread::process - Datagram exceeded max length "<<UDP_IPC_BUFFER_SIZE << endl;
success = false;
}
if(success)
{
//cout << "IPCThread::process - Received a datagram of size=" << len << endl;
IPCMsg msg(std::string(mReadBuffer, len));
mHandler->onNewIPCMsg(msg);
}
}
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,156 @@
#if !defined(IPCThread_hxx)
#define IPCThread_hxx
#include <queue>
#include <vector>
#include <string>
#include <sstream>
#include <errno.h>
#ifndef WIN32
# include <sys/socket.h>
# include <sys/select.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <stdlib.h>
#endif
#include "Thread.hxx"
#define UDP_IPC_BUFFER_SIZE 4192
namespace gateway
{
#ifndef WIN32
typedef int Socket;
#define INVALID_SOCKET (-1)
#define SOCKET_ERROR (-1)
inline int getErrno() { return errno; }
#else
typedef SOCKET Socket;
inline int getErrno() { return WSAGetLastError(); }
#endif
class IPCMutex
{
public:
IPCMutex() {}
virtual ~IPCMutex() {}
virtual void lock() = 0;
virtual void unlock() = 0;
};
class IPCMsg
{
public:
IPCMsg() {};
IPCMsg(const std::string& msg)
{
unsigned int start = 0;
for(unsigned int i = 0; i < msg.size(); i++)
{
if(msg.at(i) == '\r')
{
mArgs.push_back(msg.substr(start,i-start));
start = i+1;
}
}
}
void addArg(const std::string& arg) { mArgs.push_back(arg); }
void addArg(unsigned int arg)
{
std::ostringstream oss;
oss << arg;
mArgs.push_back(oss.str());
}
std::ostream& encode(std::ostream& strm) const
{
std::vector<std::string>::const_iterator it = mArgs.begin();
for(;it != mArgs.end();it++)
{
strm << *it << "\r"; // Note: using /r since there is a /n character at the start of the iChat call blob
}
strm.flush();
return strm;
}
const std::vector<std::string>& getArgs() const { return mArgs; }
private:
std::vector<std::string> mArgs;
};
class IPCHandler
{
public:
virtual ~IPCHandler() {}
virtual void onNewIPCMsg(const IPCMsg& msg) = 0;
};
class IPCThread : public Thread
{
public:
IPCThread(unsigned short localPort, unsigned short remotePort, IPCHandler* handler, IPCMutex* mutex);
virtual ~IPCThread();
void sendIPCMsg(IPCMsg& msg);
protected:
private:
virtual void thread();
void process(fd_set& read_fdset, fd_set& write_fdset);
Socket createIPCSocket(const std::string& printableAddr, unsigned int port);
char mReadBuffer[UDP_IPC_BUFFER_SIZE+1];
sockaddr mLocalSockaddr;
sockaddr mRemoteSockaddr;
Socket mSocket;
unsigned short mLocalPort;
unsigned short mRemotePort;
//resip::Mutex mIPCMutex;
std::queue<std::string> mDataToSend;
IPCHandler* mHandler;
IPCMutex* mMutex;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,99 @@
# $Id$
EXTRA_DIST = ichat-gw.config
EXTRA_DIST += doc
EXTRA_DIST += *.sln
EXTRA_DIST += *.vcproj
SUBDIRS = .
# this has more external dependencies, it has been adapted
# for autotools and can be enabled manually if the deps
# are available
SUBDIRS += jabberconnector
#AM_CXXFLAGS = -DUSE_ARES
sbin_PROGRAMS = ichat-gw
ichat_gw_LDADD = ../../resip/dum/libdum.la
ichat_gw_LDADD += ../../resip/stack/libresip.la ../../rutil/librutil.la
ichat_gw_LDADD += @LIBSSL_LIBADD@ -lpcre @LIBPTHREAD_LIBADD@
ichat_gw_SOURCES = \
AddressTranslator.cxx \
AppSubsystem.cxx \
B2BSession.cxx \
ConfigParser.cxx \
ichat-gw.cxx \
IChatIPPortData.cxx \
IPCThread.cxx \
MediaRelay.cxx \
MediaRelayPort.cxx \
Server.cxx \
SipRegistration.cxx \
Thread.cxx
ichat_gwincludedir = $(includedir)/ichat-gw
nobase_ichat_gwinclude_HEADERS = AddressTranslator.hxx \
AppSubsystem.hxx \
B2BSession.hxx \
ConfigParser.hxx \
IChatGatewayCmds.hxx \
IChatIPPortData.hxx \
IPCThread.hxx \
MediaRelay.hxx \
MediaRelayPort.hxx \
Server.hxx \
SipRegistration.hxx \
Thread.hxx \
Version.hxx
##############################################################################
#
# The Vovida Software License, Version 1.0
# Copyright (c) 2000-2007 Vovida Networks, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. 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.
#
# 3. The names "VOCAL", "Vovida Open Communication Application Library",
# and "Vovida Open Communication Application Library (VOCAL)" must
# not be used to endorse or promote products derived from this
# software without prior written permission. For written
# permission, please contact vocal@vovida.org.
#
# 4. Products derived from this software may not be called "VOCAL", nor
# may "VOCAL" appear in their name, without prior written
# permission of Vovida Networks, Inc.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
# NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
# IN EXCESS OF $1,000, NOR FOR ANY 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.
#
# ====================================================================
#
# This software consists of voluntary contributions made by Vovida
# Networks, Inc. and many individuals on behalf of Vovida Networks,
# Inc. For more information on Vovida Networks, Inc., please see
# <http://www.vovida.org/>.
#
##############################################################################

View File

@@ -0,0 +1,651 @@
#include "rutil/ResipAssert.h"
#include <rutil/Data.hxx>
#include <rutil/Socket.hxx>
#include <rutil/Timer.hxx>
#include <resip/stack/Symbols.hxx>
#include <rutil/TransportType.hxx>
#include <rutil/Logger.hxx>
#include <resip/stack/Tuple.hxx>
#include <rutil/Random.hxx>
#include <rutil/DnsUtil.hxx>
#include <rutil/ParseBuffer.hxx>
#include <resip/stack/Transport.hxx>
#include "AppSubsystem.hxx"
#include "MediaRelay.hxx"
#include <rutil/WinLeakCheck.hxx>
using namespace gateway;
using namespace resip;
using namespace std;
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
#ifdef WIN32
#define sleepMs(t) Sleep(t)
#else
#define sleepMs(t) usleep(t*1000)
#endif
typedef struct
{
unsigned short versionExtPayloadTypeAndMarker;
unsigned short sequenceNumber;
unsigned int timestamp;
unsigned int ssrc;
} RtpHeader;
MediaRelay::MediaRelay(bool isV6Avail, unsigned short portRangeMin, unsigned short portRangeMax) :
mIsV6Avail(isV6Avail)
{
if(portRangeMax < portRangeMin) portRangeMax = portRangeMin; // saftey check
for(unsigned int i = portRangeMin; i <= portRangeMax; i++)
{
mFreeRelayPortList.push_back(i);
}
}
MediaRelay::~MediaRelay()
{
Lock lock(mRelaysMutex);
RelayPortList::iterator it = mRelays.begin();
for(;it != mRelays.end(); it++)
{
delete it->second;
}
}
#define NUM_CREATE_TRIES 10 // Number of times to try to allocate a port, since port may be in use by another application
bool
MediaRelay::createRelay(unsigned short& port)
{
for(unsigned int i = 0; i < NUM_CREATE_TRIES; i++)
{
if(createRelayImpl(port)) return true;
}
return false;
}
bool
MediaRelay::createRelayImpl(unsigned short& port)
{
Lock lock(mRelaysMutex);
if(mFreeRelayPortList.empty()) return false;
unsigned short trialPort = mFreeRelayPortList.front();
mFreeRelayPortList.pop_front();
Tuple v4tuple(Data::Empty,trialPort,V4,UDP,Data::Empty);
resip::Socket v4fd = createRelaySocket(v4tuple);
if(v4fd == INVALID_SOCKET)
{
mFreeRelayPortList.push_back(trialPort);
return false;
}
if(mIsV6Avail)
{
Tuple v6tuple(Data::Empty,trialPort,V6,UDP,Data::Empty);
resip::Socket v6fd = createRelaySocket(v6tuple);
if(v6fd != INVALID_SOCKET)
{
port = trialPort;
mRelays[port] = new MediaRelayPort(v4fd, v4tuple, v6fd, v6tuple);
InfoLog(<< "MediaRelay::createRelayImpl - Media relay started for port " << port);
return true;
}
#if defined(WIN32)
closesocket(v4fd);
#else
close(v4fd);
#endif
mFreeRelayPortList.push_back(trialPort);
return false;
}
else
{
// Only V4 is available
port = trialPort;
mRelays[port] = new MediaRelayPort(v4fd, v4tuple);
InfoLog(<< "MediaRelay::createRelayImpl - Media relay started for port " << port);
return true;
}
}
void
MediaRelay::destroyRelay(unsigned short port)
{
Lock lock(mRelaysMutex);
RelayPortList::iterator it = mRelays.find(port);
if(it != mRelays.end())
{
InfoLog(<< "MediaRelay::destroyRelay - port=" << port);
delete it->second;
mRelays.erase(it);
mFreeRelayPortList.push_back(port);
}
}
void
MediaRelay::primeNextEndpoint(unsigned short& port, resip::Tuple& destinationIPPort)
{
Lock lock(mRelaysMutex);
RelayPortList::iterator it = mRelays.find(port);
if(it != mRelays.end())
{
if(it->second->mFirstEndpoint.mTuple.getPort() == 0)
{
InfoLog(<< "MediaRelay::primeNextEndpoint - sender=first, port=" << port << ", addr=" << destinationIPPort);
it->second->mFirstEndpoint.mTuple = destinationIPPort;
}
else
{
InfoLog(<< "MediaRelay::primeNextEndpoint - sender=second, port=" << port << ", addr=" << destinationIPPort);
it->second->mSecondEndpoint.mTuple = destinationIPPort;
}
}
}
resip::Socket
MediaRelay::createRelaySocket(resip::Tuple& tuple)
{
resip::Socket fd;
#ifdef USE_IPV6
fd = ::socket(tuple.ipVersion() == V4 ? PF_INET : PF_INET6, SOCK_DGRAM, 0);
#else
fd = ::socket(PF_INET, SOCK_DGRAM, 0);
#endif
if ( fd == INVALID_SOCKET )
{
int e = getErrno();
ErrLog (<< "MediaRelay::createRelaySocket - Failed to create socket: " << strerror(e));
return INVALID_SOCKET;
}
DebugLog (<< "MediaRelay::createRelaySocket - Creating fd=" << (int)fd
<< (tuple.ipVersion() == V4 ? " V4" : " V6")
<< ", Binding to " << Tuple::inet_ntop(tuple));
if ( ::bind( fd, &tuple.getSockaddr(), tuple.length()) == SOCKET_ERROR )
{
int e = getErrno();
if ( e == EADDRINUSE )
{
ErrLog (<< "MediaRelay::createRelaySocket - " << tuple << " already in use ");
}
else
{
ErrLog (<< "MediaRelay::createRelaySocket - Could not bind to " << tuple << ", error=" << e);
}
return INVALID_SOCKET;
}
if(tuple.getPort() == 0)
{
// If we used port 0, then query what port the OS allocated for us
socklen_t len = tuple.length();
if(::getsockname(fd, &tuple.getMutableSockaddr(), &len) == SOCKET_ERROR)
{
int e = getErrno();
ErrLog (<<"MediaRelay::createRelaySocket - getsockname failed, error=" << e);
return INVALID_SOCKET;
}
}
bool ok = makeSocketNonBlocking(fd);
if ( !ok )
{
ErrLog (<< "MediaRelay::createRelaySocket - Could not make socket non-blocking");
return INVALID_SOCKET;
}
return fd;
}
void
MediaRelay::thread()
{
while (!isShutdown())
{
try
{
if(mRelays.size() == 0)
{
// No relays yet - just wait
sleepMs(50);
}
else
{
resip::FdSet fdset;
buildFdSet(fdset);
int ret = fdset.selectMilliSeconds(50);
if (ret > 0)
{
process(fdset);
}
}
}
catch (BaseException& e)
{
ErrLog (<< "MediaRelay::thread - Unhandled exception: " << e);
}
}
WarningLog (<< "MediaRelay::thread - shutdown");
}
void
MediaRelay::buildFdSet(FdSet& fdset)
{
Lock lock(mRelaysMutex);
RelayPortList::iterator it = mRelays.begin();
for(;it != mRelays.end(); it++)
{
// Add read fd's
fdset.setRead(it->second->mV4Fd);
if(mIsV6Avail) fdset.setRead(it->second->mV6Fd);
fdset.setExcept(it->second->mV4Fd);
if(mIsV6Avail) fdset.setExcept(it->second->mV6Fd);
checkKeepalives(it->second);
// Add write fd's if there is data to write
if((it->second->mFirstEndpoint.mRelayDatagram.get() != 0 && it->second->mFirstEndpoint.mTuple.ipVersion() == V4) ||
(it->second->mSecondEndpoint.mRelayDatagram.get() != 0 && it->second->mSecondEndpoint.mTuple.ipVersion() == V4))
{
fdset.setWrite(it->second->mV4Fd);
}
if(mIsV6Avail &&
((it->second->mFirstEndpoint.mRelayDatagram.get() != 0 && it->second->mFirstEndpoint.mTuple.ipVersion() == V6) ||
(it->second->mSecondEndpoint.mRelayDatagram.get() != 0 && it->second->mSecondEndpoint.mTuple.ipVersion() == V6)))
{
fdset.setWrite(it->second->mV6Fd);
}
}
}
#define KEEPALIVETIMEOUTMS 1000
#define KEEPALIVEMS 20
#define STALEENDPOINTTIMEOUTMS 2000
void
MediaRelay::checkKeepalives(MediaRelayPort* relayPort)
{
UInt64 now = Timer::getTimeMs();
// See if First Endpoint is stale (ie. hasn't received data in STALEENDPOINTTIMEOUTMS ms)
if(relayPort->mFirstEndpoint.mTuple.getPort() != 0 &&
(now - relayPort->mFirstEndpoint.mRecvTimeMs) > STALEENDPOINTTIMEOUTMS)
{
relayPort->mFirstEndpoint.reset();
InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", haven't recevied data from first endpoint in " << STALEENDPOINTTIMEOUTMS << "ms - reseting endpoint.");
}
// See if Second Endpoint is stale (ie. hasn't received data in STALEENDPOINTTIMEOUTMS ms)
if(relayPort->mSecondEndpoint.mTuple.getPort() != 0 &&
(now - relayPort->mSecondEndpoint.mRecvTimeMs) > STALEENDPOINTTIMEOUTMS)
{
relayPort->mSecondEndpoint.reset();
InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", haven't recevied data from second endpoint in " << STALEENDPOINTTIMEOUTMS << "ms - reseting endpoint.");
}
//if(relayPort->mFirstEndpoint.mTuple.getPort() != 0)
//{
//InfoLog(<< "MediaRelay::checkKeepalives - port=" << relayPort->mFirstEndpoint.mTuple.getPort() << ", dataToSend=" <<
// (relayPort->mFirstEndpoint.mRelayDatagram.get() == 0 ? "no" : "yes") << ", time since last send=" <<
// (now - relayPort->mFirstEndpoint.mSendTimeMs));
//}
// See if keepalive needs to be sent to First Endpoint
if(relayPort->mFirstEndpoint.mTuple.getPort() != 0 &&
relayPort->mFirstEndpoint.mRelayDatagram.get() == 0 &&
((!relayPort->mFirstEndpoint.mKeepaliveMode && (now - relayPort->mFirstEndpoint.mSendTimeMs) > KEEPALIVETIMEOUTMS) ||
(relayPort->mFirstEndpoint.mKeepaliveMode && (now - relayPort->mFirstEndpoint.mSendTimeMs) > KEEPALIVEMS)))
{
RtpHeader keepalive; // Create an empty G711 packet to keep iChat happy
keepalive.versionExtPayloadTypeAndMarker = htons(0x8000);
keepalive.sequenceNumber = 0;
keepalive.timestamp = 0;
keepalive.ssrc = relayPort->mFirstEndpoint.mSsrc;
if(!relayPort->mFirstEndpoint.mKeepaliveMode)
{
InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", dispatching initial RTP keepalive to first sender!");
relayPort->mFirstEndpoint.mKeepaliveMode = true;
}
//else
//{
// InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", dispatching subsequent RTP keepalive to first sender!");
//}
// Add message to buffer
std::auto_ptr<char> buffer(new char[sizeof(RtpHeader)]);
memcpy(buffer.get(), &keepalive, sizeof(RtpHeader));
relayPort->mFirstEndpoint.mRelayDatagram = buffer;
relayPort->mFirstEndpoint.mRelayDatagramLen = sizeof(RtpHeader);
}
// See if keepalive needs to be sent to Second Endpoint
if(relayPort->mSecondEndpoint.mTuple.getPort() != 0 &&
relayPort->mSecondEndpoint.mRelayDatagram.get() == 0 &&
((!relayPort->mSecondEndpoint.mKeepaliveMode && (now - relayPort->mSecondEndpoint.mSendTimeMs) > KEEPALIVETIMEOUTMS) ||
(relayPort->mSecondEndpoint.mKeepaliveMode && (now - relayPort->mSecondEndpoint.mSendTimeMs) > KEEPALIVEMS)))
{
RtpHeader keepalive; // Create an empty G711 packet to keep iChat happy
keepalive.versionExtPayloadTypeAndMarker = htons(0x8000);
keepalive.sequenceNumber = 0;
keepalive.timestamp = 0;
keepalive.ssrc = relayPort->mSecondEndpoint.mSsrc;
if(!relayPort->mSecondEndpoint.mKeepaliveMode)
{
InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", dispatching initial RTP keepalive to second sender!");
relayPort->mSecondEndpoint.mKeepaliveMode = true;
}
//else
//{
// InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", dispatching subsequent RTP keepalive to second sender!");
//}
// Add message to buffer
std::auto_ptr<char> buffer(new char[sizeof(RtpHeader)]);
memcpy(buffer.get(), &keepalive, sizeof(RtpHeader));
relayPort->mSecondEndpoint.mRelayDatagram = buffer;
relayPort->mSecondEndpoint.mRelayDatagramLen = sizeof(RtpHeader);
}
}
void
MediaRelay::process(FdSet& fdset)
{
Lock lock(mRelaysMutex);
RelayPortList::iterator it = mRelays.begin();
for(;it != mRelays.end(); it++)
{
if(processWrites(fdset, it->second))
{
// If all writes have been processed, process reads
processReads(fdset, it->second);
}
}
}
bool
MediaRelay::processWrites(FdSet& fdset, MediaRelayPort* relayPort)
{
resip::Socket fd = INVALID_SOCKET;
Tuple tuple;
std::auto_ptr<char> buffer;
int len;
// If we have data to write to first sender then check if readyToWrite
if(relayPort->mFirstEndpoint.mRelayDatagram.get() != 0)
{
if(relayPort->mFirstEndpoint.mTuple.ipVersion() == V4 &&
fdset.readyToWrite(relayPort->mV4Fd))
{
fd = relayPort->mV4Fd;
tuple = relayPort->mFirstEndpoint.mTuple;
buffer = relayPort->mFirstEndpoint.mRelayDatagram;
len = relayPort->mFirstEndpoint.mRelayDatagramLen;
}
else if(mIsV6Avail &&
relayPort->mFirstEndpoint.mTuple.ipVersion() == V6 &&
fdset.readyToWrite(relayPort->mV6Fd))
{
fd = relayPort->mV6Fd;
tuple = relayPort->mFirstEndpoint.mTuple;
buffer = relayPort->mFirstEndpoint.mRelayDatagram;
len = relayPort->mFirstEndpoint.mRelayDatagramLen;
}
}
// If anything to send to first sender then do it
if (fd != INVALID_SOCKET)
{
int count;
count = sendto(fd,
buffer.get(),
len,
0, // flags
&tuple.getMutableSockaddr(), tuple.length());
if ( count == SOCKET_ERROR )
{
int e = getErrno();
InfoLog (<< "MediaRelay::processWrites: port=" << relayPort->mLocalV4Tuple.getPort() << ", Failed (" << e << ") sending to " << tuple);
}
else
{
// InfoLog(<< len << " bytes of data sent to " << tuple);
relayPort->mFirstEndpoint.mSendTimeMs = Timer::getTimeMs();
}
}
// check if we have data to write to second sender then check if readyToWrite
fd = INVALID_SOCKET; // reset
if(relayPort->mSecondEndpoint.mRelayDatagram.get() != 0)
{
if(relayPort->mSecondEndpoint.mTuple.ipVersion() == V4 &&
fdset.readyToWrite(relayPort->mV4Fd))
{
fd = relayPort->mV4Fd;
tuple = relayPort->mSecondEndpoint.mTuple;
buffer = relayPort->mSecondEndpoint.mRelayDatagram;
len = relayPort->mSecondEndpoint.mRelayDatagramLen;
}
else if(mIsV6Avail &&
relayPort->mSecondEndpoint.mTuple.ipVersion() == V6 &&
fdset.readyToWrite(relayPort->mV6Fd))
{
fd = relayPort->mV6Fd;
tuple = relayPort->mSecondEndpoint.mTuple;
buffer = relayPort->mSecondEndpoint.mRelayDatagram;
len = relayPort->mSecondEndpoint.mRelayDatagramLen;
}
}
// If anything to send to sender sender then do it
if (fd != INVALID_SOCKET)
{
int count;
count = sendto(fd,
buffer.get(),
len,
0, // flags
&tuple.getMutableSockaddr(), tuple.length());
if ( count == SOCKET_ERROR )
{
int e = getErrno();
InfoLog (<< "MediaRelay::processWrites: port=" << relayPort->mLocalV4Tuple.getPort() << ", Failed (" << e << ") sending to " << tuple);
}
else
{
//InfoLog(<< len << " bytes of data sent to " << tuple);
relayPort->mSecondEndpoint.mSendTimeMs = Timer::getTimeMs();
}
}
return relayPort->mFirstEndpoint.mRelayDatagram.get() == 0 &&
relayPort->mSecondEndpoint.mRelayDatagram.get() == 0;
}
#define UDP_BUFFER_SIZE 1000
void
MediaRelay::processReads(FdSet& fdset, MediaRelayPort* relayPort)
{
resip::Socket fd = INVALID_SOCKET;
Tuple tuple;
if(fdset.readyToRead(relayPort->mV4Fd))
{
//InfoLog(<<"V4 socket is ready to read.");
fd = relayPort->mV4Fd;
tuple = relayPort->mLocalV4Tuple;
}
else if(mIsV6Avail && fdset.readyToRead(relayPort->mV6Fd))
{
//InfoLog(<<"V6 socket is ready to read.");
fd = relayPort->mV6Fd;
tuple = relayPort->mLocalV6Tuple;
}
if (fd != INVALID_SOCKET)
{
std::auto_ptr<char> buffer(new char[UDP_BUFFER_SIZE+1]);
socklen_t slen = tuple.length();
int len = recvfrom( fd,
buffer.get(),
UDP_BUFFER_SIZE,
0 /*flags */,
&tuple.getMutableSockaddr(),
&slen);
if ( len == SOCKET_ERROR )
{
int err = getErrno();
if ( err != EWOULDBLOCK )
{
ErrLog (<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", Error calling recvfrom: " << err);
}
buffer.reset();
}
if (len == 0)
{
ErrLog (<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", No data calling recvfrom: len=" << len);
buffer.reset();
}
if (len+1 >= UDP_BUFFER_SIZE)
{
InfoLog(<<"MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", Datagram exceeded max length "<<UDP_BUFFER_SIZE);
buffer.reset();
}
if(buffer.get() != 0)
{
UInt64 now = Timer::getTimeMs();
RtpHeader* rtpHeader = (RtpHeader*)buffer.get();
//InfoLog(<< "Received a datagram of size=" << len << " from=" << tuple);
MediaEndpoint* pReceivingEndpoint = 0;
MediaEndpoint* pSendingEndpoint = 0;
// First check if packet is from first endpoint
if(tuple == relayPort->mFirstEndpoint.mTuple)
{
pReceivingEndpoint = &relayPort->mFirstEndpoint;
pSendingEndpoint = &relayPort->mSecondEndpoint;
}
// Next check if packet is from second endpoint
else if(tuple == relayPort->mSecondEndpoint.mTuple)
{
pReceivingEndpoint = &relayPort->mSecondEndpoint;
pSendingEndpoint = &relayPort->mFirstEndpoint;
}
else
{
// See if we can store this new sender in First Endpoint
if(relayPort->mFirstEndpoint.mTuple.getPort() == 0)
{
InfoLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", First packet received from First Endpoint " << tuple);
pReceivingEndpoint = &relayPort->mFirstEndpoint;
pSendingEndpoint = &relayPort->mSecondEndpoint;
}
else if(relayPort->mSecondEndpoint.mTuple.getPort() == 0)
{
InfoLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", First packet received from Second Endpoint " << tuple);
pReceivingEndpoint = &relayPort->mSecondEndpoint;
pSendingEndpoint = &relayPort->mFirstEndpoint;
}
else // We already have 2 endpoints - this would be a third
{
// We have a third sender - for now drop, if one of the other senders stops sending data for 2 seconds then we will start picking up this sender
WarningLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", MediaRelay on " << relayPort->mLocalV4Tuple.getPort() << " has seen a third sender " << tuple << " - not implemented yet - ignoring packet");
}
if(pReceivingEndpoint)
{
pReceivingEndpoint->mTuple = tuple;
pReceivingEndpoint->mSendTimeMs = now;
pReceivingEndpoint->mRecvTimeMs = now;
}
}
if(pReceivingEndpoint)
{
pReceivingEndpoint->mRecvTimeMs = now;
if(pSendingEndpoint && pSendingEndpoint->mTuple.getPort() != 0)
{
if(ntohs(rtpHeader->versionExtPayloadTypeAndMarker) & 0x8000) // RTP Version 2
{
// Adjust ssrc
rtpHeader->ssrc = pSendingEndpoint->mSsrc;
// relay packet to second sender
resip_assert(pSendingEndpoint->mRelayDatagram.get() == 0);
pSendingEndpoint->mRelayDatagram = buffer;
pSendingEndpoint->mRelayDatagramLen = len;
if(pSendingEndpoint->mKeepaliveMode)
{
InfoLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", received packet to forward, turning off keepalive mode for " << pSendingEndpoint->mTuple);
pSendingEndpoint->mKeepaliveMode = false;
}
//InfoLog(<< "Relaying packet from=" << tuple << " to " << pSendingEndpoint->mTuple);
}
//else
//{
// InfoLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", discarding received packet with unknown RTP version from " << tuple);
//}
}
}
}
}
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,87 @@
#if !defined(MediaRelay_hxx)
#define MediaRelay_hxx
#include <map>
#include <deque>
#include <rutil/Data.hxx>
#include <rutil/Socket.hxx>
#include <rutil/ThreadIf.hxx>
#include <rutil/TransportType.hxx>
#include <resip/stack/Tuple.hxx>
#include "MediaRelayPort.hxx"
namespace gateway
{
class MediaRelay : public resip::ThreadIf
{
public:
MediaRelay(bool isV6Avail, unsigned short portRangeMin, unsigned short portRangeMax);
virtual ~MediaRelay();
bool createRelay(unsigned short& port);
void destroyRelay(unsigned short port);
void primeNextEndpoint(unsigned short& port, resip::Tuple& destinationIPPort);
protected:
private:
virtual void thread();
void buildFdSet(resip::FdSet& fdset);
void checkKeepalives(MediaRelayPort* relayPort);
void process(resip::FdSet& fdset);
bool processWrites(resip::FdSet& fdset, MediaRelayPort* relayPort); // return true if all writes are complete
void processReads(resip::FdSet& fdset, MediaRelayPort* relayPort);
bool createRelayImpl(unsigned short& port);
resip::Socket createRelaySocket(resip::Tuple& tuple);
typedef std::map<unsigned short, MediaRelayPort*> RelayPortList;
RelayPortList mRelays;
resip::Mutex mRelaysMutex;
bool mIsV6Avail;
std::deque<unsigned int> mFreeRelayPortList;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,84 @@
#include "rutil/ResipAssert.h"
#include <rutil/Data.hxx>
#include <rutil/Socket.hxx>
#include <resip/stack/Symbols.hxx>
#include <rutil/TransportType.hxx>
#include <rutil/Logger.hxx>
#include <resip/stack/Tuple.hxx>
//#include <rutil/DnsUtil.hxx>
//#include <rutil/ParseBuffer.hxx>
#include <resip/stack/Transport.hxx>
#include "AppSubsystem.hxx"
#include "MediaRelayPort.hxx"
#include <rutil/WinLeakCheck.hxx>
using namespace gateway;
using namespace resip;
using namespace std;
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
MediaRelayPort::MediaRelayPort() : mV4Fd(INVALID_SOCKET), mV6Fd(INVALID_SOCKET)
{
}
MediaRelayPort::MediaRelayPort(resip::Socket& v4fd, resip::Tuple& v4tuple, resip::Socket& v6fd, resip::Tuple& v6tuple) :
mV4Fd(v4fd), mLocalV4Tuple(v4tuple),
mV6Fd(v6fd), mLocalV6Tuple(v6tuple)
{
}
MediaRelayPort::MediaRelayPort(resip::Socket& v4fd, resip::Tuple& v4tuple) :
mV4Fd(v4fd), mLocalV4Tuple(v4tuple),
mV6Fd(INVALID_SOCKET)
{
}
MediaRelayPort::~MediaRelayPort()
{
#if defined(WIN32)
if(mV4Fd != INVALID_SOCKET) closesocket(mV4Fd);
if(mV6Fd != INVALID_SOCKET) closesocket(mV6Fd);
#else
if(mV4Fd != INVALID_SOCKET) close(mV4Fd);
if(mV6Fd != INVALID_SOCKET) close(mV6Fd);
#endif
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,94 @@
#if !defined(MediaRelayPort_hxx)
#define MediaRelayPort_hxx
#include <map>
#include <memory>
#include <rutil/Data.hxx>
#include <rutil/Random.hxx>
#include <rutil/Socket.hxx>
#include <rutil/TransportType.hxx>
#include <resip/stack/Tuple.hxx>
namespace gateway
{
class MediaEndpoint
{
public:
MediaEndpoint() : mSsrc(resip::Random::getRandom()), mRelayDatagramLen(0), mSendTimeMs(0), mRecvTimeMs(0), mKeepaliveMode(false) {}
resip::Tuple mTuple;
unsigned int mSsrc;
std::auto_ptr<char> mRelayDatagram;
int mRelayDatagramLen;
UInt64 mSendTimeMs;
UInt64 mRecvTimeMs;
bool mKeepaliveMode;
void reset()
{
mTuple = resip::Tuple();
mRelayDatagram.release();
mRelayDatagramLen = 0;
mKeepaliveMode = false;
}
};
class MediaRelayPort
{
public:
MediaRelayPort();
MediaRelayPort(resip::Socket& v4fd, resip::Tuple& v4tuple, resip::Socket& v6fd, resip::Tuple& v6tuple);
MediaRelayPort(resip::Socket& v4fd, resip::Tuple& v4tuple);
~MediaRelayPort();
// V4 and V6 fd's and tuples
resip::Socket mV4Fd;
resip::Tuple mLocalV4Tuple;
resip::Socket mV6Fd;
resip::Tuple mLocalV6Tuple;
// Sender data
MediaEndpoint mFirstEndpoint;
MediaEndpoint mSecondEndpoint;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,360 @@
#if !defined(Server_hxx)
#define Server_hxx
#include <map>
#include <resip/stack/TransactionUser.hxx>
#include <resip/stack/InterruptableStackThread.hxx>
#include <rutil/SelectInterruptor.hxx>
#include <resip/stack/UdpTransport.hxx>
#include <resip/dum/MasterProfile.hxx>
#include <resip/dum/DumShutdownHandler.hxx>
#include <resip/dum/DialogUsageManager.hxx>
#include <resip/dum/InviteSessionHandler.hxx>
#include <resip/dum/DialogSetHandler.hxx>
#include <resip/dum/OutOfDialogHandler.hxx>
#include <resip/dum/RedirectHandler.hxx>
#include <resip/dum/SubscriptionHandler.hxx>
#include <resip/dum/RegistrationHandler.hxx>
#include <rutil/Log.hxx>
#include <rutil/SharedPtr.hxx>
#include <rutil/Mutex.hxx>
#include "ConfigParser.hxx"
#include "B2BSession.hxx"
#include "SipRegistration.hxx"
#include "AddressTranslator.hxx"
#include "MediaRelay.hxx"
#include "IChatIPPortData.hxx"
#include "IPCThread.hxx"
#ifdef WIN32
#define sleepMs(t) Sleep(t)
#else
#define sleepMs(t) usleep(t*1000)
#endif
#define SDP_ICHATGW_ORIGIN_USER "iChat-gw"
namespace gateway
{
class ShutdownCmd;
class B2BSession;
class Server : public ConfigParser,
public IPCHandler,
public resip::DumShutdownHandler,
public resip::InviteSessionHandler,
public resip::DialogSetHandler,
public resip::OutOfDialogHandler,
public resip::RedirectHandler,
public resip::ClientSubscriptionHandler,
public resip::ServerSubscriptionHandler,
public resip::ClientRegistrationHandler,
public resip::ExternalUnknownDatagramHandler
{
public:
Server(int argc, char** argv);
virtual ~Server();
/**
Starts the SIP stack thread.
@note This should be called before calling process() in a loop
*/
void startup();
/**
This should be called in a loop to give process cycles to the server.
@param timeoutMs Will return after timeoutMs if nothing to do.
Application can do some work, but should call
process again ASAP.
*/
void process(int timeoutMs); // call this in a loop
/**
Used to initiate a shutdown of the server. This function blocks
until the shutdown is complete.
@note There should not be an active process request when this
is called.
*/
void shutdown();
// Utility Methods ////////////////////////////////////////////////////////////
typedef enum
{
SubsystemAll,
SubsystemContents,
SubsystemDns,
SubsystemDum,
SubsystemSdp,
SubsystemSip,
SubsystemTransaction,
SubsystemTransport,
SubsystemStats,
SubsystemGateway
} LoggingSubsystem;
/**
Static method that sets the logging level for a particular subsystem,
or all subsystems.
@param level Logging level to set
@param subsystem Subsystem to set level on
@note: Use Server::SubsystemAll to set the logging level on all
subsystems
*/
static void setLogLevel(resip::Log::Level level, LoggingSubsystem subsystem=SubsystemAll);
/**
Called by Jabber side of gateway to notify SIP side of iChat call request.
@param to Bare JID of endpoint we are proceeding to ring
@param from Full JID of endpoint requesting the call
*/
void notifyIChatCallRequest(const std::string& to, const std::string& from);
/**
Called by Jabber side of gateway to notify SIP side of cancelled iChat call request.
@param handle Handle of the B2BSession object for the call
*/
void notifyIChatCallCancelled(const B2BSessionHandle& handle);
/**
Called by Jabber side of gateway to notify B2BSession that iChat call is proceeding.
This call will cause a timeout timer to be deactiviated.
@param handle Handle of the B2BSession object for the call
@param to Full JID of endpoint we are proceeding to ring
*/
void notifyIChatCallProceeding(const B2BSessionHandle& handle, const std::string& to);
/**
Called by Jabber side of gateway to notify B2BSession that iChat call has failed.
@param handle Handle of the B2BSession object for the call
@param statusCode Code representing the reason for the failure
*/
void notifyIChatCallFailed(const B2BSessionHandle& handle, unsigned int statusCode);
/**
Called by Jabber side of gateway to notify B2BSession that iChat call setup
has completed on the Jabber side, and that it now needs to continue via SIP.
@param handle Handle of the B2BSession object for the call
@param remoteIPPortListBlob List of transports received from the iChat client via
Jabber messaging - in proprietary iChat blob format
*/
void continueIChatCall(const B2BSessionHandle& handle, const std::string& remoteIPPortListBlob);
/**
Called by Jabber side of gateway to request that a jabber user be registered on the
configured SIP server. Note: The jabber user's JID is first transformed into a
SIP URI using the configured translation rules. Note: calling this multiple times
with the same jidToRegister is safe and will result in a no op.
@param jidToRegister - Jabber user's JID to register on the SIP server.
*/
void sipRegisterJabberUser(const std::string& jidToRegister);
/**
Called by Jabber side of gateway to request that a jabber user be unregistered from the
configured SIP server. Note: The jabber user's JID is first transformed into a
SIP URI using the configured translation rules.
@param jidToUnregister - Jabber user's JID to unregister from the SIP server.
*/
void sipUnregisterJabberUser(const std::string& jidToUnregister);
/**
Called by Jabber side of gateway to check if the JID to be subscribed will pass the
translation rules.
@param to - JID of address being subscribed to
@param from - JID of subscriber
*/
void checkSubscription(const std::string& to, const std::string& from);
B2BSession* findMatchingIChatB2BSession(const resip::SipMessage& msg);
protected:
resip::SharedPtr<resip::MasterProfile>& getMasterProfile() { return mProfile; }
bool translateAddress(const resip::Data& address, resip::Data& translation, bool failIfNoRule=false);
// IPC Handler
virtual void onNewIPCMsg(const IPCMsg& msg);
// External Unknown Packet Handler//////////////////////////////////////////////
virtual void operator()(resip::UdpTransport* transport, const resip::Tuple& source, std::auto_ptr<resip::Data> unknownPacket);
// Shutdown Handler ////////////////////////////////////////////////////////////
void onDumCanBeDeleted();
// Invite Session Handler /////////////////////////////////////////////////////
virtual void onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
virtual void onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
virtual void onFailure(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&);
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
virtual void onConnected(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onStaleCallTimeout(resip::ClientInviteSessionHandle);
virtual void onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* msg);
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&);
virtual void onOffer(resip::InviteSessionHandle handle, const resip::SipMessage& msg, const resip::SdpContents& offer);
virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg);
virtual void onOfferRequestRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onRemoteSdpChanged(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents& sdp);
virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg);
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
virtual void onForkDestroyed(resip::ClientInviteSessionHandle);
// DialogSetHandler //////////////////////////////////////////////
virtual void onTrying(resip::AppDialogSetHandle, const resip::SipMessage& msg);
virtual void onNonDialogCreatingProvisional(resip::AppDialogSetHandle, const resip::SipMessage& msg);
// ClientSubscriptionHandler ///////////////////////////////////////////////////
virtual void onUpdatePending(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
virtual void onUpdateActive(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
virtual void onUpdateExtension(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder);
virtual void onTerminated(resip::ClientSubscriptionHandle h, const resip::SipMessage* notify);
virtual void onNewSubscription(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify);
virtual int onRequestRetry(resip::ClientSubscriptionHandle h, int retryMinimum, const resip::SipMessage& notify);
// ServerSubscriptionHandler ///////////////////////////////////////////////////
virtual void onNewSubscription(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
virtual void onNewSubscriptionFromRefer(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
virtual void onRefresh(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
virtual void onTerminated(resip::ServerSubscriptionHandle);
virtual void onReadyToSend(resip::ServerSubscriptionHandle, resip::SipMessage&);
virtual void onNotifyRejected(resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
virtual void onError(resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
virtual void onExpiredByClient(resip::ServerSubscriptionHandle, const resip::SipMessage& sub, resip::SipMessage& notify);
virtual void onExpired(resip::ServerSubscriptionHandle, resip::SipMessage& notify);
virtual bool hasDefaultExpires() const;
virtual UInt32 getDefaultExpires() const;
// OutOfDialogHandler //////////////////////////////////////////////////////////
virtual void onSuccess(resip::ClientOutOfDialogReqHandle, const resip::SipMessage& response);
virtual void onFailure(resip::ClientOutOfDialogReqHandle, const resip::SipMessage& response);
virtual void onReceivedRequest(resip::ServerOutOfDialogReqHandle, const resip::SipMessage& request);
// RedirectHandler /////////////////////////////////////////////////////////////
virtual void onRedirectReceived(resip::AppDialogSetHandle, const resip::SipMessage& response);
virtual bool onTryingNextTarget(resip::AppDialogSetHandle, const resip::SipMessage& request);
// Registration Handler ////////////////////////////////////////////////////////
virtual void onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
virtual void onFailure(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
virtual void onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
virtual int onRequestRetry(resip::ClientRegistrationHandle h, int retryMinimum, const resip::SipMessage& msg);
private:
friend class ShutdownCmd;
friend class B2BSession;
friend class IChatCallTimeout;
resip::DialogUsageManager& getDialogUsageManager();
void post(resip::ApplicationMessage& message, unsigned int ms=0);
void shutdownImpl();
friend class NotifyIChatCallRequestCmd;
void notifyIChatCallRequestImpl(const std::string& to, const std::string& from);
friend class NotifyIChatCallCancelledCmd;
void notifyIChatCallCancelledImpl(const B2BSessionHandle& handle);
friend class NotifyIChatCallProceedingCmd;
void notifyIChatCallProceedingImpl(const B2BSessionHandle& handle, const std::string& to);
friend class NotifyIChatCallFailedCmd;
void notifyIChatCallFailedImpl(const B2BSessionHandle& handle, unsigned int statusCode);
friend class ContinueIChatCallCmd;
void continueIChatCallImpl(const B2BSessionHandle& handle, const std::string& remoteIPPortListBlob);
friend class SipRegisterJabberUserCmd;
void sipRegisterJabberUserImpl(const std::string& jidToRegister);
friend class SipUnregisterJabberUserCmd;
void sipUnregisterJabberUserImpl(const std::string& jidToUnregister);
resip::SharedPtr<resip::MasterProfile> mProfile;
resip::Security* mSecurity;
resip::SelectInterruptor mSelectInterruptor;
resip::SipStack mStack;
resip::DialogUsageManager mDum;
resip::InterruptableStackThread mStackThread;
volatile bool mDumShutdown;
typedef std::map<B2BSessionHandle, B2BSession*> B2BSessionMap;
B2BSessionMap mB2BSessions;
B2BSessionHandle mCurrentB2BSessionHandle;
B2BSession* getB2BSession(const B2BSessionHandle& handle) const;
B2BSessionHandle registerB2BSession(B2BSession *);
void unregisterB2BSession(const B2BSessionHandle& handle);
friend class SipRegistration;
typedef std::map<resip::Uri, SipRegistration*> RegistrationMap;
RegistrationMap mRegistrations;
void registerRegistration(SipRegistration *);
void unregisterRegistration(SipRegistration *);
bool mIsV6Avail;
IChatIPPortData mLocalIPPortData;
MediaRelay* mMediaRelay;
IPCThread* mIPCThread;
AddressTranslator mAddressTranslator;
std::map<resip::DialogSetId,B2BSession*> mActiveSessions;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,165 @@
#include "Server.hxx"
#include "AppSubsystem.hxx"
#include "SipRegistration.hxx"
#include <rutil/Log.hxx>
#include <rutil/Logger.hxx>
#include <resip/dum/DialogUsageManager.hxx>
#include <resip/dum/ClientRegistration.hxx>
using namespace gateway;
using namespace resip;
using namespace std;
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
SipRegistration::SipRegistration(Server& server, DialogUsageManager& dum, Uri& aor)
: AppDialogSet(dum),
mServer(server),
mDum(dum),
mAor(aor),
mEnded(false)
{
mServer.registerRegistration(this);
}
SipRegistration::~SipRegistration()
{
mServer.unregisterRegistration(this);
}
const resip::Uri&
SipRegistration::getAor()
{
return mAor;
}
void
SipRegistration::end()
{
if(!mEnded)
{
mEnded = true;
if(mRegistrationHandle.isValid())
{
try
{
// If ended - then just shutdown registration - likely due to shutdown
mRegistrationHandle->end();
}
catch(BaseException&)
{
// If end() call is nested - it will throw - catch here so that processing continues normally
}
}
}
}
const NameAddrs&
SipRegistration::getContactAddresses()
{
static NameAddrs empty;
if(mRegistrationHandle.isValid())
{
return mRegistrationHandle->allContacts(); // .slg. note: myContacts is not sufficient, since they do not contain the stack populated transport address
}
else
{
return empty;
}
}
////////////////////////////////////////////////////////////////////////////////
// Registration Handler ////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void
SipRegistration::onSuccess(ClientRegistrationHandle h, const SipMessage& msg)
{
InfoLog(<< "onSuccess(ClientRegistrationHandle): aor=" << mAor << ", msg=" << msg.brief());
if(!mEnded)
{
mRegistrationHandle = h;
}
else
{
try
{
// If ended - then just shutdown registration - likely due to shutdown
h->end();
}
catch(BaseException&)
{
// If end() call is nested - it will throw - catch here so that processing continues normally
}
}
}
void
SipRegistration::onFailure(ClientRegistrationHandle h, const SipMessage& msg)
{
InfoLog(<< "onFailure(ClientRegistrationHandle): aor=" << mAor << ", msg=" << msg.brief());
if(!mEnded)
{
mRegistrationHandle = h;
}
else
{
try
{
// If we don't have a handle - then just shutdown registration - likely due to shutdown
h->end();
}
catch(BaseException&)
{
// If end() call is nested - it will throw - catch here so that processing continues normally
}
}
}
void
SipRegistration::onRemoved(ClientRegistrationHandle h, const SipMessage&msg)
{
InfoLog(<< "onRemoved(ClientRegistrationHandle): aor=" << mAor << ", msg=" << msg.brief());
}
int
SipRegistration::onRequestRetry(ClientRegistrationHandle h, int retryMinimum, const SipMessage& msg)
{
InfoLog(<< "onRequestRetry(ClientRegistrationHandle): aor=" << mAor << ", msg=" << msg.brief());
return -1; // Let Profile retry setting take effect
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,89 @@
#if !defined(SipRegistration_hxx)
#define SipRegistration_hxx
#include <resip/dum/AppDialogSet.hxx>
#include <resip/dum/InviteSessionHandler.hxx>
#include <resip/dum/DialogSetHandler.hxx>
#include <resip/dum/SubscriptionHandler.hxx>
#include "Server.hxx"
namespace resip
{
class DialogUsageManager;
class SipMessage;
}
namespace gateway
{
class Server;
/**
This class is used to manage active SIP registrations.
Author: Scott Godin (sgodin AT SipSpectrum DOT com)
*/
class SipRegistration : public resip::AppDialogSet
{
public:
SipRegistration(Server& server, resip::DialogUsageManager& dum, resip::Uri& aor);
virtual ~SipRegistration();
virtual void end();
const resip::Uri& getAor();
const resip::NameAddrs& getContactAddresses();
// Registration Handler ////////////////////////////////////////////////////////
virtual void onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
virtual void onFailure(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
virtual void onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
virtual int onRequestRetry(resip::ClientRegistrationHandle h, int retryMinimum, const resip::SipMessage& msg);
private:
Server &mServer;
resip::DialogUsageManager &mDum;
resip::Uri mAor;
bool mEnded;
resip::ClientRegistrationHandle mRegistrationHandle;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,176 @@
#include "rutil/ResipAssert.h"
#include "Thread.hxx"
using namespace gateway;
using namespace std;
#if defined(WIN32)
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <process.h> // for _beginthreadex()
typedef unsigned(__stdcall *THREAD_START_ROUTINE)(void*);
#endif
#include "rutil/ResipAssert.h"
#include <iostream>
extern "C"
{
static void*
#ifdef WIN32
__stdcall
#endif
threadWrapper( void* parm )
{
resip_assert( parm );
Thread* t = static_cast < Thread* > ( parm );
resip_assert( t );
t->thread();
#ifdef WIN32
_endthreadex(0);
#endif
return 0;
}
}
Thread::Thread() :
#ifdef WIN32
mThread(0),
#endif
mId(0), mShutdown(false)
{
}
Thread::~Thread()
{
shutdown();
join();
}
void
Thread::run()
{
resip_assert(mId == 0);
#if defined(WIN32)
mThread =
(HANDLE)_beginthreadex
(
NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes
0, // DWORD dwStackSize, // initial thread stack size
THREAD_START_ROUTINE
(threadWrapper), // LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function
this, //LPVOID lpParameter, // argument for new thread
0, //DWORD dwCreationFlags, // creation flags
&mId// LPDWORD lpThreadId // pointer to receive thread ID
);
resip_assert( mThread != 0 );
#else
// spawn the thread
if ( int retval = pthread_create( &mId, 0, threadWrapper, this) )
{
std::cerr << "Failed to spawn thread: " << retval << std::endl;
resip_assert(0);
}
#endif
}
void
Thread::join()
{
if (mId == 0)
{
return;
}
#if defined(WIN32)
DWORD exitCode;
while (true)
{
if (GetExitCodeThread(mThread,&exitCode) != 0)
{
if (exitCode != STILL_ACTIVE)
{
break;
}
else
{
WaitForSingleObject(mThread,INFINITE);
}
}
else
{
break;
}
}
CloseHandle(mThread);
mThread=0;
#else
void* stat;
if (mId != pthread_self())
{
int r = pthread_join( mId , &stat );
if ( r != 0 )
{
cerr << "Internal error: pthread_join() returned " << r << endl;
resip_assert(0);
}
}
#endif
mId = 0;
}
void
Thread::shutdown()
{
mShutdown = true;
}
bool
Thread::isShutdown() const
{
return mShutdown;
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,85 @@
#if !defined(Thread_hxx)
#define Thread_hxx
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <winsock2.h>
#undef WIN32_LEAN_AND_MEAN
#else
# include <pthread.h>
#endif
namespace gateway
{
class Thread
{
public:
Thread();
virtual ~Thread();
virtual void run();
void join();
virtual void shutdown();
bool isShutdown() const;
#ifdef WIN32
typedef unsigned int Id;
#else
typedef pthread_t Id;
#endif
virtual void thread() = 0;
protected:
#ifdef WIN32
HANDLE mThread;
#endif
Id mId;
volatile bool mShutdown;
private:
// Suppress copying
Thread(const Thread &);
const Thread & operator=(const Thread &);
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,36 @@
#define ICHATGW_VERSION_STRING "0.1"
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,154 @@
########################################################
# ichat-gw configuration file
########################################################
########################################################
# SIP settings
########################################################
# Local IP Address to bind SIP transports to. If left blank
# ichat-gw will bind to all adapters.
#IPAddress = 192.168.1.106
#IPAddress = 2001:5c0:1000:a::6d
IPAddress =
# Comma separated list of DNS servers, overrides default OS detected list (leave blank for default)
DNSServers =
# Used in From header of SIP calls, when caller is unknown. Value must be a valid formatted SIP
# NameAddr. Ie. “{displayname}” <{SIP URI}>. Currently this setting is only used when
# calling iChat endpoints and is never displayed to the end user.
SIPGatewayIdentity = "iChat-gw" <sip:ichat-gw@blitzzgod.com>
# Local port to listen on for SIP messages over UDP or TCP
UDPTCPPort = 5070
# Local port to listen on for SIP messages over TLS
TLSPort = 5071
# TLS domain name for this server (note: domain cert for this domain must be present)
TLSDomain =
# Enable/Disable TCP/UDP CRLFCRLF keepalive packets for SIP endpoints
# 1|true|on|enable to enable, 0|false|off|disable to disable
KeepAlives = enable
# URI of a proxy server to use a SIP outbound proxy. This setting should not be required if
# proper DNS based SIP routing is operational.
OutboundProxy =
# SIP Registration Time - the requested amount of seconds between SIP re-registration requests
# Set to 0, to instruct the iChat gateway not to perform any registrations
RegistrationTime = 3600
# SIP Registration Retry Time - the requested amount of seconds between retrying SIP registration
# requests after a registration failure.
RegistrationRetryTime = 120
########################################################
# General settings
########################################################
# Logging level: NONE|CRIT|ERR|WARNING|INFO|DEBUG|STACK
LogLevel = INFO
# Log Filename
LogFilename = ichat-gw.log
# Log file Max Lines
LogFileMaxLines = 50000
# Gateway IPC Port - for IPC UDP socket bound to 127.0.0.1
GatewayIPCPort = 2078
# Jabber Connector IPC Port - for IPC UDP socket bound to 127.0.0.1
JabberConnectorIPCPort = 2079
# Timeout for obtaining iChat Resources when an iChat user is called.
IChatProceedingTimeout = 5000
# If enabled then any time an IChat endpoint is involved then the media relay will be used.
# If disabled then the media relay is only used if iChat is originator of a Click-to-dial call.
# Note: The media relay MUST be used to perform RTP IPV4<->IPV6 translation and to avoid
# media stream timeout during a SIP phone hold.
# 1|true|on|enable to enable, 0|false|off|disable to disable
AlwaysRelayIChatMedia = true
# Prefer IPv6 over IPv4 - this setting controls which IP address we select when presented
# with the list of IP addresses for an iChat endpoint
PreferIPv6 = true
# Comma separated codec ID filter list - specifies non-interopable codecs that should
# be filtered from Sdp Offers.
# Note: Default is 3 (GSM), since it has proven non-interopable between iChat and SNOM phones
CodecIdFilterList = 3
# Media relay port range min/max settings. These settings define the range of ports that will be used
# by the media relay.
MediaRelayPortRangeMin = 8000
MediaRelayPortRangeMax = 9999
########################################################
# Jabber settings
########################################################
# Hostname or IP address of the Jabber server to connect to
JabberServer = jabber.blitzzgod.com
# Identity of this component - note: domain suffix should match Jabber server domain
JabberComponentName = ichat-gw.jabber.blitzzgod.com
# Jabber Component Password required in order to connect to Jabber server as a component
JabberComponentPassword = password
# Jabber Component Port - port on Jabber server that accepts component connections
JabberComponentPort = 5275
# Duration between Jabber ping messages sent to the server, in order to keep the component connection alive
JabberServerPingDuration = 60
# Username for the iChat Gateway control user - Note: iChat users of the Gateway must add this user to their roster
JabberControlUsername = control
########################################################
# Address Translation Rules (must be listed in pairs)
########################################################
# Rule for mapping any sip address to appropriate jabber JID/domain
TranslationPattern=^sip:(.*)@(.*)$
TranslationOutput=xmpp:$1@jabber.blitzzgod.com
#Rule for mapping any xmpp address to appropriate SIP URI/domain
TranslationPattern=^xmpp:(.*)@(.*)$
TranslationOutput=sip:$1@blitzzgod.com
########################################################
# TLS Configurations
########################################################
#Local path to DH Parameters file
TLSDHParamsFilename =
# Local path to TLS Certificate
TLSCertificate =
# Local path to Private key file
TLSPrivateKey =
# Pass phrase of private key file (can be left blank)
TLSPrivateKeyPassPhrase =
########################################################
# iChat Jabber Connector Settings
########################################################
# Path to iChat jabber connector (ichat-gw-jc) executable
IchatJabberConnectorPath = ichat-gw-jc
#For Windows
#IchatJabberConnectorPath = ichat-gw-jc.exe

View File

@@ -0,0 +1,115 @@
#include <signal.h>
#include "AppSubsystem.hxx"
#include "Server.hxx"
#include <rutil/Log.hxx>
#include <rutil/Logger.hxx>
#include <rutil/DnsUtil.hxx>
#include <rutil/BaseException.hxx>
#include <resip/stack/NameAddr.hxx>
#include <rutil/WinLeakCheck.hxx>
using namespace gateway;
using namespace resip;
using namespace std;
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
static bool finished = false;
static void
signalHandler(int signo)
{
//std::cerr << "Shutting down..." << endl;
finished = true;
}
int
main (int argc, char** argv)
{
#ifndef _WIN32
if ( signal( SIGPIPE, SIG_IGN) == SIG_ERR)
{
cerr << "Couldn't install signal handler for SIGPIPE" << endl;
exit(-1);
}
#else
#if defined(_DEBUG) && defined(LEAK_CHECK)
resip::FindMemoryLeaks fml;
#endif
#endif
if ( signal( SIGINT, signalHandler ) == SIG_ERR )
{
cerr << "Couldn't install signal handler for SIGINT" << endl;
exit( -1 );
}
if ( signal( SIGTERM, signalHandler ) == SIG_ERR )
{
cerr << "Couldn't install signal handler for SIGTERM" << endl;
exit( -1 );
}
initNetwork();
//////////////////////////////////////////////////////////////////////////////
// Create Server
//////////////////////////////////////////////////////////////////////////////
{
Server server(argc, argv);
//////////////////////////////////////////////////////////////////////////////
// Startup and run...
//////////////////////////////////////////////////////////////////////////////
server.startup();
while(true)
{
server.process(50);
if(finished) break;
}
server.shutdown();
}
InfoLog(<< "ichat-gw is shutdown.");
sleepSeconds(2);
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,72 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ichat-gw", "ichat-gw_9_0.vcproj", "{8BA87397-9B42-4820-BA53-62FF35C22CAD}"
ProjectSection(ProjectDependencies) = postProject
{A77DCD34-20CA-4602-B185-EE3EAD97713D} = {A77DCD34-20CA-4602-B185-EE3EAD97713D}
{2A8BE839-6466-4001-B224-8F1C3168D04A} = {2A8BE839-6466-4001-B224-8F1C3168D04A}
{12720B4D-F4FC-4502-8FA9-589BF5166216} = {12720B4D-F4FC-4502-8FA9-589BF5166216}
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58} = {38594885-CF9C-4C5F-B3F0-E4969D7E3F58}
{96CD935E-1951-43B8-AF75-F1C06B3778C1} = {96CD935E-1951-43B8-AF75-F1C06B3778C1}
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106} = {3D0E5CEB-93DC-4FDB-918B-D08FA369E106}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rutil", "..\..\rutil\rutil_9_0.vcproj", "{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "resiprocate", "..\..\resip\stack\resiprocate_9_0.vcproj", "{2A8BE839-6466-4001-B224-8F1C3168D04A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dum", "..\..\resip\dum\dum_9_0.vcproj", "{12720B4D-F4FC-4502-8FA9-589BF5166216}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ares", "..\..\rutil\dns\ares\ares_9_0.vcproj", "{96CD935E-1951-43B8-AF75-F1C06B3778C1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcre", "..\..\contrib\pcre\pcre_9_0.vcproj", "{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jabberconnector", "jabberconnector\jabberconnector_9_0.vcproj", "{A77DCD34-20CA-4602-B185-EE3EAD97713D}"
ProjectSection(ProjectDependencies) = postProject
{EEDA9797-BEAA-4377-96FC-C4B41E063290} = {EEDA9797-BEAA-4377-96FC-C4B41E063290}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gloox", "..\..\contrib\gloox\gloox.vcproj", "{EEDA9797-BEAA-4377-96FC-C4B41E063290}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8BA87397-9B42-4820-BA53-62FF35C22CAD}.Debug|Win32.ActiveCfg = Debug|Win32
{8BA87397-9B42-4820-BA53-62FF35C22CAD}.Debug|Win32.Build.0 = Debug|Win32
{8BA87397-9B42-4820-BA53-62FF35C22CAD}.Release|Win32.ActiveCfg = Release|Win32
{8BA87397-9B42-4820-BA53-62FF35C22CAD}.Release|Win32.Build.0 = Release|Win32
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Debug|Win32.Build.0 = SSL-Debug|Win32
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Release|Win32.ActiveCfg = SSL-Release|Win32
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Release|Win32.Build.0 = SSL-Release|Win32
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Debug|Win32.Build.0 = SSL-Debug|Win32
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Release|Win32.ActiveCfg = SSL-Release|Win32
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Release|Win32.Build.0 = SSL-Release|Win32
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Debug|Win32.Build.0 = SSL-Debug|Win32
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Release|Win32.ActiveCfg = SSL-Release|Win32
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Release|Win32.Build.0 = SSL-Release|Win32
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Debug|Win32.ActiveCfg = Debug|Win32
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Debug|Win32.Build.0 = Debug|Win32
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Release|Win32.ActiveCfg = Release|Win32
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Release|Win32.Build.0 = Release|Win32
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Debug|Win32.ActiveCfg = Debug|Win32
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Debug|Win32.Build.0 = Debug|Win32
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Release|Win32.ActiveCfg = Release|Win32
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Release|Win32.Build.0 = Release|Win32
{A77DCD34-20CA-4602-B185-EE3EAD97713D}.Debug|Win32.ActiveCfg = Debug|Win32
{A77DCD34-20CA-4602-B185-EE3EAD97713D}.Debug|Win32.Build.0 = Debug|Win32
{A77DCD34-20CA-4602-B185-EE3EAD97713D}.Release|Win32.ActiveCfg = Release|Win32
{A77DCD34-20CA-4602-B185-EE3EAD97713D}.Release|Win32.Build.0 = Release|Win32
{EEDA9797-BEAA-4377-96FC-C4B41E063290}.Debug|Win32.ActiveCfg = Debug|Win32
{EEDA9797-BEAA-4377-96FC-C4B41E063290}.Debug|Win32.Build.0 = Debug|Win32
{EEDA9797-BEAA-4377-96FC-C4B41E063290}.Release|Win32.ActiveCfg = Release|Win32
{EEDA9797-BEAA-4377-96FC-C4B41E063290}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,300 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="ichat-gw"
ProjectGUID="{8BA87397-9B42-4820-BA53-62FF35C22CAD}"
RootNamespace="ichatgw"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)../../&quot;;&quot;$(ProjectDir)../../contrib/openssl/include&quot;;&quot;$(ProjectDir)../../contrib/openssl/inc32&quot;;&quot;$(ProjectDir)../../contrib/pcre&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;USE_SSL;USE_IPV6"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib &quot;$(ProjectDir)..\..\contrib\openssl\lib\vc\static\libeay32MDd.lib&quot; &quot;$(ProjectDir)..\..\contrib\openssl\lib\vc\static\ssleay32MDd.lib&quot;"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<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"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(ProjectDir)../../&quot;;&quot;$(ProjectDir)../../contrib/openssl/include&quot;;&quot;$(ProjectDir)../../contrib/openssl/inc32&quot;;&quot;$(ProjectDir)../../contrib/pcre&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;USE_SSL;USE_IPV6"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib &quot;$(ProjectDir)..\..\contrib\openssl\lib\vc\static\libeay32MD.lib&quot; &quot;$(ProjectDir)..\..\contrib\openssl\lib\vc\static\ssleay32MD.lib&quot;"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<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>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\AddressTranslator.cxx"
>
</File>
<File
RelativePath=".\AppSubsystem.cxx"
>
</File>
<File
RelativePath=".\B2BSession.cxx"
>
</File>
<File
RelativePath=".\ConfigParser.cxx"
>
</File>
<File
RelativePath=".\ichat-gw.cxx"
>
</File>
<File
RelativePath=".\IChatIPPortData.cxx"
>
</File>
<File
RelativePath=".\IPCThread.cxx"
>
</File>
<File
RelativePath=".\MediaRelay.cxx"
>
</File>
<File
RelativePath=".\MediaRelayPort.cxx"
>
</File>
<File
RelativePath=".\Server.cxx"
>
</File>
<File
RelativePath=".\SipRegistration.cxx"
>
</File>
<File
RelativePath=".\Thread.cxx"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\AddressTranslator.hxx"
>
</File>
<File
RelativePath=".\AppSubsystem.hxx"
>
</File>
<File
RelativePath=".\B2BSession.hxx"
>
</File>
<File
RelativePath=".\ConfigParser.hxx"
>
</File>
<File
RelativePath=".\IChatGatewayCmds.hxx"
>
</File>
<File
RelativePath=".\IChatIPPortData.hxx"
>
</File>
<File
RelativePath=".\IPCThread.hxx"
>
</File>
<File
RelativePath=".\MediaRelay.hxx"
>
</File>
<File
RelativePath=".\MediaRelayPort.hxx"
>
</File>
<File
RelativePath=".\Server.hxx"
>
</File>
<File
RelativePath=".\SipRegistration.hxx"
>
</File>
<File
RelativePath=".\Thread.hxx"
>
</File>
<File
RelativePath=".\Version.hxx"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<File
RelativePath=".\ichat-gw.config"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,8 @@
/Makefile.in
/Makefile
/.deps
/.libs
/ichat-gw-jc

View File

@@ -0,0 +1,210 @@
#include "IChatUser.hxx"
#include "JabberComponent.hxx"
using namespace gateway;
using namespace std;
namespace gateway
{
IChatUser::IChatUser(JabberComponent& component, const std::string& jid) :
mJID(jid),
mComponent(component)
{
}
IChatUser::~IChatUser()
{
ResourceMap::iterator it = mResources.begin();
for(;it!=mResources.end();it++)
{
delete it->second;
}
}
void
IChatUser::updateResourceInfo(const std::string& resourceId, const gloox::Presence& presence, int priority, bool avAvail)
{
bool originalUnavailability = isUnavailable();
if(resourceId.empty())
{
if(presence.presence() == gloox::Presence::Unavailable)
{
// All resources are unanavaiable
ResourceMap::iterator it = mResources.begin();
for(; it != mResources.end(); it++)
{
delete it->second;
}
mResources.clear();
}
else
{
// PresenceAvailable with no resource is meaningless
}
}
else
{
ResourceMap::iterator it = mResources.find(resourceId);
if(it != mResources.end())
{
if(presence.presence() == gloox::Presence::Unavailable)
{
delete it->second;
mResources.erase(it);
}
else
{
it->second->mPresence = presence;
it->second->mPriority = priority;
it->second->mAvAvail = avAvail;
}
}
else
{
if(presence.presence() != gloox::Presence::Unavailable)
{
mResources[resourceId] = new ResourceInfo(presence, mJID, priority, avAvail);
}
}
}
if(originalUnavailability && !isUnavailable())
{
// User was originally unavailable and now they are available - register SIP endpoint
mComponent.sipRegisterJabberUser(mJID);
}
else if(!originalUnavailability && isUnavailable())
{
// User was originally available and now they are unavailable - unregister SIP endpoint
mComponent.sipUnregisterJabberUser(mJID);
}
}
bool
IChatUser::isUnavailable()
{
return mResources.empty();
}
IChatUser::ResourceMap::iterator
IChatUser::getMostAvailableResourceItr()
{
ResourceMap::iterator itBestResource = mResources.end();
ResourceMap::iterator it = mResources.begin();
for(;it!=mResources.end();it++)
{
if(it->second->mAvAvail)
{
if(itBestResource == mResources.end())
{
itBestResource=it;
}
else
{
if(it->second->mPresence.presence() < itBestResource->second->mPresence.presence())
{
itBestResource=it;
}
else if(it->second->mPresence.presence() == itBestResource->second->mPresence.presence())
{
if(it->second->mPriority < itBestResource->second->mPriority)
{
itBestResource=it;
}
}
}
}
}
return itBestResource;
}
const std::string&
IChatUser::getMostAvailableResource()
{
static const std::string empty;
ResourceMap::iterator itBestResource = getMostAvailableResourceItr();
if(itBestResource != mResources.end())
{
return itBestResource->first;
}
return empty;
}
bool
IChatUser::getMostAvailableResourceList(std::list<std::string>& resourceList)
{
bool ret = false;
// Pass one - go through list and see what highest mPresence availability is
ResourceMap::iterator itBestResource = getMostAvailableResourceItr();
// Pass two - return all resources with matching mPresence and mPriority
if(itBestResource != mResources.end())
{
ResourceMap::iterator it = mResources.begin();
for(;it!=mResources.end();it++)
{
if(it->second->mAvAvail &&
it->second->mPresence.presence() == itBestResource->second->mPresence.presence() &&
it->second->mPriority == itBestResource->second->mPriority)
{
resourceList.push_back(it->first);
ret = true;
}
}
}
return ret;
}
void
IChatUser::addSubscribedGatewayUser(const std::string& jid)
{
mSubscribedGatewayUsers.insert(jid);
}
void
IChatUser::removeSubscribedGatewayUser(const std::string& jid)
{
SubscribedGatewayUserList::iterator it = mSubscribedGatewayUsers.find(jid);
if(it!=mSubscribedGatewayUsers.end())
{
mSubscribedGatewayUsers.erase(it);
}
}
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,104 @@
#if !defined(IChatUser_hxx)
#define IChatUser_hxx
#include <map>
#include <set>
#include <list>
#ifdef WIN32
#define RESIP_CONTRIB_GLOOX
#endif
// Gloox includes
#ifndef RESIP_CONTRIB_GLOOX
#include <gloox/component.h>
#include <gloox/presence.h>
#else
#include <src/component.h>
#include <src/presence.h>
#endif
namespace gateway
{
class JabberComponent;
class ResourceInfo
{
public:
ResourceInfo(const gloox::Presence& presence, const std::string& jid, int priority, bool avAvail) :
mPresence(presence.presence(), jid), mPriority(priority), mAvAvail(avAvail) {}
~ResourceInfo() {}
gloox::Presence mPresence;
int mPriority;
bool mAvAvail;
};
class IChatUser
{
public:
IChatUser(JabberComponent& component, const std::string& jid);
~IChatUser();
typedef std::set<std::string> SubscribedGatewayUserList;
void updateResourceInfo(const std::string& resourceId, const gloox::Presence& presence, int priority, bool avAvail);
bool isUnavailable();
const std::string& getMostAvailableResource();
bool getMostAvailableResourceList(std::list<std::string>& resourceList);
void addSubscribedGatewayUser(const std::string& jid);
void removeSubscribedGatewayUser(const std::string& jid);
const SubscribedGatewayUserList& getSubscribedGatewayUserList() { return mSubscribedGatewayUsers; }
private:
std::string mJID;
typedef std::map<std::string, ResourceInfo*> ResourceMap;
ResourceMap mResources;
ResourceMap::iterator getMostAvailableResourceItr();
SubscribedGatewayUserList mSubscribedGatewayUsers;
JabberComponent& mComponent;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
#if !defined(JabberComponent_hxx)
#define JabberComponent_hxx
#include "JabberUserDb.hxx"
#include "../IPCThread.hxx"
#include <string>
#include <map>
#include <set>
#include <list>
#ifdef WIN32
#define RESIP_CONTRIB_GLOOX
#endif
// Gloox includes
#ifndef RESIP_CONTRIB_GLOOX
#include <gloox/component.h>
#include <gloox/mutex.h>
#include <gloox/messagehandler.h>
#include <gloox/presencehandler.h>
#include <gloox/loghandler.h>
#include <gloox/rostermanager.h>
#include <gloox/connectionlistener.h>
#include <gloox/stanzaextension.h>
#include <gloox/iqhandler.h>
#include <gloox/disco.h>
#include <gloox/disconodehandler.h>
#include <gloox/subscriptionhandler.h>
#else
#include <src/component.h>
#include <src/mutex.h>
#include <src/messagehandler.h>
#include <src/presencehandler.h>
#include <src/loghandler.h>
#include <src/rostermanager.h>
#include <src/connectionlistener.h>
#include <src/stanzaextension.h>
#include <src/iqhandler.h>
#include <src/disco.h>
#include <src/disconodehandler.h>
#include <src/subscriptionhandler.h>
#endif
namespace gateway
{
class JabberComponent;
class IChatUser;
class IChatCallRequest
{
public:
IChatCallRequest() : mJabberComponent(0), mB2BSessionHandle(0), mCancelled(false) {}
IChatCallRequest(JabberComponent* jabberComponent, const std::string& to, const std::string& from, unsigned int handle) :
mJabberComponent(jabberComponent), mTo(to), mFrom(from), mB2BSessionHandle(handle), mCancelled(false) {}
// Client Methods
void sendIChatVCRequest(const std::string& fullTo);
void sendIChatVCCancelToAll();
void receivedIChatVCResponse(const std::string& from);
// Server Methods
void sendIChatVCResponse(bool accept);
JabberComponent* mJabberComponent;
std::string mTo;
std::string mFrom;
unsigned int mB2BSessionHandle;
bool mCancelled;
std::set<std::string> mPendingVCRequestSet;
};
class JabberComponent : public Thread,
IPCHandler,
gloox::ConnectionListener,
gloox::PresenceHandler,
gloox::MessageHandler,
gloox::LogHandler,
gloox::DiscoNodeHandler,
gloox::IqHandler,
gloox::SubscriptionHandler
{
public:
JabberComponent(unsigned short jabberConnectorIPCPort,
unsigned short gatewayIPCPort,
const std::string& server,
const std::string& component,
const std::string& password,
int port,
unsigned int serverPingDuration,
const std::string& controlUser,
const std::string& localIChatPortListBlob);
~JabberComponent();
void stop();
void disconnect();
// Client Methods
void initiateIChatCall(const std::string& to, const std::string& from, unsigned int handle, bool alertOneOnly=true);
void cancelIChatCall(const std::string& to, const std::string& from);
// Server Methods
void proceedingIChatCall(const std::string& to, const std::string& from, unsigned int handle);
void acceptIChatCall(const std::string& to, const std::string& from);
void rejectIChatCall(const std::string& to, const std::string& from);
private:
void probePresence(const std::string& to);
void sendPresenceForRequest(const gloox::Presence& presence);
void sendPresence(const std::string& to, const std::string& from, bool advertiseIChatSupport, bool available);
void sendSubscriptionResponse(const std::string& to, const std::string& from, bool success);
// Interfaces to send IPC messages
friend class IChatUser;
void notifyIChatCallRequest(const std::string& to, const std::string& from);
void notifyIChatCallCancelled(unsigned int handle);
void notifyIChatCallProceeding(unsigned int handle, const std::string& to);
void notifyIChatCallFailed(unsigned int handle, unsigned int statusCode);
void continueIChatCall(unsigned int, const std::string& remoteIPPortListBlob);
void sipRegisterJabberUser(const std::string& jidToRegister);
void sipUnregisterJabberUser(const std::string& jidToUnregister);
void checkSubscription(const std::string& to, const std::string& from);
// Handlers
virtual void onNewIPCMsg(const IPCMsg& msg);
virtual void handleLog(gloox::LogLevel level, gloox::LogArea area, const std::string& message);
virtual void onConnect();
virtual void onDisconnect(gloox::ConnectionError e);
virtual bool onTLSConnect(const gloox::CertInfo& info);
virtual void handleSubscription(const gloox::Subscription& subscription);
virtual void handlePresence(const gloox::Presence& presence);
virtual void handleMessage(const gloox::Message& msg, gloox::MessageSession* session = 0);
virtual bool handleIq(const gloox::IQ& iq);
virtual void handleIqID(const gloox::IQ& iq, int context);
virtual gloox::StringList handleDiscoNodeFeatures(const gloox::JID& from, const std::string& node);
virtual gloox::Disco::IdentityList handleDiscoNodeIdentities(const gloox::JID& from, const std::string& node);
virtual gloox::Disco::ItemList handleDiscoNodeItems(const gloox::JID& from, const gloox::JID& to, const std::string& node);
virtual void thread();
gloox::Component* mComponent;
bool mStopping;
unsigned int mServerPingDuration;
std::string mControlJID;
std::string mLocalIChatPortListBlob;
// Outstanding IChat call request maps
typedef std::map<std::string, IChatCallRequest> IChatCallRequestMap;
friend class IChatCallRequest;
std::string makeVCRequestKey(const std::string& bareTo, const std::string& bareFrom);
IChatCallRequestMap mOutstandingClientIChatCallRequests;
gloox::util::Mutex mOutstandingClientIChatCallRequestsMutex;
IChatCallRequestMap::iterator findOutstandingClientIChatCallRequest(const std::string& bareTo, const std::string& bareFrom);
void failOutstandingClientIChatCallRequest(const std::string& bareTo, const std::string& bareFrom, unsigned int code);
void failOutstandingClientIChatCallRequest(const std::string& bareTo, unsigned int code);
IChatCallRequestMap mOutstandingServerIChatCallRequests;
gloox::util::Mutex mOutstandingServerIChatCallRequestsMutex;
IChatCallRequestMap::iterator findOutstandingServerIChatCallRequest(const std::string& bareTo, const std::string& bareFrom);
void cancelOutstandingServerIChatCallRequest(const std::string& bareTo, const std::string& bareFrom);
gloox::util::Mutex mIChatUserMutex;
typedef std::map<std::string, IChatUser*> IChatUserMap;
IChatUserMap mIChatUsers;
void storeIChatSubscribedUser(const std::string& user, const std::string& subscribedJID);
void removeIChatSubscribedUser(const std::string& user, const std::string& subscribedJID);
void storeIChatPresence(const gloox::JID& jid, const gloox::Presence& presence, int priority, bool avAvail);
bool getMostAvailableIChatUserFullJID(const gloox::JID& jid, std::string& fullJID);
bool getMostAvailableIChatUserFullJIDList(const gloox::JID& jid, std::list<std::string>& fullJIDList);
JabberUserDb mUserDb;
IPCThread mIPCThread;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,168 @@
#include "JabberUserDb.hxx"
#include <iostream>
#include <fstream>
#include <iterator>
using namespace gateway;
using namespace std;
namespace gateway
{
JabberUserDb::JabberUserDb()
: mDbFilename("ichat-gw.userdb")
{
parseDbFile(mDbFilename);
}
JabberUserDb::~JabberUserDb()
{
}
void
JabberUserDb::addSubscribedJID(const std::string& user, const std::string& subscribedJID)
{
mUsers[user].insert(subscribedJID);
writeDbFile(mDbFilename);
}
void
JabberUserDb::removeSubscribedJID(const std::string& user, const std::string& subscribedJID)
{
bool found = false;
UserMap::iterator it = mUsers.find(user);
if(it!=mUsers.end())
{
SubscribeSet::iterator it2 = it->second.find(subscribedJID);
if(it2!=it->second.end())
{
found = true;
it->second.erase(it2);
}
// Remove user entirely if no subscriptions left
if(it->second.size() == 0)
{
mUsers.erase(it);
}
}
if(found)
{
writeDbFile(mDbFilename);
}
}
void
JabberUserDb::parseDbFile(const std::string& filename)
{
ifstream dbFile(filename.c_str());
string lastUser;
string sline;
// Get first line and ensure version is present
if(getline(dbFile, sline))
{
if(sline != "v1") // For now we just read version 1 format
{
cerr << "JabberUserDb::parseDbFile: invalid first line in file, expecting version line!" << endl;
return;
}
}
else
{
cerr << "JabberUserDb::parseDbFile: invalid first line in file, expecting version line!" << endl;
return;
}
while(getline(dbFile, sline))
{
if(sline.size() > 1 &&
sline.at(0) == '\t' &&
!lastUser.empty())
{
// This should be a local subscription JID
mUsers[lastUser].insert(sline.substr(1));
//cout << "'" << lastUser << "': '" << sline.substr(1) << "'" << endl;
}
else
{
// This should be a user
lastUser = sline;
}
}
}
void
JabberUserDb::writeDbFile(const std::string& filename)
{
std::string tempfilename = filename + ".tmp";
// safewrite - write to a temp file, delete original, then move temp file
ofstream dbFile(tempfilename.c_str(), std::ios_base::out | std::ios_base::trunc);
if(dbFile.is_open())
{
dbFile << "v1\n";
UserMap::iterator it = mUsers.begin();
for(;it!=mUsers.end();it++)
{
dbFile << it->first << "\n";
SubscribeSet::iterator it2 = it->second.begin();
for(;it2!=it->second.end();it2++)
{
dbFile << "\t" << *it2 << "\n";
}
}
dbFile.close();
if(remove(filename.c_str()) != 0)
{
cerr << "JabberUserDb::writeDbFile - error removing " << filename << " to update with new data." << endl;
}
else
{
if(rename(tempfilename.c_str(), filename.c_str()) != 0)
{
cerr << "JabberUserDb::writeDbFile - error renaming " << tempfilename << " to " << filename << " to update with new data." << endl;
}
}
}
else
{
cerr << "JabberUserDb::writeDbFile - error opening " << tempfilename << " for writing." << endl;
}
}
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,72 @@
#if !defined(JabberUserDb_hxx)
#define JabberUserDb_hxx
#include <list>
#include <map>
#include <set>
#include <string>
namespace gateway
{
class JabberUserDb
{
public:
JabberUserDb();
virtual ~JabberUserDb();
typedef std::set<std::string> SubscribeSet;
typedef std::map<std::string, SubscribeSet> UserMap;
const UserMap& getUserSubscriptions() const { return mUsers; }
void addSubscribedJID(const std::string& user, const std::string& subscribedJID);
void removeSubscribedJID(const std::string& user, const std::string& subscribedJID);
private:
void parseDbFile(const std::string& filename);
void writeDbFile(const std::string& filename);
std::string mDbFilename;
UserMap mUsers;
};
}
#endif
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,80 @@
# $Id$
EXTRA_DIST = *.vcproj
SUBDIRS = .
#AM_CXXFLAGS = -DUSE_ARES
sbin_PROGRAMS = ichat-gw-jc
ichat_gw_jc_LDADD = ../../../resip/dum/libdum.la
ichat_gw_jc_LDADD += ../../../resip/stack/libresip.la
ichat_gw_jc_LDADD += ../../../rutil/librutil.la
ichat_gw_jc_LDADD += -lgloox
ichat_gw_jc_LDADD += -lgnutls
ichat_gw_jc_LDADD += -lidn
ichat_gw_jc_LDADD += -lresolv
ichat_gw_jc_LDADD += @LIBPTHREAD_LIBADD@
ichat_gw_jc_SOURCES = \
ichat-gw-jc.cxx \
IChatUser.cxx \
../IPCThread.cxx \
JabberComponent.cxx \
JabberUserDb.cxx \
../Thread.cxx
ichat_gw_jcincludedir = $(includedir)/ichat-gw-jc
nobase_ichat_gw_jcinclude_HEADERS = IChatUser.hxx \
JabberComponent.hxx \
JabberUserDb.hxx
##############################################################################
#
# The Vovida Software License, Version 1.0
# Copyright (c) 2000-2007 Vovida Networks, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. 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.
#
# 3. The names "VOCAL", "Vovida Open Communication Application Library",
# and "Vovida Open Communication Application Library (VOCAL)" must
# not be used to endorse or promote products derived from this
# software without prior written permission. For written
# permission, please contact vocal@vovida.org.
#
# 4. Products derived from this software may not be called "VOCAL", nor
# may "VOCAL" appear in their name, without prior written
# permission of Vovida Networks, Inc.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
# NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
# IN EXCESS OF $1,000, NOR FOR ANY 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.
#
# ====================================================================
#
# This software consists of voluntary contributions made by Vovida
# Networks, Inc. and many individuals on behalf of Vovida Networks,
# Inc. For more information on Vovida Networks, Inc., please see
# <http://www.vovida.org/>.
#
##############################################################################

View File

@@ -0,0 +1,129 @@
#include <signal.h>
#include <iostream>
#include "rutil/ResipAssert.h"
#include "JabberComponent.hxx"
#include <unistd.h>
using namespace gateway;
using namespace std;
void sleepSeconds(unsigned int seconds)
{
#ifdef WIN32
Sleep(seconds*1000);
#else
sleep(seconds);
#endif
}
JabberComponent* g_component;
static void
signalHandler(int signo)
{
//std::cerr << "Shutting down" << endl;
g_component->stop();
}
int
main (int argc, char** argv)
{
#ifndef _WIN32
if ( signal( SIGPIPE, SIG_IGN) == SIG_ERR)
{
cerr << "Couldn't install signal handler for SIGPIPE" << endl;
exit(-1);
}
#endif
if ( signal( SIGINT, signalHandler ) == SIG_ERR )
{
cerr << "Couldn't install signal handler for SIGINT" << endl;
exit( -1 );
}
if ( signal( SIGTERM, signalHandler ) == SIG_ERR )
{
cerr << "Couldn't install signal handler for SIGTERM" << endl;
exit( -1 );
}
if(argc != 11 || std::string(argv[0]) != std::string("ichat-gw"))
{
cerr << "argc=" << argc << ", argv[0]=" << argv[0] << endl;
cerr << "Jabber connector process must not be launched manually, it is launched automatically from the main ichat-gw program." << endl;
exit(-1);
}
#if defined(WIN32)
WORD wVersionRequested = MAKEWORD( 2, 2 );
WSADATA wsaData;
int err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
// could not find a usable WinSock DLL
cerr << "Could not load winsock" << endl;
resip_assert(0);
exit(1);
}
#endif
unsigned int jabberConnectorIPCPort = atoi(argv[1]);
unsigned int gatewayIPCPort = atoi(argv[2]);
g_component = new JabberComponent(jabberConnectorIPCPort,
gatewayIPCPort,
argv[3], // Jabber server
argv[4], // Jabber component name
argv[5], // Jabber component password
atoi(argv[6]), // Jabber component port
atoi(argv[7]), // Jabber server ping duration
argv[8], // Jabber control username
argv[9]); // IPPort Data blob
g_component->run();
g_component->join();
delete g_component;
cout << "ichat-gw-jc is shutdown." << endl;
sleepSeconds(2);
}
/* ====================================================================
Copyright (c) 2009, SIP Spectrum, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of SIP Spectrum nor the names of its 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.
==================================================================== */

View File

@@ -0,0 +1,244 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="jabberconnector"
ProjectGUID="{A77DCD34-20CA-4602-B185-EE3EAD97713D}"
RootNamespace="jabberconnector"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(ProjectDir)../../../&quot;;&quot;$(ProjectDir)../../../contrib/gloox&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;USE_SSL;USE_IPV6"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib"
OutputFile="$(OutDir)\ichat-gw-jc.exe"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy $(TargetPath) $(ProjectDir)..\"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(ProjectDir)../../../&quot;;&quot;$(ProjectDir)../../../contrib/gloox&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;USE_SSL;USE_IPV6"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib"
OutputFile="$(OutDir)\ichat-gw-jc.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy $(TargetPath) $(ProjectDir)..\"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\ichat-gw-jc.cxx"
>
</File>
<File
RelativePath=".\IChatUser.cxx"
>
</File>
<File
RelativePath="..\IPCThread.cxx"
>
</File>
<File
RelativePath=".\JabberComponent.cxx"
>
</File>
<File
RelativePath=".\JabberUserDb.cxx"
>
</File>
<File
RelativePath="..\Thread.cxx"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\IChatUser.hxx"
>
</File>
<File
RelativePath="..\IPCThread.hxx"
>
</File>
<File
RelativePath=".\JabberComponent.hxx"
>
</File>
<File
RelativePath=".\JabberUserDb.hxx"
>
</File>
<File
RelativePath="..\Thread.hxx"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>