[svn-commits] dlee: branch dlee/stasis-http r381826 - in /team/dlee/stasis-http: ./ build_t...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Wed Feb 20 10:39:38 CST 2013
Author: dlee
Date: Wed Feb 20 10:39:34 2013
New Revision: 381826
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381826
Log:
Merged stasis-http work from old branch
Added:
team/dlee/stasis-http/build_tools/make_stasis_http_stubs (with props)
team/dlee/stasis-http/cog/
team/dlee/stasis-http/cog/res_stasis_http.make.cog (with props)
team/dlee/stasis-http/cog/stasis_cog.py (with props)
team/dlee/stasis-http/cog/stasis_http_resource.c.cog (with props)
team/dlee/stasis-http/cog/stasis_http_resource.h.cog (with props)
team/dlee/stasis-http/cog/stasis_http_resources.c.cog (with props)
team/dlee/stasis-http/include/asterisk/stasis_http.h (with props)
team/dlee/stasis-http/include/asterisk/stasis_http_asterisk.h (with props)
team/dlee/stasis-http/include/asterisk/stasis_http_bridges.h (with props)
team/dlee/stasis-http/include/asterisk/stasis_http_channels.h (with props)
team/dlee/stasis-http/include/asterisk/stasis_http_endpoints.h (with props)
team/dlee/stasis-http/include/asterisk/stasis_http_recordings.h (with props)
team/dlee/stasis-http/res/res_stasis_http.c (with props)
team/dlee/stasis-http/res/res_stasis_http.exports.in (with props)
team/dlee/stasis-http/res/res_stasis_http.make (with props)
team/dlee/stasis-http/res/stasis_http_asterisk.c (with props)
team/dlee/stasis-http/res/stasis_http_bridges.c (with props)
team/dlee/stasis-http/res/stasis_http_channels.c (with props)
team/dlee/stasis-http/res/stasis_http_endpoints.c (with props)
team/dlee/stasis-http/res/stasis_http_recordings.c (with props)
team/dlee/stasis-http/res/stasis_http_resources.c (with props)
team/dlee/stasis-http/rest-api/
team/dlee/stasis-http/rest-api/README.txt (with props)
team/dlee/stasis-http/rest-api/asterisk.json (with props)
team/dlee/stasis-http/rest-api/bridges.json (with props)
team/dlee/stasis-http/rest-api/channels.json (with props)
team/dlee/stasis-http/rest-api/endpoints.json (with props)
team/dlee/stasis-http/rest-api/recordings.json (with props)
team/dlee/stasis-http/rest-api/resources.json (with props)
team/dlee/stasis-http/tests/test_stasis_http.c (with props)
Modified:
team/dlee/stasis-http/Makefile
team/dlee/stasis-http/include/asterisk/http.h
team/dlee/stasis-http/include/asterisk/strings.h
team/dlee/stasis-http/include/asterisk/utils.h
team/dlee/stasis-http/main/http.c
team/dlee/stasis-http/res/Makefile
team/dlee/stasis-http/tests/test_strings.c
Modified: team/dlee/stasis-http/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/Makefile?view=diff&rev=381826&r1=381825&r2=381826
==============================================================================
--- team/dlee/stasis-http/Makefile (original)
+++ team/dlee/stasis-http/Makefile Wed Feb 20 10:39:34 2013
@@ -448,6 +448,9 @@
$(INSTALL) -m 644 $$x "$(DESTDIR)$(ASTDATADIR)/images" ; \
done
$(MAKE) -C sounds install
+ find rest-api -name "*.json" | while read x; do \
+ $(INSTALL) -m 644 $$x "$(DESTDIR)$(ASTDATADIR)/rest-api" ; \
+ done
doc/core-en_US.xml: makeopts $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
@printf "Building Documentation For: "
@@ -524,8 +527,8 @@
"$(ASTLOGDIR)/cel-custom" "$(ASTDATADIR)" "$(ASTDATADIR)/documentation" \
"$(ASTDATADIR)/documentation/thirdparty" "$(ASTDATADIR)/firmware" \
"$(ASTDATADIR)/firmware/iax" "$(ASTDATADIR)/images" "$(ASTDATADIR)/keys" \
- "$(ASTDATADIR)/phoneprov" "$(ASTDATADIR)/static-http" "$(ASTDATADIR)/sounds" \
- "$(ASTDATADIR)/moh" "$(ASTMANDIR)/man8" "$(AGI_DIR)" "$(ASTDBDIR)"
+ "$(ASTDATADIR)/phoneprov" "$(ASTDATADIR)/rest-api" "$(ASTDATADIR)/static-http" \
+ "$(ASTDATADIR)/sounds" "$(ASTDATADIR)/moh" "$(ASTMANDIR)/man8" "$(AGI_DIR)" "$(ASTDBDIR)"
installdirs:
@for i in $(INSTALLDIRS); do \
@@ -945,6 +948,10 @@
@cat sounds/sounds.xml >> $@
@echo "</menu>" >> $@
+# We don't want to require Python or Cog for every build, so this is its own target.
+stasis-stubs:
+ build_tools/make_stasis_http_stubs
+
.PHONY: menuselect
.PHONY: main
.PHONY: sounds
@@ -965,6 +972,7 @@
.PHONY: installdirs
.PHONY: validate-docs
.PHONY: _clean
+.PHONY: stasis-stubs
.PHONY: $(SUBDIRS_INSTALL)
.PHONY: $(SUBDIRS_DIST_CLEAN)
.PHONY: $(SUBDIRS_CLEAN)
Added: team/dlee/stasis-http/build_tools/make_stasis_http_stubs
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/build_tools/make_stasis_http_stubs?view=auto&rev=381826
==============================================================================
--- team/dlee/stasis-http/build_tools/make_stasis_http_stubs (added)
+++ team/dlee/stasis-http/build_tools/make_stasis_http_stubs Wed Feb 20 10:39:34 2013
@@ -1,0 +1,43 @@
+#!/bin/sh
+
+#
+# Wrapper script to run cog on stasis_http templates.
+#
+
+TOPDIR=$(cd $(dirname $0)/.. && pwd)
+PROGNAME=$(basename $0)
+
+: ${COG:=cog.py}
+
+# Exit on error
+set -e
+
+if ! which ${COG} > /dev/null 2>&1; then
+ echo "${PROGNAME}: Cannot execute ${COG}" >&2
+ echo " You probably need to run sudo pip install cogapp" >&2
+ exit 1
+fi
+
+cd ${TOPDIR}
+
+sources=""
+
+for json in rest-api/*.json; do
+ echo "Cogging ${json}"
+ name=$(basename ${json} .json)
+ sources="${sources} stasis_http_${name}.o"
+ if test ${name} = resources; then
+ ${COG} -I cog/ -D RESOURCES=${json} -d -o res/stasis_http_resources.c cog/stasis_http_resources.c.cog
+ else
+ ${COG} -I cog/ -D RESOURCE=${json} -d -o include/asterisk/stasis_http_${name}.h cog/stasis_http_resource.h.cog
+ if ! test -e res/stasis_http_${name}.c; then
+ # Only write the file if it doesn't exist; otherwise you'll overwrite someone's hard work.
+ echo " Generating source stubs"
+ ${COG} -I cog/ -D RESOURCE=${json} -d -o res/stasis_http_${name}.c cog/stasis_http_resource.c.cog
+ fi
+ fi
+done
+
+# Generate the makefile for the dependencies
+echo "Cogging res_stasis_http.make"
+${COG} -I cog/ -D SOURCES="${sources}" -D TARGET="res_stasis_http.so" -d -o res/res_stasis_http.make cog/res_stasis_http.make.cog
Propchange: team/dlee/stasis-http/build_tools/make_stasis_http_stubs
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/dlee/stasis-http/build_tools/make_stasis_http_stubs
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/dlee/stasis-http/build_tools/make_stasis_http_stubs
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/dlee/stasis-http/cog/res_stasis_http.make.cog
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/cog/res_stasis_http.make.cog?view=auto&rev=381826
==============================================================================
--- team/dlee/stasis-http/cog/res_stasis_http.make.cog (added)
+++ team/dlee/stasis-http/cog/res_stasis_http.make.cog Wed Feb 20 10:39:34 2013
@@ -1,0 +1,23 @@
+# -*- Makefile -*-
+
+#
+# Asterisk -- A telephony toolkit for Linux.
+#
+# Generated Makefile for res_stasis_http dependencies.
+#
+#
+# [[[cog
+# # Copyright (C) 2012 - 2013, Digium, Inc.
+# import cog, datetime
+# now = datetime.datetime.now()
+# # Now write the Copyright in the output makefile
+# cog.outl("# Copyright (C) 2012 - %s, Digium, Inc." % now.year)
+# ]]]
+# [[[end]]]
+#
+# This program is free software, distributed under the terms of
+# the GNU General Public License
+#
+
+# [[[cog import cog, stasis_cog; stasis_cog.do_not_edit('#'); cog.outl('%s: %s' % (TARGET, SOURCES))]]]
+# [[[end]]]
Propchange: team/dlee/stasis-http/cog/res_stasis_http.make.cog
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/dlee/stasis-http/cog/res_stasis_http.make.cog
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Propchange: team/dlee/stasis-http/cog/res_stasis_http.make.cog
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/dlee/stasis-http/cog/stasis_cog.py
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/cog/stasis_cog.py?view=auto&rev=381826
==============================================================================
--- team/dlee/stasis-http/cog/stasis_cog.py (added)
+++ team/dlee/stasis-http/cog/stasis_cog.py Wed Feb 20 10:39:34 2013
@@ -1,0 +1,503 @@
+#
+# Asterisk -- An open source telephony toolkit.
+#
+# Copyright (C) 2012 - 2013, Digium, Inc.
+#
+# David M. Lee, II <dlee at digium.com>
+#
+# See http://www.asterisk.org for more information about
+# the Asterisk project. Please do not directly contact
+# any of the maintainers of this project for assistance;
+# the project provides a web site, mailing lists and IRC
+# channels for your use.
+#
+# This program is free software, distributed under the terms of
+# the GNU General Public License Version 2. See the LICENSE file
+# at the top of the source tree.
+#
+
+"""Swagger code generator for Asterisk.
+
+This file reads in Swagger API documentation and generates a series of
+implemenation stubs for the Asterisk HTTP server. Using swagger-codegen
+was a bit too heavyweight, and adding Java as a dependency for developers
+would engender much unnecessary hate.
+"""
+
+import cog
+import json
+import os
+import os.path
+import re
+import textwrap
+from collections import OrderedDict
+
+SWAGGER_VERSION="1.1"
+
+class ResourceListingSourceWriter(object):
+ """Writes the resources.c file from Swagger API docs.
+ """
+
+ def __init__(self, root):
+ self.root = root
+
+ def write(self):
+ """Write source code for this resource, and all decendants.
+ """
+ self.write_includes()
+ # Callbacks are referenced by handlers, so write them first
+ self.write_callbacks(self.root)
+ self.write_handlers(self.root)
+
+ def write_includes(self):
+ """Write the #includes for resources.c
+ """
+ for include in self.root.includes:
+ cog.outl('#include "%s"' % include)
+ cog.outl("#include <inttypes.h>")
+ cog.outl("#include <strings.h>")
+ cog.outl()
+
+ def write_callbacks(self, resource):
+ """Write the callback functions for the resource
+ """
+ # Children first, for consistency with handler order
+ for child in resource.children.itervalues():
+ self.write_callbacks(child)
+
+ for operation in resource.operations.itervalues():
+ self.write_callback(operation)
+
+ def write_callback(self, operation):
+ """Writes the Operations's callback function definition
+ """
+ cog.outl('static void %s(struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct stasis_http_response *response)' % operation.get_callback_name())
+ cog.outl('{')
+ if operation.path_parameters or operation.query_parameters:
+ cog.outl('\tstruct ast_variable *i;');
+ cog.outl('\t%s args = {};' % operation.get_args_name())
+ cog.outl('')
+ if operation.path_parameters:
+ cog.outl('\tfor (i = path_vars; i; i = i->next) {')
+ for param in operation.path_parameters.itervalues():
+ cog.outl('\t\tif (strcmp(i->name, "%s") == 0) {' % param.name)
+ cog.outl('\t\t\targs.%s = i->value;' % param.c_name)
+ cog.outl('\t\t}')
+ cog.outl('\t}')
+ if operation.query_parameters:
+ cog.outl('\tfor (i = get_params; i; i = i->next) {')
+ for param in operation.query_parameters.itervalues():
+ cog.outl('\t\tif (strcmp(i->name, "%s") == 0) {' % param.name)
+ cog.outl('\t\t\targs.%s = %s;' % (param.c_name, param.decoder("i->value")))
+ cog.outl('\t\t}')
+ cog.outl('\t}')
+ cog.outl('\t%s(headers, &args, response);' % operation.get_impl_name())
+ cog.outl('}')
+ cog.outl()
+
+ def write_handlers(self, resource):
+ """Write the stasis_rest_handlers for the resource
+ """
+ # Children are referred to by handler, so write them first
+ for child in resource.children.itervalues():
+ self.write_handlers(child)
+
+ cog.outl('static struct stasis_rest_handlers %s = {' % resource.get_name())
+ cog.outl('\t.path_segment = "%s",' % resource.path_element)
+ if resource.is_wildcard:
+ cog.outl('\t.is_wildcard = 1,')
+ cog.outl('\t.callbacks = {')
+ for operation in resource.operations.itervalues():
+ cog.outl('\t\t[AST_HTTP_%s] = %s,' % (operation.http_method, operation.get_callback_name()))
+ cog.outl('\t},')
+ cog.outl('\t.num_children = %d,' % len(resource.children))
+ cog.out('\t.children = { ')
+ for child in resource.children.itervalues():
+ cog.out('&%s, ' % child.get_name())
+ cog.outl('},')
+ cog.outl('};')
+ cog.outl()
+
+class ApiDeclarationHeaderWriter(object):
+ """Writes the .h for for a Swagger API Declaration file.
+ """
+
+ def __init__(self, root):
+ self.root = root
+
+ def write(self):
+ """Writes the corresponding header file for this resource's operations.
+ """
+ (name, ext) = os.path.splitext(os.path.basename(cog.outFile))
+ incl_guard = '_ASTERISK_%s_H' % name.upper()
+ cog.outl('#ifndef %s' % incl_guard)
+ cog.outl('#define %s' % incl_guard)
+ # args structures first, so the prototypes can easily be copy/pasted in one blob
+ self.write_structs(self.root)
+ self.write_impl_prototypes(self.root)
+ cog.outl('#endif /* %s */' % incl_guard)
+
+ def write_structs(self, resource):
+ """Write the args structs for the resource's operations.
+ """
+ # Children first, so we're in the same order as resources.c
+ for child in resource.children.itervalues():
+ self.write_structs(child)
+
+ for operation in resource.operations.itervalues():
+ cog.outl('%s {' % operation.get_args_name())
+ for param in operation.get_all_parameters().itervalues():
+ if param.description:
+ cog.outl('\t/*! %s */' % (param.description))
+ cog.out('\t%s' % param.c_type)
+ if not param.c_type.endswith('*'):
+ cog.out(' ')
+ cog.outl('%s;' % param.c_name)
+ cog.outl('};')
+
+ def write_impl_prototypes(self, resource):
+ """Write the prototypes for all the implementation functions in the given resource's operations.
+ """
+ # Children first, so we're in the same order as resources.c
+ for child in resource.children.itervalues():
+ self.write_impl_prototypes(child)
+
+ for operation in resource.operations.itervalues():
+ cog.outl('/*!')
+ if operation.summary.endswith('.'):
+ raise ValueError("Operation summary should not end with a period (%s)" % operation.summary)
+
+ # swagger spec recommends no more than 60 chars in the summary
+ # See https://github.com/wordnik/swagger-core/wiki/API-Declaration
+ if len(operation.summary) > 60:
+ raise ValueError("Operaiton summary too long (%s)" % operation.summary)
+ cog.outl(' * \\brief %s.' % operation.summary)
+ if operation.notes:
+ cog.outl(' *')
+ for line in textwrap.wrap(operation.notes, 79, initial_indent = ' * ', subsequent_indent = ' * '):
+ cog.outl(line)
+ cog.outl(' *')
+ cog.outl(' * \param headers HTTP headers')
+ cog.outl(' * \param args Swagger parameters')
+ cog.outl(' * \param[out] response HTTP response')
+ cog.outl(' */')
+ cog.outl('void %s(struct ast_variable *headers, %s *args, struct stasis_http_response *response);' % (operation.get_impl_name(), operation.get_args_name()))
+
+def write_operation_declaration(operation):
+ """Common code for writing an operation handler's doc comment and prototype.
+ """
+
+class ApiDeclarationSourceWriter(object):
+ """Writes the .c for for a Swagger API Declaration file.
+
+ Note that these are stubs to be filled in by the developer, so they are
+ generally only generated if the target file does not exist.
+ """
+
+ def __init__(self, root):
+ self.root = root
+
+ def write(self):
+ """Writes the corresponding source stubs file for this resource's operations.
+ """
+ (name, ext) = os.path.splitext(os.path.basename(cog.outFile))
+ cog.outl('#include "asterisk/%s.h"' % name)
+ cog.outl()
+ self.write_impl_stubs(self.root)
+
+ def write_impl_stubs(self, resource):
+ """Write the stubs for all the implementation functions in the given resource's operations.
+ """
+ # Children first, so we're in the same order as the header file
+ for child in resource.children.itervalues():
+ self.write_impl_stubs(child)
+
+ for operation in resource.operations.itervalues():
+ cog.outl('void %s(struct ast_variable *headers, %s *args, struct stasis_http_response *response)' % (operation.get_impl_name(), operation.get_args_name()))
+ cog.outl('{')
+ cog.outl('\tast_log(LOG_ERROR, "TODO: %s\\n");' % operation.get_impl_name())
+ cog.outl('}')
+
+class Resource(object):
+ """Resource from a Swagger API declaration.
+
+ Each path element in the 'path' declarations of 'apis' gets a Resource
+ object associated with it, which specifies the HTTP methods that Resource
+ supports.
+
+ See https://github.com/wordnik/swagger-core/wiki/API-Declaration details on
+ the structions of the API declaration.
+ """
+
+ def __init__(self, parent_name, path_element):
+ self.parent_name = parent_name
+ if path_element.startswith('{') and path_element.endswith('}'):
+ self.is_wildcard = True
+ self.path_element = path_element[1:-1]
+ else:
+ self.is_wildcard = False
+ self.path_element = path_element
+ # It's important to maintain order of the children
+ # Otherwise, search order won't match the .json files
+ self.children = OrderedDict()
+ self.operations = OrderedDict()
+ self.includes = []
+ self.author = None
+ self.copyright = None
+ self.basePath = None
+
+ if not is_identifier(self.get_name()):
+ raise ValueError("Invalid path name: %s" % path_element)
+
+ def load_resource_listing(self, resource_listing_file):
+ """Loads resource_listing from a Swagger resources.json file.
+ """
+ assert not self.children, "Should not reload existing resource"
+ assert not self.operations, "Should not reload existing resource"
+
+ resource_listing_dir = os.path.dirname(resource_listing_file)
+ with open(resource_listing_file) as fp:
+ resource_listing = json.load(fp)
+
+ self.author = resource_listing.get('_author')
+ self.copyright = resource_listing.get('_copyright')
+
+ swagger_version = resource_listing.get('swaggerVersion')
+ if not swagger_version == SWAGGER_VERSION:
+ raise ValueError("Unsupported Swagger version %s" % swagger_version)
+
+ self.basePath = resource_listing.get('basePath')
+ if self.basePath is None:
+ raise ValueError("basePath missing from %s" % resource_listing_file)
+
+ for api in resource_listing['apis']:
+ # Path in json is URI relative, so we need to drop the initial /api/
+ path = api['path'].replace('/', '', 1)
+ api_declaration_file = os.path.abspath(os.path.join(resource_listing_dir, path)).format(format = 'json')
+ (basename, ext) = os.path.splitext(os.path.basename(api_declaration_file))
+ self.includes.append('asterisk/stasis_http_%s.h' % basename)
+ self.load_api_declaration(api_declaration_file)
+
+ def load_api_declaration(self, api_declaration_file):
+ """Loads a resource from a single Swagger resource.json file.
+ """
+ with open(api_declaration_file) as fp:
+ api_declaration = json.load(fp)
+
+ self.author = self.author or api_declaration.get('_author')
+ self.copyright = self.copyright or api_declaration.get('_copyright')
+
+ swagger_version = api_declaration.get('swaggerVersion')
+ if swagger_version != SWAGGER_VERSION:
+ raise ValueError("Unsupported Swagger version %s" % swagger_version)
+
+ if self.basePath and api_declaration.get('basePath') != self.basePath:
+ raise ValueError("invalid basePath in %s" % api_declaration_file)
+
+ for api in api_declaration['apis']:
+ resource_path = api['path'].split('/')
+ # remove empty strings from resource_path
+ resource_path = filter(lambda x: x, resource_path)
+ resource = self.get_child(resource_path)
+ for operation in api['operations']:
+ op = resource.add_operation(operation['httpMethod'], operation['nickname'])
+ op.summary = operation.get('summary')
+ op.notes = operation.get('notes')
+ for param in operation.get('parameters') or []:
+ op.add_parameter(name = param['name'],
+ description = param['description'],
+ param_type = param['paramType'],
+ required = param.get('required'),
+ allowMultiple = param.get('allowMultiple'),
+ dataType = param.get('dataType'),
+ defaultValue = param.get('defaultValue'))
+
+ def get_name(self):
+ """Returns the fully qualified name of this Resource.
+ """
+ if self.parent_name:
+ return '%s_%s' % (self.parent_name, self.path_element)
+ else:
+ return self.path_element
+
+ def get_child(self, path_list):
+ """Finds the decendent specified by path_list.
+
+ This method will create any missing decendants along the way, if needed.
+ """
+ if not path_list:
+ return self
+
+ path_element = path_list[0]
+ r = self.children.get(path_element)
+ if r is None:
+ r = Resource(self.get_name(), path_element)
+ self.children[path_element] = r
+ return r.get_child(path_list[1:])
+
+ def add_operation(self, http_method, nickname):
+ """Add an operation to this resource.
+ """
+ op = Operation(http_method, nickname)
+ self.operations[http_method] = op
+ return op
+
+class Operation(object):
+ """Swagger operation
+ """
+ def __init__(self, http_method, nickname):
+ self.http_method = http_method
+ self.nickname = snakify(nickname)
+ self.query_parameters = OrderedDict()
+ self.path_parameters = OrderedDict()
+ self.summary = None
+ self.notes = None
+
+ if not is_identifier(self.get_callback_name()) or not is_identifier(self.nickname):
+ raise ValueError("Invalid operation nickname: %s" % nickname)
+
+ def add_parameter(self, name, description, param_type, required, allowMultiple, dataType, defaultValue):
+ if param_type == 'path':
+ p = self.path_parameters
+ elif param_type == 'query':
+ p = self.query_parameters
+ else:
+ raise ValueError("Invalid param_type: %s" % param_type)
+ p[name] = Parameter(name = name, description = description, required = required, allowMultiple = allowMultiple, dataType = dataType, defaultValue = defaultValue)
+
+ def get_all_parameters(self):
+ return OrderedDict(self.path_parameters.items() + self.query_parameters.items())
+
+ def get_callback_name(self):
+ """Returns the name of this Operation's callback function.
+ """
+ return "%s_cb" % self.get_impl_name()
+
+ def get_impl_name(self):
+ """Returns the name of this Operation's callback function.
+ """
+ return "stasis_http_%s" % self.nickname
+
+ def get_args_name(self):
+ """Returns the name of impl's args struct.
+ """
+ return "struct ast_%s_args" % self.nickname
+
+class Parameter(object):
+ """Swagger operation parameter.
+ """
+ def __init__(self, name, description, required, allowMultiple, dataType, defaultValue):
+ self.name = name
+ self.description = description
+ self.required = required
+ self.allowMultiple = allowMultiple
+ self.dataType = dataType
+ self.defaultValue = defaultValue
+ self.c_name = snakify(self.name)
+
+ if dataType == 'string':
+ self.c_type = 'const char *'
+ elif dataType == 'boolean':
+ self.c_type = 'int'
+ elif dataType == 'number':
+ self.c_type = 'int'
+ else:
+ raise ValueError("Invalid dataType: %s" % dataType)
+
+ if not is_identifier(self.c_name):
+ raise ValueError("Invalid paramater name: %s" % name)
+
+ def decoder(self, char_pointer):
+ """Returns the C code for decoding this param from a string.
+ """
+ if self.dataType == 'string':
+ return char_pointer
+ elif self.dataType == 'boolean':
+ return 'ast_true(%s)' % char_pointer
+ elif self.dataType == 'number':
+ return 'strtol(%s, NULL, 0)' % char_pointer
+ else:
+ assert False, "Someone forgot to update the decoder"
+ return char_pointer
+
+def snakify(name):
+ """Helper to take a camelCase or dash-seperated name and make it snake_case.
+ """
+ r = ''
+ prior_lower = False
+ for c in name:
+ if c.isupper() and prior_lower:
+ r += "_"
+ if c is '-':
+ c = '_'
+ prior_lower = c.islower()
+ r += c.lower()
+ return r
+
+def is_identifier(str):
+ """Returns True if given string is a valid C identifier; False otherwise
+ """
+ return re.match('^[_A-Za-z][_A-Za-z0-9]*$', str) is not None
+
+def do_not_edit(comment_style = 'C'):
+ """Write the do not edit warning.
+
+ Note that this doesn't apply to this file, just the generated output. But I
+ hope that you knew that already. Right?
+ """
+ msg = """~
+~ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+~ !!!!! DO NOT EDIT !!!!!
+~ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+~ This file is generated by a Cog template. Please see the original template
+~ at %s
+~""" % cog.inFile
+ if comment_style == 'C':
+ msg = msg.replace('~', '/*', 1)
+ msg = msg.replace('~', ' *')
+ msg += '/'
+ elif comment_style == '#':
+ msg = msg.replace('~', '#')
+ else:
+ raise ValueError("Invalid comment style: %s" % comment_style)
+ cog.outl(msg)
+
+def write_resource_copyright(prefix, resource):
+ """Write the copyright statement for the given resource.
+ """
+ root = Resource('', 'stasis')
+ root.load_api_declaration(resource)
+ if root.copyright is None:
+ raise ValueError("Missing copyright statement in %s" % resource)
+ cog.out(prefix)
+ cog.out(root.copyright)
+
+def write_resource_author(prefix, resource):
+ """Write the author name for the given resource.
+ """
+ root = Resource('', 'stasis')
+ root.load_api_declaration(resource)
+ if root.author is None:
+ raise ValueError("Missing author statement in %s" % resource)
+ cog.out(prefix)
+ cog.out(root.author)
+
+def write_resources_copyright(prefix, resources):
+ """Write the copyright statement for the given resources.
+ """
+ root = Resource('', 'stasis')
+ root.load_resource_listing(resources)
+ if root.copyright is None:
+ raise ValueError("Missing copyright statement in %s" % resources)
+ cog.out(prefix)
+ cog.out(root.copyright)
+
+def write_resources_author(prefix, resources):
+ """Write the author name for the given resources.
+ """
+ root = Resource('', 'stasis')
+ root.load_resource_listing(resources)
+ if root.author is None:
+ raise ValueError("Missing author statement in %s" % resources)
+ cog.out(prefix)
+ cog.out(root.author)
Propchange: team/dlee/stasis-http/cog/stasis_cog.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/dlee/stasis-http/cog/stasis_cog.py
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Propchange: team/dlee/stasis-http/cog/stasis_cog.py
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/dlee/stasis-http/cog/stasis_http_resource.c.cog
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/cog/stasis_http_resource.c.cog?view=auto&rev=381826
==============================================================================
--- team/dlee/stasis-http/cog/stasis_http_resource.c.cog (added)
+++ team/dlee/stasis-http/cog/stasis_http_resource.c.cog Wed Feb 20 10:39:34 2013
@@ -1,0 +1,46 @@
+/* -*- C -*-
+ * Asterisk -- An open source telephony toolkit.
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resource_copyright(' * ', RESOURCE)]]]
+ * Copyright (C) 2012 - 2013, Digium, Inc.
+ [[[end]]]
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resource_author(' * ', RESOURCE)]]]
+ * David M. Lee, II <dlee at digium.com>
+ [[[end]]]
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Implementation for stasis-http stubs.
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resource_author(' * \\author ', RESOURCE)]]]
+ [[[end]]]
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+/* [[[cog
+import stasis_cog
+
+root = stasis_cog.Resource('', 'stasis')
+root.load_api_declaration(RESOURCE)
+stasis_cog.ApiDeclarationSourceWriter(root).write()
+]]] */
+/*[[[end]]]*/
Propchange: team/dlee/stasis-http/cog/stasis_http_resource.c.cog
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/dlee/stasis-http/cog/stasis_http_resource.c.cog
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Propchange: team/dlee/stasis-http/cog/stasis_http_resource.c.cog
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/dlee/stasis-http/cog/stasis_http_resource.h.cog
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/cog/stasis_http_resource.h.cog?view=auto&rev=381826
==============================================================================
--- team/dlee/stasis-http/cog/stasis_http_resource.h.cog (added)
+++ team/dlee/stasis-http/cog/stasis_http_resource.h.cog Wed Feb 20 10:39:34 2013
@@ -1,0 +1,41 @@
+/* -*- C -*-
+ * Asterisk -- An open source telephony toolkit.
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resource_copyright(' * ', RESOURCE)]]]
+ * Copyright (C) 2012 - 2013, Digium, Inc.
+ [[[end]]]
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resource_author(' * ', RESOURCE)]]]
+ * David M. Lee, II <dlee at digium.com>
+ [[[end]]]
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Generated file - declares stubs to be implemented for stasis_http
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resource_author(' * \\author ', RESOURCE)]]]
+ [[[end]]]
+ */
+
+#include "asterisk/stasis_http.h"
+
+/* [[[cog
+import stasis_cog
+
+stasis_cog.do_not_edit()
+root = stasis_cog.Resource('', 'stasis')
+root.load_api_declaration(RESOURCE)
+stasis_cog.ApiDeclarationHeaderWriter(root).write()
+]]] */
+/*[[[end]]]*/
Propchange: team/dlee/stasis-http/cog/stasis_http_resource.h.cog
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/dlee/stasis-http/cog/stasis_http_resource.h.cog
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Propchange: team/dlee/stasis-http/cog/stasis_http_resource.h.cog
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/dlee/stasis-http/cog/stasis_http_resources.c.cog
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/cog/stasis_http_resources.c.cog?view=auto&rev=381826
==============================================================================
--- team/dlee/stasis-http/cog/stasis_http_resources.c.cog (added)
+++ team/dlee/stasis-http/cog/stasis_http_resources.c.cog Wed Feb 20 10:39:34 2013
@@ -1,0 +1,55 @@
+/* -*- C -*-
+ * Asterisk -- An open source telephony toolkit.
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resources_copyright(' * ', RESOURCES)]]]
+ * Copyright (C) 2012 - 2013, Digium, Inc.
+ [[[end]]]
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resources_author(' * ', RESOURCES)]]]
+ * David M. Lee, II <dlee at digium.com>
+ [[[end]]]
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Generated file - provides Stasis API HTTP entry points
+ *
+ [[[cog import stasis_cog; stasis_cog.write_resources_author(' * \\author ', RESOURCES)]]]
+ [[[end]]]
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/stasis_http.h"
+#include "asterisk/strings.h"
+
+/* [[[cog
+import stasis_cog
+
+stasis_cog.do_not_edit()
+
+root = stasis_cog.Resource('', 'stasis')
+root.load_resource_listing(RESOURCES)
+stasis_cog.ResourceListingSourceWriter(root).write()
+]]] */
+/*[[[end]]]*/
+
+struct stasis_rest_handlers *stasis_default_root_handler(void) {
+ return &stasis;
+}
Propchange: team/dlee/stasis-http/cog/stasis_http_resources.c.cog
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/dlee/stasis-http/cog/stasis_http_resources.c.cog
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Propchange: team/dlee/stasis-http/cog/stasis_http_resources.c.cog
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/dlee/stasis-http/include/asterisk/http.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/http.h?view=diff&rev=381826&r1=381825&r2=381826
==============================================================================
--- team/dlee/stasis-http/include/asterisk/http.h (original)
+++ team/dlee/stasis-http/include/asterisk/http.h Wed Feb 20 10:39:34 2013
@@ -58,7 +58,9 @@
AST_HTTP_GET = 0,
AST_HTTP_POST,
AST_HTTP_HEAD,
- AST_HTTP_PUT, /*!< Not supported in Asterisk */
+ AST_HTTP_PUT,
+ AST_HTTP_DELETE,
+ AST_HTTP_MAX_METHOD, /*!< Last entry in ast_http_method enum */
};
struct ast_http_uri;
Added: team/dlee/stasis-http/include/asterisk/stasis_http.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/stasis_http.h?view=auto&rev=381826
==============================================================================
--- team/dlee/stasis-http/include/asterisk/stasis_http.h (added)
+++ team/dlee/stasis-http/include/asterisk/stasis_http.h Wed Feb 20 10:39:34 2013
@@ -1,0 +1,136 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012 - 2013, Digium, Inc.
+ *
+ * David M. Lee, II <dlee at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef _ASTERISK_STASIS_HTTP_H
+#define _ASTERISK_STASIS_HTTP_H
+
+/*! \file
+ *
+ * \brief Stasis RESTful API hooks.
+ *
+ * This header file is used mostly as glue code between generated declarations
+ * and res_stasis_http.c.
+ *
+ * \author David M. Lee, II <dlee at digium.com>
+ */
+
+#include "asterisk/http.h"
+#include "asterisk/json.h"
+#include "asterisk/http_websocket.h"
+
+struct stasis_http_response;
+
+/*!
+ * \brief Callback type for RESTful method handlers.
+ * \param get_params GET parameters from the HTTP request.
+ * \param path_vars Path variables from any wildcard path segments.
+ * \param headers HTTP headers from the HTTP requiest.
+ * \param[out] response The RESTful response.
+ */
+typedef void (*stasis_rest_callback)(struct ast_variable *get_params,
+ struct ast_variable *path_vars,
+ struct ast_variable *headers,
+ struct stasis_http_response *response);
+
+/*!
+ * \brief Handler for a single RESTful path segment.
+ */
+struct stasis_rest_handlers {
+ /*! Path segement to handle */
+ const char *path_segment;
+ /*! If true (non-zero), path_segment is a wildcard, and will match all values.
+ *
+ * Value of the segement will be passed into the \a path_vars parameter of the callback.
+ */
+ int is_wildcard;
+ /*! Callbacks for all handled HTTP methods. */
+ stasis_rest_callback callbacks[AST_HTTP_MAX_METHOD];
+ /*! Number of children in the children array */
+ size_t num_children;
+ /*! Handlers for sub-paths */
+ struct stasis_rest_handlers *children[];
+};
+
+/*!
+ * Response type for RESTful requests
+ */
+struct stasis_http_response {
+ /*! Response message */
+ struct ast_json *message;
+ /*! HTTP response code. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html */
+ int response_code;
+ /*! Corresponding text for the response code */
+ const char *response_text; // Shouldn't http.c handle this?
+};
+
+/*!
+ * \brief Handler for the default root RESTful resource.
+ */
+struct stasis_rest_handlers *stasis_default_root_handler(void);
+
+/*!
+ * \internal
+ * \brief Set a new handler for the root RESTful resource.
+ *
+ * Only call from res_stasis_http and test_stasis_http. Only public to allow
+ * for unit testing.
+ *
+ * \param new_handler New root RESTful handler.
+ * \param return The old handler.
+ */
+struct stasis_rest_handlers *stasis_set_root_handler(struct stasis_rest_handlers *new_handler);
+
+/*!
+ * \internal
+ * \brief Stasis RESTful invocation handler.
+ *
+ * Only call from res_stasis_http and test_stasis_http. Only public to allow
+ * for unit testing.
+ *
+ * \param uri HTTP URI, relative to the API path.
+ * \param method HTTP method.
+ * \param get_params HTTP \c GET parameters.
+ * \param headers HTTP headers.
+ * \param[out] response RESTful HTTP response.
+ */
+void stasis_http_invoke(const char *uri, enum ast_http_method method, struct ast_variable *get_params,
+ struct ast_variable *headers, struct stasis_http_response *response);
+
+/*!
+ * \internal
+ * \brief Service function for API declarations.
+ *
+ * Only call from res_stasis_http and test_stasis_http. Only public to allow
+ * for unit testing.
+ *
+ * \param uri Requested URI, relative to the docs path.
+ * \param headers HTTP headers.
+ * \param[out] response RESTful HTTP response.
+ */
+void stasis_http_get_docs(const char *uri, struct ast_variable *headers, struct stasis_http_response *response);
+
+/*!
+ * \internal
+ * \brief Stasis WebSocket connection handler
+ * \param session WebSocket session.
+ * \param parameters HTTP \c GET parameters.
+ * \param headers HTTP headers.
+ */
+void stasis_websocket_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers);
+
+#endif /* _ASTERISK_STASIS_HTTP_H */
Propchange: team/dlee/stasis-http/include/asterisk/stasis_http.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/dlee/stasis-http/include/asterisk/stasis_http.h
------------------------------------------------------------------------------
[... 4005 lines stripped ...]
More information about the svn-commits
mailing list