#include <stdio.h>
#include <dos.h>
#include <tcp.h>
#include <string.h>
#define PORT_HTTP 80
#define MAXCLIENTS 5
struct structhttp {
char filename[64];
FILE *filehand;
tcp_Socket sock;
sockaddr peer;
char laststate;
char gotreq;
unsigned long filesize;
unsigned long curpos;
} static http[MAXCLIENTS];
FILE *logfile;
struct time timeval;
struct date dateval;
char *reqstring[2] = { "GET ", "POST " };
char msg[256], msgout[4096];
int msglen;
void resetsocket(int socknum) {
sock_abort(&http[socknum].sock); //it can't hurt, right?
memset(&http[socknum].filename, 0, 64);
if (http[socknum].filehand!=NULL) fclose(http[socknum].filehand);
http[socknum].laststate = 0;
http[socknum].filesize = 0;
http[socknum].curpos = 0;
http[socknum].gotreq = 0;
tcp_listen(&http[socknum].sock, PORT_HTTP, 0, 0, NULL, 0);
}
void sendfile(int socknum) {
int remain;
remain = sock_rbleft(&http[socknum].sock) & 0xFFF; //4 KB max buffer
if (!remain) return;
msglen = fread(&msgout[0], 1, remain, http[socknum].filehand);
if (!msglen) { sock_close(&http[socknum].sock); return; }
sock_write(&http[socknum].sock, &msgout[0], msglen);
sock_flush(&http[socknum].sock);
//if (ftell(http[socknum].filehand)==http[socknum].filesize)
// sock_close(&http[socknum].sock);
}
void startsend(int socknum) {
http[socknum].filehand = fopen(&http[socknum].filename[0], "rb");
if (http[socknum].filehand==NULL) {
msglen = sprintf(&msgout[0], "HTTP/1.0 404 File Not Found\r\n\r\n");
sock_write(&http[socknum].sock, &msgout[0], msglen);
msglen = sprintf(&msgout[0], "<b><h1>404 File Not Found</h1></b><p>The requested file does not exist on this server:\r\n<b>%s</b>\r\n", &http[socknum].filename[0]);
sock_write(&http[socknum].sock, &msgout[0], msglen);
sock_flush(&http[socknum].sock);
sock_close(&http[socknum].sock);
return;
}
fseek(http[socknum].filehand, 0, SEEK_END);
http[socknum].filesize = ftell(http[socknum].filehand);
fseek(http[socknum].filehand, 0, SEEK_SET);
msglen = sprintf(&msgout[0], "HTTP/1.0 200 OK\r\n\r\n");
sock_write(&http[socknum].sock, &msgout[0], msglen);
sock_flush(&http[socknum].sock);
http[socknum].laststate = 2;
}
int getreqtype(char *request) {
int i, pos;
char cc1, cc2;
for (i=0; i<2; i++) {
pos = 0;
while (1) {
cc1 = reqstring[i][pos];
cc2 = request[pos++];
if ((cc2>96) && (cc2<123)) cc2 -= 32; //convert lowercase to uppercase
if ((cc1 != cc2) || (cc1==32)) break;
}
if (cc1==32) return(i);
}
return(i);
}
void parsefilename(int socknum, char *reqline) {
int srcpos, dstpos = 0;
char cc;
for (srcpos=5; srcpos<68; srcpos++) {
cc = reqline[srcpos];
if (cc==32) cc = 0;
if (cc==47) cc = 92; //convert forward slashes to back slashes
http[socknum].filename[dstpos++] = cc;
if (!cc) {
if ((http[socknum].filename[dstpos-2]==92) || (dstpos==1)) {
sprintf(&http[socknum].filename[0], "%sindex.htm", &http[socknum].filename[0]);
}
return;
}
}
}
void waitheader(int socknum) {
if (sock_rbused(&http[socknum].sock)==0) return;
msglen = sock_gets(&http[socknum].sock, &msg[0], 256);
if (msglen==0) {
http[socknum].laststate = 2;
return;
}
if (!http[socknum].gotreq) {
if (getreqtype(&msg[0])>0) {
msglen = sprintf(&msgout[0], "HTTP/1.0 405 Method Not Allowed\r\n\r\n<b><h1>405 Method Not Allowed</h1></b><p>Invalid request method!\r\n");
sock_write(&http[socknum].sock, &msgout[0], msglen);
sock_flush(&http[socknum].sock);
sock_close(&http[socknum].sock);
return;
}
http[socknum].gotreq = 1;
parsefilename(socknum, &msg[0]);
inet_ntoa(&msg[0], http[socknum].peer.s_ip);
getdate(&dateval); gettime(&timeval);
sprintf(&msgout[0], "[%02u-%02u-%04u %02u:%02u:%02u] %s GET \\%s\r\n", dateval.da_mon, dateval.da_day, dateval.da_year, timeval.ti_hour, timeval.ti_min, timeval.ti_sec, &msg[0], &http[socknum].filename[0]);
printf("%s", &msgout[0]);
if (logfile!=NULL) fprintf("%s", &msgout[0]);
startsend(socknum);
}
}
int main(int argc, char *argv[]) {
int i;
printf("HTTP Server for DOS v1.0 (c)2011 Mike Chambers\r\n\r\n");
printf("Initializing TCP/IP... ");
sock_init();
printf("OK!\r\n");
for (i=1; i<argc; i++)
if (strcmpi(argv[i], "-log")==0) {
printf("Logging enabled, will be written to HTTPDLOG.TXT.\r\n");
logfile = fopen("httpdlog.txt", "w");
}
for (i=0; i<MAXCLIENTS; i++) {
resetsocket(i);
}
printf("Listening for connections on port %u...\r\n", PORT_HTTP);
while (!kbhit()) {
for (i=0; i<MAXCLIENTS; i++) {
tcp_tick(&http[i].sock);
if (sock_established(&http[i].sock)) {
switch (http[i].laststate) {
case 0: //this is a new connection
getpeername(&http[i].sock, &http[i].peer, (int *)NULL);
sock_mode(&http[i].sock, TCP_MODE_ASCII);
http[i].laststate = 1;
waitheader(i); break;
case 1: //we're waiting on the request header
waitheader(i); break;
case 2: //data transfer in progress
sendfile(i); break;
default: break;
}
} else if (http[i].laststate>0) resetsocket(i);
}
}
if (logfile!=NULL) fclose(logfile);
return(0);
}