Search code examples
luasipfreeswitchjitsijitsi-meet

How Do I set up SIP Conference Calls With Freeswitch and Jitsi


I'm trying to configure my freeswitch instance to route calls to Jitsi meet and join the conference. How do I set that up?


Solution

  • I created a lua script that will answer calls and ask for the conference code and redirect the call to the correct jitsi meeting. The script will call the conference web api with the conference number the user entered and direct bridge the call with the correct meeting.

    --This script goes in the scripts folder for freeswitch.  The default location of that folder is /usr/share/freeswitch/scripts/
    local function buildGetConverenceByIdRequest(conferenceId)
      --This url should match what is set in /etc/jitsi/meet/config.js in the dialInConfCodeUrl.
      --In this case I used the api.jitsi.net one, but you could build your own.
      return string.format('https://api.jitsi.net/conferenceMapper?id=%s', conferenceId);
    end
    
    --Pass in the domain as the first argument in the extenson xml.
    local domain = argv[1]; 
    
    local request = require 'http.request'
    local cjson = require 'cjson'
    local cjson2 = cjson.new();
     
    attempt = 1
    max_attempts = 3
     
    function session_hangup_hook(status)
      freeswitch.consoleLog("NOTICE", "Session hangup: " .. status .. "\n")
      error()
    end
     
    function get_conference_num(min, max, attempts, timeout)
      local conference_num = "";
      freeswitch.consoleLog("NOTICE", "Awaiting caller to enter a conference number phrase:conference_num\n");
      -- conference_num = session:playAndGetDigits(min, max, attempts, timeout, '#', 'phrase:conference_num', '', '\\d+');
      conference_num = session:playAndGetDigits(min, max, attempts, timeout, '#', 'conference/8000/conf-enter_conf_number.wav', '', '\\d+');
      return(conference_num);
    end
     
    session:answer();
    session:setHangupHook("session_hangup_hook");
     
    if session:ready() then
      freeswitch.consoleLog("NOTICE", string.format("Caller has called conferencing server, Playing welcome message phrase:conference_welcome\n"));
      --session:execute("phrase", "conference_welcome");
      session:execute("playback", "conference/8000/conf-welcome.wav");
    end
     
    while attempt <= max_attempts and session:ready() do
      local conf_num = get_conference_num(1, 20, 3, 4000);
      local getConferenceUrl = buildGetConverenceByIdRequest(conf_num);
      freeswitch.consoleLog("NOTICE", string.format("Conference url: %s", getConferenceUrl));
      local headers, stream = assert(request.new_from_uri(getConferenceUrl):go());
      local body = assert(stream:get_body_as_string());
    
      local status = headers:get ":status";
      if status ~= "200" then
        --something went wrong
        freeswitch.consoleLog("NOTICE", string.format("Unable to access conference code service.  Error code: %s", status))
        session:execute("speak", "flite|slt|Unable to access the conference system.  Please try again later.");
        attempt = max_attempts;
        break;
    end
    local responseObject = cjson.decode(body);
    if responseObject.conference then --nil or false evaluates to false, so if there is a conference, this code will catch it.
        --invalid conference number.  Please try again.
        freeswitch.consoleLog("NOTICE", string.format("Found matching conference: %s", responseObject.conference));
        local conferenceFoundSentence = string.format("flite|slt|We found your conference %s", responseObject.conference);
        --todo:  remove this speaking here once the conference joining is worked out.
        -- session:execute("speak", conferenceFoundSentence);
        local conferenceHeader = string.format("sip_h_X-Room-Name=%s", responseObject.conference);
    
        session:execute("set", conferenceHeader);
        local userAddress = string.format("user/jitsiSipUser@%s", domain);
        session:execute("bridge", userAddress);
        break;
      else 
        --[[ if the conference number does not exist, playback message saying it is
        and invalid conference number ]]--
        -- session:execute("phrase", "conference_bad_num");
        -- session:execute("speak", "flite|slt|The conference number you entered is not valid.");
        -- session:execute("playback", "misc/8000/invalid_extension");
        -- session:execute("playback", "directory/8000/dir-please_try_again");
        session:execute("playback", "ivr/8000/ivr-please_check_number_try_again");
      end  
      
      attempt = attempt + 1;
    end
    
    -- session:execute("phrase", "conference_too_many_failures");
    -- session:execute("speak", "flite|slt|You entered the incorrect pin too many times.");
    session:execute("playback", "ivr/8000/ivr-access_denied.wav");
    
    session:hangup();
    

    To use this script, you would create a dial plan like this:

     <extension name="conference_jitsi">
      <condition field="destination_number" expression="^[number reserved for jitsi]$">
        <action application="lua" data="conference_management_jitsi_http.lua ${domain}"/>
      </condition>
    </extension>
    

    See this thread on in the jitsi community: https://community.jitsi.org/t/jitsi-meet-jigasi-freeswitch/29556/32