patches 19/11/2024

This commit is contained in:
2024-11-19 15:46:52 +07:00
parent c501ebcbb6
commit a3e37bd7cd
9 changed files with 1411 additions and 107 deletions

View File

@@ -802,6 +802,15 @@ public interface Bass extends Library {
// gak bisa
int BASS_StreamCreate(int freq, int chans, int flags, int proc, Pointer user);
class Utils {
public static int LOBYTE(int n) { return n&0xff; }
public static int HIBYTE(int n) { return (n>>8)&0xff; }
public static int LOWORD(int n) { return n&0xffff; }
public static int HIWORD(int n) { return (n>>16)&0xffff; }
public static int MAKEWORD(int a, int b) { return (a&0xff)|((b&0xff)<<8); }
public static int MAKELONG(int a, int b) { return (a&0xffff)|(b<<16); }
}
@SuppressWarnings("DataFlowIssue")
default String GetBassError(String function, int err) {
if (err==0)

View File

@@ -12,7 +12,6 @@ import peers.media.SoundSource;
* @author rdkartono
*
*/
@SuppressWarnings("FieldCanBeLocal")
public class BassFileReader implements SoundSource {
// Device = 0 --> no sound
private final int bassdev = 0;
@@ -29,7 +28,7 @@ public class BassFileReader implements SoundSource {
// Mixer create flag BASS_STREAM_DECODE karena untuk ambil data aja, bukan playback
private final int mixerflag = Bass.BASS_STREAM_DECODE;
// Mixer_AddChannel flag BAS_STREAM_AUTOFREE , supaya kalau channel habis & selesai, channel free sendiri
//private final int addchannelflag = BassLibrary.Constant.BASS_STREAM_AUTOFREE;
//private final int addchannelflag = Bass.BASS_STREAM_AUTOFREE;
private final int addchannelflag = 0;
// sekali baca data, 256 bytes
@@ -43,10 +42,9 @@ public class BassFileReader implements SoundSource {
// indicator if file opened, mixer created, and file plugged to mixer
private boolean channeladded = false;
private final BassFileReaderListener listener; // belum kepake
private BassFileReaderListener listener; // belum kepake
private final Bass BASS = Bass.Instance;
private final BassMix BASSMIX = BassMix.Instance;
public BassFileReader(final String filename, BassFileReaderListener listener) {
this.filename = filename;
this.listener = listener;
@@ -127,10 +125,12 @@ public class BassFileReader implements SoundSource {
return null;
}
public void AddListener(BassFileReaderListener listener) {
this.listener = listener;
}
private void logger_error(String msg) {
Logger.error(msg);
}
private void logger_info(String msg) {

View File

@@ -0,0 +1,265 @@
package Audio;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import peers.media.AbstractSoundManager;
/**
* Pengganti /AxisAudio/src/net/sourceforge/peers/javaxsound/JavaxSoundManager.java
* karena terbatas codec nya
* @author rdkartono
*
*/
@SuppressWarnings({"unused", "FieldCanBeLocal", "BusyWait", "ConditionalBreakInInfiniteLoop"})
public class BassSoundManager extends AbstractSoundManager {
private final Bass BASS = Bass.Instance;
private BassSoundManagerListener bsml;
private final int record_device, play_device;
private final int init_freq = 48000;
private final int samplingrate = 8000;
private final int play_initflag = Bass.BASS_DEVICE_16BITS | Bass.BASS_DEVICE_MONO;
private final int streamcreate_flag = 0;
private final int recordstart_flag = 0;
private final int read_size = 320;
private int streamhandle, recordhandle;
public BassSoundManager(int outputdevice , int inputdevice, BassSoundManagerListener listener) {
this.bsml = listener;
this.record_device = inputdevice;
this.play_device = outputdevice;
}
public void AddListener(BassSoundManagerListener listener) {
this.bsml = listener;
}
public boolean IsInitialized() {
return (streamhandle!=0) && (recordhandle!=0);
}
public void setInputChannelVolume(int value) {
if (value<0) value = 0;
if (value>100) value = 100;
if (!BASS.BASS_RecordSetInput(record_device, Bass.BASS_INPUT_ON, value/100.0f)) {
// gagal
logger_error("BASS_RecordSetInput error = "+BASS.GetBassError("BASS_RecordSetInput"));
}
}
public int getInputChannelVolume() {
Bass.FloatValue vol = new Bass.FloatValue();
int code = BASS.BASS_RecordGetInput(record_device, vol);
if (code==-1) {
logger_error("BASS_RecordGetInput error = "+BASS.GetBassError("BASS_RecordGetInput"));
return 0;
} else {
int value = (int)(vol.value * 100);
if (value<0) value = 0;
if (value>100) value = 100;
return value;
}
}
public void setOutputChannelVolume(int value) {
if (value<0) value = 0;
if (value>100) value = 100;
if (!BASS.BASS_SetVolume(value/100.0f)) {
logger_error("BASS_SetVolume error = "+BASS.GetBassError("BASS_SetVolume"));
}
}
public int getOutputChannelVolume() {
float fl = BASS.BASS_GetVolume() ;
if (fl==-1) {
logger_error("BASS_GetVolume error = "+BASS.GetBassError("BASS_GetVolume"));
return 0;
} else {
int value = (int)(fl * 100);
if (value<0) value = 0;
if (value>100) value = 100;
return value;
}
}
@Override
public byte[] readData() {
if (recordhandle!=0) {
int rs;
Pointer buf = new Memory(read_size);
while(true) {
if (BASS.BASS_ChannelIsActive(recordhandle)!=Bass.BASS_ACTIVE_PLAYING) break;
rs = BASS.BASS_ChannelGetData(recordhandle, buf, read_size);
if (rs<0) {
// ada error
if (bsml!=null) bsml.log_error("readData BASS_ChannelGetData error = "+BASS.GetBassError("BASS_ChannelGetData"));
return null;
} else if (rs>0) {
// ada hasil
byte[] result = buf.getByteArray(0, rs);
if (bsml!=null) bsml.ReadToRTP(rs, result);
return result;
} else {
// nol
try {
Thread.sleep(2);
} catch (InterruptedException e) {
return null;
}
}
}
}
return null;
}
@Override
public void init() {
if (streamhandle!=0 || recordhandle!=0) close();
if (BASS.BASS_GetVersion()!=0) {
BASS.BASS_Init(play_device, init_freq, play_initflag);
BASS.BASS_RecordInit(record_device);
recordhandle = BASS.BASS_RecordStart(samplingrate, 1, recordstart_flag,null, null);
if (recordhandle!=0) {
BASS.BASS_ChannelSetSync(recordhandle, Bass.BASS_SYNC_DEV_FAIL, 0, devfail, null);
BASS.BASS_ChannelSetSync(recordhandle, Bass.BASS_SYNC_STALL, 0, bufferinginformation, null);
if (BASS.BASS_ChannelStart(recordhandle)) {
logger_info("InputChannel Started");
} else logger_error("BASS_ChannelStart recordhandle error = "+BASS.GetBassError("BASS_ChannelStart"));
} else logger_error("BASS_RecordStart error = "+BASS.GetBassError("BASS_RecordStart"));
streamhandle = BASS.BASS_StreamCreate(samplingrate, 1, streamcreate_flag, Bass.STREAMPROC_PUSH, null);
if (streamhandle!=0) {
BASS.BASS_ChannelSetSync(streamhandle, Bass.BASS_SYNC_DEV_FAIL, 0, devfail, null);
BASS.BASS_ChannelSetSync(streamhandle, Bass.BASS_SYNC_STALL, 0, bufferinginformation, null);
if (BASS.BASS_ChannelStart(streamhandle)) {
logger_info("OutputChannel Started");
} else logger_error("BASS_ChannelStart streamhandle error = "+BASS.GetBassError("BASS_ChannelStart"));
} else logger_error("BASS_StreamCreate error = "+BASS.GetBassError("BASS_StreamCreate"));
if (IsInitialized()) {
logger_info("init complete");
new Thread(() -> {
int inputvalue;
int outputvalue;
while(IsInitialized()) {
inputvalue = BASS.BASS_ChannelGetLevel(recordhandle);
outputvalue = BASS.BASS_ChannelGetLevel(streamhandle);
if (inputvalue>=0) {
inputvalue = (int) ((Bass.Utils.LOWORD(inputvalue) * 1.0f)/32768);
if (bsml!=null) bsml.ChannelLevel(true, inputvalue);
}
if (outputvalue>=0) {
outputvalue = (int) ((Bass.Utils.LOWORD(outputvalue) * 1.0f)/32768);
if (bsml!=null) bsml.ChannelLevel(false, outputvalue);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
logger_info("ChannelLevel thread interrupted");
}
}
}).start();
if (bsml!=null) bsml.Opened();
return;
}
logger_info("init failed");
close();
}
}
@Override
public void close() {
boolean somethingclosed = false;
if (streamhandle!=0) {
BASS.BASS_StreamFree(streamhandle);
streamhandle = 0;
somethingclosed = true;
}
if (recordhandle!=0) {
BASS.BASS_ChannelStop(recordhandle);
recordhandle = 0;
somethingclosed = true;
}
if (somethingclosed) {
if (bsml!=null) bsml.Closed();
}
}
@Override
public int writeData(byte[] buffer, int offset, int length) {
if (streamhandle!=0) {
Pointer buf = new Memory(length);
buf.write(0, buffer, 0, length);
int rs = BASS.BASS_StreamPutData(streamhandle, buf, length);
if (rs==-1) {
if (bsml!=null) bsml.log_error("writeData BASS_StreamPutData error = "+BASS.GetBassError("BASS_StreamPutData"));
} else {
if (bsml!=null) bsml.WriteFromRTP(length, buffer);
return length;
}
}
return 0;
}
private void logger_error(String msg) {
if (bsml!=null) bsml.log_error(msg);
}
private void logger_info(String msg) {
if (bsml!=null) bsml.log_info(msg);
}
Bass.SYNCPROC devfail = new Bass.SYNCPROC() {
@Override
public void SYNCPROC(int handle, int channel, int data, Pointer user) {
if (channel==streamhandle) {
if (bsml!=null) bsml.DeviceFailure("OutputChannel stops unexpectedly");
} else if (channel==recordhandle) {
if (bsml!=null) bsml.DeviceFailure("InputChannel stops unexpectedly");
}
}
};
Bass.SYNCPROC bufferinginformation = new Bass.SYNCPROC() {
@Override
public void SYNCPROC(int handle, int channel, int data, Pointer user) {
if (channel==streamhandle) {
if (bsml!=null) bsml.BufferingInformation("OutputChannel "+ (data==0?"Stalled":"Resumed"));
} else if (channel==recordhandle) {
if (bsml!=null) bsml.BufferingInformation("InputChannel "+ (data==0?"Stalled":"Resumed"));
}
}
};
}

View File

@@ -0,0 +1,18 @@
package Audio;
/**
* Java Event untuk BassSoundManager
* @author rdkartono
*
*/
public interface BassSoundManagerListener {
public void Opened();
public void Closed();
public void WriteFromRTP(int length, byte[] pcmdata);
public void ReadToRTP(int length, byte[] pcmdata);
public void log_info(String msg);
public void log_error(String msg);
public void DeviceFailure(String msg);
public void BufferingInformation(String msg);
public void ChannelLevel(boolean is_input, int value);
}

View File

@@ -1,6 +1,32 @@
public class Main {
public static void main(String[] args) {
import org.pmw.tinylog.Logger;
System.out.println("Hello, World!");
public class Main {
private static String serverAddress="100.64.0.3";
private static String Username="user1";
private static String Password="12345678";
public static void main(String[] args) {
GetArguments(args);
Logger.info("Server Address: "+serverAddress);
Logger.info("Username: "+Username);
Logger.info("Password: "+Password);
}
private static void GetArguments(String[] args) {
if (args != null){
for(String a : args){
if (a.startsWith("--serverip=")){
serverAddress=a.substring(11);
}
else if (a.startsWith("--username=")){
Username=a.substring(11);
}
else if (a.startsWith("--password=")){
Password=a.substring(11);
}
}
}
}
}

30
src/common.java Normal file
View File

@@ -0,0 +1,30 @@
import peers.sip.syntaxencoding.SipHeaderFieldName;
import peers.sip.syntaxencoding.SipHeaderFieldValue;
import peers.sip.syntaxencoding.SipHeaders;
public class common {
public static boolean ValidString(String value){
if (value!=null){
return !value.isEmpty();
}
return false;
}
public static boolean ValidPortNumber(int value){
return value>0 && value<65536;
}
public static String GetSIPHeaderValue(SipHeaders head, String headername) {
if (head!=null) {
SipHeaderFieldName _fn = new SipHeaderFieldName(headername);
if (head.contains(_fn)) {
SipHeaderFieldValue _fv = head.get(_fn);
if (_fv!=null) {
return _fv.getValue();
}
}
}
return null;
}
}

998
src/jSIPClient.java Normal file
View File

@@ -0,0 +1,998 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import Audio.BassFileReader;
import Audio.BassFileReaderListener;
import Audio.BassSoundManager;
import Audio.BassSoundManagerListener;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import lombok.Getter;
import org.pmw.tinylog.Logger;
import peers.Config;
import peers.media.MediaManager;
import peers.media.MediaMode;
import peers.sip.Utils;
import peers.sip.core.useragent.SipListener;
import peers.sip.core.useragent.UserAgent;
import peers.sip.syntaxencoding.SipHeaders;
import peers.sip.syntaxencoding.SipURI;
import peers.sip.syntaxencoding.SipUriSyntaxException;
import peers.sip.transactionuser.Dialog;
import peers.sip.transactionuser.DialogManager;
import peers.sip.transport.SipRequest;
import peers.sip.transport.SipResponse;
@SuppressWarnings({"unused", "UnusedReturnValue"})
public class jSIPClient {
public jSIPClient() {
gs = new GsonBuilder()
.setPrettyPrinting()
.create();
runningfolder = new File("").getAbsolutePath();
load_config();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
raise_log_event("jSIPClient ShutdownHook called");
save_config();
HangUp();
Disconnect();
}));
}
public CustomConfig cc = new CustomConfig();
private EventManager em;
private final Gson gs;
private final String runningfolder;
private javaSipEvents jse;
private BassFileReaderListener bfrl;
private final ExecutorService exec = Executors.newSingleThreadExecutor();
/**
* Connect to SIP Server
* @param serverip SIP Server IP
* @param username Username to register
* @param password Password to register
* @param localip use if need to specify which Network Adapter to use
* @return true if parameter completed
*/
public boolean Connect(String serverip, String username, String password, String localip) {
Disconnect();
if (cc==null) {
System.out.println("Creating Custom Config");
cc = new CustomConfig();
} else System.out.println("Custom Config already created");
if (common.ValidString(serverip)) cc.setDomain(serverip);
if (common.ValidString(username)) cc.setUserPart(username);
if (common.ValidString(password)) cc.setPassword(password);
if (common.ValidString(localip)) cc.SetLocalInetAddress(localip);
em = new EventManager(cc);
return false;
}
public void SetJavaSipEvent(javaSipEvents xx) {
this.jse = xx;
}
public void SetBassFileReaderListener(BassFileReaderListener xx) {
this.bfrl = xx;
}
/**
* Set Input Volume
* @param value 0 - 100
*/
public void setInputVolume(int value) {
if (em!=null) em.setInputVolume(value);
}
/**
* Get Input Volume
* @return 0 - 100
*/
public int getInputVolume() {
if (em!=null) {
return em.getInputVolume();
} else return 0;
}
/**
* Set Output Volume
* @param value 0 - 100
*/
public void setOutputVolume(int value) {
if (em!=null) em.setOutputVolume(value);
}
/**
* Get Output Volum
* @return 0 - 100
*/
public int getOutputVolume() {
if (em!=null) {
return em.getOutputVolume();
} else return 0;
}
/**
* Disconnect from SIP Server
*/
public void Disconnect() {
if (em!=null) {
em.Close();
em = null;
}
}
/**
* HangUp current call
* @return true if success
*/
public boolean HangUp() {
if (em!=null) {
if (em.IsCreated()) {
if (em.CallingInProgress()) {
em.HangUp();
return true;
} else raise_log_event("HangUp failed, no call made");
} else raise_log_event("HangUp failed, EventManager not created");
} else raise_log_event("HangUp failed, Connect first");
return false;
}
/**
* Stream an audiofile to somebody
* @param target target to call
* @param filename file to stream
* @return true if can be streamed
*/
public boolean StreamFile(String target, String filename) {
if (em!=null) {
if (em.IsCreated()) {
if (cc!=null) {
cc.setMediaFile(filename);
cc.setMediaMode(MediaMode.file);
em.Call(target);
em.AddListener(bfrl);
return true;
} else raise_log_event("StreamFile failed, Custom Config not created");
} else raise_log_event("StreamFile failed, EventManager not created");
} else raise_log_event("StreamFile failed, Connect first");
return false;
}
/**
* Call somebody
* @param target target to call
* @return true if can be called
*/
public boolean Call(String target) {
if (em!=null) {
if (em.IsCreated()) {
if (cc!=null) {
cc.setMediaMode(MediaMode.captureAndPlayback);
em.Call(target);
return true;
} else raise_log_event("Call failed, Custom Config not created");
} else raise_log_event("Call failed, EventManager not created");
} else raise_log_event("Call failed, Connect first");
return false;
}
/**
* Accept Incoming Call
* @param req SIP_Request object
* @return true if call can be accepted
*/
public boolean AcceptIncomingCall(SIP_Request req) {
if (em!=null) {
if (em.IsCreated()) {
if (req!=null) {
cc.setMediaMode(MediaMode.captureAndPlayback);
em.AcceptCall(req.getReq());
return true;
} else raise_log_event("AcceptIncomingCall failed, SIP_Request is null");
} else raise_log_event("AcceptIncomingCall failed, EventManager not created");
} else raise_log_event("AcceptIncomingCall failed, Connect first");
return false;
}
/**
* Send DTMF code
* @param code code to send
* @return true if can be send
*/
public boolean SendDTMF(final char code) {
if (em!=null) {
if (em.IsCreated()) {
em.DTMF(code);
return true;
} else raise_log_event("SendDTMF failed, EventManager not created");
} else raise_log_event("SendDTMF failed, Connect first");
return false;
}
/**
* Reject Incoming Call
* @param req SIP_Request to reject
* @return true if can be rejected
*/
public boolean RejectIncomingCall(SIP_Request req) {
if (em!=null) {
if (em.IsCreated()) {
if (req!=null) {
em.RejectCall(req.getReq());
return true;
} else raise_log_event("RejectIncomingCall failed, SIP_Request is null");
} else raise_log_event("RejectIncomingCall failed, EventManager not created");
} else raise_log_event("RejectIncomingCall failed, Connect first");
return false;
}
/////////// Class Implementation ////////////////////
public class EventManager implements SipListener{
private UserAgent user_agent;
private SipRequest sip_request;
private boolean all_success;
//JavaxSoundManager jsm;
BassSoundManager jsm;
public EventManager(final CustomConfig xx) {
all_success = false;
//Logger lg = new FileLogger(null);
Logger lg = null;
// jsm = new JavaxSoundManager(false, lg, null);
jsm = new BassSoundManager(1,0, new BassSoundManagerListener() {
@Override
public void Opened() {
raise_log_event("BassSoundManager Opened");
raise_soundchannelopened_event();
}
@Override
public void Closed() {
raise_log_event("BassSoundManager Closed");
raise_soundchannelclosed_event();
}
@Override
public void log_info(String msg) {
raise_log_event("BassSoundManager info : "+msg);
}
@Override
public void log_error(String msg) {
raise_log_event("BassSoundManager error : "+msg);
}
@Override
public void WriteFromRTP(int length, byte[] pcmdata) {
// buat debugging aja, kalau dikeluarin, spamming log
//raise_log_event("BassSoundmanager WriteFromRTP "+length+" bytes");
raise_outputchannelpcmdata_event(length, pcmdata);
}
@Override
public void ReadToRTP(int length, byte[] pcmdata) {
// buat debugging aja, kalau dikeluarin, spamming log
//raise_log_event("BassSoundManager ReadToRTP "+length+" bytes");
raise_inputchannelpcmdata_event(length, pcmdata);
}
@Override
public void DeviceFailure(String msg) {
raise_log_event("BassSondManager DeviceFailure : "+msg);
if (msg.contains("OutputChannel"))
raise_outputchanneldevicefailure_event();
else if (msg.contains("InputChannel"))
raise_inputchanneldevicefailure_event();
}
@Override
public void BufferingInformation(String msg) {
raise_log_event("BassSoundManager BufferingInformation : "+msg);
if (msg.contains("OutputChannel"))
raise_outputchannelbuffering_event(msg);
else if (msg.contains("InputChannel"))
raise_inputchannelbuffering_event(msg);
}
@Override
public void ChannelLevel(boolean is_input, int value) {
if (is_input)
raise_inputchannellevel_event(value);
else
raise_outputchannellevel_event(value);
}
});
try {
user_agent = new UserAgent(this, xx, jsm);
exec.submit(() -> {
try {
user_agent.register();
all_success = true;
} catch (SipUriSyntaxException e) {
raise_log_event("EventManager register exception = "+e.getMessage());
}
});
} catch (SocketException e) {
raise_log_event("EventManager create exception = "+e.getMessage());
}
}
public void setInputVolume(int value) {
if (jsm!=null) jsm.setInputChannelVolume(value);
}
public int getInputVolume() {
if (jsm!=null) {
return jsm.getInputChannelVolume();
} else return 0;
}
public void setOutputVolume(int value) {
if (jsm!=null) jsm.setOutputChannelVolume(value);
}
public int getOutputVolume() {
if (jsm!=null) {
return jsm.getOutputChannelVolume();
} else return 0;
}
/**
* Check if EventManager succesfully created
* @return true if success
*/
public boolean IsCreated() {
return all_success;
}
/**
* Call
* @param targetsip Target SIP
*/
public void Call(final String targetsip) {
if (user_agent!=null) {
exec.submit(() -> {
sip_request = null;
try {
sip_request = user_agent.invite(targetsip, null);
} catch (SipUriSyntaxException e) {
raise_log_event("Call exception = "+e.getMessage());
}
});
}
}
/**
* Accept Incoming Call
* @param req SipRequest to accept
*/
public void AcceptCall(final SipRequest req) {
if (user_agent!=null) {
if (req!=null) {
exec.submit(() -> {
// source : https://github.com/ymartineau/peers/blob/master/peers-gui/src/main/java/net/sourceforge/peers/gui/EventManager.java
String callId = Utils.getMessageCallId(req);
DialogManager dialogManager = user_agent.getDialogManager();
Dialog dialog = dialogManager.getDialog(callId);
user_agent.acceptCall(req, dialog);
});
}
}
}
/**
* Add Listener for File Streaming
* @param event BassFileReaderListener
* @return true if can be added
*/
public boolean AddListener(BassFileReaderListener event) {
if (user_agent!=null) {
MediaManager mm = user_agent.getMediaManager();
if (mm!=null) {
BassFileReader bfr = mm.getFileReader();
if (bfr!=null) {
bfr.AddListener(event);
return true;
}
}
}
return false;
}
public void DTMF(final char code) {
if (user_agent!=null) {
exec.submit(() -> {
MediaManager mm = user_agent.getMediaManager();
mm.sendDtmf(code);
});
}
}
/**
* Reject Incoming Call
* @param req SipRequest to reject
*/
public void RejectCall(final SipRequest req) {
if (user_agent!=null) {
if (req!=null) {
exec.submit(() -> user_agent.rejectCall(req));
}
}
}
/**
* Check if Calling in Progress
* @return true if in progress
*/
public boolean CallingInProgress() {
return sip_request!=null;
}
/**
* Hang-Up current call
*/
public void HangUp() {
if (sip_request!=null) {
if (user_agent!=null) {
exec.submit(() -> {
user_agent.terminate(sip_request);
sip_request = null;
});
} else raise_log_event("HangUp failed, user_agent not available");
} else raise_log_event("HangUp failed, sip_request not available");
}
/**
* Close Connection to SIP Server
*/
public void Close() {
if (user_agent!=null) {
user_agent.close();
}
}
@Override
public void registering(SipRequest sipRequest) {
SIP_Request req = new SIP_Request(sipRequest);
raise_registering_event(req);
}
@Override
public void registerSuccessful(SipResponse sipResponse) {
SIP_Response resp = new SIP_Response(sipResponse);
raise_registersuccesfull_event(resp);
}
@Override
public void registerFailed(SipResponse sipResponse) {
SIP_Response resp = new SIP_Response(sipResponse);
raise_registerfailed_event(resp);
}
@Override
public void incomingCall(SipRequest sipRequest, SipResponse provResponse) {
SIP_Request req = new SIP_Request(sipRequest);
SIP_Response resp = new SIP_Response(provResponse);
raise_incomingcall_event(req, resp);
}
@Override
public void remoteHangup(SipRequest sipRequest) {
SIP_Request req = new SIP_Request(sipRequest);
raise_remotehangup_event(req);
}
@Override
public void ringing(SipResponse sipResponse) {
SIP_Response resp = new SIP_Response(sipResponse);
raise_ringing_event(resp);
}
@Override
public void calleePickup(SipResponse sipResponse) {
SIP_Response resp = new SIP_Response(sipResponse);
raise_calleepickup_event(resp);
}
@Override
public void error(SipResponse sipResponse) {
raise_log_event("sip error, response="+gs.toJson(sipResponse));
}
}
public static class SIP_Request{
private @Getter final SipRequest req;
public String To;
public String From;
public String CallID;
public String Contact;
public SIP_Request(SipRequest source) {
req = source;
if (req!=null) {
SipHeaders head = source.getSipHeaders();
this.To = common.GetSIPHeaderValue(head,"To");
this.From = common.GetSIPHeaderValue(head, "From");
this.CallID = common.GetSIPHeaderValue(head, "Call-ID");
this.Contact = common.GetSIPHeaderValue(head, "Contact");
}
}
@Override
public String toString() {
return MessageFormat.format("To:{0}\n"
+ "From:{1}\n"
+ "Call-ID:{2}\n"
+ "Contact:{3}", To, From, CallID, Contact);
}
}
public static class SIP_Response{
public SIP_Response(SipResponse source) {
resp = source;
if (resp!=null) {
this.statusCode = source.getStatusCode();
this.reasonPhrase = source.getReasonPhrase();
SipHeaders head = source.getSipHeaders();
this.To = common.GetSIPHeaderValue(head, "To");
this.From = common.GetSIPHeaderValue(head, "From");
this.CallID = common.GetSIPHeaderValue(head, "Call-ID");
this.Contact = common.GetSIPHeaderValue(head, "Contact");
this.Server = common.GetSIPHeaderValue(head, "Server");
this.Date = common.GetSIPHeaderValue(head, "Date");
}
}
private @Getter final SipResponse resp;
public int statusCode;
public String reasonPhrase;
public String From;
public String To;
public String CallID;
public String Server;
public String Contact;
public String Date;
@Override
public String toString() {
return MessageFormat.format("To:{0}\n"
+ "From:{1}\n"
+ "Call-ID:{2}\n"
+ "Contact:{3}\n"
+ "Server:{4}\n"
+ "Date:{5}\n"
+ "StatusCode:{6}\n"
+ "ReasonPhrase:{7}", To, From, CallID, Contact, Server, Date, statusCode, reasonPhrase);
}
}
public class CustomConfig implements Config{
private InetAddress localIpAddress;
private InetAddress publicIpAddress;
private String registrar;
private String username;
private String password;
private int sip_port;
private int rtp_port;
private transient MediaMode mm; // tidak disave dan load
private SipURI outbondproxy;
private transient boolean mediadebug; // tidak disave dan load
private transient String mediafile; // tidak disave dan load
/**
* Create CustomConfig
* @param registrar Server IP
* @param username username
* @param password password
*/
public CustomConfig(String registrar, String username, String password) {
this.registrar = registrar;
this.password = password;
this.username = username;
setLocalInetAddress(null);
}
/**
* Create CustomConfig
* @param registrar Server IP
* @param username username
* @param password password
* @param localip local ethernet to use to register. if not valid, will use default LocalHost
*/
public CustomConfig(String registrar, String username, String password, String localip) {
this.registrar = registrar;
this.password = password;
this.username = username;
SetLocalInetAddress(localip);
}
public CustomConfig() {
this.registrar = "192.168.5.1";
this.username = "1002";
this.password = "1234";
setLocalInetAddress(null);
}
/**
* Get Local IP Address
*/
@Override
public InetAddress getLocalInetAddress() {
return localIpAddress;
}
/**
* Get public IP Address used
*/
@Override
public InetAddress getPublicInetAddress() {
return publicIpAddress;
}
/**
* Get Username to use for registering with SIP Server
*/
@Override
public String getUserPart() {
return username;
}
/**
* Get SIP Server (registrar)
*/
@Override
public String getDomain() {
return registrar;
}
/**
* Get Password
*/
@Override
public String getPassword() {
return password;
}
/**
* Get Outbond Proxy used
*/
@Override
public SipURI getOutboundProxy() {
return outbondproxy;
}
/**
* Get SIP Port . default is 5060
*/
@Override
public int getSipPort() {
return sip_port;
}
/**
* Get Current MediaMode
*/
@Override
public MediaMode getMediaMode() {
return mm;
}
/**
* Not used
*/
@Override
public boolean isMediaDebug() {
return mediadebug;
}
/**
* Get MediaFile used
*/
@Override
public String getMediaFile() {
return mediafile;
}
/**
* Get RTP Port used
*/
@Override
public int getRtpPort() {
return rtp_port;
}
/**
* Set Local Network Interface to use with jSIPClient
* useful when having multiple network interfaces in the machine
*/
@Override
public void setLocalInetAddress(InetAddress inetAddress) {
try {
this.localIpAddress = inetAddress == null ? InetAddress.getLocalHost() : inetAddress;
} catch (UnknownHostException e) {
raise_log_event("setLocalInetAddress exception = "+e.getMessage());
}
}
/**
* Set Local Network Interface to use with jSIPClient
* useful when having multiple network interfaces in the machine
* @param ipaddress IP Address of the network interface to use in the machine
*/
public void SetLocalInetAddress(String ipaddress) {
try {
InetAddress xx = InetAddress.getByName(ipaddress);
setLocalInetAddress(xx);
} catch (UnknownHostException e) {
raise_log_event("SetLocalInetAddress exception = "+e.getMessage());
}
}
/**
* Set Public InetAddress to use with JSIPClient
* personal note : dont know if really necessary
*/
@Override
public void setPublicInetAddress(InetAddress inetAddress) {
publicIpAddress = inetAddress;
}
/**
* Set Public IP Address to use with jSIPClient
* Personal Note : dont know if really necessary
* @param ipaddress IP Address in string
*/
public void SetPublicInetAddress(String ipaddress) {
try {
InetAddress xx = InetAddress.getByName(ipaddress);
setPublicInetAddress(xx);
} catch (UnknownHostException e) {
raise_log_event("SetPublicInetAddress exception = "+e.getMessage());
}
}
/**
* Set Username to use for registering to SIP Server
*/
@Override
public void setUserPart(String username) {
this.username = username;
}
/**
* Set SIP Server (registrar) IP Address / Domain
*/
@Override
public void setDomain(String domain) {
registrar = domain;
}
/**
* Set Password to use for registering to SIP Server
*/
@Override
public void setPassword(String password) {
this.password = password;
}
/**
* Not used
*/
@Override
public void setOutboundProxy(SipURI outboundProxy) {
outbondproxy = outboundProxy;
}
/**
* Not used
*/
@Override
public void setSipPort(int sipPort) {
this.sip_port = common.ValidPortNumber(sipPort) ? sipPort : 5060;
}
/**
* Not used
*/
@Override
public void setMediaMode(MediaMode mediaMode) {
mm = mediaMode;
}
/**
* Not used
*/
@Override
public void setMediaDebug(boolean mediaDebug) {
mediadebug = mediaDebug;
}
/**
* Not used
*/
@Override
public void setMediaFile(String mediaFile) {
mediafile = mediaFile;
}
/**
* Not used
*/
@Override
public void setRtpPort(int rtpPort) {
rtp_port = common.ValidPortNumber(rtpPort) ? rtpPort : 49152 ;
}
/**
* Not used
*/
@Override
public void save() {}
}
//////////// private functions ///////////////
private void raise_log_event(String msg) {
Logger.info(msg);
}
private void raise_registering_event(SIP_Request req) {
if (jse!=null) jse.Registering(req);
}
private void raise_registersuccesfull_event(SIP_Response resp) {
if (jse!=null) jse.RegisterSuccesful(resp);
}
private void raise_registerfailed_event(SIP_Response resp) {
if (jse!=null) jse.RegisterFailed(resp);
}
private void raise_incomingcall_event(SIP_Request req, SIP_Response resp) {
if (jse!=null) jse.IncomingCall(req, resp);
}
private void raise_remotehangup_event(SIP_Request req) {
if (jse!=null) jse.RemoteHangUp(req);
}
private void raise_ringing_event(SIP_Response resp) {
if (jse!=null) jse.Ringing(resp);
}
private void raise_calleepickup_event(SIP_Response resp) {
if (jse!=null) jse.CalleePickup(resp);
}
private void raise_inputchanneldevicefailure_event(){
//if (need_inputchanneldevicefailure_event) ba.raiseEventFromDifferentThread(Me, null, 0,event+"_inputchanneldevicefailure", false,null );
}
private void raise_inputchannelbuffering_event(String msg) {
//if (need_inputchannelbuffering_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_inputchannelbuffering", false, new Object[] {msg});
}
private void raise_inputchannelpcmdata_event(int length, byte[] bb) {
//if (need_inputchannelpcmdata_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_inputchannelpcmdata", false, new Object[] {length, bb});
}
private void raise_outputchanneldevicefailure_event(){
//if (need_outputchanneldevicefailure_event) ba.raiseEventFromDifferentThread(Me, null, 0,event+"_outputchanneldevicefailure", false,null );
}
private void raise_outputchannelbuffering_event(String msg) {
//if (need_outputchannelbuffering_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_outputchannelbuffering", false, new Object[] {msg});
}
private void raise_outputchannelpcmdata_event(int length, byte[] bb) {
//if (need_outputchannelpcmdata_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_outputchannelpcmdata", false, new Object[] {length, bb});
}
private void raise_soundchannelclosed_event() {
//if (need_soundchannelclosed_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_soundchannelclosed", false, null);
}
private void raise_soundchannelopened_event() {
//if (need_soundchannelopened_event) ba.raiseEventFromDifferentThread(Me, null, 0,event+"_soundchannelopened", false, null);
}
private void raise_inputchannellevel_event(int value) {
//if (need_inputchannellevel_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_inputchannellevel", false, new Object[] {value});
}
private void raise_outputchannellevel_event(int value) {
//if (need_outputchannellevel_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_outputchannellevel", false, new Object[] {value});
}
/**
* Dipanggil saat ShutdownHook
*/
private void save_config() {
if (cc!=null) {
try {
gs.toJson(cc, new FileWriter(new File(runningfolder,"Config.json")));
raise_log_event("Config.json saved");
} catch (JsonIOException | IOException e) {
raise_log_event("save_config failed, exception = "+e.getMessage());
}
}
}
/**
* Dipanggil saat initialization
*/
private void load_config() {
try {
CustomConfig xx = gs.fromJson(new FileReader(new File(runningfolder,"Config.json")), CustomConfig.class);
raise_log_event("Config.json loaded");
cc = xx;
} catch (JsonSyntaxException | JsonIOException | FileNotFoundException e) {
raise_log_event("load_config failed, exception = "+e.getMessage());
}
}
}

10
src/javaSipEvents.java Normal file
View File

@@ -0,0 +1,10 @@
public interface javaSipEvents {
void Registering(jSIPClient.SIP_Request req);
void RegisterSuccesful(jSIPClient.SIP_Response resp);
void RegisterFailed(jSIPClient.SIP_Response resp);
void IncomingCall(jSIPClient.SIP_Request req, jSIPClient.SIP_Response resp);
void RemoteHangUp(jSIPClient.SIP_Request req);
void Ringing(jSIPClient.SIP_Response resp);
void CalleePickup(jSIPClient.SIP_Response resp);
}

View File

@@ -24,6 +24,8 @@ import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
import org.pmw.tinylog.Logger;
import peers.Config;
@@ -51,35 +53,47 @@ import peers.sip.transport.SipResponse;
import peers.sip.transport.TransportManager;
@SuppressWarnings("unused")
@SuppressWarnings({"unused", "FieldMayBeFinal", "FieldCanBeLocal", "UnusedReturnValue"})
public class UserAgent {
public final static String CONFIG_FILE = "conf" + File.separator + "peers.xml";
public final static int RTP_DEFAULT_PORT = 8000;
@Getter
private String peersHome;
@Getter
private Config config;
@Getter
private List<String> peers;
//private List<Dialog> dialogs;
//TODO factorize echo and captureRtpSender
@Setter
@Getter
private Echo echo;
@Getter
private UAC uac;
@Getter
private UAS uas;
private ChallengeManager challengeManager;
@Getter
private DialogManager dialogManager;
private TransactionManager transactionManager;
@Getter
private TransportManager transportManager;
private int cseqCounter;
@Getter
private SipListener sipListener;
private SDPManager sdpManager;
@Getter
private AbstractSoundManager soundManager;
@Getter
private MediaManager mediaManager;
public UserAgent(SipListener sipListener, String peersHome,
@@ -94,7 +108,7 @@ public class UserAgent {
this(sipListener, config, null, soundManager);
}
private UserAgent(SipListener sipListener, Config config, String peersHome,
public UserAgent(SipListener sipListener, Config config, String peersHome,
AbstractSoundManager soundManager)
throws SocketException {
this.sipListener = sipListener;
@@ -111,17 +125,16 @@ public class UserAgent {
cseqCounter = 1;
StringBuffer buf = new StringBuffer();
buf.append("starting user agent [");
buf.append("myAddress: ");
buf.append(config.getLocalInetAddress().getHostAddress()).append(", ");
buf.append("sipPort: ");
buf.append(config.getSipPort()).append(", ");
buf.append("userpart: ");
buf.append(config.getUserPart()).append(", ");
buf.append("domain: ");
buf.append(config.getDomain()).append("]");
Logger.info(buf.toString());
String buf = "starting user agent [" +
"myAddress: " +
config.getLocalInetAddress().getHostAddress() + ", " +
"sipPort: " +
config.getSipPort() + ", " +
"userpart: " +
config.getUserPart() + ", " +
"domain: " +
config.getDomain() + "]";
Logger.info(buf);
//transaction user
@@ -204,7 +217,7 @@ public class UserAgent {
inviteHandler.setChallengeManager(challengeManager);
byeHandler.setChallengeManager(challengeManager);
peers = new ArrayList<String>();
peers = new ArrayList<>();
//dialogs = new ArrayList<Dialog>();
sdpManager = new SDPManager(this);
@@ -252,7 +265,7 @@ public class UserAgent {
* Gives the sipMessage if sipMessage is a SipRequest or
* the SipRequest corresponding to the SipResponse
* if sipMessage is a SipResponse
* @param sipMessage
* @param sipMessage SipMessage
* @return null if sipMessage is neither a SipRequest neither a SipResponse
*/
public SipRequest getSipRequest(SipMessage sipMessage) {
@@ -275,32 +288,10 @@ public class UserAgent {
}
}
// public List<Dialog> getDialogs() {
// return dialogs;
// }
public List<String> getPeers() {
return peers;
}
// public Dialog getDialog(String peer) {
// for (Dialog dialog : dialogs) {
// String remoteUri = dialog.getRemoteUri();
// if (remoteUri != null) {
// if (remoteUri.contains(peer)) {
// return dialog;
// }
// }
// }
// return null;
// }
public String generateCSeq(String method) {
StringBuffer buf = new StringBuffer();
buf.append(cseqCounter++);
buf.append(' ');
buf.append(method);
return buf.toString();
return String.valueOf(cseqCounter++) +
' ' +
method;
}
public boolean isRegistered() {
@@ -308,18 +299,6 @@ public class UserAgent {
.isRegistered();
}
public UAS getUas() {
return uas;
}
public UAC getUac() {
return uac;
}
public DialogManager getDialogManager() {
return dialogManager;
}
public int getSipPort() {
return transportManager.getSipPort();
}
@@ -348,35 +327,4 @@ public class UserAgent {
return config.getOutboundProxy();
}
public Echo getEcho() {
return echo;
}
public void setEcho(Echo echo) {
this.echo = echo;
}
public SipListener getSipListener() {
return sipListener;
}
public AbstractSoundManager getSoundManager() {
return soundManager;
}
public MediaManager getMediaManager() {
return mediaManager;
}
public Config getConfig() {
return config;
}
public String getPeersHome() {
return peersHome;
}
public TransportManager getTransportManager() {
return transportManager;
}
}