diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/embedding/Makefile | 8 | ||||
-rw-r--r-- | examples/embedding/Makefile.upylib | 200 | ||||
-rw-r--r-- | examples/embedding/README | 66 | ||||
-rw-r--r-- | examples/embedding/hello-embed.c | 74 | ||||
l--------- | examples/embedding/mpconfigport.h | 1 | ||||
-rw-r--r-- | examples/embedding/mpconfigport_minimal.h | 138 | ||||
-rw-r--r-- | examples/network/http_client.py | 2 | ||||
-rw-r--r-- | examples/network/http_client_ssl.py | 2 | ||||
-rw-r--r-- | examples/network/http_server.py | 41 | ||||
-rw-r--r-- | examples/network/http_server_simplistic.py | 38 | ||||
-rw-r--r-- | examples/network/http_server_simplistic_commented.py | 76 | ||||
-rw-r--r-- | examples/network/http_server_ssl.py | 7 | ||||
-rw-r--r-- | examples/unix/machine_bios.py | 9 |
13 files changed, 649 insertions, 13 deletions
diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile new file mode 100644 index 0000000000..99f239a7c5 --- /dev/null +++ b/examples/embedding/Makefile @@ -0,0 +1,8 @@ +MPTOP = ../.. +CFLAGS = -std=c99 -I. -I$(MPTOP) -DNO_QSTR +LDFLAGS = -L. + +hello-embed: hello-embed.o -lmicropython + +-lmicropython: + $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP) diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib new file mode 100644 index 0000000000..d8dbade3fe --- /dev/null +++ b/examples/embedding/Makefile.upylib @@ -0,0 +1,200 @@ +MPTOP = ../.. +-include mpconfigport.mk +include $(MPTOP)/py/mkenv.mk + +all: lib + +# OS name, for simple autoconfig +UNAME_S := $(shell uname -s) + +# include py core make definitions +include $(MPTOP)/py/py.mk + +INC += -I. +INC += -I.. +INC += -I$(MPTOP) +INC += -I$(MPTOP)/unix +#INC += -I../lib/timeutils +INC += -I$(BUILD) + +# compiler settings +CWARN = -Wall -Werror +CWARN += -Wpointer-arith -Wuninitialized +CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) + +# Debugging/Optimization +ifdef DEBUG +CFLAGS += -g +COPT = -O0 +else +COPT = -Os #-DNDEBUG +# _FORTIFY_SOURCE is a feature in gcc/glibc which is intended to provide extra +# security for detecting buffer overflows. Some distros (Ubuntu at the very least) +# have it enabled by default. +# +# gcc already optimizes some printf calls to call puts and/or putchar. When +# _FORTIFY_SOURCE is enabled and compiling with -O1 or greater, then some +# printf calls will also be optimized to call __printf_chk (in glibc). Any +# printfs which get redirected to __printf_chk are then no longer synchronized +# with printfs that go through mp_printf. +# +# In MicroPython, we don't want to use the runtime library's printf but rather +# go through mp_printf, so that stdout is properly tied into streams, etc. +# This means that we either need to turn off _FORTIFY_SOURCE or provide our +# own implementation of __printf_chk. We've chosen to turn off _FORTIFY_SOURCE. +# It should also be noted that the use of printf in MicroPython is typically +# quite limited anyways (primarily for debug and some error reporting, etc +# in the unix version). +# +# Information about _FORTIFY_SOURCE seems to be rather scarce. The best I could +# find was this: https://securityblog.redhat.com/2014/03/26/fortify-and-you/ +# Original patchset was introduced by +# https://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html . +# +# Turning off _FORTIFY_SOURCE is only required when compiling with -O1 or greater +CFLAGS += -U _FORTIFY_SOURCE +endif + +# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed. +# The unix port of micropython on OSX must be compiled with clang, +# while cross-compile ports require gcc, so we test here for OSX and +# if necessary override the value of 'CC' set in py/mkenv.mk +ifeq ($(UNAME_S),Darwin) +CC = clang +# Use clang syntax for map file +LDFLAGS_ARCH = -Wl,-map,$@.map +else +# Use gcc syntax for map file +LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref +endif +LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) + +ifeq ($(MICROPY_FORCE_32BIT),1) +# Note: you may need to install i386 versions of dependency packages, +# starting with linux-libc-dev:i386 +ifeq ($(MICROPY_PY_FFI),1) +ifeq ($(UNAME_S),Linux) +CFLAGS_MOD += -I/usr/include/i686-linux-gnu +endif +endif +endif + +ifeq ($(MICROPY_USE_READLINE),1) +INC += -I../lib/mp-readline +CFLAGS_MOD += -DMICROPY_USE_READLINE=1 +LIB_SRC_C_EXTRA += mp-readline/readline.c +endif +ifeq ($(MICROPY_USE_READLINE),2) +CFLAGS_MOD += -DMICROPY_USE_READLINE=2 +LDFLAGS_MOD += -lreadline +# the following is needed for BSD +#LDFLAGS_MOD += -ltermcap +endif +ifeq ($(MICROPY_PY_TIME),1) +CFLAGS_MOD += -DMICROPY_PY_TIME=1 +SRC_MOD += modtime.c +endif +ifeq ($(MICROPY_PY_TERMIOS),1) +CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1 +SRC_MOD += modtermios.c +endif +ifeq ($(MICROPY_PY_SOCKET),1) +CFLAGS_MOD += -DMICROPY_PY_SOCKET=1 +SRC_MOD += modsocket.c +endif + +ifeq ($(MICROPY_PY_FFI),1) + +ifeq ($(MICROPY_STANDALONE),1) +LIBFFI_CFLAGS_MOD := -I$(shell ls -1d ../lib/libffi/build_dir/out/lib/libffi-*/include) + ifeq ($(MICROPY_FORCE_32BIT),1) + LIBFFI_LDFLAGS_MOD = ../lib/libffi/build_dir/out/lib32/libffi.a + else + LIBFFI_LDFLAGS_MOD = ../lib/libffi/build_dir/out/lib/libffi.a + endif +else +LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi) +LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi) +endif + +ifeq ($(UNAME_S),Linux) +LIBFFI_LDFLAGS_MOD += -ldl +endif + +CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1 +LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD) +SRC_MOD += modffi.c +endif + +MAIN_C = main.c + +# source files +SRC_C = $(addprefix $(MPTOP)/unix/,\ + $(MAIN_C) \ + gccollect.c \ + unix_mphal.c \ + input.c \ + file.c \ + modmachine.c \ + modos.c \ + moduselect.c \ + alloc.c \ + coverage.c \ + fatfs_port.c \ + $(SRC_MOD) \ + ) + +LIB_SRC_C = $(addprefix lib/,\ + $(LIB_SRC_C_EXTRA) \ + utils/printf.c \ + timeutils/timeutils.c \ + ) + +ifeq ($(MICROPY_FATFS),1) +LIB_SRC_C += $(addprefix lib/,\ + fatfs/ff.c \ + fatfs/option/ccsbcs.c \ + ) +endif + +OBJ = $(PY_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(STMHAL_SRC_C:.c=.o)) + +# List of sources for qstr extraction +SRC_QSTR += $(SRC_C) $(LIB_SRC_C) +# Append any auto-generated sources that are needed by sources listed in +# SRC_QSTR +SRC_QSTR_AUTO_DEPS += + +include $(MPTOP)/py/mkrules.mk + +# Value of configure's --host= option (required for cross-compilation). +# Deduce it from CROSS_COMPILE by default, but can be overriden. +ifneq ($(CROSS_COMPILE),) +CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE)) +else +CROSS_COMPILE_HOST = +endif + +deplibs: libffi axtls + +# install-exec-recursive & install-data-am targets are used to avoid building +# docs and depending on makeinfo +libffi: + cd ../lib/libffi; git clean -d -x -f + cd ../lib/libffi; ./autogen.sh + mkdir -p ../lib/libffi/build_dir; cd ../lib/libffi/build_dir; \ + ../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out CC="$(CC)" CXX="$(CXX)" LD="$(LD)"; \ + make install-exec-recursive; make -C include install-data-am + +axtls: ../lib/axtls/README + cd ../lib/axtls; cp config/upyconfig config/.config + cd ../lib/axtls; make oldconfig -B + cd ../lib/axtls; make clean + cd ../lib/axtls; make all CC="$(CC)" LD="$(LD)" + +../lib/axtls/README: + @echo "You cloned without --recursive, fetching submodules for you." + (cd ..; git submodule update --init --recursive) diff --git a/examples/embedding/README b/examples/embedding/README new file mode 100644 index 0000000000..0475e8739a --- /dev/null +++ b/examples/embedding/README @@ -0,0 +1,66 @@ +Example of embedding MicroPython in a standlone C application +============================================================= + +This directory contains a (very simple!) example of how to embed a MicroPython +in an existing C application. + +A C application is represented by the file hello-embed.c. It executes a simple +Python statement which prints to the standard output. + + +Building the example +-------------------- + +Build the example is as simple as running: + + make + +It's worth to trace what's happening behind the scenes though: + +1. As a first step, a MicroPython library is built. This is handled by a +seperate makefile, Makefile.upylib. It is more or less complex, but the +good news is that you won't need to change anything in it, just use it +as is, the main Makefile shows how. What may need editing though is +MicroPython configuration file. MicroPython is highly configurable, so +you would need to build a library suiting your application well, while +not bloating its size. Check the options in the file "mpconfigport.h". +Included is a copy of "minimal" Unix port, which should be good start +for minimal embedding. For list of all available options, see py/mpconfig.h. + +2. Once the library is built, your application is compiled and linked with +the MicroPython library produced in the previous step. The main Makefile +is very simple and shows that changes you would need to do to your +application's Makefile (or other build configuration) are also simple: + +a) You would need to use C99 standard (you're using 15+ years old standard +already, not a 25+ years old one, right?). + +b) You need to provide path to MicroPython's top-level dir, for includes. + +c) You need to include -DNO_QSTR compile-time flag. + +d) Otherwise, just link with micropython library produced in step 1. + + +Out of tree build +----------------- + +This example set up to work out of the box, being part of the MicroPython +tree. Your application of course will be outside of its tree, but the +only thing you need to do is to pass MPTOP variable pointing to +MicroPython directory to both Makefiles (in this example, the main Makefile +automatically pass it to Makefile.upylib; in your own Makefile, don't forget +to use suitable value). + +A practical way to embed MicroPython in your application is to include it +as a git submodule. Suppose you included it as libs/micropython. Then in +your main Makefile you would have something like: + +~~~ +MPTOP = libs/micropython + +my_app: $(MY_OBJS) -lmicropython + +-lmicropython: + $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP) +~~~ diff --git a/examples/embedding/hello-embed.c b/examples/embedding/hello-embed.c new file mode 100644 index 0000000000..1949305184 --- /dev/null +++ b/examples/embedding/hello-embed.c @@ -0,0 +1,74 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Paul Sokolovsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include "py/compile.h" +#include "py/runtime.h" +#include "py/gc.h" +#include "py/stackctrl.h" + +static char heap[16384]; + +mp_obj_t execute_from_lexer(mp_lexer_t *lex) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT); + mp_obj_t module_fun = mp_compile(&pt, lex->source_name, MP_EMIT_OPT_NONE, false); + mp_call_function_0(module_fun); + nlr_pop(); + return 0; + } else { + // uncaught exception + return (mp_obj_t)nlr.ret_val; + } +} + +int main() { + // Initialized stack limit + mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); + // Initialize heap + gc_init(heap, heap + sizeof(heap)); + // Initialize interpreter + mp_init(); + + const char str[] = "print('Hello world of easy embedding!')"; + mp_lexer_t *lex = mp_lexer_new_from_str_len(0/*MP_QSTR_*/, str, strlen(str), false); + if (execute_from_lexer(lex)) { + printf("Error\n"); + } +} + +uint mp_import_stat(const char *path) { + return MP_IMPORT_STAT_NO_EXIST; +} + +void nlr_jump_fail(void *val) { + printf("FATAL: uncaught NLR %p\n", val); + exit(1); +} diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h new file mode 120000 index 0000000000..142e5d6f43 --- /dev/null +++ b/examples/embedding/mpconfigport.h @@ -0,0 +1 @@ +mpconfigport_minimal.h
\ No newline at end of file diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h new file mode 100644 index 0000000000..9f080ab0e1 --- /dev/null +++ b/examples/embedding/mpconfigport_minimal.h @@ -0,0 +1,138 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// options to control how Micro Python is built + +#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (0) +#define MICROPY_STACK_CHECK (0) +#define MICROPY_COMP_CONST (0) +#define MICROPY_MEM_STATS (0) +#define MICROPY_DEBUG_PRINTERS (0) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_HELPER_LEXER_UNIX (1) +#define MICROPY_ENABLE_SOURCE_LINE (0) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) +#define MICROPY_WARNINGS (0) +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) +#define MICROPY_STREAMS_NON_BLOCK (0) +#define MICROPY_OPT_COMPUTED_GOTO (0) +#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) +#define MICROPY_CAN_OVERRIDE_BUILTINS (0) +#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) +#define MICROPY_CPYTHON_COMPAT (0) +#define MICROPY_PY_BUILTINS_BYTEARRAY (0) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (0) +#define MICROPY_PY_BUILTINS_COMPILE (0) +#define MICROPY_PY_BUILTINS_ENUMERATE (0) +#define MICROPY_PY_BUILTINS_FILTER (0) +#define MICROPY_PY_BUILTINS_FROZENSET (0) +#define MICROPY_PY_BUILTINS_REVERSED (0) +#define MICROPY_PY_BUILTINS_SET (0) +#define MICROPY_PY_BUILTINS_SLICE (0) +#define MICROPY_PY_BUILTINS_STR_UNICODE (0) +#define MICROPY_PY_BUILTINS_PROPERTY (0) +#define MICROPY_PY_BUILTINS_MIN_MAX (0) +#define MICROPY_PY___FILE__ (0) +#define MICROPY_PY_MICROPYTHON_MEM_INFO (0) +#define MICROPY_PY_GC (0) +#define MICROPY_PY_GC_COLLECT_RETVAL (0) +#define MICROPY_PY_ARRAY (0) +#define MICROPY_PY_COLLECTIONS (0) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_CMATH (0) +#define MICROPY_PY_IO (0) +#define MICROPY_PY_IO_FILEIO (0) +#define MICROPY_PY_STRUCT (0) +#define MICROPY_PY_SYS (1) +#define MICROPY_PY_SYS_EXIT (0) +#define MICROPY_PY_SYS_PLATFORM "linux" +#define MICROPY_PY_SYS_MAXSIZE (0) +#define MICROPY_PY_SYS_STDFILES (0) +#define MICROPY_PY_CMATH (0) +#define MICROPY_PY_UCTYPES (0) +#define MICROPY_PY_UZLIB (0) +#define MICROPY_PY_UJSON (0) +#define MICROPY_PY_URE (0) +#define MICROPY_PY_UHEAPQ (0) +#define MICROPY_PY_UHASHLIB (0) +#define MICROPY_PY_UBINASCII (0) + +extern const struct _mp_obj_module_t mp_module_os; + +#define MICROPY_PORT_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_os }, \ + +#define MICROPY_PORT_ROOT_POINTERS \ + mp_obj_t keyboard_interrupt_obj; + +////////////////////////////////////////// +// Do not change anything beyond this line +////////////////////////////////////////// + +// Define to 1 to use undertested inefficient GC helper implementation +// (if more efficient arch-specific one is not available). +#ifndef MICROPY_GCREGS_SETJMP + #ifdef __mips__ + #define MICROPY_GCREGS_SETJMP (1) + #else + #define MICROPY_GCREGS_SETJMP (0) + #endif +#endif + +// type definitions for the specific machine + +#ifdef __LP64__ +typedef long mp_int_t; // must be pointer size +typedef unsigned long mp_uint_t; // must be pointer size +#else +// These are definitions for machines where sizeof(int) == sizeof(void*), +// regardless for actual size. +typedef int mp_int_t; // must be pointer size +typedef unsigned int mp_uint_t; // must be pointer size +#endif + +#define BYTES_PER_WORD sizeof(mp_int_t) + +// Cannot include <sys/types.h>, as it may lead to symbol name clashes +#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) +typedef long long mp_off_t; +#else +typedef long mp_off_t; +#endif + +typedef void *machine_ptr_t; // must be of pointer size +typedef const void *machine_const_ptr_t; // must be of pointer size + +// We need to provide a declaration/definition of alloca() +#ifdef __FreeBSD__ +#include <stdlib.h> +#else +#include <alloca.h> +#endif diff --git a/examples/network/http_client.py b/examples/network/http_client.py index 3701e75e16..df66ace2a5 100644 --- a/examples/network/http_client.py +++ b/examples/network/http_client.py @@ -24,5 +24,7 @@ def main(use_stream=False): s.send(b"GET / HTTP/1.0\n\n") print(s.recv(4096)) + s.close() + main() diff --git a/examples/network/http_client_ssl.py b/examples/network/http_client_ssl.py index 53b1c732bc..46e039830f 100644 --- a/examples/network/http_client_ssl.py +++ b/examples/network/http_client_ssl.py @@ -32,5 +32,7 @@ def main(use_stream=True): s.send(b"GET / HTTP/1.0\n\n") print(s.recv(4096)) + s.close() + main() diff --git a/examples/network/http_server.py b/examples/network/http_server.py index 80dfc5db02..e3a66e8283 100644 --- a/examples/network/http_server.py +++ b/examples/network/http_server.py @@ -10,7 +10,7 @@ HTTP/1.0 200 OK Hello #%d from MicroPython! """ -def main(use_stream=False): +def main(micropython_optimize=False): s = socket.socket() # Binding to all interfaces - server will be accessible to other hosts! @@ -26,20 +26,37 @@ def main(use_stream=False): counter = 0 while True: res = s.accept() - client_s = res[0] + client_sock = res[0] client_addr = res[1] print("Client address:", client_addr) - print("Client socket:", client_s) - print("Request:") - if use_stream: - # MicroPython socket objects support stream (aka file) interface - # directly. - print(client_s.read(4096)) - client_s.write(CONTENT % counter) + print("Client socket:", client_sock) + + if not micropython_optimize: + # To read line-oriented protocol (like HTTP) from a socket (and + # avoid short read problem), it must be wrapped in a stream (aka + # file-like) object. That's how you do it in CPython: + client_stream = client_sock.makefile("rwb") else: - print(client_s.recv(4096)) - client_s.send(CONTENT % counter) - client_s.close() + # .. but MicroPython socket objects support stream interface + # directly, so calling .makefile() method is not required. If + # you develop application which will run only on MicroPython, + # especially on a resource-constrained embedded device, you + # may take this shortcut to save resources. + client_stream = client_sock + + print("Request:") + req = client_stream.readline() + print(req) + while True: + h = client_stream.readline() + if h == b"" or h == b"\r\n": + break + print(h) + client_stream.write(CONTENT % counter) + + client_stream.close() + if not micropython_optimize: + client_sock.close() counter += 1 print() diff --git a/examples/network/http_server_simplistic.py b/examples/network/http_server_simplistic.py new file mode 100644 index 0000000000..f932e48f56 --- /dev/null +++ b/examples/network/http_server_simplistic.py @@ -0,0 +1,38 @@ +try: + import usocket as socket +except: + import socket + + +CONTENT = b"""\ +HTTP/1.0 200 OK + +Hello #%d from MicroPython! +""" + +def main(): + s = socket.socket() + ai = socket.getaddrinfo("0.0.0.0", 8080) + addr = ai[0][-1] + + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + s.bind(addr) + s.listen(5) + print("Listening, connect your browser to http://<this_host>:8080/") + + counter = 0 + while True: + res = s.accept() + client_s = res[0] + client_addr = res[1] + req = client_s.recv(4096) + print("Request:") + print(req) + client_s.send(CONTENT % counter) + client_s.close() + counter += 1 + print() + + +main() diff --git a/examples/network/http_server_simplistic_commented.py b/examples/network/http_server_simplistic_commented.py new file mode 100644 index 0000000000..b58e9eeb60 --- /dev/null +++ b/examples/network/http_server_simplistic_commented.py @@ -0,0 +1,76 @@ +# +# MicroPython http_server_simplistic.py example +# +# This example shows how to write the smallest possible HTTP +# server in MicroPython. With comments and convenience code +# removed, this example can be compressed literally to ten +# lines. There's a catch though - read comments below for +# details, and use this code only for quick hacks, preferring +# http_server.py for "real thing". +# +try: + import usocket as socket +except: + import socket + + +CONTENT = b"""\ +HTTP/1.0 200 OK + +Hello #%d from MicroPython! +""" + +def main(): + s = socket.socket() + + # Bind to (allow to be connected on ) all interfaces. This means + # this server will be accessible to other hosts on your local + # network, and if your server has direct (non-firewalled) connection + # to the Internet, then to anyone on the Internet. We bind to all + # interfaces to let this example work easily on embedded MicroPython + # targets, which you will likely access from another machine on your + # local network. Take care when running this on an Internet-connected + # machine though! Replace "0.0.0.0" with "127.0.0.1" if in doubt, to + # make the server accessible only on the machine it runs on. + ai = socket.getaddrinfo("0.0.0.0", 8080) + print("Bind address info:", ai) + addr = ai[0][-1] + + # A port on which a socket listened remains inactive during some time. + # This means that if you run this sample, terminate it, and run again + # you will likely get an error. To avoid this timeout, set SO_REUSEADDR + # socket option. + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + s.bind(addr) + s.listen(5) + print("Listening, connect your browser to http://<this_host>:8080/") + + counter = 0 + while True: + res = s.accept() + client_s = res[0] + client_addr = res[1] + print("Client address:", client_addr) + print("Client socket:", client_s) + # We assume here that .recv() call will read entire HTTP request + # from client. This is usually true, at least on "big OS" systems + # like Linux/MacOS/Windows. But that doesn't have to be true in + # all cases, in particular on embedded systems, when there can + # easily be "short recv", where it returns much less than requested + # data size. That's why this example is called "simplistic" - it + # shows that writing a web server in Python that *usually works* is + # ten lines of code, and you can use this technique for quick hacks + # and experimentation. But don't do it like that in production + # applications - instead, parse HTTP request properly, as shown + # by http_server.py example. + req = client_s.recv(4096) + print("Request:") + print(req) + client_s.send(CONTENT % counter) + client_s.close() + counter += 1 + print() + + +main() diff --git a/examples/network/http_server_ssl.py b/examples/network/http_server_ssl.py index 04e0913448..9a69ca9d41 100644 --- a/examples/network/http_server_ssl.py +++ b/examples/network/http_server_ssl.py @@ -42,8 +42,13 @@ def main(use_stream=True): # next request they issue will likely be more well-behaving and # will succeed. try: - req = client_s.read(4096) + req = client_s.readline() print(req) + while True: + h = client_s.readline() + if h == b"" or h == b"\r\n": + break + print(h) if req: client_s.write(CONTENT % counter) except Exception as e: diff --git a/examples/unix/machine_bios.py b/examples/unix/machine_bios.py new file mode 100644 index 0000000000..f62e4dbdb4 --- /dev/null +++ b/examples/unix/machine_bios.py @@ -0,0 +1,9 @@ +# This example shows how to access Video BIOS memory area via machine.mem +# It requires root privilege and x86 legacy harfware (which has mentioned +# Video BIOS at all). +# It is expected to print 0xaa55, which is a signature at the start of +# Video BIOS. + +import umachine as machine + +print(hex(machine.mem16[0xc0000])) |