[Pkg-voip-commits] [SCM] reSIProcate branch, master, updated. upstream/1.8.0_pre1-42-g87a864a

Daniel Pocock daniel at pocock.com.au
Tue May 22 13:39:41 UTC 2012


The following commit has been merged in the master branch:
commit 80eaf627b550ba61b1c824f796ab0c0a31a4b2f1
Author: Daniel Pocock <daniel at pocock.com.au>
Date:   Tue May 22 13:34:49 2012 +0000

    Imported Upstream version 1.8.0~pre5

diff --git a/Makefile.am b/Makefile.am
index 6f42621..6da5081 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,6 +6,9 @@ ACLOCAL_AMFLAGS = -I m4
 SUBDIRS = rutil
 SUBDIRS += resip
 SUBDIRS += repro
+if BUILD_B2BUA
+SUBDIRS += b2bua
+endif
 if BUILD_TFM
 SUBDIRS += tfm
 endif
diff --git a/Makefile.in b/Makefile.in
index 3a40fd1..995e2c0 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -33,14 +33,15 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
- at BUILD_TFM_TRUE@am__append_1 = tfm
- at BUILD_APPS_TRUE@am__append_2 = apps
+ at BUILD_B2BUA_TRUE@am__append_1 = b2bua
+ at BUILD_TFM_TRUE@am__append_2 = tfm
+ at BUILD_APPS_TRUE@am__append_3 = apps
 
 # The Makefiles for these don't separate SSL stuff yet...
- at USE_SSL_TRUE@am__append_3 = reTurn reTurn/client
- at BUILD_RECON_TRUE@@USE_SSL_TRUE at am__append_4 = reflow resip/recon
- at USE_SSL_TRUE@am__append_5 = presSvr
- at BUILD_P2P_TRUE@@USE_SSL_TRUE at am__append_6 = p2p/s2c/s2c p2p
+ at USE_SSL_TRUE@am__append_4 = reTurn reTurn/client
+ at BUILD_RECON_TRUE@@USE_SSL_TRUE at am__append_5 = reflow resip/recon
+ at USE_SSL_TRUE@am__append_6 = presSvr
+ at BUILD_P2P_TRUE@@USE_SSL_TRUE at am__append_7 = p2p/s2c/s2c p2p
 subdir = .
 DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
 	$(srcdir)/Makefile.in $(srcdir)/config.h.in \
@@ -78,8 +79,8 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
 	distdir dist dist-all distcheck
 ETAGS = etags
 CTAGS = ctags
-DIST_SUBDIRS = rutil resip repro tfm apps reTurn reTurn/client reflow \
-	resip/recon presSvr p2p/s2c/s2c p2p
+DIST_SUBDIRS = rutil resip repro b2bua tfm apps reTurn reTurn/client \
+	reflow resip/recon presSvr p2p/s2c/s2c p2p
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
@@ -246,7 +247,7 @@ AUTOMAKE_OPTIONS = foreign dist-tarZ
 ACLOCAL_AMFLAGS = -I m4
 SUBDIRS = rutil resip repro $(am__append_1) $(am__append_2) \
 	$(am__append_3) $(am__append_4) $(am__append_5) \
-	$(am__append_6)
+	$(am__append_6) $(am__append_7)
 
 #EXTRA_DIST = build-contrib.sh
 #EXTRA_DIST += reSIProcate_7_1.sln
diff --git a/apps/sipdial/sipdialer.1 b/apps/sipdial/sipdialer.1
index dacd973..712210c 100644
--- a/apps/sipdial/sipdialer.1
+++ b/apps/sipdial/sipdialer.1
@@ -15,4 +15,4 @@ Daniel Pocock <daniel at pocock.com.au>
 .SH "REPORTING BUGS"
 See http://www.resiprocate.org
 .SH COPYRIGHT
