Skip to content

Commit

Permalink
Added custom calling context in answer api. (#43220)
Browse files Browse the repository at this point in the history
* Added custom calling context in answer api.

* Added live and unit tests.

* resolved buld issues.

* fixing the build issue and recording the live test

---------

Co-authored-by: Vinothini Dharmaraj <[email protected]>
  • Loading branch information
v-pivamshi and v-vdharmaraj authored Dec 30, 2024
1 parent 433d8b2 commit b6caa39
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/communication/azure-communication-callautomation",
"Tag": "java/communication/azure-communication-callautomation_8eed475b32"
"Tag": "java/communication/azure-communication-callautomation_cf67d9f149"
}
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,13 @@ Mono<Response<AnswerCallResult>> answerCallWithResponseInternal(AnswerCallOption
= getTranscriptionOptionsInternal(answerCallOptions.getTranscriptionOptions());
request.setTranscriptionOptions(transcriptionOptionsInternal);
}
if (answerCallOptions.getCustomCallingContext().getSipHeaders() != null
|| answerCallOptions.getCustomCallingContext().getVoipHeaders() != null) {
CustomCallingContext customContext = new CustomCallingContext();
customContext.setSipHeaders(answerCallOptions.getCustomCallingContext().getSipHeaders());
customContext.setVoipHeaders(answerCallOptions.getCustomCallingContext().getVoipHeaders());
request.setCustomCallingContext(customContext);
}

