示例#1
0
 public void errResponseReceived(final SipResponse sipResponse) {
   Dialog dialog = dialogManager.getDialog(sipResponse);
   if (dialog != null) {
     dialog.receivedOrSent300To699();
     dialogManager.removeDialog(dialog.getId());
   }
   int statusCode = sipResponse.getStatusCode();
   if (statusCode == RFC3261.CODE_401_UNAUTHORIZED
       || statusCode == RFC3261.CODE_407_PROXY_AUTHENTICATION_REQUIRED && !challenged) {
     InviteClientTransaction inviteClientTransaction =
         (InviteClientTransaction) transactionManager.getClientTransaction(sipResponse);
     SipRequest sipRequest = inviteClientTransaction.getRequest();
     String password = userAgent.getConfig().getPassword();
     if (password != null && !"".equals(password.trim())) {
       challengeManager.handleChallenge(sipRequest, sipResponse);
     }
     challenged = true;
     return;
   } else {
     challenged = false;
   }
   SipListener sipListener = userAgent.getSipListener();
   if (sipListener != null) {
     sipListener.error(sipResponse);
   }
   List<String> guiClosedCallIds = userAgent.getUac().getGuiClosedCallIds();
   String callId = Utils.getMessageCallId(sipResponse);
   if (guiClosedCallIds.contains(callId)) {
     guiClosedCallIds.remove(callId);
   }
   userAgent.getMediaManager().setDatagramSocket(null);
 }
示例#2
0
  public void handleInitialInvite(SipRequest sipRequest) {
    initialIncomingInvite = true;
    // generate 180 Ringing
    SipResponse sipResponse =
        buildGenericResponse(sipRequest, RFC3261.CODE_180_RINGING, RFC3261.REASON_180_RINGING);
    Dialog dialog = buildDialogForUas(sipResponse, sipRequest);
    // here dialog is already stored in dialogs in DialogManager

    InviteServerTransaction inviteServerTransaction =
        (InviteServerTransaction)
            transactionManager.createServerTransaction(
                sipResponse, userAgent.getSipPort(), RFC3261.TRANSPORT_UDP, this, sipRequest);

    inviteServerTransaction.start();

    inviteServerTransaction.receivedRequest(sipRequest);

    // TODO send 180 more than once
    inviteServerTransaction.sendReponse(sipResponse);

    dialog.receivedOrSent1xx();

    SipListener sipListener = userAgent.getSipListener();
    if (sipListener != null) {
      sipListener.incomingCall(sipRequest, sipResponse);
    }

    List<String> peers = userAgent.getPeers();
    String responseTo =
        sipRequest.getSipHeaders().get(new SipHeaderFieldName(RFC3261.HDR_FROM)).getValue();
    if (!peers.contains(responseTo)) {
      peers.add(responseTo);
    }
  }
示例#3
0
  public void rejectCall(SipRequest sipRequest) {
    // TODO generate 486, etc.
    SipHeaders reqHeaders = sipRequest.getSipHeaders();
    SipHeaderFieldValue callId = reqHeaders.get(new SipHeaderFieldName(RFC3261.HDR_CALLID));

    Dialog dialog = dialogManager.getDialog(callId.getValue());

    // TODO manage auto reject Do not disturb (DND)
    SipResponse sipResponse =
        RequestManager.generateResponse(
            sipRequest, dialog, RFC3261.CODE_486_BUSYHERE, RFC3261.REASON_486_BUSYHERE);

    // TODO determine port and transport for server transaction>transport
    // from initial invite
    // FIXME determine port and transport for server transaction>transport
    ServerTransaction serverTransaction = transactionManager.getServerTransaction(sipRequest);

    serverTransaction.start();

    serverTransaction.receivedRequest(sipRequest);

    serverTransaction.sendReponse(sipResponse);

    dialog.receivedOrSent300To699();

    userAgent.getMediaManager().setDatagramSocket(null);
    //        setChanged();
    //        notifyObservers(sipRequest);
  }
