Skip to content

Commit 1c174f2

Browse files
authored
Merge pull request #13 from fealone/supports_monitor_stun
Supports for stun endpoint.
2 parents 3109f27 + f3f1821 commit 1c174f2

File tree

3 files changed

+62
-5
lines changed

3 files changed

+62
-5
lines changed

src/monitapi/monitoring/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ class Method(str, Enum):
1515

1616

1717
class MonitoringTarget(BaseModel):
18-
method: Method
18+
method: Optional[Method]
1919
url: str
2020
headers: Dict[str, str] = {}
2121
body: Optional[bytes]
2222
timeout: int = 10
23-
status_code: int
23+
status_code: Optional[int]
2424
retry: int = 1
2525
retry_wait: int = 5
2626

src/monitapi/monitoring/monitor.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import asyncio
2+
import socket
3+
import time
4+
import uuid
25
from typing import Any, Dict, Generator, IO, List
36

47
from aiohttp import ClientSession
@@ -19,12 +22,15 @@ def get_targets(targets: List[Dict[str, Dict[str, Any]]]) -> Generator[Monitorin
1922
yield MonitoringTarget(**target)
2023

2124

22-
async def monitor(target: MonitoringTarget) -> MonitoringResult:
25+
async def monitor_http(target: MonitoringTarget) -> MonitoringResult:
2326
state: bool
2427
async with ClientSession(
2528
read_timeout=target.timeout,
2629
conn_timeout=target.timeout) as session:
27-
method = getattr(session, target.method.lower())
30+
if target.method:
31+
method = getattr(session, target.method.lower())
32+
else:
33+
raise Exception("Required method for monitoring http")
2834
error = ""
2935
response = None
3036
is_retry = False
@@ -75,6 +81,51 @@ async def monitor(target: MonitoringTarget) -> MonitoringResult:
7581
response=await response.text() if response else error)
7682

7783

84+
async def monitor_stun(target: MonitoringTarget) -> MonitoringResult:
85+
err = Exception()
86+
for i in range(target.retry):
87+
try:
88+
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
89+
sock.setblocking(False)
90+
host, port = target.url.split("stun:")[1].split(":")
91+
sock.bind(("0.0.0.0", int(port)))
92+
mtype = b"\x00\x01"
93+
msg = b"\x00\x01\x00\x00\xff\xff\xff\xff"
94+
tid = uuid.uuid4().bytes
95+
length = bytearray([len(msg)]).rjust(2, b"\x00")
96+
header = mtype + length + tid
97+
sock.sendto(header+msg, (host, int(port)))
98+
in_err = Exception()
99+
for j in range(int(target.timeout * 2)):
100+
time.sleep(0.5)
101+
try:
102+
sock.recvfrom(1024)
103+
break
104+
except Exception as e:
105+
in_err = e
106+
else:
107+
raise in_err
108+
break
109+
except Exception as e:
110+
logger.warning(("Monitor failed. "
111+
f"Target: {target.url}"))
112+
err = e
113+
time.sleep(target.retry_wait)
114+
else:
115+
return MonitoringResult(
116+
expected_status_code=0,
117+
status_code=0,
118+
state=False,
119+
url=target.url,
120+
response=str(err))
121+
return MonitoringResult(
122+
expected_status_code=0,
123+
status_code=0,
124+
state=True,
125+
url=target.url,
126+
response="")
127+
128+
78129
async def watch(f: IO = None) -> None:
79130
if f is None:
80131
f = open("targets.yaml")
@@ -85,7 +136,12 @@ async def watch(f: IO = None) -> None:
85136
except Exception:
86137
raise IncorrectYaml()
87138
for target in targets:
88-
task = asyncio.ensure_future(monitor(target))
139+
if target.url.startswith("http://") or target.url.startswith("https://"):
140+
task = asyncio.ensure_future(monitor_http(target))
141+
elif target.url.startswith("stun:"):
142+
task = asyncio.ensure_future(monitor_stun(target))
143+
else:
144+
logger.warning(f"Unsupported target type. target: {target.url}")
89145
monitors.append(task)
90146
results = await asyncio.gather(*monitors)
91147
for result in results:

website/docs/definition.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ monitor_targets:
2727
- HEAD, GET, POST, PUT, DELETE, OPTIONS, PATCH
2828
* monitoring-url
2929
- URL to monitor
30+
- Supports for [http://, https://, stun:]
3031
* header-name, header-value
3132
- HTTP headers
3233
* expected-status-code

0 commit comments

Comments
 (0)