return azureCommunicationCallAutomationServiceInternal.answerCallWithResponseAsync(request, context)
.map(response -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

package com.azure.communication.callautomation.models;

import java.util.HashMap;

import com.azure.core.annotation.Fluent;

/**
Expand Down Expand Up @@ -40,6 +42,11 @@ public final class AnswerCallOptions {
*/
private String operationContext;

/**
* Custom Context
*/
private final CustomCallingContext customCallingContext;

/**
* Constructor
*
Expand All @@ -49,6 +56,8 @@ public final class AnswerCallOptions {
public AnswerCallOptions(String incomingCallContext, String callbackUrl) {
this.incomingCallContext = incomingCallContext;
this.callbackUrl = callbackUrl;
this.customCallingContext
= new CustomCallingContext(new HashMap<String, String>(), new HashMap<String, String>());
}

/**
Expand Down Expand Up @@ -148,4 +157,12 @@ public AnswerCallOptions setMediaStreamingOptions(MediaStreamingOptions mediaStr
this.mediaStreamingOptions = mediaStreamingOptions;
return this;
}

/**
* get custom context
* @return custom context
*/
public CustomCallingContext getCustomCallingContext() {
return customCallingContext;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,121 @@ public void createVOIPCallAndRejectAutomatedTest(HttpClient httpClient) {
}
}

@ParameterizedTest
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
@DisabledIfEnvironmentVariable(
named = "SKIP_LIVE_TEST",
matches = "(?i)(true)",
disabledReason = "Requires environment to be set up")
public void createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest(HttpClient httpClient) {
/* Test case: ACS to ACS call
* 1. create a CallAutomationClient.
* 2. create a call from source to one ACS target.
* 3. get updated call properties and check for the connected state.
* 4. hang up the call.
* 5. once call is hung up, verify disconnected event
*/

CommunicationIdentityAsyncClient identityAsyncClient
= getCommunicationIdentityClientUsingConnectionString(httpClient).addPolicy(
(context, next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next))
.buildAsyncClient();

List<CallConnectionAsync> callDestructors = new ArrayList<>();

try {
// create caller and receiver
CommunicationUserIdentifier caller = identityAsyncClient.createUser().block();
CommunicationIdentifier target = identityAsyncClient.createUser().block();

// Create call automation client and use source as the caller.
CallAutomationAsyncClient callerAsyncClient = getCallAutomationClientUsingConnectionString(httpClient)
.addPolicy((context,
next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next))
.sourceIdentity(caller)
.buildAsyncClient();
// Create call automation client for receivers.
CallAutomationAsyncClient receiverAsyncClient = getCallAutomationClientUsingConnectionString(httpClient)
.addPolicy((context,
next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next))
.buildAsyncClient();

String uniqueId = serviceBusWithNewCall(caller, target);

// create a call
List<CommunicationIdentifier> targets = new ArrayList<>(Collections.singletonList(target));
CreateGroupCallOptions createCallOptions
= new CreateGroupCallOptions(targets, DISPATCHER_CALLBACK + String.format("?q=%s", uniqueId));
Response<CreateCallResult> createCallResultResponse
= callerAsyncClient.createGroupCallWithResponse(createCallOptions).block();

assertNotNull(createCallResultResponse);
CreateCallResult createCallResult = createCallResultResponse.getValue();
assertNotNull(createCallResult);
assertNotNull(createCallResult.getCallConnectionProperties());
String callerConnectionId = createCallResult.getCallConnectionProperties().getCallConnectionId();
assertNotNull(callerConnectionId);

// wait for the incomingCallContext
String incomingCallContext = waitForIncomingCallContext(uniqueId, Duration.ofSeconds(10));
assertNotNull(incomingCallContext);

// answer the call
AnswerCallOptions answerCallOptions
= new AnswerCallOptions(incomingCallContext, DISPATCHER_CALLBACK + String.format("?q=%s", uniqueId));
answerCallOptions.getCustomCallingContext().addSipUui("OBOuuivalue");
answerCallOptions.getCustomCallingContext().addSipX("XheaderOBO", "value");

AnswerCallResult answerCallResult
= Objects.requireNonNull(receiverAsyncClient.answerCallWithResponse(answerCallOptions).block())
.getValue();
assertNotNull(answerCallResult);
assertNotNull(answerCallResult.getCallConnectionAsync());
assertNotNull(answerCallResult.getCallConnectionProperties());
String receiverConnectionId = answerCallResult.getCallConnectionProperties().getCallConnectionId();
callDestructors.add(answerCallResult.getCallConnectionAsync());

// check events to caller side
CallConnected callerCallConnected
= waitForEvent(CallConnected.class, callerConnectionId, Duration.ofSeconds(10));
ParticipantsUpdated callerParticipantUpdatedEvent
= waitForEvent(ParticipantsUpdated.class, callerConnectionId, Duration.ofSeconds(10));
assertNotNull(callerCallConnected);
assertNotNull(callerParticipantUpdatedEvent);

// check events to receiver side
CallConnected receiverCallConnected
= waitForEvent(CallConnected.class, receiverConnectionId, Duration.ofSeconds(10));
ParticipantsUpdated receiverParticipantUpdatedEvent
= waitForEvent(ParticipantsUpdated.class, callerConnectionId, Duration.ofSeconds(10));
assertNotNull(receiverCallConnected);
assertNotNull(receiverParticipantUpdatedEvent);

// hang up the call.
answerCallResult.getCallConnectionAsync().hangUp(true).block();

// check if both parties had the call terminated.
CallDisconnected callerCallDisconnected
= waitForEvent(CallDisconnected.class, receiverConnectionId, Duration.ofSeconds(10));
CallDisconnected receiverCallDisconnected
= waitForEvent(CallDisconnected.class, callerConnectionId, Duration.ofSeconds(10));
assertNotNull(callerCallDisconnected);
assertNotNull(receiverCallDisconnected);

} catch (Exception ex) {
fail("Unexpected exception received", ex);
} finally {
if (!callDestructors.isEmpty()) {
try {
callDestructors.forEach(callConnection -> callConnection.hangUpWithResponse(true).block());
} catch (Exception ignored) {
// Some call might have been terminated during the test, and it will cause exceptions here.
// Do nothing and iterate to next call connection.
}
}
}
}

@ParameterizedTest
@MethodSource("com.azure.core.test.TestBase#getHttpClients")
@DisabledIfEnvironmentVariable(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,25 @@ public void answerCall() {
assertNotNull(answerCallResult);
}

@Test
public void answerCallWithResponseAndCustomContext() {
CallAutomationAsyncClient callAutomationAsyncClient = getCallAutomationAsyncClient(new ArrayList<>(
Collections.singletonList(new AbstractMap.SimpleEntry<>(generateCallProperties(CALL_CONNECTION_ID,
CALL_SERVER_CALL_ID, CALL_CALLER_ID, CALL_CALLER_DISPLAY_NAME, CALL_TARGET_ID, CALL_CONNECTION_STATE,
CALL_SUBJECT, CALL_CALLBACK_URL, null, null), 200))));

AnswerCallOptions answerCallOptions = new AnswerCallOptions(CALL_INCOMING_CALL_CONTEXT, CALL_CALLBACK_URL);
answerCallOptions.getCustomCallingContext().addSipUui("OBOuuivalue");
answerCallOptions.getCustomCallingContext().addSipX("XheaderOBO", "value");

Response<AnswerCallResult> answerCallResult
= callAutomationAsyncClient.answerCallWithResponse(answerCallOptions).block();

assertNotNull(answerCallResult);
assertEquals(200, answerCallResult.getStatusCode());
assertNotNull(answerCallResult.getValue());
}

@Test
public void answerCallWithResponse() {
CallAutomationAsyncClient callAutomationAsyncClient = getCallAutomationAsyncClient(new ArrayList<>(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["{\"to\":{\"kind\":\"communicationUser\",\"rawId\":\"REDACTED\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"from\":{\"kind\":\"communicationUser\",\"rawId\":\"REDACTED\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"serverCallId\":\"REDACTED\",\"callerDisplayName\":\"\",\"incomingCallContext\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\"}","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\",\"type\":\"Microsoft.Communication.CallConnected\",\"data\":{\"version\":\"2024-09-01-preview\",\"resultInformation\":{\"code\":200,\"subCode\":0,\"message\":\"\"},\"callConnectionId\":\"24002180-b059-4741-a392-a1aed1126925\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.CallConnected\"},\"time\":\"2024-12-27T21:04:58.0090118\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\",\"type\":\"Microsoft.Communication.ParticipantsUpdated\",\"data\":{\"participants\":[{\"identifier\":{\"rawId\":\"REDACTED\",\"kind\":\"communicationUser\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"isMuted\":false,\"isOnHold\":false},{\"identifier\":{\"rawId\":\"REDACTED\",\"kind\":\"communicationUser\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"isMuted\":false,\"isOnHold\":false}],\"sequenceNumber\":1,\"resultInformation\":{\"code\":200,\"subCode\":0,\"message\":\"\"},\"version\":\"2024-09-01-preview\",\"callConnectionId\":\"24002180-2951-4e61-aace-194bbd10bbb1\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.ParticipantsUpdated\"},\"time\":\"2024-12-27T21:04:58.0121227\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\",\"type\":\"Microsoft.Communication.CallConnected\",\"data\":{\"version\":\"2024-09-01-preview\",\"resultInformation\":{\"code\":200,\"subCode\":0,\"message\":\"\"},\"callConnectionId\":\"24002180-2951-4e61-aace-194bbd10bbb1\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.CallConnected\"},\"time\":\"2024-12-27T21:04:58.0090118\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\",\"type\":\"Microsoft.Communication.ParticipantsUpdated\",\"data\":{\"participants\":[{\"identifier\":{\"rawId\":\"REDACTED\",\"kind\":\"communicationUser\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"isMuted\":false,\"isOnHold\":false},{\"identifier\":{\"rawId\":\"REDACTED\",\"kind\":\"communicationUser\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"isMuted\":false,\"isOnHold\":false}],\"sequenceNumber\":1,\"resultInformation\":{\"code\":200,\"subCode\":0,\"message\":\"\"},\"version\":\"2024-09-01-preview\",\"callConnectionId\":\"24002180-b059-4741-a392-a1aed1126925\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.ParticipantsUpdated\"},\"time\":\"2024-12-27T21:04:58.0121227\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\",\"type\":\"Microsoft.Communication.CallDisconnected\",\"data\":{\"version\":\"2024-09-01-preview\",\"resultInformation\":{\"code\":200,\"subCode\":7000,\"message\":\"The conversation has ended. DiagCode: 0#7000.@\"},\"callConnectionId\":\"24002180-2951-4e61-aace-194bbd10bbb1\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.CallDisconnected\"},\"time\":\"2024-12-27T21:04:59.0901871\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\",\"type\":\"Microsoft.Communication.CallDisconnected\",\"data\":{\"version\":\"2024-09-01-preview\",\"resultInformation\":{\"code\":200,\"subCode\":5001,\"message\":\"This conversation has ended.. DiagCode: 0#5001.@\"},\"callConnectionId\":\"24002180-b059-4741-a392-a1aed1126925\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.CallDisconnected\"},\"time\":\"2024-12-27T21:04:59.3246749\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\"}]"]

0 comments on commit b6caa39

Please sign in to comment.