diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ba9aab7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.8) + +project(GermanAirlinesVA_GAConnector) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +set(PLUGIN_NAME GAConnector) + +option(DEBUG "Debug symbols" OFF) + +add_subdirectory( + xplugin +) diff --git a/GermanAirlinesVA-GAConnector/.clang-format b/GermanAirlinesVA-GAConnector/.clang-format new file mode 100644 index 0000000..edb326d --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.clang-format @@ -0,0 +1,54 @@ +Language: Cpp +AccessModifierOffset: -4 +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AlignAfterOpenBracket: Align +AllowShortFunctionsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: false +BinPackParameters: false +BreakBeforeBinaryOperators: false +BreakBeforeBraces: Linux +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerBinding: false +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +IndentFunctionDeclarationAfterType: true +IndentWidth: 4 +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +ObjCBlockIndentWidth: 4 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 100000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerBindsToType: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +Standard: c++14 +SortIncludes: true +TabWidth: 4 +UseTab: Never diff --git a/GermanAirlinesVA-GAConnector/.gitattributes b/GermanAirlinesVA-GAConnector/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/GermanAirlinesVA-GAConnector/.gitignore b/GermanAirlinesVA-GAConnector/.gitignore new file mode 100644 index 0000000..eed511b --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.gitignore @@ -0,0 +1,366 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# Cmake +build*/ \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/.idea/.gitignore b/GermanAirlinesVA-GAConnector/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/GermanAirlinesVA-GAConnector/.idea/.name b/GermanAirlinesVA-GAConnector/.idea/.name new file mode 100644 index 0000000..6abfb67 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.idea/.name @@ -0,0 +1 @@ +GermanAirlinesVA_GAConnector \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/.idea/GermanAirlinesVA-GAConnector.iml b/GermanAirlinesVA-GAConnector/.idea/GermanAirlinesVA-GAConnector.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.idea/GermanAirlinesVA-GAConnector.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/.idea/misc.xml b/GermanAirlinesVA-GAConnector/.idea/misc.xml new file mode 100644 index 0000000..79b3c94 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/.idea/modules.xml b/GermanAirlinesVA-GAConnector/.idea/modules.xml new file mode 100644 index 0000000..ff0f9b0 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/.idea/vcs.xml b/GermanAirlinesVA-GAConnector/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/CMakeLists.txt b/GermanAirlinesVA-GAConnector/CMakeLists.txt new file mode 100644 index 0000000..ba9aab7 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.8) + +project(GermanAirlinesVA_GAConnector) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +set(PLUGIN_NAME GAConnector) + +option(DEBUG "Debug symbols" OFF) + +add_subdirectory( + xplugin +) diff --git a/GermanAirlinesVA-GAConnector/Jenkinsfile b/GermanAirlinesVA-GAConnector/Jenkinsfile new file mode 100644 index 0000000..4a0105d --- /dev/null +++ b/GermanAirlinesVA-GAConnector/Jenkinsfile @@ -0,0 +1,127 @@ +pipeline { + agent any + stages { + stage('Build Windows Debug') { + when { + branch 'develop' + beforeAgent true + } + agent { + docker { + image 'llvm-mingw:latest' + reuseNode true + } + } + environment { + DEBUG = 1 + } + steps { + sh 'bash ./build.sh win32' + sh 'bash ./build.sh win64' + } + } + stage('Build Linux Debug') { + when { + branch 'develop' + beforeAgent true + } + agent { + docker { + image 'llvm:latest' + reuseNode true + } + } + environment { + DEBUG = 1 + } + steps { + sh 'bash ./build.sh lin32' + sh 'bash ./build.sh lin64' + } + } + stage('Build MacOSX Debug') { + when { + branch 'develop' + beforeAgent true + } + agent { + docker { + image 'osxcross:latest' + reuseNode true + } + } + environment { + DEBUG = 1 + } + steps { + sh 'bash ./build.sh mac' + } + } + stage('Archive Debug') { + when { + branch 'develop' + } + steps { + zip zipFile: 'Debug.zip', archive: true, dir: 'build/Plugin' + sh 'rm -rf build' + } + } + stage('Build Windows Release') { + when { + branch 'prod' + beforeAgent true + } + agent { + docker { + image 'llvm-mingw:latest' + reuseNode true + } + } + steps { + sh 'bash ./build.sh win32' + sh 'bash ./build.sh win64' + } + } + stage('Build Linux Release') { + when { + branch 'prod' + beforeAgent true + } + agent { + docker { + image 'llvm:latest' + reuseNode true + } + } + steps { + sh 'bash ./build.sh lin32' + sh 'bash ./build.sh lin64' + } + } + stage('Build MacOSX Release') { + when { + branch 'prod' + beforeAgent true + } + agent { + docker { + image 'osxcross:latest' + reuseNode true + } + } + steps { + sh 'bash ./build.sh mac' + } + } + stage('Archive Release') { + when { + branch 'prod' + beforeAgent true + } + steps { + zip zipFile: 'Release.zip', archive: true, dir: 'build/Plugin' + sh 'rm -rf build' + } + } + } +} diff --git a/GermanAirlinesVA-GAConnector/README.md b/GermanAirlinesVA-GAConnector/README.md new file mode 100644 index 0000000..5bc92d2 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/README.md @@ -0,0 +1,11 @@ +### Develop Status +[![Build Status](https://jenkins.hofmannnet.myhome-server.de/job/WebSocketTest/job/develop/badge/icon)](https://jenkins.hofmannnet.myhome-server.de/job/WebSocketTest/job/develop) + +### Prod Status +[![Build Status](https://jenkins.hofmannnet.myhome-server.de/job/WebSocketTest/job/prod/badge/icon)](https://jenkins.hofmannnet.myhome-server.de/job/WebSocketTest/job/prod) + +### Master Status +[![Build Status](https://jenkins.hofmannnet.myhome-server.de/job/WebSocketTest/job/master/badge/icon)](https://jenkins.hofmannnet.myhome-server.de/job/WebSocketTest/job/master) + +X-Plane Plugin for all supported platforms. +Demo of WebSocket capabilities diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPStandardWidgets.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPStandardWidgets.h new file mode 100644 index 0000000..ee3654c --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPStandardWidgets.h @@ -0,0 +1,628 @@ +#ifndef _XPStandardWidgets_h_ +#define _XPStandardWidgets_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * XPStandardWidgets - THEORY OF OPERATION + * + * The standard widgets are widgets built into the widgets library. While you + * can gain access to the widget function that drives them, you generally use + * them by calling XPCreateWidget and then listening for special messages, + * etc. + * + * The standard widgets often send mesages to themselves when the user + * performs an event; these messages are sent up the widget hierarchy until + * they are handled. So you can add a widget proc directly to a push button + * (for example) to intercept the message when it is clicked, or you can put + * one widget proc on a window for all of the push buttons in the window. + * Most of these messages contain the original widget ID as a parameter so you + * can know which widget is messaging no matter who it is sent to. + * + */ + +#include "XPWidgetDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * MAIN WINDOW + ***************************************************************************/ +/* + * The main window widget class provides a "window" as the user knows it. + * These windows are dragable and can be selected. Use them to create + * floating windows and non-modal dialogs. + * + */ + + +#define xpWidgetClass_MainWindow 1 + +/* + * Main Window Type Values + * + * These type values are used to control the appearance of a main window. + * + */ +enum { + /* The standard main window; pin stripes on XP7, metal frame on XP 6. */ + xpMainWindowStyle_MainWindow = 0 + + /* A translucent dark gray window, like the one ATC messages appear in. */ + , + xpMainWindowStyle_Translucent = 1 + + +}; + +/* + * Main Window Properties + * + * + */ +enum { + /* This property specifies the type of window. Set to one of the main + * window * types above. */ + xpProperty_MainWindowType = 1100 + + /* This property specifies whether the main window has close boxes in its * + * corners. */ + , + xpProperty_MainWindowHasCloseBoxes = 1200 + + +}; + +/* + * MainWindow Messages + * + * + */ +enum { + /* This message is sent when the close buttons are pressed for your window. + */ + xpMessage_CloseButtonPushed = 1200 + + +}; + +/*************************************************************************** + * SUB WINDOW + ***************************************************************************/ +/* + * X-plane dialogs are divided into separate areas; the sub window widgets + * allow you to make these areas. Create one main window and place several + * subwindows inside it. Then place your controls inside the subwindows. + * + */ + + +#define xpWidgetClass_SubWindow 2 + +/* + * SubWindow Type Values + * + * These values control the appearance of the subwindow. + * + */ +enum { + /* A panel that sits inside a main window. */ + xpSubWindowStyle_SubWindow = 0 + + /* A screen that sits inside a panel for showing text information. */ + , + xpSubWindowStyle_Screen = 2 + + /* A list view for scrolling lists. */ + , + xpSubWindowStyle_ListView = 3 + + +}; + +/* + * SubWindow Properties + * + * + */ +enum { + /* This property specifies the type of window. Set to one of the subwindow + * * types above. */ + xpProperty_SubWindowType = 1200 + + +}; + +/*************************************************************************** + * BUTTON + ***************************************************************************/ +/* + * The button class provides a number of different button styles and + * behaviors, including push buttons, radio buttons, check boxes, etc. The + * button label appears on or next to the button depending on the button's + * appearance, or type. + * + * The button's behavior is a separate property that dictates who it hilights + * and what kinds of messages it sends. Since behavior and type are + * different, you can do strange things like make check boxes that act as push + * buttons or push buttons with radio button behavior. + * + * In X-Plane 6 there were no check box graphics. The result is the following + * behavior: in x-plane 6 all check box and radio buttons are round + * (radio-button style) buttons; in X-Plane 7 they are all square (check-box + * style) buttons. In a future version of x-plane, the xpButtonBehavior enums + * will provide the correct graphic (check box or radio button) giving the + * expected result. + * + */ + + +#define xpWidgetClass_Button 3 + +/* + * Button Types + * + * These define the visual appearance of buttons but not how they respond to + * the mouse. + * + */ +enum { + /* This is a standard push button, like an "OK" or "Cancel" button in a + * dialog * box. */ + xpPushButton = 0 + + /* A check box or radio button. Use this and the button behaviors below to + * * get the desired behavior. */ + , + xpRadioButton = 1 + + /* A window close box. */ + , + xpWindowCloseBox = 3 + + /* A small down arrow. */ + , + xpLittleDownArrow = 5 + + /* A small up arrow. */ + , + xpLittleUpArrow = 6 + + +}; + +/* + * Button Behavior Values + * + * These define how the button responds to mouse clicks. + * + */ +enum { + /* Standard push button behavior. The button hilites while the mouse is * + * clicked over it and unhilites when the mouse is moved outside of it or * + * released. If the mouse is released over the button, the * + * xpMsg_PushButtonPressed message is sent. */ + xpButtonBehaviorPushButton = 0 + + /* Check box behavior. The button immediately toggles its value when the * + * mouse is clicked and sends out a xpMsg_ButtonStateChanged message. */ + , + xpButtonBehaviorCheckBox = 1 + + /* Radio button behavior. The button immediately sets its state to one and + * * sends out a xpMsg_ButtonStateChanged message if it was not already set + * to * one. You must turn off other radio buttons in a group in your + * code. */ + , + xpButtonBehaviorRadioButton = 2 + + +}; + +/* + * Button Properties + * + * + */ +enum { + /* This property sets the visual type of button. Use one of the button + * types * above. */ + xpProperty_ButtonType = 1300 + + /* This property sets the button's behavior. Use one of the button + * behaviors * above. */ + , + xpProperty_ButtonBehavior = 1301 + + /* This property tells whether a check box or radio button is "checked" or * + * not. Not used for push buttons. */ + , + xpProperty_ButtonState = 1302 + + +}; + +/* + * Button Messages + * + * These messages are sent by the button to itself and then up the widget + * chain when the button is clicked. (You may intercept them by providing a + * widget handler for the button itself or by providing a handler in a parent + * widget.) + * + */ +enum { + /* This message is sent when the user completes a click and release in a * + * button with push button behavior. Parameter one of the message is the * + * widget ID of the button. This message is dispatched up the widget * + * hierarchy. */ + xpMsg_PushButtonPressed = 1300 + + /* This message is sent when a button is clicked that has radio button or * + * check box behavior and its value changes. (Note that if the value + * changes * by setting a property you do not receive this message!) + * Parameter one is * the widget ID of the button, parameter 2 is the new + * state value, either * + * zero or one. This message is dispatched up the widget hierarchy. */ + , + xpMsg_ButtonStateChanged = 1301 + + +}; + +/*************************************************************************** + * TEXT FIELD + ***************************************************************************/ +/* + * The text field widget provides an editable text field including mouse + * selection and keyboard navigation. The contents of the text field are its + * descriptor. (The descriptor changes as the user types.) + * + * The text field can have a number of types, that effect the visual layout of + * the text field. The text field sends messages to itself so you may control + * its behavior. + * + * If you need to filter keystrokes, add a new handler and intercept the key + * press message. Since key presses are passed by pointer, you can modify the + * keystroke and pass it through to the text field widget. + * + * WARNING: in x-plane before 7.10 (including 6.70) null characters could + * crash x-plane. To prevent this, wrap this object with a filter function + * (more instructions can be found on the SDK website). + * + */ + + +#define xpWidgetClass_TextField 4 + +/* + * Text Field Type Values + * + * These control the look of the text field. + * + */ +enum { + /* A field for text entry. */ + xpTextEntryField = 0 + + /* A transparent text field. The user can type and the text is drawn, but + * no * background is drawn. You can draw your own background by adding a + * widget * handler and prehandling the draw message. */ + , + xpTextTransparent = 3 + + /* A translucent edit field, dark gray. */ + , + xpTextTranslucent = 4 + + +}; + +/* + * Text Field Properties + * + * + */ +enum { + /* This is the character position the selection starts at, zero based. If it + * * is the same as the end insertion point, the insertion point is not a * + * selection. */ + xpProperty_EditFieldSelStart = 1400 + + /* This is the character position of the end of the selection. */ + , + xpProperty_EditFieldSelEnd = 1401 + + /* This is the character position a drag was started at if the user is * + * dragging to select text, or -1 if a drag is not in progress. */ + , + xpProperty_EditFieldSelDragStart = 1402 + + /* This is the type of text field to display, from the above list. */ + , + xpProperty_TextFieldType = 1403 + + /* Set this property to 1 to password protect the field. Characters will be + * * drawn as *s even though the descriptor will contain plain-text. */ + , + xpProperty_PasswordMode = 1404 + + /* The max number of characters you can enter, if limited. Zero means * + * unlimited. */ + , + xpProperty_MaxCharacters = 1405 + + /* The first visible character on the left. This effectively scrolls the + * text * field. */ + , + xpProperty_ScrollPosition = 1406 + + /* The font to draw the field's text with. (An XPLMFontID.) */ + , + xpProperty_Font = 1407 + + /* This is the active side of the insert selection. (Internal) */ + , + xpProperty_ActiveEditSide = 1408 + + +}; + +/* + * Text Field Messages + * + * + */ +enum { + /* Text Field Messages * + * * + * The text field sends this message to itself when its text changes. It * + * sends the message up the call chain; param1 is the text field's widget + * ID. */ + xpMsg_TextFieldChanged = 1400 + + +}; + +/*************************************************************************** + * SCROLL BAR + ***************************************************************************/ +/* + * A standard scroll bar or slider control. The scroll bar has a minimum, + * maximum and current value that is updated when the user drags it. The + * scroll bar sends continuous messages as it is dragged. + * + */ + + +#define xpWidgetClass_ScrollBar 5 + +/* + * Scroll Bar Type Values + * + * This defines how the scroll bar looks. + * + */ +enum { + /* Scroll bar types. * + * * + * A standard x-plane scroll bar (with arrows on the ends). */ + xpScrollBarTypeScrollBar = 0 + + /* A slider, no arrows. */ + , + xpScrollBarTypeSlider = 1 + + +}; + +/* + * Scroll Bar Properties + * + * + */ +enum { + /* The current position of the thumb (in between the min and max, inclusive) + */ + xpProperty_ScrollBarSliderPosition = 1500 + + /* The value the scroll bar has when the thumb is in the lowest position. */ + , + xpProperty_ScrollBarMin = 1501 + + /* The value the scroll bar has when the thumb is in the highest position. + */ + , + xpProperty_ScrollBarMax = 1502 + + /* How many units to moev the scroll bar when clicking next to the thumb. + * The * scroll bar always moves one unit when the arrows are clicked. */ + , + xpProperty_ScrollBarPageAmount = 1503 + + /* The type of scrollbar from the enums above. */ + , + xpProperty_ScrollBarType = 1504 + + /* Used internally. */ + , + xpProperty_ScrollBarSlop = 1505 + + +}; + +/* + * Scroll Bar Messages + * + * + */ +enum { + /* The Scroll Bar sends this message when the slider position changes. It * + * sends the message up the call chain; param1 is the Scroll Bar widget ID. + */ + xpMsg_ScrollBarSliderPositionChanged = 1500 + + +}; + +/*************************************************************************** + * CAPTION + ***************************************************************************/ +/* + * A caption is a simple widget that shows its descriptor as a string, useful + * for labeling parts of a window. It always shows its descriptor as its + * string and is otherwise transparent. + * + */ + + +#define xpWidgetClass_Caption 6 + +/* + * Caption Properties + * + * + */ +enum { + /* This property specifies whether the caption is lit; use lit captions * + * against screens. */ + xpProperty_CaptionLit = 1600 + + +}; + +/*************************************************************************** + * GENERAL GRAPHICS + ***************************************************************************/ +/* + * The general graphics widget can show one of many icons available from + * x-plane. + * + */ + + +#define xpWidgetClass_GeneralGraphics 7 + +/* + * General Graphics Types Values + * + * These define the icon for the general graphics. + * + */ +enum { + xpShip = 4 + + , + xpILSGlideScope = 5 + + , + xpMarkerLeft = 6 + + , + xp_Airport = 7 + + , + xpNDB = 8 + + , + xpVOR = 9 + + , + xpRadioTower = 10 + + , + xpAircraftCarrier = 11 + + , + xpFire = 12 + + , + xpMarkerRight = 13 + + , + xpCustomObject = 14 + + , + xpCoolingTower = 15 + + , + xpSmokeStack = 16 + + , + xpBuilding = 17 + + , + xpPowerLine = 18 + + , + xpVORWithCompassRose = 19 + + , + xpOilPlatform = 21 + + , + xpOilPlatformSmall = 22 + + , + xpWayPoint = 23 + + +}; + +/* + * General Graphics Properties + * + * + */ +enum { + /* This property controls the type of icon that is drawn. */ + xpProperty_GeneralGraphicsType = 1700 + + +}; + +/*************************************************************************** + * PROGRESS INDICATOR + ***************************************************************************/ +/* + * This widget implements a progress indicator as seen when x-plane starts up. + * + */ + + +#define xpWidgetClass_Progress 8 + +/* + * Progress Indicator Properties + * + * + */ +enum { + /* This is the current value of the progress indicator. */ + xpProperty_ProgressPosition = 1800 + + /* This is the minimum value, equivalent to 0% filled. */ + , + xpProperty_ProgressMin = 1801 + + /* This is the maximum value, equivalent to 100% filled. */ + , + xpProperty_ProgressMax = 1802 + + +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPUIGraphics.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPUIGraphics.h new file mode 100644 index 0000000..be67bb4 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPUIGraphics.h @@ -0,0 +1,395 @@ +#ifndef _XPUIGraphics_h_ +#define _XPUIGraphics_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * + * + */ + +#include "XPWidgetDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * UI GRAPHICS + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPWindowStyle + * + * There are a few built-in window styles in X-Plane that you can use. + * + * Note that X-Plane 6 does not offer real shadow-compositing; you must make + * sure to put a window on top of another window of the right style to the + * shadows work, etc. This applies to elements with insets and shadows. The + * rules are: + * + * Sub windows must go on top of main windows, and screens and list views on + * top of subwindows. Only help and main windows can be over the main screen. + * + * + * With X-Plane 7 any window or element may be placed over any other element. + * + * Some windows are scaled by stretching, some by repeating. The drawing + * routines know which scaling method to use. The list view cannot be + * rescaled in x-plane 6 because it has both a repeating pattern and a + * gradient in one element. All other elements can be rescaled. + * + */ +enum { + /* An LCD screen that shows help. */ + xpWindow_Help = 0 + + /* A dialog box window. */ + , + xpWindow_MainWindow = 1 + + /* A panel or frame within a dialog box window. */ + , + xpWindow_SubWindow = 2 + + /* An LCD screen within a panel to hold text displays. */ + , + xpWindow_Screen = 4 + + /* A list view within a panel for scrolling file names, etc. */ + , + xpWindow_ListView = 5 + + +}; +typedef int XPWindowStyle; + +/* + * XPDrawWindow + * + * This routine draws a window of the given dimensions at the given offset on + * the virtual screen in a given style. The window is automatically scaled as + * appropriate using a bitmap scaling technique (scaling or repeating) as + * appropriate to the style. + * + */ +WIDGET_API void + XPDrawWindow(int inX1, int inY1, int inX2, int inY2, XPWindowStyle inStyle); + +/* + * XPGetWindowDefaultDimensions + * + * This routine returns the default dimensions for a window. Output is either + * a minimum or fixed value depending on whether the window is scalable. + * + */ +WIDGET_API void XPGetWindowDefaultDimensions(XPWindowStyle inStyle, + int *outWidth, /* Can be NULL */ + int *outHeight); /* Can be NULL */ + +/* + * XPElementStyle + * + * Elements are individually drawable UI things like push buttons, etc. The + * style defines what kind of element you are drawing. Elements can be + * stretched in one or two dimensions (depending on the element). Some + * elements can be lit. + * + * In x-plane 6 some elements must be drawn over metal. Some are scalable and + * some are not. Any element can be drawn anywhere in x-plane 7. + * + * Scalable Axis Required Background + * + */ +enum { + /* x metal */ + xpElement_TextField = 6 + + /* none metal */ + , + xpElement_CheckBox = 9 + + /* none metal */ + , + xpElement_CheckBoxLit = 10 + + /* none window header */ + , + xpElement_WindowCloseBox = 14 + + /* none window header */ + , + xpElement_WindowCloseBoxPressed = 15 + + /* x metal */ + , + xpElement_PushButton = 16 + + /* x metal */ + , + xpElement_PushButtonLit = 17 + + /* none any */ + , + xpElement_OilPlatform = 24 + + /* none any */ + , + xpElement_OilPlatformSmall = 25 + + /* none any */ + , + xpElement_Ship = 26 + + /* none any */ + , + xpElement_ILSGlideScope = 27 + + /* none any */ + , + xpElement_MarkerLeft = 28 + + /* none any */ + , + xpElement_Airport = 29 + + /* none any */ + , + xpElement_Waypoint = 30 + + /* none any */ + , + xpElement_NDB = 31 + + /* none any */ + , + xpElement_VOR = 32 + + /* none any */ + , + xpElement_RadioTower = 33 + + /* none any */ + , + xpElement_AircraftCarrier = 34 + + /* none any */ + , + xpElement_Fire = 35 + + /* none any */ + , + xpElement_MarkerRight = 36 + + /* none any */ + , + xpElement_CustomObject = 37 + + /* none any */ + , + xpElement_CoolingTower = 38 + + /* none any */ + , + xpElement_SmokeStack = 39 + + /* none any */ + , + xpElement_Building = 40 + + /* none any */ + , + xpElement_PowerLine = 41 + + /* none metal */ + , + xpElement_CopyButtons = 45 + + /* none metal */ + , + xpElement_CopyButtonsWithEditingGrid = 46 + + /* x, y metal */ + , + xpElement_EditingGrid = 47 + + /* THIS CAN PROBABLY BE REMOVED */ + , + xpElement_ScrollBar = 48 + + /* none any */ + , + xpElement_VORWithCompassRose = 49 + + /* none metal */ + , + xpElement_Zoomer = 51 + + /* x, y metal */ + , + xpElement_TextFieldMiddle = 52 + + /* none metal */ + , + xpElement_LittleDownArrow = 53 + + /* none metal */ + , + xpElement_LittleUpArrow = 54 + + /* none metal */ + , + xpElement_WindowDragBar = 61 + + /* none metal */ + , + xpElement_WindowDragBarSmooth = 62 + + +}; +typedef int XPElementStyle; + +/* + * XPDrawElement + * + * XPDrawElement draws a given element at an offset on the virtual screen in + * set dimensions. EVEN if the element is not scalable, it will be scaled if + * the width and height do not match the preferred dimensions; it'll just look + * ugly. Pass inLit to see the lit version of the element; if the element + * cannot be lit this is ignored. + * + */ +WIDGET_API void XPDrawElement(int inX1, + int inY1, + int inX2, + int inY2, + XPElementStyle inStyle, + int inLit); + +/* + * XPGetElementDefaultDimensions + * + * This routine returns the recommended or minimum dimensions of a given UI + * element. outCanBeLit tells whether the element has both a lit and unlit + * state. Pass NULL to not receive any of these parameters. + * + */ +WIDGET_API void + XPGetElementDefaultDimensions(XPElementStyle inStyle, + int *outWidth, /* Can be NULL */ + int *outHeight, /* Can be NULL */ + int *outCanBeLit); /* Can be NULL */ + +/* + * XPTrackStyle + * + * A track is a UI element that displays a value vertically or horizontally. + * X-Plane has three kinds of tracks: scroll bars, sliders, and progress bars. + * Tracks can be displayed either horizontally or vertically; tracks will + * choose their own layout based on the larger dimension of their dimensions + * (e.g. they know if they are tall or wide). Sliders may be lit or unlit + * (showing the user manipulating them). + * + * ScrollBar - this is a standard scroll bar with arrows and a thumb to drag. + * Slider - this is a simple track with a ball in the middle that can be + * slid. Progress - this is a progress indicator showing how a long task is + * going. + * + */ +enum { + /* not over metal can be lit can be rotated */ + xpTrack_ScrollBar = 0 + + /* over metal can be lit can be rotated */ + , + xpTrack_Slider = 1 + + /* over metal cannot be lit cannot be rotated */ + , + xpTrack_Progress = 2 + + +}; +typedef int XPTrackStyle; + +/* + * XPDrawTrack + * + * This routine draws a track. You pass in the track dimensions and size; the + * track picks the optimal orientation for these dimensions. Pass in the + * track's minimum current and maximum values; the indicator will be + * positioned appropriately. You can also specify whether the track is lit or + * not. + * + */ +WIDGET_API void XPDrawTrack(int inX1, + int inY1, + int inX2, + int inY2, + int inMin, + int inMax, + int inValue, + XPTrackStyle inTrackStyle, + int inLit); + +/* + * XPGetTrackDefaultDimensions + * + * This routine returns a track's default smaller dimension; all tracks are + * scalable in the larger dimension. It also returns whether a track can be + * lit. + * + */ +WIDGET_API void XPGetTrackDefaultDimensions(XPTrackStyle inStyle, + int *outWidth, + int *outCanBeLit); + +/* + * XPGetTrackMetrics + * + * This routine returns the metrics of a track. If you want to write UI code + * to manipulate a track, this routine helps you know where the mouse + * locations are. For most other elements, the rectangle the element is drawn + * in is enough information. However, the scrollbar drawing routine does some + * automatic placement; this routine lets you know where things ended up. You + * pass almost everything you would pass to the draw routine. You get out the + * orientation, and other useful stuff. + * + * Besides orientation, you get five dimensions for the five parts of a + * scrollbar, which are the down button, down area (area before the thumb), + * the thumb, and the up area and button. For horizontal scrollers, the left + * button decreases; for vertical scrollers, the top button decreases. + * + */ +WIDGET_API void XPGetTrackMetrics(int inX1, + int inY1, + int inX2, + int inY2, + int inMin, + int inMax, + int inValue, + XPTrackStyle inTrackStyle, + int *outIsVertical, + int *outDownBtnSize, + int *outDownPageSize, + int *outThumbSize, + int *outUpPageSize, + int *outUpBtnSize); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgetDefs.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgetDefs.h new file mode 100644 index 0000000..15ae492 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgetDefs.h @@ -0,0 +1,525 @@ +#ifndef _XPWidgetDefs_h_ +#define _XPWidgetDefs_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if APL +#if XPWIDGETS +#if __GNUC__ >= 4 +#define WIDGET_API __attribute__((visibility("default"))) +#elif __MACH__ +#define WIDGET_API +#else +#define WIDGET_API __declspec(dllexport) +#endif +#else +#define WIDGET_API +#endif +#elif IBM +#if XPWIDGETS +#define WIDGET_API __declspec(dllexport) +#else +#define WIDGET_API __declspec(dllimport) +#endif +#elif LIN +#if XPWIDGETS +#if __GNUC__ >= 4 +#define WIDGET_API __attribute__((visibility("default"))) +#else +#define WIDGET_API +#endif +#else +#define WIDGET_API +#endif +#else +#pragma error "Platform not defined!" +#endif +/*************************************************************************** + * WIDGET DEFINITIONS + ***************************************************************************/ +/* + * A widget is a call-back driven screen entity like a push-button, window, + * text entry field, etc. + * + * Use the widget API to create widgets of various classes. You can nest them + * into trees of widgets to create complex user interfaces. + * + */ + + +/* + * XPWidgetID + * + * A Widget ID is an opaque unique non-zero handle identifying your widget. + * Use 0 to specify "no widget". This type is defined as wide enough to hold + * a pointer. You receive a widget ID when you create a new widget and then + * use that widget ID to further refer to the widget. + * + */ +typedef void *XPWidgetID; + +/* + * XPWidgetPropertyID + * + * Properties are values attached to instances of your widgets. A property is + * identified by a 32-bit ID and its value is the width of a pointer. + * + * Each widget instance may have a property or not have it. When you set a + * property on a widget for the first time, the property is added to the + * widget; it then stays there for the life of the widget. + * + * Some property IDs are predefined by the widget package; you can make up + * your own property IDs as well. + * + */ +enum { + /* A window's refcon is an opaque value used by client code to find other + * data * based on it. */ + xpProperty_Refcon = 0 + + /* These properties are used by the utlities to implement dragging. */ + , + xpProperty_Dragging = 1 + + , + xpProperty_DragXOff = 2 + + , + xpProperty_DragYOff = 3 + + /* Is the widget hilited? (For widgets that support this kind of thing.) */ + , + xpProperty_Hilited = 4 + + /* Is there a C++ object attached to this widget? */ + , + xpProperty_Object = 5 + + /* If this property is 1, the widget package will use OpenGL to restrict * + * drawing to the Wiget's exposed rectangle. */ + , + xpProperty_Clip = 6 + + /* Is this widget enabled (for those that have a disabled state too)? */ + , + xpProperty_Enabled = 7 + + /* NOTE: Property IDs 1 - 999 are reserved for the widget's library. * + * * + * NOTE: Property IDs 1000 - 9999 are allocated to the standard widget + * classes * provided with the library Properties 1000 - 1099 are for widget + * class 0, * 1100 - 1199 for widget class 1, etc. */ + , + xpProperty_UserStart = 10000 + + +}; +typedef int XPWidgetPropertyID; + +/* + * XPMouseState_t + * + * When the mouse is clicked or dragged, a pointer to this structure is passed + * to your widget function. + * + */ +typedef struct { + int x; + int y; + /* Mouse Button number, left = 0 (right button not yet supported. */ + int button; +#if defined(XPLM200) + /* Scroll wheel delta (button in this case would be the wheel axis number). + */ + int delta; +#endif /* XPLM200 */ +} XPMouseState_t; + +/* + * XPKeyState_t + * + * When a key is pressed, a pointer to this struct is passed to your widget + * function. + * + */ +typedef struct { + /* The ASCII key that was pressed. WARNING: this may be 0 for some + * non-ASCII * key sequences. */ + char key; + /* The flags. Make sure to check this if you only want key-downs! */ + XPLMKeyFlags flags; + /* The virtual key code for the key */ + char vkey; +} XPKeyState_t; + +/* + * XPWidgetGeometryChange_t + * + * This structure contains the deltas for your widget's geometry when it + * changes. + * + */ +typedef struct { + int dx; + /* +Y = the widget moved up */ + int dy; + int dwidth; + int dheight; +} XPWidgetGeometryChange_t; + +/* + * XPDispatchMode + * + * The dispatching modes describe how the widgets library sends out messages. + * Currently there are three modes: + * + */ +enum { + /* The message will only be sent to the target widget. */ + xpMode_Direct = 0 + + /* The message is sent to the target widget, then up the chain of parents * + * until the message is handled or a parentless widget is reached. */ + , + xpMode_UpChain = 1 + + /* The message is sent to the target widget and then all of its children * + * recursively depth-first. */ + , + xpMode_Recursive = 2 + + /* The message is snet just to the target, but goes to every callback, even + * if * it is handled. */ + , + xpMode_DirectAllCallbacks = 3 + + /* The message is only sent to the very first handler even if it is not * + * accepted. (This is really only useful for some internal Widget Lib * + * functions. */ + , + xpMode_Once = 4 + + +}; +typedef int XPDispatchMode; + +/* + * XPWidgetClass + * + * Widget classes define predefined widget types. A widget class basically + * specifies from a library the widget function to be used for the widget. + * Most widgets can be made right from classes. + * + */ +typedef int XPWidgetClass; + +/* An unspecified widget class. Other widget classes are in * + * XPStandardWidgets.h */ +#define xpWidgetClass_None 0 + +/*************************************************************************** + * WIDGET MESSAGES + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPWidgetMessage + * + * Widgets receive 32-bit messages indicating what action is to be taken or + * notifications of events. The list of messages may be expanded. + * + */ +enum { + /* No message, should not be sent. */ + xpMsg_None = 0 + + /* The create message is sent once per widget that is created with your + * widget * function and once for any widget that has your widget function + * attached. * + * * + * Dispatching: Direct * + * * + * Param 1: 1 if you are being added as a subclass, 0 if the widget is first + * * being created. */ + , + xpMsg_Create = 1 + + /* The destroy message is sent once for each message that is destroyed that + * * has your widget function. * + * * + * Dispatching: Direct for all * + * * + * Param 1: 1 if being deleted by a recursive delete to the parent, 0 for * + * explicit deletion. */ + , + xpMsg_Destroy = 2 + + /* The paint message is sent to your widget to draw itself. The paint + * message * is the bare-bones message; in response you must draw yourself, + * draw your * children, set up clipping and culling, check for + * visibility, etc. If you * don't want to do all of this, ignore the + * paint message and a draw message * (see below) will be sent to you. * + * * + * Dispatching: Direct */ + , + xpMsg_Paint = 3 + + /* The draw message is sent to your widget when it is time to draw yourself. + * * OpenGL will be set up to draw in 2-d global screen coordinates, but you + * * should use the XPLM to set up OpenGL state. * + * * + * Dispatching: Direct */ + , + xpMsg_Draw = 4 + + /* The key press message is sent once per key that is pressed. The first * + * parameter is the type of key code (integer or char) and the second is the + * * code itself. By handling this event, you consume the key stroke. * + * * + * Handling this message 'consumes' the keystroke; not handling it passes it + * * to your parent widget. * + * * + * Dispatching: Up Chain * + * * + * : Param 1: A pointer to an XPKeyState_t structure with the keystroke. */ + , + xpMsg_KeyPress = 5 + + /* Keyboard focus is being given to you. By handling this message you + * accept * keyboard focus. The first parameter will be one if a child of + * yours gave * up focus to you, 0 if someone set focus on you explicitly. + * * + * * + * : Handling this message accepts focus; not handling refuses focus. * + * * + * Dispatching: direct * + * * + * Param 1: 1 if you are gaining focus because your child is giving it up, 0 + * * if someone is explicitly giving you focus. */ + , + xpMsg_KeyTakeFocus = 6 + + /* Keyboard focus is being taken away from you. The first parameter will be + * * one if you are losing focus because another widget is taking it, or 0 + * if * someone called the API to make you lose focus explicitly. * + * * + * Dispatching: Direct * + * * + * Param 1: 1 if focus is being taken by another widget, 0 if code requested + * * to remove focus. */ + , + xpMsg_KeyLoseFocus = 7 + + /* You receive one mousedown event per click with a mouse-state structure * + * pointed to by parameter 1, by accepting this you eat the click, otherwise + * * your parent gets it. You will not receive drag and mouse up messages + * if * you do not accept the down message. * + * * + * Handling this message consumes the mouse click, not handling it passes it + * * to the next widget. You can act 'transparent' as a window by never + * handling * moues clicks to certain areas. * + * * + * Dispatching: Up chain NOTE: Technically this is direct dispatched, but + * the * widgets library will shop it to each widget until one consumes the + * click, * making it effectively "up chain". * + * * + * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ + , + xpMsg_MouseDown = 8 + + /* You receive a series of mouse drag messages (typically one per frame in + * the * sim) as the mouse is moved once you have accepted a mouse down + * message. * Parameter one points to a mouse-state structure describing + * the mouse * location. You will continue to receive these until + * the mouse button is * released. You may receive multiple mouse state + * messages with the same mouse * position. You will receive mouse drag + * events even if the mouse is dragged * out of your current or original + * bounds at the time of the mouse down. * + * * + * Dispatching: Direct * + * * + * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ + , + xpMsg_MouseDrag = 9 + + /* The mouseup event is sent once when the mouse button is released after a + * * drag or click. You only receive this message if you accept the + * mouseDown * message. Parameter one points to a mouse state structure. + * * + * * + * Dispatching: Direct * + * * + * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ + , + xpMsg_MouseUp = 10 + + /* Your geometry or a child's geometry is being changed. * + * * + * Dispatching: Up chain * + * * + * Param 1: The widget ID of the original reshaped target. * + * * + * Param 2: A pointer to a XPWidgetGeometryChange_t struct describing the * + * change. */ + , + xpMsg_Reshape = 11 + + /* Your exposed area has changed. * + * * + * Dispatching: Direct */ + , + xpMsg_ExposedChanged = 12 + + /* A child has been added to you. The child's ID is passed in parameter + * one. * + * * + * * + * Dispatching: Direct * + * * + * Param 1: The Widget ID of the child being added. */ + , + xpMsg_AcceptChild = 13 + + /* A child has been removed from to you. The child's ID is passed in * + * parameter one. * + * * + * Dispatching: Direct * + * * + * Param 1: The Widget ID of the child being removed. */ + , + xpMsg_LoseChild = 14 + + /* You now have a new parent, or have no parent. The parent's ID is passed + * * in, or 0 for no parent. * + * * + * Dispatching: Direct * + * * + * Param 1: The Widget ID of your parent */ + , + xpMsg_AcceptParent = 15 + + /* You or a child has been shown. Note that this does not include you being + * * shown because your parent was shown, you were put in a new parent, + * your * root was shown, etc. * + * * + * Dispatching: Up chain * + * * + * Param 1: The widget ID of the shown widget. */ + , + xpMsg_Shown = 16 + + /* You have been hidden. See limitations above. * + * * + * Dispatching: Up chain * + * * + * Param 1: The widget ID of the hidden widget. */ + , + xpMsg_Hidden = 17 + + /* Your descriptor has changed. * + * * + * Dispatching: Direct */ + , + xpMsg_DescriptorChanged = 18 + + /* A property has changed. Param 1 contains the property ID. * + * * + * Dispatching: Direct * + * * + * Param 1: The Property ID being changed. * + * * + * Param 2: The new property value */ + , + xpMsg_PropertyChanged = 19 + +#if defined(XPLM200) + /* The mouse wheel has moved. * + * * + * Return 1 to consume the mouse wheel move, or 0 to pass the message to a * + * parent. Dispatching: Up chain * + * * + * Param 1: A pointer to an XPMouseState_t containing the mouse status. */ + , + xpMsg_MouseWheel = 20 + +#endif /* XPLM200 */ +#if defined(XPLM200) + /* The cursor is over your widget. If you consume this message, change the + * * XPLMCursorStatus value to indicate the desired result, with the same + * rules * as in XPLMDisplay.h. * + * * + * Return 1 to consume this message, 0 to pass it on. * + * * + * Dispatching: Up chain Param 1: A pointer to an XPMouseState_t struct * + * containing the mouse status. * + * * + * Param 2: A pointer to a XPLMCursorStatus - set this to the cursor result + * * you desire. */ + , + xpMsg_CursorAdjust = 21 + +#endif /* XPLM200 */ + /* NOTE: Message IDs 1000 - 9999 are allocated to the standard widget + * classes * provided with the library with 1000 - 1099 for widget class + * 0, 1100 - 1199 * for widget class 1, etc. Message IDs 10,000 and + * beyond are for plugin use. */ + , + xpMsg_UserStart = 10000 + + +}; +typedef int XPWidgetMessage; + +/*************************************************************************** + * WIDGET CALLBACK FUNCTION + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPWidgetFunc_t + * + * This function defines your custom widget's behavior. It will be called by + * the widgets library to send messages to your widget. The message and + * widget ID are passed in, as well as two ptr-width signed parameters whose + * meaning varies with the message. Return 1 to indicate that you have + * processed the message, 0 to indicate that you have not. For any message + * that is not understood, return 0. + * + */ +typedef int (*XPWidgetFunc_t)(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgetUtils.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgetUtils.h new file mode 100644 index 0000000..3379491 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgetUtils.h @@ -0,0 +1,224 @@ +#ifndef _XPWidgetUtils_h_ +#define _XPWidgetUtils_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * XPWidgetUtils - USAGE NOTES + * + * The XPWidgetUtils library contains useful functions that make writing and + * using widgets less of a pain. + * + * One set of functions are the widget behavior functions. These functions + * each add specific useful behaviors to widgets. They can be used in two + * manners: + * + * 1. You can add a widget behavior function to a widget as a callback proc + * using the XPAddWidgetCallback function. The widget will gain that + * behavior. Remember that the last function you add has highest priority. + * You can use this to change or augment the behavior of an existing finished + * widget. + * + * 2. You can call a widget function from inside your own widget function. + * This allows you to include useful behaviors in custom-built widgets. A + * number of the standard widgets get their behavior from this library. To do + * this, call the behavior function from your function first. If it returns + * 1, that means it handled the event and you don't need to; simply return 1. + * + */ + +#include "XPWidgetDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * GENERAL UTILITIES + ***************************************************************************/ +/* + * + * + */ + + +/* + * Convenience accessors + * + * It can be clumsy accessing the variables passed in by pointer to a struct + * for mouse and reshape messages; these accessors let you simply pass in the + * param right from the arguments of your widget proc and get back the value you + * want. + * + */ +#define MOUSE_X(param) (((XPMouseState_t *)(param))->x) +#define MOUSE_Y(param) (((XPMouseState_t *)(param))->y) + +#define DELTA_X(param) (((XPWidgetGeometryChange_t *)(param))->dx) +#define DELTA_Y(param) (((XPWidgetGeometryChange_t *)(param))->dy) +#define DELTA_W(param) (((XPWidgetGeometryChange_t *)(param))->dwidth) +#define DELTA_H(param) (((XPWidgetGeometryChange_t *)(param))->dheight) + +#define KEY_CHAR(param) (((XPKeyState_t *)(param))->key) +#define KEY_FLAGS(param) (((XPKeyState_t *)(param))->flags) +#define KEY_VKEY(param) (((XPKeyState_t *)(param))->vkey) + +#define IN_RECT(x, y, l, t, r, b) \ + (((x) >= (l)) && ((x) <= (r)) && ((y) >= (b)) && ((y) <= (t))) + +/* + * XPWidgetCreate_t + * + * This structure contains all of the parameters needed to create a wiget. It + * is used with XPUCreateWidgets to create widgets in bulk from an array. All + * parameters correspond to those of XPCreateWidget except for the container + * index. If the container index is equal to the index of a widget in the + * array, the widget in the array passed to XPUCreateWidgets is used as the + * parent of this widget. Note that if you pass an index greater than your + * own position in the array, the parent you are requesting will not exist + * yet. If the container index is NO_PARENT, the parent widget is specified as + * NULL. If the container index is PARAM_PARENT, the widget passed into + * XPUCreateWidgets is used. + * + */ +typedef struct { + int left; + int top; + int right; + int bottom; + int visible; + const char *descriptor; + int isRoot; + int containerIndex; + XPWidgetClass widgetClass; +} XPWidgetCreate_t; + +#define NO_PARENT -1 + +#define PARAM_PARENT -2 + +#define WIDGET_COUNT(x) ((sizeof(x) / sizeof(XPWidgetCreate_t))) + +/* + * XPUCreateWidgets + * + * This function creates a series of widgets from a table...see + * XPCreateWidget_t above. Pass in an array of widget creation structures and + * an array of widget IDs that will receive each widget. + * + * Widget parents are specified by index into the created widget table, + * allowing you to create nested widget structures. You can create multiple + * widget trees in one table. Generally you should create widget trees from + * the top down. + * + * You can also pass in a widget ID that will be used when the widget's parent + * is listed as PARAM_PARENT; this allows you to embed widgets created with + * XPUCreateWidgets in a widget created previously. + * + */ +WIDGET_API void XPUCreateWidgets(const XPWidgetCreate_t *inWidgetDefs, + int inCount, + XPWidgetID inParamParent, + XPWidgetID *ioWidgets); + +/* + * XPUMoveWidgetBy + * + * Simply moves a widget by an amount, +x = right, +y=up, without resizing the + * widget. + * + */ +WIDGET_API void + XPUMoveWidgetBy(XPWidgetID inWidget, int inDeltaX, int inDeltaY); + +/*************************************************************************** + * LAYOUT MANAGERS + ***************************************************************************/ +/* + * The layout managers are widget behavior functions for handling where + * widgets move. Layout managers can be called from a widget function or + * attached to a widget later. + * + */ + + +/* + * XPUFixedLayout + * + * This function causes the widget to maintain its children in fixed position + * relative to itself as it is resized. Use this on the top level 'window' + * widget for your window. + * + */ +WIDGET_API int XPUFixedLayout(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + +/*************************************************************************** + * WIDGET PROC BEHAVIORS + ***************************************************************************/ +/* + * These widget behavior functions add other useful behaviors to widgets. + * These functions cannot be attached to a widget; they must be called from + * your widget function. + * + */ + + +/* + * XPUSelectIfNeeded + * + * This causes the widget to bring its window to the foreground if it is not + * already. inEatClick specifies whether clicks in the background should be + * consumed by bringin the window to the foreground. + * + */ +WIDGET_API int XPUSelectIfNeeded(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2, + int inEatClick); + +/* + * XPUDefocusKeyboard + * + * This causes a click in the widget to send keyboard focus back to X-Plane. + * This stops editing of any text fields, etc. + * + */ +WIDGET_API int XPUDefocusKeyboard(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2, + int inEatClick); + +/* + * XPUDragWidget + * + * XPUDragWidget drags the widget in response to mouse clicks. Pass in not + * only the event, but the global coordinates of the drag region, which might + * be a sub-region of your widget (for example, a title bar). + * + */ +WIDGET_API int XPUDragWidget(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2, + int inLeft, + int inTop, + int inRight, + int inBottom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgets.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgets.h new file mode 100644 index 0000000..6cfd277 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Widgets/XPWidgets.h @@ -0,0 +1,541 @@ +#ifndef _XPWidgets_h_ +#define _XPWidgets_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * WIDGETS - THEORY OF OPERATION AND NOTES + * + * Widgets are persistent view 'objects' for X-Plane. A widget is an object + * referenced by its opaque handle (widget ID) and the APIs in this file. You + * cannot access the widget's guts directly. Every Widget has the following + * intrinsic data: + * + * - A bounding box defined in global screen coordinates with 0,0 in the + * bottom left and +y = up, +x = right. + * + * - A visible box, which is the intersection of the bounding box with the + * widget's parents visible box. + * + * - Zero or one parent widgets. (Always zero if the widget is a root widget. + * + * + * - Zero or more child widgets. + * + * - Whether the widget is a root. Root widgets are the top level plugin + * windows. + * + * - Whether the widget is visible. + * + * - A text string descriptor, whose meaning varies from widget to widget. + * + * - An arbitrary set of 32 bit integral properties defined by 32-bit integral + * keys. This is how specific widgets + * + * store specific data. + * + * - A list of widget callbacks proc that implements the widgets behaviors. + * + * The Widgets library sends messages to widgets to request specific behaviors + * or notify the widget of things. + * + * Widgets may have more than one callback function, in which case messages + * are sent to the most recently added callback function until the message is + * handled. Messages may also be sent to parents or children; see the + * XPWidgetDefs.h header file for the different widget message dispatching + * functions. By adding a callback function to a window you can 'subclass' + * its behavior. + * + * A set of standard widgets are provided that serve common UI purposes. You + * can also customize or implement entirely custom widgets. + * + * Widgets are different than other view hierarchies (most notably Win32, + * which they bear a striking resemblance to) in the following ways: + * + * - Not all behavior can be patched. State that is managed by the XPWidgets + * DLL and not by individual widgets cannot be customized. + * + * - All coordinates are in global screen coordinates. Coordinates are not + * relative to an enclosing widget, nor are they relative to a display window. + * + * + * - Widget messages are always dispatched synchronously, and there is no + * concept of scheduling an update or a dirty region. Messages originate from + * X-Plane as the sim cycle goes by. Since x-plane is constantly redrawing, + * so are widgets; there is no need to mark a part of a widget as 'needing + * redrawing' because redrawing happens frequently whether the widget needs it + * or not. + * + * - Any widget may be a 'root' widget, causing it to be drawn; there is no + * relationship between widget class and rootness. Root widgets are + * imlemented as XPLMDisply windows. + * + */ + +#include "XPWidgetDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * WIDGET CREATION AND MANAGEMENT + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPCreateWidget + * + * This function creates a new widget and returns the new widget's ID to you. + * If the widget creation fails for some reason, it returns NULL. Widget + * creation will fail either if you pass a bad class ID or if there is not + * adequate memory. + * + * Input Parameters: + * + * - Top, left, bottom, and right in global screen coordinates defining the + * widget's location on the screen. + * + * - inVisible is 1 if the widget should be drawn, 0 to start the widget as + * hidden. + * + * - inDescriptor is a null terminated string that will become the widget's + * descriptor. + * + * - inIsRoot is 1 if this is going to be a root widget, 0 if it will not be. + * + * - inContainer is the ID of this widget's container. It must be 0 for a + * root widget. for a non-root widget, pass the widget ID of the widget to + * place this widget within. If this widget is not going to start inside + * another widget, pass 0; this new widget will then just be floating off in + * space (and will not be drawn until it is placed in a widget. + * + * - inClass is the class of the widget to draw. Use one of the predefined + * class-IDs to create a standard widget. + * + * A note on widget embedding: a widget is only called (and will be drawn, + * etc.) if it is placed within a widget that will be called. Root widgets + * are always called. So it is possible to have whole chains of widgets that + * are simply not called. You can preconstruct widget trees and then place + * them into root widgets later to activate them if you wish. + * + */ +WIDGET_API XPWidgetID XPCreateWidget(int inLeft, + int inTop, + int inRight, + int inBottom, + int inVisible, + const char *inDescriptor, + int inIsRoot, + XPWidgetID inContainer, + XPWidgetClass inClass); + +/* + * XPCreateCustomWidget + * + * This function is the same as XPCreateWidget except that instead of passing + * a class ID, you pass your widget callback function pointer defining the + * widget. Use this function to define a custom widget. All parameters are + * the same as XPCreateWidget, except that the widget class has been replaced + * with the widget function. + * + */ +WIDGET_API XPWidgetID XPCreateCustomWidget(int inLeft, + int inTop, + int inRight, + int inBottom, + int inVisible, + const char *inDescriptor, + int inIsRoot, + XPWidgetID inContainer, + XPWidgetFunc_t inCallback); + +/* + * XPDestroyWidget + * + * This class destroys a widget. Pass in the ID of the widget to kill. If + * you pass 1 for inDestroyChilren, the widget's children will be destroyed + * first, then this widget will be destroyed. (Furthermore, the widget's + * children will be destroyed with the inDestroyChildren flag set to 1, so the + * destruction will recurse down the widget tree.) If you pass 0 for this + * flag, the child widgets will simply end up with their parent set to 0. + * + */ +WIDGET_API void XPDestroyWidget(XPWidgetID inWidget, int inDestroyChildren); + +/* + * XPSendMessageToWidget + * + * This sends any message to a widget. You should probably not go around + * simulating the predefined messages that the widgets library defines for + * you. You may however define custom messages for your widgets and send them + * with this method. + * + * This method supports several dispatching patterns; see XPDispatchMode for + * more info. The function returns 1 if the message was handled, 0 if it was + * not. + * + * For each widget that receives the message (see the dispatching modes), each + * widget function from the most recently installed to the oldest one + * receives the message in order until it is handled. + * + */ +WIDGET_API int XPSendMessageToWidget(XPWidgetID inWidget, + XPWidgetMessage inMessage, + XPDispatchMode inMode, + intptr_t inParam1, + intptr_t inParam2); + +/*************************************************************************** + * WIDGET POSITIONING AND VISIBILITY + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPPlaceWidgetWithin + * + * This function changes which container a widget resides in. You may NOT use + * this function on a root widget! inSubWidget is the widget that will be + * moved. Pass a widget ID in inContainer to make inSubWidget be a child of + * inContainer. It will become the last/closest widget in the container. + * Pass 0 to remove the widget from any container. Any call to this other + * than passing the widget ID of the old parent of the affected widget will + * cause the widget to be removed from its old parent. Placing a widget within + * its own parent simply makes it the last widget. + * + * NOTE: this routine does not reposition the sub widget in global + * coordinates. If the container has layout management code, it will + * reposition the subwidget for you, otherwise you must do it with + * SetWidgetGeometry. + * + */ +WIDGET_API void XPPlaceWidgetWithin(XPWidgetID inSubWidget, + XPWidgetID inContainer); + +/* + * XPCountChildWidgets + * + * This routine returns the number of widgets another widget contains. + * + */ +WIDGET_API int XPCountChildWidgets(XPWidgetID inWidget); + +/* + * XPGetNthChildWidget + * + * This routine returns the widget ID of a child widget by index. Indexes are + * 0 based, from 0 to one minus the number of widgets in the parent, + * inclusive. If the index is invalid, 0 is returned. + * + */ +WIDGET_API XPWidgetID XPGetNthChildWidget(XPWidgetID inWidget, int inIndex); + +/* + * XPGetParentWidget + * + * This routine returns the parent of a widget, or 0 if the widget has no + * parent. Root widgets never have parents and therefore always return 0. + * + */ +WIDGET_API XPWidgetID XPGetParentWidget(XPWidgetID inWidget); + +/* + * XPShowWidget + * + * This routine makes a widget visible if it is not already. Note that if a + * widget is not in a rooted widget hierarchy or one of its parents is not + * visible, it will still not be visible to the user. + * + */ +WIDGET_API void XPShowWidget(XPWidgetID inWidget); + +/* + * XPHideWidget + * + * Makes a widget invisible. See XPShowWidget for considerations of when a + * widget might not be visible despite its own visibility state. + * + */ +WIDGET_API void XPHideWidget(XPWidgetID inWidget); + +/* + * XPIsWidgetVisible + * + * This returns 1 if a widget is visible, 0 if it is not. Note that this + * routine takes into consideration whether a parent is invisible. Use this + * routine to tell if the user can see the widget. + * + */ +WIDGET_API int XPIsWidgetVisible(XPWidgetID inWidget); + +/* + * XPFindRootWidget + * + * XPFindRootWidget returns the Widget ID of the root widget that contains the + * passed in widget or NULL if the passed in widget is not in a rooted + * hierarchy. + * + */ +WIDGET_API XPWidgetID XPFindRootWidget(XPWidgetID inWidget); + +/* + * XPBringRootWidgetToFront + * + * This routine makes the specified widget be in the front most widget + * hierarchy. If this widget is a root widget, its widget hierarchy comes to + * front, otherwise the widget's root is brought to the front. If this widget + * is not in an active widget hiearchy (e.g. there is no root widget at the + * top of the tree), this routine does nothing. + * + */ +WIDGET_API void XPBringRootWidgetToFront(XPWidgetID inWidget); + +/* + * XPIsWidgetInFront + * + * This routine returns true if this widget's hierarchy is the front most + * hierarchy. It returns false if the widget's hierarchy is not in front, or + * if the widget is not in a rooted hierarchy. + * + */ +WIDGET_API int XPIsWidgetInFront(XPWidgetID inWidget); + +/* + * XPGetWidgetGeometry + * + * This routine returns the bounding box of a widget in global coordinates. + * Pass NULL for any parameter you are not interested in. + * + */ +WIDGET_API void XPGetWidgetGeometry(XPWidgetID inWidget, + int *outLeft, /* Can be NULL */ + int *outTop, /* Can be NULL */ + int *outRight, /* Can be NULL */ + int *outBottom); /* Can be NULL */ + +/* + * XPSetWidgetGeometry + * + * This function changes the bounding box of a widget. + * + */ +WIDGET_API void XPSetWidgetGeometry(XPWidgetID inWidget, + int inLeft, + int inTop, + int inRight, + int inBottom); + +/* + * XPGetWidgetForLocation + * + * Given a widget and a location, this routine returns the widget ID of the + * child of that widget that owns that location. If inRecursive is true then + * this will return a child of a child of a widget as it tries to find the + * deepest widget at that location. If inVisibleOnly is true, then only + * visible widgets are considered, otherwise all widgets are considered. The + * widget ID passed for inContainer will be returned if the location is in + * that widget but not in a child widget. 0 is returned if the location is + * not in the container. + * + * NOTE: if a widget's geometry extends outside its parents geometry, it will + * not be returned by this call for mouse locations outside the parent + * geometry. The parent geometry limits the child's eligibility for mouse + * location. + * + */ +WIDGET_API XPWidgetID XPGetWidgetForLocation(XPWidgetID inContainer, + int inXOffset, + int inYOffset, + int inRecursive, + int inVisibleOnly); + +/* + * XPGetWidgetExposedGeometry + * + * This routine returns the bounds of the area of a widget that is completely + * within its parent widgets. Since a widget's bounding box can be outside + * its parent, part of its area will not be elligible for mouse clicks and + * should not draw. Use XPGetWidgetGeometry to find out what area defines + * your widget's shape, but use this routine to find out what area to actually + * draw into. Note that the widget library does not use OpenGL clipping to + * keep frame rates up, although you could use it internally. + * + */ +WIDGET_API void XPGetWidgetExposedGeometry(XPWidgetID inWidgetID, + int *outLeft, /* Can be NULL */ + int *outTop, /* Can be NULL */ + int *outRight, /* Can be NULL */ + int *outBottom); /* Can be NULL */ + +/*************************************************************************** + * ACCESSING WIDGET DATA + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPSetWidgetDescriptor + * + * Every widget has a descriptor, which is a text string. What the text + * string is used for varies from widget to widget; for example, a push + * button's text is its descriptor, a caption shows its descriptor, and a text + * field's descriptor is the text being edited. In other words, the usage for + * the text varies from widget to widget, but this API provides a universal + * and convenient way to get at it. While not all UI widgets need their + * descriptor, many do. + * + */ +WIDGET_API void XPSetWidgetDescriptor(XPWidgetID inWidget, + const char *inDescriptor); + +/* + * XPGetWidgetDescriptor + * + * This routine returns the widget's descriptor. Pass in the length of the + * buffer you are going to receive the descriptor in. The descriptor will be + * null terminated for you. This routine returns the length of the actual + * descriptor; if you pass NULL for outDescriptor, you can get the + * descriptor's length without getting its text. If the length of the + * descriptor exceeds your buffer length, the buffer will not be null + * terminated (this routine has 'strncpy' semantics). + * + */ +WIDGET_API int XPGetWidgetDescriptor(XPWidgetID inWidget, + char *outDescriptor, + int inMaxDescLength); + +/* + * XPSetWidgetProperty + * + * This function sets a widget's property. Properties are arbitrary values + * associated by a widget by ID. + * + */ +WIDGET_API void XPSetWidgetProperty(XPWidgetID inWidget, + XPWidgetPropertyID inProperty, + intptr_t inValue); + +/* + * XPGetWidgetProperty + * + * This routine returns the value of a widget's property, or 0 if the property + * is not defined. If you need to know whether the property is defined, pass + * a pointer to an int for inExists; the existence of that property will be + * returned in the int. Pass NULL for inExists if you do not need this + * information. + * + */ +WIDGET_API intptr_t XPGetWidgetProperty(XPWidgetID inWidget, + XPWidgetPropertyID inProperty, + int *inExists); /* Can be NULL */ + +/*************************************************************************** + * KEYBOARD MANAGEMENT + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPSetKeyboardFocus + * + * XPSetKeyboardFocus controls which widget will receive keystrokes. Pass the + * Widget ID of the widget to get the keys. Note that if the widget does not + * care about keystrokes, they will go to the parent widget, and if no widget + * cares about them, they go to X-Plane. + * + * If you set the keyboard focus to Widget ID 0, X-Plane gets keyboard focus. + * + * This routine returns the widget ID that ended up with keyboard focus, or 0 + * for x-plane. + * + * Keyboard focus is not changed if the new widget will not accept it. For + * setting to x-plane, keyboard focus is always accepted. + * + * * + */ +WIDGET_API XPWidgetID XPSetKeyboardFocus(XPWidgetID inWidget); + +/* + * XPLoseKeyboardFocus + * + * This causes the specified widget to lose focus; focus is passed to its + * parent, or the next parent that will accept it. This routine does nothing + * if this widget does not have focus. + * + */ +WIDGET_API void XPLoseKeyboardFocus(XPWidgetID inWidget); + +/* + * XPGetWidgetWithFocus + * + * This routine returns the widget that has keyboard focus, or 0 if X-Plane + * has keyboard focus or some other plugin window that does not have widgets + * has focus. + * + */ +WIDGET_API XPWidgetID XPGetWidgetWithFocus(void); + +/*************************************************************************** + * CREATING CUSTOM WIDGETS + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPAddWidgetCallback + * + * This function adds a new widget callback to a widget. This widget callback + * supercedes any existing ones and will receive messages first; if it does + * not handle messages they will go on to be handled by pre-existing widgets. + * + * The widget function will remain on the widget for the life of the widget. + * The creation message will be sent to the new callback immediately with the + * widget ID, and the destruction message will be sent before the other widget + * function receives a destruction message. + * + * This provides a way to 'subclass' an existing widget. By providing a + * second hook that only handles certain widget messages, you can customize or + * extend widget behavior. + * + */ +WIDGET_API void XPAddWidgetCallback(XPWidgetID inWidget, + XPWidgetFunc_t inNewCallback); + +/* + * XPGetWidgetClassFunc + * + * Given a widget class, this function returns the callbacks that power that + * widget class. + * + */ +WIDGET_API XPWidgetFunc_t XPGetWidgetClassFunc(XPWidgetClass inWidgetClass); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCBroadcaster.cpp b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCBroadcaster.cpp new file mode 100644 index 0000000..97c14b9 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCBroadcaster.cpp @@ -0,0 +1,45 @@ +#include "XPCBroadcaster.h" +#include "XPCListener.h" + +XPCBroadcaster::XPCBroadcaster() : mIterator(NULL) {} + +XPCBroadcaster::~XPCBroadcaster() +{ + ListenerVector::iterator iter; + mIterator = &iter; + for (iter = mListeners.begin(); iter != mListeners.end(); ++iter) { + (*iter)->BroadcasterRemoved(this); + } +} + +void XPCBroadcaster::AddListener(XPCListener *inListener) +{ + mListeners.push_back(inListener); + inListener->BroadcasterAdded(this); +} + +void XPCBroadcaster::RemoveListener(XPCListener *inListener) +{ + ListenerVector::iterator iter = + std::find(mListeners.begin(), mListeners.end(), inListener); + if (iter == mListeners.end()) + return; + + if (mIterator != NULL) { + if (*mIterator >= iter) + (*mIterator)--; + } + + mListeners.erase(iter); + inListener->BroadcasterRemoved(this); +} + +void XPCBroadcaster::BroadcastMessage(int inMessage, void *inParam) +{ + ListenerVector::iterator iter; + mIterator = &iter; + for (iter = mListeners.begin(); iter != mListeners.end(); ++iter) { + (*iter)->ListenToMessage(inMessage, inParam); + } + mIterator = NULL; +} diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCBroadcaster.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCBroadcaster.h new file mode 100644 index 0000000..ae4f76f --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCBroadcaster.h @@ -0,0 +1,31 @@ +#ifndef _XPCBroadcaster_h_ +#define _XPCBroadcaster_h_ + +#include +#include + +class XPCListener; + +class XPCBroadcaster +{ +public: + XPCBroadcaster(); + virtual ~XPCBroadcaster(); + + void AddListener(XPCListener *inListener); + void RemoveListener(XPCListener *inListener); + +protected: + void BroadcastMessage(int inMessage, void *inParam = 0); + +private: + typedef std::vector ListenerVector; + + ListenerVector mListeners; + + // Reentrancy support + + ListenerVector::iterator *mIterator; +}; + +#endif \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCDisplay.cpp b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCDisplay.cpp new file mode 100644 index 0000000..ce39eb5 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCDisplay.cpp @@ -0,0 +1,107 @@ +#include "XPCDisplay.h" + +XPCKeySniffer::XPCKeySniffer(int inBeforeWindows) + : mBeforeWindows(inBeforeWindows) +{ + XPLMRegisterKeySniffer(KeySnifferCB, + mBeforeWindows, + reinterpret_cast(this)); +} + +XPCKeySniffer::~XPCKeySniffer() +{ + XPLMUnregisterKeySniffer(KeySnifferCB, + mBeforeWindows, + reinterpret_cast(this)); +} + + +int XPCKeySniffer::KeySnifferCB(char inCharKey, + XPLMKeyFlags inFlags, + char inVirtualKey, + void *inRefCon) +{ + XPCKeySniffer *me = reinterpret_cast(inRefCon); + return me->HandleKeyStroke(inCharKey, inFlags, inVirtualKey); +} + +XPCWindow::XPCWindow(int inLeft, + int inTop, + int inRight, + int inBottom, + int inIsVisible) +{ + mWindow = XPLMCreateWindow(inLeft, + inTop, + inRight, + inBottom, + inIsVisible, + DrawCB, + HandleKeyCB, + MouseClickCB, + reinterpret_cast(this)); +} + +XPCWindow::~XPCWindow() { XPLMDestroyWindow(mWindow); } + +void XPCWindow::GetWindowGeometry(int *outLeft, + int *outTop, + int *outRight, + int *outBottom) +{ + XPLMGetWindowGeometry(mWindow, outLeft, outTop, outRight, outBottom); +} + +void XPCWindow::SetWindowGeometry(int inLeft, + int inTop, + int inRight, + int inBottom) +{ + XPLMSetWindowGeometry(mWindow, inLeft, inTop, inRight, inBottom); +} + +int XPCWindow::GetWindowIsVisible(void) +{ + return XPLMGetWindowIsVisible(mWindow); +} + +void XPCWindow::SetWindowIsVisible(int inIsVisible) +{ + XPLMSetWindowIsVisible(mWindow, inIsVisible); +} + +void XPCWindow::TakeKeyboardFocus(void) { XPLMTakeKeyboardFocus(mWindow); } + +void XPCWindow::BringWindowToFront(void) { XPLMBringWindowToFront(mWindow); } + +int XPCWindow::IsWindowInFront(void) { return XPLMIsWindowInFront(mWindow); } + +void XPCWindow::DrawCB(XPLMWindowID inWindowID, void *inRefcon) +{ + XPCWindow *me = reinterpret_cast(inRefcon); + me->DoDraw(); +} + +void XPCWindow::HandleKeyCB(XPLMWindowID inWindowID, + char inKey, + XPLMKeyFlags inFlags, + char inVirtualKey, + void *inRefcon, + int losingFocus) +{ + XPCWindow *me = reinterpret_cast(inRefcon); + if (losingFocus) + me->LoseFocus(); + else + me->HandleKey(inKey, inFlags, inVirtualKey); +} + +int XPCWindow::MouseClickCB(XPLMWindowID inWindowID, + int x, + int y, + XPLMMouseStatus inMouse, + void *inRefcon) +{ + XPCWindow *me = reinterpret_cast(inRefcon); + return me->HandleClick(x, y, inMouse); +} diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCDisplay.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCDisplay.h new file mode 100644 index 0000000..13d1dc1 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCDisplay.h @@ -0,0 +1,70 @@ +#ifndef _XPCDisplay_h_ +#define _XPCDisplay_h_ + +#include "XPLMDisplay.h" + +class XPCKeySniffer +{ +public: + XPCKeySniffer(int inBeforeWindows); + virtual ~XPCKeySniffer(); + + virtual int HandleKeyStroke(char inCharKey, + XPLMKeyFlags inFlags, + char inVirtualKey) = 0; + +private: + int mBeforeWindows; + + static int KeySnifferCB(char inCharKey, + XPLMKeyFlags inFlags, + char inVirtualKey, + void *inRefCon); +}; + + +class XPCWindow +{ +public: + XPCWindow(int inLeft, + int inTop, + int inRight, + int inBottom, + int inIsVisible); + virtual ~XPCWindow(); + + virtual void DoDraw(void) = 0; + virtual void + HandleKey(char inKey, XPLMKeyFlags inFlags, char inVirtualKey) = 0; + virtual void LoseFocus(void) = 0; + virtual int HandleClick(int x, int y, XPLMMouseStatus inMouse) = 0; + + void GetWindowGeometry(int *outLeft, + int *outTop, + int *outRight, + int *outBottom); + void SetWindowGeometry(int inLeft, int inTop, int inRight, int inBottom); + int GetWindowIsVisible(void); + void SetWindowIsVisible(int inIsVisible); + void TakeKeyboardFocus(void); + void BringWindowToFront(void); + int IsWindowInFront(void); + +private: + XPLMWindowID mWindow; + + static void DrawCB(XPLMWindowID inWindowID, void *inRefcon); + static void HandleKeyCB(XPLMWindowID inWindowID, + char inKey, + XPLMKeyFlags inFlags, + char inVirtualKey, + void *inRefcon, + int losingFocus); + static int MouseClickCB(XPLMWindowID inWindowID, + int x, + int y, + XPLMMouseStatus inMouse, + void *inRefcon); +}; + +#endif \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCListener.cpp b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCListener.cpp new file mode 100644 index 0000000..467b391 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCListener.cpp @@ -0,0 +1,23 @@ +#include "XPCListener.h" +#include "XPCBroadcaster.h" + +XPCListener::XPCListener() {} + +XPCListener::~XPCListener() +{ + while (!mBroadcasters.empty()) + mBroadcasters.front()->RemoveListener(this); +} + +void XPCListener::BroadcasterAdded(XPCBroadcaster *inBroadcaster) +{ + mBroadcasters.push_back(inBroadcaster); +} + +void XPCListener::BroadcasterRemoved(XPCBroadcaster *inBroadcaster) +{ + BroadcastVector::iterator iter = + std::find(mBroadcasters.begin(), mBroadcasters.end(), inBroadcaster); + if (iter != mBroadcasters.end()) + mBroadcasters.erase(iter); +} diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCListener.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCListener.h new file mode 100644 index 0000000..bc20826 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCListener.h @@ -0,0 +1,30 @@ +#ifndef _XPCListener_h_ +#define _XPCListener_h_ + +#include +#include + +class XPCBroadcaster; + + +class XPCListener +{ +public: + XPCListener(); + virtual ~XPCListener(); + + virtual void ListenToMessage(int inMessage, void *inParam) = 0; + +private: + typedef std::vector BroadcastVector; + + BroadcastVector mBroadcasters; + + friend class XPCBroadcaster; + + void BroadcasterAdded(XPCBroadcaster *inBroadcaster); + + void BroadcasterRemoved(XPCBroadcaster *inBroadcaster); +}; + +#endif \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCProcessing.cpp b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCProcessing.cpp new file mode 100644 index 0000000..5e9552e --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCProcessing.cpp @@ -0,0 +1,60 @@ +#include "XPCProcessing.h" +#include "XPLMUtilities.h" + +XPCProcess::XPCProcess() : mInCallback(false), mCallbackTime(0) +{ + XPLMRegisterFlightLoopCallback(FlightLoopCB, + 0, + reinterpret_cast(this)); +} + +XPCProcess::~XPCProcess() +{ + XPLMUnregisterFlightLoopCallback(FlightLoopCB, + reinterpret_cast(this)); +} + +void XPCProcess::StartProcessTime(float inSeconds) +{ + mCallbackTime = inSeconds; + if (!mInCallback) + XPLMSetFlightLoopCallbackInterval(FlightLoopCB, + mCallbackTime, + 1 /*relative to now*/, + reinterpret_cast(this)); +} + +void XPCProcess::StartProcessCycles(int inCycles) +{ + mCallbackTime = -inCycles; + if (!mInCallback) + XPLMSetFlightLoopCallbackInterval(FlightLoopCB, + mCallbackTime, + 1 /*relative to now*/, + reinterpret_cast(this)); +} + +void XPCProcess::StopProcess(void) +{ + mCallbackTime = 0; + if (!mInCallback) + XPLMSetFlightLoopCallbackInterval(FlightLoopCB, + mCallbackTime, + 1 /*relative to now*/, + reinterpret_cast(this)); +} + + +float XPCProcess::FlightLoopCB(float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter, + void *inRefcon) +{ + XPCProcess *me = reinterpret_cast(inRefcon); + me->mInCallback = true; + me->DoProcessing(inElapsedSinceLastCall, + inElapsedTimeSinceLastFlightLoop, + inCounter); + me->mInCallback = false; + return me->mCallbackTime; +} \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCProcessing.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCProcessing.h new file mode 100644 index 0000000..e963d49 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCProcessing.h @@ -0,0 +1,33 @@ +#ifndef _XPCProcessing_h_ +#define _XPCProcessing_h_ + +#include "XPLMProcessing.h" + +class XPCProcess +{ +public: + XPCProcess(); + virtual ~XPCProcess(); + + void StartProcessTime(float inSeconds); + void StartProcessCycles(int inCycles); + void StopProcess(void); + + virtual void DoProcessing(float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter) = 0; + +private: + static float FlightLoopCB(float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter, + void *inRefcon); + + bool mInCallback; + float mCallbackTime; + + XPCProcess(const XPCProcess &); + XPCProcess &operator=(const XPCProcess &); +}; + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidget.cpp b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidget.cpp new file mode 100644 index 0000000..be1e6a8 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidget.cpp @@ -0,0 +1,111 @@ +#include "XPCWidget.h" + +XPCWidget::XPCWidget(int inLeft, + int inTop, + int inRight, + int inBottom, + bool inVisible, + const char *inDescriptor, + bool inIsRoot, + XPWidgetID inParent, + XPWidgetClass inClass) + : mWidget(NULL), mOwnsChildren(false), mOwnsWidget(true) +{ + mWidget = XPCreateWidget(inLeft, + inTop, + inRight, + inBottom, + inVisible ? 1 : 0, + inDescriptor, + inIsRoot ? 1 : 0, + inIsRoot ? NULL : inParent, + inClass); + + XPSetWidgetProperty(mWidget, + xpProperty_Object, + reinterpret_cast(this)); + XPAddWidgetCallback(mWidget, WidgetCallback); +} + +XPCWidget::XPCWidget(XPWidgetID inWidget, bool inOwnsWidget) + : mWidget(inWidget), mOwnsChildren(false), mOwnsWidget(inOwnsWidget) +{ + XPSetWidgetProperty(mWidget, + xpProperty_Object, + reinterpret_cast(this)); + XPAddWidgetCallback(mWidget, WidgetCallback); +} + +XPCWidget::~XPCWidget() +{ + if (mOwnsWidget) + XPDestroyWidget(mWidget, mOwnsChildren ? 1 : 0); +} + +void XPCWidget::SetOwnsWidget(bool inOwnsWidget) { mOwnsWidget = inOwnsWidget; } + +void XPCWidget::SetOwnsChildren(bool inOwnsChildren) +{ + mOwnsChildren = inOwnsChildren; +} + +XPCWidget::operator XPWidgetID() const { return mWidget; } + +XPWidgetID XPCWidget::Get(void) const { return mWidget; } + +void XPCWidget::AddAttachment(XPCWidgetAttachment *inAttachment, + bool inOwnsAttachment, + bool inPrefilter) +{ + if (inPrefilter) { + mAttachments.insert(mAttachments.begin(), + AttachmentInfo(inAttachment, inOwnsAttachment)); + } else { + mAttachments.push_back(AttachmentInfo(inAttachment, inOwnsAttachment)); + } +} + +void XPCWidget::RemoveAttachment(XPCWidgetAttachment *inAttachment) +{ + for (AttachmentVector::iterator iter = mAttachments.begin(); + iter != mAttachments.end(); + ++iter) { + if (iter->first == inAttachment) { + mAttachments.erase(iter); + return; + } + } +} + +int XPCWidget::HandleWidgetMessage(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + return 0; +} + +int XPCWidget::WidgetCallback(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + XPCWidget *me = reinterpret_cast( + XPGetWidgetProperty(inWidget, xpProperty_Object, NULL)); + if (me == NULL) + return 0; + + for (AttachmentVector::iterator iter = me->mAttachments.begin(); + iter != me->mAttachments.end(); + ++iter) { + int result = iter->first->HandleWidgetMessage(me, + inMessage, + inWidget, + inParam1, + inParam2); + if (result != 0) + return result; + } + + return me->HandleWidgetMessage(inMessage, inWidget, inParam1, inParam2); +} diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidget.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidget.h new file mode 100644 index 0000000..584a5ee --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidget.h @@ -0,0 +1,71 @@ +#ifndef _XPCWidget_h_ +#define _XPCWidget_h_ + +#include "XPWidgets.h" +#include +#include + +class XPCWidget; + +class XPCWidgetAttachment +{ +public: + virtual int HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) = 0; +}; + +class XPCWidget +{ +public: + XPCWidget(int inLeft, + int inTop, + int inRight, + int inBottom, + bool inVisible, + const char *inDescriptor, + bool inIsRoot, + XPWidgetID inParent, + XPWidgetClass inClass); + XPCWidget(XPWidgetID inWidget, bool inOwnsWidget); + virtual ~XPCWidget(); + + void SetOwnsWidget(bool inOwnsWidget); + void SetOwnsChildren(bool inOwnsChildren); + + operator XPWidgetID() const; + + XPWidgetID Get(void) const; + + void AddAttachment(XPCWidgetAttachment *inAttachment, + bool inOwnsAttachment, + bool inPrefilter); + void RemoveAttachment(XPCWidgetAttachment *inAttachment); + + virtual int HandleWidgetMessage(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + +private: + static int WidgetCallback(XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + + typedef std::pair AttachmentInfo; + typedef std::vector AttachmentVector; + + AttachmentVector mAttachments; + XPWidgetID mWidget; + bool mOwnsChildren; + bool mOwnsWidget; + + XPCWidget(); + XPCWidget(const XPCWidget &); + XPCWidget &operator=(const XPCWidget &); +}; + +#endif \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp new file mode 100644 index 0000000..9d3a03d --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.cpp @@ -0,0 +1,235 @@ +#include "XPCWidgetAttachments.h" +#include "XPStandardWidgets.h" +#include "XPWidgetUtils.h" + +static void XPCGetOrderedSubWidgets(XPWidgetID inWidget, + std::vector &outChildren); + +XPCKeyFilterAttachment::XPCKeyFilterAttachment(const char *inValidKeys, + const char *outValidKeys) + : mInput(inValidKeys), mOutput(outValidKeys) +{ +} + +XPCKeyFilterAttachment::~XPCKeyFilterAttachment() {} + +int XPCKeyFilterAttachment::HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if (inMessage == xpMsg_KeyPress) { + char &theKey = KEY_CHAR(inParam1); + std::string::size_type pos = mInput.find(theKey); + if (pos == std::string::npos) + return 1; // Not found; eat the key! + else { + theKey = mOutput[pos]; + return 0; + } // Let it live. + } + return 0; +} + + +XPCKeyMessageAttachment::XPCKeyMessageAttachment(char inKey, + int inMessage, + void *inParam, + bool inConsume, + bool inVkey, + XPCListener *inListener) + : mKey(inKey), mMsg(inMessage), mParam(inParam), mConsume(inConsume), + mVkey(inVkey) +{ + if (inListener != NULL) + this->AddListener(inListener); +} + +XPCKeyMessageAttachment::~XPCKeyMessageAttachment() {} + +int XPCKeyMessageAttachment::HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if (inMessage == xpMsg_KeyPress) { + char theKey = mVkey ? KEY_VKEY(inParam1) : KEY_CHAR(inParam1); + if (theKey != mKey) + return 0; + if (!(KEY_FLAGS(inParam1) & xplm_DownFlag)) + return 0; + + BroadcastMessage(mMsg, mParam); + return mConsume ? 1 : 0; + } + return 0; +} + +XPCPushButtonMessageAttachment::XPCPushButtonMessageAttachment( + XPWidgetID inWidget, + int inMessage, + void *inParam, + XPCListener *inListener) + : mMsg(inMessage), mParam(inParam), mWidget(inWidget) +{ + if (inListener != NULL) + this->AddListener(inListener); +} + +XPCPushButtonMessageAttachment::~XPCPushButtonMessageAttachment() {} + +int XPCPushButtonMessageAttachment::HandleWidgetMessage( + XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if ((inMessage == xpMsg_PushButtonPressed) && + ((XPWidgetID)inParam1 == mWidget)) { + BroadcastMessage(mMsg, mParam); + return 1; + } + + if ((inMessage == xpMsg_ButtonStateChanged) && + ((XPWidgetID)inParam1 == mWidget)) { + BroadcastMessage(mMsg, mParam); + return 1; + } + return 0; +} + +XPCSliderMessageAttachment::XPCSliderMessageAttachment(XPWidgetID inWidget, + int inMessage, + void *inParam, + XPCListener *inListener) + : mMsg(inMessage), mParam(inParam), mWidget(inWidget) +{ + if (inListener != NULL) + this->AddListener(inListener); +} + +XPCSliderMessageAttachment::~XPCSliderMessageAttachment() {} + +int XPCSliderMessageAttachment::HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if ((inMessage == xpMsg_ScrollBarSliderPositionChanged) && + ((XPWidgetID)inParam1 == mWidget)) { + BroadcastMessage(mMsg, mParam); + return 1; + } + + return 0; +} + + +XPCCloseButtonMessageAttachment::XPCCloseButtonMessageAttachment( + XPWidgetID inWidget, + int inMessage, + void *inParam, + XPCListener *inListener) + : mMsg(inMessage), mParam(inParam), mWidget(inWidget) +{ + if (inListener != NULL) + this->AddListener(inListener); +} + +XPCCloseButtonMessageAttachment::~XPCCloseButtonMessageAttachment() {} + +int XPCCloseButtonMessageAttachment::HandleWidgetMessage( + XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if ((inMessage == xpMessage_CloseButtonPushed) && + ((XPWidgetID)inParam1 == mWidget)) { + BroadcastMessage(mMsg, mParam); + return 1; + } + + return 0; +} + +XPCTabGroupAttachment::XPCTabGroupAttachment() {} + +XPCTabGroupAttachment::~XPCTabGroupAttachment() {} + +int XPCTabGroupAttachment::HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2) +{ + if ((inMessage == xpMsg_KeyPress) && (KEY_CHAR(inParam1) == XPLM_KEY_TAB) && + ((KEY_FLAGS(inParam1) & xplm_UpFlag) == 0)) { + bool backwards = (KEY_FLAGS(inParam1) & xplm_ShiftFlag) != 0; + std::vector widgets; + XPCGetOrderedSubWidgets(inWidget, widgets); + int n, index = 0; + XPWidgetID focusWidget = XPGetWidgetWithFocus(); + std::vector::iterator iter = + std::find(widgets.begin(), widgets.end(), focusWidget); + if (iter != widgets.end()) { + index = std::distance(widgets.begin(), iter); + if (backwards) + index--; + else + index++; + if (index < 0) + index = widgets.size() - 1; + if (index >= widgets.size()) + index = 0; + } + + if (backwards) { + for (n = index; n >= 0; --n) { + if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) + if (XPSetKeyboardFocus(widgets[n]) != NULL) + return 1; + } + for (n = widgets.size() - 1; n > index; --n) { + if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) + if (XPSetKeyboardFocus(widgets[n]) != NULL) + return 1; + } + } else { + for (n = index; n < widgets.size(); ++n) { + if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) + if (XPSetKeyboardFocus(widgets[n]) != NULL) + return 1; + } + for (n = 0; n < index; ++n) { + if (XPGetWidgetProperty(widgets[n], xpProperty_Enabled, NULL)) + if (XPSetKeyboardFocus(widgets[n]) != NULL) + return 1; + } + } + } + return 0; +} + + +static void XPCGetOrderedSubWidgets(XPWidgetID inWidget, + std::vector &outChildren) +{ + outChildren.clear(); + int count = XPCountChildWidgets(inWidget); + for (int n = 0; n < count; ++n) { + XPWidgetID child = XPGetNthChildWidget(inWidget, n); + outChildren.push_back(child); + std::vector grandChildren; + XPCGetOrderedSubWidgets(child, grandChildren); + + outChildren.insert(outChildren.end(), + grandChildren.begin(), + grandChildren.end()); + } +} diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.h new file mode 100644 index 0000000..086d6ea --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/Wrappers/XPCWidgetAttachments.h @@ -0,0 +1,132 @@ +#ifndef _XPCWidgetAttachments_h_ +#define _XPCWidgetAttachments_h_ + +#include + +#include "XPCBroadcaster.h" +#include "XPCWidget.h" + +class XPCKeyFilterAttachment : public XPCWidgetAttachment +{ +public: + XPCKeyFilterAttachment(const char *inValidKeys, const char *outValidKeys); + virtual ~XPCKeyFilterAttachment(); + + virtual int HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + +private: + std::string mInput; + std::string mOutput; +}; + + +class XPCKeyMessageAttachment : public XPCWidgetAttachment, + public XPCBroadcaster +{ +public: + XPCKeyMessageAttachment(char inKey, + int inMessage, + void *inParam, + bool inConsume, + bool inVkey, + XPCListener *inListener); + virtual ~XPCKeyMessageAttachment(); + + virtual int HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + +private: + char mKey; + bool mVkey; + int mMsg; + void *mParam; + bool mConsume; +}; + +class XPCPushButtonMessageAttachment : public XPCWidgetAttachment, + XPCBroadcaster +{ +public: + XPCPushButtonMessageAttachment(XPWidgetID inWidget, + int inMessage, + void *inParam, + XPCListener *inListener); + virtual ~XPCPushButtonMessageAttachment(); + + virtual int HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + +private: + XPWidgetID mWidget; + int mMsg; + void *mParam; +}; + +class XPCSliderMessageAttachment : public XPCWidgetAttachment, XPCBroadcaster +{ +public: + XPCSliderMessageAttachment(XPWidgetID inWidget, + int inMessage, + void *inParam, + XPCListener *inListener); + virtual ~XPCSliderMessageAttachment(); + + virtual int HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + +private: + XPWidgetID mWidget; + int mMsg; + void *mParam; +}; + + +class XPCCloseButtonMessageAttachment : public XPCWidgetAttachment, + XPCBroadcaster +{ +public: + XPCCloseButtonMessageAttachment(XPWidgetID inWidget, + int inMessage, + void *inParam, + XPCListener *inListener); + virtual ~XPCCloseButtonMessageAttachment(); + + virtual int HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); + +private: + XPWidgetID mWidget; + int mMsg; + void *mParam; +}; + +class XPCTabGroupAttachment : public XPCWidgetAttachment +{ +public: + XPCTabGroupAttachment(); + virtual ~XPCTabGroupAttachment(); + + virtual int HandleWidgetMessage(XPCWidget *inObject, + XPWidgetMessage inMessage, + XPWidgetID inWidget, + intptr_t inParam1, + intptr_t inParam2); +}; + +#endif \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMCamera.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMCamera.h new file mode 100644 index 0000000..f493525 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMCamera.h @@ -0,0 +1,167 @@ +#ifndef _XPLMCamera_h_ +#define _XPLMCamera_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * XPLMCamera - THEORY OF OPERATION The XPLMCamera APIs allow plug-ins to + * control the camera angle in X-Plane. This has a number of applications, + * including but not limited to: + * + * - Creating new views (including dynamic/user-controllable views) for the + * user. + * + * - Creating applications that use X-Plane as a renderer of scenery, + * aircrafts, or both. + * + * The camera is controlled via six parameters: a location in OpenGL + * coordinates and pitch, roll and yaw, similar to an airplane's position. + * OpenGL coordinate info is described in detail in the XPLMGraphics + * documentation; generally you should use the XPLMGraphics routines to + * convert from world to local coordinates. The camera's orientation starts + * facing level with the ground directly up the negative-Z axis + * (approximately north) with the horizon horizontal. It is then rotated + * clockwise for yaw, pitched up for positive pitch, and rolled clockwise + * around the vector it is looking along for roll. + * + * You control the camera either either until the user selects a new view or + * permanently (the later being similar to how UDP camera control works). You + * control the camera by registering a callback per frame from which you + * calculate the new camera positions. This guarantees smooth camera motion. + * + * Use the XPLMDataAccess APIs to get information like the position of the + * aircraft, etc. for complex camera positioning. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * CAMERA CONTROL + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPLMCameraControlDuration + * + * This enumeration states how long you want to retain control of the camera. + * You can retain it indefinitely or until the user selects a new view. + * + */ +enum { + /* Control the camera until the user picks a new view. */ + xplm_ControlCameraUntilViewChanges = 1 + + /* Control the camera until your plugin is disabled or another plugin + * forcably * takes control. */ + , + xplm_ControlCameraForever = 2 + + +}; +typedef int XPLMCameraControlDuration; + +/* + * XPLMCameraPosition_t + * + * This structure contains a full specification of the camera. X, Y, and Z + * are the camera's position in OpenGL coordiantes; pitch, roll, and yaw are + * rotations from a camera facing flat north in degrees. Positive pitch means + * nose up, positive roll means roll right, and positive yaw means yaw right, + * all in degrees. Zoom is a zoom factor, with 1.0 meaning normal zoom and 2.0 + * magnifying by 2x (objects appear larger). + * + */ +typedef struct { + float x; + float y; + float z; + float pitch; + float heading; + float roll; + float zoom; +} XPLMCameraPosition_t; + +/* + * XPLMCameraControl_f + * + * You use an XPLMCameraControl function to provide continuous control over + * the camera. You are passed in a structure in which to put the new camera + * position; modify it and return 1 to reposition the camera. Return 0 to + * surrender control of the camera; camera control will be handled by X-Plane + * on this draw loop. The contents of the structure as you are called are + * undefined. + * + * If X-Plane is taking camera control away from you, this function will be + * called with inIsLosingControl set to 1 and ioCameraPosition NULL. + * + */ +typedef int (*XPLMCameraControl_f)( + XPLMCameraPosition_t *outCameraPosition, /* Can be NULL */ + int inIsLosingControl, + void *inRefcon); + +/* + * XPLMControlCamera + * + * This function repositions the camera on the next drawing cycle. You must + * pass a non-null control function. Specify in inHowLong how long you'd like + * control (indefinitely or until a key is pressed). + * + */ +XPLM_API void XPLMControlCamera(XPLMCameraControlDuration inHowLong, + XPLMCameraControl_f inControlFunc, + void *inRefcon); + +/* + * XPLMDontControlCamera + * + * This function stops you from controlling the camera. If you have a camera + * control function, it will not be called with an inIsLosingControl flag. + * X-Plane will control the camera on the next cycle. + * + * For maximum compatibility you should not use this routine unless you are in + * posession of the camera. + * + */ +XPLM_API void XPLMDontControlCamera(void); + +/* + * XPLMIsCameraBeingControlled + * + * This routine returns 1 if the camera is being controlled, zero if it is + * not. If it is and you pass in a pointer to a camera control duration, the + * current control duration will be returned. + * + */ +XPLM_API int XPLMIsCameraBeingControlled( + XPLMCameraControlDuration *outCameraControlDuration); /* Can be NULL */ + +/* + * XPLMReadCameraPosition + * + * This function reads the current camera position. + * + */ +XPLM_API void XPLMReadCameraPosition(XPLMCameraPosition_t *outCameraPosition); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDataAccess.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDataAccess.h new file mode 100644 index 0000000..ba37559 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDataAccess.h @@ -0,0 +1,670 @@ +#ifndef _XPLMDataAccess_h_ +#define _XPLMDataAccess_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * XPLM Data Access API - Theory of Operation + * + * The data access API gives you a generic, flexible, high performance way to + * read and write data to and from X-Plane and other plug-ins. For example, + * this API allows you to read and set the nav radios, get the plane location, + * determine the current effective graphics frame rate, etc. + * + * The data access APIs are the way that you read and write data from the sim + * as well as other plugins. + * + * The API works using opaque data references. A data reference is a source + * of data; you do not know where it comes from, but once you have it you can + * read the data quickly and possibly write it. To get a data reference, you + * look it up. + * + * Data references are identified by verbose string names + * (sim/cockpit/radios/nav1_freq_hz). The actual numeric value of the data + * reference is implementation defined and is likely to change each time the + * simulator is run (or the plugin that provides the datareference is + * reloaded). + * + * The task of looking up a data reference is relatively expensive; look up + * your data references once based on verbose strings, and save the opaque + * data reference value for the duration of your plugin's operation. Reading + * and writing data references is relatively fast (the cost is equivalent to + * two function calls through function pointers). + * + * This allows data access to be high performance, while leaving in + * abstraction; since data references are opaque and are searched for, the + * underlying data access system can be rebuilt. + * + * A note on typing: you must know the correct data type to read and write. + * APIs are provided for reading and writing data in a number of ways. You + * can also double check the data type for a data ref. Note that automatic + * conversion is not done for you. + * + * A note for plugins sharing data with other plugins: the load order of + * plugins is not guaranteed. To make sure that every plugin publishing data + * has published their data references before other plugins try to subscribe, + * publish your data references in your start routine but resolve them the + * first time your 'enable' routine is called, or the first time they are + * needed in code. + * + * X-Plane publishes well over 1000 datarefs; a complete list may be found in + * the reference section of the SDK online documentation (from the SDK home + * page, choose Documentation). + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * READING AND WRITING DATA + ***************************************************************************/ +/* + * These routines allow you to access a wide variety of data from within + * x-plane and modify some of it. + * + */ + + +/* + * XPLMDataRef + * + * A data ref is an opaque handle to data provided by the simulator or another + * plugin. It uniquely identifies one variable (or array of variables) over + * the lifetime of your plugin. You never hard code these values; you always + * get them from XPLMFindDataRef. + * + */ +typedef void *XPLMDataRef; + +/* + * XPLMDataTypeID + * + * This is an enumeration that defines the type of the data behind a data + * reference. This allows you to sanity check that the data type matches what + * you expect. But for the most part, you will know the type of data you are + * expecting from the online documentation. + * + * Data types each take a bit field, so sets of data types may be formed. + * + */ +enum { + /* Data of a type the current XPLM doesn't do. */ + xplmType_Unknown = 0 + + /* A single 4-byte integer, native endian. */ + , + xplmType_Int = 1 + + /* A single 4-byte float, native endian. */ + , + xplmType_Float = 2 + + /* A single 8-byte double, native endian. */ + , + xplmType_Double = 4 + + /* An array of 4-byte floats, native endian. */ + , + xplmType_FloatArray = 8 + + /* An array of 4-byte integers, native endian. */ + , + xplmType_IntArray = 16 + + /* A variable block of data. */ + , + xplmType_Data = 32 + + +}; +typedef int XPLMDataTypeID; + +/* + * XPLMFindDataRef + * + * Given a c-style string that names the data ref, this routine looks up the + * actual opaque XPLMDataRef that you use to read and write the data. The + * string names for datarefs are published on the x-plane SDK web site. + * + * This function returns NULL if the data ref cannot be found. + * + * NOTE: this function is relatively expensive; save the XPLMDataRef this + * function returns for future use. Do not look up your data ref by string + * every time you need to read or write it. + * + */ +XPLM_API XPLMDataRef XPLMFindDataRef(const char *inDataRefName); + +/* + * XPLMCanWriteDataRef + * + * Given a data ref, this routine returns true if you can successfully set + * the data, false otherwise. Some datarefs are read-only. + * + */ +XPLM_API int XPLMCanWriteDataRef(XPLMDataRef inDataRef); + +/* + * XPLMIsDataRefGood + * + * WARNING: This function is deprecated and should not be used. Datarefs are + * valid until plugins are reloaded or the sim quits. Plugins sharing + * datarefs should support these semantics by not unregistering datarefs + * during operation. (You should however unregister datarefs when your plugin + * is unloaded, as part of general resource cleanup.) + * + * This function returns whether a data ref is still valid. If it returns + * false, you should refind the data ref from its original string. Calling an + * accessor function on a bad data ref will return a default value, typically + * 0 or 0-length data. + * + */ +XPLM_API int XPLMIsDataRefGood(XPLMDataRef inDataRef); + +/* + * XPLMGetDataRefTypes + * + * This routine returns the types of the data ref for accessor use. If a data + * ref is available in multiple data types, they will all be returned. + * + */ +XPLM_API XPLMDataTypeID XPLMGetDataRefTypes(XPLMDataRef inDataRef); + +/*************************************************************************** + * DATA ACCESSORS + ***************************************************************************/ +/* + * These routines read and write the data references. For each supported data + * type there is a reader and a writer. + * + * If the data ref is invalid or the plugin that provides it is disabled or + * there is a type mismatch, the functions that read data will return 0 as a + * default value or not modify the passed in memory. The plugins that write + * data will not write under these circumstances or if the data ref is + * read-only. NOTE: to keep the overhead of reading datarefs low, these + * routines do not do full validation of a dataref; passing a junk value for + * a dataref can result in crashing the sim. + * + * For array-style datarefs, you specify the number of items to read/write and + * the offset into the array; the actual number of items read or written is + * returned. This may be less to prevent an array-out-of-bounds error. + * + */ + + +/* + * XPLMGetDatai + * + * Read an integer data ref and return its value. The return value is the + * dataref value or 0 if the dataref is invalid/NULL or the plugin is + * disabled. + * + */ +XPLM_API int XPLMGetDatai(XPLMDataRef inDataRef); + +/* + * XPLMSetDatai + * + * Write a new value to an integer data ref. This routine is a no-op if the + * plugin publishing the dataref is disabled, the dataref is invalid, or the + * dataref is not writable. + * + */ +XPLM_API void XPLMSetDatai(XPLMDataRef inDataRef, int inValue); + +/* + * XPLMGetDataf + * + * Read a single precision floating point dataref and return its value. The + * return value is the dataref value or 0.0 if the dataref is invalid/NULL or + * the plugin is disabled. + * + */ +XPLM_API float XPLMGetDataf(XPLMDataRef inDataRef); + +/* + * XPLMSetDataf + * + * Write a new value to a single precision floating point data ref. This + * routine is a no-op if the plugin publishing the dataref is disabled, the + * dataref is invalid, or the dataref is not writable. + * + */ +XPLM_API void XPLMSetDataf(XPLMDataRef inDataRef, float inValue); + +/* + * XPLMGetDatad + * + * Read a double precision floating point dataref and return its value. The + * return value is the dataref value or 0.0 if the dataref is invalid/NULL or + * the plugin is disabled. + * + */ +XPLM_API double XPLMGetDatad(XPLMDataRef inDataRef); + +/* + * XPLMSetDatad + * + * Write a new value to a double precision floating point data ref. This + * routine is a no-op if the plugin publishing the dataref is disabled, the + * dataref is invalid, or the dataref is not writable. + * + */ +XPLM_API void XPLMSetDatad(XPLMDataRef inDataRef, double inValue); + +/* + * XPLMGetDatavi + * + * Read a part of an integer array dataref. If you pass NULL for outVaules, + * the routine will return the size of the array, ignoring inOffset and inMax. + * + * + * If outValues is not NULL, then up to inMax values are copied from the + * dataref into outValues, starting at inOffset in the dataref. If inMax + + * inOffset is larger than the size of the dataref, less than inMax values + * will be copied. The number of values copied is returned. + * + * Note: the semantics of array datarefs are entirely implemented by the + * plugin (or X-Plane) that provides the dataref, not the SDK itself; the + * above description is how these datarefs are intended to work, but a rogue + * plugin may have different behavior. + * + */ +XPLM_API int XPLMGetDatavi(XPLMDataRef inDataRef, + int *outValues, /* Can be NULL */ + int inOffset, + int inMax); + +/* + * XPLMSetDatavi + * + * Write part or all of an integer array dataref. The values passed by + * inValues are written into the dataref starting at inOffset. Up to inCount + * values are written; however if the values would write "off the end" of the + * dataref array, then fewer values are written. + * + * Note: the semantics of array datarefs are entirely implemented by the + * plugin (or X-Plane) that provides the dataref, not the SDK itself; the + * above description is how these datarefs are intended to work, but a rogue + * plugin may have different behavior. + * + */ +XPLM_API void XPLMSetDatavi(XPLMDataRef inDataRef, + int *inValues, + int inoffset, + int inCount); + +/* + * XPLMGetDatavf + * + * Read a part of a single precision floating point array dataref. If you + * pass NULL for outVaules, the routine will return the size of the array, + * ignoring inOffset and inMax. + * + * If outValues is not NULL, then up to inMax values are copied from the + * dataref into outValues, starting at inOffset in the dataref. If inMax + + * inOffset is larger than the size of the dataref, less than inMax values + * will be copied. The number of values copied is returned. + * + * Note: the semantics of array datarefs are entirely implemented by the + * plugin (or X-Plane) that provides the dataref, not the SDK itself; the + * above description is how these datarefs are intended to work, but a rogue + * plugin may have different behavior. + * + */ +XPLM_API int XPLMGetDatavf(XPLMDataRef inDataRef, + float *outValues, /* Can be NULL */ + int inOffset, + int inMax); + +/* + * XPLMSetDatavf + * + * Write part or all of a single precision floating point array dataref. The + * values passed by inValues are written into the dataref starting at + * inOffset. Up to inCount values are written; however if the values would + * write "off the end" of the dataref array, then fewer values are written. + * + * Note: the semantics of array datarefs are entirely implemented by the + * plugin (or X-Plane) that provides the dataref, not the SDK itself; the + * above description is how these datarefs are intended to work, but a rogue + * plugin may have different behavior. + * + */ +XPLM_API void XPLMSetDatavf(XPLMDataRef inDataRef, + float *inValues, + int inoffset, + int inCount); + +/* + * XPLMGetDatab + * + * Read a part of a byte array dataref. If you pass NULL for outVaules, the + * routine will return the size of the array, ignoring inOffset and inMax. + * + * If outValues is not NULL, then up to inMax values are copied from the + * dataref into outValues, starting at inOffset in the dataref. If inMax + + * inOffset is larger than the size of the dataref, less than inMax values + * will be copied. The number of values copied is returned. + * + * Note: the semantics of array datarefs are entirely implemented by the + * plugin (or X-Plane) that provides the dataref, not the SDK itself; the + * above description is how these datarefs are intended to work, but a rogue + * plugin may have different behavior. + * + */ +XPLM_API int XPLMGetDatab(XPLMDataRef inDataRef, + void *outValue, /* Can be NULL */ + int inOffset, + int inMaxBytes); + +/* + * XPLMSetDatab + * + * Write part or all of a byte array dataref. The values passed by inValues + * are written into the dataref starting at inOffset. Up to inCount values + * are written; however if the values would write "off the end" of the dataref + * array, then fewer values are written. + * + * Note: the semantics of array datarefs are entirely implemented by the + * plugin (or X-Plane) that provides the dataref, not the SDK itself; the + * above description is how these datarefs are intended to work, but a rogue + * plugin may have different behavior. + * + */ +XPLM_API void XPLMSetDatab(XPLMDataRef inDataRef, + void *inValue, + int inOffset, + int inLength); + +/*************************************************************************** + * PUBLISHING YOUR PLUGINS DATA + ***************************************************************************/ +/* + * These functions allow you to create data references that other plug-ins can + * access via the above data access APIs. Data references published by other + * plugins operate the same as ones published by x-plane in all manners except + * that your data reference will not be available to other plugins if/when + * your plugin is disabled. + * + * You share data by registering data provider callback functions. When a + * plug-in requests your data, these callbacks are then called. You provide + * one callback to return the value when a plugin 'reads' it and another to + * change the value when a plugin 'writes' it. + * + * Important: you must pick a prefix for your datarefs other than "sim/" - + * this prefix is reserved for X-Plane. The X-Plane SDK website contains a + * registry where authors can select a unique first word for dataref names, to + * prevent dataref collisions between plugins. + * + */ + + +/* + * XPLMGetDatai_f + * + * Data provider function pointers. + * + * These define the function pointers you provide to get or set data. Note + * that you are passed a generic pointer for each one. This is the same + * pointer you pass in your register routine; you can use it to find global + * variables, etc. + * + * The semantics of your callbacks are the same as the dataref accessor above + * - basically routines like XPLMGetDatai are just pass-throughs from a caller + * to your plugin. Be particularly mindful in implementing array dataref + * read-write accessors; you are responsible for avoiding overruns, supporting + * offset read/writes, and handling a read with a NULL buffer. + * + */ +typedef int (*XPLMGetDatai_f)(void *inRefcon); + +/* + * XPLMSetDatai_f + * + * + */ +typedef void (*XPLMSetDatai_f)(void *inRefcon, int inValue); + +/* + * XPLMGetDataf_f + * + * + */ +typedef float (*XPLMGetDataf_f)(void *inRefcon); + +/* + * XPLMSetDataf_f + * + * + */ +typedef void (*XPLMSetDataf_f)(void *inRefcon, float inValue); + +/* + * XPLMGetDatad_f + * + * + */ +typedef double (*XPLMGetDatad_f)(void *inRefcon); + +/* + * XPLMSetDatad_f + * + * + */ +typedef void (*XPLMSetDatad_f)(void *inRefcon, double inValue); + +/* + * XPLMGetDatavi_f + * + * + */ +typedef int (*XPLMGetDatavi_f)(void *inRefcon, + int *outValues, /* Can be NULL */ + int inOffset, + int inMax); + +/* + * XPLMSetDatavi_f + * + * + */ +typedef void (*XPLMSetDatavi_f)(void *inRefcon, + int *inValues, + int inOffset, + int inCount); + +/* + * XPLMGetDatavf_f + * + * + */ +typedef int (*XPLMGetDatavf_f)(void *inRefcon, + float *outValues, /* Can be NULL */ + int inOffset, + int inMax); + +/* + * XPLMSetDatavf_f + * + * + */ +typedef void (*XPLMSetDatavf_f)(void *inRefcon, + float *inValues, + int inOffset, + int inCount); + +/* + * XPLMGetDatab_f + * + * + */ +typedef int (*XPLMGetDatab_f)(void *inRefcon, + void *outValue, /* Can be NULL */ + int inOffset, + int inMaxLength); + +/* + * XPLMSetDatab_f + * + * + */ +typedef void (*XPLMSetDatab_f)(void *inRefcon, + void *inValue, + int inOffset, + int inLength); + +/* + * XPLMRegisterDataAccessor + * + * This routine creates a new item of data that can be read and written. Pass + * in the data's full name for searching, the type(s) of the data for + * accessing, and whether the data can be written to. For each data type you + * support, pass in a read accessor function and a write accessor function if + * necessary. Pass NULL for data types you do not support or write accessors + * if you are read-only. + * + * You are returned a data ref for the new item of data created. You can use + * this data ref to unregister your data later or read or write from it. + * + */ +XPLM_API XPLMDataRef XPLMRegisterDataAccessor(const char *inDataName, + XPLMDataTypeID inDataType, + int inIsWritable, + XPLMGetDatai_f inReadInt, + XPLMSetDatai_f inWriteInt, + XPLMGetDataf_f inReadFloat, + XPLMSetDataf_f inWriteFloat, + XPLMGetDatad_f inReadDouble, + XPLMSetDatad_f inWriteDouble, + XPLMGetDatavi_f inReadIntArray, + XPLMSetDatavi_f inWriteIntArray, + XPLMGetDatavf_f inReadFloatArray, + XPLMSetDatavf_f inWriteFloatArray, + XPLMGetDatab_f inReadData, + XPLMSetDatab_f inWriteData, + void *inReadRefcon, + void *inWriteRefcon); + +/* + * XPLMUnregisterDataAccessor + * + * Use this routine to unregister any data accessors you may have registered. + * You unregister a data ref by the XPLMDataRef you get back from + * registration. Once you unregister a data ref, your function pointer will + * not be called anymore. + * + * For maximum compatibility, do not unregister your data accessors until + * final shutdown (when your XPluginStop routine is called). This allows + * other plugins to find your data reference once and use it for their entire + * time of operation. + * + */ +XPLM_API void XPLMUnregisterDataAccessor(XPLMDataRef inDataRef); + +/*************************************************************************** + * SHARING DATA BETWEEN MULTIPLE PLUGINS + ***************************************************************************/ +/* + * The data reference registration APIs from the previous section allow a + * plugin to publish data in a one-owner manner; the plugin that publishes the + * data reference owns the real memory that the data ref uses. This is + * satisfactory for most cases, but there are also cases where plugnis need to + * share actual data. + * + * With a shared data reference, no one plugin owns the actual memory for the + * data reference; the plugin SDK allocates that for you. When the first + * plugin asks to 'share' the data, the memory is allocated. When the data is + * changed, every plugin that is sharing the data is notified. + * + * Shared data references differ from the 'owned' data references from the + * previous section in a few ways: + * + * - With shared data references, any plugin can create the data reference; + * with owned plugins one plugin must create the data reference and others + * subscribe. (This can be a problem if you don't know which set of plugins + * will be present). + * + * - With shared data references, every plugin that is sharing the data is + * notified when the data is changed. With owned data references, only the + * one owner is notified when the data is changed. + * + * - With shared data references, you cannot access the physical memory of the + * data reference; you must use the XPLMGet... and XPLMSet... APIs. With an + * owned data reference, the one owning data reference can manipulate the + * data reference's memory in any way it sees fit. + * + * Shared data references solve two problems: if you need to have a data + * reference used by several plugins but do not know which plugins will be + * installed, or if all plugins sharing data need to be notified when that + * data is changed, use shared data references. + * + */ + + +/* + * XPLMDataChanged_f + * + * An XPLMDataChanged_f is a callback that the XPLM calls whenever any other + * plug-in modifies shared data. A refcon you provide is passed back to help + * identify which data is being changed. In response, you may want to call one + * of the XPLMGetDataxxx routines to find the new value of the data. + * + */ +typedef void (*XPLMDataChanged_f)(void *inRefcon); + +/* + * XPLMShareData + * + * This routine connects a plug-in to shared data, creating the shared data if + * necessary. inDataName is a standard path for the data ref, and inDataType + * specifies the type. This function will create the data if it does not + * exist. If the data already exists but the type does not match, an error is + * returned, so it is important that plug-in authors collaborate to establish + * public standards for shared data. + * + * If a notificationFunc is passed in and is not NULL, that notification + * function will be called whenever the data is modified. The notification + * refcon will be passed to it. This allows your plug-in to know which shared + * data was changed if multiple shared data are handled by one callback, or if + * the plug-in does not use global variables. + * + * A one is returned for successfully creating or finding the shared data; a + * zero if the data already exists but is of the wrong type. + * + */ +XPLM_API int XPLMShareData(const char *inDataName, + XPLMDataTypeID inDataType, + XPLMDataChanged_f inNotificationFunc, + void *inNotificationRefcon); + +/* + * XPLMUnshareData + * + * This routine removes your notification function for shared data. Call it + * when done with the data to stop receiving change notifications. Arguments + * must match XPLMShareData. The actual memory will not necessarily be freed, + * since other plug-ins could be using it. + * + */ +XPLM_API int XPLMUnshareData(const char *inDataName, + XPLMDataTypeID inDataType, + XPLMDataChanged_f inNotificationFunc, + void *inNotificationRefcon); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDefs.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDefs.h new file mode 100644 index 0000000..c720e70 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDefs.h @@ -0,0 +1,518 @@ +#ifndef _XPLMDefs_h_ +#define _XPLMDefs_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * This file is contains the cross-platform and basic definitions for the + * X-Plane SDK. + * + * The preprocessor macros APL and IBM must be defined to specify the + * compilation target; define APL to 1 and IBM 0 to compile on Macintosh and + * APL to 0 and IBM to 1 for Windows. You must specify these macro definitions + * before including XPLMDefs.h or any other XPLM headers. You can do this + * using the -D command line option or a preprocessor header. + * + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +#if IBM +#include +#else +#include +#endif +/*************************************************************************** + * DLL Definitions + ***************************************************************************/ +/* + * These definitions control the importing and exporting of functions within + * the DLL. + * + * You can prefix your five required callbacks with the PLUGIN_API macro to + * declare them as exported C functions. The XPLM_API macro identifies + * functions that are provided to you via the plugin SDK. (Link against + * XPLM.lib to use these functions.) + * + */ + + +#ifdef __cplusplus +#if APL +#if __GNUC__ >= 4 +#define PLUGIN_API extern "C" __attribute__((visibility("default"))) +#elif __MACH__ +#define PLUGIN_API extern "C" +#else +#define PLUGIN_API extern "C" __declspec(dllexport) +#endif +#elif IBM +#define PLUGIN_API extern "C" __declspec(dllexport) +#elif LIN +#if __GNUC__ >= 4 +#define PLUGIN_API extern "C" __attribute__((visibility("default"))) +#else +#define PLUGIN_API extern "C" +#endif +#else +#error "Platform not defined!" +#endif +#else +#if APL +#if __GNUC__ >= 4 +#define PLUGIN_API __attribute__((visibility("default"))) +#elif __MACH__ +#define PLUGIN_API +#else +#define PLUGIN_API __declspec(dllexport) +#endif +#elif IBM +#define PLUGIN_API __declspec(dllexport) +#elif LIN +#if __GNUC__ >= 4 +#define PLUGIN_API __attribute__((visibility("default"))) +#else +#define PLUGIN_API +#endif +#else +#error "Platform not defined!" +#endif +#endif + +#if APL +#if XPLM +#if __GNUC__ >= 4 +#define XPLM_API __attribute__((visibility("default"))) +#elif __MACH__ +#define XPLM_API +#else +#define XPLM_API __declspec(dllexport) +#endif +#else +#define XPLM_API +#endif +#elif IBM +#if XPLM +#define XPLM_API __declspec(dllexport) +#else +#define XPLM_API __declspec(dllimport) +#endif +#elif LIN +#if XPLM +#if __GNUC__ >= 4 +#define XPLM_API __attribute__((visibility("default"))) +#else +#define XPLM_API +#endif +#else +#define XPLM_API +#endif +#else +#error "Platform not defined!" +#endif + +/*************************************************************************** + * GLOBAL DEFINITIONS + ***************************************************************************/ +/* + * These definitions are used in all parts of the SDK. + * + */ + + +/* + * XPLMPluginID + * + * Each plug-in is identified by a unique integer ID. This ID can be used to + * disable or enable a plug-in, or discover what plug-in is 'running' at the + * time. A plug-in ID is unique within the currently running instance of + * X-Plane unless plug-ins are reloaded. Plug-ins may receive a different + * unique ID each time they are loaded. + * + * For persistent identification of plug-ins, use XPLMFindPluginBySignature in + * XPLMUtiltiies.h + * + * -1 indicates no plug-in. + * + */ +typedef int XPLMPluginID; + +/* No plugin. */ +#define XPLM_NO_PLUGIN_ID (-1) + +/* X-Plane itself */ +#define XPLM_PLUGIN_XPLANE (0) + +/* The current XPLM revision is 2.10 (210). */ +#define kXPLM_Version (210) + +/* + * XPLMKeyFlags + * + * These bitfields define modifier keys in a platform independent way. When a + * key is pressed, a series of messages are sent to your plugin. The down + * flag is set in the first of these messages, and the up flag in the last. + * While the key is held down, messages are sent with neither to indicate that + * the key is being held down as a repeated character. + * + * The control flag is mapped to the control flag on Macintosh and PC. + * Generally X-Plane uses the control key and not the command key on + * Macintosh, providing a consistent interface across platforms that does not + * necessarily match the Macintosh user interface guidelines. There is not + * yet a way for plugins to access the Macintosh control keys without using + * #ifdefed code. + * + */ +enum { + /* The shift key is down */ + xplm_ShiftFlag = 1 + + /* The option or alt key is down */ + , + xplm_OptionAltFlag = 2 + + /* The control key is down* */ + , + xplm_ControlFlag = 4 + + /* The key is being pressed down */ + , + xplm_DownFlag = 8 + + /* The key is being released */ + , + xplm_UpFlag = 16 + + +}; +typedef int XPLMKeyFlags; + +/*************************************************************************** + * ASCII CONTROL KEY CODES + ***************************************************************************/ +/* + * These definitions define how various control keys are mapped to ASCII key + * codes. Not all key presses generate an ASCII value, so plugin code should + * be prepared to see null characters come from the keyboard...this usually + * represents a key stroke that has no equivalent ASCII, like a page-down + * press. Use virtual key codes to find these key strokes. ASCII key codes + * take into account modifier keys; shift keys will affect capitals and + * punctuation; control key combinations may have no vaild ASCII and produce + * NULL. To detect control-key combinations, use virtual key codes, not ASCII + * keys. + * + */ + + +#define XPLM_KEY_RETURN 13 + +#define XPLM_KEY_ESCAPE 27 + +#define XPLM_KEY_TAB 9 + +#define XPLM_KEY_DELETE 8 + +#define XPLM_KEY_LEFT 28 + +#define XPLM_KEY_RIGHT 29 + +#define XPLM_KEY_UP 30 + +#define XPLM_KEY_DOWN 31 + +#define XPLM_KEY_0 48 + +#define XPLM_KEY_1 49 + +#define XPLM_KEY_2 50 + +#define XPLM_KEY_3 51 + +#define XPLM_KEY_4 52 + +#define XPLM_KEY_5 53 + +#define XPLM_KEY_6 54 + +#define XPLM_KEY_7 55 + +#define XPLM_KEY_8 56 + +#define XPLM_KEY_9 57 + +#define XPLM_KEY_DECIMAL 46 + +/*************************************************************************** + * VIRTUAL KEY CODES + ***************************************************************************/ +/* + * These are cross-platform defines for every distinct keyboard press on the + * computer. Every physical key on the keyboard has a virtual key code. So + * the "two" key on the top row of the main keyboard has a different code + * from the "two" key on the numeric key pad. But the 'w' and 'W' character + * are indistinguishable by virtual key code because they are the same + * physical key (one with and one without the shift key). + * + * Use virtual key codes to detect keystrokes that do not have ASCII + * equivalents, allow the user to map the numeric keypad separately from the + * main keyboard, and detect control key and other modifier-key combinations + * that generate ASCII control key sequences (many of which are not available + * directly via character keys in the SDK). + * + * To assign virtual key codes we started with the Microsoft set but made some + * additions and changes. A few differences: + * + * 1. Modifier keys are not available as virtual key codes. You cannot get + * distinct modifier press and release messages. Please do not try to use + * modifier keys as regular keys; doing so will almost certainly interfere + * with users' abilities to use the native x-plane key bindings. + * + * 2. Some keys that do not exist on both Mac and PC keyboards are removed. + * + * 3. Do not assume that the values of these keystrokes are interchangeable + * with MS v-keys. + * + */ + + +#define XPLM_VK_BACK 0x08 + +#define XPLM_VK_TAB 0x09 + +#define XPLM_VK_CLEAR 0x0C + +#define XPLM_VK_RETURN 0x0D + +#define XPLM_VK_ESCAPE 0x1B + +#define XPLM_VK_SPACE 0x20 + +#define XPLM_VK_PRIOR 0x21 + +#define XPLM_VK_NEXT 0x22 + +#define XPLM_VK_END 0x23 + +#define XPLM_VK_HOME 0x24 + +#define XPLM_VK_LEFT 0x25 + +#define XPLM_VK_UP 0x26 + +#define XPLM_VK_RIGHT 0x27 + +#define XPLM_VK_DOWN 0x28 + +#define XPLM_VK_SELECT 0x29 + +#define XPLM_VK_PRINT 0x2A + +#define XPLM_VK_EXECUTE 0x2B + +#define XPLM_VK_SNAPSHOT 0x2C + +#define XPLM_VK_INSERT 0x2D + +#define XPLM_VK_DELETE 0x2E + +#define XPLM_VK_HELP 0x2F + +/* XPLM_VK_0 thru XPLM_VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */ +#define XPLM_VK_0 0x30 + +#define XPLM_VK_1 0x31 + +#define XPLM_VK_2 0x32 + +#define XPLM_VK_3 0x33 + +#define XPLM_VK_4 0x34 + +#define XPLM_VK_5 0x35 + +#define XPLM_VK_6 0x36 + +#define XPLM_VK_7 0x37 + +#define XPLM_VK_8 0x38 + +#define XPLM_VK_9 0x39 + +/* XPLM_VK_A thru XPLM_VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */ +#define XPLM_VK_A 0x41 + +#define XPLM_VK_B 0x42 + +#define XPLM_VK_C 0x43 + +#define XPLM_VK_D 0x44 + +#define XPLM_VK_E 0x45 + +#define XPLM_VK_F 0x46 + +#define XPLM_VK_G 0x47 + +#define XPLM_VK_H 0x48 + +#define XPLM_VK_I 0x49 + +#define XPLM_VK_J 0x4A + +#define XPLM_VK_K 0x4B + +#define XPLM_VK_L 0x4C + +#define XPLM_VK_M 0x4D + +#define XPLM_VK_N 0x4E + +#define XPLM_VK_O 0x4F + +#define XPLM_VK_P 0x50 + +#define XPLM_VK_Q 0x51 + +#define XPLM_VK_R 0x52 + +#define XPLM_VK_S 0x53 + +#define XPLM_VK_T 0x54 + +#define XPLM_VK_U 0x55 + +#define XPLM_VK_V 0x56 + +#define XPLM_VK_W 0x57 + +#define XPLM_VK_X 0x58 + +#define XPLM_VK_Y 0x59 + +#define XPLM_VK_Z 0x5A + +#define XPLM_VK_NUMPAD0 0x60 + +#define XPLM_VK_NUMPAD1 0x61 + +#define XPLM_VK_NUMPAD2 0x62 + +#define XPLM_VK_NUMPAD3 0x63 + +#define XPLM_VK_NUMPAD4 0x64 + +#define XPLM_VK_NUMPAD5 0x65 + +#define XPLM_VK_NUMPAD6 0x66 + +#define XPLM_VK_NUMPAD7 0x67 + +#define XPLM_VK_NUMPAD8 0x68 + +#define XPLM_VK_NUMPAD9 0x69 + +#define XPLM_VK_MULTIPLY 0x6A + +#define XPLM_VK_ADD 0x6B + +#define XPLM_VK_SEPARATOR 0x6C + +#define XPLM_VK_SUBTRACT 0x6D + +#define XPLM_VK_DECIMAL 0x6E + +#define XPLM_VK_DIVIDE 0x6F + +#define XPLM_VK_F1 0x70 + +#define XPLM_VK_F2 0x71 + +#define XPLM_VK_F3 0x72 + +#define XPLM_VK_F4 0x73 + +#define XPLM_VK_F5 0x74 + +#define XPLM_VK_F6 0x75 + +#define XPLM_VK_F7 0x76 + +#define XPLM_VK_F8 0x77 + +#define XPLM_VK_F9 0x78 + +#define XPLM_VK_F10 0x79 + +#define XPLM_VK_F11 0x7A + +#define XPLM_VK_F12 0x7B + +#define XPLM_VK_F13 0x7C + +#define XPLM_VK_F14 0x7D + +#define XPLM_VK_F15 0x7E + +#define XPLM_VK_F16 0x7F + +#define XPLM_VK_F17 0x80 + +#define XPLM_VK_F18 0x81 + +#define XPLM_VK_F19 0x82 + +#define XPLM_VK_F20 0x83 + +#define XPLM_VK_F21 0x84 + +#define XPLM_VK_F22 0x85 + +#define XPLM_VK_F23 0x86 + +#define XPLM_VK_F24 0x87 + +/* The following definitions are extended and are not based on the Microsoft * + * key set. */ +#define XPLM_VK_EQUAL 0xB0 + +#define XPLM_VK_MINUS 0xB1 + +#define XPLM_VK_RBRACE 0xB2 + +#define XPLM_VK_LBRACE 0xB3 + +#define XPLM_VK_QUOTE 0xB4 + +#define XPLM_VK_SEMICOLON 0xB5 + +#define XPLM_VK_BACKSLASH 0xB6 + +#define XPLM_VK_COMMA 0xB7 + +#define XPLM_VK_SLASH 0xB8 + +#define XPLM_VK_PERIOD 0xB9 + +#define XPLM_VK_BACKQUOTE 0xBA + +#define XPLM_VK_ENTER 0xBB + +#define XPLM_VK_NUMPAD_ENT 0xBC + +#define XPLM_VK_NUMPAD_EQ 0xBD + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDisplay.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDisplay.h new file mode 100644 index 0000000..c2f16bc --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMDisplay.h @@ -0,0 +1,743 @@ +#ifndef _XPLMDisplay_h_ +#define _XPLMDisplay_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * XPLM Display APIs - THEORY OF OPERATION + * + * This API provides the basic hooks to draw in X-Plane and create user + * interface. All X-Plane drawing is done in OpenGL. The X-Plane plug-in + * manager takes care of properly setting up the OpenGL context and matrices. + * You do not decide when in your code's execution to draw; X-Plane tells you + * when it is ready to have your plugin draw. + * + * X-Plane's drawing strategy is straightforward: every "frame" the screen is + * rendered by drawing the 3-d scene (dome, ground, objects, airplanes, etc.) + * and then drawing the cockpit on top of it. Alpha blending is used to + * overlay the cockpit over the world (and the gauges over the panel, etc.). + * + * There are two ways you can draw: directly and in a window. + * + * Direct drawing involves drawing to the screen before or after X-Plane + * finishes a phase of drawing. When you draw directly, you can specify + * whether x-plane is to complete this phase or not. This allows you to do + * three things: draw before x-plane does (under it), draw after x-plane does + * (over it), or draw instead of x-plane. + * + * To draw directly, you register a callback and specify what phase you want + * to intercept. The plug-in manager will call you over and over to draw that + * phase. + * + * Direct drawing allows you to override scenery, panels, or anything. Note + * that you cannot assume that you are the only plug-in drawing at this + * phase. + * + * Window drawing provides slightly higher level functionality. With window + * drawing you create a window that takes up a portion of the screen. Window + * drawing is always two dimensional. Window drawing is front-to-back + * controlled; you can specify that you want your window to be brought on + * top, and other plug-ins may put their window on top of you. Window drawing + * also allows you to sign up for key presses and receive mouse clicks. + * + * There are three ways to get keystrokes: + * + * If you create a window, the window can take keyboard focus. It will then + * receive all keystrokes. If no window has focus, X-Plane receives + * keystrokes. Use this to implement typing in dialog boxes, etc. Only one + * window may have focus at a time; your window will be notified if it loses + * focus. + * + * If you need to associate key strokes with commands/functions in your + * plug-in, use a hot key. A hoy is a key-specific callback. Hotkeys are + * sent based on virtual key strokes, so any key may be distinctly mapped with + * any modifiers. Hot keys can be remapped by other plug-ins. As a plug-in, + * you don't have to worry about what your hot key ends up mapped to; other + * plug-ins may provide a UI for remapping keystrokes. So hotkeys allow a + * user to resolve conflicts and customize keystrokes. + * + * If you need low level access to the keystroke stream, install a key + * sniffer. Key sniffers can be installed above everything or right in front + * of the sim. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * DRAWING CALLBACKS + ***************************************************************************/ +/* + * Basic drawing callbacks, for low level intercepting of render loop. The + * purpose of drawing callbacks is to provide targeted additions or + * replacements to x-plane's graphics environment (for example, to add extra + * custom objects, or replace drawing of the AI aircraft). Do not assume that + * the drawing callbacks will be called in the order implied by the + * enumerations. Also do not assume that each drawing phase ends before + * another begins; they may be nested. + * + */ + + +/* + * XPLMDrawingPhase + * + * This constant indicates which part of drawing we are in. Drawing is done + * from the back to the front. We get a callback before or after each item. + * Metaphases provide access to the beginning and end of the 3d (scene) and 2d + * (cockpit) drawing in a manner that is independent of new phases added via + * x-plane implementation. + * + * WARNING: As X-Plane's scenery evolves, some drawing phases may cease to + * exist and new ones may be invented. If you need a particularly specific + * use of these codes, consult Austin and/or be prepared to revise your code + * as X-Plane evolves. + * + */ +enum { + /* This is the earliest point at which you can draw in 3-d. */ + xplm_Phase_FirstScene = 0 + + /* Drawing of land and water. */ + , + xplm_Phase_Terrain = 5 + + /* Drawing runways and other airport detail. */ + , + xplm_Phase_Airports = 10 + + /* Drawing roads, trails, trains, etc. */ + , + xplm_Phase_Vectors = 15 + + /* 3-d objects (houses, smokestacks, etc. */ + , + xplm_Phase_Objects = 20 + + /* External views of airplanes, both yours and the AI aircraft. */ + , + xplm_Phase_Airplanes = 25 + + /* This is the last point at which you can draw in 3-d. */ + , + xplm_Phase_LastScene = 30 + + /* This is the first phase where you can draw in 2-d. */ + , + xplm_Phase_FirstCockpit = 35 + + /* The non-moving parts of the aircraft panel. */ + , + xplm_Phase_Panel = 40 + + /* The moving parts of the aircraft panel. */ + , + xplm_Phase_Gauges = 45 + + /* Floating windows from plugins. */ + , + xplm_Phase_Window = 50 + + /* The last change to draw in 2d. */ + , + xplm_Phase_LastCockpit = 55 + +#if defined(XPLM200) + /* 3-d Drawing for the local map. Use regular OpenGL coordinates to draw in + * * this phase. */ + , + xplm_Phase_LocalMap3D = 100 + +#endif /* XPLM200 */ +#if defined(XPLM200) + /* 2-d Drawing of text over the local map. */ + , + xplm_Phase_LocalMap2D = 101 + +#endif /* XPLM200 */ +#if defined(XPLM200) + /* Drawing of the side-profile view in the local map screen. */ + , + xplm_Phase_LocalMapProfile = 102 + +#endif /* XPLM200 */ + +}; +typedef int XPLMDrawingPhase; + +/* + * XPLMDrawCallback_f + * + * This is the prototype for a low level drawing callback. You are passed in + * the phase and whether it is before or after. If you are before the phase, + * return 1 to let x-plane draw or 0 to suppress x-plane drawing. If you are + * after the phase the return value is ignored. + * + * Refcon is a unique value that you specify when registering the callback, + * allowing you to slip a pointer to your own data to the callback. + * + * Upon entry the OpenGL context will be correctly set up for you and OpenGL + * will be in 'local' coordinates for 3d drawing and panel coordinates for 2d + * drawing. The OpenGL state (texturing, etc.) will be unknown. + * + */ +typedef int (*XPLMDrawCallback_f)(XPLMDrawingPhase inPhase, + int inIsBefore, + void *inRefcon); + +/* + * XPLMKeySniffer_f + * + * This is the prototype for a low level key-sniffing function. Window-based + * UI _should not use this_! The windowing system provides high-level + * mediated keyboard access. By comparison, the key sniffer provides low + * level keyboard access. + * + * Key sniffers are provided to allow libraries to provide non-windowed user + * interaction. For example, the MUI library uses a key sniffer to do pop-up + * text entry. + * + * inKey is the character pressed, inRefCon is a value you supply during + * registration. Return 1 to pass the key on to the next sniffer, the window + * mgr, x-plane, or whomever is down stream. Return 0 to consume the key. + * + * Warning: this API declares virtual keys as a signed character; however the + * VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values + * (that is 0x80 instead of -0x80). So you may need to cast the incoming vkey + * to an unsigned char to get correct comparisons in C. + * + */ +typedef int (*XPLMKeySniffer_f)(char inChar, + XPLMKeyFlags inFlags, + char inVirtualKey, + void *inRefcon); + +/* + * XPLMRegisterDrawCallback + * + * This routine registers a low level drawing callback. Pass in the phase you + * want to be called for and whether you want to be called before or after. + * This routine returns 1 if the registration was successful, or 0 if the + * phase does not exist in this version of x-plane. You may register a + * callback multiple times for the same or different phases as long as the + * refcon is unique each time. + * + */ +XPLM_API int XPLMRegisterDrawCallback(XPLMDrawCallback_f inCallback, + XPLMDrawingPhase inPhase, + int inWantsBefore, + void *inRefcon); + +/* + * XPLMUnregisterDrawCallback + * + * This routine unregisters a draw callback. You must unregister a callback + * for each time you register a callback if you have registered it multiple + * times with different refcons. The routine returns 1 if it can find the + * callback to unregister, 0 otherwise. + * + */ +XPLM_API int XPLMUnregisterDrawCallback(XPLMDrawCallback_f inCallback, + XPLMDrawingPhase inPhase, + int inWantsBefore, + void *inRefcon); + +/* + * XPLMRegisterKeySniffer + * + * This routine registers a key sniffing callback. You specify whether you + * want to sniff before the window system, or only sniff keys the window + * system does not consume. You should ALMOST ALWAYS sniff non-control keys + * after the window system. When the window system consumes a key, it is + * because the user has "focused" a window. Consuming the key or taking + * action based on the key will produce very weird results. Returns 1 if + * successful. + * + */ +XPLM_API int XPLMRegisterKeySniffer(XPLMKeySniffer_f inCallback, + int inBeforeWindows, + void *inRefcon); + +/* + * XPLMUnregisterKeySniffer + * + * This routine unregisters a key sniffer. You must unregister a key sniffer + * for every time you register one with the exact same signature. Returns 1 + * if successful. + * + */ +XPLM_API int XPLMUnregisterKeySniffer(XPLMKeySniffer_f inCallback, + int inBeforeWindows, + void *inRefcon); + +/*************************************************************************** + * WINDOW API + ***************************************************************************/ +/* + * Window API, for higher level drawing with UI interaction. + * + * Note: all 2-d (and thus all window drawing) is done in 'cockpit pixels'. + * Even when the OpenGL window contains more than 1024x768 pixels, the cockpit + * drawing is magnified so that only 1024x768 pixels are available. + * + */ + + +/* + * XPLMMouseStatus + * + * When the mouse is clicked, your mouse click routine is called repeatedly. + * It is first called with the mouse down message. It is then called zero or + * more times with the mouse-drag message, and finally it is called once with + * the mouse up message. All of these messages will be directed to the same + * window. + * + */ +enum { + xplm_MouseDown = 1 + + , + xplm_MouseDrag = 2 + + , + xplm_MouseUp = 3 + + +}; +typedef int XPLMMouseStatus; + +#if defined(XPLM200) +/* + * XPLMCursorStatus + * + * XPLMCursorStatus describes how you would like X-Plane to manage the cursor. + * See XPLMHandleCursor_f for more info. + * + */ +enum { + /* X-Plane manages the cursor normally, plugin does not affect the cusrsor. + */ + xplm_CursorDefault = 0 + + /* X-Plane hides the cursor. */ + , + xplm_CursorHidden = 1 + + /* X-Plane shows the cursor as the default arrow. */ + , + xplm_CursorArrow = 2 + + /* X-Plane shows the cursor but lets you select an OS cursor. */ + , + xplm_CursorCustom = 3 + + +}; +typedef int XPLMCursorStatus; +#endif /* XPLM200 */ + +/* + * XPLMWindowID + * + * This is an opaque identifier for a window. You use it to control your + * window. When you create a window, you will specify callbacks to handle + * drawing and mouse interaction, etc. + * + */ +typedef void *XPLMWindowID; + +/* + * XPLMDrawWindow_f + * + * This function handles drawing. You are passed in your window and its + * refcon. Draw the window. You can use XPLM functions to find the current + * dimensions of your window, etc. When this callback is called, the OpenGL + * context will be set properly for cockpit drawing. NOTE: Because you are + * drawing your window over a background, you can make a translucent window + * easily by simply not filling in your entire window's bounds. + * + */ +typedef void (*XPLMDrawWindow_f)(XPLMWindowID inWindowID, void *inRefcon); + +/* + * XPLMHandleKey_f + * + * This function is called when a key is pressed or keyboard focus is taken + * away from your window. If losingFocus is 1, you are losign the keyboard + * focus, otherwise a key was pressed and inKey contains its character. You + * are also passewd your window and a refcon. Warning: this API declares + * virtual keys as a signed character; however the VKEY #define macros in + * XPLMDefs.h define the vkeys using unsigned values (that is 0x80 instead of + * -0x80). So you may need to cast the incoming vkey to an unsigned char to + * get correct comparisons in C. + * + */ +typedef void (*XPLMHandleKey_f)(XPLMWindowID inWindowID, + char inKey, + XPLMKeyFlags inFlags, + char inVirtualKey, + void *inRefcon, + int losingFocus); + +/* + * XPLMHandleMouseClick_f + * + * You receive this call when the mouse button is pressed down or released. + * Between then these two calls is a drag. You receive the x and y of the + * click, your window, and a refcon. Return 1 to consume the click, or 0 to + * pass it through. + * + * WARNING: passing clicks through windows (as of this writing) causes mouse + * tracking problems in X-Plane; do not use this feature! + * + */ +typedef int (*XPLMHandleMouseClick_f)(XPLMWindowID inWindowID, + int x, + int y, + XPLMMouseStatus inMouse, + void *inRefcon); + +#if defined(XPLM200) +/* + * XPLMHandleCursor_f + * + * The SDK calls your cursor status callback when the mouse is over your + * plugin window. Return a cursor status code to indicate how you would like + * X-Plane to manage the cursor. If you return xplm_CursorDefault, the SDK + * will try lower-Z-order plugin windows, then let the sim manage the cursor. + * + * Note: you should never show or hide the cursor yourself - these APIs are + * typically reference-counted and thus cannot safely and predictably be used + * by the SDK. Instead return one of xplm_CursorHidden to hide the cursor or + * xplm_CursorArrow/xplm_CursorCustom to show the cursor. + * + * If you want to implement a custom cursor by drawing a cursor in OpenGL, use + * xplm_CursorHidden to hide the OS cursor and draw the cursor using a 2-d + * drawing callback (after xplm_Phase_Window is probably a good choice). If + * you want to use a custom OS-based cursor, use xplm_CursorCustom to ask + * X-Plane to show the cursor but not affect its image. You can then use an + * OS specific call like SetThemeCursor (Mac) or SetCursor/LoadCursor + * (Windows). + * + */ +typedef XPLMCursorStatus (*XPLMHandleCursor_f)(XPLMWindowID inWindowID, + int x, + int y, + void *inRefcon); +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMHandleMouseWheel_f + * + * The SDK calls your mouse wheel callback when one of the mouse wheels is + * turned within your window. Return 1 to consume the mouse wheel clicks or + * 0 to pass them on to a lower window. (You should consume mouse wheel + * clicks even if they do nothing if your window appears opaque to the user.) + * The number of clicks indicates how far the wheel was turned since the last + * callback. The wheel is 0 for the vertical axis or 1 for the horizontal axis + * (for OS/mouse combinations that support this). + * + */ +typedef int (*XPLMHandleMouseWheel_f)(XPLMWindowID inWindowID, + int x, + int y, + int wheel, + int clicks, + void *inRefcon); +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMCreateWindow_t + * + * The XPMCreateWindow_t structure defines all of the parameters used to + * create a window using XPLMCreateWindowEx. The structure will be expanded + * in future SDK APIs to include more features. Always set the structSize + * member to the size of your struct in bytes! + * + */ +typedef struct { + int structSize; + int left; + int top; + int right; + int bottom; + int visible; + XPLMDrawWindow_f drawWindowFunc; + XPLMHandleMouseClick_f handleMouseClickFunc; + XPLMHandleKey_f handleKeyFunc; + XPLMHandleCursor_f handleCursorFunc; + XPLMHandleMouseWheel_f handleMouseWheelFunc; + void *refcon; +} XPLMCreateWindow_t; +#endif /* XPLM200 */ + +/* + * XPLMGetScreenSize + * + * This routine returns the size of the size of the X-Plane OpenGL window in + * pixels. Please note that this is not the size of the screen when doing + * 2-d drawing (the 2-d screen is currently always 1024x768, and graphics are + * scaled up by OpenGL when doing 2-d drawing for higher-res monitors). This + * number can be used to get a rough idea of the amount of detail the user + * will be able to see when drawing in 3-d. + * + */ +XPLM_API void XPLMGetScreenSize(int *outWidth, /* Can be NULL */ + int *outHeight); /* Can be NULL */ + +/* + * XPLMGetMouseLocation + * + * This routine returns the current mouse location in cockpit pixels. The + * bottom left corner of the display is 0,0. Pass NULL to not receive info + * about either parameter. + * + */ +XPLM_API void XPLMGetMouseLocation(int *outX, /* Can be NULL */ + int *outY); /* Can be NULL */ + +/* + * XPLMCreateWindow + * + * This routine creates a new window. Pass in the dimensions and offsets to + * the window's bottom left corner from the bottom left of the screen. You + * can specify whether the window is initially visible or not. Also, you pass + * in three callbacks to run the window and a refcon. This function returns a + * window ID you can use to refer to the new window. + * + * NOTE: windows do not have "frames"; you are responsible for drawing the + * background and frame of the window. Higher level libraries have routines + * which make this easy. + * + */ +XPLM_API XPLMWindowID XPLMCreateWindow(int inLeft, + int inTop, + int inRight, + int inBottom, + int inIsVisible, + XPLMDrawWindow_f inDrawCallback, + XPLMHandleKey_f inKeyCallback, + XPLMHandleMouseClick_f inMouseCallback, + void *inRefcon); + +#if defined(XPLM200) +/* + * XPLMCreateWindowEx + * + * This routine creates a new window - you pass in an XPLMCreateWindow_t + * structure with all of the fields set in. You must set the structSize of + * the structure to the size of the actual structure you used. Also, you + * must provide funtions for every callback - you may not leave them null! + * (If you do not support the cursor or mouse wheel, use functions that return + * the default values.) The numeric values of the XPMCreateWindow_t structure + * correspond to the parameters of XPLMCreateWindow. + * + */ +XPLM_API XPLMWindowID XPLMCreateWindowEx(XPLMCreateWindow_t *inParams); +#endif /* XPLM200 */ + +/* + * XPLMDestroyWindow + * + * This routine destroys a window. The callbacks are not called after this + * call. Keyboard focus is removed from the window before destroying it. + * + */ +XPLM_API void XPLMDestroyWindow(XPLMWindowID inWindowID); + +/* + * XPLMGetWindowGeometry + * + * This routine returns the position and size of a window in cockpit pixels. + * Pass NULL to not receive any paramter. + * + */ +XPLM_API void XPLMGetWindowGeometry(XPLMWindowID inWindowID, + int *outLeft, /* Can be NULL */ + int *outTop, /* Can be NULL */ + int *outRight, /* Can be NULL */ + int *outBottom); /* Can be NULL */ + +/* + * XPLMSetWindowGeometry + * + * This routine allows you to set the position or height aspects of a window. + * + */ +XPLM_API void XPLMSetWindowGeometry(XPLMWindowID inWindowID, + int inLeft, + int inTop, + int inRight, + int inBottom); + +/* + * XPLMGetWindowIsVisible + * + * This routine returns whether a window is visible. + * + */ +XPLM_API int XPLMGetWindowIsVisible(XPLMWindowID inWindowID); + +/* + * XPLMSetWindowIsVisible + * + * This routine shows or hides a window. + * + */ +XPLM_API void XPLMSetWindowIsVisible(XPLMWindowID inWindowID, int inIsVisible); + +/* + * XPLMGetWindowRefCon + * + * This routine returns a windows refcon, the unique value you can use for + * your own purposes. + * + */ +XPLM_API void *XPLMGetWindowRefCon(XPLMWindowID inWindowID); + +/* + * XPLMSetWindowRefCon + * + * This routine sets a window's reference constant. Use this to pass data to + * yourself in the callbacks. + * + */ +XPLM_API void XPLMSetWindowRefCon(XPLMWindowID inWindowID, void *inRefcon); + +/* + * XPLMTakeKeyboardFocus + * + * This routine gives a specific window keyboard focus. Keystrokes will be + * sent to that window. Pass a window ID of 0 to pass keyboard strokes + * directly to X-Plane. + * + */ +XPLM_API void XPLMTakeKeyboardFocus(XPLMWindowID inWindow); + +/* + * XPLMBringWindowToFront + * + * This routine brings the window to the front of the Z-order. Windows are + * brought to the front when they are created...beyond that you should make + * sure you are front before handling mouse clicks. + * + */ +XPLM_API void XPLMBringWindowToFront(XPLMWindowID inWindow); + +/* + * XPLMIsWindowInFront + * + * This routine returns true if you pass inthe ID of the frontmost visible + * window. + * + */ +XPLM_API int XPLMIsWindowInFront(XPLMWindowID inWindow); + +/*************************************************************************** + * HOT KEYS + ***************************************************************************/ +/* + * Hot Keys - keystrokes that can be managed by others. + * + */ + + +/* + * XPLMHotKey_f + * + * Your hot key callback simply takes a pointer of your choosing. + * + */ +typedef void (*XPLMHotKey_f)(void *inRefcon); + +/* + * XPLMHotKeyID + * + * Hot keys are identified by opaque IDs. + * + */ +typedef void *XPLMHotKeyID; + +/* + * XPLMRegisterHotKey + * + * This routine registers a hot key. You specify your preferred key stroke + * virtual key/flag combination, a description of what your callback does (so + * other plug-ins can describe the plug-in to the user for remapping) and a + * callback function and opaque pointer to pass in). A new hot key ID is + * returned. During execution, the actual key associated with your hot key + * may change, but you are insulated from this. + * + */ +XPLM_API XPLMHotKeyID XPLMRegisterHotKey(char inVirtualKey, + XPLMKeyFlags inFlags, + const char *inDescription, + XPLMHotKey_f inCallback, + void *inRefcon); + +/* + * XPLMUnregisterHotKey + * + * This API unregisters a hot key. You can only register your own hot keys. + * + */ +XPLM_API void XPLMUnregisterHotKey(XPLMHotKeyID inHotKey); + +/* + * XPLMCountHotKeys + * + * Returns the number of current hot keys. + * + */ +XPLM_API int XPLMCountHotKeys(void); + +/* + * XPLMGetNthHotKey + * + * Returns a hot key by index, for iteration on all hot keys. + * + */ +XPLM_API XPLMHotKeyID XPLMGetNthHotKey(int inIndex); + +/* + * XPLMGetHotKeyInfo + * + * Returns information about the hot key. Return NULL for any parameter you + * don't want info about. The description should be at least 512 chars long. + * + */ +XPLM_API void XPLMGetHotKeyInfo(XPLMHotKeyID inHotKey, + char *outVirtualKey, /* Can be NULL */ + XPLMKeyFlags *outFlags, /* Can be NULL */ + char *outDescription, /* Can be NULL */ + XPLMPluginID *outPlugin); /* Can be NULL */ + +/* + * XPLMSetHotKeyCombination + * + * XPLMSetHotKeyCombination remaps a hot keys keystrokes. You may remap + * another plugin's keystrokes. + * + */ +XPLM_API void XPLMSetHotKeyCombination(XPLMHotKeyID inHotKey, + char inVirtualKey, + XPLMKeyFlags inFlags); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMGraphics.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMGraphics.h new file mode 100644 index 0000000..0eb3630 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMGraphics.h @@ -0,0 +1,413 @@ +#ifndef _XPLMGraphics_h_ +#define _XPLMGraphics_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * Graphics routines for X-Plane and OpenGL. + * + * A few notes on coordinate systems: + * + * X-Plane uses three kinds of coordinates. Global coordinates are specified + * as latitude, longitude and elevation. This coordinate system never changes + * but is not very precise. + * + * OpenGL (or 'local') coordinates are cartesian and shift with the plane. + * They offer more precision and are used for 3-d OpenGL drawing. The X axis + * is aligned east-west with positive X meaning east. The Y axis is aligned + * straight up and down at the point 0,0,0 (but since the earth is round it is + * not truly straight up and down at other points). The Z axis is aligned + * north-south at 0, 0, 0 with positive Z pointing south (but since the earth + * is round it isn't exactly north-south as you move east or west of 0, 0, 0). + * One unit is one meter and the point 0,0,0 is on the surface of the earth + * at sea level for some latitude and longitude picked by the sim such that + * the user's aircraft is reasonably nearby. + * + * Cockpit coordinates are 2d, with the X axis horizontal and the Y axis + * vertical. The point 0,0 is the bottom left and 1024,768 is the upper right + * of the screen. This is true no matter what resolution the user's monitor is + * in; when running in higher resolution, graphics will be scaled. + * + * Use X-Plane's routines to convert between global and local coordinates. Do + * not attempt to do this conversion yourself; the precise 'roundness' of + * X-Plane's physics model may not match your own, and (to make things + * weirder) the user can potentially customize the physics of the current + * planet. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * X-PLANE GRAPHICS + ***************************************************************************/ +/* + * These routines allow you to use OpenGL with X-Plane. + * + */ + + +/* + * XPLMTextureID + * + * XPLM Texture IDs name well-known textures in the sim for you to use. This + * allows you to recycle textures from X-Plane, saving VRAM. + * + */ +enum { + /* The bitmap that contains window outlines, button outlines, fonts, etc. */ + xplm_Tex_GeneralInterface = 0 + + /* The exterior paint for the user's aircraft (daytime). */ + , + xplm_Tex_AircraftPaint = 1 + + /* The exterior light map for the user's aircraft. */ + , + xplm_Tex_AircraftLiteMap = 2 + + +}; +typedef int XPLMTextureID; + +/* + * XPLMSetGraphicsState + * + * XPLMSetGraphicsState changes OpenGL's graphics state in a number of ways: + * + * inEnableFog - enables or disables fog, equivalent to: glEnable(GL_FOG); + * + * inNumberTexUnits - enables or disables a number of multitexturing units. If + * the number is 0, 2d texturing is disabled entirely, as in + * glDisable(GL_TEXTURE_2D); Otherwise, 2d texturing is enabled, and a + * number of multitexturing units are enabled sequentially, starting with + * unit 0, e.g. glActiveTextureARB(GL_TEXTURE0_ARB); glEnable + * (GL_TEXTURE_2D); + * + * inEnableLighting - enables or disables OpenGL lighting, e.g. + * glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); + * + * inEnableAlphaTesting - enables or disables the alpha test per pixel, e.g. + * glEnable(GL_ALPHA_TEST); + * + * inEnableAlphaBlending - enables or disables alpha blending per pixel, e.g. + * glEnable(GL_BLEND); + * + * inEnableDepthTesting - enables per pixel depth testing, as in + * glEnable(GL_DEPTH_TEST); + * + * inEnableDepthWriting - enables writing back of depth information to the + * depth bufffer, as in glDepthMask(GL_TRUE); + * + * The purpose of this function is to change OpenGL state while keeping + * X-Plane aware of the state changes; this keeps X-Plane from getting + * surprised by OGL state changes, and prevents X-Plane and plug-ins from + * having to set all state before all draws; XPLMSetGraphicsState internally + * skips calls to change state that is already properly enabled. + * + * X-Plane does not have a 'default' OGL state to plug-ins; plug-ins should + * totally set OGL state before drawing. Use XPLMSetGraphicsState instead of + * any of the above OpenGL calls. + * + * WARNING: Any routine that performs drawing (e.g. XPLMDrawString or widget + * code) may change X-Plane's state. Always set state before drawing after + * unknown code has executed. + * + */ +XPLM_API void XPLMSetGraphicsState(int inEnableFog, + int inNumberTexUnits, + int inEnableLighting, + int inEnableAlphaTesting, + int inEnableAlphaBlending, + int inEnableDepthTesting, + int inEnableDepthWriting); + +/* + * XPLMBindTexture2d + * + * XPLMBindTexture2d changes what texture is bound to the 2d texturing target. + * This routine caches the current 2d texture across all texturing units in + * the sim and plug-ins, preventing extraneous binding. For example, consider + * several plug-ins running in series; if they all use the 'general interface' + * bitmap to do UI, calling this function will skip the rebinding of the + * general interface texture on all but the first plug-in, which can provide + * better frame rate son some graphics cards. + * + * inTextureID is the ID of the texture object to bind; inTextureUnit is a + * zero-based texture unit (e.g. 0 for the first one), up to a maximum of 4 + * units. (This number may increase in future versions of x-plane.) + * + * Use this routine instead of glBindTexture(GL_TEXTURE_2D, ....); + * + */ +XPLM_API void XPLMBindTexture2d(int inTextureNum, int inTextureUnit); + +/* + * XPLMGenerateTextureNumbers + * + * This routine generates unused texture numbers that a plug-in can use to + * safely bind textures. Use this routine instead of glGenTextures; + * glGenTextures will allocate texture numbers in ranges that X-Plane reserves + * for its own use but does not always use; for example, it might provide an + * ID within the range of textures reserved for terrain...loading a new .env + * file as the plane flies might then cause X-Plane to use this texture ID. + * X-Plane will then overwrite the plug-ins texture. This routine returns + * texture IDs that are out of X-Plane's usage range. + * + */ +XPLM_API void XPLMGenerateTextureNumbers(int *outTextureIDs, int inCount); + +/* + * XPLMGetTexture + * + * XPLMGetTexture returns the OpenGL texture enumeration of an X-Plane texture + * based on a generic identifying code. For example, you can get the texture + * for X-Plane's UI bitmaps. This allows you to build new gauges that take + * advantage of x-plane's textures, for smooth artwork integration and also + * saving texture memory. Note that the texture might not be loaded yet, + * depending on what the plane's panel contains. + * + * OPEN ISSUE: We really need a way to make sure X-Plane loads this texture if + * it isn't around, or at least a way to find out whether it is loaded or not. + * + */ +XPLM_API int XPLMGetTexture(XPLMTextureID inTexture); + +/* + * XPLMWorldToLocal + * + * This routine translates coordinates from latitude, longitude, and altitude + * to local scene coordinates. Latitude and longitude are in decimal degrees, + * and altitude is in meters MSL (mean sea level). The XYZ coordinates are in + * meters in the local OpenGL coordinate system. + * + */ +XPLM_API void XPLMWorldToLocal(double inLatitude, + double inLongitude, + double inAltitude, + double *outX, + double *outY, + double *outZ); + +/* + * XPLMLocalToWorld + * + * This routine translates a local coordinate triplet back into latitude, + * longitude, and altitude. Latitude and longitude are in decimal degrees, + * and altitude is in meters MSL (mean sea level). The XYZ coordinates are in + * meters in the local OpenGL coordinate system. + * + * NOTE: world coordinates are less precise than local coordinates; you should + * try to avoid round tripping from local to world and back. + * + */ +XPLM_API void XPLMLocalToWorld(double inX, + double inY, + double inZ, + double *outLatitude, + double *outLongitude, + double *outAltitude); + +/* + * XPLMDrawTranslucentDarkBox + * + * This routine draws a translucent dark box, partially obscuring parts of the + * screen but making text easy to read. This is the same graphics primitive + * used by X-Plane to show text files and ATC info. + * + */ +XPLM_API void XPLMDrawTranslucentDarkBox(int inLeft, + int inTop, + int inRight, + int inBottom); + +/*************************************************************************** + * X-PLANE TEXT + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPLMFontID + * + * X-Plane features some fixed-character fonts. Each font may have its own + * metrics. + * + * WARNING: Some of these fonts are no longer supported or may have changed + * geometries. For maximum copmatibility, see the comments below. + * + * Note: X-Plane 7 supports proportional-spaced fonts. Since no measuring + * routine is available yet, the SDK will normally draw using a fixed-width + * font. You can use a dataref to enable proportional font drawing on XP7 if + * you want to. + * + */ +enum { + /* Mono-spaced font for user interface. Available in all versions of the + SDK. */ + xplmFont_Basic = 0 + + /* Deprecated, do not use. */ + , + xplmFont_Menus = 1 + + /* Deprecated, do not use. */ + , + xplmFont_Metal = 2 + + /* Deprecated, do not use. */ + , + xplmFont_Led = 3 + + /* Deprecated, do not use. */ + , + xplmFont_LedWide = 4 + + /* Deprecated, do not use. */ + , + xplmFont_PanelHUD = 5 + + /* Deprecated, do not use. */ + , + xplmFont_PanelEFIS = 6 + + /* Deprecated, do not use. */ + , + xplmFont_PanelGPS = 7 + + /* Deprecated, do not use. */ + , + xplmFont_RadiosGA = 8 + + /* Deprecated, do not use. */ + , + xplmFont_RadiosBC = 9 + + /* Deprecated, do not use. */ + , + xplmFont_RadiosHM = 10 + + /* Deprecated, do not use. */ + , + xplmFont_RadiosGANarrow = 11 + + /* Deprecated, do not use. */ + , + xplmFont_RadiosBCNarrow = 12 + + /* Deprecated, do not use. */ + , + xplmFont_RadiosHMNarrow = 13 + + /* Deprecated, do not use. */ + , + xplmFont_Timer = 14 + + /* Deprecated, do not use. */ + , + xplmFont_FullRound = 15 + + /* Deprecated, do not use. */ + , + xplmFont_SmallRound = 16 + + /* Deprecated, do not use. */ + , + xplmFont_Menus_Localized = 17 + +#if defined(XPLM200) + /* Proportional UI font. */ + , + xplmFont_Proportional = 18 + +#endif /* XPLM200 */ + +}; +typedef int XPLMFontID; + +/* + * XPLMDrawString + * + * This routine draws a NULL termianted string in a given font. Pass in the + * lower left pixel that the character is to be drawn onto. Also pass the + * character and font ID. This function returns the x offset plus the width of + * all drawn characters. The color to draw in is specified as a pointer to an + * array of three floating point colors, representing RGB intensities from 0.0 + * to 1.0. + * + */ +XPLM_API void XPLMDrawString(float *inColorRGB, + int inXOffset, + int inYOffset, + char *inChar, + int *inWordWrapWidth, /* Can be NULL */ + XPLMFontID inFontID); + +/* + * XPLMDrawNumber + * + * This routine draws a number similar to the digit editing fields in + * PlaneMaker and data output display in X-Plane. Pass in a color, a + * position, a floating point value, and formatting info. Specify how many + * integer and how many decimal digits to show and whether to show a sign, as + * well as a character set. This routine returns the xOffset plus width of the + * string drawn. + * + */ +XPLM_API void XPLMDrawNumber(float *inColorRGB, + int inXOffset, + int inYOffset, + double inValue, + int inDigits, + int inDecimals, + int inShowSign, + XPLMFontID inFontID); + +/* + * XPLMGetFontDimensions + * + * This routine returns the width and height of a character in a given font. + * It also tells you if the font only supports numeric digits. Pass NULL if + * you don't need a given field. Note that for a proportional font the width + * will be an arbitrary, hopefully average width. + * + */ +XPLM_API void XPLMGetFontDimensions(XPLMFontID inFontID, + int *outCharWidth, /* Can be NULL */ + int *outCharHeight, /* Can be NULL */ + int *outDigitsOnly); /* Can be NULL */ + +#if defined(XPLM200) +/* + * XPLMMeasureString + * + * This routine returns the width in pixels of a string using a given font. + * The string is passed as a pointer plus length (and does not need to be null + * terminated); this is used to allow for measuring substrings. The return + * value is floating point; it is possible that future font drawing may allow + * for fractional pixels. + * + */ +XPLM_API float + XPLMMeasureString(XPLMFontID inFontID, const char *inChar, int inNumChars); +#endif /* XPLM200 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMMenus.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMMenus.h new file mode 100644 index 0000000..a94d7dd --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMMenus.h @@ -0,0 +1,210 @@ +#ifndef _XPLMMenus_h_ +#define _XPLMMenus_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * XPLMMenus - Theory of Operation + * + * Plug-ins can create menus in the menu bar of X-Plane. This is done by + * creating a menu and then creating items. Menus are referred to by an + * opaque ID. Items are referred to by index number. For each menu and item + * you specify a void *. Per menu you specify a handler function that is + * called with each void * when the menu item is picked. Menu item indices + * are zero based. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * XPLM MENUS + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPLMMenuCheck + * + * These enumerations define the various 'check' states for an X-Plane menu. + * 'checking' in x-plane actually appears as a light which may or may not be + * lit. So there are three possible states. + * + */ +enum { + /* there is no symbol to the left of the menu item. */ + xplm_Menu_NoCheck = 0 + + /* the menu has a mark next to it that is unmarked (not lit). */ + , + xplm_Menu_Unchecked = 1 + + /* the menu has a mark next to it that is checked (lit). */ + , + xplm_Menu_Checked = 2 + + +}; +typedef int XPLMMenuCheck; + +/* + * XPLMMenuID + * + * This is a unique ID for each menu you create. + * + */ +typedef void *XPLMMenuID; + +/* + * XPLMMenuHandler_f + * + * A menu handler function takes two reference pointers, one for the menu + * (specified when the menu was created) and one for the item (specified when + * the item was created). + * + */ +typedef void (*XPLMMenuHandler_f)(void *inMenuRef, void *inItemRef); + +/* + * XPLMFindPluginsMenu + * + * This function returns the ID of the plug-ins menu, which is created for you + * at startup. + * + */ +XPLM_API XPLMMenuID XPLMFindPluginsMenu(void); + +/* + * XPLMCreateMenu + * + * This function creates a new menu and returns its ID. It returns NULL if + * the menu cannot be created. Pass in a parent menu ID and an item index to + * create a submenu, or NULL for the parent menu to put the menu in the menu + * bar. The menu's name is only used if the menu is in the menubar. You also + * pass a handler function and a menu reference value. Pass NULL for the + * handler if you do not need callbacks from the menu (for example, if it only + * contains submenus). + * + * Important: you must pass a valid, non-empty menu title even if the menu is + * a submenu where the title is not visible. + * + */ +XPLM_API XPLMMenuID XPLMCreateMenu(const char *inName, + XPLMMenuID inParentMenu, + int inParentItem, + XPLMMenuHandler_f inHandler, + void *inMenuRef); + +/* + * XPLMDestroyMenu + * + * This function destroys a menu that you have created. Use this to remove a + * submenu if necessary. (Normally this function will not be necessary.) + * + */ +XPLM_API void XPLMDestroyMenu(XPLMMenuID inMenuID); + +/* + * XPLMClearAllMenuItems + * + * This function removes all menu items from a menu, allowing you to rebuild + * it. Use this function if you need to change the number of items on a menu. + * + */ +XPLM_API void XPLMClearAllMenuItems(XPLMMenuID inMenuID); + +/* + * XPLMAppendMenuItem + * + * This routine appends a new menu item to the bottom of a menu and returns + * its index. Pass in the menu to add the item to, the items name, and a void + * * ref for this item. If you pass in inForceEnglish, this menu item will be + * drawn using the english character set no matter what language x-plane is + * running in. Otherwise the menu item will be drawn localized. (An example + * of why you'd want to do this is for a proper name.) See XPLMUtilities for + * determining the current langauge. + * + */ +XPLM_API int XPLMAppendMenuItem(XPLMMenuID inMenu, + const char *inItemName, + void *inItemRef, + int inForceEnglish); + +/* + * XPLMAppendMenuSeparator + * + * This routine adds a seperator to the end of a menu. + * + */ +XPLM_API void XPLMAppendMenuSeparator(XPLMMenuID inMenu); + +/* + * XPLMSetMenuItemName + * + * This routine changes the name of an existing menu item. Pass in the menu + * ID and the index of the menu item. + * + */ +XPLM_API void XPLMSetMenuItemName(XPLMMenuID inMenu, + int inIndex, + const char *inItemName, + int inForceEnglish); + +/* + * XPLMCheckMenuItem + * + * Set whether a menu item is checked. Pass in the menu ID and item index. + * + */ +XPLM_API void + XPLMCheckMenuItem(XPLMMenuID inMenu, int index, XPLMMenuCheck inCheck); + +/* + * XPLMCheckMenuItemState + * + * This routine returns whether a menu item is checked or not. A menu item's + * check mark may be on or off, or a menu may not have an icon at all. + * + */ +XPLM_API void XPLMCheckMenuItemState(XPLMMenuID inMenu, + int index, + XPLMMenuCheck *outCheck); + +/* + * XPLMEnableMenuItem + * + * Sets whether this menu item is enabled. Items start out enabled. + * + */ +XPLM_API void XPLMEnableMenuItem(XPLMMenuID inMenu, int index, int enabled); + +#if defined(XPLM210) +/* + * XPLMRemoveMenuItem + * + * Removes one item from a menu. Note that all menu items below are moved up + * one; your plugin must track the change in index numbers. + * + */ +XPLM_API void XPLMRemoveMenuItem(XPLMMenuID inMenu, int inIndex); +#endif /* XPLM210 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMNavigation.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMNavigation.h new file mode 100644 index 0000000..8bdbde2 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMNavigation.h @@ -0,0 +1,373 @@ +#ifndef _XPLMNavigation_h_ +#define _XPLMNavigation_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * XPLMNavigation - THEORY OF OPERATION + * + * The XPLM Navigation APIs give you some access to the navigation databases + * inside X-Plane. X-Plane stores all navigation information in RAM, so by + * using these APIs you can gain access to most information without having to + * go to disk or parse the files yourself. + * + * You can also use this API to program the FMS. You must use the navigation + * APIs to find the nav-aids you want to program into the FMS, since the FMS + * is powered internally by x-plane's navigation database. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * NAVIGATION DATABASE ACCESS + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPLMNavType + * + * These enumerations define the different types of navaids. They are each + * defined with a separate bit so that they may be bit-wise added together to + * form sets of nav-aid types. + * + * NOTE: xplm_Nav_LatLon is a specific lat-lon coordinate entered into the + * FMS. It will not exist in the database, and cannot be programmed into the + * FMS. Querying the FMS for navaids will return it. Use + * XPLMSetFMSEntryLatLon to set a lat/lon waypoint. + * + */ +enum { + xplm_Nav_Unknown = 0 + + , + xplm_Nav_Airport = 1 + + , + xplm_Nav_NDB = 2 + + , + xplm_Nav_VOR = 4 + + , + xplm_Nav_ILS = 8 + + , + xplm_Nav_Localizer = 16 + + , + xplm_Nav_GlideSlope = 32 + + , + xplm_Nav_OuterMarker = 64 + + , + xplm_Nav_MiddleMarker = 128 + + , + xplm_Nav_InnerMarker = 256 + + , + xplm_Nav_Fix = 512 + + , + xplm_Nav_DME = 1024 + + , + xplm_Nav_LatLon = 2048 + + +}; +typedef int XPLMNavType; + +/* + * XPLMNavRef + * + * XPLMNavRef is an iterator into the navigation database. The navigation + * database is essentially an array, but it is not necessarily densely + * populated. The only assumption you can safely make is that like-typed + * nav-aids are grouped together. + * + * Use XPLMNavRef to refer to a nav-aid. + * + * XPLM_NAV_NOT_FOUND is returned by functions that return an XPLMNavRef when + * the iterator must be invalid. + * + */ +typedef int XPLMNavRef; + +#define XPLM_NAV_NOT_FOUND -1 + +/* + * XPLMGetFirstNavAid + * + * This returns the very first navaid in the database. Use this to traverse + * the entire database. Returns XPLM_NAV_NOT_FOUND if the nav database is + * empty. + * + */ +XPLM_API XPLMNavRef XPLMGetFirstNavAid(void); + +/* + * XPLMGetNextNavAid + * + * Given a nav aid ref, this routine returns the next navaid. It returns + * XPLM_NAV_NOT_FOUND if the nav aid passed in was invalid or if the navaid + * passed in was the last one in the database. Use this routine to iterate + * across all like-typed navaids or the entire database. + * + * WARNING: due to a bug in the SDK, when fix loading is disabled in the + * rendering settings screen, calling this routine with the last airport + * returns a bogus nav aid. Using this nav aid can crash x-plane. + * + */ +XPLM_API XPLMNavRef XPLMGetNextNavAid(XPLMNavRef inNavAidRef); + +/* + * XPLMFindFirstNavAidOfType + * + * This routine returns the ref of the first navaid of the given type in the + * database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the + * database. You must pass exactly one nav aid type to this routine. + * + * WARNING: due to a bug in the SDK, when fix loading is disabled in the + * rendering settings screen, calling this routine with fixes returns a bogus + * nav aid. Using this nav aid can crash x-plane. + * + */ +XPLM_API XPLMNavRef XPLMFindFirstNavAidOfType(XPLMNavType inType); + +/* + * XPLMFindLastNavAidOfType + * + * This routine returns the ref of the last navaid of the given type in the + * database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the + * database. You must pass exactly one nav aid type to this routine. + * + * WARNING: due to a bug in the SDK, when fix loading is disabled in the + * rendering settings screen, calling this routine with fixes returns a bogus + * nav aid. Using this nav aid can crash x-plane. + * + */ +XPLM_API XPLMNavRef XPLMFindLastNavAidOfType(XPLMNavType inType); + +/* + * XPLMFindNavAid + * + * This routine provides a number of searching capabilities for the nav + * database. XPLMFindNavAid will search through every nav aid whose type is + * within inType (multiple types may be added together) and return any + * nav-aids found based on the following rules: + * + * If inLat and inLon are not NULL, the navaid nearest to that lat/lon will be + * returned, otherwise the last navaid found will be returned. + * + * If inFrequency is not NULL, then any navaids considered must match this + * frequency. Note that this will screen out radio beacons that do not have + * frequency data published (like inner markers) but not fixes and airports. + * + * If inNameFragment is not NULL, only navaids that contain the fragment in + * their name will be returned. + * + * If inIDFragment is not NULL, only navaids that contain the fragment in + * their IDs will be returned. + * + * This routine provides a simple way to do a number of useful searches: + * + * Find the nearest navaid on this frequency. Find the nearest airport. Find + * the VOR whose ID is "KBOS". Find the nearest airport whose name contains + * "Chicago". + * + */ +XPLM_API XPLMNavRef XPLMFindNavAid(const char *inNameFragment, /* Can be NULL */ + const char *inIDFragment, /* Can be NULL */ + float *inLat, /* Can be NULL */ + float *inLon, /* Can be NULL */ + int *inFrequency, /* Can be NULL */ + XPLMNavType inType); + +/* + * XPLMGetNavAidInfo + * + * This routine returns information about a navaid. Any non-null field is + * filled out with information if it is available. + * + * Frequencies are in the nav.dat convention as described in the X-Plane nav + * database FAQ: NDB frequencies are exact, all others are multiplied by 100. + * + * The buffer for IDs should be at least 6 chars and the buffer for names + * should be at least 41 chars, but since these values are likely to go up, I + * recommend passing at least 32 chars for IDs and 256 chars for names when + * possible. + * + * The outReg parameter tells if the navaid is within the local "region" of + * loaded DSFs. (This information may not be particularly useful to plugins.) + * The parameter is a single byte value 1 for true or 0 for false, not a C + * string. + * + */ +XPLM_API void XPLMGetNavAidInfo(XPLMNavRef inRef, + XPLMNavType *outType, /* Can be NULL */ + float *outLatitude, /* Can be NULL */ + float *outLongitude, /* Can be NULL */ + float *outHeight, /* Can be NULL */ + int *outFrequency, /* Can be NULL */ + float *outHeading, /* Can be NULL */ + char *outID, /* Can be NULL */ + char *outName, /* Can be NULL */ + char *outReg); /* Can be NULL */ + +/*************************************************************************** + * FLIGHT MANAGEMENT COMPUTER + ***************************************************************************/ +/* + * Note: the FMS works based on an array of entries. Indices into the array + * are zero-based. Each entry is a nav-aid plus an altitude. The FMS tracks + * the currently displayed entry and the entry that it is flying to. + * + * The FMS must be programmed with contiguous entries, so clearing an entry at + * the end shortens the effective flight plan. There is a max of 100 + * waypoints in the flight plan. + * + */ + + +/* + * XPLMCountFMSEntries + * + * This routine returns the number of entries in the FMS. + * + */ +XPLM_API int XPLMCountFMSEntries(void); + +/* + * XPLMGetDisplayedFMSEntry + * + * This routine returns the index of the entry the pilot is viewing. + * + */ +XPLM_API int XPLMGetDisplayedFMSEntry(void); + +/* + * XPLMGetDestinationFMSEntry + * + * This routine returns the index of the entry the FMS is flying to. + * + */ +XPLM_API int XPLMGetDestinationFMSEntry(void); + +/* + * XPLMSetDisplayedFMSEntry + * + * This routine changes which entry the FMS is showing to the index specified. + * * + */ +XPLM_API void XPLMSetDisplayedFMSEntry(int inIndex); + +/* + * XPLMSetDestinationFMSEntry + * + * This routine changes which entry the FMS is flying the aircraft toward. + * + */ +XPLM_API void XPLMSetDestinationFMSEntry(int inIndex); + +/* + * XPLMGetFMSEntryInfo + * + * This routine returns information about a given FMS entry. A reference to a + * navaid can be returned allowing you to find additional information (such as + * a frequency, ILS heading, name, etc.). Some information is available + * immediately. For a lat/lon entry, the lat/lon is returned by this routine + * but the navaid cannot be looked up (and the reference will be + * XPLM_NAV_NOT_FOUND. FMS name entry buffers should be at least 256 chars in + * length. + * + */ +XPLM_API void XPLMGetFMSEntryInfo(int inIndex, + XPLMNavType *outType, /* Can be NULL */ + char *outID, /* Can be NULL */ + XPLMNavRef *outRef, /* Can be NULL */ + int *outAltitude, /* Can be NULL */ + float *outLat, /* Can be NULL */ + float *outLon); /* Can be NULL */ + +/* + * XPLMSetFMSEntryInfo + * + * This routine changes an entry in the FMS to have the destination navaid + * passed in and the altitude specified. Use this only for airports, fixes, + * and radio-beacon navaids. Currently of radio beacons, the FMS can only + * support VORs and NDBs. Use the routines below to clear or fly to a lat/lon. + * + */ +XPLM_API void + XPLMSetFMSEntryInfo(int inIndex, XPLMNavRef inRef, int inAltitude); + +/* + * XPLMSetFMSEntryLatLon + * + * This routine changes the entry in the FMS to a lat/lon entry with the given + * coordinates. + * + */ +XPLM_API void XPLMSetFMSEntryLatLon(int inIndex, + float inLat, + float inLon, + int inAltitude); + +/* + * XPLMClearFMSEntry + * + * This routine clears the given entry, potentially shortening the flight + * plan. + * + */ +XPLM_API void XPLMClearFMSEntry(int inIndex); + +/*************************************************************************** + * GPS RECEIVER + ***************************************************************************/ +/* + * These APIs let you read data from the GPS unit. + * + */ + + +/* + * XPLMGetGPSDestinationType + * + * This routine returns the type of the currently selected GPS destination, + * one of fix, airport, VOR or NDB. + * + */ +XPLM_API XPLMNavType XPLMGetGPSDestinationType(void); + +/* + * XPLMGetGPSDestination + * + * This routine returns the current GPS destination. + * + */ +XPLM_API XPLMNavRef XPLMGetGPSDestination(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMPlanes.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMPlanes.h new file mode 100644 index 0000000..4b4d3a5 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMPlanes.h @@ -0,0 +1,245 @@ +#ifndef _XPLMPlanes_h_ +#define _XPLMPlanes_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * The XPLMPlanes APIs allow you to control the various aircraft in x-plane, + * both the user's and the sim's. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * USER AIRCRAFT ACCESS + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPLMSetUsersAircraft + * + * This routine changes the user's aircraft. Note that this will reinitialize + * the user to be on the nearest airport's first runway. Pass in a full path + * (hard drive and everything including the .acf extension) to the .acf file. + * + */ +XPLM_API void XPLMSetUsersAircraft(const char *inAircraftPath); +/* + * XPLMPlaceUserAtAirport + * + * This routine places the user at a given airport. Specify the airport by + * its ICAO code (e.g. 'KBOS'). + * + */ +XPLM_API void XPLMPlaceUserAtAirport(const char *inAirportCode); +/*************************************************************************** + * GLOBAL AIRCRAFT ACCESS + ***************************************************************************/ +/* + * + * + */ + + +/* The user's aircraft is always index 0. */ +#define XPLM_USER_AIRCRAFT 0 +/* + * XPLMPlaneDrawState_t + * + * This structure contains additional plane parameter info to be passed to + * draw plane. Make sure to fill in the size of the structure field with + * sizeof(XPLMDrawPlaneState_t) so that the XPLM can tell how many fields you + * knew about when compiling your plugin (since more fields may be added + * later). + * + * Most of these fields are ratios from 0 to 1 for control input. X-Plane + * calculates what the actual controls look like based on the .acf file for + * that airplane. Note for the yoke inputs, this is what the pilot of the + * plane has commanded (post artificial stability system if there were one) + * and affects aelerons, rudder, etc. It is not necessarily related to the + * actual position of the plane! + * + */ +typedef struct { + /* The size of the draw state struct. */ + int structSize; + /* A ratio from [0..1] describing how far the landing gear is extended. */ + float gearPosition; + /* Ratio of flap deployment, 0 = up, 1 = full deploy. */ + float flapRatio; + /* Ratio of spoiler deployment, 0 = none, 1 = full deploy. */ + float spoilerRatio; + /* Ratio of speed brake deployment, 0 = none, 1 = full deploy. */ + float speedBrakeRatio; + /* Ratio of slat deployment, 0 = none, 1 = full deploy. */ + float slatRatio; + /* Wing sweep ratio, 0 = forward, 1 = swept. */ + float wingSweep; + /* Thrust power, 0 = none, 1 = full fwd, -1 = full reverse. */ + float thrust; + /* Total pitch input for this plane. */ + float yokePitch; + /* Total Heading input for this plane. */ + float yokeHeading; + /* Total Roll input for this plane. */ + float yokeRoll; +} XPLMPlaneDrawState_t; +/* + * XPLMCountAircraft + * + * This function returns the number of aircraft X-Plane is capable of having, + * as well as the number of aircraft that are currently active. These numbers + * count the user's aircraft. It can also return the plugin that is currently + * controlling aircraft. In X-Plane 7, this routine reflects the number of + * aircraft the user has enabled in the rendering options window. + * + */ +XPLM_API void XPLMCountAircraft(int *outTotalAircraft, + int *outActiveAircraft, + XPLMPluginID *outController); +/* + * XPLMGetNthAircraftModel + * + * This function returns the aircraft model for the Nth aircraft. Indices are + * zero based, with zero being the user's aircraft. The file name should be + * at least 256 chars in length; the path should be at least 512 chars in + * length. + * + */ +XPLM_API void + XPLMGetNthAircraftModel(int inIndex, char *outFileName, char *outPath); +/*************************************************************************** + * EXCLUSIVE AIRCRAFT ACCESS + ***************************************************************************/ +/* + * The following routines require exclusive access to the airplane APIs. Only + * one plugin may have this access at a time. + * + */ + + +/* + * XPLMPlanesAvailable_f + * + * Your airplanes available callback is called when another plugin gives up + * access to the multiplayer planes. Use this to wait for access to + * multiplayer. + * + */ +typedef void (*XPLMPlanesAvailable_f)(void *inRefcon); + +/* + * XPLMAcquirePlanes + * + * XPLMAcquirePlanes grants your plugin exclusive access to the aircraft. It + * returns 1 if you gain access, 0 if you do not. inAircraft - pass in an + * array of pointers to strings specifying the planes you want loaded. For + * any plane index you do not want loaded, pass a 0-length string. Other + * strings should be full paths with the .acf extension. NULL terminates this + * array, or pass NULL if there are no planes you want loaded. If you pass in + * a callback and do not receive access to the planes your callback will be + * called when the airplanes are available. If you do receive airplane access, + * your callback will not be called. + * + */ +XPLM_API int XPLMAcquirePlanes(char **inAircraft, /* Can be NULL */ + XPLMPlanesAvailable_f inCallback, + void *inRefcon); + +/* + * XPLMReleasePlanes + * + * Call this function to release access to the planes. Note that if you are + * disabled, access to planes is released for you and you must reacquire it. + * + */ +XPLM_API void XPLMReleasePlanes(void); + +/* + * XPLMSetActiveAircraftCount + * + * This routine sets the number of active planes. If you pass in a number + * higher than the total number of planes availables, only the total number of + * planes available is actually used. + * + */ +XPLM_API void XPLMSetActiveAircraftCount(int inCount); + +/* + * XPLMSetAircraftModel + * + * This routine loads an aircraft model. It may only be called if you have + * exclusive access to the airplane APIs. Pass in the path of the model with + * the .acf extension. The index is zero based, but you may not pass in 0 + * (use XPLMSetUsersAircraft to load the user's aircracft). + * + */ +XPLM_API void XPLMSetAircraftModel(int inIndex, const char *inAircraftPath); + +/* + * XPLMDisableAIForPlane + * + * This routine turns off X-Plane's AI for a given plane. The plane will + * continue to draw and be a real plane in X-Plane, but will not move itself. + * + */ +XPLM_API void XPLMDisableAIForPlane(int inPlaneIndex); + +/* + * XPLMDrawAircraft + * + * This routine draws an aircraft. It can only be called from a 3-d drawing + * callback. Pass in the position of the plane in OpenGL local coordinates + * and the orientation of the plane. A 1 for full drawing indicates that the + * whole plane must be drawn; a 0 indicates you only need the nav lights + * drawn. (This saves rendering time when planes are far away.) + * + */ +XPLM_API void XPLMDrawAircraft(int inPlaneIndex, + float inX, + float inY, + float inZ, + float inPitch, + float inRoll, + float inYaw, + int inFullDraw, + XPLMPlaneDrawState_t *inDrawStateInfo); + +/* + * XPLMReinitUsersPlane + * + * This function recomputes the derived flight model data from the aircraft + * structure in memory. If you have used the data access layer to modify the + * aircraft structure, use this routine to resynchronize x-plane; since + * X-plane works at least partly from derived values, the sim will not behave + * properly until this is called. + * + * WARNING: this routine does not necessarily place the airplane at the + * airport; use XPLMSetUsersAircraft to be compatible. This routine is + * provided to do special experimentation with flight models without resetting + * flight. + * + */ +XPLM_API void XPLMReinitUsersPlane(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMPlugin.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMPlugin.h new file mode 100644 index 0000000..8080a94 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMPlugin.h @@ -0,0 +1,311 @@ +#ifndef _XPLMPlugin_h_ +#define _XPLMPlugin_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * These APIs provide facilities to find and work with other plugins and + * manage other plugins. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * FINDING PLUGINS + ***************************************************************************/ +/* + * These APIs allow you to find another plugin or yourself, or iterate across + * all plugins. For example, if you wrote an FMS plugin that needed to talk + * to an autopilot plugin, you could use these APIs to locate the autopilot + * plugin. + * + */ + + +/* + * XPLMGetMyID + * + * This routine returns the plugin ID of the calling plug-in. Call this to + * get your own ID. + * + */ +XPLM_API XPLMPluginID XPLMGetMyID(void); + +/* + * XPLMCountPlugins + * + * This routine returns the total number of plug-ins that are loaded, both + * disabled and enabled. + * + */ +XPLM_API int XPLMCountPlugins(void); + +/* + * XPLMGetNthPlugin + * + * This routine returns the ID of a plug-in by index. Index is 0 based from 0 + * to XPLMCountPlugins-1, inclusive. Plugins may be returned in any arbitrary + * order. + * + */ +XPLM_API XPLMPluginID XPLMGetNthPlugin(int inIndex); + +/* + * XPLMFindPluginByPath + * + * This routine returns the plug-in ID of the plug-in whose file exists at the + * passed in absolute file system path. XPLM_NO_PLUGIN_ID is returned if the + * path does not point to a currently loaded plug-in. + * + */ +XPLM_API XPLMPluginID XPLMFindPluginByPath(const char *inPath); + +/* + * XPLMFindPluginBySignature + * + * This routine returns the plug-in ID of the plug-in whose signature matches + * what is passed in or XPLM_NO_PLUGIN_ID if no running plug-in has this + * signature. Signatures are the best way to identify another plug-in as they + * are independent of the file system path of a plug-in or the human-readable + * plug-in name, and should be unique for all plug-ins. Use this routine to + * locate another plugin that your plugin interoperates with + * + */ +XPLM_API XPLMPluginID XPLMFindPluginBySignature(const char *inSignature); + +/* + * XPLMGetPluginInfo + * + * This routine returns information about a plug-in. Each parameter should be + * a pointer to a buffer of at least 256 characters, or NULL to not receive + * the information. + * + * outName - the human-readable name of the plug-in. outFilePath - the + * absolute file path to the file that contains this plug-in. outSignature - a + * unique string that identifies this plug-in. outDescription - a + * human-readable description of this plug-in. + * + */ +XPLM_API void XPLMGetPluginInfo(XPLMPluginID inPlugin, + char *outName, /* Can be NULL */ + char *outFilePath, /* Can be NULL */ + char *outSignature, /* Can be NULL */ + char *outDescription); /* Can be NULL */ + +/*************************************************************************** + * ENABLING/DISABLING PLUG-INS + ***************************************************************************/ +/* + * These routines are used to work with plug-ins and manage them. Most + * plugins will not need to use these APIs. + * + */ + + +/* + * XPLMIsPluginEnabled + * + * Returns whether the specified plug-in is enabled for running. + * + */ +XPLM_API int XPLMIsPluginEnabled(XPLMPluginID inPluginID); + +/* + * XPLMEnablePlugin + * + * This routine enables a plug-in if it is not already enabled. It returns 1 + * if the plugin was enabled or successfully enables itself, 0 if it does not. + * Plugins may fail to enable (for example, if resources cannot be acquired) + * by returning 0 from their XPluginEnable callback. + * + */ +XPLM_API int XPLMEnablePlugin(XPLMPluginID inPluginID); + +/* + * XPLMDisablePlugin + * + * This routine disableds an enabled plug-in. + * + */ +XPLM_API void XPLMDisablePlugin(XPLMPluginID inPluginID); + +/* + * XPLMReloadPlugins + * + * This routine reloads all plug-ins. Once this routine is called and you + * return from the callback you were within (e.g. a menu select callback) you + * will receive your XPluginDisable and XPluginStop callbacks and your DLL + * will be unloaded, then the start process happens as if the sim was starting + * up. + * + */ +XPLM_API void XPLMReloadPlugins(void); + +/*************************************************************************** + * INTERPLUGIN MESSAGING + ***************************************************************************/ +/* + * Plugin messages are defined as 32-bit integers. Messages below 0x00FFFFFF + * are reserved for X-Plane and the plugin SDK. + * + * Messages have two conceptual uses: notifications and commands. Commands + * are sent from one plugin to another to induce behavior; notifications are + * sent from one plugin to all others for informational purposes. It is + * important that commands and notifications not have the same values because + * this could cause a notification sent by one plugin to accidentally induce a + * command in another. + * + * By convention, plugin-defined notifications should have the high bit set + * (e.g. be greater or equal to unsigned 0x8000000) while commands should have + * this bit be cleared. + * + * The following messages are sent to your plugin by x-plane. + * + */ + + +/* This message is sent to your plugin whenever the user's plane crashes. */ +#define XPLM_MSG_PLANE_CRASHED 101 + +/* This message is sent to your plugin whenever a new plane is loaded. The * + * parameter is the number of the plane being loaded; 0 indicates the user's * + * plane. */ +#define XPLM_MSG_PLANE_LOADED 102 + +/* This messages is called whenever the user's plane is positioned at a new * + * airport. */ +#define XPLM_MSG_AIRPORT_LOADED 103 + +/* This message is sent whenever new scenery is loaded. Use datarefs to * + * determine the new scenery files that were loaded. */ +#define XPLM_MSG_SCENERY_LOADED 104 + +/* This message is sent whenever the user adjusts the number of X-Plane * + * aircraft models. You must use XPLMCountPlanes to find out how many planes * + * are now available. This message will only be sent in XP7 and higher * + * because in XP6 the number of aircraft is not user-adjustable. */ +#define XPLM_MSG_AIRPLANE_COUNT_CHANGED 105 + +#if defined(XPLM200) +/* This message is sent to your plugin whenever a plane is unloaded. The * + * parameter is the number of the plane being unloaded; 0 indicates the user's * + * plane. The parameter is of type int, passed as the value of the pointer. * + * (That is: the parameter is an int, not a pointer to an int.) */ +#define XPLM_MSG_PLANE_UNLOADED 106 +#endif /* XPLM200 */ + +#if defined(XPLM210) +/* This message is sent to your plugin right before X-Plane writes its * + * preferences file. You can use this for two purposes: to write your own * + * preferences, and to modify any datarefs to influence preferences output. * + * For example, if your plugin temporarily modifies saved preferences, you can * + * put them back to their default values here to avoid having the tweaks be * + * persisted if your plugin is not loaded on the next invocation of X-Plane. */ +#define XPLM_MSG_WILL_WRITE_PREFS 107 +#endif /* XPLM210 */ + +#if defined(XPLM210) +/* This message is sent to your plugin right after a livery is loaded for an * + * airplane. You can use this to check the new livery (via datarefs) and * + * react accordingly. The parameter is of type int, passed as the value of a * + * pointer and represents the aicraft plane number - 0 is the user's plane. */ +#define XPLM_MSG_LIVERY_LOADED 108 +#endif /* XPLM210 */ + +/* + * XPLMSendMessageToPlugin + * + * This function sends a message to another plug-in or X-Plane. Pass + * XPLM_NO_PLUGIN_ID to broadcast to all plug-ins. Only enabled plug-ins with + * a message receive function receive the message. + * + */ +XPLM_API void XPLMSendMessageToPlugin(XPLMPluginID inPlugin, + int inMessage, + void *inParam); + +#if defined(XPLM200) +/*************************************************************************** + * Plugin Features API + ***************************************************************************/ +/* + * The plugin features API allows your plugin to "sign up" for additional + * capabilities and plugin system features that are normally disabled for + * backward compatibility. This allows advanced plugins to "opt-in" to new + * behavior. + * + * Each feature is defined by a permanent string name. The feature string + * names will vary with the particular installation of X-Plane, so plugins + * should not expect a feature to be guaranteed present. + * + */ + + +/* + * XPLMFeatureEnumerator_f + * + * You pass an XPLMFeatureEnumerator_f to get a list of all features supported + * by a given version running version of X-Plane. This routine is called once + * for each feature. + * + */ +typedef void (*XPLMFeatureEnumerator_f)(const char *inFeature, void *inRef); + +/* + * XPLMHasFeature + * + * This returns 1 if the given installation of X-Plane supports a feature, or + * 0 if it does not. + * + */ +XPLM_API int XPLMHasFeature(const char *inFeature); + +/* + * XPLMIsFeatureEnabled + * + * This returns 1 if a feature is currently enabled for your plugin, or 0 if + * it is not enabled. It is an error to call this routine with an unsupported + * feature. + * + */ +XPLM_API int XPLMIsFeatureEnabled(const char *inFeature); + +/* + * XPLMEnableFeature + * + * This routine enables or disables a feature for your plugin. This will + * change the running behavior of X-Plane and your plugin in some way, + * depending on the feature. + * + */ +XPLM_API void XPLMEnableFeature(const char *inFeature, int inEnable); + +/* + * XPLMEnumerateFeatures + * + * This routine calls your enumerator callback once for each feature that this + * running version of X-Plane supports. Use this routine to determine all of + * the features that X-Plane can support. + * + */ +XPLM_API void XPLMEnumerateFeatures(XPLMFeatureEnumerator_f inEnumerator, + void *inRef); + +#endif /* XPLM200 */ +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMProcessing.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMProcessing.h new file mode 100644 index 0000000..5119449 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMProcessing.h @@ -0,0 +1,248 @@ +#ifndef _XPLMProcessing_h_ +#define _XPLMProcessing_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * This API allows you to get regular callbacks during the flight loop, the + * part of X-Plane where the plane's position calculates the physics of + * flight, etc. Use these APIs to accomplish periodic tasks like logging data + * and performing I/O. + * + * WARNING: Do NOT use these callbacks to draw! You cannot draw during flight + * loop callbacks. Use the drawing callbacks (see XPLMDisplay for more info) + * for graphics. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * FLIGHT LOOP CALLBACKS + ***************************************************************************/ +/* + * + * + */ + + +#if defined(XPLM210) +/* + * XPLMFlightLoopPhaseType + * + * You can register a flight loop callback to run either before or after the + * flight model is integrated by X-Plane. + * + */ +enum { + /* Your callback runs before X-Plane integrates the flight model. */ + xplm_FlightLoop_Phase_BeforeFlightModel = 0 + + /* Your callback runs after X-Plane integrates the flight model. */ + , + xplm_FlightLoop_Phase_AfterFlightModel = 1 + + +}; +typedef int XPLMFlightLoopPhaseType; +#endif /* XPLM210 */ + +#if defined(XPLM210) +/* + * XPLMFlightLoopID + * + * This is an opaque identifier for a flight loop callback. You can use this + * identifier to easily track and remove your callbacks, or to use the new + * flight loop APIs. + * + */ +typedef void *XPLMFlightLoopID; +#endif /* XPLM210 */ + +/* + * XPLMFlightLoop_f + * + * This is your flight loop callback. Each time the flight loop is iterated + * through, you receive this call at the end. You receive a time since you + * were last called and a time since the last loop, as well as a loop counter. + * The 'phase' parameter is deprecated and should be ignored. + * + * Your return value controls when you will next be called. Return 0 to stop + * receiving callbacks. Pass a positive number to specify how many seconds + * until the next callback. (You will be called at or after this time, not + * before.) Pass a negative number to specify how many loops must go by until + * you are called. For example, -1.0 means call me the very next loop. Try + * to run your flight loop as infrequently as is practical, and suspend it + * (using return value 0) when you do not need it; lots of flight loop + * callbacks that do nothing lowers x-plane's frame rate. + * + * Your callback will NOT be unregistered if you return 0; it will merely be + * inactive. + * + * The reference constant you passed to your loop is passed back to you. + * + */ +typedef float (*XPLMFlightLoop_f)(float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter, + void *inRefcon); + +#if defined(XPLM210) +/* + * XPLMCreateFlightLoop_t + * + * XPLMCreateFlightLoop_t contains the parameters to create a new flight loop + * callback. The strsucture can be expanded in future SDKs - always set + * structSize to the size of your structure in bytes. + * + */ +typedef struct { + int structSize; + XPLMFlightLoopPhaseType phase; + XPLMFlightLoop_f callbackFunc; + void *refcon; +} XPLMCreateFlightLoop_t; +#endif /* XPLM210 */ + +/* + * XPLMGetElapsedTime + * + * This routine returns the elapsed time since the sim started up in decimal + * seconds. + * + */ +XPLM_API float XPLMGetElapsedTime(void); + +/* + * XPLMGetCycleNumber + * + * This routine returns a counter starting at zero for each sim cycle + * computed/video frame rendered. + * + */ +XPLM_API int XPLMGetCycleNumber(void); + +/* + * XPLMRegisterFlightLoopCallback + * + * This routine registers your flight loop callback. Pass in a pointer to a + * flight loop function and a refcon. inInterval defines when you will be + * called. Pass in a positive number to specify seconds from registration + * time to the next callback. Pass in a negative number to indicate when you + * will be called (e.g. pass -1 to be called at the next cylcle). Pass 0 to + * not be called; your callback will be inactive. + * + */ +XPLM_API void XPLMRegisterFlightLoopCallback(XPLMFlightLoop_f inFlightLoop, + float inInterval, + void *inRefcon); + +/* + * XPLMUnregisterFlightLoopCallback + * + * This routine unregisters your flight loop callback. Do NOT call it from + * your flight loop callback. Once your flight loop callback is + * unregistered, it will not be called again. + * + */ +XPLM_API void XPLMUnregisterFlightLoopCallback(XPLMFlightLoop_f inFlightLoop, + void *inRefcon); + +/* + * XPLMSetFlightLoopCallbackInterval + * + * This routine sets when a callback will be called. Do NOT call it from your + * callback; use the return value of the callback to change your callback + * interval from inside your callback. + * + * inInterval is formatted the same way as in XPLMRegisterFlightLoopCallback; + * positive for seconds, negative for cycles, and 0 for deactivating the + * callback. If inRelativeToNow is 1, times are from the time of this call; + * otherwise they are from the time the callback was last called (or the time + * it was registered if it has never been called. + * + */ +XPLM_API void XPLMSetFlightLoopCallbackInterval(XPLMFlightLoop_f inFlightLoop, + float inInterval, + int inRelativeToNow, + void *inRefcon); + +#if defined(XPLM210) +/* + * XPLMCreateFlightLoop + * + * This routine creates a flight loop callback and returns its ID. The flight + * loop callback is created using the input param struct, and is inited to be + * unscheduled. + * + */ +XPLM_API XPLMFlightLoopID + XPLMCreateFlightLoop(XPLMCreateFlightLoop_t *inParams); +#endif /* XPLM210 */ + +#if defined(XPLM210) +/* + * XPLMDestroyFlightLoop + * + * This routine destroys a flight loop callback by ID. + * + */ +XPLM_API void XPLMDestroyFlightLoop(XPLMFlightLoopID inFlightLoopID); +#endif /* XPLM210 */ + +#if defined(XPLM210) +/* + * XPLMScheduleFlightLoop + * + * This routine schedules a flight loop callback for future execution. If + * inInterval is negative, it is run in a certain number of frames based on + * the absolute value of the input. If the interval is positive, it is a + * duration in seconds. + * + * If inRelativeToNow is true, ties are interpretted relative to the time this + * routine is called; otherwise they are relative to the last call time or the + * time the flight loop was registered (if never called). + * + * THREAD SAFETY: it is legal to call this routine from any thread under the + * following conditions: + * + * 1. The call must be between the beginning of an XPLMEnable and the end of + * an XPLMDisable sequence. (That is, you must not call this routine from + * thread activity when your plugin was supposed to be disabled. Since + * plugins are only enabled while loaded, this also implies you cannot run + * this routine outside an XPLMStart/XPLMStop sequence.) + * + * 2. You may not call this routine re-entrantly for a single flight loop ID. + * (That is, you can't enable from multiple threads at the same time.) + * + * 3. You must call this routine between the time after XPLMCreateFlightLoop + * returns a value and the time you call XPLMDestroyFlightLoop. (That is, you + * must ensure that your threaded activity is within the life of the object. + * The SDK does not check this for you, nor does it synchronize destruction of + * the object.) + * + * 4. The object must be unscheduled if this routine is to be called from a + * thread other than the main thread. + * + */ +XPLM_API void XPLMScheduleFlightLoop(XPLMFlightLoopID inFlightLoopID, + float inInterval, + int inRelativeToNow); +#endif /* XPLM210 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMScenery.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMScenery.h new file mode 100644 index 0000000..0233cbb --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMScenery.h @@ -0,0 +1,386 @@ +#ifndef _XPLMScenery_h_ +#define _XPLMScenery_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * This package contains APIs to interact with X-Plane's scenery system. + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(XPLM200) +/*************************************************************************** + * Terrain Y-Testing + ***************************************************************************/ +/* + * The Y-testing API allows you to locate the physical scenery mesh. This + * would be used to place dynamic graphics on top of the ground in a + * plausible way or do physics interactions. + * + * The Y-test API works via probe objects, which are allocated by your plugin + * and used to query terrain. Probe objects exist both to capture which + * algorithm you have requested (see probe types) and also to cache query + * information. + * + * Performance guidelines: It is generally faster to use the same probe for + * nearby points and different probes for different points. Try not to + * allocate more than "hundreds" of probes at most. Share probes if you need + * more. Generally, probing operations are expensive, and should be avoided + * via caching when possible. + * + * Y testing returns a location on the terrain, a normal vectory, and a + * velocity vector. The normal vector tells you the slope of the terrain at + * that point. The velocity vector tells you if that terrain is moving (and + * is in meters/second). For example, if your Y test hits the aircraft carrier + * deck, this tells you the velocity of that point on the deck. + * + * Note: the Y-testing API is limited to probing the loaded scenery area, + * which is approximately 300x300 km in X-Plane 9. Probes outside this area + * will return the height of a 0 MSL sphere. + * + */ + + +/* + * XPLMProbeType + * + * XPLMProbeType defines the type of terrain probe - each probe has a + * different algorithm. (Only one type of probe is provided right now, but + * future APIs will expose more flexible or poewrful or useful probes. + * + */ +enum { + /* The Y probe gives you the location of the tallest physical scenery along + * * the Y axis going through the queried point. */ + xplm_ProbeY = 0 + + +}; +typedef int XPLMProbeType; + +/* + * XPLMProbeResult + * + * Probe results - possible results from a probe query. + * + */ +enum { + /* The probe hit terrain and returned valid values. */ + xplm_ProbeHitTerrain = 0 + + /* An error in the API call. Either the probe struct size is bad, or the * + * probe is invalid or the type is mismatched for the specific query call. + */ + , + xplm_ProbeError = 1 + + /* The probe call succeeded but there is no terrain under this point + * (perhaps * it is off the side of the planet?) */ + , + xplm_ProbeMissed = 2 + + +}; +typedef int XPLMProbeResult; + +/* + * XPLMProbeRef + * + * An XPLMProbeRef is an opaque handle to a probe, used for querying the + * terrain. + * + */ +typedef void *XPLMProbeRef; + +/* + * XPLMProbeInfo_t + * + * XPLMProbeInfo_t contains the results of a probe call. Make sure to set + * structSize to the size of the struct before using it. + * + */ +typedef struct { + /* Size of structure in bytes - always set this before calling the XPLM. */ + int structSize; + /* Resulting X location of the terrain point we hit, in local OpenGL * + * coordinates. */ + float locationX; + /* Resulting Y location of the terrain point we hit, in local OpenGL * + * coordinates. */ + float locationY; + /* Resulting Z location of the terrain point we hit, in local OpenGL * + * coordinates. */ + float locationZ; + /* X component of the normal vector to the terrain we found. */ + float normalX; + /* Y component of the normal vector to the terrain we found. */ + float normalY; + /* Z component of the normal vector to the terrain we found. */ + float normalZ; + /* X component of the velocity vector of the terrain we found. */ + float velocityX; + /* Y component of the velocity vector of the terrain we found. */ + float velocityY; + /* Z component of the velocity vector of the terrain we found. */ + float velocityZ; + /* Tells if the surface we hit is water (otherwise it is land). */ + int is_wet; +} XPLMProbeInfo_t; + +/* + * XPLMCreateProbe + * + * Creates a new probe object of a given type and returns. + * + */ +XPLM_API XPLMProbeRef XPLMCreateProbe(XPLMProbeType inProbeType); + +/* + * XPLMDestroyProbe + * + * Deallocates an existing probe object. + * + */ +XPLM_API void XPLMDestroyProbe(XPLMProbeRef inProbe); + +/* + * XPLMProbeTerrainXYZ + * + * Probes the terrain. Pass in the XYZ coordinate of the probe point, a probe + * object, and an XPLMProbeInfo_t struct that has its structSize member set + * properly. Other fields are filled in if we hit terrain, and a probe result + * is returned. + * + */ +XPLM_API XPLMProbeResult XPLMProbeTerrainXYZ(XPLMProbeRef inProbe, + float inX, + float inY, + float inZ, + XPLMProbeInfo_t *outInfo); + +#endif /* XPLM200 */ +/*************************************************************************** + * Object Drawing + ***************************************************************************/ +/* + * The object drawing routines let you load and draw X-Plane OBJ files. + * Objects are loaded by file path and managed via an opaque handle. X-Plane + * naturally reference counts objects, so it is important that you balance + * every successful call to XPLMLoadObject with a call to XPLMUnloadObject! + * + */ + + +#if defined(XPLM200) +/* + * XPLMObjectRef + * + * An XPLMObjectRef is a opaque handle to an .obj file that has been loaded + * into memory. + * + */ +typedef void *XPLMObjectRef; +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMDrawInfo_t + * + * The XPLMDrawInfo_t structure contains positioning info for one object that + * is to be drawn. Be sure to set structSize to the size of the structure for + * future expansion. + * + */ +typedef struct { + /* Set this to the size of this structure! */ + int structSize; + /* X location of the object in local coordinates. */ + float x; + /* Y location of the object in local coordinates. */ + float y; + /* Z location of the object in local coordinates. */ + float z; + /* Pitch in degres to rotate the object, positive is up. */ + float pitch; + /* Heading in local coordinates to rotate the object, clockwise. */ + float heading; + /* Roll to rotate the object. */ + float roll; +} XPLMDrawInfo_t; +#endif /* XPLM200 */ + +#if defined(XPLM210) +/* + * XPLMObjectLoaded_f + * + * You provide this callback when loading an object asynchronously; it will be + * called once the object is loaded. Your refcon is passed back. The object + * ref passed in is the newly loaded object (ready for use) or NULL if an + * error occured. + * + * If your plugin is disabled, this callback will be delivered as soon as the + * plugin is re-enabled. If your plugin is unloaded before this callback is + * ever called, the SDK will release the object handle for you. + * + */ +typedef void (*XPLMObjectLoaded_f)(XPLMObjectRef inObject, void *inRefcon); +#endif /* XPLM210 */ + +#if defined(XPLM200) +/* + * XPLMLoadObject + * + * This routine loads an OBJ file and returns a handle to it. If X-plane has + * already loaded the object, the handle to the existing object is returned. + * Do not assume you will get the same handle back twice, but do make sure to + * call unload once for every load to avoid "leaking" objects. The object + * will be purged from memory when no plugins and no scenery are using it. + * + * The path for the object must be relative to the X-System base folder. If + * the path is in the root of the X-System folder you may need to prepend ./ + * to it; loading objects in the root of the X-System folder is STRONGLY + * discouraged - your plugin should not dump art resources in the root folder! + * + * + * XPLMLoadObject will return NULL if the object cannot be loaded (either + * because it is not found or the file is misformatted). This routine will + * load any object that can be used in the X-Plane scenery system. + * + * It is important that the datarefs an object uses for animation already be + * loaded before you load the object. For this reason it may be necessary to + * defer object loading until the sim has fully started. + * + */ +XPLM_API XPLMObjectRef XPLMLoadObject(const char *inPath); +#endif /* XPLM200 */ + +#if defined(XPLM210) +/* + * XPLMLoadObjectAsync + * + * This routine loads an object asynchronously; control is returned to you + * immediately while X-Plane loads the object. The sim will not stop flying + * while the object loads. For large objects, it may be several seconds + * before the load finishes. + * + * You provide a callback function that is called once the load has completed. + * Note that if the object cannot be loaded, you will not find out until the + * callback function is called with a NULL object handle. + * + * There is no way to cancel an asynchronous object load; you must wait for + * the load to complete and then release the object if it is no longer + * desired. + * + */ +XPLM_API void XPLMLoadObjectAsync(const char *inPath, + XPLMObjectLoaded_f inCallback, + void *inRefcon); +#endif /* XPLM210 */ + +#if defined(XPLM200) +/* + * XPLMDrawObjects + * + * XPLMDrawObjects draws an object from an OBJ file one or more times. You + * pass in the object and an array of XPLMDrawInfo_t structs, one for each + * place you would like the object to be drawn. + * + * X-Plane will attempt to cull the objects based on LOD and visibility, and + * will pick the appropriate LOD. + * + * Lighting is a boolean; pass 1 to show the night version of object with + * night-only lights lit up. Pass 0 to show the daytime version of the + * object. + * + * earth_relative controls the coordinate system. If this is 1, the rotations + * you specify are applied to the object after its coordinate system is + * transformed from local to earth-relative coordinates -- that is, an object + * with no rotations will point toward true north and the Y axis will be up + * against gravity. If this is 0, the object is drawn with your rotations + * from local coordanates -- that is, an object with no rotations is drawn + * pointing down the -Z axis and the Y axis of the object matches the local + * coordinate Y axis. + * + */ +XPLM_API void XPLMDrawObjects(XPLMObjectRef inObject, + int inCount, + XPLMDrawInfo_t *inLocations, + int lighting, + int earth_relative); +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMUnloadObject + * + * This routine marks an object as no longer being used by your plugin. + * Objects are reference counted: once no plugins are using an object, it is + * purged from memory. Make sure to call XPLMUnloadObject once for each + * successful call to XPLMLoadObject. + * + */ +XPLM_API void XPLMUnloadObject(XPLMObjectRef inObject); +#endif /* XPLM200 */ + +#if defined(XPLM200) +/*************************************************************************** + * Library Access + ***************************************************************************/ +/* + * The library access routines allow you to locate scenery objects via the + * X-Plane library system. Right now library access is only provided for + * objects, allowing plugin-drawn objects to be extended using the library + * system. + * + */ + + +/* + * XPLMLibraryEnumerator_f + * + * An XPLMLibraryEnumerator_f is a callback you provide that is called once + * for each library element that is located. The returned paths will be + * relative to the X-System folder. + * + */ +typedef void (*XPLMLibraryEnumerator_f)(const char *inFilePath, void *inRef); + +/* + * XPLMLookupObjects + * + * This routine looks up a virtual path in the library system and returns all + * matching elements. You provide a callback - one virtual path may match + * many objects in the library. XPLMLookupObjects returns the number of + * objects found. + * + * The latitude and longitude parameters specify the location the object will + * be used. The library system allows for scenery packages to only provide + * objects to certain local locations. Only objects that are allowed at the + * latitude/longitude you provide will be returned. + * + */ +XPLM_API int XPLMLookupObjects(const char *inPath, + float inLatitude, + float inLongitude, + XPLMLibraryEnumerator_f enumerator, + void *ref); + +#endif /* XPLM200 */ +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMUtilities.h b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMUtilities.h new file mode 100644 index 0000000..ab57f10 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/CHeaders/XPLM/XPLMUtilities.h @@ -0,0 +1,829 @@ +#ifndef _XPLMUtilities_h_ +#define _XPLMUtilities_h_ + +/* + * Copyright 2005-2012 Sandy Barbour and Ben Supnik + * + * All rights reserved. See license.txt for usage. + * + * X-Plane SDK Version: 2.1.1 + * + */ + +/* + * + * + */ + +#include "XPLMDefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + * X-PLANE USER INTERACTION + ***************************************************************************/ +/* + * The user interaction APIs let you simulate commands the user can do with a + * joystick, keyboard etc. Note that it is generally safer for future + * compatibility to use one of these commands than to manipulate the + * underlying sim data. + * + */ + + +/* + * XPLMCommandKeyID + * + * These enums represent all the keystrokes available within x-plane. They + * can be sent to x-plane directly. For example, you can reverse thrust using + * these enumerations. + * + */ +enum { + xplm_key_pause = 0, + xplm_key_revthrust, + xplm_key_jettison, + xplm_key_brakesreg, + xplm_key_brakesmax, + xplm_key_gear, + xplm_key_timedn, + xplm_key_timeup, + xplm_key_fadec, + xplm_key_otto_dis, + xplm_key_otto_atr, + xplm_key_otto_asi, + xplm_key_otto_hdg, + xplm_key_otto_gps, + xplm_key_otto_lev, + xplm_key_otto_hnav, + xplm_key_otto_alt, + xplm_key_otto_vvi, + xplm_key_otto_vnav, + xplm_key_otto_nav1, + xplm_key_otto_nav2, + xplm_key_targ_dn, + xplm_key_targ_up, + xplm_key_hdgdn, + xplm_key_hdgup, + xplm_key_barodn, + xplm_key_baroup, + xplm_key_obs1dn, + xplm_key_obs1up, + xplm_key_obs2dn, + xplm_key_obs2up, + xplm_key_com1_1, + xplm_key_com1_2, + xplm_key_com1_3, + xplm_key_com1_4, + xplm_key_nav1_1, + xplm_key_nav1_2, + xplm_key_nav1_3, + xplm_key_nav1_4, + xplm_key_com2_1, + xplm_key_com2_2, + xplm_key_com2_3, + xplm_key_com2_4, + xplm_key_nav2_1, + xplm_key_nav2_2, + xplm_key_nav2_3, + xplm_key_nav2_4, + xplm_key_adf_1, + xplm_key_adf_2, + xplm_key_adf_3, + xplm_key_adf_4, + xplm_key_adf_5, + xplm_key_adf_6, + xplm_key_transpon_1, + xplm_key_transpon_2, + xplm_key_transpon_3, + xplm_key_transpon_4, + xplm_key_transpon_5, + xplm_key_transpon_6, + xplm_key_transpon_7, + xplm_key_transpon_8, + xplm_key_flapsup, + xplm_key_flapsdn, + xplm_key_cheatoff, + xplm_key_cheaton, + xplm_key_sbrkoff, + xplm_key_sbrkon, + xplm_key_ailtrimL, + xplm_key_ailtrimR, + xplm_key_rudtrimL, + xplm_key_rudtrimR, + xplm_key_elvtrimD, + xplm_key_elvtrimU, + xplm_key_forward, + xplm_key_down, + xplm_key_left, + xplm_key_right, + xplm_key_back, + xplm_key_tower, + xplm_key_runway, + xplm_key_chase, + xplm_key_free1, + xplm_key_free2, + xplm_key_spot, + xplm_key_fullscrn1, + xplm_key_fullscrn2, + xplm_key_tanspan, + xplm_key_smoke, + xplm_key_map, + xplm_key_zoomin, + xplm_key_zoomout, + xplm_key_cycledump, + xplm_key_replay, + xplm_key_tranID, + xplm_key_max +}; +typedef int XPLMCommandKeyID; + +/* + * XPLMCommandButtonID + * + * These are enumerations for all of the things you can do with a joystick + * button in X-Plane. They currently match the buttons menu in the equipment + * setup dialog, but these enums will be stable even if they change in + * X-Plane. + * + */ +enum { + xplm_joy_nothing = 0, + xplm_joy_start_all, + xplm_joy_start_0, + xplm_joy_start_1, + xplm_joy_start_2, + xplm_joy_start_3, + xplm_joy_start_4, + xplm_joy_start_5, + xplm_joy_start_6, + xplm_joy_start_7, + xplm_joy_throt_up, + xplm_joy_throt_dn, + xplm_joy_prop_up, + xplm_joy_prop_dn, + xplm_joy_mixt_up, + xplm_joy_mixt_dn, + xplm_joy_carb_tog, + xplm_joy_carb_on, + xplm_joy_carb_off, + xplm_joy_trev, + xplm_joy_trm_up, + xplm_joy_trm_dn, + xplm_joy_rot_trm_up, + xplm_joy_rot_trm_dn, + xplm_joy_rud_lft, + xplm_joy_rud_cntr, + xplm_joy_rud_rgt, + xplm_joy_ail_lft, + xplm_joy_ail_cntr, + xplm_joy_ail_rgt, + xplm_joy_B_rud_lft, + xplm_joy_B_rud_rgt, + xplm_joy_look_up, + xplm_joy_look_dn, + xplm_joy_look_lft, + xplm_joy_look_rgt, + xplm_joy_glance_l, + xplm_joy_glance_r, + xplm_joy_v_fnh, + xplm_joy_v_fwh, + xplm_joy_v_tra, + xplm_joy_v_twr, + xplm_joy_v_run, + xplm_joy_v_cha, + xplm_joy_v_fr1, + xplm_joy_v_fr2, + xplm_joy_v_spo, + xplm_joy_flapsup, + xplm_joy_flapsdn, + xplm_joy_vctswpfwd, + xplm_joy_vctswpaft, + xplm_joy_gear_tog, + xplm_joy_gear_up, + xplm_joy_gear_down, + xplm_joy_lft_brake, + xplm_joy_rgt_brake, + xplm_joy_brakesREG, + xplm_joy_brakesMAX, + xplm_joy_speedbrake, + xplm_joy_ott_dis, + xplm_joy_ott_atr, + xplm_joy_ott_asi, + xplm_joy_ott_hdg, + xplm_joy_ott_alt, + xplm_joy_ott_vvi, + xplm_joy_tim_start, + xplm_joy_tim_reset, + xplm_joy_ecam_up, + xplm_joy_ecam_dn, + xplm_joy_fadec, + xplm_joy_yaw_damp, + xplm_joy_art_stab, + xplm_joy_chute, + xplm_joy_JATO, + xplm_joy_arrest, + xplm_joy_jettison, + xplm_joy_fuel_dump, + xplm_joy_puffsmoke, + xplm_joy_prerotate, + xplm_joy_UL_prerot, + xplm_joy_UL_collec, + xplm_joy_TOGA, + xplm_joy_shutdown, + xplm_joy_con_atc, + xplm_joy_fail_now, + xplm_joy_pause, + xplm_joy_rock_up, + xplm_joy_rock_dn, + xplm_joy_rock_lft, + xplm_joy_rock_rgt, + xplm_joy_rock_for, + xplm_joy_rock_aft, + xplm_joy_idle_hilo, + xplm_joy_lanlights, + xplm_joy_max +}; +typedef int XPLMCommandButtonID; + +/* + * XPLMHostApplicationID + * + * The plug-in system is based on Austin's cross-platform OpenGL framework and + * could theoretically be adapted to run in other apps like WorldMaker. The + * plug-in system also runs against a test harness for internal development + * and could be adapted to another flight sim (in theory at least). So an ID + * is providing allowing plug-ins to indentify what app they are running + * under. + * + */ +enum { + xplm_Host_Unknown = 0 + + , + xplm_Host_XPlane = 1 + + , + xplm_Host_PlaneMaker = 2 + + , + xplm_Host_WorldMaker = 3 + + , + xplm_Host_Briefer = 4 + + , + xplm_Host_PartMaker = 5 + + , + xplm_Host_YoungsMod = 6 + + , + xplm_Host_XAuto = 7 + + +}; +typedef int XPLMHostApplicationID; + +/* + * XPLMLanguageCode + * + * These enums define what language the sim is running in. These enumerations + * do not imply that the sim can or does run in all of these languages; they + * simply provide a known encoding in the event that a given sim version is + * localized to a certain language. + * + */ +enum { + xplm_Language_Unknown = 0 + + , + xplm_Language_English = 1 + + , + xplm_Language_French = 2 + + , + xplm_Language_German = 3 + + , + xplm_Language_Italian = 4 + + , + xplm_Language_Spanish = 5 + + , + xplm_Language_Korean = 6 + +#if defined(XPLM200) + , + xplm_Language_Russian = 7 + +#endif /* XPLM200 */ +#if defined(XPLM200) + , + xplm_Language_Greek = 8 + +#endif /* XPLM200 */ +#if defined(XPLM200) + , + xplm_Language_Japanese = 9 + +#endif /* XPLM200 */ +#if defined(XPLM200) + , + xplm_Language_Chinese = 10 + +#endif /* XPLM200 */ + +}; +typedef int XPLMLanguageCode; + +#if defined(XPLM200) +/* + * XPLMDataFileType + * + * These enums define types of data files you can load or unload using the + * SDK. + * + */ +enum { + /* A situation (.sit) file, which starts off a flight in a given * + * configuration. */ + xplm_DataFile_Situation = 1 + + /* A situation movie (.smo) file, which replays a past flight. */ + , + xplm_DataFile_ReplayMovie = 2 + + +}; +typedef int XPLMDataFileType; +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMError_f + * + * An XPLM error callback is a function that you provide to receive debugging + * information from the plugin SDK. See XPLMSetErrorCallback for more + * information. NOTE: for the sake of debugging, your error callback will be + * called even if your plugin is not enabled, allowing you to receive debug + * info in your XPluginStart and XPluginStop callbacks. To avoid causing + * logic errors in the management code, do not call any other plugin routines + * from your error callback - it is only meant for logging! + * + */ +typedef void (*XPLMError_f)(const char *inMessage); +#endif /* XPLM200 */ + +/* + * XPLMSimulateKeyPress + * + * This function simulates a key being pressed for x-plane. The keystroke + * goes directly to x-plane; it is never sent to any plug-ins. However, since + * this is a raw key stroke it may be mapped by the keys file or enter text + * into a field. + * + * WARNING: This function will be deprecated; do not use it. Instead use + * XPLMCommandKeyStroke. + * + */ +XPLM_API void XPLMSimulateKeyPress(int inKeyType, int inKey); + +/* + * XPLMSpeakString + * + * This function displays the string in a translucent overlay over the current + * display and also speaks the string if text-to-speech is enabled. The + * string is spoken asynchronously, this function returns immediately. + * + */ +XPLM_API void XPLMSpeakString(const char *inString); + +/* + * XPLMCommandKeyStroke + * + * This routine simulates a command-key stroke. However, the keys are done by + * function, not by actual letter, so this function works even if the user has + * remapped their keyboard. Examples of things you might do with this include + * pausing the simulator. + * + */ +XPLM_API void XPLMCommandKeyStroke(XPLMCommandKeyID inKey); + +/* + * XPLMCommandButtonPress + * + * This function simulates any of the actions that might be taken by pressing + * a joystick button. However, this lets you call the command directly rather + * than have to know which button is mapped where. Important: you must + * release each button you press. The APIs are separate so that you can 'hold + * down' a button for a fixed amount of time. + * + */ +XPLM_API void XPLMCommandButtonPress(XPLMCommandButtonID inButton); + +/* + * XPLMCommandButtonRelease + * + * This function simulates any of the actions that might be taken by pressing + * a joystick button. See XPLMCommandButtonPress + * + */ +XPLM_API void XPLMCommandButtonRelease(XPLMCommandButtonID inButton); + +/* + * XPLMGetVirtualKeyDescription + * + * Given a virtual key code (as defined in XPLMDefs.h) this routine returns a + * human-readable string describing the character. This routine is provided + * for showing users what keyboard mappings they have set up. The string may + * read 'unknown' or be a blank or NULL string if the virtual key is unknown. + * + */ +XPLM_API const char *XPLMGetVirtualKeyDescription(char inVirtualKey); + +/*************************************************************************** + * X-PLANE MISC + ***************************************************************************/ +/* + * + * + */ + + +/* + * XPLMReloadScenery + * + * XPLMReloadScenery reloads the current set of scenery. You can use this + * function in two typical ways: simply call it to reload the scenery, picking + * up any new installed scenery, .env files, etc. from disk. Or, change the + * lat/ref and lon/ref data refs and then call this function to shift the + * scenery environment. + * + */ +XPLM_API void XPLMReloadScenery(void); + +/* + * XPLMGetSystemPath + * + * This function returns the full path to the X-System folder. Note that this + * is a directory path, so it ends in a trailing : or /. The buffer you pass + * should be at least 512 characters long. + * + */ +XPLM_API void XPLMGetSystemPath(char *outSystemPath); + +/* + * XPLMGetPrefsPath + * + * This routine returns a full path to the proper directory to store + * preferences in. It ends in a : or /. The buffer you pass should be at + * least 512 characters long. + * + */ +XPLM_API void XPLMGetPrefsPath(char *outPrefsPath); + +/* + * XPLMGetDirectorySeparator + * + * This routine returns a string with one char and a null terminator that is + * the directory separator for the current platform. This allows you to write + * code that concatinates directory paths without having to #ifdef for + * platform. + * + */ +XPLM_API const char *XPLMGetDirectorySeparator(void); + +/* + * XPLMExtractFileAndPath + * + * Given a full path to a file, this routine separates the path from the file. + * If the path is a partial directory (e.g. ends in : or \) the trailing + * directory separator is removed. This routine works in-place; a pointer to + * the file part of the buffer is returned; the original buffer still starts + * with the path. + * + */ +XPLM_API char *XPLMExtractFileAndPath(char *inFullPath); + +/* + * XPLMGetDirectoryContents + * + * This routine returns a list of files in a directory (specified by a full + * path, no trailing : or \). The output is returned as a list of NULL + * terminated strings. An index array (if specified) is filled with pointers + * into the strings. This routine The last file is indicated by a zero-length + * string (and NULL in the indices). This routine will return 1 if you had + * capacity for all files or 0 if you did not. You can also skip a given + * number of files. + * + * inDirectoryPath - a null terminated C string containing the full path to + * the directory with no trailing directory char. + * + * inFirstReturn - the zero-based index of the first file in the directory to + * return. (Usually zero to fetch all in one pass.) + * + * outFileNames - a buffer to receive a series of sequential null terminated + * C-string file names. A zero-length C string will be appended to the very + * end. + * + * inFileNameBufSize - the size of the file name buffer in bytes. + * + * outIndices - a pointer to an array of character pointers that will become + * an index into the directory. The last file will be followed by a NULL + * value. Pass NULL if you do not want indexing information. + * + * inIndexCount - the max size of the index in entries. + * + * outTotalFiles - if not NULL, this is filled in with the number of files in + * the directory. + * + * outReturnedFiles - if not NULL, the number of files returned by this + * iteration. + * + * Return value - 1 if all info could be returned, 0 if there was a buffer + * overrun. + * + * WARNING: Before X-Plane 7 this routine did not properly iterate through + * directories. If X-Plane 6 compatibility is needed, use your own code to + * iterate directories. + * + */ +XPLM_API int XPLMGetDirectoryContents(const char *inDirectoryPath, + int inFirstReturn, + char *outFileNames, + int inFileNameBufSize, + char **outIndices, /* Can be NULL */ + int inIndexCount, + int *outTotalFiles, /* Can be NULL */ + int *outReturnedFiles); /* Can be NULL */ + +/* + * XPLMInitialized + * + * This function returns 1 if X-Plane has properly initialized the plug-in + * system. If this routine returns 0, many XPLM functions will not work. + * + * NOTE: Under normal circumstances a plug-in should never be running while + * the plug-in manager is not initialized. + * + * WARNING: This function is generally not needed and may be deprecated in the + * future. + * + */ +XPLM_API int XPLMInitialized(void); + +/* + * XPLMGetVersions + * + * This routine returns the revision of both X-Plane and the XPLM DLL. All + * versions are three-digit decimal numbers (e.g. 606 for version 6.06 of + * X-Plane); the current revision of the XPLM is 200 (2.00). This routine + * also returns the host ID of the app running us. + * + * The most common use of this routine is to special-case around x-plane + * version-specific behavior. + * + */ +XPLM_API void XPLMGetVersions(int *outXPlaneVersion, + int *outXPLMVersion, + XPLMHostApplicationID *outHostID); + +/* + * XPLMGetLanguage + * + * This routine returns the langauge the sim is running in. + * + */ +XPLM_API XPLMLanguageCode XPLMGetLanguage(void); + +/* + * XPLMDebugString + * + * This routine outputs a C-style string to the Log.txt file. The file is + * immediately flushed so you will not lose data. (This does cause a + * performance penalty.) + * + */ +XPLM_API void XPLMDebugString(const char *inString); + +#if defined(XPLM200) +/* + * XPLMSetErrorCallback + * + * XPLMSetErrorCallback installs an error-reporting callback for your plugin. + * Normally the plugin system performs minimum diagnostics to maximize + * performance. When you install an error callback, you will receive calls + * due to certain plugin errors, such as passing bad parameters or incorrect + * data. + * + * The intention is for you to install the error callback during debug + * sections and put a break-point inside your callback. This will cause you + * to break into the debugger from within the SDK at the point in your plugin + * where you made an illegal call. + * + * Installing an error callback may activate error checking code that would + * not normally run, and this may adversely affect performance, so do not + * leave error callbacks installed in shipping plugins. + * + */ +XPLM_API void XPLMSetErrorCallback(XPLMError_f inCallback); +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMFindSymbol + * + * This routine will attempt to find the symbol passed in the inString + * parameter. If the symbol is found a pointer the function is returned, + * othewise the function will return NULL. + * + */ +XPLM_API void *XPLMFindSymbol(const char *inString); +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMLoadDataFile + * + * Loads a data file of a given type. Paths must be relative to the X-System + * folder. To clear the replay, pass a NULL file name (this is only valid with + * replay movies, not sit files). + * + */ +XPLM_API int XPLMLoadDataFile(XPLMDataFileType inFileType, + const char *inFilePath); /* Can be NULL */ +#endif /* XPLM200 */ + +#if defined(XPLM200) +/* + * XPLMSaveDataFile + * + * Saves the current situation or replay; paths are relative to the X-System + * folder. + * + */ +XPLM_API int XPLMSaveDataFile(XPLMDataFileType inFileType, + const char *inFilePath); +#endif /* XPLM200 */ + +#if defined(XPLM200) +/*************************************************************************** + * X-PLANE COMMAND MANAGEMENT + ***************************************************************************/ +/* + * The command management APIs let plugins interact with the command-system in + * X-Plane, the abstraction behind keyboard presses and joystick buttons. + * This API lets you create new commands and modify the behavior (or get + * notification) of existing ones. + * + * An X-Plane command consists of three phases: a beginning, continuous + * repetition, and an ending. The command may be repeated zero times in the + * event that the user presses a button only momentarily. + * + */ + + +/* + * XPLMCommandPhase + * + * The phases of a command. + * + */ +enum { + /* The command is being started. */ + xplm_CommandBegin = 0 + + /* The command is continuing to execute. */ + , + xplm_CommandContinue = 1 + + /* The command has ended. */ + , + xplm_CommandEnd = 2 + + +}; +typedef int XPLMCommandPhase; + +/* + * XPLMCommandRef + * + * A command ref is an opaque identifier for an X-Plane command. Command + * references stay the same for the life of your plugin but not between + * executions of X-Plane. Command refs are used to execute commands, create + * commands, and create callbacks for particular commands. + * + * Note that a command is not "owned" by a particular plugin. Since many + * plugins may participate in a command's execution, the command does not go + * away if the plugin that created it is unloaded. + * + */ +typedef void *XPLMCommandRef; + +/* + * XPLMCommandCallback_f + * + * A command callback is a function in your plugin that is called when a + * command is pressed. Your callback receives the commadn reference for the + * particular command, the phase of the command that is executing, and a + * reference pointer that you specify when registering the callback. + * + * Your command handler should return 1 to let processing of the command + * continue to other plugins and X-Plane, or 0 to halt processing, + * potentially bypassing X-Plane code. + * + */ +typedef int (*XPLMCommandCallback_f)(XPLMCommandRef inCommand, + XPLMCommandPhase inPhase, + void *inRefcon); + +/* + * XPLMFindCommand + * + * XPLMFindCommand looks up a command by name, and returns its command + * reference or NULL if the command does not exist. + * + */ +XPLM_API XPLMCommandRef XPLMFindCommand(const char *inName); + +/* + * XPLMCommandBegin + * + * XPLMCommandBegin starts the execution of a command, specified by its + * command reference. The command is "held down" until XPLMCommandEnd is + * called. + * + */ +XPLM_API void XPLMCommandBegin(XPLMCommandRef inCommand); + +/* + * XPLMCommandEnd + * + * XPLMCommandEnd ends the execution of a given command that was started with + * XPLMCommandBegin. + * + */ +XPLM_API void XPLMCommandEnd(XPLMCommandRef inCommand); + +/* + * XPLMCommandOnce + * + * This executes a given command momentarily, that is, the command begins and + * ends immediately. + * + */ +XPLM_API void XPLMCommandOnce(XPLMCommandRef inCommand); + +/* + * XPLMCreateCommand + * + * XPLMCreateCommand creates a new command for a given string. If the command + * already exists, the existing command reference is returned. The + * description may appear in user interface contexts, such as the joystick + * configuration screen. + * + */ +XPLM_API XPLMCommandRef XPLMCreateCommand(const char *inName, + const char *inDescription); + +/* + * XPLMRegisterCommandHandler + * + * XPLMRegisterCommandHandler registers a callback to be called when a command + * is executed. You provide a callback with a reference pointer. + * + * If inBefore is true, your command handler callback will be executed before + * X-Plane executes the command, and returning 0 from your callback will + * disable X-Plane's processing of the command. If inBefore is false, your + * callback will run after X-Plane. (You can register a single callback both + * before and after a command.) + * + */ +XPLM_API void XPLMRegisterCommandHandler(XPLMCommandRef inComand, + XPLMCommandCallback_f inHandler, + int inBefore, + void *inRefcon); + +/* + * XPLMUnregisterCommandHandler + * + * XPLMUnregisterCommandHandler removes a command callback registered with + * XPLMRegisterCommandHandler. + * + */ +XPLM_API void XPLMUnregisterCommandHandler(XPLMCommandRef inComand, + XPLMCommandCallback_f inHandler, + int inBefore, + void *inRefcon); + +#endif /* XPLM200 */ +#ifdef __cplusplus +} +#endif + +#endif diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPStandardWidgets.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPStandardWidgets.pas new file mode 100644 index 0000000..bde7c77 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPStandardWidgets.pas @@ -0,0 +1,497 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPStandardWidgets; +INTERFACE +{ + XPStandardWidgets - THEORY OF OPERATION + + The standard widgets are widgets built into the widgets library. While you + can gain access to the widget function that drives them, you generally use + them by calling XPCreateWidget and then listening for special messages, + etc. + + The standard widgets often send mesages to themselves when the user + performs an event; these messages are sent up the widget hierarchy until + they are handled. So you can add a widget proc directly to a push button + (for example) to intercept the message when it is clicked, or you can put + one widget proc on a window for all of the push buttons in the window. + Most of these messages contain the original widget ID as a parameter so you + can know which widget is messaging no matter who it is sent to. +} + +USES XPWidgetDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * MAIN WINDOW + ___________________________________________________________________________} +{ + The main window widget class provides a "window" as the user knows it. + These windows are dragable and can be selected. Use them to create + floating windows and non-modal dialogs. +} + + + +CONST + xpWidgetClass_MainWindow = 1; + + { + Main Window Type Values + + These type values are used to control the appearance of a main window. + } + { The standard main window; pin stripes on XP7, metal frame on XP 6. } + xpMainWindowStyle_MainWindow = 0 +; + { A translucent dark gray window, like the one ATC messages appear in. } + xpMainWindowStyle_Translucent = 1 +; + + { + Main Window Properties + + } + { This property specifies the type of window. Set to one of the main window } + { types above. } + xpProperty_MainWindowType = 1100 +; + { This property specifies whether the main window has close boxes in its } + { corners. } + xpProperty_MainWindowHasCloseBoxes = 1200 +; + + { + MainWindow Messages + + } + { This message is sent when the close buttons are pressed for your window. } + xpMessage_CloseButtonPushed = 1200 +; + +{___________________________________________________________________________ + * SUB WINDOW + ___________________________________________________________________________} +{ + X-plane dialogs are divided into separate areas; the sub window widgets + allow you to make these areas. Create one main window and place several + subwindows inside it. Then place your controls inside the subwindows. +} + + + +CONST + xpWidgetClass_SubWindow = 2; + + { + SubWindow Type Values + + These values control the appearance of the subwindow. + } + { A panel that sits inside a main window. } + xpSubWindowStyle_SubWindow = 0 +; + { A screen that sits inside a panel for showing text information. } + xpSubWindowStyle_Screen = 2 +; + { A list view for scrolling lists. } + xpSubWindowStyle_ListView = 3 +; + + { + SubWindow Properties + + } + { This property specifies the type of window. Set to one of the subwindow } + { types above. } + xpProperty_SubWindowType = 1200 +; + +{___________________________________________________________________________ + * BUTTON + ___________________________________________________________________________} +{ + The button class provides a number of different button styles and + behaviors, including push buttons, radio buttons, check boxes, etc. The + button label appears on or next to the button depending on the button's + appearance, or type. + + The button's behavior is a separate property that dictates who it hilights + and what kinds of messages it sends. Since behavior and type are + different, you can do strange things like make check boxes that act as push + buttons or push buttons with radio button behavior. + + In X-Plane 6 there were no check box graphics. The result is the following + behavior: in x-plane 6 all check box and radio buttons are round + (radio-button style) buttons; in X-Plane 7 they are all square (check-box + style) buttons. In a future version of x-plane, the xpButtonBehavior enums + will provide the correct graphic (check box or radio button) giving the + expected result. +} + + + +CONST + xpWidgetClass_Button = 3; + + { + Button Types + + These define the visual appearance of buttons but not how they respond to + the mouse. + } + { This is a standard push button, like an "OK" or "Cancel" button in a dialog } + { box. } + xpPushButton = 0 +; + { A check box or radio button. Use this and the button behaviors below to } + { get the desired behavior. } + xpRadioButton = 1 +; + { A window close box. } + xpWindowCloseBox = 3 +; + { A small down arrow. } + xpLittleDownArrow = 5 +; + { A small up arrow. } + xpLittleUpArrow = 6 +; + + { + Button Behavior Values + + These define how the button responds to mouse clicks. + } + { Standard push button behavior. The button hilites while the mouse is } + { clicked over it and unhilites when the mouse is moved outside of it or } + { released. If the mouse is released over the button, the } + { xpMsg_PushButtonPressed message is sent. } + xpButtonBehaviorPushButton = 0 +; + { Check box behavior. The button immediately toggles its value when the } + { mouse is clicked and sends out a xpMsg_ButtonStateChanged message. } + xpButtonBehaviorCheckBox = 1 +; + { Radio button behavior. The button immediately sets its state to one and } + { sends out a xpMsg_ButtonStateChanged message if it was not already set to } + { one. You must turn off other radio buttons in a group in your code. } + xpButtonBehaviorRadioButton = 2 +; + + { + Button Properties + + } + { This property sets the visual type of button. Use one of the button types } + { above. } + xpProperty_ButtonType = 1300 +; + { This property sets the button's behavior. Use one of the button behaviors } + { above. } + xpProperty_ButtonBehavior = 1301 +; + { This property tells whether a check box or radio button is "checked" or } + { not. Not used for push buttons. } + xpProperty_ButtonState = 1302 +; + + { + Button Messages + + These messages are sent by the button to itself and then up the widget + chain when the button is clicked. (You may intercept them by providing a + widget handler for the button itself or by providing a handler in a parent + widget.) + } + { This message is sent when the user completes a click and release in a } + { button with push button behavior. Parameter one of the message is the } + { widget ID of the button. This message is dispatched up the widget } + { hierarchy. } + xpMsg_PushButtonPressed = 1300 +; + { This message is sent when a button is clicked that has radio button or } + { check box behavior and its value changes. (Note that if the value changes } + { by setting a property you do not receive this message!) Parameter one is } + { the widget ID of the button, parameter 2 is the new state value, either } + { zero or one. This message is dispatched up the widget hierarchy. } + xpMsg_ButtonStateChanged = 1301 +; + +{___________________________________________________________________________ + * TEXT FIELD + ___________________________________________________________________________} +{ + The text field widget provides an editable text field including mouse + selection and keyboard navigation. The contents of the text field are its + descriptor. (The descriptor changes as the user types.) + + The text field can have a number of types, that effect the visual layout of + the text field. The text field sends messages to itself so you may control + its behavior. + + If you need to filter keystrokes, add a new handler and intercept the key + press message. Since key presses are passed by pointer, you can modify the + keystroke and pass it through to the text field widget. + + WARNING: in x-plane before 7.10 (including 6.70) null characters could + crash x-plane. To prevent this, wrap this object with a filter function + (more instructions can be found on the SDK website). +} + + + +CONST + xpWidgetClass_TextField = 4; + + { + Text Field Type Values + + These control the look of the text field. + } + { A field for text entry. } + xpTextEntryField = 0 +; + { A transparent text field. The user can type and the text is drawn, but no } + { background is drawn. You can draw your own background by adding a widget } + { handler and prehandling the draw message. } + xpTextTransparent = 3 +; + { A translucent edit field, dark gray. } + xpTextTranslucent = 4 +; + + { + Text Field Properties + + } + { This is the character position the selection starts at, zero based. If it } + { is the same as the end insertion point, the insertion point is not a } + { selection. } + xpProperty_EditFieldSelStart = 1400 +; + { This is the character position of the end of the selection. } + xpProperty_EditFieldSelEnd = 1401 +; + { This is the character position a drag was started at if the user is } + { dragging to select text, or -1 if a drag is not in progress. } + xpProperty_EditFieldSelDragStart = 1402 +; + { This is the type of text field to display, from the above list. } + xpProperty_TextFieldType = 1403 +; + { Set this property to 1 to password protect the field. Characters will be } + { drawn as *s even though the descriptor will contain plain-text. } + xpProperty_PasswordMode = 1404 +; + { The max number of characters you can enter, if limited. Zero means } + { unlimited. } + xpProperty_MaxCharacters = 1405 +; + { The first visible character on the left. This effectively scrolls the text } + { field. } + xpProperty_ScrollPosition = 1406 +; + { The font to draw the field's text with. (An XPLMFontID.) } + xpProperty_Font = 1407 +; + { This is the active side of the insert selection. (Internal) } + xpProperty_ActiveEditSide = 1408 +; + + { + Text Field Messages + + } + { Text Field Messages } + { } + { The text field sends this message to itself when its text changes. It } + { sends the message up the call chain; param1 is the text field's widget ID. } + xpMsg_TextFieldChanged = 1400 +; + +{___________________________________________________________________________ + * SCROLL BAR + ___________________________________________________________________________} +{ + A standard scroll bar or slider control. The scroll bar has a minimum, + maximum and current value that is updated when the user drags it. The + scroll bar sends continuous messages as it is dragged. +} + + + +CONST + xpWidgetClass_ScrollBar = 5; + + { + Scroll Bar Type Values + + This defines how the scroll bar looks. + } + { Scroll bar types. } + { } + { A standard x-plane scroll bar (with arrows on the ends). } + xpScrollBarTypeScrollBar = 0 +; + { A slider, no arrows. } + xpScrollBarTypeSlider = 1 +; + + { + Scroll Bar Properties + + } + { The current position of the thumb (in between the min and max, inclusive) } + xpProperty_ScrollBarSliderPosition = 1500 +; + { The value the scroll bar has when the thumb is in the lowest position. } + xpProperty_ScrollBarMin = 1501 +; + { The value the scroll bar has when the thumb is in the highest position. } + xpProperty_ScrollBarMax = 1502 +; + { How many units to moev the scroll bar when clicking next to the thumb. The } + { scroll bar always moves one unit when the arrows are clicked. } + xpProperty_ScrollBarPageAmount = 1503 +; + { The type of scrollbar from the enums above. } + xpProperty_ScrollBarType = 1504 +; + { Used internally. } + xpProperty_ScrollBarSlop = 1505 +; + + { + Scroll Bar Messages + + } + { The Scroll Bar sends this message when the slider position changes. It } + { sends the message up the call chain; param1 is the Scroll Bar widget ID. } + xpMsg_ScrollBarSliderPositionChanged = 1500 +; + +{___________________________________________________________________________ + * CAPTION + ___________________________________________________________________________} +{ + A caption is a simple widget that shows its descriptor as a string, useful + for labeling parts of a window. It always shows its descriptor as its + string and is otherwise transparent. +} + + + +CONST + xpWidgetClass_Caption = 6; + + { + Caption Properties + + } + { This property specifies whether the caption is lit; use lit captions } + { against screens. } + xpProperty_CaptionLit = 1600 +; + +{___________________________________________________________________________ + * GENERAL GRAPHICS + ___________________________________________________________________________} +{ + The general graphics widget can show one of many icons available from + x-plane. +} + + + +CONST + xpWidgetClass_GeneralGraphics = 7; + + { + General Graphics Types Values + + These define the icon for the general graphics. + } + xpShip = 4 +; + xpILSGlideScope = 5 +; + xpMarkerLeft = 6 +; + xp_Airport = 7 +; + xpNDB = 8 +; + xpVOR = 9 +; + xpRadioTower = 10 +; + xpAircraftCarrier = 11 +; + xpFire = 12 +; + xpMarkerRight = 13 +; + xpCustomObject = 14 +; + xpCoolingTower = 15 +; + xpSmokeStack = 16 +; + xpBuilding = 17 +; + xpPowerLine = 18 +; + xpVORWithCompassRose = 19 +; + xpOilPlatform = 21 +; + xpOilPlatformSmall = 22 +; + xpWayPoint = 23 +; + + { + General Graphics Properties + + } + { This property controls the type of icon that is drawn. } + xpProperty_GeneralGraphicsType = 1700 +; + +{___________________________________________________________________________ + * PROGRESS INDICATOR + ___________________________________________________________________________} +{ + This widget implements a progress indicator as seen when x-plane starts up. +} + + + +CONST + xpWidgetClass_Progress = 8; + + { + Progress Indicator Properties + + } + { This is the current value of the progress indicator. } + xpProperty_ProgressPosition = 1800 +; + { This is the minimum value, equivalent to 0% filled. } + xpProperty_ProgressMin = 1801 +; + { This is the maximum value, equivalent to 100% filled. } + xpProperty_ProgressMax = 1802 +; + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPUIGraphics.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPUIGraphics.pas new file mode 100644 index 0000000..f06806a --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPUIGraphics.pas @@ -0,0 +1,380 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPUIGraphics; +INTERFACE +{ + +} + +USES XPWidgetDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * UI GRAPHICS + ___________________________________________________________________________} +{ + +} + + + { + XPWindowStyle + + There are a few built-in window styles in X-Plane that you can use. + + Note that X-Plane 6 does not offer real shadow-compositing; you must make + sure to put a window on top of another window of the right style to the + shadows work, etc. This applies to elements with insets and shadows. The + rules are: + + Sub windows must go on top of main windows, and screens and list views on + top of subwindows. Only help and main windows can be over the main screen. + + + With X-Plane 7 any window or element may be placed over any other element. + + Some windows are scaled by stretching, some by repeating. The drawing + routines know which scaling method to use. The list view cannot be + rescaled in x-plane 6 because it has both a repeating pattern and a + gradient in one element. All other elements can be rescaled. + } +TYPE + XPWindowStyle = ( + { An LCD screen that shows help. } + xpWindow_Help = 0 + + { A dialog box window. } + ,xpWindow_MainWindow = 1 + + { A panel or frame within a dialog box window. } + ,xpWindow_SubWindow = 2 + + { An LCD screen within a panel to hold text displays. } + ,xpWindow_Screen = 4 + + { A list view within a panel for scrolling file names, etc. } + ,xpWindow_ListView = 5 + + ); + PXPWindowStyle = ^XPWindowStyle; + + { + XPDrawWindow + + This routine draws a window of the given dimensions at the given offset on + the virtual screen in a given style. The window is automatically scaled as + appropriate using a bitmap scaling technique (scaling or repeating) as + appropriate to the style. + } + PROCEDURE XPDrawWindow( + inX1 : integer; + inY1 : integer; + inX2 : integer; + inY2 : integer; + inStyle : XPWindowStyle); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetWindowDefaultDimensions + + This routine returns the default dimensions for a window. Output is either + a minimum or fixed value depending on whether the window is scalable. + } + PROCEDURE XPGetWindowDefaultDimensions( + inStyle : XPWindowStyle; + outWidth : Pinteger; { Can be nil } + outHeight : Pinteger); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPElementStyle + + Elements are individually drawable UI things like push buttons, etc. The + style defines what kind of element you are drawing. Elements can be + stretched in one or two dimensions (depending on the element). Some + elements can be lit. + + In x-plane 6 some elements must be drawn over metal. Some are scalable and + some are not. Any element can be drawn anywhere in x-plane 7. + + Scalable Axis Required Background + } +TYPE + XPElementStyle = ( + { x metal } + xpElement_TextField = 6 + + { none metal } + ,xpElement_CheckBox = 9 + + { none metal } + ,xpElement_CheckBoxLit = 10 + + { none window header } + ,xpElement_WindowCloseBox = 14 + + { none window header } + ,xpElement_WindowCloseBoxPressed = 15 + + { x metal } + ,xpElement_PushButton = 16 + + { x metal } + ,xpElement_PushButtonLit = 17 + + { none any } + ,xpElement_OilPlatform = 24 + + { none any } + ,xpElement_OilPlatformSmall = 25 + + { none any } + ,xpElement_Ship = 26 + + { none any } + ,xpElement_ILSGlideScope = 27 + + { none any } + ,xpElement_MarkerLeft = 28 + + { none any } + ,xpElement_Airport = 29 + + { none any } + ,xpElement_Waypoint = 30 + + { none any } + ,xpElement_NDB = 31 + + { none any } + ,xpElement_VOR = 32 + + { none any } + ,xpElement_RadioTower = 33 + + { none any } + ,xpElement_AircraftCarrier = 34 + + { none any } + ,xpElement_Fire = 35 + + { none any } + ,xpElement_MarkerRight = 36 + + { none any } + ,xpElement_CustomObject = 37 + + { none any } + ,xpElement_CoolingTower = 38 + + { none any } + ,xpElement_SmokeStack = 39 + + { none any } + ,xpElement_Building = 40 + + { none any } + ,xpElement_PowerLine = 41 + + { none metal } + ,xpElement_CopyButtons = 45 + + { none metal } + ,xpElement_CopyButtonsWithEditingGrid = 46 + + { x, y metal } + ,xpElement_EditingGrid = 47 + + { THIS CAN PROBABLY BE REMOVED } + ,xpElement_ScrollBar = 48 + + { none any } + ,xpElement_VORWithCompassRose = 49 + + { none metal } + ,xpElement_Zoomer = 51 + + { x, y metal } + ,xpElement_TextFieldMiddle = 52 + + { none metal } + ,xpElement_LittleDownArrow = 53 + + { none metal } + ,xpElement_LittleUpArrow = 54 + + { none metal } + ,xpElement_WindowDragBar = 61 + + { none metal } + ,xpElement_WindowDragBarSmooth = 62 + + ); + PXPElementStyle = ^XPElementStyle; + + { + XPDrawElement + + XPDrawElement draws a given element at an offset on the virtual screen in + set dimensions. EVEN if the element is not scalable, it will be scaled if + the width and height do not match the preferred dimensions; it'll just look + ugly. Pass inLit to see the lit version of the element; if the element + cannot be lit this is ignored. + } + PROCEDURE XPDrawElement( + inX1 : integer; + inY1 : integer; + inX2 : integer; + inY2 : integer; + inStyle : XPElementStyle; + inLit : integer); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetElementDefaultDimensions + + This routine returns the recommended or minimum dimensions of a given UI + element. outCanBeLit tells whether the element has both a lit and unlit + state. Pass NULL to not receive any of these parameters. + } + PROCEDURE XPGetElementDefaultDimensions( + inStyle : XPElementStyle; + outWidth : Pinteger; { Can be nil } + outHeight : Pinteger; { Can be nil } + outCanBeLit : Pinteger); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPTrackStyle + + A track is a UI element that displays a value vertically or horizontally. + X-Plane has three kinds of tracks: scroll bars, sliders, and progress bars. + Tracks can be displayed either horizontally or vertically; tracks will + choose their own layout based on the larger dimension of their dimensions + (e.g. they know if they are tall or wide). Sliders may be lit or unlit + (showing the user manipulating them). + + ScrollBar - this is a standard scroll bar with arrows and a thumb to drag. + Slider - this is a simple track with a ball in the middle that can be + slid. Progress - this is a progress indicator showing how a long task is + going. + } +TYPE + XPTrackStyle = ( + { not over metal can be lit can be rotated } + xpTrack_ScrollBar = 0 + + { over metal can be lit can be rotated } + ,xpTrack_Slider = 1 + + { over metal cannot be lit cannot be rotated } + ,xpTrack_Progress = 2 + + ); + PXPTrackStyle = ^XPTrackStyle; + + { + XPDrawTrack + + This routine draws a track. You pass in the track dimensions and size; the + track picks the optimal orientation for these dimensions. Pass in the + track's minimum current and maximum values; the indicator will be + positioned appropriately. You can also specify whether the track is lit or + not. + } + PROCEDURE XPDrawTrack( + inX1 : integer; + inY1 : integer; + inX2 : integer; + inY2 : integer; + inMin : integer; + inMax : integer; + inValue : integer; + inTrackStyle : XPTrackStyle; + inLit : integer); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetTrackDefaultDimensions + + This routine returns a track's default smaller dimension; all tracks are + scalable in the larger dimension. It also returns whether a track can be + lit. + } + PROCEDURE XPGetTrackDefaultDimensions( + inStyle : XPTrackStyle; + outWidth : Pinteger; + outCanBeLit : Pinteger); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetTrackMetrics + + This routine returns the metrics of a track. If you want to write UI code + to manipulate a track, this routine helps you know where the mouse + locations are. For most other elements, the rectangle the element is drawn + in is enough information. However, the scrollbar drawing routine does some + automatic placement; this routine lets you know where things ended up. You + pass almost everything you would pass to the draw routine. You get out the + orientation, and other useful stuff. + + Besides orientation, you get five dimensions for the five parts of a + scrollbar, which are the down button, down area (area before the thumb), + the thumb, and the up area and button. For horizontal scrollers, the left + button decreases; for vertical scrollers, the top button decreases. + } + PROCEDURE XPGetTrackMetrics( + inX1 : integer; + inY1 : integer; + inX2 : integer; + inY2 : integer; + inMin : integer; + inMax : integer; + inValue : integer; + inTrackStyle : XPTrackStyle; + outIsVertical : Pinteger; + outDownBtnSize : Pinteger; + outDownPageSize : Pinteger; + outThumbSize : Pinteger; + outUpPageSize : Pinteger; + outUpBtnSize : Pinteger); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgetDefs.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgetDefs.pas new file mode 100644 index 0000000..2e55830 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgetDefs.pas @@ -0,0 +1,441 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPWidgetDefs; +INTERFACE +{ + +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * WIDGET DEFINITIONS + ___________________________________________________________________________} +{ + A widget is a call-back driven screen entity like a push-button, window, + text entry field, etc. + + Use the widget API to create widgets of various classes. You can nest them + into trees of widgets to create complex user interfaces. +} + + + +TYPE + { + XPWidgetID + + A Widget ID is an opaque unique non-zero handle identifying your widget. + Use 0 to specify "no widget". This type is defined as wide enough to hold + a pointer. You receive a widget ID when you create a new widget and then + use that widget ID to further refer to the widget. + } + XPWidgetID = pointer; + PXPWidgetID = ^XPWidgetID; + + { + XPWidgetPropertyID + + Properties are values attached to instances of your widgets. A property is + identified by a 32-bit ID and its value is the width of a pointer. + + Each widget instance may have a property or not have it. When you set a + property on a widget for the first time, the property is added to the + widget; it then stays there for the life of the widget. + + Some property IDs are predefined by the widget package; you can make up + your own property IDs as well. + } + XPWidgetPropertyID = ( + { A window's refcon is an opaque value used by client code to find other data } + { based on it. } + xpProperty_Refcon = 0 + + { These properties are used by the utlities to implement dragging. } + ,xpProperty_Dragging = 1 + + ,xpProperty_DragXOff = 2 + + ,xpProperty_DragYOff = 3 + + { Is the widget hilited? (For widgets that support this kind of thing.) } + ,xpProperty_Hilited = 4 + + { Is there a C++ object attached to this widget? } + ,xpProperty_Object = 5 + + { If this property is 1, the widget package will use OpenGL to restrict } + { drawing to the Wiget's exposed rectangle. } + ,xpProperty_Clip = 6 + + { Is this widget enabled (for those that have a disabled state too)? } + ,xpProperty_Enabled = 7 + + { NOTE: Property IDs 1 - 999 are reserved for the widget's library. } + { } + { NOTE: Property IDs 1000 - 9999 are allocated to the standard widget classes } + { provided with the library Properties 1000 - 1099 are for widget class 0, } + { 1100 - 1199 for widget class 1, etc. } + ,xpProperty_UserStart = 10000 + + ); + PXPWidgetPropertyID = ^XPWidgetPropertyID; + + { + XPMouseState_t + + When the mouse is clicked or dragged, a pointer to this structure is passed + to your widget function. + } + XPMouseState_t = RECORD + x : integer; + y : integer; + { Mouse Button number, left = 0 (right button not yet supported. } + button : integer; +{$IFDEF XPLM200} + { Scroll wheel delta (button in this case would be the wheel axis number). } + delta : integer; +{$ENDIF} + END; + PXPMouseState_t = ^XPMouseState_t; + + { + XPKeyState_t + + When a key is pressed, a pointer to this struct is passed to your widget + function. + } + XPKeyState_t = RECORD + { The ASCII key that was pressed. WARNING: this may be 0 for some non-ASCII } + { key sequences. } + key : char; + { The flags. Make sure to check this if you only want key-downs! } + flags : XPLMKeyFlags; + { The virtual key code for the key } + vkey : char; + END; + PXPKeyState_t = ^XPKeyState_t; + + { + XPWidgetGeometryChange_t + + This structure contains the deltas for your widget's geometry when it + changes. + } + XPWidgetGeometryChange_t = RECORD + dx : integer; + { +Y = the widget moved up } + dy : integer; + dwidth : integer; + dheight : integer; + END; + PXPWidgetGeometryChange_t = ^XPWidgetGeometryChange_t; + + { + XPDispatchMode + + The dispatching modes describe how the widgets library sends out messages. + Currently there are three modes: + } + XPDispatchMode = ( + { The message will only be sent to the target widget. } + xpMode_Direct = 0 + + { The message is sent to the target widget, then up the chain of parents } + { until the message is handled or a parentless widget is reached. } + ,xpMode_UpChain = 1 + + { The message is sent to the target widget and then all of its children } + { recursively depth-first. } + ,xpMode_Recursive = 2 + + { The message is snet just to the target, but goes to every callback, even if } + { it is handled. } + ,xpMode_DirectAllCallbacks = 3 + + { The message is only sent to the very first handler even if it is not } + { accepted. (This is really only useful for some internal Widget Lib } + { functions. } + ,xpMode_Once = 4 + + ); + PXPDispatchMode = ^XPDispatchMode; + + { + XPWidgetClass + + Widget classes define predefined widget types. A widget class basically + specifies from a library the widget function to be used for the widget. + Most widgets can be made right from classes. + } + XPWidgetClass = integer; + PXPWidgetClass = ^XPWidgetClass; + +CONST + { An unspecified widget class. Other widget classes are in } + { XPStandardWidgets.h } + xpWidgetClass_None = 0; + +{___________________________________________________________________________ + * WIDGET MESSAGES + ___________________________________________________________________________} +{ + +} + + + { + XPWidgetMessage + + Widgets receive 32-bit messages indicating what action is to be taken or + notifications of events. The list of messages may be expanded. + } +TYPE + XPWidgetMessage = ( + { No message, should not be sent. } + xpMsg_None = 0 + + { The create message is sent once per widget that is created with your widget } + { function and once for any widget that has your widget function attached. } + { } + { Dispatching: Direct } + { } + { Param 1: 1 if you are being added as a subclass, 0 if the widget is first } + { being created. } + ,xpMsg_Create = 1 + + { The destroy message is sent once for each message that is destroyed that } + { has your widget function. } + { } + { Dispatching: Direct for all } + { } + { Param 1: 1 if being deleted by a recursive delete to the parent, 0 for } + { explicit deletion. } + ,xpMsg_Destroy = 2 + + { The paint message is sent to your widget to draw itself. The paint message } + { is the bare-bones message; in response you must draw yourself, draw your } + { children, set up clipping and culling, check for visibility, etc. If you } + { don't want to do all of this, ignore the paint message and a draw message } + { (see below) will be sent to you. } + { } + { Dispatching: Direct } + ,xpMsg_Paint = 3 + + { The draw message is sent to your widget when it is time to draw yourself. } + { OpenGL will be set up to draw in 2-d global screen coordinates, but you } + { should use the XPLM to set up OpenGL state. } + { } + { Dispatching: Direct } + ,xpMsg_Draw = 4 + + { The key press message is sent once per key that is pressed. The first } + { parameter is the type of key code (integer or char) and the second is the } + { code itself. By handling this event, you consume the key stroke. } + { } + { Handling this message 'consumes' the keystroke; not handling it passes it } + { to your parent widget. } + { } + { Dispatching: Up Chain } + { } + { : Param 1: A pointer to an XPKeyState_t structure with the keystroke. } + ,xpMsg_KeyPress = 5 + + { Keyboard focus is being given to you. By handling this message you accept } + { keyboard focus. The first parameter will be one if a child of yours gave } + { up focus to you, 0 if someone set focus on you explicitly. } + { } + { : Handling this message accepts focus; not handling refuses focus. } + { } + { Dispatching: direct } + { } + { Param 1: 1 if you are gaining focus because your child is giving it up, 0 } + { if someone is explicitly giving you focus. } + ,xpMsg_KeyTakeFocus = 6 + + { Keyboard focus is being taken away from you. The first parameter will be } + { one if you are losing focus because another widget is taking it, or 0 if } + { someone called the API to make you lose focus explicitly. } + { } + { Dispatching: Direct } + { } + { Param 1: 1 if focus is being taken by another widget, 0 if code requested } + { to remove focus. } + ,xpMsg_KeyLoseFocus = 7 + + { You receive one mousedown event per click with a mouse-state structure } + { pointed to by parameter 1, by accepting this you eat the click, otherwise } + { your parent gets it. You will not receive drag and mouse up messages if } + { you do not accept the down message. } + { } + { Handling this message consumes the mouse click, not handling it passes it } + { to the next widget. You can act 'transparent' as a window by never handling } + { moues clicks to certain areas. } + { } + { Dispatching: Up chain NOTE: Technically this is direct dispatched, but the } + { widgets library will shop it to each widget until one consumes the click, } + { making it effectively "up chain". } + { } + { Param 1: A pointer to an XPMouseState_t containing the mouse status. } + ,xpMsg_MouseDown = 8 + + { You receive a series of mouse drag messages (typically one per frame in the } + { sim) as the mouse is moved once you have accepted a mouse down message. } + { Parameter one points to a mouse-state structure describing the mouse } + { location. You will continue to receive these until the mouse button is } + { released. You may receive multiple mouse state messages with the same mouse } + { position. You will receive mouse drag events even if the mouse is dragged } + { out of your current or original bounds at the time of the mouse down. } + { } + { Dispatching: Direct } + { } + { Param 1: A pointer to an XPMouseState_t containing the mouse status. } + ,xpMsg_MouseDrag = 9 + + { The mouseup event is sent once when the mouse button is released after a } + { drag or click. You only receive this message if you accept the mouseDown } + { message. Parameter one points to a mouse state structure. } + { } + { Dispatching: Direct } + { } + { Param 1: A pointer to an XPMouseState_t containing the mouse status. } + ,xpMsg_MouseUp = 10 + + { Your geometry or a child's geometry is being changed. } + { } + { Dispatching: Up chain } + { } + { Param 1: The widget ID of the original reshaped target. } + { } + { Param 2: A pointer to a XPWidgetGeometryChange_t struct describing the } + { change. } + ,xpMsg_Reshape = 11 + + { Your exposed area has changed. } + { } + { Dispatching: Direct } + ,xpMsg_ExposedChanged = 12 + + { A child has been added to you. The child's ID is passed in parameter one. } + { } + { } + { Dispatching: Direct } + { } + { Param 1: The Widget ID of the child being added. } + ,xpMsg_AcceptChild = 13 + + { A child has been removed from to you. The child's ID is passed in } + { parameter one. } + { } + { Dispatching: Direct } + { } + { Param 1: The Widget ID of the child being removed. } + ,xpMsg_LoseChild = 14 + + { You now have a new parent, or have no parent. The parent's ID is passed } + { in, or 0 for no parent. } + { } + { Dispatching: Direct } + { } + { Param 1: The Widget ID of your parent } + ,xpMsg_AcceptParent = 15 + + { You or a child has been shown. Note that this does not include you being } + { shown because your parent was shown, you were put in a new parent, your } + { root was shown, etc. } + { } + { Dispatching: Up chain } + { } + { Param 1: The widget ID of the shown widget. } + ,xpMsg_Shown = 16 + + { You have been hidden. See limitations above. } + { } + { Dispatching: Up chain } + { } + { Param 1: The widget ID of the hidden widget. } + ,xpMsg_Hidden = 17 + + { Your descriptor has changed. } + { } + { Dispatching: Direct } + ,xpMsg_DescriptorChanged = 18 + + { A property has changed. Param 1 contains the property ID. } + { } + { Dispatching: Direct } + { } + { Param 1: The Property ID being changed. } + { } + { Param 2: The new property value } + ,xpMsg_PropertyChanged = 19 + +{$IFDEF XPLM200} + { The mouse wheel has moved. } + { } + { Return 1 to consume the mouse wheel move, or 0 to pass the message to a } + { parent. Dispatching: Up chain } + { } + { Param 1: A pointer to an XPMouseState_t containing the mouse status. } + ,xpMsg_MouseWheel = 20 +{$ENDIF} + +{$IFDEF XPLM200} + { The cursor is over your widget. If you consume this message, change the } + { XPLMCursorStatus value to indicate the desired result, with the same rules } + { as in XPLMDisplay.h. } + { } + { Return 1 to consume this message, 0 to pass it on. } + { } + { Dispatching: Up chain Param 1: A pointer to an XPMouseState_t struct } + { containing the mouse status. } + { } + { Param 2: A pointer to a XPLMCursorStatus - set this to the cursor result } + { you desire. } + ,xpMsg_CursorAdjust = 21 +{$ENDIF} + + { NOTE: Message IDs 1000 - 9999 are allocated to the standard widget classes } + { provided with the library with 1000 - 1099 for widget class 0, 1100 - 1199 } + { for widget class 1, etc. Message IDs 10,000 and beyond are for plugin use. } + ,xpMsg_UserStart = 10000 + + ); + PXPWidgetMessage = ^XPWidgetMessage; + +{___________________________________________________________________________ + * WIDGET CALLBACK FUNCTION + ___________________________________________________________________________} +{ + +} + + + { + XPWidgetFunc_t + + This function defines your custom widget's behavior. It will be called by + the widgets library to send messages to your widget. The message and + widget ID are passed in, as well as two ptr-width signed parameters whose + meaning varies with the message. Return 1 to indicate that you have + processed the message, 0 to indicate that you have not. For any message + that is not understood, return 0. + } +TYPE + XPWidgetFunc_t = FUNCTION( + inMessage : XPWidgetMessage; + inWidget : XPWidgetID; + inParam1 : intptr_t; + inParam2 : intptr_t) : integer; cdecl; + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgetUtils.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgetUtils.pas new file mode 100644 index 0000000..9dcb1d2 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgetUtils.pas @@ -0,0 +1,225 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPWidgetUtils; +INTERFACE +{ + XPWidgetUtils - USAGE NOTES + + The XPWidgetUtils library contains useful functions that make writing and + using widgets less of a pain. + + One set of functions are the widget behavior functions. These functions + each add specific useful behaviors to widgets. They can be used in two + manners: + + 1. You can add a widget behavior function to a widget as a callback proc + using the XPAddWidgetCallback function. The widget will gain that + behavior. Remember that the last function you add has highest priority. + You can use this to change or augment the behavior of an existing finished + widget. + + 2. You can call a widget function from inside your own widget function. + This allows you to include useful behaviors in custom-built widgets. A + number of the standard widgets get their behavior from this library. To do + this, call the behavior function from your function first. If it returns + 1, that means it handled the event and you don't need to; simply return 1. +} + +USES XPWidgetDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * GENERAL UTILITIES + ___________________________________________________________________________} +{ + +} + + + + { + XPWidgetCreate_t + + This structure contains all of the parameters needed to create a wiget. It + is used with XPUCreateWidgets to create widgets in bulk from an array. All + parameters correspond to those of XPCreateWidget except for the container + index. If the container index is equal to the index of a widget in the + array, the widget in the array passed to XPUCreateWidgets is used as the + parent of this widget. Note that if you pass an index greater than your + own position in the array, the parent you are requesting will not exist + yet. If the container index is NO_PARENT, the parent widget is specified as + NULL. If the container index is PARAM_PARENT, the widget passed into + XPUCreateWidgets is used. + } +TYPE + XPWidgetCreate_t = RECORD + left : integer; + top : integer; + right : integer; + bottom : integer; + visible : integer; + descriptor : Pchar; + isRoot : integer; + containerIndex : integer; + widgetClass : XPWidgetClass; + END; + PXPWidgetCreate_t = ^XPWidgetCreate_t; + +CONST + NO_PARENT = -1; + + PARAM_PARENT = -2; + + + { + XPUCreateWidgets + + This function creates a series of widgets from a table...see + XPCreateWidget_t above. Pass in an array of widget creation structures and + an array of widget IDs that will receive each widget. + + Widget parents are specified by index into the created widget table, + allowing you to create nested widget structures. You can create multiple + widget trees in one table. Generally you should create widget trees from + the top down. + + You can also pass in a widget ID that will be used when the widget's parent + is listed as PARAM_PARENT; this allows you to embed widgets created with + XPUCreateWidgets in a widget created previously. + } + PROCEDURE XPUCreateWidgets( + inWidgetDefs : PXPWidgetCreate_t; + inCount : integer; + inParamParent : XPWidgetID; + ioWidgets : PXPWidgetID); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPUMoveWidgetBy + + Simply moves a widget by an amount, +x = right, +y=up, without resizing the + widget. + } + PROCEDURE XPUMoveWidgetBy( + inWidget : XPWidgetID; + inDeltaX : integer; + inDeltaY : integer); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * LAYOUT MANAGERS + ___________________________________________________________________________} +{ + The layout managers are widget behavior functions for handling where + widgets move. Layout managers can be called from a widget function or + attached to a widget later. +} + + + + { + XPUFixedLayout + + This function causes the widget to maintain its children in fixed position + relative to itself as it is resized. Use this on the top level 'window' + widget for your window. + } + FUNCTION XPUFixedLayout( + inMessage : XPWidgetMessage; + inWidget : XPWidgetID; + inParam1 : intptr_t; + inParam2 : intptr_t) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * WIDGET PROC BEHAVIORS + ___________________________________________________________________________} +{ + These widget behavior functions add other useful behaviors to widgets. + These functions cannot be attached to a widget; they must be called from + your widget function. +} + + + + { + XPUSelectIfNeeded + + This causes the widget to bring its window to the foreground if it is not + already. inEatClick specifies whether clicks in the background should be + consumed by bringin the window to the foreground. + } + FUNCTION XPUSelectIfNeeded( + inMessage : XPWidgetMessage; + inWidget : XPWidgetID; + inParam1 : intptr_t; + inParam2 : intptr_t; + inEatClick : integer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPUDefocusKeyboard + + This causes a click in the widget to send keyboard focus back to X-Plane. + This stops editing of any text fields, etc. + } + FUNCTION XPUDefocusKeyboard( + inMessage : XPWidgetMessage; + inWidget : XPWidgetID; + inParam1 : intptr_t; + inParam2 : intptr_t; + inEatClick : integer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPUDragWidget + + XPUDragWidget drags the widget in response to mouse clicks. Pass in not + only the event, but the global coordinates of the drag region, which might + be a sub-region of your widget (for example, a title bar). + } + FUNCTION XPUDragWidget( + inMessage : XPWidgetMessage; + inWidget : XPWidgetID; + inParam1 : intptr_t; + inParam2 : intptr_t; + inLeft : integer; + inTop : integer; + inRight : integer; + inBottom : integer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgets.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgets.pas new file mode 100644 index 0000000..44623dc --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/Widgets/XPWidgets.pas @@ -0,0 +1,665 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPWidgets; +INTERFACE +{ + WIDGETS - THEORY OF OPERATION AND NOTES + + Widgets are persistent view 'objects' for X-Plane. A widget is an object + referenced by its opaque handle (widget ID) and the APIs in this file. You + cannot access the widget's guts directly. Every Widget has the following + intrinsic data: + + - A bounding box defined in global screen coordinates with 0,0 in the + bottom left and +y = up, +x = right. + + - A visible box, which is the intersection of the bounding box with the + widget's parents visible box. + + - Zero or one parent widgets. (Always zero if the widget is a root widget. + + + - Zero or more child widgets. + + - Whether the widget is a root. Root widgets are the top level plugin + windows. + + - Whether the widget is visible. + + - A text string descriptor, whose meaning varies from widget to widget. + + - An arbitrary set of 32 bit integral properties defined by 32-bit integral + keys. This is how specific widgets + + store specific data. + + - A list of widget callbacks proc that implements the widgets behaviors. + + The Widgets library sends messages to widgets to request specific behaviors + or notify the widget of things. + + Widgets may have more than one callback function, in which case messages + are sent to the most recently added callback function until the message is + handled. Messages may also be sent to parents or children; see the + XPWidgetDefs.h header file for the different widget message dispatching + functions. By adding a callback function to a window you can 'subclass' + its behavior. + + A set of standard widgets are provided that serve common UI purposes. You + can also customize or implement entirely custom widgets. + + Widgets are different than other view hierarchies (most notably Win32, + which they bear a striking resemblance to) in the following ways: + + - Not all behavior can be patched. State that is managed by the XPWidgets + DLL and not by individual widgets cannot be customized. + + - All coordinates are in global screen coordinates. Coordinates are not + relative to an enclosing widget, nor are they relative to a display window. + + + - Widget messages are always dispatched synchronously, and there is no + concept of scheduling an update or a dirty region. Messages originate from + X-Plane as the sim cycle goes by. Since x-plane is constantly redrawing, + so are widgets; there is no need to mark a part of a widget as 'needing + redrawing' because redrawing happens frequently whether the widget needs it + or not. + + - Any widget may be a 'root' widget, causing it to be drawn; there is no + relationship between widget class and rootness. Root widgets are + imlemented as XPLMDisply windows. +} + +USES XPWidgetDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * WIDGET CREATION AND MANAGEMENT + ___________________________________________________________________________} +{ + +} + + + { + XPCreateWidget + + This function creates a new widget and returns the new widget's ID to you. + If the widget creation fails for some reason, it returns NULL. Widget + creation will fail either if you pass a bad class ID or if there is not + adequate memory. + + Input Parameters: + + - Top, left, bottom, and right in global screen coordinates defining the + widget's location on the screen. + + - inVisible is 1 if the widget should be drawn, 0 to start the widget as + hidden. + + - inDescriptor is a null terminated string that will become the widget's + descriptor. + + - inIsRoot is 1 if this is going to be a root widget, 0 if it will not be. + + - inContainer is the ID of this widget's container. It must be 0 for a + root widget. for a non-root widget, pass the widget ID of the widget to + place this widget within. If this widget is not going to start inside + another widget, pass 0; this new widget will then just be floating off in + space (and will not be drawn until it is placed in a widget. + + - inClass is the class of the widget to draw. Use one of the predefined + class-IDs to create a standard widget. + + A note on widget embedding: a widget is only called (and will be drawn, + etc.) if it is placed within a widget that will be called. Root widgets + are always called. So it is possible to have whole chains of widgets that + are simply not called. You can preconstruct widget trees and then place + them into root widgets later to activate them if you wish. + } + FUNCTION XPCreateWidget( + inLeft : integer; + inTop : integer; + inRight : integer; + inBottom : integer; + inVisible : integer; + inDescriptor : Pchar; + inIsRoot : integer; + inContainer : XPWidgetID; + inClass : XPWidgetClass) : XPWidgetID; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPCreateCustomWidget + + This function is the same as XPCreateWidget except that instead of passing + a class ID, you pass your widget callback function pointer defining the + widget. Use this function to define a custom widget. All parameters are + the same as XPCreateWidget, except that the widget class has been replaced + with the widget function. + } + FUNCTION XPCreateCustomWidget( + inLeft : integer; + inTop : integer; + inRight : integer; + inBottom : integer; + inVisible : integer; + inDescriptor : Pchar; + inIsRoot : integer; + inContainer : XPWidgetID; + inCallback : XPWidgetFunc_t) : XPWidgetID; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPDestroyWidget + + This class destroys a widget. Pass in the ID of the widget to kill. If + you pass 1 for inDestroyChilren, the widget's children will be destroyed + first, then this widget will be destroyed. (Furthermore, the widget's + children will be destroyed with the inDestroyChildren flag set to 1, so the + destruction will recurse down the widget tree.) If you pass 0 for this + flag, the child widgets will simply end up with their parent set to 0. + } + PROCEDURE XPDestroyWidget( + inWidget : XPWidgetID; + inDestroyChildren : integer); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPSendMessageToWidget + + This sends any message to a widget. You should probably not go around + simulating the predefined messages that the widgets library defines for + you. You may however define custom messages for your widgets and send them + with this method. + + This method supports several dispatching patterns; see XPDispatchMode for + more info. The function returns 1 if the message was handled, 0 if it was + not. + + For each widget that receives the message (see the dispatching modes), each + widget function from the most recently installed to the oldest one + receives the message in order until it is handled. + } + FUNCTION XPSendMessageToWidget( + inWidget : XPWidgetID; + inMessage : XPWidgetMessage; + inMode : XPDispatchMode; + inParam1 : intptr_t; + inParam2 : intptr_t) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * WIDGET POSITIONING AND VISIBILITY + ___________________________________________________________________________} +{ + +} + + + { + XPPlaceWidgetWithin + + This function changes which container a widget resides in. You may NOT use + this function on a root widget! inSubWidget is the widget that will be + moved. Pass a widget ID in inContainer to make inSubWidget be a child of + inContainer. It will become the last/closest widget in the container. + Pass 0 to remove the widget from any container. Any call to this other + than passing the widget ID of the old parent of the affected widget will + cause the widget to be removed from its old parent. Placing a widget within + its own parent simply makes it the last widget. + + NOTE: this routine does not reposition the sub widget in global + coordinates. If the container has layout management code, it will + reposition the subwidget for you, otherwise you must do it with + SetWidgetGeometry. + } + PROCEDURE XPPlaceWidgetWithin( + inSubWidget : XPWidgetID; + inContainer : XPWidgetID); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPCountChildWidgets + + This routine returns the number of widgets another widget contains. + } + FUNCTION XPCountChildWidgets( + inWidget : XPWidgetID) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetNthChildWidget + + This routine returns the widget ID of a child widget by index. Indexes are + 0 based, from 0 to one minus the number of widgets in the parent, + inclusive. If the index is invalid, 0 is returned. + } + FUNCTION XPGetNthChildWidget( + inWidget : XPWidgetID; + inIndex : integer) : XPWidgetID; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetParentWidget + + This routine returns the parent of a widget, or 0 if the widget has no + parent. Root widgets never have parents and therefore always return 0. + } + FUNCTION XPGetParentWidget( + inWidget : XPWidgetID) : XPWidgetID; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPShowWidget + + This routine makes a widget visible if it is not already. Note that if a + widget is not in a rooted widget hierarchy or one of its parents is not + visible, it will still not be visible to the user. + } + PROCEDURE XPShowWidget( + inWidget : XPWidgetID); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPHideWidget + + Makes a widget invisible. See XPShowWidget for considerations of when a + widget might not be visible despite its own visibility state. + } + PROCEDURE XPHideWidget( + inWidget : XPWidgetID); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPIsWidgetVisible + + This returns 1 if a widget is visible, 0 if it is not. Note that this + routine takes into consideration whether a parent is invisible. Use this + routine to tell if the user can see the widget. + } + FUNCTION XPIsWidgetVisible( + inWidget : XPWidgetID) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPFindRootWidget + + XPFindRootWidget returns the Widget ID of the root widget that contains the + passed in widget or NULL if the passed in widget is not in a rooted + hierarchy. + } + FUNCTION XPFindRootWidget( + inWidget : XPWidgetID) : XPWidgetID; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPBringRootWidgetToFront + + This routine makes the specified widget be in the front most widget + hierarchy. If this widget is a root widget, its widget hierarchy comes to + front, otherwise the widget's root is brought to the front. If this widget + is not in an active widget hiearchy (e.g. there is no root widget at the + top of the tree), this routine does nothing. + } + PROCEDURE XPBringRootWidgetToFront( + inWidget : XPWidgetID); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPIsWidgetInFront + + This routine returns true if this widget's hierarchy is the front most + hierarchy. It returns false if the widget's hierarchy is not in front, or + if the widget is not in a rooted hierarchy. + } + FUNCTION XPIsWidgetInFront( + inWidget : XPWidgetID) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetWidgetGeometry + + This routine returns the bounding box of a widget in global coordinates. + Pass NULL for any parameter you are not interested in. + } + PROCEDURE XPGetWidgetGeometry( + inWidget : XPWidgetID; + outLeft : Pinteger; { Can be nil } + outTop : Pinteger; { Can be nil } + outRight : Pinteger; { Can be nil } + outBottom : Pinteger); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPSetWidgetGeometry + + This function changes the bounding box of a widget. + } + PROCEDURE XPSetWidgetGeometry( + inWidget : XPWidgetID; + inLeft : integer; + inTop : integer; + inRight : integer; + inBottom : integer); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetWidgetForLocation + + Given a widget and a location, this routine returns the widget ID of the + child of that widget that owns that location. If inRecursive is true then + this will return a child of a child of a widget as it tries to find the + deepest widget at that location. If inVisibleOnly is true, then only + visible widgets are considered, otherwise all widgets are considered. The + widget ID passed for inContainer will be returned if the location is in + that widget but not in a child widget. 0 is returned if the location is + not in the container. + + NOTE: if a widget's geometry extends outside its parents geometry, it will + not be returned by this call for mouse locations outside the parent + geometry. The parent geometry limits the child's eligibility for mouse + location. + } + FUNCTION XPGetWidgetForLocation( + inContainer : XPWidgetID; + inXOffset : integer; + inYOffset : integer; + inRecursive : integer; + inVisibleOnly : integer) : XPWidgetID; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetWidgetExposedGeometry + + This routine returns the bounds of the area of a widget that is completely + within its parent widgets. Since a widget's bounding box can be outside + its parent, part of its area will not be elligible for mouse clicks and + should not draw. Use XPGetWidgetGeometry to find out what area defines + your widget's shape, but use this routine to find out what area to actually + draw into. Note that the widget library does not use OpenGL clipping to + keep frame rates up, although you could use it internally. + } + PROCEDURE XPGetWidgetExposedGeometry( + inWidgetID : XPWidgetID; + outLeft : Pinteger; { Can be nil } + outTop : Pinteger; { Can be nil } + outRight : Pinteger; { Can be nil } + outBottom : Pinteger); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * ACCESSING WIDGET DATA + ___________________________________________________________________________} +{ + +} + + + { + XPSetWidgetDescriptor + + Every widget has a descriptor, which is a text string. What the text + string is used for varies from widget to widget; for example, a push + button's text is its descriptor, a caption shows its descriptor, and a text + field's descriptor is the text being edited. In other words, the usage for + the text varies from widget to widget, but this API provides a universal + and convenient way to get at it. While not all UI widgets need their + descriptor, many do. + } + PROCEDURE XPSetWidgetDescriptor( + inWidget : XPWidgetID; + inDescriptor : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetWidgetDescriptor + + This routine returns the widget's descriptor. Pass in the length of the + buffer you are going to receive the descriptor in. The descriptor will be + null terminated for you. This routine returns the length of the actual + descriptor; if you pass NULL for outDescriptor, you can get the + descriptor's length without getting its text. If the length of the + descriptor exceeds your buffer length, the buffer will not be null + terminated (this routine has 'strncpy' semantics). + } + FUNCTION XPGetWidgetDescriptor( + inWidget : XPWidgetID; + outDescriptor : Pchar; + inMaxDescLength : integer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPSetWidgetProperty + + This function sets a widget's property. Properties are arbitrary values + associated by a widget by ID. + } + PROCEDURE XPSetWidgetProperty( + inWidget : XPWidgetID; + inProperty : XPWidgetPropertyID; + inValue : intptr_t); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetWidgetProperty + + This routine returns the value of a widget's property, or 0 if the property + is not defined. If you need to know whether the property is defined, pass + a pointer to an int for inExists; the existence of that property will be + returned in the int. Pass NULL for inExists if you do not need this + information. + } + FUNCTION XPGetWidgetProperty( + inWidget : XPWidgetID; + inProperty : XPWidgetPropertyID; + inExists : Pinteger) : intptr_t; { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * KEYBOARD MANAGEMENT + ___________________________________________________________________________} +{ + +} + + + { + XPSetKeyboardFocus + + XPSetKeyboardFocus controls which widget will receive keystrokes. Pass the + Widget ID of the widget to get the keys. Note that if the widget does not + care about keystrokes, they will go to the parent widget, and if no widget + cares about them, they go to X-Plane. + + If you set the keyboard focus to Widget ID 0, X-Plane gets keyboard focus. + + This routine returns the widget ID that ended up with keyboard focus, or 0 + for x-plane. + + Keyboard focus is not changed if the new widget will not accept it. For + setting to x-plane, keyboard focus is always accepted. + + } + FUNCTION XPSetKeyboardFocus( + inWidget : XPWidgetID) : XPWidgetID; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLoseKeyboardFocus + + This causes the specified widget to lose focus; focus is passed to its + parent, or the next parent that will accept it. This routine does nothing + if this widget does not have focus. + } + PROCEDURE XPLoseKeyboardFocus( + inWidget : XPWidgetID); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetWidgetWithFocus + + This routine returns the widget that has keyboard focus, or 0 if X-Plane + has keyboard focus or some other plugin window that does not have widgets + has focus. + } + FUNCTION XPGetWidgetWithFocus: XPWidgetID; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * CREATING CUSTOM WIDGETS + ___________________________________________________________________________} +{ + +} + + + { + XPAddWidgetCallback + + This function adds a new widget callback to a widget. This widget callback + supercedes any existing ones and will receive messages first; if it does + not handle messages they will go on to be handled by pre-existing widgets. + + The widget function will remain on the widget for the life of the widget. + The creation message will be sent to the new callback immediately with the + widget ID, and the destruction message will be sent before the other widget + function receives a destruction message. + + This provides a way to 'subclass' an existing widget. By providing a + second hook that only handles certain widget messages, you can customize or + extend widget behavior. + } + PROCEDURE XPAddWidgetCallback( + inWidget : XPWidgetID; + inNewCallback : XPWidgetFunc_t); +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPGetWidgetClassFunc + + Given a widget class, this function returns the callbacks that power that + widget class. + } + FUNCTION XPGetWidgetClassFunc( + inWidgetClass : XPWidgetClass) : XPWidgetFunc_t; +{$IFDEF DELPHI} + cdecl; external 'XPWIDGETS.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMCamera.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMCamera.pas new file mode 100644 index 0000000..44b121c --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMCamera.pas @@ -0,0 +1,174 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMCamera; +INTERFACE +{ + XPLMCamera - THEORY OF OPERATION The XPLMCamera APIs allow plug-ins to + control the camera angle in X-Plane. This has a number of applications, + including but not limited to: + + - Creating new views (including dynamic/user-controllable views) for the + user. + + - Creating applications that use X-Plane as a renderer of scenery, + aircrafts, or both. + + The camera is controlled via six parameters: a location in OpenGL + coordinates and pitch, roll and yaw, similar to an airplane's position. + OpenGL coordinate info is described in detail in the XPLMGraphics + documentation; generally you should use the XPLMGraphics routines to + convert from world to local coordinates. The camera's orientation starts + facing level with the ground directly up the negative-Z axis + (approximately north) with the horizon horizontal. It is then rotated + clockwise for yaw, pitched up for positive pitch, and rolled clockwise + around the vector it is looking along for roll. + + You control the camera either either until the user selects a new view or + permanently (the later being similar to how UDP camera control works). You + control the camera by registering a callback per frame from which you + calculate the new camera positions. This guarantees smooth camera motion. + + Use the XPLMDataAccess APIs to get information like the position of the + aircraft, etc. for complex camera positioning. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * CAMERA CONTROL + ___________________________________________________________________________} +{ + +} + + + { + XPLMCameraControlDuration + + This enumeration states how long you want to retain control of the camera. + You can retain it indefinitely or until the user selects a new view. + } +TYPE + XPLMCameraControlDuration = ( + { Control the camera until the user picks a new view. } + xplm_ControlCameraUntilViewChanges = 1 + + { Control the camera until your plugin is disabled or another plugin forcably } + { takes control. } + ,xplm_ControlCameraForever = 2 + + ); + PXPLMCameraControlDuration = ^XPLMCameraControlDuration; + + { + XPLMCameraPosition_t + + This structure contains a full specification of the camera. X, Y, and Z + are the camera's position in OpenGL coordiantes; pitch, roll, and yaw are + rotations from a camera facing flat north in degrees. Positive pitch means + nose up, positive roll means roll right, and positive yaw means yaw right, + all in degrees. Zoom is a zoom factor, with 1.0 meaning normal zoom and 2.0 + magnifying by 2x (objects appear larger). + } + XPLMCameraPosition_t = RECORD + x : single; + y : single; + z : single; + pitch : single; + heading : single; + roll : single; + zoom : single; + END; + PXPLMCameraPosition_t = ^XPLMCameraPosition_t; + + { + XPLMCameraControl_f + + You use an XPLMCameraControl function to provide continuous control over + the camera. You are passed in a structure in which to put the new camera + position; modify it and return 1 to reposition the camera. Return 0 to + surrender control of the camera; camera control will be handled by X-Plane + on this draw loop. The contents of the structure as you are called are + undefined. + + If X-Plane is taking camera control away from you, this function will be + called with inIsLosingControl set to 1 and ioCameraPosition NULL. + } + XPLMCameraControl_f = FUNCTION( + outCameraPosition : PXPLMCameraPosition_t; { Can be nil } + inIsLosingControl : integer; + inRefcon : pointer) : integer; cdecl; + + { + XPLMControlCamera + + This function repositions the camera on the next drawing cycle. You must + pass a non-null control function. Specify in inHowLong how long you'd like + control (indefinitely or until a key is pressed). + } + PROCEDURE XPLMControlCamera( + inHowLong : XPLMCameraControlDuration; + inControlFunc : XPLMCameraControl_f; + inRefcon : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDontControlCamera + + This function stops you from controlling the camera. If you have a camera + control function, it will not be called with an inIsLosingControl flag. + X-Plane will control the camera on the next cycle. + + For maximum compatibility you should not use this routine unless you are in + posession of the camera. + } + PROCEDURE XPLMDontControlCamera; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMIsCameraBeingControlled + + This routine returns 1 if the camera is being controlled, zero if it is + not. If it is and you pass in a pointer to a camera control duration, the + current control duration will be returned. + } + FUNCTION XPLMIsCameraBeingControlled( + outCameraControlDuration: PXPLMCameraControlDuration) : integer; { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMReadCameraPosition + + This function reads the current camera position. + } + PROCEDURE XPLMReadCameraPosition( + outCameraPosition : PXPLMCameraPosition_t); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDataAccess.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDataAccess.pas new file mode 100644 index 0000000..e82ded4 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDataAccess.pas @@ -0,0 +1,764 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMDataAccess; +INTERFACE +{ + XPLM Data Access API - Theory of Operation + + The data access API gives you a generic, flexible, high performance way to + read and write data to and from X-Plane and other plug-ins. For example, + this API allows you to read and set the nav radios, get the plane location, + determine the current effective graphics frame rate, etc. + + The data access APIs are the way that you read and write data from the sim + as well as other plugins. + + The API works using opaque data references. A data reference is a source + of data; you do not know where it comes from, but once you have it you can + read the data quickly and possibly write it. To get a data reference, you + look it up. + + Data references are identified by verbose string names + (sim/cockpit/radios/nav1_freq_hz). The actual numeric value of the data + reference is implementation defined and is likely to change each time the + simulator is run (or the plugin that provides the datareference is + reloaded). + + The task of looking up a data reference is relatively expensive; look up + your data references once based on verbose strings, and save the opaque + data reference value for the duration of your plugin's operation. Reading + and writing data references is relatively fast (the cost is equivalent to + two function calls through function pointers). + + This allows data access to be high performance, while leaving in + abstraction; since data references are opaque and are searched for, the + underlying data access system can be rebuilt. + + A note on typing: you must know the correct data type to read and write. + APIs are provided for reading and writing data in a number of ways. You + can also double check the data type for a data ref. Note that automatic + conversion is not done for you. + + A note for plugins sharing data with other plugins: the load order of + plugins is not guaranteed. To make sure that every plugin publishing data + has published their data references before other plugins try to subscribe, + publish your data references in your start routine but resolve them the + first time your 'enable' routine is called, or the first time they are + needed in code. + + X-Plane publishes well over 1000 datarefs; a complete list may be found in + the reference section of the SDK online documentation (from the SDK home + page, choose Documentation). +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * READING AND WRITING DATA + ___________________________________________________________________________} +{ + These routines allow you to access a wide variety of data from within + x-plane and modify some of it. +} + + + +TYPE + { + XPLMDataRef + + A data ref is an opaque handle to data provided by the simulator or another + plugin. It uniquely identifies one variable (or array of variables) over + the lifetime of your plugin. You never hard code these values; you always + get them from XPLMFindDataRef. + } + XPLMDataRef = pointer; + PXPLMDataRef = ^XPLMDataRef; + + { + XPLMDataTypeID + + This is an enumeration that defines the type of the data behind a data + reference. This allows you to sanity check that the data type matches what + you expect. But for the most part, you will know the type of data you are + expecting from the online documentation. + + Data types each take a bit field, so sets of data types may be formed. + } + XPLMDataTypeID = ( + { Data of a type the current XPLM doesn't do. } + xplmType_Unknown = 0 + + { A single 4-byte integer, native endian. } + ,xplmType_Int = 1 + + { A single 4-byte float, native endian. } + ,xplmType_Float = 2 + + { A single 8-byte double, native endian. } + ,xplmType_Double = 4 + + { An array of 4-byte floats, native endian. } + ,xplmType_FloatArray = 8 + + { An array of 4-byte integers, native endian. } + ,xplmType_IntArray = 16 + + { A variable block of data. } + ,xplmType_Data = 32 + + ); + PXPLMDataTypeID = ^XPLMDataTypeID; + + { + XPLMFindDataRef + + Given a c-style string that names the data ref, this routine looks up the + actual opaque XPLMDataRef that you use to read and write the data. The + string names for datarefs are published on the x-plane SDK web site. + + This function returns NULL if the data ref cannot be found. + + NOTE: this function is relatively expensive; save the XPLMDataRef this + function returns for future use. Do not look up your data ref by string + every time you need to read or write it. + } + FUNCTION XPLMFindDataRef( + inDataRefName : Pchar) : XPLMDataRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCanWriteDataRef + + Given a data ref, this routine returns true if you can successfully set + the data, false otherwise. Some datarefs are read-only. + } + FUNCTION XPLMCanWriteDataRef( + inDataRef : XPLMDataRef) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMIsDataRefGood + + WARNING: This function is deprecated and should not be used. Datarefs are + valid until plugins are reloaded or the sim quits. Plugins sharing + datarefs should support these semantics by not unregistering datarefs + during operation. (You should however unregister datarefs when your plugin + is unloaded, as part of general resource cleanup.) + + This function returns whether a data ref is still valid. If it returns + false, you should refind the data ref from its original string. Calling an + accessor function on a bad data ref will return a default value, typically + 0 or 0-length data. + } + FUNCTION XPLMIsDataRefGood( + inDataRef : XPLMDataRef) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDataRefTypes + + This routine returns the types of the data ref for accessor use. If a data + ref is available in multiple data types, they will all be returned. + } + FUNCTION XPLMGetDataRefTypes( + inDataRef : XPLMDataRef) : XPLMDataTypeID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * DATA ACCESSORS + ___________________________________________________________________________} +{ + These routines read and write the data references. For each supported data + type there is a reader and a writer. + + If the data ref is invalid or the plugin that provides it is disabled or + there is a type mismatch, the functions that read data will return 0 as a + default value or not modify the passed in memory. The plugins that write + data will not write under these circumstances or if the data ref is + read-only. NOTE: to keep the overhead of reading datarefs low, these + routines do not do full validation of a dataref; passing a junk value for + a dataref can result in crashing the sim. + + For array-style datarefs, you specify the number of items to read/write and + the offset into the array; the actual number of items read or written is + returned. This may be less to prevent an array-out-of-bounds error. +} + + + + { + XPLMGetDatai + + Read an integer data ref and return its value. The return value is the + dataref value or 0 if the dataref is invalid/NULL or the plugin is + disabled. + } + FUNCTION XPLMGetDatai( + inDataRef : XPLMDataRef) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetDatai + + Write a new value to an integer data ref. This routine is a no-op if the + plugin publishing the dataref is disabled, the dataref is invalid, or the + dataref is not writable. + } + PROCEDURE XPLMSetDatai( + inDataRef : XPLMDataRef; + inValue : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDataf + + Read a single precision floating point dataref and return its value. The + return value is the dataref value or 0.0 if the dataref is invalid/NULL or + the plugin is disabled. + } + FUNCTION XPLMGetDataf( + inDataRef : XPLMDataRef) : single; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetDataf + + Write a new value to a single precision floating point data ref. This + routine is a no-op if the plugin publishing the dataref is disabled, the + dataref is invalid, or the dataref is not writable. + } + PROCEDURE XPLMSetDataf( + inDataRef : XPLMDataRef; + inValue : single); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDatad + + Read a double precision floating point dataref and return its value. The + return value is the dataref value or 0.0 if the dataref is invalid/NULL or + the plugin is disabled. + } + FUNCTION XPLMGetDatad( + inDataRef : XPLMDataRef) : real; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetDatad + + Write a new value to a double precision floating point data ref. This + routine is a no-op if the plugin publishing the dataref is disabled, the + dataref is invalid, or the dataref is not writable. + } + PROCEDURE XPLMSetDatad( + inDataRef : XPLMDataRef; + inValue : real); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDatavi + + Read a part of an integer array dataref. If you pass NULL for outVaules, + the routine will return the size of the array, ignoring inOffset and inMax. + + + If outValues is not NULL, then up to inMax values are copied from the + dataref into outValues, starting at inOffset in the dataref. If inMax + + inOffset is larger than the size of the dataref, less than inMax values + will be copied. The number of values copied is returned. + + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. + } + FUNCTION XPLMGetDatavi( + inDataRef : XPLMDataRef; + outValues : Pinteger; { Can be nil } + inOffset : integer; + inMax : integer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetDatavi + + Write part or all of an integer array dataref. The values passed by + inValues are written into the dataref starting at inOffset. Up to inCount + values are written; however if the values would write "off the end" of the + dataref array, then fewer values are written. + + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. + } + PROCEDURE XPLMSetDatavi( + inDataRef : XPLMDataRef; + inValues : Pinteger; + inoffset : integer; + inCount : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDatavf + + Read a part of a single precision floating point array dataref. If you + pass NULL for outVaules, the routine will return the size of the array, + ignoring inOffset and inMax. + + If outValues is not NULL, then up to inMax values are copied from the + dataref into outValues, starting at inOffset in the dataref. If inMax + + inOffset is larger than the size of the dataref, less than inMax values + will be copied. The number of values copied is returned. + + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. + } + FUNCTION XPLMGetDatavf( + inDataRef : XPLMDataRef; + outValues : Psingle; { Can be nil } + inOffset : integer; + inMax : integer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetDatavf + + Write part or all of a single precision floating point array dataref. The + values passed by inValues are written into the dataref starting at + inOffset. Up to inCount values are written; however if the values would + write "off the end" of the dataref array, then fewer values are written. + + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. + } + PROCEDURE XPLMSetDatavf( + inDataRef : XPLMDataRef; + inValues : Psingle; + inoffset : integer; + inCount : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDatab + + Read a part of a byte array dataref. If you pass NULL for outVaules, the + routine will return the size of the array, ignoring inOffset and inMax. + + If outValues is not NULL, then up to inMax values are copied from the + dataref into outValues, starting at inOffset in the dataref. If inMax + + inOffset is larger than the size of the dataref, less than inMax values + will be copied. The number of values copied is returned. + + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. + } + FUNCTION XPLMGetDatab( + inDataRef : XPLMDataRef; + outValue : pointer; { Can be nil } + inOffset : integer; + inMaxBytes : integer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetDatab + + Write part or all of a byte array dataref. The values passed by inValues + are written into the dataref starting at inOffset. Up to inCount values + are written; however if the values would write "off the end" of the dataref + array, then fewer values are written. + + Note: the semantics of array datarefs are entirely implemented by the + plugin (or X-Plane) that provides the dataref, not the SDK itself; the + above description is how these datarefs are intended to work, but a rogue + plugin may have different behavior. + } + PROCEDURE XPLMSetDatab( + inDataRef : XPLMDataRef; + inValue : pointer; + inOffset : integer; + inLength : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * PUBLISHING YOUR PLUGINS DATA + ___________________________________________________________________________} +{ + These functions allow you to create data references that other plug-ins can + access via the above data access APIs. Data references published by other + plugins operate the same as ones published by x-plane in all manners except + that your data reference will not be available to other plugins if/when + your plugin is disabled. + + You share data by registering data provider callback functions. When a + plug-in requests your data, these callbacks are then called. You provide + one callback to return the value when a plugin 'reads' it and another to + change the value when a plugin 'writes' it. + + Important: you must pick a prefix for your datarefs other than "sim/" - + this prefix is reserved for X-Plane. The X-Plane SDK website contains a + registry where authors can select a unique first word for dataref names, to + prevent dataref collisions between plugins. +} + + + + { + XPLMGetDatai_f + + Data provider function pointers. + + These define the function pointers you provide to get or set data. Note + that you are passed a generic pointer for each one. This is the same + pointer you pass in your register routine; you can use it to find global + variables, etc. + + The semantics of your callbacks are the same as the dataref accessor above + - basically routines like XPLMGetDatai are just pass-throughs from a caller + to your plugin. Be particularly mindful in implementing array dataref + read-write accessors; you are responsible for avoiding overruns, supporting + offset read/writes, and handling a read with a NULL buffer. + } +TYPE + XPLMGetDatai_f = FUNCTION( + inRefcon : pointer) : integer; cdecl; + + { + XPLMSetDatai_f + + } + XPLMSetDatai_f = PROCEDURE( + inRefcon : pointer; + inValue : integer); cdecl; + + { + XPLMGetDataf_f + + } + XPLMGetDataf_f = FUNCTION( + inRefcon : pointer) : single; cdecl; + + { + XPLMSetDataf_f + + } + XPLMSetDataf_f = PROCEDURE( + inRefcon : pointer; + inValue : single); cdecl; + + { + XPLMGetDatad_f + + } + XPLMGetDatad_f = FUNCTION( + inRefcon : pointer) : real; cdecl; + + { + XPLMSetDatad_f + + } + XPLMSetDatad_f = PROCEDURE( + inRefcon : pointer; + inValue : real); cdecl; + + { + XPLMGetDatavi_f + + } + XPLMGetDatavi_f = FUNCTION( + inRefcon : pointer; + outValues : Pinteger; { Can be nil } + inOffset : integer; + inMax : integer) : integer; cdecl; + + { + XPLMSetDatavi_f + + } + XPLMSetDatavi_f = PROCEDURE( + inRefcon : pointer; + inValues : Pinteger; + inOffset : integer; + inCount : integer); cdecl; + + { + XPLMGetDatavf_f + + } + XPLMGetDatavf_f = FUNCTION( + inRefcon : pointer; + outValues : Psingle; { Can be nil } + inOffset : integer; + inMax : integer) : integer; cdecl; + + { + XPLMSetDatavf_f + + } + XPLMSetDatavf_f = PROCEDURE( + inRefcon : pointer; + inValues : Psingle; + inOffset : integer; + inCount : integer); cdecl; + + { + XPLMGetDatab_f + + } + XPLMGetDatab_f = FUNCTION( + inRefcon : pointer; + outValue : pointer; { Can be nil } + inOffset : integer; + inMaxLength : integer) : integer; cdecl; + + { + XPLMSetDatab_f + + } + XPLMSetDatab_f = PROCEDURE( + inRefcon : pointer; + inValue : pointer; + inOffset : integer; + inLength : integer); cdecl; + + { + XPLMRegisterDataAccessor + + This routine creates a new item of data that can be read and written. Pass + in the data's full name for searching, the type(s) of the data for + accessing, and whether the data can be written to. For each data type you + support, pass in a read accessor function and a write accessor function if + necessary. Pass NULL for data types you do not support or write accessors + if you are read-only. + + You are returned a data ref for the new item of data created. You can use + this data ref to unregister your data later or read or write from it. + } + FUNCTION XPLMRegisterDataAccessor( + inDataName : Pchar; + inDataType : XPLMDataTypeID; + inIsWritable : integer; + inReadInt : XPLMGetDatai_f; + inWriteInt : XPLMSetDatai_f; + inReadFloat : XPLMGetDataf_f; + inWriteFloat : XPLMSetDataf_f; + inReadDouble : XPLMGetDatad_f; + inWriteDouble : XPLMSetDatad_f; + inReadIntArray : XPLMGetDatavi_f; + inWriteIntArray : XPLMSetDatavi_f; + inReadFloatArray : XPLMGetDatavf_f; + inWriteFloatArray : XPLMSetDatavf_f; + inReadData : XPLMGetDatab_f; + inWriteData : XPLMSetDatab_f; + inReadRefcon : pointer; + inWriteRefcon : pointer) : XPLMDataRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMUnregisterDataAccessor + + Use this routine to unregister any data accessors you may have registered. + You unregister a data ref by the XPLMDataRef you get back from + registration. Once you unregister a data ref, your function pointer will + not be called anymore. + + For maximum compatibility, do not unregister your data accessors until + final shutdown (when your XPluginStop routine is called). This allows + other plugins to find your data reference once and use it for their entire + time of operation. + } + PROCEDURE XPLMUnregisterDataAccessor( + inDataRef : XPLMDataRef); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * SHARING DATA BETWEEN MULTIPLE PLUGINS + ___________________________________________________________________________} +{ + The data reference registration APIs from the previous section allow a + plugin to publish data in a one-owner manner; the plugin that publishes the + data reference owns the real memory that the data ref uses. This is + satisfactory for most cases, but there are also cases where plugnis need to + share actual data. + + With a shared data reference, no one plugin owns the actual memory for the + data reference; the plugin SDK allocates that for you. When the first + plugin asks to 'share' the data, the memory is allocated. When the data is + changed, every plugin that is sharing the data is notified. + + Shared data references differ from the 'owned' data references from the + previous section in a few ways: + + - With shared data references, any plugin can create the data reference; + with owned plugins one plugin must create the data reference and others + subscribe. (This can be a problem if you don't know which set of plugins + will be present). + + - With shared data references, every plugin that is sharing the data is + notified when the data is changed. With owned data references, only the + one owner is notified when the data is changed. + + - With shared data references, you cannot access the physical memory of the + data reference; you must use the XPLMGet... and XPLMSet... APIs. With an + owned data reference, the one owning data reference can manipulate the + data reference's memory in any way it sees fit. + + Shared data references solve two problems: if you need to have a data + reference used by several plugins but do not know which plugins will be + installed, or if all plugins sharing data need to be notified when that + data is changed, use shared data references. +} + + + + { + XPLMDataChanged_f + + An XPLMDataChanged_f is a callback that the XPLM calls whenever any other + plug-in modifies shared data. A refcon you provide is passed back to help + identify which data is being changed. In response, you may want to call one + of the XPLMGetDataxxx routines to find the new value of the data. + } +TYPE + XPLMDataChanged_f = PROCEDURE( + inRefcon : pointer); cdecl; + + { + XPLMShareData + + This routine connects a plug-in to shared data, creating the shared data if + necessary. inDataName is a standard path for the data ref, and inDataType + specifies the type. This function will create the data if it does not + exist. If the data already exists but the type does not match, an error is + returned, so it is important that plug-in authors collaborate to establish + public standards for shared data. + + If a notificationFunc is passed in and is not NULL, that notification + function will be called whenever the data is modified. The notification + refcon will be passed to it. This allows your plug-in to know which shared + data was changed if multiple shared data are handled by one callback, or if + the plug-in does not use global variables. + + A one is returned for successfully creating or finding the shared data; a + zero if the data already exists but is of the wrong type. + } + FUNCTION XPLMShareData( + inDataName : Pchar; + inDataType : XPLMDataTypeID; + inNotificationFunc : XPLMDataChanged_f; + inNotificationRefcon: pointer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMUnshareData + + This routine removes your notification function for shared data. Call it + when done with the data to stop receiving change notifications. Arguments + must match XPLMShareData. The actual memory will not necessarily be freed, + since other plug-ins could be using it. + } + FUNCTION XPLMUnshareData( + inDataName : Pchar; + inDataType : XPLMDataTypeID; + inNotificationFunc : XPLMDataChanged_f; + inNotificationRefcon: pointer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDefs.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDefs.pas new file mode 100644 index 0000000..57ffba1 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDefs.pas @@ -0,0 +1,446 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMDefs; +INTERFACE +{ + This file is contains the cross-platform and basic definitions for the + X-Plane SDK. + + The preprocessor macros APL and IBM must be defined to specify the + compilation target; define APL to 1 and IBM 0 to compile on Macintosh and + APL to 0 and IBM to 1 for Windows. You must specify these macro definitions + before including XPLMDefs.h or any other XPLM headers. You can do this + using the -D command line option or a preprocessor header. +} + + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{$IFDEF LINUX} + {$DEFINE KYLIX} +{$ENDIF} +TYPE +{$IFNDEF DELPHI} +{$IFNDEF KYLIX} + Pchar = ^char; + Ppchar = ^Pchar; + Psingle = ^single; + Pinteger = ^integer; +{$ENDIF} +{$ENDIF} + Preal = ^real; + Plongint = ^longint; +{___________________________________________________________________________ + * DLL Definitions + ___________________________________________________________________________} +{ + These definitions control the importing and exporting of functions within + the DLL. + + You can prefix your five required callbacks with the PLUGIN_API macro to + declare them as exported C functions. The XPLM_API macro identifies + functions that are provided to you via the plugin SDK. (Link against + XPLM.lib to use these functions.) +} + + + + +{___________________________________________________________________________ + * GLOBAL DEFINITIONS + ___________________________________________________________________________} +{ + These definitions are used in all parts of the SDK. +} + + + +TYPE + { + XPLMPluginID + + Each plug-in is identified by a unique integer ID. This ID can be used to + disable or enable a plug-in, or discover what plug-in is 'running' at the + time. A plug-in ID is unique within the currently running instance of + X-Plane unless plug-ins are reloaded. Plug-ins may receive a different + unique ID each time they are loaded. + + For persistent identification of plug-ins, use XPLMFindPluginBySignature in + XPLMUtiltiies.h + + -1 indicates no plug-in. + } + XPLMPluginID = integer; + PXPLMPluginID = ^XPLMPluginID; + +CONST + { No plugin. } + XPLM_NO_PLUGIN_ID = (-1); + + { X-Plane itself } + XPLM_PLUGIN_XPLANE = (0); + + { The current XPLM revision is 2.10 (210). } + kXPLM_Version = (210); + + { + XPLMKeyFlags + + These bitfields define modifier keys in a platform independent way. When a + key is pressed, a series of messages are sent to your plugin. The down + flag is set in the first of these messages, and the up flag in the last. + While the key is held down, messages are sent with neither to indicate that + the key is being held down as a repeated character. + + The control flag is mapped to the control flag on Macintosh and PC. + Generally X-Plane uses the control key and not the command key on + Macintosh, providing a consistent interface across platforms that does not + necessarily match the Macintosh user interface guidelines. There is not + yet a way for plugins to access the Macintosh control keys without using + #ifdefed code. + } +TYPE + XPLMKeyFlags = ( + { The shift key is down } + xplm_ShiftFlag = 1 + + { The option or alt key is down } + ,xplm_OptionAltFlag = 2 + + { The control key is down* } + ,xplm_ControlFlag = 4 + + { The key is being pressed down } + ,xplm_DownFlag = 8 + + { The key is being released } + ,xplm_UpFlag = 16 + + ); + PXPLMKeyFlags = ^XPLMKeyFlags; + +{___________________________________________________________________________ + * ASCII CONTROL KEY CODES + ___________________________________________________________________________} +{ + These definitions define how various control keys are mapped to ASCII key + codes. Not all key presses generate an ASCII value, so plugin code should + be prepared to see null characters come from the keyboard...this usually + represents a key stroke that has no equivalent ASCII, like a page-down + press. Use virtual key codes to find these key strokes. ASCII key codes + take into account modifier keys; shift keys will affect capitals and + punctuation; control key combinations may have no vaild ASCII and produce + NULL. To detect control-key combinations, use virtual key codes, not ASCII + keys. +} + + + +CONST + XPLM_KEY_RETURN = 13; + + XPLM_KEY_ESCAPE = 27; + + XPLM_KEY_TAB = 9; + + XPLM_KEY_DELETE = 8; + + XPLM_KEY_LEFT = 28; + + XPLM_KEY_RIGHT = 29; + + XPLM_KEY_UP = 30; + + XPLM_KEY_DOWN = 31; + + XPLM_KEY_0 = 48; + + XPLM_KEY_1 = 49; + + XPLM_KEY_2 = 50; + + XPLM_KEY_3 = 51; + + XPLM_KEY_4 = 52; + + XPLM_KEY_5 = 53; + + XPLM_KEY_6 = 54; + + XPLM_KEY_7 = 55; + + XPLM_KEY_8 = 56; + + XPLM_KEY_9 = 57; + + XPLM_KEY_DECIMAL = 46; + +{___________________________________________________________________________ + * VIRTUAL KEY CODES + ___________________________________________________________________________} +{ + These are cross-platform defines for every distinct keyboard press on the + computer. Every physical key on the keyboard has a virtual key code. So + the "two" key on the top row of the main keyboard has a different code + from the "two" key on the numeric key pad. But the 'w' and 'W' character + are indistinguishable by virtual key code because they are the same + physical key (one with and one without the shift key). + + Use virtual key codes to detect keystrokes that do not have ASCII + equivalents, allow the user to map the numeric keypad separately from the + main keyboard, and detect control key and other modifier-key combinations + that generate ASCII control key sequences (many of which are not available + directly via character keys in the SDK). + + To assign virtual key codes we started with the Microsoft set but made some + additions and changes. A few differences: + + 1. Modifier keys are not available as virtual key codes. You cannot get + distinct modifier press and release messages. Please do not try to use + modifier keys as regular keys; doing so will almost certainly interfere + with users' abilities to use the native x-plane key bindings. + + 2. Some keys that do not exist on both Mac and PC keyboards are removed. + + 3. Do not assume that the values of these keystrokes are interchangeable + with MS v-keys. +} + + + +CONST + XPLM_VK_BACK = $08; + + XPLM_VK_TAB = $09; + + XPLM_VK_CLEAR = $0C; + + XPLM_VK_RETURN = $0D; + + XPLM_VK_ESCAPE = $1B; + + XPLM_VK_SPACE = $20; + + XPLM_VK_PRIOR = $21; + + XPLM_VK_NEXT = $22; + + XPLM_VK_END = $23; + + XPLM_VK_HOME = $24; + + XPLM_VK_LEFT = $25; + + XPLM_VK_UP = $26; + + XPLM_VK_RIGHT = $27; + + XPLM_VK_DOWN = $28; + + XPLM_VK_SELECT = $29; + + XPLM_VK_PRINT = $2A; + + XPLM_VK_EXECUTE = $2B; + + XPLM_VK_SNAPSHOT = $2C; + + XPLM_VK_INSERT = $2D; + + XPLM_VK_DELETE = $2E; + + XPLM_VK_HELP = $2F; + + { XPLM_VK_0 thru XPLM_VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) } + XPLM_VK_0 = $30; + + XPLM_VK_1 = $31; + + XPLM_VK_2 = $32; + + XPLM_VK_3 = $33; + + XPLM_VK_4 = $34; + + XPLM_VK_5 = $35; + + XPLM_VK_6 = $36; + + XPLM_VK_7 = $37; + + XPLM_VK_8 = $38; + + XPLM_VK_9 = $39; + + { XPLM_VK_A thru XPLM_VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) } + XPLM_VK_A = $41; + + XPLM_VK_B = $42; + + XPLM_VK_C = $43; + + XPLM_VK_D = $44; + + XPLM_VK_E = $45; + + XPLM_VK_F = $46; + + XPLM_VK_G = $47; + + XPLM_VK_H = $48; + + XPLM_VK_I = $49; + + XPLM_VK_J = $4A; + + XPLM_VK_K = $4B; + + XPLM_VK_L = $4C; + + XPLM_VK_M = $4D; + + XPLM_VK_N = $4E; + + XPLM_VK_O = $4F; + + XPLM_VK_P = $50; + + XPLM_VK_Q = $51; + + XPLM_VK_R = $52; + + XPLM_VK_S = $53; + + XPLM_VK_T = $54; + + XPLM_VK_U = $55; + + XPLM_VK_V = $56; + + XPLM_VK_W = $57; + + XPLM_VK_X = $58; + + XPLM_VK_Y = $59; + + XPLM_VK_Z = $5A; + + XPLM_VK_NUMPAD0 = $60; + + XPLM_VK_NUMPAD1 = $61; + + XPLM_VK_NUMPAD2 = $62; + + XPLM_VK_NUMPAD3 = $63; + + XPLM_VK_NUMPAD4 = $64; + + XPLM_VK_NUMPAD5 = $65; + + XPLM_VK_NUMPAD6 = $66; + + XPLM_VK_NUMPAD7 = $67; + + XPLM_VK_NUMPAD8 = $68; + + XPLM_VK_NUMPAD9 = $69; + + XPLM_VK_MULTIPLY = $6A; + + XPLM_VK_ADD = $6B; + + XPLM_VK_SEPARATOR = $6C; + + XPLM_VK_SUBTRACT = $6D; + + XPLM_VK_DECIMAL = $6E; + + XPLM_VK_DIVIDE = $6F; + + XPLM_VK_F1 = $70; + + XPLM_VK_F2 = $71; + + XPLM_VK_F3 = $72; + + XPLM_VK_F4 = $73; + + XPLM_VK_F5 = $74; + + XPLM_VK_F6 = $75; + + XPLM_VK_F7 = $76; + + XPLM_VK_F8 = $77; + + XPLM_VK_F9 = $78; + + XPLM_VK_F10 = $79; + + XPLM_VK_F11 = $7A; + + XPLM_VK_F12 = $7B; + + XPLM_VK_F13 = $7C; + + XPLM_VK_F14 = $7D; + + XPLM_VK_F15 = $7E; + + XPLM_VK_F16 = $7F; + + XPLM_VK_F17 = $80; + + XPLM_VK_F18 = $81; + + XPLM_VK_F19 = $82; + + XPLM_VK_F20 = $83; + + XPLM_VK_F21 = $84; + + XPLM_VK_F22 = $85; + + XPLM_VK_F23 = $86; + + XPLM_VK_F24 = $87; + + { The following definitions are extended and are not based on the Microsoft } + { key set. } + XPLM_VK_EQUAL = $B0; + + XPLM_VK_MINUS = $B1; + + XPLM_VK_RBRACE = $B2; + + XPLM_VK_LBRACE = $B3; + + XPLM_VK_QUOTE = $B4; + + XPLM_VK_SEMICOLON = $B5; + + XPLM_VK_BACKSLASH = $B6; + + XPLM_VK_COMMA = $B7; + + XPLM_VK_SLASH = $B8; + + XPLM_VK_PERIOD = $B9; + + XPLM_VK_BACKQUOTE = $BA; + + XPLM_VK_ENTER = $BB; + + XPLM_VK_NUMPAD_ENT = $BC; + + XPLM_VK_NUMPAD_EQ = $BD; + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDisplay.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDisplay.pas new file mode 100644 index 0000000..751b5b5 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMDisplay.pas @@ -0,0 +1,835 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMDisplay; +INTERFACE +{ + XPLM Display APIs - THEORY OF OPERATION + + This API provides the basic hooks to draw in X-Plane and create user + interface. All X-Plane drawing is done in OpenGL. The X-Plane plug-in + manager takes care of properly setting up the OpenGL context and matrices. + You do not decide when in your code's execution to draw; X-Plane tells you + when it is ready to have your plugin draw. + + X-Plane's drawing strategy is straightforward: every "frame" the screen is + rendered by drawing the 3-d scene (dome, ground, objects, airplanes, etc.) + and then drawing the cockpit on top of it. Alpha blending is used to + overlay the cockpit over the world (and the gauges over the panel, etc.). + + There are two ways you can draw: directly and in a window. + + Direct drawing involves drawing to the screen before or after X-Plane + finishes a phase of drawing. When you draw directly, you can specify + whether x-plane is to complete this phase or not. This allows you to do + three things: draw before x-plane does (under it), draw after x-plane does + (over it), or draw instead of x-plane. + + To draw directly, you register a callback and specify what phase you want + to intercept. The plug-in manager will call you over and over to draw that + phase. + + Direct drawing allows you to override scenery, panels, or anything. Note + that you cannot assume that you are the only plug-in drawing at this + phase. + + Window drawing provides slightly higher level functionality. With window + drawing you create a window that takes up a portion of the screen. Window + drawing is always two dimensional. Window drawing is front-to-back + controlled; you can specify that you want your window to be brought on + top, and other plug-ins may put their window on top of you. Window drawing + also allows you to sign up for key presses and receive mouse clicks. + + There are three ways to get keystrokes: + + If you create a window, the window can take keyboard focus. It will then + receive all keystrokes. If no window has focus, X-Plane receives + keystrokes. Use this to implement typing in dialog boxes, etc. Only one + window may have focus at a time; your window will be notified if it loses + focus. + + If you need to associate key strokes with commands/functions in your + plug-in, use a hot key. A hoy is a key-specific callback. Hotkeys are + sent based on virtual key strokes, so any key may be distinctly mapped with + any modifiers. Hot keys can be remapped by other plug-ins. As a plug-in, + you don't have to worry about what your hot key ends up mapped to; other + plug-ins may provide a UI for remapping keystrokes. So hotkeys allow a + user to resolve conflicts and customize keystrokes. + + If you need low level access to the keystroke stream, install a key + sniffer. Key sniffers can be installed above everything or right in front + of the sim. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * DRAWING CALLBACKS + ___________________________________________________________________________} +{ + Basic drawing callbacks, for low level intercepting of render loop. The + purpose of drawing callbacks is to provide targeted additions or + replacements to x-plane's graphics environment (for example, to add extra + custom objects, or replace drawing of the AI aircraft). Do not assume that + the drawing callbacks will be called in the order implied by the + enumerations. Also do not assume that each drawing phase ends before + another begins; they may be nested. +} + + + + { + XPLMDrawingPhase + + This constant indicates which part of drawing we are in. Drawing is done + from the back to the front. We get a callback before or after each item. + Metaphases provide access to the beginning and end of the 3d (scene) and 2d + (cockpit) drawing in a manner that is independent of new phases added via + x-plane implementation. + + WARNING: As X-Plane's scenery evolves, some drawing phases may cease to + exist and new ones may be invented. If you need a particularly specific + use of these codes, consult Austin and/or be prepared to revise your code + as X-Plane evolves. + } +TYPE + XPLMDrawingPhase = ( + { This is the earliest point at which you can draw in 3-d. } + xplm_Phase_FirstScene = 0 + + { Drawing of land and water. } + ,xplm_Phase_Terrain = 5 + + { Drawing runways and other airport detail. } + ,xplm_Phase_Airports = 10 + + { Drawing roads, trails, trains, etc. } + ,xplm_Phase_Vectors = 15 + + { 3-d objects (houses, smokestacks, etc. } + ,xplm_Phase_Objects = 20 + + { External views of airplanes, both yours and the AI aircraft. } + ,xplm_Phase_Airplanes = 25 + + { This is the last point at which you can draw in 3-d. } + ,xplm_Phase_LastScene = 30 + + { This is the first phase where you can draw in 2-d. } + ,xplm_Phase_FirstCockpit = 35 + + { The non-moving parts of the aircraft panel. } + ,xplm_Phase_Panel = 40 + + { The moving parts of the aircraft panel. } + ,xplm_Phase_Gauges = 45 + + { Floating windows from plugins. } + ,xplm_Phase_Window = 50 + + { The last change to draw in 2d. } + ,xplm_Phase_LastCockpit = 55 + +{$IFDEF XPLM200} + { 3-d Drawing for the local map. Use regular OpenGL coordinates to draw in } + { this phase. } + ,xplm_Phase_LocalMap3D = 100 +{$ENDIF} + +{$IFDEF XPLM200} + { 2-d Drawing of text over the local map. } + ,xplm_Phase_LocalMap2D = 101 +{$ENDIF} + +{$IFDEF XPLM200} + { Drawing of the side-profile view in the local map screen. } + ,xplm_Phase_LocalMapProfile = 102 +{$ENDIF} + + ); + PXPLMDrawingPhase = ^XPLMDrawingPhase; + + { + XPLMDrawCallback_f + + This is the prototype for a low level drawing callback. You are passed in + the phase and whether it is before or after. If you are before the phase, + return 1 to let x-plane draw or 0 to suppress x-plane drawing. If you are + after the phase the return value is ignored. + + Refcon is a unique value that you specify when registering the callback, + allowing you to slip a pointer to your own data to the callback. + + Upon entry the OpenGL context will be correctly set up for you and OpenGL + will be in 'local' coordinates for 3d drawing and panel coordinates for 2d + drawing. The OpenGL state (texturing, etc.) will be unknown. + } + XPLMDrawCallback_f = FUNCTION( + inPhase : XPLMDrawingPhase; + inIsBefore : integer; + inRefcon : pointer) : integer; cdecl; + + { + XPLMKeySniffer_f + + This is the prototype for a low level key-sniffing function. Window-based + UI _should not use this_! The windowing system provides high-level + mediated keyboard access. By comparison, the key sniffer provides low + level keyboard access. + + Key sniffers are provided to allow libraries to provide non-windowed user + interaction. For example, the MUI library uses a key sniffer to do pop-up + text entry. + + inKey is the character pressed, inRefCon is a value you supply during + registration. Return 1 to pass the key on to the next sniffer, the window + mgr, x-plane, or whomever is down stream. Return 0 to consume the key. + + Warning: this API declares virtual keys as a signed character; however the + VKEY #define macros in XPLMDefs.h define the vkeys using unsigned values + (that is 0x80 instead of -0x80). So you may need to cast the incoming vkey + to an unsigned char to get correct comparisons in C. + } + XPLMKeySniffer_f = FUNCTION( + inChar : char; + inFlags : XPLMKeyFlags; + inVirtualKey : char; + inRefcon : pointer) : integer; cdecl; + + { + XPLMRegisterDrawCallback + + This routine registers a low level drawing callback. Pass in the phase you + want to be called for and whether you want to be called before or after. + This routine returns 1 if the registration was successful, or 0 if the + phase does not exist in this version of x-plane. You may register a + callback multiple times for the same or different phases as long as the + refcon is unique each time. + } + FUNCTION XPLMRegisterDrawCallback( + inCallback : XPLMDrawCallback_f; + inPhase : XPLMDrawingPhase; + inWantsBefore : integer; + inRefcon : pointer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMUnregisterDrawCallback + + This routine unregisters a draw callback. You must unregister a callback + for each time you register a callback if you have registered it multiple + times with different refcons. The routine returns 1 if it can find the + callback to unregister, 0 otherwise. + } + FUNCTION XPLMUnregisterDrawCallback( + inCallback : XPLMDrawCallback_f; + inPhase : XPLMDrawingPhase; + inWantsBefore : integer; + inRefcon : pointer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMRegisterKeySniffer + + This routine registers a key sniffing callback. You specify whether you + want to sniff before the window system, or only sniff keys the window + system does not consume. You should ALMOST ALWAYS sniff non-control keys + after the window system. When the window system consumes a key, it is + because the user has "focused" a window. Consuming the key or taking + action based on the key will produce very weird results. Returns 1 if + successful. + } + FUNCTION XPLMRegisterKeySniffer( + inCallback : XPLMKeySniffer_f; + inBeforeWindows : integer; + inRefcon : pointer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMUnregisterKeySniffer + + This routine unregisters a key sniffer. You must unregister a key sniffer + for every time you register one with the exact same signature. Returns 1 + if successful. + } + FUNCTION XPLMUnregisterKeySniffer( + inCallback : XPLMKeySniffer_f; + inBeforeWindows : integer; + inRefcon : pointer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * WINDOW API + ___________________________________________________________________________} +{ + Window API, for higher level drawing with UI interaction. + + Note: all 2-d (and thus all window drawing) is done in 'cockpit pixels'. + Even when the OpenGL window contains more than 1024x768 pixels, the cockpit + drawing is magnified so that only 1024x768 pixels are available. +} + + + + { + XPLMMouseStatus + + When the mouse is clicked, your mouse click routine is called repeatedly. + It is first called with the mouse down message. It is then called zero or + more times with the mouse-drag message, and finally it is called once with + the mouse up message. All of these messages will be directed to the same + window. + } +TYPE + XPLMMouseStatus = ( + xplm_MouseDown = 1 + + ,xplm_MouseDrag = 2 + + ,xplm_MouseUp = 3 + + ); + PXPLMMouseStatus = ^XPLMMouseStatus; + +{$IFDEF XPLM200} + { + XPLMCursorStatus + + XPLMCursorStatus describes how you would like X-Plane to manage the cursor. + See XPLMHandleCursor_f for more info. + } + XPLMCursorStatus = ( + { X-Plane manages the cursor normally, plugin does not affect the cusrsor. } + xplm_CursorDefault = 0 + + { X-Plane hides the cursor. } + ,xplm_CursorHidden = 1 + + { X-Plane shows the cursor as the default arrow. } + ,xplm_CursorArrow = 2 + + { X-Plane shows the cursor but lets you select an OS cursor. } + ,xplm_CursorCustom = 3 + + ); + PXPLMCursorStatus = ^XPLMCursorStatus; +{$ENDIF} + + { + XPLMWindowID + + This is an opaque identifier for a window. You use it to control your + window. When you create a window, you will specify callbacks to handle + drawing and mouse interaction, etc. + } + XPLMWindowID = pointer; + PXPLMWindowID = ^XPLMWindowID; + + { + XPLMDrawWindow_f + + This function handles drawing. You are passed in your window and its + refcon. Draw the window. You can use XPLM functions to find the current + dimensions of your window, etc. When this callback is called, the OpenGL + context will be set properly for cockpit drawing. NOTE: Because you are + drawing your window over a background, you can make a translucent window + easily by simply not filling in your entire window's bounds. + } + XPLMDrawWindow_f = PROCEDURE( + inWindowID : XPLMWindowID; + inRefcon : pointer); cdecl; + + { + XPLMHandleKey_f + + This function is called when a key is pressed or keyboard focus is taken + away from your window. If losingFocus is 1, you are losign the keyboard + focus, otherwise a key was pressed and inKey contains its character. You + are also passewd your window and a refcon. Warning: this API declares + virtual keys as a signed character; however the VKEY #define macros in + XPLMDefs.h define the vkeys using unsigned values (that is 0x80 instead of + -0x80). So you may need to cast the incoming vkey to an unsigned char to + get correct comparisons in C. + } + XPLMHandleKey_f = PROCEDURE( + inWindowID : XPLMWindowID; + inKey : char; + inFlags : XPLMKeyFlags; + inVirtualKey : char; + inRefcon : pointer; + losingFocus : integer); cdecl; + + { + XPLMHandleMouseClick_f + + You receive this call when the mouse button is pressed down or released. + Between then these two calls is a drag. You receive the x and y of the + click, your window, and a refcon. Return 1 to consume the click, or 0 to + pass it through. + + WARNING: passing clicks through windows (as of this writing) causes mouse + tracking problems in X-Plane; do not use this feature! + } + XPLMHandleMouseClick_f = FUNCTION( + inWindowID : XPLMWindowID; + x : integer; + y : integer; + inMouse : XPLMMouseStatus; + inRefcon : pointer) : integer; cdecl; + +{$IFDEF XPLM200} + { + XPLMHandleCursor_f + + The SDK calls your cursor status callback when the mouse is over your + plugin window. Return a cursor status code to indicate how you would like + X-Plane to manage the cursor. If you return xplm_CursorDefault, the SDK + will try lower-Z-order plugin windows, then let the sim manage the cursor. + + Note: you should never show or hide the cursor yourself - these APIs are + typically reference-counted and thus cannot safely and predictably be used + by the SDK. Instead return one of xplm_CursorHidden to hide the cursor or + xplm_CursorArrow/xplm_CursorCustom to show the cursor. + + If you want to implement a custom cursor by drawing a cursor in OpenGL, use + xplm_CursorHidden to hide the OS cursor and draw the cursor using a 2-d + drawing callback (after xplm_Phase_Window is probably a good choice). If + you want to use a custom OS-based cursor, use xplm_CursorCustom to ask + X-Plane to show the cursor but not affect its image. You can then use an + OS specific call like SetThemeCursor (Mac) or SetCursor/LoadCursor + (Windows). + } + XPLMHandleCursor_f = FUNCTION( + inWindowID : XPLMWindowID; + x : integer; + y : integer; + inRefcon : pointer) : XPLMCursorStatus; cdecl; +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMHandleMouseWheel_f + + The SDK calls your mouse wheel callback when one of the mouse wheels is + turned within your window. Return 1 to consume the mouse wheel clicks or + 0 to pass them on to a lower window. (You should consume mouse wheel + clicks even if they do nothing if your window appears opaque to the user.) + The number of clicks indicates how far the wheel was turned since the last + callback. The wheel is 0 for the vertical axis or 1 for the horizontal axis + (for OS/mouse combinations that support this). + } + XPLMHandleMouseWheel_f = FUNCTION( + inWindowID : XPLMWindowID; + x : integer; + y : integer; + wheel : integer; + clicks : integer; + inRefcon : pointer) : integer; cdecl; +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMCreateWindow_t + + The XPMCreateWindow_t structure defines all of the parameters used to + create a window using XPLMCreateWindowEx. The structure will be expanded + in future SDK APIs to include more features. Always set the structSize + member to the size of your struct in bytes! + } + XPLMCreateWindow_t = RECORD + structSize : integer; + left : integer; + top : integer; + right : integer; + bottom : integer; + visible : integer; + drawWindowFunc : XPLMDrawWindow_f; + handleMouseClickFunc : XPLMHandleMouseClick_f; + handleKeyFunc : XPLMHandleKey_f; + handleCursorFunc : XPLMHandleCursor_f; + handleMouseWheelFunc : XPLMHandleMouseWheel_f; + refcon : pointer; + END; + PXPLMCreateWindow_t = ^XPLMCreateWindow_t; +{$ENDIF} + + { + XPLMGetScreenSize + + This routine returns the size of the size of the X-Plane OpenGL window in + pixels. Please note that this is not the size of the screen when doing + 2-d drawing (the 2-d screen is currently always 1024x768, and graphics are + scaled up by OpenGL when doing 2-d drawing for higher-res monitors). This + number can be used to get a rough idea of the amount of detail the user + will be able to see when drawing in 3-d. + } + PROCEDURE XPLMGetScreenSize( + outWidth : Pinteger; { Can be nil } + outHeight : Pinteger); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetMouseLocation + + This routine returns the current mouse location in cockpit pixels. The + bottom left corner of the display is 0,0. Pass NULL to not receive info + about either parameter. + } + PROCEDURE XPLMGetMouseLocation( + outX : Pinteger; { Can be nil } + outY : Pinteger); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCreateWindow + + This routine creates a new window. Pass in the dimensions and offsets to + the window's bottom left corner from the bottom left of the screen. You + can specify whether the window is initially visible or not. Also, you pass + in three callbacks to run the window and a refcon. This function returns a + window ID you can use to refer to the new window. + + NOTE: windows do not have "frames"; you are responsible for drawing the + background and frame of the window. Higher level libraries have routines + which make this easy. + } + FUNCTION XPLMCreateWindow( + inLeft : integer; + inTop : integer; + inRight : integer; + inBottom : integer; + inIsVisible : integer; + inDrawCallback : XPLMDrawWindow_f; + inKeyCallback : XPLMHandleKey_f; + inMouseCallback : XPLMHandleMouseClick_f; + inRefcon : pointer) : XPLMWindowID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMCreateWindowEx + + This routine creates a new window - you pass in an XPLMCreateWindow_t + structure with all of the fields set in. You must set the structSize of + the structure to the size of the actual structure you used. Also, you + must provide funtions for every callback - you may not leave them null! + (If you do not support the cursor or mouse wheel, use functions that return + the default values.) The numeric values of the XPMCreateWindow_t structure + correspond to the parameters of XPLMCreateWindow. + } + FUNCTION XPLMCreateWindowEx( + inParams : PXPLMCreateWindow_t) : XPLMWindowID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + + { + XPLMDestroyWindow + + This routine destroys a window. The callbacks are not called after this + call. Keyboard focus is removed from the window before destroying it. + } + PROCEDURE XPLMDestroyWindow( + inWindowID : XPLMWindowID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetWindowGeometry + + This routine returns the position and size of a window in cockpit pixels. + Pass NULL to not receive any paramter. + } + PROCEDURE XPLMGetWindowGeometry( + inWindowID : XPLMWindowID; + outLeft : Pinteger; { Can be nil } + outTop : Pinteger; { Can be nil } + outRight : Pinteger; { Can be nil } + outBottom : Pinteger); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetWindowGeometry + + This routine allows you to set the position or height aspects of a window. + } + PROCEDURE XPLMSetWindowGeometry( + inWindowID : XPLMWindowID; + inLeft : integer; + inTop : integer; + inRight : integer; + inBottom : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetWindowIsVisible + + This routine returns whether a window is visible. + } + FUNCTION XPLMGetWindowIsVisible( + inWindowID : XPLMWindowID) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetWindowIsVisible + + This routine shows or hides a window. + } + PROCEDURE XPLMSetWindowIsVisible( + inWindowID : XPLMWindowID; + inIsVisible : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetWindowRefCon + + This routine returns a windows refcon, the unique value you can use for + your own purposes. + } + FUNCTION XPLMGetWindowRefCon( + inWindowID : XPLMWindowID) : pointer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetWindowRefCon + + This routine sets a window's reference constant. Use this to pass data to + yourself in the callbacks. + } + PROCEDURE XPLMSetWindowRefCon( + inWindowID : XPLMWindowID; + inRefcon : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMTakeKeyboardFocus + + This routine gives a specific window keyboard focus. Keystrokes will be + sent to that window. Pass a window ID of 0 to pass keyboard strokes + directly to X-Plane. + } + PROCEDURE XPLMTakeKeyboardFocus( + inWindow : XPLMWindowID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMBringWindowToFront + + This routine brings the window to the front of the Z-order. Windows are + brought to the front when they are created...beyond that you should make + sure you are front before handling mouse clicks. + } + PROCEDURE XPLMBringWindowToFront( + inWindow : XPLMWindowID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMIsWindowInFront + + This routine returns true if you pass inthe ID of the frontmost visible + window. + } + FUNCTION XPLMIsWindowInFront( + inWindow : XPLMWindowID) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * HOT KEYS + ___________________________________________________________________________} +{ + Hot Keys - keystrokes that can be managed by others. +} + + + + { + XPLMHotKey_f + + Your hot key callback simply takes a pointer of your choosing. + } +TYPE + XPLMHotKey_f = PROCEDURE( + inRefcon : pointer); cdecl; + + { + XPLMHotKeyID + + Hot keys are identified by opaque IDs. + } + XPLMHotKeyID = pointer; + PXPLMHotKeyID = ^XPLMHotKeyID; + + { + XPLMRegisterHotKey + + This routine registers a hot key. You specify your preferred key stroke + virtual key/flag combination, a description of what your callback does (so + other plug-ins can describe the plug-in to the user for remapping) and a + callback function and opaque pointer to pass in). A new hot key ID is + returned. During execution, the actual key associated with your hot key + may change, but you are insulated from this. + } + FUNCTION XPLMRegisterHotKey( + inVirtualKey : char; + inFlags : XPLMKeyFlags; + inDescription : Pchar; + inCallback : XPLMHotKey_f; + inRefcon : pointer) : XPLMHotKeyID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMUnregisterHotKey + + This API unregisters a hot key. You can only register your own hot keys. + } + PROCEDURE XPLMUnregisterHotKey( + inHotKey : XPLMHotKeyID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCountHotKeys + + Returns the number of current hot keys. + } + FUNCTION XPLMCountHotKeys: integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetNthHotKey + + Returns a hot key by index, for iteration on all hot keys. + } + FUNCTION XPLMGetNthHotKey( + inIndex : integer) : XPLMHotKeyID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetHotKeyInfo + + Returns information about the hot key. Return NULL for any parameter you + don't want info about. The description should be at least 512 chars long. + } + PROCEDURE XPLMGetHotKeyInfo( + inHotKey : XPLMHotKeyID; + outVirtualKey : Pchar; { Can be nil } + outFlags : PXPLMKeyFlags; { Can be nil } + outDescription : Pchar; { Can be nil } + outPlugin : PXPLMPluginID); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetHotKeyCombination + + XPLMSetHotKeyCombination remaps a hot keys keystrokes. You may remap + another plugin's keystrokes. + } + PROCEDURE XPLMSetHotKeyCombination( + inHotKey : XPLMHotKeyID; + inVirtualKey : char; + inFlags : XPLMKeyFlags); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMGraphics.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMGraphics.pas new file mode 100644 index 0000000..713f14a --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMGraphics.pas @@ -0,0 +1,441 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMGraphics; +INTERFACE +{ + Graphics routines for X-Plane and OpenGL. + + A few notes on coordinate systems: + + X-Plane uses three kinds of coordinates. Global coordinates are specified + as latitude, longitude and elevation. This coordinate system never changes + but is not very precise. + + OpenGL (or 'local') coordinates are cartesian and shift with the plane. + They offer more precision and are used for 3-d OpenGL drawing. The X axis + is aligned east-west with positive X meaning east. The Y axis is aligned + straight up and down at the point 0,0,0 (but since the earth is round it is + not truly straight up and down at other points). The Z axis is aligned + north-south at 0, 0, 0 with positive Z pointing south (but since the earth + is round it isn't exactly north-south as you move east or west of 0, 0, 0). + One unit is one meter and the point 0,0,0 is on the surface of the earth + at sea level for some latitude and longitude picked by the sim such that + the user's aircraft is reasonably nearby. + + Cockpit coordinates are 2d, with the X axis horizontal and the Y axis + vertical. The point 0,0 is the bottom left and 1024,768 is the upper right + of the screen. This is true no matter what resolution the user's monitor is + in; when running in higher resolution, graphics will be scaled. + + Use X-Plane's routines to convert between global and local coordinates. Do + not attempt to do this conversion yourself; the precise 'roundness' of + X-Plane's physics model may not match your own, and (to make things + weirder) the user can potentially customize the physics of the current + planet. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * X-PLANE GRAPHICS + ___________________________________________________________________________} +{ + These routines allow you to use OpenGL with X-Plane. +} + + + + { + XPLMTextureID + + XPLM Texture IDs name well-known textures in the sim for you to use. This + allows you to recycle textures from X-Plane, saving VRAM. + } +TYPE + XPLMTextureID = ( + { The bitmap that contains window outlines, button outlines, fonts, etc. } + xplm_Tex_GeneralInterface = 0 + + { The exterior paint for the user's aircraft (daytime). } + ,xplm_Tex_AircraftPaint = 1 + + { The exterior light map for the user's aircraft. } + ,xplm_Tex_AircraftLiteMap = 2 + + ); + PXPLMTextureID = ^XPLMTextureID; + + { + XPLMSetGraphicsState + + XPLMSetGraphicsState changes OpenGL's graphics state in a number of ways: + + inEnableFog - enables or disables fog, equivalent to: glEnable(GL_FOG); + + inNumberTexUnits - enables or disables a number of multitexturing units. If + the number is 0, 2d texturing is disabled entirely, as in + glDisable(GL_TEXTURE_2D); Otherwise, 2d texturing is enabled, and a + number of multitexturing units are enabled sequentially, starting with + unit 0, e.g. glActiveTextureARB(GL_TEXTURE0_ARB); glEnable + (GL_TEXTURE_2D); + + inEnableLighting - enables or disables OpenGL lighting, e.g. + glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); + + inEnableAlphaTesting - enables or disables the alpha test per pixel, e.g. + glEnable(GL_ALPHA_TEST); + + inEnableAlphaBlending - enables or disables alpha blending per pixel, e.g. + glEnable(GL_BLEND); + + inEnableDepthTesting - enables per pixel depth testing, as in + glEnable(GL_DEPTH_TEST); + + inEnableDepthWriting - enables writing back of depth information to the + depth bufffer, as in glDepthMask(GL_TRUE); + + The purpose of this function is to change OpenGL state while keeping + X-Plane aware of the state changes; this keeps X-Plane from getting + surprised by OGL state changes, and prevents X-Plane and plug-ins from + having to set all state before all draws; XPLMSetGraphicsState internally + skips calls to change state that is already properly enabled. + + X-Plane does not have a 'default' OGL state to plug-ins; plug-ins should + totally set OGL state before drawing. Use XPLMSetGraphicsState instead of + any of the above OpenGL calls. + + WARNING: Any routine that performs drawing (e.g. XPLMDrawString or widget + code) may change X-Plane's state. Always set state before drawing after + unknown code has executed. + } + PROCEDURE XPLMSetGraphicsState( + inEnableFog : integer; + inNumberTexUnits : integer; + inEnableLighting : integer; + inEnableAlphaTesting: integer; + inEnableAlphaBlending: integer; + inEnableDepthTesting: integer; + inEnableDepthWriting: integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMBindTexture2d + + XPLMBindTexture2d changes what texture is bound to the 2d texturing target. + This routine caches the current 2d texture across all texturing units in + the sim and plug-ins, preventing extraneous binding. For example, consider + several plug-ins running in series; if they all use the 'general interface' + bitmap to do UI, calling this function will skip the rebinding of the + general interface texture on all but the first plug-in, which can provide + better frame rate son some graphics cards. + + inTextureID is the ID of the texture object to bind; inTextureUnit is a + zero-based texture unit (e.g. 0 for the first one), up to a maximum of 4 + units. (This number may increase in future versions of x-plane.) + + Use this routine instead of glBindTexture(GL_TEXTURE_2D, ....); + } + PROCEDURE XPLMBindTexture2d( + inTextureNum : integer; + inTextureUnit : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGenerateTextureNumbers + + This routine generates unused texture numbers that a plug-in can use to + safely bind textures. Use this routine instead of glGenTextures; + glGenTextures will allocate texture numbers in ranges that X-Plane reserves + for its own use but does not always use; for example, it might provide an + ID within the range of textures reserved for terrain...loading a new .env + file as the plane flies might then cause X-Plane to use this texture ID. + X-Plane will then overwrite the plug-ins texture. This routine returns + texture IDs that are out of X-Plane's usage range. + } + PROCEDURE XPLMGenerateTextureNumbers( + outTextureIDs : Pinteger; + inCount : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetTexture + + XPLMGetTexture returns the OpenGL texture enumeration of an X-Plane texture + based on a generic identifying code. For example, you can get the texture + for X-Plane's UI bitmaps. This allows you to build new gauges that take + advantage of x-plane's textures, for smooth artwork integration and also + saving texture memory. Note that the texture might not be loaded yet, + depending on what the plane's panel contains. + + OPEN ISSUE: We really need a way to make sure X-Plane loads this texture if + it isn't around, or at least a way to find out whether it is loaded or not. + } + FUNCTION XPLMGetTexture( + inTexture : XPLMTextureID) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMWorldToLocal + + This routine translates coordinates from latitude, longitude, and altitude + to local scene coordinates. Latitude and longitude are in decimal degrees, + and altitude is in meters MSL (mean sea level). The XYZ coordinates are in + meters in the local OpenGL coordinate system. + } + PROCEDURE XPLMWorldToLocal( + inLatitude : real; + inLongitude : real; + inAltitude : real; + outX : Preal; + outY : Preal; + outZ : Preal); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMLocalToWorld + + This routine translates a local coordinate triplet back into latitude, + longitude, and altitude. Latitude and longitude are in decimal degrees, + and altitude is in meters MSL (mean sea level). The XYZ coordinates are in + meters in the local OpenGL coordinate system. + + NOTE: world coordinates are less precise than local coordinates; you should + try to avoid round tripping from local to world and back. + } + PROCEDURE XPLMLocalToWorld( + inX : real; + inY : real; + inZ : real; + outLatitude : Preal; + outLongitude : Preal; + outAltitude : Preal); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDrawTranslucentDarkBox + + This routine draws a translucent dark box, partially obscuring parts of the + screen but making text easy to read. This is the same graphics primitive + used by X-Plane to show text files and ATC info. + } + PROCEDURE XPLMDrawTranslucentDarkBox( + inLeft : integer; + inTop : integer; + inRight : integer; + inBottom : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * X-PLANE TEXT + ___________________________________________________________________________} +{ + +} + + + + { + XPLMFontID + + X-Plane features some fixed-character fonts. Each font may have its own + metrics. + + WARNING: Some of these fonts are no longer supported or may have changed + geometries. For maximum copmatibility, see the comments below. + + Note: X-Plane 7 supports proportional-spaced fonts. Since no measuring + routine is available yet, the SDK will normally draw using a fixed-width + font. You can use a dataref to enable proportional font drawing on XP7 if + you want to. + } +TYPE + XPLMFontID = ( + { Mono-spaced font for user interface. Available in all versions of the SDK. } + xplmFont_Basic = 0 + + { Deprecated, do not use. } + ,xplmFont_Menus = 1 + + { Deprecated, do not use. } + ,xplmFont_Metal = 2 + + { Deprecated, do not use. } + ,xplmFont_Led = 3 + + { Deprecated, do not use. } + ,xplmFont_LedWide = 4 + + { Deprecated, do not use. } + ,xplmFont_PanelHUD = 5 + + { Deprecated, do not use. } + ,xplmFont_PanelEFIS = 6 + + { Deprecated, do not use. } + ,xplmFont_PanelGPS = 7 + + { Deprecated, do not use. } + ,xplmFont_RadiosGA = 8 + + { Deprecated, do not use. } + ,xplmFont_RadiosBC = 9 + + { Deprecated, do not use. } + ,xplmFont_RadiosHM = 10 + + { Deprecated, do not use. } + ,xplmFont_RadiosGANarrow = 11 + + { Deprecated, do not use. } + ,xplmFont_RadiosBCNarrow = 12 + + { Deprecated, do not use. } + ,xplmFont_RadiosHMNarrow = 13 + + { Deprecated, do not use. } + ,xplmFont_Timer = 14 + + { Deprecated, do not use. } + ,xplmFont_FullRound = 15 + + { Deprecated, do not use. } + ,xplmFont_SmallRound = 16 + + { Deprecated, do not use. } + ,xplmFont_Menus_Localized = 17 + +{$IFDEF XPLM200} + { Proportional UI font. } + ,xplmFont_Proportional = 18 +{$ENDIF} + + ); + PXPLMFontID = ^XPLMFontID; + + { + XPLMDrawString + + This routine draws a NULL termianted string in a given font. Pass in the + lower left pixel that the character is to be drawn onto. Also pass the + character and font ID. This function returns the x offset plus the width of + all drawn characters. The color to draw in is specified as a pointer to an + array of three floating point colors, representing RGB intensities from 0.0 + to 1.0. + } + PROCEDURE XPLMDrawString( + inColorRGB : Psingle; + inXOffset : integer; + inYOffset : integer; + inChar : Pchar; + inWordWrapWidth : Pinteger; { Can be nil } + inFontID : XPLMFontID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDrawNumber + + This routine draws a number similar to the digit editing fields in + PlaneMaker and data output display in X-Plane. Pass in a color, a + position, a floating point value, and formatting info. Specify how many + integer and how many decimal digits to show and whether to show a sign, as + well as a character set. This routine returns the xOffset plus width of the + string drawn. + } + PROCEDURE XPLMDrawNumber( + inColorRGB : Psingle; + inXOffset : integer; + inYOffset : integer; + inValue : real; + inDigits : integer; + inDecimals : integer; + inShowSign : integer; + inFontID : XPLMFontID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetFontDimensions + + This routine returns the width and height of a character in a given font. + It also tells you if the font only supports numeric digits. Pass NULL if + you don't need a given field. Note that for a proportional font the width + will be an arbitrary, hopefully average width. + } + PROCEDURE XPLMGetFontDimensions( + inFontID : XPLMFontID; + outCharWidth : Pinteger; { Can be nil } + outCharHeight : Pinteger; { Can be nil } + outDigitsOnly : Pinteger); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMMeasureString + + This routine returns the width in pixels of a string using a given font. + The string is passed as a pointer plus length (and does not need to be null + terminated); this is used to allow for measuring substrings. The return + value is floating point; it is possible that future font drawing may allow + for fractional pixels. + } + FUNCTION XPLMMeasureString( + inFontID : XPLMFontID; + inChar : Pchar; + inNumChars : integer) : single; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMMenus.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMMenus.pas new file mode 100644 index 0000000..d113952 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMMenus.pas @@ -0,0 +1,259 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMMenus; +INTERFACE +{ + XPLMMenus - Theory of Operation + + Plug-ins can create menus in the menu bar of X-Plane. This is done by + creating a menu and then creating items. Menus are referred to by an + opaque ID. Items are referred to by index number. For each menu and item + you specify a void *. Per menu you specify a handler function that is + called with each void * when the menu item is picked. Menu item indices + are zero based. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * XPLM MENUS + ___________________________________________________________________________} +{ + +} + + + + { + XPLMMenuCheck + + These enumerations define the various 'check' states for an X-Plane menu. + 'checking' in x-plane actually appears as a light which may or may not be + lit. So there are three possible states. + } +TYPE + XPLMMenuCheck = ( + { there is no symbol to the left of the menu item. } + xplm_Menu_NoCheck = 0 + + { the menu has a mark next to it that is unmarked (not lit). } + ,xplm_Menu_Unchecked = 1 + + { the menu has a mark next to it that is checked (lit). } + ,xplm_Menu_Checked = 2 + + ); + PXPLMMenuCheck = ^XPLMMenuCheck; + + { + XPLMMenuID + + This is a unique ID for each menu you create. + } + XPLMMenuID = pointer; + PXPLMMenuID = ^XPLMMenuID; + + { + XPLMMenuHandler_f + + A menu handler function takes two reference pointers, one for the menu + (specified when the menu was created) and one for the item (specified when + the item was created). + } + XPLMMenuHandler_f = PROCEDURE( + inMenuRef : pointer; + inItemRef : pointer); cdecl; + + { + XPLMFindPluginsMenu + + This function returns the ID of the plug-ins menu, which is created for you + at startup. + } + FUNCTION XPLMFindPluginsMenu: XPLMMenuID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCreateMenu + + This function creates a new menu and returns its ID. It returns NULL if + the menu cannot be created. Pass in a parent menu ID and an item index to + create a submenu, or NULL for the parent menu to put the menu in the menu + bar. The menu's name is only used if the menu is in the menubar. You also + pass a handler function and a menu reference value. Pass NULL for the + handler if you do not need callbacks from the menu (for example, if it only + contains submenus). + + Important: you must pass a valid, non-empty menu title even if the menu is + a submenu where the title is not visible. + } + FUNCTION XPLMCreateMenu( + inName : Pchar; + inParentMenu : XPLMMenuID; + inParentItem : integer; + inHandler : XPLMMenuHandler_f; + inMenuRef : pointer) : XPLMMenuID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDestroyMenu + + This function destroys a menu that you have created. Use this to remove a + submenu if necessary. (Normally this function will not be necessary.) + } + PROCEDURE XPLMDestroyMenu( + inMenuID : XPLMMenuID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMClearAllMenuItems + + This function removes all menu items from a menu, allowing you to rebuild + it. Use this function if you need to change the number of items on a menu. + } + PROCEDURE XPLMClearAllMenuItems( + inMenuID : XPLMMenuID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMAppendMenuItem + + This routine appends a new menu item to the bottom of a menu and returns + its index. Pass in the menu to add the item to, the items name, and a void + * ref for this item. If you pass in inForceEnglish, this menu item will be + drawn using the english character set no matter what language x-plane is + running in. Otherwise the menu item will be drawn localized. (An example + of why you'd want to do this is for a proper name.) See XPLMUtilities for + determining the current langauge. + } + FUNCTION XPLMAppendMenuItem( + inMenu : XPLMMenuID; + inItemName : Pchar; + inItemRef : pointer; + inForceEnglish : integer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMAppendMenuSeparator + + This routine adds a seperator to the end of a menu. + } + PROCEDURE XPLMAppendMenuSeparator( + inMenu : XPLMMenuID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetMenuItemName + + This routine changes the name of an existing menu item. Pass in the menu + ID and the index of the menu item. + } + PROCEDURE XPLMSetMenuItemName( + inMenu : XPLMMenuID; + inIndex : integer; + inItemName : Pchar; + inForceEnglish : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCheckMenuItem + + Set whether a menu item is checked. Pass in the menu ID and item index. + } + PROCEDURE XPLMCheckMenuItem( + inMenu : XPLMMenuID; + index : integer; + inCheck : XPLMMenuCheck); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCheckMenuItemState + + This routine returns whether a menu item is checked or not. A menu item's + check mark may be on or off, or a menu may not have an icon at all. + } + PROCEDURE XPLMCheckMenuItemState( + inMenu : XPLMMenuID; + index : integer; + outCheck : PXPLMMenuCheck); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMEnableMenuItem + + Sets whether this menu item is enabled. Items start out enabled. + } + PROCEDURE XPLMEnableMenuItem( + inMenu : XPLMMenuID; + index : integer; + enabled : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$IFDEF XPLM210} + { + XPLMRemoveMenuItem + + Removes one item from a menu. Note that all menu items below are moved up + one; your plugin must track the change in index numbers. + } + PROCEDURE XPLMRemoveMenuItem( + inMenu : XPLMMenuID; + inIndex : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMNavigation.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMNavigation.pas new file mode 100644 index 0000000..993ef58 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMNavigation.pas @@ -0,0 +1,434 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMNavigation; +INTERFACE +{ + XPLMNavigation - THEORY OF OPERATION + + The XPLM Navigation APIs give you some access to the navigation databases + inside X-Plane. X-Plane stores all navigation information in RAM, so by + using these APIs you can gain access to most information without having to + go to disk or parse the files yourself. + + You can also use this API to program the FMS. You must use the navigation + APIs to find the nav-aids you want to program into the FMS, since the FMS + is powered internally by x-plane's navigation database. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * NAVIGATION DATABASE ACCESS + ___________________________________________________________________________} +{ + +} + + + + { + XPLMNavType + + These enumerations define the different types of navaids. They are each + defined with a separate bit so that they may be bit-wise added together to + form sets of nav-aid types. + + NOTE: xplm_Nav_LatLon is a specific lat-lon coordinate entered into the + FMS. It will not exist in the database, and cannot be programmed into the + FMS. Querying the FMS for navaids will return it. Use + XPLMSetFMSEntryLatLon to set a lat/lon waypoint. + } +TYPE + XPLMNavType = ( + xplm_Nav_Unknown = 0 + + ,xplm_Nav_Airport = 1 + + ,xplm_Nav_NDB = 2 + + ,xplm_Nav_VOR = 4 + + ,xplm_Nav_ILS = 8 + + ,xplm_Nav_Localizer = 16 + + ,xplm_Nav_GlideSlope = 32 + + ,xplm_Nav_OuterMarker = 64 + + ,xplm_Nav_MiddleMarker = 128 + + ,xplm_Nav_InnerMarker = 256 + + ,xplm_Nav_Fix = 512 + + ,xplm_Nav_DME = 1024 + + ,xplm_Nav_LatLon = 2048 + + ); + PXPLMNavType = ^XPLMNavType; + + { + XPLMNavRef + + XPLMNavRef is an iterator into the navigation database. The navigation + database is essentially an array, but it is not necessarily densely + populated. The only assumption you can safely make is that like-typed + nav-aids are grouped together. + + Use XPLMNavRef to refer to a nav-aid. + + XPLM_NAV_NOT_FOUND is returned by functions that return an XPLMNavRef when + the iterator must be invalid. + } + XPLMNavRef = integer; + PXPLMNavRef = ^XPLMNavRef; + +CONST + XPLM_NAV_NOT_FOUND = -1; + + { + XPLMGetFirstNavAid + + This returns the very first navaid in the database. Use this to traverse + the entire database. Returns XPLM_NAV_NOT_FOUND if the nav database is + empty. + } + FUNCTION XPLMGetFirstNavAid: XPLMNavRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetNextNavAid + + Given a nav aid ref, this routine returns the next navaid. It returns + XPLM_NAV_NOT_FOUND if the nav aid passed in was invalid or if the navaid + passed in was the last one in the database. Use this routine to iterate + across all like-typed navaids or the entire database. + + WARNING: due to a bug in the SDK, when fix loading is disabled in the + rendering settings screen, calling this routine with the last airport + returns a bogus nav aid. Using this nav aid can crash x-plane. + } + FUNCTION XPLMGetNextNavAid( + inNavAidRef : XPLMNavRef) : XPLMNavRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMFindFirstNavAidOfType + + This routine returns the ref of the first navaid of the given type in the + database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the + database. You must pass exactly one nav aid type to this routine. + + WARNING: due to a bug in the SDK, when fix loading is disabled in the + rendering settings screen, calling this routine with fixes returns a bogus + nav aid. Using this nav aid can crash x-plane. + } + FUNCTION XPLMFindFirstNavAidOfType( + inType : XPLMNavType) : XPLMNavRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMFindLastNavAidOfType + + This routine returns the ref of the last navaid of the given type in the + database or XPLM_NAV_NOT_FOUND if there are no navaids of that type in the + database. You must pass exactly one nav aid type to this routine. + + WARNING: due to a bug in the SDK, when fix loading is disabled in the + rendering settings screen, calling this routine with fixes returns a bogus + nav aid. Using this nav aid can crash x-plane. + } + FUNCTION XPLMFindLastNavAidOfType( + inType : XPLMNavType) : XPLMNavRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMFindNavAid + + This routine provides a number of searching capabilities for the nav + database. XPLMFindNavAid will search through every nav aid whose type is + within inType (multiple types may be added together) and return any + nav-aids found based on the following rules: + + If inLat and inLon are not NULL, the navaid nearest to that lat/lon will be + returned, otherwise the last navaid found will be returned. + + If inFrequency is not NULL, then any navaids considered must match this + frequency. Note that this will screen out radio beacons that do not have + frequency data published (like inner markers) but not fixes and airports. + + If inNameFragment is not NULL, only navaids that contain the fragment in + their name will be returned. + + If inIDFragment is not NULL, only navaids that contain the fragment in + their IDs will be returned. + + This routine provides a simple way to do a number of useful searches: + + Find the nearest navaid on this frequency. Find the nearest airport. Find + the VOR whose ID is "KBOS". Find the nearest airport whose name contains + "Chicago". + } + FUNCTION XPLMFindNavAid( + inNameFragment : Pchar; { Can be nil } + inIDFragment : Pchar; { Can be nil } + inLat : Psingle; { Can be nil } + inLon : Psingle; { Can be nil } + inFrequency : Pinteger; { Can be nil } + inType : XPLMNavType) : XPLMNavRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetNavAidInfo + + This routine returns information about a navaid. Any non-null field is + filled out with information if it is available. + + Frequencies are in the nav.dat convention as described in the X-Plane nav + database FAQ: NDB frequencies are exact, all others are multiplied by 100. + + The buffer for IDs should be at least 6 chars and the buffer for names + should be at least 41 chars, but since these values are likely to go up, I + recommend passing at least 32 chars for IDs and 256 chars for names when + possible. + + The outReg parameter tells if the navaid is within the local "region" of + loaded DSFs. (This information may not be particularly useful to plugins.) + The parameter is a single byte value 1 for true or 0 for false, not a C + string. + } + PROCEDURE XPLMGetNavAidInfo( + inRef : XPLMNavRef; + outType : PXPLMNavType; { Can be nil } + outLatitude : Psingle; { Can be nil } + outLongitude : Psingle; { Can be nil } + outHeight : Psingle; { Can be nil } + outFrequency : Pinteger; { Can be nil } + outHeading : Psingle; { Can be nil } + outID : Pchar; { Can be nil } + outName : Pchar; { Can be nil } + outReg : Pchar); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * FLIGHT MANAGEMENT COMPUTER + ___________________________________________________________________________} +{ + Note: the FMS works based on an array of entries. Indices into the array + are zero-based. Each entry is a nav-aid plus an altitude. The FMS tracks + the currently displayed entry and the entry that it is flying to. + + The FMS must be programmed with contiguous entries, so clearing an entry at + the end shortens the effective flight plan. There is a max of 100 + waypoints in the flight plan. +} + + + + { + XPLMCountFMSEntries + + This routine returns the number of entries in the FMS. + } + FUNCTION XPLMCountFMSEntries: integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDisplayedFMSEntry + + This routine returns the index of the entry the pilot is viewing. + } + FUNCTION XPLMGetDisplayedFMSEntry: integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDestinationFMSEntry + + This routine returns the index of the entry the FMS is flying to. + } + FUNCTION XPLMGetDestinationFMSEntry: integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetDisplayedFMSEntry + + This routine changes which entry the FMS is showing to the index specified. + } + PROCEDURE XPLMSetDisplayedFMSEntry( + inIndex : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetDestinationFMSEntry + + This routine changes which entry the FMS is flying the aircraft toward. + } + PROCEDURE XPLMSetDestinationFMSEntry( + inIndex : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetFMSEntryInfo + + This routine returns information about a given FMS entry. A reference to a + navaid can be returned allowing you to find additional information (such as + a frequency, ILS heading, name, etc.). Some information is available + immediately. For a lat/lon entry, the lat/lon is returned by this routine + but the navaid cannot be looked up (and the reference will be + XPLM_NAV_NOT_FOUND. FMS name entry buffers should be at least 256 chars in + length. + } + PROCEDURE XPLMGetFMSEntryInfo( + inIndex : integer; + outType : PXPLMNavType; { Can be nil } + outID : Pchar; { Can be nil } + outRef : PXPLMNavRef; { Can be nil } + outAltitude : Pinteger; { Can be nil } + outLat : Psingle; { Can be nil } + outLon : Psingle); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetFMSEntryInfo + + This routine changes an entry in the FMS to have the destination navaid + passed in and the altitude specified. Use this only for airports, fixes, + and radio-beacon navaids. Currently of radio beacons, the FMS can only + support VORs and NDBs. Use the routines below to clear or fly to a lat/lon. + } + PROCEDURE XPLMSetFMSEntryInfo( + inIndex : integer; + inRef : XPLMNavRef; + inAltitude : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetFMSEntryLatLon + + This routine changes the entry in the FMS to a lat/lon entry with the given + coordinates. + } + PROCEDURE XPLMSetFMSEntryLatLon( + inIndex : integer; + inLat : single; + inLon : single; + inAltitude : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMClearFMSEntry + + This routine clears the given entry, potentially shortening the flight + plan. + } + PROCEDURE XPLMClearFMSEntry( + inIndex : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * GPS RECEIVER + ___________________________________________________________________________} +{ + These APIs let you read data from the GPS unit. +} + + + + { + XPLMGetGPSDestinationType + + This routine returns the type of the currently selected GPS destination, + one of fix, airport, VOR or NDB. + } + FUNCTION XPLMGetGPSDestinationType: XPLMNavType; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetGPSDestination + + This routine returns the current GPS destination. + } + FUNCTION XPLMGetGPSDestination: XPLMNavRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMPlanes.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMPlanes.pas new file mode 100644 index 0000000..b5d19a2 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMPlanes.pas @@ -0,0 +1,294 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMPlanes; +INTERFACE +{ + The XPLMPlanes APIs allow you to control the various aircraft in x-plane, + both the user's and the sim's. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * USER AIRCRAFT ACCESS + ___________________________________________________________________________} +{ + +} + + + { + XPLMSetUsersAircraft + + This routine changes the user's aircraft. Note that this will reinitialize + the user to be on the nearest airport's first runway. Pass in a full path + (hard drive and everything including the .acf extension) to the .acf file. + } + PROCEDURE XPLMSetUsersAircraft( + inAircraftPath : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + { + XPLMPlaceUserAtAirport + + This routine places the user at a given airport. Specify the airport by + its ICAO code (e.g. 'KBOS'). + } + PROCEDURE XPLMPlaceUserAtAirport( + inAirportCode : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{___________________________________________________________________________ + * GLOBAL AIRCRAFT ACCESS + ___________________________________________________________________________} +{ + +} + + +CONST + { The user's aircraft is always index 0. } + XPLM_USER_AIRCRAFT = 0; + { + XPLMPlaneDrawState_t + + This structure contains additional plane parameter info to be passed to + draw plane. Make sure to fill in the size of the structure field with + sizeof(XPLMDrawPlaneState_t) so that the XPLM can tell how many fields you + knew about when compiling your plugin (since more fields may be added + later). + + Most of these fields are ratios from 0 to 1 for control input. X-Plane + calculates what the actual controls look like based on the .acf file for + that airplane. Note for the yoke inputs, this is what the pilot of the + plane has commanded (post artificial stability system if there were one) + and affects aelerons, rudder, etc. It is not necessarily related to the + actual position of the plane! + } +TYPE + XPLMPlaneDrawState_t = RECORD + { The size of the draw state struct. } + structSize : integer; + { A ratio from [0..1] describing how far the landing gear is extended. } + gearPosition : single; + { Ratio of flap deployment, 0 = up, 1 = full deploy. } + flapRatio : single; + { Ratio of spoiler deployment, 0 = none, 1 = full deploy. } + spoilerRatio : single; + { Ratio of speed brake deployment, 0 = none, 1 = full deploy. } + speedBrakeRatio : single; + { Ratio of slat deployment, 0 = none, 1 = full deploy. } + slatRatio : single; + { Wing sweep ratio, 0 = forward, 1 = swept. } + wingSweep : single; + { Thrust power, 0 = none, 1 = full fwd, -1 = full reverse. } + thrust : single; + { Total pitch input for this plane. } + yokePitch : single; + { Total Heading input for this plane. } + yokeHeading : single; + { Total Roll input for this plane. } + yokeRoll : single; + END; + PXPLMPlaneDrawState_t = ^XPLMPlaneDrawState_t; + { + XPLMCountAircraft + + This function returns the number of aircraft X-Plane is capable of having, + as well as the number of aircraft that are currently active. These numbers + count the user's aircraft. It can also return the plugin that is currently + controlling aircraft. In X-Plane 7, this routine reflects the number of + aircraft the user has enabled in the rendering options window. + } + PROCEDURE XPLMCountAircraft( + outTotalAircraft : Pinteger; + outActiveAircraft : Pinteger; + outController : PXPLMPluginID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + { + XPLMGetNthAircraftModel + + This function returns the aircraft model for the Nth aircraft. Indices are + zero based, with zero being the user's aircraft. The file name should be + at least 256 chars in length; the path should be at least 512 chars in + length. + } + PROCEDURE XPLMGetNthAircraftModel( + inIndex : integer; + outFileName : Pchar; + outPath : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{___________________________________________________________________________ + * EXCLUSIVE AIRCRAFT ACCESS + ___________________________________________________________________________} +{ + The following routines require exclusive access to the airplane APIs. Only + one plugin may have this access at a time. +} + + + + { + XPLMPlanesAvailable_f + + Your airplanes available callback is called when another plugin gives up + access to the multiplayer planes. Use this to wait for access to + multiplayer. + } +TYPE + XPLMPlanesAvailable_f = PROCEDURE( + inRefcon : pointer); cdecl; + + { + XPLMAcquirePlanes + + XPLMAcquirePlanes grants your plugin exclusive access to the aircraft. It + returns 1 if you gain access, 0 if you do not. inAircraft - pass in an + array of pointers to strings specifying the planes you want loaded. For + any plane index you do not want loaded, pass a 0-length string. Other + strings should be full paths with the .acf extension. NULL terminates this + array, or pass NULL if there are no planes you want loaded. If you pass in + a callback and do not receive access to the planes your callback will be + called when the airplanes are available. If you do receive airplane access, + your callback will not be called. + } + FUNCTION XPLMAcquirePlanes( + inAircraft : PPchar; { Can be nil } + inCallback : XPLMPlanesAvailable_f; + inRefcon : pointer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMReleasePlanes + + Call this function to release access to the planes. Note that if you are + disabled, access to planes is released for you and you must reacquire it. + } + PROCEDURE XPLMReleasePlanes; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetActiveAircraftCount + + This routine sets the number of active planes. If you pass in a number + higher than the total number of planes availables, only the total number of + planes available is actually used. + } + PROCEDURE XPLMSetActiveAircraftCount( + inCount : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetAircraftModel + + This routine loads an aircraft model. It may only be called if you have + exclusive access to the airplane APIs. Pass in the path of the model with + the .acf extension. The index is zero based, but you may not pass in 0 + (use XPLMSetUsersAircraft to load the user's aircracft). + } + PROCEDURE XPLMSetAircraftModel( + inIndex : integer; + inAircraftPath : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDisableAIForPlane + + This routine turns off X-Plane's AI for a given plane. The plane will + continue to draw and be a real plane in X-Plane, but will not move itself. + } + PROCEDURE XPLMDisableAIForPlane( + inPlaneIndex : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDrawAircraft + + This routine draws an aircraft. It can only be called from a 3-d drawing + callback. Pass in the position of the plane in OpenGL local coordinates + and the orientation of the plane. A 1 for full drawing indicates that the + whole plane must be drawn; a 0 indicates you only need the nav lights + drawn. (This saves rendering time when planes are far away.) + } + PROCEDURE XPLMDrawAircraft( + inPlaneIndex : integer; + inX : single; + inY : single; + inZ : single; + inPitch : single; + inRoll : single; + inYaw : single; + inFullDraw : integer; + inDrawStateInfo : PXPLMPlaneDrawState_t); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMReinitUsersPlane + + This function recomputes the derived flight model data from the aircraft + structure in memory. If you have used the data access layer to modify the + aircraft structure, use this routine to resynchronize x-plane; since + X-plane works at least partly from derived values, the sim will not behave + properly until this is called. + + WARNING: this routine does not necessarily place the airplane at the + airport; use XPLMSetUsersAircraft to be compatible. This routine is + provided to do special experimentation with flight models without resetting + flight. + } + PROCEDURE XPLMReinitUsersPlane; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMPlugin.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMPlugin.pas new file mode 100644 index 0000000..f053f80 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMPlugin.pas @@ -0,0 +1,381 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMPlugin; +INTERFACE +{ + These APIs provide facilities to find and work with other plugins and + manage other plugins. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * FINDING PLUGINS + ___________________________________________________________________________} +{ + These APIs allow you to find another plugin or yourself, or iterate across + all plugins. For example, if you wrote an FMS plugin that needed to talk + to an autopilot plugin, you could use these APIs to locate the autopilot + plugin. +} + + + + { + XPLMGetMyID + + This routine returns the plugin ID of the calling plug-in. Call this to + get your own ID. + } + FUNCTION XPLMGetMyID: XPLMPluginID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCountPlugins + + This routine returns the total number of plug-ins that are loaded, both + disabled and enabled. + } + FUNCTION XPLMCountPlugins: integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetNthPlugin + + This routine returns the ID of a plug-in by index. Index is 0 based from 0 + to XPLMCountPlugins-1, inclusive. Plugins may be returned in any arbitrary + order. + } + FUNCTION XPLMGetNthPlugin( + inIndex : integer) : XPLMPluginID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMFindPluginByPath + + This routine returns the plug-in ID of the plug-in whose file exists at the + passed in absolute file system path. XPLM_NO_PLUGIN_ID is returned if the + path does not point to a currently loaded plug-in. + } + FUNCTION XPLMFindPluginByPath( + inPath : Pchar) : XPLMPluginID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMFindPluginBySignature + + This routine returns the plug-in ID of the plug-in whose signature matches + what is passed in or XPLM_NO_PLUGIN_ID if no running plug-in has this + signature. Signatures are the best way to identify another plug-in as they + are independent of the file system path of a plug-in or the human-readable + plug-in name, and should be unique for all plug-ins. Use this routine to + locate another plugin that your plugin interoperates with + } + FUNCTION XPLMFindPluginBySignature( + inSignature : Pchar) : XPLMPluginID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetPluginInfo + + This routine returns information about a plug-in. Each parameter should be + a pointer to a buffer of at least 256 characters, or NULL to not receive + the information. + + outName - the human-readable name of the plug-in. outFilePath - the + absolute file path to the file that contains this plug-in. outSignature - a + unique string that identifies this plug-in. outDescription - a + human-readable description of this plug-in. + } + PROCEDURE XPLMGetPluginInfo( + inPlugin : XPLMPluginID; + outName : Pchar; { Can be nil } + outFilePath : Pchar; { Can be nil } + outSignature : Pchar; { Can be nil } + outDescription : Pchar); { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * ENABLING/DISABLING PLUG-INS + ___________________________________________________________________________} +{ + These routines are used to work with plug-ins and manage them. Most + plugins will not need to use these APIs. +} + + + + { + XPLMIsPluginEnabled + + Returns whether the specified plug-in is enabled for running. + } + FUNCTION XPLMIsPluginEnabled( + inPluginID : XPLMPluginID) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMEnablePlugin + + This routine enables a plug-in if it is not already enabled. It returns 1 + if the plugin was enabled or successfully enables itself, 0 if it does not. + Plugins may fail to enable (for example, if resources cannot be acquired) + by returning 0 from their XPluginEnable callback. + } + FUNCTION XPLMEnablePlugin( + inPluginID : XPLMPluginID) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDisablePlugin + + This routine disableds an enabled plug-in. + } + PROCEDURE XPLMDisablePlugin( + inPluginID : XPLMPluginID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMReloadPlugins + + This routine reloads all plug-ins. Once this routine is called and you + return from the callback you were within (e.g. a menu select callback) you + will receive your XPluginDisable and XPluginStop callbacks and your DLL + will be unloaded, then the start process happens as if the sim was starting + up. + } + PROCEDURE XPLMReloadPlugins; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * INTERPLUGIN MESSAGING + ___________________________________________________________________________} +{ + Plugin messages are defined as 32-bit integers. Messages below 0x00FFFFFF + are reserved for X-Plane and the plugin SDK. + + Messages have two conceptual uses: notifications and commands. Commands + are sent from one plugin to another to induce behavior; notifications are + sent from one plugin to all others for informational purposes. It is + important that commands and notifications not have the same values because + this could cause a notification sent by one plugin to accidentally induce a + command in another. + + By convention, plugin-defined notifications should have the high bit set + (e.g. be greater or equal to unsigned 0x8000000) while commands should have + this bit be cleared. + + The following messages are sent to your plugin by x-plane. +} + + + +CONST + { This message is sent to your plugin whenever the user's plane crashes. } + XPLM_MSG_PLANE_CRASHED = 101; + + { This message is sent to your plugin whenever a new plane is loaded. The } + { parameter is the number of the plane being loaded; 0 indicates the user's } + { plane. } + XPLM_MSG_PLANE_LOADED = 102; + + { This messages is called whenever the user's plane is positioned at a new } + { airport. } + XPLM_MSG_AIRPORT_LOADED = 103; + + { This message is sent whenever new scenery is loaded. Use datarefs to } + { determine the new scenery files that were loaded. } + XPLM_MSG_SCENERY_LOADED = 104; + + { This message is sent whenever the user adjusts the number of X-Plane } + { aircraft models. You must use XPLMCountPlanes to find out how many planes } + { are now available. This message will only be sent in XP7 and higher } + { because in XP6 the number of aircraft is not user-adjustable. } + XPLM_MSG_AIRPLANE_COUNT_CHANGED = 105; + +{$IFDEF XPLM200} + { This message is sent to your plugin whenever a plane is unloaded. The } + { parameter is the number of the plane being unloaded; 0 indicates the user's } + { plane. The parameter is of type int, passed as the value of the pointer. } + { (That is: the parameter is an int, not a pointer to an int.) } + XPLM_MSG_PLANE_UNLOADED = 106; +{$ENDIF} + +{$IFDEF XPLM210} + { This message is sent to your plugin right before X-Plane writes its } + { preferences file. You can use this for two purposes: to write your own } + { preferences, and to modify any datarefs to influence preferences output. } + { For example, if your plugin temporarily modifies saved preferences, you can } + { put them back to their default values here to avoid having the tweaks be } + { persisted if your plugin is not loaded on the next invocation of X-Plane. } + XPLM_MSG_WILL_WRITE_PREFS = 107; +{$ENDIF} + +{$IFDEF XPLM210} + { This message is sent to your plugin right after a livery is loaded for an } + { airplane. You can use this to check the new livery (via datarefs) and } + { react accordingly. The parameter is of type int, passed as the value of a } + { pointer and represents the aicraft plane number - 0 is the user's plane. } + XPLM_MSG_LIVERY_LOADED = 108; +{$ENDIF} + + { + XPLMSendMessageToPlugin + + This function sends a message to another plug-in or X-Plane. Pass + XPLM_NO_PLUGIN_ID to broadcast to all plug-ins. Only enabled plug-ins with + a message receive function receive the message. + } + PROCEDURE XPLMSendMessageToPlugin( + inPlugin : XPLMPluginID; + inMessage : integer; + inParam : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$IFDEF XPLM200} +{___________________________________________________________________________ + * Plugin Features API + ___________________________________________________________________________} +{ + The plugin features API allows your plugin to "sign up" for additional + capabilities and plugin system features that are normally disabled for + backward compatibility. This allows advanced plugins to "opt-in" to new + behavior. + + Each feature is defined by a permanent string name. The feature string + names will vary with the particular installation of X-Plane, so plugins + should not expect a feature to be guaranteed present. +} + + + + + { + XPLMFeatureEnumerator_f + + You pass an XPLMFeatureEnumerator_f to get a list of all features supported + by a given version running version of X-Plane. This routine is called once + for each feature. + } +TYPE + XPLMFeatureEnumerator_f = PROCEDURE( + inFeature : Pchar; + inRef : pointer); cdecl; + + { + XPLMHasFeature + + This returns 1 if the given installation of X-Plane supports a feature, or + 0 if it does not. + } + FUNCTION XPLMHasFeature( + inFeature : Pchar) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMIsFeatureEnabled + + This returns 1 if a feature is currently enabled for your plugin, or 0 if + it is not enabled. It is an error to call this routine with an unsupported + feature. + } + FUNCTION XPLMIsFeatureEnabled( + inFeature : Pchar) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMEnableFeature + + This routine enables or disables a feature for your plugin. This will + change the running behavior of X-Plane and your plugin in some way, + depending on the feature. + } + PROCEDURE XPLMEnableFeature( + inFeature : Pchar; + inEnable : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMEnumerateFeatures + + This routine calls your enumerator callback once for each feature that this + running version of X-Plane supports. Use this routine to determine all of + the features that X-Plane can support. + } + PROCEDURE XPLMEnumerateFeatures( + inEnumerator : XPLMFeatureEnumerator_f; + inRef : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$ENDIF} +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMProcessing.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMProcessing.pas new file mode 100644 index 0000000..79c7b2e --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMProcessing.pas @@ -0,0 +1,276 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMProcessing; +INTERFACE +{ + This API allows you to get regular callbacks during the flight loop, the + part of X-Plane where the plane's position calculates the physics of + flight, etc. Use these APIs to accomplish periodic tasks like logging data + and performing I/O. + + WARNING: Do NOT use these callbacks to draw! You cannot draw during flight + loop callbacks. Use the drawing callbacks (see XPLMDisplay for more info) + for graphics. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * FLIGHT LOOP CALLBACKS + ___________________________________________________________________________} +{ + +} + + + +{$IFDEF XPLM210} + { + XPLMFlightLoopPhaseType + + You can register a flight loop callback to run either before or after the + flight model is integrated by X-Plane. + } +TYPE + XPLMFlightLoopPhaseType = ( + { Your callback runs before X-Plane integrates the flight model. } + xplm_FlightLoop_Phase_BeforeFlightModel = 0 + + { Your callback runs after X-Plane integrates the flight model. } + ,xplm_FlightLoop_Phase_AfterFlightModel = 1 + + ); + PXPLMFlightLoopPhaseType = ^XPLMFlightLoopPhaseType; +{$ENDIF} + +{$IFDEF XPLM210} + { + XPLMFlightLoopID + + This is an opaque identifier for a flight loop callback. You can use this + identifier to easily track and remove your callbacks, or to use the new + flight loop APIs. + } + XPLMFlightLoopID = pointer; + PXPLMFlightLoopID = ^XPLMFlightLoopID; +{$ENDIF} + + { + XPLMFlightLoop_f + + This is your flight loop callback. Each time the flight loop is iterated + through, you receive this call at the end. You receive a time since you + were last called and a time since the last loop, as well as a loop counter. + The 'phase' parameter is deprecated and should be ignored. + + Your return value controls when you will next be called. Return 0 to stop + receiving callbacks. Pass a positive number to specify how many seconds + until the next callback. (You will be called at or after this time, not + before.) Pass a negative number to specify how many loops must go by until + you are called. For example, -1.0 means call me the very next loop. Try + to run your flight loop as infrequently as is practical, and suspend it + (using return value 0) when you do not need it; lots of flight loop + callbacks that do nothing lowers x-plane's frame rate. + + Your callback will NOT be unregistered if you return 0; it will merely be + inactive. + + The reference constant you passed to your loop is passed back to you. + } + XPLMFlightLoop_f = FUNCTION( + inElapsedSinceLastCall: single; + inElapsedTimeSinceLastFlightLoop: single; + inCounter : integer; + inRefcon : pointer) : single; cdecl; + +{$IFDEF XPLM210} + { + XPLMCreateFlightLoop_t + + XPLMCreateFlightLoop_t contains the parameters to create a new flight loop + callback. The strsucture can be expanded in future SDKs - always set + structSize to the size of your structure in bytes. + } + XPLMCreateFlightLoop_t = RECORD + structSize : integer; + phase : XPLMFlightLoopPhaseType; + callbackFunc : XPLMFlightLoop_f; + refcon : pointer; + END; + PXPLMCreateFlightLoop_t = ^XPLMCreateFlightLoop_t; +{$ENDIF} + + { + XPLMGetElapsedTime + + This routine returns the elapsed time since the sim started up in decimal + seconds. + } + FUNCTION XPLMGetElapsedTime: single; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetCycleNumber + + This routine returns a counter starting at zero for each sim cycle + computed/video frame rendered. + } + FUNCTION XPLMGetCycleNumber: integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMRegisterFlightLoopCallback + + This routine registers your flight loop callback. Pass in a pointer to a + flight loop function and a refcon. inInterval defines when you will be + called. Pass in a positive number to specify seconds from registration + time to the next callback. Pass in a negative number to indicate when you + will be called (e.g. pass -1 to be called at the next cylcle). Pass 0 to + not be called; your callback will be inactive. + } + PROCEDURE XPLMRegisterFlightLoopCallback( + inFlightLoop : XPLMFlightLoop_f; + inInterval : single; + inRefcon : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMUnregisterFlightLoopCallback + + This routine unregisters your flight loop callback. Do NOT call it from + your flight loop callback. Once your flight loop callback is + unregistered, it will not be called again. + } + PROCEDURE XPLMUnregisterFlightLoopCallback( + inFlightLoop : XPLMFlightLoop_f; + inRefcon : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSetFlightLoopCallbackInterval + + This routine sets when a callback will be called. Do NOT call it from your + callback; use the return value of the callback to change your callback + interval from inside your callback. + + inInterval is formatted the same way as in XPLMRegisterFlightLoopCallback; + positive for seconds, negative for cycles, and 0 for deactivating the + callback. If inRelativeToNow is 1, times are from the time of this call; + otherwise they are from the time the callback was last called (or the time + it was registered if it has never been called. + } + PROCEDURE XPLMSetFlightLoopCallbackInterval( + inFlightLoop : XPLMFlightLoop_f; + inInterval : single; + inRelativeToNow : integer; + inRefcon : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$IFDEF XPLM210} + { + XPLMCreateFlightLoop + + This routine creates a flight loop callback and returns its ID. The flight + loop callback is created using the input param struct, and is inited to be + unscheduled. + } + FUNCTION XPLMCreateFlightLoop( + inParams : PXPLMCreateFlightLoop_t) : XPLMFlightLoopID; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM210} + { + XPLMDestroyFlightLoop + + This routine destroys a flight loop callback by ID. + } + PROCEDURE XPLMDestroyFlightLoop( + inFlightLoopID : XPLMFlightLoopID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM210} + { + XPLMScheduleFlightLoop + + This routine schedules a flight loop callback for future execution. If + inInterval is negative, it is run in a certain number of frames based on + the absolute value of the input. If the interval is positive, it is a + duration in seconds. + + If inRelativeToNow is true, ties are interpretted relative to the time this + routine is called; otherwise they are relative to the last call time or the + time the flight loop was registered (if never called). + + THREAD SAFETY: it is legal to call this routine from any thread under the + following conditions: + + 1. The call must be between the beginning of an XPLMEnable and the end of + an XPLMDisable sequence. (That is, you must not call this routine from + thread activity when your plugin was supposed to be disabled. Since + plugins are only enabled while loaded, this also implies you cannot run + this routine outside an XPLMStart/XPLMStop sequence.) + + 2. You may not call this routine re-entrantly for a single flight loop ID. + (That is, you can't enable from multiple threads at the same time.) + + 3. You must call this routine between the time after XPLMCreateFlightLoop + returns a value and the time you call XPLMDestroyFlightLoop. (That is, you + must ensure that your threaded activity is within the life of the object. + The SDK does not check this for you, nor does it synchronize destruction of + the object.) + + 4. The object must be unscheduled if this routine is to be called from a + thread other than the main thread. + } + PROCEDURE XPLMScheduleFlightLoop( + inFlightLoopID : XPLMFlightLoopID; + inInterval : single; + inRelativeToNow : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMScenery.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMScenery.pas new file mode 100644 index 0000000..e0c51ac --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMScenery.pas @@ -0,0 +1,419 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMScenery; +INTERFACE +{ + This package contains APIs to interact with X-Plane's scenery system. +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{$IFDEF XPLM200} +{___________________________________________________________________________ + * Terrain Y-Testing + ___________________________________________________________________________} +{ + The Y-testing API allows you to locate the physical scenery mesh. This + would be used to place dynamic graphics on top of the ground in a + plausible way or do physics interactions. + + The Y-test API works via probe objects, which are allocated by your plugin + and used to query terrain. Probe objects exist both to capture which + algorithm you have requested (see probe types) and also to cache query + information. + + Performance guidelines: It is generally faster to use the same probe for + nearby points and different probes for different points. Try not to + allocate more than "hundreds" of probes at most. Share probes if you need + more. Generally, probing operations are expensive, and should be avoided + via caching when possible. + + Y testing returns a location on the terrain, a normal vectory, and a + velocity vector. The normal vector tells you the slope of the terrain at + that point. The velocity vector tells you if that terrain is moving (and + is in meters/second). For example, if your Y test hits the aircraft carrier + deck, this tells you the velocity of that point on the deck. + + Note: the Y-testing API is limited to probing the loaded scenery area, + which is approximately 300x300 km in X-Plane 9. Probes outside this area + will return the height of a 0 MSL sphere. +} + + + + + { + XPLMProbeType + + XPLMProbeType defines the type of terrain probe - each probe has a + different algorithm. (Only one type of probe is provided right now, but + future APIs will expose more flexible or poewrful or useful probes. + } +TYPE + XPLMProbeType = ( + { The Y probe gives you the location of the tallest physical scenery along } + { the Y axis going through the queried point. } + xplm_ProbeY = 0 + + ); + PXPLMProbeType = ^XPLMProbeType; + + { + XPLMProbeResult + + Probe results - possible results from a probe query. + } + XPLMProbeResult = ( + { The probe hit terrain and returned valid values. } + xplm_ProbeHitTerrain = 0 + + { An error in the API call. Either the probe struct size is bad, or the } + { probe is invalid or the type is mismatched for the specific query call. } + ,xplm_ProbeError = 1 + + { The probe call succeeded but there is no terrain under this point (perhaps } + { it is off the side of the planet?) } + ,xplm_ProbeMissed = 2 + + ); + PXPLMProbeResult = ^XPLMProbeResult; + + { + XPLMProbeRef + + An XPLMProbeRef is an opaque handle to a probe, used for querying the + terrain. + } + XPLMProbeRef = pointer; + PXPLMProbeRef = ^XPLMProbeRef; + + { + XPLMProbeInfo_t + + XPLMProbeInfo_t contains the results of a probe call. Make sure to set + structSize to the size of the struct before using it. + } + XPLMProbeInfo_t = RECORD + { Size of structure in bytes - always set this before calling the XPLM. } + structSize : integer; + { Resulting X location of the terrain point we hit, in local OpenGL } + { coordinates. } + locationX : single; + { Resulting Y location of the terrain point we hit, in local OpenGL } + { coordinates. } + locationY : single; + { Resulting Z location of the terrain point we hit, in local OpenGL } + { coordinates. } + locationZ : single; + { X component of the normal vector to the terrain we found. } + normalX : single; + { Y component of the normal vector to the terrain we found. } + normalY : single; + { Z component of the normal vector to the terrain we found. } + normalZ : single; + { X component of the velocity vector of the terrain we found. } + velocityX : single; + { Y component of the velocity vector of the terrain we found. } + velocityY : single; + { Z component of the velocity vector of the terrain we found. } + velocityZ : single; + { Tells if the surface we hit is water (otherwise it is land). } + is_wet : integer; + END; + PXPLMProbeInfo_t = ^XPLMProbeInfo_t; + + { + XPLMCreateProbe + + Creates a new probe object of a given type and returns. + } + FUNCTION XPLMCreateProbe( + inProbeType : XPLMProbeType) : XPLMProbeRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDestroyProbe + + Deallocates an existing probe object. + } + PROCEDURE XPLMDestroyProbe( + inProbe : XPLMProbeRef); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMProbeTerrainXYZ + + Probes the terrain. Pass in the XYZ coordinate of the probe point, a probe + object, and an XPLMProbeInfo_t struct that has its structSize member set + properly. Other fields are filled in if we hit terrain, and a probe result + is returned. + } + FUNCTION XPLMProbeTerrainXYZ( + inProbe : XPLMProbeRef; + inX : single; + inY : single; + inZ : single; + outInfo : PXPLMProbeInfo_t) : XPLMProbeResult; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$ENDIF} +{___________________________________________________________________________ + * Object Drawing + ___________________________________________________________________________} +{ + The object drawing routines let you load and draw X-Plane OBJ files. + Objects are loaded by file path and managed via an opaque handle. X-Plane + naturally reference counts objects, so it is important that you balance + every successful call to XPLMLoadObject with a call to XPLMUnloadObject! +} + + + +{$IFDEF XPLM200} +TYPE + { + XPLMObjectRef + + An XPLMObjectRef is a opaque handle to an .obj file that has been loaded + into memory. + } + XPLMObjectRef = pointer; + PXPLMObjectRef = ^XPLMObjectRef; +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMDrawInfo_t + + The XPLMDrawInfo_t structure contains positioning info for one object that + is to be drawn. Be sure to set structSize to the size of the structure for + future expansion. + } + XPLMDrawInfo_t = RECORD + { Set this to the size of this structure! } + structSize : integer; + { X location of the object in local coordinates. } + x : single; + { Y location of the object in local coordinates. } + y : single; + { Z location of the object in local coordinates. } + z : single; + { Pitch in degres to rotate the object, positive is up. } + pitch : single; + { Heading in local coordinates to rotate the object, clockwise. } + heading : single; + { Roll to rotate the object. } + roll : single; + END; + PXPLMDrawInfo_t = ^XPLMDrawInfo_t; +{$ENDIF} + +{$IFDEF XPLM210} + { + XPLMObjectLoaded_f + + You provide this callback when loading an object asynchronously; it will be + called once the object is loaded. Your refcon is passed back. The object + ref passed in is the newly loaded object (ready for use) or NULL if an + error occured. + + If your plugin is disabled, this callback will be delivered as soon as the + plugin is re-enabled. If your plugin is unloaded before this callback is + ever called, the SDK will release the object handle for you. + } + XPLMObjectLoaded_f = PROCEDURE( + inObject : XPLMObjectRef; + inRefcon : pointer); cdecl; +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMLoadObject + + This routine loads an OBJ file and returns a handle to it. If X-plane has + already loaded the object, the handle to the existing object is returned. + Do not assume you will get the same handle back twice, but do make sure to + call unload once for every load to avoid "leaking" objects. The object + will be purged from memory when no plugins and no scenery are using it. + + The path for the object must be relative to the X-System base folder. If + the path is in the root of the X-System folder you may need to prepend ./ + to it; loading objects in the root of the X-System folder is STRONGLY + discouraged - your plugin should not dump art resources in the root folder! + + + XPLMLoadObject will return NULL if the object cannot be loaded (either + because it is not found or the file is misformatted). This routine will + load any object that can be used in the X-Plane scenery system. + + It is important that the datarefs an object uses for animation already be + loaded before you load the object. For this reason it may be necessary to + defer object loading until the sim has fully started. + } + FUNCTION XPLMLoadObject( + inPath : Pchar) : XPLMObjectRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM210} + { + XPLMLoadObjectAsync + + This routine loads an object asynchronously; control is returned to you + immediately while X-Plane loads the object. The sim will not stop flying + while the object loads. For large objects, it may be several seconds + before the load finishes. + + You provide a callback function that is called once the load has completed. + Note that if the object cannot be loaded, you will not find out until the + callback function is called with a NULL object handle. + + There is no way to cancel an asynchronous object load; you must wait for + the load to complete and then release the object if it is no longer + desired. + } + PROCEDURE XPLMLoadObjectAsync( + inPath : Pchar; + inCallback : XPLMObjectLoaded_f; + inRefcon : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMDrawObjects + + XPLMDrawObjects draws an object from an OBJ file one or more times. You + pass in the object and an array of XPLMDrawInfo_t structs, one for each + place you would like the object to be drawn. + + X-Plane will attempt to cull the objects based on LOD and visibility, and + will pick the appropriate LOD. + + Lighting is a boolean; pass 1 to show the night version of object with + night-only lights lit up. Pass 0 to show the daytime version of the + object. + + earth_relative controls the coordinate system. If this is 1, the rotations + you specify are applied to the object after its coordinate system is + transformed from local to earth-relative coordinates -- that is, an object + with no rotations will point toward true north and the Y axis will be up + against gravity. If this is 0, the object is drawn with your rotations + from local coordanates -- that is, an object with no rotations is drawn + pointing down the -Z axis and the Y axis of the object matches the local + coordinate Y axis. + } + PROCEDURE XPLMDrawObjects( + inObject : XPLMObjectRef; + inCount : integer; + inLocations : PXPLMDrawInfo_t; + lighting : integer; + earth_relative : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMUnloadObject + + This routine marks an object as no longer being used by your plugin. + Objects are reference counted: once no plugins are using an object, it is + purged from memory. Make sure to call XPLMUnloadObject once for each + successful call to XPLMLoadObject. + } + PROCEDURE XPLMUnloadObject( + inObject : XPLMObjectRef); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM200} +{___________________________________________________________________________ + * Library Access + ___________________________________________________________________________} +{ + The library access routines allow you to locate scenery objects via the + X-Plane library system. Right now library access is only provided for + objects, allowing plugin-drawn objects to be extended using the library + system. +} + + + + + { + XPLMLibraryEnumerator_f + + An XPLMLibraryEnumerator_f is a callback you provide that is called once + for each library element that is located. The returned paths will be + relative to the X-System folder. + } +TYPE + XPLMLibraryEnumerator_f = PROCEDURE( + inFilePath : Pchar; + inRef : pointer); cdecl; + + { + XPLMLookupObjects + + This routine looks up a virtual path in the library system and returns all + matching elements. You provide a callback - one virtual path may match + many objects in the library. XPLMLookupObjects returns the number of + objects found. + + The latitude and longitude parameters specify the location the object will + be used. The library system allows for scenery packages to only provide + objects to certain local locations. Only objects that are allowed at the + latitude/longitude you provide will be returned. + } + FUNCTION XPLMLookupObjects( + inPath : Pchar; + inLatitude : single; + inLongitude : single; + enumerator : XPLMLibraryEnumerator_f; + ref : pointer) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$ENDIF} +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMUtilities.pas b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMUtilities.pas new file mode 100644 index 0000000..0595d1c --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/Delphi/XPLM/XPLMUtilities.pas @@ -0,0 +1,927 @@ +{ + Copyright 2005-2012 Sandy Barbour and Ben Supnik + + All rights reserved. See license.txt for usage. + + X-Plane SDK Version: 2.1.1 +} + +UNIT XPLMUtilities; +INTERFACE +{ + +} + +USES XPLMDefs; + {$A4} +{$IFDEF MSWINDOWS} + {$DEFINE DELPHI} +{$ENDIF} +{___________________________________________________________________________ + * X-PLANE USER INTERACTION + ___________________________________________________________________________} +{ + The user interaction APIs let you simulate commands the user can do with a + joystick, keyboard etc. Note that it is generally safer for future + compatibility to use one of these commands than to manipulate the + underlying sim data. +} + + + + { + XPLMCommandKeyID + + These enums represent all the keystrokes available within x-plane. They + can be sent to x-plane directly. For example, you can reverse thrust using + these enumerations. + } +TYPE + XPLMCommandKeyID = ( + xplm_key_pause=0, + xplm_key_revthrust, + xplm_key_jettison, + xplm_key_brakesreg, + xplm_key_brakesmax, + xplm_key_gear, + xplm_key_timedn, + xplm_key_timeup, + xplm_key_fadec, + xplm_key_otto_dis, + xplm_key_otto_atr, + xplm_key_otto_asi, + xplm_key_otto_hdg, + xplm_key_otto_gps, + xplm_key_otto_lev, + xplm_key_otto_hnav, + xplm_key_otto_alt, + xplm_key_otto_vvi, + xplm_key_otto_vnav, + xplm_key_otto_nav1, + xplm_key_otto_nav2, + xplm_key_targ_dn, + xplm_key_targ_up, + xplm_key_hdgdn, + xplm_key_hdgup, + xplm_key_barodn, + xplm_key_baroup, + xplm_key_obs1dn, + xplm_key_obs1up, + xplm_key_obs2dn, + xplm_key_obs2up, + xplm_key_com1_1, + xplm_key_com1_2, + xplm_key_com1_3, + xplm_key_com1_4, + xplm_key_nav1_1, + xplm_key_nav1_2, + xplm_key_nav1_3, + xplm_key_nav1_4, + xplm_key_com2_1, + xplm_key_com2_2, + xplm_key_com2_3, + xplm_key_com2_4, + xplm_key_nav2_1, + xplm_key_nav2_2, + xplm_key_nav2_3, + xplm_key_nav2_4, + xplm_key_adf_1, + xplm_key_adf_2, + xplm_key_adf_3, + xplm_key_adf_4, + xplm_key_adf_5, + xplm_key_adf_6, + xplm_key_transpon_1, + xplm_key_transpon_2, + xplm_key_transpon_3, + xplm_key_transpon_4, + xplm_key_transpon_5, + xplm_key_transpon_6, + xplm_key_transpon_7, + xplm_key_transpon_8, + xplm_key_flapsup, + xplm_key_flapsdn, + xplm_key_cheatoff, + xplm_key_cheaton, + xplm_key_sbrkoff, + xplm_key_sbrkon, + xplm_key_ailtrimL, + xplm_key_ailtrimR, + xplm_key_rudtrimL, + xplm_key_rudtrimR, + xplm_key_elvtrimD, + xplm_key_elvtrimU, + xplm_key_forward, + xplm_key_down, + xplm_key_left, + xplm_key_right, + xplm_key_back, + xplm_key_tower, + xplm_key_runway, + xplm_key_chase, + xplm_key_free1, + xplm_key_free2, + xplm_key_spot, + xplm_key_fullscrn1, + xplm_key_fullscrn2, + xplm_key_tanspan, + xplm_key_smoke, + xplm_key_map, + xplm_key_zoomin, + xplm_key_zoomout, + xplm_key_cycledump, + xplm_key_replay, + xplm_key_tranID, + xplm_key_max + ); + PXPLMCommandKeyID = ^XPLMCommandKeyID; + + { + XPLMCommandButtonID + + These are enumerations for all of the things you can do with a joystick + button in X-Plane. They currently match the buttons menu in the equipment + setup dialog, but these enums will be stable even if they change in + X-Plane. + } + XPLMCommandButtonID = ( + xplm_joy_nothing=0, + xplm_joy_start_all, + xplm_joy_start_0, + xplm_joy_start_1, + xplm_joy_start_2, + xplm_joy_start_3, + xplm_joy_start_4, + xplm_joy_start_5, + xplm_joy_start_6, + xplm_joy_start_7, + xplm_joy_throt_up, + xplm_joy_throt_dn, + xplm_joy_prop_up, + xplm_joy_prop_dn, + xplm_joy_mixt_up, + xplm_joy_mixt_dn, + xplm_joy_carb_tog, + xplm_joy_carb_on, + xplm_joy_carb_off, + xplm_joy_trev, + xplm_joy_trm_up, + xplm_joy_trm_dn, + xplm_joy_rot_trm_up, + xplm_joy_rot_trm_dn, + xplm_joy_rud_lft, + xplm_joy_rud_cntr, + xplm_joy_rud_rgt, + xplm_joy_ail_lft, + xplm_joy_ail_cntr, + xplm_joy_ail_rgt, + xplm_joy_B_rud_lft, + xplm_joy_B_rud_rgt, + xplm_joy_look_up, + xplm_joy_look_dn, + xplm_joy_look_lft, + xplm_joy_look_rgt, + xplm_joy_glance_l, + xplm_joy_glance_r, + xplm_joy_v_fnh, + xplm_joy_v_fwh, + xplm_joy_v_tra, + xplm_joy_v_twr, + xplm_joy_v_run, + xplm_joy_v_cha, + xplm_joy_v_fr1, + xplm_joy_v_fr2, + xplm_joy_v_spo, + xplm_joy_flapsup, + xplm_joy_flapsdn, + xplm_joy_vctswpfwd, + xplm_joy_vctswpaft, + xplm_joy_gear_tog, + xplm_joy_gear_up, + xplm_joy_gear_down, + xplm_joy_lft_brake, + xplm_joy_rgt_brake, + xplm_joy_brakesREG, + xplm_joy_brakesMAX, + xplm_joy_speedbrake, + xplm_joy_ott_dis, + xplm_joy_ott_atr, + xplm_joy_ott_asi, + xplm_joy_ott_hdg, + xplm_joy_ott_alt, + xplm_joy_ott_vvi, + xplm_joy_tim_start, + xplm_joy_tim_reset, + xplm_joy_ecam_up, + xplm_joy_ecam_dn, + xplm_joy_fadec, + xplm_joy_yaw_damp, + xplm_joy_art_stab, + xplm_joy_chute, + xplm_joy_JATO, + xplm_joy_arrest, + xplm_joy_jettison, + xplm_joy_fuel_dump, + xplm_joy_puffsmoke, + xplm_joy_prerotate, + xplm_joy_UL_prerot, + xplm_joy_UL_collec, + xplm_joy_TOGA, + xplm_joy_shutdown, + xplm_joy_con_atc, + xplm_joy_fail_now, + xplm_joy_pause, + xplm_joy_rock_up, + xplm_joy_rock_dn, + xplm_joy_rock_lft, + xplm_joy_rock_rgt, + xplm_joy_rock_for, + xplm_joy_rock_aft, + xplm_joy_idle_hilo, + xplm_joy_lanlights, + xplm_joy_max + ); + PXPLMCommandButtonID = ^XPLMCommandButtonID; + + { + XPLMHostApplicationID + + The plug-in system is based on Austin's cross-platform OpenGL framework and + could theoretically be adapted to run in other apps like WorldMaker. The + plug-in system also runs against a test harness for internal development + and could be adapted to another flight sim (in theory at least). So an ID + is providing allowing plug-ins to indentify what app they are running + under. + } + XPLMHostApplicationID = ( + xplm_Host_Unknown = 0 + + ,xplm_Host_XPlane = 1 + + ,xplm_Host_PlaneMaker = 2 + + ,xplm_Host_WorldMaker = 3 + + ,xplm_Host_Briefer = 4 + + ,xplm_Host_PartMaker = 5 + + ,xplm_Host_YoungsMod = 6 + + ,xplm_Host_XAuto = 7 + + ); + PXPLMHostApplicationID = ^XPLMHostApplicationID; + + { + XPLMLanguageCode + + These enums define what language the sim is running in. These enumerations + do not imply that the sim can or does run in all of these languages; they + simply provide a known encoding in the event that a given sim version is + localized to a certain language. + } + XPLMLanguageCode = ( + xplm_Language_Unknown = 0 + + ,xplm_Language_English = 1 + + ,xplm_Language_French = 2 + + ,xplm_Language_German = 3 + + ,xplm_Language_Italian = 4 + + ,xplm_Language_Spanish = 5 + + ,xplm_Language_Korean = 6 + +{$IFDEF XPLM200} + ,xplm_Language_Russian = 7 +{$ENDIF} + +{$IFDEF XPLM200} + ,xplm_Language_Greek = 8 +{$ENDIF} + +{$IFDEF XPLM200} + ,xplm_Language_Japanese = 9 +{$ENDIF} + +{$IFDEF XPLM200} + ,xplm_Language_Chinese = 10 +{$ENDIF} + + ); + PXPLMLanguageCode = ^XPLMLanguageCode; + +{$IFDEF XPLM200} + { + XPLMDataFileType + + These enums define types of data files you can load or unload using the + SDK. + } + XPLMDataFileType = ( + { A situation (.sit) file, which starts off a flight in a given } + { configuration. } + xplm_DataFile_Situation = 1 + + { A situation movie (.smo) file, which replays a past flight. } + ,xplm_DataFile_ReplayMovie = 2 + + ); + PXPLMDataFileType = ^XPLMDataFileType; +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMError_f + + An XPLM error callback is a function that you provide to receive debugging + information from the plugin SDK. See XPLMSetErrorCallback for more + information. NOTE: for the sake of debugging, your error callback will be + called even if your plugin is not enabled, allowing you to receive debug + info in your XPluginStart and XPluginStop callbacks. To avoid causing + logic errors in the management code, do not call any other plugin routines + from your error callback - it is only meant for logging! + } + XPLMError_f = PROCEDURE( + inMessage : Pchar); cdecl; +{$ENDIF} + + { + XPLMSimulateKeyPress + + This function simulates a key being pressed for x-plane. The keystroke + goes directly to x-plane; it is never sent to any plug-ins. However, since + this is a raw key stroke it may be mapped by the keys file or enter text + into a field. + + WARNING: This function will be deprecated; do not use it. Instead use + XPLMCommandKeyStroke. + } + PROCEDURE XPLMSimulateKeyPress( + inKeyType : integer; + inKey : integer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMSpeakString + + This function displays the string in a translucent overlay over the current + display and also speaks the string if text-to-speech is enabled. The + string is spoken asynchronously, this function returns immediately. + } + PROCEDURE XPLMSpeakString( + inString : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCommandKeyStroke + + This routine simulates a command-key stroke. However, the keys are done by + function, not by actual letter, so this function works even if the user has + remapped their keyboard. Examples of things you might do with this include + pausing the simulator. + } + PROCEDURE XPLMCommandKeyStroke( + inKey : XPLMCommandKeyID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCommandButtonPress + + This function simulates any of the actions that might be taken by pressing + a joystick button. However, this lets you call the command directly rather + than have to know which button is mapped where. Important: you must + release each button you press. The APIs are separate so that you can 'hold + down' a button for a fixed amount of time. + } + PROCEDURE XPLMCommandButtonPress( + inButton : XPLMCommandButtonID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCommandButtonRelease + + This function simulates any of the actions that might be taken by pressing + a joystick button. See XPLMCommandButtonPress + } + PROCEDURE XPLMCommandButtonRelease( + inButton : XPLMCommandButtonID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetVirtualKeyDescription + + Given a virtual key code (as defined in XPLMDefs.h) this routine returns a + human-readable string describing the character. This routine is provided + for showing users what keyboard mappings they have set up. The string may + read 'unknown' or be a blank or NULL string if the virtual key is unknown. + } + FUNCTION XPLMGetVirtualKeyDescription( + inVirtualKey : char) : Pchar; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{___________________________________________________________________________ + * X-PLANE MISC + ___________________________________________________________________________} +{ + +} + + + + { + XPLMReloadScenery + + XPLMReloadScenery reloads the current set of scenery. You can use this + function in two typical ways: simply call it to reload the scenery, picking + up any new installed scenery, .env files, etc. from disk. Or, change the + lat/ref and lon/ref data refs and then call this function to shift the + scenery environment. + } + PROCEDURE XPLMReloadScenery; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetSystemPath + + This function returns the full path to the X-System folder. Note that this + is a directory path, so it ends in a trailing : or /. The buffer you pass + should be at least 512 characters long. + } + PROCEDURE XPLMGetSystemPath( + outSystemPath : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetPrefsPath + + This routine returns a full path to the proper directory to store + preferences in. It ends in a : or /. The buffer you pass should be at + least 512 characters long. + } + PROCEDURE XPLMGetPrefsPath( + outPrefsPath : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDirectorySeparator + + This routine returns a string with one char and a null terminator that is + the directory separator for the current platform. This allows you to write + code that concatinates directory paths without having to #ifdef for + platform. + } + FUNCTION XPLMGetDirectorySeparator: Pchar; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMExtractFileAndPath + + Given a full path to a file, this routine separates the path from the file. + If the path is a partial directory (e.g. ends in : or \) the trailing + directory separator is removed. This routine works in-place; a pointer to + the file part of the buffer is returned; the original buffer still starts + with the path. + } + FUNCTION XPLMExtractFileAndPath( + inFullPath : Pchar) : Pchar; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetDirectoryContents + + This routine returns a list of files in a directory (specified by a full + path, no trailing : or \). The output is returned as a list of NULL + terminated strings. An index array (if specified) is filled with pointers + into the strings. This routine The last file is indicated by a zero-length + string (and NULL in the indices). This routine will return 1 if you had + capacity for all files or 0 if you did not. You can also skip a given + number of files. + + inDirectoryPath - a null terminated C string containing the full path to + the directory with no trailing directory char. + + inFirstReturn - the zero-based index of the first file in the directory to + return. (Usually zero to fetch all in one pass.) + + outFileNames - a buffer to receive a series of sequential null terminated + C-string file names. A zero-length C string will be appended to the very + end. + + inFileNameBufSize - the size of the file name buffer in bytes. + + outIndices - a pointer to an array of character pointers that will become + an index into the directory. The last file will be followed by a NULL + value. Pass NULL if you do not want indexing information. + + inIndexCount - the max size of the index in entries. + + outTotalFiles - if not NULL, this is filled in with the number of files in + the directory. + + outReturnedFiles - if not NULL, the number of files returned by this + iteration. + + Return value - 1 if all info could be returned, 0 if there was a buffer + overrun. + + WARNING: Before X-Plane 7 this routine did not properly iterate through + directories. If X-Plane 6 compatibility is needed, use your own code to + iterate directories. + } + FUNCTION XPLMGetDirectoryContents( + inDirectoryPath : Pchar; + inFirstReturn : integer; + outFileNames : Pchar; + inFileNameBufSize : integer; + outIndices : PPchar; { Can be nil } + inIndexCount : integer; + outTotalFiles : Pinteger; { Can be nil } + outReturnedFiles : Pinteger) : integer; { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMInitialized + + This function returns 1 if X-Plane has properly initialized the plug-in + system. If this routine returns 0, many XPLM functions will not work. + + NOTE: Under normal circumstances a plug-in should never be running while + the plug-in manager is not initialized. + + WARNING: This function is generally not needed and may be deprecated in the + future. + } + FUNCTION XPLMInitialized: integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetVersions + + This routine returns the revision of both X-Plane and the XPLM DLL. All + versions are three-digit decimal numbers (e.g. 606 for version 6.06 of + X-Plane); the current revision of the XPLM is 200 (2.00). This routine + also returns the host ID of the app running us. + + The most common use of this routine is to special-case around x-plane + version-specific behavior. + } + PROCEDURE XPLMGetVersions( + outXPlaneVersion : Pinteger; + outXPLMVersion : Pinteger; + outHostID : PXPLMHostApplicationID); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMGetLanguage + + This routine returns the langauge the sim is running in. + } + FUNCTION XPLMGetLanguage: XPLMLanguageCode; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMDebugString + + This routine outputs a C-style string to the Log.txt file. The file is + immediately flushed so you will not lose data. (This does cause a + performance penalty.) + } + PROCEDURE XPLMDebugString( + inString : Pchar); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMSetErrorCallback + + XPLMSetErrorCallback installs an error-reporting callback for your plugin. + Normally the plugin system performs minimum diagnostics to maximize + performance. When you install an error callback, you will receive calls + due to certain plugin errors, such as passing bad parameters or incorrect + data. + + The intention is for you to install the error callback during debug + sections and put a break-point inside your callback. This will cause you + to break into the debugger from within the SDK at the point in your plugin + where you made an illegal call. + + Installing an error callback may activate error checking code that would + not normally run, and this may adversely affect performance, so do not + leave error callbacks installed in shipping plugins. + } + PROCEDURE XPLMSetErrorCallback( + inCallback : XPLMError_f); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMFindSymbol + + This routine will attempt to find the symbol passed in the inString + parameter. If the symbol is found a pointer the function is returned, + othewise the function will return NULL. + } + FUNCTION XPLMFindSymbol( + inString : Pchar) : pointer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMLoadDataFile + + Loads a data file of a given type. Paths must be relative to the X-System + folder. To clear the replay, pass a NULL file name (this is only valid with + replay movies, not sit files). + } + FUNCTION XPLMLoadDataFile( + inFileType : XPLMDataFileType; + inFilePath : Pchar) : integer; { Can be nil } +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM200} + { + XPLMSaveDataFile + + Saves the current situation or replay; paths are relative to the X-System + folder. + } + FUNCTION XPLMSaveDataFile( + inFileType : XPLMDataFileType; + inFilePath : Pchar) : integer; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} +{$ENDIF} + +{$IFDEF XPLM200} +{___________________________________________________________________________ + * X-PLANE COMMAND MANAGEMENT + ___________________________________________________________________________} +{ + The command management APIs let plugins interact with the command-system in + X-Plane, the abstraction behind keyboard presses and joystick buttons. + This API lets you create new commands and modify the behavior (or get + notification) of existing ones. + + An X-Plane command consists of three phases: a beginning, continuous + repetition, and an ending. The command may be repeated zero times in the + event that the user presses a button only momentarily. +} + + + + + { + XPLMCommandPhase + + The phases of a command. + } +TYPE + XPLMCommandPhase = ( + { The command is being started. } + xplm_CommandBegin = 0 + + { The command is continuing to execute. } + ,xplm_CommandContinue = 1 + + { The command has ended. } + ,xplm_CommandEnd = 2 + + ); + PXPLMCommandPhase = ^XPLMCommandPhase; + + { + XPLMCommandRef + + A command ref is an opaque identifier for an X-Plane command. Command + references stay the same for the life of your plugin but not between + executions of X-Plane. Command refs are used to execute commands, create + commands, and create callbacks for particular commands. + + Note that a command is not "owned" by a particular plugin. Since many + plugins may participate in a command's execution, the command does not go + away if the plugin that created it is unloaded. + } + XPLMCommandRef = pointer; + PXPLMCommandRef = ^XPLMCommandRef; + + { + XPLMCommandCallback_f + + A command callback is a function in your plugin that is called when a + command is pressed. Your callback receives the commadn reference for the + particular command, the phase of the command that is executing, and a + reference pointer that you specify when registering the callback. + + Your command handler should return 1 to let processing of the command + continue to other plugins and X-Plane, or 0 to halt processing, + potentially bypassing X-Plane code. + } + XPLMCommandCallback_f = FUNCTION( + inCommand : XPLMCommandRef; + inPhase : XPLMCommandPhase; + inRefcon : pointer) : integer; cdecl; + + { + XPLMFindCommand + + XPLMFindCommand looks up a command by name, and returns its command + reference or NULL if the command does not exist. + } + FUNCTION XPLMFindCommand( + inName : Pchar) : XPLMCommandRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCommandBegin + + XPLMCommandBegin starts the execution of a command, specified by its + command reference. The command is "held down" until XPLMCommandEnd is + called. + } + PROCEDURE XPLMCommandBegin( + inCommand : XPLMCommandRef); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCommandEnd + + XPLMCommandEnd ends the execution of a given command that was started with + XPLMCommandBegin. + } + PROCEDURE XPLMCommandEnd( + inCommand : XPLMCommandRef); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCommandOnce + + This executes a given command momentarily, that is, the command begins and + ends immediately. + } + PROCEDURE XPLMCommandOnce( + inCommand : XPLMCommandRef); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMCreateCommand + + XPLMCreateCommand creates a new command for a given string. If the command + already exists, the existing command reference is returned. The + description may appear in user interface contexts, such as the joystick + configuration screen. + } + FUNCTION XPLMCreateCommand( + inName : Pchar; + inDescription : Pchar) : XPLMCommandRef; +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMRegisterCommandHandler + + XPLMRegisterCommandHandler registers a callback to be called when a command + is executed. You provide a callback with a reference pointer. + + If inBefore is true, your command handler callback will be executed before + X-Plane executes the command, and returning 0 from your callback will + disable X-Plane's processing of the command. If inBefore is false, your + callback will run after X-Plane. (You can register a single callback both + before and after a command.) + } + PROCEDURE XPLMRegisterCommandHandler( + inComand : XPLMCommandRef; + inHandler : XPLMCommandCallback_f; + inBefore : integer; + inRefcon : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + + { + XPLMUnregisterCommandHandler + + XPLMUnregisterCommandHandler removes a command callback registered with + XPLMRegisterCommandHandler. + } + PROCEDURE XPLMUnregisterCommandHandler( + inComand : XPLMCommandRef; + inHandler : XPLMCommandCallback_f; + inBefore : integer; + inRefcon : pointer); +{$IFDEF DELPHI} + cdecl; external 'XPLM.DLL'; +{$ELSE} + cdecl; external ''; +{$ENDIF} + +{$ENDIF} +IMPLEMENTATION +END. diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Mac/XPLM.framework/XPLM b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Mac/XPLM.framework/XPLM new file mode 100644 index 0000000..c03cf48 Binary files /dev/null and b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Mac/XPLM.framework/XPLM differ diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Mac/XPWidgets.framework/XPWidgets b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Mac/XPWidgets.framework/XPWidgets new file mode 100644 index 0000000..aba93db Binary files /dev/null and b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Mac/XPWidgets.framework/XPWidgets differ diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPLM.lib b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPLM.lib new file mode 100644 index 0000000..c7b00b1 Binary files /dev/null and b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPLM.lib differ diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPLM_64.lib b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPLM_64.lib new file mode 100644 index 0000000..51fdf70 Binary files /dev/null and b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPLM_64.lib differ diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPWidgets.lib b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPWidgets.lib new file mode 100644 index 0000000..1eac5bf Binary files /dev/null and b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPWidgets.lib differ diff --git a/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPWidgets_64.lib b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPWidgets_64.lib new file mode 100644 index 0000000..32c3ae4 Binary files /dev/null and b/GermanAirlinesVA-GAConnector/XPSDK/Libraries/Win/XPWidgets_64.lib differ diff --git a/GermanAirlinesVA-GAConnector/XPSDK/README.txt b/GermanAirlinesVA-GAConnector/XPSDK/README.txt new file mode 100644 index 0000000..2316eb5 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/README.txt @@ -0,0 +1,197 @@ +------------------------------------------------------------------------------- + THE X-PLANE PLUGIN SDK +------------------------------------------------------------------------------- + +This download contains the files necessary to build plugins for X-Plane. The +X-Plane plugin website is: + +http://www.xsquawkbox.net/xpsdk/ + +The website contains full documentation on the SDK including tech notes, sample +plugins, sample code, contact information, and links to the latest versions of +this SDK. + +The X-Plane SDK authors can be reached at: + +xplanesdk@xsquawkbox.net + +Please do not email Austin or Laminar Research for SDK questions or support; +the SDK is a third party effort. + +the X-Plane developer mailing list is an unlisted yahoo group frequented by +many X-Plane developers. + +x-plane-dev@yahoogroups.com + +------------------------------------------------------------------------------- + SDK FILES +------------------------------------------------------------------------------- + +license.txt Copyright information for this download. +README.txt This document +CHeaders Header files for compiling C/C++ plugins +Delphi Interfaces for compiling Pascal plugins +Libraries Import libraries for linking on Windows + and frameworks for linking on Mac. + +Note: there are no import/link-time libraries for Linux; on Linux, plugins +simply leave SDK symbols undefined and they are discovered at runtime. The +SDK website explains this process in more detail. + +Mac CFM plugins are not supported by the SDK versions 2.0 and higher; the +2.0 SDK requires X-Plane 9.0 or newer, and X-Plane 9 will not run on +Mac OS 9. Therefore CFM plugins are not useful (and are probably +counterproductive since they cannot support x86 code). If you have a CFM +plugin, continue to use the 1.0 SDK to build it. You will have to port to +Mach-O if you want to use 2.0 features. + +------------------------------------------------------------------------------- + RELEASE NOTES +------------------------------------------------------------------------------- + +This section contains per-release notes for the history of the X-Plane SDK. + +X-Plane SDK Release 2.1.3 11/14/13 + +Fixed XPC Wrappers to use int and intptr_t instead of long. This fixes +crashes for plugins on 64-bit Windows. + +X-Plane SDK Release 2.1.2 RC2 1/15/13 + +Removed headers from frameworks, as they don't work; updated README. + +X-Plane SDK Release 2.1.2 RC1 1/12/13 + +The 2.1.2 SDK adds frameworks for the XPLM and XPWidgets; Mac developers +can link directly against these frameworks and avoid unresolved symbols +and flat namespace problems. The frameworks produce plugins that will +work on X-Plane 8, 9, and 10 depending on the plugin CPU architecture, +minimum system SDK, and XPLM API revision number. + +X-Plane SDK Release 2.1.1 RC1 10/29/12 + +The 2.1.1 update to the SDK provides 64-bit build materials. + +X-Plane SDK Release 2.1.0 RC1 3/31/12 + +This is the first release of the version 2.1 X-Plane SDK. This version of the +SDK exposes new APIs. + +This API also replaces all references to "long" with int or intptr_t, +depending on whether the integer needs to be wide enough to hold coerced +pointers. Most of the time, int is used; the notable exception is the widgets +library where params and properties can contain pointers to user data. + +This change is not an ABI change - compiled plugins will work unmodified. +However for some compilers, you may need to replace long with int or intptr_t +in your code. + +X-Plane SDK Release 2.0.1 RC1 7/21/10 + +This release adds symbol visibility macros for GCC 4 on Linux and corrects a few +function documentation comments. + +X-Plane SDK Release 2.0 RC1 7/11/08 + +This release includes a corrected XPLM.lib for windows with exports for some of +the new 2.0 APIs. + +X-Plane SDK Release 2.0 Beta 2 4/23/08 + +This release includes new APIs for reading and writing data files and drawing +hooks for the local map screen, as well as some minor tweaks: + +- Sim version is 2.0 in the headers. +- unload plane msg marked as 2.0 only. +- New enumerations for additional languages. +- Function level docs improved. + +X-Plane SDK Release 2.0 Beta 1 1/19/08 + +This is the first release of the version 2.0 X-Plane SDK. CFM support has +been removed, and the license has been simplified, reflecting that it only has +to cover the SDK include/import lib files and not the sample code or examples. + +X-Plane SDK Release 1.0.2 1/5/05 + +The headers of the SDK are modified to support Kylix. No changes for Mac, +Windows, or C users. Headers now have SDK version numbers. + +X-Plane SDK Release 1.0.1 12/29/04 + +The headers of this SDK are modified to support Linux complication. No changes +for Mac and Windows users. + +X-Plane SDK Release Candidate 1 + +Only one slight change in the enums: the enum xpProperty_SubWindowHasCloseBoxes +in XPStandardWidgets.h has been changed to xpProperty_MainWindowHasCloseBoxes. +Its value has not been changed, so you will need to search-and-replace your code +when using this version of the SDK, but already-compiled plugins will experience +no different operation. + +The documentation has been revised for all headers to revise changes made to the +SDK over the course of beta. + +X-Plane SDK Beta 5 + +This version of the SDK features a number of enumeration changes to reflect the +X-Plane interface more correctly. This became crucial when X-Plane 7's new user +interface was released. With X-Plane in release candidates hopefully beta 5 of +the SDK could be the last one. Please see: + +www.xsquawkbox.net/xpsdk/newui.html + +For a comprehensive description of all the enumeration changes. For most +plugins (no developers reported using the deprecated enumerations), a simple +search and replace should suffice. Plugins compiled against the beta 4 SDK that +do not use now-unsupported graphics will continue to work correctly. + +X-Plane SDK Beta 4 + +This release corrects two problems with the Pascal headers: function pointer +types are now declared cdecl (since this is how the SDK calls them), and the +import library for the widget callbacks is now XPWIDGETS.DLL as it should be. + +X-Plane SDK Beta 3 + +This release finally features full documentation and a stable widgets API, as +well as a few other minor bug fixes. + +Starting with beta 3, the DLLs necessary to run plugins ship with X-Plane 660. +The SDK will work with X-Plane 660 RC3 and later. The XPWidgets DLL now lives +in the Resources/plugins folder. + +Starting with beta 3, extra plugins, documentation, sample code, and sample +projects are now featured directly on the web in the new X-Plane SDK library. +They are not included in the SDK zip file; the zip file only contains headers +and lib files for the SDK. + +X-Plane SDK Beta 2 + +You must recompile your plugin for the beta 2 plugin SDK! Plugins compiled +against the beta 1 SDK will not work with X-Plane 660 or the new XPLM.DLL. + +A huge number of data refs have been added. Unfortunately the documentation +is thin. Use the data ref tester plugin to view the data refs in real time +and find what you need. + +The data ref APIs have also changed to allow for arrays of integers as well +as floats. Some sim variables are now arrays that were previously many +individual items. + +A new drawing phase is available for replacing aircraft graphics. The +texturing APIs in XPLMGraphics have been revised. The most notable change is +that you cannot use the SDK to load your textures. (This functionality was +broken and never worked in beta 1.) See the x-plane-dev list for sample code +on how to load your own bitmaps. + +X-Plane can reload plugins on the fly. Use the Plugin Enabler plugin to reload +your plugin. On the Mac you can throw the old DLL in the trash and put a new +one in its place to reload a new version of the plugin. On the PC, an alert +comes up; while this alert is up you can swap your plugins' DLL. This allows +you to recompile your plugin without rebooting the sim. + +Delphi Pascal interfaces and sample code are in the SDK. Thanks to Billy +Verreynne for his hard work on this. + diff --git a/GermanAirlinesVA-GAConnector/XPSDK/license.txt b/GermanAirlinesVA-GAConnector/XPSDK/license.txt new file mode 100644 index 0000000..8b9cbfc --- /dev/null +++ b/GermanAirlinesVA-GAConnector/XPSDK/license.txt @@ -0,0 +1,27 @@ +Copyright (c) 2008, Sandy Barbour and Ben Supnik +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Neither the names of the authors nor that of X-Plane or Laminar Research + may be used to endorse or promote products derived from this software + without specific prior written permission from the authors or + Laminar Research, respectively. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/GermanAirlinesVA-GAConnector/build.sh b/GermanAirlinesVA-GAConnector/build.sh new file mode 100755 index 0000000..eb68bfa --- /dev/null +++ b/GermanAirlinesVA-GAConnector/build.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +mkdir -p build +cd build +mkdir -p Plugin/WebSocketTest/32 +mkdir -p Plugin/WebSocketTest/64 +rm -f CMakeCache.txt + +case $1 in + "mac") + cmake -DDEBUG=$DEBUG -DCMAKE_TOOLCHAIN_FILE=../toolchain-mac.cmake .. + ;; + "lin32") + cmake -DDEBUG=$DEBUG -DBIT=32 -DCMAKE_TOOLCHAIN_FILE=../toolchain-lin.cmake .. + ;; + "lin64") + cmake -DDEBUG=$DEBUG -DBIT=64 -DCMAKE_TOOLCHAIN_FILE=../toolchain-lin.cmake .. + ;; + "win32") + cmake -DDEBUG=$DEBUG -DBIT=32 -DCMAKE_TOOLCHAIN_FILE=../toolchain-win-32.cmake .. + ;; + "win64") + cmake -DDEBUG=$DEBUG -DBIT=64 -DCMAKE_TOOLCHAIN_FILE=../toolchain-win-64.cmake .. + ;; +esac + +make -j +code=$? +if [ "$code" -ne 0 ] +then + exit $code +fi + +if [ "$1" = "mac" ] && [ "$DEBUG" = "1" ] +then + /opt/osxcross/target/bin/osxcross-llvm-dsymutil Plugin/WebSocketTest/mac.xpl +fi diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXBench.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXBench.cpp new file mode 100644 index 0000000..665f3fe --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXBench.cpp @@ -0,0 +1,56 @@ +/* + * IXBench.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved. + */ + +#include "IXBench.h" + +#include + +namespace ix +{ +Bench::Bench(const std::string &description) : _description(description) +{ + reset(); +} + +Bench::~Bench() +{ + if (!_reported) { + report(); + } +} + +void Bench::reset() +{ + _start = std::chrono::high_resolution_clock::now(); + _reported = false; +} + +void Bench::report() +{ + auto now = std::chrono::high_resolution_clock::now(); + auto microseconds = + std::chrono::duration_cast(now - _start); + + _duration = microseconds.count(); + std::cerr << _description << " completed in " << _duration << " us" + << std::endl; + + setReported(); +} + +void Bench::record() +{ + auto now = std::chrono::high_resolution_clock::now(); + auto microseconds = + std::chrono::duration_cast(now - _start); + + _duration = microseconds.count(); +} + +void Bench::setReported() { _reported = true; } + +uint64_t Bench::getDuration() const { return _duration; } +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXCancellationRequest.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXCancellationRequest.cpp new file mode 100644 index 0000000..ddc58e5 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXCancellationRequest.cpp @@ -0,0 +1,39 @@ +/* + * IXCancellationRequest.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXCancellationRequest.h" + +#include +#include + +namespace ix +{ +CancellationRequest makeCancellationRequestWithTimeout( + int secs, + std::atomic &requestInitCancellation) +{ + assert(secs > 0); + + auto start = std::chrono::system_clock::now(); + auto timeout = std::chrono::seconds(secs); + + auto isCancellationRequested = + [&requestInitCancellation, start, timeout]() -> bool { + // Was an explicit cancellation requested ? + if (requestInitCancellation) + return true; + + auto now = std::chrono::system_clock::now(); + if ((now - start) > timeout) + return true; + + // No cancellation request + return false; + }; + + return isCancellationRequested; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXConnectionState.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXConnectionState.cpp new file mode 100644 index 0000000..43eb9e1 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXConnectionState.cpp @@ -0,0 +1,54 @@ +/* + * IXConnectionState.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXConnectionState.h" + +namespace ix +{ +std::atomic ConnectionState::_globalId(0); + +ConnectionState::ConnectionState() : _terminated(false) { computeId(); } + +void ConnectionState::computeId() { _id = std::to_string(_globalId++); } + +const std::string &ConnectionState::getId() const { return _id; } + +std::shared_ptr ConnectionState::createConnectionState() +{ + return std::make_shared(); +} + +void ConnectionState::setOnSetTerminatedCallback( + const OnSetTerminatedCallback &callback) +{ + _onSetTerminatedCallback = callback; +} + +bool ConnectionState::isTerminated() const { return _terminated; } + +void ConnectionState::setTerminated() +{ + _terminated = true; + + if (_onSetTerminatedCallback) { + _onSetTerminatedCallback(); + } +} + +const std::string &ConnectionState::getRemoteIp() { return _remoteIp; } + +int ConnectionState::getRemotePort() { return _remotePort; } + +void ConnectionState::setRemoteIp(const std::string &remoteIp) +{ + _remoteIp = remoteIp; +} + +void ConnectionState::setRemotePort(int remotePort) +{ + _remotePort = remotePort; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXDNSLookup.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXDNSLookup.cpp new file mode 100644 index 0000000..db0b8d1 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXDNSLookup.cpp @@ -0,0 +1,190 @@ +/* + * IXDNSLookup.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +// +// On Windows Universal Platform (uwp), gai_strerror defaults behavior is to +// returns wchar_t which is different from all other platforms. We want the non +// unicode version. See https://github.com/microsoft/vcpkg/pull/11030 We could +// do this in IXNetSystem.cpp but so far we are only using gai_strerror in here. +// +#ifdef _UNICODE +#undef _UNICODE +#endif +#ifdef UNICODE +#undef UNICODE +#endif + +#include "IXDNSLookup.h" + +#include "IXNetSystem.h" +#include +#include +#include + +// mingw build quirks +#if defined(_WIN32) && defined(__GNUC__) +#define AI_NUMERICSERV NI_NUMERICSERV +#define AI_ADDRCONFIG LUP_ADDRCONFIG +#endif + +namespace ix +{ +const int64_t DNSLookup::kDefaultWait = 1; // ms + +DNSLookup::DNSLookup(const std::string &hostname, int port, int64_t wait) + : _hostname(hostname), _port(port), _wait(wait), _res(nullptr), _done(false) +{ + ; +} + +struct addrinfo *DNSLookup::getAddrInfo(const std::string &hostname, + int port, + std::string &errMsg) +{ + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + std::string sport = std::to_string(port); + + struct addrinfo *res; + int getaddrinfo_result = + getaddrinfo(hostname.c_str(), sport.c_str(), &hints, &res); + if (getaddrinfo_result) { + errMsg = gai_strerror(getaddrinfo_result); + res = nullptr; + } + return res; +} + +struct addrinfo * + DNSLookup::resolve(std::string &errMsg, + const CancellationRequest &isCancellationRequested, + bool cancellable) +{ + return cancellable ? resolveCancellable(errMsg, isCancellationRequested) + : resolveUnCancellable(errMsg, isCancellationRequested); +} + +void DNSLookup::release(struct addrinfo *addr) { freeaddrinfo(addr); } + +struct addrinfo *DNSLookup::resolveUnCancellable( + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + errMsg = "no error"; + + // Maybe a cancellation request got in before the background thread + // terminated ? + if (isCancellationRequested()) { + errMsg = "cancellation requested"; + return nullptr; + } + + return getAddrInfo(_hostname, _port, errMsg); +} + +struct addrinfo *DNSLookup::resolveCancellable( + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + errMsg = "no error"; + + // Can only be called once, otherwise we would have to manage a pool + // of background thread which is overkill for our usage. + if (_done) { + return nullptr; // programming error, create a second DNSLookup instance + // if you need a second lookup. + } + + // + // Good resource on thread forced termination + // https://www.bo-yang.net/2017/11/19/cpp-kill-detached-thread + // + auto ptr = shared_from_this(); + std::weak_ptr self(ptr); + + int port = _port; + std::string hostname(_hostname); + + // We make the background thread doing the work a shared pointer + // instead of a member variable, because it can keep running when + // this object goes out of scope, in case of cancellation + auto t = std::make_shared(&DNSLookup::run, + this, + self, + hostname, + port); + t->detach(); + + while (!_done) { + // Wait for 1 milliseconds, to see if the bg thread has terminated. + // We do not use a condition variable to wait, as destroying this one + // if the bg thread is alive can cause undefined behavior. + std::this_thread::sleep_for(std::chrono::milliseconds(_wait)); + + // Were we cancelled ? + if (isCancellationRequested()) { + errMsg = "cancellation requested"; + return nullptr; + } + } + + // Maybe a cancellation request got in before the bg terminated ? + if (isCancellationRequested()) { + errMsg = "cancellation requested"; + return nullptr; + } + + errMsg = getErrMsg(); + return getRes(); +} + +void DNSLookup::run(std::weak_ptr self, + std::string hostname, + int port) // thread runner +{ + // We don't want to read or write into members variables of an object that + // could be gone, so we use temporary variables (res) or we pass in by copy + // everything that getAddrInfo needs to work. + std::string errMsg; + struct addrinfo *res = getAddrInfo(hostname, port, errMsg); + + if (auto lock = self.lock()) { + // Copy result into the member variables + setRes(res); + setErrMsg(errMsg); + + _done = true; + } +} + +void DNSLookup::setErrMsg(const std::string &errMsg) +{ + std::lock_guard lock(_errMsgMutex); + _errMsg = errMsg; +} + +const std::string &DNSLookup::getErrMsg() +{ + std::lock_guard lock(_errMsgMutex); + return _errMsg; +} + +void DNSLookup::setRes(struct addrinfo *addr) +{ + std::lock_guard lock(_resMutex); + _res = addr; +} + +struct addrinfo *DNSLookup::getRes() +{ + std::lock_guard lock(_resMutex); + return _res; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXExponentialBackoff.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXExponentialBackoff.cpp new file mode 100644 index 0000000..9a40999 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXExponentialBackoff.cpp @@ -0,0 +1,30 @@ +/* + * IXExponentialBackoff.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXExponentialBackoff.h" + +#include + +namespace ix +{ +uint32_t + calculateRetryWaitMilliseconds(uint32_t retryCount, + uint32_t maxWaitBetweenReconnectionRetries, + uint32_t minWaitBetweenReconnectionRetries) +{ + uint32_t waitTime = (retryCount < 26) ? (std::pow(2, retryCount) * 100) : 0; + + if (waitTime < minWaitBetweenReconnectionRetries) { + waitTime = minWaitBetweenReconnectionRetries; + } + + if (waitTime > maxWaitBetweenReconnectionRetries || waitTime == 0) { + waitTime = maxWaitBetweenReconnectionRetries; + } + + return waitTime; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXGetFreePort.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXGetFreePort.cpp new file mode 100644 index 0000000..d5ac863 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXGetFreePort.cpp @@ -0,0 +1,95 @@ +/* + * IXGetFreePort.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone. All rights reserved. + */ + +// Using inet_addr will trigger an error on uwp without this +// FIXME: use a different api +#ifdef _WIN32 +#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#endif +#endif + +#include "IXGetFreePort.h" + +#include "IXNetSystem.h" +#include "IXSocket.h" +#include +#include + +namespace ix +{ +int getAnyFreePortRandom() +{ + std::random_device rd; + std::uniform_int_distribution dist(1024 + 1, 65535); + + return dist(rd); +} + +int getAnyFreePort() +{ + socket_t sockfd; + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return getAnyFreePortRandom(); + } + + int enable = 1; + if (setsockopt(sockfd, + SOL_SOCKET, + SO_REUSEADDR, + (char *)&enable, + sizeof(enable)) < 0) { + return getAnyFreePortRandom(); + } + + // Bind to port 0. This is the standard way to get a free port. + struct sockaddr_in server; // server address information + server.sin_family = AF_INET; + server.sin_port = htons(0); + server.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) { + Socket::closeSocket(sockfd); + return getAnyFreePortRandom(); + } + + struct sockaddr_in sa; // server address information + socklen_t len = sizeof(sa); + if (getsockname(sockfd, (struct sockaddr *)&sa, &len) < 0) { + Socket::closeSocket(sockfd); + return getAnyFreePortRandom(); + } + + int port = ntohs(sa.sin_port); + Socket::closeSocket(sockfd); + + return port; +} + +int getFreePort() +{ + while (true) { +#if defined(__has_feature) +#if __has_feature(address_sanitizer) + int port = getAnyFreePortRandom(); +#else + int port = getAnyFreePort(); +#endif +#else + int port = getAnyFreePort(); +#endif + // + // Only port above 1024 can be used by non root users, but for some + // reason I got port 7 returned with macOS when binding on port 0... + // + if (port > 1024) { + return port; + } + } + + return -1; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXGzipCodec.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXGzipCodec.cpp new file mode 100644 index 0000000..82251f5 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXGzipCodec.cpp @@ -0,0 +1,186 @@ +/* + * IXGzipCodec.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone, Inc. All rights reserved. + */ + +#include "IXGzipCodec.h" + +#include "IXBench.h" +#include +#include + +#ifdef IXWEBSOCKET_USE_ZLIB +#include +#endif + +#ifdef IXWEBSOCKET_USE_DEFLATE +#include +#endif + +namespace ix +{ +std::string gzipCompress(const std::string &str) +{ +#ifndef IXWEBSOCKET_USE_ZLIB + return std::string(); +#else +#ifdef IXWEBSOCKET_USE_DEFLATE + int compressionLevel = 6; + struct libdeflate_compressor *compressor; + + compressor = libdeflate_alloc_compressor(compressionLevel); + + const void *uncompressed_data = str.data(); + size_t uncompressed_size = str.size(); + void *compressed_data; + size_t actual_compressed_size; + size_t max_compressed_size; + + max_compressed_size = + libdeflate_gzip_compress_bound(compressor, uncompressed_size); + compressed_data = malloc(max_compressed_size); + + if (compressed_data == NULL) { + return std::string(); + } + + actual_compressed_size = libdeflate_gzip_compress(compressor, + uncompressed_data, + uncompressed_size, + compressed_data, + max_compressed_size); + + libdeflate_free_compressor(compressor); + + if (actual_compressed_size == 0) { + free(compressed_data); + return std::string(); + } + + std::string out; + out.assign(reinterpret_cast(compressed_data), + actual_compressed_size); + free(compressed_data); + + return out; +#else + z_stream zs; // z_stream is zlib's control structure + memset(&zs, 0, sizeof(zs)); + + // deflateInit2 configure the file format: request gzip instead of deflate + const int windowBits = 15; + const int GZIP_ENCODING = 16; + + deflateInit2(&zs, + Z_DEFAULT_COMPRESSION, + Z_DEFLATED, + windowBits | GZIP_ENCODING, + 8, + Z_DEFAULT_STRATEGY); + + zs.next_in = (Bytef *)str.data(); + zs.avail_in = (uInt)str.size(); // set the z_stream's input + + int ret; + char outbuffer[32768]; + std::string outstring; + + // retrieve the compressed bytes blockwise + do { + zs.next_out = reinterpret_cast(outbuffer); + zs.avail_out = sizeof(outbuffer); + + ret = deflate(&zs, Z_FINISH); + + if (outstring.size() < zs.total_out) { + // append the block to the output string + outstring.append(outbuffer, zs.total_out - outstring.size()); + } + } while (ret == Z_OK); + + deflateEnd(&zs); + + return outstring; +#endif // IXWEBSOCKET_USE_DEFLATE +#endif // IXWEBSOCKET_USE_ZLIB +} + +#ifdef IXWEBSOCKET_USE_DEFLATE +static uint32_t loadDecompressedGzipSize(const uint8_t *p) +{ + return ((uint32_t)p[0] << 0) | ((uint32_t)p[1] << 8) | + ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24); +} +#endif + +bool gzipDecompress(const std::string &in, std::string &out) +{ +#ifndef IXWEBSOCKET_USE_ZLIB + return false; +#else +#ifdef IXWEBSOCKET_USE_DEFLATE + struct libdeflate_decompressor *decompressor; + decompressor = libdeflate_alloc_decompressor(); + + const void *compressed_data = in.data(); + size_t compressed_size = in.size(); + + // Retrieve uncompressed size from the trailer of the gziped data + const uint8_t *ptr = reinterpret_cast(&in.front()); + auto uncompressed_size = + loadDecompressedGzipSize(&ptr[compressed_size - 4]); + + // Use it to redimension our output buffer + out.resize(uncompressed_size); + + libdeflate_result result = libdeflate_gzip_decompress(decompressor, + compressed_data, + compressed_size, + &out.front(), + uncompressed_size, + NULL); + + libdeflate_free_decompressor(decompressor); + return result == LIBDEFLATE_SUCCESS; +#else + z_stream inflateState; + memset(&inflateState, 0, sizeof(inflateState)); + + inflateState.zalloc = Z_NULL; + inflateState.zfree = Z_NULL; + inflateState.opaque = Z_NULL; + inflateState.avail_in = 0; + inflateState.next_in = Z_NULL; + + if (inflateInit2(&inflateState, 16 + MAX_WBITS) != Z_OK) { + return false; + } + + inflateState.avail_in = (uInt)in.size(); + inflateState.next_in = (unsigned char *)(const_cast(in.data())); + + const int kBufferSize = 1 << 14; + std::array compressBuffer; + + do { + inflateState.avail_out = (uInt)kBufferSize; + inflateState.next_out = &compressBuffer.front(); + + int ret = inflate(&inflateState, Z_SYNC_FLUSH); + + if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) { + inflateEnd(&inflateState); + return false; + } + + out.append(reinterpret_cast(&compressBuffer.front()), + kBufferSize - inflateState.avail_out); + } while (inflateState.avail_out == 0); + + inflateEnd(&inflateState); + return true; +#endif // IXWEBSOCKET_USE_DEFLATE +#endif // IXWEBSOCKET_USE_ZLIB +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttp.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttp.cpp new file mode 100644 index 0000000..ac87598 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttp.cpp @@ -0,0 +1,208 @@ +/* + * IXHttp.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXHttp.h" + +#include "IXCancellationRequest.h" +#include "IXGzipCodec.h" +#include "IXSocket.h" +#include +#include + +namespace ix +{ +std::string Http::trim(const std::string &str) +{ + std::string out; + for (auto c : str) { + if (c != ' ' && c != '\n' && c != '\r') { + out += c; + } + } + + return out; +} + +std::pair Http::parseStatusLine(const std::string &line) +{ + // Request-Line = Method SP Request-URI SP HTTP-Version CRLF + std::string token; + std::stringstream tokenStream(line); + std::vector tokens; + + // Split by ' ' + while (std::getline(tokenStream, token, ' ')) { + tokens.push_back(token); + } + + std::string httpVersion; + if (tokens.size() >= 1) { + httpVersion = trim(tokens[0]); + } + + int statusCode = -1; + if (tokens.size() >= 2) { + std::stringstream ss; + ss << trim(tokens[1]); + ss >> statusCode; + } + + return std::make_pair(httpVersion, statusCode); +} + +std::tuple + Http::parseRequestLine(const std::string &line) +{ + // Request-Line = Method SP Request-URI SP HTTP-Version CRLF + std::string token; + std::stringstream tokenStream(line); + std::vector tokens; + + // Split by ' ' + while (std::getline(tokenStream, token, ' ')) { + tokens.push_back(token); + } + + std::string method; + if (tokens.size() >= 1) { + method = trim(tokens[0]); + } + + std::string requestUri; + if (tokens.size() >= 2) { + requestUri = trim(tokens[1]); + } + + std::string httpVersion; + if (tokens.size() >= 3) { + httpVersion = trim(tokens[2]); + } + + return std::make_tuple(method, requestUri, httpVersion); +} + +std::tuple + Http::parseRequest(std::unique_ptr &socket, int timeoutSecs) +{ + HttpRequestPtr httpRequest; + + std::atomic requestInitCancellation(false); + + auto isCancellationRequested = + makeCancellationRequestWithTimeout(timeoutSecs, + requestInitCancellation); + + // Read first line + auto lineResult = socket->readLine(isCancellationRequested); + auto lineValid = lineResult.first; + auto line = lineResult.second; + + if (!lineValid) { + return std::make_tuple(false, + "Error reading HTTP request line", + httpRequest); + } + + // Parse request line (GET /foo HTTP/1.1\r\n) + auto requestLine = Http::parseRequestLine(line); + auto method = std::get<0>(requestLine); + auto uri = std::get<1>(requestLine); + auto httpVersion = std::get<2>(requestLine); + + // Retrieve and validate HTTP headers + auto result = parseHttpHeaders(socket, isCancellationRequested); + auto headersValid = result.first; + auto headers = result.second; + + if (!headersValid) { + return std::make_tuple(false, + "Error parsing HTTP headers", + httpRequest); + } + + std::string body; + if (headers.find("Content-Length") != headers.end()) { + int contentLength = 0; + try { + contentLength = std::stoi(headers["Content-Length"]); + } catch (const std::exception &) { + return std::make_tuple(false, + "Error parsing HTTP Header 'Content-Length'", + httpRequest); + } + + if (contentLength < 0) { + return std::make_tuple( + false, + "Error: 'Content-Length' should be a positive integer", + httpRequest); + } + + auto res = + socket->readBytes(contentLength, nullptr, isCancellationRequested); + if (!res.first) { + return std::make_tuple(false, + std::string("Error reading request: ") + + res.second, + httpRequest); + } + body = res.second; + } + + // If the content was compressed with gzip, decode it + if (headers["Content-Encoding"] == "gzip") { +#ifdef IXWEBSOCKET_USE_ZLIB + std::string decompressedPayload; + if (!gzipDecompress(body, decompressedPayload)) { + return std::make_tuple( + false, + std::string("Error during gzip decompression of the body"), + httpRequest); + } + body = decompressedPayload; +#else + std::string errorMsg( + "ixwebsocket was not compiled with gzip support on"); + return std::make_tuple(false, errorMsg, httpRequest); +#endif + } + + httpRequest = + std::make_shared(uri, method, httpVersion, body, headers); + return std::make_tuple(true, "", httpRequest); +} + +bool Http::sendResponse(HttpResponsePtr response, + std::unique_ptr &socket) +{ + // Write the response to the socket + std::stringstream ss; + ss << "HTTP/1.1 "; + ss << response->statusCode; + ss << " "; + ss << response->description; + ss << "\r\n"; + + if (!socket->writeBytes(ss.str(), nullptr)) { + return false; + } + + // Write headers + ss.str(""); + ss << "Content-Length: " << response->body.size() << "\r\n"; + for (auto &&it : response->headers) { + ss << it.first << ": " << it.second << "\r\n"; + } + ss << "\r\n"; + + if (!socket->writeBytes(ss.str(), nullptr)) { + return false; + } + + return response->body.empty() ? true + : socket->writeBytes(response->body, nullptr); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttpClient.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttpClient.cpp new file mode 100644 index 0000000..7deb3d7 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttpClient.cpp @@ -0,0 +1,724 @@ +/* + * IXHttpClient.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXHttpClient.h" + +#include "IXGzipCodec.h" +#include "IXSocketFactory.h" +#include "IXUrlParser.h" +#include "IXUserAgent.h" +#include "IXWebSocketHttpHeaders.h" +#include +#include +#include +#include +#include +#include + +namespace ix +{ +// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods +const std::string HttpClient::kPost = "POST"; +const std::string HttpClient::kGet = "GET"; +const std::string HttpClient::kHead = "HEAD"; +const std::string HttpClient::kDelete = "DELETE"; +const std::string HttpClient::kPut = "PUT"; +const std::string HttpClient::kPatch = "PATCH"; + +HttpClient::HttpClient(bool async) + : _async(async), _stop(false), _forceBody(false) +{ + if (!_async) + return; + + _thread = std::thread(&HttpClient::run, this); +} + +HttpClient::~HttpClient() +{ + if (!_thread.joinable()) + return; + + _stop = true; + _condition.notify_one(); + _thread.join(); +} + +void HttpClient::setTLSOptions(const SocketTLSOptions &tlsOptions) +{ + _tlsOptions = tlsOptions; +} + +void HttpClient::setForceBody(bool value) { _forceBody = value; } + +HttpRequestArgsPtr HttpClient::createRequest(const std::string &url, + const std::string &verb) +{ + auto request = std::make_shared(); + request->url = url; + request->verb = verb; + return request; +} + +bool HttpClient::performRequest(HttpRequestArgsPtr args, + const OnResponseCallback &onResponseCallback) +{ + assert(_async && "HttpClient needs its async parameter set to true " + "in order to call performRequest"); + if (!_async) + return false; + + // Enqueue the task + { + // acquire lock + std::unique_lock lock(_queueMutex); + + // add the task + _queue.push(std::make_pair(args, onResponseCallback)); + } // release lock + + // wake up one thread + _condition.notify_one(); + + return true; +} + +void HttpClient::run() +{ + while (true) { + HttpRequestArgsPtr args; + OnResponseCallback onResponseCallback; + + { + std::unique_lock lock(_queueMutex); + + while (!_stop && _queue.empty()) { + _condition.wait(lock); + } + + if (_stop) + return; + + auto p = _queue.front(); + _queue.pop(); + + args = p.first; + onResponseCallback = p.second; + } + + if (_stop) + return; + + HttpResponsePtr response = + request(args->url, args->verb, args->body, args); + onResponseCallback(response); + + if (_stop) + return; + } +} + +HttpResponsePtr HttpClient::request(const std::string &url, + const std::string &verb, + const std::string &body, + HttpRequestArgsPtr args, + int redirects) +{ + // We only have one socket connection, so we cannot + // make multiple requests concurrently. + std::lock_guard lock(_mutex); + + uint64_t uploadSize = 0; + uint64_t downloadSize = 0; + int code = 0; + WebSocketHttpHeaders headers; + std::string payload; + std::string description; + + std::string protocol, host, path, query; + int port; + + if (!UrlParser::parse(url, protocol, host, path, query, port)) { + std::stringstream ss; + ss << "Cannot parse url: " << url; + return std::make_shared(code, + description, + HttpErrorCode::UrlMalformed, + headers, + payload, + ss.str(), + uploadSize, + downloadSize); + } + + bool tls = protocol == "https"; + std::string errorMsg; + _socket = createSocket(tls, -1, errorMsg, _tlsOptions); + + if (!_socket) { + return std::make_shared(code, + description, + HttpErrorCode::CannotCreateSocket, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + // Build request string + std::stringstream ss; + ss << verb << " " << path << " HTTP/1.1\r\n"; + ss << "Host: " << host << "\r\n"; + +#ifdef IXWEBSOCKET_USE_ZLIB + if (args->compress) { + ss << "Accept-Encoding: gzip" + << "\r\n"; + } +#endif + + // Append extra headers + for (auto &&it : args->extraHeaders) { + ss << it.first << ": " << it.second << "\r\n"; + } + + // Set a default Accept header if none is present + if (args->extraHeaders.find("Accept") == args->extraHeaders.end()) { + ss << "Accept: */*" + << "\r\n"; + } + + // Set a default User agent if none is present + if (args->extraHeaders.find("User-Agent") == args->extraHeaders.end()) { + ss << "User-Agent: " << userAgent() << "\r\n"; + } + + if (verb == kPost || verb == kPut || verb == kPatch || _forceBody) { + // Set request compression header +#ifdef IXWEBSOCKET_USE_ZLIB + if (args->compressRequest) { + ss << "Content-Encoding: gzip" + << "\r\n"; + } +#endif + + ss << "Content-Length: " << body.size() << "\r\n"; + + // Set default Content-Type if unspecified + if (args->extraHeaders.find("Content-Type") == + args->extraHeaders.end()) { + if (args->multipartBoundary.empty()) { + ss << "Content-Type: application/x-www-form-urlencoded" + << "\r\n"; + } else { + ss << "Content-Type: multipart/form-data; boundary=" + << args->multipartBoundary << "\r\n"; + } + } + ss << "\r\n"; + ss << body; + } else { + ss << "\r\n"; + } + + std::string req(ss.str()); + std::string errMsg; + + // Make a cancellation object dealing with connection timeout + auto isCancellationRequested = + makeCancellationRequestWithTimeout(args->connectTimeout, _stop); + + bool success = + _socket->connect(host, port, errMsg, isCancellationRequested); + if (!success) { + std::stringstream ss; + ss << "Cannot connect to url: " << url << " / error : " << errMsg; + return std::make_shared(code, + description, + HttpErrorCode::CannotConnect, + headers, + payload, + ss.str(), + uploadSize, + downloadSize); + } + + // Make a new cancellation object dealing with transfer timeout + isCancellationRequested = + makeCancellationRequestWithTimeout(args->transferTimeout, _stop); + + if (args->verbose) { + std::stringstream ss; + ss << "Sending " << verb << " request " + << "to " << host << ":" << port << std::endl + << "request size: " << req.size() << " bytes" << std::endl + << "=============" << std::endl + << req << "=============" << std::endl + << std::endl; + + log(ss.str(), args); + } + + if (!_socket->writeBytes(req, isCancellationRequested)) { + std::string errorMsg("Cannot send request"); + return std::make_shared(code, + description, + HttpErrorCode::SendError, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + uploadSize = req.size(); + + auto lineResult = _socket->readLine(isCancellationRequested); + auto lineValid = lineResult.first; + auto line = lineResult.second; + + if (!lineValid) { + std::string errorMsg("Cannot retrieve status line"); + return std::make_shared( + code, + description, + HttpErrorCode::CannotReadStatusLine, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + if (args->verbose) { + std::stringstream ss; + ss << "Status line " << line; + log(ss.str(), args); + } + + if (sscanf(line.c_str(), "HTTP/1.1 %d", &code) != 1) { + std::string errorMsg("Cannot parse response code from status line"); + return std::make_shared(code, + description, + HttpErrorCode::MissingStatus, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + auto result = parseHttpHeaders(_socket, isCancellationRequested); + auto headersValid = result.first; + headers = result.second; + + if (!headersValid) { + std::string errorMsg("Cannot parse http headers"); + return std::make_shared(code, + description, + HttpErrorCode::HeaderParsingError, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + // Redirect ? + if ((code >= 301 && code <= 308) && args->followRedirects) { + if (headers.find("Location") == headers.end()) { + std::string errorMsg("Missing location header for redirect"); + return std::make_shared( + code, + description, + HttpErrorCode::MissingLocation, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + if (redirects >= args->maxRedirects) { + std::stringstream ss; + ss << "Too many redirects: " << redirects; + return std::make_shared( + code, + description, + HttpErrorCode::TooManyRedirects, + headers, + payload, + ss.str(), + uploadSize, + downloadSize); + } + + // Recurse + std::string location = headers["Location"]; + return request(location, verb, body, args, redirects + 1); + } + + if (verb == "HEAD") { + return std::make_shared(code, + description, + HttpErrorCode::Ok, + headers, + payload, + std::string(), + uploadSize, + downloadSize); + } + + // Parse response: + if (headers.find("Content-Length") != headers.end()) { + ssize_t contentLength = -1; + ss.str(""); + ss << headers["Content-Length"]; + ss >> contentLength; + + payload.reserve(contentLength); + + auto chunkResult = _socket->readBytes(contentLength, + args->onProgressCallback, + isCancellationRequested); + if (!chunkResult.first) { + errorMsg = "Cannot read chunk"; + return std::make_shared(code, + description, + HttpErrorCode::ChunkReadError, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + payload += chunkResult.second; + } else if (headers.find("Transfer-Encoding") != headers.end() && + headers["Transfer-Encoding"] == "chunked") { + std::stringstream ss; + + while (true) { + lineResult = _socket->readLine(isCancellationRequested); + line = lineResult.second; + + if (!lineResult.first) { + return std::make_shared( + code, + description, + HttpErrorCode::ChunkReadError, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + uint64_t chunkSize; + ss.str(""); + ss << std::hex << line; + ss >> chunkSize; + + if (args->verbose) { + std::stringstream oss; + oss << "Reading " << chunkSize << " bytes" << std::endl; + log(oss.str(), args); + } + + payload.reserve(payload.size() + (size_t)chunkSize); + + // Read a chunk + auto chunkResult = _socket->readBytes((size_t)chunkSize, + args->onProgressCallback, + isCancellationRequested); + if (!chunkResult.first) { + errorMsg = "Cannot read chunk"; + return std::make_shared( + code, + description, + HttpErrorCode::ChunkReadError, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + payload += chunkResult.second; + + // Read the line that terminates the chunk (\r\n) + lineResult = _socket->readLine(isCancellationRequested); + + if (!lineResult.first) { + return std::make_shared( + code, + description, + HttpErrorCode::ChunkReadError, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + if (chunkSize == 0) + break; + } + } else if (code == 204) { + ; // 204 is NoContent response code + } else { + std::string errorMsg("Cannot read http body"); + return std::make_shared(code, + description, + HttpErrorCode::CannotReadBody, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + + downloadSize = payload.size(); + + // If the content was compressed with gzip, decode it + if (headers["Content-Encoding"] == "gzip") { +#ifdef IXWEBSOCKET_USE_ZLIB + std::string decompressedPayload; + if (!gzipDecompress(payload, decompressedPayload)) { + std::string errorMsg("Error decompressing payload"); + return std::make_shared(code, + description, + HttpErrorCode::Gzip, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); + } + payload = decompressedPayload; +#else + std::string errorMsg( + "ixwebsocket was not compiled with gzip support on"); + return std::make_shared(code, + description, + HttpErrorCode::Gzip, + headers, + payload, + errorMsg, + uploadSize, + downloadSize); +#endif + } + + return std::make_shared(code, + description, + HttpErrorCode::Ok, + headers, + payload, + std::string(), + uploadSize, + downloadSize); +} + +HttpResponsePtr HttpClient::get(const std::string &url, HttpRequestArgsPtr args) +{ + return request(url, kGet, std::string(), args); +} + +HttpResponsePtr HttpClient::head(const std::string &url, + HttpRequestArgsPtr args) +{ + return request(url, kHead, std::string(), args); +} + +HttpResponsePtr HttpClient::Delete(const std::string &url, + HttpRequestArgsPtr args) +{ + return request(url, kDelete, std::string(), args); +} + +HttpResponsePtr + HttpClient::request(const std::string &url, + const std::string &verb, + const HttpParameters &httpParameters, + const HttpFormDataParameters &httpFormDataParameters, + HttpRequestArgsPtr args) +{ + std::string body; + + if (httpFormDataParameters.empty()) { + body = serializeHttpParameters(httpParameters); + } else { + std::string multipartBoundary = generateMultipartBoundary(); + args->multipartBoundary = multipartBoundary; + body = serializeHttpFormDataParameters(multipartBoundary, + httpFormDataParameters, + httpParameters); + } + +#ifdef IXWEBSOCKET_USE_ZLIB + if (args->compressRequest) { + body = gzipCompress(body); + } +#endif + + return request(url, verb, body, args); +} + +HttpResponsePtr + HttpClient::post(const std::string &url, + const HttpParameters &httpParameters, + const HttpFormDataParameters &httpFormDataParameters, + HttpRequestArgsPtr args) +{ + return request(url, kPost, httpParameters, httpFormDataParameters, args); +} + +HttpResponsePtr HttpClient::post(const std::string &url, + const std::string &body, + HttpRequestArgsPtr args) +{ + return request(url, kPost, body, args); +} + +HttpResponsePtr + HttpClient::put(const std::string &url, + const HttpParameters &httpParameters, + const HttpFormDataParameters &httpFormDataParameters, + HttpRequestArgsPtr args) +{ + return request(url, kPut, httpParameters, httpFormDataParameters, args); +} + +HttpResponsePtr HttpClient::put(const std::string &url, + const std::string &body, + const HttpRequestArgsPtr args) +{ + return request(url, kPut, body, args); +} + +HttpResponsePtr + HttpClient::patch(const std::string &url, + const HttpParameters &httpParameters, + const HttpFormDataParameters &httpFormDataParameters, + HttpRequestArgsPtr args) +{ + return request(url, kPatch, httpParameters, httpFormDataParameters, args); +} + +HttpResponsePtr HttpClient::patch(const std::string &url, + const std::string &body, + const HttpRequestArgsPtr args) +{ + return request(url, kPatch, body, args); +} + +std::string HttpClient::urlEncode(const std::string &value) +{ + std::ostringstream escaped; + escaped.fill('0'); + escaped << std::hex; + + for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; + ++i) { + std::string::value_type c = (*i); + + // Keep alphanumeric and other accepted characters intact + if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { + escaped << c; + continue; + } + + // Any other characters are percent-encoded + escaped << std::uppercase; + escaped << '%' << std::setw(2) << int((unsigned char)c); + escaped << std::nouppercase; + } + + return escaped.str(); +} + +std::string + HttpClient::serializeHttpParameters(const HttpParameters &httpParameters) +{ + std::stringstream ss; + size_t count = httpParameters.size(); + size_t i = 0; + + for (auto &&it : httpParameters) { + ss << urlEncode(it.first) << "=" << urlEncode(it.second); + + if (i++ < (count - 1)) { + ss << "&"; + } + } + return ss.str(); +} + +std::string HttpClient::serializeHttpFormDataParameters( + const std::string &multipartBoundary, + const HttpFormDataParameters &httpFormDataParameters, + const HttpParameters &httpParameters) +{ + // + // --AaB03x + // Content-Disposition: form-data; name="submit-name" + + // Larry + // --AaB03x + // Content-Disposition: form-data; name="foo.txt"; filename="file1.txt" + // Content-Type: text/plain + + // ... contents of file1.txt ... + // --AaB03x-- + // + std::stringstream ss; + + for (auto &&it : httpFormDataParameters) { + ss << "--" << multipartBoundary << "\r\n" + << "Content-Disposition:" + << " form-data; name=\"" << it.first << "\";" + << " filename=\"" << it.first << "\"" + << "\r\n" + << "Content-Type: application/octet-stream" + << "\r\n" + << "\r\n" + << it.second << "\r\n"; + } + + for (auto &&it : httpParameters) { + ss << "--" << multipartBoundary << "\r\n" + << "Content-Disposition:" + << " form-data; name=\"" << it.first << "\";" + << "\r\n" + << "\r\n" + << it.second << "\r\n"; + } + + ss << "--" << multipartBoundary << "--\r\n"; + + return ss.str(); +} + +void HttpClient::log(const std::string &msg, HttpRequestArgsPtr args) +{ + if (args->logger) { + args->logger(msg); + } +} + +std::string HttpClient::generateMultipartBoundary() +{ + std::string str( + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); + + static std::random_device rd; + static std::mt19937 generator(rd()); + + std::shuffle(str.begin(), str.end(), generator); + + return str; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttpServer.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttpServer.cpp new file mode 100644 index 0000000..743394c --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXHttpServer.cpp @@ -0,0 +1,239 @@ +/* + * IXHttpServer.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXHttpServer.h" + +#include "IXGzipCodec.h" +#include "IXNetSystem.h" +#include "IXSocketConnect.h" +#include "IXUserAgent.h" +#include +#include +#include +#include + +namespace +{ +std::pair> load(const std::string &path) +{ + std::vector memblock; + + std::ifstream file(path); + if (!file.is_open()) + return std::make_pair(false, memblock); + + file.seekg(0, file.end); + std::streamoff size = file.tellg(); + file.seekg(0, file.beg); + + memblock.resize((size_t)size); + file.read((char *)&memblock.front(), static_cast(size)); + + return std::make_pair(true, memblock); +} + +std::pair readAsString(const std::string &path) +{ + auto res = load(path); + auto vec = res.second; + return std::make_pair(res.first, std::string(vec.begin(), vec.end())); +} +} // namespace + +namespace ix +{ +const int HttpServer::kDefaultTimeoutSecs(30); + +HttpServer::HttpServer(int port, + const std::string &host, + int backlog, + size_t maxConnections, + int addressFamily, + int timeoutSecs) + : SocketServer(port, host, backlog, maxConnections, addressFamily), + _connectedClientsCount(0), _timeoutSecs(timeoutSecs) +{ + setDefaultConnectionCallback(); +} + +HttpServer::~HttpServer() { stop(); } + +void HttpServer::stop() +{ + stopAcceptingConnections(); + + // FIXME: cancelling / closing active clients ... + + SocketServer::stop(); +} + +void HttpServer::setOnConnectionCallback(const OnConnectionCallback &callback) +{ + _onConnectionCallback = callback; +} + +void HttpServer::handleConnection( + std::unique_ptr socket, + std::shared_ptr connectionState) +{ + _connectedClientsCount++; + + auto ret = Http::parseRequest(socket, _timeoutSecs); + // FIXME: handle errors in parseRequest + + if (std::get<0>(ret)) { + auto response = + _onConnectionCallback(std::get<2>(ret), connectionState); + if (!Http::sendResponse(response, socket)) { + logError("Cannot send response"); + } + } + connectionState->setTerminated(); + + _connectedClientsCount--; +} + +size_t HttpServer::getConnectedClientsCount() { return _connectedClientsCount; } + +void HttpServer::setDefaultConnectionCallback() +{ + setOnConnectionCallback( + [this](HttpRequestPtr request, + std::shared_ptr connectionState) + -> HttpResponsePtr { + std::string uri(request->uri); + if (uri.empty() || uri == "/") { + uri = "/index.html"; + } + + WebSocketHttpHeaders headers; + headers["Server"] = userAgent(); + + std::string path("." + uri); + auto res = readAsString(path); + bool found = res.first; + if (!found) { + return std::make_shared(404, + "Not Found", + HttpErrorCode::Ok, + WebSocketHttpHeaders(), + std::string()); + } + + std::string content = res.second; + +#ifdef IXWEBSOCKET_USE_ZLIB + std::string acceptEncoding = request->headers["Accept-encoding"]; + if (acceptEncoding == "*" || + acceptEncoding.find("gzip") != std::string::npos) { + content = gzipCompress(content); + headers["Content-Encoding"] = "gzip"; + } +#endif + + // Log request + std::stringstream ss; + ss << connectionState->getRemoteIp() << ":" + << connectionState->getRemotePort() << " " << request->method + << " " << request->headers["User-Agent"] << " " << request->uri + << " " << content.size(); + logInfo(ss.str()); + + // FIXME: check extensions to set the content type + // headers["Content-Type"] = "application/octet-stream"; + headers["Accept-Ranges"] = "none"; + + for (auto &&it : request->headers) { + headers[it.first] = it.second; + } + + return std::make_shared(200, + "OK", + HttpErrorCode::Ok, + headers, + content); + }); +} + +void HttpServer::makeRedirectServer(const std::string &redirectUrl) +{ + // + // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections + // + setOnConnectionCallback( + [this, redirectUrl](HttpRequestPtr request, + std::shared_ptr connectionState) + -> HttpResponsePtr { + WebSocketHttpHeaders headers; + headers["Server"] = userAgent(); + + // Log request + std::stringstream ss; + ss << connectionState->getRemoteIp() << ":" + << connectionState->getRemotePort() << " " << request->method + << " " << request->headers["User-Agent"] << " " << request->uri; + logInfo(ss.str()); + + if (request->method == "POST") { + return std::make_shared(200, + "OK", + HttpErrorCode::Ok, + headers, + std::string()); + } + + headers["Location"] = redirectUrl; + + return std::make_shared(301, + "OK", + HttpErrorCode::Ok, + headers, + std::string()); + }); +} + +// +// Display the client parameter and body on the console +// +void HttpServer::makeDebugServer() +{ + setOnConnectionCallback( + [this](HttpRequestPtr request, + std::shared_ptr connectionState) + -> HttpResponsePtr { + WebSocketHttpHeaders headers; + headers["Server"] = userAgent(); + + // Log request + std::stringstream ss; + ss << connectionState->getRemoteIp() << ":" + << connectionState->getRemotePort() << " " << request->method + << " " << request->headers["User-Agent"] << " " << request->uri; + logInfo(ss.str()); + + logInfo("== Headers == "); + for (auto &&it : request->headers) { + std::ostringstream oss; + oss << it.first << ": " << it.second; + logInfo(oss.str()); + } + logInfo(""); + + logInfo("== Body == "); + logInfo(request->body); + logInfo(""); + + return std::make_shared(200, + "OK", + HttpErrorCode::Ok, + headers, + std::string("OK")); + }); +} + +int HttpServer::getTimeoutSecs() { return _timeoutSecs; } + +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXNetSystem.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXNetSystem.cpp new file mode 100644 index 0000000..ea5b105 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXNetSystem.cpp @@ -0,0 +1,296 @@ +/* + * IXNetSystem.cpp + * Author: Korchynskyi Dmytro + * Copyright (c) 2019 Machine Zone. All rights reserved. + */ + +#include "IXNetSystem.h" +#include +#include + +namespace ix +{ +bool initNetSystem() +{ +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + int err; + + // Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h + wVersionRequested = MAKEWORD(2, 2); + err = WSAStartup(wVersionRequested, &wsaData); + + return err == 0; +#else + return true; +#endif +} + +bool uninitNetSystem() +{ +#ifdef _WIN32 + int err = WSACleanup(); + return err == 0; +#else + return true; +#endif +} + +// +// That function could 'return WSAPoll(pfd, nfds, timeout);' +// but WSAPoll is said to have weird behaviors on the internet +// (the curl folks have had problems with it). +// +// So we make it a select wrapper +// +int poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ +#ifdef _WIN32 + socket_t maxfd = 0; + fd_set readfds, writefds, errorfds; + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&errorfds); + + for (nfds_t i = 0; i < nfds; ++i) { + struct pollfd *fd = &fds[i]; + + if (fd->fd > maxfd) { + maxfd = fd->fd; + } + if ((fd->events & POLLIN)) { + FD_SET(fd->fd, &readfds); + } + if ((fd->events & POLLOUT)) { + FD_SET(fd->fd, &writefds); + } + if ((fd->events & POLLERR)) { + FD_SET(fd->fd, &errorfds); + } + } + + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + int ret = select(maxfd + 1, + &readfds, + &writefds, + &errorfds, + timeout != -1 ? &tv : NULL); + + if (ret < 0) { + return ret; + } + + for (nfds_t i = 0; i < nfds; ++i) { + struct pollfd *fd = &fds[i]; + fd->revents = 0; + + if (FD_ISSET(fd->fd, &readfds)) { + fd->revents |= POLLIN; + } + if (FD_ISSET(fd->fd, &writefds)) { + fd->revents |= POLLOUT; + } + if (FD_ISSET(fd->fd, &errorfds)) { + fd->revents |= POLLERR; + } + } + + return ret; +#else + // + // It was reported that on Android poll can fail and return -1 with + // errno == EINTR, which should be a temp error and should typically + // be handled by retrying in a loop. + // Maybe we need to put all syscall / C functions in + // a new IXSysCalls.cpp and wrap them all. + // + // The style from libuv is as such. + // + int ret = -1; + do { + ret = ::poll(fds, nfds, timeout); + } while (ret == -1 && errno == EINTR); + + return ret; +#endif +} + +// +// mingw does not have inet_ntop, which were taken as is from the musl C +// library. +// +const char *inet_ntop(int af, const void *a0, char *s, socklen_t l) +{ +#if defined(_WIN32) && defined(__GNUC__) + const unsigned char *a = (const unsigned char *)a0; + int i, j, max, best; + char buf[100]; + + switch (af) { + case AF_INET: + if (snprintf(s, l, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]) < l) + return s; + break; + case AF_INET6: + if (memcmp(a, "\0\0\0\0\0\0\0\0\0\0\377\377", 12)) + snprintf(buf, + sizeof buf, + "%x:%x:%x:%x:%x:%x:%x:%x", + 256 * a[0] + a[1], + 256 * a[2] + a[3], + 256 * a[4] + a[5], + 256 * a[6] + a[7], + 256 * a[8] + a[9], + 256 * a[10] + a[11], + 256 * a[12] + a[13], + 256 * a[14] + a[15]); + else + snprintf(buf, + sizeof buf, + "%x:%x:%x:%x:%x:%x:%d.%d.%d.%d", + 256 * a[0] + a[1], + 256 * a[2] + a[3], + 256 * a[4] + a[5], + 256 * a[6] + a[7], + 256 * a[8] + a[9], + 256 * a[10] + a[11], + a[12], + a[13], + a[14], + a[15]); + /* Replace longest /(^0|:)[:0]{2,}/ with "::" */ + for (i = best = 0, max = 2; buf[i]; i++) { + if (i && buf[i] != ':') + continue; + j = strspn(buf + i, ":0"); + if (j > max) + best = i, max = j; + } + if (max > 3) { + buf[best] = buf[best + 1] = ':'; + memmove(buf + best + 2, buf + best + max, i - best - max + 1); + } + if (strlen(buf) < l) { + strcpy(s, buf); + return s; + } + break; + default: + errno = EAFNOSUPPORT; + return 0; + } + errno = ENOSPC; + return 0; +#else + return ::inet_ntop(af, a0, s, l); +#endif +} + +#if defined(_WIN32) && defined(__GNUC__) +static int hexval(unsigned c) +{ + if (c - '0' < 10) + return c - '0'; + c |= 32; + if (c - 'a' < 6) + return c - 'a' + 10; + return -1; +} +#endif + +// +// mingw does not have inet_pton, which were taken as is from the musl C +// library. +// +int inet_pton(int af, const char *s, void *a0) +{ +#if defined(_WIN32) && defined(__GNUC__) + uint16_t ip[8]; + unsigned char *a = (unsigned char *)a0; + int i, j, v, d, brk = -1, need_v4 = 0; + + if (af == AF_INET) { + for (i = 0; i < 4; i++) { + for (v = j = 0; j < 3 && isdigit(s[j]); j++) + v = 10 * v + s[j] - '0'; + if (j == 0 || (j > 1 && s[0] == '0') || v > 255) + return 0; + a[i] = v; + if (s[j] == 0 && i == 3) + return 1; + if (s[j] != '.') + return 0; + s += j + 1; + } + return 0; + } else if (af != AF_INET6) { + errno = EAFNOSUPPORT; + return -1; + } + + if (*s == ':' && *++s != ':') + return 0; + + for (i = 0;; i++) { + if (s[0] == ':' && brk < 0) { + brk = i; + ip[i & 7] = 0; + if (!*++s) + break; + if (i == 7) + return 0; + continue; + } + for (v = j = 0; j < 4 && (d = hexval(s[j])) >= 0; j++) + v = 16 * v + d; + if (j == 0) + return 0; + ip[i & 7] = v; + if (!s[j] && (brk >= 0 || i == 7)) + break; + if (i == 7) + return 0; + if (s[j] != ':') { + if (s[j] != '.' || (i < 6 && brk < 0)) + return 0; + need_v4 = 1; + i++; + break; + } + s += j + 1; + } + if (brk >= 0) { + memmove(ip + brk + 7 - i, ip + brk, 2 * (i + 1 - brk)); + for (j = 0; j < 7 - i; j++) + ip[brk + j] = 0; + } + for (j = 0; j < 8; j++) { + *a++ = ip[j] >> 8; + *a++ = ip[j]; + } + if (need_v4 && inet_pton(AF_INET, (const char *)s, a - 4) <= 0) + return 0; + return 1; +#else + return ::inet_pton(af, s, a0); +#endif +} + +// Convert network bytes to host bytes. Copied from the ASIO library +unsigned short network_to_host_short(unsigned short value) +{ +#if defined(_WIN32) + unsigned char *value_p = reinterpret_cast(&value); + unsigned short result = (static_cast(value_p[0]) << 8) | + static_cast(value_p[1]); + return result; +#else // defined(_WIN32) + return ntohs(value); +#endif // defined(_WIN32) +} + +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterrupt.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterrupt.cpp new file mode 100644 index 0000000..f29a837 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterrupt.cpp @@ -0,0 +1,27 @@ +/* + * IXSelectInterrupt.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXSelectInterrupt.h" + +namespace ix +{ +const uint64_t SelectInterrupt::kSendRequest = 1; +const uint64_t SelectInterrupt::kCloseRequest = 2; + +SelectInterrupt::SelectInterrupt() { ; } + +SelectInterrupt::~SelectInterrupt() { ; } + +bool SelectInterrupt::init(std::string & /*errorMsg*/) { return true; } + +bool SelectInterrupt::notify(uint64_t /*value*/) { return true; } + +uint64_t SelectInterrupt::read() { return 0; } + +bool SelectInterrupt::clear() { return true; } + +int SelectInterrupt::getFd() const { return -1; } +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterruptFactory.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterruptFactory.cpp new file mode 100644 index 0000000..9ab6347 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterruptFactory.cpp @@ -0,0 +1,26 @@ +/* + * IXSelectInterruptFactory.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXSelectInterruptFactory.h" + +#include "IXUniquePtr.h" +#if defined(__linux__) || defined(__APPLE__) +#include "IXSelectInterruptPipe.h" +#else +#include "IXSelectInterrupt.h" +#endif + +namespace ix +{ +SelectInterruptPtr createSelectInterrupt() +{ +#if defined(__linux__) || defined(__APPLE__) + return ix::make_unique(); +#else + return ix::make_unique(); +#endif +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterruptPipe.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterruptPipe.cpp new file mode 100644 index 0000000..def317f --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSelectInterruptPipe.cpp @@ -0,0 +1,156 @@ +/* + * IXSelectInterruptPipe.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved. + */ + +// +// On UNIX we use pipes to wake up select. There is no way to do that +// on Windows so this file is compiled out on Windows. +// +#ifndef _WIN32 + +#include "IXSelectInterruptPipe.h" + +#include +#include +#include +#include +#include // for strerror +#include // for write + +namespace ix +{ +// File descriptor at index 0 in _fildes is the read end of the pipe +// File descriptor at index 1 in _fildes is the write end of the pipe +const int SelectInterruptPipe::kPipeReadIndex = 0; +const int SelectInterruptPipe::kPipeWriteIndex = 1; + +SelectInterruptPipe::SelectInterruptPipe() +{ + _fildes[kPipeReadIndex] = -1; + _fildes[kPipeWriteIndex] = -1; +} + +SelectInterruptPipe::~SelectInterruptPipe() +{ + ::close(_fildes[kPipeReadIndex]); + ::close(_fildes[kPipeWriteIndex]); + _fildes[kPipeReadIndex] = -1; + _fildes[kPipeWriteIndex] = -1; +} + +bool SelectInterruptPipe::init(std::string &errorMsg) +{ + std::lock_guard lock(_fildesMutex); + + // calling init twice is a programming error + assert(_fildes[kPipeReadIndex] == -1); + assert(_fildes[kPipeWriteIndex] == -1); + + if (pipe(_fildes) < 0) { + std::stringstream ss; + ss << "SelectInterruptPipe::init() failed in pipe() call" + << " : " << strerror(errno); + errorMsg = ss.str(); + return false; + } + + if (fcntl(_fildes[kPipeReadIndex], F_SETFL, O_NONBLOCK) == -1) { + std::stringstream ss; + ss << "SelectInterruptPipe::init() failed in fcntl(..., O_NONBLOCK) " + "call" + << " : " << strerror(errno); + errorMsg = ss.str(); + + _fildes[kPipeReadIndex] = -1; + _fildes[kPipeWriteIndex] = -1; + return false; + } + + if (fcntl(_fildes[kPipeWriteIndex], F_SETFL, O_NONBLOCK) == -1) { + std::stringstream ss; + ss << "SelectInterruptPipe::init() failed in fcntl(..., O_NONBLOCK) " + "call" + << " : " << strerror(errno); + errorMsg = ss.str(); + + _fildes[kPipeReadIndex] = -1; + _fildes[kPipeWriteIndex] = -1; + return false; + } + +#ifdef F_SETNOSIGPIPE + if (fcntl(_fildes[kPipeWriteIndex], F_SETNOSIGPIPE, 1) == -1) { + std::stringstream ss; + ss << "SelectInterruptPipe::init() failed in fcntl(.... " + "F_SETNOSIGPIPE) call" + << " : " << strerror(errno); + errorMsg = ss.str(); + + _fildes[kPipeReadIndex] = -1; + _fildes[kPipeWriteIndex] = -1; + return false; + } + + if (fcntl(_fildes[kPipeWriteIndex], F_SETNOSIGPIPE, 1) == -1) { + std::stringstream ss; + ss << "SelectInterruptPipe::init() failed in fcntl(..., " + "F_SETNOSIGPIPE) call" + << " : " << strerror(errno); + errorMsg = ss.str(); + + _fildes[kPipeReadIndex] = -1; + _fildes[kPipeWriteIndex] = -1; + return false; + } +#endif + + return true; +} + +bool SelectInterruptPipe::notify(uint64_t value) +{ + std::lock_guard lock(_fildesMutex); + + int fd = _fildes[kPipeWriteIndex]; + if (fd == -1) + return false; + + ssize_t ret = -1; + do { + ret = ::write(fd, &value, sizeof(value)); + } while (ret == -1 && errno == EINTR); + + // we should write 8 bytes for an uint64_t + return ret == 8; +} + +// TODO: return max uint64_t for errors ? +uint64_t SelectInterruptPipe::read() +{ + std::lock_guard lock(_fildesMutex); + + int fd = _fildes[kPipeReadIndex]; + + uint64_t value = 0; + + ssize_t ret = -1; + do { + ret = ::read(fd, &value, sizeof(value)); + } while (ret == -1 && errno == EINTR); + + return value; +} + +bool SelectInterruptPipe::clear() { return true; } + +int SelectInterruptPipe::getFd() const +{ + std::lock_guard lock(_fildesMutex); + + return _fildes[kPipeReadIndex]; +} +} // namespace ix + +#endif // !_WIN32 diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSetThreadName.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSetThreadName.cpp new file mode 100644 index 0000000..f4f83f8 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSetThreadName.cpp @@ -0,0 +1,81 @@ +/* + * IXSetThreadName.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 2020 Machine Zone, Inc. All rights reserved. + */ +#include "IXSetThreadName.h" + +// unix systems +#if defined(__APPLE__) || defined(__linux__) || defined(BSD) +#include +#endif + +// freebsd needs this header as well +#if defined(BSD) +#include +#endif + +// Windows +#ifdef _WIN32 +#include +#endif + +namespace ix +{ +#ifdef _WIN32 +const DWORD MS_VC_EXCEPTION = 0x406D1388; + +#pragma pack(push, 8) +typedef struct tagTHREADNAME_INFO { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. +} THREADNAME_INFO; +#pragma pack(pop) + +void SetThreadName(DWORD dwThreadID, const char *threadName) +{ +#ifndef __GNUC__ + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = threadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + __try { + RaiseException(MS_VC_EXCEPTION, + 0, + sizeof(info) / sizeof(ULONG_PTR), + (ULONG_PTR *)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { + } +#endif +} +#endif + +void setThreadName(const std::string &name) +{ +#if defined(__APPLE__) + // + // Apple reserves 16 bytes for its thread names + // Notice that the Apple version of pthread_setname_np + // does not take a pthread_t argument + // + pthread_setname_np(name.substr(0, 63).c_str()); +#elif defined(__linux__) + // + // Linux only reserves 16 bytes for its thread names + // See prctl and PR_SET_NAME property in + // http://man7.org/linux/man-pages/man2/prctl.2.html + // + pthread_setname_np(pthread_self(), name.substr(0, 15).c_str()); +#elif defined(_WIN32) + SetThreadName(-1, name.c_str()); +#elif defined(BSD) + pthread_set_name_np(pthread_self(), name.substr(0, 15).c_str()); +#else + // ... assert here ? +#endif +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocket.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocket.cpp new file mode 100644 index 0000000..1f00d96 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocket.cpp @@ -0,0 +1,373 @@ +/* + * IXSocket.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXSocket.h" + +#include "IXNetSystem.h" +#include "IXSelectInterrupt.h" +#include "IXSelectInterruptFactory.h" +#include "IXSocketConnect.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef min +#undef min +#endif + +namespace ix +{ +const int Socket::kDefaultPollNoTimeout = -1; // No poll timeout by default +const int Socket::kDefaultPollTimeout = kDefaultPollNoTimeout; + +Socket::Socket(int fd) : _sockfd(fd), _selectInterrupt(createSelectInterrupt()) +{ + ; +} + +Socket::~Socket() { close(); } + +PollResultType Socket::poll(bool readyToRead, + int timeoutMs, + int sockfd, + const SelectInterruptPtr &selectInterrupt) +{ + // + // We used to use ::select to poll but on Android 9 we get large fds out of + // ::connect which crash in FD_SET as they are larger than FD_SETSIZE. + // Switching to ::poll does fix that. + // + // However poll isn't as portable as select and has bugs on Windows, so we + // have a shim to fallback to select on those platforms. See + // https://github.com/mpv-player/mpv/pull/5203/files for such a select + // wrapper. + // + nfds_t nfds = 1; + struct pollfd fds[2]; + memset(fds, 0, sizeof(fds)); + + fds[0].fd = sockfd; + fds[0].events = (readyToRead) ? POLLIN : POLLOUT; + + // this is ignored by poll, but our select based poll wrapper on Windows + // needs it + fds[0].events |= POLLERR; + + // File descriptor used to interrupt select when needed + int interruptFd = -1; + if (selectInterrupt) { + interruptFd = selectInterrupt->getFd(); + + if (interruptFd != -1) { + nfds = 2; + fds[1].fd = interruptFd; + fds[1].events = POLLIN; + } + } + + int ret = ix::poll(fds, nfds, timeoutMs); + + PollResultType pollResult = PollResultType::ReadyForRead; + if (ret < 0) { + pollResult = PollResultType::Error; + } else if (ret == 0) { + pollResult = PollResultType::Timeout; + } else if (interruptFd != -1 && fds[1].revents & POLLIN) { + uint64_t value = selectInterrupt->read(); + + if (value == SelectInterrupt::kSendRequest) { + pollResult = PollResultType::SendRequest; + } else if (value == SelectInterrupt::kCloseRequest) { + pollResult = PollResultType::CloseRequest; + } + } else if (sockfd != -1 && readyToRead && fds[0].revents & POLLIN) { + pollResult = PollResultType::ReadyForRead; + } else if (sockfd != -1 && !readyToRead && fds[0].revents & POLLOUT) { + pollResult = PollResultType::ReadyForWrite; + +#ifdef _WIN32 + // On connect error, in async mode, windows will write to the exceptions + // fds + if (fds[0].revents & POLLERR) { + pollResult = PollResultType::Error; + } +#else + int optval = -1; + socklen_t optlen = sizeof(optval); + + // getsockopt() puts the errno value for connect into optval so 0 + // means no-error. + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1 || + optval != 0) { + pollResult = PollResultType::Error; + + // set errno to optval so that external callers can have an + // appropriate error description when calling strerror + errno = optval; + } +#endif + } else if (sockfd != -1 && + (fds[0].revents & POLLERR || fds[0].revents & POLLHUP || + fds[0].revents & POLLNVAL)) { + pollResult = PollResultType::Error; + } + + return pollResult; +} + +PollResultType Socket::isReadyToRead(int timeoutMs) +{ + if (_sockfd == -1) { + return PollResultType::Error; + } + + bool readyToRead = true; + return poll(readyToRead, timeoutMs, _sockfd, _selectInterrupt); +} + +PollResultType Socket::isReadyToWrite(int timeoutMs) +{ + if (_sockfd == -1) { + return PollResultType::Error; + } + + bool readyToRead = false; + return poll(readyToRead, timeoutMs, _sockfd, _selectInterrupt); +} + +// Wake up from poll/select by writing to the pipe which is watched by select +bool Socket::wakeUpFromPoll(uint64_t wakeUpCode) +{ + return _selectInterrupt->notify(wakeUpCode); +} + +bool Socket::accept(std::string &errMsg) +{ + if (_sockfd == -1) { + errMsg = "Socket is uninitialized"; + return false; + } + return true; +} + +bool Socket::connect(const std::string &host, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + std::lock_guard lock(_socketMutex); + + if (!_selectInterrupt->clear()) + return false; + + _sockfd = + SocketConnect::connect(host, port, errMsg, isCancellationRequested); + return _sockfd != -1; +} + +void Socket::close() +{ + std::lock_guard lock(_socketMutex); + + if (_sockfd == -1) + return; + + closeSocket(_sockfd); + _sockfd = -1; +} + +ssize_t Socket::send(char *buffer, size_t length) +{ + int flags = 0; +#ifdef MSG_NOSIGNAL + flags = MSG_NOSIGNAL; +#endif + + return ::send(_sockfd, buffer, length, flags); +} + +ssize_t Socket::send(const std::string &buffer) +{ + return send((char *)&buffer[0], buffer.size()); +} + +ssize_t Socket::recv(void *buffer, size_t length) +{ + int flags = 0; +#ifdef MSG_NOSIGNAL + flags = MSG_NOSIGNAL; +#endif + + return ::recv(_sockfd, (char *)buffer, length, flags); +} + +int Socket::getErrno() +{ + int err; + +#ifdef _WIN32 + err = WSAGetLastError(); +#else + err = errno; +#endif + + return err; +} + +bool Socket::isWaitNeeded() +{ + int err = getErrno(); + + if (err == EWOULDBLOCK || err == EAGAIN || err == EINPROGRESS) { + return true; + } + + return false; +} + +void Socket::closeSocket(int fd) +{ +#ifdef _WIN32 + closesocket(fd); +#else + ::close(fd); +#endif +} + +bool Socket::init(std::string &errorMsg) +{ + return _selectInterrupt->init(errorMsg); +} + +bool Socket::writeBytes(const std::string &str, + const CancellationRequest &isCancellationRequested) +{ + int offset = 0; + int len = (int)str.size(); + + while (true) { + if (isCancellationRequested && isCancellationRequested()) + return false; + + ssize_t ret = send((char *)&str[offset], len); + + // We wrote some bytes, as needed, all good. + if (ret > 0) { + if (ret == len) { + return true; + } else { + offset += ret; + len -= ret; + continue; + } + } + // There is possibly something to be writen, try again + else if (ret < 0 && Socket::isWaitNeeded()) { + continue; + } + // There was an error during the write, abort + else { + return false; + } + } +} + +bool Socket::readByte(void *buffer, + const CancellationRequest &isCancellationRequested) +{ + while (true) { + if (isCancellationRequested && isCancellationRequested()) + return false; + + ssize_t ret; + ret = recv(buffer, 1); + + // We read one byte, as needed, all good. + if (ret == 1) { + return true; + } + // There is possibly something to be read, try again + else if (ret < 0 && Socket::isWaitNeeded()) { + // Wait with a 1ms timeout until the socket is ready to read. + // This way we are not busy looping + if (isReadyToRead(1) == PollResultType::Error) { + return false; + } + } + // There was an error during the read, abort + else { + return false; + } + } +} + +std::pair + Socket::readLine(const CancellationRequest &isCancellationRequested) +{ + char c; + std::string line; + line.reserve(64); + + for (int i = 0; i < 2 || (line[i - 2] != '\r' && line[i - 1] != '\n'); + ++i) { + if (!readByte(&c, isCancellationRequested)) { + // Return what we were able to read + return std::make_pair(false, line); + } + + line += c; + } + + return std::make_pair(true, line); +} + +std::pair + Socket::readBytes(size_t length, + const OnProgressCallback &onProgressCallback, + const CancellationRequest &isCancellationRequested) +{ + std::array readBuffer; + + std::vector output; + while (output.size() != length) { + if (isCancellationRequested && isCancellationRequested()) { + const std::string errorMsg("Cancellation Requested"); + return std::make_pair(false, errorMsg); + } + + size_t size = std::min(readBuffer.size(), length - output.size()); + ssize_t ret = recv((char *)&readBuffer[0], size); + + if (ret > 0) { + output.insert(output.end(), + readBuffer.begin(), + readBuffer.begin() + ret); + } else if (ret <= 0 && !Socket::isWaitNeeded()) { + const std::string errorMsg("Recv Error"); + return std::make_pair(false, errorMsg); + } + + if (onProgressCallback) + onProgressCallback((int)output.size(), (int)length); + + // Wait with a 1ms timeout until the socket is ready to read. + // This way we are not busy looping + if (isReadyToRead(1) == PollResultType::Error) { + const std::string errorMsg("Poll Error"); + return std::make_pair(false, errorMsg); + } + } + + return std::make_pair(true, std::string(output.begin(), output.end())); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketAppleSSL.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketAppleSSL.cpp new file mode 100644 index 0000000..81e14a0 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketAppleSSL.cpp @@ -0,0 +1,307 @@ +/* + * IXSocketAppleSSL.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved. + * + * Adapted from Satori SDK Apple SSL code. + */ +#ifdef IXWEBSOCKET_USE_SECURE_TRANSPORT + +#include "IXSocketAppleSSL.h" + +#include "IXSocketConnect.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define socketerrno errno + +#include + +namespace ix +{ +SocketAppleSSL::SocketAppleSSL(const SocketTLSOptions &tlsOptions, int fd) + : Socket(fd), _sslContext(nullptr), _tlsOptions(tlsOptions) +{ + ; +} + +SocketAppleSSL::~SocketAppleSSL() { SocketAppleSSL::close(); } + +std::string SocketAppleSSL::getSSLErrorDescription(OSStatus status) +{ + std::string errMsg("Unknown SSL error."); + + CFErrorRef error = CFErrorCreate(kCFAllocatorDefault, + kCFErrorDomainOSStatus, + status, + NULL); + if (error) { + CFStringRef message = CFErrorCopyDescription(error); + if (message) { + char localBuffer[128]; + Boolean success; + success = CFStringGetCString(message, + localBuffer, + 128, + kCFStringEncodingUTF8); + if (success) { + errMsg = localBuffer; + } + CFRelease(message); + } + CFRelease(error); + } + + return errMsg; +} + +OSStatus SocketAppleSSL::readFromSocket(SSLConnectionRef connection, + void *data, + size_t *len) +{ + int fd = (int)(long)connection; + if (fd < 0) + return errSSLInternal; + + assert(data != nullptr); + assert(len != nullptr); + + size_t requested_sz = *len; + + ssize_t status = read(fd, data, requested_sz); + + if (status > 0) { + *len = (size_t)status; + if (requested_sz > *len) { + return errSSLWouldBlock; + } else { + return noErr; + } + } else if (status == 0) { + *len = 0; + return errSSLClosedGraceful; + } else { + *len = 0; + switch (errno) { + case ENOENT: + return errSSLClosedGraceful; + + case EAGAIN: + return errSSLWouldBlock; // EWOULDBLOCK is a define for EAGAIN + // on osx + case EINPROGRESS: + return errSSLWouldBlock; + + case ECONNRESET: + return errSSLClosedAbort; + + default: + return errSecIO; + } + } +} + +OSStatus SocketAppleSSL::writeToSocket(SSLConnectionRef connection, + const void *data, + size_t *len) +{ + int fd = (int)(long)connection; + if (fd < 0) + return errSSLInternal; + + assert(data != nullptr); + assert(len != nullptr); + + size_t to_write_sz = *len; + ssize_t status = write(fd, data, to_write_sz); + + if (status > 0) { + *len = (size_t)status; + if (to_write_sz > *len) { + return errSSLWouldBlock; + } else { + return noErr; + } + } else if (status == 0) { + *len = 0; + return errSSLClosedGraceful; + } else { + *len = 0; + switch (errno) { + case ENOENT: + return errSSLClosedGraceful; + + case EAGAIN: + return errSSLWouldBlock; // EWOULDBLOCK is a define for EAGAIN + // on osx + case EINPROGRESS: + return errSSLWouldBlock; + + case ECONNRESET: + return errSSLClosedAbort; + + default: + return errSecIO; + } + } +} + + +bool SocketAppleSSL::accept(std::string &errMsg) +{ + errMsg = "TLS not supported yet in server mode with apple ssl backend"; + return false; +} + +OSStatus SocketAppleSSL::tlsHandShake( + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + OSStatus status; + + do { + status = SSLHandshake(_sslContext); + + // Interrupt the handshake + if (isCancellationRequested()) { + errMsg = "Cancellation requested"; + return errSSLInternal; + } + } while (status == errSSLWouldBlock || status == errSSLServerAuthCompleted); + + return status; +} + +// No wait support +bool SocketAppleSSL::connect(const std::string &host, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + OSStatus status; + { + std::lock_guard lock(_mutex); + + _sockfd = + SocketConnect::connect(host, port, errMsg, isCancellationRequested); + if (_sockfd == -1) + return false; + + _sslContext = SSLCreateContext(kCFAllocatorDefault, + kSSLClientSide, + kSSLStreamType); + + SSLSetIOFuncs(_sslContext, + SocketAppleSSL::readFromSocket, + SocketAppleSSL::writeToSocket); + SSLSetConnection(_sslContext, (SSLConnectionRef)(long)_sockfd); + SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12); + SSLSetPeerDomainName(_sslContext, host.c_str(), host.size()); + + if (_tlsOptions.isPeerVerifyDisabled()) { + Boolean option(1); + SSLSetSessionOption(_sslContext, + kSSLSessionOptionBreakOnServerAuth, + option); + + status = tlsHandShake(errMsg, isCancellationRequested); + + if (status == errSSLServerAuthCompleted) { + // proceed with the handshake + status = tlsHandShake(errMsg, isCancellationRequested); + } + } else { + status = tlsHandShake(errMsg, isCancellationRequested); + } + } + + if (status != noErr) { + errMsg = getSSLErrorDescription(status); + close(); + return false; + } + + return true; +} + +void SocketAppleSSL::close() +{ + std::lock_guard lock(_mutex); + + if (_sslContext == nullptr) + return; + + SSLClose(_sslContext); + CFRelease(_sslContext); + _sslContext = nullptr; + + Socket::close(); +} + +ssize_t SocketAppleSSL::send(char *buf, size_t nbyte) +{ + OSStatus status = errSSLWouldBlock; + while (status == errSSLWouldBlock) { + size_t processed = 0; + std::lock_guard lock(_mutex); + status = SSLWrite(_sslContext, buf, nbyte, &processed); + + if (processed > 0) + return (ssize_t)processed; + + // The connection was reset, inform the caller that this + // Socket should close + if (status == errSSLClosedGraceful || status == errSSLClosedNoNotify || + status == errSSLClosedAbort) { + errno = ECONNRESET; + return -1; + } + + if (status == errSSLWouldBlock) { + errno = EWOULDBLOCK; + return -1; + } + } + return -1; +} + +// No wait support +ssize_t SocketAppleSSL::recv(void *buf, size_t nbyte) +{ + OSStatus status = errSSLWouldBlock; + while (status == errSSLWouldBlock) { + size_t processed = 0; + std::lock_guard lock(_mutex); + status = SSLRead(_sslContext, buf, nbyte, &processed); + + if (processed > 0) + return (ssize_t)processed; + + // The connection was reset, inform the caller that this + // Socket should close + if (status == errSSLClosedGraceful || status == errSSLClosedNoNotify || + status == errSSLClosedAbort) { + errno = ECONNRESET; + return -1; + } + + if (status == errSSLWouldBlock) { + errno = EWOULDBLOCK; + return -1; + } + } + return -1; +} + +} // namespace ix + +#endif // IXWEBSOCKET_USE_SECURE_TRANSPORT diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketConnect.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketConnect.cpp new file mode 100644 index 0000000..eb2d793 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketConnect.cpp @@ -0,0 +1,150 @@ +/* + * IXSocketConnect.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXSocketConnect.h" + +#include "IXDNSLookup.h" +#include "IXNetSystem.h" +#include "IXSelectInterrupt.h" +#include "IXSocket.h" +#include "IXUniquePtr.h" +#include +#include +#include + +// Android needs extra headers for TCP_NODELAY and IPPROTO_TCP +#ifdef ANDROID +#include +#include +#endif + +namespace ix +{ +// +// This function can be cancelled every 50 ms +// This is important so that we don't block the main UI thread when shutting +// down a connection which is already trying to reconnect, and can be blocked +// waiting for +// ::connect to respond. +// +int SocketConnect::connectToAddress( + const struct addrinfo *address, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + errMsg = "no error"; + + socket_t fd = + socket(address->ai_family, address->ai_socktype, address->ai_protocol); + if (fd < 0) { + errMsg = "Cannot create a socket"; + return -1; + } + + // Set the socket to non blocking mode, so that slow responses cannot + // block us for too long + SocketConnect::configure(fd); + + int res = ::connect(fd, address->ai_addr, address->ai_addrlen); + + if (res == -1 && !Socket::isWaitNeeded()) { + errMsg = strerror(Socket::getErrno()); + Socket::closeSocket(fd); + return -1; + } + + for (;;) { + if (isCancellationRequested && + isCancellationRequested()) // Must handle timeout as well + { + Socket::closeSocket(fd); + errMsg = "Cancelled"; + return -1; + } + + int timeoutMs = 10; + bool readyToRead = false; + auto selectInterrupt = ix::make_unique(); + PollResultType pollResult = + Socket::poll(readyToRead, timeoutMs, fd, selectInterrupt); + + if (pollResult == PollResultType::Timeout) { + continue; + } else if (pollResult == PollResultType::Error) { + Socket::closeSocket(fd); + errMsg = + std::string("Connect error: ") + strerror(Socket::getErrno()); + return -1; + } else if (pollResult == PollResultType::ReadyForWrite) { + return fd; + } else { + Socket::closeSocket(fd); + errMsg = + std::string("Connect error: ") + strerror(Socket::getErrno()); + return -1; + } + } + + Socket::closeSocket(fd); + errMsg = "connect timed out after 60 seconds"; + return -1; +} + +int SocketConnect::connect(const std::string &hostname, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + // + // First do DNS resolution + // + auto dnsLookup = std::make_shared(hostname, port); + struct addrinfo *res = dnsLookup->resolve(errMsg, isCancellationRequested); + if (res == nullptr) { + return -1; + } + + int sockfd = -1; + + // iterate through the records to find a working peer + struct addrinfo *address; + for (address = res; address != nullptr; address = address->ai_next) { + // + // Second try to connect to the remote host + // + sockfd = connectToAddress(address, errMsg, isCancellationRequested); + if (sockfd != -1) { + break; + } + } + + freeaddrinfo(res); + return sockfd; +} + +// FIXME: configure is a terrible name +void SocketConnect::configure(int sockfd) +{ + // 1. disable Nagle's algorithm + int flag = 1; + setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); + + // 2. make socket non blocking +#ifdef _WIN32 + unsigned long nonblocking = 1; + ioctlsocket(sockfd, FIONBIO, &nonblocking); +#else + fcntl(sockfd, F_SETFL, O_NONBLOCK); // make socket non blocking +#endif + + // 3. (apple) prevent SIGPIPE from being emitted when the remote end + // disconnect +#ifdef SO_NOSIGPIPE + int value = 1; + setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&value, sizeof(value)); +#endif +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketFactory.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketFactory.cpp new file mode 100644 index 0000000..0e8434b --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketFactory.cpp @@ -0,0 +1,60 @@ +/* + * IXSocketFactory.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXSocketFactory.h" + +#include "IXUniquePtr.h" +#ifdef IXWEBSOCKET_USE_TLS + +#ifdef IXWEBSOCKET_USE_MBED_TLS +#include "IXSocketMbedTLS.h" +#elif defined(IXWEBSOCKET_USE_OPEN_SSL) +#include "IXSocketOpenSSL.h" +#elif __APPLE__ +#include "IXSocketAppleSSL.h" +#endif + +#else + +#include "IXSocket.h" + +#endif + +namespace ix +{ +std::unique_ptr createSocket(bool tls, + int fd, + std::string &errorMsg, + const SocketTLSOptions &tlsOptions) +{ + (void)tlsOptions; + errorMsg.clear(); + std::unique_ptr socket; + + if (!tls) { + socket = ix::make_unique(fd); + } else { +#ifdef IXWEBSOCKET_USE_TLS +#if defined(IXWEBSOCKET_USE_MBED_TLS) + socket = ix::make_unique(tlsOptions, fd); +#elif defined(IXWEBSOCKET_USE_OPEN_SSL) + socket = ix::make_unique(tlsOptions, fd); +#elif defined(__APPLE__) + socket = ix::make_unique(tlsOptions, fd); +#endif +#else + errorMsg = "TLS support is not enabled on this platform."; + return nullptr; +#endif + } + + if (!socket->init(errorMsg)) { + socket.reset(); + } + + return socket; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketMbedTLS.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketMbedTLS.cpp new file mode 100644 index 0000000..93fa6af --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketMbedTLS.cpp @@ -0,0 +1,350 @@ +/* + * IXSocketMbedTLS.cpp + * Author: Benjamin Sergeant, Max Weisel + * Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved. + * + * Some code taken from + * https://github.com/rottor12/WsClientLib/blob/master/lib/src/WsClientLib.cpp + * and mini_client.c example from mbedtls + */ +#ifdef IXWEBSOCKET_USE_MBED_TLS + +#include "IXSocketMbedTLS.h" + +#include "IXNetSystem.h" +#include "IXSocket.h" +#include "IXSocketConnect.h" +#include + +#ifdef _WIN32 +// For manipulating the certificate store +#include +#endif + +namespace ix +{ +SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions &tlsOptions, int fd) + : Socket(fd), _tlsOptions(tlsOptions) +{ + initMBedTLS(); +} + +SocketMbedTLS::~SocketMbedTLS() { SocketMbedTLS::close(); } + +void SocketMbedTLS::initMBedTLS() +{ + std::lock_guard lock(_mutex); + + mbedtls_ssl_init(&_ssl); + mbedtls_ssl_config_init(&_conf); + mbedtls_ctr_drbg_init(&_ctr_drbg); + mbedtls_entropy_init(&_entropy); + mbedtls_x509_crt_init(&_cacert); + mbedtls_x509_crt_init(&_cert); + mbedtls_pk_init(&_pkey); +} + +bool SocketMbedTLS::loadSystemCertificates(std::string &errorMsg) +{ +#ifdef _WIN32 + DWORD flags = CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG | + CERT_SYSTEM_STORE_CURRENT_USER; + HCERTSTORE systemStore = + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, flags, L"Root"); + + if (!systemStore) { + errorMsg = "CertOpenStore failed with "; + errorMsg += std::to_string(GetLastError()); + return false; + } + + PCCERT_CONTEXT certificateIterator = NULL; + + int certificateCount = 0; + while (certificateIterator = + CertEnumCertificatesInStore(systemStore, certificateIterator)) { + if (certificateIterator->dwCertEncodingType & X509_ASN_ENCODING) { + int ret = + mbedtls_x509_crt_parse(&_cacert, + certificateIterator->pbCertEncoded, + certificateIterator->cbCertEncoded); + if (ret == 0) { + ++certificateCount; + } + } + } + + CertFreeCertificateContext(certificateIterator); + CertCloseStore(systemStore, 0); + + if (certificateCount == 0) { + errorMsg = "No certificates found"; + return false; + } + + return true; +#else + // On macOS we can query the system cert location from the keychain + // On Linux we could try to fetch some local files based on the distribution + // On Android we could use JNI to get to the system certs + return false; +#endif +} + +bool SocketMbedTLS::init(const std::string &host, + bool isClient, + std::string &errMsg) +{ + initMBedTLS(); + std::lock_guard lock(_mutex); + + const char *pers = "IXSocketMbedTLS"; + + if (mbedtls_ctr_drbg_seed(&_ctr_drbg, + mbedtls_entropy_func, + &_entropy, + (const unsigned char *)pers, + strlen(pers)) != 0) { + errMsg = "Setting entropy seed failed"; + return false; + } + + if (mbedtls_ssl_config_defaults(&_conf, + (isClient) ? MBEDTLS_SSL_IS_CLIENT + : MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT) != 0) { + errMsg = "Setting config default failed"; + return false; + } + + mbedtls_ssl_conf_rng(&_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); + + if (_tlsOptions.hasCertAndKey()) { + if (mbedtls_x509_crt_parse_file(&_cert, _tlsOptions.certFile.c_str()) < + 0) { + errMsg = "Cannot parse cert file '" + _tlsOptions.certFile + "'"; + return false; + } +#ifdef IXWEBSOCKET_USE_MBED_TLS_MIN_VERSION_3 + if (mbedtls_pk_parse_keyfile(&_pkey, + _tlsOptions.keyFile.c_str(), + "", + mbedtls_ctr_drbg_random, + &_ctr_drbg) < 0) +#else + if (mbedtls_pk_parse_keyfile(&_pkey, _tlsOptions.keyFile.c_str(), "") < + 0) +#endif + { + errMsg = "Cannot parse key file '" + _tlsOptions.keyFile + "'"; + return false; + } + if (mbedtls_ssl_conf_own_cert(&_conf, &_cert, &_pkey) < 0) { + errMsg = "Problem configuring cert '" + _tlsOptions.certFile + "'"; + return false; + } + } + + if (_tlsOptions.isPeerVerifyDisabled()) { + mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_NONE); + } else { + // FIXME: should we call mbedtls_ssl_conf_verify ? + mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_REQUIRED); + + if (_tlsOptions.isUsingSystemDefaults()) { + if (!loadSystemCertificates(errMsg)) { + return false; + } + } else { + if (_tlsOptions.isUsingInMemoryCAs()) { + const char *buffer = _tlsOptions.caFile.c_str(); + size_t bufferSize = _tlsOptions.caFile.size() + + 1; // Needs to include null terminating + // character otherwise mbedtls will fail. + if (mbedtls_x509_crt_parse(&_cacert, + (const unsigned char *)buffer, + bufferSize) < 0) { + errMsg = "Cannot parse CA from memory."; + return false; + } + } else if (mbedtls_x509_crt_parse_file(&_cacert, + _tlsOptions.caFile.c_str()) < + 0) { + errMsg = "Cannot parse CA file '" + _tlsOptions.caFile + "'"; + return false; + } + } + + mbedtls_ssl_conf_ca_chain(&_conf, &_cacert, NULL); + } + + if (mbedtls_ssl_setup(&_ssl, &_conf) != 0) { + errMsg = "SSL setup failed"; + return false; + } + + if (!host.empty() && mbedtls_ssl_set_hostname(&_ssl, host.c_str()) != 0) { + errMsg = "SNI setup failed"; + return false; + } + + return true; +} + +bool SocketMbedTLS::accept(std::string &errMsg) +{ + bool isClient = false; + bool initialized = init(std::string(), isClient, errMsg); + if (!initialized) { + close(); + return false; + } + + mbedtls_ssl_set_bio(&_ssl, + &_sockfd, + mbedtls_net_send, + mbedtls_net_recv, + NULL); + + int res; + do { + std::lock_guard lock(_mutex); + res = mbedtls_ssl_handshake(&_ssl); + } while (res == MBEDTLS_ERR_SSL_WANT_READ || + res == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (res != 0) { + char buf[256]; + mbedtls_strerror(res, buf, sizeof(buf)); + + errMsg = "error in handshake : "; + errMsg += buf; + + if (res == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { + char verifyBuf[512]; + uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl); + + mbedtls_x509_crt_verify_info(verifyBuf, + sizeof(verifyBuf), + " ! ", + flags); + errMsg += " : "; + errMsg += verifyBuf; + } + + close(); + return false; + } + + return true; +} + +bool SocketMbedTLS::connect(const std::string &host, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + { + std::lock_guard lock(_mutex); + _sockfd = + SocketConnect::connect(host, port, errMsg, isCancellationRequested); + if (_sockfd == -1) + return false; + } + + bool isClient = true; + bool initialized = init(host, isClient, errMsg); + if (!initialized) { + close(); + return false; + } + + mbedtls_ssl_set_bio(&_ssl, + &_sockfd, + mbedtls_net_send, + mbedtls_net_recv, + NULL); + + int res; + do { + { + std::lock_guard lock(_mutex); + res = mbedtls_ssl_handshake(&_ssl); + } + + if (isCancellationRequested()) { + errMsg = "Cancellation requested"; + close(); + return false; + } + } while (res == MBEDTLS_ERR_SSL_WANT_READ || + res == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (res != 0) { + char buf[256]; + mbedtls_strerror(res, buf, sizeof(buf)); + + errMsg = "error in handshake : "; + errMsg += buf; + + close(); + return false; + } + + return true; +} + +void SocketMbedTLS::close() +{ + std::lock_guard lock(_mutex); + + mbedtls_ssl_free(&_ssl); + mbedtls_ssl_config_free(&_conf); + mbedtls_ctr_drbg_free(&_ctr_drbg); + mbedtls_entropy_free(&_entropy); + mbedtls_x509_crt_free(&_cacert); + mbedtls_x509_crt_free(&_cert); + + Socket::close(); +} + +ssize_t SocketMbedTLS::send(char *buf, size_t nbyte) +{ + std::lock_guard lock(_mutex); + + ssize_t res = mbedtls_ssl_write(&_ssl, (unsigned char *)buf, nbyte); + + if (res > 0) { + return res; + } else if (res == MBEDTLS_ERR_SSL_WANT_READ || + res == MBEDTLS_ERR_SSL_WANT_WRITE) { + errno = EWOULDBLOCK; + return -1; + } else { + return -1; + } +} + +ssize_t SocketMbedTLS::recv(void *buf, size_t nbyte) +{ + while (true) { + std::lock_guard lock(_mutex); + + ssize_t res = mbedtls_ssl_read(&_ssl, (unsigned char *)buf, (int)nbyte); + + if (res > 0) { + return res; + } + + if (res == MBEDTLS_ERR_SSL_WANT_READ || + res == MBEDTLS_ERR_SSL_WANT_WRITE) { + errno = EWOULDBLOCK; + } + return -1; + } +} + +} // namespace ix + +#endif // IXWEBSOCKET_USE_MBED_TLS diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketOpenSSL.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketOpenSSL.cpp new file mode 100644 index 0000000..4c18538 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketOpenSSL.cpp @@ -0,0 +1,761 @@ +/* + * IXSocketOpenSSL.cpp + * Author: Benjamin Sergeant, Matt DeBoer, Max Weisel + * Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved. + * + * Adapted from Satori SDK OpenSSL code. + */ +#ifdef IXWEBSOCKET_USE_OPEN_SSL + +#include "IXSocketOpenSSL.h" + +#include "IXSocketConnect.h" +#include "IXUniquePtr.h" +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#include +#endif +#define socketerrno errno + +#ifdef _WIN32 +// For manipulating the certificate store +#include +#endif + +#ifdef _WIN32 +namespace +{ +bool loadWindowsSystemCertificates(SSL_CTX *ssl, std::string &errorMsg) +{ + DWORD flags = CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG | + CERT_SYSTEM_STORE_CURRENT_USER; + HCERTSTORE systemStore = + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, flags, L"Root"); + + if (!systemStore) { + errorMsg = "CertOpenStore failed with "; + errorMsg += std::to_string(GetLastError()); + return false; + } + + PCCERT_CONTEXT certificateIterator = NULL; + X509_STORE *opensslStore = SSL_CTX_get_cert_store(ssl); + + int certificateCount = 0; + while (certificateIterator = + CertEnumCertificatesInStore(systemStore, certificateIterator)) { + X509 *x509 = d2i_X509( + NULL, + (const unsigned char **)&certificateIterator->pbCertEncoded, + certificateIterator->cbCertEncoded); + + if (x509) { + if (X509_STORE_add_cert(opensslStore, x509) == 1) { + ++certificateCount; + } + + X509_free(x509); + } + } + + CertFreeCertificateContext(certificateIterator); + CertCloseStore(systemStore, 0); + + if (certificateCount == 0) { + errorMsg = "No certificates found"; + return false; + } + + return true; +} +} // namespace +#endif + +namespace ix +{ +const std::string kDefaultCiphers = + "ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 " + "ECDHE-ECDSA-AES128-SHA " + "ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES128-SHA256 " + "ECDHE-ECDSA-AES256-SHA384 " + "ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-GCM-SHA384 " + "ECDHE-RSA-AES128-SHA " + "ECDHE-RSA-AES256-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES256-SHA384 " + "DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES128-SHA " + "DHE-RSA-AES256-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES256-SHA256 AES128-SHA"; + +std::atomic SocketOpenSSL::_openSSLInitializationSuccessful(false); +std::once_flag SocketOpenSSL::_openSSLInitFlag; +std::vector> openSSLMutexes; + +SocketOpenSSL::SocketOpenSSL(const SocketTLSOptions &tlsOptions, int fd) + : Socket(fd), _ssl_connection(nullptr), _ssl_context(nullptr), + _tlsOptions(tlsOptions) +{ + std::call_once(_openSSLInitFlag, &SocketOpenSSL::openSSLInitialize, this); +} + +SocketOpenSSL::~SocketOpenSSL() { SocketOpenSSL::close(); } + +void SocketOpenSSL::openSSLInitialize() +{ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, nullptr)) + return; +#else + (void)OPENSSL_config(nullptr); + + if (CRYPTO_get_locking_callback() == nullptr) { + openSSLMutexes.clear(); + for (int i = 0; i < CRYPTO_num_locks(); ++i) { + openSSLMutexes.push_back(ix::make_unique()); + } + CRYPTO_set_locking_callback(SocketOpenSSL::openSSLLockingCallback); + } +#endif + + (void)OpenSSL_add_ssl_algorithms(); + (void)SSL_load_error_strings(); + + _openSSLInitializationSuccessful = true; +} + +void SocketOpenSSL::openSSLLockingCallback(int mode, + int type, + const char * /*file*/, + int /*line*/) +{ + if (mode & CRYPTO_LOCK) { + openSSLMutexes[type]->lock(); + } else { + openSSLMutexes[type]->unlock(); + } +} + +std::string SocketOpenSSL::getSSLError(int ret) +{ + unsigned long e; + + int err = SSL_get_error(_ssl_connection, ret); + + if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_ACCEPT) { + return "OpenSSL failed - connection failure"; + } else if (err == SSL_ERROR_WANT_X509_LOOKUP) { + return "OpenSSL failed - x509 error"; + } else if (err == SSL_ERROR_SYSCALL) { + e = ERR_get_error(); + if (e > 0) { + std::string errMsg("OpenSSL failed - "); + errMsg += ERR_error_string(e, nullptr); + return errMsg; + } else if (e == 0 && ret == 0) { + return "OpenSSL failed - received early EOF"; + } else { + return "OpenSSL failed - underlying BIO reported an I/O error"; + } + } else if (err == SSL_ERROR_SSL) { + e = ERR_get_error(); + std::string errMsg("OpenSSL failed - "); + errMsg += ERR_error_string(e, nullptr); + return errMsg; + } else if (err == SSL_ERROR_NONE) { + return "OpenSSL failed - err none"; + } else if (err == SSL_ERROR_ZERO_RETURN) { + return "OpenSSL failed - err zero return"; + } else { + return "OpenSSL failed - unknown error"; + } +} + +SSL_CTX *SocketOpenSSL::openSSLCreateContext(std::string &errMsg) +{ + const SSL_METHOD *method = SSLv23_client_method(); + if (method == nullptr) { + errMsg = "SSLv23_client_method failure"; + return nullptr; + } + _ssl_method = method; + + SSL_CTX *ctx = SSL_CTX_new(_ssl_method); + if (ctx) { + SSL_CTX_set_mode(ctx, + SSL_MODE_ENABLE_PARTIAL_WRITE | + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + + int options = + SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_CIPHER_SERVER_PREFERENCE; + +#ifdef SSL_OP_NO_TLSv1_3 + // (partially?) work around hang in openssl 1.1.1b, by disabling TLS + // V1.3 https://github.com/openssl/openssl/issues/7967 + options |= SSL_OP_NO_TLSv1_3; +#endif + SSL_CTX_set_options(ctx, options); + } + return ctx; +} + +bool SocketOpenSSL::openSSLAddCARootsFromString(const std::string roots) +{ + // Create certificate store + X509_STORE *certificate_store = SSL_CTX_get_cert_store(_ssl_context); + if (certificate_store == nullptr) + return false; + + // Configure to allow intermediate certs + X509_STORE_set_flags(certificate_store, + X509_V_FLAG_TRUSTED_FIRST | X509_V_FLAG_PARTIAL_CHAIN); + + // Create a new buffer and populate it with the roots + BIO *buffer = BIO_new_mem_buf((void *)roots.c_str(), + static_cast(roots.length())); + if (buffer == nullptr) + return false; + + // Read each root in the buffer and add to the certificate store + bool success = true; + size_t number_of_roots = 0; + + while (true) { + // Read the next root in the buffer + X509 *root = + PEM_read_bio_X509_AUX(buffer, nullptr, nullptr, (void *)""); + if (root == nullptr) { + // No more certs left in the buffer, we're done. + ERR_clear_error(); + break; + } + + // Try adding the root to the certificate store + ERR_clear_error(); + if (!X509_STORE_add_cert(certificate_store, root)) { + // Failed to add. If the error is unrelated to the x509 lib or the + // cert already exists, we're safe to continue. + unsigned long error = ERR_get_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { + // Failed. Clean up and bail. + success = false; + X509_free(root); + break; + } + } + + // Clean up and loop + X509_free(root); + number_of_roots++; + } + + // Clean up buffer + BIO_free(buffer); + + // Make sure we loaded at least one certificate. + if (number_of_roots == 0) + success = false; + + return success; +} + +/** + * Check whether a hostname matches a pattern + */ +bool SocketOpenSSL::checkHost(const std::string &host, const char *pattern) +{ +#ifdef _WIN32 + return PathMatchSpecA(host.c_str(), pattern); +#else + return fnmatch(pattern, host.c_str(), 0) != FNM_NOMATCH; +#endif +} + +bool SocketOpenSSL::openSSLCheckServerCert(SSL *ssl, + const std::string &hostname, + std::string &errMsg) +{ + X509 *server_cert = SSL_get_peer_certificate(ssl); + if (server_cert == nullptr) { + errMsg = "OpenSSL failed - peer didn't present a X509 certificate."; + return false; + } + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + // Check server name + bool hostname_verifies_ok = false; + STACK_OF(GENERAL_NAME) *san_names = (STACK_OF(GENERAL_NAME) *) + X509_get_ext_d2i((X509 *)server_cert, NID_subject_alt_name, NULL, NULL); + if (san_names) { + for (int i = 0; i < sk_GENERAL_NAME_num(san_names); i++) { + const GENERAL_NAME *sk_name = sk_GENERAL_NAME_value(san_names, i); + if (sk_name->type == GEN_DNS) { + char *name = (char *)ASN1_STRING_data(sk_name->d.dNSName); + if ((size_t)ASN1_STRING_length(sk_name->d.dNSName) == + strlen(name) && + checkHost(hostname, name)) { + hostname_verifies_ok = true; + break; + } + } + } + } + sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free); + + if (!hostname_verifies_ok) { + int cn_pos = X509_NAME_get_index_by_NID( + X509_get_subject_name((X509 *)server_cert), + NID_commonName, + -1); + if (cn_pos) { + X509_NAME_ENTRY *cn_entry = + X509_NAME_get_entry(X509_get_subject_name((X509 *)server_cert), + cn_pos); + + if (cn_entry) { + ASN1_STRING *cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry); + char *cn = (char *)ASN1_STRING_data(cn_asn1); + + if ((size_t)ASN1_STRING_length(cn_asn1) == strlen(cn) && + checkHost(hostname, cn)) { + hostname_verifies_ok = true; + } + } + } + } + + if (!hostname_verifies_ok) { + errMsg = + "OpenSSL failed - certificate was issued for a different domain."; + return false; + } +#endif + + X509_free(server_cert); + return true; +} + +bool SocketOpenSSL::openSSLClientHandshake( + const std::string &host, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + while (true) { + if (_ssl_connection == nullptr || _ssl_context == nullptr) { + return false; + } + + if (isCancellationRequested()) { + errMsg = "Cancellation requested"; + return false; + } + + ERR_clear_error(); + int connect_result = SSL_connect(_ssl_connection); + if (connect_result == 1) { + return openSSLCheckServerCert(_ssl_connection, host, errMsg); + } + int reason = SSL_get_error(_ssl_connection, connect_result); + + bool rc = false; + if (reason == SSL_ERROR_WANT_READ || reason == SSL_ERROR_WANT_WRITE) { + rc = true; + } else { + errMsg = getSSLError(connect_result); + rc = false; + } + + if (!rc) { + return false; + } + } +} + +bool SocketOpenSSL::openSSLServerHandshake(std::string &errMsg) +{ + while (true) { + if (_ssl_connection == nullptr || _ssl_context == nullptr) { + return false; + } + + ERR_clear_error(); + int accept_result = SSL_accept(_ssl_connection); + if (accept_result == 1) { + return true; + } + int reason = SSL_get_error(_ssl_connection, accept_result); + + bool rc = false; + if (reason == SSL_ERROR_WANT_READ || reason == SSL_ERROR_WANT_WRITE) { + rc = true; + } else { + errMsg = getSSLError(accept_result); + rc = false; + } + + if (!rc) { + return false; + } + } +} + +bool SocketOpenSSL::handleTLSOptions(std::string &errMsg) +{ + ERR_clear_error(); + if (_tlsOptions.hasCertAndKey()) { + if (SSL_CTX_use_certificate_chain_file(_ssl_context, + _tlsOptions.certFile.c_str()) != + 1) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - SSL_CTX_use_certificate_chain_file(\"" + + _tlsOptions.certFile + "\") failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + } else if (SSL_CTX_use_PrivateKey_file(_ssl_context, + _tlsOptions.keyFile.c_str(), + SSL_FILETYPE_PEM) != 1) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - SSL_CTX_use_PrivateKey_file(\"" + + _tlsOptions.keyFile + "\") failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + } else if (!SSL_CTX_check_private_key(_ssl_context)) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - cert/key mismatch(\"" + + _tlsOptions.certFile + ", " + _tlsOptions.keyFile + "\")"; + errMsg += ERR_error_string(sslErr, nullptr); + } + } + + ERR_clear_error(); + if (!_tlsOptions.isPeerVerifyDisabled()) { + if (_tlsOptions.isUsingSystemDefaults()) { +#ifdef _WIN32 + if (!loadWindowsSystemCertificates(_ssl_context, errMsg)) { + return false; + } +#else + if (SSL_CTX_set_default_verify_paths(_ssl_context) == 0) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - SSL_CTX_default_verify_paths " + "loading failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + return false; + } +#endif + } else { + if (_tlsOptions.isUsingInMemoryCAs()) { + // Load from memory + openSSLAddCARootsFromString(_tlsOptions.caFile); + } else { + if (SSL_CTX_load_verify_locations(_ssl_context, + _tlsOptions.caFile.c_str(), + NULL) != 1) { + auto sslErr = ERR_get_error(); + errMsg = + "OpenSSL failed - SSL_CTX_load_verify_locations(\"" + + _tlsOptions.caFile + "\") failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + return false; + } + } + } + + SSL_CTX_set_verify( + _ssl_context, + SSL_VERIFY_PEER, + [](int preverify, X509_STORE_CTX *) -> int { return preverify; }); + SSL_CTX_set_verify_depth(_ssl_context, 4); + } else { + SSL_CTX_set_verify(_ssl_context, SSL_VERIFY_NONE, nullptr); + } + + if (_tlsOptions.isUsingDefaultCiphers()) { + if (SSL_CTX_set_cipher_list(_ssl_context, kDefaultCiphers.c_str()) != + 1) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - SSL_CTX_set_cipher_list(\"" + + kDefaultCiphers + "\") failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + return false; + } + } else if (SSL_CTX_set_cipher_list(_ssl_context, + _tlsOptions.ciphers.c_str()) != 1) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - SSL_CTX_set_cipher_list(\"" + + _tlsOptions.ciphers + "\") failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + return false; + } + + return true; +} + +bool SocketOpenSSL::accept(std::string &errMsg) +{ + bool handshakeSuccessful = false; + { + std::lock_guard lock(_mutex); + + if (!_openSSLInitializationSuccessful) { + errMsg = "OPENSSL_init_ssl failure"; + return false; + } + + if (_sockfd == -1) { + return false; + } + + { + const SSL_METHOD *method = SSLv23_server_method(); + if (method == nullptr) { + errMsg = "SSLv23_server_method failure"; + _ssl_context = nullptr; + } else { + _ssl_method = method; + + _ssl_context = SSL_CTX_new(_ssl_method); + if (_ssl_context) { + SSL_CTX_set_mode(_ssl_context, + SSL_MODE_ENABLE_PARTIAL_WRITE); + SSL_CTX_set_mode(_ssl_context, + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + SSL_CTX_set_options(_ssl_context, + SSL_OP_ALL | SSL_OP_NO_SSLv2 | + SSL_OP_NO_SSLv3); + } + } + } + + if (_ssl_context == nullptr) { + return false; + } + + ERR_clear_error(); + if (_tlsOptions.hasCertAndKey()) { + if (SSL_CTX_use_certificate_chain_file( + _ssl_context, + _tlsOptions.certFile.c_str()) != 1) { + auto sslErr = ERR_get_error(); + errMsg = + "OpenSSL failed - SSL_CTX_use_certificate_chain_file(\"" + + _tlsOptions.certFile + "\") failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + } else if (SSL_CTX_use_PrivateKey_file(_ssl_context, + _tlsOptions.keyFile.c_str(), + SSL_FILETYPE_PEM) != 1) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - SSL_CTX_use_PrivateKey_file(\"" + + _tlsOptions.keyFile + "\") failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + } + } + + + ERR_clear_error(); + if (!_tlsOptions.isPeerVerifyDisabled()) { + if (_tlsOptions.isUsingSystemDefaults()) { + if (SSL_CTX_set_default_verify_paths(_ssl_context) == 0) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - SSL_CTX_default_verify_paths " + "loading failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + } + } else { + if (_tlsOptions.isUsingInMemoryCAs()) { + // Load from memory + openSSLAddCARootsFromString(_tlsOptions.caFile); + } else { + const char *root_ca_file = _tlsOptions.caFile.c_str(); + STACK_OF(X509_NAME) * rootCAs; + rootCAs = SSL_load_client_CA_file(root_ca_file); + if (rootCAs == NULL) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - SSL_load_client_CA_file('" + + _tlsOptions.caFile + "') failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + } else { + SSL_CTX_set_client_CA_list(_ssl_context, rootCAs); + if (SSL_CTX_load_verify_locations(_ssl_context, + root_ca_file, + nullptr) != 1) { + auto sslErr = ERR_get_error(); + errMsg = "OpenSSL failed - " + "SSL_CTX_load_verify_locations(\"" + + _tlsOptions.caFile + "\") failed: "; + errMsg += ERR_error_string(sslErr, nullptr); + } + } + } + } + + SSL_CTX_set_verify(_ssl_context, + SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + nullptr); + SSL_CTX_set_verify_depth(_ssl_context, 4); + } else { + SSL_CTX_set_verify(_ssl_context, SSL_VERIFY_NONE, nullptr); + } + if (_tlsOptions.isUsingDefaultCiphers()) { + if (SSL_CTX_set_cipher_list(_ssl_context, + kDefaultCiphers.c_str()) != 1) { + return false; + } + } else if (SSL_CTX_set_cipher_list(_ssl_context, + _tlsOptions.ciphers.c_str()) != 1) { + return false; + } + + _ssl_connection = SSL_new(_ssl_context); + if (_ssl_connection == nullptr) { + errMsg = "OpenSSL failed to connect"; + SSL_CTX_free(_ssl_context); + _ssl_context = nullptr; + return false; + } + + SSL_set_ecdh_auto(_ssl_connection, 1); + + SSL_set_fd(_ssl_connection, _sockfd); + + handshakeSuccessful = openSSLServerHandshake(errMsg); + } + + if (!handshakeSuccessful) { + close(); + return false; + } + + return true; +} + +bool SocketOpenSSL::connect(const std::string &host, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) +{ + bool handshakeSuccessful = false; + { + std::lock_guard lock(_mutex); + + if (!_openSSLInitializationSuccessful) { + errMsg = "OPENSSL_init_ssl failure"; + return false; + } + + _sockfd = + SocketConnect::connect(host, port, errMsg, isCancellationRequested); + if (_sockfd == -1) + return false; + + _ssl_context = openSSLCreateContext(errMsg); + if (_ssl_context == nullptr) { + return false; + } + + if (!handleTLSOptions(errMsg)) { + return false; + } + + _ssl_connection = SSL_new(_ssl_context); + if (_ssl_connection == nullptr) { + errMsg = "OpenSSL failed to connect"; + SSL_CTX_free(_ssl_context); + _ssl_context = nullptr; + return false; + } + SSL_set_fd(_ssl_connection, _sockfd); + + // SNI support + SSL_set_tlsext_host_name(_ssl_connection, host.c_str()); + +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + // Support for server name verification + // (The docs say that this should work from 1.0.2, and is the default + // from 1.1.0, but it does not. To be on the safe side, the manual test + // below is enabled for all versions prior to 1.1.0.) + X509_VERIFY_PARAM *param = SSL_get0_param(_ssl_connection); + X509_VERIFY_PARAM_set1_host(param, host.c_str(), 0); +#endif + handshakeSuccessful = + openSSLClientHandshake(host, errMsg, isCancellationRequested); + } + + if (!handshakeSuccessful) { + close(); + return false; + } + + return true; +} + +void SocketOpenSSL::close() +{ + std::lock_guard lock(_mutex); + + if (_ssl_connection != nullptr) { + SSL_free(_ssl_connection); + _ssl_connection = nullptr; + } + if (_ssl_context != nullptr) { + SSL_CTX_free(_ssl_context); + _ssl_context = nullptr; + } + + Socket::close(); +} + +ssize_t SocketOpenSSL::send(char *buf, size_t nbyte) +{ + std::lock_guard lock(_mutex); + + if (_ssl_connection == nullptr || _ssl_context == nullptr) { + return 0; + } + + ERR_clear_error(); + ssize_t write_result = SSL_write(_ssl_connection, buf, (int)nbyte); + int reason = SSL_get_error(_ssl_connection, (int)write_result); + + if (reason == SSL_ERROR_NONE) { + return write_result; + } else if (reason == SSL_ERROR_WANT_READ || + reason == SSL_ERROR_WANT_WRITE) { + errno = EWOULDBLOCK; + return -1; + } else { + return -1; + } +} + +ssize_t SocketOpenSSL::recv(void *buf, size_t nbyte) +{ + while (true) { + std::lock_guard lock(_mutex); + + if (_ssl_connection == nullptr || _ssl_context == nullptr) { + return 0; + } + + ERR_clear_error(); + ssize_t read_result = SSL_read(_ssl_connection, buf, (int)nbyte); + + if (read_result > 0) { + return read_result; + } + + int reason = SSL_get_error(_ssl_connection, (int)read_result); + + if (reason == SSL_ERROR_WANT_READ || reason == SSL_ERROR_WANT_WRITE) { + errno = EWOULDBLOCK; + } + return -1; + } +} + +} // namespace ix + +#endif // IXWEBSOCKET_USE_OPEN_SSL diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketServer.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketServer.cpp new file mode 100644 index 0000000..968b48a --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketServer.cpp @@ -0,0 +1,467 @@ +/* + * IXSocketServer.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXSocketServer.h" + +#include "IXNetSystem.h" +#include "IXSelectInterrupt.h" +#include "IXSelectInterruptFactory.h" +#include "IXSetThreadName.h" +#include "IXSocket.h" +#include "IXSocketConnect.h" +#include "IXSocketFactory.h" +#include +#include +#include +#include + +namespace ix +{ +const int SocketServer::kDefaultPort(8080); +const std::string SocketServer::kDefaultHost("127.0.0.1"); +const int SocketServer::kDefaultTcpBacklog(5); +const size_t SocketServer::kDefaultMaxConnections(128); +const int SocketServer::kDefaultAddressFamily(AF_INET); + +SocketServer::SocketServer(int port, + const std::string &host, + int backlog, + size_t maxConnections, + int addressFamily) + : _port(port), _host(host), _backlog(backlog), + _maxConnections(maxConnections), _addressFamily(addressFamily), + _serverFd(-1), _stop(false), _stopGc(false), + _connectionStateFactory(&ConnectionState::createConnectionState), + _acceptSelectInterrupt(createSelectInterrupt()) +{ +} + +SocketServer::~SocketServer() { stop(); } + +void SocketServer::logError(const std::string &str) +{ + std::lock_guard lock(_logMutex); + fprintf(stderr, "%s\n", str.c_str()); +} + +void SocketServer::logInfo(const std::string &str) +{ + std::lock_guard lock(_logMutex); + fprintf(stdout, "%s\n", str.c_str()); +} + +std::pair SocketServer::listen() +{ + std::string acceptSelectInterruptInitErrorMsg; + if (!_acceptSelectInterrupt->init(acceptSelectInterruptInitErrorMsg)) { + std::stringstream ss; + ss << "SocketServer::listen() error in SelectInterrupt::init: " + << acceptSelectInterruptInitErrorMsg; + + return std::make_pair(false, ss.str()); + } + + if (_addressFamily != AF_INET && _addressFamily != AF_INET6) { + std::string errMsg( + "SocketServer::listen() AF_INET and AF_INET6 are currently " + "the only supported address families"); + return std::make_pair(false, errMsg); + } + + // Get a socket for accepting connections. + if ((_serverFd = socket(_addressFamily, SOCK_STREAM, 0)) < 0) { + std::stringstream ss; + ss << "SocketServer::listen() error creating socket): " + << strerror(Socket::getErrno()); + + return std::make_pair(false, ss.str()); + } + + // Make that socket reusable. (allow restarting this server at will) + int enable = 1; + if (setsockopt(_serverFd, + SOL_SOCKET, + SO_REUSEADDR, + (char *)&enable, + sizeof(enable)) < 0) { + std::stringstream ss; + ss << "SocketServer::listen() error calling setsockopt(SO_REUSEADDR) " + << "at address " << _host << ":" << _port << " : " + << strerror(Socket::getErrno()); + + Socket::closeSocket(_serverFd); + return std::make_pair(false, ss.str()); + } + + if (_addressFamily == AF_INET) { + struct sockaddr_in server; + server.sin_family = _addressFamily; + server.sin_port = htons(_port); + + if (ix::inet_pton(_addressFamily, + _host.c_str(), + &server.sin_addr.s_addr) <= 0) { + std::stringstream ss; + ss << "SocketServer::listen() error calling inet_pton " + << "at address " << _host << ":" << _port << " : " + << strerror(Socket::getErrno()); + + Socket::closeSocket(_serverFd); + return std::make_pair(false, ss.str()); + } + + // Bind the socket to the server address. + if (bind(_serverFd, (struct sockaddr *)&server, sizeof(server)) < 0) { + std::stringstream ss; + ss << "SocketServer::listen() error calling bind " + << "at address " << _host << ":" << _port << " : " + << strerror(Socket::getErrno()); + + Socket::closeSocket(_serverFd); + return std::make_pair(false, ss.str()); + } + } else // AF_INET6 + { + struct sockaddr_in6 server; + server.sin6_family = _addressFamily; + server.sin6_port = htons(_port); + + if (ix::inet_pton(_addressFamily, _host.c_str(), &server.sin6_addr) <= + 0) { + std::stringstream ss; + ss << "SocketServer::listen() error calling inet_pton " + << "at address " << _host << ":" << _port << " : " + << strerror(Socket::getErrno()); + + Socket::closeSocket(_serverFd); + return std::make_pair(false, ss.str()); + } + + // Bind the socket to the server address. + if (bind(_serverFd, (struct sockaddr *)&server, sizeof(server)) < 0) { + std::stringstream ss; + ss << "SocketServer::listen() error calling bind " + << "at address " << _host << ":" << _port << " : " + << strerror(Socket::getErrno()); + + Socket::closeSocket(_serverFd); + return std::make_pair(false, ss.str()); + } + } + + // + // Listen for connections. Specify the tcp backlog. + // + if (::listen(_serverFd, _backlog) < 0) { + std::stringstream ss; + ss << "SocketServer::listen() error calling listen " + << "at address " << _host << ":" << _port << " : " + << strerror(Socket::getErrno()); + + Socket::closeSocket(_serverFd); + return std::make_pair(false, ss.str()); + } + + return std::make_pair(true, ""); +} + +void SocketServer::start() +{ + _stop = false; + + if (!_thread.joinable()) { + _thread = std::thread(&SocketServer::run, this); + } + + if (!_gcThread.joinable()) { + _gcThread = std::thread(&SocketServer::runGC, this); + } +} + +void SocketServer::wait() +{ + std::unique_lock lock(_conditionVariableMutex); + _conditionVariable.wait(lock); +} + +void SocketServer::stopAcceptingConnections() { _stop = true; } + +void SocketServer::stop() +{ + // Stop accepting connections, and close the 'accept' thread + if (_thread.joinable()) { + _stop = true; + // Wake up select + if (!_acceptSelectInterrupt->notify(SelectInterrupt::kCloseRequest)) { + logError("SocketServer::stop: Cannot wake up from select"); + } + + _thread.join(); + _stop = false; + } + + // Join all threads and make sure that all connections are terminated + if (_gcThread.joinable()) { + _stopGc = true; + _conditionVariableGC.notify_one(); + _gcThread.join(); + _stopGc = false; + } + + _conditionVariable.notify_one(); + Socket::closeSocket(_serverFd); +} + +void SocketServer::setConnectionStateFactory( + const ConnectionStateFactory &connectionStateFactory) +{ + _connectionStateFactory = connectionStateFactory; +} + +// +// join the threads for connections that have been closed +// +// When a connection is closed by a client, the connection state terminated +// field becomes true, and we can use that to know that we can join that thread +// and remove it from our _connectionsThreads data structure (a list). +// +void SocketServer::closeTerminatedThreads() +{ + std::lock_guard lock(_connectionsThreadsMutex); + auto it = _connectionsThreads.begin(); + auto itEnd = _connectionsThreads.end(); + + while (it != itEnd) { + auto &connectionState = it->first; + auto &thread = it->second; + + if (!connectionState->isTerminated()) { + ++it; + continue; + } + + if (thread.joinable()) + thread.join(); + it = _connectionsThreads.erase(it); + } +} + +void SocketServer::run() +{ + // Set the socket to non blocking mode, so that accept calls are not + // blocking + SocketConnect::configure(_serverFd); + + setThreadName("SocketServer::accept"); + + for (;;) { + if (_stop) + return; + + // Use poll to check whether a new connection is in progress + int timeoutMs = -1; +#ifdef _WIN32 + // select cannot be interrupted on Windows so we need to pass a small + // timeout + timeoutMs = 10; +#endif + + bool readyToRead = true; + PollResultType pollResult = Socket::poll(readyToRead, + timeoutMs, + _serverFd, + _acceptSelectInterrupt); + + if (pollResult == PollResultType::Error) { + std::stringstream ss; + ss << "SocketServer::run() error in select: " << +#ifndef _WIN32 + strerror(Socket::getErrno()); +#else + + Socket::getErrno(); +#endif + logError(ss.str()); + continue; + } + + if (pollResult != PollResultType::ReadyForRead) { + continue; + } + + // Accept a connection. + // FIXME: Is this working for ipv6 ? + struct sockaddr_in client; // client address information + int clientFd; // socket connected to client + socklen_t addressLen = sizeof(client); + memset(&client, 0, sizeof(client)); + + if ((clientFd = + accept(_serverFd, (struct sockaddr *)&client, &addressLen)) < + 0) { + if (!Socket::isWaitNeeded()) { + // FIXME: that error should be propagated + int err = Socket::getErrno(); + std::stringstream ss; + ss << "SocketServer::run() error accepting connection: " << err + << ", " << strerror(err); + logError(ss.str()); + } + continue; + } + + if (getConnectedClientsCount() >= _maxConnections) { + std::stringstream ss; + ss << "SocketServer::run() reached max connections = " + << _maxConnections << ". " + << "Not accepting connection"; + logError(ss.str()); + + Socket::closeSocket(clientFd); + + continue; + } + + // Retrieve connection info, the ip address of the remote peer/client) + std::string remoteIp; + int remotePort; + + if (_addressFamily == AF_INET) { + char remoteIp4[INET_ADDRSTRLEN]; + if (ix::inet_ntop(AF_INET, + &client.sin_addr, + remoteIp4, + INET_ADDRSTRLEN) == nullptr) { + int err = Socket::getErrno(); + std::stringstream ss; + ss << "SocketServer::run() error calling inet_ntop (ipv4): " + << err << ", " << strerror(err); + logError(ss.str()); + + Socket::closeSocket(clientFd); + + continue; + } + + remotePort = ix::network_to_host_short(client.sin_port); + remoteIp = remoteIp4; + } else // AF_INET6 + { + char remoteIp6[INET6_ADDRSTRLEN]; + if (ix::inet_ntop(AF_INET6, + &client.sin_addr, + remoteIp6, + INET6_ADDRSTRLEN) == nullptr) { + int err = Socket::getErrno(); + std::stringstream ss; + ss << "SocketServer::run() error calling inet_ntop (ipv6): " + << err << ", " << strerror(err); + logError(ss.str()); + + Socket::closeSocket(clientFd); + + continue; + } + + remotePort = ix::network_to_host_short(client.sin_port); + remoteIp = remoteIp6; + } + + std::shared_ptr connectionState; + if (_connectionStateFactory) { + connectionState = _connectionStateFactory(); + } + connectionState->setOnSetTerminatedCallback( + [this] { onSetTerminatedCallback(); }); + connectionState->setRemoteIp(remoteIp); + connectionState->setRemotePort(remotePort); + + if (_stop) + return; + + // create socket + std::string errorMsg; + bool tls = _socketTLSOptions.tls; + auto socket = createSocket(tls, clientFd, errorMsg, _socketTLSOptions); + + if (socket == nullptr) { + logError("SocketServer::run() cannot create socket: " + errorMsg); + Socket::closeSocket(clientFd); + continue; + } + + // Set the socket to non blocking mode + other tweaks + SocketConnect::configure(clientFd); + + if (!socket->accept(errorMsg)) { + logError("SocketServer::run() tls accept failed: " + errorMsg); + Socket::closeSocket(clientFd); + continue; + } + + // Launch the handleConnection work asynchronously in its own thread. + std::lock_guard lock(_connectionsThreadsMutex); + _connectionsThreads.push_back( + std::make_pair(connectionState, + std::thread(&SocketServer::handleConnection, + this, + std::move(socket), + connectionState))); + } +} + +size_t SocketServer::getConnectionsThreadsCount() +{ + std::lock_guard lock(_connectionsThreadsMutex); + return _connectionsThreads.size(); +} + +void SocketServer::runGC() +{ + setThreadName("SocketServer::GC"); + + for (;;) { + // Garbage collection to shutdown/join threads for closed connections. + closeTerminatedThreads(); + + // We quit this thread if all connections are closed and we received + // a stop request by setting _stopGc to true. + if (_stopGc && getConnectionsThreadsCount() == 0) { + break; + } + + // Unless we are stopping the server, wait for a connection + // to be terminated to run the threads GC, instead of busy waiting + // with a sleep + if (!_stopGc) { + std::unique_lock lock(_conditionVariableMutexGC); + _conditionVariableGC.wait(lock); + } + } +} + +void SocketServer::setTLSOptions(const SocketTLSOptions &socketTLSOptions) +{ + _socketTLSOptions = socketTLSOptions; +} + +void SocketServer::onSetTerminatedCallback() +{ + // a connection got terminated, we can run the connection thread GC, + // so wake up the thread responsible for that + _conditionVariableGC.notify_one(); +} + +int SocketServer::getPort() { return _port; } + +std::string SocketServer::getHost() { return _host; } + +int SocketServer::getBacklog() { return _backlog; } + +std::size_t SocketServer::getMaxConnections() { return _maxConnections; } + +int SocketServer::getAddressFamily() { return _addressFamily; } +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketTLSOptions.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketTLSOptions.cpp new file mode 100644 index 0000000..c0a84f2 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXSocketTLSOptions.cpp @@ -0,0 +1,86 @@ +/* + * IXSocketTLSOptions.h + * Author: Matt DeBoer + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXSocketTLSOptions.h" + +#include +#include +#include + +namespace ix +{ +const char *kTLSCAFileUseSystemDefaults = "SYSTEM"; +const char *kTLSCAFileDisableVerify = "NONE"; +const char *kTLSCiphersUseDefault = "DEFAULT"; +const char *kTLSInMemoryMarker = "-----BEGIN CERTIFICATE-----"; + +bool SocketTLSOptions::isValid() const +{ + if (!_validated) { + if (!certFile.empty() && !std::ifstream(certFile)) { + _errMsg = "certFile not found: " + certFile; + return false; + } + if (!keyFile.empty() && !std::ifstream(keyFile)) { + _errMsg = "keyFile not found: " + keyFile; + return false; + } + if (!caFile.empty() && caFile != kTLSCAFileDisableVerify && + caFile != kTLSCAFileUseSystemDefaults && !std::ifstream(caFile)) { + _errMsg = "caFile not found: " + caFile; + return false; + } + + if (certFile.empty() != keyFile.empty()) { + _errMsg = + "certFile and keyFile must be both present, or both absent"; + return false; + } + + _validated = true; + } + return true; +} + +bool SocketTLSOptions::hasCertAndKey() const +{ + return !certFile.empty() && !keyFile.empty(); +} + +bool SocketTLSOptions::isUsingSystemDefaults() const +{ + return caFile == kTLSCAFileUseSystemDefaults; +} + +bool SocketTLSOptions::isUsingInMemoryCAs() const +{ + return caFile.find(kTLSInMemoryMarker) != std::string::npos; +} + +bool SocketTLSOptions::isPeerVerifyDisabled() const +{ + return caFile == kTLSCAFileDisableVerify; +} + +bool SocketTLSOptions::isUsingDefaultCiphers() const +{ + return ciphers.empty() || ciphers == kTLSCiphersUseDefault; +} + +const std::string &SocketTLSOptions::getErrorMsg() const { return _errMsg; } + +std::string SocketTLSOptions::getDescription() const +{ + std::stringstream ss; + ss << "TLS Options:" << std::endl; + ss << " certFile = " << certFile << std::endl; + ss << " keyFile = " << keyFile << std::endl; + ss << " caFile = " << caFile << std::endl; + ss << " ciphers = " << ciphers << std::endl; + ss << " ciphers = " << ciphers << std::endl; + return ss.str(); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXStrCaseCompare.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXStrCaseCompare.cpp new file mode 100644 index 0000000..ca305e7 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXStrCaseCompare.cpp @@ -0,0 +1,39 @@ +/* + * IXStrCaseCompare.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone. All rights reserved. + */ + +#include "IXStrCaseCompare.h" + +#include +#include + +namespace ix +{ +bool CaseInsensitiveLess::NocaseCompare::operator()( + const unsigned char &c1, + const unsigned char &c2) const +{ +#if defined(_WIN32) && !defined(__GNUC__) + return std::tolower(c1, std::locale()) < std::tolower(c2, std::locale()); +#else + return std::tolower(c1) < std::tolower(c2); +#endif +} + +bool CaseInsensitiveLess::cmp(const std::string &s1, const std::string &s2) +{ + return std::lexicographical_compare(s1.begin(), + s1.end(), // source range + s2.begin(), + s2.end(), // dest range + NocaseCompare()); // comparison +} + +bool CaseInsensitiveLess::operator()(const std::string &s1, + const std::string &s2) const +{ + return CaseInsensitiveLess::cmp(s1, s2); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXUdpSocket.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXUdpSocket.cpp new file mode 100644 index 0000000..e64efdb --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXUdpSocket.cpp @@ -0,0 +1,125 @@ +/* + * IXUdpSocket.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone, Inc. All rights reserved. + */ + +#include "IXUdpSocket.h" + +#include "IXNetSystem.h" +#include +#include + +namespace ix +{ +UdpSocket::UdpSocket(int fd) : _sockfd(fd) { ; } + +UdpSocket::~UdpSocket() { close(); } + +void UdpSocket::close() +{ + if (_sockfd == -1) + return; + + closeSocket(_sockfd); + _sockfd = -1; +} + +int UdpSocket::getErrno() +{ + int err; + +#ifdef _WIN32 + err = WSAGetLastError(); +#else + err = errno; +#endif + + return err; +} + +bool UdpSocket::isWaitNeeded() +{ + int err = getErrno(); + + if (err == EWOULDBLOCK || err == EAGAIN || err == EINPROGRESS) { + return true; + } + + return false; +} + +void UdpSocket::closeSocket(int fd) +{ +#ifdef _WIN32 + closesocket(fd); +#else + ::close(fd); +#endif +} + +bool UdpSocket::init(const std::string &host, int port, std::string &errMsg) +{ + _sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (_sockfd < 0) { + errMsg = "Could not create socket"; + return false; + } + +#ifdef _WIN32 + unsigned long nonblocking = 1; + ioctlsocket(_sockfd, FIONBIO, &nonblocking); +#else + fcntl(_sockfd, F_SETFL, O_NONBLOCK); // make socket non blocking +#endif + + memset(&_server, 0, sizeof(_server)); + _server.sin_family = AF_INET; + _server.sin_port = htons(port); + + // DNS resolution. + struct addrinfo hints, *result = nullptr; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + + int ret = getaddrinfo(host.c_str(), nullptr, &hints, &result); + if (ret != 0) { + errMsg = strerror(UdpSocket::getErrno()); + freeaddrinfo(result); + close(); + return false; + } + + struct sockaddr_in *host_addr = (struct sockaddr_in *)result->ai_addr; + memcpy(&_server.sin_addr, &host_addr->sin_addr, sizeof(struct in_addr)); + freeaddrinfo(result); + + return true; +} + +ssize_t UdpSocket::sendto(const std::string &buffer) +{ + return (ssize_t)::sendto(_sockfd, + buffer.data(), + buffer.size(), + 0, + (struct sockaddr *)&_server, + sizeof(_server)); +} + +ssize_t UdpSocket::recvfrom(char *buffer, size_t length) +{ +#ifdef _WIN32 + int addressLen = (int)sizeof(_server); +#else + socklen_t addressLen = (socklen_t)sizeof(_server); +#endif + return (ssize_t)::recvfrom(_sockfd, + buffer, + length, + 0, + (struct sockaddr *)&_server, + &addressLen); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXUrlParser.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXUrlParser.cpp new file mode 100644 index 0000000..6cccc5e --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXUrlParser.cpp @@ -0,0 +1,363 @@ +/* + * Lightweight URL & URI parser (RFC 1738, RFC 3986) + * https://github.com/corporateshark/LUrlParser + * + * The MIT License (MIT) + * + * Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * IXUrlParser.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXUrlParser.h" + +#include +#include +#include + +namespace +{ +enum LUrlParserError { + LUrlParserError_Ok = 0, + LUrlParserError_Uninitialized = 1, + LUrlParserError_NoUrlCharacter = 2, + LUrlParserError_InvalidSchemeName = 3, + LUrlParserError_NoDoubleSlash = 4, + LUrlParserError_NoAtSign = 5, + LUrlParserError_UnexpectedEndOfLine = 6, + LUrlParserError_NoSlash = 7, +}; + +class clParseURL +{ +public: + LUrlParserError m_ErrorCode; + std::string m_Scheme; + std::string m_Host; + std::string m_Port; + std::string m_Path; + std::string m_Query; + std::string m_Fragment; + std::string m_UserName; + std::string m_Password; + + clParseURL() : m_ErrorCode(LUrlParserError_Uninitialized) {} + + /// return 'true' if the parsing was successful + bool IsValid() const { return m_ErrorCode == LUrlParserError_Ok; } + + /// helper to convert the port number to int, return 'true' if the port is + /// valid (within the 0..65535 range) + bool GetPort(int *OutPort) const; + + /// parse the URL + static clParseURL ParseURL(const std::string &URL); + +private: + explicit clParseURL(LUrlParserError ErrorCode) : m_ErrorCode(ErrorCode) {} +}; + +static bool IsSchemeValid(const std::string &SchemeName) +{ + for (auto c : SchemeName) { + if (!isalpha(c) && c != '+' && c != '-' && c != '.') + return false; + } + + return true; +} + +bool clParseURL::GetPort(int *OutPort) const +{ + if (!IsValid()) { + return false; + } + + int Port = atoi(m_Port.c_str()); + + if (Port <= 0 || Port > 65535) { + return false; + } + + if (OutPort) { + *OutPort = Port; + } + + return true; +} + +// based on RFC 1738 and RFC 3986 +clParseURL clParseURL::ParseURL(const std::string &URL) +{ + clParseURL Result; + + const char *CurrentString = URL.c_str(); + + /* + * : + * := [a-z\+\-\.]+ + * For resiliency, programs interpreting URLs should treat upper case + *letters as equivalent to lower case in scheme names + */ + + // try to read scheme + { + const char *LocalString = strchr(CurrentString, ':'); + + if (!LocalString) { + return clParseURL(LUrlParserError_NoUrlCharacter); + } + + // save the scheme name + Result.m_Scheme = + std::string(CurrentString, LocalString - CurrentString); + + if (!IsSchemeValid(Result.m_Scheme)) { + return clParseURL(LUrlParserError_InvalidSchemeName); + } + + // scheme should be lowercase + std::transform(Result.m_Scheme.begin(), + Result.m_Scheme.end(), + Result.m_Scheme.begin(), + ::tolower); + + // skip ':' + CurrentString = LocalString + 1; + } + + /* + * //:@:/ + * any ":", "@" and "/" must be normalized + */ + + // skip "//" + if (*CurrentString++ != '/') + return clParseURL(LUrlParserError_NoDoubleSlash); + if (*CurrentString++ != '/') + return clParseURL(LUrlParserError_NoDoubleSlash); + + // check if the user name and password are specified + bool bHasUserName = false; + + const char *LocalString = CurrentString; + + while (*LocalString) { + if (*LocalString == '@') { + // user name and password are specified + bHasUserName = true; + break; + } else if (*LocalString == '/') { + // end of : specification + bHasUserName = false; + break; + } + + LocalString++; + } + + // user name and password + LocalString = CurrentString; + + if (bHasUserName) { + // read user name + while (*LocalString && *LocalString != ':' && *LocalString != '@') + LocalString++; + + Result.m_UserName = + std::string(CurrentString, LocalString - CurrentString); + + // proceed with the current pointer + CurrentString = LocalString; + + if (*CurrentString == ':') { + // skip ':' + CurrentString++; + + // read password + LocalString = CurrentString; + + while (*LocalString && *LocalString != '@') + LocalString++; + + Result.m_Password = + std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + } + + // skip '@' + if (*CurrentString != '@') { + return clParseURL(LUrlParserError_NoAtSign); + } + + CurrentString++; + } + + bool bHasBracket = (*CurrentString == '['); + + // go ahead, read the host name + LocalString = CurrentString; + + while (*LocalString) { + if (bHasBracket && *LocalString == ']') { + // end of IPv6 address + LocalString++; + break; + } else if (!bHasBracket && + (*LocalString == ':' || *LocalString == '/')) { + // port number is specified + break; + } + + LocalString++; + } + + Result.m_Host = std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + + // is port number specified? + if (*CurrentString == ':') { + CurrentString++; + + // read port number + LocalString = CurrentString; + + while (*LocalString && *LocalString != '/') + LocalString++; + + Result.m_Port = std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + } + + // end of string + if (!*CurrentString) { + Result.m_ErrorCode = LUrlParserError_Ok; + + return Result; + } + + // skip '/' + if (*CurrentString != '/') { + return clParseURL(LUrlParserError_NoSlash); + } + + CurrentString++; + + // parse the path + LocalString = CurrentString; + + while (*LocalString && *LocalString != '#' && *LocalString != '?') + LocalString++; + + Result.m_Path = std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + + // check for query + if (*CurrentString == '?') { + // skip '?' + CurrentString++; + + // read query + LocalString = CurrentString; + + while (*LocalString && *LocalString != '#') + LocalString++; + + Result.m_Query = + std::string(CurrentString, LocalString - CurrentString); + + CurrentString = LocalString; + } + + // check for fragment + if (*CurrentString == '#') { + // skip '#' + CurrentString++; + + // read fragment + LocalString = CurrentString; + + while (*LocalString) + LocalString++; + + Result.m_Fragment = + std::string(CurrentString, LocalString - CurrentString); + } + + Result.m_ErrorCode = LUrlParserError_Ok; + + return Result; +} +} // namespace + +namespace ix +{ +bool UrlParser::parse(const std::string &url, + std::string &protocol, + std::string &host, + std::string &path, + std::string &query, + int &port) +{ + clParseURL res = clParseURL::ParseURL(url); + + if (!res.IsValid()) { + return false; + } + + protocol = res.m_Scheme; + host = res.m_Host; + path = res.m_Path; + query = res.m_Query; + + if (!res.GetPort(&port)) { + if (protocol == "ws" || protocol == "http") { + port = 80; + } else if (protocol == "wss" || protocol == "https") { + port = 443; + } else { + // Invalid protocol. Should be caught by regex check + // but this missing branch trigger cpplint linter. + return false; + } + } + + if (path.empty()) { + path = "/"; + } else if (path[0] != '/') { + path = '/' + path; + } + + if (!query.empty()) { + path += "?"; + path += query; + } + + return true; +} + +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXUserAgent.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXUserAgent.cpp new file mode 100644 index 0000000..aa9a37e --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXUserAgent.cpp @@ -0,0 +1,92 @@ +/* + * IXUserAgent.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXUserAgent.h" + +#include "IXWebSocketVersion.h" +#include +#ifdef IXWEBSOCKET_USE_ZLIB +#include +#endif + +// Platform name +#if defined(_WIN32) +#define PLATFORM_NAME "windows" // Windows +#elif defined(_WIN64) +#define PLATFORM_NAME "windows" // Windows +#elif defined(__CYGWIN__) && !defined(_WIN32) +#define PLATFORM_NAME "windows" // Windows (Cygwin POSIX under Microsoft Window) +#elif defined(__ANDROID__) +#define PLATFORM_NAME \ + "android" // Android (implies Linux, so it must come first) +#elif defined(__linux__) +#define PLATFORM_NAME \ + "linux" // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and + // other +#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__) +#include +#if defined(BSD) +#define PLATFORM_NAME "bsd" // FreeBSD, NetBSD, OpenBSD, DragonFly BSD +#endif +#elif defined(__hpux) +#define PLATFORM_NAME "hp-ux" // HP-UX +#elif defined(_AIX) +#define PLATFORM_NAME "aix" // IBM AIX +#elif defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin) +#include +#if TARGET_IPHONE_SIMULATOR == 1 +#define PLATFORM_NAME "ios" // Apple iOS +#elif TARGET_OS_IPHONE == 1 +#define PLATFORM_NAME "ios" // Apple iOS +#elif TARGET_OS_MAC == 1 +#define PLATFORM_NAME "macos" // Apple OSX +#endif +#elif defined(__sun) && defined(__SVR4) +#define PLATFORM_NAME "solaris" // Oracle Solaris, Open Indiana +#else +#define PLATFORM_NAME "unknown platform" +#endif + +// SSL +#ifdef IXWEBSOCKET_USE_MBED_TLS +#include +#elif defined(IXWEBSOCKET_USE_OPEN_SSL) +#include +#endif + +namespace ix +{ +std::string userAgent() +{ + std::stringstream ss; + + // IXWebSocket Version + ss << "ixwebsocket/" << IX_WEBSOCKET_VERSION; + + // Platform + ss << " " << PLATFORM_NAME; + + // TLS +#ifdef IXWEBSOCKET_USE_TLS +#ifdef IXWEBSOCKET_USE_MBED_TLS + ss << " ssl/mbedtls " << MBEDTLS_VERSION_STRING; +#elif defined(IXWEBSOCKET_USE_OPEN_SSL) + ss << " ssl/OpenSSL " << OPENSSL_VERSION_TEXT; +#elif __APPLE__ + ss << " ssl/SecureTransport"; +#endif +#else + ss << " nossl"; +#endif + +#ifdef IXWEBSOCKET_USE_ZLIB + // Zlib version + ss << " zlib " << ZLIB_VERSION; +#endif + + return ss.str(); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXUuid.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXUuid.cpp new file mode 100644 index 0000000..103bc47 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXUuid.cpp @@ -0,0 +1,75 @@ +/* + * IXUuid.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone. All rights reserved. + */ + +/** + * Generate a random uuid similar to the uuid python module + * + * >>> import uuid + * >>> uuid.uuid4().hex + * 'bec08155b37d4050a1f3c3fa0276bf12' + * + * Code adapted from https://github.com/r-lyeh-archived/sole + */ + +#include "IXUuid.h" + +#include +#include +#include +#include + + +namespace ix +{ +class Uuid +{ +public: + Uuid(); + std::string toString() const; + +private: + uint64_t _ab; + uint64_t _cd; +}; + +Uuid::Uuid() +{ + static std::random_device rd; + static std::uniform_int_distribution dist(0, (uint64_t)(~0)); + + _ab = dist(rd); + _cd = dist(rd); + + _ab = (_ab & 0xFFFFFFFFFFFF0FFFULL) | 0x0000000000004000ULL; + _cd = (_cd & 0x3FFFFFFFFFFFFFFFULL) | 0x8000000000000000ULL; +} + +std::string Uuid::toString() const +{ + std::stringstream ss; + ss << std::hex << std::nouppercase << std::setfill('0'); + + uint32_t a = (_ab >> 32); + uint32_t b = (_ab & 0xFFFFFFFF); + uint32_t c = (_cd >> 32); + uint32_t d = (_cd & 0xFFFFFFFF); + + ss << std::setw(8) << (a); + ss << std::setw(4) << (b >> 16); + ss << std::setw(4) << (b & 0xFFFF); + ss << std::setw(4) << (c >> 16); + ss << std::setw(4) << (c & 0xFFFF); + ss << std::setw(8) << d; + + return ss.str(); +} + +std::string uuid4() +{ + Uuid id; + return id.toString(); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocket.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocket.cpp new file mode 100644 index 0000000..efb8e5a --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocket.cpp @@ -0,0 +1,588 @@ +/* + * IXWebSocket.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocket.h" + +#include "IXExponentialBackoff.h" +#include "IXSetThreadName.h" +#include "IXUniquePtr.h" +#include "IXUtf8Validator.h" +#include "IXWebSocketHandshake.h" +#include +#include + + +namespace +{ +const std::string emptyMsg; +} // namespace + + +namespace ix +{ +OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr; +const int WebSocket::kDefaultHandShakeTimeoutSecs(60); +const int WebSocket::kDefaultPingIntervalSecs(-1); +const bool WebSocket::kDefaultEnablePong(true); +const uint32_t + WebSocket::kDefaultMaxWaitBetweenReconnectionRetries(10 * 1000); // 10s +const uint32_t WebSocket::kDefaultMinWaitBetweenReconnectionRetries(1); // 1 ms + +WebSocket::WebSocket() + : _onMessageCallback(OnMessageCallback()), _stop(false), + _automaticReconnection(true), + _maxWaitBetweenReconnectionRetries( + kDefaultMaxWaitBetweenReconnectionRetries), + _minWaitBetweenReconnectionRetries( + kDefaultMinWaitBetweenReconnectionRetries), + _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs), + _enablePong(kDefaultEnablePong), + _pingIntervalSecs(kDefaultPingIntervalSecs) +{ + _ws.setOnCloseCallback([this](uint16_t code, + const std::string &reason, + size_t wireSize, + bool remote) { + _onMessageCallback(ix::make_unique( + WebSocketMessageType::Close, + emptyMsg, + wireSize, + WebSocketErrorInfo(), + WebSocketOpenInfo(), + WebSocketCloseInfo(code, reason, remote))); + }); +} + +WebSocket::~WebSocket() +{ + stop(); + _ws.setOnCloseCallback(nullptr); +} + +void WebSocket::setUrl(const std::string &url) +{ + std::lock_guard lock(_configMutex); + _url = url; +} + +void WebSocket::setHandshakeTimeout(int handshakeTimeoutSecs) +{ + _handshakeTimeoutSecs = handshakeTimeoutSecs; +} + +void WebSocket::setExtraHeaders(const WebSocketHttpHeaders &headers) +{ + std::lock_guard lock(_configMutex); + _extraHeaders = headers; +} + +const std::string WebSocket::getUrl() const +{ + std::lock_guard lock(_configMutex); + return _url; +} + +void WebSocket::setPerMessageDeflateOptions( + const WebSocketPerMessageDeflateOptions &perMessageDeflateOptions) +{ + std::lock_guard lock(_configMutex); + _perMessageDeflateOptions = perMessageDeflateOptions; +} + +void WebSocket::setTLSOptions(const SocketTLSOptions &socketTLSOptions) +{ + std::lock_guard lock(_configMutex); + _socketTLSOptions = socketTLSOptions; +} + +const WebSocketPerMessageDeflateOptions + WebSocket::getPerMessageDeflateOptions() const +{ + std::lock_guard lock(_configMutex); + return _perMessageDeflateOptions; +} + +void WebSocket::setPingInterval(int pingIntervalSecs) +{ + std::lock_guard lock(_configMutex); + _pingIntervalSecs = pingIntervalSecs; +} + +int WebSocket::getPingInterval() const +{ + std::lock_guard lock(_configMutex); + return _pingIntervalSecs; +} + +void WebSocket::enablePong() +{ + std::lock_guard lock(_configMutex); + _enablePong = true; +} + +void WebSocket::disablePong() +{ + std::lock_guard lock(_configMutex); + _enablePong = false; +} + +void WebSocket::enablePerMessageDeflate() +{ + std::lock_guard lock(_configMutex); + WebSocketPerMessageDeflateOptions perMessageDeflateOptions(true); + _perMessageDeflateOptions = perMessageDeflateOptions; +} + +void WebSocket::disablePerMessageDeflate() +{ + std::lock_guard lock(_configMutex); + WebSocketPerMessageDeflateOptions perMessageDeflateOptions(false); + _perMessageDeflateOptions = perMessageDeflateOptions; +} + +void WebSocket::setMaxWaitBetweenReconnectionRetries( + uint32_t maxWaitBetweenReconnectionRetries) +{ + std::lock_guard lock(_configMutex); + _maxWaitBetweenReconnectionRetries = maxWaitBetweenReconnectionRetries; +} + +void WebSocket::setMinWaitBetweenReconnectionRetries( + uint32_t minWaitBetweenReconnectionRetries) +{ + std::lock_guard lock(_configMutex); + _minWaitBetweenReconnectionRetries = minWaitBetweenReconnectionRetries; +} + +uint32_t WebSocket::getMaxWaitBetweenReconnectionRetries() const +{ + std::lock_guard lock(_configMutex); + return _maxWaitBetweenReconnectionRetries; +} + +uint32_t WebSocket::getMinWaitBetweenReconnectionRetries() const +{ + std::lock_guard lock(_configMutex); + return _minWaitBetweenReconnectionRetries; +} + +void WebSocket::start() +{ + if (_thread.joinable()) + return; // we've already been started + + _thread = std::thread(&WebSocket::run, this); +} + +void WebSocket::stop(uint16_t code, const std::string &reason) +{ + close(code, reason); + + if (_thread.joinable()) { + // wait until working thread will exit + // it will exit after close operation is finished + _stop = true; + _sleepCondition.notify_one(); + _thread.join(); + _stop = false; + } +} + +WebSocketInitResult WebSocket::connect(int timeoutSecs) +{ + { + std::lock_guard lock(_configMutex); + _ws.configure(_perMessageDeflateOptions, + _socketTLSOptions, + _enablePong, + _pingIntervalSecs); + } + + WebSocketHttpHeaders headers(_extraHeaders); + std::string subProtocolsHeader; + auto subProtocols = getSubProtocols(); + if (!subProtocols.empty()) { + // + // Sub Protocol strings are comma separated. + // Python code to do that is: + // >>> ','.join(['json', 'msgpack']) + // 'json,msgpack' + // + int i = 0; + for (auto subProtocol : subProtocols) { + if (i++ != 0) { + subProtocolsHeader += ","; + } + subProtocolsHeader += subProtocol; + } + headers["Sec-WebSocket-Protocol"] = subProtocolsHeader; + } + + WebSocketInitResult status = _ws.connectToUrl(_url, headers, timeoutSecs); + if (!status.success) { + return status; + } + + _onMessageCallback(ix::make_unique( + WebSocketMessageType::Open, + emptyMsg, + 0, + WebSocketErrorInfo(), + WebSocketOpenInfo(status.uri, status.headers, status.protocol), + WebSocketCloseInfo())); + + if (_pingIntervalSecs > 0) { + // Send a heart beat right away + _ws.sendHeartBeat(); + } + + return status; +} + +WebSocketInitResult WebSocket::connectToSocket(std::unique_ptr socket, + int timeoutSecs, + bool enablePerMessageDeflate) +{ + { + std::lock_guard lock(_configMutex); + _ws.configure(_perMessageDeflateOptions, + _socketTLSOptions, + _enablePong, + _pingIntervalSecs); + } + + WebSocketInitResult status = _ws.connectToSocket(std::move(socket), + timeoutSecs, + enablePerMessageDeflate); + if (!status.success) { + return status; + } + + _onMessageCallback(ix::make_unique( + WebSocketMessageType::Open, + emptyMsg, + 0, + WebSocketErrorInfo(), + WebSocketOpenInfo(status.uri, status.headers), + WebSocketCloseInfo())); + + if (_pingIntervalSecs > 0) { + // Send a heart beat right away + _ws.sendHeartBeat(); + } + + return status; +} + +bool WebSocket::isConnected() const +{ + return getReadyState() == ReadyState::Open; +} + +bool WebSocket::isClosing() const +{ + return getReadyState() == ReadyState::Closing; +} + +void WebSocket::close(uint16_t code, const std::string &reason) +{ + _ws.close(code, reason); +} + +void WebSocket::checkConnection(bool firstConnectionAttempt) +{ + using millis = std::chrono::duration; + + uint32_t retries = 0; + millis duration(0); + + // Try to connect perpertually + while (true) { + if (isConnected() || isClosing() || _stop) { + break; + } + + if (!firstConnectionAttempt && !_automaticReconnection) { + // Do not attempt to reconnect + break; + } + + firstConnectionAttempt = false; + + // Only sleep if we are retrying + if (duration.count() > 0) { + std::unique_lock lock(_sleepMutex); + _sleepCondition.wait_for(lock, duration); + } + + if (_stop) { + break; + } + + // Try to connect synchronously + ix::WebSocketInitResult status = connect(_handshakeTimeoutSecs); + + if (!status.success) { + WebSocketErrorInfo connectErr; + + if (_automaticReconnection) { + duration = millis(calculateRetryWaitMilliseconds( + retries++, + _maxWaitBetweenReconnectionRetries, + _minWaitBetweenReconnectionRetries)); + + connectErr.wait_time = duration.count(); + connectErr.retries = retries; + } + + connectErr.reason = status.errorStr; + connectErr.http_status = status.http_status; + + _onMessageCallback( + ix::make_unique(WebSocketMessageType::Error, + emptyMsg, + 0, + connectErr, + WebSocketOpenInfo(), + WebSocketCloseInfo())); + } + } +} + +void WebSocket::run() +{ + setThreadName(getUrl()); + + bool firstConnectionAttempt = true; + + while (true) { + // 1. Make sure we are always connected + checkConnection(firstConnectionAttempt); + + firstConnectionAttempt = false; + + // if here we are closed then checkConnection was not able to connect + if (getReadyState() == ReadyState::Closed) { + break; + } + + // We can avoid to poll if we want to stop and are not closing + if (_stop && !isClosing()) + break; + + // 2. Poll to see if there's any new data available + WebSocketTransport::PollResult pollResult = _ws.poll(); + + // 3. Dispatch the incoming messages + _ws.dispatch( + pollResult, + [this](const std::string &msg, + size_t wireSize, + bool decompressionError, + WebSocketTransport::MessageKind messageKind) { + WebSocketMessageType webSocketMessageType{ + WebSocketMessageType::Error}; + switch (messageKind) { + case WebSocketTransport::MessageKind::MSG_TEXT: + case WebSocketTransport::MessageKind::MSG_BINARY: { + webSocketMessageType = WebSocketMessageType::Message; + } break; + + case WebSocketTransport::MessageKind::PING: { + webSocketMessageType = WebSocketMessageType::Ping; + } break; + + case WebSocketTransport::MessageKind::PONG: { + webSocketMessageType = WebSocketMessageType::Pong; + } break; + + case WebSocketTransport::MessageKind::FRAGMENT: { + webSocketMessageType = WebSocketMessageType::Fragment; + } break; + } + + WebSocketErrorInfo webSocketErrorInfo; + webSocketErrorInfo.decompressionError = decompressionError; + + bool binary = + messageKind == WebSocketTransport::MessageKind::MSG_BINARY; + + _onMessageCallback( + ix::make_unique(webSocketMessageType, + msg, + wireSize, + webSocketErrorInfo, + WebSocketOpenInfo(), + WebSocketCloseInfo(), + binary)); + + WebSocket::invokeTrafficTrackerCallback(wireSize, true); + }); + } +} + +void WebSocket::setOnMessageCallback(const OnMessageCallback &callback) +{ + _onMessageCallback = callback; +} + +bool WebSocket::isOnMessageCallbackRegistered() const +{ + return _onMessageCallback != nullptr; +} + +void WebSocket::setTrafficTrackerCallback( + const OnTrafficTrackerCallback &callback) +{ + _onTrafficTrackerCallback = callback; +} + +void WebSocket::resetTrafficTrackerCallback() +{ + setTrafficTrackerCallback(nullptr); +} + +void WebSocket::invokeTrafficTrackerCallback(size_t size, bool incoming) +{ + if (_onTrafficTrackerCallback) { + _onTrafficTrackerCallback(size, incoming); + } +} + +WebSocketSendInfo WebSocket::send(const std::string &data, + bool binary, + const OnProgressCallback &onProgressCallback) +{ + return (binary) ? sendBinary(data, onProgressCallback) + : sendText(data, onProgressCallback); +} + +WebSocketSendInfo + WebSocket::sendBinary(const std::string &text, + const OnProgressCallback &onProgressCallback) +{ + return sendMessage(text, SendMessageKind::Binary, onProgressCallback); +} + +WebSocketSendInfo + WebSocket::sendText(const std::string &text, + const OnProgressCallback &onProgressCallback) +{ + if (!validateUtf8(text)) { + close(WebSocketCloseConstants::kInvalidFramePayloadData, + WebSocketCloseConstants::kInvalidFramePayloadDataMessage); + return false; + } + return sendMessage(text, SendMessageKind::Text, onProgressCallback); +} + +WebSocketSendInfo WebSocket::ping(const std::string &text) +{ + // Standard limit ping message size + constexpr size_t pingMaxPayloadSize = 125; + if (text.size() > pingMaxPayloadSize) + return WebSocketSendInfo(false); + + return sendMessage(text, SendMessageKind::Ping); +} + +WebSocketSendInfo + WebSocket::sendMessage(const std::string &text, + SendMessageKind sendMessageKind, + const OnProgressCallback &onProgressCallback) +{ + if (!isConnected()) + return WebSocketSendInfo(false); + + // + // It is OK to read and write on the same socket in 2 different threads. + // https://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid + // + // This makes it so that messages are sent right away, and we dont need + // a timeout while we poll to keep wake ups to a minimum (which helps + // with battery life), and use the system select call to notify us when + // incoming messages are arriving / there's data to be received. + // + std::lock_guard lock(_writeMutex); + WebSocketSendInfo webSocketSendInfo; + + switch (sendMessageKind) { + case SendMessageKind::Text: { + webSocketSendInfo = _ws.sendText(text, onProgressCallback); + } break; + + case SendMessageKind::Binary: { + webSocketSendInfo = _ws.sendBinary(text, onProgressCallback); + } break; + + case SendMessageKind::Ping: { + webSocketSendInfo = _ws.sendPing(text); + } break; + } + + WebSocket::invokeTrafficTrackerCallback(webSocketSendInfo.wireSize, false); + + return webSocketSendInfo; +} + +ReadyState WebSocket::getReadyState() const +{ + switch (_ws.getReadyState()) { + case ix::WebSocketTransport::ReadyState::OPEN: + return ReadyState::Open; + case ix::WebSocketTransport::ReadyState::CONNECTING: + return ReadyState::Connecting; + case ix::WebSocketTransport::ReadyState::CLOSING: + return ReadyState::Closing; + case ix::WebSocketTransport::ReadyState::CLOSED: + return ReadyState::Closed; + default: + return ReadyState::Closed; + } +} + +std::string WebSocket::readyStateToString(ReadyState readyState) +{ + switch (readyState) { + case ReadyState::Open: + return "OPEN"; + case ReadyState::Connecting: + return "CONNECTING"; + case ReadyState::Closing: + return "CLOSING"; + case ReadyState::Closed: + return "CLOSED"; + default: + return "UNKNOWN"; + } +} + +void WebSocket::enableAutomaticReconnection() { _automaticReconnection = true; } + +void WebSocket::disableAutomaticReconnection() +{ + _automaticReconnection = false; +} + +bool WebSocket::isAutomaticReconnectionEnabled() const +{ + return _automaticReconnection; +} + +size_t WebSocket::bufferedAmount() const { return _ws.bufferedAmount(); } + +void WebSocket::addSubProtocol(const std::string &subProtocol) +{ + std::lock_guard lock(_configMutex); + _subProtocols.push_back(subProtocol); +} + +const std::vector &WebSocket::getSubProtocols() +{ + std::lock_guard lock(_configMutex); + return _subProtocols; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketCloseConstants.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketCloseConstants.cpp new file mode 100644 index 0000000..6c7159c --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketCloseConstants.cpp @@ -0,0 +1,46 @@ +/* + * IXWebSocketCloseConstants.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocketCloseConstants.h" + +namespace ix +{ +const uint16_t WebSocketCloseConstants::kNormalClosureCode(1000); +const uint16_t WebSocketCloseConstants::kInternalErrorCode(1011); +const uint16_t WebSocketCloseConstants::kAbnormalCloseCode(1006); +const uint16_t WebSocketCloseConstants::kInvalidFramePayloadData(1007); +const uint16_t WebSocketCloseConstants::kProtocolErrorCode(1002); +const uint16_t WebSocketCloseConstants::kNoStatusCodeErrorCode(1005); + +const std::string + WebSocketCloseConstants::kNormalClosureMessage("Normal closure"); +const std::string + WebSocketCloseConstants::kInternalErrorMessage("Internal error"); +const std::string + WebSocketCloseConstants::kAbnormalCloseMessage("Abnormal closure"); +const std::string WebSocketCloseConstants::kPingTimeoutMessage("Ping timeout"); +const std::string + WebSocketCloseConstants::kProtocolErrorMessage("Protocol error"); +const std::string + WebSocketCloseConstants::kNoStatusCodeErrorMessage("No status code"); +const std::string + WebSocketCloseConstants::kProtocolErrorReservedBitUsed("Reserved bit used"); +const std::string WebSocketCloseConstants::kProtocolErrorPingPayloadOversized( + "Ping reason control frame with payload length > 125 octets"); +const std::string + WebSocketCloseConstants::kProtocolErrorCodeControlMessageFragmented( + "Control message fragmented"); +const std::string + WebSocketCloseConstants::kProtocolErrorCodeDataOpcodeOutOfSequence( + "Fragmentation: data message out of sequence"); +const std::string + WebSocketCloseConstants::kProtocolErrorCodeContinuationOpCodeOutOfSequence( + "Fragmentation: continuation opcode out of sequence"); +const std::string WebSocketCloseConstants::kInvalidFramePayloadDataMessage( + "Invalid frame payload data"); +const std::string + WebSocketCloseConstants::kInvalidCloseCodeMessage("Invalid close code"); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketHandshake.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketHandshake.cpp new file mode 100644 index 0000000..5cd7874 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketHandshake.cpp @@ -0,0 +1,365 @@ +/* + * IXWebSocketHandshake.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocketHandshake.h" + +#include "IXHttp.h" +#include "IXSocketConnect.h" +#include "IXStrCaseCompare.h" +#include "IXUrlParser.h" +#include "IXUserAgent.h" +#include "IXWebSocketHandshakeKeyGen.h" +#include +#include +#include +#include + + +namespace ix +{ +WebSocketHandshake::WebSocketHandshake( + std::atomic &requestInitCancellation, + std::unique_ptr &socket, + WebSocketPerMessageDeflatePtr &perMessageDeflate, + WebSocketPerMessageDeflateOptions &perMessageDeflateOptions, + std::atomic &enablePerMessageDeflate) + : _requestInitCancellation(requestInitCancellation), _socket(socket), + _perMessageDeflate(perMessageDeflate), + _perMessageDeflateOptions(perMessageDeflateOptions), + _enablePerMessageDeflate(enablePerMessageDeflate) +{ +} + +bool WebSocketHandshake::insensitiveStringCompare(const std::string &a, + const std::string &b) +{ + return CaseInsensitiveLess::cmp(a, b) == 0; +} + +std::string WebSocketHandshake::genRandomString(const int len) +{ + std::string alphanum = "0123456789" + "ABCDEFGH" + "abcdefgh"; + + std::random_device r; + std::default_random_engine e1(r()); + std::uniform_int_distribution dist(0, (int)alphanum.size() - 1); + + std::string s; + s.resize(len); + + for (int i = 0; i < len; ++i) { + int x = dist(e1); + s[i] = alphanum[x]; + } + + return s; +} + +WebSocketInitResult + WebSocketHandshake::sendErrorResponse(int code, const std::string &reason) +{ + std::stringstream ss; + ss << "HTTP/1.1 "; + ss << code; + ss << " "; + ss << reason; + ss << "\r\n"; + ss << "Server: " << userAgent() << "\r\n"; + + // Socket write can only be cancelled through a timeout here, not manually. + static std::atomic requestInitCancellation(false); + auto isCancellationRequested = + makeCancellationRequestWithTimeout(1, requestInitCancellation); + + if (!_socket->writeBytes(ss.str(), isCancellationRequested)) { + return WebSocketInitResult(false, + 500, + "Timed out while sending error response"); + } + + return WebSocketInitResult(false, code, reason); +} + +WebSocketInitResult WebSocketHandshake::clientHandshake( + const std::string &url, + const WebSocketHttpHeaders &extraHeaders, + const std::string &host, + const std::string &path, + int port, + int timeoutSecs) +{ + _requestInitCancellation = false; + + auto isCancellationRequested = + makeCancellationRequestWithTimeout(timeoutSecs, + _requestInitCancellation); + + std::string errMsg; + bool success = + _socket->connect(host, port, errMsg, isCancellationRequested); + if (!success) { + std::stringstream ss; + ss << "Unable to connect to " << host << " on port " << port + << ", error: " << errMsg; + return WebSocketInitResult(false, 0, ss.str()); + } + + // + // Generate a random 24 bytes string which looks like it is base64 encoded + // y3JJHMbDL1EzLkh9GBhXDw== + // 0cb3Vd9HkbpVVumoS3Noka== + // + // See + // https://stackoverflow.com/questions/18265128/what-is-sec-websocket-key-for + // + std::string secWebSocketKey = genRandomString(22); + secWebSocketKey += "=="; + + std::stringstream ss; + ss << "GET " << path << " HTTP/1.1\r\n"; + ss << "Host: " << host << ":" << port << "\r\n"; + ss << "Upgrade: websocket\r\n"; + ss << "Connection: Upgrade\r\n"; + ss << "Sec-WebSocket-Version: 13\r\n"; + ss << "Sec-WebSocket-Key: " << secWebSocketKey << "\r\n"; + + // User-Agent can be customized by users + if (extraHeaders.find("User-Agent") == extraHeaders.end()) { + ss << "User-Agent: " << userAgent() << "\r\n"; + } + + for (auto &it : extraHeaders) { + ss << it.first << ": " << it.second << "\r\n"; + } + + if (_enablePerMessageDeflate) { + ss << _perMessageDeflateOptions.generateHeader(); + } + + ss << "\r\n"; + + if (!_socket->writeBytes(ss.str(), isCancellationRequested)) { + return WebSocketInitResult( + false, + 0, + std::string("Failed sending GET request to ") + url); + } + + // Read HTTP status line + auto lineResult = _socket->readLine(isCancellationRequested); + auto lineValid = lineResult.first; + auto line = lineResult.second; + + if (!lineValid) { + return WebSocketInitResult( + false, + 0, + std::string("Failed reading HTTP status line from ") + url); + } + + // Validate status + auto statusLine = Http::parseStatusLine(line); + std::string httpVersion = statusLine.first; + int status = statusLine.second; + + // HTTP/1.0 is too old. + if (httpVersion != "HTTP/1.1") { + std::stringstream ss; + ss << "Expecting HTTP/1.1, got " << httpVersion << ". " + << "Rejecting connection to " << url << ", status: " << status + << ", HTTP Status line: " << line; + return WebSocketInitResult(false, status, ss.str()); + } + + auto result = parseHttpHeaders(_socket, isCancellationRequested); + auto headersValid = result.first; + auto headers = result.second; + + if (!headersValid) { + return WebSocketInitResult(false, status, "Error parsing HTTP headers"); + } + + // We want an 101 HTTP status for websocket, otherwise it could be + // a redirection (like 301) + if (status != 101) { + std::stringstream ss; + ss << "Expecting status 101 (Switching Protocol), got " << status + << " status connecting to " << url << ", HTTP Status line: " << line; + + return WebSocketInitResult(false, status, ss.str(), headers, path); + } + + // Check the presence of the connection field + if (headers.find("connection") == headers.end()) { + std::string errorMsg("Missing connection value"); + return WebSocketInitResult(false, status, errorMsg); + } + + // Check the value of the connection field + // Some websocket servers (Go/Gorilla?) send lowercase values for the + // connection header, so do a case insensitive comparison + // + // See + // https://github.com/apache/thrift/commit/7c4bdf9914fcba6c89e0f69ae48b9675578f084a + // + if (!insensitiveStringCompare(headers["connection"], "Upgrade")) { + std::stringstream ss; + ss << "Invalid connection value: " << headers["connection"]; + return WebSocketInitResult(false, status, ss.str()); + } + + char output[29] = {}; + WebSocketHandshakeKeyGen::generate(secWebSocketKey, output); + if (std::string(output) != headers["sec-websocket-accept"]) { + std::string errorMsg("Invalid Sec-WebSocket-Accept value"); + return WebSocketInitResult(false, status, errorMsg); + } + + if (_enablePerMessageDeflate) { + // Parse the server response. Does it support deflate ? + std::string header = headers["sec-websocket-extensions"]; + WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions( + header); + + // If the server does not support that extension, disable it. + if (!webSocketPerMessageDeflateOptions.enabled()) { + _enablePerMessageDeflate = false; + } + // Otherwise try to initialize the deflate engine (zlib) + else if (!_perMessageDeflate->init(webSocketPerMessageDeflateOptions)) { + return WebSocketInitResult( + false, + 0, + "Failed to initialize per message deflate engine"); + } + } + + return WebSocketInitResult(true, status, "", headers, path); +} + +WebSocketInitResult + WebSocketHandshake::serverHandshake(int timeoutSecs, + bool enablePerMessageDeflate) +{ + _requestInitCancellation = false; + + auto isCancellationRequested = + makeCancellationRequestWithTimeout(timeoutSecs, + _requestInitCancellation); + + // Read first line + auto lineResult = _socket->readLine(isCancellationRequested); + auto lineValid = lineResult.first; + auto line = lineResult.second; + + if (!lineValid) { + return sendErrorResponse(400, "Error reading HTTP request line"); + } + + // Validate request line (GET /foo HTTP/1.1\r\n) + auto requestLine = Http::parseRequestLine(line); + auto method = std::get<0>(requestLine); + auto uri = std::get<1>(requestLine); + auto httpVersion = std::get<2>(requestLine); + + if (method != "GET") { + return sendErrorResponse(400, + "Invalid HTTP method, need GET, got " + + method); + } + + if (httpVersion != "HTTP/1.1") { + return sendErrorResponse(400, + "Invalid HTTP version, need HTTP/1.1, got: " + + httpVersion); + } + + // Retrieve and validate HTTP headers + auto result = parseHttpHeaders(_socket, isCancellationRequested); + auto headersValid = result.first; + auto headers = result.second; + + if (!headersValid) { + return sendErrorResponse(400, "Error parsing HTTP headers"); + } + + if (headers.find("sec-websocket-key") == headers.end()) { + return sendErrorResponse(400, "Missing Sec-WebSocket-Key value"); + } + + if (headers.find("upgrade") == headers.end()) { + return sendErrorResponse(400, "Missing Upgrade header"); + } + + if (!insensitiveStringCompare(headers["upgrade"], "WebSocket") && + headers["Upgrade"] != "keep-alive, Upgrade") // special case for firefox + { + return sendErrorResponse(400, + "Invalid Upgrade header, " + "need WebSocket, got " + + headers["upgrade"]); + } + + if (headers.find("sec-websocket-version") == headers.end()) { + return sendErrorResponse(400, "Missing Sec-WebSocket-Version value"); + } + + { + std::stringstream ss; + ss << headers["sec-websocket-version"]; + int version; + ss >> version; + + if (version != 13) { + return sendErrorResponse(400, + "Invalid Sec-WebSocket-Version, " + "need 13, got " + + ss.str()); + } + } + + char output[29] = {}; + WebSocketHandshakeKeyGen::generate(headers["sec-websocket-key"], output); + + std::stringstream ss; + ss << "HTTP/1.1 101 Switching Protocols\r\n"; + ss << "Sec-WebSocket-Accept: " << std::string(output) << "\r\n"; + ss << "Upgrade: websocket\r\n"; + ss << "Connection: Upgrade\r\n"; + ss << "Server: " << userAgent() << "\r\n"; + + // Parse the client headers. Does it support deflate ? + std::string header = headers["sec-websocket-extensions"]; + WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(header); + + // If the client has requested that extension, + if (webSocketPerMessageDeflateOptions.enabled() && + enablePerMessageDeflate) { + _enablePerMessageDeflate = true; + + if (!_perMessageDeflate->init(webSocketPerMessageDeflateOptions)) { + return WebSocketInitResult( + false, + 0, + "Failed to initialize per message deflate engine"); + } + ss << webSocketPerMessageDeflateOptions.generateHeader(); + } + + ss << "\r\n"; + + if (!_socket->writeBytes(ss.str(), isCancellationRequested)) { + return WebSocketInitResult( + false, + 0, + std::string("Failed sending response to remote end")); + } + + return WebSocketInitResult(true, 200, "", headers, uri); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketHttpHeaders.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketHttpHeaders.cpp new file mode 100644 index 0000000..1100bf3 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketHttpHeaders.cpp @@ -0,0 +1,71 @@ +/* + * IXWebSocketHttpHeaders.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocketHttpHeaders.h" + +#include "IXSocket.h" +#include +#include + +namespace ix +{ +std::pair + parseHttpHeaders(std::unique_ptr &socket, + const CancellationRequest &isCancellationRequested) +{ + WebSocketHttpHeaders headers; + + char line[1024]; + int i; + + while (true) { + int colon = 0; + + for (i = 0; + i < 2 || (i < 1023 && line[i - 2] != '\r' && line[i - 1] != '\n'); + ++i) { + if (!socket->readByte(line + i, isCancellationRequested)) { + return std::make_pair(false, headers); + } + + if (line[i] == ':' && colon == 0) { + colon = i; + } + } + if (line[0] == '\r' && line[1] == '\n') { + break; + } + + // line is a single header entry. split by ':', and add it to our + // header map. ignore lines with no colon. + if (colon > 0) { + line[i] = '\0'; + std::string lineStr(line); + // colon is ':', usually colon+1 is ' ', and colon+2 is the start of + // the value. some webservers do not put a space after the colon + // character, so the start of the value might be farther than + // colon+2. The spec says that space after the : should be + // discarded. i is end of string (\0), i-colon is length of string + // minus key; subtract 1 for '\0', 1 for '\n', 1 for '\r', 1 for the + // ' ' after the ':', and total is -4 since we use an std::string + // later on and don't account for '\0', plus the optional first + // space, total is -2 + int start = colon + 1; + while (lineStr[start] == ' ') { + start++; + } + + std::string name(lineStr.substr(0, colon)); + std::string value( + lineStr.substr(start, lineStr.size() - start - 2)); + + headers[name] = value; + } + } + + return std::make_pair(true, headers); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflate.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflate.cpp new file mode 100644 index 0000000..0106598 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflate.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Peter Thorson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the WebSocket++ Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + * + * Adapted from websocketpp/extensions/permessage_deflate/enabled.hpp + * (same license as MZ: https://opensource.org/licenses/BSD-3-Clause) + * + * - Reused zlib compression + decompression bits. + * - Refactored to have 2 class for compression and decompression, to allow + * multi-threading and make sure that _compressBuffer is not shared between + * threads. + * - Original code wasn't working for some reason, I had to add checks + * for the presence of the kEmptyUncompressedBlock at the end of buffer so + * that servers would start accepting receiving/decoding compressed messages. + * Original code was probably modifying the passed in buffers before processing + * in enabled.hpp ? + * - Added more documentation. + * + * Per message Deflate RFC: https://tools.ietf.org/html/rfc7692 + * Chrome websocket -> + * https://github.com/chromium/chromium/tree/2ca8c5037021c9d2ecc00b787d58a31ed8fc8bcb/net/websockets + * + */ + +#include "IXWebSocketPerMessageDeflate.h" + +#include "IXUniquePtr.h" +#include "IXWebSocketPerMessageDeflateCodec.h" +#include "IXWebSocketPerMessageDeflateOptions.h" + +namespace ix +{ +WebSocketPerMessageDeflate::WebSocketPerMessageDeflate() + : _compressor(ix::make_unique()), + _decompressor(ix::make_unique()) +{ + ; +} + +WebSocketPerMessageDeflate::~WebSocketPerMessageDeflate() { ; } + +bool WebSocketPerMessageDeflate::init( + const WebSocketPerMessageDeflateOptions &perMessageDeflateOptions) +{ + bool clientNoContextTakeover = + perMessageDeflateOptions.getClientNoContextTakeover(); + + uint8_t deflateBits = perMessageDeflateOptions.getClientMaxWindowBits(); + uint8_t inflateBits = perMessageDeflateOptions.getServerMaxWindowBits(); + + return _compressor->init(deflateBits, clientNoContextTakeover) && + _decompressor->init(inflateBits, clientNoContextTakeover); +} + +bool WebSocketPerMessageDeflate::compress(const std::string &in, + std::string &out) +{ + return _compressor->compress(in, out); +} + +bool WebSocketPerMessageDeflate::decompress(const std::string &in, + std::string &out) +{ + return _decompressor->decompress(in, out); +} + +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp new file mode 100644 index 0000000..dc41d33 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp @@ -0,0 +1,253 @@ +/* + * IXWebSocketPerMessageDeflateCodec.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocketPerMessageDeflateCodec.h" + +#include "IXWebSocketPerMessageDeflateOptions.h" +#include +#include + +namespace +{ +// The passed in size (4) is important, without it the string litteral +// is treated as a char* and the null termination (\x00) makes it +// look like an empty string. +const std::string kEmptyUncompressedBlock = std::string("\x00\x00\xff\xff", 4); +} // namespace + +namespace ix +{ +// +// Compressor +// +WebSocketPerMessageDeflateCompressor::WebSocketPerMessageDeflateCompressor() +{ +#ifdef IXWEBSOCKET_USE_ZLIB + memset(&_deflateState, 0, sizeof(_deflateState)); + + _deflateState.zalloc = Z_NULL; + _deflateState.zfree = Z_NULL; + _deflateState.opaque = Z_NULL; +#endif +} + +WebSocketPerMessageDeflateCompressor::~WebSocketPerMessageDeflateCompressor() +{ +#ifdef IXWEBSOCKET_USE_ZLIB + deflateEnd(&_deflateState); +#endif +} + +bool WebSocketPerMessageDeflateCompressor::init(uint8_t deflateBits, + bool clientNoContextTakeOver) +{ +#ifdef IXWEBSOCKET_USE_ZLIB + int ret = deflateInit2(&_deflateState, + Z_DEFAULT_COMPRESSION, + Z_DEFLATED, + -1 * deflateBits, + 4, // memory level 1-9 + Z_DEFAULT_STRATEGY); + + if (ret != Z_OK) + return false; + + _flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH; + + return true; +#else + return false; +#endif +} + +template +bool WebSocketPerMessageDeflateCompressor::endsWithEmptyUnCompressedBlock( + const T &value) +{ + if (kEmptyUncompressedBlock.size() > value.size()) + return false; + auto N = value.size(); + return value[N - 1] == kEmptyUncompressedBlock[3] && + value[N - 2] == kEmptyUncompressedBlock[2] && + value[N - 3] == kEmptyUncompressedBlock[1] && + value[N - 4] == kEmptyUncompressedBlock[0]; +} + +bool WebSocketPerMessageDeflateCompressor::compress(const std::string &in, + std::string &out) +{ + return compressData(in, out); +} + +bool WebSocketPerMessageDeflateCompressor::compress(const std::string &in, + std::vector &out) +{ + return compressData(in, out); +} + +bool WebSocketPerMessageDeflateCompressor::compress( + const std::vector &in, + std::string &out) +{ + return compressData(in, out); +} + +bool WebSocketPerMessageDeflateCompressor::compress( + const std::vector &in, + std::vector &out) +{ + return compressData(in, out); +} + +template +bool WebSocketPerMessageDeflateCompressor::compressData(const T &in, S &out) +{ +#ifdef IXWEBSOCKET_USE_ZLIB + // + // 7.2.1. Compression + // + // An endpoint uses the following algorithm to compress a message. + // + // 1. Compress all the octets of the payload of the message using + // DEFLATE. + // + // 2. If the resulting data does not end with an empty DEFLATE block + // with no compression (the "BTYPE" bits are set to 00), append an + // empty DEFLATE block with no compression to the tail end. + // + // 3. Remove 4 octets (that are 0x00 0x00 0xff 0xff) from the tail end. + // After this step, the last octet of the compressed data contains + // (possibly part of) the DEFLATE header bits with the "BTYPE" bits + // set to 00. + // + size_t output; + + // Clear output + out.clear(); + + if (in.empty()) { + // See issue #167 + // The normal buffer size should be 6 but + // we remove the 4 octets from the tail (#4) + uint8_t buf[2] = {0x02, 0x00}; + out.push_back(buf[0]); + out.push_back(buf[1]); + + return true; + } + + _deflateState.avail_in = (uInt)in.size(); + _deflateState.next_in = (Bytef *)in.data(); + + do { + // Output to local buffer + _deflateState.avail_out = (uInt)_compressBuffer.size(); + _deflateState.next_out = &_compressBuffer.front(); + + deflate(&_deflateState, _flush); + + output = _compressBuffer.size() - _deflateState.avail_out; + + out.insert(out.end(), + _compressBuffer.begin(), + _compressBuffer.begin() + output); + } while (_deflateState.avail_out == 0); + + if (endsWithEmptyUnCompressedBlock(out)) { + out.resize(out.size() - 4); + } + + return true; +#else + return false; +#endif +} + +// +// Decompressor +// +WebSocketPerMessageDeflateDecompressor::WebSocketPerMessageDeflateDecompressor() +{ +#ifdef IXWEBSOCKET_USE_ZLIB + memset(&_inflateState, 0, sizeof(_inflateState)); + + _inflateState.zalloc = Z_NULL; + _inflateState.zfree = Z_NULL; + _inflateState.opaque = Z_NULL; + _inflateState.avail_in = 0; + _inflateState.next_in = Z_NULL; +#endif +} + +WebSocketPerMessageDeflateDecompressor:: + ~WebSocketPerMessageDeflateDecompressor() +{ +#ifdef IXWEBSOCKET_USE_ZLIB + inflateEnd(&_inflateState); +#endif +} + +bool WebSocketPerMessageDeflateDecompressor::init(uint8_t inflateBits, + bool clientNoContextTakeOver) +{ +#ifdef IXWEBSOCKET_USE_ZLIB + int ret = inflateInit2(&_inflateState, -1 * inflateBits); + + if (ret != Z_OK) + return false; + + _flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH; + + return true; +#else + return false; +#endif +} + +bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string &in, + std::string &out) +{ +#ifdef IXWEBSOCKET_USE_ZLIB + // + // 7.2.2. Decompression + // + // An endpoint uses the following algorithm to decompress a message. + // + // 1. Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the + // payload of the message. + // + // 2. Decompress the resulting data using DEFLATE. + // + std::string inFixed(in); + inFixed += kEmptyUncompressedBlock; + + _inflateState.avail_in = (uInt)inFixed.size(); + _inflateState.next_in = + (unsigned char *)(const_cast(inFixed.data())); + + // Clear output + out.clear(); + + do { + _inflateState.avail_out = (uInt)_compressBuffer.size(); + _inflateState.next_out = &_compressBuffer.front(); + + int ret = inflate(&_inflateState, Z_SYNC_FLUSH); + + if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) { + return false; // zlib error + } + + out.append(reinterpret_cast(&_compressBuffer.front()), + _compressBuffer.size() - _inflateState.avail_out); + } while (_inflateState.avail_out == 0); + + return true; +#else + return false; +#endif +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp new file mode 100644 index 0000000..3f2b4cb --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp @@ -0,0 +1,193 @@ +/* + * IXWebSocketPerMessageDeflateOptions.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocketPerMessageDeflateOptions.h" + +#include +#include +#include + +namespace ix +{ +/// Default values as defined in the RFC +const uint8_t WebSocketPerMessageDeflateOptions::kDefaultServerMaxWindowBits = + 15; +static const uint8_t minServerMaxWindowBits = 8; +static const uint8_t maxServerMaxWindowBits = 15; + +const uint8_t WebSocketPerMessageDeflateOptions::kDefaultClientMaxWindowBits = + 15; +static const uint8_t minClientMaxWindowBits = 8; +static const uint8_t maxClientMaxWindowBits = 15; + +WebSocketPerMessageDeflateOptions::WebSocketPerMessageDeflateOptions( + bool enabled, + bool clientNoContextTakeover, + bool serverNoContextTakeover, + uint8_t clientMaxWindowBits, + uint8_t serverMaxWindowBits) +{ + _enabled = enabled; + _clientNoContextTakeover = clientNoContextTakeover; + _serverNoContextTakeover = serverNoContextTakeover; + _clientMaxWindowBits = clientMaxWindowBits; + _serverMaxWindowBits = serverMaxWindowBits; + + sanitizeClientMaxWindowBits(); +} + +// +// Four extension parameters are defined for "permessage-deflate" to +// help endpoints manage per-connection resource usage. +// +// - "server_no_context_takeover" +// - "client_no_context_takeover" +// - "server_max_window_bits" +// - "client_max_window_bits" +// +// Server response could look like that: +// +// Sec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover; +// server_no_context_takeover +// +WebSocketPerMessageDeflateOptions::WebSocketPerMessageDeflateOptions( + std::string extension) +{ + extension = removeSpaces(extension); + + _enabled = false; + _clientNoContextTakeover = false; + _serverNoContextTakeover = false; + _clientMaxWindowBits = kDefaultClientMaxWindowBits; + _serverMaxWindowBits = kDefaultServerMaxWindowBits; + +#ifdef IXWEBSOCKET_USE_ZLIB + // Split by ; + std::string token; + std::stringstream tokenStream(extension); + + while (std::getline(tokenStream, token, ';')) { + if (token == "permessage-deflate") { + _enabled = true; + } + + if (token == "server_no_context_takeover") { + _serverNoContextTakeover = true; + } + + if (token == "client_no_context_takeover") { + _clientNoContextTakeover = true; + } + + if (startsWith(token, "server_max_window_bits=")) { + uint8_t x = + strtol(token.substr(token.find_last_of("=") + 1).c_str(), + nullptr, + 10); + + // Sanitize values to be in the proper range [8, 15] in + // case a server would give us bogus values + _serverMaxWindowBits = + std::min(maxServerMaxWindowBits, + std::max(x, minServerMaxWindowBits)); + } + + if (startsWith(token, "client_max_window_bits=")) { + uint8_t x = + strtol(token.substr(token.find_last_of("=") + 1).c_str(), + nullptr, + 10); + + // Sanitize values to be in the proper range [8, 15] in + // case a server would give us bogus values + _clientMaxWindowBits = + std::min(maxClientMaxWindowBits, + std::max(x, minClientMaxWindowBits)); + + sanitizeClientMaxWindowBits(); + } + } +#endif +} + +void WebSocketPerMessageDeflateOptions::sanitizeClientMaxWindowBits() +{ + // zlib/deflate has a bug with windowsbits == 8, so we silently upgrade it + // to 9 See https://bugs.chromium.org/p/chromium/issues/detail?id=691074 + if (_clientMaxWindowBits == 8) { + _clientMaxWindowBits = 9; + } +} + +std::string WebSocketPerMessageDeflateOptions::generateHeader() +{ +#ifdef IXWEBSOCKET_USE_ZLIB + std::stringstream ss; + ss << "Sec-WebSocket-Extensions: permessage-deflate"; + + if (_clientNoContextTakeover) + ss << "; client_no_context_takeover"; + if (_serverNoContextTakeover) + ss << "; server_no_context_takeover"; + + ss << "; server_max_window_bits=" << _serverMaxWindowBits; + ss << "; client_max_window_bits=" << _clientMaxWindowBits; + + ss << "\r\n"; + + return ss.str(); +#else + return std::string(); +#endif +} + +bool WebSocketPerMessageDeflateOptions::enabled() const +{ +#ifdef IXWEBSOCKET_USE_ZLIB + return _enabled; +#else + return false; +#endif +} + +bool WebSocketPerMessageDeflateOptions::getClientNoContextTakeover() const +{ + return _clientNoContextTakeover; +} + +bool WebSocketPerMessageDeflateOptions::getServerNoContextTakeover() const +{ + return _serverNoContextTakeover; +} + +uint8_t WebSocketPerMessageDeflateOptions::getClientMaxWindowBits() const +{ + return _clientMaxWindowBits; +} + +uint8_t WebSocketPerMessageDeflateOptions::getServerMaxWindowBits() const +{ + return _serverMaxWindowBits; +} + +bool WebSocketPerMessageDeflateOptions::startsWith(const std::string &str, + const std::string &start) +{ + return str.compare(0, start.length(), start) == 0; +} + +std::string + WebSocketPerMessageDeflateOptions::removeSpaces(const std::string &str) +{ + std::string out(str); + out.erase(std::remove_if(out.begin(), + out.end(), + [](unsigned char x) { return std::isspace(x); }), + out.end()); + + return out; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketProxyServer.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketProxyServer.cpp new file mode 100644 index 0000000..a4ac231 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketProxyServer.cpp @@ -0,0 +1,117 @@ +/* + * IXWebSocketProxyServer.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocketProxyServer.h" + +#include "IXWebSocketServer.h" +#include + +namespace ix +{ +class ProxyConnectionState : public ix::ConnectionState +{ +public: + ProxyConnectionState() : _connected(false) {} + + ix::WebSocket &webSocket() { return _serverWebSocket; } + + bool isConnected() { return _connected; } + + void setConnected() { _connected = true; } + +private: + ix::WebSocket _serverWebSocket; + bool _connected; +}; + +int websocket_proxy_server_main(int port, + const std::string &hostname, + const ix::SocketTLSOptions &tlsOptions, + const std::string &remoteUrl, + const RemoteUrlsMapping &remoteUrlsMapping, + bool /*verbose*/) +{ + ix::WebSocketServer server(port, hostname); + server.setTLSOptions(tlsOptions); + + auto factory = []() -> std::shared_ptr { + return std::make_shared(); + }; + server.setConnectionStateFactory(factory); + + server.setOnConnectionCallback( + [remoteUrl, + remoteUrlsMapping](std::weak_ptr webSocket, + std::shared_ptr connectionState) { + auto state = std::dynamic_pointer_cast( + connectionState); + auto remoteIp = connectionState->getRemoteIp(); + + // Server connection + state->webSocket().setOnMessageCallback( + [webSocket, state, remoteIp](const WebSocketMessagePtr &msg) { + if (msg->type == ix::WebSocketMessageType::Close) { + state->setTerminated(); + } else if (msg->type == ix::WebSocketMessageType::Message) { + auto ws = webSocket.lock(); + if (ws) { + ws->send(msg->str, msg->binary); + } + } + }); + + // Client connection + auto ws = webSocket.lock(); + if (ws) { + ws->setOnMessageCallback([state, remoteUrl, remoteUrlsMapping]( + const WebSocketMessagePtr &msg) { + if (msg->type == ix::WebSocketMessageType::Open) { + // Connect to the 'real' server + std::string url(remoteUrl); + + // maybe we want a different url based on the mapping + std::string host = msg->openInfo.headers["Host"]; + auto it = remoteUrlsMapping.find(host); + if (it != remoteUrlsMapping.end()) { + url = it->second; + } + + // append the uri to form the full url + // (say ws://localhost:1234/foo/?bar=baz) + url += msg->openInfo.uri; + + state->webSocket().setUrl(url); + state->webSocket().disableAutomaticReconnection(); + state->webSocket().start(); + + // we should sleep here for a bit until we've + // established the connection with the remote server + while (state->webSocket().getReadyState() != + ReadyState::Open) { + std::this_thread::sleep_for( + std::chrono::milliseconds(10)); + } + } else if (msg->type == ix::WebSocketMessageType::Close) { + state->webSocket().close(msg->closeInfo.code, + msg->closeInfo.reason); + } else if (msg->type == ix::WebSocketMessageType::Message) { + state->webSocket().send(msg->str, msg->binary); + } + }); + } + }); + + auto res = server.listen(); + if (!res.first) { + return 1; + } + + server.start(); + server.wait(); + + return 0; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketServer.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketServer.cpp new file mode 100644 index 0000000..dca3a18 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketServer.cpp @@ -0,0 +1,206 @@ +/* + * IXWebSocketServer.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#include "IXWebSocketServer.h" + +#include "IXNetSystem.h" +#include "IXSetThreadName.h" +#include "IXSocketConnect.h" +#include "IXWebSocket.h" +#include "IXWebSocketTransport.h" +#include +#include +#include + +namespace ix +{ +const int WebSocketServer::kDefaultHandShakeTimeoutSecs(3); // 3 seconds +const bool WebSocketServer::kDefaultEnablePong(true); + +WebSocketServer::WebSocketServer(int port, + const std::string &host, + int backlog, + size_t maxConnections, + int handshakeTimeoutSecs, + int addressFamily) + : SocketServer(port, host, backlog, maxConnections, addressFamily), + _handshakeTimeoutSecs(handshakeTimeoutSecs), + _enablePong(kDefaultEnablePong), _enablePerMessageDeflate(true) +{ +} + +WebSocketServer::~WebSocketServer() { stop(); } + +void WebSocketServer::stop() +{ + stopAcceptingConnections(); + + auto clients = getClients(); + for (auto client : clients) { + client->close(); + } + + SocketServer::stop(); +} + +void WebSocketServer::enablePong() { _enablePong = true; } + +void WebSocketServer::disablePong() { _enablePong = false; } + +void WebSocketServer::disablePerMessageDeflate() +{ + _enablePerMessageDeflate = false; +} + +void WebSocketServer::setOnConnectionCallback( + const OnConnectionCallback &callback) +{ + _onConnectionCallback = callback; +} + +void WebSocketServer::setOnClientMessageCallback( + const OnClientMessageCallback &callback) +{ + _onClientMessageCallback = callback; +} + +void WebSocketServer::handleConnection( + std::unique_ptr socket, + std::shared_ptr connectionState) +{ + setThreadName("WebSocketServer::" + connectionState->getId()); + + auto webSocket = std::make_shared(); + if (_onConnectionCallback) { + _onConnectionCallback(webSocket, connectionState); + + if (!webSocket->isOnMessageCallbackRegistered()) { + logError("WebSocketServer Application developer error: Server " + "callback improperly " + "registerered."); + logError("Missing call to setOnMessageCallback inside " + "setOnConnectionCallback."); + connectionState->setTerminated(); + return; + } + } else if (_onClientMessageCallback) { + WebSocket *webSocketRawPtr = webSocket.get(); + webSocket->setOnMessageCallback([this, + webSocketRawPtr, + connectionState]( + const WebSocketMessagePtr &msg) { + _onClientMessageCallback(connectionState, *webSocketRawPtr, msg); + }); + } else { + logError("WebSocketServer Application developer error: No server " + "callback is registerered."); + logError("Missing call to setOnConnectionCallback or " + "setOnClientMessageCallback."); + connectionState->setTerminated(); + return; + } + + webSocket->disableAutomaticReconnection(); + + if (_enablePong) { + webSocket->enablePong(); + } else { + webSocket->disablePong(); + } + + // Add this client to our client set + { + std::lock_guard lock(_clientsMutex); + _clients.insert(webSocket); + } + + auto status = webSocket->connectToSocket(std::move(socket), + _handshakeTimeoutSecs, + _enablePerMessageDeflate); + if (status.success) { + // Process incoming messages and execute callbacks + // until the connection is closed + webSocket->run(); + } else { + std::stringstream ss; + ss << "WebSocketServer::handleConnection() HTTP status: " + << status.http_status << " error: " << status.errorStr; + logError(ss.str()); + } + + webSocket->setOnMessageCallback(nullptr); + + // Remove this client from our client set + { + std::lock_guard lock(_clientsMutex); + if (_clients.erase(webSocket) != 1) { + logError("Cannot delete client"); + } + } + + connectionState->setTerminated(); +} + +std::set> WebSocketServer::getClients() +{ + std::lock_guard lock(_clientsMutex); + return _clients; +} + +size_t WebSocketServer::getConnectedClientsCount() +{ + std::lock_guard lock(_clientsMutex); + return _clients.size(); +} + +// +// Classic servers +// +void WebSocketServer::makeBroadcastServer() +{ + setOnClientMessageCallback( + [this](std::shared_ptr connectionState, + WebSocket &webSocket, + const WebSocketMessagePtr &msg) { + auto remoteIp = connectionState->getRemoteIp(); + if (msg->type == ix::WebSocketMessageType::Message) { + for (auto &&client : getClients()) { + if (client.get() != &webSocket) { + client->send(msg->str, msg->binary); + + // Make sure the OS send buffer is flushed before moving + // on + do { + std::chrono::duration duration( + 500); + std::this_thread::sleep_for(duration); + } while (client->bufferedAmount() != 0); + } + } + } + }); +} + +bool WebSocketServer::listenAndStart() +{ + auto res = listen(); + if (!res.first) { + return false; + } + + start(); + return true; +} + +int WebSocketServer::getHandshakeTimeoutSecs() { return _handshakeTimeoutSecs; } + +bool WebSocketServer::isPongEnabled() { return _enablePong; } + +bool WebSocketServer::isPerMessageDeflateEnabled() +{ + return _enablePerMessageDeflate; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketTransport.cpp b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketTransport.cpp new file mode 100644 index 0000000..e35848b --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/IXWebSocketTransport.cpp @@ -0,0 +1,1130 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2012, 2013 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * IXWebSocketTransport.cpp + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +// +// Adapted from https://github.com/dhbaird/easywsclient +// + +#include "IXWebSocketTransport.h" + +#include "IXSocketFactory.h" +#include "IXSocketTLSOptions.h" +#include "IXUniquePtr.h" +#include "IXUrlParser.h" +#include "IXUtf8Validator.h" +#include "IXWebSocketHandshake.h" +#include "IXWebSocketHttpHeaders.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace ix +{ +const std::string WebSocketTransport::kPingMessage("ixwebsocket::heartbeat"); +const int WebSocketTransport::kDefaultPingIntervalSecs(-1); +const bool WebSocketTransport::kDefaultEnablePong(true); +const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300); +constexpr size_t WebSocketTransport::kChunkSize; + +WebSocketTransport::WebSocketTransport() + : _useMask(true), _blockingSend(false), _receivedMessageCompressed(false), + _readyState(ReadyState::CLOSED), + _closeCode(WebSocketCloseConstants::kInternalErrorCode), + _closeWireSize(0), _closeRemote(false), _enablePerMessageDeflate(false), + _requestInitCancellation(false), + _closingTimePoint(std::chrono::steady_clock::now()), + _enablePong(kDefaultEnablePong), + _pingIntervalSecs(kDefaultPingIntervalSecs), _pongReceived(false), + _pingCount(0), _lastSendPingTimePoint(std::chrono::steady_clock::now()) +{ + setCloseReason(WebSocketCloseConstants::kInternalErrorMessage); + _readbuf.resize(kChunkSize); +} + +WebSocketTransport::~WebSocketTransport() { ; } + +void WebSocketTransport::configure( + const WebSocketPerMessageDeflateOptions &perMessageDeflateOptions, + const SocketTLSOptions &socketTLSOptions, + bool enablePong, + int pingIntervalSecs) +{ + _perMessageDeflateOptions = perMessageDeflateOptions; + _enablePerMessageDeflate = _perMessageDeflateOptions.enabled(); + _socketTLSOptions = socketTLSOptions; + _enablePong = enablePong; + _pingIntervalSecs = pingIntervalSecs; +} + +// Client +WebSocketInitResult + WebSocketTransport::connectToUrl(const std::string &url, + const WebSocketHttpHeaders &headers, + int timeoutSecs) +{ + std::lock_guard lock(_socketMutex); + + std::string protocol, host, path, query; + int port; + std::string remoteUrl(url); + + WebSocketInitResult result; + const int maxRedirections = 10; + + for (int i = 0; i < maxRedirections; ++i) { + if (!UrlParser::parse(remoteUrl, protocol, host, path, query, port)) { + std::stringstream ss; + ss << "Could not parse url: '" << url << "'"; + return WebSocketInitResult(false, 0, ss.str()); + } + + std::string errorMsg; + bool tls = protocol == "wss"; + _socket = createSocket(tls, -1, errorMsg, _socketTLSOptions); + _perMessageDeflate = ix::make_unique(); + + if (!_socket) { + return WebSocketInitResult(false, 0, errorMsg); + } + + WebSocketHandshake webSocketHandshake(_requestInitCancellation, + _socket, + _perMessageDeflate, + _perMessageDeflateOptions, + _enablePerMessageDeflate); + + result = webSocketHandshake.clientHandshake(remoteUrl, + headers, + host, + path, + port, + timeoutSecs); + + if (result.http_status >= 300 && result.http_status < 400) { + auto it = result.headers.find("Location"); + if (it == result.headers.end()) { + std::stringstream ss; + ss << "Missing Location Header for HTTP Redirect response. " + << "Rejecting connection to " << url + << ", status: " << result.http_status; + result.errorStr = ss.str(); + break; + } + + remoteUrl = it->second; + continue; + } + + if (result.success) { + setReadyState(ReadyState::OPEN); + } + return result; + } + + return result; +} + +// Server +WebSocketInitResult + WebSocketTransport::connectToSocket(std::unique_ptr socket, + int timeoutSecs, + bool enablePerMessageDeflate) +{ + std::lock_guard lock(_socketMutex); + + // Server should not mask the data it sends to the client + _useMask = false; + _blockingSend = true; + + _socket = std::move(socket); + _perMessageDeflate = ix::make_unique(); + + WebSocketHandshake webSocketHandshake(_requestInitCancellation, + _socket, + _perMessageDeflate, + _perMessageDeflateOptions, + _enablePerMessageDeflate); + + auto result = webSocketHandshake.serverHandshake(timeoutSecs, + enablePerMessageDeflate); + if (result.success) { + setReadyState(ReadyState::OPEN); + } + return result; +} + +WebSocketTransport::ReadyState WebSocketTransport::getReadyState() const +{ + return _readyState; +} + +void WebSocketTransport::setReadyState(ReadyState readyState) +{ + // No state change, return + if (_readyState == readyState) + return; + + if (readyState == ReadyState::CLOSED) { + if (_onCloseCallback) { + _onCloseCallback(_closeCode, + getCloseReason(), + _closeWireSize, + _closeRemote); + } + setCloseReason(WebSocketCloseConstants::kInternalErrorMessage); + _closeCode = WebSocketCloseConstants::kInternalErrorCode; + _closeWireSize = 0; + _closeRemote = false; + } else if (readyState == ReadyState::OPEN) { + initTimePointsAfterConnect(); + _pongReceived = false; + } + + _readyState = readyState; +} + +void WebSocketTransport::setOnCloseCallback( + const OnCloseCallback &onCloseCallback) +{ + _onCloseCallback = onCloseCallback; +} + +void WebSocketTransport::initTimePointsAfterConnect() +{ + { + std::lock_guard lock(_lastSendPingTimePointMutex); + _lastSendPingTimePoint = std::chrono::steady_clock::now(); + } +} + +// Only consider send PING time points for that computation. +bool WebSocketTransport::pingIntervalExceeded() +{ + if (_pingIntervalSecs <= 0) + return false; + + std::lock_guard lock(_lastSendPingTimePointMutex); + auto now = std::chrono::steady_clock::now(); + return now - _lastSendPingTimePoint > + std::chrono::seconds(_pingIntervalSecs); +} + +WebSocketSendInfo WebSocketTransport::sendHeartBeat() +{ + _pongReceived = false; + std::stringstream ss; + ss << kPingMessage << "::" << _pingIntervalSecs << "s" + << "::" << _pingCount++; + return sendPing(ss.str()); +} + +bool WebSocketTransport::closingDelayExceeded() +{ + std::lock_guard lock(_closingTimePointMutex); + auto now = std::chrono::steady_clock::now(); + return now - _closingTimePoint > + std::chrono::milliseconds(kClosingMaximumWaitingDelayInMs); +} + +WebSocketTransport::PollResult WebSocketTransport::poll() +{ + if (_readyState == ReadyState::OPEN) { + if (pingIntervalExceeded()) { + if (!_pongReceived) { + // ping response (PONG) exceeds the maximum delay, close the + // connection + close(WebSocketCloseConstants::kInternalErrorCode, + WebSocketCloseConstants::kPingTimeoutMessage); + } else { + sendHeartBeat(); + } + } + } + + // No timeout if state is not OPEN, otherwise computed + // pingIntervalOrTimeoutGCD (equals to -1 if no ping and no ping timeout are + // set) + int lastingTimeoutDelayInMs = + (_readyState != ReadyState::OPEN) ? 0 : _pingIntervalSecs; + + if (_pingIntervalSecs > 0) { + // compute lasting delay to wait for next ping / timeout, if at least + // one set + auto now = std::chrono::steady_clock::now(); + int timeSinceLastPingMs = + (int)std::chrono::duration_cast( + now - _lastSendPingTimePoint) + .count(); + lastingTimeoutDelayInMs = + (1000 * _pingIntervalSecs) - timeSinceLastPingMs; + } + +#ifdef _WIN32 + // Windows does not have select interrupt capabilities, so wait with a small + // timeout + if (lastingTimeoutDelayInMs <= 0) { + lastingTimeoutDelayInMs = 20; + } +#endif + + // If we are requesting a cancellation, pass in a positive and small timeout + // to never poll forever without a timeout. + if (_requestInitCancellation) { + lastingTimeoutDelayInMs = 100; + } + + // poll the socket + PollResultType pollResult = _socket->isReadyToRead(lastingTimeoutDelayInMs); + + // Make sure we send all the buffered data + // there can be a lot of it for large messages. + if (pollResult == PollResultType::SendRequest) { + if (!flushSendBuffer()) { + return PollResult::CannotFlushSendBuffer; + } + } else if (pollResult == PollResultType::ReadyForRead) { + if (!receiveFromSocket()) { + return PollResult::AbnormalClose; + } + } else if (pollResult == PollResultType::Error) { + closeSocket(); + } else if (pollResult == PollResultType::CloseRequest) { + closeSocket(); + } + + if (_readyState == ReadyState::CLOSING && closingDelayExceeded()) { + _rxbuf.clear(); + // close code and reason were set when calling close() + closeSocket(); + setReadyState(ReadyState::CLOSED); + } + + return PollResult::Succeeded; +} + +bool WebSocketTransport::isSendBufferEmpty() const +{ + std::lock_guard lock(_txbufMutex); + return _txbuf.empty(); +} + +template +void WebSocketTransport::appendToSendBuffer(const std::vector &header, + Iterator begin, + Iterator end, + uint64_t message_size, + uint8_t masking_key[4]) +{ + std::lock_guard lock(_txbufMutex); + + _txbuf.insert(_txbuf.end(), header.begin(), header.end()); + _txbuf.insert(_txbuf.end(), begin, end); + + if (_useMask) { + for (size_t i = 0; i != (size_t)message_size; ++i) { + *(_txbuf.end() - (size_t)message_size + i) ^= masking_key[i & 0x3]; + } + } +} + +void WebSocketTransport::unmaskReceiveBuffer(const wsheader_type &ws) +{ + if (ws.mask) { + for (size_t j = 0; j != ws.N; ++j) { + _rxbuf[j + ws.header_size] ^= ws.masking_key[j & 0x3]; + } + } +} + +// +// http://tools.ietf.org/html/rfc6455#section-5.2 Base Framing Protocol +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-------+-+-------------+-------------------------------+ +// |F|R|R|R| opcode|M| Payload len | Extended payload length | +// |I|S|S|S| (4) |A| (7) | (16/64) | +// |N|V|V|V| |S| | (if payload len==126/127) | +// | |1|2|3| |K| | | +// +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + +// | Extended payload length continued, if payload len == 127 | +// + - - - - - - - - - - - - - - - +-------------------------------+ +// | |Masking-key, if MASK set to 1 | +// +-------------------------------+-------------------------------+ +// | Masking-key (continued) | Payload Data | +// +-------------------------------- - - - - - - - - - - - - - - - + +// : Payload Data continued ... : +// + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// | Payload Data continued ... | +// +---------------------------------------------------------------+ +// +void WebSocketTransport::dispatch(WebSocketTransport::PollResult pollResult, + const OnMessageCallback &onMessageCallback) +{ + while (true) { + wsheader_type ws; + if (_rxbuf.size() < 2) + break; /* Need at least 2 */ + const uint8_t *data = (uint8_t *)&_rxbuf[0]; // peek, but don't consume + ws.fin = (data[0] & 0x80) == 0x80; + ws.rsv1 = (data[0] & 0x40) == 0x40; + ws.rsv2 = (data[0] & 0x20) == 0x20; + ws.rsv3 = (data[0] & 0x10) == 0x10; + ws.opcode = (wsheader_type::opcode_type)(data[0] & 0x0f); + ws.mask = (data[1] & 0x80) == 0x80; + ws.N0 = (data[1] & 0x7f); + ws.header_size = 2 + (ws.N0 == 126 ? 2 : 0) + (ws.N0 == 127 ? 8 : 0) + + (ws.mask ? 4 : 0); + if (_rxbuf.size() < ws.header_size) + break; /* Need: ws.header_size - _rxbuf.size() */ + + if ((ws.rsv1 && !_enablePerMessageDeflate) || ws.rsv2 || ws.rsv3) { + close(WebSocketCloseConstants::kProtocolErrorCode, + WebSocketCloseConstants::kProtocolErrorReservedBitUsed, + _rxbuf.size()); + return; + } + + // + // Calculate payload length: + // 0-125 mean the payload is that long. + // 126 means that the following two bytes indicate the length, + // 127 means the next 8 bytes indicate the length. + // + int i = 0; + if (ws.N0 < 126) { + ws.N = ws.N0; + i = 2; + } else if (ws.N0 == 126) { + ws.N = 0; + ws.N |= ((uint64_t)data[2]) << 8; + ws.N |= ((uint64_t)data[3]) << 0; + i = 4; + } else if (ws.N0 == 127) { + ws.N = 0; + ws.N |= ((uint64_t)data[2]) << 56; + ws.N |= ((uint64_t)data[3]) << 48; + ws.N |= ((uint64_t)data[4]) << 40; + ws.N |= ((uint64_t)data[5]) << 32; + ws.N |= ((uint64_t)data[6]) << 24; + ws.N |= ((uint64_t)data[7]) << 16; + ws.N |= ((uint64_t)data[8]) << 8; + ws.N |= ((uint64_t)data[9]) << 0; + i = 10; + } else { + // invalid payload length according to the spec. bail out + return; + } + + if (ws.mask) { + ws.masking_key[0] = ((uint8_t)data[i + 0]) << 0; + ws.masking_key[1] = ((uint8_t)data[i + 1]) << 0; + ws.masking_key[2] = ((uint8_t)data[i + 2]) << 0; + ws.masking_key[3] = ((uint8_t)data[i + 3]) << 0; + } else { + ws.masking_key[0] = 0; + ws.masking_key[1] = 0; + ws.masking_key[2] = 0; + ws.masking_key[3] = 0; + } + + // Prevent integer overflow in the next conditional + const uint64_t maxFrameSize(1ULL << 63); + if (ws.N > maxFrameSize) { + return; + } + + if (_rxbuf.size() < ws.header_size + ws.N) { + return; /* Need: ws.header_size+ws.N - _rxbuf.size() */ + } + + if (!ws.fin && (ws.opcode == wsheader_type::PING || + ws.opcode == wsheader_type::PONG || + ws.opcode == wsheader_type::CLOSE)) { + // Control messages should not be fragmented + close(WebSocketCloseConstants::kProtocolErrorCode, + WebSocketCloseConstants:: + kProtocolErrorCodeControlMessageFragmented); + return; + } + + unmaskReceiveBuffer(ws); + std::string frameData(_rxbuf.begin() + ws.header_size, + _rxbuf.begin() + ws.header_size + (size_t)ws.N); + + // We got a whole message, now do something with it: + if (ws.opcode == wsheader_type::TEXT_FRAME || + ws.opcode == wsheader_type::BINARY_FRAME || + ws.opcode == wsheader_type::CONTINUATION) { + if (ws.opcode != wsheader_type::CONTINUATION) { + _fragmentedMessageKind = + (ws.opcode == wsheader_type::TEXT_FRAME) + ? MessageKind::MSG_TEXT + : MessageKind::MSG_BINARY; + + _receivedMessageCompressed = + _enablePerMessageDeflate && ws.rsv1; + + // Continuation message needs to follow a non-fin TEXT or BINARY + // message + if (!_chunks.empty()) { + close(WebSocketCloseConstants::kProtocolErrorCode, + WebSocketCloseConstants:: + kProtocolErrorCodeDataOpcodeOutOfSequence); + } + } else if (_chunks.empty()) { + // Continuation message need to follow a non-fin TEXT or BINARY + // message + close(WebSocketCloseConstants::kProtocolErrorCode, + WebSocketCloseConstants:: + kProtocolErrorCodeContinuationOpCodeOutOfSequence); + } + + // + // Usual case. Small unfragmented messages + // + if (ws.fin && _chunks.empty()) { + emitMessage(_fragmentedMessageKind, + frameData, + _receivedMessageCompressed, + onMessageCallback); + + _receivedMessageCompressed = false; + } else { + // + // Add intermediary message to our chunk list. + // We use a chunk list instead of a big buffer because resizing + // large buffer can be very costly when we need to re-allocate + // the internal buffer which is slow and can let the internal OS + // receive buffer fill out. + // + _chunks.emplace_back(frameData); + + if (ws.fin) { + emitMessage(_fragmentedMessageKind, + getMergedChunks(), + _receivedMessageCompressed, + onMessageCallback); + + _chunks.clear(); + _receivedMessageCompressed = false; + } else { + emitMessage(MessageKind::FRAGMENT, + std::string(), + false, + onMessageCallback); + } + } + } else if (ws.opcode == wsheader_type::PING) { + // too large + if (frameData.size() > 125) { + // Unexpected frame type + close(WebSocketCloseConstants::kProtocolErrorCode, + WebSocketCloseConstants:: + kProtocolErrorPingPayloadOversized); + return; + } + + if (_enablePong) { + // Reply back right away + bool compress = false; + sendData(wsheader_type::PONG, frameData, compress); + } + + emitMessage(MessageKind::PING, frameData, false, onMessageCallback); + } else if (ws.opcode == wsheader_type::PONG) { + _pongReceived = true; + emitMessage(MessageKind::PONG, frameData, false, onMessageCallback); + } else if (ws.opcode == wsheader_type::CLOSE) { + std::string reason; + uint16_t code = 0; + + if (ws.N >= 2) { + // Extract the close code first, available as the first 2 bytes + code |= ((uint64_t)_rxbuf[ws.header_size]) << 8; + code |= ((uint64_t)_rxbuf[ws.header_size + 1]) << 0; + + // Get the reason. + if (ws.N > 2) { + reason = frameData.substr(2, frameData.size()); + } + + // Validate that the reason is proper utf-8. Autobahn 7.5.1 + if (!validateUtf8(reason)) { + code = WebSocketCloseConstants::kInvalidFramePayloadData; + reason = WebSocketCloseConstants:: + kInvalidFramePayloadDataMessage; + } + + // + // Validate close codes. Autobahn 7.9.* + // 1014, 1015 are debattable. The firefox MSDN has a description + // for them. Full list of status code and status range is + // defined in the dedicated RFC section at + // https://tools.ietf.org/html/rfc6455#page-45 + // + if (code < 1000 || code == 1004 || code == 1006 || + (code > 1013 && code < 3000)) { + // build up an error message containing the bad error code + std::stringstream ss; + ss << WebSocketCloseConstants::kInvalidCloseCodeMessage + << ": " << code; + reason = ss.str(); + + code = WebSocketCloseConstants::kProtocolErrorCode; + } + } else { + // no close code received + code = WebSocketCloseConstants::kNoStatusCodeErrorCode; + reason = WebSocketCloseConstants::kNoStatusCodeErrorMessage; + } + + // We receive a CLOSE frame from remote and are NOT the ones who + // triggered the close + if (_readyState != ReadyState::CLOSING) { + // send back the CLOSE frame + sendCloseFrame(code, reason); + + wakeUpFromPoll(SelectInterrupt::kCloseRequest); + + bool remote = true; + closeSocketAndSwitchToClosedState(code, + reason, + _rxbuf.size(), + remote); + } else { + // we got the CLOSE frame answer from our close, so we can close + // the connection if the code/reason are the same + bool identicalReason = + _closeCode == code && getCloseReason() == reason; + + if (identicalReason) { + bool remote = false; + closeSocketAndSwitchToClosedState(code, + reason, + _rxbuf.size(), + remote); + } + } + } else { + // Unexpected frame type + close(WebSocketCloseConstants::kProtocolErrorCode, + WebSocketCloseConstants::kProtocolErrorMessage, + _rxbuf.size()); + } + + // Erase the message that has been processed from the input/read buffer + _rxbuf.erase(_rxbuf.begin(), + _rxbuf.begin() + ws.header_size + (size_t)ws.N); + } + + // if an abnormal closure was raised in poll, and nothing else triggered a + // CLOSED state in the received and processed data then close the connection + if (pollResult != PollResult::Succeeded) { + _rxbuf.clear(); + + // if we previously closed the connection (CLOSING state), then set + // state to CLOSED (code/reason were set before) + if (_readyState == ReadyState::CLOSING) { + closeSocket(); + setReadyState(ReadyState::CLOSED); + } + // if we weren't closing, then close using abnormal close code and + // message + else if (_readyState != ReadyState::CLOSED) { + closeSocketAndSwitchToClosedState( + WebSocketCloseConstants::kAbnormalCloseCode, + WebSocketCloseConstants::kAbnormalCloseMessage, + 0, + false); + } + } +} + +std::string WebSocketTransport::getMergedChunks() const +{ + size_t length = 0; + for (auto &&chunk : _chunks) { + length += chunk.size(); + } + + std::string msg; + msg.reserve(length); + + for (auto &&chunk : _chunks) { + msg += chunk; + } + + return msg; +} + +void WebSocketTransport::emitMessage(MessageKind messageKind, + const std::string &message, + bool compressedMessage, + const OnMessageCallback &onMessageCallback) +{ + size_t wireSize = message.size(); + + // When the RSV1 bit is 1 it means the message is compressed + if (compressedMessage && messageKind != MessageKind::FRAGMENT) { + bool success = + _perMessageDeflate->decompress(message, _decompressedMessage); + + if (messageKind == MessageKind::MSG_TEXT && + !validateUtf8(_decompressedMessage)) { + close(WebSocketCloseConstants::kInvalidFramePayloadData, + WebSocketCloseConstants::kInvalidFramePayloadDataMessage); + } else { + onMessageCallback(_decompressedMessage, + wireSize, + !success, + messageKind); + } + } else { + if (messageKind == MessageKind::MSG_TEXT && !validateUtf8(message)) { + close(WebSocketCloseConstants::kInvalidFramePayloadData, + WebSocketCloseConstants::kInvalidFramePayloadDataMessage); + } else { + onMessageCallback(message, wireSize, false, messageKind); + } + } +} + +unsigned WebSocketTransport::getRandomUnsigned() +{ + auto now = std::chrono::system_clock::now(); + auto seconds = + std::chrono::duration_cast(now.time_since_epoch()) + .count(); + return static_cast(seconds); +} + +template +WebSocketSendInfo + WebSocketTransport::sendData(wsheader_type::opcode_type type, + const T &message, + bool compress, + const OnProgressCallback &onProgressCallback) +{ + if (_readyState != ReadyState::OPEN && _readyState != ReadyState::CLOSING) { + return WebSocketSendInfo(false); + } + + size_t payloadSize = message.size(); + size_t wireSize = message.size(); + bool compressionError = false; + + auto message_begin = message.cbegin(); + auto message_end = message.cend(); + + if (compress) { + if (!_perMessageDeflate->compress(message, _compressedMessage)) { + bool success = false; + compressionError = true; + payloadSize = 0; + wireSize = 0; + return WebSocketSendInfo(success, + compressionError, + payloadSize, + wireSize); + } + compressionError = false; + wireSize = _compressedMessage.size(); + + message_begin = _compressedMessage.cbegin(); + message_end = _compressedMessage.cend(); + } + + { + std::lock_guard lock(_txbufMutex); + _txbuf.reserve(wireSize); + } + + bool success = true; + + // Common case for most message. No fragmentation required. + if (wireSize < kChunkSize) { + success = + sendFragment(type, true, message_begin, message_end, compress); + + if (onProgressCallback) { + onProgressCallback(0, 1); + } + } else { + // + // Large messages need to be fragmented + // + // Rules: + // First message needs to specify a proper type (BINARY or TEXT) + // Intermediary and last messages need to be of type CONTINUATION + // Last message must set the fin byte. + // + auto steps = wireSize / kChunkSize; + + std::string::const_iterator begin = message_begin; + std::string::const_iterator end = message_end; + + for (uint64_t i = 0; i < steps; ++i) { + bool firstStep = i == 0; + bool lastStep = (i + 1) == steps; + bool fin = lastStep; + + end = begin + kChunkSize; + if (lastStep) { + end = message_end; + } + + auto opcodeType = type; + if (!firstStep) { + opcodeType = wsheader_type::CONTINUATION; + } + + // Send message + if (!sendFragment(opcodeType, fin, begin, end, compress)) { + return WebSocketSendInfo(false); + } + + if (onProgressCallback && !onProgressCallback((int)i, (int)steps)) { + break; + } + + begin += kChunkSize; + } + } + + // Request to flush the send buffer on the background thread if it isn't + // empty + if (!isSendBufferEmpty()) { + wakeUpFromPoll(SelectInterrupt::kSendRequest); + + // FIXME: we should have a timeout when sending large messages: see #131 + if (_blockingSend && !flushSendBuffer()) { + success = false; + } + } + + return WebSocketSendInfo(success, compressionError, payloadSize, wireSize); +} + +template +bool WebSocketTransport::sendFragment(wsheader_type::opcode_type type, + bool fin, + Iterator message_begin, + Iterator message_end, + bool compress) +{ + uint64_t message_size = static_cast(message_end - message_begin); + + unsigned x = getRandomUnsigned(); + uint8_t masking_key[4] = {}; + masking_key[0] = (x >> 24); + masking_key[1] = (x >> 16) & 0xff; + masking_key[2] = (x >> 8) & 0xff; + masking_key[3] = (x)&0xff; + + std::vector header; + header.assign(2 + (message_size >= 126 ? 2 : 0) + + (message_size >= 65536 ? 6 : 0) + (_useMask ? 4 : 0), + 0); + header[0] = type; + + // The fin bit indicate that this is the last fragment. Fin is French for + // end. + if (fin) { + header[0] |= 0x80; + } + + // The rsv1 bit indicate that the frame is compressed + // continuation opcodes should not set it. Autobahn 12.2.10 and others 12.X + if (compress && type != wsheader_type::CONTINUATION) { + header[0] |= 0x40; + } + + if (message_size < 126) { + header[1] = (message_size & 0xff) | (_useMask ? 0x80 : 0); + + if (_useMask) { + header[2] = masking_key[0]; + header[3] = masking_key[1]; + header[4] = masking_key[2]; + header[5] = masking_key[3]; + } + } else if (message_size < 65536) { + header[1] = 126 | (_useMask ? 0x80 : 0); + header[2] = (message_size >> 8) & 0xff; + header[3] = (message_size >> 0) & 0xff; + + if (_useMask) { + header[4] = masking_key[0]; + header[5] = masking_key[1]; + header[6] = masking_key[2]; + header[7] = masking_key[3]; + } + } else { // TODO: run coverage testing here + header[1] = 127 | (_useMask ? 0x80 : 0); + header[2] = (message_size >> 56) & 0xff; + header[3] = (message_size >> 48) & 0xff; + header[4] = (message_size >> 40) & 0xff; + header[5] = (message_size >> 32) & 0xff; + header[6] = (message_size >> 24) & 0xff; + header[7] = (message_size >> 16) & 0xff; + header[8] = (message_size >> 8) & 0xff; + header[9] = (message_size >> 0) & 0xff; + + if (_useMask) { + header[10] = masking_key[0]; + header[11] = masking_key[1]; + header[12] = masking_key[2]; + header[13] = masking_key[3]; + } + } + + // _txbuf will keep growing until it can be transmitted over the socket: + appendToSendBuffer(header, + message_begin, + message_end, + message_size, + masking_key); + + // Now actually send this data + return sendOnSocket(); +} + +WebSocketSendInfo WebSocketTransport::sendPing(const std::string &message) +{ + bool compress = false; + WebSocketSendInfo info = sendData(wsheader_type::PING, message, compress); + + if (info.success) { + std::lock_guard lck(_lastSendPingTimePointMutex); + _lastSendPingTimePoint = std::chrono::steady_clock::now(); + } + + return info; +} + +WebSocketSendInfo + WebSocketTransport::sendBinary(const std::string &message, + const OnProgressCallback &onProgressCallback) + +{ + return sendData(wsheader_type::BINARY_FRAME, + message, + _enablePerMessageDeflate, + onProgressCallback); +} + +WebSocketSendInfo + WebSocketTransport::sendText(const std::string &message, + const OnProgressCallback &onProgressCallback) + +{ + return sendData(wsheader_type::TEXT_FRAME, + message, + _enablePerMessageDeflate, + onProgressCallback); +} + +bool WebSocketTransport::sendOnSocket() +{ + std::lock_guard lock(_txbufMutex); + + while (_txbuf.size()) { + ssize_t ret = 0; + { + std::lock_guard lock(_socketMutex); + ret = _socket->send((char *)&_txbuf[0], _txbuf.size()); + } + + if (ret < 0 && Socket::isWaitNeeded()) { + break; + } else if (ret <= 0) { + closeSocket(); + setReadyState(ReadyState::CLOSED); + return false; + } else { + _txbuf.erase(_txbuf.begin(), _txbuf.begin() + ret); + } + } + + return true; +} + +bool WebSocketTransport::receiveFromSocket() +{ + while (true) { + ssize_t ret = _socket->recv((char *)&_readbuf[0], _readbuf.size()); + + if (ret < 0 && Socket::isWaitNeeded()) { + break; + } else if (ret <= 0) { + // if there are received data pending to be processed, then delay + // the abnormal closure to after dispatch (other close code/reason + // could be read from the buffer) + + closeSocket(); + return false; + } else { + _rxbuf.insert(_rxbuf.end(), + _readbuf.begin(), + _readbuf.begin() + ret); + } + } + + return true; +} + +void WebSocketTransport::sendCloseFrame(uint16_t code, + const std::string &reason) +{ + bool compress = false; + + // if a status is set/was read + if (code != WebSocketCloseConstants::kNoStatusCodeErrorCode) { + // See list of close events here: + // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent + std::string closure{(char)(code >> 8), (char)(code & 0xff)}; + + // copy reason after code + closure.append(reason); + + sendData(wsheader_type::CLOSE, closure, compress); + } else { + // no close code/reason set + sendData(wsheader_type::CLOSE, std::string(""), compress); + } +} + +void WebSocketTransport::closeSocket() +{ + std::lock_guard lock(_socketMutex); + _socket->close(); +} + +bool WebSocketTransport::wakeUpFromPoll(uint64_t wakeUpCode) +{ + std::lock_guard lock(_socketMutex); + return _socket->wakeUpFromPoll(wakeUpCode); +} + +void WebSocketTransport::closeSocketAndSwitchToClosedState( + uint16_t code, + const std::string &reason, + size_t closeWireSize, + bool remote) +{ + closeSocket(); + + setCloseReason(reason); + _closeCode = code; + _closeWireSize = closeWireSize; + _closeRemote = remote; + + setReadyState(ReadyState::CLOSED); + _requestInitCancellation = false; +} + +void WebSocketTransport::close(uint16_t code, + const std::string &reason, + size_t closeWireSize, + bool remote) +{ + _requestInitCancellation = true; + + if (_readyState == ReadyState::CLOSING || _readyState == ReadyState::CLOSED) + return; + + if (closeWireSize == 0) { + closeWireSize = reason.size(); + } + + setCloseReason(reason); + _closeCode = code; + _closeWireSize = closeWireSize; + _closeRemote = remote; + + { + std::lock_guard lock(_closingTimePointMutex); + _closingTimePoint = std::chrono::steady_clock::now(); + } + setReadyState(ReadyState::CLOSING); + + sendCloseFrame(code, reason); + + // wake up the poll, but do not close yet + wakeUpFromPoll(SelectInterrupt::kSendRequest); +} + +size_t WebSocketTransport::bufferedAmount() const +{ + std::lock_guard lock(_txbufMutex); + return _txbuf.size(); +} + +bool WebSocketTransport::flushSendBuffer() +{ + while (!isSendBufferEmpty() && !_requestInitCancellation) { + // Wait with a 10ms timeout until the socket is ready to write. + // This way we are not busy looping + PollResultType result = _socket->isReadyToWrite(10); + + if (result == PollResultType::Error) { + closeSocket(); + setReadyState(ReadyState::CLOSED); + return false; + } else if (result == PollResultType::ReadyForWrite) { + if (!sendOnSocket()) { + return false; + } + } + } + + return true; +} + +void WebSocketTransport::setCloseReason(const std::string &reason) +{ + std::lock_guard lock(_closeReasonMutex); + _closeReason = reason; +} + +const std::string &WebSocketTransport::getCloseReason() const +{ + std::lock_guard lock(_closeReasonMutex); + return _closeReason; +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/License.txt b/GermanAirlinesVA-GAConnector/ixwebsocket/License.txt new file mode 100644 index 0000000..dffb40e --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/License.txt @@ -0,0 +1,29 @@ +Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXBench.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXBench.h new file mode 100644 index 0000000..873e016 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXBench.h @@ -0,0 +1,32 @@ +/* + * IXBench.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved. + */ +#pragma once + +#include +#include +#include + +namespace ix +{ +class Bench +{ +public: + Bench(const std::string &description); + ~Bench(); + + void reset(); + void record(); + void report(); + void setReported(); + uint64_t getDuration() const; + +private: + std::string _description; + std::chrono::time_point _start; + uint64_t _duration; + bool _reported; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXCancellationRequest.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXCancellationRequest.h new file mode 100644 index 0000000..2a4f048 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXCancellationRequest.h @@ -0,0 +1,19 @@ +/* + * IXCancellationRequest.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ +using CancellationRequest = std::function; + +CancellationRequest makeCancellationRequestWithTimeout( + int seconds, + std::atomic &requestInitCancellation); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXConnectionState.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXConnectionState.h new file mode 100644 index 0000000..c561318 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXConnectionState.h @@ -0,0 +1,54 @@ +/* + * IXConnectionState.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace ix +{ +using OnSetTerminatedCallback = std::function; + +class ConnectionState +{ +public: + ConnectionState(); + virtual ~ConnectionState() = default; + + virtual void computeId(); + virtual const std::string &getId() const; + + void setTerminated(); + bool isTerminated() const; + + const std::string &getRemoteIp(); + int getRemotePort(); + + static std::shared_ptr createConnectionState(); + +private: + void setOnSetTerminatedCallback(const OnSetTerminatedCallback &callback); + + void setRemoteIp(const std::string &remoteIp); + void setRemotePort(int remotePort); + +protected: + std::atomic _terminated; + std::string _id; + OnSetTerminatedCallback _onSetTerminatedCallback; + + static std::atomic _globalId; + + std::string _remoteIp; + int _remotePort; + + friend class SocketServer; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXDNSLookup.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXDNSLookup.h new file mode 100644 index 0000000..dea9301 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXDNSLookup.h @@ -0,0 +1,73 @@ +/* + * IXDNSLookup.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + * + * Resolve a hostname+port to a struct addrinfo obtained with getaddrinfo + * Does this in a background thread so that it can be cancelled, since + * getaddrinfo is a blocking call, and we don't want to block the main thread + * on Mobile. + */ + +#pragma once + +#include "IXCancellationRequest.h" +#include +#include +#include +#include +#include + +struct addrinfo; + +namespace ix +{ +class DNSLookup : public std::enable_shared_from_this +{ +public: + DNSLookup(const std::string &hostname, + int port, + int64_t wait = DNSLookup::kDefaultWait); + ~DNSLookup() = default; + + struct addrinfo *resolve(std::string &errMsg, + const CancellationRequest &isCancellationRequested, + bool cancellable = true); + + void release(struct addrinfo *addr); + +private: + struct addrinfo * + resolveCancellable(std::string &errMsg, + const CancellationRequest &isCancellationRequested); + struct addrinfo *resolveUnCancellable( + std::string &errMsg, + const CancellationRequest &isCancellationRequested); + + static struct addrinfo * + getAddrInfo(const std::string &hostname, int port, std::string &errMsg); + + void run(std::weak_ptr self, + std::string hostname, + int port); // thread runner + + void setErrMsg(const std::string &errMsg); + const std::string &getErrMsg(); + + void setRes(struct addrinfo *addr); + struct addrinfo *getRes(); + + std::string _hostname; + int _port; + int64_t _wait; + const static int64_t kDefaultWait; + + struct addrinfo *_res; + std::mutex _resMutex; + + std::string _errMsg; + std::mutex _errMsgMutex; + + std::atomic _done; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXExponentialBackoff.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXExponentialBackoff.h new file mode 100644 index 0000000..4df2387 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXExponentialBackoff.h @@ -0,0 +1,17 @@ +/* + * IXExponentialBackoff.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +uint32_t + calculateRetryWaitMilliseconds(uint32_t retryCount, + uint32_t maxWaitBetweenReconnectionRetries, + uint32_t minWaitBetweenReconnectionRetries); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXGetFreePort.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXGetFreePort.h new file mode 100644 index 0000000..7632922 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXGetFreePort.h @@ -0,0 +1,12 @@ +/* + * IXGetFreePort.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone. All rights reserved. + */ + +#pragma once + +namespace ix +{ +int getFreePort(); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXGzipCodec.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXGzipCodec.h new file mode 100644 index 0000000..38e3580 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXGzipCodec.h @@ -0,0 +1,15 @@ +/* + * IXGzipCodec.h + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +std::string gzipCompress(const std::string &str); +bool gzipDecompress(const std::string &in, std::string &out); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttp.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttp.h new file mode 100644 index 0000000..942fc7e --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttp.h @@ -0,0 +1,117 @@ +/* + * IXHttp.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXProgressCallback.h" +#include "IXWebSocketHttpHeaders.h" +#include +#include + +namespace ix +{ +enum class HttpErrorCode : int { + Ok = 0, + CannotConnect = 1, + Timeout = 2, + Gzip = 3, + UrlMalformed = 4, + CannotCreateSocket = 5, + SendError = 6, + ReadError = 7, + CannotReadStatusLine = 8, + MissingStatus = 9, + HeaderParsingError = 10, + MissingLocation = 11, + TooManyRedirects = 12, + ChunkReadError = 13, + CannotReadBody = 14, + Invalid = 100 +}; + +struct HttpResponse { + int statusCode; + std::string description; + HttpErrorCode errorCode; + WebSocketHttpHeaders headers; + std::string body; + std::string errorMsg; + uint64_t uploadSize; + uint64_t downloadSize; + + HttpResponse(int s = 0, + const std::string &des = std::string(), + const HttpErrorCode &c = HttpErrorCode::Ok, + const WebSocketHttpHeaders &h = WebSocketHttpHeaders(), + const std::string &b = std::string(), + const std::string &e = std::string(), + uint64_t u = 0, + uint64_t d = 0) + : statusCode(s), description(des), errorCode(c), headers(h), body(b), + errorMsg(e), uploadSize(u), downloadSize(d) + { + ; + } +}; + +using HttpResponsePtr = std::shared_ptr; +using HttpParameters = std::unordered_map; +using HttpFormDataParameters = std::unordered_map; +using Logger = std::function; +using OnResponseCallback = std::function; + +struct HttpRequestArgs { + std::string url; + std::string verb; + WebSocketHttpHeaders extraHeaders; + std::string body; + std::string multipartBoundary; + int connectTimeout = 60; + int transferTimeout = 1800; + bool followRedirects = true; + int maxRedirects = 5; + bool verbose = false; + bool compress = true; + bool compressRequest = false; + Logger logger; + OnProgressCallback onProgressCallback; +}; + +using HttpRequestArgsPtr = std::shared_ptr; + +struct HttpRequest { + std::string uri; + std::string method; + std::string version; + std::string body; + WebSocketHttpHeaders headers; + + HttpRequest(const std::string &u, + const std::string &m, + const std::string &v, + const std::string &b, + const WebSocketHttpHeaders &h = WebSocketHttpHeaders()) + : uri(u), method(m), version(v), body(b), headers(h) + { + } +}; + +using HttpRequestPtr = std::shared_ptr; + +class Http +{ +public: + static std::tuple + parseRequest(std::unique_ptr &socket, int timeoutSecs); + static bool sendResponse(HttpResponsePtr response, + std::unique_ptr &socket); + + static std::pair parseStatusLine(const std::string &line); + static std::tuple + parseRequestLine(const std::string &line); + static std::string trim(const std::string &str); +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttpClient.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttpClient.h new file mode 100644 index 0000000..98f47e8 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttpClient.h @@ -0,0 +1,126 @@ +/* + * IXHttpClient.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXHttp.h" +#include "IXSocket.h" +#include "IXSocketTLSOptions.h" +#include "IXWebSocketHttpHeaders.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ix +{ +class HttpClient +{ +public: + HttpClient(bool async = false); + ~HttpClient(); + + HttpResponsePtr get(const std::string &url, HttpRequestArgsPtr args); + HttpResponsePtr head(const std::string &url, HttpRequestArgsPtr args); + HttpResponsePtr Delete(const std::string &url, HttpRequestArgsPtr args); + + HttpResponsePtr post(const std::string &url, + const HttpParameters &httpParameters, + const HttpFormDataParameters &httpFormDataParameters, + HttpRequestArgsPtr args); + HttpResponsePtr post(const std::string &url, + const std::string &body, + HttpRequestArgsPtr args); + + HttpResponsePtr put(const std::string &url, + const HttpParameters &httpParameters, + const HttpFormDataParameters &httpFormDataParameters, + HttpRequestArgsPtr args); + HttpResponsePtr put(const std::string &url, + const std::string &body, + HttpRequestArgsPtr args); + + HttpResponsePtr patch(const std::string &url, + const HttpParameters &httpParameters, + const HttpFormDataParameters &httpFormDataParameters, + HttpRequestArgsPtr args); + HttpResponsePtr patch(const std::string &url, + const std::string &body, + HttpRequestArgsPtr args); + + HttpResponsePtr request(const std::string &url, + const std::string &verb, + const std::string &body, + HttpRequestArgsPtr args, + int redirects = 0); + + HttpResponsePtr + request(const std::string &url, + const std::string &verb, + const HttpParameters &httpParameters, + const HttpFormDataParameters &httpFormDataParameters, + HttpRequestArgsPtr args); + + void setForceBody(bool value); + + // Async API + HttpRequestArgsPtr + createRequest(const std::string &url = std::string(), + const std::string &verb = HttpClient::kGet); + + bool performRequest(HttpRequestArgsPtr request, + const OnResponseCallback &onResponseCallback); + + // TLS + void setTLSOptions(const SocketTLSOptions &tlsOptions); + + std::string serializeHttpParameters(const HttpParameters &httpParameters); + + std::string serializeHttpFormDataParameters( + const std::string &multipartBoundary, + const HttpFormDataParameters &httpFormDataParameters, + const HttpParameters &httpParameters = HttpParameters()); + + std::string generateMultipartBoundary(); + + std::string urlEncode(const std::string &value); + + const static std::string kPost; + const static std::string kGet; + const static std::string kHead; + const static std::string kDelete; + const static std::string kPut; + const static std::string kPatch; + +private: + void log(const std::string &msg, HttpRequestArgsPtr args); + + // Async API background thread runner + void run(); + // Async API + bool _async; + std::queue> _queue; + mutable std::mutex _queueMutex; + std::condition_variable _condition; + std::atomic _stop; + std::thread _thread; + + std::unique_ptr _socket; + std::recursive_mutex + _mutex; // to protect accessing the _socket (only one socket per + // client) the mutex needs to be recursive as this function + // might be called recursively to follow HTTP redirections + + SocketTLSOptions _tlsOptions; + + bool _forceBody; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttpServer.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttpServer.h new file mode 100644 index 0000000..f8a76d6 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXHttpServer.h @@ -0,0 +1,62 @@ +/* + * IXHttpServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXHttp.h" +#include "IXSocketServer.h" +#include "IXWebSocket.h" +#include +#include +#include +#include +#include +#include +#include // pair + +namespace ix +{ +class HttpServer final : public SocketServer +{ +public: + using OnConnectionCallback = + std::function)>; + + HttpServer(int port = SocketServer::kDefaultPort, + const std::string &host = SocketServer::kDefaultHost, + int backlog = SocketServer::kDefaultTcpBacklog, + size_t maxConnections = SocketServer::kDefaultMaxConnections, + int addressFamily = SocketServer::kDefaultAddressFamily, + int timeoutSecs = HttpServer::kDefaultTimeoutSecs); + virtual ~HttpServer(); + virtual void stop() final; + + void setOnConnectionCallback(const OnConnectionCallback &callback); + + void makeRedirectServer(const std::string &redirectUrl); + + void makeDebugServer(); + + int getTimeoutSecs(); + +private: + // Member variables + OnConnectionCallback _onConnectionCallback; + std::atomic _connectedClientsCount; + + const static int kDefaultTimeoutSecs; + int _timeoutSecs; + + // Methods + virtual void handleConnection( + std::unique_ptr, + std::shared_ptr connectionState) final; + virtual size_t getConnectedClientsCount() final; + + void setDefaultConnectionCallback(); +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXNetSystem.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXNetSystem.h new file mode 100644 index 0000000..3b1258d --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXNetSystem.h @@ -0,0 +1,87 @@ +/* + * IXNetSystem.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone. All rights reserved. + */ + +#pragma once + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include +#include + +#undef EWOULDBLOCK +#undef EAGAIN +#undef EINPROGRESS +#undef EBADF +#undef EINVAL + +// map to WSA error codes +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EAGAIN WSATRY_AGAIN +#define EINPROGRESS WSAEINPROGRESS +#define EBADF WSAEBADF +#define EINVAL WSAEINVAL + +// Define our own poll on Windows, as a wrapper on top of select +typedef unsigned long int nfds_t; + +// pollfd is not defined by some versions of mingw64 since _WIN32_WINNT is too +// low +#if _WIN32_WINNT < 0x0600 +struct pollfd { + int fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ +}; + +#define POLLIN 0x001 /* There is data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ +#endif + +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include + +namespace ix +{ +#ifdef _WIN32 +typedef SOCKET socket_t; +#else +typedef int socket_t; +#endif + +bool initNetSystem(); +bool uninitNetSystem(); + +int poll(struct pollfd *fds, nfds_t nfds, int timeout); + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); +int inet_pton(int af, const char *src, void *dst); + +unsigned short network_to_host_short(unsigned short value); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXProgressCallback.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXProgressCallback.h new file mode 100644 index 0000000..c8b992a --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXProgressCallback.h @@ -0,0 +1,14 @@ +/* + * IXProgressCallback.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +using OnProgressCallback = std::function; +} diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterrupt.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterrupt.h new file mode 100644 index 0000000..d1d2350 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterrupt.h @@ -0,0 +1,34 @@ +/* + * IXSelectInterrupt.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include +#include + +namespace ix +{ +class SelectInterrupt +{ +public: + SelectInterrupt(); + virtual ~SelectInterrupt(); + + virtual bool init(std::string &errorMsg); + + virtual bool notify(uint64_t value); + virtual bool clear(); + virtual uint64_t read(); + virtual int getFd() const; + + // Used as special codes for pipe communication + static const uint64_t kSendRequest; + static const uint64_t kCloseRequest; +}; + +using SelectInterruptPtr = std::unique_ptr; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterruptFactory.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterruptFactory.h new file mode 100644 index 0000000..cf9a9d2 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterruptFactory.h @@ -0,0 +1,16 @@ +/* + * IXSelectInterruptFactory.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +class SelectInterrupt; +using SelectInterruptPtr = std::unique_ptr; +SelectInterruptPtr createSelectInterrupt(); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterruptPipe.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterruptPipe.h new file mode 100644 index 0000000..6eaacff --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSelectInterruptPipe.h @@ -0,0 +1,40 @@ +/* + * IXSelectInterruptPipe.h + * Author: Benjamin Sergeant + * Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXSelectInterrupt.h" +#include +#include +#include + +namespace ix +{ +class SelectInterruptPipe final : public SelectInterrupt +{ +public: + SelectInterruptPipe(); + virtual ~SelectInterruptPipe(); + + bool init(std::string &errorMsg) final; + + bool notify(uint64_t value) final; + bool clear() final; + uint64_t read() final; + int getFd() const final; + +private: + // Store file descriptors used by the communication pipe. Communication + // happens between a control thread and a background thread, which is + // blocked on select. + int _fildes[2]; + mutable std::mutex _fildesMutex; + + // Used to identify the read/write idx + static const int kPipeReadIndex; + static const int kPipeWriteIndex; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSetThreadName.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSetThreadName.h new file mode 100644 index 0000000..1a60bb3 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSetThreadName.h @@ -0,0 +1,12 @@ +/* + * IXSetThreadName.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ +#pragma once +#include + +namespace ix +{ +void setThreadName(const std::string &name); +} diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocket.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocket.h new file mode 100644 index 0000000..da94916 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocket.h @@ -0,0 +1,97 @@ +/* + * IXSocket.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#ifndef _SSIZE_T_DEFINED +#include +typedef SSIZE_T ssize_t; +#endif +#endif + +#include "IXCancellationRequest.h" +#include "IXProgressCallback.h" +#include "IXSelectInterrupt.h" + +namespace ix +{ +enum class PollResultType { + ReadyForRead = 0, + ReadyForWrite = 1, + Timeout = 2, + Error = 3, + SendRequest = 4, + CloseRequest = 5 +}; + +class Socket +{ +public: + Socket(int fd = -1); + virtual ~Socket(); + bool init(std::string &errorMsg); + + // Functions to check whether there is activity on the socket + PollResultType poll(int timeoutMs = kDefaultPollTimeout); + bool wakeUpFromPoll(uint64_t wakeUpCode); + + PollResultType isReadyToWrite(int timeoutMs); + PollResultType isReadyToRead(int timeoutMs); + + // Virtual methods + virtual bool accept(std::string &errMsg); + + virtual bool connect(const std::string &host, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested); + virtual void close(); + + virtual ssize_t send(char *buffer, size_t length); + ssize_t send(const std::string &buffer); + virtual ssize_t recv(void *buffer, size_t length); + + // Blocking and cancellable versions, working with socket that can be set + // to non blocking mode. Used during HTTP upgrade. + bool readByte(void *buffer, + const CancellationRequest &isCancellationRequested); + bool writeBytes(const std::string &str, + const CancellationRequest &isCancellationRequested); + + std::pair + readLine(const CancellationRequest &isCancellationRequested); + std::pair + readBytes(size_t length, + const OnProgressCallback &onProgressCallback, + const CancellationRequest &isCancellationRequested); + + static int getErrno(); + static bool isWaitNeeded(); + static void closeSocket(int fd); + + static PollResultType poll(bool readyToRead, + int timeoutMs, + int sockfd, + const SelectInterruptPtr &selectInterrupt); + +protected: + std::atomic _sockfd; + std::mutex _socketMutex; + +private: + static const int kDefaultPollTimeout; + static const int kDefaultPollNoTimeout; + + SelectInterruptPtr _selectInterrupt; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketAppleSSL.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketAppleSSL.h new file mode 100644 index 0000000..47ef8d6 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketAppleSSL.h @@ -0,0 +1,56 @@ +/* + * IXSocketAppleSSL.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved. + */ +#ifdef IXWEBSOCKET_USE_SECURE_TRANSPORT + +#pragma once + +#include "IXCancellationRequest.h" +#include "IXSocket.h" +#include "IXSocketTLSOptions.h" +#include +#include +#include + +namespace ix +{ +class SocketAppleSSL final : public Socket +{ +public: + SocketAppleSSL(const SocketTLSOptions &tlsOptions, int fd = -1); + ~SocketAppleSSL(); + + virtual bool accept(std::string &errMsg) final; + + virtual bool + connect(const std::string &host, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) final; + virtual void close() final; + + virtual ssize_t send(char *buffer, size_t length) final; + virtual ssize_t recv(void *buffer, size_t length) final; + +private: + static std::string getSSLErrorDescription(OSStatus status); + static OSStatus writeToSocket(SSLConnectionRef connection, + const void *data, + size_t *len); + static OSStatus + readFromSocket(SSLConnectionRef connection, void *data, size_t *len); + + OSStatus tlsHandShake(std::string &errMsg, + const CancellationRequest &isCancellationRequested); + + SSLContextRef _sslContext; + mutable std::mutex _mutex; // AppleSSL routines are not thread-safe + + SocketTLSOptions _tlsOptions; +}; + +} // namespace ix + +#endif // IXWEBSOCKET_USE_SECURE_TRANSPORT diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketConnect.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketConnect.h new file mode 100644 index 0000000..71aac82 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketConnect.h @@ -0,0 +1,32 @@ +/* + * IXSocketConnect.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXCancellationRequest.h" +#include + +struct addrinfo; + +namespace ix +{ +class SocketConnect +{ +public: + static int connect(const std::string &hostname, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested); + + static void configure(int sockfd); + +private: + static int + connectToAddress(const struct addrinfo *address, + std::string &errMsg, + const CancellationRequest &isCancellationRequested); +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketFactory.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketFactory.h new file mode 100644 index 0000000..5e92bc6 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketFactory.h @@ -0,0 +1,21 @@ + +/* + * IXSocketFactory.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXSocketTLSOptions.h" +#include +#include + +namespace ix +{ +class Socket; +std::unique_ptr createSocket(bool tls, + int fd, + std::string &errorMsg, + const SocketTLSOptions &tlsOptions); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketMbedTLS.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketMbedTLS.h new file mode 100644 index 0000000..8af50fc --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketMbedTLS.h @@ -0,0 +1,61 @@ +/* + * IXSocketMbedTLS.h + * Author: Benjamin Sergeant + * Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved. + */ +#ifdef IXWEBSOCKET_USE_MBED_TLS + +#pragma once + +#include "IXSocket.h" +#include "IXSocketTLSOptions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ix +{ +class SocketMbedTLS final : public Socket +{ +public: + SocketMbedTLS(const SocketTLSOptions &tlsOptions, int fd = -1); + ~SocketMbedTLS(); + + virtual bool accept(std::string &errMsg) final; + + virtual bool + connect(const std::string &host, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) final; + virtual void close() final; + + virtual ssize_t send(char *buffer, size_t length) final; + virtual ssize_t recv(void *buffer, size_t length) final; + +private: + mbedtls_ssl_context _ssl; + mbedtls_ssl_config _conf; + mbedtls_entropy_context _entropy; + mbedtls_ctr_drbg_context _ctr_drbg; + mbedtls_x509_crt _cacert; + mbedtls_x509_crt _cert; + mbedtls_pk_context _pkey; + + std::mutex _mutex; + SocketTLSOptions _tlsOptions; + + bool init(const std::string &host, bool isClient, std::string &errMsg); + void initMBedTLS(); + bool loadSystemCertificates(std::string &errMsg); +}; + +} // namespace ix + +#endif // IXWEBSOCKET_USE_MBED_TLS diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketOpenSSL.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketOpenSSL.h new file mode 100644 index 0000000..977fbc6 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketOpenSSL.h @@ -0,0 +1,75 @@ +/* + * IXSocketOpenSSL.h + * Author: Benjamin Sergeant, Matt DeBoer + * Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved. + */ +#ifdef IXWEBSOCKET_USE_OPEN_SSL + +#pragma once + +#include "IXCancellationRequest.h" +#include "IXSocket.h" +#include "IXSocketTLSOptions.h" +#include +#include +#include +#include +#include +#include + +namespace ix +{ +class SocketOpenSSL final : public Socket +{ +public: + SocketOpenSSL(const SocketTLSOptions &tlsOptions, int fd = -1); + ~SocketOpenSSL(); + + virtual bool accept(std::string &errMsg) final; + + virtual bool + connect(const std::string &host, + int port, + std::string &errMsg, + const CancellationRequest &isCancellationRequested) final; + virtual void close() final; + + virtual ssize_t send(char *buffer, size_t length) final; + virtual ssize_t recv(void *buffer, size_t length) final; + +private: + void openSSLInitialize(); + std::string getSSLError(int ret); + SSL_CTX *openSSLCreateContext(std::string &errMsg); + bool openSSLAddCARootsFromString(const std::string roots); + bool openSSLClientHandshake( + const std::string &hostname, + std::string &errMsg, + const CancellationRequest &isCancellationRequested); + bool openSSLCheckServerCert(SSL *ssl, + const std::string &hostname, + std::string &errMsg); + bool checkHost(const std::string &host, const char *pattern); + bool handleTLSOptions(std::string &errMsg); + bool openSSLServerHandshake(std::string &errMsg); + + // Required for OpenSSL < 1.1 + static void openSSLLockingCallback(int mode, + int type, + const char * /*file*/, + int /*line*/); + + SSL *_ssl_connection; + SSL_CTX *_ssl_context; + const SSL_METHOD *_ssl_method; + SocketTLSOptions _tlsOptions; + + mutable std::mutex _mutex; // OpenSSL routines are not thread-safe + + static std::once_flag _openSSLInitFlag; + static std::atomic _openSSLInitializationSuccessful; +}; + +} // namespace ix + +#endif // IXWEBSOCKET_USE_OPEN_SSL diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketServer.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketServer.h new file mode 100644 index 0000000..2ec6a4e --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketServer.h @@ -0,0 +1,134 @@ +/* + * IXSocketServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXConnectionState.h" +#include "IXNetSystem.h" +#include "IXSelectInterrupt.h" +#include "IXSocketTLSOptions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // pair + +namespace ix +{ +class Socket; + +class SocketServer +{ +public: + using ConnectionStateFactory = + std::function()>; + + // Each connection is handled by its own worker thread. + // We use a list as we only care about remove and append operations. + using ConnectionThreads = + std::list, std::thread>>; + + SocketServer(int port = SocketServer::kDefaultPort, + const std::string &host = SocketServer::kDefaultHost, + int backlog = SocketServer::kDefaultTcpBacklog, + size_t maxConnections = SocketServer::kDefaultMaxConnections, + int addressFamily = SocketServer::kDefaultAddressFamily); + virtual ~SocketServer(); + virtual void stop(); + + // It is possible to override ConnectionState through inheritance + // this method allows user to change the factory by returning an object + // that inherits from ConnectionState but has its own methods. + void setConnectionStateFactory( + const ConnectionStateFactory &connectionStateFactory); + + const static int kDefaultPort; + const static std::string kDefaultHost; + const static int kDefaultTcpBacklog; + const static size_t kDefaultMaxConnections; + const static int kDefaultAddressFamily; + + void start(); + std::pair listen(); + void wait(); + + void setTLSOptions(const SocketTLSOptions &socketTLSOptions); + + int getPort(); + std::string getHost(); + int getBacklog(); + std::size_t getMaxConnections(); + int getAddressFamily(); + +protected: + // Logging + void logError(const std::string &str); + void logInfo(const std::string &str); + + void stopAcceptingConnections(); + +private: + // Member variables + int _port; + std::string _host; + int _backlog; + size_t _maxConnections; + int _addressFamily; + + // socket for accepting connections + socket_t _serverFd; + + std::atomic _stop; + + std::mutex _logMutex; + + // background thread to wait for incoming connections + std::thread _thread; + void run(); + void onSetTerminatedCallback(); + + // background thread to cleanup (join) terminated threads + std::atomic _stopGc; + std::thread _gcThread; + void runGC(); + + // the list of (connectionState, threads) for each connections + ConnectionThreads _connectionsThreads; + std::mutex _connectionsThreadsMutex; + + // used to have the main control thread for a server + // wait for a 'terminate' notification without busy polling + std::condition_variable _conditionVariable; + std::mutex _conditionVariableMutex; + + // the factory to create ConnectionState objects + ConnectionStateFactory _connectionStateFactory; + + virtual void + handleConnection(std::unique_ptr, + std::shared_ptr connectionState) = 0; + virtual size_t getConnectedClientsCount() = 0; + + // Returns true if all connection threads are joined + void closeTerminatedThreads(); + size_t getConnectionsThreadsCount(); + + SocketTLSOptions _socketTLSOptions; + + // to wake up from select + SelectInterruptPtr _acceptSelectInterrupt; + + // used by the gc thread, to know that a thread needs to be garbage + // collected as a connection + std::condition_variable _conditionVariableGC; + std::mutex _conditionVariableMutexGC; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketTLSOptions.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketTLSOptions.h new file mode 100644 index 0000000..b2ae968 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXSocketTLSOptions.h @@ -0,0 +1,53 @@ +/* + * IXSocketTLSOptions.h + * Author: Matt DeBoer + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +struct SocketTLSOptions { +public: + // check validity of the object + bool isValid() const; + + // the certificate presented to peers + std::string certFile; + + // the key used for signing/encryption + std::string keyFile; + + // the ca certificate (or certificate bundle) file containing + // certificates to be trusted by peers; use 'SYSTEM' to + // leverage the system defaults, use 'NONE' to disable peer verification + std::string caFile = "SYSTEM"; + + // list of ciphers (rsa, etc...) + std::string ciphers = "DEFAULT"; + + // whether tls is enabled, used for server code + bool tls = false; + + bool hasCertAndKey() const; + + bool isUsingSystemDefaults() const; + + bool isUsingInMemoryCAs() const; + + bool isPeerVerifyDisabled() const; + + bool isUsingDefaultCiphers() const; + + const std::string &getErrorMsg() const; + + std::string getDescription() const; + +private: + mutable std::string _errMsg; + mutable bool _validated = false; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXStrCaseCompare.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXStrCaseCompare.h new file mode 100644 index 0000000..5c3d9a4 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXStrCaseCompare.h @@ -0,0 +1,23 @@ +/* + * IXStrCaseCompare.h + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +struct CaseInsensitiveLess { + // Case Insensitive compare_less binary function + struct NocaseCompare { + bool operator()(const unsigned char &c1, const unsigned char &c2) const; + }; + + static bool cmp(const std::string &s1, const std::string &s2); + + bool operator()(const std::string &s1, const std::string &s2) const; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUdpSocket.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUdpSocket.h new file mode 100644 index 0000000..75cef02 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUdpSocket.h @@ -0,0 +1,45 @@ +/* + * IXUdpSocket.h + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include +#include + +#ifdef _WIN32 +#ifndef _SSIZE_T_DEFINED +#include +typedef SSIZE_T ssize_t; +#endif +#endif + +#include "IXNetSystem.h" + +namespace ix +{ +class UdpSocket +{ +public: + UdpSocket(int fd = -1); + ~UdpSocket(); + + // Virtual methods + bool init(const std::string &host, int port, std::string &errMsg); + ssize_t sendto(const std::string &buffer); + ssize_t recvfrom(char *buffer, size_t length); + + void close(); + + static int getErrno(); + static bool isWaitNeeded(); + static void closeSocket(int fd); + +private: + std::atomic _sockfd; + struct sockaddr_in _server; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUniquePtr.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUniquePtr.h new file mode 100644 index 0000000..0fb530a --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUniquePtr.h @@ -0,0 +1,18 @@ +/* + * IXUniquePtr.h + * Author: Benjamin Sergeant + * Copyright (c) 2020 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +template +std::unique_ptr make_unique(Args &&... args) +{ + return std::unique_ptr(new T(std::forward(args)...)); +} +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUrlParser.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUrlParser.h new file mode 100644 index 0000000..e7ed1cc --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUrlParser.h @@ -0,0 +1,23 @@ +/* + * IXUrlParser.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +class UrlParser +{ +public: + static bool parse(const std::string &url, + std::string &protocol, + std::string &host, + std::string &path, + std::string &query, + int &port); +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUserAgent.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUserAgent.h new file mode 100644 index 0000000..7278494 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUserAgent.h @@ -0,0 +1,14 @@ +/* + * IXUserAgent.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +std::string userAgent(); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUtf8Validator.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUtf8Validator.h new file mode 100644 index 0000000..8e8fb87 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUtf8Validator.h @@ -0,0 +1,184 @@ +/* + * The following code is adapted from code originally written by Bjoern + * Hoehrmann . See + * http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + * + * The original license: + * + * Copyright (c) 2008-2009 Bjoern Hoehrmann + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * IXUtf8Validator.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + * + * From websocketpp. Tiny modifications made for code style, function names + * etc... + */ + +#pragma once + +#include +#include + +namespace ix +{ +/// State that represents a valid utf8 input sequence +static unsigned int const utf8_accept = 0; +/// State that represents an invalid utf8 input sequence +static unsigned int const utf8_reject = 1; + +/// Lookup table for the UTF8 decode state machine +static uint8_t const utf8d[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df + 0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef + 0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, + 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff + 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, + 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 + 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 + 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8 +}; + +/// Decode the next byte of a UTF8 sequence +/** + * @param [out] state The decoder state to advance + * @param [out] codep The codepoint to fill in + * @param [in] byte The byte to input + * @return The ending state of the decode operation + */ +inline uint32_t decodeNextByte(uint32_t *state, uint32_t *codep, uint8_t byte) +{ + uint32_t type = utf8d[byte]; + + *codep = (*state != utf8_accept) ? (byte & 0x3fu) | (*codep << 6) + : (0xff >> type) & (byte); + + *state = utf8d[256 + *state * 16 + type]; + return *state; +} + +/// Provides streaming UTF8 validation functionality +class Utf8Validator +{ +public: + /// Construct and initialize the validator + Utf8Validator() : m_state(utf8_accept), m_codepoint(0) {} + + /// Advance the state of the validator with the next input byte + /** + * @param byte The byte to advance the validation state with + * @return Whether or not the byte resulted in a validation error. + */ + bool consume(uint8_t byte) + { + if (decodeNextByte(&m_state, &m_codepoint, byte) == utf8_reject) { + return false; + } + return true; + } + + /// Advance Validator state with input from an iterator pair + /** + * @param begin Input iterator to the start of the input range + * @param end Input iterator to the end of the input range + * @return Whether or not decoding the bytes resulted in a validation error. + */ + template + bool decode(iterator_type begin, iterator_type end) + { + for (iterator_type it = begin; it != end; ++it) { + unsigned int result = decodeNextByte(&m_state, + &m_codepoint, + static_cast(*it)); + + if (result == utf8_reject) { + return false; + } + } + return true; + } + + /// Return whether the input sequence ended on a valid utf8 codepoint + /** + * @return Whether or not the input sequence ended on a valid codepoint. + */ + bool complete() { return m_state == utf8_accept; } + + /// Reset the Validator to decode another message + void reset() + { + m_state = utf8_accept; + m_codepoint = 0; + } + +private: + uint32_t m_state; + uint32_t m_codepoint; +}; + +/// Validate a UTF8 string +/** + * convenience function that creates a Validator, validates a complete string + * and returns the result. + */ +inline bool validateUtf8(std::string const &s) +{ + Utf8Validator v; + if (!v.decode(s.begin(), s.end())) { + return false; + } + return v.complete(); +} + +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUuid.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUuid.h new file mode 100644 index 0000000..f7c70b8 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXUuid.h @@ -0,0 +1,17 @@ +/* + * IXUuid.h + * Author: Benjamin Sergeant + * Copyright (c) 2017 Machine Zone. All rights reserved. + */ +#pragma once + +#include + +namespace ix +{ +/** + * Generate a random uuid + */ +std::string uuid4(); + +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocket.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocket.h new file mode 100644 index 0000000..1e841f0 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocket.h @@ -0,0 +1,174 @@ +/* + * IXWebSocket.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + * + * WebSocket RFC + * https://tools.ietf.org/html/rfc6455 + */ + +#pragma once + +#include "IXProgressCallback.h" +#include "IXSocketTLSOptions.h" +#include "IXWebSocketCloseConstants.h" +#include "IXWebSocketErrorInfo.h" +#include "IXWebSocketHttpHeaders.h" +#include "IXWebSocketMessage.h" +#include "IXWebSocketPerMessageDeflateOptions.h" +#include "IXWebSocketSendInfo.h" +#include "IXWebSocketTransport.h" +#include +#include +#include +#include +#include + +namespace ix +{ +// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants +enum class ReadyState { Connecting = 0, Open = 1, Closing = 2, Closed = 3 }; + +using OnMessageCallback = std::function; + +using OnTrafficTrackerCallback = + std::function; + +class WebSocket +{ +public: + WebSocket(); + ~WebSocket(); + + void setUrl(const std::string &url); + + // send extra headers in client handshake request + void setExtraHeaders(const WebSocketHttpHeaders &headers); + void setPerMessageDeflateOptions( + const WebSocketPerMessageDeflateOptions &perMessageDeflateOptions); + void setTLSOptions(const SocketTLSOptions &socketTLSOptions); + void setPingInterval(int pingIntervalSecs); + void enablePong(); + void disablePong(); + void enablePerMessageDeflate(); + void disablePerMessageDeflate(); + void addSubProtocol(const std::string &subProtocol); + void setHandshakeTimeout(int handshakeTimeoutSecs); + + // Run asynchronously, by calling start and stop. + void start(); + + // stop is synchronous + void stop(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, + const std::string &reason = + WebSocketCloseConstants::kNormalClosureMessage); + + // Run in blocking mode, by connecting first manually, and then calling run. + WebSocketInitResult connect(int timeoutSecs); + void run(); + + // send is in text mode by default + WebSocketSendInfo + send(const std::string &data, + bool binary = false, + const OnProgressCallback &onProgressCallback = nullptr); + WebSocketSendInfo + sendBinary(const std::string &text, + const OnProgressCallback &onProgressCallback = nullptr); + WebSocketSendInfo + sendText(const std::string &text, + const OnProgressCallback &onProgressCallback = nullptr); + WebSocketSendInfo ping(const std::string &text); + + void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, + const std::string &reason = + WebSocketCloseConstants::kNormalClosureMessage); + + void setOnMessageCallback(const OnMessageCallback &callback); + bool isOnMessageCallbackRegistered() const; + static void + setTrafficTrackerCallback(const OnTrafficTrackerCallback &callback); + static void resetTrafficTrackerCallback(); + + ReadyState getReadyState() const; + static std::string readyStateToString(ReadyState readyState); + + const std::string getUrl() const; + const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const; + int getPingInterval() const; + size_t bufferedAmount() const; + + void enableAutomaticReconnection(); + void disableAutomaticReconnection(); + bool isAutomaticReconnectionEnabled() const; + void setMaxWaitBetweenReconnectionRetries( + uint32_t maxWaitBetweenReconnectionRetries); + void setMinWaitBetweenReconnectionRetries( + uint32_t minWaitBetweenReconnectionRetries); + uint32_t getMaxWaitBetweenReconnectionRetries() const; + uint32_t getMinWaitBetweenReconnectionRetries() const; + const std::vector &getSubProtocols(); + +private: + WebSocketSendInfo sendMessage(const std::string &text, + SendMessageKind sendMessageKind, + const OnProgressCallback &callback = nullptr); + + bool isConnected() const; + bool isClosing() const; + void checkConnection(bool firstConnectionAttempt); + static void invokeTrafficTrackerCallback(size_t size, bool incoming); + + // Server + WebSocketInitResult connectToSocket(std::unique_ptr, + int timeoutSecs, + bool enablePerMessageDeflate); + + WebSocketTransport _ws; + + std::string _url; + WebSocketHttpHeaders _extraHeaders; + + WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; + + SocketTLSOptions _socketTLSOptions; + + mutable std::mutex _configMutex; // protect all config variables access + + OnMessageCallback _onMessageCallback; + static OnTrafficTrackerCallback _onTrafficTrackerCallback; + + std::atomic _stop; + std::thread _thread; + std::mutex _writeMutex; + + // Automatic reconnection + std::atomic _automaticReconnection; + static const uint32_t kDefaultMaxWaitBetweenReconnectionRetries; + static const uint32_t kDefaultMinWaitBetweenReconnectionRetries; + uint32_t _maxWaitBetweenReconnectionRetries; + uint32_t _minWaitBetweenReconnectionRetries; + + // Make the sleeping in the automatic reconnection cancellable + std::mutex _sleepMutex; + std::condition_variable _sleepCondition; + + std::atomic _handshakeTimeoutSecs; + static const int kDefaultHandShakeTimeoutSecs; + + // enable or disable PONG frame response to received PING frame + bool _enablePong; + static const bool kDefaultEnablePong; + + // Optional ping and pong timeout + int _pingIntervalSecs; + int _pingTimeoutSecs; + static const int kDefaultPingIntervalSecs; + static const int kDefaultPingTimeoutSecs; + + // Subprotocols + std::vector _subProtocols; + + friend class WebSocketServer; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketCloseConstants.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketCloseConstants.h new file mode 100644 index 0000000..d70dfd5 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketCloseConstants.h @@ -0,0 +1,36 @@ +/* + * IXWebSocketCloseConstants.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ +struct WebSocketCloseConstants { + static const uint16_t kNormalClosureCode; + static const uint16_t kInternalErrorCode; + static const uint16_t kAbnormalCloseCode; + static const uint16_t kProtocolErrorCode; + static const uint16_t kNoStatusCodeErrorCode; + static const uint16_t kInvalidFramePayloadData; + + static const std::string kNormalClosureMessage; + static const std::string kInternalErrorMessage; + static const std::string kAbnormalCloseMessage; + static const std::string kPingTimeoutMessage; + static const std::string kProtocolErrorMessage; + static const std::string kNoStatusCodeErrorMessage; + static const std::string kProtocolErrorReservedBitUsed; + static const std::string kProtocolErrorPingPayloadOversized; + static const std::string kProtocolErrorCodeControlMessageFragmented; + static const std::string kProtocolErrorCodeDataOpcodeOutOfSequence; + static const std::string kProtocolErrorCodeContinuationOpCodeOutOfSequence; + static const std::string kInvalidFramePayloadDataMessage; + static const std::string kInvalidCloseCodeMessage; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketCloseInfo.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketCloseInfo.h new file mode 100644 index 0000000..fd6abc8 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketCloseInfo.h @@ -0,0 +1,27 @@ +/* + * IXWebSocketCloseInfo.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ +struct WebSocketCloseInfo { + uint16_t code; + std::string reason; + bool remote; + + WebSocketCloseInfo(uint16_t c = 0, + const std::string &r = std::string(), + bool rem = false) + : code(c), reason(r), remote(rem) + { + ; + } +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketErrorInfo.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketErrorInfo.h new file mode 100644 index 0000000..07cb8e6 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketErrorInfo.h @@ -0,0 +1,21 @@ +/* + * IXWebSocketErrorInfo.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include +#include + +namespace ix +{ +struct WebSocketErrorInfo { + uint32_t retries = 0; + double wait_time = 0; + int http_status = 0; + std::string reason; + bool decompressionError = false; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHandshake.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHandshake.h new file mode 100644 index 0000000..0a86fb8 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHandshake.h @@ -0,0 +1,57 @@ +/* + * IXWebSocketHandshake.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXCancellationRequest.h" +#include "IXSocket.h" +#include "IXWebSocketHttpHeaders.h" +#include "IXWebSocketInitResult.h" +#include "IXWebSocketPerMessageDeflate.h" +#include "IXWebSocketPerMessageDeflateOptions.h" +#include +#include +#include +#include + +namespace ix +{ +class WebSocketHandshake +{ +public: + WebSocketHandshake( + std::atomic &requestInitCancellation, + std::unique_ptr &_socket, + WebSocketPerMessageDeflatePtr &perMessageDeflate, + WebSocketPerMessageDeflateOptions &perMessageDeflateOptions, + std::atomic &enablePerMessageDeflate); + + WebSocketInitResult + clientHandshake(const std::string &url, + const WebSocketHttpHeaders &extraHeaders, + const std::string &host, + const std::string &path, + int port, + int timeoutSecs); + + WebSocketInitResult serverHandshake(int timeoutSecs, + bool enablePerMessageDeflate); + +private: + std::string genRandomString(const int len); + + // Parse HTTP headers + WebSocketInitResult sendErrorResponse(int code, const std::string &reason); + + bool insensitiveStringCompare(const std::string &a, const std::string &b); + + std::atomic &_requestInitCancellation; + std::unique_ptr &_socket; + WebSocketPerMessageDeflatePtr &_perMessageDeflate; + WebSocketPerMessageDeflateOptions &_perMessageDeflateOptions; + std::atomic &_enablePerMessageDeflate; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHandshakeKeyGen.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHandshakeKeyGen.h new file mode 100644 index 0000000..285cbce --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHandshakeKeyGen.h @@ -0,0 +1,174 @@ +// Copyright (c) 2016 Alex Hultman and contributors + +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. + +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: + +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgement in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +#pragma once + +#include +#include +#include +#include + +class WebSocketHandshakeKeyGen +{ + template struct static_for { + void operator()(uint32_t *a, uint32_t *b) + { + static_for()(a, b); + T::template f(a, b); + } + }; + + template struct static_for<0, T> { + void operator()(uint32_t * /*a*/, uint32_t * /*hash*/) {} + }; + + template struct Sha1Loop { + static inline uint32_t rol(uint32_t value, size_t bits) + { + return (value << bits) | (value >> (32 - bits)); + } + static inline uint32_t blk(uint32_t b[16], size_t i) + { + return rol(b[(i + 13) & 15] ^ b[(i + 8) & 15] ^ b[(i + 2) & 15] ^ + b[i], + 1); + } + + template static inline void f(uint32_t *a, uint32_t *b) + { + switch (state) { + case 1: + a[i % 5] += + ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ + a[(1 + i) % 5]) + + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + break; + case 2: + b[i] = blk(b, i); + a[(1 + i) % 5] += + ((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ + a[(2 + i) % 5]) + + b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5); + a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30); + break; + case 3: + b[(i + 4) % 16] = blk(b, (i + 4) % 16); + a[i % 5] += + (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + break; + case 4: + b[(i + 8) % 16] = blk(b, (i + 8) % 16); + a[i % 5] += + (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | + (a[(3 + i) % 5] & a[(2 + i) % 5])) + + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + break; + case 5: + b[(i + 12) % 16] = blk(b, (i + 12) % 16); + a[i % 5] += + (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5); + a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30); + break; + case 6: + b[i] += a[4 - i]; + } + } + }; + + static inline void sha1(uint32_t hash[5], uint32_t b[16]) + { + uint32_t a[5] = {hash[4], hash[3], hash[2], hash[1], hash[0]}; + static_for<16, Sha1Loop<1>>()(a, b); + static_for<4, Sha1Loop<2>>()(a, b); + static_for<20, Sha1Loop<3>>()(a, b); + static_for<20, Sha1Loop<4>>()(a, b); + static_for<20, Sha1Loop<5>>()(a, b); + static_for<5, Sha1Loop<6>>()(a, hash); + } + + static inline void base64(unsigned char *src, char *dst) + { + const char *b64 = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + for (int i = 0; i < 18; i += 3) { + *dst++ = b64[(src[i] >> 2) & 63]; + *dst++ = b64[((src[i] & 3) << 4) | ((src[i + 1] & 240) >> 4)]; + *dst++ = b64[((src[i + 1] & 15) << 2) | ((src[i + 2] & 192) >> 6)]; + *dst++ = b64[src[i + 2] & 63]; + } + *dst++ = b64[(src[18] >> 2) & 63]; + *dst++ = b64[((src[18] & 3) << 4) | ((src[19] & 240) >> 4)]; + *dst++ = b64[((src[19] & 15) << 2)]; + *dst++ = '='; + } + +public: + static inline void generate(const std::string &inputStr, char output[28]) + { + char input[25] = {}; + strncpy(input, inputStr.c_str(), 25 - 1); + input[25 - 1] = '\0'; + + uint32_t b_output[5] = {0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, + 0xc3d2e1f0}; + uint32_t b_input[16] = {0, + 0, + 0, + 0, + 0, + 0, + 0x32353845, + 0x41464135, + 0x2d453931, + 0x342d3437, + 0x44412d39, + 0x3543412d, + 0x43354142, + 0x30444338, + 0x35423131, + 0x80000000}; + + for (int i = 0; i < 6; i++) { + b_input[i] = (input[4 * i + 3] & 0xff) | + (input[4 * i + 2] & 0xff) << 8 | + (input[4 * i + 1] & 0xff) << 16 | + (input[4 * i + 0] & 0xff) << 24; + } + sha1(b_output, b_input); + uint32_t last_b[16] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480}; + sha1(b_output, last_b); + for (int i = 0; i < 5; i++) { + uint32_t tmp = b_output[i]; + char *bytes = (char *)&b_output[i]; + bytes[3] = tmp & 0xff; + bytes[2] = (tmp >> 8) & 0xff; + bytes[1] = (tmp >> 16) & 0xff; + bytes[0] = (tmp >> 24) & 0xff; + } + base64((unsigned char *)b_output, output); + } +}; diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHttpHeaders.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHttpHeaders.h new file mode 100644 index 0000000..b93034f --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketHttpHeaders.h @@ -0,0 +1,25 @@ +/* + * IXWebSocketHttpHeaders.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXCancellationRequest.h" +#include "IXStrCaseCompare.h" +#include +#include +#include + +namespace ix +{ +class Socket; + +using WebSocketHttpHeaders = + std::map; + +std::pair + parseHttpHeaders(std::unique_ptr &socket, + const CancellationRequest &isCancellationRequested); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketInitResult.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketInitResult.h new file mode 100644 index 0000000..414ae0c --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketInitResult.h @@ -0,0 +1,35 @@ +/* + * IXWebSocketInitResult.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXWebSocketHttpHeaders.h" + +namespace ix +{ +struct WebSocketInitResult { + bool success; + int http_status; + std::string errorStr; + WebSocketHttpHeaders headers; + std::string uri; + std::string protocol; + + WebSocketInitResult(bool s = false, + int status = 0, + const std::string &e = std::string(), + WebSocketHttpHeaders h = WebSocketHttpHeaders(), + const std::string &u = std::string()) + { + success = s; + http_status = status; + errorStr = e; + headers = h; + uri = u; + protocol = h["Sec-WebSocket-Protocol"]; + } +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketMessage.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketMessage.h new file mode 100644 index 0000000..006b7f4 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketMessage.h @@ -0,0 +1,55 @@ +/* + * IXWebSocketMessage.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXWebSocketCloseInfo.h" +#include "IXWebSocketErrorInfo.h" +#include "IXWebSocketMessageType.h" +#include "IXWebSocketOpenInfo.h" +#include +#include + +namespace ix +{ +struct WebSocketMessage { + WebSocketMessageType type; + const std::string &str; + size_t wireSize; + WebSocketErrorInfo errorInfo; + WebSocketOpenInfo openInfo; + WebSocketCloseInfo closeInfo; + bool binary; + + WebSocketMessage(WebSocketMessageType t, + const std::string &s, + size_t w, + WebSocketErrorInfo e, + WebSocketOpenInfo o, + WebSocketCloseInfo c, + bool b = false) + : type(t), str(s), wireSize(w), errorInfo(e), openInfo(o), closeInfo(c), + binary(b) + { + ; + } + + /** + * @brief Deleted overload to prevent binding `str` to a temporary, which + * would cause undefined behavior since class members don't extend lifetime + * beyond the constructor call. + */ + WebSocketMessage(WebSocketMessageType t, + std::string &&s, + size_t w, + WebSocketErrorInfo e, + WebSocketOpenInfo o, + WebSocketCloseInfo c, + bool b = false) = delete; +}; + +using WebSocketMessagePtr = std::unique_ptr; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketMessageType.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketMessageType.h new file mode 100644 index 0000000..6073b9b --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketMessageType.h @@ -0,0 +1,20 @@ +/* + * IXWebSocketMessageType.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +namespace ix +{ +enum class WebSocketMessageType { + Message = 0, + Open = 1, + Close = 2, + Error = 3, + Ping = 4, + Pong = 5, + Fragment = 6 +}; +} diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketOpenInfo.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketOpenInfo.h new file mode 100644 index 0000000..2221323 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketOpenInfo.h @@ -0,0 +1,28 @@ +/* + * IXWebSocketOpenInfo.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXWebSocketHttpHeaders.h" +#include +#include + +namespace ix +{ +struct WebSocketOpenInfo { + std::string uri; + WebSocketHttpHeaders headers; + std::string protocol; + + WebSocketOpenInfo(const std::string &u = std::string(), + const WebSocketHttpHeaders &h = WebSocketHttpHeaders(), + const std::string &p = std::string()) + : uri(u), headers(h), protocol(p) + { + ; + } +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflate.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflate.h new file mode 100644 index 0000000..1b6aa21 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflate.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, Peter Thorson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the WebSocket++ Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + * + * Adapted from websocketpp/extensions/permessage_deflate/enabled.hpp + * (same license as MZ: https://opensource.org/licenses/BSD-3-Clause) + */ + +#pragma once + +#include +#include + +namespace ix +{ +class WebSocketPerMessageDeflateOptions; +class WebSocketPerMessageDeflateCompressor; +class WebSocketPerMessageDeflateDecompressor; + +class WebSocketPerMessageDeflate +{ +public: + WebSocketPerMessageDeflate(); + ~WebSocketPerMessageDeflate(); + + bool + init(const WebSocketPerMessageDeflateOptions &perMessageDeflateOptions); + bool compress(const std::string &in, std::string &out); + bool decompress(const std::string &in, std::string &out); + +private: + std::unique_ptr _compressor; + std::unique_ptr _decompressor; +}; + +using WebSocketPerMessageDeflatePtr = + std::unique_ptr; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflateCodec.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflateCodec.h new file mode 100644 index 0000000..0399817 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflateCodec.h @@ -0,0 +1,60 @@ +/* + * IXWebSocketPerMessageDeflateCodec.h + * Author: Benjamin Sergeant + * Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#ifdef IXWEBSOCKET_USE_ZLIB +#include "zlib.h" +#endif +#include +#include +#include + +namespace ix +{ +class WebSocketPerMessageDeflateCompressor +{ +public: + WebSocketPerMessageDeflateCompressor(); + ~WebSocketPerMessageDeflateCompressor(); + + bool init(uint8_t deflateBits, bool clientNoContextTakeOver); + bool compress(const std::string &in, std::string &out); + bool compress(const std::string &in, std::vector &out); + bool compress(const std::vector &in, std::string &out); + bool compress(const std::vector &in, std::vector &out); + +private: + template bool compressData(const T &in, S &out); + template bool endsWithEmptyUnCompressedBlock(const T &value); + + int _flush; + std::array _compressBuffer; + +#ifdef IXWEBSOCKET_USE_ZLIB + z_stream _deflateState; +#endif +}; + +class WebSocketPerMessageDeflateDecompressor +{ +public: + WebSocketPerMessageDeflateDecompressor(); + ~WebSocketPerMessageDeflateDecompressor(); + + bool init(uint8_t inflateBits, bool clientNoContextTakeOver); + bool decompress(const std::string &in, std::string &out); + +private: + int _flush; + std::array _compressBuffer; + +#ifdef IXWEBSOCKET_USE_ZLIB + z_stream _inflateState; +#endif +}; + +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflateOptions.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflateOptions.h new file mode 100644 index 0000000..4938284 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketPerMessageDeflateOptions.h @@ -0,0 +1,47 @@ +/* + * IXWebSocketPerMessageDeflateOptions.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include + +namespace ix +{ +class WebSocketPerMessageDeflateOptions +{ +public: + WebSocketPerMessageDeflateOptions( + bool enabled = false, + bool clientNoContextTakeover = false, + bool serverNoContextTakeover = false, + uint8_t clientMaxWindowBits = kDefaultClientMaxWindowBits, + uint8_t serverMaxWindowBits = kDefaultServerMaxWindowBits); + + WebSocketPerMessageDeflateOptions(std::string extension); + + std::string generateHeader(); + bool enabled() const; + bool getClientNoContextTakeover() const; + bool getServerNoContextTakeover() const; + uint8_t getServerMaxWindowBits() const; + uint8_t getClientMaxWindowBits() const; + + static bool startsWith(const std::string &str, const std::string &start); + static std::string removeSpaces(const std::string &str); + + static uint8_t const kDefaultClientMaxWindowBits; + static uint8_t const kDefaultServerMaxWindowBits; + +private: + bool _enabled; + bool _clientNoContextTakeover; + bool _serverNoContextTakeover; + uint8_t _clientMaxWindowBits; + uint8_t _serverMaxWindowBits; + + void sanitizeClientMaxWindowBits(); +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketProxyServer.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketProxyServer.h new file mode 100644 index 0000000..b2f0da0 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketProxyServer.h @@ -0,0 +1,24 @@ +/* + * IXWebSocketProxyServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved. + */ +#pragma once + +#include "IXSocketTLSOptions.h" +#include +#include +#include +#include + +namespace ix +{ +using RemoteUrlsMapping = std::map; + +int websocket_proxy_server_main(int port, + const std::string &hostname, + const ix::SocketTLSOptions &tlsOptions, + const std::string &remoteUrl, + const RemoteUrlsMapping &remoteUrlsMapping, + bool verbose); +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketSendInfo.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketSendInfo.h new file mode 100644 index 0000000..78e1116 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketSendInfo.h @@ -0,0 +1,26 @@ +/* + * IXWebSocketSendInfo.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +namespace ix +{ +struct WebSocketSendInfo { + bool success; + bool compressionError; + size_t payloadSize; + size_t wireSize; + + WebSocketSendInfo(bool s = false, + bool c = false, + size_t p = 0, + size_t w = 0) + : success(s), compressionError(c), payloadSize(p), wireSize(w) + { + ; + } +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketServer.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketServer.h new file mode 100644 index 0000000..63bb7f8 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketServer.h @@ -0,0 +1,84 @@ +/* + * IXWebSocketServer.h + * Author: Benjamin Sergeant + * Copyright (c) 2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#include "IXSocketServer.h" +#include "IXWebSocket.h" +#include +#include +#include +#include +#include +#include +#include +#include // pair + +namespace ix +{ +class WebSocketServer : public SocketServer +{ +public: + using OnConnectionCallback = + std::function, + std::shared_ptr)>; + + using OnClientMessageCallback = + std::function, + WebSocket &, + const WebSocketMessagePtr &)>; + + WebSocketServer( + int port = SocketServer::kDefaultPort, + const std::string &host = SocketServer::kDefaultHost, + int backlog = SocketServer::kDefaultTcpBacklog, + size_t maxConnections = SocketServer::kDefaultMaxConnections, + int handshakeTimeoutSecs = + WebSocketServer::kDefaultHandShakeTimeoutSecs, + int addressFamily = SocketServer::kDefaultAddressFamily); + virtual ~WebSocketServer(); + virtual void stop() final; + + void enablePong(); + void disablePong(); + void disablePerMessageDeflate(); + + void setOnConnectionCallback(const OnConnectionCallback &callback); + void setOnClientMessageCallback(const OnClientMessageCallback &callback); + + // Get all the connected clients + std::set> getClients(); + + void makeBroadcastServer(); + bool listenAndStart(); + + const static int kDefaultHandShakeTimeoutSecs; + + int getHandshakeTimeoutSecs(); + bool isPongEnabled(); + bool isPerMessageDeflateEnabled(); + +private: + // Member variables + int _handshakeTimeoutSecs; + bool _enablePong; + bool _enablePerMessageDeflate; + + OnConnectionCallback _onConnectionCallback; + OnClientMessageCallback _onClientMessageCallback; + + std::mutex _clientsMutex; + std::set> _clients; + + const static bool kDefaultEnablePong; + + // Methods + virtual void + handleConnection(std::unique_ptr socket, + std::shared_ptr connectionState); + virtual size_t getConnectedClientsCount() final; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketTransport.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketTransport.h new file mode 100644 index 0000000..e58a66d --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketTransport.h @@ -0,0 +1,261 @@ +/* + * IXWebSocketTransport.h + * Author: Benjamin Sergeant + * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +// +// Adapted from https://github.com/dhbaird/easywsclient +// + +#include "IXCancellationRequest.h" +#include "IXProgressCallback.h" +#include "IXSocketTLSOptions.h" +#include "IXWebSocketCloseConstants.h" +#include "IXWebSocketHandshake.h" +#include "IXWebSocketHttpHeaders.h" +#include "IXWebSocketPerMessageDeflate.h" +#include "IXWebSocketPerMessageDeflateOptions.h" +#include "IXWebSocketSendInfo.h" +#include +#include +#include +#include +#include +#include +#include + +namespace ix +{ +class Socket; + +enum class SendMessageKind { Text, Binary, Ping }; + +class WebSocketTransport +{ +public: + enum class ReadyState { CLOSING, CLOSED, CONNECTING, OPEN }; + + enum class MessageKind { MSG_TEXT, MSG_BINARY, PING, PONG, FRAGMENT }; + + enum class PollResult { Succeeded, AbnormalClose, CannotFlushSendBuffer }; + + using OnMessageCallback = + std::function; + using OnCloseCallback = + std::function; + + WebSocketTransport(); + ~WebSocketTransport(); + + void configure( + const WebSocketPerMessageDeflateOptions &perMessageDeflateOptions, + const SocketTLSOptions &socketTLSOptions, + bool enablePong, + int pingIntervalSecs); + + // Client + WebSocketInitResult connectToUrl(const std::string &url, + const WebSocketHttpHeaders &headers, + int timeoutSecs); + + // Server + WebSocketInitResult connectToSocket(std::unique_ptr socket, + int timeoutSecs, + bool enablePerMessageDeflate); + + PollResult poll(); + WebSocketSendInfo sendBinary(const std::string &message, + const OnProgressCallback &onProgressCallback); + WebSocketSendInfo sendText(const std::string &message, + const OnProgressCallback &onProgressCallback); + WebSocketSendInfo sendPing(const std::string &message); + + void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, + const std::string &reason = + WebSocketCloseConstants::kNormalClosureMessage, + size_t closeWireSize = 0, + bool remote = false); + + void closeSocket(); + + ReadyState getReadyState() const; + void setReadyState(ReadyState readyState); + void setOnCloseCallback(const OnCloseCallback &onCloseCallback); + void dispatch(PollResult pollResult, + const OnMessageCallback &onMessageCallback); + size_t bufferedAmount() const; + + // internal + WebSocketSendInfo sendHeartBeat(); + +private: + std::string _url; + + struct wsheader_type { + unsigned header_size; + bool fin; + bool rsv1; + bool rsv2; + bool rsv3; + bool mask; + enum opcode_type { + CONTINUATION = 0x0, + TEXT_FRAME = 0x1, + BINARY_FRAME = 0x2, + CLOSE = 8, + PING = 9, + PONG = 0xa, + } opcode; + int N0; + uint64_t N; + uint8_t masking_key[4]; + }; + + // Tells whether we should mask the data we send. + // client should mask but server should not + std::atomic _useMask; + + // Tells whether we should flush the send buffer before + // saying that a send is complete. This is the mode for server code. + std::atomic _blockingSend; + + // Buffer for reading from our socket. That buffer is never resized. + std::vector _readbuf; + + // Contains all messages that were fetched in the last socket read. + // This could be a mix of control messages (Close, Ping, etc...) and + // data messages. That buffer is resized + std::vector _rxbuf; + + // Contains all messages that are waiting to be sent + std::vector _txbuf; + mutable std::mutex _txbufMutex; + + // Hold fragments for multi-fragments messages in a list. We support + // receiving very large messages (tested messages up to 700M) and we cannot + // put them in a single buffer that is resized, as this operation can be + // slow when a buffer has its size increased 2 fold, while appending to a + // list has a fixed cost. + std::list _chunks; + + // Record the message kind (will be TEXT or BINARY) for a fragmented + // message, present in the first chunk, since the final chunk will be a + // CONTINUATION opcode and doesn't tell the full message kind + MessageKind _fragmentedMessageKind; + + // Ditto for whether a message is compressed + bool _receivedMessageCompressed; + + // Fragments are 32K long + static constexpr size_t kChunkSize = 1 << 15; + + // Underlying TCP socket + std::unique_ptr _socket; + std::mutex _socketMutex; + + // Hold the state of the connection (OPEN, CLOSED, etc...) + std::atomic _readyState; + + OnCloseCallback _onCloseCallback; + std::string _closeReason; + mutable std::mutex _closeReasonMutex; + std::atomic _closeCode; + std::atomic _closeWireSize; + std::atomic _closeRemote; + + // Data used for Per Message Deflate compression (with zlib) + WebSocketPerMessageDeflatePtr _perMessageDeflate; + WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; + std::atomic _enablePerMessageDeflate; + + std::string _decompressedMessage; + std::string _compressedMessage; + + // Used to control TLS connection behavior + SocketTLSOptions _socketTLSOptions; + + // Used to cancel dns lookup + socket connect + http upgrade + std::atomic _requestInitCancellation; + + mutable std::mutex _closingTimePointMutex; + std::chrono::time_point _closingTimePoint; + static const int kClosingMaximumWaitingDelayInMs; + + // enable auto response to ping + std::atomic _enablePong; + static const bool kDefaultEnablePong; + + // Optional ping and pong timeout + int _pingIntervalSecs; + std::atomic _pongReceived; + + static const int kDefaultPingIntervalSecs; + static const std::string kPingMessage; + std::atomic _pingCount; + + // We record when ping are being sent so that we can know when to send the + // next one + mutable std::mutex _lastSendPingTimePointMutex; + std::chrono::time_point _lastSendPingTimePoint; + + // If this function returns true, it is time to send a new ping + bool pingIntervalExceeded(); + void initTimePointsAfterConnect(); + + // after calling close(), if no CLOSE frame answer is received back from the + // remote, we should close the connexion + bool closingDelayExceeded(); + + void sendCloseFrame(uint16_t code, const std::string &reason); + + void closeSocketAndSwitchToClosedState(uint16_t code, + const std::string &reason, + size_t closeWireSize, + bool remote); + + bool wakeUpFromPoll(uint64_t wakeUpCode); + + bool flushSendBuffer(); + bool sendOnSocket(); + bool receiveFromSocket(); + + template + WebSocketSendInfo + sendData(wsheader_type::opcode_type type, + const T &message, + bool compress, + const OnProgressCallback &onProgressCallback = nullptr); + + template + bool sendFragment(wsheader_type::opcode_type type, + bool fin, + Iterator begin, + Iterator end, + bool compress); + + void emitMessage(MessageKind messageKind, + const std::string &message, + bool compressedMessage, + const OnMessageCallback &onMessageCallback); + + bool isSendBufferEmpty() const; + + template + void appendToSendBuffer(const std::vector &header, + Iterator begin, + Iterator end, + uint64_t message_size, + uint8_t masking_key[4]); + + unsigned getRandomUnsigned(); + void unmaskReceiveBuffer(const wsheader_type &ws); + + std::string getMergedChunks() const; + + void setCloseReason(const std::string &reason); + const std::string &getCloseReason() const; +}; +} // namespace ix diff --git a/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketVersion.h b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketVersion.h new file mode 100644 index 0000000..ccaec84 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/ixwebsocket/include/IXWebSocketVersion.h @@ -0,0 +1,9 @@ +/* + * IXWebSocketVersion.h + * Author: Benjamin Sergeant + * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. + */ + +#pragma once + +#define IX_WEBSOCKET_VERSION "11.3.2" diff --git a/GermanAirlinesVA-GAConnector/nlohmann/License.txt b/GermanAirlinesVA-GAConnector/nlohmann/License.txt new file mode 100644 index 0000000..d8a3085 --- /dev/null +++ b/GermanAirlinesVA-GAConnector/nlohmann/License.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2021 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/GermanAirlinesVA-GAConnector/nlohmann/json.hpp b/GermanAirlinesVA-GAConnector/nlohmann/json.hpp new file mode 100644 index 0000000..d3aafeb --- /dev/null +++ b/GermanAirlinesVA-GAConnector/nlohmann/json.hpp @@ -0,0 +1,31780 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.10.4 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2019 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 10 +#define NLOHMANN_JSON_VERSION_PATCH 4 + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO +#include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include + + +#include +#include + +// #include + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include + + +#include // exception +#include // runtime_error +#include // to_string +#include // vector + +// #include + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +namespace nlohmann +{ +namespace detail +{ +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t { + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + static constexpr std::array order = {{ + 0 /* null */, + 3 /* object */, + 4 /* array */, + 5 /* string */, + 1 /* boolean */, + 2 /* integer */, + 2 /* unsigned */, + 2 /* float */, + 6 /* binary */ + }}; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); + return l_index < order.size() && r_index < order.size() && + order[l_index] < order[r_index]; +} +} // namespace detail +} // namespace nlohmann + +// #include + + +#include +// #include + + +#include // declval, pair +// #include + + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) +#undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) +#undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) +#undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) +#undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a, b) a##b + +#if defined(JSON_HEDLEY_CONCAT) +#undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a, b) JSON_HEDLEY_CONCAT_EX(a, b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) +#undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a, b, c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) +#undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a, b, c) JSON_HEDLEY_CONCAT3_EX(a, b, c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) +#undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major, minor, revision) \ + (((major)*1000000) + ((minor)*1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) +#undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) +#undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) +#undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) +#undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) +#define JSON_HEDLEY_GNUC_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) +#define JSON_HEDLEY_GNUC_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) +#undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) +#define JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_GNUC_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) +#undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) +#define JSON_HEDLEY_MSVC_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, \ + (_MSC_FULL_VER % 10000000) / 100000, \ + (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) +#define JSON_HEDLEY_MSVC_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, \ + (_MSC_FULL_VER % 1000000) / 10000, \ + (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) +#define JSON_HEDLEY_MSVC_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) +#undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \ + (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \ + (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \ + (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) +#undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && \ + !defined(__ICL) +#define JSON_HEDLEY_INTEL_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, \ + __INTEL_COMPILER % 100, \ + __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) +#define JSON_HEDLEY_INTEL_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, \ + __INTEL_COMPILER % 100, \ + 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) +#undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) +#define JSON_HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_INTEL_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) +#undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && \ + defined(__ICL) +#define JSON_HEDLEY_INTEL_CL_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) +#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) +#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_INTEL_CL_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) +#undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && \ + defined(__PGIC_PATCHLEVEL__) +#define JSON_HEDLEY_PGI_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) +#undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) +#define JSON_HEDLEY_PGI_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_PGI_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) +#undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) +#define JSON_HEDLEY_SUNPRO_VERSION \ + JSON_HEDLEY_VERSION_ENCODE( \ + (((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \ + (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), \ + (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) +#define JSON_HEDLEY_SUNPRO_VERSION \ + JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, \ + (__SUNPRO_C >> 4) & 0xf, \ + (__SUNPRO_C)&0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) +#define JSON_HEDLEY_SUNPRO_VERSION \ + JSON_HEDLEY_VERSION_ENCODE( \ + (((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \ + (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), \ + (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) +#define JSON_HEDLEY_SUNPRO_VERSION \ + JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, \ + (__SUNPRO_CC >> 4) & 0xf, \ + (__SUNPRO_CC)&0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) +#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) +#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_SUNPRO_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) +#define JSON_HEDLEY_EMSCRIPTEN_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, \ + __EMSCRIPTEN_minor__, \ + __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) +#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_EMSCRIPTEN_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) +#undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) +#define JSON_HEDLEY_ARM_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, \ + (__ARMCOMPILER_VERSION % 1000000) / 10000, \ + (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) +#define JSON_HEDLEY_ARM_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, \ + (__ARMCC_VERSION % 1000000) / 10000, \ + (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) +#undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) +#define JSON_HEDLEY_ARM_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_ARM_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) +#undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) +#define JSON_HEDLEY_IBM_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, \ + __ibmxl_release__, \ + __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) +#define JSON_HEDLEY_IBM_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, \ + __xlC__ & 0xff, \ + (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) +#define JSON_HEDLEY_IBM_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) +#undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) +#define JSON_HEDLEY_IBM_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_IBM_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) +#undef JSON_HEDLEY_TI_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && \ + (defined(__TMS470__) || defined(__TI_ARM__) || defined(__MSP430__) || \ + defined(__TMS320C2000__)) +#if (__TI_COMPILER_VERSION__ >= 16000000) +#define JSON_HEDLEY_TI_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \ + (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ + (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) +#undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) +#define JSON_HEDLEY_TI_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TI_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) +#undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) +#define JSON_HEDLEY_TI_CL2000_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \ + (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ + (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) +#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) +#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_TI_CL2000_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) +#undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) +#define JSON_HEDLEY_TI_CL430_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \ + (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ + (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) +#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) +#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_TI_CL430_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) +#undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && \ + (defined(__TMS470__) || defined(__TI_ARM__)) +#define JSON_HEDLEY_TI_ARMCL_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \ + (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ + (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) +#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) +#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_TI_ARMCL_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) +#undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) +#define JSON_HEDLEY_TI_CL6X_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \ + (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ + (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) +#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) +#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_TI_CL6X_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) +#undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) +#define JSON_HEDLEY_TI_CL7X_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \ + (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ + (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) +#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) +#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_TI_CL7X_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) +#undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) +#define JSON_HEDLEY_TI_CLPRU_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \ + (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ + (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) +#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) +#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_TI_CLPRU_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) +#undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) +#if defined(_RELEASE_PATCHLEVEL) +#define JSON_HEDLEY_CRAY_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, \ + _RELEASE_MINOR, \ + _RELEASE_PATCHLEVEL) +#else +#define JSON_HEDLEY_CRAY_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) +#endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) +#undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) +#define JSON_HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_CRAY_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) +#undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) +#if __VER__ > 1000 +#define JSON_HEDLEY_IAR_VERSION \ + JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), \ + ((__VER__ / 1000) % 1000), \ + (__VER__ % 1000)) +#else +#define JSON_HEDLEY_IAR_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) +#endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) +#undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) +#define JSON_HEDLEY_IAR_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_IAR_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) +#undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) +#define JSON_HEDLEY_TINYC_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, \ + (__TINYC__ / 100) % 10, \ + __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) +#undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) +#define JSON_HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_TINYC_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) +#undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) +#define JSON_HEDLEY_DMC_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, \ + (__DMC__ >> 4) & 0xf, \ + __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) +#undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) +#define JSON_HEDLEY_DMC_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_DMC_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) +#undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) +#define JSON_HEDLEY_COMPCERT_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, \ + (__COMPCERT_VERSION__ / 100) % 100, \ + __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) +#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) +#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_COMPCERT_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) +#undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) +#define JSON_HEDLEY_PELLES_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) +#undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) +#define JSON_HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_PELLES_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) +#undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) +#define JSON_HEDLEY_MCST_LCC_VERSION \ + JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) +#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) +#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_MCST_LCC_VERSION >= \ + JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) +#undef JSON_HEDLEY_GCC_VERSION +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) && !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) +#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) +#undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) +#define JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) \ + (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) +#undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) && ((!defined(JSON_HEDLEY_IAR_VERSION) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 5, 9))) +#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) +#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) +#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ + JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else +#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ + JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) +#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) +#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ + JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else +#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ + JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0)) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) (0) +#elif !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(19, 20, 0)) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) \ + JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) +#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) +#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \ + __has_cpp_attribute(attribute) +#else +#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \ + JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) +#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) +#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \ + __has_cpp_attribute(attribute) +#else +#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \ + JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) +#undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) +#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else +#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) +#undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) +#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \ + __has_builtin(builtin) +#else +#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \ + JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) +#undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) +#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) \ + __has_builtin(builtin) +#else +#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) \ + JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) +#undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) +#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else +#define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) +#undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) +#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) \ + __has_feature(feature) +#else +#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) \ + JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) +#undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) +#define JSON_HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) \ + __has_feature(feature) +#else +#define JSON_HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) \ + JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) +#undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) +#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else +#define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) +#undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) +#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) \ + __has_extension(extension) +#else +#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) \ + JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) +#undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) +#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) \ + __has_extension(extension) +#else +#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) \ + JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) +#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) \ + __has_declspec_attribute(attribute) +#else +#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) +#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, \ + major, \ + minor, \ + patch) \ + __has_declspec_attribute(attribute) +#else +#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, \ + major, \ + minor, \ + patch) \ + JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) +#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \ + __has_declspec_attribute(attribute) +#else +#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \ + JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) +#undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) +#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else +#define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) +#undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) +#define JSON_HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) \ + __has_warning(warning) +#else +#define JSON_HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) \ + JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) +#undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) +#define JSON_HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) \ + __has_warning(warning) +#else +#define JSON_HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) \ + JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) +#endif + +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18, 4, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 0, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5, 0, 0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8, 0, 0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) && \ + defined(__C99_PRAGMA_OPERATOR)) +#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) +#define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else +#define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) +#undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) +#undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) +#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 4, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 90, 0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else +#define JSON_HEDLEY_DIAGNOSTIC_PUSH +#define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +#if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +#if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr JSON_HEDLEY_DIAGNOSTIC_POP +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) +#undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +#define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_CONST_CAST(T, expr) \ + (__extension__({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL((T)(expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +#define JSON_HEDLEY_CONST_CAST(T, expr) ((T)(expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) +#undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) +#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else +#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T)(expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) +#undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) +#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else +#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T)(expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) +#undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +#if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +#define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"")((T)(expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 3, 0) +#define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") JSON_HEDLEY_DIAGNOSTIC_POP +#else +#define JSON_HEDLEY_CPP_CAST(T, expr) ((T)(expr)) +#endif +#else +#define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + __pragma(warning(disable : 1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20, 7, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + __pragma(warning(disable : 4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) && !defined(__cplusplus) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) && defined(__cplusplus) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \ + _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 90, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + __pragma(warning(disable : 161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + __pragma(warning(disable : 4068)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(16, 9, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + _Pragma("diag_suppress 161") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + __pragma(warning(disable : 1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + __pragma(warning(disable : 5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20, 7, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("error_messages(off,attrskipunsup)") +#elif JSON_HEDLEY_TI_VERSION_CHECK(18, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 3, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \ + _Pragma("diag_suppress 1097") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION \ + _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION \ + _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION \ + __pragma(warning(disable : 4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION \ + _Pragma("diag_suppress 3142") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) +#undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) +#undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " #since)) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \ + __declspec(deprecated("Since " #since "; use " #replacement)) +#elif (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18, 1, 0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 3, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_DEPRECATED(since) \ + __attribute__((__deprecated__("Since " #since))) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \ + __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) +#define JSON_HEDLEY_DEPRECATED(since) \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_( \ + [[deprecated("Since " #since)]]) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_( \ + [[deprecated("Since " #since "; use " #replacement)]]) +#elif JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0) +#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \ + __attribute__((__deprecated__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6, 50, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else +#define JSON_HEDLEY_DEPRECATED(since) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) +#undef JSON_HEDLEY_UNAVAILABLE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_UNAVAILABLE(available_since) \ + __attribute__((__warning__("Not available until " #available_since))) +#else +#define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) +#undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) +#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) \ + __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) +#define JSON_HEDLEY_WARN_UNUSED_RESULT \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) +#define JSON_HEDLEY_WARN_UNUSED_RESULT \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ +#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ +#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else +#define JSON_HEDLEY_WARN_UNUSED_RESULT +#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) +#undef JSON_HEDLEY_SENTINEL +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5, 4, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else +#define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) +#undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_NO_RETURN __noreturn +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) +#define JSON_HEDLEY_NO_RETURN \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 2, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0) +#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) +#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 0, 0) && defined(__cplusplus) +#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3, 2, 0) +#define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9, 0, 0) +#define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else +#define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) +#undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) +#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else +#define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) +#undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) +#undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) +#undef JSON_HEDLEY_ASSUME +#endif +#if JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) +#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) +#if defined(__cplusplus) +#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) +#else +#define JSON_HEDLEY_ASSUME(expr) _nassert(expr) +#endif +#endif +#if (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && \ + (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18, 10, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10, 0, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) +#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) +#if defined(JSON_HEDLEY_UNREACHABLE) +#define JSON_HEDLEY_ASSUME(expr) \ + JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) +#else +#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) +#endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) +#if JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) \ + return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) +#else +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() +#endif +#else +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) +#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") +#pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros", 4, 0, 0) +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wvariadic-macros" +#elif defined(JSON_HEDLEY_GCC_VERSION) +#pragma GCC diagnostic ignored "-Wvariadic-macros" +#endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) +#undef JSON_HEDLEY_NON_NULL +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) +#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else +#define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) +#undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && \ + !defined(__USE_MINGW_ANSI_STDIO) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \ + __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && \ + JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && \ + defined(__USE_MINGW_ANSI_STDIO) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \ + __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \ + __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6, 0, 0) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \ + __declspec(vaformat(printf, string_idx, first_to_check)) +#else +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) +#undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) +#if __cplusplus >= 201103L +#define JSON_HEDLEY_CONSTEXPR \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) +#endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) +#define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) +#undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) +#undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) +#undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) +#undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) +#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && \ + !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9, 0, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_PREDICT(expr, value, probability) \ + __builtin_expect_with_probability((expr), (value), (probability)) +#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + __builtin_expect_with_probability(!!(expr), 1, (probability)) +#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + __builtin_expect_with_probability(!!(expr), 0, (probability)) +#define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +#define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#elif (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && \ + !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) \ + ? __builtin_expect((expr), (expected)) \ + : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) \ + ? __builtin_expect(!!(expr), 1) \ + : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) \ + : !!(expr))); \ + })) +#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) \ + ? __builtin_expect(!!(expr), 0) \ + : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) \ + : !!(expr))); \ + })) +#define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +#define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +#define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +#define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +#define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) +#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) +#undef JSON_HEDLEY_MALLOC +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) +#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_MALLOC __declspec(restrict) +#else +#define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) +#undef JSON_HEDLEY_PURE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2, 96, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) +#define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && (JSON_HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0)) +#define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +#define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) +#undef JSON_HEDLEY_CONST +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2, 5, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) +#define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else +#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) +#undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__cplusplus) +#define JSON_HEDLEY_RESTRICT restrict +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus) +#define JSON_HEDLEY_RESTRICT _Restrict +#else +#define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) +#undef JSON_HEDLEY_INLINE +#endif +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) +#define JSON_HEDLEY_INLINE inline +#elif defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_ARM_VERSION_CHECK(6, 2, 0) +#define JSON_HEDLEY_INLINE __inline__ +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 1, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_INLINE __inline +#else +#define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) +#undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0) +#define JSON_HEDLEY_ALWAYS_INLINE \ + __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0)) +#define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +#define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) +#undef JSON_HEDLEY_NEVER_INLINE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0) +#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10, 2, 0) +#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 0, 0) && defined(__cplusplus) +#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3, 2, 0) +#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9, 0, 0) +#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else +#define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) +#undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) +#undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) +#undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +#define JSON_HEDLEY_PRIVATE +#define JSON_HEDLEY_PUBLIC __declspec(dllexport) +#define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +#if JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \ + (defined(__TI_EABI__) && ((JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && \ + defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0))) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +#define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +#else +#define JSON_HEDLEY_PRIVATE +#define JSON_HEDLEY_PUBLIC +#endif +#define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) +#undef JSON_HEDLEY_NO_THROW +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 1, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) +#define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else +#define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) +#undef JSON_HEDLEY_FALL_THROUGH +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7, 0, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang, fallthrough) +#define JSON_HEDLEY_FALL_THROUGH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) +#define JSON_HEDLEY_FALL_THROUGH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ +#define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else +#define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) +#undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ +#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else +#define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) +#undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && !defined(JSON_HEDLEY_TINYC_VERSION) +#define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else +#define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) +#undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) +#undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) +#undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) +#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5, 4, 0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 24) +#if defined(__INTPTR_TYPE__) +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \ + __builtin_types_compatible_p( \ + __typeof__((1 ? (void *)((__INTPTR_TYPE__)((expr)*0)) : (int *)0)), \ + int *) +#else +#include +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \ + __builtin_types_compatible_p( \ + __typeof__((1 ? (void *)((intptr_t)((expr)*0)) : (int *)0)), \ + int *) +#endif +#elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17, 0, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12, 1, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5, 3, 0) +#if defined(__INTPTR_TYPE__) +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \ + _Generic((1 ? (void *)((__INTPTR_TYPE__)((expr)*0)) : (int *)0), \ + int * : 1, \ + void * : 0) +#else +#include +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \ + _Generic((1 ? (void *)((intptr_t)*0) : (int *)0), int * : 1, void * : 0) +#endif +#elif defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18, 12, 0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || defined(__clang__) +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \ + (sizeof(void) != sizeof(*(1 ? ((void *)((expr)*0L)) : ((struct { \ + char v[sizeof(void) * 2]; \ + } *)1)))) +#endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) +#if !defined(JSON_HEDLEY_IS_CONSTANT) +#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) +#endif +#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) \ + (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else +#if !defined(JSON_HEDLEY_IS_CONSTANT) +#define JSON_HEDLEY_IS_CONSTANT(expr) (0) +#endif +#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) +#undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) +#undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) +#undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) +#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { +#define JSON_HEDLEY_END_C_DECLS } +#define JSON_HEDLEY_C_DECL extern "C" +#else +#define JSON_HEDLEY_BEGIN_C_DECLS +#define JSON_HEDLEY_END_C_DECLS +#define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) +#undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if !defined(__cplusplus) && \ + ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && \ + !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || defined(_Static_assert)) +#define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_STATIC_ASSERT(expr, message) \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_( \ + static_assert(expr, message)) +#else +#define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) +#undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) +#if __cplusplus >= 201103L +#define JSON_HEDLEY_NULL \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) +#elif defined(NULL) +#define JSON_HEDLEY_NULL NULL +#else +#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void *, 0) +#endif +#elif defined(NULL) +#define JSON_HEDLEY_NULL NULL +#else +#define JSON_HEDLEY_NULL ((void *)0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) +#undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +#define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5, 0, 0) +#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 0, 0) +#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +#define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) +#undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +#define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 8, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) +#undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) +#undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +#if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +#define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#define JSON_HEDLEY_REQUIRE_MSG(expr, msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#else +#define JSON_HEDLEY_REQUIRE(expr) \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) +#define JSON_HEDLEY_REQUIRE_MSG(expr, msg) \ + __attribute__((diagnose_if(!(expr), msg, "error"))) +#endif +#else +#define JSON_HEDLEY_REQUIRE(expr) +#define JSON_HEDLEY_REQUIRE_MSG(expr, msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) +#undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && \ + (!defined(__cplusplus) || \ + JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) +#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else +#define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) +#undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19, 0, 0) +#define JSON_HEDLEY_FLAGS_CAST(T, expr) \ + (__extension__({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)")((T)(expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +#define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) +#undef JSON_HEDLEY_EMPTY_BASES +#endif +#if (JSON_HEDLEY_MSVC_VERSION_CHECK(19, 0, 23918) && \ + !JSON_HEDLEY_MSVC_VERSION_CHECK(20, 0, 0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) +#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else +#define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) +#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) +#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) (0) +#else +#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) \ + JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) +#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) \ + JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) +#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) \ + JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) +#undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) +#undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) +#undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) \ + JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) +#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) \ + JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) +#undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + +// #include + + +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void { + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + + +// https://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch { + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const &) = delete; + nonesuch(nonesuch const &&) = delete; + void operator=(nonesuch const &) = delete; + void operator=(nonesuch &&) = delete; +}; + +template + class Op, + class... Args> +struct detector { + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> { + using value_t = std::true_type; + using type = Op; +}; + +template