I'm trying to make a call from client side(browser) to FreeSWITCH server using this libs:
And also I use React.
When I make a call I successfully invite destination URI.
After click button and call function callSip our SessionState changes to Ringing, then successful invitation, then SessionState is "Answered" and after that the function onAccept in requestDelegate object is run, but no connection is established because the SessionState goes to "Ended"
After all I have this log.
How to establish a voice connection so that it does not break off after receiving a call? How to add a remote sound from sip to an audio ref element?
const CallList: React.FC<Props> = (props) => {
const [userURI, setUserURI] = useState<URI | null>(null);
const audioRef = useRef(null);
useEffect(() => {
const uri = UserAgent.makeURI("sip:9012@serverpoint");
if (!uri) {
throw new Error("Failed to create URI");
}
setUserURI(uri);
return () => {
console.log("unmount");
};
}, []);
if (!userURI) {
return <div></div>;
}
const userAgentOptions: UserAgentOptions = {
uri: userURI,
authorizationPassword: "pasw",
authorizationUsername: "9012",
transportOptions: {
server: "ws://serverpoint",
},
};
const userAgent = new UserAgent(userAgentOptions);
const target = UserAgent.makeURI("sip:9005@serverpoint");
const session = new Inviter(userAgent, target as URI);
// Setup session state change handler
session.stateChange.addListener((newState: SessionState) => {
switch (newState) {
case SessionState.Establishing:
alert("Ringing");
break;
case SessionState.Established:
alert("Answered");
break;
case SessionState.Terminated:
alert("Ended");
break;
}
});
// Options including delegate to capture response messages
const inviteOptions: InviterInviteOptions = {
requestDelegate: {
onAccept: (response) => {
console.log(response.message);
alert("Positive response");
console.log("Positive response = " + response);
},
onReject: (response) => {
console.log("Negative response = " + response);
},
},
sessionDescriptionHandlerOptions: {
constraints: {
audio: true,
video: false,
},
},
};
const callSIP = () => {
session
.invite(inviteOptions)
.then((request: OutgoingInviteRequest) => {
alert("Successfully sent INVITE");
alert("INVITE request = " + request);
})
.catch((error: Error) => {
console.log("Failed to send INVITE");
});
};
const stop = () =>
setTimeout(() => {
userAgent
.stop()
.then(() => {
console.log("Stopped");
})
.catch((error) => {
console.error("Failed to stop");
});
}, 5000);
userAgent
.start()
.then(() => {
console.log("Connected");
const registerer = new Registerer(userAgent);
registerer.stateChange.addListener((newStat) => {
console.log(newStat);
// switch (newState) {
// case RegistererState.Registered:
// console.log("Registered");
// break;
// case RegistererState.Unregistered:
// console.log("Unregistered");
// break;
// case RegistererState.Terminated:
// console.log("Terminated");
// break;
// }
});
registerer
.register()
.then((request) => {
alert("Successfully sent REGISTER");
alert("Sent request = " + request);
})
.catch((error) => {
console.error("Failed to send REGISTER");
});
if (registerer.state === "Registered") {
// Currently registered
alert("Registered");
}
// stop();
})
.catch((error) => {
console.error("Failed to connect");
});
const panes = [
{
menuItem: "Calls",
render: () => (
<Tab.Pane loading={false}>
<List celled>
<List.Item>
<audio ref={audioRef} id="remote-audio"></audio>
</List.Item>
{props.data.map((item) => (
<List.Item key={v4()} onClick={callSIP}>
<Image avatar src="" />
<List.Content>
<List.Header>
{item.location} - {item.number}
</List.Header>
{item.timestamp}
</List.Content>
<List.Content floated="right">
<Button>Call</Button>
</List.Content>
</List.Item>
))}
</List>
</Tab.Pane>
),
},
{
menuItem: "tab 2",
render: () => <Tab.Pane>Tab 2 Content</Tab.Pane>,
},
];
return (
<Container>
<Tab panes={panes} />
</Container>
);
};
export default CallList;
After session is established you can set medias, example: https://github.com/onsip/SIP.js/blob/master/src/platform/web/simple-user/simple-user.ts#L750