Compiling ESL Library
The Event Socket Library (ESL) is a key component that allows communication with FreeSWITCH using socket-based interactions. This guide provides comprehensive steps to compile and install the Python or Java ESL library as part of a FreeSWITCH installation.
For a comprehensive guide on compiling ESL libraries, including for other programming languages such as Perl, Ruby, and PHP, please refer to the official Event Socket Library documentation. This documentation provides detailed instructions and insights for integrating the Event Socket Library with various programming environments.
To avoid compatibility and linking issues with FreeSWITCH core libraries and system core libraries, it's highly recommended to compile the ESL library with each FreeSWITCH installation.
Compiling Java ESL Library
The Java ESL (Event Socket Library) allows you to control and interact with FreeSWITCH using Java programming language. This guide walks you through the process of compiling and installing the Java ESL library from source.
Prerequisites
-
Java Development Kit (JDK) 17 or above: Ensure you have Java 17 (or higher) installed on your system. For this guide, we'll assume you're using JDK 17, but the process is similar for any version starting from Java 8.
-
FreeSWITCH Source Code: You need to have the FreeSWITCH source code downloaded and extracted. We will assume the path is
/usr/local/src/freeswitch-1.10.12-release/
. -
Required Build Tools:
- GNU Make: Used to compile the code.
- SWIG (Simplified Wrapper and Interface Generator): For generating Java wrappers.
- GCC/G++: C++ compiler for building the native code.
Install Dependencies
-
Install SWIG:
If SWIG is not installed, you can install it via your package manager:
sudo apt-get install swig3.0
-
Install GNU Compiler Collection (GCC) and Make:
if GCC is installed in your system then you can install it using following command.
sudo apt-get install build-essential
-
Verify Java Installation:
Ensure that Java 17 (or higher) is installed and properly configured. To check:
java -version
javac -versionThe output should indicate that Java 17 (or the version you're using) is installed, such as:
openjdk version "17.0.4" 2022-07-19
If Java is not installed, you can install OpenJDK 17 with:
sudo apt install openjdk-17-jdk
Set Up the ESL Source Directory
Navigate to the libs/esl directory inside your FreeSWITCH source folder:
cd /usr/local/src/freeswitch-1.10.12-release/libs/esl
This folder contains the Makefile and necessary source files for compiling the ESL Java client.
Modify Makefile
Since the Makefile is written for older versions of Java (such as Java 6), we need to update it for Java 17 or any version above Java 8.
-
Update Java Include Paths and Compilation Settings:
Edit the Makefile in the java directory:
vim java/Makefile
-
Update Java Include Paths: Modify the
LOCAL_CFLAGS
variable to point to the Java 17 include directories. Assuming you’re using OpenJDK 17, yourLOCAL_CFLAGS
should look like this:LOCAL_CFLAGS=-I../src/include \
-I/usr/lib/jvm/java-17-openjdk-amd64/include \
-I/usr/lib/jvm/java-17-openjdk-amd64/include/linuxIf you are using a different installation path, adjust the paths accordingly.
-
Update
javac
Compilation Flags: Update the javac compilation flags to use-source 17
and-target 17
:esl.jar: libesljni.so
mkdir -p classes
javac -sourcepath org -d classes -source 17 -target 17 $(CLASSES)
jar cf esl.jar -C classes org -
After these changes, your updated Makefile should look like this:
LOCAL_CFLAGS=-I../src/include \
-I/usr/lib/jvm/java-17-openjdk-amd64/include \
-I/usr/lib/jvm/java-17-openjdk-amd64/include/linux
GCC_WARNING_JUNK=-w
CLASSES=org/freeswitch/esl/*
all: esl.jar
esl_wrap.cpp:
swig3.0 -module esl -java -c++ $(LOCAL_CFLAGS) -package org.freeswitch.esl \
-outdir org/freeswitch/esl -o esl_wrap.cpp ../ESL.i
esl_wrap.o: esl_wrap.cpp
$(CXX) $(CXX_CFLAGS) $(LOCAL_CFLAGS) $(CXXFLAGS) $(GCC_WARNING_JUNK) \
-c esl_wrap.cpp -o esl_wrap.o
libesljni.so: esl_wrap.o
$(CXX) $(SOLINK) -o libesljni.so esl_wrap.o $(MYLIB)
esl.jar: libesljni.so
mkdir -p classes
javac -sourcepath org -d classes -source 17 -target 17 $(CLASSES)
jar cf esl.jar -C classes org
clean:
rm -f _.o _.so _~ _.jar
swigclean:
rm -f esl_wrap.\*
reswig: swigclean esl_wrap.cppNote: If you're using Java 8, change the -source and -target flags to 8.
-
Compile
After updating the Makefile
, you are ready to compile the Java ESL client.
-
Clean Previous Build Artifacts:
It’s always a good idea to clean previous builds:
make clean
-
Compile the Java Module:
Now, run the command to build the Java module:
make javamod
Execution of above command will:
- Generate the Java bindings using SWIG.
- Compile the native C++ code.
- Generate the Java .jar file and the shared library (libesljni.so).
Verify the Output
After the compilation is complete, verify that the following files are generated:
libesljni.so
: The shared library that contains the native C++ bindings.esl.jar
: The Java archive (JAR) file that contains the Java classes.
You can check their existence with:
ls -l java/libesljni.so java/esl.jar
If both files are present, the build was successful.
Installation
-
For Non-Maven/Gradle Projects:
warningUsing the FreeSWITCH ESL Java library in a core Java project that does not utilize Maven, Gradle, or Spring Boot is generally not recommended.
If you’re using the ESL library in a project that does not use
Maven
orGradle
, follow these steps:-
Locate and Copy the
org
Directory:-
Navigate to the ESL FreeSWITCH source directory:
cd /usr/local/src/freeswitch-1.10.12-release/libs/esl/java
-
Inside this directory, you'll find the
org
directory which contains the necessary Java classes for the ESL library. -
Copy the
org
directory to your project’s source code directory. This should be done in a way that maintains the directory structure relative to your project’s source path.
-
-
Load the Native Library:
-
In your Java code, you need to load the native library. Add the following line:
System.load("/path/to/libesljni.so");
-
Replace
"/path/to/libesljni.so"
with the actual path to the native library file (libesljni.so
). Thelibesljni.so
file is typically found in the libs directory of your ESL installation.
-
-
-
For Maven/Gradle Projects (Recommended Approach):
If you're using Maven or Gradle for your project, follow these steps to include the ESL library:
-
Install the JAR into Your Local Maven Repository:
-
Open a terminal or command prompt.
-
Run the following command to install the ESL JAR file into your local Maven repository:
Using Maven:
mvn install:install-file -Dfile=/path/to/esl.jar -DgroupId=org.freeswitch.esl -DartifactId=esl -Dversion=1.0.0 -Dpackaging=jar
Using Maven Wrapper (
mvnw
): If your project includes a Maven Wrapper script, use it instead:./mvnw install:install-file -Dfile=/path/to/esl.jar -DgroupId=org.freeswitch.esl -DartifactId=esl -Dversion=1.0.0 -Dpackaging=jar
noteReplace
/path/to/esl.jar
with the actual path to your ESL JAR file. -
-
Add the Dependency to Your Maven/Gradle Project:
-
For Maven Projects: Open your
pom.xml
file and add the following dependency:<dependencies>
<dependency>
<groupId>org.freeswitch.esl</groupId>
<artifactId>esl</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies> -
For Gradle Projects: Open your build.gradle file and add the following dependency:
dependencies {
implementation 'org.freeswitch.esl:esl:1.0.0'
}
-
For more details on using Maven or Gradle, consult their respective documentation.
-
Usage
TO use this maven library in your project, use following:
<dependencies>
<dependency>
<groupId>org.freeswitch.esl</groupId>
<artifactId>esl</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
Compiling Python ESL Library
The Python ESL (Event Socket Library) allows you to control and interact with FreeSWITCH using Python. This guide walks you through the process of compiling and installing the Python ESL library from source.
Install Python and Python Development Libraries
Make sure you have Python 3 and the necessary Python development libraries installed.
sudo apt install python3 python3-dev python3-pip
Compile the ESL Library
Now, compile the ESL library, including the Python bindings.
-
Navigate to FreeSWITCH source code. It is typically located in
/usr/local/src/freeswitch-1.10.12.-release
cd /usr/local/src/freeswitch-1.10.12.-release
-
Navigate to the ESL directory:
cd libs/esl
-
Compile the ESL Python library:
make pymod
This will compile the Python ESL module (
_ESL.so
) located in python directory. -
After compiling the library, install it so Python can import the ESL module.
-
Locate the compiled Python module (
_ESL.so
). It should be in:/usr/local/src/freeswitch-1.10.12.-release/libs/esl/python/_ESL.so
-
Copy the ESL Python files to your Python installation:
sudo cp python/_ESL.so /usr/local/lib/python3.12/dist-packages/
sudo cp python/ESL.py /usr/local/lib/python3.12/dist-packages/Ensure you're copying the Python files to the correct Python version path (in this example, Python 3.12).
-
Fix Compatibility Issues with Python 3.12
The ESL Python bindings might use outdated libraries that are incompatible with modern Python versions. In our case, we encountered a deprecated imp module. Here’s how we fixed it:
-
Edit the
ESL.py
file:sudo vi /usr/local/lib/python3.12/dist-packages/ESL.py
-
Replace the deprecated
imp
module withimportlib
. Here's the code for the updatedESL.py
file:from sys import version_info
import importlib.util
import os
if version_info >= (2, 6, 0):
def swig_import_helper():
module_name = '_ESL'
module_path = os.path.join(os.path.dirname(__file__), '_ESL.so')
if importlib.util.find_spec(module_name) is None:
# Module not found, try to load it dynamically
if os.path.exists(module_path):
spec = importlib.util.spec_from_file_location(module_name, module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
else:
raise ImportError(f"Module '{module_name}' not found at '{module_path}'")
else:
# Module is already found in the search path
import _ESL
return _ESL
_ESL = swig_import_helper()
del swig_import_helper
else:
import _ESL
del version_info
def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
if name == "thisown":
return self.this.own(value)
if name == "this":
if type(value).__name__ == 'SwigPyObject':
self.__dict__[name] = value
return
method = class_type.__swig_setmethods__.get(name, None)
if method:
return method(self, value)
if not static:
self.__dict__[name] = value
else:
raise AttributeError(f"You cannot add attributes to {self}")
def _swig_setattr(self, class_type, name, value):
return _swig_setattr_nondynamic(self, class_type, name, value, 0)
def _swig_getattr(self, class_type, name):
if name == "thisown":
return self.this.own()
method = class_type.__swig_getmethods__.get(name, None)
if method:
return method(self)
raise AttributeError(name)
def _swig_repr(self):
try:
strthis = "proxy of " + self.this.__repr__()
except:
strthis = ""
return f"<{self.__class__.__module__}.{self.__class__.__name__}; {strthis} >"
class ESLevent:
__swig_setmethods__ = {}
__setattr__ = lambda self, name, value: _swig_setattr(self, ESLevent, name, value)
__swig_getmethods__ = {}
__getattr__ = lambda self, name: _swig_getattr(self, ESLevent, name)
__repr__ = _swig_repr
__swig_setmethods__["event"] = _ESL.ESLevent_event_set
__swig_getmethods__["event"] = _ESL.ESLevent_event_get
__swig_setmethods__["serialized_string"] = _ESL.ESLevent_serialized_string_set
__swig_getmethods__["serialized_string"] = _ESL.ESLevent_serialized_string_get
__swig_setmethods__["mine"] = _ESL.ESLevent_mine_set
__swig_getmethods__["mine"] = _ESL.ESLevent_mine_get
def __init__(self, *args):
this = _ESL.new_ESLevent(*args)
try:
self.this.append(this)
except:
self.this = this
__swig_destroy__ = _ESL.delete_ESLevent
__del__ = lambda self: None
def serialize(self, format=None):
return _ESL.ESLevent_serialize(self, format)
def setPriority(self, *args):
return _ESL.ESLevent_setPriority(self, *args)
def getHeader(self, *args):
return _ESL.ESLevent_getHeader(self, *args)
def getBody(self):
return _ESL.ESLevent_getBody(self)
def getType(self):
return _ESL.ESLevent_getType(self)
def addBody(self, *args):
return _ESL.ESLevent_addBody(self, *args)
def addHeader(self, *args):
return _ESL.ESLevent_addHeader(self, *args)
def pushHeader(self, *args):
return _ESL.ESLevent_pushHeader(self, *args)
def unshiftHeader(self, *args):
return _ESL.ESLevent_unshiftHeader(self, *args)
def delHeader(self, *args):
return _ESL.ESLevent_delHeader(self, *args)
def firstHeader(self):
return _ESL.ESLevent_firstHeader(self)
def nextHeader(self):
return _ESL.ESLevent_nextHeader(self)
ESLevent_swigregister = _ESL.ESLevent_swigregister
ESLevent_swigregister(ESLevent)
class ESLconnection:
__swig_setmethods__ = {}
__setattr__ = lambda self, name, value: _swig_setattr(self, ESLconnection, name, value)
__swig_getmethods__ = {}
__getattr__ = lambda self, name: _swig_getattr(self, ESLconnection, name)
__repr__ = _swig_repr
def __init__(self, *args):
this = _ESL.new_ESLconnection(*args)
try:
self.this.append(this)
except:
self.this = this
__swig_destroy__ = _ESL.delete_ESLconnection
__del__ = lambda self: None
def socketDescriptor(self):
return _ESL.ESLconnection_socketDescriptor(self)
def connected(self):
return _ESL.ESLconnection_connected(self)
def getInfo(self):
return _ESL.ESLconnection_getInfo(self)
def send(self, *args):
return _ESL.ESLconnection_send(self, *args)
def sendRecv(self, *args):
return _ESL.ESLconnection_sendRecv(self, *args)
def api(self, *args):
return _ESL.ESLconnection_api(self, *args)
def bgapi(self, *args):
return _ESL.ESLconnection_bgapi(self, *args)
def sendEvent(self, *args):
return _ESL.ESLconnection_sendEvent(self, *args)
def sendMSG(self, *args):
return _ESL.ESLconnection_sendMSG(self, *args)
def recvEvent(self):
return _ESL.ESLconnection_recvEvent(self)
def recvEventTimed(self, *args):
return _ESL.ESLconnection_recvEventTimed(self, *args)
def filter(self, *args):
return _ESL.ESLconnection_filter(self, *args)
def events(self, *args):
return _ESL.ESLconnection_events(self, *args)
def execute(self, *args):
return _ESL.ESLconnection_execute(self, *args)
def executeAsync(self, *args):
return _ESL.ESLconnection_executeAsync(self, *args)
def setAsyncExecute(self, *args):
return _ESL.ESLconnection_setAsyncExecute(self, *args)
def setEventLock(self, *args):
return _ESL.ESLconnection_setEventLock(self, *args)
def disconnect(self):
return _ESL.ESLconnection_disconnect(self)
ESLconnection_swigregister = _ESL.ESLconnection_swigregister
ESLconnection_swigregister(ESLconnection)
def eslSetLogLevel(*args):
return _ESL.eslSetLogLevel(*args) -
Save the file and exit.
Verify the ESL Module
Now, verify that the Python ESL module works.
-
Open a Python 3 terminal:
python3
-
Import the ESL module:
import ESL
If the module imports without errors, the ESL library is successfully compiled and installed!
Troubleshooting
-
No Module Named
ESL
Error: If you get a "ModuleNotFoundError," check if the_ESL.so
andESL.py
files are in your Python'ssite-packages
ordist-packages
directory.python3 -m site
-
Module
_ESL
Not Found: If Python complains about_ESL
, make sure that the_ESL.so
file is copied correctly to the directory where Python is looking for it.
Conclusion
By following this guide, you have now successfully compiled and installed the Python ESL library for FreeSWITCH! You should be able to integrate FreeSWITCH with Python and start developing your own telephony applications.
If you encounter any issues, check the paths and ensure that the compiled ESL files are in the correct Python directories. Feel free to modify the process to suit your specific Python version or system setup.