Unison Help
- Unison Kernel
- Pthreads
- pthread_create()
- pthread_exit()
- pthread_self()
- pthread_equal()
- pthread_join()
- pthread_detach()
- pthread_setschedparam()
- pthread_getschedparam()
- pthread_attr_init()
- pthread_attr_destroy()
- pthread_attr_setstackaddr()
- pthread_attr_getstackaddr()
- pthread_attr_setstacksize()
- pthread_attr_getstacksize()
- pthread_attr_setschedparam()
- pthread_attr_getschedparam()
- pthread_attr_setdetachstate()
- pthread_attr_getdetachstate()
- pthread_stackinfo()
- pthread_setprio()
- pthread_getprio()
- sched_get_priority_max()
- sched_get_priority_min()
- sched_yield()
- Pthread Cancellation
- Mutex
- Semaphores
- Message Queues
- Conditional Variables
- Barriers
- Timers
- Clocks
- Memory Allocation
- Rendezvous
- Interrupts
- Directory Services
- Miscellaneous
- Pthreads
- Unison I/O Library
- Unison STDIO Library
- STDIO Library Calls
- clearerr()
- dprintf()
- fclose()
- fdopen()
- feof()
- ferror()
- fileno()
- fflush()
- fgetc()
- fgetpos()
- fgets()
- fopen()
- fprintf()
- fputc()
- fputs()
- fread()
- freopen()
- fscanf()
- fseek()
- fseeko()
- fsetpos()
- ftell()
- ftello()
- fwrite()
- getc()
- getc_unlocked()
- getchar()
- getchar_unlocked()
- getdelim()
- getline()
- gets()
- get_stderr_ptr()
- get_stdin_ptr()
- get_stdout_ptr()
- noperprintf()
- perprintf()
- perror()
- posix_compat()
- printf()
- putc()
- putc_unlocked()
- putchar()
- putchar_unlocked()
- puts()
- remove()
- rewind()
- scanf()
- setbuf()
- setvbuf()
- snprintf()
- sprintf()
- sscanf()
- stderr_init()
- stderr_close()
- stdin_init()
- stdin_close()
- stdout_init()
- stdout_close()
- vdprintf()
- vscanf()
- vsscanf()
- vfscanf()
- vprintf()
- vsnprintf()
- vsprintf()
- vfprintf()
- ungetc()
- Do-nothing Stubs
- STDIO Library Calls
- Unison LIBC Library
- Unison I/O Servers
- Graphics, Camera, Video, Audio
- Network Protocols
- TCP and UDP Server - tcpd
- DHCP Client Service - dhcp client
- DHCP Server - dhcpd
- Telnet Server - telnetd
- Tiny FTP Server - tftpd
- Point to Point - pppd
- Network Translation - NAT with PAT
- Firewall
- Tiny HTTP Server - thttpd
- Tiny HTTP Server with TLS
- POP3 Server
- Simple Mail Transfer Protocol Services (SMTP)
- Bootp Protocol
- File Transfer Protocol Server (FTP)
- File Transfer Client Services
- RPC / XDR
- DNS Client
- HTTP/HTTPS Client
- REST Client
- AutoIP Service - autoip client
- mDNS server - mdnsd
- SNTP Client
- SNMP Agent - Snmpd server
- SSL/TLS library
- SSH server
- IP security
- Power Control
- Serial I/O
- System Services
- Universal Serial Bus (USB)
- Wireless
- Remedy Tools for Unison
7.9.Tiny HTTP Server - thttpd #
NAME
Tiny HTTP Server – thttpd
SYNOPSIS
#include <sys.h>
#include <stdio.h>
#include <tcpinit.h>
#include <sys/socket.h>
#include <thttpd.h>
thttpd_main((char *)httpdconf_name);
DESCRIPTION
thttpd is simple of use and fast solution for adding HTTP support to your application.
The thttpd server provides the capability to provide the following services and support
- HTTP 0.9, 1.0 and 1.1 support
- Support for GET, POST, HEAD
-
Support CGI interface for user applications
- Minimal Footprint in both RAM and Flash
- Simple C language callout to deal with forms, buttons and login parse by user
- Optional ogin support
- Chunked file transfers
- Secure operation
- Thread only implementation
- Support for multiple file systems.
- Error Responses:
- HTTP/1.X 404 PAGE NOT FOUND
- HTTP/1.X 500 SERVER ERROR
- HTTP/1.X 400 BAD REQUEST
Thttpd server requires for work TCP and FatFs/Fsys servers. This servers must be started before run thttpd.
Thttpd starting by command:
thttpd_main((char *)httpdconf_name);
Where httpdconf_name is a full configuration file name. This file holds basic configuration parameters for thttp and has another structure:
Pram:value
Pram:value
…
Pram:value
-
Param
Description
Sample
server_software
software product name
UnisonHttpd
http_index
default start page
index.html
http_root
server root folder
/dev/rd/thttp/
http_port
default http port
80
server_name
server name, used by http protocol
Thttpd server
host_name
host name, used by http protocol
Myhost
cgi_ena
enable cgi handling (0 or 1)
1
data_timeout
watchdog to handle physical link loss
20
keepalive_timeout
timeout to keep socket opened, after handling browser requests
30
Login and Authentication Support
Thttpd server can provide access to some pages by password.
To setup the login information, users need to do the following:
- Put the pages in a sub directory of thttpd which has limited access
- Create a password file and set it up for the thttpd server.
- Initialize the login table.
- Add any users that the user requires
Example:
#include <login.h> set_loginfile((char *)htpasswd_name); //htpasswd_name - full path to .htpasswd file init_login_table((char *)htpasswd_name);
To add or delete new user run:
add_user( "username", "passwd" ); delete_user( "username");
Now if client access to protected files he must enter valid password and username. Server can support many different users
CGI Support
If application need to have CGI getaway support you need:
- set in “httpdconf” file option “cgi_ena” to 1
-
register cgi handler to one or many server folder.
Example:
register_cgi_handler("name", "URL_path", cgi_handler_funk);
Parameters:
- name – handler name for server. Name could be any “string”. This name is used to register handler in server and deletes. Any existing handler with the same name. Handler names should NOT be duplicated in system!
-
URL_path – address. which should be specified in the input POST to get server automatically call user function for handling this request. Addresses (or path names) should not be duplicated.
- cgi_handler_func – pointer to function-handler which will handle requests any existing handler with the same name.
It is possible to register a few cgi handlers in system. It is also possible to register one handler for different addresses.
Example:
register_cgi_handler ("test1", "cgi-bin/userI1.cgi", UI_cgi_handler); register_cgi_handler ("test2", "cgi-bin/userI2.cgi", UI_cgi_handler); register_cgi_handler ("test3", "cgi-bin/userI3.cgi", ABC_cgi_handler);
In this way the server will use one handler UI_cgi_handler for addresses
XXX/cgi-bin/userI1.cgi and XXX/cgi-bin/userI2.cgi. It will use a completely different handler ABC_cgi_handler for XXX/cgibin/userI3.cgi
To delete registerd cgi handler run del_cgi_handler
Example:
del_cgi_handler(“name”);
-
- name – handler name for server.
To handle all user data which is input from the Browser a next parameters list is passed into the cgi-handler.
int cgi_handler (char * path , char ** argv , char ** envp, int fd);
*path – path for which this handler is called. For instance, “cgi-bin/userI.cgi”
**argv – pointer array to parameters strings (to date it is 2 max)
argv[0] – called file name. For instance “userI.cgi”
argv[1] – If parameters are passed using method GET, then in argv[1] string with this parameters is passed, else (null)
**envp – pointers array to strings, which is containing information, passed by Browser using http headers (according to CGI standard). This array can contain variable numbers of elements, with the array ended by ‘\0’.
Example:
HTTP_USER_AGENT=Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.2.15 Version/10.10
HTTP_HOST=192.168.16.201
HTTP_ACCEPT=text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/xxbitmap,*/*;q=0.1
HTTP_ACCEPT_LANGUAGE=ru-RU,ru;q=0.9,en;q=0.8
HTTP_ACCEPT_CHARSET=iso-8859-1, utf-8, utf-16, *;q=0.1
HTTP_ACCEPT_ENCODING=deflate, gzip, x-gzip, identity, *;q=0
HTTP_REFERER=http://192.168.16.201/
HTTP_CONNECTION=Keep-Alive, TE
HTTP_TE=deflate, gzip, chunked, identity, trailers
HTTP_CONTENT_LENGTH=43
HTTP_CONTENT_TYPE=application/x-www-form-urlencoded
SERVER_NAME=Myhost
GATEWAY_INTERFACE=CGI/1.1
SERVER_PROTOCOL=HTTP/1.1
REQUEST_METHOD=POST
SCRIPT_NAME=/cgi-bin/userI.cgi
SCRIPT_FILENAME=cgi-bin/userI.cgi
SERVER_SOFTWARE=UnisonHttpd
REQUEST_URI=cgi-bin/userI.cgi
CONTENT_TYPE=application/x-www-form-urlencoded
CONTENT_LENGTH=43
SERVER_PORT=1568
REMOTE_ADDR=192.168.18.1
fd – socket ID, from which the handler will read data and where the handler will write the newly created page
In summary, the cgi_handler function inputs the parameters, processes the input arguments and creates a new page which is streamed back to the browser to update the user.
You can parse input parameters **envp by use function httpgetenv(“header name”, envp); and getparam(str, “field=”);
Example:
env = httpgetenv("REQUEST_METHOD", envp);
if (strcmp(env, "POST")==0) { //metod == "POST"
size = atoi(httpgetenv("CONTENT_LENGTH", envp)); //getting received data size
pos = recv(fd, str, size, 0); //receiving data from stream
str[pos] = '\0';
}else { //metod == "GET"
env = httpgetenv("QUERY_STRING", envp); //Reading query string sended by GET metod
strcpy(str,env);
}
name = getparam(str,"name_field="); //get entered "user Name"
age = getparam(str,"age_field="); //get entered "user Age"
Note: These CGI handlers must be compiled into the executable as part of the image. This means that changes to the web pages create a need to update the CGI handlers if the updates are more than cosmetic, or in other words, new variables are added.
SPECIFIC OPTIONS (Compile time)
Option | Default | Description | Values |
---|---|---|---|
TCPRIO | 5 | Priority for TCP thread | Dec: 0…16 |
THTTPPRIO | 8 | Priority for HTTP thread | Dec: 0…16 |
FSYSPRIO | 9 | Priority for FSYS thread | Dec: 0…16 |
TCPSTACKSIZE | 2560 | Stack size for TCP thread | Decimal |
THTTPSTACKSIZE | 3072 | Stack size for HTTP thread | Decimal |
FSYSSTACKSIZE | 2048 | Stack size for FSYS thread | Decimal |
EXAMPLE
pthread_t tid;
pthread_attr_t attr;
struct fsysinit fsysinit;
struct sched_param myNewPriority;
int mkfs_status, mount_status;
int fd;
xprintf("Start Main\n");
/*FSYS Initialization*/
fsysinit.fsi_msgsize = sizeof(struct fsysinit);
fsysinit.fsi_nclones = 1;
fsysinit.fsi_datalog = 0x3;
fsysinit.fsi_nbuffers = 4; /* num of disk buffers (cache size) */
fsysinit.fsi_maxopen = 2; /* max num of open files */
fsysinit.fsi_blocksize = 256;
// set up stack size and priority for main fsys threads and all clones
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, FSYSSTACKSIZE);
myNewPriority.sched_priority = FSYSPRIO;
pthread_attr_setschedparam(&attr, &myNewPriority);
if(!pthread_create(&tid, &attr,(void*(*)(void *))&_file_server, (char*)&fsysinit))
{
if(!dir_register(FSYS_DIRECTORY, tid, TYPE_SERVER))
{
xprintf("..Unable to register name of File Server\n..");
xprintf("..Required resource not present - aborting..\n");
pthread_exit((void*)1);
}
}
else
{
xprintf("..Unable to create File Server..\n");
xprintf("..Required resource for program not present - aborting..\n");
pthread_exit((void*)1);
}
xprintf("..File server is now created.\n..");
xprintf("\n..Attempting to mount it...\n");
if((mount(DEVICE_NO, FSYS_MOUNT, 0)) == -1) {
xprintf("..Unable to mount flash disk. errno=%d\n", errno);
xprintf("..Please fix me\n..");
pthread_exit((void*)1);
}
xprintf("..done fsys initialization..\n");
xprintf("\n--- Prepare files ---\n");
//preparing configuration file
fd = open(httpdconf_name, O_CREAT | O_RDWR, 0666);
write(fd, &httpdconf_str, strlen(httpdconf_str));
close(fd);
//preparing html and other files to work http server
fd = open(page_name1, O_CREAT | O_RDWR, 0666); //put to disk index.html
write(fd, page_str1, strlen(page_str1));
close(fd);
fd = open(page_name2, O_CREAT | O_RDWR, 0666); //put to disk page1.htm
write(fd, page_str2, strlen(page_str2));
close(fd);
fd = open(image_name, O_CREAT | O_RDWR, 0666); //put to disk OK.gif
write(fd, image, sizeof(image));
close(fd);
mkdir(secret_dir_name, 0777); //make directory with limited access
fd = open(page_name4, O_CREAT | O_RDWR, 0666); //put to disk page with limited access
write(fd, page_str4, sizeof(page_str4));
close(fd);
set_loginfile((char *)htpasswd_name); //set login and pass to access to files in this dir
init_login_table((char *)htpasswd_name);
add_user( "root", "root" );
/* make virtual link to user handler call address
* http://xxx.xxx.xxx.xxx/cgi-bin/userI.cgi
* will run UI_cgi_handler();
*/
register_cgi_handler("test", "cgi-bin/userI.cgi", UI_cgi_handler);
/* Start tcpd server*/
xprintf("\n--- Start tcpd ---\n");
myNewPriority.sched_priority = TCPRIO;
pthread_attr_setschedparam(&attr, &myNewPriority);
pthread_attr_setstacksize(&attr, TCPSTACKSIZE);
if(pthread_create(&tid, &attr, &tcp_shell, 0)!=0)
{
xprintf("pthread_create = %d\n", errno);
pthread_exit(0);
}
if(dir_register("/dev/tcpd", tid, TYPE_SERVER)==0)
{
xprintf("dir_register = %d\n", errno);
pthread_exit(0);
}
/* Start THTTP server */
xprintf("\n--- Start HTTP server ---\n");
// set up stack size and priority for main THTTP thread
pthread_attr_setstacksize(&attr, THTTPSTACKSIZE);
myNewPriority.sched_priority = THTTPPRIO;
pthread_attr_setschedparam(&attr, &myNewPriority);
if(pthread_create(&tid, &attr,(void*(*)(void *))&thttp_shell, NULL)!=0)
{
xprintf("..Unable to create THTTP Server..\n");
pthread_exit((void*)1);
}
...
THREAD tcp_shell(void * args)
{
tcpd(ðerinit);
return (THREAD)0;
}
THREAD thttp_shell(void * args)
{
thttpd_main((char *)httpdconf_name);
return (THREAD)0;
}
NOTES
There is demo available for the Unison and DSPnano thttpd which are found in installdir/demos which provide examples of using the server with simple page, password protected and CGI generated pages.