Skip to content

Instantly share code, notes, and snippets.

@r2dev
Created April 18, 2021 20:23
Show Gist options
  • Save r2dev/aff0b96fa84cf207b9e3495b4da95e9d to your computer and use it in GitHub Desktop.
Save r2dev/aff0b96fa84cf207b9e3495b4da95e9d to your computer and use it in GitHub Desktop.
httpd in c
@echo off
IF NOT EXIST .\build mkdir .\build
pushd .\build
cl -nologo -Zi -FC ..\main.cpp Ws2_32.lib
popd
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdint.h>
#include <stdio.h>
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef s32 b32;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef float r32;
typedef double r64;
#define DEFAULT_BUFLEN 1024
char ListenBuffer[DEFAULT_BUFLEN];
int ListenBufferLen = DEFAULT_BUFLEN;
#define MAX_CLIENT 16
SOCKET ClientSockets[MAX_CLIENT];
void Hello(int client) {
char buf[1024];
sprintf(buf, "HTTP/1.0 200 Ok\r\n");
send(client, buf, strlen(buf), 0);
sprintf(buf, "Content-Type: text/html\r\n");
send(client, buf, strlen(buf), 0);
sprintf(buf, "\r\n");
send(client, buf, strlen(buf), 0);
sprintf(buf, "<HTML><TITLE>Hello world</TITLE>\r\n");
send(client, buf, strlen(buf), 0);
sprintf(buf, "<BODY><P>Hello\r\n");
send(client, buf, strlen(buf), 0);
sprintf(buf, "</P></BODY></HTML>\r\n");
send(client, buf, strlen(buf), 0);
}
int CALLBACK
WinMain(HINSTANCE Instance,
HINSTANCE PrevInstance,
LPSTR CommandLine,
int ShowCode)
{
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 2), &WSAData)) {
}
if (LOBYTE(WSAData.wVersion) != 2 && HIBYTE(WSAData.wVersion) != 2) {
}
addrinfo *AddressInfo;
addrinfo AddressInfoHint = {};
AddressInfoHint.ai_flags = AI_PASSIVE;
AddressInfoHint.ai_family = AF_INET;
AddressInfoHint.ai_socktype = SOCK_STREAM;
AddressInfoHint.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(0, "8888", &AddressInfoHint, &AddressInfo) != 0) {
printf("getaddrinfo failed\n");
WSACleanup();
return 1;
}
SOCKET Httpd = socket(AddressInfo->ai_family, AddressInfo->ai_socktype, AddressInfo->ai_protocol);
if (Httpd == INVALID_SOCKET) {
freeaddrinfo(AddressInfo);
WSACleanup();
return 1;
}
if (bind(Httpd, AddressInfo->ai_addr, (int)AddressInfo->ai_addrlen) == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(AddressInfo);
closesocket(Httpd);
WSACleanup();
return 1;
}
freeaddrinfo(AddressInfo);
if (listen(Httpd, SOMAXCONN) == SOCKET_ERROR) {
closesocket(Httpd);
WSACleanup();
return 1;
}
// note: initialization
for (u32 ClientIndex = 0; ClientIndex < MAX_CLIENT; ++ClientIndex) {
SOCKET *ClientSocket = ClientSockets + ClientIndex;
*ClientSocket = 0;
}
fd_set SocketSet;
for(;;) {
FD_ZERO(&SocketSet);
FD_SET(Httpd, &SocketSet);
int max_sd = Httpd;
// note: find a empty slot
for (u32 ClientIndex = 0; ClientIndex < MAX_CLIENT; ++ClientIndex) {
SOCKET *ClientSocket = ClientSockets + ClientIndex;
if (*ClientSocket > 0) {
FD_SET(*ClientSocket, &SocketSet);
}
if (*ClientSocket > max_sd) {
max_sd = *ClientSocket;
}
}
int Activity = select(max_sd + 1, &SocketSet, 0, 0, 0);
if (Activity != SOCKET_ERROR) {
if (FD_ISSET(Httpd, &SocketSet)) {
SOCKET NewSocket = accept(Httpd, 0, 0);
for (u32 ClientIndex = 0; ClientIndex < MAX_CLIENT; ++ClientIndex) {
SOCKET *ClientSocket = ClientSockets + ClientIndex;
if (*ClientSocket == 0) {
*ClientSocket = NewSocket;
break;
}
}
}
for (u32 ClientIndex = 0; ClientIndex < MAX_CLIENT; ++ClientIndex) {
SOCKET *ClientSocket = ClientSockets + ClientIndex;
if (*ClientSocket != 0 && FD_ISSET(*ClientSocket, &SocketSet)) {
int ListenResult;
do {
ListenResult = recv(*ClientSocket, ListenBuffer, ListenBufferLen, 0);
if (ListenResult > 0) {
Hello(*ClientSocket);
break;
} else if (ListenResult == 0) {
} else {
}
} while (ListenResult > 0);
FD_CLR(*ClientSocket, &SocketSet);
closesocket(*ClientSocket);
*ClientSocket = 0;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment