diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-09-14 14:07:21 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-09-14 14:07:21 +0000 |
commit | b12d1dada94cd7083c2a5a023ec2e7a9a51c192a (patch) | |
tree | 78375ed0dfcfed58f45bf266c76a1f9230df01c9 /apps/examples/xmlrpc | |
parent | bf8d0c68312793631ed4ade1541ec36168b3722b (diff) | |
download | px4-nuttx-b12d1dada94cd7083c2a5a023ec2e7a9a51c192a.tar.gz px4-nuttx-b12d1dada94cd7083c2a5a023ec2e7a9a51c192a.tar.bz2 px4-nuttx-b12d1dada94cd7083c2a5a023ec2e7a9a51c192a.zip |
Add XML RPC server plus NXWM build fixes from Max Holtzberg
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5150 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps/examples/xmlrpc')
-rw-r--r-- | apps/examples/xmlrpc/Kconfig | 45 | ||||
-rw-r--r-- | apps/examples/xmlrpc/Makefile | 106 | ||||
-rw-r--r-- | apps/examples/xmlrpc/calls.c | 122 | ||||
-rw-r--r-- | apps/examples/xmlrpc/xmlrpc_main.c | 419 |
4 files changed, 692 insertions, 0 deletions
diff --git a/apps/examples/xmlrpc/Kconfig b/apps/examples/xmlrpc/Kconfig new file mode 100644 index 000000000..ee61feb50 --- /dev/null +++ b/apps/examples/xmlrpc/Kconfig @@ -0,0 +1,45 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_XMLRPC + bool "XML RPC example" + default n + depends on NET_TCP && !DISABLE_POLL + select NETUTILS_XMLRPC + ---help--- + An example for the netutils/xmlrpc library. + This example implements a lightweight HTTP server and uses the xmlrpc lib + for parsing xml remote procedure calls. + +config EXAMPLES_XMLRPC_BUFFERSIZE + int "HTTP buffer size" + default 1024 + +config EXAMPLES_XMLRPC_DHCPC + bool "DHCP Client" + default n + depends on EXAMPLES_XMLRPC && !NSH_BUILTIN_APPS + select NETUTILS_DHCPC + select NETUTILS_RESOLV + +config EXAMPLES_XMLRPC_NOMAC + bool "Use Canned MAC Address" + default n + depends on EXAMPLES_XMLRPC && !NSH_BUILTIN_APPS + +config EXAMPLES_XMLRPC_IPADDR + hex "Target IP address" + default 0x0a000002 + depends on EXAMPLES_XMLRPC && !NSH_BUILTIN_APPS && !EXAMPLES_XMLRPC_DHCPC + +config EXAMPLES_XMLRPC_DRIPADDR + hex "Default Router IP address (Gateway)" + default 0x0a000001 + depends on EXAMPLES_XMLRPC && !NSH_BUILTIN_APPS + +config EXAMPLES_XMLRPC_NETMASK + hex "Network Mask" + default 0xffffff00 + depends on EXAMPLES_XMLRPC && !NSH_BUILTIN_APPS diff --git a/apps/examples/xmlrpc/Makefile b/apps/examples/xmlrpc/Makefile new file mode 100644 index 000000000..9fa03bf7e --- /dev/null +++ b/apps/examples/xmlrpc/Makefile @@ -0,0 +1,106 @@ +############################################################################ +# apps/examples/xmlrpc/Makefile +# +# Copyright (C) 2012 Max Holtzberg. All rights reserved. +# Copyright (C) 2008, 2010-2012 Gregory Nutt. All rights reserved. +# +# Authors: Max Holtzberg <mh@uvc.de> +# Gregory Nutt <gnutt@nuttx.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# XML RPC built-in application info + +APPNAME = xmlrpc +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +ASRCS = +CSRCS = xmlrpc_main.c calls.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +ifeq ($(WINTOOL),y) + BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}" +else + BIN = "$(APPDIR)/libapps$(LIBEXT)" +endif + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $(BIN), $${obj}); \ + done ; ) + @touch .built + +.context: +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + @touch $@ +endif + +context: .context + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/examples/xmlrpc/calls.c b/apps/examples/xmlrpc/calls.c new file mode 100644 index 000000000..bda164f4d --- /dev/null +++ b/apps/examples/xmlrpc/calls.c @@ -0,0 +1,122 @@ +/**************************************************************************** + * apps/examples/xmlrpc/calls.c + * + * Copyright (C) 2012 Max Holtzberg. All rights reserved. + * Author: Max Holtzberg <mh@uvc.de> + * + * Based on the embeddable lightweight XML-RPC server code discussed + * in the article at: http://www.drdobbs.com/web-development/\ + * an-embeddable-lightweight-xml-rpc-server/184405364 + * + * Copyright (c) 2002 Cogito LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, is hereby granted without fee provided + * that the following conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * 3. Neither the name of Cogito LLC nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY COGITO LLC AND CONTRIBUTERS 'AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COGITO LLC + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARAY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <string.h> +#include <apps/netutils/xmlrpc.h> + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int calls_get_device_stats(struct xmlrpc_s *xmlcall); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct xmlrpc_entry_s get_device_stats = +{ + .name = "get_device_stats", + .func = calls_get_device_stats +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int calls_get_device_stats(struct xmlrpc_s *xmlcall) +{ + char username[80], password[80]; + char lastCommand[80], curState[80]; + int request = 0, status, ret; + + do + { + ret = xmlrpc_getstring(xmlcall, username); + if (ret != XMLRPC_NO_ERROR) + { + break; + } + + ret = xmlrpc_getstring(xmlcall, password); + if (ret != XMLRPC_NO_ERROR) + { + break; + } + + ret = xmlrpc_getinteger(xmlcall, &request); + if (ret != XMLRPC_NO_ERROR) + { + break; + } + } + while (0); + + if (ret == XMLRPC_NO_ERROR) + { + /* Dummy up some data... */ + + status = 1; + strcpy(lastCommand, "reboot"); + strcpy(curState, "Normal Operation"); + + ret = xmlrpc_buildresponse(xmlcall, "{iss}", + "status", status, + "lastCommand", lastCommand, + "currentState", curState); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void calls_register(void) +{ + xmlrpc_register(&get_device_stats); +} diff --git a/apps/examples/xmlrpc/xmlrpc_main.c b/apps/examples/xmlrpc/xmlrpc_main.c new file mode 100644 index 000000000..5f5ce5f06 --- /dev/null +++ b/apps/examples/xmlrpc/xmlrpc_main.c @@ -0,0 +1,419 @@ +/**************************************************************************** + * apps/examples/xmlrpc/xmlrpc_main.c + * + * Copyright (C) 2012 Max Holtzberg. All rights reserved. + * Author: Max Holtzberg <mh@uvc.de> + * + * Based on the embeddable lightweight XML-RPC server code discussed + * in the article at: http://www.drdobbs.com/web-development/\ + * an-embeddable-lightweight-xml-rpc-server/184405364 + * + * Copyright (c) 2002 Cogito LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, is hereby granted without fee provided + * that the following conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * 3. Neither the name of Cogito LLC nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY COGITO LLC AND CONTRIBUTERS 'AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COGITO LLC + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARAY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + ****************************************************************************/ + +/* + * Lightweight Embedded XML-RPC Server main + * + * mtj@cogitollc.com + * + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <debug.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <arpa/inet.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <net/if.h> +#include <nuttx/net/uip/uip.h> +#include <nuttx/net/uip/uip-arp.h> + +#include <apps/netutils/uiplib.h> +#include <apps/netutils/xmlrpc.h> + +#ifdef CONFIG_EXAMPLES_XMLRPC_DHCPC +# include <arpa/inet.h> +#endif + +/* Here we include the header file for the application(s) we use in + * our project as defined in the config/<board-name>/defconfig file + */ + +/* DHCPC may be used in conjunction with any other feature (or not) */ + +#ifdef CONFIG_EXAMPLES_XMLRPC_DHCPC +# include <apps/netutils/resolv.h> +# include <apps/netutils/dhcpc.h> +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char *notimplemented = { "HTTP/1.1 501 Not Implemented\n\n" }; +static const char *separator = { "\015\012\015\012" }; + +/**************************************************************************** + * External Function Prototypes + ****************************************************************************/ + +extern void calls_register(void); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: xmlrpc_findbody + * + * Description: + * Find the message body of an HTTP Request Message + * + ****************************************************************************/ + +static char *xmlrpc_findbody(char *buf) +{ + char *temp; + + temp = strstr(buf, separator); + + if (temp == NULL) + { + return NULL; + } + else + { + return temp + 4; + } +} + +/**************************************************************************** + * Name: xmlrpc_getheader + * + * Description: + * Find the HTTP header and return it's value. + * + ****************************************************************************/ + +static int xmlrpc_getheader(char *buffer, char *header, char *value, int size) +{ + char *temp; + int i = 0; + + temp = strstr(buffer, header); + if (temp) + { + /* Skip the header element */ + + temp += strlen(header); + + /* Skip any white-space */ + + while (*temp == ' ') + { + temp++; + } + + /* Copy the rest to the value parameter */ + + while ((*temp != ' ') && (*temp != '\n') && (i < size)) + { + value[i++] = *temp++; + } + + value[i] = 0; + return i; + } + + return -1; +} + +/**************************************************************************** + * Name: xmlrpc_handler + * + * Description: + * Parse and handle the current HTTP request message. + * + ****************************************************************************/ + +static void xmlrpc_handler(int fd) +{ + fd_set rfds; + struct timeval tv; + int ret, len, max = 0, loadlen = -1; + char buffer[CONFIG_EXAMPLES_XMLRPC_BUFFERSIZE] = { 0 }; + char value[CONFIG_XMLRPC_STRINGSIZE + 1]; + char *temp; + + /* Read in the Request Header */ + + do + { + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + tv.tv_sec = 1; + tv.tv_usec = 0; + + ndbg("[%d] select...\n", fd); + ret = select(fd + 1, &rfds, NULL, NULL, &tv); + ndbg("[%d] data ready\n", fd); + + if (ret > 0) + { + if (FD_ISSET(fd, &rfds)) + { + len = recv(fd, &buffer[max], 1024, 0); + ndbg("[%d] %d bytes received\n", fd, len); + + if (len > 0) + { + max += len; + buffer[max] = 0; + + ret = xmlrpc_getheader(buffer, "Content-Length:", value, + CONFIG_EXAMPLES_XMLRPC_BUFFERSIZE); + if (ret > 0) + loadlen = atoi(value); + } + else + { + ret = -1; + break; + } + } + } + else + { + /* Timeout... */ + + ndbg("[%d] timeout\n", fd); + ret = -1; + break; + } + + temp = strstr(buffer, separator); + + if (temp) + { + if (strlen(temp) - 4 == loadlen) + break; + } + + } + while (1); + + /* Determine request */ + + if (!strncmp(buffer, "POST", 4)) + { + temp = xmlrpc_findbody(buffer); + xmlrpc_parse(fd, temp); + } + else + { + write(fd, notimplemented, strlen(notimplemented)); + } +} + +/**************************************************************************** + * Name: xmlrpc_netinit + * + * Description: + * Setup network configuration. + * + ****************************************************************************/ + +static int xmlrpc_netinit(void) +{ + /* If this task is excecutated as an NSH built-in function, then the network + * has already been configured by NSH's start-up logic. + */ + +#ifndef CONFIG_NSH_BUILTIN_APPS + struct in_addr addr; +#if defined(CONFIG_EXAMPLES_XMLRPC_DHCPC) || defined(CONFIG_EXAMPLES_XMLRPC_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif +#ifdef CONFIG_EXAMPLES_XMLRPC_DHCPC + void *handle; +#endif + +/* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLES_XMLRPC_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xde; + mac[3] = 0xad; + mac[4] = 0xbe; + mac[5] = 0xef; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + +#ifdef CONFIG_EXAMPLES_XMLRPC_DHCPC + addr.s_addr = 0; +#else + addr.s_addr = HTONL(CONFIG_EXAMPLES_XMLRPC_IPADDR); +#endif + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLES_XMLRPC_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLES_XMLRPC_NETMASK); + uip_setnetmask("eth0", &addr); + +#ifdef CONFIG_EXAMPLES_XMLRPC_DHCPC + /* Set up the resolver */ + + resolv_init(); + + /* Get the MAC address of the NIC */ + + uip_getmacaddr("eth0", mac); + + /* Set up the DHCPC modules */ + + handle = dhcpc_open(&mac, IFHWADDRLEN); + + /* Get an IP address. Note: there is no logic here for renewing the address + * in this example. The address should be renewed in ds.lease_time/2 + * seconds. + */ + + printf("Getting IP address\n"); + if (handle) + { + struct dhcpc_state ds; + (void)dhcpc_request(handle, &ds); + uip_sethostaddr("eth1", &ds.ipaddr); + + if (ds.netmask.s_addr != 0) + { + uip_setnetmask("eth0", &ds.netmask); + } + + if (ds.default_router.s_addr != 0) + { + uip_setdraddr("eth0", &ds.default_router); + } + + if (ds.dnsaddr.s_addr != 0) + { + resolv_conf(&ds.dnsaddr); + } + + dhcpc_close(handle); + printf("IP: %s\n", inet_ntoa(ds.ipaddr)); + } + +#endif /* CONFIG_EXAMPLES_XMLRPC_DHCPC */ +#endif /* CONFIG_NSH_BUILTIN_APPS */ + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: xmlrpc_main + * + * Description: + * The embedded HTTP server main + * + ****************************************************************************/ + +int xmlrpc_main(int argc, char *argv[]) +{ + int listenfd, connfd, on = 1; + socklen_t clilen; + struct sockaddr_in cliaddr, servaddr; + + if (xmlrpc_netinit() < 0) + { + ndbg("Could not initialize the network interface\n"); + return ERROR; + } + + /* Register RPC functions. */ + + calls_register(); + + listenfd = socket(AF_INET, SOCK_STREAM, 0); + + setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + + bzero((void *)&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(80); + + bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); + + listen(listenfd, 5); + + for (;;) + { + clilen = sizeof(cliaddr); + connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen); + if (connfd <= 0) + { + break; + } + ndbg("Connection accepted: %d\n", connfd); + + xmlrpc_handler(connfd); + close(connfd); + ndbg("[%d] connection closed\n", connfd); + } + + close(listenfd); + return (0); +} |