snf.h:
/* Removed long signature for the sake of posting.
*/
#include "snferror.h"
#ifdef WIN32 // It's portable
#include
#else
#include
#include
#include
#include
#endif
#define TCP 5000 // not defined this way for any reason, move along
#define UDP 5001
class snfc {
int errormode;
bool initcalled;
bool client_made;
bool server_made;
int s; // our socket
short port; // the port for our server to run on
int bl; // int for bind and listen
int sr; // int for send and recv (and connect)
int ac; // int for accept
struct sockaddr_in cstruct; // struct used for certain calls
struct sockaddr_in cli; // stores client info
int clilen; // eventually set (needed for accept)
public:
void changemode(int mode)
{
if(mode > -1 && mode < TOTAL_MODES)
errormode = mode;
}
int init() // take care of all of that annoying stuff
{
if(initcalled == true)
return snferror(INIT_CALLED, errormode);
error_start();
changemode(PRINT_RETURN);
client_made = false;
server_made = false;
initcalled = true;
return 0;
}
int makeclient(short port, char ip[], int ipproto)
{
if(server_made == true || client_made == true)
return snferror(MULTIPLE_SOCK, errormode);
if(initcalled != true)
return snferror(INIT_NOCALL, errormode);
cstruct.sin_family = AF_INET;
cstruct.sin_port = htons(port);
cstruct.sin_addr.s_addr = inet_addr(ip);
WORD wsaversion = MAKEWORD(2, 2);
WSADATA wsadata;
if(WSAStartup(wsaversion, &wsadata) != 0)
return snferror(STARTUP_ERROR, errormode);
if(ipproto == TCP)
s = socket(AF_INET, SOCK_STREAM, 0);
else if(ipproto == UDP)
s = socket(AF_INET, SOCK_DGRAM, 0);
if(s == INVALID_SOCKET)
return snferror(SOCKET_ERROR, errormode);
sr = connect(s, (struct sockaddr *)&cstruct, sizeof(cstruct));
if(sr)
return snferror(CONNECT_ERROR, errormode);
client_made = true;
return SUCESS;
}
int makeserver(short port, int ipproto)
{
if(server_made == true || client_made == true)
return snferror(MULTIPLE_SOCK, errormode);
if(initcalled != true)
return snferror(INIT_NOCALL, errormode);
port = port;
cstruct.sin_family = AF_INET;
cstruct.sin_port = htons(port);
cstruct.sin_addr.s_addr = htonl(INADDR_ANY);
WORD wsaversion = MAKEWORD(2, 2);
WSADATA wsadata;
if(WSAStartup(wsaversion, &wsadata) != 0)
return snferror(STARTUP_ERROR, errormode);
if(ipproto == TCP)
s = socket(AF_INET, SOCK_STREAM, 0);
else if(ipproto == UDP)
s = socket(AF_INET, SOCK_DGRAM, 0);
if(s == INVALID_SOCKET)
return snferror(SOCK_ERROR, errormode);
bl = bind(s, (struct sockaddr *)&cstruct, sizeof(cstruct));
if(bl != 0)
return snferror(BIND_ERROR, errormode);
server_made = true;
return SUCESS;
}
int getclient(int max)
{
if((server_made != true && client_made == false) ||
(server_made == false && client_made != true) ||
(server_made != true && client_made != true))
return snferror(SERCLI_NOMADE, errormode);
clilen = sizeof(cli); // needed for accept
bl = listen(s, max);
if(bl)
return snferror(LISTEN_ERROR, errormode);
ac = accept(s, (struct sockaddr *)&cli, &clilen);
if(ac == INVALID_SOCKET)
return snferror(ACCEPT_ERROR, errormode);
return SUCESS;
}
int snfsend(const char FAR *data)
{
if((server_made != true && client_made == false) ||
(server_made == false && client_made != true) ||
(server_made != true && client_made != true))
return snferror(SERCLI_NOMADE, errormode);
if(server_made == true)
sr = send(ac, data, strlen(data), 0);
if(client_made == true)
sr = send(s, data, strlen(data), 0);
if(sr == -1)
return snferror(SEND_ERROR, errormode);
return sr;
}
int snfrecv(char FAR *target, int max)
{
if((server_made != true && client_made == false) ||
(server_made == false && client_made != true) ||
(server_made != true && client_made != true))
return snferror(SERCLI_NOMADE, errormode);
if(server_made == true)
sr = recv(ac, target, max, 0);
if(client_made == true)
sr = recv(s, target, max, 0);
if(sr == -1)
return snferror(RECV_ERROR, errormode);
return sr;
}
char * clientip()
{
if(server_made != true)
{
snferror(SERVER_NOMADE, errormode);
return "SNF_ERROR";
}
char *ourbuffer = (char *)calloc(18, sizeof(char));
sprintf(ourbuffer, "%s", inet_ntoa(cli.sin_addr));
int where = strlen(inet_ntoa(cli.sin_addr));
ourbuffer[where] = NULL;
return ourbuffer;
}
void closesock()
{
if(server_made == true)
closesocket(ac);
if(client_made == true)
closesocket(s);
}
};
snferror.h:
/* Removed long signature for the sake of posting.
*/
#include // strcat
#include // printf
typedef char error_str[256];
#define STARTUP_ERROR 0
#define SOCK_ERROR 1 // renamed from SOCKET_ERROR to avoid repeated definition
#define BIND_ERROR 2
#define LISTEN_ERROR 3
#define ACCEPT_ERROR 4
#define CONNECT_ERROR 5
#define SEND_ERROR 6
#define RECV_ERROR 7
#define INIT_NOCALL 8
#define SERVER_NOMADE 9
#define CLIENT_NOMADE 10
#define SERCLI_NOMADE 11
#define INIT_CALLED 12
#define MULTIPLE_SOCK 13
#define SUCESS 2600
#define TOTAL_ERRORS 14
char errors[TOTAL_ERRORS][256];
void error_start()
{
strcat(errors[STARTUP_ERROR], "There was an error while calling WSAStartup" );
strcat(errors[SOCK_ERROR], "There was an error while creating the socket" );
strcat(errors[BIND_ERROR], "There was an error while binding to the socket" );
strcat(errors[LISTEN_ERROR], "There was an error while listening on the socket" );
strcat(errors[ACCEPT_ERROR], "There was an error while accepting a connection" );
strcat(errors[CONNECT_ERROR], "There was an error while connecting to the host" );
strcat(errors[SEND_ERROR], "There was an error while sending data" );
strcat(errors[RECV_ERROR], "There was an error while recieving data" );
strcat(errors[INIT_NOCALL], "Function init() has not been called!" );
strcat(errors[SERVER_NOMADE], "The client has not yet been made!" );
strcat(errors[CLIENT_NOMADE], "The server has not yet been made!" );
strcat(errors[SERCLI_NOMADE], "Neither a server nor a client has been made!" );
strcat(errors[INIT_CALLED], "Function init() has already been called!" );
strcat(errors[MULTIPLE_SOCK], "A server or client is already in use. Please call flush() first.");
}
#define PRINT 0
#define STORE 1
#define RETURN 2
#define PRINT_STORE 3
#define PRINT_RETURN 4
#define STORE_RETURN 5
#define PRINT_STORE_RETURN 6
#define TOTAL_MODES 7
error_str errstr;
int snferror(int error, int mode)
{
if(error > TOTAL_ERRORS || error < 0)
return -1;
if(mode == PRINT || mode == PRINT_STORE || mode == PRINT_RETURN || mode == PRINT_STORE_RETURN)
{
printf("SNF ERROR: %s\n", errors[error]);
if(mode == PRINT_STORE)
strcat(errstr, errors[error]);
else if(mode == PRINT_RETURN)
return error;
else if(mode == PRINT_STORE_RETURN)
{
strcat(errstr, errors[error]);
return error;
}
}
else if(mode == STORE || mode == STORE_RETURN)
{
strcat(errstr, errors[error]);
if(mode == STORE_RETURN)
return error;
}
else if(mode == RETURN)
return error;
return TOTAL_ERRORS + 1; // you didn't ask for a return
}
example.cpp
#include "snf.h"
#include
#include
void main()
{
char mypage[] = "\n\nIf you are viewing this page, you are viewing a page from a HTTP server coded with Shell\'s Network Framework (or SNF for short)\n\n";
char mybuffer[1024];
char response[4096];
char formtime[128];
time_t thetime;
struct tm *timeinfo;
snfc server;
server.init();
server.makeserver(8080, TCP);
for(;;)
{
server.getclient(2);
int where = server.snfrecv(mybuffer, 1023);
char *clientip = server.clientip();
mybuffer[where] = NULL;
printf("Got a request from %s\n", clientip);
time(&thetime);
timeinfo = localtime(&thetime);
strftime(formtime, sizeof formtime, "%a, %d %b %Y %X SST", timeinfo);
sprintf(response, "HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nDate: %s\r\nContent-Type: text/html\r\nServer: ShellHTTPServer\r\n\r\ne2 \x0d\x0a\x0a%s", formtime, mypage);
server.snfsend(response);
server.closesock();
}
}