GithubHelp home page GithubHelp logo

fraunhofer-iis / libjapi Goto Github PK

View Code? Open in Web Editor NEW
3.0 4.0 0.0 237 KB

libjapi is a universal JSON to C API library. It receives newline-delimited JSON (NDJSON) messages via TCP and calls registered C functions. A JSON response is returned for each request. Furthermore, it is also possible to create push services, which asynchronously push JSON messages to the clients subscribed to them.

License: MIT License

CMake 23.78% C++ 16.12% CSS 0.68% Python 1.91% Dockerfile 0.10% Shell 0.46% C 56.94%
libjapi

libjapi's Introduction

libjapi

libjapi is a universal JSON to C API library. It receives newline-delimited JSON (NDJSON) messages via TCP and calls registered C functions. A JSON response is returned for each request. Furthermore, it is also possible to create push services, which asynchronously push JSON messages to the clients subscribed to them.

Documentation

The documentation can be found here.

Packages

Prebuild packages for CentOS 7 can be downloaded from the latest package Action.

Features

  • Synchronous communication (request, response)
  • Asynchronous communication (register, push)
  • Multi-client support

Getting started

Prerequisites

Installation

Clone the git repository and it's submodules:

$ git clone --recurse-submodules [email protected]:Fraunhofer-IIS/libjapi.git

Create a build directory and call cmake in that directory.

$ mkdir build
$ cd build/
$ cmake ../

A Makefile is generated. Run 'make' to build the libjapi libraries.

$ make

A shared and a static library is built.

To run the internal tests run

$ make run_test

Demo

You can clone the demo project, with examples for all features from the repository listed below:

$ git clone --recurse-submodules [email protected]:ks-ip-lib/software/libjapi-demo.git

References

Contributing

Pre-commit hooks

When contributing to this project, automatic formatting of changes is strongly encouraged, so that formatting is getting more consistent over time.

To do so, ensure you have pre-commit installed and do the following

$ pre-commit install
pre-commit installed at .git/hooks/pre-commit

This will run clang-format on all changes you commit, gradually reformatting the code base to a more consistent state.

Code Coverage

To test which part of the code is called by tests, use the coverage tool.

To do so, make sure you have lcov installed and do the following

$ mkdir build
$ cd build/
$ cmake -DCMAKE_BUILD_TYPE=Debug ../
$ make coverage

The result ist displayed in the console. Additionally a report is created at "build/coverage/index.html". You can also find it here.

libjapi's People

Contributors

cstender avatar jannismain avatar michael-m-baron avatar vornkat-iis avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

libjapi's Issues

✨ Proposal: Specify first level of all JAPI responses

In GitLab by @jannismain on Jul 8, 2019, 16:50

Current Implementation

Right now, the format of JAPI responses is partly specified and partly up to japi_request_handler, which is implemented for each server application:

JAPI command handled by libjapi:

-> { "japi_request": "japi_pushsrv_list"}
<- { "japi_response": "japi_pushsrv_list", "services": [ "push_temperature", "push_counter" ] }

JAPI command handled by application-defined response handler (but still including japi_response key):

-> { "japi_request": "get_temperature" }
<- { "japi_response": "get_temperature", "temperature": 27.0, "unit": "celsius" }

Another command handled by application-defined response handler (without japi_response key):

-> { "japi_request": "japi_pushsrv_subscribe", "service": "push_temperature" }
<- { "temperature": 39.91664810452468, "japi_pushsrv": "push_temperature" }
<- { "temperature": 39.73847630878195, "japi_pushsrv": "push_temperature" }
<- { "temperature": 39.46300087687415, "japi_pushsrv": "push_temperature" }
<- { "temperature": 39.09297426825681, "japi_pushsrv": "push_temperature" }
...

Problems

A badly (or maliciously) designed request handler could use JAPI package identifiers listed above to trick the parser into doing things he shouldn't be doing.

Example of a forged response:

-> { "japi_request": "japi_pushsrv_list", "services": [ "push_temperature", "push_counter" ] }
-> { "japi_request": "japi_pushsrv_subscribe", "service": "push_temperature" }
<- { "japi_response": "japi_pushsrv_subscribe", "service": "push_temperature", "success": true }
<- { "temperature": 39.91664810452468, "japi_pushsrv": "push_temperature" }
<- { "temperature": 39.73847630878195, "japi_pushsrv": "push_temperature" }
// forged response to advertise service that doesn't exist:
<- { "japi_response": "japi_pushsrv_list", "services": [ "push_temperature", "push_counter", "push_bitcoin_miner" ] }
<- { "temperature": 39.09297426825681, "japi_pushsrv": "push_temperature" }
...

If the client-side parser has no logic to match responses to initiated requests, it will now think, there is a registered push_bitcoin_miner service, which there isn't really.

But even if the client-parser only handles responses with matching requests, a push service package (with a forged response) might always arrive in between request and authentic response.

Possible Solutions

  1. Blacklist internal JAPI keys (japi_response, japi_response_msg, japi_pushsrv, service, services, success) from being used in request handler functions.
  2. Strictly specify first level of JAPI response messages (request handler values would be attached on the second level )

Proposed Solution

Specify the first level of all JAPI responses to guarantee, that the same parser can parse all JAPI response packages.

A specification could look like this:

Regular JAPI packages:

{
    "japi_response": str,
    "value": any,
    "success": bool
}

JAPI Push Service Update Packages:

{
    "japi_pushsrv": str,
    "value": any
}

Here, the application defined fields (any) are separated from any internal JAPI fields ("value", "japi_pushsrv") through hierarchy, rendering the forged response above meaningless:

Example of a forged response:

...
<- { "value": 39.91664810452468, "japi_pushsrv": "push_temperature" }
<- { "value": 39.73847630878195, "japi_pushsrv": "push_temperature" }
// forged response to advertise service that doesn't exist:
<- { "value": { "japi_response": "japi_pushsrv_list", "services": [ "push_temperature", "push_counter", "push_bitcoin_miner" ] }, "japi_pushsrv": "push_temperature" }
// client is indifferent to this attack:
-> 凸( ̄ヘ ̄)
<- { "temperature": 39.09297426825681, "japi_pushsrv": "push_temperature" }
...

creadline failed

In GitLab by @fraunhofer-iis-anon on Nov 20, 2018, 10:33

beim updaten des servers wird der base 64 decodede tarball über einen json-string gesendet. Er ist allerdings zu lang für creadline und das update schägt fehl. ich habe manuell jetzt die maximale zeilenlänge erhöht und es geht. ich würde also vorschlagen wir erhöhen die maximale zeichenlänge, bin mir aber noch nicht sicher auf welchen wert. das boot_adc hat nach dem dekoden 9MB. wenn wir also alles auf einmal senden(boot_adc + sw_adc + fw_adc) wird eine relativ lange "nachricht" gesendet.

Support usage in a C++ program

In GitLab by @kolb on Jul 30, 2019, 17:41

libjapi cannot currently be linked in a C++ program because C and C++ compilers generate different symbol names.

To fix this, we have to tell the C++ compiler to use C-style symbol names for all libjapi references and therefore put the following construct into all externally used headers:

#ifdef __cplusplus
extern "C" {
#endif

// Function definitions here

#ifdef __cplusplus
}
#endif

Make clean fails

In GitLab by @jannismain on Jul 8, 2019, 13:28

❯ make clean
rm -rf obj lib testobj doc testsuite
cd googletest/googletest/make && make clean
/bin/sh: line 0: cd: googletest/googletest/make: No such file or directory
make: *** [clean] Error 1

if googletest dir is not available, it should be skipped and make clean should continue with remaining dirs.

Undescriptive error messages

In GitLab by @jannismain on Jul 8, 2019, 13:26

❯ make run-static
./demo-static 1234
ERROR: JAPI_COMMAND not found!
ERROR: JAPI_COMMAND not found!
ERROR: JAPI_COMMAND not found!

When sending unknown commands to japi-server, the error message should include, which JAPI_COMMAND it didn't understand.

Bonus: It could offer a list of available commands, so one can see, what the problem was (typo, wrong libjapi version, etc)

Fix usage of boolean types

In GitLab by @kolb on Jun 17, 2019, 11:02

Boolean type usage is currently dependent on the compiler’s default settings and may generate errors when different compilers are used (for example Clang).

In order to clean this up, multiple steps are necessary:

  1. Explicitely set the C standard the compiler should use, at least -std=c99
  2. Add #include <stdbool.h> where necessary
  3. Replace all variants of boolean types with the standard bool, true and false keywords

For more info about C99-booleans see https://en.cppreference.com/w/c/types/boolean

For a problematic example, see https://git01.iis.fhg.de/ks-ip-lib/software/libjapi/blob/47e7871b/src/japi_pushsrv.c#L175

pass japi_client context instead of raw socket ids

In GitLab by @cstender on Jul 8, 2019, 15:57

It shall be discussed if we better pass a japi_client context instead of raw socket ids to the following functions:

  • japi_remove_client
  • japi_pushsrv_remove_client
  • japi_process_message
  • japi_pushsrv_subscribe
  • japi_pushsrv_unsubscribe

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.