Created
March 30, 2009 20:20
-
-
Save adh/87870 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <netdb.h> | |
#include <netinet/in.h> | |
#include <sys/socket.h> | |
#include <sys/un.h> | |
#include <fcntl.h> | |
#include <string.h> | |
#include <sys/wait.h> | |
#include <signal.h> | |
#include <pthread.h> | |
#include <gc/gc.h> | |
int tcp_bind(unsigned int port){ | |
struct sockaddr_in inet_addr; | |
int fd; | |
inet_addr.sin_family=AF_INET; | |
inet_addr.sin_port=htons(port); | |
inet_addr.sin_addr.s_addr = INADDR_ANY; | |
fd = socket(PF_INET, SOCK_STREAM, 0); | |
if (fd == -1){ | |
perror("socket"); | |
exit(EXIT_FAILURE); | |
} | |
if (bind(fd,(struct sockaddr*)&inet_addr, | |
sizeof(inet_addr))==-1){ | |
close(fd); | |
perror("bind"); | |
exit(EXIT_FAILURE); | |
} | |
if (listen(fd, 3) == -1){ | |
perror("bind"); | |
exit(EXIT_FAILURE); | |
} | |
return fd; | |
} | |
static size_t scgi_read_length(FILE* stream){ | |
size_t res = 0; | |
int ch; | |
while ((ch = fgetc(stream)) != EOF){ | |
if (ch == ':'){ | |
return res; | |
} else if (ch >= '0' && ch <= '9'){ | |
res *= 10; | |
res += ch - '0'; | |
} else { | |
abort(); // error | |
} | |
} | |
} | |
typedef struct buffer_t { | |
char* ptr; | |
size_t len; | |
} buffer_t; | |
buffer_t* scgi_read_netstring(FILE* stream){ | |
size_t res; | |
buffer_t* bs = GC_NEW(buffer_t); | |
bs->len = scgi_read_length(stream); | |
bs->ptr = GC_MALLOC_ATOMIC(bs->len); | |
res = fread(bs->ptr, 1, bs->len, stream); | |
if (res != bs->len){ | |
abort(); // error | |
} | |
if (fgetc(stream) != ','){ | |
abort(); // error | |
} | |
return bs; | |
} | |
void scgi_read_headers(FILE* stream){ | |
buffer_t* buf = scgi_read_netstring(stream); | |
fprintf(stream, "Status: 200 OK\r\nContent-Type: text/plain\r\n\r\n"); | |
while (buf->len){ | |
size_t itemlen = strlen(buf->ptr); | |
fprintf(stream, "[%s]\n", buf->ptr); | |
buf->len -= itemlen + 1; | |
buf->ptr += itemlen + 1; | |
} | |
} | |
int main(int argc, char**argv){ | |
int server_fd = tcp_bind(1337); | |
int client_fd; | |
while ((client_fd = accept(server_fd, NULL, NULL)) != -1){ | |
fprintf(stderr, "client_fd=%d\n", client_fd); | |
FILE* stream = fdopen(client_fd, "r+"); | |
if (!stream){ | |
perror("fdopen"); | |
} | |
scgi_read_headers(stream); | |
fclose(stream); | |
} | |
perror("accept"); | |
return EXIT_FAILURE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment