Verawebsockets

From MiOS
(Difference between revisions)
Jump to: navigation, search
(Created page with "== What is ''verawebsockets''? == '''verawebsockets''' is a Lua library based on the '''libwebsockets v2.4''' library (https://libwebsockets.org). The intention is to provid...")
 
 
(11 intermediate revisions by one user not shown)
Line 1: Line 1:
 +
<br>
 
== What is ''verawebsockets''? ==
 
== What is ''verawebsockets''? ==
  
Line 7: Line 8:
 
== Functions ==
 
== Functions ==
 
=== create ===
 
=== create ===
Creates a websocket oject, which can be passed to the [[#connect|connect]] function.
+
Creates a websocket oject, which must be passed to other functions which require it.
 +
 
 
Parameters:
 
Parameters:
* url (string): The URL to connect to.
+
* '''url''' (string): The URL to connect to.
* event_handlers (table): A table where the index is the [[#event_ids|event ID]], and the value is the callback function name.
+
* '''event_handlers''' (table): A table where the index is the [[#Event_IDs|event ID]], and the value is the callback function name.
* ssl_settings (table): A table where the index is the SSL setting name, and the value is the SSL setting value.
+
* '''ssl_settings''' (table): A table where the index is the SSL setting name, and the value is the SSL setting value.
* standalone (boolean): In ''standalone'' mode the service thread won't be detached, which means that the main thread should wait for the service thread to exit, before exiting itself.
+
* '''standalone''' (boolean): Set this to '''true''' if using the library from a standalone Lua script, or to '''false''' if using the library from LuaUPnP. If not set, the default value is '''false'''. If ''standalone'' is ''true'', you must call the [[#loop|''loop'']] function after you call the [[#connect|''connect'']] function.
This is done by calling the [[#loop]] function from Lua.
+
This mode should be used when the library is loaded from a standalone Lua script, which can afford to block for an undefined amount of time.
+
If the library is loaded from LuaUPnP, ''standalone'' should be '''false''', because LuaUPnP functions can't block for much time, otherwise the watchdog will restart the Luup engine.
+
  
 
Returns:
 
Returns:
* wso (websocket)
+
* '''wso''' (websocket): The websocket object.
  
==== Event IDs ====
+
=== connect ===
 +
Connects to the URL from the websocket object.
 +
 
 +
Parameters:
 +
* '''wso''' (websocket): This is the websocket object returned by the [[#create|''create'']] function.
 +
Returns:
 +
* nothing
 +
 
 +
=== loop ===
 +
This function must be called if the [[#create|''create'']] function was called with the ''standalone'' parameter set to ''true''.
 +
It blocks the main thread, waiting for the service thread to finish execution.
 +
 
 +
Parameters:
 +
* none
 +
Returns:
 +
* nothing
 +
 
 +
=== set_log_level ===
 +
Set how verbose the logs should be.
 +
 
 +
The default log level is 0, meaning nothing is logged.
 +
 
 +
If the library is used from LuaUPnP, the logs can be seen in <code>/tmp/log.Init-LuaUPnP</code>
 +
 
 +
Parameters:
 +
* '''log_levels''' (int or string): ''log_levels'' can be either a number, representing a bit mask where each bit is a log level, or the string ''"all"'', which means all log levels enabled, and it's the equivalent of setting all the bits in the mask (''log_levels'' = 2047). The available log levels are listed [[#Log_levels|here]].
 +
<br>
 +
 
 +
== Reference ==
 +
=== Event IDs ===
 
Since ''verawebsockets'' is based on the ''libwebsockets'' library, the verawebsockets event IDs are the same as the libwebsockets callback reasons, which are documented here:
 
Since ''verawebsockets'' is based on the ''libwebsockets'' library, the verawebsockets event IDs are the same as the libwebsockets callback reasons, which are documented here:
 +
 
https://libwebsockets.org/lws-api-doc-v2.4-stable/html/group__usercb.html
 
https://libwebsockets.org/lws-api-doc-v2.4-stable/html/group__usercb.html
  
Line 31: Line 60:
 
! style="border: 1px solid #000" | Description
 
! style="border: 1px solid #000" | Description
 
|-
 
|-
| style="border: 1px solid #000" | 1
+
| style="border: 1px solid #000; text-align: center" | 1
 
| style="border: 1px solid #000" | LWS_CALLBACK_CLIENT_CONNECTION_ERROR
 
| style="border: 1px solid #000" | LWS_CALLBACK_CLIENT_CONNECTION_ERROR
 
| style="border: 1px solid #000" | Failed to connect to the server. The reason for the failure is passed as parameter to the callback function. Some possible values are:
 
| style="border: 1px solid #000" | Failed to connect to the server. The reason for the failure is passed as parameter to the callback function. Some possible values are:
Line 71: Line 100:
 
* HS: Rejected at CLIENT_ESTABLISHED
 
* HS: Rejected at CLIENT_ESTABLISHED
 
|-
 
|-
| style="border: 1px solid #000" | 3
+
| style="border: 1px solid #000; text-align: center" | 3
 
| style="border: 1px solid #000" | LWS_CALLBACK_CLIENT_ESTABLISHED
 
| style="border: 1px solid #000" | LWS_CALLBACK_CLIENT_ESTABLISHED
 
| style="border: 1px solid #000" | Called after the connection with the server has been established. No parameter is passed to the callback function.
 
| style="border: 1px solid #000" | Called after the connection with the server has been established. No parameter is passed to the callback function.
 
|-
 
|-
| style="border: 1px solid #000" | 4
+
| style="border: 1px solid #000; text-align: center" | 4
 
| style="border: 1px solid #000" | LWS_CALLBACK_CLOSED
 
| style="border: 1px solid #000" | LWS_CALLBACK_CLOSED
 
| style="border: 1px solid #000" | Called after the websocket connection closed. No parameter is passed to the callback function.
 
| style="border: 1px solid #000" | Called after the websocket connection closed. No parameter is passed to the callback function.
 
|-
 
|-
| style="border: 1px solid #000" | 8
+
| style="border: 1px solid #000; text-align: center" | 8
 
| style="border: 1px solid #000" | LWS_CALLBACK_CLIENT_RECEIVE
 
| style="border: 1px solid #000" | LWS_CALLBACK_CLIENT_RECEIVE
 
| style="border: 1px solid #000" | Called when we receive data from the server. The received data is passed as parameter to the callback function.
 
| style="border: 1px solid #000" | Called when we receive data from the server. The received data is passed as parameter to the callback function.
 
|}
 
|}
 
+
<br>
==== SSL settings ====
+
=== SSL settings ===
 
These are the SSL settings which are currently supported:
 
These are the SSL settings which are currently supported:
  client_ssl_cert_filepath       : The certificate the client should present to the server on connection.
+
{| style="border: 1px solid #000; border-collapse: collapse"
client_ssl_private_key_filepath : Filepath to the client private key.
+
|-
 +
! style="border: 1px solid #000" | SSL setting
 +
! style="border: 1px solid #000" | Description
 +
|-
 +
| style="border: 1px solid #000; padding: 0px 10px" | client_ssl_cert_filepath
 +
| style="border: 1px solid #000; padding: 0px 10px" | The certificate the client should present to the server on connection.
 +
|-
 +
| style="border: 1px solid #000; padding: 0px 10px" | client_ssl_private_key_filepath
 +
| style="border: 1px solid #000; padding: 0px 10px" | Filepath to the client private key.
 +
|}
 +
<br>
 +
=== Log levels ===
 +
{| style="border: 1px solid #000;  border-collapse: collapse"
 +
|-
 +
! style="border: 1px solid #000; padding: 2px 10px" | Log level
 +
! style="border: 1px solid #000; padding: 2px 10px" | Description
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 1
 +
| style="border: 1px solid #000; padding-left: 10px" | Error
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 2
 +
| style="border: 1px solid #000; padding-left: 10px" | Warning
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 4
 +
| style="border: 1px solid #000; padding-left: 10px" | Notice
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 8
 +
| style="border: 1px solid #000; padding-left: 10px" | Info
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 16
 +
| style="border: 1px solid #000; padding-left: 10px" | Debug
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 32
 +
| style="border: 1px solid #000; padding-left: 10px" | Parser
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 64
 +
| style="border: 1px solid #000; padding-left: 10px" | Header
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 128
 +
| style="border: 1px solid #000; padding-left: 10px" | Extensions
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 256
 +
| style="border: 1px solid #000; padding-left: 10px" | Client
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 512
 +
| style="border: 1px solid #000; padding-left: 10px" | Latency
 +
|-
 +
| style="border: 1px solid #000; text-align: right; padding-right: 10px" | 1024
 +
| style="border: 1px solid #000; padding-left: 10px" | User
 +
|}
 +
<br>
 +
== Example ==
 +
<source lang="lua">#!/usr/bin/lua
  
=== connect ===
+
local ws = require("verawebsockets")
Connects to the URL from the websocket object.
+
if not ws then
Parameters:
+
print("ERROR: Failed to load the verawebsockets library")
* wso (websocket): This is the websocket object returned by the [[#create|create]] function.
+
os.exit(1)
Returns:
+
end
* nothing
+
  
=== loop ===
+
local g_wso
Parameters:
+
 
* none
+
local sslSettings = {
Returns:
+
client_ssl_cert_filepath = "ws.pem"
* nothing
+
}
 +
 
 +
local eventHandlers = {
 +
[1] = "connerror", -- LWS_CALLBACK_CLIENT_CONNECTION_ERROR
 +
[3] = "open",      -- LWS_CALLBACK_CLIENT_ESTABLISHED
 +
[4] = "close",    -- LWS_CALLBACK_CLOSED
 +
[8] = "incoming"  -- LWS_CALLBACK_CLIENT_RECEIVE
 +
}
 +
 
 +
 
 +
function main()
 +
-- Log only errors and warnings.
 +
ws.set_log_level(3)
 +
-- This script is meant to be run standalone, so we set "standalone" to "true".
 +
g_wso = ws.create {
 +
["url"] = "wss://echo.websocket.org",
 +
["ssl_settings"] = sslSettings,
 +
["event_handlers"] = eventHandlers,
 +
["standalone"] = true
 +
}
 +
if not g_wso then
 +
print("ERROR: Failed to create connection")
 +
return 1
 +
end
 +
ws.connect(g_wso)
 +
-- Because we're in standalone mode, call the "loop" function
 +
-- to prevent the main thread from terminating.
 +
ws.loop()
 +
return 0
 +
end
 +
 
 +
 
 +
function connerror (reason)
 +
print("Connection error: "..(reason or nil))
 +
os.exit(1)
 +
end
 +
 
 +
 
 +
function open()
 +
local message = "Hello world!"
 +
print("Connection successful, send message: ".. message)
 +
ws.send(g_wso, message);
 +
end
 +
 
 +
 
 +
function close()
 +
print("Connection closed")
 +
end
 +
 
 +
 
 +
function incoming (data)
 +
data = data or "nil"
 +
print("Received message: ".. data)
 +
if data:match("^Hello world!") then
 +
ws.send(g_wso, "Hello again!");
 +
end
 +
end
  
=== set_log_level ===
 
Parameters:
 
* log_levels (int or string)
 
  
 +
os.exit(main())</source>
 +
<br>
 
== Further documentation ==
 
== Further documentation ==
 
* The WebSocket protocol:
 
* The WebSocket protocol:

Latest revision as of 09:54, 9 March 2018


Contents

[edit] What is verawebsockets?

verawebsockets is a Lua library based on the libwebsockets v2.4 library (https://libwebsockets.org).

The intention is to provide websockets support for the Luup plugins, which means that verawebsockets can be used from LuaUPnP as well as from standalone Lua scripts.

[edit] Functions

[edit] create

Creates a websocket oject, which must be passed to other functions which require it.

Parameters:

  • url (string): The URL to connect to.
  • event_handlers (table): A table where the index is the event ID, and the value is the callback function name.
  • ssl_settings (table): A table where the index is the SSL setting name, and the value is the SSL setting value.
  • standalone (boolean): Set this to true if using the library from a standalone Lua script, or to false if using the library from LuaUPnP. If not set, the default value is false. If standalone is true, you must call the loop function after you call the connect function.

Returns:

  • wso (websocket): The websocket object.

[edit] connect

Connects to the URL from the websocket object.

Parameters:

  • wso (websocket): This is the websocket object returned by the create function.

Returns:

  • nothing

[edit] loop

This function must be called if the create function was called with the standalone parameter set to true. It blocks the main thread, waiting for the service thread to finish execution.

Parameters:

  • none

Returns:

  • nothing

[edit] set_log_level

Set how verbose the logs should be.

The default log level is 0, meaning nothing is logged.

If the library is used from LuaUPnP, the logs can be seen in /tmp/log.Init-LuaUPnP

Parameters:

  • log_levels (int or string): log_levels can be either a number, representing a bit mask where each bit is a log level, or the string "all", which means all log levels enabled, and it's the equivalent of setting all the bits in the mask (log_levels = 2047). The available log levels are listed here.


[edit] Reference

[edit] Event IDs

Since verawebsockets is based on the libwebsockets library, the verawebsockets event IDs are the same as the libwebsockets callback reasons, which are documented here:

https://libwebsockets.org/lws-api-doc-v2.4-stable/html/group__usercb.html

These are the event IDs which are currently supported:

Event ID libwebsockets callback reason Description
1 LWS_CALLBACK_CLIENT_CONNECTION_ERROR Failed to connect to the server. The reason for the failure is passed as parameter to the callback function. Some possible values are:
  • getaddrinfo (ipv6) failed
  • unknown address family
  • getaddrinfo (ipv4) failed
  • set socket opts failed
  • insert wsi failed
  • lws_ssl_client_connect1 failed
  • lws_ssl_client_connect2 failed
  • Peer hung up
  • read failed
  • HS: URI missing
  • HS: Redirect code but no Location
  • HS: URI did not parse
  • HS: Redirect failed
  • HS: Server did not return 200
  • HS: OOM
  • HS: disallowed by client filter
  • HS: disallowed at ESTABLISHED
  • HS: ACCEPT missing
  • HS: ws upgrade response not 101
  • HS: UPGRADE missing
  • HS: Upgrade to something other than websocket
  • HS: CONNECTION missing
  • HS: UPGRADE malformed
  • HS: PROTOCOL malformed
  • HS: Cannot match protocol
  • HS: EXT: list too big
  • HS: EXT: failed setting defaults
  • HS: EXT: failed parsing defaults
  • HS: EXT: failed parsing options
  • HS: EXT: Rejects server options
  • HS: EXT: unknown ext
  • HS: Accept hash wrong
  • HS: Rejected by filter cb
  • HS: OOM
  • HS: SO_SNDBUF failed
  • HS: Rejected at CLIENT_ESTABLISHED
3 LWS_CALLBACK_CLIENT_ESTABLISHED Called after the connection with the server has been established. No parameter is passed to the callback function.
4 LWS_CALLBACK_CLOSED Called after the websocket connection closed. No parameter is passed to the callback function.
8 LWS_CALLBACK_CLIENT_RECEIVE Called when we receive data from the server. The received data is passed as parameter to the callback function.


[edit] SSL settings

These are the SSL settings which are currently supported:

SSL setting Description
client_ssl_cert_filepath The certificate the client should present to the server on connection.
client_ssl_private_key_filepath Filepath to the client private key.


[edit] Log levels

Log level Description
1 Error
2 Warning
4 Notice
8 Info
16 Debug
32 Parser
64 Header
128 Extensions
256 Client
512 Latency
1024 User


[edit] Example

#!/usr/bin/lua
 
local ws = require("verawebsockets")
if not ws then
	print("ERROR: Failed to load the verawebsockets library")
	os.exit(1)
end
 
local g_wso
 
local sslSettings = {
	client_ssl_cert_filepath = "ws.pem"
}
 
local eventHandlers = {
	[1] = "connerror", -- LWS_CALLBACK_CLIENT_CONNECTION_ERROR
	[3] = "open",      -- LWS_CALLBACK_CLIENT_ESTABLISHED
	[4] = "close",     -- LWS_CALLBACK_CLOSED
	[8] = "incoming"   -- LWS_CALLBACK_CLIENT_RECEIVE
}
 
 
function main()
	-- Log only errors and warnings.
	ws.set_log_level(3)
	-- This script is meant to be run standalone, so we set "standalone" to "true".
	g_wso = ws.create {
		["url"] = "wss://echo.websocket.org",
		["ssl_settings"] = sslSettings,
		["event_handlers"] = eventHandlers,
		["standalone"] = true
	}
	if not g_wso then
		print("ERROR: Failed to create connection")
		return 1
	end
	ws.connect(g_wso)
	-- Because we're in standalone mode, call the "loop" function
	-- to prevent the main thread from terminating.
	ws.loop()
	return 0
end
 
 
function connerror (reason)
	print("Connection error: "..(reason or nil))
	os.exit(1)
end
 
 
function open()
	local message = "Hello world!"
	print("Connection successful, send message: ".. message)
	ws.send(g_wso, message);
end
 
 
function close()
	print("Connection closed")
end
 
 
function incoming (data)
	data = data or "nil"
	print("Received message: ".. data)
	if data:match("^Hello world!") then
		ws.send(g_wso, "Hello again!");
	end
end
 
 
os.exit(main())


[edit] Further documentation

  • The WebSocket protocol:

https://tools.ietf.org/html/rfc6455

  • The libwebsockets library:

https://libwebsockets.org

  • libwebsockets v2.4 documentation:

https://libwebsockets.org/lws-api-doc-v2.4-stable/html/index.html

Personal tools