Source code for yodel.sender

# this file deals with the setup and interaction with the sender thread
# interaction is done through a pipeline and a stack
# the stack is used to give the sender thread data to send out
# the pipline is used to give other instructions to the thread, things like settings updates
# both the stack and the pipeline are assumed to be one-way, that being from the main thread to the sender thread
#

import multiprocessing as mp
import yodel.standardformats as standardformats
from .dynamicheaders import *
import random
from .classes import *
from yodel.config import *
import sys
import yodel.globaldat as globaldat
from yodel.config import *
from typing import *

# setup for communication with sender thread
# print("init")
globaldat.sender_pipe, sender_pipe_output = mp.Pipe()
globaldat.outgoing = mp.Queue()
#####


# template that gets filled whenever send is called. this is to avoid
# having to generate a new class object every time send is called
outgoing_data = Section(standardformats.standard_header_format)
exiting = False
exist_start = 0


[docs]def sendData(packet: FrameStruct, repeats: int) -> NoReturn: """ Generate 80211 header and send completed data Args: packet: framestruct that holds raw outgoing data as well and info about how it should be sent repeats: number of times message should be sent """ ftype = b'\x08\x00' dur = b'\x00\x00' # random hex stream, could be used as additional space of bits src = b'\x08\x00\x27\x8e\x75\x44' # broadcast address is used to stop certain drivers retransmitting frames dst = b'\xff\xff\xff\xff\xff\xff' bssid = src # semi unique id, annoyingly not usable due to lack of bits for this appli sn = (random.randint(0, 4096)) sn = sn << 4 seq = sn.to_bytes(4, 'little') # generate 80211 header header80211 = ftype + dur + dst + src + bssid + seq # combine header with other data to create valid frame data = globaldat.RADIO_TAP + header80211 + b"\x72\x6f\x62\x6f\x74" + \ packet # attach radiotap headers, 80211 headers and yodel payload for i in range(repeats): # re-transmmit message a couple times globaldat.yodelSocket.send(data) # send the data
[docs]def send(payload: any, name: str = "", group: str = "") -> NoReturn: """ take in payload and generate additional data needed to be complient with yodel standard header and add it to the stack for the thread to access. Args: payload: data being sent name: name of recipient group: group of recipient """ global outgoing, outgoing_data # name = kwargs.get("name", '') #receiver name # group = kwargs.get("group", '') #receiver group mtype = 0 # kwargs.get("type", '') #message type if isinstance( payload, Section): # if type is a section than it can be processed automatically mtype = payload.format.mtype payload = bytes(payload) if name: # check for a provided receiver name otherwise make it blank outgoing_data.Rname = name else: outgoing_data.Rname = "" if group: # check for a provided receiving group, otherwise make it blank outgoing_data.Gname = group else: outgoing_data.Gname = "" # set the Sender name for the outgoing data to be equal to the robots name outgoing_data.Sname = globaldat.robotName # generate random indetifier for the message outgoing_data.mid = random.randint(-2147483648, 2147483647) # take the payload and convert it to bytes outgoing_data.payload = typeManagment(payload) outgoing_data.mtype = mtype encoded_frame = bytes(outgoing_data) # get bytes # create object that holds raw bytes as well as data about how it should # be sent outgoing_frame = FrameStruct(encoded_frame) outgoing_frame.repeats = globaldat.totalsends # push data onto stack so that sender thread can access and send off frame globaldat.outgoing.put(outgoing_frame)
[docs]def sender(outgoing: mp.Queue, pipe: mp.Pipe) -> NoReturn: # thread that manages sending out data """ create thread to manage sending data from outgoing stack Args: outgoing: queue that holds all messages being sent pipe: used to send settings updates and other status updates from main to this thread """ while True: if pipe.poll( 0): # check for any new settings updates or other instructions from the main thread settings = pipe.recv() # if there are any then receive them # use these as inputs to the settings update function setting_update(settings[0], settings[1]) frame = outgoing.get() # wait for data in stack to be sent (is blocking) sendData(frame.bytes, frame.repeats)