Skip to content

Commit

Permalink
fix(calling-sdk): add ip4 candidate in SDP if SDP does not have ip4 c…
Browse files Browse the repository at this point in the history
…andidate (#4091)
  • Loading branch information
rsarika authored Feb 14, 2025
1 parent 7a02894 commit 444424d
Show file tree
Hide file tree
Showing 11 changed files with 432 additions and 34 deletions.
14 changes: 13 additions & 1 deletion docs/samples/calling/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const cfaDataElem = document.querySelector('#callforwardalways-data');
const makeCallBtn = document.querySelector('#create-call-action');
const muteElm = document.getElementById('mute_button');
const bnrButton = document.getElementById('bnr-button');
const uploadLogsResultElm = document.getElementById('upload-logs-result');

let base64;
let audio64;
Expand Down Expand Up @@ -117,6 +118,17 @@ const getOptionValue = (select) => {
return selected ? selected.value : undefined;
};

async function uploadLogs() {
try {
await callingClient.uploadLogs();
console.log('Logs uploaded successfully');
uploadLogsResultElm.innerText = 'Logs uploaded successfully';
} catch (error) {
console.error('Failed to upload logs:', error);
uploadLogsResultElm.innerText = 'Failed to upload logs';
}
}

function getMediaSettings() {
const settings = {};

Expand Down Expand Up @@ -245,7 +257,7 @@ async function initCalling(e) {
}

const loggerConfig = {
level: 'info'
level: 'info',
}

const {region, country, guestName} = credentialsFormElm.elements;
Expand Down
2 changes: 2 additions & 0 deletions docs/samples/calling/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<section>
<h2>Calling SDK </h2>
<p>This is the kitchen sink sample for the calling webrtc SDK.</p>
<P>If you face any issues, please click <button id="upload-logs" type="button" onclick="uploadLogs()">Upload Logs</button></p>
<p id="upload-logs-result"></p>
</section>

<!-- ############################## ############################## ############################## -->
Expand Down
21 changes: 20 additions & 1 deletion packages/calling/src/CallingClient/CallingClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
/* eslint-disable @typescript-eslint/no-shadow */
import * as Media from '@webex/internal-media-core';
import {Mutex} from 'async-mutex';
import {filterMobiusUris, handleCallingClientErrors, validateServiceData} from '../common/Utils';
import {v4 as uuid} from 'uuid';
import {
filterMobiusUris,
handleCallingClientErrors,
uploadLogs,
validateServiceData,
} from '../common/Utils';
import {LOGGER, LogContext} from '../Logger/types';
import SDKConnector from '../SDKConnector';
import {ClientRegionInfo, ISDKConnector, ServiceHost, WebexSDK} from '../SDKConnector/types';
Expand Down Expand Up @@ -501,6 +507,19 @@ export class CallingClient extends Eventing<CallingClientEventTypes> implements

return connectCall;
}

/**
* uploads logs to backend for trouble shooting
* @param data
*/
public async uploadLogs(data: {feedbackId?: string} = {}) {
if (!data.feedbackId) {
// spread the data object to avoid mutation
data = {...data, feedbackId: uuid()};
}

return uploadLogs(this.webex, data);
}
}

