docs: adding tutorial 1

This commit is contained in:
Blake J. Harnden 2023-06-05 11:11:00 -07:00
parent 01585b6ec5
commit a5727e3355
12 changed files with 764 additions and 0 deletions

View file

@ -0,0 +1,63 @@
import argparse
import select
import socket
import sys
import termios
DEFAULT_PORT: int = 9001
READ_SIZE: int = 4096
def prompt():
sys.stdout.write(">> ")
sys.stdout.flush()
class ChatClient:
def __init__(self, address, port):
self.address = address
self.port = port
def run(self):
server = socket.create_connection((self.address, self.port))
sockname = server.getsockname()
print(f"connected to server({self.address}:{self.port}) as client({sockname[0]}:{sockname[1]})")
sockets = [sys.stdin, server]
prompt()
try:
while True:
read_sockets, write_socket, error_socket = select.select(sockets, [], [])
for sock in read_sockets:
if sock == server:
message = server.recv(READ_SIZE)
if not message:
print("server closed")
sys.exit(1)
else:
termios.tcflush(sys.stdin, termios.TCIOFLUSH)
print("\x1b[2K\r", end="")
print(message.decode().strip())
prompt()
else:
message = sys.stdin.readline().strip()
server.sendall(f"{message}\n".encode())
prompt()
except KeyboardInterrupt:
print("client exiting")
server.close()
def main():
parser = argparse.ArgumentParser(
description="chat app client",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument("-a", "--address", help="address to listen on", required=True)
parser.add_argument("-p", "--port", type=int, help="port to listen on", default=DEFAULT_PORT)
args = parser.parse_args()
client = ChatClient(args.address, args.port)
client.run()
if __name__ == "__main__":
main()

View file

@ -0,0 +1,73 @@
import argparse
import select
import socket
DEFAULT_ADDRESS: str = ""
DEFAULT_PORT: int = 9001
READ_SIZE: int = 4096
class ChatServer:
def __init__(self, address, port):
self.address = address
self.port = port
self.sockets = []
def broadcast(self, ignore, message):
for sock in self.sockets:
if sock not in ignore:
sock.sendall(message.encode())
def run(self):
print(f"chat server listening on: {self.address}:{self.port}")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((self.address, self.port))
server.listen()
self.sockets.append(server)
try:
while True:
read_sockets, write_sockets, error_sockets = select.select(self.sockets, [], [])
for sock in read_sockets:
if sock == server:
client_sock, addr = server.accept()
self.sockets.append(client_sock)
name = f"{addr[0]}:{addr[1]}"
print(f"[server] {name} joining")
self.broadcast({server, client_sock}, f"[server] {name} entered room\n")
else:
peer = sock.getpeername()
name = f"{peer[0]}:{peer[1]}"
try:
data = sock.recv(READ_SIZE).decode().strip()
if data:
print(f"[{name}] {data}")
self.broadcast({server, sock}, f"[{name}] {data}\n")
else:
print(f"[server] {name} leaving")
self.broadcast({server, sock}, f"[server] {name} leaving\n")
sock.close()
self.sockets.remove(sock)
except socket.error:
print(f"[server] {name} leaving")
self.broadcast({server, sock}, f"[server] {name} leaving\n")
sock.close()
self.sockets.remove(sock)
except KeyboardInterrupt:
print("closing server")
def main():
parser = argparse.ArgumentParser(
description="chat app server",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument("-a", "--address", help="address to listen on", default=DEFAULT_ADDRESS)
parser.add_argument("-p", "--port", type=int, help="port to listen on", default=DEFAULT_PORT)
args = parser.parse_args()
server = ChatServer(args.address, args.port)
server.run()
if __name__ == "__main__":
main()

View file

@ -0,0 +1,26 @@
from typing import Dict, List
from core.config import Configuration
from core.configservice.base import ConfigService, ConfigServiceMode, ShadowDir
class ChatAppService(ConfigService):
name: str = "ChatApp Server"
group: str = "ChatApp"
directories: List[str] = []
files: List[str] = ["chatapp.sh"]
executables: List[str] = []
dependencies: List[str] = []
startup: List[str] = [f"bash {files[0]}"]
validate: List[str] = []
shutdown: List[str] = []
validation_mode: ConfigServiceMode = ConfigServiceMode.BLOCKING
default_configs: List[Configuration] = []
modes: Dict[str, Dict[str, str]] = {}
shadow_directories: List[ShadowDir] = []
def get_text_template(self, _name: str) -> str:
return """
export PATH=$PATH:/usr/local/bin
PYTHONUNBUFFERED=1 chatapp-server > chatapp.log 2>&1 &
"""

View file

@ -0,0 +1,17 @@
from setuptools import setup, find_packages
setup(
name="chatapp",
version="0.1.0",
packages=find_packages(),
description="Chat App",
entry_points={
"console_scripts": [
"chatapp-client = chatapp.client:main",
"chatapp-server = chatapp.server:main",
],
},
include_package_data=True,
zip_safe=False,
python_requires=">=3.6",
)

View file

@ -0,0 +1,36 @@
from core.api.grpc import client
from core.api.grpc.wrappers import Position
def main():
# interface helper
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
# create grpc client and connect
core = client.CoreGrpcClient()
core.connect()
# create session
session = core.create_session()
# create nodes
position = Position(x=250, y=250)
node1 = session.add_node(_id=1, name="n1", position=position)
position = Position(x=500, y=250)
node2 = session.add_node(_id=2, name="n2", position=position)
# create link
node1_iface = iface_helper.create_iface(node_id=node1.id, iface_id=0)
node1_iface.ip4 = "10.0.0.20"
node1_iface.ip6 = "2001::14"
node2_iface = iface_helper.create_iface(node_id=node2.id, iface_id=0)
node2_iface.ip4 = "10.0.0.21"
node2_iface.ip6 = "2001::15"
session.add_link(node1=node1, node2=node2, iface1=node1_iface, iface2=node2_iface)
# start session
core.start_session(session=session)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,77 @@
<?xml version='1.0' encoding='UTF-8'?>
<scenario name="/tmp/tmpa_gpqzdf">
<networks/>
<devices>
<device id="1" name="n1" icon="" canvas="1" type="PC" class="" image="">
<position x="250.0" y="250.0" lat="47.57679395743362" lon="-122.12891511224676" alt="2.0"/>
<configservices>
<service name="DefaultRoute"/>
</configservices>
</device>
<device id="2" name="n2" icon="" canvas="1" type="PC" class="" image="">
<position x="500.0" y="250.0" lat="47.576775777287395" lon="-122.12534430899237" alt="2.0"/>
<configservices>
<service name="DefaultRoute"/>
</configservices>
</device>
</devices>
<links>
<link node1="1" node2="2">
<iface1 id="0" name="eth0" mac="00:00:00:aa:00:00" ip4="10.0.0.20" ip4_mask="24" ip6="2001::14" ip6_mask="64"/>
<iface2 id="0" name="eth0" mac="00:00:00:aa:00:01" ip4="10.0.0.21" ip4_mask="24" ip6="2001::15" ip6_mask="64"/>
<options delay="0" bandwidth="0" loss="0.0" dup="0" jitter="0" unidirectional="0" buffer="0"/>
</link>
</links>
<emane_global_configuration>
<emulator/>
<core>
<configuration name="platform_id_start" value="1"/>
<configuration name="nem_id_start" value="1"/>
<configuration name="link_enabled" value="1"/>
<configuration name="loss_threshold" value="30"/>
<configuration name="link_interval" value="1"/>
<configuration name="link_timeout" value="4"/>
</core>
</emane_global_configuration>
<session_origin lat="47.579166412353516" lon="-122.13232421875" alt="2.0" scale="150.0"/>
<session_options>
<configuration name="controlnet" value=""/>
<configuration name="controlnet0" value=""/>
<configuration name="controlnet1" value=""/>
<configuration name="controlnet2" value=""/>
<configuration name="controlnet3" value=""/>
<configuration name="controlnet_updown_script" value=""/>
<configuration name="enablerj45" value="1"/>
<configuration name="preservedir" value="0"/>
<configuration name="enablesdt" value="0"/>
<configuration name="sdturl" value="tcp://127.0.0.1:50000/"/>
<configuration name="ovs" value="0"/>
</session_options>
<session_metadata>
<configuration name="shapes" value="[]"/>
<configuration name="hidden" value="[]"/>
<configuration name="canvas" value="{&quot;gridlines&quot;: true, &quot;dimensions&quot;: [1000, 750], &quot;canvases&quot;: [{&quot;id&quot;: 1, &quot;wallpaper&quot;: null, &quot;wallpaper_style&quot;: 1, &quot;fit_image&quot;: false}]}"/>
<configuration name="edges" value="[]"/>
</session_metadata>
<default_services>
<node type="mdr">
<service name="zebra"/>
<service name="OSPFv3MDR"/>
<service name="IPForward"/>
</node>
<node type="PC">
<service name="DefaultRoute"/>
</node>
<node type="prouter"/>
<node type="router">
<service name="zebra"/>
<service name="OSPFv2"/>
<service name="OSPFv3"/>
<service name="IPForward"/>
</node>
<node type="host">
<service name="DefaultRoute"/>
<service name="SSH"/>
</node>
</default_services>
</scenario>

View file

@ -0,0 +1,37 @@
from core.api.grpc import client
from core.api.grpc.wrappers import Position
def main():
# interface helper
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
# create grpc client and connect
core = client.CoreGrpcClient()
core.connect()
# create session
session = core.create_session()
# create nodes
position = Position(x=250, y=250)
node1 = session.add_node(_id=1, name="n1", position=position)
node1.config_services.add("ChatApp Server")
position = Position(x=500, y=250)
node2 = session.add_node(_id=2, name="n2", position=position)
# create link
node1_iface = iface_helper.create_iface(node_id=node1.id, iface_id=0)
node1_iface.ip4 = "10.0.0.20"
node1_iface.ip6 = "2001::14"
node2_iface = iface_helper.create_iface(node_id=node2.id, iface_id=0)
node2_iface.ip4 = "10.0.0.21"
node2_iface.ip6 = "2001::15"
session.add_link(node1=node1, node2=node2, iface1=node1_iface, iface2=node2_iface)
# start session
core.start_session(session=session)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,81 @@
<?xml version='1.0' encoding='UTF-8'?>
<scenario name="/tmp/tmp2exmy1y9">
<networks/>
<devices>
<device id="1" name="n1" icon="" canvas="0" type="PC" class="" image="">
<position x="250.0" y="250.0" lat="47.576893948125004" lon="-122.12895553643455" alt="2.0"/>
<configservices>
<service name="ChatApp Server"/>
<service name="DefaultRoute"/>
</configservices>
</device>
<device id="2" name="n2" icon="" canvas="0" type="PC" class="" image="">
<position x="500.0" y="250.0" lat="47.576893948125004" lon="-122.12558685411909" alt="2.0"/>
<configservices>
<service name="DefaultRoute"/>
</configservices>
</device>
</devices>
<links>
<link node1="1" node2="2">
<iface1 id="0" name="eth0" mac="00:00:00:aa:00:00" ip4="10.0.0.20" ip4_mask="24" ip6="2001::14" ip6_mask="64"/>
<iface2 id="0" name="eth0" mac="00:00:00:aa:00:01" ip4="10.0.0.21" ip4_mask="24" ip6="2001::15" ip6_mask="64"/>
<options delay="0" bandwidth="0" loss="0.0" dup="0" jitter="0" unidirectional="0" buffer="0"/>
</link>
</links>
<emane_global_configuration>
<emulator/>
<core>
<configuration name="platform_id_start" value="1"/>
<configuration name="nem_id_start" value="1"/>
<configuration name="link_enabled" value="1"/>
<configuration name="loss_threshold" value="30"/>
<configuration name="link_interval" value="1"/>
<configuration name="link_timeout" value="4"/>
</core>
</emane_global_configuration>
<configservice_configurations>
<service name="ChatApp Server" node="1"/>
</configservice_configurations>
<session_origin lat="47.579166412353516" lon="-122.13232421875" alt="2.0" scale="150.0"/>
<session_options>
<configuration name="controlnet" value=""/>
<configuration name="controlnet0" value=""/>
<configuration name="controlnet1" value=""/>
<configuration name="controlnet2" value=""/>
<configuration name="controlnet3" value=""/>
<configuration name="controlnet_updown_script" value=""/>
<configuration name="enablerj45" value="1"/>
<configuration name="preservedir" value="0"/>
<configuration name="enablesdt" value="0"/>
<configuration name="sdturl" value="tcp://127.0.0.1:50000/"/>
<configuration name="ovs" value="0"/>
</session_options>
<session_metadata>
<configuration name="shapes" value="[]"/>
<configuration name="hidden" value="[]"/>
<configuration name="canvas" value="{&quot;gridlines&quot;: true, &quot;dimensions&quot;: [1000, 750], &quot;canvases&quot;: [{&quot;id&quot;: 1, &quot;wallpaper&quot;: null, &quot;wallpaper_style&quot;: 1, &quot;fit_image&quot;: false}]}"/>
<configuration name="edges" value="[]"/>
</session_metadata>
<default_services>
<node type="mdr">
<service name="zebra"/>
<service name="OSPFv3MDR"/>
<service name="IPForward"/>
</node>
<node type="PC">
<service name="DefaultRoute"/>
</node>
<node type="prouter"/>
<node type="router">
<service name="zebra"/>
<service name="OSPFv2"/>
<service name="OSPFv3"/>
<service name="IPForward"/>
</node>
<node type="host">
<service name="DefaultRoute"/>
<service name="SSH"/>
</node>
</default_services>
</scenario>