示例#4
0
  public void provResponseReceived(SipResponse sipResponse, Transaction transaction) {
    // dialog may have already been created if a previous 1xx has
    // already been received
    Dialog dialog = dialogManager.getDialog(sipResponse);
    boolean isFirstProvRespWithToTag = false;
    if (dialog == null) {
      SipHeaderFieldValue to =
          sipResponse.getSipHeaders().get(new SipHeaderFieldName(RFC3261.HDR_TO));
      String toTag = to.getParam(new SipHeaderParamName(RFC3261.PARAM_TAG));
      if (toTag != null) {
        dialog = dialogManager.createDialog(sipResponse);
        isFirstProvRespWithToTag = true;
      } else {
        // TODO maybe stop retransmissions
      }
    }

    if (dialog != null) {
      buildOrUpdateDialogForUac(sipResponse, transaction);
    }

    //
    //        if (dialog == null && sipResponse.getStatusCode() != RFC3261.CODE_100_TRYING) {
    //            logger.debug("dialog not found for prov response");
    //            isFirstProvRespWithToTag = true;
    //            SipHeaderFieldValue to = sipResponse.getSipHeaders()
    //                .get(new SipHeaderFieldName(RFC3261.HDR_TO));
    //            String toTag = to.getParam(new SipHeaderParamName(RFC3261.PARAM_TAG));
    //            if (toTag != null) {
    //                dialog = buildOrUpdateDialogForUac(sipResponse, transaction);
    //            }
    //        }
    // TODO this notification is probably useless because dialog state modification
    //     thereafter always notify dialog observers
    if (isFirstProvRespWithToTag) {
      SipListener sipListener = userAgent.getSipListener();
      if (sipListener != null) {
        sipListener.ringing(sipResponse);
      }
      dialog.receivedOrSent1xx();
    }
    List<String> guiClosedCallIds = userAgent.getUac().getGuiClosedCallIds();
    String callId = Utils.getMessageCallId(sipResponse);
    if (guiClosedCallIds.contains(callId)) {
      SipRequest sipRequest = transaction.getRequest();
      logger.debug(
          "cancel after prov response: sipRequest " + sipRequest + ", sipResponse " + sipResponse);
      userAgent.terminate(sipRequest);
    }
  }
示例#5
0
  public void acceptCall(SipRequest sipRequest, Dialog dialog) {
    sendSuccessfulResponse(sipRequest, dialog);

    dialog.receivedOrSent2xx();
    //        logger.getInstance().debug("dialog state: " + dialog.getState());
    //        logger.getInstance().debug("after dialog.receivedOrSent2xx();");

    //        setChanged();
    //        notifyObservers(sipRequest);
  }
示例#6
0
  public void handleReInvite(SipRequest sipRequest, Dialog dialog) {
    logger.debug("handleReInvite");
    initialIncomingInvite = false;
    SipHeaders sipHeaders = sipRequest.getSipHeaders();

    // 12.2.2 update dialog
    SipHeaderFieldValue contact = sipHeaders.get(new SipHeaderFieldName(RFC3261.HDR_CONTACT));
    if (contact != null) {
      String contactStr = contact.getValue();
      if (contactStr.indexOf(RFC3261.LEFT_ANGLE_BRACKET) > -1) {
        contactStr = NameAddress.nameAddressToUri(contactStr);
      }
      dialog.setRemoteTarget(contactStr);
    }

    // update session
    sendSuccessfulResponse(sipRequest, dialog);
  }