-Copyright (C) 2007 Daniel Pocock - licenced under the terms of GPL v3
+Copyright (C) 2007 Daniel Pocock - licenced under BSD terms
diff --git a/b2bua/AccountingManager.hxx b/b2bua/AccountingManager.hxx
new file mode 100644
index 0000000..f0bac7b
--- /dev/null
+++ b/b2bua/AccountingManager.hxx
@@ -0,0 +1,68 @@
+
+#ifndef __AccountingManager_h
+#define __AccountingManager_h
+
+
+#include "rutil/Data.h"
+
+namespace b2bua
+{
+
+class AccountingManager {
+
+public:
+  // Call has entered system
+  virtual void onCallStart() = 0;
+  // Call has been authorised
+  virtual void onCallAuthorise() = 0;
+  // Call has connected
+  virtual void onCallConnect() = 0;
+  // A route has failed
+  virtual void onCallRouteFail() = 0;
+  // All routes have been tried and failed, or the call was not authorised
+  virtual void onCallFail() = 0;
+  // The call connected and completed successfully
+  virtual void onCallFinish() = 0;
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/AuthenticationManager.cxx b/b2bua/AuthenticationManager.cxx
new file mode 100644
index 0000000..22484bf
--- /dev/null
+++ b/b2bua/AuthenticationManager.cxx
@@ -0,0 +1,45 @@
+
+#include "AuthenticationManager.hxx"
+
+using namespace b2bua;
+
+AuthenticationManager::SecretListener::~SecretListener() {
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/AuthenticationManager.hxx b/b2bua/AuthenticationManager.hxx
new file mode 100644
index 0000000..76d40a2
--- /dev/null
+++ b/b2bua/AuthenticationManager.hxx
@@ -0,0 +1,79 @@
+
+#ifndef __AuthenticationManager_h
+#define __AuthenticationManager_h
+
+#include "rutil/Data.hxx"
+
+namespace b2bua
+{
+
+class AuthenticationManager {
+
+//  const resip::Data& realm;
+//  const resip::Data& user;
+
+public:
+
+  /**
+   * The application should implement SecretListener to receive callbacks
+   * when authentication is complete.
+   */
+  class SecretListener {
+  public:
+    virtual ~SecretListener();
+    // Called when the secret is found successfully
+    virtual void onSuccess(const resip::Data& realm, const resip::Data& user, const resip::Data& secret) = 0;
+    // Called when the user ID is not recognised
+    virtual void onUserUnknown(const resip::Data& realm, const resip::Data& user) = 0;
+    // Called when an internal failure or timeout occurs
+    virtual void onFailure(const resip::Data& realm, const resip::Data& user) = 0;
+  };
+
+  virtual ~AuthenticationManager() {};
+
+  virtual void getSecret(const resip::Data& realm, const resip::Data& user, AuthenticationManager::SecretListener *secretListener) = 0;
+
+};
+
+}
+
+#endif
+
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/AuthorizationManager.hxx b/b2bua/AuthorizationManager.hxx
new file mode 100644
index 0000000..d50817e
--- /dev/null
+++ b/b2bua/AuthorizationManager.hxx
@@ -0,0 +1,92 @@
+
+#ifndef __AuthorizationManager_h
+#define __AuthorizationManager_h
+
+#include "rutil/Data.hxx"
+
+#include "CallHandle.hxx"
+
+namespace b2bua
+{
+
+class AuthorizationManager {
+
+public:
+
+  typedef enum DenialReason {
+    AuthenticationRequired, 		// A username is required
+    PeerUnknown,  			// IP or username unrecognised by
+					// the AuthorizationManager
+    InsufficientFunds,			// Deposit more funds
+    Unspecified,			// Request denied for an unspecified
+					// reason (e.g. account suspended),
+					// but not due to error
+    DestinationIncomplete,		// Number is too short
+    DestinationInvalid,			// Unrecognised destination prefix
+					// or name
+    InvalidRequest,			// Some other aspect of the request
+					// is invalid
+    NetworkError,			// An error occurred communicating
+					// with a remote auth server
+    Timeout,				// A timeout occurred
+    GeneralError			// An error while processing
+  };
+
+  class AuthorizationListener {
+  public:
+    virtual ~AuthorizationListener() {};
+    // Call is authorized 
+    virtual void onSuccess() = 0;
+    // Call is denied
+    virtual void onDeny(AuthorizationManager::DenialReason reason) = 0;
+  };
+
+  //virtual void getAuthorization();
+
+  virtual ~AuthorizationManager() {};
+
+  virtual CallHandle *authorizeCall(const resip::NameAddr& sourceAddr, const resip::Uri& destinationAddr, const resip::Data& authRealm, const resip::Data& authUser, const resip::Data& authPass, const resip::Data& srcIp, const resip::Data& contextId, const resip::Data& accountId, const resip::Data& baseIp, const resip::Data& controlId, time_t startTime) = 0;
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/B2BCall.cxx b/b2bua/B2BCall.cxx
new file mode 100644
index 0000000..424d197
--- /dev/null
+++ b/b2bua/B2BCall.cxx
@@ -0,0 +1,1321 @@
+
+#include <sstream>
+
+#include "resip/dum/ServerInviteSession.hxx"
+
+#include "B2BCall.hxx"
+#include "CallHandle.hxx"
+#include "Logging.hxx"
+#include "MyAppDialog.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+// DialogUsageManager *B2BCall::dum = NULL;
+// CallController *B2BCall::callController = NULL;
+// list<B2BCall *> B2BCall::calls;
+
+Data B2BCall::callStateNames[] = {
+  Data("NewCall"),
+  Data("CallerCancel"),
+  Data("AuthorizationPending"),
+  Data("AuthorizationSuccess"),
+  Data("AuthorizationFail"),
+  Data("MediaProxySuccess"),
+  Data("MediaProxyFail"),
+  Data("ReadyToDial"),
+  Data("DialInProgress"),
+  Data("DialFailed"),
+  Data("DialRejected"),
+  Data("SelectAlternateRoute"),
+  Data("DialAborted"),
+  Data("DialReceived180"),
+  Data("DialReceivedEarlyAnswer"),
+  Data("DialEarlyMediaProxySuccess"),
+  Data("DialEarlyMediaProxyFail"),
+  Data("CallAccepted"),
+  Data("CallAcceptedMediaProxySuccess"),
+  Data("CallAcceptedMediaProxyFail"),
+  Data("CallActive"),
+  Data("CallerHangup"),
+  Data("CalleeHangup"),
+  Data("LocalHangup"),
+  Data("CallStop"),
+  Data("CallStopMediaProxySuccess"),
+  Data("CallStopMediaProxyFail"),
+  Data("CallStopFinal")
+};
+
+const char *B2BCall::basicClearingReasonName[] = {
+  "NO ANSWER",
+  "BUSY",
+  "CONGESTION",
+  "ERROR",
+  "ANSWERED"
+};
+
+/* void B2BCall::setDum(DialogUsageManager *dum) {
+  B2BCall::dum = dum;
+} */
+
+/* void B2BCall::setCallController(CallController *callController) {
+  B2BCall::callController = callController;
+} */
+
+B2BCall::B2BCall(CDRHandler& cdrHandler, DialogUsageManager& dum, AuthorizationManager& authorizationManager, MyAppDialog *aLegAppDialog, const resip::NameAddr& sourceAddr, const resip::Uri& destinationAddr, const resip::Data& authRealm, const resip::Data& authUser, const resip::Data& authPassword, const resip::Data& srcIp, const resip::Data& contextId, const resip::Data& accountId, const resip::Data& baseIp, const resip::Data& controlId) : cdrHandler(cdrHandler), dum(dum), authorizationManager(authorizationManager), sourceAddr(sourceAddr), destinationAddr(destinationAddr), authRealm(authRealm), authUser(authUser), authPassword(authPassword), srcIp(srcIp), contextId(contextId), accountId(accountId), baseIp(baseIp), controlId(controlId) {
+  callHandle = NULL;
+  fullClearingReason = Unset;
+  rejectOtherCode = 0;
+  failureStatusCode = -1;
+  this->aLegAppDialog = aLegAppDialog;
+  aLegAppDialog->setB2BCall(this);
+  bLegAppDialogSet = NULL;
+  bLegAppDialog = NULL;
+  //callState = CALL_NEW;
+  callState = NewCall;
+  time(&startTime);
+  connectTime = 0;
+  finishTime = 0;
+  //aLegSdp = NULL;
+  //bLegSdp = NULL;
+  try {
+    mediaManager = new MediaManager(*this, aLegAppDialog->getDialogId().getCallId(), aLegAppDialog->getDialogId().getLocalTag(), Data(""));
+  } catch (...) {
+    B2BUA_LOG_ERR("failed to instantiate MediaManager");
+    throw new exception;
+  }
+  earlyAnswerSent = false;
+  failureReason = NULL;
+//  calls.push_back(this);
+}
+
+B2BCall::~B2BCall() {
+  if(callHandle != NULL)
+    delete callHandle;
+  if(mediaManager != NULL)
+    delete mediaManager;
+  if(failureReason != NULL)
+    delete failureReason;
+  if(aLegAppDialog != NULL)
+    aLegAppDialog->setB2BCall(NULL);
+  if(bLegAppDialogSet != NULL)
+    bLegAppDialogSet->setB2BCall(NULL);
+  if(bLegAppDialog != NULL)
+    bLegAppDialog->setB2BCall(NULL);
+}
+
+
+bool B2BCall::setCallState(B2BCall::B2BCallState newCallState) {
+  B2BUA_LOG_DEBUG("CallState change: " << callState << ":" << getCallStateName(callState) << " -> " << newCallState << ":" << getCallStateName(newCallState) << ": ");
+  if(!isCallStatePermitted(newCallState)) {
+    B2BUA_LOG_ERR("Denied call state change: %d: %s -> %d: %s", callState, getCallStateName(callState).c_str(), newCallState, getCallStateName(newCallState).c_str());
+    return false;
+  }
+  B2BUA_LOG_DEBUG("permitted.");
+  callState = newCallState;
+  return true;
+}
+
+bool B2BCall::isCallStatePermitted(B2BCall::B2BCallState newCallState) {
+  switch(callState) {
+
+  case NewCall:
+    switch(newCallState) {
+    case CallerCancel:
+    case AuthorizationPending:
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case CallerCancel:
+    switch(newCallState) {
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default: 
+      return false;
+    };
+
+  case AuthorizationPending:
+    switch(newCallState) {
+    case AuthorizationSuccess:
+    case AuthorizationFail:
+    case CallerCancel:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case AuthorizationSuccess:
+    switch(newCallState) {
+    case CallerCancel:
+    case MediaProxySuccess:
+    case MediaProxyFail:
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case AuthorizationFail:
+    switch(newCallState) {
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case MediaProxySuccess:
+    switch(newCallState) {
+    case CallerCancel:
+    case ReadyToDial:
+    //case DialInProgress:
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case MediaProxyFail:
+    switch(newCallState) {
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case ReadyToDial:
+    switch(newCallState) {
+    case CallerCancel:
+    case DialInProgress:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    }
+
+  case DialInProgress:
+    switch(newCallState) {
+    case CallerCancel:
+    case DialFailed:
+    case DialRejected:
+    case DialInProgress:	// FIXME - should we change to same state?
+    //case DialReceived100:
+    case DialReceived180:
+    case DialReceivedEarlyAnswer:
+    case CallAccepted:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case DialFailed:
+    switch(newCallState) {
+    case CallerCancel:
+    //case MediaProxySuccess:
+    //case ReadyToDial:
+    case SelectAlternateRoute:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case DialRejected:
+    switch(newCallState) {
+    case CallerCancel:
+    //case MediaProxySuccess:
+    //case ReadyToDial:
+    case SelectAlternateRoute:
+    case DialAborted:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case SelectAlternateRoute:
+    switch(newCallState) {
+    case CallerCancel:
+    case ReadyToDial:
+    case DialAborted:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+  
+  case DialAborted:
+    switch(newCallState) {
+    case CallStop:
+      return true;
+    default:
+      return false;
+    };
+
+  /* case DialReceived100:
+    switch(newCallState) {
+    case CallerCancel:
+    case DialInProgress:
+    case DialReceived180:
+    case DialReceivedEarlyAnswer:
+    case DialFailed:
+    case DialRejected:
+    case CallAccepted:
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    }; */
+
+  case DialReceived180:
+    switch(newCallState) {
+    case CallerCancel:
+    case DialInProgress:
+    case DialFailed:
+    case DialRejected:
+    case DialReceivedEarlyAnswer:
+    case CallAccepted:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case DialReceivedEarlyAnswer:
+    switch(newCallState) {
+    case CallerCancel:
+    case DialInProgress:
+    case DialFailed:
+    case DialRejected:
+    case DialEarlyMediaProxySuccess:
+    case DialEarlyMediaProxyFail:
+    case CallAccepted:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+/*  case DialEarlyMediaProxyRequested:
+    switch(newCallState) {
+    case :
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    }; */
+
+  case DialEarlyMediaProxySuccess:
+    switch(newCallState) {
+    case CallerCancel:
+    case DialInProgress:
+    case DialFailed:
+    case DialRejected:
+    case CallAccepted:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case DialEarlyMediaProxyFail:
+    switch(newCallState) {
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    }; 
+
+  case CallAccepted:
+    switch(newCallState) {
+    case CallerCancel:
+    case CallAcceptedMediaProxySuccess:
+    case CallAcceptedMediaProxyFail:
+    case CallActive:
+    case CallerHangup:
+    case CalleeHangup:
+    case LocalHangup:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+/*  case CallAcceptedMediaProxyRequested:
+    switch(newCallState) {
+    case :
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    }; */
+
+  case CallAcceptedMediaProxySuccess:
+    switch(newCallState) {
+    case CallerCancel:
+    case CallActive:
+    case CallerHangup:
+    case CalleeHangup:
+    case LocalHangup:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case CallAcceptedMediaProxyFail:
+    switch(newCallState) {
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case CallActive:
+    switch(newCallState) {
+    case CallerCancel:
+    case CallerHangup:
+    case CalleeHangup:
+    case LocalHangup:
+    //case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case CallerHangup:
+    switch(newCallState) {
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case CalleeHangup:
+    switch(newCallState) {
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case LocalHangup:
+    switch(newCallState) {
+    case CallStop:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case CallStop:
+    switch(newCallState) {
+    case CallStopMediaProxySuccess:
+    case CallStopMediaProxyFail:
+    case CallStopFinal:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+/*  case CallStopMediaProxyNotified:
+    switch(newCallState) {
+    case :
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    }; */
+
+  case CallStopMediaProxySuccess:
+    switch(newCallState) {
+    case CallStopFinal:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    };
+
+  case CallStopMediaProxyFail:
+    switch(newCallState) {
+    case CallStopFinal:
+      callState = newCallState;
+      return true;
+    default:
+      return false;
+    }; 
+
+  case CallStopFinal:
+    return false;  // no state changes permitted
+
+  default:
+    B2BUA_LOG_ERR("B2BCall in unknown call state %d", callState);
+    return false;
+  };
+};
+
+const Data& B2BCall::getCallStateName(B2BCallState s) {
+  return callStateNames[s];
+};
+
+void B2BCall::setALegSdp(const SdpContents& sdp, const in_addr_t& msgSourceAddress) {
+  // try {
+    mediaManager->setALegSdp(sdp, msgSourceAddress);
+  //} catch (...) {
+    // FIXME - call state
+   // B2BUA_LOG_WARNING, "failed to accept SDP from A leg");
+    //callState = CALL_STOP;
+  //}
+}
+
+void B2BCall::setBLegSdp(const SdpContents& sdp, const in_addr_t& msgSourceAddress) {
+  //try {
+    mediaManager->setBLegSdp(sdp, msgSourceAddress);
+  //} catch (...) {
+   // B2BUA_LOG_WARNING, "failed to accept SDP from B leg");
+    //callState = CALL_STOP;
+  //}
+}
+
+void B2BCall::setBLegAppDialog(MyAppDialog *myAppDialog) {
+  bLegAppDialog = myAppDialog; 
+  //mediaManager->setToTag(bLegAppDialog->getDialogId().getLocalTag());
+}
+
+void B2BCall::releaseAppDialog(MyAppDialog *myAppDialog) {
+  if(myAppDialog == aLegAppDialog) {
+    aLegAppDialog = NULL;
+  } else if(myAppDialog == bLegAppDialog) {
+    bLegAppDialog = NULL;
+  } else {
+    B2BUA_LOG_ERR("releaseAppDialog for unknown AppDialog");
+  }
+}
+
+void B2BCall::releaseAppDialogSet(MyAppDialogSet *myAppDialogSet) {
+  if(myAppDialogSet == bLegAppDialogSet) {
+    bLegAppDialogSet = NULL;
+  } else {
+    B2BUA_LOG_ERR("releaseAppDialogSet for unknown AppDialogSet");
+  }
+}
+
+/* This method is called regularly.
+  Instead, the callbacks or setCallState should send a message to 
+  B2BUA to say that the call needs attention. */
+void B2BCall::checkProgress(time_t now, bool stopping) {
+  switch(callState) {
+    case NewCall:
+      doNewCall();
+      break;
+    case CallerCancel:
+      doCallerCancel();
+      break;
+    case AuthorizationPending:
+      doAuthorizationPending();
+      break;
+    case AuthorizationSuccess:
+      doAuthorizationSuccess();
+      break;
+    case AuthorizationFail:
+      doAuthorizationFail();
+      break;
+    case MediaProxySuccess:
+      doMediaProxySuccess();
+      break;
+    case MediaProxyFail:
+      doMediaProxyFail();
+      break;
+    case ReadyToDial:
+      doReadyToDial();
+      break;
+    case DialInProgress:
+      // FIXME - route timeout?
+      break;
+    case DialFailed:
+      doDialFailed();
+      break;
+    case DialRejected:
+      doDialRejected();
+      break;
+    case SelectAlternateRoute:
+      doSelectAlternateRoute();
+      break;
+    case DialAborted:
+      doDialAborted();
+      break;
+    /* case DialReceived100:
+      doDialReceived100();
+      break; */
+    case DialReceived180:
+      doDialReceived180();
+      break;
+    /* case CALL_DIAL_183:
+      doCallDial183();
+      break; */
+    case DialReceivedEarlyAnswer:
+      doDialReceivedEarlyAnswer();
+      break;
+    case DialEarlyMediaProxySuccess:
+      doDialEarlyMediaProxySuccess();
+      break;
+    case DialEarlyMediaProxyFail:
+      doDialEarlyMediaProxyFail();
+      break;
+    //case CALL_DIAL_PROGRESS:
+      //doCallDialProgress();
+      //break;
+    case CallAccepted:
+      doCallAccepted();
+      break;
+    case CallAcceptedMediaProxySuccess:
+      doCallAcceptedMediaProxySuccess();
+      break;
+    case CallAcceptedMediaProxyFail:
+      doCallAcceptedMediaProxyFail();
+      break;
+    case CallActive:
+      doCallActive();
+      break;
+    case CallerHangup:
+    case CalleeHangup:
+    case LocalHangup:
+      doHangup();
+    case CallStop:
+      doCallStop();
+      break;
+    case CallStopMediaProxySuccess:
+      doCallStopMediaProxySuccess();
+      break;
+    case CallStopMediaProxyFail:
+      doCallStopMediaProxyFail();
+      break;
+    case CallStopFinal:
+      doCallStopFinal();
+      break;
+    default:
+      B2BUA_LOG_ERR("unknown call state %d", callState);
+      assert(0);
+      break;
+  }
+}
+
+bool B2BCall::isComplete() {
+  return (callState == CallStopFinal);
+}
+
+B2BCall::CallStatus B2BCall::getStatus() {
+  switch(callState) {
+  case NewCall:
+    return PreDial;
+  case CallerCancel:
+    return Finishing;
+  case AuthorizationPending:
+  case AuthorizationSuccess:
+  case AuthorizationFail:
+  case MediaProxySuccess:
+  case MediaProxyFail:
+    return PreDial;
+  case ReadyToDial:
+  case DialInProgress:
+  case DialFailed:
+  case DialRejected:
+  case SelectAlternateRoute:
+  case DialAborted:
+  //case DialReceived100:
+  case DialReceived180:
+  case DialReceivedEarlyAnswer:
+  case DialEarlyMediaProxySuccess:
+  case DialEarlyMediaProxyFail:
+    return Dialing;
+  case CallAccepted:
+  case CallAcceptedMediaProxySuccess:
+  case CallAcceptedMediaProxyFail:
+  case CallActive:
+    return Connected;
+  case CallerHangup:
+  case CalleeHangup:
+  case LocalHangup:
+  case CallStop:
+  case CallStopMediaProxySuccess:
+  case CallStopMediaProxyFail:
+  case CallStopFinal:
+    return Finishing;
+  default:
+    return Unknown;
+  }
+}
+
+void B2BCall::doNewCall() {
+  // Indicate trying
+  ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+  sis->provisional(100);
+  callHandle = authorizationManager.authorizeCall(sourceAddr, destinationAddr, authRealm, authUser, authPassword, srcIp, contextId, accountId, baseIp, controlId, startTime);
+  if(callHandle == NULL) {
+    B2BUA_LOG_WARNING("failed to get callHandle");
+    setCallState(CallStop);
+  } else {
+    setCallState(AuthorizationPending);
+  }
+}
+
+void B2BCall::doCallerCancel() {
+  setClearingReason(NoAnswerCancel, -1);
+  // If B leg dialing, send a CANCEL
+  if(bLegAppDialogSet != NULL) {
+    bLegAppDialogSet->end();
+  }
+  setCallState(CallStop);
+}
+
+void B2BCall::doAuthorizationPending() {
+  switch(callHandle->getAuthResult()) {
+  case CC_PENDING:
+    return;
+  case CC_PERMITTED:
+    setCallState(AuthorizationSuccess);
+    break;
+  default:
+    setCallState(AuthorizationFail);
+  }
+  return;
+}
+
+void B2BCall::doAuthorizationSuccess() {
+  // point to the first route
+  callRoute = callHandle->getRoutes().begin();
+  if(callRoute == callHandle->getRoutes().end()) {
+    appRef1 = Data("");
+    appRef2 = Data("");
+    setClearingReason(InvalidDestination, -1);
+    B2BUA_LOG_NOTICE("no routes returned");
+    ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get()); 
+    sis->reject(500);  // Server internal error
+    setCallState(CallStop);
+    return;
+  }
+  appRef1 = (*callRoute)->getAppRef1();
+  appRef2 = (*callRoute)->getAppRef2();
+  setCallState(MediaProxySuccess);
+  doMediaProxySuccess();
+}
+
+void B2BCall::doAuthorizationFail() {
+  setClearingReason(AuthError, -1);
+  if(aLegAppDialog != NULL) {
+    ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+    switch(callHandle->getAuthResult()) {
+    case CC_AUTH_REQUIRED:
+      sis->reject(401);  // Unauthorized/credentials required
+      break;
+    case CC_PAYMENT_REQUIRED:
+      sis->reject(402);  // Payment required
+      break;
+    case CC_REQUEST_DENIED:
+    case CC_IP_DENIED:
+      sis->reject(403);  // Permission denied/forbidden
+      break;  
+    case CC_ERROR:
+      sis->reject(500);  // Server internal error
+      break;
+    case CC_INVALID:
+      sis->reject(403);  // Forbidden
+      break;
+    case CC_DESTINATION_INCOMPLETE:
+      sis->reject(484);  // Incomplete
+      break;
+    case CC_DESTINATION_INVALID:
+      sis->reject(404);  // User doesn't exist
+      break;
+    case CC_TIMEOUT:
+      sis->reject(500);  // Server internal error
+      break;
+    default:
+      sis->reject(500);  // Server internal error
+    }
+  }
+  setCallState(CallStop);
+}
+
+void B2BCall::doMediaProxySuccess() {
+  setCallState(ReadyToDial);
+  doReadyToDial();
+}
+
+void B2BCall::doMediaProxyFail() {
+  setClearingReason(AuthError, -1);
+  B2BUA_LOG_ERR("failed to prepare media proxy");
+  setCallState(CallStop);
+}
+
+void B2BCall::doReadyToDial() {
+  // Media Proxy is ready, now we can create the B-leg and send an INVITE
+  try {
+    //SharedPtr<UserProfile> outboundUserProfile(new UserProfile);
+    SharedPtr<UserProfile> outboundUserProfile(dum.getMasterUserProfile());
+    outboundUserProfile->setDefaultFrom((*callRoute)->getSourceAddr());
+    outboundUserProfile->setDigestCredential((*callRoute)->getAuthRealm(), (*callRoute)->getAuthUser(), (*callRoute)->getAuthPass());
+    if((*callRoute)->getOutboundProxy() != Uri())
+      outboundUserProfile->setOutboundProxy((*callRoute)->getOutboundProxy());
+    bLegAppDialogSet = new MyAppDialogSet(dum, this, outboundUserProfile);
+
+    SharedPtr<SipMessage> msgB;
+    SdpContents *initialOffer = (SdpContents *)mediaManager->getALegSdp().clone();
+    msgB = dum.makeInviteSession((*callRoute)->getDestinationAddr(), outboundUserProfile, initialOffer, bLegAppDialogSet);
+    delete initialOffer;
+    dum.send(msgB);
+
+    setCallState(DialInProgress);
+  } catch (...) {
+    B2BUA_LOG_WARNING("failed to create new InviteSession");
+    setClearingReason(AuthError, -1);
+    setCallState(DialFailed);
+    return;
+  } 
+}
+
+// A route failed (timeout, ICMP, invalid domain, etc), try the next route
+void B2BCall::doDialFailed() {
+  if(bLegAppDialogSet != NULL) {
+    bLegAppDialogSet->end();
+    bLegAppDialogSet->setB2BCall(NULL);
+  }
+  bLegAppDialogSet = NULL;
+  bLegAppDialog = NULL;
+  failureStatusCode = -1;
+  //setClearingReason(AuthError, -1);
+  setCallState(SelectAlternateRoute); 
+  doSelectAlternateRoute();
+}
+
+// A route rejected the call, try the next route
+void B2BCall::doDialRejected() {
+  switch(failureStatusCode) {
+  case -1:
+    //setClearingReason(AuthError, -1);
+    setCallState(SelectAlternateRoute);
+    doSelectAlternateRoute();
+    break;
+  //case 480: // Temporarily not available
+  case 486: // Busy
+  //case 600: // Busy everywhere
+  //case 603: // Decline
+    // We will consider all of the above to be `BUSY'
+    setClearingReason(RejectBusy, failureStatusCode);
+    setCallState(DialAborted);
+    doDialAborted();
+    break;
+  default:
+    //setClearingReason(RejectOther, failureStatusCode);
+    if(bLegAppDialogSet != NULL) {
+      bLegAppDialogSet->end();
+      bLegAppDialogSet->setB2BCall(NULL);
+    }
+    bLegAppDialogSet = NULL;
+    bLegAppDialog = NULL;
+    setCallState(SelectAlternateRoute);
+    doSelectAlternateRoute();
+    break;
+  }
+}
+
+void B2BCall::doSelectAlternateRoute() {
+  callRoute++;
+  if(callRoute == callHandle->getRoutes().end()) {
+    B2BUA_LOG_DEBUG("no routes remaining, aborting attempt");
+    setCallState(DialAborted);
+    doDialAborted();
+    return;
+  }
+  appRef1 = (*callRoute)->getAppRef1();
+  appRef2 = (*callRoute)->getAppRef2();
+  setCallState(ReadyToDial);
+  doReadyToDial();
+}
+
+void B2BCall::doDialAborted() {
+  ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+  if(failureStatusCode == -1) {
+    setClearingReason(AuthError, failureStatusCode); // FIXME
+    sis->reject(503);
+  } else {
+    setClearingReason(RejectOther, failureStatusCode);
+    sis->reject(failureStatusCode);
+  }
+  setCallState(CallStop);
+  doCallStop();
+}
+
+
+/* void B2BCall::doDialReceived100() {
+  setCallState(DialInProgress);
+} */
+
+void B2BCall::doDialReceived180() {
+  if(setCallState(DialInProgress)) {
+    ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+    sis->provisional(180);
+  }
+}
+
+/* void B2BCall::doCallDial183() {
+  // FIXME - do nothing for now, unless there is an offer
+  setCallState(DialInProgress);
+} */
+
+void B2BCall::doDialReceivedEarlyAnswer() {
+  if(earlyAnswerSent == true) {
+    setCallState(DialInProgress);
+    return;
+  }
+  ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+  //sis->provideAnswer(*bLegSdp);
+  try {
+    sis->provideAnswer(mediaManager->getBLegSdp());
+  } catch (...) {
+    B2BUA_LOG_WARNING("failed to get B Leg SDP");
+    setClearingReason(AuthError, -1);
+    setCallState(DialEarlyMediaProxyFail);
+    return;
+  } 
+  //sis->provisional(183); 
+  //earlyAnswerSent = true;
+  setCallState(DialEarlyMediaProxySuccess);
+  doDialEarlyMediaProxySuccess();
+}
+
+void B2BCall::doDialEarlyMediaProxySuccess() {
+  ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+  sis->provisional(183);
+  earlyAnswerSent = true;
+  setCallState(DialInProgress);
+}
+
+void B2BCall::doDialEarlyMediaProxyFail() {
+  setClearingReason(AuthError, -1);
+  ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+  sis->reject(500);  // FIXME - error code
+  setCallState(CallStop);
+}
+
+void B2BCall::doCallAccepted() {
+  ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get()); 
+  if(!earlyAnswerSent) {
+    try {
+      SdpContents& sdp = mediaManager->getBLegSdp();
+      sis->provideAnswer(sdp); // FIXME - for re-INVITE
+    } catch(...) {
+      //setClearingReason(Error, -1);
+      setClearingReason(AnsweredError, -1);
+      setCallState(CallAcceptedMediaProxyFail);
+      return;
+    }
+  }
+  setCallState(CallAcceptedMediaProxySuccess);
+  doCallAcceptedMediaProxySuccess();
+}
+
+void B2BCall::doCallAcceptedMediaProxySuccess() {
+  ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+  sis->accept();
+  time(&connectTime);
+  callHandle->connect(&connectTime);
+  setCallState(CallActive);
+}
+
+void B2BCall::doCallAcceptedMediaProxyFail() {
+  setClearingReason(AnsweredError, -1);
+  ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+  sis->reject(500); // FIXME - error codes
+  setCallState(CallStop);
+}
+
+void B2BCall::doCallActive() {
+  if(callHandle->mustHangup()) {
+    B2BUA_LOG_DEBUG("ending a call due to mustHangup()");
+    setClearingReason(AnsweredLimit, -1);
+    setCallState(LocalHangup);
+  }
+}
+
+void B2BCall::doHangup() {
+  setCallState(CallStop);
+}
+
+void B2BCall::doCallStop() {
+//  setClearingReason(AnsweredUnknown, -1);
+  time(&finishTime);
+  if(callHandle != NULL) {
+    if(connectTime != 0)
+      callHandle->finish(&finishTime);
+    else
+      callHandle->fail(&finishTime);
+  }
+  if(aLegAppDialog != NULL) {
+    ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+    sis->end();
+  } 
+  if(bLegAppDialogSet != NULL) {
+    bLegAppDialogSet->end();
+  }
+  writeCDR();
+  setCallState(CallStopFinal);
+}
+
+void B2BCall::doCallStopMediaProxySuccess() {
+  setCallState(CallStopFinal);
+}
+
+void B2BCall::doCallStopMediaProxyFail() {
+  setCallState(CallStopFinal);
+}
+
+void B2BCall::doCallStopFinal() {
+  // do nothing, the call should be deleted shortly
+  if(callHandle != NULL) {
+    delete callHandle;
+    callHandle = NULL;
+  }
+}
+
+void B2BCall::setClearingReason(FullClearingReason reason, int code) {
+  // has a reason already been specified?  If so, leave it alone
+  if(fullClearingReason != Unset) 
+    return; 
+
+  fullClearingReason = reason;
+  if(fullClearingReason == RejectOther)
+    rejectOtherCode = code;
+  switch(fullClearingReason) {
+  case InvalidDestination:
+  case AuthError:
+    basicClearingReason = Error;
+    break;
+  case NoAnswerCancel:
+  case NoAnswerTimeout:
+    basicClearingReason = NoAnswer;
+    break;
+  case NoAnswerError:
+    basicClearingReason = Error;
+    break;
+  case RejectBusy:
+    basicClearingReason = Busy;
+    break;
+  case RejectOther:
+    switch(rejectOtherCode) {
+    /* case 503:  // ambiguous, could also indicate out of funds with a carrier
+      basicClearingReason = Congestion;
+      break; */
+    default:
+      basicClearingReason = Error;
+      break;
+    };
+    break;
+  case AnsweredALegHangup:
+  case AnsweredBLegHangup:
+  case AnsweredLimit:
+  case AnsweredShutdown:
+  case AnsweredError:
+  case AnsweredUnknown:
+    basicClearingReason = Answered;
+    break;
+  default:
+    basicClearingReason = Error;
+    break;
+  };
+}
+
+void B2BCall::setClearingReasonMediaFail() {
+  if(connectTime == 0)
+    setClearingReason(NoAnswerError, -1);
+  else
+    setClearingReason(AnsweredError, -1);
+}
+
+void B2BCall::writeCDR() {
+  std::ostringstream cdrStream;
+  cdrStream << sourceAddr << ",";
+  cdrStream << destinationAddr << ",";
+  cdrStream << contextId << ",";
+  cdrStream << '"' << basicClearingReasonName[basicClearingReason] << '"' << ",";
+  cdrStream << fullClearingReason << ",";
+  cdrStream << rejectOtherCode << ",";
+  cdrStream << startTime << ",";
+  if(connectTime == 0)
+    cdrStream << ",";
+  else
+    cdrStream << connectTime << ",";
+  cdrStream << finishTime << ",";
+  cdrStream << finishTime - startTime << ",";
+  if(connectTime != 0)
+    cdrStream << finishTime - connectTime;
+  cdrStream << ",";
+  cdrStream << appRef1 << "," << appRef2 << ",";
+  cdrHandler.handleRecord(cdrStream.str());
+}
+
+/* void B2BCall::onTrying() {
+  setCallState(DialReceived100);
+} */
+
+void B2BCall::onRinging() {
+  //callState = CALL_DIAL_180;
+  setCallState(DialReceived180);
+}
+
+//void B2BCall::onSessionProgress() {
+  //callState = CALL_DIAL_183;
+  //setCallState(DialReceived183);
+//}
+
+void B2BCall::onEarlyMedia(const SdpContents& sdp, const in_addr_t& msgSourceAddress) {
+  setCallState(DialReceivedEarlyAnswer);
+  try {
+    setBLegSdp(sdp, msgSourceAddress); 
+  } catch (...) {
+    // FIXME
+    setCallState(DialEarlyMediaProxyFail);
+    B2BUA_LOG_WARNING("onEarlyMedia: exception while calling setBLegSdp");
+    setClearingReason(NoAnswerError, -1);
+    //setCallState(CallStop);
+    return;
+  }
+  //ServerInviteSession *sis = (ServerInviteSession *)(aLegAppDialog->getInviteSession().get());
+  //sis->provideOffer(sdp);
+  //sis->provisional(183);
+}
+
+void B2BCall::onCancel() {
+  //callState = CALL_CANCEL;
+  setCallState(CallerCancel);
+}
+
+// Dial Failure due to ICMP, Timeout, protocol error or other reason
+void B2BCall::onFailure(MyAppDialog *myAppDialog) {
+  
+  // If we are about to try another route, bLegAppDialogSet will be NULL
+  if(bLegAppDialogSet == NULL) 
+    return;
+
+  // No need to do anything if it's already been rejected
+  if(callState == DialRejected)
+    return;
+
+  if(setCallState(DialFailed)) {
+  }
+}
+
+// Dial failure due to rejection by remote party
+void B2BCall::onRejected(int statusCode, const Data& reason) {
+  if(setCallState(DialRejected)) {
+    failureStatusCode = statusCode;
+    failureReason = new Data(reason);
+  }
+}
+
+
+void B2BCall::onOffer(MyAppDialog *myAppDialog, const SdpContents& sdp, const in_addr_t& msgSourceAddress) {
+  InviteSession *otherInviteSession = NULL;	// used to relay SDP to
+						// other party
+  SdpContents *otherSdp = NULL;
+  if(myAppDialog == aLegAppDialog) {
+    B2BUA_LOG_DEBUG("received SDP offer from A leg");
+    try {
+      setALegSdp(sdp, msgSourceAddress);
+    } catch (...) {
+      // FIXME - 
+      setClearingReasonMediaFail();
+      B2BUA_LOG_WARNING("onOffer: exception while calling setALegSdp");
+      setCallState(CallStop);
+      return;
+    }
+    if(bLegAppDialog != NULL) {
+      otherInviteSession = (InviteSession *)(bLegAppDialog->getInviteSession().get());
+      otherSdp = (SdpContents *)mediaManager->getALegSdp().clone();
+    }
+  } else if(myAppDialog == bLegAppDialog) {
+    B2BUA_LOG_DEBUG("received SDP offer from B leg");
+    try {
+      setBLegSdp(sdp, msgSourceAddress);
+    } catch (...) {
+      // FIXME
+      setClearingReasonMediaFail();
+      B2BUA_LOG_WARNING("onOffer: exception while calling setBLegSdp");
+      setCallState(CallStop);
+      return;
+    }
+    if(aLegAppDialog != NULL) {
+      otherInviteSession = (InviteSession *)(aLegAppDialog->getInviteSession().get());
+      otherSdp = (SdpContents *)mediaManager->getBLegSdp().clone();
+    }
+  } else {
+    B2BUA_LOG_ERR("onOffer: unrecognised myAppDialog");
+    throw new exception;
+  }
+  if(callState == CallActive) {
+    // Must be a re-INVITE, relay to other party
+    // FIXME - change state
+    B2BUA_LOG_DEBUG("processing a re-INVITE");
+    if(otherInviteSession != NULL)
+      otherInviteSession->provideOffer(*otherSdp);
+    else {
+      B2BUA_LOG_ERR("onOffer: otherInviteSession == NULL");
+      throw new exception; // FIXME
+    }
+  }
+  if(otherSdp != NULL)
+    delete otherSdp;
+}
+
+void B2BCall::onAnswer(MyAppDialog *myAppDialog, const SdpContents& sdp, const in_addr_t& msgSourceAddress) {
+  mediaManager->setToTag(bLegAppDialog->getDialogId().getLocalTag());
+  if(callState != CallActive) {
+    B2BUA_LOG_DEBUG("received answer");
+    // Answer to original INVITE
+    //callState = CALL_ANSWERED;
+    setCallState(CallAccepted);
+    time(&connectTime);
+    try {
+      setBLegSdp(sdp, msgSourceAddress);
+    } catch (...) {
+      // FIXME - stop the call
+      setClearingReasonMediaFail();
+      B2BUA_LOG_WARNING("onAnswer: exception while processing SDP");
+      setCallState(CallStop);
+      return;
+    }
+  } else {
+    // Answer to re-INVITE
+    InviteSession *inviteSession = NULL;
+    SdpContents *otherSdp = NULL;
+    if(myAppDialog == aLegAppDialog) {
+      B2BUA_LOG_DEBUG("answer received from A leg");
+      setALegSdp(sdp, msgSourceAddress);
+      inviteSession = (InviteSession *)(bLegAppDialog->getInviteSession().get());
+      otherSdp = (SdpContents *)mediaManager->getALegSdp().clone();
+    } else {
+      B2BUA_LOG_DEBUG("answer received from B leg");
+      setBLegSdp(sdp, msgSourceAddress);
+      inviteSession = (InviteSession *)(aLegAppDialog->getInviteSession().get());
+      otherSdp = (SdpContents *)mediaManager->getBLegSdp().clone();
+    }
+    inviteSession->provideAnswer(*otherSdp);
+    if(otherSdp != NULL)
+      delete otherSdp;
+  }
+}
+
+void B2BCall::onMediaTimeout() {
+  B2BUA_LOG_NOTICE("call hangup due to media timeout");
+  if(connectTime == 0)
+    setClearingReason(AnsweredNoMedia, -1);
+  else
+    setClearingReason(NoAnswerError, -1);
+  time(&finishTime);
+  setCallState(CallStop); 
+}
+
+void B2BCall::onHangup(MyAppDialog *myAppDialog) {
+  if(myAppDialog == aLegAppDialog) {
+    B2BUA_LOG_DEBUG("call hung up by a leg");
+    setClearingReason(AnsweredALegHangup, -1);
+    setCallState(CallerHangup);
+    time(&finishTime);
+  } else if(myAppDialog == bLegAppDialog) {
+    B2BUA_LOG_DEBUG("call hung up by b leg");
+    setClearingReason(AnsweredBLegHangup, -1);
+    setCallState(CalleeHangup);
+    time(&finishTime);
+  } else {
+    // possible termination of B leg after route fail
+    B2BUA_LOG_WARNING("B2BCall::onHangup(): unrecognised MyAppDialog");
+  }
+  //time(&finishTime);
+  //setCallState(CallStop);
+}
+
+void B2BCall::onStopping() {
+  // FIXME - should any states be handled differently?
+  switch(callState) {
+  case CallerCancel:
+  case AuthorizationFail:
+  case MediaProxyFail:
+  case DialEarlyMediaProxyFail:
+  case CallAcceptedMediaProxyFail:
+  case CallerHangup:
+  case CalleeHangup:
+  case LocalHangup:
+  case CallStop:
+  case CallStopMediaProxySuccess:
+  case CallStopMediaProxyFail:
+  case CallStopFinal:
+    return;
+  default:
+    onHangup(NULL);
+  }
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/B2BCall.hxx b/b2bua/B2BCall.hxx
new file mode 100644
index 0000000..f941285
--- /dev/null
+++ b/b2bua/B2BCall.hxx
@@ -0,0 +1,308 @@
+
+#ifndef __B2BCall_h
+#define __B2BCall_h
+
+/* B2BCall models a bridged call between a caller and a callee
+*/
+
+#include "rutil/Data.hxx"
+#include "resip/dum/DialogUsageManager.hxx"
+
+namespace b2bua
+{
+
+class B2BCall;
+class MyDialogSetHandler;
+
+}
+
+#include "AuthorizationManager.hxx"
+#include "CallHandle.hxx"
+#include "CDRHandler.hxx"
+#include "MediaManager.hxx"
+#include "MyAppDialog.hxx"
+
+
+namespace b2bua
+{
+
+class B2BCall {
+
+protected:
+
+  typedef enum B2BCallState {
+    NewCall = 0,				// just started
+    CallerCancel,				// CANCEL received from A leg
+    AuthorizationPending,
+    AuthorizationSuccess,
+    AuthorizationFail,
+//    RoutesPending,				// routes requested
+//    RoutesSuccess,
+//    RoutesFail,
+//   MediaProxyPending,				// Media Proxy requested
+    MediaProxySuccess,
+    MediaProxyFail,
+    ReadyToDial,				// Route ready
+    DialInProgress,				// INVITE sent
+    DialFailed,					// Network error, e.g. ICMP
+    DialRejected,				// SIP error received
+						// error code in data member
+						// failureStatusCode
+    SelectAlternateRoute,			// Need to select another
+						// route
+    DialAborted,				// No other carriers 
+						// available, or a failure
+						// that doesn't require us
+						// to try another carrier
+						// e.g. Busy
+//    DialReceived100,				// 100 response received
+    DialReceived180,				// 180 response received
+//    DialReceived183,				// 183 response received
+    DialReceivedEarlyAnswer,			// early answer (SDP) received
+//    DialEarlyMediaProxyRequested,		// Media proxy requested for
+						// early media
+    DialEarlyMediaProxySuccess,			// Media Proxy ready
+    DialEarlyMediaProxyFail,			// Media Proxy failed
+    CallAccepted,				// 200 received
+//    CallAcceptedMediaProxyRequested,		// Media proxy requested for
+						// media
+    CallAcceptedMediaProxySuccess,		// Media Proxy ready
+    CallAcceptedMediaProxyFail,			// Media proxy failed
+    CallActive,					// Call in progress
+    CallerHangup,				// Caller has hungup
+    CalleeHangup,				// Callee has hungup
+    LocalHangup,				// B2BUA initiated hangup
+    CallStop,					// Call is stopped
+//    CallStopMediaProxyNotified,			// Media proxy informed
+    CallStopMediaProxySuccess,			// Media proxy acknowledged
+    CallStopMediaProxyFail,			// Media proxy failed to ack
+    CallStopFinal				// Call can be purged from
+						// the system
+  };
+  
+  static resip::Data callStateNames[];
+
+  typedef enum BasicClearingReason {
+    NoAnswer = 0,	// caller gave up/timeout
+    Busy,		// callee indicated busy
+    Congestion,		// callee indicated congestion
+    Error,		// callee indicated error
+    Answered		// call was answered
+  };
+
+  static const char *basicClearingReasonName[];
+
+  typedef enum FullClearingReason {
+    Unset,
+
+    // No attempted
+    InvalidDestination,
+    AuthError,
+
+    // not answered
+    NoAnswerCancel,
+    NoAnswerTimeout,
+    NoAnswerError,	// media negotiation failed
+
+    // Rejected
+    RejectBusy,
+    RejectOther,	// rejectOtherCode = SIP error code
+
+    // Answered
+    AnsweredALegHangup,	// A leg hangup first
+    AnsweredBLegHangup, // B leg hangup first
+    AnsweredLimit,      // reached limit
+    AnsweredShutdown,   // Answered, B2BUA shutdown
+    AnsweredError,      // An error occured, e.g. during a re-INVITE
+    AnsweredNoMedia,	// Media stopped
+    AnsweredUnknown	// Answered, hangup for unknown reason
+  };
+
+  CDRHandler& cdrHandler;
+  resip::DialogUsageManager& dum;
+  //CallController *callController;
+  AuthorizationManager& authorizationManager;
+  
+  //static std::list<B2BCall *> calls;
+
+  // Attributes of the call, from the original INVITE
+  resip::NameAddr sourceAddr;
+  resip::Uri destinationAddr;
+  resip::Data authRealm;
+  resip::Data authUser;
+  resip::Data authPassword;
+  resip::Data srcIp;
+  resip::Data contextId;
+  resip::Data accountId;
+  resip::Data baseIp;
+  resip::Data controlId;
+
+  //int callState;
+
+  B2BCallState callState;
+
+  BasicClearingReason basicClearingReason;
+  FullClearingReason fullClearingReason;
+  int rejectOtherCode;
+
+  // Call time information
+  time_t startTime;
+  time_t connectTime;
+  time_t finishTime;
+
+  // CallHandle from CallController
+  CallHandle *callHandle;
+  std::list<CallRoute *>::iterator callRoute;
+  resip::Data appRef1;
+  resip::Data appRef2;
+ 
+  // If we are waiting for something, this is the timeout
+  time_t timeout;
+
+  MyAppDialog *aLegAppDialog;
+  MyAppDialog *bLegAppDialog;
+  MyAppDialogSet *bLegAppDialogSet;
+  //resip::SdpContents *aLegSdp;		// most recent offer from A leg
+  //resip::SdpContents *bLegSdp;		// most recent offer from B leg
+  bool earlyAnswerSent;
+  MediaManager *mediaManager;
+  // resip::SharedPtr<resip::UserProfile> outboundUserProfile;
+
+  int failureStatusCode;
+  resip::Data *failureReason;
+
+  // Returns true if successful, false if new state is not
+  // permitted
+  bool setCallState(B2BCallState newCallState);
+  bool isCallStatePermitted(B2BCallState newCallState);
+  const resip::Data& getCallStateName(B2BCallState s);
+
+  void setALegSdp(const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress);
+  void setBLegSdp(const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress);
+
+  void doNewCall();
+  void doCallerCancel();
+  void doAuthorizationPending();
+  void doAuthorizationSuccess();
+  void doAuthorizationFail();
+  void doMediaProxySuccess();
+  void doMediaProxyFail();
+  void doReadyToDial();
+  void doDialFailed();
+  void doDialRejected();
+  void doSelectAlternateRoute();
+  void doDialAborted();
+  //void doDialReceived100();
+  void doDialReceived180();
+  //void doCallDial183();
+  void doDialReceivedEarlyAnswer();
+  void doDialEarlyMediaProxySuccess();
+  void doDialEarlyMediaProxyFail();
+  void doCallAccepted();
+  void doCallAcceptedMediaProxySuccess();
+  void doCallAcceptedMediaProxyFail();
+  void doCallActive();
+  void doHangup();
+  void doCallStop();
+  void doCallStopMediaProxySuccess();
+  void doCallStopMediaProxyFail();
+  void doCallStopFinal();
+
+  // sets the clearing reason codes if necessary
+  void setClearingReason(FullClearingReason reason, int code);
+  void setClearingReasonMediaFail();
+
+  void writeCDR();
+
+public:
+
+  // More basic then B2BCallState, used for reporting
+  typedef enum CallStatus {
+    PreDial,			// the call hasn't started dialing
+    Dialing,			// the call is dialing
+    Connected,			// the call has connected
+    Finishing,			// the call has been hung up
+    Unknown			// unknown
+  };
+
+  void checkProgress(time_t now, bool stopping);
+  bool isComplete();
+
+  CallStatus getStatus();
+
+  //static void setDum(resip::DialogUsageManager *dum);
+  //static void setCallController(CallController *callController);
+
+  // B2BCall(MyAppDialog *aLegDialog);
+  B2BCall(CDRHandler& cdrHandler, resip::DialogUsageManager& dum, AuthorizationManager& authorizationManager, MyAppDialog *aLegDialog, const resip::NameAddr& sourceAddr, const resip::Uri& destinationAddr, const resip::Data& authRealm, const resip::Data& authUser, const resip::Data& authPassword, const resip::Data& srcIp, const resip::Data& contextId, const resip::Data& accountId, const resip::Data& baseIp, const resip::Data& controlId);
+  virtual ~B2BCall();
+
+  void setBLegAppDialog(MyAppDialog *myAppDialog);
+
+  // called every time we go through the main program loop
+  //static void checkCalls();
+
+  // For InviteSessionHandler
+  //void onTrying();
+  void onRinging();
+  //void onSessionProgress();
+  void onEarlyMedia(const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress);
+  void onCancel();
+  void onFailure(MyAppDialog *myAppDialog);
+  void onRejected(int statusCode, const resip::Data& reason);
+  void onOffer(MyAppDialog *myAppDialog, const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress);
+  void onAnswer(MyAppDialog *myAppDialog, const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress);
+  void onMediaTimeout();
+  void onHangup(MyAppDialog *myAppDialog);
+
+  // For B2BCallManager
+  void onStopping();
+
+  void releaseAppDialog(MyAppDialog *myAppDialog);
+  void releaseAppDialogSet(MyAppDialogSet *myAppDialogSet);
+
+  friend class MyDialogSetHandler;
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/B2BCallManager.cxx b/b2bua/B2BCallManager.cxx
new file mode 100644
index 0000000..c66db5d
--- /dev/null
+++ b/b2bua/B2BCallManager.cxx
@@ -0,0 +1,135 @@
+
+
+#include <syslog.h>
+
+#include "B2BCallManager.hxx"
+#include "Logging.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+B2BCallManager::B2BCallManager(resip::DialogUsageManager& dum, AuthorizationManager *authorizationManager, CDRHandler& cdrHandler) : dum(dum), authorizationManager(authorizationManager), cdrHandler(cdrHandler) {
+  stopping = false;
+  mustStopCalls = false;
+}
+
+B2BCallManager::~B2BCallManager() {
+}
+
+void B2BCallManager::setAuthorizationManager(AuthorizationManager *authorizationManager) {
+  this->authorizationManager = authorizationManager;
+}
+
+TaskManager::TaskResult B2BCallManager::doTaskProcessing() {
+  time_t now;
+
+  if(mustStopCalls) {
+    B2BUA_LOG_NOTICE("notifying calls to stop");
+    list<B2BCall *>::iterator call = calls.begin();
+    while(call != calls.end()) {
+      (*call)->onStopping();
+      call++;
+    }
+    mustStopCalls = false;
+  }
+
+  time(&now);
+  list<B2BCall *>::iterator i = calls.begin();
+  while(i != calls.end()) {
+    (*i)->checkProgress(now, stopping);
+    if((*i)->isComplete()) {
+      B2BCall *call = *i;
+      i++;
+      calls.remove(call);
+      delete call;
+    } else
+      i++;
+  }
+  if(stopping && calls.begin() == calls.end()) {
+    B2BUA_LOG_NOTICE("no (more) calls in progress");
+    return TaskManager::TaskComplete;
+  }
+  return TaskManager::TaskNotComplete;
+}
+
+void B2BCallManager::stop() {
+  stopping = true;
+  mustStopCalls = true;
+}
+
+bool B2BCallManager::isStopping() {
+  return stopping;
+}
+
+void B2BCallManager::onNewCall(MyAppDialog *aLegDialog, const resip::NameAddr& sourceAddr, const resip::Uri& destinationAddr, const resip::Data& authRealm, const resip::Data& authUser, const resip::Data& authPassword, const resip::Data& srcIp, const resip::Data& contextId, const resip::Data& accountId, const resip::Data& baseIp, const resip::Data& controlId) {
+
+  B2BCall *call = new B2BCall(cdrHandler, dum, *authorizationManager, aLegDialog, sourceAddr, destinationAddr, authRealm, authUser, authPassword, srcIp, contextId, accountId, baseIp, controlId);
+
+  calls.push_back(call);
+
+}
+
+void B2BCallManager::logStats() {
+  int preDial = 0, dialing = 0, connected = 0, finishing = 0, unknown = 0;
+  list<B2BCall *>::iterator call = calls.begin();
+  while(call != calls.end()) {
+    switch((*call)->getStatus()) {
+    case B2BCall::PreDial:
+      preDial++;
+      break;
+    case B2BCall::Dialing:
+      dialing++;
+      break;
+    case B2BCall::Connected:
+      connected++;
+      break;
+    case B2BCall::Finishing:
+      finishing++;
+      break;
+    default:
+      unknown++;
+      break;
+    }
+    call++;
+  }
+  B2BUA_LOG_NOTICE("call info: preDial = %d, dialing = %d, connected = %d, finishing = %d, unknown = %d, total = %d", preDial, dialing, connected, finishing, unknown, (preDial + dialing + connected + finishing + unknown));
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/B2BCallManager.hxx b/b2bua/B2BCallManager.hxx
new file mode 100644
index 0000000..b9f7cf7
--- /dev/null
+++ b/b2bua/B2BCallManager.hxx
@@ -0,0 +1,94 @@
+
+#ifndef __B2BCallManager_h
+#define __B2BCallManager_h
+
+#include <fstream>
+#include <list>
+
+
+#include "resip/dum/DialogUsageManager.hxx"
+
+#include "AuthorizationManager.hxx"
+#include "B2BCall.hxx"
+#include "CDRHandler.hxx"
+#include "TaskManager.hxx"
+
+namespace b2bua
+{
+
+class B2BCallManager : public TaskManager::RecurringTask {
+
+protected:
+  resip::DialogUsageManager& dum;
+  AuthorizationManager *authorizationManager;
+
+  std::list<B2BCall *> calls;
+
+  bool stopping;
+  bool mustStopCalls;
+
+  CDRHandler& cdrHandler;
+
+public:
+  B2BCallManager(resip::DialogUsageManager& dum, AuthorizationManager *authorizationManager, CDRHandler& cdrHandler);
+  virtual ~B2BCallManager();
+
+  void setAuthorizationManager(AuthorizationManager *authorizationManager);
+
+  TaskManager::TaskResult doTaskProcessing();
+
+  /**
+   * Stop accepting new calls 
+   * Shutdown existing calls
+   * Blocks until all existing calls stopped
+   */
+  void stop();
+  bool isStopping();
+
+  void onNewCall(MyAppDialog *aLegDialog, const resip::NameAddr& sourceAddr, const resip::Uri& destinationAddr, const resip::Data& authRealm, const resip::Data& authUser, const resip::Data& authPassword, const resip::Data& srcIp, const resip::Data& contextId, const resip::Data& accountId, const resip::Data& baseIp, const resip::Data& controlId);
+
+  void logStats();
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/B2BUA.cxx b/b2bua/B2BUA.cxx
new file mode 100644
index 0000000..0988b29
--- /dev/null
+++ b/b2bua/B2BUA.cxx
@@ -0,0 +1,111 @@
+
+
+#include "resip/stack/SipMessage.hxx"
+#include "resip/dum/ClientAuthManager.hxx"
+#include "resip/dum/DialogUsageManager.hxx"
+#include "resip/dum/MasterProfile.hxx"
+#include "resip/dum/ServerAuthManager.hxx"
+
+#include "B2BUA.hxx"
+#include "DefaultAuthorizationManager.hxx"
+#include "DialogUsageManagerRecurringTask.hxx"
+#include "Logging.hxx"
+#include "MyAppDialog.hxx"
+#include "MyDialogSetHandler.hxx"
+#include "MyInviteSessionHandler.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+B2BUA::B2BUA(AuthorizationManager *authorizationManager, CDRHandler& cdrHandler) {
+
+  if(authorizationManager == NULL) {
+    authorizationManager = new DefaultAuthorizationManager();
+  }
+
+  taskManager = new TaskManager();
+
+  sipStack = new SipStack();
+  dialogUsageManager = new DialogUsageManager(*sipStack);
+  uasMasterProfile = SharedPtr<MasterProfile>(new MasterProfile);
+  dialogUsageManager->setMasterProfile(uasMasterProfile);
+  auto_ptr<AppDialogSetFactory> myAppDialogSetFactory(new MyAppDialogSetFactory);
+  dialogUsageManager->setAppDialogSetFactory(myAppDialogSetFactory);
+
+  // Set up authentication when we act as UAC
+  auto_ptr<ClientAuthManager> clientAuth(new ClientAuthManager);
+  dialogUsageManager->setClientAuthManager(clientAuth);
+
+  dialogUsageManager->setDialogSetHandler(new MyDialogSetHandler());
+
+  DialogUsageManagerRecurringTask *dialogUsageManagerTask = new DialogUsageManagerRecurringTask(*sipStack, *dialogUsageManager);
+  taskManager->addRecurringTask(dialogUsageManagerTask);
+  callManager = new B2BCallManager(*dialogUsageManager, authorizationManager, cdrHandler);
+  taskManager->addRecurringTask(callManager);
+
+  MyInviteSessionHandler *uas = new MyInviteSessionHandler(*dialogUsageManager, *callManager);
+  dialogUsageManager->setInviteSessionHandler(uas);
+
+}
+
+B2BUA::~B2BUA() {
+}
+
+void B2BUA::setAuthorizationManager(AuthorizationManager *authorizationManager) {
+  this->authorizationManager = authorizationManager;
+  callManager->setAuthorizationManager(authorizationManager);
+}
+
+void B2BUA::run() {
+  taskManager->start(); 
+}
+
+void B2BUA::logStats() {
+  callManager->logStats();
+}
+
+void B2BUA::stop() {
+  //B2BUA_LOG_CRIT("B2BUA::stop not implemented!");
+  //assert(0);
+  B2BUA_LOG_NOTICE("B2BUA beginning shutdown process");
+  taskManager->stop();
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/B2BUA.hxx b/b2bua/B2BUA.hxx
new file mode 100644
index 0000000..18bb02a
--- /dev/null
+++ b/b2bua/B2BUA.hxx
@@ -0,0 +1,102 @@
+
+#ifndef __B2BUA_h
+#define __B2BUA_h
+
+#include "resip/stack/SipStack.hxx"
+#include "resip/dum/DialogUsageManager.hxx"
+
+#include "B2BCallManager.hxx"
+#include "CDRHandler.hxx"
+#include "DefaultAuthorizationManager.hxx"
+#include "TaskManager.hxx"
+
+namespace b2bua
+{
+
+/**
+ * Provides the framework for a B2BUA and implements the core activities
+ * 
+ * Derived classes might extend the way some activities are performed, and
+ * must define ways to initialise the managers required by the application
+ */
+class B2BUA {
+
+protected:
+
+  TaskManager *taskManager;
+
+  B2BCallManager *callManager;
+
+  AuthorizationManager *authorizationManager;
+//  AuthorizationManager *authorizationManager;
+//  AccountingManager *accountingManager;
+  
+//  std::list<B2BUACall *> calls;
+
+//  MediaManager *mediaManager;
+  
+//  resip::ServerAuthManager *serverAuthManager;
+//  resip::InviteSessionHandler *inviteSessionHandler;
+  resip::SharedPtr<resip::MasterProfile> uasMasterProfile;
+  resip::DialogUsageManager *dialogUsageManager; 
+  resip::SipStack *sipStack;
+
+  B2BUA(AuthorizationManager *authorizationManager, CDRHandler& cdrHandler);
+  virtual ~B2BUA();
+  void setAuthorizationManager(AuthorizationManager *authorizationManager);
+
+public:
+  // Run the B2BUA
+  // only returns when B2BUA stops
+  virtual void run();
+
+  // Send some stats about the system to syslog
+  virtual void logStats();
+
+  // Indicate to the B2BUA that it should shutdown cleanly
+  // (stop all calls, wait for all managers to stop)
+  virtual void stop();
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/CDRHandler.hxx b/b2bua/CDRHandler.hxx
new file mode 100644
index 0000000..a151404
--- /dev/null
+++ b/b2bua/CDRHandler.hxx
@@ -0,0 +1,81 @@
+
+#ifndef __CDRHandler_h
+#define __CDRHandler_h
+
+#include <fstream>
+#include <iostream>
+#include <time.h>
+
+namespace b2bua
+{
+
+class CDRHandler {
+
+public:
+
+
+  virtual ~CDRHandler() {};
+
+  virtual void handleRecord(const std::string& record) = 0;
+
+};
+
+class DailyCDRHandler : public CDRHandler {
+
+protected:
+  std::string mBasename;
+  int last_write;
+  std::ofstream cdrStream;
+
+  int day_number(struct tm* tm);
+  void updateTime();
+  void initFile(struct tm* tm);
+
+public:
+  DailyCDRHandler(const char* basename);
+  ~DailyCDRHandler();
+  void handleRecord(const std::string& record);
+  
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/CallHandle.cxx b/b2bua/CallHandle.cxx
new file mode 100644
index 0000000..ec49cb1
--- /dev/null
+++ b/b2bua/CallHandle.cxx
@@ -0,0 +1,48 @@
+
+#include "CallHandle.hxx"
+
+using namespace b2bua;
+
+CallRoute::~CallRoute() {
+}
+
+CallHandle::~CallHandle() {
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/CallHandle.hxx b/b2bua/CallHandle.hxx
new file mode 100644
index 0000000..d14031e
--- /dev/null
+++ b/b2bua/CallHandle.hxx
@@ -0,0 +1,101 @@
+
+#ifndef __CallHandle_h
+#define __CallHandle_h
+
+#include <iostream>
+#include <list>
+
+#include "resip/stack/NameAddr.hxx"
+#include "resip/stack/Uri.hxx"
+#include "rutil/Data.hxx"
+#include "rutil/SharedPtr.hxx"
+
+namespace b2bua
+{
+
+#define CC_PERMITTED 0				// Call is permitted	
+#define CC_AUTH_REQUIRED 1			// Auth is required
+#define CC_PAYMENT_REQUIRED 2			// Payment is required
+#define CC_IP_DENIED 3				// IP is blocked/unrecognised
+#define CC_ERROR 4				// Server error 
+#define CC_INVALID 5				// Request is invalid
+#define CC_PENDING 6				// Waiting for server
+#define CC_DESTINATION_INCOMPLETE 7		// Destination number too short
+#define CC_DESTINATION_INVALID 8		// Destination invalid
+#define CC_TIMEOUT 9				// Timeout waiting for server
+#define CC_USER_UNKNOWN 10			// User unknown
+#define CC_REALM_UNKNOWN 11			// Realm unknown
+#define CC_REQUEST_DENIED 12			// Request denied for 
+						// administrative reason
+
+class CallRoute {
+public:
+  virtual ~CallRoute();
+  virtual const resip::Data& getAppRef1() = 0;
+  virtual const resip::Data& getAppRef2() = 0;
+  virtual const resip::Data& getAuthRealm() = 0;
+  virtual const resip::Data& getAuthUser() = 0;
+  virtual const resip::Data& getAuthPass() = 0;
+  virtual const resip::NameAddr& getSourceAddr() = 0;
+  virtual const resip::NameAddr& getDestinationAddr() = 0;
+  virtual const resip::Uri& getOutboundProxy() = 0;
+  virtual const bool isSrvQuery() = 0;
+};
+
+class CallHandle {
+public:
+  virtual ~CallHandle();
+  virtual int getAuthResult() = 0; 
+  virtual const resip::Data& getRealm() = 0;	// Realm for client auth,
+						// if we require further auth
+  virtual time_t getHangupTime() = 0;		// The time to hangup,
+						// 0 for no limit
+  virtual bool mustHangup() = 0;
+  virtual void connect(time_t *connectTime) = 0; // The call connected
+  virtual void fail(time_t *finishTime) = 0;	// The attempt failed, or
+						// the caller gave up
+  virtual void finish(time_t *finishTime) = 0;	// The call hungup
+  virtual std::list<CallRoute *>& getRoutes() = 0;
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/DailyCDRHandler.cxx b/b2bua/DailyCDRHandler.cxx
new file mode 100644
index 0000000..f0ffaf9
--- /dev/null
+++ b/b2bua/DailyCDRHandler.cxx
@@ -0,0 +1,93 @@
+
+#include "CDRHandler.hxx"
+#include "Logging.hxx"
+
+using namespace b2bua;
+
+DailyCDRHandler::DailyCDRHandler(const char* basename) : 
+  mBasename(basename),
+  last_write(0) {
+  
+}
+
+DailyCDRHandler::~DailyCDRHandler() {
+  if(cdrStream.is_open())
+    cdrStream.close();
+}
+
+void DailyCDRHandler::handleRecord(const std::string& record) {
+
+  // First check the time
+  updateTime();
+
+  // Now write to file
+  cdrStream << record << std::endl;
+  cdrStream.flush();
+}
+
+int DailyCDRHandler::day_number(struct tm* tm) {
+  return (tm->tm_year + 1900) * 10000 + ((tm->tm_mon + 1) * 100) + tm->tm_mday;
+}
+
+void DailyCDRHandler::updateTime() {
+  time_t now;
+  time(&now);
+  struct tm* tm = gmtime(&now);
+  int x = day_number(tm);
+  if(x > last_write) {
+    last_write = x;
+    initFile(tm);
+  }
+}
+
+void DailyCDRHandler::initFile(struct tm* tm) {
+  if(cdrStream.is_open()) {
+    cdrStream.close();
+  }
+  char buf[200];
+  sprintf(buf, "%s-%04d-%02d-%02d.csv", mBasename.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
+  cdrStream.open(buf, std::ios::out | std::ios::app);
+  if(!cdrStream.is_open()) {
+    B2BUA_LOG_ERR("Failed to open CDR file");
+    throw;
+  }
+}
+
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/DefaultAuthorizationManager.cxx b/b2bua/DefaultAuthorizationManager.cxx
new file mode 100644
index 0000000..b0ba6b0
--- /dev/null
+++ b/b2bua/DefaultAuthorizationManager.cxx
@@ -0,0 +1,60 @@
+
+
+
+#include "DefaultAuthorizationManager.hxx"
+#include "Logging.hxx"
+
+using namespace b2bua;
+
+DefaultAuthorizationManager::DefaultAuthorizationManager() {
+}
+
+
+void DefaultAuthorizationManager::getAuthorization() {
+  B2BUA_LOG_CRIT("DefaultAuthorizationManager::getAuthorization not implemented");
+  assert(0);
+}
+
+CallHandle *DefaultAuthorizationManager::authorizeCall(const resip::NameAddr& sourceAddr, const resip::Uri& destinationAddr, const resip::Data& authRealm, const resip::Data& authUser, const resip::Data& authPass, const resip::Data& srcIp, const resip::Data& contextId, const resip::Data& accountId, const resip::Data& baseIp, const resip::Data& controlId, time_t startTime) {
+  B2BUA_LOG_CRIT("DefaultAuthorizationManager::authorizeCall not implemented");
+  assert(0);
+  return NULL;
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/DefaultAuthorizationManager.hxx b/b2bua/DefaultAuthorizationManager.hxx
new file mode 100644
index 0000000..9f8f657
--- /dev/null
+++ b/b2bua/DefaultAuthorizationManager.hxx
@@ -0,0 +1,60 @@
+
+#ifndef __DefaultAuthorizationManager_h
+#define __DefaultAuthorizationManager_h
+
+
+#include "AuthorizationManager.hxx"
+#include "CallHandle.hxx"
+
+namespace b2bua
+{
+
+class DefaultAuthorizationManager : public AuthorizationManager {
+
+public:
+  DefaultAuthorizationManager();
+  void getAuthorization();
+  CallHandle *authorizeCall(const resip::NameAddr& sourceAddr, const resip::Uri& destinationAddr, const resip::Data& authRealm, const resip::Data& authUser, const resip::Data& authPass, const resip::Data& srcIp, const resip::Data& contextId, const resip::Data& accountId, const resip::Data& baseIp, const resip::Data& controlId, time_t startTime);
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/DialogUsageManagerRecurringTask.cxx b/b2bua/DialogUsageManagerRecurringTask.cxx
new file mode 100644
index 0000000..4068e17
--- /dev/null
+++ b/b2bua/DialogUsageManagerRecurringTask.cxx
@@ -0,0 +1,91 @@
+
+
+#include "resip/dum/DialogUsageManager.hxx"
+
+#include "DialogUsageManagerRecurringTask.hxx"
+#include "Logging.hxx"
+#include "TaskManager.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+DialogUsageManagerRecurringTask::DialogUsageManagerRecurringTask(resip::SipStack& sipStack, resip::DialogUsageManager& dum) : sipStack(sipStack), dum(dum) {
+  stopping = false;
+}
+
+TaskManager::TaskResult DialogUsageManagerRecurringTask::doTaskProcessing() {
+  FdSet fdset;
+  sipStack.buildFdSet(fdset);
+  // FIXME - allow time for other tasks
+  int err = fdset.selectMilliSeconds(resipMin((int)sipStack.getTimeTillNextProcessMS(), 50));
+  if(err == -1) {
+    if(errno != EINTR) {
+      B2BUA_LOG_ERR("fdset.select returned error code %d", err);
+      assert(0);  // FIXME
+    }
+  }
+  // Process all SIP stack activity
+  sipStack.process(fdset);
+  // Process all DUM activity
+  //try {
+    while(dum.process()); 
+  //} catch(...) {
+  //  B2BUA_LOG_ERR("Exception in dum.process(), continuing anyway");
+  //}
+
+  // FIXME If sipStack and dum are finished, then we should return TaskDone
+  if(!stopping)
+    return TaskManager::TaskNotComplete;
+
+  time_t t;
+  time(&t);
+  if(t > stopTime)
+    return TaskManager::TaskIndefinite;
+  else
+    return TaskManager::TaskNotComplete;
+}
+
+void DialogUsageManagerRecurringTask::stop() {
+  stopping = true;
+  time(&stopTime);
+  stopTime += STOP_TIMEOUT;
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/DialogUsageManagerRecurringTask.hxx b/b2bua/DialogUsageManagerRecurringTask.hxx
new file mode 100644
index 0000000..821d175
--- /dev/null
+++ b/b2bua/DialogUsageManagerRecurringTask.hxx
@@ -0,0 +1,72 @@
+
+#ifndef __DialogUsageManagerRecurringTask_h
+#define __DialogUsageManagerRecurringTask_h
+
+#include "resip/stack/SipStack.hxx"
+#include "resip/dum/DialogUsageManager.hxx"
+
+#include "TaskManager.hxx"
+
+namespace b2bua
+{
+
+#define STOP_TIMEOUT 3		// how many seconds to wait before shutdown
+
+class DialogUsageManagerRecurringTask : public TaskManager::RecurringTask {
+
+protected:
+  resip::SipStack& sipStack;
+  resip::DialogUsageManager& dum;
+  bool stopping;
+  time_t stopTime;
+
+public:
+  DialogUsageManagerRecurringTask(resip::SipStack& sipStack, resip::DialogUsageManager& dum);
+  TaskManager::TaskResult doTaskProcessing();
+
+  // let's the task know the application would like to stop soon
+  void stop();
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/DummyRegistrationPersistenceManager.cxx b/b2bua/DummyRegistrationPersistenceManager.cxx
new file mode 100644
index 0000000..bf54561
--- /dev/null
+++ b/b2bua/DummyRegistrationPersistenceManager.cxx
@@ -0,0 +1,75 @@
+
+
+#include "DummyRegistrationPersistenceManager.hxx"
+
+using namespace b2bua;
+
+void DummyRegistrationPersistenceManager::addAor(const resip::Uri& aor, const resip::ContactList contacts = resip::ContactList()) {
+}
+
+void DummyRegistrationPersistenceManager::removeAor(const resip::Uri& aor) {
+}
+
+bool DummyRegistrationPersistenceManager::aorIsRegistered(const resip::Uri& aor) {
+  return false;
+}
+
+void DummyRegistrationPersistenceManager::lockRecord(const resip::Uri& aor) {
+}
+
+void DummyRegistrationPersistenceManager::unlockRecord(const resip::Uri& aor) {
+}
+
+resip::RegistrationPersistenceManager::UriList DummyRegistrationPersistenceManager::getAors() {
+  return resip::RegistrationPersistenceManager::UriList();
+}
+
+resip::RegistrationPersistenceManager::update_status_t DummyRegistrationPersistenceManager::updateContact(const resip::Uri& aor, const resip::Uri& contact, time_t expires, float q) {
+  return CONTACT_CREATED;
+}
+
+void DummyRegistrationPersistenceManager::removeContact(const resip::Uri& aor, const resip::Uri& contact) {
+}
+
+resip::ContactList DummyRegistrationPersistenceManager::getContacts(const resip::Uri& aor) {
+  return resip::ContactList();
+}
+
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/DummyRegistrationPersistenceManager.hxx b/b2bua/DummyRegistrationPersistenceManager.hxx
new file mode 100644
index 0000000..1e9caa7
--- /dev/null
+++ b/b2bua/DummyRegistrationPersistenceManager.hxx
@@ -0,0 +1,67 @@
+
+#ifndef __DummyRegistrationPersistenceManager_h
+#define __DummyRegistrationPersistenceManager_h
+
+#include "resip/dum/ContactInstanceRecord.hxx"
+#include "resip/dum/RegistrationPersistenceManager.hxx"
+
+namespace b2bua
+{
+
+class DummyRegistrationPersistenceManager : public resip::RegistrationPersistenceManager {
+public:
+
+  void addAor(const resip::Uri& aor, const resip::ContactList contacts);
+  void removeAor(const resip::Uri& aor);
+  bool aorIsRegistered(const resip::Uri& aor);
+  void lockRecord(const resip::Uri& aor);
+  void unlockRecord(const resip::Uri& aor);
+  UriList getAors();
+  update_status_t updateContact(const resip::Uri& aor, const resip::Uri& contact, time_t expires, float q = -1);
+  void removeContact(const resip::Uri& aor, const resip::Uri& contact);
+  resip::ContactList getContacts(const resip::Uri& aor);
+
+  
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/DummyServerRegistrationHandler.cxx b/b2bua/DummyServerRegistrationHandler.cxx
new file mode 100644
index 0000000..eabe5d7
--- /dev/null
+++ b/b2bua/DummyServerRegistrationHandler.cxx
@@ -0,0 +1,34 @@
+
+
+#include "resip/stack/SipMessage.hxx"
+
+#include "resip/dum/ServerRegistration.hxx"
+
+#include "DummyServerRegistrationHandler.hxx"
+#include "Logging.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+void DummyServerRegistrationHandler::onRefresh(ServerRegistrationHandle sr, const SipMessage& reg) {
+  sr->accept(200);
+}
+
+void DummyServerRegistrationHandler::onRemove(ServerRegistrationHandle sr, const SipMessage& reg) {
+  sr->accept(200);
+}
+
+void DummyServerRegistrationHandler::onRemoveAll(ServerRegistrationHandle sr, const SipMessage& reg) {
+  sr->accept(200);
+}
+
+void DummyServerRegistrationHandler::onAdd(ServerRegistrationHandle sr, const SipMessage& reg) {
+  B2BUA_LOG_INFO("client trying to register, username=%s", reg.header(h_From).uri().user().c_str());
+  sr->accept(200);
+}
+
+void DummyServerRegistrationHandler::onQuery(ServerRegistrationHandle sr, const SipMessage& reg) {
+  sr->accept(200);
+}
+
diff --git a/b2bua/DummyServerRegistrationHandler.hxx b/b2bua/DummyServerRegistrationHandler.hxx
new file mode 100644
index 0000000..511db9e
--- /dev/null
+++ b/b2bua/DummyServerRegistrationHandler.hxx
@@ -0,0 +1,62 @@
+
+#ifndef __DummyServerRegistrationHandler_h
+#define __DummyServerRegistrationHandler_h
+
+#include "resip/dum/RegistrationHandler.hxx"
+
+namespace b2bua
+{
+
+class DummyServerRegistrationHandler : public resip::ServerRegistrationHandler {
+
+public:
+//  virtual ~ServerRegistrationHandler();
+  void onRefresh(resip::ServerRegistrationHandle, const resip::SipMessage& reg);
+  void onRemove(resip::ServerRegistrationHandle, const resip::SipMessage& reg);
+  void onRemoveAll(resip::ServerRegistrationHandle, const resip::SipMessage& reg);
+  void onAdd(resip::ServerRegistrationHandle, const resip::SipMessage& reg);
+  void onQuery(resip::ServerRegistrationHandle, const resip::SipMessage& reg);
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/Logging.hxx b/b2bua/Logging.hxx
new file mode 100644
index 0000000..f0b91aa
--- /dev/null
+++ b/b2bua/Logging.hxx
@@ -0,0 +1,71 @@
+
+/*
+
+  Logging.h provides definitions for logging.
+
+  Possible implementations of these definitions are:
+  - no logging - empty definitions for production use
+  - syslog - pass all messages to syslog
+  - file or stream - log all messages to a file or stream
+  - resip - log all messages to the underlying resiprocate logging method
+  - Log4C - pass all logging to Log4c
+*/
+
+#ifndef __Logging_h
+#define __Logging_h
+
+
+// syslog implementation 
+
+#include <syslog.h>
+
+#define B2BUA_LOG_INIT(n) openlog(n, LOG_ODELAY | LOG_PID, LOG_LOCAL0)
+
+#define B2BUA_LOG_DEBUG(fmt, ...) syslog(LOG_DEBUG, "b2bua:%s:%d: " #fmt, __FILE__, __LINE__, ## __VA_ARGS__)
+#define B2BUA_LOG_INFO(fmt, ...) syslog(LOG_INFO, "b2bua:%s:%d: " #fmt, __FILE__, __LINE__, ## __VA_ARGS__)
+#define B2BUA_LOG_NOTICE(fmt, ...) syslog(LOG_NOTICE, "b2bua:%s:%d: " #fmt, __FILE__, __LINE__, ## __VA_ARGS__)
+#define B2BUA_LOG_WARNING(fmt, ...) syslog(LOG_WARNING, "b2bua:%s:%d: " #fmt, __FILE__, __LINE__, ## __VA_ARGS__)
+#define B2BUA_LOG_ERR(fmt, ...) syslog(LOG_ERR, "b2bua:%s:%d: " #fmt, __FILE__, __LINE__, ## __VA_ARGS__)
+#define B2BUA_LOG_CRIT(fmt, ...) syslog(LOG_CRIT, "b2bua:%s:%d: " #fmt, __FILE__, __LINE__, ## __VA_ARGS__)
+
+
+#endif
+
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/Makefile.am b/b2bua/Makefile.am
new file mode 100644
index 0000000..582c719
--- /dev/null
+++ b/b2bua/Makefile.am
@@ -0,0 +1,92 @@
+# $Id$
+
+EXTRA_DIST = README.txt
+
+SUBDIRS = . 
+
+#AM_CXXFLAGS = -DUSE_ARES
+
+lib_LTLIBRARIES = libb2bua.la
+
+libb2bua_la_LDFLAGS = @LIBTOOL_VERSION_RELEASE@ -export-dynamic
+libb2bua_la_LIBADD = ../resip/dum/libdum.la
+libb2bua_la_LIBADD += ../resip/stack/libresip.la ../rutil/librutil.la
+libb2bua_la_LIBADD += @LIBSSL_LIBADD@ -lpthread
+
+libb2bua_la_SOURCES = \
+        AuthenticationManager.cxx \
+        B2BCall.cxx \
+        B2BCallManager.cxx \
+        B2BUA.cxx \
+        CallHandle.cxx \
+        DailyCDRHandler.cxx \
+        DefaultAuthorizationManager.cxx \
+        DialogUsageManagerRecurringTask.cxx \
+        DummyRegistrationPersistenceManager.cxx \
+        DummyServerRegistrationHandler.cxx \
+        MediaManager.cxx \
+        MediaProxy.cxx \
+        MyAppDialog.cxx \
+        MyDialogSetHandler.cxx \
+        MyInviteSessionHandler.cxx \
+        RtpProxyRecurringTask.cxx \
+        RtpProxyUtil.cxx \
+        TaskManager.cxx
+
+b2buaincludedir = $(includedir)/b2bua
+nobase_b2buainclude_HEADERS = \
+        AccountingManager.hxx \
+        AuthenticationManager.hxx \
+        AuthorizationManager.hxx \
+        B2BCall.hxx \
+        B2BCallManager.hxx \
+        B2BUA.hxx \
+        CallHandle.hxx \
+        CDRHandler.hxx \
+        DefaultAuthorizationManager.hxx \
+        DialogUsageManagerRecurringTask.hxx \
+        DummyRegistrationPersistenceManager.hxx \
+        DummyServerRegistrationHandler.hxx \
+        Logging.hxx \
+        MediaManager.hxx \
+        MediaProxy.hxx \
+        MyAppDialog.hxx \
+        MyDialogSetHandler.hxx \
+        MyInviteSessionHandler.hxx \
+        RtpProxyRecurringTask.hxx \
+        RtpProxyUtil.hxx \
+        TaskManager.hxx
+
+##############################################################################
+# 
+# Copyright (c) 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+# 
+##############################################################################
diff --git a/b2bua/Makefile.in b/b2bua/Makefile.in
new file mode 100644
index 0000000..50ad7d5
--- /dev/null
+++ b/b2bua/Makefile.in
@@ -0,0 +1,826 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ at SET_MAKE@
+
+# $Id$
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = b2bua
+DIST_COMMON = $(nobase_b2buainclude_HEADERS) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_have_epoll.m4 \
+	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(b2buaincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libb2bua_la_DEPENDENCIES = ../resip/dum/libdum.la \
+	../resip/stack/libresip.la ../rutil/librutil.la
+am_libb2bua_la_OBJECTS = AuthenticationManager.lo B2BCall.lo \
+	B2BCallManager.lo B2BUA.lo CallHandle.lo DailyCDRHandler.lo \
+	DefaultAuthorizationManager.lo \
+	DialogUsageManagerRecurringTask.lo \
+	DummyRegistrationPersistenceManager.lo \
+	DummyServerRegistrationHandler.lo MediaManager.lo \
+	MediaProxy.lo MyAppDialog.lo MyDialogSetHandler.lo \
+	MyInviteSessionHandler.lo RtpProxyRecurringTask.lo \
+	RtpProxyUtil.lo TaskManager.lo
+libb2bua_la_OBJECTS = $(am_libb2bua_la_OBJECTS)
+libb2bua_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libb2bua_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libb2bua_la_SOURCES)
+DIST_SOURCES = $(libb2bua_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+HEADERS = $(nobase_b2buainclude_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+	$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+	distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBARES_LIBADD = @LIBARES_LIBADD@
+LIBGEOIP_LIBADD = @LIBGEOIP_LIBADD@
+LIBMYSQL_LIBADD = @LIBMYSQL_LIBADD@
+LIBOBJS = @LIBOBJS@
+LIBPOPT_LIBADD = @LIBPOPT_LIBADD@
+LIBRADIUS_LIBADD = @LIBRADIUS_LIBADD@
+LIBS = @LIBS@
+LIBSSL_LIBADD = @LIBSSL_LIBADD@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_VERSION_RELEASE = @LIBTOOL_VERSION_RELEASE@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SO_RELEASE = @SO_RELEASE@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = README.txt
+SUBDIRS = . 
+
+#AM_CXXFLAGS = -DUSE_ARES
+lib_LTLIBRARIES = libb2bua.la
+libb2bua_la_LDFLAGS = @LIBTOOL_VERSION_RELEASE@ -export-dynamic
+libb2bua_la_LIBADD = ../resip/dum/libdum.la ../resip/stack/libresip.la \
+	../rutil/librutil.la @LIBSSL_LIBADD@ -lpthread
+libb2bua_la_SOURCES = \
+        AuthenticationManager.cxx \
+        B2BCall.cxx \
+        B2BCallManager.cxx \
+        B2BUA.cxx \
+        CallHandle.cxx \
+        DailyCDRHandler.cxx \
+        DefaultAuthorizationManager.cxx \
+        DialogUsageManagerRecurringTask.cxx \
+        DummyRegistrationPersistenceManager.cxx \
+        DummyServerRegistrationHandler.cxx \
+        MediaManager.cxx \
+        MediaProxy.cxx \
+        MyAppDialog.cxx \
+        MyDialogSetHandler.cxx \
+        MyInviteSessionHandler.cxx \
+        RtpProxyRecurringTask.cxx \
+        RtpProxyUtil.cxx \
+        TaskManager.cxx
+
+b2buaincludedir = $(includedir)/b2bua
+nobase_b2buainclude_HEADERS = \
+        AccountingManager.hxx \
+        AuthenticationManager.hxx \
+        AuthorizationManager.hxx \
+        B2BCall.hxx \
+        B2BCallManager.hxx \
+        B2BUA.hxx \
+        CallHandle.hxx \
+        CDRHandler.hxx \
+        DefaultAuthorizationManager.hxx \
+        DialogUsageManagerRecurringTask.hxx \
+        DummyRegistrationPersistenceManager.hxx \
+        DummyServerRegistrationHandler.hxx \
+        Logging.hxx \
+        MediaManager.hxx \
+        MediaProxy.hxx \
+        MyAppDialog.hxx \
+        MyDialogSetHandler.hxx \
+        MyInviteSessionHandler.hxx \
+        RtpProxyRecurringTask.hxx \
+        RtpProxyUtil.hxx \
+        TaskManager.hxx
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .cxx .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu b2bua/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu b2bua/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+	}
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libb2bua.la: $(libb2bua_la_OBJECTS) $(libb2bua_la_DEPENDENCIES) 
+	$(libb2bua_la_LINK) -rpath $(libdir) $(libb2bua_la_OBJECTS) $(libb2bua_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/AuthenticationManager.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/B2BCall.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/B2BCallManager.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/B2BUA.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/CallHandle.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DailyCDRHandler.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DefaultAuthorizationManager.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DialogUsageManagerRecurringTask.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DummyRegistrationPersistenceManager.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/DummyServerRegistrationHandler.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/MediaManager.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/MediaProxy.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/MyAppDialog.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/MyDialogSetHandler.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/MyInviteSessionHandler.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/RtpProxyRecurringTask.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/RtpProxyUtil.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/TaskManager.Plo at am__quote@
+
+.cxx.o:
+ at am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cxx.obj:
+ at am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cxx.lo:
+ at am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-nobase_b2buaincludeHEADERS: $(nobase_b2buainclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(b2buaincludedir)" || $(MKDIR_P) "$(DESTDIR)$(b2buaincludedir)"
+	@list='$(nobase_b2buainclude_HEADERS)'; test -n "$(b2buaincludedir)" || list=; \
+	$(am__nobase_list) | while read dir files; do \
+	  xfiles=; for file in $$files; do \
+	    if test -f "$$file"; then xfiles="$$xfiles $$file"; \
+	    else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
+	  test -z "$$xfiles" || { \
+	    test "x$$dir" = x. || { \
+	      echo "$(MKDIR_P) '$(DESTDIR)$(b2buaincludedir)/$$dir'"; \
+	      $(MKDIR_P) "$(DESTDIR)$(b2buaincludedir)/$$dir"; }; \
+	    echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(b2buaincludedir)/$$dir'"; \
+	    $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(b2buaincludedir)/$$dir" || exit $$?; }; \
+	done
+
+uninstall-nobase_b2buaincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(nobase_b2buainclude_HEADERS)'; test -n "$(b2buaincludedir)" || list=; \
+	$(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(b2buaincludedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(b2buaincludedir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(b2buaincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-nobase_b2buaincludeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES \
+	uninstall-nobase_b2buaincludeHEADERS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+	install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags ctags-recursive \
+	distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-libLTLIBRARIES install-man \
+	install-nobase_b2buaincludeHEADERS install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags tags-recursive uninstall uninstall-am \
+	uninstall-libLTLIBRARIES uninstall-nobase_b2buaincludeHEADERS
+
+
+##############################################################################
+# 
+# Copyright (c) 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+# 
+##############################################################################
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/b2bua/MediaManager.cxx b/b2bua/MediaManager.cxx
new file mode 100644
index 0000000..633e6cf
--- /dev/null
+++ b/b2bua/MediaManager.cxx
@@ -0,0 +1,112 @@
+
+#include "rutil/Data.hxx"
+
+#include "MediaManager.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+Data MediaManager::proxyAddress;
+
+void MediaManager::setProxyAddress(const Data& proxyAddress) {
+  MediaManager::proxyAddress = proxyAddress;
+};
+
+MediaManager::MediaManager(B2BCall& b2BCall) : b2BCall(b2BCall) {
+  aLegProxy = NULL;
+  bLegProxy = NULL;
+  rtpProxyUtil = NULL;
+};
+
+MediaManager::MediaManager(B2BCall& b2BCall, const Data& callId, const Data& fromTag, const Data& toTag) : b2BCall(b2BCall), callId(callId), fromTag(fromTag), toTag(toTag) {
+  aLegProxy = NULL;
+  bLegProxy = NULL;
+  rtpProxyUtil = NULL;
+};
+
+MediaManager::~MediaManager() {
+  if(aLegProxy != NULL)
+    delete aLegProxy;
+  if(bLegProxy != NULL)
+    delete bLegProxy;
+  if(rtpProxyUtil != NULL)
+    delete rtpProxyUtil;
+};
+
+void MediaManager::setFromTag(const Data& fromTag) {
+  this->fromTag = fromTag;
+};
+
+void MediaManager::setToTag(const Data& toTag) {
+  this->toTag = toTag;
+};
+
+int MediaManager::setALegSdp(const SdpContents& sdp, const in_addr_t& msgSourceAddress) {
+  aLegSdp = sdp;
+  if(aLegProxy == NULL)
+    aLegProxy = new MediaProxy(*this);
+  return aLegProxy->updateSdp(aLegSdp, msgSourceAddress);
+};
+
+SdpContents& MediaManager::getALegSdp() {
+  if(aLegProxy == NULL) {
+    throw new exception;
+  }
+  return aLegProxy->getSdp();
+};
+
+int MediaManager::setBLegSdp(const SdpContents& sdp, const in_addr_t& msgSourceAddress) {
+  bLegSdp = sdp;
+  if(bLegProxy == NULL)
+    bLegProxy = new MediaProxy(*this);
+  return bLegProxy->updateSdp(bLegSdp, msgSourceAddress);
+};
+
+SdpContents& MediaManager::getBLegSdp() {
+  if(bLegProxy == NULL)
+    throw new exception;
+  return bLegProxy->getSdp();
+};
+
+void MediaManager::onMediaTimeout() {
+  b2BCall.onMediaTimeout();
+};
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MediaManager.hxx b/b2bua/MediaManager.hxx
new file mode 100644
index 0000000..01b99e3
--- /dev/null
+++ b/b2bua/MediaManager.hxx
@@ -0,0 +1,130 @@
+
+#ifndef __MediaManager_h
+#define __MediaManager_h
+
+#include "resip/stack/SdpContents.hxx"
+#include "rutil/Data.hxx"
+
+namespace b2bua
+{
+
+class MediaManager;
+
+}
+
+#include "B2BCall.hxx"
+#include "MediaProxy.hxx"
+#include "RtpProxyUtil.hxx"
+
+namespace b2bua
+{
+
+/*
+  Each B2BCall requires a MediaManager to handle the SDP and media 
+  (typically RTP/AVP).
+
+  MediaManager is responsible for:
+  - validating the content of the SDP (IP4 only, UDP only, etc)
+  - creating and destroying pairs of MediaProxy instances as needed
+  - rewriting the SDP connection addresses and port numbers
+  - hiding information about the remote party (e.g. phone, web, fax)
+*/
+
+// FIXME - use enum types
+#define MM_SDP_OK 0			// The SDP was acceptable
+#define MM_SDP_BAD 1			// The SDP was not acceptable
+
+class B2BCall;
+
+class MediaManager : public RtpProxyUtil::TimeoutListener {
+
+private:
+
+  static resip::Data proxyAddress;
+
+  B2BCall& b2BCall;
+
+  resip::Data callId;				// from A Leg
+  resip::Data fromTag;				// `from' tag for A leg party
+  resip::Data toTag;				// `to' tag for B leg party
+  resip::SdpContents aLegSdp;
+  resip::SdpContents newALegSdp;
+  resip::SdpContents bLegSdp;
+  resip::SdpContents newBLegSdp;
+ 
+  RtpProxyUtil *rtpProxyUtil;			// Access to rtpproxy
+
+  MediaProxy *aLegProxy;			// Proxies on behalf of A leg
+  MediaProxy *bLegProxy;			// Proxies on behalf of B leg
+
+public:
+  friend class MediaProxy;
+
+  // Set the proxyAddress
+  static void setProxyAddress(const resip::Data& proxyAddress);
+
+  // Instantiate a MediaManager
+  MediaManager(B2BCall& b2BCall);
+  MediaManager(B2BCall& b2BCall, const resip::Data& callId, const resip::Data& fromTag, const resip::Data& toTag);
+  virtual ~MediaManager();
+
+  // Set the From tag
+  void setFromTag(const resip::Data& fromTag);
+  // Set the To tag
+  void setToTag(const resip::Data& toTag);
+
+  // inspect and save an offer (A leg)
+  int setALegSdp(const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress);
+  // generate an offer (to send to B leg)
+  resip::SdpContents& getALegSdp();
+  
+  // inspect and save an answer (B leg)
+  int setBLegSdp(const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress);
+  // generate an answer (to send to A leg)
+  resip::SdpContents& getBLegSdp();
+
+  void onMediaTimeout();
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MediaProxy.cxx b/b2bua/MediaProxy.cxx
new file mode 100644
index 0000000..0d46a06
--- /dev/null
+++ b/b2bua/MediaProxy.cxx
@@ -0,0 +1,218 @@
+
+#include <exception>
+#include <iostream>
+
+#include "Logging.hxx"
+#include "MediaProxy.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+bool MediaProxy::mNatHelper = false;
+
+void MediaProxy::setNatHelper(bool natHelper) {
+  mNatHelper = natHelper;
+}
+
+MediaProxy::MediaProxy(MediaManager& mediaManager) : mediaManager(mediaManager) {
+  originalSdp = NULL;
+  newSdp = NULL;
+}
+
+MediaProxy::~MediaProxy() {
+  if(originalSdp != NULL)
+    delete originalSdp;
+  if(newSdp != NULL) 
+    delete newSdp;
+}
+
+int MediaProxy::updateSdp(const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress) {
+  bool callerAsymmetric = true;
+  bool calleeAsymmetric = true;
+  if(originalSdp != NULL)
+    delete originalSdp;
+  originalSdp = (SdpContents *)sdp.clone();
+  if(newSdp != NULL)
+    delete newSdp;
+  newSdp = (SdpContents *)sdp.clone();
+
+  // Process the Origin
+  if(originalSdp->session().origin().getAddressType() != SdpContents::IP4) {
+    // FIXME - implement IPv6
+    B2BUA_LOG_WARNING("processing SDP origin, only IP4 is supported"); 
+    return MM_SDP_BAD;
+  }
+  // FIXME - set username also
+  newSdp->session().origin().setAddress(MediaManager::proxyAddress);
+
+  // Process the default connection
+  if(originalSdp->session().connection().getAddressType() != SdpContents::IP4) {
+    // FIXME - implement IPv6
+    B2BUA_LOG_WARNING("processing SDP connection, only IP4 is supported");
+    return MM_SDP_BAD;
+  }
+  newSdp->session().connection().setAddress(MediaManager::proxyAddress);
+
+  newSdp->session().clearMedium();
+  list<SdpContents::Session::Medium>::iterator i = originalSdp->session().media().begin();
+  while(i != originalSdp->session().media().end()) {
+    if(allowProtocol((*i).protocol())) {
+      if(newSdp->session().media().size() > 0) {
+	// FIXME
+        B2BUA_LOG_WARNING("only one medium definition supported");
+	return MM_SDP_BAD;
+      }
+      struct MediaProxy::EndPoint endpoint;
+      endpoint.address = originalSdp->session().connection().getAddress();
+      // Should we adjust the address because of NAT?
+      if(mNatHelper) {
+        in_addr_t sdpConnectionAddr = inet_addr(originalSdp->session().connection().getAddress().c_str());
+        // Is the endpoint a private address?
+        bool addressIsPrivate = isAddressPrivate(sdpConnectionAddr);
+        if(addressIsPrivate)
+          B2BUA_LOG_WARNING("IP address in SDP is private: %s", originalSdp->session().connection().getAddress().c_str());
+
+        // Does the endpoint address not match the msg source address?
+        bool matchesMsgSource = false;
+        if(sdpConnectionAddr == msgSourceAddress)
+          matchesMsgSource = true;
+
+        if(addressIsPrivate && !matchesMsgSource) {
+          // use the msg source address instead of the address in the SDP
+          struct in_addr sa;
+          sa.s_addr = msgSourceAddress;
+          endpoint.address = Data(inet_ntoa(sa));
+          callerAsymmetric = false;
+          B2BUA_LOG_WARNING("rewriting NAT address, was %s, using %s", originalSdp->session().connection().getAddress().c_str(), endpoint.address.c_str());
+        } 
+      }
+      // Check for a connection spec
+      if((*i).getMediumConnections().size() > 1) {
+        // FIXME - connection for each medium
+        B2BUA_LOG_WARNING("multiple medium specific connections not supported");
+	return MM_SDP_BAD;
+      }
+      if((*i).getMediumConnections().size() == 1) {
+        const SdpContents::Session::Connection& mc = (*i).getMediumConnections().front();
+	// FIXME - check address type, etc, or implement operator==
+        if(!(mc.getAddress() == originalSdp->session().connection().getAddress())) {
+          B2BUA_LOG_WARNING("medium specific connection doesn't match global connection");
+	  return MM_SDP_BAD;
+        }
+        
+      }
+      // Get the old port, insert new port
+      endpoint.originalPort = (*i).port();
+      SdpContents::Session::Medium m(*i);
+      // FIXME - only needed until more detailed handling of medium specific
+      // connections is implemented:
+      //m.getMediumConnections().clear();
+      m.setConnection(newSdp->session().connection());
+      if(mediaManager.aLegProxy == this) {
+        // this must be A leg
+        if(mediaManager.rtpProxyUtil == NULL) {
+	  mediaManager.rtpProxyUtil = new RtpProxyUtil();
+          mediaManager.rtpProxyUtil->setTimeoutListener(&mediaManager);
+        }
+ 	endpoint.proxyPort = mediaManager.rtpProxyUtil->setupCaller(mediaManager.callId.c_str(), endpoint.address.c_str(), endpoint.originalPort, mediaManager.fromTag.c_str(), callerAsymmetric);
+        if(endpoint.proxyPort == 0)
+          throw new exception;
+      } else {
+	// this must be B leg
+	endpoint.proxyPort = mediaManager.rtpProxyUtil->setupCallee(endpoint.address.c_str(), endpoint.originalPort, mediaManager.toTag.c_str(), calleeAsymmetric);
+        if(endpoint.proxyPort == 0)
+          throw new exception;
+      }
+      m.setPort(endpoint.proxyPort);
+      //newMedia.push_back(m);
+      newSdp->session().addMedium(m);
+      endpoints.push_back(endpoint);
+    } else {
+      B2BUA_LOG_WARNING("media protocol %s not recognised, removed from SDP", (*i).protocol().c_str());
+    }
+    i++;
+  }
+  if(endpoints.size() == 0) {
+    B2BUA_LOG_WARNING("no acceptable media protocol found, try RTP/AVP or UDP");
+    return MM_SDP_BAD;
+  }
+
+  return MM_SDP_OK;
+
+}
+
+resip::SdpContents& MediaProxy::getSdp() {
+  return *newSdp;
+}
+
+bool MediaProxy::allowProtocol(const resip::Data& protocol) {
+  if(protocol == Data("RTP/AVP") || protocol == Data("UDP") || protocol == Data("udp") || protocol == Data("udptl")) {
+    return true;
+  }
+  return false;
+}
+
+// 10.0.0.0/8 - 10.255.255.255
+// 172.16.0.0/12 - 172.31.255.255
+// 192.168.0.0/16 - 192.168.255.255
+bool MediaProxy::isAddressPrivate(const in_addr_t& subj_addr) {
+  //in_addr_t subj_addr = inet_addr(address.c_str());
+  if(subj_addr == INADDR_NONE) {
+    B2BUA_LOG_WARNING("subject address is invalid: INADDR_NONE");
+    return false;
+  }
+ 
+  uint32_t subj_addr1 = ntohl(subj_addr);
+  uint32_t priv1 = (10 << 24);
+  uint32_t nm1 = 0xff000000;
+  uint32_t priv2 = (172 << 24) + (16 << 16);
+  uint32_t nm2 = 0xfff00000;
+  uint32_t priv3 = (192 << 24) + (168 << 16);
+  uint32_t nm3 = 0xffff0000;
+
+  if(((subj_addr1 & nm1) == priv1) ||
+     ((subj_addr1 & nm2) == priv2) ||
+     ((subj_addr1 & nm3) == priv3))
+    return true;
+ 
+  return false;
+}
+ 
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MediaProxy.hxx b/b2bua/MediaProxy.hxx
new file mode 100644
index 0000000..577f058
--- /dev/null
+++ b/b2bua/MediaProxy.hxx
@@ -0,0 +1,111 @@
+
+#ifndef __MediaProxy_h
+#define __MediaProxy_h
+
+#include "resip/stack/SdpContents.hxx"
+
+namespace b2bua
+{
+
+class MediaProxy;
+
+}
+
+#include "MediaManager.hxx"
+
+namespace b2bua
+{
+
+/*
+  A generic MediaProxy is based on the SDP from a single endpoint.
+
+  Two MediaProxys must work together to provide a symmetric RTP service
+  that will get through NAT.  The two MediaProxy instances are
+  synchronised by the MediaManager.
+
+  For an implementation based on rtpproxy, we must also use SIP callID,
+  from-tag and to-tag, as these are the values rtpproxy expects to use
+  for uniquely identifying each call.
+
+  Alternatively, we could use our own unique identifier system.
+*/
+
+class MediaProxy {
+
+protected:
+  struct EndPoint {
+    resip::Data address;		// the address we should forward to
+    unsigned int originalPort;		// the port on the dest address
+    unsigned int proxyPort;		// the port we listen with
+  };
+
+  static bool mNatHelper;
+
+private:
+  MediaManager& mediaManager;		// the MediaManager who controls us
+  std::list<EndPoint> endpoints;	// the endpoints for each media
+					// offer in the SDP
+  resip::SdpContents *originalSdp;	// the original SDP
+  resip::SdpContents *newSdp;		// the modified SDP
+
+public:
+  static void setNatHelper(bool natHelper);
+  MediaProxy(MediaManager& mediaManager);
+  virtual ~MediaProxy();
+  int updateSdp(const resip::SdpContents& sdp, const in_addr_t& msgSourceAddress);		// update the SDP,
+							// as a result of a
+							// new offer
+  resip::SdpContents& getSdp();				// get the SDP
+							// that should be sent
+							// to the other party
+							// we correspond with
+  bool allowProtocol(const resip::Data& protocol);	// discover if protocol
+							// is permitted/handled
+							// by this proxy
+							// implementation
+
+  bool isAddressPrivate(const in_addr_t& subj_addr);
+
+};
+
+}
+
+#endif 
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MyAppDialog.cxx b/b2bua/MyAppDialog.cxx
new file mode 100644
index 0000000..92403d3
--- /dev/null
+++ b/b2bua/MyAppDialog.cxx
@@ -0,0 +1,100 @@
+
+#include "MyAppDialog.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+MyAppDialog::MyAppDialog(HandleManager& ham) : AppDialog(ham) {
+  setB2BCall(NULL);
+}
+
+MyAppDialog::MyAppDialog(HandleManager& ham, B2BCall *b2BCall) : AppDialog(ham) {
+  setB2BCall(b2BCall);
+  // FIXME - is this the B Leg?
+  if(b2BCall != NULL)
+    b2BCall->setBLegAppDialog(this);
+}
+
+MyAppDialog::~MyAppDialog() {
+  if(b2BCall != NULL)
+    b2BCall->releaseAppDialog(this);
+}
+
+B2BCall *MyAppDialog::getB2BCall() {
+  return b2BCall;
+}
+
+void MyAppDialog::setB2BCall(B2BCall *b2BCall) {
+  this->b2BCall = b2BCall;
+}
+
+MyAppDialogSet::MyAppDialogSet(DialogUsageManager& dum) : AppDialogSet(dum) {
+  this->b2BCall = NULL;
+  //userProfile = NULL;
+}
+
+MyAppDialogSet::MyAppDialogSet(DialogUsageManager& dum, B2BCall *b2BCall, SharedPtr<UserProfile>& userProfile) : AppDialogSet(dum) {
+  this->b2BCall = b2BCall;
+  this->userProfile = userProfile;
+}
+
+MyAppDialogSet::~MyAppDialogSet() {
+  if(b2BCall != NULL)
+    b2BCall->releaseAppDialogSet(this);
+}
+
+AppDialog* MyAppDialogSet::createAppDialog(const SipMessage& msg) {
+  return new MyAppDialog(mDum, b2BCall);
+}
+
+/* SharedPtr<UserProfile> MyAppDialogSet::getUserProfile() {
+  return userProfile;
+} */
+
+SharedPtr<UserProfile> MyAppDialogSet::selectUASUserProfile(const SipMessage& msg) {
+  //return getUserProfile();
+  return mDum.getMasterUserProfile();
+}
+
+AppDialogSet* MyAppDialogSetFactory::createAppDialogSet(DialogUsageManager& dum, const SipMessage& msg) {
+  return new MyAppDialogSet(dum);
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MyAppDialog.hxx b/b2bua/MyAppDialog.hxx
new file mode 100644
index 0000000..bc1ad98
--- /dev/null
+++ b/b2bua/MyAppDialog.hxx
@@ -0,0 +1,107 @@
+
+#ifndef __MyAppDialog_h
+#define __MyAppDialog_h
+
+#include "resip/stack/SipMessage.hxx"
+
+#include "resip/dum/AppDialog.hxx"
+#include "resip/dum/AppDialogSet.hxx"
+#include "resip/dum/AppDialogSetFactory.hxx"
+#include "resip/dum/DialogUsageManager.hxx"
+
+namespace b2bua
+{
+
+class MyAppDialog;
+class MyAppDialogSet;
+class MyDialogSetHandler;
+
+}
+
+#include "B2BCall.hxx"
+
+namespace b2bua
+{
+
+class MyAppDialog : public resip::AppDialog {
+
+protected:
+  B2BCall *b2BCall;
+  
+public:
+
+  MyAppDialog(resip::HandleManager& ham);
+  MyAppDialog(resip::HandleManager& ham, B2BCall *b2BCall);
+  virtual ~MyAppDialog();
+  B2BCall *getB2BCall();
+  void setB2BCall(B2BCall *b2BCall); 
+
+};
+
+class MyAppDialogSet : public resip::AppDialogSet {
+
+protected:
+  B2BCall *b2BCall;
+  resip::SharedPtr<resip::UserProfile> userProfile;
+
+public:
+  MyAppDialogSet(resip::DialogUsageManager& dum);
+  MyAppDialogSet(resip::DialogUsageManager& dum, B2BCall *b2BCall, resip::SharedPtr<resip::UserProfile>& userProfile);
+  virtual ~MyAppDialogSet();
+  virtual resip::AppDialog* createAppDialog(const resip::SipMessage& msg);
+  // virtual resip::SharedPtr<resip::UserProfile> getUserProfile();
+  virtual resip::SharedPtr<resip::UserProfile> selectUASUserProfile(const resip::SipMessage& msg);
+  void setB2BCall(B2BCall *b2BCall)
+    { this->b2BCall = b2BCall; };
+
+  friend class MyDialogSetHandler;
+};
+
+class MyAppDialogSetFactory : public resip::AppDialogSetFactory {
+
+public:
+  virtual resip::AppDialogSet* createAppDialogSet(resip::DialogUsageManager& dum, const resip::SipMessage& msg);
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MyDialogSetHandler.cxx b/b2bua/MyDialogSetHandler.cxx
new file mode 100644
index 0000000..1ee005e
--- /dev/null
+++ b/b2bua/MyDialogSetHandler.cxx
@@ -0,0 +1,64 @@
+
+
+#include "B2BCall.hxx"
+#include "Logging.hxx"
+#include "MyAppDialog.hxx"
+#include "MyDialogSetHandler.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+MyDialogSetHandler::~MyDialogSetHandler() {
+}
+
+void MyDialogSetHandler::onTrying(resip::AppDialogSetHandle ah, const resip::SipMessage& msg) {
+}
+
+void MyDialogSetHandler::onNonDialogCreatingProvisional(resip::AppDialogSetHandle ah, const resip::SipMessage& msg) {
+  B2BUA_LOG_DEBUG("received 180 without contact header");
+  MyAppDialogSet *ads = dynamic_cast<MyAppDialogSet *>(ah.get());
+  if(ads) {
+    B2BUA_LOG_DEBUG("dialog found");
+    if(ads->b2BCall)
+      ads->b2BCall->doDialReceived180();
+  }
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MyDialogSetHandler.hxx b/b2bua/MyDialogSetHandler.hxx
new file mode 100644
index 0000000..b692f7d
--- /dev/null
+++ b/b2bua/MyDialogSetHandler.hxx
@@ -0,0 +1,61 @@
+
+#ifndef __MyDialogSetHandler_h
+#define __MyDialogSetHandler_h
+
+#include "resip/dum/DialogSetHandler.hxx"
+
+namespace b2bua
+{
+
+class MyDialogSetHandler : public resip::DialogSetHandler {
+
+public:
+  ~MyDialogSetHandler();
+
+  virtual void onTrying(resip::AppDialogSetHandle ah, const resip::SipMessage& msg);
+
+  virtual void onNonDialogCreatingProvisional(resip::AppDialogSetHandle ah, const resip::SipMessage& msg);
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MyInviteSessionHandler.cxx b/b2bua/MyInviteSessionHandler.cxx
new file mode 100644
index 0000000..816f451
--- /dev/null
+++ b/b2bua/MyInviteSessionHandler.cxx
@@ -0,0 +1,334 @@
+
+
+
+#include "resip/stack/ExtensionHeader.hxx"
+#include "resip/stack/SipMessage.hxx"
+#include "resip/stack/Tuple.hxx"
+#include "rutil/Data.hxx"
+
+#include "B2BCall.hxx"
+#include "B2BCallManager.hxx"
+#include "Logging.hxx"
+#include "MyInviteSessionHandler.hxx"
+
+using namespace b2bua;
+using namespace resip;
+using namespace std;
+
+MyInviteSessionHandler::MyInviteSessionHandler(DialogUsageManager& dum, B2BCallManager& callManager) : dum(dum), callManager(callManager) {
+}
+
+void MyInviteSessionHandler::onSuccess(ClientRegistrationHandle h, const SipMessage& response) {
+}
+
+void MyInviteSessionHandler::onFailure(ClientRegistrationHandle, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onMessage(resip::Handle<resip::InviteSession>, const resip::SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onMessageSuccess(resip::Handle<resip::InviteSession>, const resip::SipMessage&) {
+}
+
+void MyInviteSessionHandler::onMessageFailure(resip::Handle<resip::InviteSession>, const resip::SipMessage&) {
+}
+
+void MyInviteSessionHandler::onFailure(ClientInviteSessionHandle cis, const SipMessage& msg) {
+  B2BUA_LOG_DEBUG("onFailure: %d, %s", msg.header(h_StatusLine).statusCode(), msg.header(h_StatusLine).reason().c_str());
+  B2BCall *call = getB2BCall(cis.get());
+  if(call == NULL) {
+    B2BUA_LOG_WARNING("onFailure: unrecognised dialog");
+    return;
+  }
+  call->onRejected(msg.header(h_StatusLine).statusCode(), msg.header(h_StatusLine).reason());
+}
+
+void MyInviteSessionHandler::onForkDestroyed(ClientInviteSessionHandle) {
+}
+
+void MyInviteSessionHandler::onInfoSuccess(InviteSessionHandle, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onInfoFailure(InviteSessionHandle, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onProvisional(ClientInviteSessionHandle cis, const SipMessage& msg) {
+  B2BCall *call = getB2BCall(cis.get());
+  if(call == NULL) {
+    B2BUA_LOG_WARNING("onProvisional: unrecognised dialog");
+    return;
+  }
+  int code = msg.header(h_StatusLine).statusCode();
+  switch(code) {
+  case 100:
+    //call->onTrying();
+    break;
+  case 180:
+    call->onRinging();
+    break;
+  case 183:
+    //call->onSessionProgress();
+    break;
+  default:
+    B2BUA_LOG_DEBUG("onProvisional: unknown provisional code (%d)", code);
+  } 
+}
+
+void MyInviteSessionHandler::onConnected(ClientInviteSessionHandle, const SipMessage& msg) {
+  // FIXME - start charging here instead of waiting for onAnswer
+}
+
+void MyInviteSessionHandler::onStaleCallTimeout(ClientInviteSessionHandle) {
+}
+
+void MyInviteSessionHandler::onConnected(InviteSessionHandle, const SipMessage& msg) {
+  // FIXME
+}
+
+void MyInviteSessionHandler::onRedirected(ClientInviteSessionHandle, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onAnswer(InviteSessionHandle is, const SipMessage& msg, const SdpContents& sdp) {
+  MyAppDialog *myAppDialog = (MyAppDialog *)is->getAppDialog().get();
+  B2BCall *call = getB2BCall(is.get());
+  if(call == NULL) {
+    B2BUA_LOG_WARNING("onAnswer: unrecognised dialog");
+    return;
+  }
+  Tuple sourceTuple = msg.getSource();
+  in_addr_t msgSourceAddress = sourceTuple.toGenericIPAddress().v4Address.sin_addr.s_addr;
+  call->onAnswer(myAppDialog, sdp, msgSourceAddress);
+}
+
+void MyInviteSessionHandler::onEarlyMedia(ClientInviteSessionHandle cis, const SipMessage& msg, const SdpContents& sdp) {
+  B2BCall *call = getB2BCall(cis.get());
+  if(call == NULL) {
+    B2BUA_LOG_WARNING("onEarlyMedia: unrecognised dialog");
+    return;
+  }
+  Tuple sourceTuple = msg.getSource();
+  in_addr_t msgSourceAddress = sourceTuple.toGenericIPAddress().v4Address.sin_addr.s_addr;
+  call->onEarlyMedia(sdp, msgSourceAddress);
+}
+
+void MyInviteSessionHandler::onOfferRequired(InviteSessionHandle, const SipMessage& msg) {
+  // FIXME
+}
+
+void MyInviteSessionHandler::onOfferRejected(Handle<InviteSession>, const SipMessage *msg) {
+  // FIXME
+  B2BUA_LOG_DEBUG("onOfferRejected: %d, %s", msg->header(h_StatusLine).statusCode(), msg->header(h_StatusLine).reason().c_str());
+}
+
+void MyInviteSessionHandler::onInfo(InviteSessionHandle, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onRefer(InviteSessionHandle, ServerSubscriptionHandle, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onReferAccepted(InviteSessionHandle, ClientSubscriptionHandle, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onReferRejected(InviteSessionHandle, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onReferNoSub(resip::Handle<resip::InviteSession> is, const resip::SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onRemoved(ClientRegistrationHandle) {
+}
+
+int MyInviteSessionHandler::onRequestRetry(ClientRegistrationHandle, int retrySeconds, const SipMessage& response) {
+//  cerr << "onRequestRetry not implemented" << endl;
+  //FIXME
+  B2BUA_LOG_DEBUG("onRequestRetry not implemented");
+  return -1;
+}
+
+// New inbound connection
+// We must create a B2BCall and insert the B2BCall into the linked list
+void MyInviteSessionHandler::onNewSession(ServerInviteSessionHandle sis, InviteSession::OfferAnswerType oat, const SipMessage& msg) {
+  //cerr << "onNewSession sis" << endl;
+
+  // Are we shutting down?  If so, reject the call with SIP code 503
+  if(callManager.isStopping()) {
+    B2BUA_LOG_DEBUG("rejecting inbound call as we are stopping");
+    sis->reject(503);
+    return;
+  }
+
+  // Check the headers
+  if(!msg.exists(h_From)) {
+    B2BUA_LOG_WARNING("inbound connection missing from header, rejecting dialog");
+    sis->reject(603);
+    return;
+  }
+  // FIXME - do above for all headers
+  if(msg.getReceivedTransport() == 0) {
+    // msg not received from the wire
+    // FIXME
+    B2BUA_LOG_WARNING("request not received from the wire");
+    sis->reject(603);
+  }
+  Tuple sourceTuple = msg.getSource();
+  Data sourceIp = Data(inet_ntoa(sourceTuple.toGenericIPAddress().v4Address.sin_addr));
+  Data contextId;
+  Data accountId;
+  Data baseIp;
+  Data controlId;
+  ExtensionHeader xContextId("X-MyB2BUA-Context-ID");
+  if(msg.exists(xContextId)) {
+    const StringCategories& contextIds = msg.header(xContextId);
+    contextId = Data((contextIds.begin())->value());
+  }
+  ExtensionHeader xAccountId("X-MyB2BUA-Account-ID");
+  if(msg.exists(xAccountId)) {
+    const StringCategories& accountIds = msg.header(xAccountId);
+    accountId = Data((accountIds.begin())->value());
+  }
+  ExtensionHeader xBaseIp("X-MyB2BUA-Base-IP");
+  if(msg.exists(xBaseIp)) {
+    const StringCategories& baseIps = msg.header(xBaseIp);
+    baseIp = Data((baseIps.begin())->value());
+  }
+  ExtensionHeader xControlId("X-MyB2BUA-Control-ID");
+  if(msg.exists(xControlId)) {
+    const StringCategories& controlIds = msg.header(xControlId);
+    controlId = Data((controlIds.begin())->value());
+  }
+  // Now inspect the authentication info
+  Data authRealm("");
+  Data authUser("");
+  Data authPassword(""); 
+  if(msg.exists(h_ProxyAuthorizations)) {
+    for(Auths::const_iterator it = msg.header(h_ProxyAuthorizations).begin(); it != msg.header(h_ProxyAuthorizations).end(); it++) {
+      if(dum.isMyDomain(it->param(p_realm))) {
+        authRealm = it->param(p_realm);
+        authUser = it->param(p_username);
+      }
+    }
+  }
+  try {
+    callManager.onNewCall((MyAppDialog *)sis->getAppDialog().get(), msg.header(h_From), msg.header(h_RequestLine).uri(), authRealm, authUser, Data(""), sourceIp, contextId, accountId, baseIp, controlId);
+  } catch (...) {
+    B2BUA_LOG_ERR("failed to instantiate B2BCall");
+    sis->reject(500);   // Indicate temporary error condition
+  }
+}
+
+void MyInviteSessionHandler::onNewSession(ClientInviteSessionHandle cis, InviteSession::OfferAnswerType oat, const SipMessage& msg) {
+}
+
+void MyInviteSessionHandler::onTerminated(InviteSessionHandle is, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg) {
+  B2BUA_LOG_DEBUG("onTerminated, reason = %d", reason);
+  B2BCall *call = getB2BCall(is.get());
+  if(call == NULL) {
+    B2BUA_LOG_WARNING("onTerminated: unrecognised dialog");
+    return;
+  }
+  MyAppDialog *myAppDialog = (MyAppDialog *)is->getAppDialog().get();
+  switch(reason) {
+
+  // received a BYE or CANCEL from peer
+  case RemoteCancel: 
+    B2BUA_LOG_DEBUG("onTerminated: RemoteCancel");
+    call->onCancel();
+    break;
+
+  case RemoteBye: 
+    B2BUA_LOG_DEBUG("onTerminated: RemoteBye");
+    // MyAppDialog *myAppDialog = (MyAppDialog *)is->getAppDialog().get();
+    call->onHangup(myAppDialog);
+    break;
+
+  // ended by the application
+  case LocalBye: 
+    B2BUA_LOG_DEBUG("onTerminated: LocalBye");
+    //call->onFailure(myAppDialog);
+    break;
+
+  case Referred: 
+    B2BUA_LOG_DEBUG("onTerminated: Referred");
+    //call->onFailure(myAppDialog);
+    break;
+
+  // ended due to a failure
+  case Error:
+    B2BUA_LOG_DEBUG("onTerminated: Error");
+    call->onFailure(myAppDialog);
+    break;
+
+  case Timeout:
+    B2BUA_LOG_DEBUG("onTerminated: Timeout");
+    call->onFailure(myAppDialog);
+    break;
+
+  case LocalCancel: // ended by the application via Cancel
+    B2BUA_LOG_DEBUG("onTerminated: LocalCancel"); 
+    // no need to do anything, because we have initiated this cancel
+    break;
+
+  default:
+    B2BUA_LOG_WARNING("onTerminated: unhandled case %d", reason);
+    break;
+  }
+}
+
+void MyInviteSessionHandler::onOffer(InviteSessionHandle is, const SipMessage& msg, const SdpContents& sdp) {
+  B2BCall *call = getB2BCall(is.get());
+  if(call == NULL) {
+    B2BUA_LOG_WARNING("onOffer: unrecognised dialog");
+    return;
+  }
+  B2BUA_LOG_DEBUG("onOffer received");
+  MyAppDialog *myAppDialog = (MyAppDialog *)is->getAppDialog().get();
+  Tuple sourceTuple = msg.getSource();
+  in_addr_t msgSourceAddress = sourceTuple.toGenericIPAddress().v4Address.sin_addr.s_addr;
+  call->onOffer(myAppDialog, sdp, msgSourceAddress);  
+}
+
+/**
+ * Handy utility functions
+ */
+B2BCall *MyInviteSessionHandler::getB2BCall(InviteSession *is) {
+  MyAppDialog *myAppDialog = (MyAppDialog *)is->getAppDialog().get();
+  return (B2BCall *)myAppDialog->getB2BCall();
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/MyInviteSessionHandler.hxx b/b2bua/MyInviteSessionHandler.hxx
new file mode 100644
index 0000000..c1de9e2
--- /dev/null
+++ b/b2bua/MyInviteSessionHandler.hxx
@@ -0,0 +1,97 @@
+
+
+#ifndef __MyInviteSessionHandler_h
+#define __MyInviteSessionHandler_h
+
+#include "resip/stack/SipMessage.hxx"
+#include "resip/dum/ClientInviteSession.hxx"
+#include "resip/dum/InviteSessionHandler.hxx"
+#include "resip/dum/ServerInviteSession.hxx"
+
+namespace b2bua
+{
+
+class MyInviteSessionHandler : public resip::InviteSessionHandler {
+
+protected:
+  resip::DialogUsageManager& dum;
+  B2BCallManager& callManager;
+
+public:
+  MyInviteSessionHandler(resip::DialogUsageManager& dum, B2BCallManager& callManager);
+  virtual void onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
+  virtual void onFailure(resip::ClientRegistrationHandle, const resip::SipMessage& msg);
+  virtual void onMessage(resip::Handle<resip::InviteSession>, const resip::SipMessage& msg);
+  virtual void onMessageSuccess(resip::Handle<resip::InviteSession>, const resip::SipMessage&);
+  virtual void onMessageFailure(resip::Handle<resip::InviteSession>, const resip::SipMessage&);
+  virtual void onFailure(resip::ClientInviteSessionHandle cis, const resip::SipMessage& msg);
+  virtual void onForkDestroyed(resip::ClientInviteSessionHandle);
+  virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
+  virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
+  virtual void onProvisional(resip::ClientInviteSessionHandle cis, const resip::SipMessage& msg);
+  virtual void onConnected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
+  virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg);
+  virtual void onStaleCallTimeout(resip::ClientInviteSessionHandle);
+  virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
+  virtual void onAnswer(resip::InviteSessionHandle is, const resip::SipMessage& msg, const resip::SdpContents& sdp);
+  virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents& sdp);
+  virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg);
+  virtual void onOfferRejected(resip::Handle<resip::InviteSession>, const resip::SipMessage *msg);
+  virtual void onInfo(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::Handle<resip::InviteSession>, const resip::SipMessage&);
+  virtual void onRemoved(resip::ClientRegistrationHandle);
+  virtual int onRequestRetry(resip::ClientRegistrationHandle, int retrySeconds, const resip::SipMessage& response);
+  virtual void onNewSession(resip::ServerInviteSessionHandle sis, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
+  virtual void onNewSession(resip::ClientInviteSessionHandle cis, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
+  virtual void onTerminated(resip::InviteSessionHandle is, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* msg);
+  virtual void onOffer(resip::InviteSessionHandle is, const resip::SipMessage& msg, const resip::SdpContents& sdp);
+
+  // Utility functions
+  B2BCall *getB2BCall(resip::InviteSession *is);
+  
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/README.txt b/b2bua/README.txt
new file mode 100644
index 0000000..c522153
--- /dev/null
+++ b/b2bua/README.txt
@@ -0,0 +1,94 @@
+
+Introduction
+============
+
+This is a reSIProcate based B2BUA library.
+
+The library is libb2bua.so
+
+It is built on top of reSIProcate's dialog usage manager (DUM)
+
+Building
+========
+
+In the main reSIProcate directory:
+
+./configure
+make b2bua
+
+NOTE:  the command `make' or `make all' will NOT build the B2BUA
+  by default.  I have left it out of the default build until
+  it has been tested more extensively by the reSIProcate community.
+
+Background and technical notes
+==============================
+
+The code has been adapted from a previous project.  Consequently,
+the initial import to the reSIProcate repository doesn't fully adhere to
+reSIProcate coding standards.  Nonetheless, it is working code,
+so a decision was taken to commit the code as-is, without
+modification, and then gradually overhaul it in subsequent commits.
+
+Some key points about this code:
+
+- It produces a shared object - to produce an executable, 
+  the B2BUA class must be instantiated and put to work.
+  Such an example will be added shortly.  A typical
+  implementation of a B2BUA must implement the following
+  classes:
+  - b2bua::CallRoute
+  - b2bua::CallHandle
+  - b2bua::AuthorizationManager
+  - b2bua::B2BUA
+
+- It relies on rtpproxy from http://www.rtpproxy.org to relay
+  the media streams.  I have created various patches for
+  rtpproxy 0.2:
+  - rtpproxy sends notification to the B2BUA on media timeout
+  - fix a file descriptor bug
+  - timeout on either direction
+  The rtpproxy patches are being posted on the rtpproxy mailing
+  list shortly.
+
+Daniel Pocock
+daniel at readytechnology.co.uk
+
+
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/RtpProxyRecurringTask.cxx b/b2bua/RtpProxyRecurringTask.cxx
new file mode 100644
index 0000000..9faae5e
--- /dev/null
+++ b/b2bua/RtpProxyRecurringTask.cxx
@@ -0,0 +1,54 @@
+
+#include "RtpProxyRecurringTask.hxx"
+#include "RtpProxyUtil.hxx"
+
+using namespace b2bua;
+
+RtpProxyRecurringTask::RtpProxyRecurringTask() {
+}
+
+TaskManager::TaskResult RtpProxyRecurringTask::doTaskProcessing() {
+  RtpProxyUtil::do_timeouts();
+  return TaskManager::TaskIndefinite;
+}
+
+void RtpProxyRecurringTask::stop() {
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/RtpProxyRecurringTask.hxx b/b2bua/RtpProxyRecurringTask.hxx
new file mode 100644
index 0000000..ab8f5d2
--- /dev/null
+++ b/b2bua/RtpProxyRecurringTask.hxx
@@ -0,0 +1,68 @@
+
+#ifndef __RtpProxyRecurringTask_h
+#define __RtpProxyRecurringTask_h
+
+
+#include "TaskManager.hxx"
+
+namespace b2bua
+{
+
+#define STOP_TIMEOUT 3		// how many seconds to wait before shutdown
+
+class RtpProxyRecurringTask : public TaskManager::RecurringTask {
+
+protected:
+  bool stopping;
+  time_t stopTime;
+
+public:
+  RtpProxyRecurringTask();
+  TaskManager::TaskResult doTaskProcessing();
+
+  // let's the task know the application would like to stop soon
+  void stop();
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/RtpProxyUtil.cxx b/b2bua/RtpProxyUtil.cxx
new file mode 100644
index 0000000..e989a0c
--- /dev/null
+++ b/b2bua/RtpProxyUtil.cxx
@@ -0,0 +1,488 @@
+
+/* Todo:
+    - handle re-INVITE
+    - share a socket?
+    - test socket when app starts
+    - release ports when object destroyed
+*/
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <exception>
+#include <iostream>
+
+#include "Logging.hxx"
+#include "RtpProxyUtil.hxx"
+
+#define STR2IOVEC(sx, ix)       {(ix).iov_base = (sx); (ix).iov_len = strlen((sx));}
+
+#define RTPPROXY_RETRY_COUNT 3
+
+using namespace b2bua;
+using namespace std;
+
+int RtpProxyUtil::umode = 0;
+char *RtpProxyUtil::rtpproxy_sock = (char *)DEFAULT_RTPPROXY_SOCK;
+int RtpProxyUtil::controlfd = 0;
+char *RtpProxyUtil::timeout_sock = (char *)DEFAULT_RTPPROXY_TIMEOUT_SOCK;
+int RtpProxyUtil::timeoutfd = 0;
+int RtpProxyUtil::timeout_clientfd = -1;
+int RtpProxyUtil::rtpproxy_retr = DEFAULT_RTPPROXY_RETR;
+int RtpProxyUtil::rtpproxy_tout = DEFAULT_RTPPROXY_TOUT;
+
+map<int, RtpProxyUtil *> RtpProxyUtil::proxies;
+
+void RtpProxyUtil::setSocket(const char *socket) {
+  if((rtpproxy_sock = (char *)malloc(strlen(socket) + 1)) == NULL) {
+    B2BUA_LOG_ERR("setSocket: malloc failed");
+    throw;
+  }
+  strcpy(rtpproxy_sock, socket);
+}
+
+void RtpProxyUtil::setTimeoutSocket(const char *socket) {
+  if((timeout_sock = (char *)malloc(strlen(socket) + 1)) == NULL) {
+    B2BUA_LOG_ERR("setSocket: malloc failed");
+    throw;
+  }
+  strcpy(timeout_sock, socket);
+}
+
+void RtpProxyUtil::init() {
+  umode = 0;
+//  rtpproxy_sock = DEFAULT_RTPPROXY_SOCK;
+//  timeout_sock = DEFAULT_RTPPROXY_TIMEOUT_SOCK;
+  rtpproxy_retr = DEFAULT_RTPPROXY_RETR;
+  rtpproxy_tout = DEFAULT_RTPPROXY_TOUT;
+
+  int len;
+  struct sockaddr_un local;
+
+  int flags;
+
+  if ((timeoutfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+    B2BUA_LOG_ERR("socket: %m");
+    exit(1); // FIXME
+  }
+
+  local.sun_family = AF_UNIX;
+  strcpy(local.sun_path, timeout_sock);
+  unlink(local.sun_path);
+  len = strlen(local.sun_path) + sizeof(local.sun_family);
+  if (bind(timeoutfd, (struct sockaddr *)&local, len) == -1) {
+    B2BUA_LOG_ERR("bind: %m");
+    exit(1); // FIXME
+  }
+
+  if (listen(timeoutfd, 5) == -1) {
+    B2BUA_LOG_ERR("listen: %m");
+    exit(1); // FIXME
+  } 
+
+  flags = fcntl(timeoutfd, F_GETFL);
+  flags |= O_NONBLOCK;
+  fcntl(timeoutfd, F_SETFL, flags);
+
+  timeout_clientfd = -1;
+
+  B2BUA_LOG_NOTICE("telling rtpproxy to flush calls");
+  // Check the version
+  struct iovec v[2] = {{NULL, 0}, {(char *)"x", 1}};
+  char *cp = sendCommandRetry(RTPPROXY_RETRY_COUNT, v, 2, "");
+  if(cp == NULL)
+    throw new exception;
+}
+
+void RtpProxyUtil::do_timeouts() {
+  // check for new connections with accept
+  // read any data with read
+  socklen_t t;
+  struct sockaddr_un remote;
+  int flags;
+  int n;
+  char buf[100];
+  int p1, p2;
+
+  if(timeout_clientfd == -1) {
+    t = sizeof(remote);
+    if((timeout_clientfd = accept(timeoutfd, (struct sockaddr *)&remote, &t)) == -1) {
+      if(errno == EAGAIN) {
+        // no connections coming in from rtpproxy
+        return;
+      }
+      B2BUA_LOG_ERR("accept: %m");
+      exit(1);
+    }
+    B2BUA_LOG_DEBUG("accepted a new connection from rtpproxy");
+    flags = fcntl(timeout_clientfd, F_GETFL);
+    flags |= O_NONBLOCK;
+    fcntl(timeout_clientfd, F_SETFL, flags);
+  }
+  
+  n = recv(timeout_clientfd, buf, 100, 0);
+  if (n == -1) {
+    if (errno != EAGAIN) {
+      // FIXME
+      B2BUA_LOG_ERR("recv: %m");
+      close(timeout_clientfd);
+      timeout_clientfd = -1;
+    } 
+    return;
+  }
+  if(n== 0) {
+    // n = 0 means that socket closed remotely
+    timeout_clientfd = -1;
+    return;
+  }
+
+  buf[n] = 0;
+  if((n = sscanf(buf, "%d %d\n", &p1, &p2)) != 2) {
+    B2BUA_LOG_WARNING("invalid number of arguments from rtpproxy_timeout client [%s]", buf);
+  } else {
+    B2BUA_LOG_DEBUG("timeout on ports %d %d", p1, p2);
+    if(proxies.count(p1) == 1) {
+      RtpProxyUtil *proxy = proxies.find(p1)->second;
+      proxy->mediaTimeout();
+    }
+  }
+}
+
+
+RtpProxyUtil::RtpProxyUtil() {
+  timeoutListener = NULL;
+  valid = true;
+  mypid = getpid();
+  myseqn = 0;
+  callID = NULL;
+  callerAddr = NULL;
+  callerPort = 0;
+  calleeAddr = NULL;
+  calleePort = 0;
+  fromTag = NULL;
+  toTag = NULL;
+
+  callerProxyPort = 0;
+  calleeProxyPort = 0;
+
+  // Check the version
+  struct iovec v[2] = {{NULL, 0}, {(char *)"V", 1}};
+  char *cp = sendCommandRetry(RTPPROXY_RETRY_COUNT, v, 2, gencookie());
+  if(cp == NULL)
+    throw new exception;
+
+}
+
+RtpProxyUtil::~RtpProxyUtil() {
+
+  if(callerProxyPort != 0)
+    proxies.erase(callerProxyPort);
+  if(calleeProxyPort != 0)
+    proxies.erase(calleeProxyPort);
+
+  struct iovec v[1 + 4 + 3] = {{NULL, 0}, {(char *)"D", 1}, {(char *)" ", 1}, {NULL, 0}, {(char *)" ", 1}, {NULL, 0}, {(char *)" ", 1}, {NULL, 0}};
+  STR2IOVEC(callID, v[3]);
+  STR2IOVEC(fromTag, v[5]);
+  if(toTag != NULL)
+    STR2IOVEC(toTag, v[7]);
+  // ignore return value
+  sendCommandRetry(RTPPROXY_RETRY_COUNT, v, (toTag != NULL) ? 8 : 6, gencookie());
+
+  if(callID != NULL)
+    free(callID);
+  if(callerAddr != NULL)
+    free(callerAddr);
+  if(calleeAddr != NULL)
+    free(calleeAddr);
+  if(fromTag != NULL)
+    free(fromTag);
+  if(toTag != NULL)
+    free(toTag);
+
+}
+
+void RtpProxyUtil::setTimeoutListener(TimeoutListener *timeoutListener) {
+  this->timeoutListener = timeoutListener; 
+}
+
+void RtpProxyUtil::mediaTimeout() {
+  valid = false;
+  if(timeoutListener != NULL)
+    timeoutListener->onMediaTimeout();
+}
+
+unsigned int RtpProxyUtil::setupCaller(const char *callID, const char *callerAddr, int callerPort, const char *fromTag, bool callerAsymmetric) {
+  if(this->callID != NULL)
+    free(this->callID);
+  if((this->callID=(char *)malloc(strlen(callID) + 1))==NULL) {
+    return 0;
+  }
+  if(this->callerAddr != NULL)
+    free(this->callerAddr);
+  if((this->callerAddr=(char *)malloc(strlen(callerAddr) + 1))==NULL) {
+    return 0;
+  }
+  if(this->fromTag != NULL)
+    free(this->fromTag);
+  if((this->fromTag=(char *)malloc(strlen(fromTag) + 1))==NULL) {
+    return 0;
+  }
+  strcpy(this->callID, callID);
+  strcpy(this->callerAddr, callerAddr);
+  this->callerPort = callerPort;
+  strcpy(this->fromTag, fromTag);
+
+  char buf[BUF_SIZE];
+  struct iovec v[1 + 6 + 5] = {{NULL, 0}, {NULL, 0}, {(char *)" ", 1}, {NULL, 0},
+    {(char *)" ", 1}, {NULL, 7}, {(char *)" ", 1}, {NULL, 1}, {(char *)" ", 1}, {NULL, 0},
+    {(char *)" ", 1}, {NULL, 0}};
+  if(callerAsymmetric == true)
+    v[1].iov_base = (char *)"Ua";
+  else
+    v[1].iov_base = (char *)"Us";
+  v[1].iov_len = 2;
+  STR2IOVEC((char *)callID, v[3]);
+  STR2IOVEC((char *)callerAddr, v[5]);
+  sprintf(buf, "%d", callerPort);
+  STR2IOVEC(buf, v[7]);
+  STR2IOVEC((char *)fromTag, v[9]);
+  // STR2IOVEC(toTag, v[11]);
+  char *cp = sendCommandRetry(RTPPROXY_RETRY_COUNT, v, 10, gencookie());
+  if(cp == NULL)
+    throw new exception;
+  callerProxyPort = atoi(cp);
+  proxies[callerProxyPort] = this;
+  return callerProxyPort;
+}
+
+void RtpProxyUtil::ammendCaller(const char *callerAddr, int callerPort) {
+}
+
+unsigned int RtpProxyUtil::setupCallee(const char *calleeAddr, int calleePort, const char *toTag, bool calleeAsymmetric) {
+  if(this->calleeAddr != NULL)
+    free(this->calleeAddr);
+  if((this->calleeAddr=(char *)malloc(strlen(calleeAddr) + 1))==NULL) {
+    return 0;
+  }
+  if(this->toTag != NULL)
+    free(this->toTag);
+  if((this->toTag=(char *)malloc(strlen(toTag) + 1))==NULL) {
+    return 0;
+  }  
+  strcpy(this->calleeAddr, calleeAddr);
+  this->calleePort = calleePort;
+  strcpy(this->toTag, toTag);
+
+  char buf[BUF_SIZE];
+  struct iovec v[1 + 6 + 5] = {{NULL, 0}, {NULL, 0}, {(char *)" ", 1}, {NULL, 0},
+    {(char *)" ", 1}, {NULL, 7}, {(char *)" ", 1}, {NULL, 1}, {(char *)" ", 1},
+{NULL, 0},
+    {(char *)" ", 1}, {NULL, 0}};
+  if(calleeAsymmetric == true)
+    v[1].iov_base = (char *)"La";
+  else 
+    v[1].iov_base = (char *)"Ls";
+  v[1].iov_len = 2;
+  STR2IOVEC(callID, v[3]);
+  STR2IOVEC((char *)calleeAddr, v[5]);
+  sprintf(buf, "%d", calleePort);
+  STR2IOVEC(buf, v[7]);
+  STR2IOVEC(fromTag, v[9]);
+  STR2IOVEC((char *)toTag, v[11]);
+  char *cp = sendCommandRetry(RTPPROXY_RETRY_COUNT, v, 12, gencookie());
+  if(cp == NULL)
+    throw new exception;
+  calleeProxyPort = atoi(cp);
+  proxies[calleeProxyPort] = this;
+  return calleeProxyPort;
+}
+
+void RtpProxyUtil::ammendCallee(const char *calleeAddr, int calleePort) {
+}
+
+unsigned int RtpProxyUtil::getCallerProxyPort() {
+  return callerProxyPort;
+}
+
+unsigned int RtpProxyUtil::getCalleeProxyPort() {
+  return calleeProxyPort;
+}
+
+char *RtpProxyUtil::sendCommandRetry(int retries, struct iovec *v, int vcnt, char *my_cookie) {
+  int c = 0;
+  char *result;
+  while(c++ < retries) {
+    result = sendCommand(v, vcnt, my_cookie);
+    if(result != NULL)
+      return result; 
+  }
+  return NULL;
+}
+
+char *RtpProxyUtil::sendCommand(struct iovec *v, int vcnt, char *my_cookie) {
+
+        struct sockaddr_un addr;
+        int fd, i, len;
+        char *cp;
+        static char buf[256];
+        struct pollfd fds[1];
+
+        len = 0;
+        cp = buf;
+        if (umode == 0) {
+                memset(&addr, 0, sizeof(addr));
+                addr.sun_family = AF_LOCAL;
+                strncpy(addr.sun_path, rtpproxy_sock,
+                    sizeof(addr.sun_path) - 1);
+#ifdef HAVE_SOCKADDR_SA_LEN
+                addr.sun_len = strlen(addr.sun_path);
+#endif
+
+                fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+                if (fd < 0) {
+			B2BUA_LOG_ERR("send_rtpp_command: can't create socket");
+                        return NULL;
+                }
+                if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+                        close(fd);
+			B2BUA_LOG_ERR("ERROR: send_rtpp_command: can't connect to RTP proxy: %s", addr.sun_path);
+			//perror("RtpProxyUtil");
+                        return NULL;
+                }
+
+                do {
+                        len = writev(fd, v + 1, vcnt - 1);
+                } while (len == -1 && errno == EINTR);
+                if (len <= 0) {
+                        close(fd);
+			B2BUA_LOG_ERR("ERROR: send_rtpp_command: can't send command to a RTP proxy");
+                        return NULL;
+                }
+                do {
+                        len = read(fd, buf, sizeof(buf) - 1);
+                } while (len == -1 && errno == EINTR);
+                close(fd);
+                if (len <= 0) {
+			B2BUA_LOG_ERR("ERROR: send_rtpp_command: can't read reply from the RTP proxy, errno = %d", errno);
+                        return NULL;
+                }
+        } else {
+                fds[0].fd = controlfd;
+                fds[0].events = POLLIN;
+                fds[0].revents = 0;
+                /* Drain input buffer */
+                while ((poll(fds, 1, 0) == 1) &&
+                    ((fds[0].revents & POLLIN) != 0)) {
+                        recv(controlfd, buf, sizeof(buf) - 1, 0);
+                        fds[0].revents = 0;
+                }
+                v[0].iov_base = my_cookie;
+                v[0].iov_len = strlen((const char *)v[0].iov_base);
+                for (i = 0; i < rtpproxy_retr; i++) {
+                        do {
+                                len = writev(controlfd, v, vcnt);
+                        } while (len == -1 && (errno == EINTR || errno == ENOBUFS));
+                        if (len <= 0) {
+                                /* LOG(L_ERR, "ERROR: send_rtpp_command: "
+                                    "can't send command to a RTP proxy\n"); */
+				B2BUA_LOG_ERR("ERROR: send_rtpp_command: can't send command to a RTP proxy");
+                                return NULL;
+                        }
+                        while ((poll(fds, 1, rtpproxy_tout * 1000) == 1) &&
+                            (fds[0].revents & POLLIN) != 0) {
+                                do {
+                                        len = recv(controlfd, buf, sizeof(buf) - 1, 0);
+                                } while (len == -1 && errno == EINTR);
+                                if (len <= 0) {
+                                        /* LOG(L_ERR, "ERROR: send_rtpp_command: "
+                                            "can't read reply from a RTP proxy\n"); */
+					B2BUA_LOG_ERR("ERROR: send_rtpp_command:can't read reply from a RTP proxy");
+                                        return NULL;
+                                }
+                                if (len >= (v[0].iov_len - 1) &&
+                                    memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {
+                                        len -= (v[0].iov_len - 1);
+                                        cp += (v[0].iov_len - 1);
+                                        if (len != 0) {
+                                                len--;
+                                                cp++;
+                                        }
+                                        goto out;
+                                }
+                                fds[0].revents = 0;
+                        }
+                }
+                if (i == rtpproxy_retr) {
+                        /* LOG(L_ERR, "ERROR: send_rtpp_command: "
+                            "timeout waiting reply from a RTP proxy\n"); */
+			B2BUA_LOG_ERR("ERROR: send_rtpp_command: timeout waiting reply from a RTP proxy");
+                        return NULL;
+                }
+        }
+
+out:
+        cp[len] = '\0';
+        return cp;  
+
+}
+
+
+char *RtpProxyUtil::gencookie() {
+        static char cook[34];
+
+        sprintf(cook, "%d_%u ", (int)mypid, myseqn);
+        myseqn++;
+        return cook;
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/RtpProxyUtil.hxx b/b2bua/RtpProxyUtil.hxx
new file mode 100644
index 0000000..bf602f7
--- /dev/null
+++ b/b2bua/RtpProxyUtil.hxx
@@ -0,0 +1,137 @@
+
+#ifndef __RtpProxyUtil_h
+#define __RtpProxyUtil_h
+
+#include <map>
+
+namespace b2bua
+{
+
+#define DEFAULT_RTPPROXY_SOCK "/var/run/rtpproxy.sock"
+#define DEFAULT_RTPPROXY_TIMEOUT_SOCK "/var/run/rtpproxy.timeout.sock"
+#define DEFAULT_RTPPROXY_RETR 5
+#define DEFAULT_RTPPROXY_TOUT 1
+
+#define BUF_SIZE 250
+
+class RtpProxyUtil {
+
+public:
+
+  class TimeoutListener {
+  public:
+    virtual ~TimeoutListener() {};
+    virtual void onMediaTimeout() = 0;
+  };
+
+
+private:
+
+
+  // Static variables for system wide settings
+  static int umode;
+  static char *rtpproxy_sock;
+  static int controlfd;
+  static char *timeout_sock;
+  static int timeoutfd;
+  static int timeout_clientfd;
+  static int rtpproxy_retr;
+  static int rtpproxy_tout;
+  static std::map<int, RtpProxyUtil *> proxies;
+
+  // Instance variables for per-instance data
+  pid_t mypid;
+  int myseqn;
+
+
+  TimeoutListener *timeoutListener;
+
+  bool valid;
+
+  char *callID;
+  char *callerAddr;
+  unsigned int callerPort;
+  char *calleeAddr;
+  unsigned int calleePort;
+  char *fromTag;
+  char *toTag; 
+
+  unsigned int callerProxyPort;
+  unsigned int calleeProxyPort;
+
+protected:
+  static char *sendCommandRetry(int retries, struct iovec *v, int vcnt, char *my_cookie);
+  static char *sendCommand(struct iovec *v, int vcnt, char *my_cookie);
+  char *gencookie();
+
+  // called when a media timeout occurs
+  void mediaTimeout();
+
+public:
+
+  static void setSocket(const char *socket);
+  static void setTimeoutSocket(const char *socket);
+  static void init();
+  // check for timeout data from socket
+  static void do_timeouts();
+
+  RtpProxyUtil();
+  ~RtpProxyUtil();
+
+  void setTimeoutListener(TimeoutListener *timeoutListener);
+
+  // Inform rtpproxy of the caller's details
+  unsigned int setupCaller(const char *callID, const char *callerAddr, int callerPort, const char *fromTag, bool callerAsymmetric);
+  // ammend the caller's details (after the caller sends re-INVITE)
+  void ammendCaller(const char *callerAddr, int callerPort);
+  // Inform rtpproxy of the callee's details
+  unsigned int setupCallee(const char *calleeAddr, int calleePort, const char *toTag, bool calleeAsymmetric);
+  // ammend the callee's details
+  void ammendCallee(const char *calleeAddr, int calleePort);
+
+  unsigned int getCallerProxyPort();
+  unsigned int getCalleeProxyPort();
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/TaskManager.cxx b/b2bua/TaskManager.cxx
new file mode 100644
index 0000000..48493b3
--- /dev/null
+++ b/b2bua/TaskManager.cxx
@@ -0,0 +1,99 @@
+
+#include <cassert>
+#include <list>
+
+#include "Logging.hxx"
+#include "TaskManager.hxx"
+
+using namespace b2bua;
+using namespace std;
+
+TaskManager::TaskManager() {
+}
+
+void TaskManager::start() {
+  while(true) {
+    int incompleteCount = 0;
+    list<RecurringTask *>::iterator iterator = recurringTasks.begin();
+    while(iterator != recurringTasks.end()) {
+      // FIXME - read return value, remove completed tasks
+      RecurringTask *t = *iterator;
+      iterator++;
+      TaskResult r = t->doTaskProcessing();
+      switch(r) {
+        case TaskComplete:
+          recurringTasks.remove(t);
+          break;
+        case TaskNotComplete:
+          incompleteCount++;
+          break;
+        default:
+          // ignore any other return value
+          break;
+      }
+    }
+    if(incompleteCount == 0) {
+      // All tasks are done
+      B2BUA_LOG_NOTICE("all tasks complete");
+      return;
+    }
+    // FIXME - do scheduled tasks (not yet implemented)
+  }
+}
+
+void TaskManager::addRecurringTask(RecurringTask *t) {
+  recurringTasks.push_back(t);
+}
+
+void TaskManager::scheduleTask(ScheduledTask *t, time_t& executionTime) {
+  // FIXME - not yet implemented
+  B2BUA_LOG_CRIT("scheduleTask not implemented");
+  assert(0);
+}
+
+void TaskManager::stop() {
+  list<RecurringTask *>::iterator iterator = recurringTasks.begin();
+  while(iterator != recurringTasks.end()) {
+    RecurringTask *t = *iterator;
+    iterator++;
+    t->stop();
+  }
+}
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/b2bua/TaskManager.hxx b/b2bua/TaskManager.hxx
new file mode 100644
index 0000000..41cbbb6
--- /dev/null
+++ b/b2bua/TaskManager.hxx
@@ -0,0 +1,102 @@
+
+#ifndef __TaskManager_h
+#define __TaskManager_h
+
+#include <ctime>
+#include <list>
+
+namespace b2bua
+{
+
+/**
+ * The TaskManager keeps a record of all recurring tasks, and
+ * also tasks scheduled to take place at a specified time.
+ * It provides an efficient way of giving CPU time to each task.
+ * TaskManager is expected to be used with tasks that do not block
+ * or run for extended periods of time.
+ * TaskManager runs all tasks in a single thread.
+ */
+
+class TaskManager {
+
+public:
+
+  typedef enum TaskResult {
+    TaskComplete,		// the task doesn't need to run again
+    TaskNotComplete,		// the task would like to run again shortly
+    TaskIndefinite		// the task can be run again, but doesn't
+				// object if the TaskManager stops
+  };
+
+  class RecurringTask {
+  public:
+    virtual ~RecurringTask() {};
+    virtual TaskResult doTaskProcessing() = 0;
+    virtual void stop() = 0;
+  };
+
+  class ScheduledTask {
+  public:
+    virtual ~ScheduledTask() {};
+    virtual void doTaskSchedule() = 0;
+  };
+
+  TaskManager();
+  
+  /**
+   * Start the task manager - blocks until complete.
+   * Exits when all recurring tasks exit and no scheduled tasks remain.
+   */
+  void start();
+  void addRecurringTask(RecurringTask *t);
+  void scheduleTask(ScheduledTask *t, time_t& executionTime);
+
+  void stop();
+
+protected:
+  std::list<RecurringTask *> recurringTasks;
+  std::list<ScheduledTask *> scheduleTasks;
+
+};
+
+}
+
+#endif
+
+/* ====================================================================
+ *
+ * Copyright 2012 Daniel Pocock.  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 the author(s) nor the names of any contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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.
+ *
+ * ====================================================================
+ *
+ *
+ */
+
diff --git a/config.h.in b/config.h.in
index 73672f9..efa2f18 100644
--- a/config.h.in
+++ b/config.h.in
@@ -3,6 +3,9 @@
 /* BUILD_APPS */
 #undef BUILD_APPS
 
+/* BUILD_B2BUA */
+#undef BUILD_B2BUA
+
 /* BUILD_ICHAT_GW */
 #undef BUILD_ICHAT_GW
 
diff --git a/configure b/configure
index 714fd44..94e3ba8 100755
--- a/configure
+++ b/configure
@@ -757,6 +757,8 @@ BUILD_APPS_FALSE
 BUILD_APPS_TRUE
 BUILD_TFM_FALSE
 BUILD_TFM_TRUE
+BUILD_B2BUA_FALSE
+BUILD_B2BUA_TRUE
 LIBRADIUS_LIBADD
 USE_RADIUS_CLIENT_FALSE
 USE_RADIUS_CLIENT_TRUE
@@ -911,6 +913,7 @@ enable_dtls
 with_mysql
 with_geoip
 with_radius
+with_b2bua
 with_tfm
 with_apps
 with_ichat_gw
@@ -1576,6 +1579,7 @@ Optional Packages:
   --with-mysql            Link against MySQL client libraries
   --with-geoip            Link against MaxMind GeoIP libraries
   --with-radius           Link against RADIUS client libraries
+  --with-b2bua            Build B2BUA lib, no extra dependencies
   --with-tfm              Build TFM, links against Netxx and cppunit
   --with-apps             Build apps, links against various things
   --with-ichat-gw         Build iChat gateway, links against gloox
@@ -5122,13 +5126,13 @@ if test "${lt_cv_nm_interface+set}" = set; then :
 else
   lt_cv_nm_interface="BSD nm"
   echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:5125: $ac_compile\"" >&5)
+  (eval echo "\"\$as_me:5129: $ac_compile\"" >&5)
   (eval "$ac_compile" 2>conftest.err)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:5128: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval echo "\"\$as_me:5132: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:5131: output\"" >&5)
+  (eval echo "\"\$as_me:5135: output\"" >&5)
   cat conftest.out >&5
   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
     lt_cv_nm_interface="MS dumpbin"
@@ -6334,7 +6338,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6337 "configure"' > conftest.$ac_ext
+  echo '#line 6341 "configure"' > conftest.$ac_ext
   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -8390,11 +8394,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8393: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8397: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8397: \$? = $ac_status" >&5
+   echo "$as_me:8401: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8729,11 +8733,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8732: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8736: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8736: \$? = $ac_status" >&5
+   echo "$as_me:8740: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8834,11 +8838,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8837: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8841: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8841: \$? = $ac_status" >&5
+   echo "$as_me:8845: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -8889,11 +8893,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8892: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8896: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8896: \$? = $ac_status" >&5
+   echo "$as_me:8900: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -11273,7 +11277,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11276 "configure"
+#line 11280 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11369,7 +11373,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11372 "configure"
+#line 11376 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13325,11 +13329,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13328: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13332: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13332: \$? = $ac_status" >&5
+   echo "$as_me:13336: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13424,11 +13428,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13427: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13431: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13431: \$? = $ac_status" >&5
+   echo "$as_me:13435: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -13476,11 +13480,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13479: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13483: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13483: \$? = $ac_status" >&5
+   echo "$as_me:13487: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -15080,6 +15084,33 @@ fi
 
 
  if false; then
+  BUILD_B2BUA_TRUE=
+  BUILD_B2BUA_FALSE='#'
+else
+  BUILD_B2BUA_TRUE='#'
+  BUILD_B2BUA_FALSE=
+fi
+
+
+# Check whether --with-b2bua was given.
+if test "${with_b2bua+set}" = set; then :
+  withval=$with_b2bua;
+cat >>confdefs.h <<_ACEOF
+#define BUILD_B2BUA /**/
+_ACEOF
+
+  if true; then
+  BUILD_B2BUA_TRUE=
+  BUILD_B2BUA_FALSE='#'
+else
+  BUILD_B2BUA_TRUE='#'
+  BUILD_B2BUA_FALSE=
+fi
+
+fi
+
+
+ if false; then
   BUILD_TFM_TRUE=
   BUILD_TFM_FALSE='#'
 else
@@ -15671,7 +15702,7 @@ fi
 
 
 
-ac_config_files="$ac_config_files Makefile rutil/dns/ares/Makefile rutil/Makefile rutil/test/Makefile resip/Makefile resip/stack/Makefile resip/stack/test/Makefile resip/dum/Makefile resip/dum/test/Makefile resip/certs/Makefile repro/Makefile repro/reprocmd/Makefile repro/test/Makefile tfm/Makefile tfm/repro/Makefile tfm/tfdum/Makefile apps/Makefile apps/clicktocall/Makefile apps/ichat-gw/Makefile apps/ichat-gw/jabberconnector/Makefile apps/sipdial/Makefile resip.spec reTurn/Makefile reTurn/test/Makefile reTurn/client/Makefile reflow/Makefile resip/recon/Makefile presSvr/Makefile p2p/s2c/s2c/Makefile p2p/Makefile"
+ac_config_files="$ac_config_files Makefile rutil/dns/ares/Makefile rutil/Makefile rutil/test/Makefile resip/Makefile resip/stack/Makefile resip/stack/test/Makefile resip/dum/Makefile resip/dum/test/Makefile resip/certs/Makefile repro/Makefile repro/reprocmd/Makefile repro/test/Makefile b2bua/Makefile tfm/Makefile tfm/repro/Makefile tfm/tfdum/Makefile apps/Makefile apps/clicktocall/Makefile apps/ichat-gw/Makefile apps/ichat-gw/jabberconnector/Makefile apps/sipdial/Makefile resip.spec reTurn/Makefile reTurn/test/Makefile reTurn/client/Makefile reflow/Makefile resip/recon/Makefile presSvr/Makefile p2p/s2c/s2c/Makefile p2p/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -15851,6 +15882,14 @@ if test -z "${USE_RADIUS_CLIENT_TRUE}" && test -z "${USE_RADIUS_CLIENT_FALSE}";
   as_fn_error $? "conditional \"USE_RADIUS_CLIENT\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${BUILD_B2BUA_TRUE}" && test -z "${BUILD_B2BUA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_B2BUA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_B2BUA_TRUE}" && test -z "${BUILD_B2BUA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_B2BUA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${BUILD_TFM_TRUE}" && test -z "${BUILD_TFM_FALSE}"; then
   as_fn_error $? "conditional \"BUILD_TFM\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -16865,6 +16904,7 @@ do
     "repro/Makefile") CONFIG_FILES="$CONFIG_FILES repro/Makefile" ;;
     "repro/reprocmd/Makefile") CONFIG_FILES="$CONFIG_FILES repro/reprocmd/Makefile" ;;
     "repro/test/Makefile") CONFIG_FILES="$CONFIG_FILES repro/test/Makefile" ;;
+    "b2bua/Makefile") CONFIG_FILES="$CONFIG_FILES b2bua/Makefile" ;;
     "tfm/Makefile") CONFIG_FILES="$CONFIG_FILES tfm/Makefile" ;;
     "tfm/repro/Makefile") CONFIG_FILES="$CONFIG_FILES tfm/repro/Makefile" ;;
     "tfm/tfdum/Makefile") CONFIG_FILES="$CONFIG_FILES tfm/tfdum/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index 9316da0..3ddebe4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -200,6 +200,12 @@ AC_ARG_WITH(radius,
  AM_CONDITIONAL(USE_RADIUS_CLIENT, true)],
  [ AC_SUBST(LIBRADIUS_LIBADD, "")])
 
+AM_CONDITIONAL(BUILD_B2BUA, false)
+AC_ARG_WITH(b2bua,
+[  --with-b2bua            Build B2BUA lib, no extra dependencies],
+ [AC_DEFINE_UNQUOTED(BUILD_B2BUA, , BUILD_B2BUA)
+ AM_CONDITIONAL(BUILD_B2BUA, true)], )
+
 AM_CONDITIONAL(BUILD_TFM, false)
 AC_ARG_WITH(tfm,
 [  --with-tfm              Build TFM, links against Netxx and cppunit],
@@ -254,6 +260,7 @@ AC_OUTPUT(Makefile \
 	repro/Makefile \
 	repro/reprocmd/Makefile \
 	repro/test/Makefile \
+	b2bua/Makefile \
 	tfm/Makefile \
 	tfm/repro/Makefile \
 	tfm/tfdum/Makefile \

-- 
reSIProcate



More information about the Pkg-voip-commits mailing list