Skip to content

iothpy tutorial #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* [libioth: the definitive API for the IoTh](/tutorials/ioth_libioth.md)
* [IoTh: vdestack](/tutorials/ioth_vdestack.md)
* [picoxnet: a stack for the IoTh](/tutorials/ioth_picoxnet.md)
* [iothpy: a Python module for IoTh](/tutorials/ioth_iothpy.md)
* ---
* **VUOS**
* [VUOS/umvu basic concepts](/tutorials/vuosbasics.md)
Expand Down
247 changes: 247 additions & 0 deletions tutorials/ioth_iothpy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
# iothpy : Python module for IoTh, iothconf and iothdns support


This module provides the creation and configuration of Internet of Threads stack and socket, with an additional support for clients who need to query DNS servers, using iothdns API.

## Classes
Iothpy module provides the classes to use IoTh in Python. The classes are Stack and Socket.

### Stack

#### Creation
To create a stack object, the constructor is:
```py
iothpy.Stack(stack_name, vdeurl = None, config_dns = None)
```
where:
* `stack_name` (required): it is the name of IoTh stack to be used (e.g. vdestack, picox, ...), or a string following newstackc configuration syntax.
* `vdeurl` (optional): can be a string or a list of strings representing the VDE URLs. The stack will have an interface for each vde.
* `config_dns` (optional): path or string for the configuration of iothdns descriptor, following /etc/resolv.conf syntax. Default value is "/etc/resolv.conf".

Note: if `stack_name` isn't a configuration and `vdeurl` is None, then the stack will be initialized with no interface. Vdestack doesn't support the addition of interface at runtime.

#### Configuration
To configure the stack you can use these functions:
`linksetupdown`, `linkgetaddr`, `linksetaddr`, `iplink_add`, `iplink_del`, `linksetmtu`, `ipaddr_add`, `ipaddr_del`,`iproute_add`, `iproute_del`.

Or you can use a single method: `iothconfig(config)`.

To update the DNS, you can use `iothdns_update(config)`, where `config` follows the same principles of `config_dns` in stack initialization.

#### Other methods
```py
Stack.getaddrinfo(host, port, family=0, type=0, proto=0)
```
It translates the *host/port* argument in a sequence of 5-tuple containing all the info for create a socket connected to service.
This method has the same signature of built-in Python method `socket.getaddrinfo()`, but uses iothdns.


```py
Stack.socket(self, family=-1, type=-1, proto=-1, fileno=None)
```
Create and return a new socket on this stack.
This method takes the same parameters of the built-in Python method `socket.socket()`.

### Socket
This class has the main methods of the builtin socket module, like `bind`, `close`, `connect` , `send` and more.

