[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