/*
* quick-and-dirty HTTP server which allows a remote web browser
* to interface with the target machine.
*/
#include "vxWorks.h"
#include "sys/types.h"
#include "ioLib.h"
#include "ifLib.h"
#include "fioLib.h"
#include "stdio.h"
#include "unistd.h"
#include "string.h"
#include "usrLib.h"
#include "errnoLib.h"
#include "hostLib.h"
#include "sockLib.h"
#include "socket.h"
#include "inetLib.h"
#include "in.h"
#include "selectLib.h"
#include "taskLib.h"
#include "ctype.h"
#include "dirent.h"
#include "sys/stat.h"
#include "errnoLib.h"
#include "fcntl.h"
#include "unistd.h"
#include "fioLib.h"
/*********** kludge delay to make this work! ***************/
int kludge_delay = 0;
/*********** kludge delay to make this work! ****************/
int vhttpVerbose = 1;
#define HTTP_PORT 80
#define DEBUG 1 /* XXX */
#define MAX_SESSIONS 12 /* 12 concurrent HTTP sessions */
WIND_TCB *vhttp_tasks [MAX_SESSIONS];
WIND_TCB *vhttpd_task = 0;
char MyIPAddr[32];
char *getMyIpAddr()
{
ifAddrGet( "cs0",MyIPAddr );
return MyIPAddr;
}
int vt1();
int vt2();
int vt3();
/*
* customizable menu User interface
*/
struct vtMenu {
char * menu_desc;
int (* menu_func)();
};
#define MAX_CMDS 3 /* XXX this must match the struct below */
/* list of available commands and callback functions */
struct vtMenu vtCmds[MAX_CMDS] = {
{ "1. Stuff", vt1 },
{ "2. More Stuff", vt2 },
{ "3. More and More Stuff", vt3 },
};
int vt1()
{
printf("Command Handler: vt1, Stuff\n");
return OK;
}
int vt2()
{
printf("Command Handler: vt2, More Stuff\n");
return OK;
}
int vt3()
{
printf("Command Handler: vt3, More and More Stuff\n");
return OK;
}
#ifdef DEBUG
static void
errorMsg(char *msg)
{
printf("ERROR: %s, errno 0x%x\n", msg, errnoGet());
}
static void
infoMsg(char *msg)
{
printf("INFO: %s\n", msg);
}
#else
#define errorMsg(msg) ;
#define infoMsg(msg) ;
#endif
int
vhttpReadInputLine(int sock, char *buffer)
{
int num;
int i;
if (ioctl(sock, FIONREAD, &num) < 0){
errorMsg("vhttpReadInputLine: ioctl FIONREAD error");
return -1;
}
if (num < 1) return -1;
for (i=0;;) {
char ch;
int count;
count = read(sock, &ch, 1);
if (count < 1) {
errorMsg("vhttpReadInputLine: read error");
return -2;
}
if (ch == (char)0xd) { /* carriage return */
read(sock, &ch, 1); /* eat linefeed */
if (ch != (char)0xa) {
errorMsg("vhttpReadInputLine: LF expected but got someting else");
return -2;
}
break;
}
buffer[i++] = ch;
}
buffer[i] = '\0';
return(i);
}
void
vhttpSendErr(int sock, int code, char *msg)
{
char buf[128];
sprintf(buf, "%d %s\n", code, msg);
#ifdef DEBUG
printf(buf);
#endif
write(sock, buf, strlen(buf));
}
int
vhttpWriteSock(int sock, char *msg)
{
int result = write (sock, msg, strlen(msg));
/*********** kludge delay to make this work! ***************/
if( kludge_delay ) taskDelay( kludge_delay );
/*********** kludge delay to make this work! ****************/
return result;
}
void
vhttpSendText(int sock, char *URL)
{
int i;
struct vtMenu *mp;
char buf[128];
char my_addr[20];
vhttpWriteSock(sock, "HTTP/1.0 200 OK\nMIME-Version: 1.0\nContent-Type: ");
vhttpWriteSock(sock, "text/html\n\n");
vhttpWriteSock(sock, "
Bigger Text File");
vhttpWriteSock(sock, "\n");
vhttpWriteSock(sock, "
\n");
vhttpWriteSock(sock, "URL: "); vhttpWriteSock(sock, URL ); vhttpWriteSock(sock, "
");
vhttpWriteSock(sock, "
");
vhttpWriteSock(sock, "
\n");
vhttpWriteSock(sock, "00: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
vhttpWriteSock(sock, "01: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
");
vhttpWriteSock(sock, "02: cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
");
vhttpWriteSock(sock, "03: dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
");
vhttpWriteSock(sock, "04: eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
");
vhttpWriteSock(sock, "05: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
");
vhttpWriteSock(sock, "06: gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
");
vhttpWriteSock(sock, "07: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
");
vhttpWriteSock(sock, "08: iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
");
vhttpWriteSock(sock, "09: jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
");
vhttpWriteSock(sock, "10: kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
");
vhttpWriteSock(sock, "11: llllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
");
vhttpWriteSock(sock, "12: mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
");
vhttpWriteSock(sock, "13: nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
");
vhttpWriteSock(sock, "14: oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
");
vhttpWriteSock(sock, "15: pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp
");
vhttpWriteSock(sock, "16: qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
");
vhttpWriteSock(sock, "17: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
");
vhttpWriteSock(sock, "18: ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
");
vhttpWriteSock(sock, "19: tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
");
vhttpWriteSock(sock, "20: uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
");
vhttpWriteSock(sock, "21: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
");
vhttpWriteSock(sock, "22: wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
");
vhttpWriteSock(sock, "23: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
");
vhttpWriteSock(sock, "24: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
");
vhttpWriteSock(sock, "25: zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
");
vhttpWriteSock(sock, "
");
vhttpWriteSock(sock, "
");
vhttpWriteSock(sock, "");
vhttpWriteSock(sock, "\n");
}
void
vhttpSendMenu(int sock)
{
int i;
struct vtMenu *mp;
char buf[128];
char my_addr[20];
memset(my_addr,0,sizeof(my_addr));
sprintf(my_addr,"My IP is: %s
",getMyIpAddr());
vhttpWriteSock(sock, "HTTP/1.0 200 OK\nMIME-Version: 1.0\nContent-Type: ");
vhttpWriteSock(sock, "text/html\n\n");
vhttpWriteSock(sock, "Welcome to MyHacks, Inc.");
vhttpWriteSock(sock, "\n");
vhttpWriteSock(sock, "Welcome To MyHacks, Inc.\n");
vhttpWriteSock(sock, my_addr);
vhttpWriteSock(sock, "
\n");
memset(my_addr,0,sizeof(my_addr));
strcpy( my_addr,getMyIpAddr() );
for (i = 0, mp = &vtCmds[0]; i < MAX_CMDS; i++, mp++) {
vhttpWriteSock(sock, "- \n");
sprintf(buf, " %s ", my_addr,
HTTP_PORT, i, mp->menu_desc);
vhttpWriteSock(sock, buf);
}
vhttpWriteSock(sock, "
\n");
}
int
vhttpSendHTML(int sock, char *HTML)
{
int inFd;
int s=0;
inFd = open (HTML, O_RDONLY, 0);
if (inFd < OK) {
errorMsg("can't open HTML file");
return (ERROR);
}
vhttpWriteSock(sock, "HTTP/1.0 200 OK\nMIME-Version: 1.0\nContent-Type: ");
vhttpWriteSock(sock, "text/html\n\n");
vhttpWriteSock(sock, "SENDING HTML\n\n");
return (s);
}
int
vhttpSendGIF(int sock, char *GIF)
{
int inFd;
int s=0;
inFd = open (GIF, O_RDONLY, 0);
if (inFd < OK) {
errorMsg("can't open GIF file");
return (ERROR);
}
vhttpWriteSock(sock, "HTTP/1.0 200 OK\nMIME-Version: 1.0\nContent-Type: ");
vhttpWriteSock(sock, "image/gif\n\n");
vhttpWriteSock(sock, "SENDING GIF\n\n");
return (s);
}
int
vhttpSendJPEG(int sock, char *JPEG)
{
int inFd;
int s=0;
inFd = open (JPEG, O_RDONLY, 0);
if (inFd < OK) {
errorMsg("can't open JPEG file");
return (ERROR);
}
vhttpWriteSock(sock, "HTTP/1.0 200 OK\nMIME-Version: 1.0\nContent-Type: ");
vhttpWriteSock(sock, "image/jpeg\n\n");
vhttpWriteSock(sock, "SENDING JPG\n\n");
return (s);
}
int
vhttpProcessURL(int sock, char *URL)
{
int num;
int result;
char *suffix;
#ifdef DEBUG
printf("URL requested <%s>\n", URL);
#endif
if(URL[1]==' ') URL[1]=0;
if (strcmp(URL, "/" ) == 0) vhttpSendMenu(sock);
else {
suffix = strrchr(URL, '.');
#ifdef DEBUG
printf("URL requested Suffix=%s\n", suffix);
#endif
if (suffix != 0) {
if (strcmp(suffix,".html") == 0) vhttpSendHTML(sock,++URL);
else if (strcmp(suffix,".gif") == 0) vhttpSendGIF(sock,++URL);
else if (strcmp(suffix,".jpeg") == 0) vhttpSendJPEG(sock,++URL);
else if (strcmp(suffix,".text") == 0) vhttpSendText(sock,++URL);
else {
vhttpSendMenu(sock);
vhttpSendErr(sock, 666, "Unknown URL");
vhttpSendErr(sock, 666, URL);
}
}
else {
URL[0] = ' '; /* wipe out leading slash char */
num = atoi(URL);
if (num >= 0 && num < MAX_CMDS) {
#ifdef DEBUG
printf("URL requested dispatch to command handler: %d\n", num );
#endif
vhttpSendMenu(sock);
result = (*vtCmds[num].menu_func)();
if (result == OK) vhttpSendErr(sock, 205, "Command success");
else vhttpSendErr(sock, 905, "Command Failed");
} else {
vhttpSendErr(sock, 505, "Invalid menu item URL");
return ERROR;
}
}
}
return OK;
}
int
vhttpProcess(int sock, struct sockaddr_in *sinptr)
{
fd_set read_fdset;
fd_set write_fdset;
fd_set except_fdset;
int finishedHeader=0;
char buffer[1024];
char method[20];
char URL[200];
char proto[20];
char *p1,*p2;
fprintf(stderr,"\nVHTTP Process ");
for (;;) {
FD_SET(sock, &read_fdset);
FD_SET(sock, &write_fdset);
FD_SET(sock, &except_fdset);
if (select(64, &read_fdset, &write_fdset, &except_fdset, 0) < 0) continue;
if (FD_ISSET(sock, &read_fdset)) {
int result;
result = vhttpReadInputLine(sock, buffer);
memset(method,0,sizeof(method));
memset(URL,0,sizeof(URL));
strncpy(method,buffer,3);
p1 = URL;
p2 = &buffer[4];
while( !isspace(*p2) ) *p1++ = *p2++;
/*strncpy(URL,&buffer[4],strlen(buffer)-4);*/
fprintf(stderr,"\nVHTTP: rdInpLine[%u]=%s ",result,buffer );
fprintf(stderr,"\nVHTTP: method=%s ",method );
fprintf(stderr,"\nVHTTP: URL=%s ",URL );
fprintf(stderr,"\n");
if (result < 0) return -1;
if (result == 0) {
finishedHeader=1;
return 0;
}
if (!finishedHeader) {
if (strcmp(method, "GET") != 0 && strcmp(method, "PUT") != 0) {
vhttpSendErr(sock, 501, "Invalid Method. Expecting GET or PUT.");
close(sock);
return -1;
}
if (vhttpProcessURL(sock, URL) != OK) {
vhttpSendErr(sock, 404, "Invalid URL");
close(sock);
return -1;
}
close(sock);
finishedHeader=1;
return 0;
}
}
else if (FD_ISSET(sock, &write_fdset)) {
;
}
else if (FD_ISSET(sock, &except_fdset)) {
errorMsg("exception fd set");
}
#if 0
taskDelay(2 * 60);
#endif
}
}
int
vhttpMainLoop(int sock, struct sockaddr_in *sinptr)
{
int client;
char name[25];
static int procNum = 1;
int i;
int size;
fprintf(stderr,"\nVHTTP Main Loop ");
for (;;) {
WIND_TCB *tcb;
size = sizeof(*sinptr);
client = accept(sock, (struct sockaddr *)sinptr, &size);
if (client < 0) {
errorMsg("accept");
return -1;
}
infoMsg("vhttp: accepted a new client\n");
sprintf(name, "vhttp%d", procNum++);
tcb = taskSpawn(name, 101, 0, 1024 * 4, vhttpProcess,
client, sinptr, 0, 0, 0, 0, 0, 0, 0, 0);
tcb->spare4 = client;
for (i = 0; i < MAX_SESSIONS; i++) {
if (vhttp_tasks[i] == 0)
break;
}
if (i < MAX_SESSIONS) vhttp_tasks[i] = tcb;
else {
vhttpSendErr(sock, 501, "Too many sessions");
close(client);
return -1;
}
}
return OK;
}
int
vhttpDelete(WIND_TCB *tcb)
{
int i;
if (tcb == vhttpd_task) close(tcb->spare4); /* delete server socket */
for (i = 0; i < MAX_SESSIONS; i++) {
if (tcb == vhttp_tasks[i]) {
close(tcb->spare4);
vhttp_tasks[i] = 0;
}
}
}
int
vxhttp()
{
int sock;
struct sockaddr_in sin;
struct sockaddr_in *sinptr = &sin;
int true = 1;
WIND_TCB *tcb;
int i;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
errorMsg("socket");
return -1;
}
if((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(void *)&true, sizeof(true))) == -1) {
errorMsg("setsockopt");
return -1;
}
bzero(sinptr, sizeof(*sinptr));
sinptr->sin_family = AF_INET;
sinptr->sin_port = htons(HTTP_PORT);
sinptr->sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr *) sinptr, sizeof(*sinptr)) < 0) {
errorMsg("bind");
return -1;
}
if (listen (sock, 5) < 0) {
errorMsg("listen");
return -1;
}
for (i = 0; i < MAX_SESSIONS; i++) vhttp_tasks[i] = 0;
fprintf(stderr,"\nSpawn Main VHTTP");
tcb = taskSpawn("vHttpD", 100, 0, 2048, vhttpMainLoop,
sock, sinptr, 0, 0, 0, 0, 0, 0, 0, 0);
tcb->spare4 = sock;
vhttpd_task = tcb;
taskDeleteHookAdd(vhttpDelete);
return OK;
}