#!/usr/bin/luaweb

omg = require("omg")
sip = require("sip")

function doIt(filein,sipp,other,filterPrack,fileout)
   local responsePlayWritten = false

   local fh,err = io.open(filein)
   if err then 
      print("OOps") 
      return false 
   end

   local fho,err = io.open(fileout,"w")

   fho:write('<?xml version="1.0" encoding="ISO-8859-1" ?>' .. "\n")
   fho:write('<!DOCTYPE scenario SYSTEM "sipp.dtd">' .. "\n")
   fho:write("\n")
   fho:write('<scenario name="sippgen">' .. "\n")

   local sipBuf
   while true do
      line = fh:read()
      if line == nil then 
         break 
      end

      if string.find(line,"----- " .. other .. " ") then
         --print(string.rep("=",80))
         --print(sipBuf)
         --print(string.rep("=",80))

         local message = sip.parse_headers(sipBuf)
         --omg.dumpTable(message);

         if filterPrack==true and message.CSeq.Method=="PRACK" then
            line = line
         else
            if message.response ~= nil then
               fho:write('  <recv response="' .. message.response["Status-Code"] .. '">' .. "\n")
               fho:write("  </recv>\n")
               fho:write("\n")

            elseif message.request ~= nil then
               fho:write('  <recv request="' .. message.request["Method"] .. '">' .. "\n")
               fho:write("  </recv>\n")
               fho:write("\n")
            end
         end
      end

      if string.find(line,"----- " .. sipp .. " ") then
         --print(string.rep("=",80))
         --print(sipBuf)
         --print(string.rep("=",80))

         local message = sip.parse_headers(sipBuf)
         --omg.dumpTable(message);

         if filterPrack==true and message.CSeq.Method=="PRACK" then
            line = line
         else	
            if message.request ~= nil then
               message.request["Request-URI"] = "sip:[service]@[remote_ip]:[remote_port]"
               message["Call-ID"] = "[call_id]"

               --message.Via[1] = string.gsub(message.Via[1],"branch=[^;$]*","branch=[branch]")
               message.Via={}
               message.Via[1] = "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]"
               
               message.From["addr-spec"]="sip:999@[local_ip]:[local_port]"
               message.From.tag="[pid]SIPpTag00[call_number]"		

               message.To["addr-spec"]="sip:[service]@[remote_ip]:[remote_port]"

               message.Contact={}
               message.Contact[1] = {}
               message.Contact[1]["addr-spec"] = "sip:999@[local_ip]:[local_port]"

               if message.body ~= nil then
                  message.body = string.gsub(message.body,"(o=.-IN IP).-\n","%1[local_ip_type] [local_ip]\n")
                  message.body = string.gsub(message.body,"c=IN IP.-\n","c=IN IP[media_ip_type] [media_ip]\n")
                  message.body = string.gsub(message.body,"(m=audio) .- (.-)\n","%1 [media_port] %2\n")
               end

               message["Content-Length"] = "[len]"

               if filterPrack==true then
                  if message.Supported ~= nil then
                     for k,v in pairs(message.Supported) do
                        if v == "100rel" then
                           message.Supported[k]=nil
                        end
                     end
                     if table.getn(message.Supported) == 0  then
                        message.Supported=nil
                     end
                  end

                  if message.Require ~= nil then
                     for k,v in pairs(message.Require) do
                        if v == "100rel" then
                           message.Require[k]=nil
                        end
                     end
                     if table.getn(message.Require) == 0  then
                        message.Require=nil
                     end
                  end
               end

               if message.request["Method"] == "ACK" then
                  fho:write('  <send>' .. "\n")
               else
                  fho:write('  <send retrans="500">' .. "\n")
               end

               fho:write('    <![CDATA[' .. "\n")

               sipBuf = sip.cons_headers(message)

               --patch TO tag
               sipBuf = string.gsub(sipBuf,"([Tt][Oo]:.-);tag=[^;]-([;\n])(.*)","%1[peer_tag_param]%2%3")

               sipBuf = string.gsub(sipBuf,"(.-)\n","      %1\n")
               fho:write(sipBuf .. "\n")

               fho:write('    ]]>' .. "\n")
               fho:write('  </send>' .. "\n")
               fho:write("\n")

               if message.request["Method"] == "ACK" then
                  fho:write('  <nop>' .. "\n")
                  fho:write('    <action>' .. "\n")
                  fho:write('      <exec play_pcap_audio="dtmf.pcap"/>' .. "\n")
                  fho:write('    </action>' .. "\n")
                  fho:write('  </nop>' .. "\n")
                  fho:write("\n")

                  fho:write('  <pause />' .. "\n")
                  fho:write("\n")
               end

            elseif message.response ~= nil then
               message.Contact={}
               message.Contact[1] = {}
               message.Contact[1]["addr-spec"] = "sip:999@[local_ip]:[local_port]"
               
               if message.body ~= nil then
                  message.body = string.gsub(message.body,"(o=.-IN IP).-\n","%1[local_ip_type] [local_ip]\n")
                  message.body = string.gsub(message.body,"c=IN IP.-\n","c=IN IP[media_ip_type] [media_ip]\n")
                  message.body = string.gsub(message.body,"(m=audio) .- (.-)\n","%1 [media_port] %2\n")
               end	
               
               message["Content-Length"] = "[len]"
               
               if filterPrack==true then
                  if message.Require ~= nil then
                     for k,v in pairs(message.Require) do
                        if v == "100rel" then
                           message.Require[k]=nil
                        end
                     end
                     if table.getn(message.Require) == 0  then
                        message.Require=nil
                     end
                  end
               end

               fho:write('  <send>' .. "\n")
               fho:write('    <![CDATA[' .. "\n")

               sipBuf = sip.cons_headers(message);
               
               sipBuf = string.gsub(sipBuf,"([Vv][Ii][Aa]:.-)\n","[last_Via:]\n")
               sipBuf = string.gsub(sipBuf,"([Ff][Rr][Oo][Mm]:.-)\n","[last_From:]\n")
               sipBuf = string.gsub(sipBuf,"([Tt][Oo]:.-)\n","[last_To:]\n")
               sipBuf = string.gsub(sipBuf,"([Cc][Aa][Ll][Ll].[Ii][Dd]:.-)\n","[last_Call-Id:]\n")
               sipBuf = string.gsub(sipBuf,"([Cc][Ss][Ee][Qq]:.-)\n","[last_CSeq:]\n")

               sipBuf = string.gsub(sipBuf,"(.-)\n","      %1\n")
               fho:write(sipBuf .. "\n")

               fho:write('    ]]>' .. "\n")
               fho:write('  </send>' .. "\n")
               fho:write("\n")

               if message.response["Status-Code"] == 200 and not responsePlayWritten then
                  fho:write('  <nop>' .. "\n")
                  fho:write('    <action>' .. "\n")
                  fho:write('      <exec play_pcap_audio="dtmf.pcap"/>' .. "\n")
                  fho:write('    </action>' .. "\n")
                  fho:write('  </nop>' .. "\n")
                  fho:write("\n")

                  responsePlayWritten = true;
               end

            end
         end
         sipBuf=nil
      end

      if sipBuf~=nil then
         local beaf

         _,_,beaf=string.find(line,".*SIPMSG:[%s]*(.*)")
         if beaf ~= nil then
            sipBuf = sipBuf .. beaf .. "\n"
         end
      end

      if string.find(line,"+++++ rec ") or string.find(line,"+++++ snd ") then
         sipBuf=""
      end
   end

   fho:write("\n")
   fho:write('  <pause milliseconds="100"/>' .. "\n")
   fho:write("\n")
   fho:write('  <!-- definition of the response time repartition table (unit is ms)   -->' .. "\n")
   fho:write('  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>' .. "\n")
   fho:write("\n")
   fho:write('  <!-- definition of the call length repartition table (unit is ms)     -->' .. "\n")
   fho:write('  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>' .. "\n")
   fho:write("\n")
   fho:write('</scenario>' .. "\n")

   fho:close()
   fh:close()
end

helpString=arg[0] .. " " .. "gen sipp scenario from log file\n"
helpString=helpString .. "\t--logfile=file    the log file to read\n"
helpString=helpString .. "\t--outfile=file    the scenario file to write\n"
helpString=helpString .. "\t--outfilerec=file the scenario receive file to write\n"
helpString=helpString .. "\t--nofilterprack   do not filter prack\n"
helpString=helpString .. "\t--help            gives help\n"

myOptions=omg.splitCommandlineString(arg)

if myOptions ~= nil then
   local filterprack=true

   --omg.dumpTable(myOptions)

   if myOptions.help then
      io.write(helpString .. "\n")
      os.exit(0)
   end

   if myOptions.logfile==nil then
      io.write(helpString .. "\n")
      os.exit(-1)
   end

   if myOptions.outfile==nil then
      myOptions.outfile="sippgen.xml"
   end

   if myOptions.outfilerec==nil then
      if myOptions.outfile~=nil then
         myOptions.outfilerec = string.gsub(myOptions.outfile,"([^.]*)(.*)","%1_rec%2",1)
      else
         myOptions.outfilerec="sippgen_rec.xml"
      end	
   end

   if myOptions.nofilterprack~=nil then
      filterprack=false
   end

   doIt(myOptions.logfile,"rec","snd",filterprack,myOptions.outfile)
   doIt(myOptions.logfile,"snd","rec",filterprack,myOptions.outfilerec)
end
