diff --git a/pom.xml b/pom.xml index d1b384b6a1..f71c4f1c37 100644 --- a/pom.xml +++ b/pom.xml @@ -143,7 +143,7 @@ log4j log4j - 1.2.8 + 1.2.17 @@ -279,7 +279,7 @@ diff --git a/src/main/java/org/cafesip/sipunit/PresenceSubscriber.java b/src/main/java/org/cafesip/sipunit/PresenceSubscriber.java index 738406ea0a..26af3eac65 100644 --- a/src/main/java/org/cafesip/sipunit/PresenceSubscriber.java +++ b/src/main/java/org/cafesip/sipunit/PresenceSubscriber.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.Calendar; import javax.sip.header.AcceptHeader; import javax.sip.header.ContentTypeHeader; @@ -33,6 +34,7 @@ import javax.xml.bind.Unmarshaller; import javax.xml.bind.ValidationEvent; import javax.xml.bind.ValidationEventHandler; +import javax.xml.datatype.XMLGregorianCalendar; import org.cafesip.sipunit.presenceparser.pidf.Contact; import org.cafesip.sipunit.presenceparser.pidf.Note; @@ -210,9 +212,11 @@ public boolean handleEvent(ValidationEvent arg0) while (i.hasNext()) { Tuple t = (Tuple) i.next(); + XMLGregorianCalendar gregCal = t.getTimestamp(); + Calendar cvtTs = gregCal.toGregorianCalendar(); PresenceDeviceInfo dev = new PresenceDeviceInfo(); - dev.setBasicStatus(t.getStatus().getBasic()); + dev.setBasicStatus(t.getStatus().getBasic().toString()); Contact contact = t.getContact(); if (contact != null) @@ -228,7 +232,7 @@ public boolean handleEvent(ValidationEvent arg0) dev.setDeviceExtensions(t.getAny()); dev.setId(t.getId()); dev.setStatusExtensions(t.getStatus().getAny()); - dev.setTimestamp(t.getTimestamp()); + dev.setTimestamp(cvtTs); ArrayList notes = new ArrayList(); if (t.getNote() != null) diff --git a/src/main/java/org/cafesip/sipunit/SipCall.java b/src/main/java/org/cafesip/sipunit/SipCall.java index b9b12106d5..511abe6995 100644 --- a/src/main/java/org/cafesip/sipunit/SipCall.java +++ b/src/main/java/org/cafesip/sipunit/SipCall.java @@ -2850,6 +2850,14 @@ public boolean waitReinviteResponse(SipTransaction siptrans, long timeout) return true; } + public boolean disconnect() + { + if (sendDisconnect() == null) { + return false; + } + return true; + } + /** * This method sends a basic BYE message. It incorporates required * authorization headers that have previously been accumulated during the @@ -2858,9 +2866,9 @@ public boolean waitReinviteResponse(SipTransaction siptrans, long timeout) * * @return true if the message was successfully sent, false otherwise. */ - public boolean disconnect() + public SipTransaction sendDisconnect() { - return disconnect(null, null, null); + return sendDisconnect(null, null, null); } /** @@ -2895,7 +2903,7 @@ public boolean disconnect() * for this body to be included in the message. Use null for no * body bytes. */ - public boolean disconnect(ArrayList
additionalHeaders, + public SipTransaction sendDisconnect(ArrayList
additionalHeaders, ArrayList
replaceHeaders, String body) { initErrorInfo(); @@ -2907,7 +2915,7 @@ public boolean disconnect(ArrayList
additionalHeaders, .get(new Integer(returnCode)) + " - dialog hasn't been established"; - return false; + return null; } try @@ -2924,14 +2932,14 @@ public boolean disconnect(ArrayList
additionalHeaders, if (transaction != null) { - return true; + return transaction; } setReturnCode(parent.getReturnCode()); setErrorMessage(parent.getErrorMessage()); setException(parent.getException()); - return false; + return null; } catch (Exception ex) @@ -2941,10 +2949,24 @@ public boolean disconnect(ArrayList
additionalHeaders, setErrorMessage("Exception: " + ex.getClass().getName() + ": " + ex.getMessage()); + return null; + } + } + + public boolean disconnect(String body, String contentType, + String contentSubType, ArrayList additionalHeaders, + ArrayList replaceHeaders) + { + SipTransaction siptrans = sendDisconnect(body, contentType, contentSubType, + additionalHeaders, replaceHeaders); + + if (siptrans == null) { return false; } + + return true; } - + /** * This method is the same as the basic disconnect() method except that it * allows the caller to specify a message body and/or additional message @@ -2993,13 +3015,14 @@ public boolean disconnect(ArrayList
additionalHeaders, * null for no replacement of message headers. * */ - public boolean disconnect(String body, String contentType, + public SipTransaction sendDisconnect(String body, String contentType, String contentSubType, ArrayList additionalHeaders, ArrayList replaceHeaders) { + SipTransaction ret = null; try { - return disconnect(parent.toHeader(additionalHeaders, contentType, + ret = sendDisconnect(parent.toHeader(additionalHeaders, contentType, contentSubType), parent.toHeader(replaceHeaders), body); } catch (Exception ex) @@ -3008,8 +3031,8 @@ public boolean disconnect(String body, String contentType, setErrorMessage("Exception: " + ex.getClass().getName() + ": " + ex.getMessage()); setReturnCode(SipSession.EXCEPTION_ENCOUNTERED); - return false; } + return ret; } /** @@ -4278,6 +4301,76 @@ public boolean waitForCancelResponse(SipTransaction siptrans, long timeout) return true; } + /** + * The waitForDisconnectResponse() method waits for a response to be received + * from the network for a sent BYE. Call this method after calling + * sendDisconnect(). + *

+ * This method blocks until one of the following occurs: 1) A response + * message has been received. In this case, a value of true is returned. + * Call the getLastReceivedResponse() method to get the response details. 2) + * A timeout occurs. A false value is returned in this case. 3) An error + * occurs. False is returned in this case. + *

+ * Regardless of the outcome, getReturnCode() can be called after this + * method returns to get the status code: IE, the SIP response code received + * from the network (defined in SipResponse, along with the corresponding + * textual equivalent) or a SipUnit internal status/error code (defined in + * SipSession, along with the corresponding textual equivalent). SipUnit + * internal codes are in a specially designated range + * (SipSession.SIPUNIT_INTERNAL_RETURNCODE_MIN and upward). + *

+ * + * @param siptrans + * This is the object that was returned by method sendDisconnect(). + * It identifies a specific Disconnect transaction. + * @param timeout + * The maximum amount of time to wait, in milliseconds. Use a + * value of 0 to wait indefinitely. + * @return true if a response was received - in that case, call + * getReturnCode() to get the status code that was contained in the + * received response, and/or call getLastReceivedResponse() to see + * the response details. Returns false if timeout or error. + */ + public boolean waitForDisconnectResponse(SipTransaction siptrans, long timeout) + { + initErrorInfo(); + + if (siptrans == null) + { + returnCode = SipSession.INVALID_OPERATION; + errorMessage = (String) SipSession.statusCodeDescription + .get(new Integer(returnCode)) + + " - no transaction object given"; + return false; + } + + EventObject response_event = parent.waitResponse(siptrans, timeout); + + if (response_event == null) + { + setErrorMessage(parent.getErrorMessage()); + setException(parent.getException()); + setReturnCode(parent.getReturnCode()); + return false; + } + + if (response_event instanceof TimeoutEvent == true) + { + setReturnCode(SipPhone.TIMEOUT_OCCURRED); + setErrorMessage("A Timeout Event was received"); + return false; + } + + Response resp = ((ResponseEvent) response_event).getResponse(); + receivedResponses.add(new SipResponse((ResponseEvent) response_event)); + SipStack.trace("BYE response received: " + resp.toString()); + + setReturnCode(resp.getStatusCode()); + + return true; + } + /** * Gets the SIP Call ID for this incoming or outgoing call. * @@ -4292,4 +4385,4 @@ public String getCallId() return callId.getCallId(); } -} \ No newline at end of file +} diff --git a/src/main/java/org/cafesip/sipunit/SipSession.java b/src/main/java/org/cafesip/sipunit/SipSession.java index 2f3975e2ce..fb683b79e7 100644 --- a/src/main/java/org/cafesip/sipunit/SipSession.java +++ b/src/main/java/org/cafesip/sipunit/SipSession.java @@ -448,13 +448,14 @@ public void processRequest(RequestEvent request) { SipStack .trace(" skipping 'To' check, we're not loopback (see setLoopback())"); - return; } - - // check 'To' for a match - if (to.getAddress().getURI().toString().equals(me) == false) + else { - return; + // check 'To' for a match + if (to.getAddress().getURI().toString().equals(me) == false) + { + return; + } } } @@ -2460,4 +2461,4 @@ public void processDialogTerminated(DialogTerminatedEvent arg0) // TODO Auto-generated method stub } -} \ No newline at end of file +} diff --git a/src/main/java/org/cafesip/sipunit/SipStack.java b/src/main/java/org/cafesip/sipunit/SipStack.java index 0306525da5..025f97b005 100644 --- a/src/main/java/org/cafesip/sipunit/SipStack.java +++ b/src/main/java/org/cafesip/sipunit/SipStack.java @@ -47,6 +47,8 @@ import javax.sip.header.RouteHeader; import javax.sip.message.MessageFactory; +import org.apache.log4j.Logger; + /** * This class is the starting point for a SipUnit test. Before establishing any * SIP sessions, the test program must instantiate this class. Each SipStack @@ -63,6 +65,8 @@ */ public class SipStack implements SipListener { + static Logger log = null; + private static boolean traceEnabled = false; private static SipFactory sipFactory = null; @@ -135,6 +139,16 @@ public class SipStack implements SipListener public static final String DEFAULT_PROTOCOL = PROTOCOL_UDP; + /** + * This constructor is a wrapper around the usual constructor, + * which allows an additional logging object to be passed. + */ + public SipStack(String proto, int port, Properties props, Logger log) throws Exception + { + this(proto, port, props); + SipStack.log = log; + } + /** * A constructor for this class. Before establishing any SIP sessions, * instantiate this class. You may provide the parameters for SIP protocol @@ -529,8 +543,12 @@ public synchronized static void trace(String msg) // grossly simplified { if (traceEnabled) { - System.out.println("SIPUNIT TRACE: " + System.currentTimeMillis() + if (log == null) { + System.out.println("SIPUNIT TRACE: " + System.currentTimeMillis() + " " + msg); + } else { + log.trace("SIPUNIT TRACE\t" + msg); + } } } @@ -606,4 +624,4 @@ public void processDialogTerminated(DialogTerminatedEvent arg0) public int getRetransmissions() { return retransmissions; } -} \ No newline at end of file +}