示例#7
0
  public void successResponseReceived(SipResponse sipResponse, Transaction transaction) {
    SipHeaders responseHeaders = sipResponse.getSipHeaders();
    String cseq = responseHeaders.get(new SipHeaderFieldName(RFC3261.HDR_CSEQ)).getValue();
    String method = cseq.substring(cseq.trim().lastIndexOf(' ') + 1);
    if (!RFC3261.METHOD_INVITE.equals(method)) {
      return;
    }

    challenged = false;

    // 13.2.2.4

    List<String> peers = userAgent.getPeers();
    String responseTo = responseHeaders.get(new SipHeaderFieldName(RFC3261.HDR_TO)).getValue();
    if (!peers.contains(responseTo)) {
      peers.add(responseTo);
      // timer used to purge dialogs which are not confirmed
      // after a given time
      ackTimer.schedule(new AckTimerTask(responseTo), 64 * RFC3261.TIMER_T1);
    }

    Dialog dialog = dialogManager.getDialog(sipResponse);

    if (dialog != null) {
      // dialog already created with a 180 for example
      dialog.setRouteSet(computeRouteSet(sipResponse.getSipHeaders()));
    }
    dialog = buildOrUpdateDialogForUac(sipResponse, transaction);

    SipListener sipListener = userAgent.getSipListener();
    if (sipListener != null) {
      sipListener.calleePickup(sipResponse);
    }

    // added for media
    SessionDescription sessionDescription = sdpManager.parse(sipResponse.getBody());
    try {
      mediaDestination = sdpManager.getMediaDestination(sessionDescription);
    } catch (NoCodecException e) {
      logger.error(e.getMessage(), e);
    }
    String remoteAddress = mediaDestination.getDestination();
    int remotePort = mediaDestination.getPort();
    Codec codec = mediaDestination.getCodec();
    String localAddress = userAgent.getConfig().getLocalInetAddress().getHostAddress();

    userAgent
        .getMediaManager()
        .successResponseReceived(localAddress, remoteAddress, remotePort, codec);

    // switch to confirmed state
    dialog.receivedOrSent2xx();

    // generate ack
    // p. 82 §3
    SipRequest ack = dialog.buildSubsequentRequest(RFC3261.METHOD_ACK);

    // update CSeq

    SipHeaders ackHeaders = ack.getSipHeaders();
    SipHeaderFieldName cseqName = new SipHeaderFieldName(RFC3261.HDR_CSEQ);
    SipHeaderFieldValue ackCseq = ackHeaders.get(cseqName);

    SipRequest request = transaction.getRequest();
    SipHeaders requestHeaders = request.getSipHeaders();
    SipHeaderFieldValue requestCseq = requestHeaders.get(cseqName);

    ackCseq.setValue(requestCseq.toString().replace(RFC3261.METHOD_INVITE, RFC3261.METHOD_ACK));

    // add Via with only the branchid parameter

    SipHeaderFieldValue via = new SipHeaderFieldValue("");
    SipHeaderParamName branchIdName = new SipHeaderParamName(RFC3261.PARAM_BRANCH);
    via.addParam(branchIdName, Utils.generateBranchId());

    ackHeaders.add(new SipHeaderFieldName(RFC3261.HDR_VIA), via, 0);

    // TODO authentication headers

    if (request.getBody() == null && sipResponse.getBody() != null) {
      // TODO add a real SDP answer
      ack.setBody(sipResponse.getBody());
    }

    // TODO check if sdp is acceptable

    SipURI destinationUri = RequestManager.getDestinationUri(ack, logger);
    challengeManager.postProcess(ack);

    // TODO if header route is present, addrspec = toproute.nameaddress.addrspec

    String transport = RFC3261.TRANSPORT_UDP;
    Hashtable<String, String> params = destinationUri.getUriParameters();
    if (params != null) {
      String reqUriTransport = params.get(RFC3261.PARAM_TRANSPORT);
      if (reqUriTransport != null) {
        transport = reqUriTransport;
      }
    }
    int port = destinationUri.getPort();
    if (port == SipURI.DEFAULT_PORT) {
      port = RFC3261.TRANSPORT_DEFAULT_PORT;
    }

    SipURI sipUri = userAgent.getConfig().getOutboundProxy();
    if (sipUri == null) {
      sipUri = destinationUri;
    }
    InetAddress inetAddress;
    try {
      inetAddress = InetAddress.getByName(sipUri.getHost());
    } catch (UnknownHostException e) {
      logger.error("unknown host: " + sipUri.getHost(), e);
      return;
    }
    try {
      MessageSender sender =
          transportManager.createClientTransport(ack, inetAddress, port, transport);
      sender.sendMessage(ack);
    } catch (IOException e) {
      logger.error("input/output error", e);
    }

    List<String> guiClosedCallIds = userAgent.getUac().getGuiClosedCallIds();
    String callId = Utils.getMessageCallId(sipResponse);
    if (guiClosedCallIds.contains(callId)) {
      userAgent.terminate(request);
    }
  }
