Skip to content
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

Add a requests-like interface to pysipp.agent.Scenario #4

Closed
goodboy opened this issue Jan 20, 2016 · 8 comments
Closed

Add a requests-like interface to pysipp.agent.Scenario #4

goodboy opened this issue Jan 20, 2016 · 8 comments

Comments

@goodboy
Copy link
Member

goodboy commented Jan 20, 2016

Currently the scenario object supports an interface where you can immediately apply user agent instance variables (which eventually translate to cmd paramaters) via the MultiAccess type with syntax:

def pysipp_conf_scen(scen):
    scen.agents.sockaddr = ('10.10.8.1',  5060)
    scen.clients.timeout = 10000

The agents attr here references the entire scenario agent set and applies the named variable for all contained agents immediately in a loop. Getting the same attribute will result in a returned dictionary who's keys are the agent names and values are the accessed value per agent. This __getattr__/__setattr__ is not only asymmetric but unintuitive.

@vodik has suggested something similar to the requests.session interface.

I propose the following:

  • Scenario.agents, clients, servers simply become dict objects which can contain optional parameter (attribute) overrides. The keys can be any attribute of a pysipp.agent.UserAgent and values act as defaults.
    • clients and servers values (which are mutex) will override agents values and attributes set directly on a UserAgent will always take the highest precedence.
  • pysipp.agent.Scenario will get a prepare method similar to prepared-requests. This method takes in a single UserAgent and returns a copy of that agent now modified as per the params overrides from above such that can be used in place of the original. Scenario.__call__ will of course call prepare on each contained agent before invoking the run protocol hook with the full agent set.
  • the default pysipp_run_protocol hook will be changed to take in an agents sequence argument instead of a scen arg and accordingly the runner arg must be explicitly provided by the caller.
  • the launch.PopenRunner will be modified to remove it's agents arg to __init__ and instead take in a cmditems arg to __call__ such that the entire object becomes 'agent' agnostic and is only concerned with running commands.
@goodboy
Copy link
Member Author

goodboy commented Jan 22, 2016

The last bullet is completed by 18b560b

@goodboy
Copy link
Member Author

goodboy commented Jan 22, 2016

Looking at making requests it seems to me that there really isn't a parallel between pysipp agents and requests request methods.

That is,
requests.post("http://httpbin.org/post", data = {"key":"value"})
and
pysipp.client(sockaddr=('10.10.88.1', 5060), destsockaddr=(<ip>, <port>))
aren't really comparable. Whereas down the road something like
pysipp.invite(<siprequri>)
would be.

In terms of applying command parameters more globally might (some of) the following be appropriate?

# these set the 'global' scenario state
scen.global.sockaddr = ('10.10.8.1',  5060)
scen.global['sockaddr'] = ('10.10.8.1',  5060)
scen.global.update({'sockaddr': ('10.10.8.1',  5060)})

# sets clients group state
scen.clients.sockaddr = ('10.10.8.1',  5060)  
scen.clients['sockaddr'] = ('10.10.8.1',  5060)
scen.clients.update({'sockaddr': ('10.10.8.1',  5060)})

# passed in at run time but not saved permanently
allagents = {
    'sockaddr': ('10.10.8.1',  5060),
    'key_vals': {'domainstr': 'cowboy@horserider.net:5060'},
}
clients = {'sockaddr': ('10.10.8.2',  5060)}
# run the scenario by invoking all commands
scen(block=False, timeout=10, global=allagents, clients=clients)

Also any opinion on whether the __call__ syntax should instead be an explicit method name?

The scenario api could look like:

scen = pysipp.scenario(global=agents, clients=clients)

# create a default ua pair
uas = pysipp.server(sockaddr=(<ip>, <port>))
uac = pysipp.client(*uas.sockaddr, sockaddr=(<ip>, <port>))

# assign agents to the scenario in launch order 
scen.agents = [uas, uac]
# could also have be added at instance time
scen = pysipp.scenario(agents=[uas, uac], global=allagents, clients=clients)

# don't add to `agents` but modify with params and return (copy?)
# this is always done at run time for each agent?
prepped_uac = scen.prepare_agent(uac)

# maybe allow passing agents at call time as well?
# means passed agents are run in place of contained ones?
scen(agents=[uas, uac], block=False, timeout=10, global=agents, clients=clients)

For the hook api I agree that we should definitely have:

def pysipp_conf_scen(agents, scen):
    agents['some wild UAC name'].sockaddr = (<ip>, <port>)
    scen.global.timeout = 10000

^ agents is a dict for explicit referencing whereas scen.agents is a sequence which determines not only contained agents but also the launch order?

Looking for some serious feedback here...

@vodik
Copy link
Member

vodik commented Jan 22, 2016

How about:

def pysipp_conf_scen(agents, scen):
    agents['some wild UAC name'].sockaddr = (<ip>, <port>)
    scen.timeout = 10000

Less typing. You can keep the scen.global dict (I think defaults is more descriptive) behind the scenes for storage.

@goodboy
Copy link
Member Author

goodboy commented Jan 22, 2016

+1

@goodboy
Copy link
Member Author

goodboy commented Jan 22, 2016

For the pysipp.agent.UserAgent api I also suggest the following changes:
sockaddr -> srcaddr
remotesockaddr -> destaddr
mediasockaddr -> mediaaddr
ipcsockaddr -> ipcaddr

for Scenario I propose:
socket2agents -> findbyaddr

@vodik
Copy link
Member

vodik commented Jan 25, 2016

Works for me.

@goodboy
Copy link
Member Author

goodboy commented Jan 29, 2016

For the record I ended up going with:

def pysipp_conf_scen(scen):
    scen.defaults.sockaddr = ('10.10.8.1',  5060)
    scen.clientdefaults.timeout = 10000

__setattr__, __setitem__, AND update are supported

@goodboy
Copy link
Member Author

goodboy commented Feb 3, 2016

Closed by dbe28b1

@goodboy goodboy closed this as completed Feb 3, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants