import rest client
This commit is contained in:
@@ -0,0 +1,85 @@
|
|||||||
|
cmake_minimum_required (VERSION 3.0)
|
||||||
|
|
||||||
|
project (uhttpd-awox-api-plugin)
|
||||||
|
|
||||||
|
set (CMAKE_MODULE_PATH "${MODULE_PATH}")
|
||||||
|
set (CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
|
include (aw)
|
||||||
|
|
||||||
|
include_directories ($ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/)
|
||||||
|
|
||||||
|
file (
|
||||||
|
GLOB_RECURSE
|
||||||
|
source_files
|
||||||
|
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/plugin.c
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/uhttp-server.cpp
|
||||||
|
# core
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/core/http-reason.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/core/http-parameter.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/core/http-header.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/core/uri-transform.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/core/web-controller.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/core/web-connection.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/core/ubus-connection.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/core/ubus-reason.cpp
|
||||||
|
# rest
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/rest/rest-controller.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/rest/rest-connection.cpp
|
||||||
|
#etag-rest
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/etag-rest/etag-rest-controller.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/etag-rest/etag-rest-connection.cpp
|
||||||
|
# notification
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/notification/notification-controller.cpp
|
||||||
|
$ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/notification/notification-connection.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library (awox-api-plugin SHARED ${source_files})
|
||||||
|
|
||||||
|
target_link_libraries (awox-api-plugin
|
||||||
|
LINK_PUBLIC
|
||||||
|
ubus
|
||||||
|
ubox
|
||||||
|
blobmsg_json
|
||||||
|
json-c
|
||||||
|
fmt
|
||||||
|
aw-ubus
|
||||||
|
)
|
||||||
|
|
||||||
|
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
|
||||||
|
|
||||||
|
set_target_properties (awox-api-plugin PROPERTIES PREFIX "uhttpd_")
|
||||||
|
|
||||||
|
target_include_directories (awox-api-plugin PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
install (TARGETS awox-api-plugin LIBRARY DESTINATION local/bin/Plugins/)
|
||||||
|
|
||||||
|
if (INSTALL_CORE)
|
||||||
|
install (FILES $ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/configs/core.json DESTINATION local/configs/restd/)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (INSTALL_SPOTIFY)
|
||||||
|
install (FILES $ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/configs/spotify.json DESTINATION local/configs/restd/)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (INSTALL_DEAP)
|
||||||
|
install (FILES $ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/configs/deap.json DESTINATION local/configs/restd/)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (INSTALL_LIGHT)
|
||||||
|
install (FILES $ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/configs/light.json DESTINATION local/configs/restd/)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (INSTALL_LIGHT_COLOR)
|
||||||
|
install (FILES $ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/configs/light-color.json DESTINATION local/configs/restd/)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (INSTALL_LIGHT_WHITE)
|
||||||
|
install (FILES $ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/configs/light-white.json DESTINATION local/configs/restd/)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (INSTALL_VOICE_CONTROL)
|
||||||
|
install (FILES $ENV{AWOXCVS}/AwoxAudio/Plugins/uhttpd/uhttpd-awox-api/configs/voice-control.json DESTINATION local/configs/restd/)
|
||||||
|
endif ()
|
||||||
|
|
||||||
431
src/plugins/uhttpd/uhttpd-rest-api/configs/core.json
Normal file
431
src/plugins/uhttpd/uhttpd-rest-api/configs/core.json
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
// Comments
|
||||||
|
{
|
||||||
|
"controller": [
|
||||||
|
// --- Network
|
||||||
|
{
|
||||||
|
// Network Info Controller
|
||||||
|
"path": "/Network/Info.json",
|
||||||
|
"model_name": "network.info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// WIFI AP List.
|
||||||
|
"path": "/Network/Wifi/List.json",
|
||||||
|
"model_name": "network.wifi",
|
||||||
|
"get_method": "list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// WIFI Connection.
|
||||||
|
"path": "/Network/Wifi/Connect.json",
|
||||||
|
"model_name": "network.wifi",
|
||||||
|
"set_method": "connect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Static Settings.
|
||||||
|
"path": "/Network/StaticConfig.json",
|
||||||
|
"model_name": "network.config",
|
||||||
|
"set_method": "static_config"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Enable/Disable Wifi.
|
||||||
|
"path": "/Network/EnableWifi.json",
|
||||||
|
"model_name": "network.config",
|
||||||
|
"set_method": "wifi_enable"
|
||||||
|
},
|
||||||
|
// --- System
|
||||||
|
{
|
||||||
|
// Locale Control Controller
|
||||||
|
"path": "/System/Locale.json",
|
||||||
|
"model_name": "system.locale"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Time Zone Controller
|
||||||
|
"path": "/System/Timezone.json",
|
||||||
|
"model_name": "system.timezone"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// FriendlyName Control Controller
|
||||||
|
"path": "/System/FriendlyName.json",
|
||||||
|
"model_name": "system.friendlyname"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// SoundNotification Control Controller
|
||||||
|
"path": "/System/SoundNotification.json",
|
||||||
|
"model_name": "system.soundnotification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Reboot
|
||||||
|
"path": "/System/Reboot.json",
|
||||||
|
"model_name": "system.maintenance",
|
||||||
|
"set_method": "reboot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Reset
|
||||||
|
"path": "/System/Reset.json",
|
||||||
|
"model_name": "system.maintenance",
|
||||||
|
"set_method": "reset"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// DeviceInfo Controller
|
||||||
|
"path": "/System/DeviceInfo.json",
|
||||||
|
"model_name": "system.deviceinfo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Standby
|
||||||
|
"path": "/System/Standby.json",
|
||||||
|
"model_name": "system.standby"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Standby switch
|
||||||
|
"path": "/System/Standby/Switch.json",
|
||||||
|
"model_name": "system.standby",
|
||||||
|
"set_method": "switch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Block Input
|
||||||
|
"path": "/System/Input/Block.json",
|
||||||
|
"model_name": "system.input.control"
|
||||||
|
},
|
||||||
|
// System - Upgrade Auto
|
||||||
|
{
|
||||||
|
"path": "/System/Upgrade/Auto.json",
|
||||||
|
"model_name": "system.upgrade.auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/System/Upgrade/Check.json",
|
||||||
|
"model_name": "system.upgrade",
|
||||||
|
"set_method": "check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/System/Upgrade/Start.json",
|
||||||
|
"model_name": "system.upgrade",
|
||||||
|
"set_method": "start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/System/Upgrade/Stop.json",
|
||||||
|
"model_name": "system.upgrade",
|
||||||
|
"set_method": "stop"
|
||||||
|
},
|
||||||
|
// -- Miscellaneous
|
||||||
|
{
|
||||||
|
"path": "/System/RangeExtender.json",
|
||||||
|
"model_name": "network.range_extender"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/System/Status/Led.json",
|
||||||
|
"model_name": "light.capability.blue_led",
|
||||||
|
"get_method": "get_statewhenlightisoff",
|
||||||
|
"set_method": "set_statewhenlightisoff"
|
||||||
|
},
|
||||||
|
// --- Hardware Control Controller
|
||||||
|
{
|
||||||
|
"path": "/Hardware/Cpu/Info.json",
|
||||||
|
"model_name": "hardware.cpuinfo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Hardware/Memory/Info.json",
|
||||||
|
"model_name": "hardware.memoryinfo"
|
||||||
|
},
|
||||||
|
// --- Presets Controller
|
||||||
|
{
|
||||||
|
// Browse.
|
||||||
|
"path": "/Player/Presets.json",
|
||||||
|
"model_name": "player.dlna.presets",
|
||||||
|
"set_method": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Play Preset.
|
||||||
|
"path": "/Player/PlayPreset.json",
|
||||||
|
"model_name": "player.dlna.presets",
|
||||||
|
"set_method": "play"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Store Preset.
|
||||||
|
"path": "/Player/StorePreset.json",
|
||||||
|
"model_name": "player.dlna.presets",
|
||||||
|
"set_method": "store"
|
||||||
|
},
|
||||||
|
// --- Alarms Controller
|
||||||
|
{
|
||||||
|
// Configuration
|
||||||
|
"path": "/Alarm/Configuration.json",
|
||||||
|
"model_name": "alarm.configuration"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Count
|
||||||
|
"path": "/Alarm/Count.json",
|
||||||
|
"model_name": "alarm.count"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Preset Control
|
||||||
|
"path": "/Alarm/Preset/Info.json",
|
||||||
|
"model_name": "alarm.presets"
|
||||||
|
},
|
||||||
|
// --- Mixer Controller
|
||||||
|
{
|
||||||
|
"path": "/Mixer/Capabilities.json",
|
||||||
|
"model_name": "system.mixer.capabilities"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Mixer/Capability/Volume.json",
|
||||||
|
"model_name": "zone.mixer.volume"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Mixer/Capability/Mute.json",
|
||||||
|
"model_name": "zone.mixer.mute"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Mixer/Capability/Mute/Switch.json",
|
||||||
|
"model_name": "zone.mixer.mute",
|
||||||
|
"set_method": "switch"
|
||||||
|
},
|
||||||
|
// --- Song Queue Controller
|
||||||
|
// --- Content
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Content/List.json",
|
||||||
|
"model_name": "songqueue.content",
|
||||||
|
"get_method": "list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Content/Add.json",
|
||||||
|
"model_name": "songqueue.content",
|
||||||
|
"set_method": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Content/Remove.json",
|
||||||
|
"model_name": "songqueue.content",
|
||||||
|
"set_method": "remove"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Content/Clear.json",
|
||||||
|
"model_name": "songqueue.content",
|
||||||
|
"set_method": "clear"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Content/MaxSongsNumber.json",
|
||||||
|
"model_name": "songqueue.content",
|
||||||
|
"get_method": "get_maxsongsnumber"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Content/MovePosition.json",
|
||||||
|
"model_name": "songqueue.content",
|
||||||
|
"set_method": "move_position"
|
||||||
|
},
|
||||||
|
//--- Control
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/Position.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"get_method": "get_position",
|
||||||
|
"set_method": "set_position"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/Play.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"set_method": "play"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/Pause.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"set_method": "pause"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/PlayPause.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"set_method": "play_pause"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/Stop.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"set_method": "stop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/Next.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"set_method": "next"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/Previous.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"set_method": "previous"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/RepeatMode.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"get_method": "get_repeatmode",
|
||||||
|
"set_method": "set_repeatmode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/ToggleRepeatMode.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"set_method": "toggle_repeatmode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/ShuffleMode.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"get_method": "get_shufflemode",
|
||||||
|
"set_method": "set_shufflemode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/ToggleShuffleMode.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"set_method": "toggle_shufflemode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/SongQueue/Control/ActiveState.json",
|
||||||
|
"model_name": "songqueue.control",
|
||||||
|
"get_method": "get_activestate"
|
||||||
|
},
|
||||||
|
// --- Player Controller
|
||||||
|
{
|
||||||
|
"path": "/Player/PlayPause.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "play_pause"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/Pause.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "pause"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/Play.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "play"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/Stop.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "stop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/Previous.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "previous"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/Next.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "next"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/SetPosition.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "set_position"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/PlayURI.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "play_uri"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/Say.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "say"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/Player/NotifyURI.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"set_method": "notify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// --- source selection
|
||||||
|
"path": "/Player/SourceSelection.json",
|
||||||
|
"model_name": "player.audio.source"
|
||||||
|
},
|
||||||
|
// --- Private Controller
|
||||||
|
{
|
||||||
|
// --- PreProd Controller
|
||||||
|
"path": "/Control/PreProd.json",
|
||||||
|
"model_name": "system.upgrade",
|
||||||
|
"get_method": "get_preprod_state",
|
||||||
|
"set_method": "set_preprod_state"
|
||||||
|
},
|
||||||
|
// --- Discovery Controller
|
||||||
|
{
|
||||||
|
"path": "/System/Discovery.json",
|
||||||
|
"model_name": "mdns.browser"
|
||||||
|
},
|
||||||
|
// --- Playback stats controller
|
||||||
|
{
|
||||||
|
"path": "/ContentService/PlaybackStat/Start.json",
|
||||||
|
"model_name": "contentService.playbackStats",
|
||||||
|
"set_method": "start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/ContentService/PlaybackStat/Stop.json",
|
||||||
|
"model_name": "contentService.playbackStats",
|
||||||
|
"set_method": "stop"
|
||||||
|
},
|
||||||
|
// --- AudioHub controller
|
||||||
|
{
|
||||||
|
// --- Control
|
||||||
|
"path": "/System/AudioHub.json",
|
||||||
|
"model_name": "system.audiohub"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// --- Troubleshooting and statistics
|
||||||
|
"path": "/Stats/AudioHub/Bandwidth.json",
|
||||||
|
"model_name": "stats.audiohub.bandwidth"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"etag_controller": [
|
||||||
|
{
|
||||||
|
// Zone State Controller
|
||||||
|
"path": "/Zone/State.json",
|
||||||
|
"model_name": "zone.state",
|
||||||
|
"event_name": "zone.state.updated",
|
||||||
|
"etag_key": "version_above",
|
||||||
|
"set_method": "post"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Zone Status (monitoring) Controller
|
||||||
|
"path": "/Zone/Status.json",
|
||||||
|
"model_name": "zone.status",
|
||||||
|
"event_name": "zone.status.updated",
|
||||||
|
"etag_key": "version_above"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Player State Controller
|
||||||
|
"path": "/Player/State.json",
|
||||||
|
"model_name": "player.meta",
|
||||||
|
"event_name": "player.state.updated",
|
||||||
|
"etag_key": "version_above",
|
||||||
|
"get_method": "get_state"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"notification": [
|
||||||
|
{
|
||||||
|
// Source selection.
|
||||||
|
"path": "/Service/Notification/SourceSelection.json",
|
||||||
|
"event_name": "player.sourceSelection"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Player Presets.
|
||||||
|
"path": "/Service/Notification/Presets.json",
|
||||||
|
"event_name": "player.preset"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Mixer.
|
||||||
|
"path": "/Service/Notification/Mixer.json",
|
||||||
|
"event_name": "system_mixer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Song Queue.
|
||||||
|
"path": "/Service/Notification/SongQueue.json",
|
||||||
|
"event_name": "songqueue.notification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Firmware upgrade.
|
||||||
|
"path": "/Service/Notification/Upgrade.json",
|
||||||
|
"event_name": "system.upgrade.notification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Player state.
|
||||||
|
"path": "/Service/Notification/PlayerState.json",
|
||||||
|
"event_name": "player.state"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Player track.
|
||||||
|
"path": "/Service/Notification/PlayerTrack.json",
|
||||||
|
"event_name": "player.track"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
src/plugins/uhttpd/uhttpd-rest-api/configs/spotify.json
Normal file
11
src/plugins/uhttpd/uhttpd-rest-api/configs/spotify.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Comments
|
||||||
|
{
|
||||||
|
"controller": [
|
||||||
|
{
|
||||||
|
// --- Spotify Connect Controller
|
||||||
|
"path": "/spotify/Connect.json",
|
||||||
|
"model_name": "player.spotify.connect",
|
||||||
|
"raw_response": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// Comments
|
||||||
|
{
|
||||||
|
"controller": [
|
||||||
|
{
|
||||||
|
"path": "/VoiceControl/State.json",
|
||||||
|
"model_name": "voice.control",
|
||||||
|
"get_method": "get"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/VoiceControl/Associate.json",
|
||||||
|
"model_name": "voice.control",
|
||||||
|
"set_method": "associate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/VoiceControl/Disassociate.json",
|
||||||
|
"model_name": "voice.control",
|
||||||
|
"set_method": "disassociate"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
178
src/plugins/uhttpd/uhttpd-rest-api/core/http-header.cpp
Normal file
178
src/plugins/uhttpd/uhttpd-rest-api/core/http-header.cpp
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 30/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libubox/ustream.h>
|
||||||
|
#include <libubox/blobmsg_json.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
#include <uhttpd/plugin.h>
|
||||||
|
|
||||||
|
#include "http-reason.h"
|
||||||
|
|
||||||
|
#include "http-header.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char * const g_http_versions[] = {
|
||||||
|
[UH_HTTP_VER_0_9] = "HTTP/0.9",
|
||||||
|
[UH_HTTP_VER_1_0] = "HTTP/1.0",
|
||||||
|
[UH_HTTP_VER_1_1] = "HTTP/1.1",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn HttpHeader
|
||||||
|
*
|
||||||
|
* @brief constructor of the http header.
|
||||||
|
*/
|
||||||
|
HttpHeader::HttpHeader (void) :
|
||||||
|
m_origin("*"),
|
||||||
|
m_timeout(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn HttpHeader
|
||||||
|
*
|
||||||
|
* @brief constructor of the http header.
|
||||||
|
*/
|
||||||
|
HttpHeader::HttpHeader (uint16_t a_timeout) :
|
||||||
|
m_origin("*"),
|
||||||
|
m_timeout(a_timeout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn send
|
||||||
|
*
|
||||||
|
* @brief send an http header response.
|
||||||
|
*/
|
||||||
|
void HttpHeader::send (uhttpd_ops *an_ops, client *a_client, uint16_t a_code, bool a_chunked)
|
||||||
|
{
|
||||||
|
prepare_header(a_client, a_code, HttpReason::get(a_code));
|
||||||
|
ustream_printf(a_client->us, "Access-Control-Allow-Origin: %s\r\n", m_origin.c_str());
|
||||||
|
|
||||||
|
if (!m_etag.empty()) {
|
||||||
|
|
||||||
|
ustream_printf(a_client->us, "ETag: %s\r\n", m_etag.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
ustream_printf(a_client->us, "Content-Type: application/json\r\n");
|
||||||
|
|
||||||
|
if (!a_chunked)
|
||||||
|
ustream_printf(a_client->us, "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn send_option
|
||||||
|
*
|
||||||
|
* @brief send an http header option response.
|
||||||
|
*/
|
||||||
|
void HttpHeader::send_option (uhttpd_ops *an_ops, client *a_client, uint16_t a_code)
|
||||||
|
{
|
||||||
|
prepare_header(a_client, a_code, HttpReason::get(a_code));
|
||||||
|
ustream_printf(a_client->us, "Access-Control-Allow-Headers: Accept, Content-Type, If-None-Match, Prefer\r\n");
|
||||||
|
ustream_printf(a_client->us, "Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\r\n");
|
||||||
|
ustream_printf(a_client->us, "Access-Control-Allow-Origin: %s\r\n", m_origin.c_str());
|
||||||
|
|
||||||
|
an_ops->request_done(a_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn add_origin
|
||||||
|
*
|
||||||
|
* @brief add an etag to the header request.
|
||||||
|
*/
|
||||||
|
void HttpHeader::add_origin (const std::string &an_origin)
|
||||||
|
{
|
||||||
|
m_origin = an_origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn add_etag
|
||||||
|
*
|
||||||
|
* @brief add an etag to the header request.
|
||||||
|
*/
|
||||||
|
void HttpHeader::add_etag (const std::string &an_etag)
|
||||||
|
{
|
||||||
|
m_etag = an_etag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn add_timeout
|
||||||
|
*
|
||||||
|
* @brief change the time out of the header request.
|
||||||
|
*/
|
||||||
|
void HttpHeader::add_timeout (uint16_t a_timeout)
|
||||||
|
{
|
||||||
|
m_timeout = a_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn use_chunked
|
||||||
|
*
|
||||||
|
* @brief return true if the connection could use a chunked response.
|
||||||
|
*/
|
||||||
|
bool HttpHeader::use_chunked (struct client *a_client)
|
||||||
|
{
|
||||||
|
if (a_client->request.version != UH_HTTP_VER_1_1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (a_client->request.method == UH_HTTP_MSG_HEAD || a_client->request.method == UH_HTTP_MSG_OPTIONS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* RFC2616 10.2.5, 10.3.5 */
|
||||||
|
if (a_client->http_code == 204 || a_client->http_code == 304)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !a_client->request.disable_chunked;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn prepare_header
|
||||||
|
*
|
||||||
|
* @brief prepare and fill the first part of the http header.
|
||||||
|
*/
|
||||||
|
void HttpHeader::prepare_header (struct client *a_client, int a_code, const std::string &a_summary)
|
||||||
|
{
|
||||||
|
struct http_request *the_req = &a_client->request;
|
||||||
|
const char *the_enc = "Transfer-Encoding: chunked\r\n";
|
||||||
|
const char *the_conn;
|
||||||
|
|
||||||
|
a_client->http_code = a_code;
|
||||||
|
|
||||||
|
if (!use_chunked(a_client))
|
||||||
|
the_enc = "";
|
||||||
|
|
||||||
|
if (the_req->connection_close)
|
||||||
|
the_conn = "Connection: close";
|
||||||
|
else
|
||||||
|
the_conn = "Connection: Keep-Alive";
|
||||||
|
|
||||||
|
ustream_printf(a_client->us, "%s %03i %s\r\n%s\r\n%s",
|
||||||
|
g_http_versions[a_client->request.version],
|
||||||
|
a_code, a_summary.c_str(), the_conn, the_enc);
|
||||||
|
|
||||||
|
if (!the_req->connection_close)
|
||||||
|
ustream_printf(a_client->us, "Keep-Alive: timeout=%d\r\n", m_timeout);
|
||||||
|
}
|
||||||
48
src/plugins/uhttpd/uhttpd-rest-api/core/http-header.h
Normal file
48
src/plugins/uhttpd/uhttpd-rest-api/core/http-header.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 30/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HTTP_HEADER_H
|
||||||
|
#define _HTTP_HEADER_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
struct client;
|
||||||
|
struct uhttpd_ops;
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class HttpHeader {
|
||||||
|
|
||||||
|
public:
|
||||||
|
HttpHeader (void);
|
||||||
|
HttpHeader (uint16_t a_timeout);
|
||||||
|
|
||||||
|
void send (uhttpd_ops *an_ops, client *a_client, uint16_t a_code, bool a_chunked = false);
|
||||||
|
void send_option (uhttpd_ops *an_ops, client *a_client, uint16_t a_code);
|
||||||
|
|
||||||
|
void add_origin (const std::string &an_origin);
|
||||||
|
void add_etag (const std::string &an_etag);
|
||||||
|
void add_timeout (uint16_t a_timeout);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool use_chunked (struct client *a_client);
|
||||||
|
void prepare_header (struct client *a_client, int a_code, const std::string &a_summary);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_etag;
|
||||||
|
std::string m_origin;
|
||||||
|
uint16_t m_timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _HTTP_HEADER_H */
|
||||||
218
src/plugins/uhttpd/uhttpd-rest-api/core/http-parameter.cpp
Normal file
218
src/plugins/uhttpd/uhttpd-rest-api/core/http-parameter.cpp
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 30/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libubox/blobmsg_json.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
|
||||||
|
#include "core/uri-transform.h"
|
||||||
|
|
||||||
|
#include "http-parameter.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define kIfNoneMatch "if-none-match"
|
||||||
|
#define kPrefer "prefer"
|
||||||
|
#define kOrigin "origin"
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn HttpParameter
|
||||||
|
*
|
||||||
|
* @brief constructor of the http parameter.
|
||||||
|
*/
|
||||||
|
HttpParameter::HttpParameter (void) :
|
||||||
|
m_request_timeout(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn parse_from_uri
|
||||||
|
*
|
||||||
|
* @brief parse parameters from the uri.
|
||||||
|
*/
|
||||||
|
std::string HttpParameter::parse_from_uri (const std::string &a_parameters)
|
||||||
|
{
|
||||||
|
std::string the_result;
|
||||||
|
std::vector<std::string> the_list;
|
||||||
|
std::vector<std::string>::iterator the_it;
|
||||||
|
std::string the_key, the_value, the_value_decoded;
|
||||||
|
std::size_t the_pos;
|
||||||
|
struct json_object *the_root_node = NULL;
|
||||||
|
the_root_node = json_object_new_object();
|
||||||
|
|
||||||
|
the_list = split_params(a_parameters, '&');
|
||||||
|
for (the_it = the_list.begin(); the_it != the_list.end(); ++the_it) {
|
||||||
|
|
||||||
|
// printf("--> %s\n", (*the_it).c_str());
|
||||||
|
the_pos = (*the_it).find_first_of("=", 0);
|
||||||
|
if (the_pos != std::string::npos) {
|
||||||
|
|
||||||
|
the_key = (*the_it).substr(0, the_pos);
|
||||||
|
the_value = (*the_it).substr(the_pos + 1);
|
||||||
|
the_value_decoded = UriTransform::decode(the_value);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf(" - key = %s\n", the_key.c_str());
|
||||||
|
printf(" - value = %s\n", the_value.c_str());
|
||||||
|
printf(" - valuedecode = %s\n", the_value_decoded.c_str());
|
||||||
|
#endif
|
||||||
|
if (is_number(the_value_decoded))
|
||||||
|
json_object_object_add(the_root_node, the_key.c_str(), json_object_new_int(std::stoi(the_value_decoded)));
|
||||||
|
else if (the_value_decoded == "true")
|
||||||
|
json_object_object_add(the_root_node, the_key.c_str(), json_object_new_boolean(true));
|
||||||
|
else if (the_value_decoded == "false")
|
||||||
|
json_object_object_add(the_root_node, the_key.c_str(), json_object_new_boolean(false));
|
||||||
|
else
|
||||||
|
json_object_object_add(the_root_node, the_key.c_str(), json_object_new_string(the_value_decoded.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
the_result = json_object_to_json_string(the_root_node);
|
||||||
|
|
||||||
|
// Clean the json object.
|
||||||
|
json_object_put(the_root_node);
|
||||||
|
|
||||||
|
return the_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn parse
|
||||||
|
*
|
||||||
|
* @brief parse the http header and save only the wanted headers.
|
||||||
|
*/
|
||||||
|
bool HttpParameter::parse (client *a_client)
|
||||||
|
{
|
||||||
|
std::string the_prefer_string;
|
||||||
|
char *the_string = blobmsg_format_json(a_client->hdr.head, true);
|
||||||
|
struct json_object *the_root_node = NULL, *the_value_node;
|
||||||
|
|
||||||
|
the_root_node = json_tokener_parse(the_string);
|
||||||
|
// printf("HttpParameter::parse: <%s>\n", the_string);
|
||||||
|
free(the_string);
|
||||||
|
|
||||||
|
if (the_root_node == NULL) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get if-none-match
|
||||||
|
if (json_object_object_get_ex(the_root_node, kIfNoneMatch, &the_value_node)) {
|
||||||
|
|
||||||
|
m_etag = json_object_get_string(the_value_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Prefer - wait RFC 7240 // Prefer: wait=120
|
||||||
|
if (json_object_object_get_ex(the_root_node, kPrefer, &the_value_node)) {
|
||||||
|
|
||||||
|
std::vector<std::string> the_list;
|
||||||
|
the_prefer_string = json_object_get_string(the_value_node);
|
||||||
|
the_list = split_params(the_prefer_string, '=');
|
||||||
|
std::string the_token = the_list [1];
|
||||||
|
//printf("the_prefer_string: %s\n", the_prefer_string.c_str());
|
||||||
|
//printf("the_token: %s\n", the_token.c_str());
|
||||||
|
|
||||||
|
if (is_number(the_token)) {
|
||||||
|
|
||||||
|
m_request_timeout = std::atoi(the_token.c_str());
|
||||||
|
}
|
||||||
|
// printf("timeout = %d\n", m_request_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Origin
|
||||||
|
if (json_object_object_get_ex(the_root_node, kOrigin, &the_value_node)) {
|
||||||
|
|
||||||
|
m_origin = json_object_get_string(the_value_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_put(the_root_node);
|
||||||
|
|
||||||
|
// printf("parse: E-tag: %s, timeout: %d, origin: %s\n", m_etag.c_str(), m_request_timeout, m_origin.c_str());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_origin
|
||||||
|
*
|
||||||
|
* @brief get the etag from the header request.
|
||||||
|
*/
|
||||||
|
std::string HttpParameter::get_origin (void)
|
||||||
|
{
|
||||||
|
return m_origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_etag
|
||||||
|
*
|
||||||
|
* @brief get the etag from the header request.
|
||||||
|
*/
|
||||||
|
std::string HttpParameter::get_etag (void)
|
||||||
|
{
|
||||||
|
return m_etag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_request_timeout
|
||||||
|
*
|
||||||
|
* @brief extract the the keep-alive timeout from the header (as second)
|
||||||
|
* and return it as millisecond timeout.
|
||||||
|
*/
|
||||||
|
int16_t HttpParameter::get_request_timeout (void)
|
||||||
|
{
|
||||||
|
return m_request_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn split_params
|
||||||
|
*
|
||||||
|
* @brief method to split a string into sub string from a separator. and return a
|
||||||
|
* vector from all the substrings.
|
||||||
|
*/
|
||||||
|
std::vector<std::string> HttpParameter::split_params (const std::string &a_string, char a_seperator)
|
||||||
|
{
|
||||||
|
std::vector<std::string> the_output;
|
||||||
|
|
||||||
|
std::string::size_type the_prev_pos = 0, the_pos = 0;
|
||||||
|
|
||||||
|
while ((the_pos = a_string.find(a_seperator, the_pos)) != std::string::npos) {
|
||||||
|
|
||||||
|
std::string substring(a_string.substr(the_prev_pos, the_pos - the_prev_pos));
|
||||||
|
the_output.push_back(substring);
|
||||||
|
the_prev_pos = ++the_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
the_output.push_back(a_string.substr(the_prev_pos, the_pos - the_prev_pos)); // Last word
|
||||||
|
|
||||||
|
return the_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn is_number
|
||||||
|
*
|
||||||
|
* @brief return true if the string given has parameter is a number.
|
||||||
|
*/
|
||||||
|
bool HttpParameter::is_number (const std::string & a_string)
|
||||||
|
{
|
||||||
|
char* p;
|
||||||
|
strtod (a_string.c_str(), &p);
|
||||||
|
return *p == 0;
|
||||||
|
}
|
||||||
49
src/plugins/uhttpd/uhttpd-rest-api/core/http-parameter.h
Normal file
49
src/plugins/uhttpd/uhttpd-rest-api/core/http-parameter.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 30/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HTTP_PARAMETERS_H
|
||||||
|
#define _HTTP_PARAMETERS_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
struct client;
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class HttpParameter {
|
||||||
|
|
||||||
|
public:
|
||||||
|
HttpParameter (void);
|
||||||
|
|
||||||
|
std::string parse_from_uri (const std::string &a_parameters);
|
||||||
|
|
||||||
|
bool parse (client *a_client);
|
||||||
|
|
||||||
|
std::string get_origin (void);
|
||||||
|
std::string get_etag (void);
|
||||||
|
int16_t get_request_timeout (void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> split_params (const std::string &a_string, char a_seperator);
|
||||||
|
bool is_number (const std::string & a_string);
|
||||||
|
|
||||||
|
std::string m_origin;
|
||||||
|
std::string m_etag;
|
||||||
|
int16_t m_request_timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _HTTP_PARAMETERS_H */
|
||||||
161
src/plugins/uhttpd/uhttpd-rest-api/core/http-reason.cpp
Normal file
161
src/plugins/uhttpd/uhttpd-rest-api/core/http-reason.cpp
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 22/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include "http-reason.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn HttpReason
|
||||||
|
*
|
||||||
|
* @brief constructor of the http reason.
|
||||||
|
*/
|
||||||
|
HttpReason::HttpReason (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get
|
||||||
|
*
|
||||||
|
* @brief return as string the reazson from the http code.
|
||||||
|
*/
|
||||||
|
std::string HttpReason::get (uint16_t a_code)
|
||||||
|
{
|
||||||
|
switch (a_code) {
|
||||||
|
// --- 100
|
||||||
|
case 100:
|
||||||
|
return "Continue";
|
||||||
|
case 101:
|
||||||
|
return "Switching Protocols";
|
||||||
|
case 102:
|
||||||
|
return "Processing";
|
||||||
|
// --- 200
|
||||||
|
case 200:
|
||||||
|
return "OK";
|
||||||
|
case 201:
|
||||||
|
return "Created";
|
||||||
|
case 202:
|
||||||
|
return "Accepted";
|
||||||
|
case 203:
|
||||||
|
return "Non-Authoritative Information";
|
||||||
|
case 204:
|
||||||
|
return "No Content";
|
||||||
|
case 205:
|
||||||
|
return "Reset Content";
|
||||||
|
case 206:
|
||||||
|
return "Partial Content";
|
||||||
|
case 207:
|
||||||
|
return "Multi-Status";
|
||||||
|
// --- 300
|
||||||
|
case 300:
|
||||||
|
return "Multiple Choices";
|
||||||
|
case 301:
|
||||||
|
return "Moved Permanently";
|
||||||
|
case 302:
|
||||||
|
return "Moved Temporarily";
|
||||||
|
case 303:
|
||||||
|
return "See Other";
|
||||||
|
case 304:
|
||||||
|
return "Not Modified";
|
||||||
|
case 305:
|
||||||
|
return "Use Proxy";
|
||||||
|
case 307:
|
||||||
|
return "Temporary Redirect";
|
||||||
|
case 308:
|
||||||
|
return "Permanent Redirect";
|
||||||
|
case 310:
|
||||||
|
return "Too many Redirects";
|
||||||
|
// --- 400
|
||||||
|
case 400:
|
||||||
|
return "Bad Request";
|
||||||
|
case 401:
|
||||||
|
return "Unauthorized";
|
||||||
|
case 402:
|
||||||
|
return "Payment Required";
|
||||||
|
case 403:
|
||||||
|
return "Forbidden";
|
||||||
|
case 404:
|
||||||
|
return "Not Found";
|
||||||
|
case 405:
|
||||||
|
return "Method Not Allowed";
|
||||||
|
case 406:
|
||||||
|
return "Not Acceptable";
|
||||||
|
case 407:
|
||||||
|
return "Proxy Authentication Required";
|
||||||
|
case 408:
|
||||||
|
return "Request Time-out";
|
||||||
|
case 409:
|
||||||
|
return "Conflict";
|
||||||
|
case 410:
|
||||||
|
return "Gone";
|
||||||
|
case 411:
|
||||||
|
return "Length Required";
|
||||||
|
case 412:
|
||||||
|
return "Precondition Failed";
|
||||||
|
case 413:
|
||||||
|
return "Request Entity Too Large";
|
||||||
|
case 414:
|
||||||
|
return "Request-URI Too Long";
|
||||||
|
case 415:
|
||||||
|
return "Unsupported Media Type";
|
||||||
|
case 416:
|
||||||
|
return "Requested range unsatisfiable";
|
||||||
|
case 417:
|
||||||
|
return "Expectation failed";
|
||||||
|
case 418:
|
||||||
|
return "I’m a teapot";
|
||||||
|
case 421:
|
||||||
|
return "Bad mapping / Misdirected Request";
|
||||||
|
case 422:
|
||||||
|
return "Unprocessable entity";
|
||||||
|
case 423:
|
||||||
|
return "Locked";
|
||||||
|
case 424:
|
||||||
|
return "Method failure";
|
||||||
|
case 425:
|
||||||
|
return "Unordered Collection";
|
||||||
|
case 426:
|
||||||
|
return "Upgrade Required";
|
||||||
|
case 449:
|
||||||
|
return "Retry With";
|
||||||
|
case 450:
|
||||||
|
return "Blocked by Windows Parental Controls";
|
||||||
|
case 451:
|
||||||
|
return "Unavailable For Legal Reasons";
|
||||||
|
case 456:
|
||||||
|
return "Unrecoverable Error";
|
||||||
|
// --- 500
|
||||||
|
case 500:
|
||||||
|
return "Internal Server Error";
|
||||||
|
case 501:
|
||||||
|
return "Not Implemented";
|
||||||
|
case 502:
|
||||||
|
return "Bad Gateway";
|
||||||
|
case 503:
|
||||||
|
return "Service Unavailable";
|
||||||
|
case 504:
|
||||||
|
return "Gateway Time-out";
|
||||||
|
case 505:
|
||||||
|
return "HTTP Version not supported";
|
||||||
|
case 506:
|
||||||
|
return "Variant Also Negotiates";
|
||||||
|
case 507:
|
||||||
|
return "Insufficient storage";
|
||||||
|
case 509:
|
||||||
|
return "Bandwidth Limit Exceeded";
|
||||||
|
case 510:
|
||||||
|
return "Not extended";
|
||||||
|
case 511:
|
||||||
|
return "Network authentication required";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
29
src/plugins/uhttpd/uhttpd-rest-api/core/http-reason.h
Normal file
29
src/plugins/uhttpd/uhttpd-rest-api/core/http-reason.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 22/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HTTP_REASON_H
|
||||||
|
#define _HTTP_REASON_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class HttpReason {
|
||||||
|
|
||||||
|
public:
|
||||||
|
HttpReason (void);
|
||||||
|
|
||||||
|
static std::string get (uint16_t a_code);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _HTTP_REASON_H */
|
||||||
72
src/plugins/uhttpd/uhttpd-rest-api/core/ubus-reason.cpp
Normal file
72
src/plugins/uhttpd/uhttpd-rest-api/core/ubus-reason.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 07/07/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <aw-ubus/UBusCall.h>
|
||||||
|
|
||||||
|
#include "ubus-reason.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn UbusReason
|
||||||
|
*
|
||||||
|
* @brief constructor of the ubus reason.
|
||||||
|
*/
|
||||||
|
UbusReason::UbusReason (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get
|
||||||
|
*
|
||||||
|
* @brief return as an http code from an ubus code.
|
||||||
|
*/
|
||||||
|
uint16_t UbusReason::get (int16_t an_exec_result)
|
||||||
|
{
|
||||||
|
int the_result_code;
|
||||||
|
// printf("%s result code: %d\n", __PRETTY_FUNCTION__, an_exec_result);
|
||||||
|
|
||||||
|
switch (an_exec_result) {
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
the_result_code = 200; // HTTP_OK
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
the_result_code = 404; // HTTP_NOT_FOUND
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
the_result_code = 507; // HTTP_INSUFFICIENT_STORAGE
|
||||||
|
break;
|
||||||
|
case UBUS_STATUS_METHOD_NOT_FOUND:
|
||||||
|
the_result_code = 405; // HTTP_METHOD_NOT_ALLOWED
|
||||||
|
break;
|
||||||
|
case -3:
|
||||||
|
the_result_code = 500; // HTTP_INTERNAL_SERVER_ERROR
|
||||||
|
break;
|
||||||
|
case -4: // NotImplemented
|
||||||
|
case 4:
|
||||||
|
the_result_code = 501; // HTTP_NOT_IMPLEMENTED
|
||||||
|
break;
|
||||||
|
case kExecInvalidArguments:
|
||||||
|
case UBUS_STATUS_INVALID_ARGUMENT:
|
||||||
|
the_result_code = 412; // HTTP_PRECONDITION_FAILED
|
||||||
|
break;
|
||||||
|
case kExecFailed:
|
||||||
|
the_result_code = 400; // HTTP_BAD_REQUEST
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
the_result_code = 500; // HTTP_INTERNAL_SERVER_ERROR
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return the_result_code;
|
||||||
|
}
|
||||||
29
src/plugins/uhttpd/uhttpd-rest-api/core/ubus-reason.h
Normal file
29
src/plugins/uhttpd/uhttpd-rest-api/core/ubus-reason.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 07/07/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UBUS_REASON_H
|
||||||
|
#define _UBUS_REASON_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class UbusReason {
|
||||||
|
|
||||||
|
public:
|
||||||
|
UbusReason (void);
|
||||||
|
|
||||||
|
static uint16_t get (int16_t an_exec_result);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _UBUS_REASON_H */
|
||||||
176
src/plugins/uhttpd/uhttpd-rest-api/core/uri-transform.cpp
Normal file
176
src/plugins/uhttpd/uhttpd-rest-api/core/uri-transform.cpp
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 22/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include "uri-transform.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Only alphanum is safe.
|
||||||
|
const char SAFE[256] =
|
||||||
|
{
|
||||||
|
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||||
|
/* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0,
|
||||||
|
|
||||||
|
/* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
|
||||||
|
/* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
|
||||||
|
/* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
|
||||||
|
/* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
|
||||||
|
|
||||||
|
/* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
|
||||||
|
/* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
||||||
|
/* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
|
||||||
|
};
|
||||||
|
|
||||||
|
const int8_t HEX2DEC[256] =
|
||||||
|
{
|
||||||
|
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||||
|
/* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1,
|
||||||
|
|
||||||
|
/* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
|
||||||
|
/* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
|
||||||
|
/* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
/* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string iso_8859_1_to_utf8 (std::string str)
|
||||||
|
{
|
||||||
|
std::string strOut;
|
||||||
|
for (std::string::iterator it = str.begin(); it != str.end(); ++it)
|
||||||
|
{
|
||||||
|
uint8_t ch = *it;
|
||||||
|
if (ch < 0x80) {
|
||||||
|
strOut.push_back(ch);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strOut.push_back(0xc0 | ch >> 6);
|
||||||
|
strOut.push_back(0x80 | (ch & 0x3f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn UriTransform
|
||||||
|
*
|
||||||
|
* @brief class to encode and decode a string from an uri.
|
||||||
|
*/
|
||||||
|
UriTransform::UriTransform (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn encode
|
||||||
|
*
|
||||||
|
* @brief Encode A string.
|
||||||
|
*/
|
||||||
|
std::string UriTransform::encode (const std::string &a_src)
|
||||||
|
{
|
||||||
|
const char DEC2HEX[16 + 1] = "0123456789ABCDEF";
|
||||||
|
const unsigned char * p_src = (const unsigned char *)a_src.c_str();
|
||||||
|
const int SRC_LEN = a_src.length();
|
||||||
|
unsigned char * const p_start = new unsigned char[SRC_LEN * 3];
|
||||||
|
unsigned char * p_end = p_start;
|
||||||
|
const unsigned char * const SRC_END = p_src + SRC_LEN;
|
||||||
|
|
||||||
|
for (; p_src < SRC_END; ++p_src) {
|
||||||
|
|
||||||
|
if (SAFE[*p_src])
|
||||||
|
*p_end++ = *p_src;
|
||||||
|
else {
|
||||||
|
|
||||||
|
// escape this char
|
||||||
|
*p_end++ = '%';
|
||||||
|
*p_end++ = DEC2HEX[*p_src >> 4];
|
||||||
|
*p_end++ = DEC2HEX[*p_src & 0x0F];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string s_result((char *)p_start, (char *)p_end);
|
||||||
|
delete [] p_start;
|
||||||
|
return s_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn decode
|
||||||
|
*
|
||||||
|
* @brief Decode a String
|
||||||
|
*/
|
||||||
|
std::string UriTransform::decode (const std::string &a_src)
|
||||||
|
{
|
||||||
|
// Note from RFC1630: "Sequences which start with a percent sign
|
||||||
|
// but are not followed by two hexadecimal characters (0-9, A-F) are reserved
|
||||||
|
// for future extension"
|
||||||
|
|
||||||
|
const unsigned char * p_src = (const unsigned char *)a_src.c_str();
|
||||||
|
const int SRC_LEN = a_src.length();
|
||||||
|
const unsigned char * const SRC_END = p_src + SRC_LEN;
|
||||||
|
const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%'
|
||||||
|
|
||||||
|
char * const p_start = new char[SRC_LEN];
|
||||||
|
char * p_end = p_start;
|
||||||
|
|
||||||
|
while (p_src < SRC_LAST_DEC) {
|
||||||
|
|
||||||
|
if (*p_src == '%') {
|
||||||
|
|
||||||
|
char dec1, dec2;
|
||||||
|
if (-1 != (dec1 = HEX2DEC[*(p_src + 1)])
|
||||||
|
&& -1 != (dec2 = HEX2DEC[*(p_src + 2)])) {
|
||||||
|
|
||||||
|
*p_end++ = (dec1 << 4) + dec2;
|
||||||
|
p_src += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*p_end++ = *p_src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the last 2- chars
|
||||||
|
while (p_src < SRC_END)
|
||||||
|
*p_end++ = *p_src++;
|
||||||
|
|
||||||
|
std::string s_result(p_start, p_end);
|
||||||
|
delete [] p_start;
|
||||||
|
|
||||||
|
//char *theData = awUTF_ISO88591ToUTF8 (sResult.c_str(), sResult.length());
|
||||||
|
|
||||||
|
std::string theoutput = iso_8859_1_to_utf8(s_result);
|
||||||
|
//sResult= theData;
|
||||||
|
//free(theData);
|
||||||
|
|
||||||
|
return theoutput;
|
||||||
|
}
|
||||||
30
src/plugins/uhttpd/uhttpd-rest-api/core/uri-transform.h
Normal file
30
src/plugins/uhttpd/uhttpd-rest-api/core/uri-transform.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 22/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _URI_TRANSFORM_H
|
||||||
|
#define _URI_TRANSFORM_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class UriTransform {
|
||||||
|
|
||||||
|
public:
|
||||||
|
UriTransform (void);
|
||||||
|
|
||||||
|
static std::string encode (const std::string &a_src);
|
||||||
|
static std::string decode (const std::string &a_src);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _URI_TRANSFORM_H */
|
||||||
85
src/plugins/uhttpd/uhttpd-rest-api/core/web-connection.cpp
Normal file
85
src/plugins/uhttpd/uhttpd-rest-api/core/web-connection.cpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 23/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
#include <uhttpd/plugin.h>
|
||||||
|
|
||||||
|
#include "core/web-connection.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn WebConnection
|
||||||
|
*
|
||||||
|
* @brief constructor of the web connection object.
|
||||||
|
*/
|
||||||
|
WebConnection::WebConnection (struct uhttpd_ops *an_ops, struct client *a_client) :
|
||||||
|
m_ops(an_ops),
|
||||||
|
m_client(a_client),
|
||||||
|
m_should_be_removed(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~WebConnection
|
||||||
|
*
|
||||||
|
* @brief destructor of the web connection object.
|
||||||
|
*/
|
||||||
|
WebConnection::~WebConnection (void)
|
||||||
|
{
|
||||||
|
// printf("WebConnection:: desctructor....\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn add_data
|
||||||
|
*
|
||||||
|
* @brief add data to the request.
|
||||||
|
*/
|
||||||
|
int WebConnection::add_data (const char *a_data, int a_len)
|
||||||
|
{
|
||||||
|
m_connection_data += a_data;
|
||||||
|
|
||||||
|
return a_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_client
|
||||||
|
*
|
||||||
|
* @brief return pointer on the client object.
|
||||||
|
*/
|
||||||
|
struct client * WebConnection::get_client (void)
|
||||||
|
{
|
||||||
|
return m_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn invoke
|
||||||
|
*
|
||||||
|
* @brief invoke a web connection.
|
||||||
|
*/
|
||||||
|
void WebConnection::invoke (struct ubus_context *a_ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn should_be_removed
|
||||||
|
*
|
||||||
|
* @brief return true if the connection should be removed.
|
||||||
|
*/
|
||||||
|
bool WebConnection::should_be_removed (void)
|
||||||
|
{
|
||||||
|
return m_should_be_removed;
|
||||||
|
}
|
||||||
46
src/plugins/uhttpd/uhttpd-rest-api/core/web-connection.h
Normal file
46
src/plugins/uhttpd/uhttpd-rest-api/core/web-connection.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 23/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WEB_CONNECTION_H
|
||||||
|
#define _WEB_CONNECTION_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
struct client;
|
||||||
|
struct uhttpd_ops;
|
||||||
|
struct ubus_context;
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class WebConnection {
|
||||||
|
|
||||||
|
public:
|
||||||
|
WebConnection (struct uhttpd_ops *an_ops, struct client *a_client);
|
||||||
|
virtual ~WebConnection (void);
|
||||||
|
|
||||||
|
int add_data (const char *a_data, int a_len);
|
||||||
|
struct client *get_client (void);
|
||||||
|
|
||||||
|
virtual void invoke (struct ubus_context *a_ctx);
|
||||||
|
|
||||||
|
bool should_be_removed (void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct uhttpd_ops *m_ops;
|
||||||
|
struct client *m_client;
|
||||||
|
std::string m_connection_data;
|
||||||
|
bool m_should_be_removed;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _WEB_CONNECTION_H */
|
||||||
79
src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.cpp
Normal file
79
src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 23/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include "core/web-connection.h"
|
||||||
|
|
||||||
|
#include "core/web-controller.h"
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn WebController
|
||||||
|
*
|
||||||
|
* @brief constructor of the web controller object.
|
||||||
|
*/
|
||||||
|
WebController::WebController (const std::string &a_path) :
|
||||||
|
m_path(a_path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~WebController
|
||||||
|
*
|
||||||
|
* @brief destructor of the web controller object.
|
||||||
|
*/
|
||||||
|
WebController::~WebController (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn set_name
|
||||||
|
*
|
||||||
|
* @brief set the name of the controller
|
||||||
|
*/
|
||||||
|
void WebController::set_name (const std::string &a_name)
|
||||||
|
{
|
||||||
|
m_name = a_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_name
|
||||||
|
*
|
||||||
|
* @brief return the name of the controller.
|
||||||
|
*/
|
||||||
|
const std::string &WebController::get_name (void)
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_path
|
||||||
|
*
|
||||||
|
* @brief return the model path of the controller.
|
||||||
|
*/
|
||||||
|
std::string WebController::get_path (void)
|
||||||
|
{
|
||||||
|
return m_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn new_connection
|
||||||
|
*
|
||||||
|
* @brief return a new connection object.
|
||||||
|
*/
|
||||||
|
WebConnection *WebController::new_connection (struct uhttpd_ops *an_ops, struct client *a_client, const std::string &a_parameters)
|
||||||
|
{
|
||||||
|
return new WebConnection(an_ops, a_client);
|
||||||
|
}
|
||||||
47
src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.h
Normal file
47
src/plugins/uhttpd/uhttpd-rest-api/core/web-controller.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 23/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WEB_CONTROLLER_H
|
||||||
|
#define _WEB_CONTROLLER_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*--------------------------------- Define ----------------------------------*/
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
class WebConnection;
|
||||||
|
struct uhttpd_ops;
|
||||||
|
struct client;
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class WebController {
|
||||||
|
|
||||||
|
public:
|
||||||
|
WebController (const std::string &a_path);
|
||||||
|
virtual ~WebController (void);
|
||||||
|
|
||||||
|
void set_name (const std::string &a_name);
|
||||||
|
const std::string &get_name (void);
|
||||||
|
|
||||||
|
std::string get_path (void);
|
||||||
|
|
||||||
|
virtual WebConnection *new_connection (struct uhttpd_ops *an_ops, struct client *a_client, const std::string &a_parameters);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _WEB_CONTROLLER_H */
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 28/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
|
#include <aw-ubus/UBusCall.h>
|
||||||
|
|
||||||
|
#include <mozart/event/messages.h>
|
||||||
|
|
||||||
|
#include "etag-rest/etag-rest-controller.h"
|
||||||
|
|
||||||
|
#include "core/http-reason.h"
|
||||||
|
#include "core/http-parameter.h"
|
||||||
|
|
||||||
|
#include "etag-rest-connection.h"
|
||||||
|
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
#include <uhttpd/plugin.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define kdefaultTimeout 30000
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn EtagRestConnection
|
||||||
|
*
|
||||||
|
* @brief constructor of the etag rest connection object.
|
||||||
|
*/
|
||||||
|
EtagRestConnection::EtagRestConnection (struct uhttpd_ops *an_ops, struct client *a_client, EtagRestController *a_controller, const std::string &a_parameters) :
|
||||||
|
WebConnection(an_ops, a_client),
|
||||||
|
m_controller(a_controller),
|
||||||
|
m_http_header(kdefaultTimeout),
|
||||||
|
m_ctx(NULL),
|
||||||
|
m_wait_response_timeout(kdefaultTimeout)
|
||||||
|
{
|
||||||
|
uh_client_ref(a_client);
|
||||||
|
// printf("%s\n", __PRETTY_FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~EtagRestConnection
|
||||||
|
*
|
||||||
|
* @brief destructor of the etag rest connection object.
|
||||||
|
*/
|
||||||
|
EtagRestConnection::~EtagRestConnection (void)
|
||||||
|
{
|
||||||
|
// printf("%s for client: %d\n", __PRETTY_FUNCTION__, m_client->id);
|
||||||
|
// Stop Timers.
|
||||||
|
stop();
|
||||||
|
// Stop receive async events.
|
||||||
|
if (m_ctx != NULL) {
|
||||||
|
|
||||||
|
unregister_event(m_ctx);
|
||||||
|
abort(m_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("%s-done\n", __PRETTY_FUNCTION__);
|
||||||
|
uh_client_unref(m_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn invoke
|
||||||
|
*
|
||||||
|
* @brief invoke the etag rest connection.
|
||||||
|
*/
|
||||||
|
void EtagRestConnection::invoke (struct ubus_context *a_ctx)
|
||||||
|
{
|
||||||
|
uint32_t the_id = 0;
|
||||||
|
awUBusCall the_cmd;
|
||||||
|
std::string the_method;
|
||||||
|
|
||||||
|
m_ctx = a_ctx;
|
||||||
|
|
||||||
|
the_method = m_controller->get_method(m_client->request.method);
|
||||||
|
|
||||||
|
parse_parameter();
|
||||||
|
|
||||||
|
// printf("%s (object: %s)....\n", __PRETTY_FUNCTION__, m_controller->get_path().c_str());
|
||||||
|
if (!ubus_lookup_id(a_ctx, m_controller->get_path().c_str(), &the_id)) {
|
||||||
|
|
||||||
|
// printf ("%s launch async call (%s)(%s)....\n", __PRETTY_FUNCTION__, the_method.c_str(), m_parameters.c_str());
|
||||||
|
the_cmd.ExecAsync(a_ctx, the_id, the_method, m_parameters, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_client->request.method == UH_HTTP_MSG_GET) {
|
||||||
|
// printf("start timer (%d)....\n", m_wait_response_timeout);
|
||||||
|
start(m_wait_response_timeout, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn complete
|
||||||
|
*
|
||||||
|
* @brief method called when an async exec result is arrived for this connection.
|
||||||
|
*/
|
||||||
|
void EtagRestConnection::complete (void)
|
||||||
|
{
|
||||||
|
// printf("%s.\n", __PRETTY_FUNCTION__);
|
||||||
|
manage_response(get_data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn handle_event
|
||||||
|
*
|
||||||
|
* @brief method called when a registered event is arrived for this connection.
|
||||||
|
*/
|
||||||
|
void EtagRestConnection::handle_event (const char *a_type, const char *a_json_msg)
|
||||||
|
{
|
||||||
|
// printf("%s.\n", __PRETTY_FUNCTION__);
|
||||||
|
manage_response(a_json_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn parse_parameter
|
||||||
|
*
|
||||||
|
* @brief Extract parameters from the http header to get the wanted parameters by this controller.
|
||||||
|
*/
|
||||||
|
int EtagRestConnection::parse_parameter (void)
|
||||||
|
{
|
||||||
|
HttpParameter the_http_params;
|
||||||
|
std::string the_origin;
|
||||||
|
std::string the_etag;
|
||||||
|
int32_t the_wait_response_timeout = -1;
|
||||||
|
struct json_object *the_response_node;
|
||||||
|
|
||||||
|
if (the_http_params.parse(m_client)) {
|
||||||
|
|
||||||
|
the_etag = the_http_params.get_etag();
|
||||||
|
the_wait_response_timeout = the_http_params.get_request_timeout();
|
||||||
|
the_origin = the_http_params.get_origin();
|
||||||
|
if (!the_origin.empty())
|
||||||
|
m_http_header.add_origin(the_origin);
|
||||||
|
}
|
||||||
|
// printf("EtagRestConnection::parse_parameter timeout: %d\n", the_wait_response_timeout);
|
||||||
|
if (the_wait_response_timeout != -1) {
|
||||||
|
|
||||||
|
// Convert it as milli seconds.
|
||||||
|
m_wait_response_timeout = the_wait_response_timeout * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("%s - etag: %s, keep alive: %d\n", __PRETTY_FUNCTION__, the_etag.c_str(), the_wait_response_timeout);
|
||||||
|
|
||||||
|
if (m_client->request.method == UH_HTTP_MSG_GET) {
|
||||||
|
|
||||||
|
the_response_node = json_object_new_object();
|
||||||
|
|
||||||
|
if (!the_etag.empty())
|
||||||
|
json_object_object_add(the_response_node, m_controller->get_etag_key().c_str(), json_object_new_string(the_etag.c_str()));
|
||||||
|
|
||||||
|
m_parameters = json_object_to_json_string(the_response_node);
|
||||||
|
json_object_put(the_response_node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct json_object *the_content_node, *the_root_node;
|
||||||
|
|
||||||
|
if (!m_connection_data.empty()) {
|
||||||
|
|
||||||
|
the_root_node = json_object_new_object();
|
||||||
|
the_content_node = json_tokener_parse(m_connection_data.c_str());
|
||||||
|
if (the_content_node != NULL) {
|
||||||
|
|
||||||
|
json_object_object_add(the_root_node, kEvent_Message_content_entry, the_content_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_parameters = json_object_to_json_string(the_root_node);
|
||||||
|
json_object_put(the_root_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn manage_response
|
||||||
|
*
|
||||||
|
* @brief manage the response rerceived by an event or an async response.
|
||||||
|
*/
|
||||||
|
void EtagRestConnection::manage_response (std::string a_response_data)
|
||||||
|
{
|
||||||
|
std::string the_etag;
|
||||||
|
struct json_object *the_root_node, *the_status_node, *the_content_node, *the_etag_node;
|
||||||
|
int the_result_code = 500;
|
||||||
|
|
||||||
|
// printf("receive notification client id: %d!!!!\n", m_client->id);
|
||||||
|
// printf("\tdata: (%s)\n", a_response_data.c_str());
|
||||||
|
|
||||||
|
the_root_node = json_tokener_parse(a_response_data.c_str());
|
||||||
|
if (the_root_node == NULL) {
|
||||||
|
|
||||||
|
// response couldn't be parsed.
|
||||||
|
m_http_header.send(m_ops, m_client, 500);
|
||||||
|
m_ops->chunk_printf(m_client, "0\r\n\r\n");
|
||||||
|
// printf("response couldn't be parsed.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get status
|
||||||
|
if (json_object_object_get_ex(the_root_node, kEvent_Message_status_entry, &the_status_node)) {
|
||||||
|
|
||||||
|
the_result_code = json_object_get_int(the_status_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get etag.
|
||||||
|
if (json_object_object_get_ex(the_root_node, kEvent_Message_version_entry, &the_etag_node)) {
|
||||||
|
|
||||||
|
enum json_type the_json_type;
|
||||||
|
|
||||||
|
the_json_type = json_object_get_type(the_etag_node);
|
||||||
|
if (the_json_type == json_type_int) {
|
||||||
|
|
||||||
|
int the_tmp_value;
|
||||||
|
the_tmp_value = json_object_get_int(the_etag_node);
|
||||||
|
the_etag = std::to_string(the_tmp_value);
|
||||||
|
}
|
||||||
|
else if (the_json_type == json_type_string) {
|
||||||
|
the_etag = json_object_get_string(the_etag_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_http_header.add_etag(the_etag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get contents
|
||||||
|
the_content_node = NULL;
|
||||||
|
if (!json_object_object_get_ex(the_root_node, kEvent_Message_content_entry, &the_content_node)) {
|
||||||
|
|
||||||
|
the_content_node = the_root_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (the_result_code == 204) {
|
||||||
|
|
||||||
|
json_object_put(the_root_node);
|
||||||
|
register_event(m_ctx, m_controller->get_event_name());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop the timer.
|
||||||
|
stop();
|
||||||
|
|
||||||
|
m_http_header.send(m_ops, m_client, the_result_code);
|
||||||
|
|
||||||
|
m_ops->chunk_printf(m_client, "%s", json_object_to_json_string(the_content_node));
|
||||||
|
|
||||||
|
json_object_put(the_root_node);
|
||||||
|
|
||||||
|
m_ops->request_done(m_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn expire
|
||||||
|
*
|
||||||
|
* @brief method called when the connection time has expired. we will close the connection
|
||||||
|
* with a 204
|
||||||
|
*/
|
||||||
|
int EtagRestConnection::expire (void)
|
||||||
|
{
|
||||||
|
// printf("%s client id: %d, path:%s\n", __PRETTY_FUNCTION__, m_client->id, m_controller->get_path().c_str());
|
||||||
|
stop();
|
||||||
|
|
||||||
|
m_http_header.send(m_ops, m_client, 204);
|
||||||
|
uh_client_ref(m_client);
|
||||||
|
m_ops->request_done(m_client);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 28/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ETAG_REST_CONNECTION_H
|
||||||
|
#define _ETAG_REST_CONNECTION_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <aw-ubus/UloopTimer.h>
|
||||||
|
#include <aw-ubus/UBusExecReceiver.h>
|
||||||
|
#include "aw-ubus/UBusEventReceiver.h"
|
||||||
|
#include <aw-ubus/UBusEvent.h>
|
||||||
|
|
||||||
|
#include "core/http-header.h"
|
||||||
|
|
||||||
|
#include "core/web-connection.h"
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
class EtagRestController;
|
||||||
|
struct ubus_context;
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class EtagRestConnection : public WebConnection, public awUBusExecReceiver, public awUBusEventReceiver, public ULoopTimer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
EtagRestConnection (struct uhttpd_ops *an_ops, struct client *a_client, EtagRestController *a_controller, const std::string &a_parameters);
|
||||||
|
~EtagRestConnection (void);
|
||||||
|
|
||||||
|
// WebConnection
|
||||||
|
void invoke (struct ubus_context *a_ctx);
|
||||||
|
|
||||||
|
// awUBusExecReceiver
|
||||||
|
void complete (void);
|
||||||
|
|
||||||
|
// awUBusEventReceiver
|
||||||
|
void handle_event (const char *a_type, const char *a_json_msg);
|
||||||
|
|
||||||
|
// ULoopTimer.
|
||||||
|
int expire (void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int parse_parameter (void);
|
||||||
|
void manage_response (std::string a_response_data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
EtagRestController *m_controller;
|
||||||
|
HttpHeader m_http_header;
|
||||||
|
struct ubus_context *m_ctx;
|
||||||
|
int32_t m_wait_response_timeout;
|
||||||
|
std::string m_parameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _ETAG_REST_CONNECTION_H */
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 28/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "etag-rest/etag-rest-connection.h"
|
||||||
|
|
||||||
|
#include "etag-rest/etag-rest-controller.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn EtagRestController
|
||||||
|
*
|
||||||
|
* @brief constructor of the etag rest controller object.
|
||||||
|
*/
|
||||||
|
EtagRestController::EtagRestController (const std::string &a_path, const std::string &an_event_name, const std::string &an_etag_key,
|
||||||
|
const std::string &a_method_get, const std::string &a_method_put, int a_timeout, bool a_raw_response) :
|
||||||
|
RestController(a_path, a_method_get, a_method_put, a_timeout, a_raw_response),
|
||||||
|
m_event_name(an_event_name),
|
||||||
|
m_etag_key(an_etag_key)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~EtagRestController
|
||||||
|
*
|
||||||
|
* @brief destructor of the etag rest controller object.
|
||||||
|
*/
|
||||||
|
EtagRestController::~EtagRestController (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn new_connection
|
||||||
|
*
|
||||||
|
* @brief return a new etag rest connection attached to this controller.
|
||||||
|
*/
|
||||||
|
WebConnection *EtagRestController::new_connection (struct uhttpd_ops *an_ops, struct client *a_client, const std::string &a_parameters)
|
||||||
|
{
|
||||||
|
// printf("%s.\n", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
return new EtagRestConnection(an_ops, a_client, this, a_parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_event_name
|
||||||
|
*
|
||||||
|
* @brief set the etag key attached to the etag rest controller.
|
||||||
|
*/
|
||||||
|
std::string EtagRestController::get_event_name (void)
|
||||||
|
{
|
||||||
|
return m_event_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_etag_key
|
||||||
|
*
|
||||||
|
* @brief return the etag key attached to the etag rest controller.
|
||||||
|
*/
|
||||||
|
std::string EtagRestController::get_etag_key (void)
|
||||||
|
{
|
||||||
|
return m_etag_key;
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 28/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ETAG_REST_CONTROLLER_H
|
||||||
|
#define _ETAG_REST_CONTROLLER_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <rest/rest-controller.h>
|
||||||
|
|
||||||
|
/*--------------------------------- Define ----------------------------------*/
|
||||||
|
|
||||||
|
#define kDefaultTimeout 20
|
||||||
|
#define kPassed "passed"
|
||||||
|
#define kFailed "failed"
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class EtagRestController : public RestController {
|
||||||
|
|
||||||
|
public:
|
||||||
|
EtagRestController (const std::string &a_path, const std::string &an_event_name, const std::string &an_etag_key,
|
||||||
|
const std::string &a_method_get = "", const std::string &a_method_put = "",
|
||||||
|
int a_timeout = kDefaultTimeout, bool a_raw_response = false);
|
||||||
|
~EtagRestController (void);
|
||||||
|
|
||||||
|
WebConnection *new_connection (struct uhttpd_ops *an_ops, struct client *a_client, const std::string &a_parameters);
|
||||||
|
|
||||||
|
std::string get_event_name (void);
|
||||||
|
std::string get_etag_key (void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_event_name;
|
||||||
|
std::string m_etag_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _ETAG_REST_CONTROLLER_H */
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 23/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libubox/ustream.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
#include <uhttpd/plugin.h>
|
||||||
|
|
||||||
|
#include <notification-center/StringNotification.h>
|
||||||
|
|
||||||
|
#include "core/http-reason.h"
|
||||||
|
|
||||||
|
#include "notification/notification-controller.h"
|
||||||
|
#include "notification/notification-connection.h"
|
||||||
|
|
||||||
|
#define kdefaultTimeout 20000
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn NotificationConnection
|
||||||
|
*
|
||||||
|
* @brief constructor of the notification connection object.
|
||||||
|
*/
|
||||||
|
NotificationConnection::NotificationConnection (struct uhttpd_ops *an_ops, struct client *a_client, NotificationController *a_controller) :
|
||||||
|
WebConnection(an_ops, a_client),
|
||||||
|
m_controller(a_controller),
|
||||||
|
m_ctx(NULL)
|
||||||
|
{
|
||||||
|
// printf("constructor NotificationConnection : %p\n", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~NotificationConnection
|
||||||
|
*
|
||||||
|
* @brief destructor of the notification controller object.
|
||||||
|
*/
|
||||||
|
NotificationConnection::~NotificationConnection (void)
|
||||||
|
{
|
||||||
|
//printf("destructor NotificationConnection : %p\n", this);
|
||||||
|
stop();
|
||||||
|
if (m_ctx != NULL) {
|
||||||
|
unregister_event(m_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn invoke
|
||||||
|
*
|
||||||
|
* @brief invoke an async connection.
|
||||||
|
*/
|
||||||
|
void NotificationConnection::invoke (struct ubus_context *a_ctx)
|
||||||
|
{
|
||||||
|
m_ctx = a_ctx;
|
||||||
|
|
||||||
|
register_event(m_ctx, m_controller->get_path());
|
||||||
|
|
||||||
|
m_ops->http_header(m_client, 200, HttpReason::get(200).c_str());
|
||||||
|
ustream_printf(m_client->us, "Content-Type: application/json\r\n");
|
||||||
|
start(kdefaultTimeout, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn handle_event
|
||||||
|
*
|
||||||
|
* @brief method called when a registered event is arrived for this connection.
|
||||||
|
*/
|
||||||
|
void NotificationConnection::handle_event (const char *a_type, const char *a_json_msg)
|
||||||
|
{
|
||||||
|
// printf("NotificationConnection::handle_event\n");
|
||||||
|
stop();
|
||||||
|
m_ops->chunk_printf(m_client, "%s", a_json_msg);
|
||||||
|
start(kdefaultTimeout, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn expire
|
||||||
|
*
|
||||||
|
* @brief method called when no data is arrived to the notification canal.
|
||||||
|
*/
|
||||||
|
int NotificationConnection::expire (void)
|
||||||
|
{
|
||||||
|
// printf ("NotificationConnection::expire\n");
|
||||||
|
m_ops->chunk_printf(m_client, "{}");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 23/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NOTIFICATION_CONNECTION_H
|
||||||
|
#define _NOTIFICATION_CONNECTION_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <aw-ubus/UloopTimer.h>
|
||||||
|
#include "aw-ubus/UBusEventReceiver.h"
|
||||||
|
#include "core/web-connection.h"
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
class NotificationController;
|
||||||
|
struct ubus_context;
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class NotificationConnection : public WebConnection, public awUBusEventReceiver, public ULoopTimer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
NotificationConnection (struct uhttpd_ops *an_ops, struct client *a_client, NotificationController *a_controller);
|
||||||
|
virtual ~NotificationConnection (void);
|
||||||
|
|
||||||
|
// WebConnection
|
||||||
|
void invoke (struct ubus_context *a_ctx);
|
||||||
|
|
||||||
|
// awUBusEventReceiver
|
||||||
|
void handle_event (const char *a_type, const char *a_json_msg);
|
||||||
|
|
||||||
|
// Timer.
|
||||||
|
int expire (void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NotificationController *m_controller;
|
||||||
|
struct ubus_context *m_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _NOTIFICATION_CONNECTION_H */
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 23/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include "notification/notification-connection.h"
|
||||||
|
|
||||||
|
#include "notification/notification-controller.h"
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn NotificationController
|
||||||
|
*
|
||||||
|
* @brief constructor of the notification controller object.
|
||||||
|
*/
|
||||||
|
NotificationController::NotificationController (const std::string &a_path) :
|
||||||
|
WebController(a_path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~NotificationController
|
||||||
|
*
|
||||||
|
* @brief destructor of the notification controller object.
|
||||||
|
*/
|
||||||
|
NotificationController::~NotificationController (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn new_connection
|
||||||
|
*
|
||||||
|
* @brief create a new connection for this controller.
|
||||||
|
*/
|
||||||
|
WebConnection *NotificationController::new_connection (struct uhttpd_ops *an_ops, struct client *a_client, const std::string &a_parameters)
|
||||||
|
{
|
||||||
|
// printf("%s.\n", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
return new NotificationConnection(an_ops, a_client, this);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 22/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NOTIFICATION_CONTROLLER_H
|
||||||
|
#define _NOTIFICATION_CONTROLLER_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <core/web-controller.h>
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class NotificationController : public WebController {
|
||||||
|
public:
|
||||||
|
NotificationController (const std::string &a_path);
|
||||||
|
~NotificationController (void);
|
||||||
|
|
||||||
|
WebConnection *new_connection (struct uhttpd_ops *an_ops, struct client *a_client, const std::string &a_parameters);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _NOTIFICATION_CONTROLLER_H */
|
||||||
83
src/plugins/uhttpd/uhttpd-rest-api/plugin.c
Normal file
83
src/plugins/uhttpd/uhttpd-rest-api/plugin.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @author: Awox
|
||||||
|
* @date: 15/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <libubus.h>
|
||||||
|
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
#include <uhttpd/plugin.h>
|
||||||
|
|
||||||
|
/*--------------------------------- PLUGINS ----------------------------------*/
|
||||||
|
|
||||||
|
extern struct ubus_context *get_uhttp_server_ctx (void);
|
||||||
|
extern int uhttp_server_setup (struct ubus_context *a_ctx, const struct uhttpd_ops *an_ops);
|
||||||
|
extern bool uhttp_server_check_url (const char *an_url);
|
||||||
|
extern void uhttp_server_handle_request (struct client *a_cl, char *an_url, struct path_info *a_pi);
|
||||||
|
|
||||||
|
|
||||||
|
bool uhttp_server_check_path(struct path_info *pi, const char *url)
|
||||||
|
{
|
||||||
|
// printf ("uhttp_server_check_path: url: %s\n", url);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! ---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static struct dispatch_handler g_ubus_dispatch = {
|
||||||
|
|
||||||
|
.check_url = uhttp_server_check_url,
|
||||||
|
.handle_request = uhttp_server_handle_request,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn uh_awox_api_plugin_init
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
static int uh_awox_api_plugin_init (const struct uhttpd_ops *an_ops, struct config *a_conf)
|
||||||
|
{
|
||||||
|
struct ubus_context *the_ctx;
|
||||||
|
|
||||||
|
the_ctx = ubus_connect(NULL);
|
||||||
|
if (!the_ctx) {
|
||||||
|
|
||||||
|
fprintf(stderr, "Unable to connect to ubus socket\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
an_ops->dispatch_add(&g_ubus_dispatch);
|
||||||
|
|
||||||
|
uloop_done();
|
||||||
|
|
||||||
|
uhttp_server_setup(the_ctx, an_ops);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn uh_awox_api_plugin_post_init
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
static void uh_awox_api_plugin_post_init (void)
|
||||||
|
{
|
||||||
|
ubus_add_uloop(get_uhttp_server_ctx());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! ---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
struct uhttpd_plugin uhttpd_plugin = {
|
||||||
|
|
||||||
|
.init = uh_awox_api_plugin_init,
|
||||||
|
.post_init = uh_awox_api_plugin_post_init,
|
||||||
|
};
|
||||||
189
src/plugins/uhttpd/uhttpd-rest-api/rest/rest-connection.cpp
Normal file
189
src/plugins/uhttpd/uhttpd-rest-api/rest/rest-connection.cpp
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 20/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
|
#include <mozart/event/messages.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
#include <uhttpd/plugin.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <aw-ubus/UBusCall.h>
|
||||||
|
|
||||||
|
#include "core/http-reason.h"
|
||||||
|
#include "core/http-parameter.h"
|
||||||
|
#include "core/http-header.h"
|
||||||
|
#include "core/ubus-reason.h"
|
||||||
|
#include "core/uri-transform.h"
|
||||||
|
|
||||||
|
#include "rest/rest-controller.h"
|
||||||
|
|
||||||
|
#include "rest/rest-connection.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn RestConnection
|
||||||
|
*
|
||||||
|
* @brief constructor of the rest connection object.
|
||||||
|
*/
|
||||||
|
RestConnection::RestConnection (struct uhttpd_ops *an_ops, struct client *a_client, RestController *a_controller, const std::string &a_parameters) :
|
||||||
|
WebConnection(an_ops, a_client),
|
||||||
|
m_controller(a_controller), m_ctx(0)
|
||||||
|
{
|
||||||
|
if (!a_parameters.empty()) {
|
||||||
|
|
||||||
|
HttpParameter the_http_parm;
|
||||||
|
m_connection_data = the_http_parm.parse_from_uri(a_parameters);
|
||||||
|
}
|
||||||
|
// printf("RestConnection:: constructor....\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~RestConnection
|
||||||
|
*
|
||||||
|
* @brief destructor of the rest connection object.
|
||||||
|
*/
|
||||||
|
RestConnection::~RestConnection (void)
|
||||||
|
{
|
||||||
|
abort(m_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn complete
|
||||||
|
*
|
||||||
|
* @brief method called when the async call has been done.
|
||||||
|
*/
|
||||||
|
void RestConnection::complete (void)
|
||||||
|
{
|
||||||
|
int the_result_code;
|
||||||
|
// printf("resultat: <%s>\n", get_data().c_str());
|
||||||
|
|
||||||
|
the_result_code = UbusReason::get(get_result());
|
||||||
|
|
||||||
|
send_response(the_result_code, get_data().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn invoke
|
||||||
|
*
|
||||||
|
* @brief invoke an async connection.
|
||||||
|
*/
|
||||||
|
void RestConnection::invoke (struct ubus_context *a_ctx)
|
||||||
|
{
|
||||||
|
uint32_t the_id = 0;
|
||||||
|
awUBusCall the_cmd;
|
||||||
|
std::string the_method;
|
||||||
|
|
||||||
|
m_ctx = a_ctx;
|
||||||
|
|
||||||
|
the_method = m_controller->get_method(m_client->request.method);
|
||||||
|
|
||||||
|
// printf("RestConnection::invoke(object: %s)....\n", m_controller->get_path().c_str());
|
||||||
|
if (!ubus_lookup_id(a_ctx, m_controller->get_path().c_str(), &the_id)) {
|
||||||
|
json_object *the_parameter_doc;
|
||||||
|
|
||||||
|
the_parameter_doc = json_tokener_parse(m_connection_data.c_str());
|
||||||
|
|
||||||
|
if (the_parameter_doc == 0)
|
||||||
|
the_parameter_doc = parse_form_encoded_data();
|
||||||
|
|
||||||
|
// printf("RestConnection::invoke launch async call (%d)....\n", the_id);
|
||||||
|
the_cmd.ExecAsync(a_ctx, the_id, the_method, json_object_to_json_string(the_parameter_doc), this);
|
||||||
|
|
||||||
|
json_object_put(the_parameter_doc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
send_response(404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn parse_form_encoded_data
|
||||||
|
*
|
||||||
|
* @brief Parse the document content as form encoded parameters
|
||||||
|
* and return them as a json object with an attribute for each parameter.
|
||||||
|
*/
|
||||||
|
json_object* RestConnection::parse_form_encoded_data ()
|
||||||
|
{
|
||||||
|
json_object *the_parsed_document;
|
||||||
|
char *the_parameters = strdup(m_connection_data.c_str());
|
||||||
|
const char *the_encoded_name;
|
||||||
|
const char *the_encoded_value;
|
||||||
|
|
||||||
|
the_parsed_document = json_object_new_object();
|
||||||
|
|
||||||
|
for (the_encoded_name = strtok(the_parameters, "="); the_encoded_name != NULL; the_encoded_name = strtok(NULL, "=")) {
|
||||||
|
std::string the_name, the_value;
|
||||||
|
|
||||||
|
the_encoded_value = strtok(NULL, "&");
|
||||||
|
|
||||||
|
if (the_encoded_value == NULL)
|
||||||
|
the_encoded_value = "";
|
||||||
|
|
||||||
|
the_name = UriTransform::decode(std::string(the_encoded_name));
|
||||||
|
the_value = UriTransform::decode(std::string(the_encoded_value));
|
||||||
|
|
||||||
|
json_object_object_add(the_parsed_document, the_name.c_str(), json_object_new_string(the_value.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(the_parameters);
|
||||||
|
|
||||||
|
return the_parsed_document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn send_response
|
||||||
|
*
|
||||||
|
* @brief Send a response to the client
|
||||||
|
*/
|
||||||
|
void RestConnection::send_response(int a_result_code, std::string a_content_document)
|
||||||
|
{
|
||||||
|
std::string the_status;
|
||||||
|
struct json_object *the_root_node;
|
||||||
|
HttpHeader the_http_header;
|
||||||
|
|
||||||
|
if (m_controller->is_raw_response()) {
|
||||||
|
|
||||||
|
the_http_header.send(m_ops, m_client, a_result_code);
|
||||||
|
m_ops->chunk_printf(m_client, "%s", get_data().c_str());
|
||||||
|
m_ops->request_done(m_client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_result_code == 200)
|
||||||
|
the_status = kPassed;
|
||||||
|
else
|
||||||
|
the_status = kFailed;
|
||||||
|
|
||||||
|
if (a_content_document.empty()) {
|
||||||
|
the_root_node = json_object_new_object();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
the_root_node = json_tokener_parse(get_data().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_object_add(the_root_node, "id", json_object_new_string(m_controller->get_name().c_str()));
|
||||||
|
json_object_object_add(the_root_node, kEvent_Message_status_entry, json_object_new_string(the_status.c_str()));
|
||||||
|
json_object_object_add(the_root_node, "response_code", json_object_new_int(a_result_code));
|
||||||
|
|
||||||
|
the_http_header.send(m_ops, m_client, a_result_code);
|
||||||
|
m_ops->chunk_printf(m_client, "%s", json_object_to_json_string(the_root_node));
|
||||||
|
m_ops->request_done(m_client);
|
||||||
|
|
||||||
|
json_object_put(the_root_node);
|
||||||
|
}
|
||||||
48
src/plugins/uhttpd/uhttpd-rest-api/rest/rest-connection.h
Normal file
48
src/plugins/uhttpd/uhttpd-rest-api/rest/rest-connection.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 20/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _REST_CONNECTION_H
|
||||||
|
#define _REST_CONNECTION_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "core/web-connection.h"
|
||||||
|
|
||||||
|
#include <aw-ubus/UBusExecReceiver.h>
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
class RestController;
|
||||||
|
struct json_object;
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class RestConnection : public WebConnection, public awUBusExecReceiver {
|
||||||
|
|
||||||
|
public:
|
||||||
|
RestConnection (struct uhttpd_ops *an_ops, struct client *a_client, RestController *a_controller, const std::string &a_parameters);
|
||||||
|
~RestConnection (void);
|
||||||
|
|
||||||
|
void complete (void);
|
||||||
|
|
||||||
|
void invoke (struct ubus_context *a_ctx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RestController *m_controller;
|
||||||
|
struct ubus_context *m_ctx;
|
||||||
|
|
||||||
|
json_object *parse_form_encoded_data (void);
|
||||||
|
void send_response (int a_result_code, std::string a_content_document = "");
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _REST_CONNECTION_H */
|
||||||
121
src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.cpp
Normal file
121
src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.cpp
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 19/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include "rest/rest-connection.h"
|
||||||
|
|
||||||
|
#include "rest/rest-controller.h"
|
||||||
|
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn RestController
|
||||||
|
*
|
||||||
|
* @brief constructor of the rest controller object.
|
||||||
|
*/
|
||||||
|
RestController::RestController (const std::string &a_path, const std::string &a_method_get, const std::string &a_method_put, int a_timeout, bool a_raw_response) :
|
||||||
|
WebController(a_path),
|
||||||
|
m_method_get(a_method_get),
|
||||||
|
m_method_put(a_method_put),
|
||||||
|
m_timeout(a_timeout),
|
||||||
|
mf_raw_response(a_raw_response)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~RestController
|
||||||
|
*
|
||||||
|
* @brief destructor of the rest controller object.
|
||||||
|
*/
|
||||||
|
RestController::~RestController (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn new_connection
|
||||||
|
*
|
||||||
|
* @brief return a new rest connection attached to this controller.
|
||||||
|
*/
|
||||||
|
WebConnection *RestController::new_connection (struct uhttpd_ops *an_ops, struct client *a_client, const std::string &a_parameters)
|
||||||
|
{
|
||||||
|
return new RestConnection(an_ops, a_client, this, a_parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_method_get
|
||||||
|
*
|
||||||
|
* @brief return the get method of the controller.
|
||||||
|
*/
|
||||||
|
std::string RestController::get_method_get (void)
|
||||||
|
{
|
||||||
|
return m_method_get;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_method_put
|
||||||
|
*
|
||||||
|
* @brief return the put method of the controller.
|
||||||
|
*/
|
||||||
|
std::string RestController::get_method_put (void)
|
||||||
|
{
|
||||||
|
return m_method_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_timeout
|
||||||
|
*
|
||||||
|
* @brief return the wanted timeout of the controller.
|
||||||
|
*/
|
||||||
|
uint16_t RestController::get_timeout (void)
|
||||||
|
{
|
||||||
|
return m_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn is_raw_response
|
||||||
|
*
|
||||||
|
* @brief return the true if the controller didn't need the awox api response template.
|
||||||
|
*/
|
||||||
|
bool RestController::is_raw_response (void)
|
||||||
|
{
|
||||||
|
return mf_raw_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_method
|
||||||
|
*
|
||||||
|
* @brief return the right method in function of the client connection.
|
||||||
|
*/
|
||||||
|
std::string RestController::get_method (uint8_t a_method)
|
||||||
|
{
|
||||||
|
switch (a_method) {
|
||||||
|
|
||||||
|
case UH_HTTP_MSG_GET:
|
||||||
|
return m_method_get;
|
||||||
|
break;
|
||||||
|
case UH_HTTP_MSG_PUT:
|
||||||
|
case UH_HTTP_MSG_POST:
|
||||||
|
return m_method_put;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TODO ERROR
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
57
src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.h
Normal file
57
src/plugins/uhttpd/uhttpd-rest-api/rest/rest-controller.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 19/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _REST_CONTROLLER_H
|
||||||
|
#define _REST_CONTROLLER_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <core/web-controller.h>
|
||||||
|
|
||||||
|
/*--------------------------------- Define ----------------------------------*/
|
||||||
|
|
||||||
|
#define kDefaultTimeout 20
|
||||||
|
#define kPassed "passed"
|
||||||
|
#define kFailed "failed"
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class RestController : public WebController {
|
||||||
|
|
||||||
|
public:
|
||||||
|
RestController (const std::string &a_path, const std::string &a_method_get = "", const std::string &a_method_put = "", int a_timeout = kDefaultTimeout, bool a_raw_response = false);
|
||||||
|
virtual ~RestController (void);
|
||||||
|
|
||||||
|
WebConnection *new_connection (struct uhttpd_ops *an_ops, struct client *a_client, const std::string &a_parameters);
|
||||||
|
|
||||||
|
std::string get_method_get (void);
|
||||||
|
std::string get_method_put (void);
|
||||||
|
uint16_t get_timeout (void);
|
||||||
|
bool is_raw_response (void);
|
||||||
|
|
||||||
|
std::string get_method (uint8_t a_method);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_path;
|
||||||
|
std::string m_method_get;
|
||||||
|
std::string m_method_put;
|
||||||
|
uint16_t m_timeout;
|
||||||
|
bool mf_raw_response;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _REST_CONTROLLER_H */
|
||||||
693
src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.cpp
Normal file
693
src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.cpp
Normal file
@@ -0,0 +1,693 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 16/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libubox/ustream.h>
|
||||||
|
#include <libubus.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
|
#include "core/web-connection.h"
|
||||||
|
#include "core/http-header.h"
|
||||||
|
|
||||||
|
#include "rest/rest-connection.h"
|
||||||
|
#include "rest/rest-controller.h"
|
||||||
|
|
||||||
|
#include "etag-rest/etag-rest-controller.h"
|
||||||
|
|
||||||
|
#include "notification/notification-controller.h"
|
||||||
|
|
||||||
|
#include "uhttp-server.h"
|
||||||
|
|
||||||
|
#include <uhttpd/uhttpd.h>
|
||||||
|
#include <uhttpd/plugin.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------- GLOBALS ----------------------------------*/
|
||||||
|
|
||||||
|
#define kConfigDirectory "/usr/local/configs/restd/"
|
||||||
|
|
||||||
|
#define kControllerKey "controller"
|
||||||
|
#define kEtagControllerKey "etag_controller"
|
||||||
|
|
||||||
|
#define kNotificationKey "notification"
|
||||||
|
|
||||||
|
#define kControllerPathKey "path"
|
||||||
|
#define kControllerModelNameKey "model_name"
|
||||||
|
#define kControllerEventNameKey "event_name"
|
||||||
|
#define kControllerEtagKey "etag_key"
|
||||||
|
#define kControllerGetMethodKey "get_method"
|
||||||
|
#define kControllerSetMethodKey "set_method"
|
||||||
|
#define kControllerRawResponseKey "raw_response"
|
||||||
|
|
||||||
|
#define kdefaultGetMethod "get"
|
||||||
|
#define kdefaultSetMethod "set"
|
||||||
|
|
||||||
|
|
||||||
|
#define kJsonControlerNotFound "{{\n" \
|
||||||
|
" \"id\": \"{}\",\n" \
|
||||||
|
" \"status\": \"failed\",\n" \
|
||||||
|
" \"error\": \"Controller Not Found\",\n" \
|
||||||
|
" \"response_code\": 404\n}}"
|
||||||
|
|
||||||
|
|
||||||
|
#define DEBUG_REQUEST 1
|
||||||
|
#define BUFFER_SIZE 100
|
||||||
|
|
||||||
|
#ifdef DEBUG_REQUEST
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn log_with_timestamp
|
||||||
|
*
|
||||||
|
* @brief method to log with time stamp.
|
||||||
|
*/
|
||||||
|
void log_with_timestamp (const char *a_msg)
|
||||||
|
{
|
||||||
|
char the_buffer[512];
|
||||||
|
time_t the_time;
|
||||||
|
struct timeval the_timeval;
|
||||||
|
|
||||||
|
the_time = time(NULL);
|
||||||
|
strftime(the_buffer, sizeof(the_buffer), "%m/%d/%Y %H:%M:%S", localtime(&the_time));
|
||||||
|
|
||||||
|
gettimeofday(&the_timeval, NULL);
|
||||||
|
fprintf (stdout, "%s.%09ld - %s\n", the_buffer, the_timeval.tv_usec*1000, a_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
double time_diff(struct timeval x , struct timeval y)
|
||||||
|
{
|
||||||
|
double x_ms , y_ms , diff;
|
||||||
|
|
||||||
|
x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
|
||||||
|
y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
|
||||||
|
|
||||||
|
diff = (double)y_ms - (double)x_ms;
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_uhttp_server_ctx
|
||||||
|
*
|
||||||
|
* @brief method to return ubux context to c plugin.
|
||||||
|
*/
|
||||||
|
extern "C" struct ubus_context *get_uhttp_server_ctx (void)
|
||||||
|
{
|
||||||
|
return UhttpServer::get_instance().get_context();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn set_uhttp_server_ctx
|
||||||
|
*
|
||||||
|
* @brief init method from c plugin to uhttp server.
|
||||||
|
*/
|
||||||
|
extern "C" int uhttp_server_setup (struct ubus_context *a_ctx, const struct uhttpd_ops *an_ops)
|
||||||
|
{
|
||||||
|
return UhttpServer::get_instance().setup(a_ctx, an_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn uhttp_server_check_url
|
||||||
|
*
|
||||||
|
* @brief Check if the url is managed by this plugin
|
||||||
|
*/
|
||||||
|
extern "C" bool uhttp_server_check_url (const char *an_url)
|
||||||
|
{
|
||||||
|
return UhttpServer::get_instance().check_url(an_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn uhttp_server_handle_request
|
||||||
|
*
|
||||||
|
* @brief Handle the request.
|
||||||
|
*/
|
||||||
|
extern "C" void uhttp_server_handle_request (struct client *a_cl, char *an_url, struct path_info *a_pi)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_REQUEST
|
||||||
|
gettimeofday(&a_cl->start_request, NULL);
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
snprintf(buffer, sizeof(buffer), "uhttp handle_request : client id: %d - %s", a_cl->id, an_url);
|
||||||
|
log_with_timestamp(buffer);
|
||||||
|
#endif
|
||||||
|
UhttpServer::get_instance().handle_request(a_cl, an_url, a_pi);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn uhttp_server_data_send
|
||||||
|
*
|
||||||
|
* @brief callback called when data should .
|
||||||
|
*/
|
||||||
|
static int uhttp_server_data_send (struct client *a_cl, const char *a_data, int a_len)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_REQUEST
|
||||||
|
log_with_timestamp("uhttp_server_data_send");
|
||||||
|
#endif
|
||||||
|
return UhttpServer::get_instance().data_send(a_cl, a_data, a_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn uhttp_server_data_done
|
||||||
|
*
|
||||||
|
* @brief callback called when the server is ready to launch the request.
|
||||||
|
*/
|
||||||
|
static void uhttp_server_data_done (struct client *a_cl)
|
||||||
|
{
|
||||||
|
UhttpServer::get_instance().invoke_request(a_cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn uhttp_server_request_free
|
||||||
|
*
|
||||||
|
* @brief callback call to free the request.
|
||||||
|
*/
|
||||||
|
static void uhttp_server_request_free (struct client *a_cl)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_REQUEST
|
||||||
|
struct timeval the_current_timeval;
|
||||||
|
gettimeofday(&the_current_timeval, NULL);
|
||||||
|
char buffer [BUFFER_SIZE];
|
||||||
|
snprintf (buffer, sizeof(buffer), "client id: %d duree: %.0lf ms", a_cl->id, time_diff(a_cl->start_request , the_current_timeval) / 1000);
|
||||||
|
log_with_timestamp(buffer);
|
||||||
|
#endif
|
||||||
|
UhttpServer::get_instance().request_free(a_cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn uhttp_server_close_fds
|
||||||
|
*
|
||||||
|
* @brief callback call when the process close. (needed ? to be dfefined).
|
||||||
|
*/
|
||||||
|
static void uhttp_server_close_fds (struct client *cl)
|
||||||
|
{
|
||||||
|
// printf("uhttp_server_close_fds(%p)... client id: %d\n", cl, cl->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_instance
|
||||||
|
*
|
||||||
|
* @brief singleton to return the instance of UhttpServer.
|
||||||
|
*/
|
||||||
|
UhttpServer &UhttpServer::get_instance (void)
|
||||||
|
{
|
||||||
|
static UhttpServer m_ptr;
|
||||||
|
return m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn UhttpServer
|
||||||
|
*
|
||||||
|
* @brief Constructor of the Uhttp Server
|
||||||
|
*/
|
||||||
|
UhttpServer::UhttpServer (void):
|
||||||
|
m_ctx(NULL),
|
||||||
|
m_ops(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn ~UhttpServer
|
||||||
|
*
|
||||||
|
* @brief Destructor of the Uhttp Server
|
||||||
|
*/
|
||||||
|
UhttpServer::~UhttpServer (void)
|
||||||
|
{
|
||||||
|
ControllerIterator it;
|
||||||
|
ConnectionIterator the_cnx_it;
|
||||||
|
for (it=m_controller_array.begin(); it!=m_controller_array.end(); ++it) {
|
||||||
|
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (the_cnx_it=m_connections.begin(); the_cnx_it!=m_connections.end(); ++the_cnx_it) {
|
||||||
|
|
||||||
|
delete the_cnx_it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus_free(m_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn setup
|
||||||
|
*
|
||||||
|
* @brief setup the http server.
|
||||||
|
*/
|
||||||
|
int UhttpServer::setup (struct ubus_context *a_ctx, const struct uhttpd_ops *an_ops)
|
||||||
|
{
|
||||||
|
m_ctx = a_ctx;
|
||||||
|
m_ops = const_cast<struct uhttpd_ops *>(an_ops);
|
||||||
|
|
||||||
|
return load_config_dir();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_context
|
||||||
|
*
|
||||||
|
* @brief return the ubus context.
|
||||||
|
*/
|
||||||
|
struct ubus_context *UhttpServer::get_context (void)
|
||||||
|
{
|
||||||
|
return m_ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn check_url
|
||||||
|
*
|
||||||
|
* @brief check if the url is managed by this plugin.
|
||||||
|
*/
|
||||||
|
bool UhttpServer::check_url (const std::string &an_url)
|
||||||
|
{
|
||||||
|
std::list<std::string>::iterator the_it;
|
||||||
|
// printf("UhttpServer::check_url: %s\n", an_url.c_str());
|
||||||
|
|
||||||
|
for (the_it = m_path_list.begin(); the_it != m_path_list.end(); the_it++) {
|
||||||
|
|
||||||
|
if (an_url.find(*the_it) != std::string::npos)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn handle_request
|
||||||
|
*
|
||||||
|
* @brief Handle the Request.
|
||||||
|
*/
|
||||||
|
void UhttpServer::handle_request (struct client *a_cl, const std::string &an_url, struct path_info *a_pi)
|
||||||
|
{
|
||||||
|
std::string the_url, the_parameters;
|
||||||
|
std::size_t the_pos;
|
||||||
|
WebController *the_controller;
|
||||||
|
// printf("uhttp_server_handle_request : url: <%s> client: %p\n", an_url.c_str(), a_cl);
|
||||||
|
|
||||||
|
// Check if parameters are present on the url.
|
||||||
|
the_pos = an_url.find_first_of("?", 0);
|
||||||
|
if (the_pos != std::string::npos) {
|
||||||
|
// parameters are present.
|
||||||
|
the_url = an_url.substr(0, the_pos);
|
||||||
|
the_parameters = an_url.substr(the_pos + 1);
|
||||||
|
// printf("url: <%s> | parameters: <%s>\n", the_url.c_str(), the_parameters.c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
the_url = an_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
the_controller = m_controller_array [the_url];
|
||||||
|
if (the_controller == NULL) {
|
||||||
|
|
||||||
|
std::string the_msg;
|
||||||
|
the_msg = fmt::format(kJsonControlerNotFound, the_url);
|
||||||
|
send_error(a_cl, 404, "Not Found", the_msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We found the controller.
|
||||||
|
// printf("method: %d\n", a_cl->request.method);
|
||||||
|
struct dispatch *d = &a_cl->dispatch;
|
||||||
|
switch (a_cl->request.method)
|
||||||
|
{
|
||||||
|
case UH_HTTP_MSG_GET:
|
||||||
|
case UH_HTTP_MSG_PUT:
|
||||||
|
case UH_HTTP_MSG_POST:
|
||||||
|
case UH_HTTP_MSG_DELETE:
|
||||||
|
d->data_send = uhttp_server_data_send;
|
||||||
|
d->data_done = uhttp_server_data_done;
|
||||||
|
d->close_fds = uhttp_server_close_fds;
|
||||||
|
d->free = uhttp_server_request_free;
|
||||||
|
m_connections[a_cl->id] = the_controller->new_connection(m_ops, a_cl, the_parameters);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UH_HTTP_MSG_OPTIONS:
|
||||||
|
{
|
||||||
|
HttpHeader the_http_header;
|
||||||
|
the_http_header.send_option(m_ops, a_cl, 200);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// printf("Invalid Request\n");
|
||||||
|
send_error(a_cl, 400, "Bad Request", "Invalid Request");
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("uhttp_server_handle_request -done.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn invoke_request
|
||||||
|
*
|
||||||
|
* @brief This method to invoke the request.
|
||||||
|
*/
|
||||||
|
void UhttpServer::invoke_request (struct client *a_client)
|
||||||
|
{
|
||||||
|
uh_client_ref(a_client);
|
||||||
|
// printf("UhttpServer::invoke_request\n");
|
||||||
|
m_connections[a_client->id]->invoke(m_ctx);
|
||||||
|
|
||||||
|
uh_client_unref(a_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn request_free
|
||||||
|
*
|
||||||
|
* @brief This method free the complete request.
|
||||||
|
*/
|
||||||
|
void UhttpServer::request_free (struct client *a_client)
|
||||||
|
{
|
||||||
|
ConnectionIterator the_it;
|
||||||
|
// printf("UhttpServer::request_free id:%d nb connection: %ld\n", a_client->id, m_connections.size());
|
||||||
|
uh_client_ref(a_client);
|
||||||
|
|
||||||
|
the_it = m_connections.find(a_client->id);
|
||||||
|
if (the_it != m_connections.end()) {
|
||||||
|
|
||||||
|
if ((the_it->second)->should_be_removed()) {
|
||||||
|
delete the_it->second;
|
||||||
|
m_connections.erase(the_it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uh_client_unref(a_client);
|
||||||
|
// printf("UhttpServer::request_free-done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn data_send
|
||||||
|
*
|
||||||
|
* @brief This method called when data arrived from the client.
|
||||||
|
*/
|
||||||
|
int UhttpServer::data_send (struct client *a_client, const char *a_data, int a_len)
|
||||||
|
{
|
||||||
|
return m_connections[a_client->id]->add_data(a_data, a_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn load_config_dir
|
||||||
|
*
|
||||||
|
* @brief Load config from the configuration directory
|
||||||
|
*/
|
||||||
|
int UhttpServer::load_config_dir (void)
|
||||||
|
{
|
||||||
|
DIR *the_rep = NULL;
|
||||||
|
struct dirent *the_dir_ent = NULL;
|
||||||
|
std::string the_path;
|
||||||
|
struct json_object *the_root_node;
|
||||||
|
the_rep = opendir(kConfigDirectory);
|
||||||
|
|
||||||
|
while ((the_dir_ent = readdir(the_rep)) != NULL) {
|
||||||
|
|
||||||
|
if (strcmp(the_dir_ent->d_name, ".") != 0 && strcmp(the_dir_ent->d_name, "..") != 0) {
|
||||||
|
|
||||||
|
// printf ("load: %s\n", the_dir_ent->d_name);
|
||||||
|
the_path = kConfigDirectory;
|
||||||
|
the_path += the_dir_ent->d_name;
|
||||||
|
|
||||||
|
the_root_node = load(the_path);
|
||||||
|
if (the_root_node == NULL) {
|
||||||
|
|
||||||
|
fprintf(stderr, "Failed to load controller configuration file (%s).\n", the_path.c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_controller_from_json(the_root_node);
|
||||||
|
json_object_put(the_root_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(the_rep);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn add_controller_from_json
|
||||||
|
*
|
||||||
|
* @brief Load config from the configuration directory
|
||||||
|
*/
|
||||||
|
int UhttpServer::add_controller_from_json (struct json_object *a_root_node)
|
||||||
|
{
|
||||||
|
struct json_object *the_ctr_array_node, *the_ctrl_node, *the_note_array_node, *the_etag_ctrl_array_node;
|
||||||
|
|
||||||
|
std::string the_path, the_model_name, the_event_name, the_etag_key, the_get_method, the_set_method;
|
||||||
|
bool the_raw_response = false;
|
||||||
|
int the_len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(a_root_node, kControllerKey, &the_ctr_array_node)) {
|
||||||
|
|
||||||
|
the_len = json_object_array_length(the_ctr_array_node);
|
||||||
|
|
||||||
|
for (i = 0; i < the_len; i++) {
|
||||||
|
|
||||||
|
the_ctrl_node = json_object_array_get_idx(the_ctr_array_node, i);
|
||||||
|
|
||||||
|
if (get_controller_fields(the_ctrl_node, the_path, the_model_name, the_event_name, the_etag_key, the_get_method, the_set_method, the_raw_response)) {
|
||||||
|
#if 0
|
||||||
|
printf("Path: <%s>\n", the_path.c_str());
|
||||||
|
printf("\t- model name: <%s>\n", the_model_name.c_str());
|
||||||
|
printf("\t- get: <%s>\n", the_get_method.c_str());
|
||||||
|
printf("\t- set: <%s>\n", the_set_method.c_str());
|
||||||
|
printf("\t- raw response: <%s>\n", the_raw_response?"true":"false");
|
||||||
|
#endif
|
||||||
|
add_controller(the_path, new RestController(the_model_name, the_get_method, the_set_method, kDefaultTimeout, the_raw_response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (json_object_object_get_ex(a_root_node, kEtagControllerKey, &the_etag_ctrl_array_node)) {
|
||||||
|
|
||||||
|
the_len = json_object_array_length(the_etag_ctrl_array_node);
|
||||||
|
|
||||||
|
for (i = 0; i < the_len; i++) {
|
||||||
|
|
||||||
|
the_ctrl_node = json_object_array_get_idx(the_etag_ctrl_array_node, i);
|
||||||
|
|
||||||
|
if (get_controller_fields(the_ctrl_node, the_path, the_model_name, the_event_name, the_etag_key, the_get_method, the_set_method, the_raw_response)) {
|
||||||
|
|
||||||
|
EtagRestController *the_etag_rest_controller;
|
||||||
|
the_etag_rest_controller = new EtagRestController(the_model_name, the_event_name, the_etag_key, the_get_method, the_set_method, kDefaultTimeout, the_raw_response);
|
||||||
|
|
||||||
|
add_controller(the_path, the_etag_rest_controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (json_object_object_get_ex(a_root_node, kNotificationKey, &the_note_array_node)) {
|
||||||
|
|
||||||
|
the_len = json_object_array_length(the_note_array_node);
|
||||||
|
|
||||||
|
for (i = 0; i < the_len; i++) {
|
||||||
|
|
||||||
|
the_ctrl_node = json_object_array_get_idx(the_note_array_node, i);
|
||||||
|
|
||||||
|
if (get_controller_fields(the_ctrl_node, the_path, the_model_name, the_event_name, the_etag_key, the_get_method, the_set_method, the_raw_response)) {
|
||||||
|
|
||||||
|
NotificationController *the_notification_controller;
|
||||||
|
the_notification_controller = new NotificationController(the_event_name);
|
||||||
|
add_controller(the_path, the_notification_controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn get_controller_fields
|
||||||
|
*
|
||||||
|
* @brief This method extract the controller fields from a json node.
|
||||||
|
*/
|
||||||
|
bool UhttpServer::get_controller_fields (struct json_object *a_node, std::string &a_path, std::string &a_model_name,
|
||||||
|
std::string &an_event_name, std::string &an_etag_key,
|
||||||
|
std::string &a_get_method, std::string &a_set_method, bool &a_raw_response)
|
||||||
|
{
|
||||||
|
bool the_result = false;
|
||||||
|
struct json_object *the_path_node, *the_ubus_model_node, *the_ubus_event_node, *the_get_method_node, *the_etag_key_node;
|
||||||
|
struct json_object *the_set_method_node, *the_raw_response_node;
|
||||||
|
|
||||||
|
// path
|
||||||
|
if (json_object_object_get_ex(a_node, kControllerPathKey, &the_path_node)) {
|
||||||
|
a_path = json_object_get_string(the_path_node);
|
||||||
|
the_result = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a_path.clear();
|
||||||
|
}
|
||||||
|
// model_name
|
||||||
|
if (json_object_object_get_ex(a_node, kControllerModelNameKey, &the_ubus_model_node)) {
|
||||||
|
a_model_name = json_object_get_string(the_ubus_model_node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a_model_name.clear();
|
||||||
|
}
|
||||||
|
// event name
|
||||||
|
if (json_object_object_get_ex(a_node, kControllerEventNameKey, &the_ubus_event_node)) {
|
||||||
|
an_event_name = json_object_get_string(the_ubus_event_node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
an_event_name.clear();
|
||||||
|
}
|
||||||
|
// etag key
|
||||||
|
if (json_object_object_get_ex(a_node, kControllerEtagKey, &the_etag_key_node)) {
|
||||||
|
an_etag_key = json_object_get_string(the_etag_key_node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
an_etag_key.clear();
|
||||||
|
}
|
||||||
|
// get_method
|
||||||
|
if (json_object_object_get_ex(a_node, kControllerGetMethodKey, &the_get_method_node)) {
|
||||||
|
a_get_method = json_object_get_string(the_get_method_node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a_get_method = kdefaultGetMethod;
|
||||||
|
}
|
||||||
|
// set_method
|
||||||
|
if (json_object_object_get_ex(a_node, kControllerSetMethodKey, &the_set_method_node)) {
|
||||||
|
a_set_method = json_object_get_string(the_set_method_node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a_set_method = kdefaultSetMethod;
|
||||||
|
}
|
||||||
|
// raw_response
|
||||||
|
if (json_object_object_get_ex(a_node, kControllerRawResponseKey, &the_raw_response_node)) {
|
||||||
|
a_raw_response = json_object_get_boolean(the_raw_response_node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a_raw_response = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return the_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn load
|
||||||
|
*
|
||||||
|
* @brief This method load the restd controllers and file it into a json object.
|
||||||
|
* return null otherwise.
|
||||||
|
*/
|
||||||
|
struct json_object *UhttpServer::load (const std::string &a_file)
|
||||||
|
{
|
||||||
|
struct json_object *the_root_node = NULL;
|
||||||
|
struct stat the_stat;
|
||||||
|
int the_fd;
|
||||||
|
char *the_addr;
|
||||||
|
|
||||||
|
the_fd = open(a_file.c_str(), O_RDONLY);
|
||||||
|
if (the_fd == -1) {
|
||||||
|
|
||||||
|
perror("open");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (fstat(the_fd, &the_stat) == -1) {
|
||||||
|
|
||||||
|
perror("fstat");
|
||||||
|
close(the_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
the_addr = (char *) mmap(NULL, the_stat.st_size, PROT_READ, MAP_PRIVATE, the_fd, 0);
|
||||||
|
if (the_addr == MAP_FAILED) {
|
||||||
|
|
||||||
|
perror("mmap");
|
||||||
|
close(the_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
the_root_node = json_tokener_parse(the_addr);
|
||||||
|
|
||||||
|
close(the_fd);
|
||||||
|
|
||||||
|
return the_root_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn add_rest_controller
|
||||||
|
*
|
||||||
|
* @brief add a rest controller.
|
||||||
|
*/
|
||||||
|
int UhttpServer::add_controller (const std::string &an_uri, WebController *a_controller)
|
||||||
|
{
|
||||||
|
std::string the_path;
|
||||||
|
std::size_t the_pos;
|
||||||
|
if (a_controller == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
a_controller->set_name(an_uri);
|
||||||
|
m_controller_array[an_uri] = a_controller;
|
||||||
|
|
||||||
|
// printf("add: an_uri:%s\n", an_uri.c_str());
|
||||||
|
|
||||||
|
// Keep a list of the API root. to check if a controller is managed by this plugin or not.
|
||||||
|
the_pos = an_uri.find_first_of("/", 1);
|
||||||
|
if (the_pos != std::string::npos) {
|
||||||
|
|
||||||
|
the_path = an_uri.substr(0, the_pos + 1);
|
||||||
|
if (std::find(m_path_list.begin(), m_path_list.end(), the_path) == m_path_list.end()) {
|
||||||
|
// uniq version. we add it.
|
||||||
|
m_path_list.push_back(the_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! ----------------------------------------------------------------------------
|
||||||
|
* @fn send_error
|
||||||
|
*
|
||||||
|
* @brief Send an error message to the client.
|
||||||
|
*/
|
||||||
|
void UhttpServer::send_error (struct client *a_cl, int a_code, const char *a_summary, const std::string &a_msg)
|
||||||
|
{
|
||||||
|
m_ops->http_header(a_cl, a_code, a_summary);
|
||||||
|
ustream_printf(a_cl->us, "Content-Type: application/json\r\n\r\n");
|
||||||
|
|
||||||
|
m_ops->chunk_printf(a_cl, "%s", a_msg.c_str());
|
||||||
|
|
||||||
|
m_ops->request_done(a_cl);
|
||||||
|
}
|
||||||
77
src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.h
Normal file
77
src/plugins/uhttpd/uhttpd-rest-api/uhttp-server.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*!
|
||||||
|
* (C) Copyright 2003-2017 Awox SA. All rights reserved.
|
||||||
|
* This work contains confidential trade secrets of Awox.
|
||||||
|
* Use, examination, copying, transfer and disclosure to others
|
||||||
|
* are prohibited, except with the express written agreement of Awox.
|
||||||
|
*
|
||||||
|
* @Author: Awox
|
||||||
|
* @Date: 16/06/2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UHTTP_SERVER_H
|
||||||
|
#define _UHTTP_SERVER_H
|
||||||
|
|
||||||
|
/*------------------------------- INCLUDES ----------------------------------*/
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*--------------------------------- Define ----------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------- Dependencies --------------------------------*/
|
||||||
|
|
||||||
|
struct ubus_context;
|
||||||
|
struct uhttpd_ops;
|
||||||
|
struct json_object;
|
||||||
|
|
||||||
|
class WebController;
|
||||||
|
class WebConnection;
|
||||||
|
|
||||||
|
/*--------------------------------- CLASS ----------------------------------*/
|
||||||
|
|
||||||
|
class UhttpServer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef std::unordered_map<std::string, WebController *> ControllerContainer;
|
||||||
|
typedef ControllerContainer::iterator ControllerIterator;
|
||||||
|
typedef std::unordered_map <int, WebConnection *> ConnectionContainer;
|
||||||
|
typedef ConnectionContainer::iterator ConnectionIterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UhttpServer (void);
|
||||||
|
~UhttpServer (void);
|
||||||
|
|
||||||
|
static UhttpServer &get_instance (void);
|
||||||
|
|
||||||
|
int setup (struct ubus_context *a_ctx, const struct uhttpd_ops *an_ops);
|
||||||
|
|
||||||
|
struct ubus_context *get_context (void);
|
||||||
|
|
||||||
|
bool check_url (const std::string &an_url);
|
||||||
|
void handle_request (struct client *a_cl, const std::string &an_url, struct path_info *a_pi);
|
||||||
|
void invoke_request (struct client *a_client);
|
||||||
|
void request_free (struct client *a_client);
|
||||||
|
|
||||||
|
int data_send (struct client *a_client, const char *a_data, int a_len);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int load_config_dir (void);
|
||||||
|
int add_controller_from_json (struct json_object *a_root_node);
|
||||||
|
bool get_controller_fields (struct json_object *a_node, std::string &a_path, std::string &a_model_name,
|
||||||
|
std::string &an_event_name, std::string &an_etag_key,
|
||||||
|
std::string &a_get_method, std::string &a_set_method, bool &a_raw_response);
|
||||||
|
struct json_object *load (const std::string &a_file);
|
||||||
|
int add_controller (const std::string &an_uri, WebController *a_controller);
|
||||||
|
void send_error (struct client *a_cl, int a_code, const char *a_summary, const std::string &a_msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ubus_context *m_ctx;
|
||||||
|
struct uhttpd_ops *m_ops;
|
||||||
|
ControllerContainer m_controller_array;
|
||||||
|
ConnectionContainer m_connections;
|
||||||
|
std::list<std::string> m_path_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _UHTTP_SERVER_H */
|
||||||
Reference in New Issue
Block a user