示例#8
0
  private synchronized void sendSuccessfulResponse(SipRequest sipRequest, Dialog dialog) {
    SipHeaders reqHeaders = sipRequest.getSipHeaders();
    SipHeaderFieldValue contentType =
        reqHeaders.get(new SipHeaderFieldName(RFC3261.HDR_CONTENT_TYPE));

    if (RFC3261.CONTENT_TYPE_SDP.equals(contentType)) {
      // TODO
      //            String sdpResponse;
      //            try {
      //                sdpResponse = sdpManager.handleOffer(
      //                        new String(sipRequest.getBody()));
      //            } catch (NoCodecException e) {
      //                sdpResponse = sdpManager.generateErrorResponse();
      //            }
    } else {
      // TODO manage empty bodies and non-application/sdp content type
    }

    // TODO if mode autoanswer just send 200 without asking any question
    SipResponse sipResponse =
        RequestManager.generateResponse(
            sipRequest, dialog, RFC3261.CODE_200_OK, RFC3261.REASON_200_OK);

    // TODO 13.3 dialog invite-specific processing

    // TODO timer if there is an Expires header in INVITE

    // TODO 3xx

    // TODO 486 or 600

    byte[] offerBytes = sipRequest.getBody();
    SessionDescription answer;
    try {
      DatagramSocket datagramSocket = getDatagramSocket();

      if (offerBytes != null
          && contentType != null
          && RFC3261.CONTENT_TYPE_SDP.equals(contentType.getValue())) {
        // create response in 200
        try {
          SessionDescription offer = sdpManager.parse(offerBytes);
          answer = sdpManager.createSessionDescription(offer, datagramSocket.getLocalPort());
          mediaDestination = sdpManager.getMediaDestination(offer);
        } catch (NoCodecException e) {
          answer = sdpManager.createSessionDescription(null, datagramSocket.getLocalPort());
        }
      } else {
        // create offer in 200 (never tested...)
        answer = sdpManager.createSessionDescription(null, datagramSocket.getLocalPort());
      }
      sipResponse.setBody(answer.toString().getBytes());
    } catch (IOException e) {
      logger.error(e.getMessage(), e);
    }

    SipHeaders respHeaders = sipResponse.getSipHeaders();
    respHeaders.add(
        new SipHeaderFieldName(RFC3261.HDR_CONTENT_TYPE),
        new SipHeaderFieldValue(RFC3261.CONTENT_TYPE_SDP));

    ArrayList<String> routeSet = dialog.getRouteSet();
    if (routeSet != null) {
      SipHeaderFieldName recordRoute = new SipHeaderFieldName(RFC3261.HDR_RECORD_ROUTE);
      for (String route : routeSet) {
        respHeaders.add(recordRoute, new SipHeaderFieldValue(route));
      }
    }

    // TODO determine port and transport for server transaction>transport
    // from initial invite
    // FIXME determine port and transport for server transaction>transport
    ServerTransaction serverTransaction = transactionManager.getServerTransaction(sipRequest);
    if (serverTransaction == null) {
      // in re-INVITE case, no serverTransaction has been created
      serverTransaction =
          (InviteServerTransaction)
              transactionManager.createServerTransaction(
                  sipResponse, userAgent.getSipPort(), RFC3261.TRANSPORT_UDP, this, sipRequest);
    }
    serverTransaction.start();

    serverTransaction.receivedRequest(sipRequest);

    serverTransaction.sendReponse(sipResponse);
    // TODO manage retransmission of the response (send to the transport)
    // until ACK arrives, if no ACK is received within 64*T1, confirm dialog
    // and terminate it with a BYE

    //        logger.getInstance().debug("before dialog.receivedOrSent2xx();");
    //        logger.getInstance().debug("dialog state: " + dialog.getState());
  }
示例#9
0
 public void terminate(SipRequest sipRequest) {
   String callId = Utils.getMessageCallId(sipRequest);
   if (!guiClosedCallIds.contains(callId)) {
     guiClosedCallIds.add(callId);
   }
   Dialog dialog = dialogManager.getDialog(callId);
   SipRequest inviteWithAuth = getInviteWithAuth(callId);
   if (dialog != null) {
     SipRequest originatingRequest;
     if (inviteWithAuth != null) {
       originatingRequest = inviteWithAuth;
     } else {
       originatingRequest = sipRequest;
     }
     ClientTransaction clientTransaction =
         transactionManager.getClientTransaction(originatingRequest);
     if (clientTransaction != null) {
       synchronized (clientTransaction) {
         DialogState dialogState = dialog.getState();
         if (dialog.EARLY.equals(dialogState)) {
           initialRequestManager.createCancel(inviteWithAuth, midDialogRequestManager, profileUri);
         } else if (dialog.CONFIRMED.equals(dialogState)) {
           // clientTransaction not yet removed
           midDialogRequestManager.generateMidDialogRequest(dialog, RFC3261.METHOD_BYE, null);
           guiClosedCallIds.remove(callId);
         }
       }
     } else {
       // clientTransaction Terminated and removed
       logger.debug("clientTransaction null");
       midDialogRequestManager.generateMidDialogRequest(dialog, RFC3261.METHOD_BYE, null);
       guiClosedCallIds.remove(callId);
     }
   } else {
     InviteClientTransaction inviteClientTransaction =
         (InviteClientTransaction) transactionManager.getClientTransaction(inviteWithAuth);
     if (inviteClientTransaction == null) {
       logger.error("cannot find invite client transaction" + " for call " + callId);
     } else {
       SipResponse sipResponse = inviteClientTransaction.getLastResponse();
       if (sipResponse != null) {
         int statusCode = sipResponse.getStatusCode();
         if (statusCode < RFC3261.CODE_200_OK) {
           initialRequestManager.createCancel(inviteWithAuth, midDialogRequestManager, profileUri);
         }
       }
     }
   }
   switch (userAgent.getMediaMode()) {
     case captureAndPlayback:
       userAgent.getMediaManager().stopSession();
       SoundManager soundManager = userAgent.getSoundManager();
       if (soundManager != null) {
         soundManager.closeLines();
       }
       break;
     case echo:
       Echo echo = userAgent.getEcho();
       if (echo != null) {
         echo.stop();
         userAgent.setEcho(null);
       }
       break;
     case file:
       MediaManager mediaManager = userAgent.getMediaManager();
       mediaManager.stopSession();
       break;
     default:
       break;
   }
 }