Code:
//http.c
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include "server.h"
#include "http.h"
#define SERVER_PORT (8080)
static char web_pages_path[1000] = "./web_pages";
/* main() funcion */
int main(int argc, char *argv[]) {
int sock;
int conn;
pid_t pid;
struct sockaddr_in servaddr;
/* Create socket */
//if ( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
//Error_Quit("Couldn't create listening socket.");
sock = socket(AF_INET, SOCK_STREAM, 0);
/* Populate socket address structure */
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERVER_PORT);
/* Assign socket address to socket */
//if ( bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
//Error_Quit("Couldn't bind listening socket.");
bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
/* Make socket a listening socket */
//if ( listen(sock, LISTENQ) < 0 )
//Error_Quit("Call to listen failed.");
listen(sock, LISTENQ);
/* Loop infinitely to accept and service connections */
while ( 1 ) {
/* Wait for connection */
if ( (conn = accept(sock, NULL, NULL)) < 0 )
Error_Quit("Error calling accept()");
/* Fork child process to service connection */
if ( (pid = fork()) == 0 ) {
/* This is now the forked child process, so
close listening socket and service request */
if ( close(sock) < 0 )
Error_Quit("Error closing listening socket in child.");
Service_Request(conn);
/* Close connected socket and exit */
if ( close(conn) < 0 )
Error_Quit("Error closing connection socket.");
exit(EXIT_SUCCESS);
}
/* If we get here, we are still in the parent process,
so close the connected socket, clean up child processes,
and go back to accept a new connection. */
if ( close(conn) < 0 )
Error_Quit("Error closing connection socket in parent.");
waitpid(-1, NULL, WNOHANG);
}
return EXIT_FAILURE; /* We shouldn't get here */
}
//===========================================servreq====
/* Service an HTTP request */
int Service_Request(int conn) {
struct ReqInfo reqinfo;
int resource = 0;
InitReqInfo(&reqinfo);
/* Get HTTP request */
if ( Get_Request(conn, &reqinfo) < 0 )
return -1;
/* Check whether resource exists, whether we have permission
to access it, and update status code accordingly. */
if ( reqinfo.status == 200 )
if ( (resource = Check_Resource(&reqinfo)) < 0 ) {
if ( errno == EACCES )
reqinfo.status = 401;
else
reqinfo.status = 404;
}
/* Output HTTP response headers if we have a full request */
if ( reqinfo.type == FULL )
Output_HTTP_Headers(conn, &reqinfo);
/* Service the HTTP request */
if ( reqinfo.status == 200 ) {
if ( Return_Resource(conn, resource, &reqinfo) )
Error_Quit("Something wrong returning resource.");
}
else
Return_Error_Msg(conn, &reqinfo);
if ( resource > 0 )
if ( close(resource) < 0 )
Error_Quit("Error closing resource.");
FreeReqInfo(&reqinfo);
return 0;
}
//=====================resource============
/* Returns a resource */
int Return_Resource(int conn, int resource, struct ReqInfo * reqinfo) {
char c;
int i;
while ( (i = read(resource, &c, 1)) ) {
if ( i < 0 )
Error_Quit("Error reading from file.");
if ( write(conn, &c, 1) < 1 )
Error_Quit("Error sending file.");
}
return 0;
}
/* Tries to open a resource. The calling function can use
the return value to check for success, and then examine
errno to determine the cause of failure if neceesary. */
int Check_Resource(struct ReqInfo * reqinfo) {
/* Resource name can contain urlencoded
data, so clean it up just in case. */
CleanURL(reqinfo->resource);
/* Concatenate resource name to server root, and try to open */
strcat(web_pages_path, reqinfo->resource);
return open(web_pages_path, O_RDONLY);
}
//modify this to show msg successfull
/* Returns an error message */
int Return_Error_Msg(int conn, struct ReqInfo * reqinfo) {
char buffer[100];
sprintf(buffer, "<HTML>\n<HEAD>\n<TITLE>Base Command Center | Message Sent</TITLE>\n"
"</HEAD>\n\n", reqinfo->status);
Writeline(conn, buffer, strlen(buffer));
sprintf(buffer, "<BODY>\n<H1>Message Sent Successfully</H1>\n", reqinfo->status);
Writeline(conn, buffer, strlen(buffer));
sprintf(buffer, "<P>The message has been sent successfully. You may click back now to return to home page.</P>\n"
"</BODY>\n</HTML>\n");
Writeline(conn, buffer, strlen(buffer));
return 0;
}
//=============================reqhead========================
/* Parses a string and updates a request
information structure if necessary. */
int Parse_HTTP_Header(char * buffer, struct ReqInfo * reqinfo) {
static int first_header = 1;
char *temp;
char *endptr;
int len;
if ( first_header == 1 ) {
/* If first_header is 0, this is the first line of
the HTTP request, so this should be the request line. */
/* Get the request method, which is case-sensitive. This
version of the server only supports the GET and HEAD
request methods. */
if ( !strncmp(buffer, "GET ", 4) ) {
reqinfo->method = GET;
printf("#:%s\n", buffer);
//Return_Resource(conn, resource, &reqinfo)
//bt_send();
buffer += 4;
}
else if ( !strncmp(buffer, "HEAD ", 5) ) {
reqinfo->method = HEAD;
buffer += 5;
}
else {
reqinfo->method = UNSUPPORTED;
reqinfo->status = 501;
return -1;
}
/* Skip to start of resource */
while ( *buffer && isspace(*buffer) )
buffer++;
/* Calculate string length of resource... */
endptr = strchr(buffer, ' ');
if ( endptr == NULL )
len = strlen(buffer);
else
len = endptr - buffer;
if ( len == 0 ) {
reqinfo->status = 400;
return -1;
}
/* ...and store it in the request information structure. */
reqinfo->resource = calloc(len + 1, sizeof(char));
strncpy(reqinfo->resource, buffer, len);
/* Test to see if we have any HTTP version information.
If there isn't, this is a simple HTTP request, and we
should not try to read any more headers. For simplicity,
we don't bother checking the validity of the HTTP version
information supplied - we just assume that if it is
supplied, then it's a full request. */
if ( strstr(buffer, "HTTP/") )
reqinfo->type = FULL;
else
reqinfo->type = SIMPLE;
first_header = 0;
return 0;
}
/* If we get here, we have further headers aside from the
request line to parse, so this is a "full" HTTP request. */
/* HTTP field names are case-insensitive, so make an
upper-case copy of the field name to aid comparison.
We need to make a copy of the header up until the colon.
If there is no colon, we return a status code of 400
(bad request) and terminate the connection. Note that
HTTP/1.0 allows (but discourages) headers to span multiple
lines if the following lines start with a space or a
tab. For simplicity, we do not allow this here. */
endptr = strchr(buffer, ':');
if ( endptr == NULL ) {
reqinfo->status = 400;
return -1;
}
temp = calloc( (endptr - buffer) + 1, sizeof(char) );
strncpy(temp, buffer, (endptr - buffer));
StrUpper(temp);
/* Increment buffer so that it now points to the value.
If there is no value, just return. */
buffer = endptr + 1;
while ( *buffer && isspace(*buffer) )
++buffer;
if ( *buffer == '\0' )
return 0;
/* Now update the request information structure with the
appropriate field value. This version only supports the
"Referer:" and "User-Agent:" headers, ignoring all others. */
if ( !strcmp(temp, "USER-AGENT") ) {
reqinfo->useragent = malloc( strlen(buffer) + 1 );
strcpy(reqinfo->useragent, buffer);
}
else if ( !strcmp(temp, "REFERER") ) {
reqinfo->referer = malloc( strlen(buffer) + 1 );
strcpy(reqinfo->referer, buffer);
}
free(temp);
return 0;
}
/* Gets request headers. A CRLF terminates a HTTP header line,
but if one is never sent we would wait forever. Therefore,
we use select() to set a maximum length of time we will
wait for the next complete header. If we timeout before
this is received, we terminate the connection. */
int Get_Request(int conn, struct ReqInfo * reqinfo) {
char buffer[MAX_REQ_LINE] = {0};
int rval;
fd_set fds;
struct timeval tv;
/* Set timeout to 5 seconds */
tv.tv_sec = 5;
tv.tv_usec = 0;
/* Loop through request headers. If we have a simple request,
then we will loop only once. Otherwise, we will loop until
we receive a blank line which signifies the end of the headers,
or until select() times out, whichever is sooner. */
do {
/* Reset file descriptor set */
FD_ZERO(&fds);
FD_SET (conn, &fds);
/* Wait until the timeout to see if input is ready */
rval = select(conn + 1, &fds, NULL, NULL, &tv);
/* Take appropriate action based on return from select() */
if ( rval < 0 ) {
Error_Quit("Error calling select() in get_request()");
}
else if ( rval == 0 ) {
/* input not ready after timeout */
return -1;
}
else {
/* We have an input line waiting, so retrieve it */
Readline(conn, buffer, MAX_REQ_LINE - 1);
Trim(buffer);
if ( buffer[0] == '\0' )
break;
if ( Parse_HTTP_Header(buffer, reqinfo) )
break;
}
} while ( reqinfo->type != SIMPLE );
return 0;
}
/* Initialises a request information structure */
void InitReqInfo(struct ReqInfo * reqinfo) {
reqinfo->useragent = NULL;
reqinfo->referer = NULL;
reqinfo->resource = NULL;
reqinfo->method = UNSUPPORTED;
reqinfo->status = 200;
}
/* Frees memory allocated for a request information structure */
void FreeReqInfo(struct ReqInfo * reqinfo) {
if ( reqinfo->useragent )
free(reqinfo->useragent);
if ( reqinfo->referer )
free(reqinfo->referer);
if ( reqinfo->resource )
free(reqinfo->resource);
}
//=================================resphead=====================
/* Outputs HTTP response headers */
int Output_HTTP_Headers(int conn, struct ReqInfo * reqinfo) {
char buffer[100];
sprintf(buffer, "HTTP/1.0 %d OK\r\n", reqinfo->status);
Writeline(conn, buffer, strlen(buffer));
Writeline(conn, "Server: PGWebServ v0.1\r\n", 24);
Writeline(conn, "Content-Type: text/html\r\n", 25);
Writeline(conn, "\r\n", 2);
return 0;
}
//=============================helper==========================
/* Prints an error message and quits */
void Error_Quit(char const * msg) {
fprintf(stderr, "WEBSERV: %s\n", msg);
exit(EXIT_FAILURE);
}
/* Read a line from a socket */
ssize_t Readline(int sockd, void *vptr, size_t maxlen) {
ssize_t n, rc;
char c, *buffer;
buffer = vptr;
for ( n = 1; n < maxlen; n++ ) {
if ( (rc = read(sockd, &c, 1)) == 1 ) {
*buffer++ = c;
if ( c == '\n' )
break;
}
else if ( rc == 0 ) {
if ( n == 1 )
return 0;
else
break;
}
else {
if ( errno == EINTR )
continue;
Error_Quit("Error in Readline()");
}
}
*buffer = 0;
return n;
}
/* Write a line to a socket */
ssize_t Writeline(int sockd, const void *vptr, size_t n) {
size_t nleft;
ssize_t nwritten;
const char *buffer;
buffer = vptr;
nleft = n;
while ( nleft > 0 ) {
if ( (nwritten = write(sockd, buffer, nleft)) <= 0 ) {
if ( errno == EINTR )
nwritten = 0;
else
Error_Quit("Error in Writeline()");
}
nleft -= nwritten;
buffer += nwritten;
}
return n;
}
/* Removes trailing whitespace from a string */
int Trim(char * buffer) {
int n = strlen(buffer) - 1;
while ( !isalnum(buffer[n]) && n >= 0 )
buffer[n--] = '\0';
return 0;
}
/* Converts a string to upper-case */
int StrUpper(char * buffer) {
while ( *buffer ) {
*buffer = toupper(*buffer);
++buffer;
}
return 0;
}
/* Cleans up url-encoded string */
void CleanURL(char * buffer) {
char asciinum[3] = {0};
int i = 0, c;
while ( buffer[i] ) {
if ( buffer[i] == '+' )
buffer[i] = ' ';
else if ( buffer[i] == '%' ) {
asciinum[0] = buffer[i+1];
asciinum[1] = buffer[i+2];
buffer[i] = strtol(asciinum, NULL, 16);
c = i+1;
do {
buffer[c] = buffer[c+2];
} while ( buffer[2+(c++)] );
}
++i;
}
}
and this is server.c:
Code:
//rfcomm Server
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <stdlib.h>
#include "server.h"
char buffer[1024] = { 0 };
int bt_recv()
{
struct sockaddr_rc BASE_addr = { 0 }, CORE_addr = { 0 };
//variable deceleration
int sock;
int client;
int bytes_read;
socklen_t opt = sizeof(CORE_addr);
// Socket Allocation
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// Socket Binding
BASE_addr.rc_family = AF_BLUETOOTH;
BASE_addr.rc_bdaddr = *BDADDR_ANY;
BASE_addr.rc_channel = (uint8_t) 1;
bind(sock, (struct sockaddr *)&BASE_addr, sizeof(BASE_addr));
// put socket into listening mode
listen(sock, 1);
// accept incomming connection
client = accept(sock, (struct sockaddr *)&CORE_addr, &opt);
ba2str( &CORE_addr.rc_bdaddr, buffer );
fprintf(stderr, "accepted connection from %s\n", buffer);
memset(buffer, 0, sizeof(buffer));
// read data after connection is established
bytes_read = read(client, buffer, sizeof(buffer));
if( bytes_read > 0 ) {
printf("Received Command: %s \n", buffer);
printf("Command Logged!\n");
logger();
}
// close connection after sending
close(client);
close(sock);
return 0;
}
//Logging Functions
int logger()
{
FILE *file;
file = fopen("file.txt","a+"); // apend file (add text to a file or create a file if it does not exist.
fprintf(file,"# Command = %s\n", buffer );
fclose(file);
return 0;
}
//send function?
int bt_send()
{
struct sockaddr_rc addr = { 0 };
int sock; //as in socket
int status;
char mac_address[18] = "00:19:7E:F9:3B:92"; //Core's MAC Address
// Scoket Allocation
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// set the connection parameters (who to connect to)
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( mac_address, &addr.rc_bdaddr );
// connect to server
status = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
// send message - Write a message on the socket (sock)
if( status == 0 ) {
status = write(sock, "START", 6);
}
//error handling
if( status < 0 ) perror("Error On Sending Message");
//Close Socket after sending
close(sock);
return 0;
}
/*
int main(int argc, char **argv)
{
printf("Awaiting Connection...\n");
while (1)
{
bt_recv();
}
}
*/
and server.h: