Jump to content

Recommended Posts

Posted

I would like to export some data out of a mission while it's running using socket.http, but I can't for the life of me get it to work. I've editod my MissionScripting.lua file so nothing is sanitzed and I have access to the require module. 

Looking at other (older) threads on the forum here, as far as I can tell the following code should work?

package.path = package.path..";"..lfs.currentdir().."\\LuaSocket\\?.lua"
package.cpath = package.cpath..";"..lfs.currentdir().."\\LuaSocket\\?.dll"
local http = require("socket.http")

 

But it errors out with:

2022-01-23 16:36:37.313 ERROR   SCRIPTING: Mission script error: [string "G:/My Drive/Coconut Cockpit/Missions/DCS_CaucasusTraining/Scripts/init.lua"]:58: module 'socket.http' not found:
	no field package.preload['socket.http']
	no file '.\socket\http.lua'
	no file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\bin\lua\socket\http.lua'
	no file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\bin\lua\socket\http\init.lua'
	no file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\bin\socket\http.lua'
	no file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\bin\socket\http\init.lua'
	no file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\\LuaSocket\socket\http.lua'socket.http
	no file '.\lua-socket\http.dll'
	no file '.\socket\http.dll'
	no file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\bin\lua-socket\http.dll'
	no file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\bin\socket\http.dll'
	no file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\\LuaSocket\socket\http.dll'
	no module 'socket.http' in file 'C:\Program Files\Eagle Dynamics\DCS World OpenBeta\bin\lua-socket.dll'
stack traceback:
	[C]: ?
	[C]: in function 'require'
	[string "G:/My Drive/Coconut Cockpit/Missions/DCS_CaucasusTraining/Scripts/init.lua"]:58: in main chunk
	[string "ROOT_PATH = "G:/My Drive/Coconut Cockpit/Missions/DCS_CaucasusTraining/Scripts/"..."]:8: in main chunk

Does anyone have an idea what I'm doing wrong? Any help is appreciated!

Posted

Don't quite know if because of all my trying and retrying I didn't restart DCS after making changes to MissionScripting.lua, but the following code seems to be working just fine now. So for anyone coming here from Google, give this a try:

 

package.path = package.path..";"..lfs.currentdir().."\\LuaSocket\\?.lua"
package.cpath = package.cpath..";"..lfs.currentdir().."\\LuaSocket\\?.dll"

local socket = require("socket")
require("mime")
require("ltn12")
require("url")
require("http")

 

Posted

I believe http is not supported in the socket package with the version of lua supplies by the dcs scripting environment. You can either create TCP sockets or UDP sockets, and you must handle the send/receive manually. I've done some of this work myself in an older MissionScripting.lua as an example. This code has been battle tested quite a bit and the socket connections were pretty reliable. You send messages via json strings, which are just lua objects encoded into a json string and sent over the wire. Anything listening on the other end can use a json parser library to read back the receive and parse the message. 

It's not as simple as using a rest api or http, but it does the job.

 

Scripts\\ServerGameGUI.lua

package.path  = package.path..";.\\LuaSocket\\?.lua;"
package.cpath = package.cpath..";.\\LuaSocket\\?.dll;"

local JSONPath = lfs.writedir() .. "Scripts\\JSON.lua"
local _errormsg = ""
net.log("JSON File Path: " .. JSONPath)

KI = {}

-- UDP Port Numbers to communicate with the server side mod
KI.Config.GAMEGUI_RECEIVE_PORT = 6005       -- the port to listen on for server side messages
KI.Config.GAMEGUI_SEND_TO_PORT = 6006       -- the port to send messages to server side
KI.Config.SERVER_SESSION_RECEIVE_PORT = 6007  -- the port to listen for server side session/server info

-- Initialize Sockets
KI.UDPSendSocket = socket.udp()
KI.UDPReceiveSocket = socket.udp()
KI.UDPReceiveSocket:setsockname("*", KIServer.Config.GAMEGUI_RECEIVE_PORT)
KI.UDPReceiveSocket:settimeout(.0001) --receive timer



--=============================================================================--
-- TCPSocket INIT

KI.TCPSocket = 
{
  Object = nil,
  IsConnected = false
}


function KI.TCPSocket.Connect()
  net.log("KI.TCPSocket.Connect called")
  
  -- if the socket handle is not nil, invoke close on it just in case it was still left open
  if KI.TCPSocket.Object ~= nil then
    KI.TCPSocket.Object:close()
  end
  
  -- start connection
  KI.TCPSocket.Object = socket.tcp()
  KI.TCPSocket.Object:settimeout(5)
  KI.TCPSocket.Object:setoption("tcp-nodelay", true)
  KI.TCPSocket.IsConnected = false
  local _r, _err = KI.TCPSocket.Object:connect(KI.Config.TCP_SERVER_IP, KI.Config.TCP_SERVER_PORT)
  KI.TCPSocket.Object:settimeout(.0001)
  if _r ~= 1 or _err then
    net.log("KI.TCPSocket.Connect - ERROR - Failed to connect to TCP Server (Reason: " .. _err .. ")")
    KI.TCPSocket.IsConnected = false
    return false
  else
    KI.TCPSocket.IsConnected = true
    return true
  end
end

function KI.TCPSocket.Disconnect()
  net.log("KI.TCPSocket.Disconnect called")
  KI.TCPSocket.Object:close()
  KI.TCPSocket.IsConnected = false
end


