Skip to content

Instantly share code, notes, and snippets.

@manniru
Forked from phanmn/sipTcpTransport.js
Created November 11, 2024 00:00
Show Gist options
  • Save manniru/c33c50c6782f4cae89fd641d09e9edf0 to your computer and use it in GitHub Desktop.
Save manniru/c33c50c6782f4cae89fd641d09e9edf0 to your computer and use it in GitHub Desktop.
SIP.js TCP Transport Implementation
const SIP = require('sip.js');
const net = require('net');
const TransportStatus = {
STATUS_CONNECTING: 'STATUS_CONNECTING',
STATUS_CONNECTED: 'STATUS_CONNECTED',
STATUS_CLOSING: 'STATUS_CLOSING',
STATUS_CLOSED: 'STATUS_CLOSED'
};
class SipTcpTransport extends SIP.Transport {
constructor(logger, options) {
super(logger, options);
this.type = SIP.TypeStrings.Transport;
this.status = TransportStatus.STATUS_CONNECTING;
this.configuration = options;
}
isConnected() {
return this.status === TransportStatus.STATUS_CONNECTED;
}
connectPromise(options) {
let socket = new net.Socket();
this._tcpSocket = socket;
let { ip, port } = this.configuration;
let promise = new Promise((resolve, reject) => {
socket.connect(port, ip, {}, () => {
this.status = TransportStatus.STATUS_CONNECTED;
this.emit('connected');
resolve({ overrideEvent: true });
});
});
socket.setEncoding('utf8');
this.boundOnMessage = this.onMessage.bind(this);
this.boundOnError = this.onError.bind(this);
this.boundOnClose = this.onClose.bind(this);
socket.on('data', this.boundOnMessage);
socket.on('error', this.boundOnError);
socket.on('close', this.boundOnClose);
return promise;
}
sendPromise(message, options) {
if (!this._tcpSocket) {
return Promise.reject();
}
this._tcpSocket.write(message);
return Promise.resolve({ msg: message });
}
disconnectPromise(options) {
if (!this._tcpSocket) {
return Promise.reject();
}
this._tcpSocket.destroy();
return Promise.resolve();
}
onMessage(data) {
let finishedData;
if (/^(\r\n)+$/.test(data)) {
// this.clearKeepAliveTimeout();
// if (this.configuration.traceSip === true) {
// this.logger.log(
// 'received WebSocket message with CRLF Keep Alive response'
// );
// }
return;
} else if (!data) {
this.logger.warn('received empty message, message discarded');
return;
} else if (typeof data !== 'string') {
// WebSocket binary message.
// try {
// // the UInt8Data was here prior to types, and doesn't check
// finishedData = String.fromCharCode.apply(null, (new Uint8Array(data) as unknown as Array<number>));
// } catch (err) {
// this.logger.warn("received WebSocket binary message failed to be converted into string, message discarded");
// return;
// }
// if (this.configuration.traceSip === true) {
// this.logger.log("received WebSocket binary message:\n\n" + data + "\n");
// }
} else {
// WebSocket text message.
// if (this.configuration.traceSip === true) {
// this.logger.log("received WebSocket text message:\n\n" + data + "\n");
// }
finishedData = data;
}
this.emit('message', finishedData);
}
onError(e) {
this.logger.warn('Transport error: ' + e);
this.emit('transportError');
}
onClose(e) {
this.logger.log(
'TCPSocket disconnected (code: ' +
e.code +
(e.reason ? '| reason: ' + e.reason : '') +
')'
);
this.status = TransportStatus.STATUS_CLOSED;
this.emit('disconnected', { code: e.code, reason: e.reason });
}
}
module.exports = SipTcpTransport;
const SIP = require('sip.js');
const SipTcpTransport = require('./sipTcpTransport');
let uri = '[email protected]'; // Update your sip uri
let authorizationUser = 'xxxx'; // Update your sip user
let password = 'yyyyyyy'; // Update your sip password
let ip = '123.456.789.012'; // Update your sip ip
var userAgent = new SIP.UA({
uri,
authorizationUser,
password,
hackViaTcp: true,
contactTransport: 'tcp',
transportConstructor: SipTcpTransport,
transportOptions: {
ip,
port: 5060,
},
});
userAgent.on('invite', (session) => session.accept());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment