mirror of
https://github.com/EDCD/EDDN.git
synced 2025-04-20 18:47:39 +03:00
Merge branch 'develop' of github.com:EDCD/EDDN into develop
This commit is contained in:
commit
afddf9f849
21
.editorconfig
Normal file
21
.editorconfig
Normal file
@ -0,0 +1,21 @@
|
||||
# This is the project top-level .editorconfig
|
||||
root = true
|
||||
|
||||
# Defaults for all file types
|
||||
[*]
|
||||
# 4-space indents, no TABs
|
||||
indent_style = space
|
||||
tab_width = 4
|
||||
indent_size = tab
|
||||
|
||||
# Hard-wrap at 120 columns
|
||||
max_line_length = 119
|
||||
|
||||
# Unix EOL, single \n
|
||||
end_of_line = lf
|
||||
|
||||
# UTF-8 is the only sensible option, no BOM
|
||||
charset = utf-8
|
||||
|
||||
# All files should have a final newline
|
||||
insert_final_newline = true
|
@ -87,8 +87,9 @@ do
|
||||
log " Archiving ${service}.log ..."
|
||||
# We have no means to tell the service to close and re-open output, it's
|
||||
# to stdout/err anyway. So we copy it.
|
||||
COMPRESSED_NAME="${service}.log.$(date --iso-8601=seconds)"
|
||||
cp ${service}.log "${COMPRESSED_NAME}"
|
||||
TIMESTAMP="$(date --iso-8601=seconds)"
|
||||
ARCHIVED_NAME="${service}.log.${TIMESTAMP}"
|
||||
cp ${service}.log "${ARCHIVED_NAME}"
|
||||
if [ $? -ne 0 ];
|
||||
then
|
||||
echo " FAILED copying live log file to new archive!!!" >&2
|
||||
@ -97,8 +98,15 @@ do
|
||||
fi
|
||||
# Truncate the live file.
|
||||
:> ${service}.log
|
||||
|
||||
if [ "${service}" == "gateway" ];
|
||||
then
|
||||
# Produce a report of interesting errors
|
||||
${HOME}/.local/bin/eddn-report-log-errors "${ARCHIVED_NAME}" > "${HOME}/reports/eddn-errors/by-log-rotation/eddn-errors-${TIMESTAMP}.txt"
|
||||
fi
|
||||
|
||||
# Now compress the newly archived log
|
||||
gzip -9v "${COMPRESSED_NAME}"
|
||||
gzip -9v "${ARCHIVED_NAME}"
|
||||
log " DONE"
|
||||
else
|
||||
log " No"
|
||||
|
13
docs/Contributing.md
Normal file
13
docs/Contributing.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Contributing to the EDDN Project
|
||||
|
||||
## Introduction
|
||||
|
||||
This file is still mostly a stub.
|
||||
|
||||
## Text format
|
||||
|
||||
The project contains an `.editorconfig` file at its root. Please either ensure
|
||||
your editor is taking note of those settings, or cross-check its contents
|
||||
with the
|
||||
[editorconfig documentation](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties)
|
||||
, and ensure your editor/IDE's settings match.
|
@ -244,6 +244,10 @@ Each `message` object must have, at bare minimum:
|
||||
2. At least one other key/value pair representing the data. In general there
|
||||
will be much more than this. Consult the
|
||||
[schemas and their documentation](./).
|
||||
3. Where the data is sourced from a Journal event please do preserve the
|
||||
event key and value. Yes, where we use an event-specific schema this
|
||||
might seem redundant, but it might aid an EDDN listener in streamlining
|
||||
their code, and it does no harm.
|
||||
|
||||
Because the first versions of some schemas were defined when only the CAPI
|
||||
data was available, before Journal files existed, many of the key names chosen
|
||||
@ -268,6 +272,39 @@ changes to your code.
|
||||
It is also advisable to Watch this repository on GitHub so as to be aware
|
||||
of any changes to schemas.
|
||||
|
||||
#### `horizons` and `odyssey` flags
|
||||
|
||||
Where the schema allows for them, add the `horizons` and `odyssey`
|
||||
keys with boolean values. `null` is not allowed in the values, so if
|
||||
you cannot determine a value do not include that key at all. The best
|
||||
source of these is the `LoadGame` event from journals. It's present
|
||||
both in the PC local files and the CAPI journal data. If you're
|
||||
composing a shipyard or outfitting message from CAPI data then it is
|
||||
possible to synthesise the `horizons` flag. For now consult the function
|
||||
`capi_is_horizons()` in
|
||||
[EDMarketConnector:plugins/eddn.py](https://github.com/EDCD/EDMarketConnector/blob/stable/plugins/eddn.py)
|
||||
for a method to achieve this.
|
||||
|
||||
As of 2022-01-22 the following was observed for the `LoadGame` events as
|
||||
present in CAPI-sourced Journal files (which were confirmed to match the
|
||||
PC-local files for these events):
|
||||
|
||||
- PC Odyssey Client, game version `4.0.0.1002`:
|
||||
```json
|
||||
{ "timestamp":"2022-01-20T11:15:22Z", "event":"LoadGame", "FID":"F<elided>", "Commander":"<elided>", "Horizons":true, "Odyssey":true,...
|
||||
```
|
||||
- PC Horizons Client, game version `3.8.0.403`, no `Odyssey` key was
|
||||
present:
|
||||
```json
|
||||
{ "timestamp":"2022-01-20T11:20:17Z", "event":"LoadGame", "FID":"F<elided>", "Commander":"<elided>", "Horizons":true,...
|
||||
```
|
||||
|
||||
- PC 'base' Client, game version `3.8.0.403`, no `Odyssey` key was
|
||||
present:
|
||||
```json
|
||||
{ "timestamp":"2022-01-20T11:22:54Z", "event":"LoadGame", "FID":"F<elided>", "Commander":"<elided>", "Horizons":false,...
|
||||
```
|
||||
|
||||
### Server responses
|
||||
There are three possible sources of HTTP responses when sending an upload
|
||||
to EDDN.
|
||||
@ -299,8 +336,10 @@ make a valid request" responses you might experience the following:
|
||||
|
||||
#### bottle responses
|
||||
1. `413` - `Payload Too Large` - `bottle` enforces a maximum request size
|
||||
and the request exceeds that. As of 2022-01-07 the limit is 1MiB, and
|
||||
pertains to the plain-text size, not after gzip compression if used.
|
||||
and the request exceeds that. As of 2022-01-07 the limit is 1MiB,
|
||||
which is versus the compressed size of the body, if compression is
|
||||
used. Thus compression *will* allow for sending approximately 10x
|
||||
larger messages.
|
||||
To verify the current limit check for the line that looks like:
|
||||
|
||||
```
|
||||
|
33
schemas/approachsettlement-README.md
Normal file
33
schemas/approachsettlement-README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# EDDN ApproachSettlement Schema
|
||||
|
||||
## Introduction
|
||||
Here we document how to take data from an ED `ApproachSettlement` Journal
|
||||
Event and properly structure it for sending to EDDN.
|
||||
|
||||
Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general
|
||||
documentation for a schema such as this.
|
||||
|
||||
## Senders
|
||||
The primary data source for this schema is the ED Journal event
|
||||
`ApproachSettlement`.
|
||||
|
||||
### Key Renames
|
||||
Many of the key names have a different case defined in this schema, make
|
||||
sure you are renaming them as appropriate.
|
||||
|
||||
### Elisions
|
||||
None
|
||||
|
||||
### Augmentations
|
||||
#### horizons flag
|
||||
You SHOULD add this key/value pair, using the value from the `LoadGame` event.
|
||||
|
||||
#### odyssey flag
|
||||
You SHOULD add this key/value pair, using the value from the `LoadGame` event.
|
||||
|
||||
#### StarSystem
|
||||
|
||||
You MUST add a StarSystem key/value pair representing the name of the system this event occurred in. Source this from either Location, FSDJump or CarrierJump as appropriate.
|
||||
|
||||
#### StarPos
|
||||
You MUST add a `StarPos` array containing the system co-ordinates from the last `FSDJump`, `CarrierJump`, or `Location` event.
|
93
schemas/approachsettlement-v1.0.json
Normal file
93
schemas/approachsettlement-v1.0.json
Normal file
@ -0,0 +1,93 @@
|
||||
{
|
||||
"$schema" : "http://json-schema.org/draft-04/schema#",
|
||||
"id" : "https://eddn.edcd.io/schemas/approachsettlement/1#",
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"required": [ "$schemaRef", "header", "message" ],
|
||||
"properties": {
|
||||
"$schemaRef": {
|
||||
"type" : "string"
|
||||
},
|
||||
"header": {
|
||||
"type" : "object",
|
||||
"additionalProperties" : true,
|
||||
"required" : [ "uploaderID", "softwareName", "softwareVersion" ],
|
||||
"properties" : {
|
||||
"uploaderID": {
|
||||
"type" : "string"
|
||||
},
|
||||
"softwareName": {
|
||||
"type" : "string"
|
||||
},
|
||||
"softwareVersion": {
|
||||
"type" : "string"
|
||||
},
|
||||
"gatewayTimestamp": {
|
||||
"type" : "string",
|
||||
"format" : "date-time",
|
||||
"description" : "Timestamp upon receipt at the gateway. If present, this property will be overwritten by the gateway; submitters are not intended to populate this property."
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"type" : "object",
|
||||
"description" : "Contains all properties from the listed events in the client's journal minus the Localised strings and the properties marked below as 'disallowed'",
|
||||
"additionalProperties" : false,
|
||||
"required" : [ "timestamp", "event", "StarSystem", "StarPos", "SystemAddress", "Name", "MarketID", "BodyID", "BodyName", "Latitude", "Longitude" ],
|
||||
"properties" : {
|
||||
"timestamp": {
|
||||
"type" : "string",
|
||||
"format" : "date-time"
|
||||
},
|
||||
"event" : {
|
||||
"enum" : [ "ApproachSettlement" ]
|
||||
},
|
||||
"horizons": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether the sending Cmdr has a Horizons pass."
|
||||
},
|
||||
"odyssey": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether the sending Cmdr has an Odyssey expansion."
|
||||
},
|
||||
"StarSystem": {
|
||||
"type" : "string",
|
||||
"minLength" : 1,
|
||||
"description" : "Must be added by the sender"
|
||||
},
|
||||
"StarPos": {
|
||||
"type" : "array",
|
||||
"items" : { "type": "number" },
|
||||
"minItems" : 3,
|
||||
"maxItems" : 3,
|
||||
"description" : "Must be added by the sender"
|
||||
},
|
||||
"SystemAddress": {
|
||||
"type" : "integer"
|
||||
},
|
||||
"Name" : {
|
||||
"type" : "string",
|
||||
"description" : "Name of settlement"
|
||||
},
|
||||
"MarketID": {
|
||||
"type" : "integer"
|
||||
},
|
||||
"BodyID": {
|
||||
"type" : "integer"
|
||||
},
|
||||
"BodyName": {
|
||||
"type" : "string"
|
||||
},
|
||||
"Latitude": {
|
||||
"type" : "number"
|
||||
},
|
||||
"Longitude": {
|
||||
"type" : "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"disallowed" : { "not" : { "type": [ "array", "boolean", "integer", "number", "null", "object", "string" ] } }
|
||||
}
|
||||
}
|
30
schemas/fssallbodiesfound-README.md
Normal file
30
schemas/fssallbodiesfound-README.md
Normal file
@ -0,0 +1,30 @@
|
||||
# EDDN FSSAllBodiesFound Schema
|
||||
|
||||
## Introduction
|
||||
Here we document how to take data from an ED `FSSAllBodiesFound` Journal
|
||||
Event and properly structure it for sending to EDDN.
|
||||
|
||||
Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general
|
||||
documentation for a schema such as this.
|
||||
|
||||
## Senders
|
||||
The primary data source for this schema is the ED Journal event
|
||||
`FSSAllBodiesFound`.
|
||||
|
||||
### Key Renames
|
||||
Many of the key names have a different case defined in this schema, make
|
||||
sure you are renaming them as appropriate.
|
||||
|
||||
### Elisions
|
||||
None
|
||||
|
||||
### Augmentations
|
||||
#### horizons flag
|
||||
You SHOULD add this key/value pair, using the value from the `LoadGame` event.
|
||||
|
||||
#### odyssey flag
|
||||
You SHOULD add this key/value pair, using the value from the `LoadGame` event.
|
||||
|
||||
#### StarPos
|
||||
You MUST add a `StarPos` array containing the system co-ordinates from the
|
||||
last `FSDJump`, `CarrierJump`, or `Location` event.
|
78
schemas/fssallbodiesfound-v1.0.json
Normal file
78
schemas/fssallbodiesfound-v1.0.json
Normal file
@ -0,0 +1,78 @@
|
||||
{
|
||||
"$schema" : "http://json-schema.org/draft-04/schema#",
|
||||
"id" : "https://eddn.edcd.io/schemas/fssallbodiesfound/1#",
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"required": [ "$schemaRef", "header", "message" ],
|
||||
"properties": {
|
||||
"$schemaRef": {
|
||||
"type" : "string"
|
||||
},
|
||||
"header": {
|
||||
"type" : "object",
|
||||
"additionalProperties" : true,
|
||||
"required" : [ "uploaderID", "softwareName", "softwareVersion" ],
|
||||
"properties" : {
|
||||
"uploaderID": {
|
||||
"type" : "string"
|
||||
},
|
||||
"softwareName": {
|
||||
"type" : "string"
|
||||
},
|
||||
"softwareVersion": {
|
||||
"type" : "string"
|
||||
},
|
||||
"gatewayTimestamp": {
|
||||
"type" : "string",
|
||||
"format" : "date-time",
|
||||
"description" : "Timestamp upon receipt at the gateway. If present, this property will be overwritten by the gateway; submitters are not intended to populate this property."
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"type" : "object",
|
||||
"description" : "Contains all properties from the listed events in the client's journal, minus the Localised strings and the properties marked below as 'disallowed'",
|
||||
"additionalProperties" : false,
|
||||
"required" : [ "timestamp", "event", "SystemName", "StarPos", "SystemAddress", "Count" ],
|
||||
"properties" : {
|
||||
"timestamp": {
|
||||
"type" : "string",
|
||||
"format" : "date-time"
|
||||
},
|
||||
"event" : {
|
||||
"enum" : [ "FSSAllBodiesFound" ]
|
||||
},
|
||||
"horizons": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether the sending Cmdr has a Horizons pass."
|
||||
},
|
||||
"odyssey": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether the sending Cmdr has an Odyssey expansion."
|
||||
},
|
||||
"SystemName": {
|
||||
"type" : "string",
|
||||
"minLength" : 1
|
||||
},
|
||||
"StarPos": {
|
||||
"type" : "array",
|
||||
"items" : { "type": "number" },
|
||||
"minItems" : 3,
|
||||
"maxItems" : 3,
|
||||
"description" : "Must be added by the sender if not present in the journal event"
|
||||
},
|
||||
"SystemAddress": {
|
||||
"type" : "integer",
|
||||
"description" : "Should be added by the sender if not present in the journal event"
|
||||
},
|
||||
"Count" : {
|
||||
"type" : "integer",
|
||||
"description" : "Number of bodies in this system"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"disallowed" : { "not" : { "type": [ "array", "boolean", "integer", "number", "null", "object", "string" ] } }
|
||||
}
|
||||
}
|
@ -105,6 +105,23 @@ def process_file(input_file: str) -> None:
|
||||
print(matches.group('err_msg'))
|
||||
print(line)
|
||||
|
||||
elif matches.group('schema_ref') == 'https://eddn.edcd.io/schemas/journal/1':
|
||||
# <https://github.com/EDCD/EDMarketConnector/issues/1403>
|
||||
if matches.group('err_msg') == 'Failed Validation "[<ValidationError: "\'SystemAddress\' is a required property">]"':
|
||||
# <https://github.com/EDCD/EDMarketConnector/issues/1403>
|
||||
pass
|
||||
|
||||
elif matches.group('err_msg').startswith(
|
||||
'Failed Validation "[<ValidationError: "{\'type\': [\'array\', \'boolean\', \'integer\', \'number\', \'null\', \'object\', \'string\']} is not allowed for'
|
||||
):
|
||||
# <https://github.com/EDCD/EDMarketConnector/issues/1403>
|
||||
pass
|
||||
|
||||
elif matches.group('schema_ref') == 'https://eddn.edcd.io/schemas/fssdiscoveryscan/1':
|
||||
if matches.group('err_msg') == 'Failed Validation "[<ValidationError: "None is not of type \'boolean\'">]"':
|
||||
# <https://github.com/EDCD/EDMarketConnector/issues/1403>
|
||||
pass
|
||||
|
||||
else:
|
||||
print(line)
|
||||
|
||||
@ -179,6 +196,12 @@ def process_file(input_file: str) -> None:
|
||||
if matches.group('software_version') == '2.0.0.660':
|
||||
print(line)
|
||||
|
||||
# Abandoned/unmaintained project
|
||||
# <https://forums.frontier.co.uk/threads/release-eva-elite-virtual-assistant-for-iphone-ipad-no-longer-working-jan-2020.245900/page-18>
|
||||
# <https://apps.apple.com/gb/app/eva/id1098763533>
|
||||
elif matches.group('software_name') in ('EVA [iPhone]', 'EVA [iPad]'):
|
||||
pass
|
||||
|
||||
###################################################################
|
||||
# Issues we know about, but haven't yet alerted developers to
|
||||
###################################################################
|
||||
|
23
scripts/testing/gateway-responses/approachsettlement.json
Normal file
23
scripts/testing/gateway-responses/approachsettlement.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schemaRef": "https://eddn.edcd.io/schemas/approachsettlement/1",
|
||||
"header": {
|
||||
"uploaderID": "from Athanasius Testing",
|
||||
"softwareName": "Athanasius Testing script",
|
||||
"softwareVersion": "v0.0.1"
|
||||
},
|
||||
"message": {
|
||||
"timestamp":"2021-10-14T12:37:54Z",
|
||||
"event":"ApproachSettlement",
|
||||
"Name":"Arnold Defence Base",
|
||||
"MarketID":3915738368,
|
||||
"SystemAddress":2381282543963,
|
||||
"StarSystem": "Ix",
|
||||
"BodyID":32,
|
||||
"BodyName":"Ix 5 a a",
|
||||
"Latitude":17.090912,
|
||||
"Longitude":160.236679,
|
||||
"StarPos": [
|
||||
-65.21875 , 7.75 , -111.03125
|
||||
]
|
||||
}
|
||||
}
|
2266
scripts/testing/gateway-responses/commodity-just-over-50KiB.json
Normal file
2266
scripts/testing/gateway-responses/commodity-just-over-50KiB.json
Normal file
File diff suppressed because it is too large
Load Diff
2206
scripts/testing/gateway-responses/commodity-just-under-50KiB.json
Normal file
2206
scripts/testing/gateway-responses/commodity-just-under-50KiB.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
||||
{"$schemaRef":"https://eddn.edcd.io/schemas/commodity/3","header":{"softwareName":"E:D Market Connector Windows","softwareVersion":"5.3.0-beta4extra","uploaderID":"abcdefghijklm"},"message":{"systemName":"delphi","stationName":"The Oracle","marketId":128782803,"timestamp":"2022-01-26T12:00:00Z","commodities":[]}}
|
18
scripts/testing/gateway-responses/fssallbodiesfound.json
Normal file
18
scripts/testing/gateway-responses/fssallbodiesfound.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schemaRef": "https://eddn.edcd.io/schemas/fssallbodiesfound/1",
|
||||
"message": {
|
||||
"timestamp":"2022-01-26T16:21:00Z",
|
||||
"event":"FSSAllBodiesFound",
|
||||
"SystemName":"Zeta Doradus",
|
||||
"StarPos": [
|
||||
30.40625,-22.65625,-2.18750
|
||||
],
|
||||
"SystemAddress":44853889387,
|
||||
"Count":1
|
||||
},
|
||||
"header": {
|
||||
"uploaderID": "from Athanasius Testing",
|
||||
"softwareName": "Athanasius Testing script",
|
||||
"softwareVersion": "v0.0.1"
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
{"$schemaRef":"https://eddn.edcd.io/schemas/shipyard/2","header":{"softwareName":"E:D Market Connector Windows","softwareVersion":"5.3.0-beta4extra","uploaderID":"abcdefghijklm"},"message":{"systemName":"delphi","stationName":"The Oracle","marketId":128782803,"timestamp":"2022-01-26T12:00:00Z","ships":[]}}
|
10
setup.py
10
setup.py
@ -163,16 +163,6 @@ shutil.copy(
|
||||
'%s/start-eddn-%s-service' % ( START_SCRIPT_BIN, setup_env.EDDN_ENV )
|
||||
)
|
||||
|
||||
# Ensure the service log file archiving script is in place
|
||||
print """
|
||||
******************************************************************************
|
||||
Ensuring the service log file archiving script is in place
|
||||
"""
|
||||
shutil.copy(
|
||||
'contrib/eddn-logs-archive',
|
||||
START_SCRIPT_BIN
|
||||
)
|
||||
|
||||
# Ensure the latest monitor files are in place
|
||||
old_umask = os.umask(022)
|
||||
print """
|
||||
|
@ -26,6 +26,7 @@ Architecture:
|
||||
4. `push_message()` then sends the message to the configured live/real
|
||||
Gateway.
|
||||
"""
|
||||
import argparse
|
||||
import gevent
|
||||
import hashlib
|
||||
import logging
|
||||
@ -47,8 +48,15 @@ from bottle import Bottle, run, request, response, get, post
|
||||
app = Bottle()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(logging.StreamHandler())
|
||||
logger.setLevel(logging.INFO)
|
||||
__logger_channel = logging.StreamHandler()
|
||||
__logger_formatter = logging.Formatter(
|
||||
'%(asctime)s - %(levelname)s - %(module)s:%(lineno)d: %(message)s'
|
||||
)
|
||||
__logger_formatter.default_time_format = '%Y-%m-%d %H:%M:%S'
|
||||
__logger_formatter.default_msec_format = '%s.%03d'
|
||||
__logger_channel.setFormatter(__logger_formatter)
|
||||
logger.addHandler(__logger_channel)
|
||||
logger.info('Made logger')
|
||||
|
||||
|
||||
@ -57,6 +65,27 @@ from eddn.core.StatsCollector import StatsCollector
|
||||
statsCollector = StatsCollector()
|
||||
statsCollector.start()
|
||||
|
||||
|
||||
def parse_cl_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='Gateway',
|
||||
description='EDDN Gateway server',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--loglevel',
|
||||
help='Logging level to output at',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-c', '--config',
|
||||
metavar='config filename',
|
||||
nargs='?',
|
||||
default=None,
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def push_message(message_body):
|
||||
"""
|
||||
Spawned as a greenlet to push messages (strings) through ZeroMQ.
|
||||
@ -243,8 +272,12 @@ class CustomLogging(object):
|
||||
return _log_to_logger
|
||||
|
||||
def main():
|
||||
cl_args = parse_cl_args()
|
||||
if cl_args.loglevel:
|
||||
logger.setLevel(cl_args.loglevel)
|
||||
|
||||
logger.info('Loading config...')
|
||||
loadConfig()
|
||||
loadConfig(cl_args)
|
||||
|
||||
logger.info('Installing EnableCors ...')
|
||||
app.install(EnableCors())
|
||||
|
@ -4,6 +4,7 @@
|
||||
Contains the necessary ZeroMQ socket and a helper function to publish
|
||||
market data to the Announcer daemons.
|
||||
"""
|
||||
import argparse
|
||||
import gevent
|
||||
import hashlib
|
||||
import logging
|
||||
@ -51,6 +52,27 @@ statsCollector = StatsCollector()
|
||||
statsCollector.start()
|
||||
|
||||
|
||||
def parse_cl_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='Gateway',
|
||||
description='EDDN Gateway server',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--loglevel',
|
||||
help='Logging level to output at',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-c', '--config',
|
||||
metavar='config filename',
|
||||
nargs='?',
|
||||
default=None,
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def extract_message_details(parsed_message):
|
||||
uploader_id = '<<UNKNOWN>>'
|
||||
software_name = '<<UNKNOWN>>'
|
||||
@ -138,6 +160,7 @@ def get_decompressed_message():
|
||||
# Auto header checking.
|
||||
logger.debug('Trying zlib.decompress (15 + 32)...')
|
||||
message_body = zlib.decompress(request.body.read(), 15 + 32)
|
||||
|
||||
except zlib.error:
|
||||
logger.error('zlib.error, trying zlib.decompress (-15)')
|
||||
# Negative wbits suppresses adler32 checksumming.
|
||||
@ -149,12 +172,14 @@ def get_decompressed_message():
|
||||
# body. If it's not form-encoded, this will return an empty dict.
|
||||
form_enc_parsed = urlparse.parse_qs(message_body)
|
||||
if form_enc_parsed:
|
||||
logger.debug('Request is form-encoded')
|
||||
logger.info('Request is form-encoded, compressed, from %s' % (get_remote_address()))
|
||||
# This is a form-encoded POST. The value of the data attrib will
|
||||
# be the body we're looking for.
|
||||
try:
|
||||
message_body = form_enc_parsed['data'][0]
|
||||
|
||||
except (KeyError, IndexError):
|
||||
logger.error('form-encoded, compressed, upload did not contain a "data" key. From %s', get_remote_address())
|
||||
raise MalformedUploadError(
|
||||
"No 'data' POST key/value found. Check your POST key "
|
||||
"name for spelling, and make sure you're passing a value."
|
||||
@ -170,7 +195,7 @@ def get_decompressed_message():
|
||||
# POST key/vals, or un-encoded body.
|
||||
data_key = request.forms.get('data')
|
||||
if data_key:
|
||||
logger.debug('form-encoded POST request detected...')
|
||||
logger.info('Request is form-encoded, uncompressed, from %s' % (get_remote_address()))
|
||||
# This is a form-encoded POST. Support the silly people.
|
||||
message_body = data_key
|
||||
|
||||
@ -342,7 +367,12 @@ class EnableCors(object):
|
||||
|
||||
|
||||
def main():
|
||||
loadConfig()
|
||||
|
||||
cl_args = parse_cl_args()
|
||||
if cl_args.loglevel:
|
||||
logger.setLevel(cl_args.loglevel)
|
||||
|
||||
loadConfig(cl_args)
|
||||
configure()
|
||||
|
||||
app.install(EnableCors())
|
||||
|
@ -4,6 +4,7 @@
|
||||
Monitor sit below gateways, or another relay, and simply parse what it receives over SUB.
|
||||
"""
|
||||
from threading import Thread
|
||||
import argparse
|
||||
import zlib
|
||||
import gevent
|
||||
import simplejson
|
||||
@ -27,6 +28,26 @@ if Settings.RELAY_DUPLICATE_MAX_MINUTES:
|
||||
duplicateMessages.start()
|
||||
|
||||
|
||||
def parse_cl_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='Gateway',
|
||||
description='EDDN Gateway server',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--loglevel',
|
||||
help='CURRENTLY NO EFFECT - Logging level to output at',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-c', '--config',
|
||||
metavar='config filename',
|
||||
nargs='?',
|
||||
default=None,
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def date(__format):
|
||||
d = datetime.datetime.utcnow()
|
||||
return d.strftime(__format)
|
||||
@ -237,7 +258,9 @@ class EnableCors(object):
|
||||
return _enable_cors
|
||||
|
||||
def main():
|
||||
loadConfig()
|
||||
cl_args = parse_cl_args()
|
||||
loadConfig(cl_args)
|
||||
|
||||
m = Monitor()
|
||||
m.start()
|
||||
app.install(EnableCors())
|
||||
|
@ -4,20 +4,32 @@
|
||||
Relays sit below an announcer, or another relay, and simply repeat what
|
||||
they receive over PUB/SUB.
|
||||
"""
|
||||
# Logging has to be configured first before we do anything.
|
||||
import argparse
|
||||
import gevent
|
||||
import hashlib
|
||||
import logging
|
||||
import simplejson
|
||||
import time
|
||||
import uuid
|
||||
import zlib
|
||||
from threading import Thread
|
||||
|
||||
import time
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
import zlib
|
||||
|
||||
import gevent
|
||||
import simplejson
|
||||
import hashlib
|
||||
import uuid
|
||||
import zmq.green as zmq
|
||||
|
||||
|
||||
# Logging has to be configured first before we do anything.
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.INFO)
|
||||
__logger_channel = logging.StreamHandler()
|
||||
__logger_formatter = logging.Formatter(
|
||||
'%(asctime)s - %(levelname)s - %(module)s:%(lineno)d: %(message)s'
|
||||
)
|
||||
__logger_formatter.default_time_format = '%Y-%m-%d %H:%M:%S'
|
||||
__logger_formatter.default_msec_format = '%s.%03d'
|
||||
__logger_channel.setFormatter(__logger_formatter)
|
||||
logger.addHandler(__logger_channel)
|
||||
logger.info('Made logger')
|
||||
|
||||
from eddn.conf.Settings import Settings, loadConfig
|
||||
|
||||
from gevent import monkey
|
||||
@ -25,6 +37,7 @@ monkey.patch_all()
|
||||
from bottle import Bottle, get, request, response, run
|
||||
app = Bottle()
|
||||
|
||||
|
||||
# This import must be done post-monkey-patching!
|
||||
from eddn.core.StatsCollector import StatsCollector
|
||||
statsCollector = StatsCollector()
|
||||
@ -37,6 +50,26 @@ if Settings.RELAY_DUPLICATE_MAX_MINUTES:
|
||||
duplicateMessages.start()
|
||||
|
||||
|
||||
def parse_cl_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='Gateway',
|
||||
description='EDDN Gateway server',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--loglevel',
|
||||
help='Logging level to output at',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-c', '--config',
|
||||
metavar='config filename',
|
||||
nargs='?',
|
||||
default=None,
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
@app.route('/stats/', method=['OPTIONS', 'GET'])
|
||||
def stats():
|
||||
stats = statsCollector.getSummary()
|
||||
@ -171,7 +204,12 @@ class EnableCors(object):
|
||||
|
||||
|
||||
def main():
|
||||
loadConfig()
|
||||
cl_args = parse_cl_args()
|
||||
if cl_args.loglevel:
|
||||
logger.setLevel(cl_args.loglevel)
|
||||
|
||||
loadConfig(cl_args)
|
||||
|
||||
r = Relay()
|
||||
r.start()
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
# coding: utf8
|
||||
|
||||
import argparse
|
||||
import simplejson
|
||||
from eddn.conf.Version import __version__ as version
|
||||
|
||||
@ -74,6 +73,11 @@ class _Settings(object):
|
||||
|
||||
"https://eddn.edcd.io/schemas/navroute/1" : "schemas/navroute-v1.0.json",
|
||||
"https://eddn.edcd.io/schemas/navroute/1/test" : "schemas/navroute-v1.0.json",
|
||||
|
||||
"https://eddn.edcd.io/schemas/approachsettlement/1" : "schemas/approachsettlement-v1.0.json",
|
||||
"https://eddn.edcd.io/schemas/approachsettlement/1/test" : "schemas/approachsettlement-v1.0.json",
|
||||
"https://eddn.edcd.io/schemas/fssallbodiesfound/1" : "schemas/fssallbodiesfound-v1.0.json",
|
||||
"https://eddn.edcd.io/schemas/fssallbodiesfound/1/test" : "schemas/fssallbodiesfound-v1.0.json",
|
||||
}
|
||||
|
||||
GATEWAY_OUTDATED_SCHEMAS = [
|
||||
@ -134,15 +138,14 @@ class _Settings(object):
|
||||
Settings = _Settings()
|
||||
|
||||
|
||||
def loadConfig():
|
||||
'''
|
||||
Loads in a settings file specified on the commandline if one has been specified.
|
||||
def loadConfig(cl_args):
|
||||
"""
|
||||
Load in a commandline-specified settings file, if applicable.
|
||||
|
||||
A convenience method if you don't need other things specified as commandline
|
||||
options. Otherwise, point the filename to Settings.loadFrom().
|
||||
'''
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-c", "--config", nargs="?", default=None)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.config:
|
||||
Settings.loadFrom(args.config)
|
||||
:param cl_args: An `argparse.parse_args()` return.
|
||||
"""
|
||||
if cl_args.config:
|
||||
Settings.loadFrom(cl_args.config)
|
||||
|
Loading…
x
Reference in New Issue
Block a user