-- Creates the message in the correct format the server expects
-- Encodes into JSON, and appends size of message in first 6 characters of string
function KI.TCPSocket.CreateMessage(action_name, dest, is_bulk_query, data)
  net.log("KI.TCPSocket.CreateMessage called")
  local _msg = 
  {
    Action = action_name,
    Destination = dest,
    BulkQuery = is_bulk_query,
    Data = data,
  }
  local _jsonmsg = KI.JSON:encode(_msg)
  -- sending 6 char header that is size of msg string
  local _m = string.format("%06d", string.len(_jsonmsg)) .. _jsonmsg
  net.log("KI.TCPSocket.CreateMessage - dumping message")
  net.log(_m)
  return _m
end


-- Decodes message from JSON string into LUA Table Object
function KI.TCPSocket.DecodeMessage(msg)
  net.log("KI.TCPSocket.DecodeMessage called")
  local _err = ""
  local _result, _luaObject = xpcall(function() return KI.JSON:decode(msg) end, function(err) _err = err end)
  if _result and _luaObject ~= nil then
    net.log("KI.TCPSocket.DecodeMessage - Message Decoded")
    return _luaObject
  elseif _err ~= "" then
    net.log("KI.TCPSocket.DecodeMessage ERROR - " .. _err)
    return nil
  else
    net.log("KI.TCPSocket.DecodeMessage ERROR - UNKNOWN ERROR")
    return nil
  end
end



function KIServer.TCPSocket.SendUntilComplete(msg, timeout)
  net.log("KIServer.TCPSocket.SendUntilComplete called")
  if not KIServer.TCPSocket.IsConnected then
    net.log("KIServer.TCPSocket.SendUntilComplete - ERROR - Socket is not connected to DB server")
    return false
  end
  if timeout then
    KIServer.TCPSocket.Object:settimeout(timeout) -- set the timeout (used to handle particularly large messages)
  else
    KIServer.TCPSocket.Object:settimeout(.0001)
  end
  local bytes_sent = 0
  local msg_size = string.len(msg)
  -- copy the original msg parameter as we want to manipulate the copy without changing the original (but if strings are not by ref - why bother?)
  local _msgCopy = msg 
  while bytes_sent ~= msg_size do
    local _indexSent, _error, _lastIndexSent = KIServer.TCPSocket.Object:send(_msgCopy)
    
    -- successful send
    if _indexSent then
      bytes_sent = bytes_sent + _indexSent
    else
      -- error encountered - check third parameter to see if at least some data was sent and retry
      if _lastIndexSent ~= 0 then
        net.log("KIServer.TCPSocket.SendUntilComplete - partial send occurred (reason: " .. _error .. ") - Continuing")
        bytes_sent = bytes_sent + _lastIndexSent
      else
        -- complete failure - log
        net.log("KIServer.TCPSocket.SendUntilComplete - ERROR in sending data (reason: " .. _error .. ")")
        KIServer.TCPSocket.Disconnect()
        return false
      end
    end
    -- net.log("KIServer.TCPSocket.SendUntilComplete - bytes sent: "..tostring(bytes_sent))
    -- net.log("KIServer.TCPSocket.SendUntilComplete - sent string: '" .. _msgCopy:sub(1, bytes_sent).."'")
    _msgCopy = _msgCopy:sub(bytes_sent + 1) -- shrink the msg down to what has not been sent
    -- net.log("KIServer.TCPSocket.SendUntilComplete - Remaining buffer length: " .. tostring(string.len(_msgCopy)) .. " data : '" .. _msgCopy .. "'")
  end
  return true
end


function KIServer.TCPSocket.ReceiveUntilComplete(timeout)
  net.log("KIServer.TCPSocket.ReceiveUntilComplete called")
  if timeout then
    KIServer.TCPSocket.Object:settimeout(timeout)
  else
    KIServer.TCPSocket.Object:settimeout(.0001)
  end
  local header, _error = KIServer.TCPSocket.Object:receive(6)
  
  if header and header:len() == 6 then
    local msg_size = tonumber(header)
    local msg, _error = KIServer.TCPSocket.Object:receive(msg_size)
    
    if msg and msg:len() == msg_size then
      net.log("KIServer.TCPSocket.ReceiveUntilComplete - received data transmission")
      return msg
    elseif msg and msg:len() < msg_size then
      net.log("KIServer.TCPSocket.ReceiveUntilComplete - partial data received (Reason: " .. _error .. ")")
      net.log("KIServer.TCPSocket.ReceiveUntilComplete - trying again")
      local partmsg, _error = KIServer.TCPSocket.Object:receive(msg_size - msg:len())
      -- check if the partial message came through and is the size we are expecting it to be
      if partmsg and partmsg:len() == (msg_size - msg:len()) then
        msg = msg .. partmsg
        return msg
      else
        net.log("KIServer.TCPSocket.ReceiveUntilComplete - second try failed to receive (Reason: " .. _error .. ")")
        KIServer.TCPSocket.Disconnect()
        return nil
      end
    else
      net.log("KIServer.TCPSocket.ReceiveUntilComplete - ERROR in receiving body data (Reason: " .. _error .. ")")
      KIServer.TCPSocket.Disconnect()
      return nil
    end
  else
    net.log("KIServer.TCPSocket.ReceiveUntilComplete - WARNING - did not receive header data (reason: " .. _error .. ")")
    if _error == "closed" then
      KIServer.TCPSocket.Disconnect()   -- disconnect the socket if the server closed the connection
    end
    return nil
  end
end
-- end Server TCP Socket
-- ========================================================================================================== --

 

Developer of Kaukasus Insurgency - a customizable Dynamic PvE Campaign with cloud hosting and stats tracking. (Alpha)

 

http://kaukasusinsurgency.com/

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...