## Installation
The following libreries are requested to use this module:
* [libioth](https://github.com/virtualsquare/libioth)
* [iothconf](https://github.com/virtualsquare/iothconf)
* [iothdns](https://github.com/virtualsquare/iothconf)

To install iothpy module, do:
```bash
pip install iothpy
```

To uninstall the library, do:
```bash
pip uninstall iothpy
```

## Examples

### Getting started
Here is an example of a basic creation and configuration of a networking stack connected to a VDE URL:

```python
import iothpy

# Create a new stack using vdestack connected to vde:///tmp/mysw
stack = iothpy.Stack("vdestack", "vde:///tmp/mysw")

# Get the index of the default interface vde0
if_index = stack.if_nametoindex("vde0")


# Enable the interface
stack.linksetupdown(if_index, 1)

# Set MAC address of the interface
stack.linksetaddr(if_index, "80:00:42:0e:e7:3a")

# Add IPv4 address and default gateway
stack.ipaddr_add(iothpy.AF_INET, "10.0.0.1", 24, if_index)
stack.iproute_add(iothpy.AF_INET, "10.0.0.254")

# Create a new socket on the stack
s = stack.socket(iothpy.AF_INET, iothpy.SOCK_STREAM)

```
The Stack constructor takes the name of a ioth plugin (`vdestack`, `picox`, ...) and one or a list of vde urls. The new stack has a virtual interface connected to each vde network identified by the VNL.

The stack object has methods for all the configuration options defined by libioth, for more details you can run `help("iothpy.Stack")` inside a python interpreter.

After the configuration you can create sockets using the `Stack.socket` method. The parameters and the API of the returned socket is the same as the Python built-in socket module.


### Server-client
Let's make a server-client communication:
#### `server.py`
```py
#!/usr/bin/python

import sys
import iothpy
import time
import threading

# Check arguments
if(len(sys.argv) != 2):
name = sys.argv[0]
print("Usage: {0} vdeurl\ne,g: {1} vxvde://234.0.0.1\n\n".format(name, name))
exit(1)

# Create and configure stack
stack = iothpy.Stack("vdestack", sys.argv[1])
ifindex = stack.if_nametoindex("vde0")
stack.linksetupdown(ifindex, 1)
stack.ipaddr_add(iothpy.AF_INET, "10.0.0.1", 24, ifindex)
stack.iproute_add(iothpy.AF_INET, "10.0.0.254")

# To create and configure stack, you can use also:
# stack = iothpy.Stack("stack=vdestack,vnl={0},eth, ip=10.0.0.1/24".format(sys.argv[1]))

# Create a tcp listening socket from
sock = stack.socket(iothpy.AF_INET, iothpy.SOCK_STREAM)

# From here on we can use the ioth socket as if we were using a python socket
sock.bind(('', 5000))
sock.listen(1)

# Handle incoming connection
def handle(conn, addr):
while True:
data = conn.recv(1024)
if not data:
print("Connection closed by", addr)
break
print("Got:", data.decode(), "from", addr)
conn.send(data)

# Listen on the socket for a new connection
while True:
conn, addr = sock.accept()
print("New connection by {}".format((conn, addr)))
# Create a new thread to handle multiple concurrent connections
t = threading.Thread(target = handle, args=(conn, addr), daemon=True)
t.start()
```

#### `client.py`

```py
# file client.py:

#!/usr/bin/python

import iothpy

import sys
import time
import select

# Check arguments
if(len(sys.argv) != 2):
name = sys.argv[0]
print("Usage: {0} vdeurl\ne,g: {1} vxvde://234.0.0.1\n\n".format(name, name))
exit(1)

# Create and configure stack
stack = iothpy.Stack("vdestack", sys.argv[1])
ifindex = stack.if_nametoindex("vde0")
stack.linksetupdown(ifindex, 1)
stack.ipaddr_add(iothpy.AF_INET, "10.0.0.2", 24, ifindex)
stack.iproute_add(iothpy.AF_INET, "10.0.0.254")

# To configure the stack, you can use the single function:
# stack.ioth_config("eth,ip=10.0.0.53/24,gw=10.0.0.1".format(sys.argv[1]))

# Create a tcp socket and connect to server
sock = stack.socket(iothpy.AF_INET, iothpy.SOCK_STREAM)

# From here on we can use the ioth socket as if we were using a python socket
sock.connect(("10.0.0.1", 5000))

print("Connected to server at", sock.getpeername())

# Create a poll object to wait for messsages from the server and stdin
poll_obj = select.poll()
poll_obj.register(sock, select.POLLIN)
poll_obj.register(sys.stdin, select.POLLIN)

while(True):
events = poll_obj.poll()
for fd, event in events:
# Read messages from the server
if(fd == sock.fileno()):
message = sock.recv(1024)
if(message):
print(message.decode())
else:
break
# Read from stdin
if(fd == sys.stdin.fileno()):
message = input().rstrip()
if(message):
sock.send(message.encode())
else:
break
```

### Getaddrinfo

Note: this example needs [`libvdeslirp`](https://github.com/virtualsquare/libvdeslirp)

```py
#file gai.py:

import iothpy

#create and configure stack
stack = iothpy.Stack("vdestack","slirp://")
stack.ioth_config("auto")

# host and port to connect to
host ="www.google.com"
port = 80

addrinfos = stack.getaddrinfo(host, port)

print(f"All addresses info of {host}, port {port}:\n\n{addrinfos}]\n")

family, type, proto, _, sockaddr = addrinfos[0]
print(f"Address 0 info, used as test:\n{addrinfos[0]}.\nSo the address to connect the socket is:\n{sockaddr}\n")

# create socket from the stack
socket = stack.socket(family, type, proto)

socket.connect(sockaddr)

print("Connection established to ", socket.getpeername())
```

### Other examples
You can find other examples in [iothpy repo](https://github.com/ramenguy99/iothpy) on GitHub.