/**
Expand Down
17 changes: 15 additions & 2 deletions packages/calling/src/CallingClient/calling/call.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2835,6 +2835,7 @@ describe('Supplementary Services tests', () => {

/* A spy on handleCallErrors to check whether it is being invoked or not depending on tests */
const handleErrorSpy = jest.spyOn(Utils, 'handleCallErrors');
const uploadLogsSpy = jest.spyOn(Utils, 'uploadLogs');
const transferLoggingContext = {
file: 'call',
method: 'completeTransfer',
Expand Down Expand Up @@ -2866,7 +2867,7 @@ describe('Supplementary Services tests', () => {
});

it('Handle successful consult transfer case ', async () => {
expect.assertions(9);
expect.assertions(10);
const responsePayload = <SSResponse>(<unknown>{
statusCode: 200,
body: mockResponseBody,
Expand Down Expand Up @@ -2904,6 +2905,7 @@ describe('Supplementary Services tests', () => {
expect(call['callStateMachine'].state.value).toStrictEqual('S_RECV_CALL_DISCONNECT');
expect(secondCall['callStateMachine'].state.value).toStrictEqual('S_RECV_CALL_DISCONNECT');
expect(handleErrorSpy).not.toBeCalled();
expect(uploadLogsSpy).not.toBeCalled();
expect(infoSpy).toHaveBeenCalledWith(
`Initiating Consult transfer between : ${call.getCallId()} and ${secondCall.getCallId()}`,
transferLoggingContext
Expand All @@ -2915,7 +2917,7 @@ describe('Supplementary Services tests', () => {
});

it('Handle successful blind transfer case ', async () => {
expect.assertions(7);
expect.assertions(8);
const responsePayload = <SSResponse>(<unknown>{
statusCode: 200,
body: mockResponseBody,
Expand Down Expand Up @@ -2948,6 +2950,7 @@ describe('Supplementary Services tests', () => {
/* We should return back to S_RECV_CALL_DISCONNECT state */
expect(call['callStateMachine'].state.value).toStrictEqual('S_RECV_CALL_DISCONNECT');
expect(handleErrorSpy).not.toBeCalled();
expect(uploadLogsSpy).not.toBeCalled();
expect(infoSpy).toHaveBeenCalledWith(
`Initiating Blind transfer with : ${transfereeNumber}`,
transferLoggingContext
Expand Down Expand Up @@ -2985,6 +2988,10 @@ describe('Supplementary Services tests', () => {
'completeTransfer',
'call'
);
expect(uploadLogsSpy).toHaveBeenCalledWith(webex, {
correlationId: call.getCorrelationId(),
callId: call.getCallId(),
});
/* check whether error event is being emitted by sdk */
expect(emitSpy).toBeCalledOnceWith(CALL_EVENT_KEYS.TRANSFER_ERROR, expect.any(CallError));
expect(warnSpy).toHaveBeenCalledWith(
Expand Down Expand Up @@ -3031,6 +3038,10 @@ describe('Supplementary Services tests', () => {
'completeTransfer',
'call'
);
expect(uploadLogsSpy).toHaveBeenCalledWith(webex, {
correlationId: call.getCorrelationId(),
callId: call.getCallId(),
});
/* check whether error event is being emitted by sdk */
expect(emitSpy).toHaveBeenCalledWith(CALL_EVENT_KEYS.TRANSFER_ERROR, expect.any(CallError));
expect(warnSpy).toHaveBeenCalledWith(
Expand All @@ -3057,6 +3068,7 @@ describe('Supplementary Services tests', () => {
expect(call['callStateMachine'].state.value).toStrictEqual('S_CALL_ESTABLISHED');
expect(secondCall['callStateMachine'].state.value).toStrictEqual('S_CALL_ESTABLISHED');
expect(handleErrorSpy).not.toBeCalled();
expect(uploadLogsSpy).not.toBeCalled();
expect(requestSpy).not.toBeCalled();
expect(warnSpy).toBeCalledOnceWith(
`Invalid information received, transfer failed for correlationId: ${call.getCorrelationId()}`,
Expand All @@ -3074,6 +3086,7 @@ describe('Supplementary Services tests', () => {
expect(call['callStateMachine'].state.value).toStrictEqual('S_CALL_ESTABLISHED');
expect(secondCall['callStateMachine'].state.value).toStrictEqual('S_CALL_ESTABLISHED');
expect(handleErrorSpy).not.toBeCalled();
expect(uploadLogsSpy).not.toBeCalled();
expect(requestSpy).not.toBeCalled();
expect(warnSpy).toBeCalledOnceWith(
`Invalid information received, transfer failed for correlationId: ${call.getCorrelationId()}`,
Expand Down
81 changes: 81 additions & 0 deletions packages/calling/src/CallingClient/calling/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import ExtendedError from '../../Errors/catalog/ExtendedError';
import {ERROR_LAYER, ERROR_TYPE, ErrorContext} from '../../Errors/types';
import {
handleCallErrors,
modifySdpForIPv4,
parseMediaQualityStatistics,
serviceErrorCodeHandler,
uploadLogs,
} from '../../common/Utils';
import {
ALLOWED_SERVICES,
Expand Down Expand Up @@ -968,6 +970,10 @@ export class Call extends Eventing<CallEventTypes> implements ICall {

try {
const response = await this.post(message);
log.log(`handleOutgoingCallSetup: Response: ${JSON.stringify(response)}`, {
file: CALL_FILE,
method: this.handleOutgoingCallSetup.name,
});

log.log(`handleOutgoingCallSetup: Response code: ${response.statusCode}`, {
file: CALL_FILE,
Expand Down Expand Up @@ -995,6 +1001,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleOutgoingCallSetup.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}

Expand Down Expand Up @@ -1064,6 +1075,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleOutgoingCallSetup.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}

Expand Down Expand Up @@ -1133,6 +1149,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleOutgoingCallSetup.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}

Expand Down Expand Up @@ -1251,6 +1272,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleOutgoingCallAlerting.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}

Expand Down Expand Up @@ -1330,6 +1356,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleOutgoingCallConnect.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}

Expand Down Expand Up @@ -1496,6 +1527,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleCallEstablished.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}, DEFAULT_SESSION_TIMER);
}
Expand Down Expand Up @@ -1675,6 +1711,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleRoapEstablished.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
} else {
log.info('Notifying internal-media-core about ROAP OK message', {
Expand Down Expand Up @@ -1750,6 +1791,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleRoapError.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}

Expand Down Expand Up @@ -1821,6 +1867,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleOutgoingRoapOffer.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}

Expand Down Expand Up @@ -1869,6 +1920,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.handleOutgoingRoapAnswer.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
}

Expand Down Expand Up @@ -2357,6 +2413,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.completeTransfer.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
} else if (transferType === TransferType.CONSULT && transferCallId) {
/* Consult transfer */
Expand Down Expand Up @@ -2402,6 +2463,11 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
this.completeTransfer.name,
CALL_FILE
);

uploadLogs(this.webex, {
correlationId: this.correlationId,
callId: this.callId,
});
}
} else {
log.warn(
Expand Down Expand Up @@ -2498,18 +2564,32 @@ export class Call extends Eventing<CallEventTypes> implements ICall {

case RoapScenario.OFFER: {
// TODO: Remove these after the Media-Core adds the fix
// Check if at least one IPv6 "c=" line is present
log.info(`before modifying sdp: ${event.roapMessage.sdp}`, {
file: CALL_FILE,
method: this.mediaRoapEventsListener.name,
});

event.roapMessage.sdp = modifySdpForIPv4(event.roapMessage.sdp);

const sdpVideoPortZero = event.roapMessage.sdp.replace(
/^m=(video) (?:\d+) /gim,
'm=$1 0 '
);

log.info(`after modification sdp: ${sdpVideoPortZero}`, {
file: CALL_FILE,
method: this.mediaRoapEventsListener.name,
});

event.roapMessage.sdp = sdpVideoPortZero;
this.localRoapMessage = event.roapMessage;
this.sendCallStateMachineEvt({type: 'E_SEND_CALL_SETUP', data: event.roapMessage});
break;
}

case RoapScenario.ANSWER:
event.roapMessage.sdp = modifySdpForIPv4(event.roapMessage.sdp);
this.localRoapMessage = event.roapMessage;
this.sendMediaStateMachineEvt({type: 'E_SEND_ROAP_ANSWER', data: event.roapMessage});
break;
Expand All @@ -2519,6 +2599,7 @@ export class Call extends Eventing<CallEventTypes> implements ICall {
break;

case RoapScenario.OFFER_RESPONSE:
event.roapMessage.sdp = modifySdpForIPv4(event.roapMessage.sdp);
this.localRoapMessage = event.roapMessage;
this.sendMediaStateMachineEvt({type: 'E_SEND_ROAP_OFFER', data: event.roapMessage});
break;
Expand Down
Loading

0 comments on commit 444424d

Please sign in to comment.