summaryrefslogtreecommitdiffstats
path: root/api/c/api.c
diff options
context:
space:
mode:
Diffstat (limited to 'api/c/api.c')
-rw-r--r--api/c/api.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/api/c/api.c b/api/c/api.c
new file mode 100644
index 0000000..e452617
--- /dev/null
+++ b/api/c/api.c
@@ -0,0 +1,244 @@
+/*
+ * threaded.c -- A simple multi-threaded FastCGI application.
+ */
+
+#ifndef lint
+// static const char rcsid[] = "$Id: threaded.c,v 1.9 2001/11/20 03:23:21 robs Exp $"; // just popps up warnings
+#endif /* not lint */
+
+#include "fcgi_config.h"
+
+#include <pthread.h>
+#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "fcgiapp.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "urlcode.c"
+#include <limits.h>
+#include <stdio.h>
+#define MALLOC_RETURNED_NULL fprintf(stderr, "%s()@" __FILE__ ":%d: malloc() returned NULL\n", __func__, __LINE__);
+
+
+#define THREAD_COUNT 20
+
+static int counts[THREAD_COUNT];
+
+struct assoc_s {
+ char * key;
+ char * value;
+}; // value je lahko NULL
+
+void free_assoc_s(struct assoc_s * s) {
+ if (s->key != NULL) {
+ free(s->key);
+ s->key = NULL;
+ }
+ if (s->value != NULL) {
+ free(s->value);
+ s->value = NULL;
+ }
+ free(s);
+ s = NULL;
+ return;
+}
+
+struct request_uri_s {
+ char * path;
+ struct assoc_s ** params; // to je "array". zadnji naj bo NULL.
+};
+
+void free_request_uri_s(struct request_uri_s * s) {
+ int unsigned i = 0;
+ while (s->params[i] != NULL) {
+ free_assoc_s(s->params[i]);
+ s->params[i++] = NULL;
+ }
+ free(s->path);
+ s->path = NULL;
+ free(s->params);
+ s->params = NULL;
+ free(s);
+ s = NULL;
+ return;
+}
+
+struct assoc_s ** parse_html_keyvalue(const char * t) {
+ struct assoc_s ** params = malloc(sizeof(void *));
+ if (params == NULL) {
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ unsigned int o = 0; // številka parametra od 0 vključno z 0
+ unsigned int n = 0; // 0 če smo v key, 1 če smo v value, 3 če je konec urija
+ unsigned int a = 0; // nakazuje pozicijo naslednjega znaka, ki ga bomo napisa.
+ params[0] = malloc(sizeof(struct assoc_s));
+ if (params[0] == NULL) {
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ for (unsigned int e = 0; n != 3 && e <= UINT_MAX; e++) {
+ switch (t[e]) {
+ case '\0':
+ params = realloc(params, sizeof(struct assoc_s)*(o+1));
+ if (params == NULL) {
+ MALLOC_RETURNED_NULL
+ return NULL;
+ } // zadnji mora biti null
+ params[o+1] = NULL;
+ n = 3;
+ break;
+ case '=':
+ if (n == 0) { // ni treba mallocat, realloca se pred vsakim writom bajta
+ n = 1;
+ a = 0;
+ } else { // this is some undocumented behaviour, adding = to param value
+ params[o]->value = realloc(params[o]->value, a+1);
+ if (params[o]->value == NULL) {
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ params[o]->value[a++] = '=';
+ }
+ break;
+ case '&': // tu je treba mallocat, ker assoc_s še ne obstaja za naslednji
+ n = 0;
+ a = 0;
+ o++;
+ params = realloc(params, sizeof(struct assoc_s)*(o+1));
+ if (params == NULL) {
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ params[o] = malloc(sizeof(struct assoc_s)); // value kasneje
+ if (params[o] == NULL) {
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ break;
+ default:
+ if (n == 0) {
+ params[o]->key = realloc(params[o]->key, a+1);
+ if (params[o]->key == NULL) {
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ params[o]->key[a++] = t[e];
+ } else {
+ params[o]->value = realloc(params[o]->value, a+1);
+ if (params[o]->value == NULL) {
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ params[o]->value[a++] = t[e];
+ }
+ break;
+ }
+ }
+ return params;
+}
+
+struct request_uri_s * parse_request_uri(char * uri) { // returns NULL on fail!
+ struct request_uri_s * parsed = malloc(sizeof(struct request_uri_s));
+ if (parsed == NULL) { // and returns pointer to ONE request_uri_s on success^
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ char * t = strchr(uri, '?'); // remember to free /\ !
+ if (t != NULL)
+ t[0] = '\0'; // uri vedno vseeno pride ven nespremenjen/popravljen
+ parsed->path = malloc(sizeof(char)*strlen(uri)+1); //znak po path je itak NULL
+ if (parsed->path == NULL) { // malloc returna NULL, fucking panic!
+ if (t != NULL) // popravimo še \0 nazaj na ?
+ t[0] = '?';
+ MALLOC_RETURNED_NULL
+ return NULL;
+ }
+ strncpy(parsed->path, uri, strlen(uri)+1); // torej zadnji znak patha bo NULL
+ parsed->params = NULL; // če slučajno ni query_stringa in kmalu returnamo
+ if (t == NULL) // ni query stringa zato je path parse dovoljšen
+ return parsed; // parsed.params je NULL, to pred uporabo PREVERIMO!
+ t[0] = '?'; // ker smo prej zaradi strlen in strncpy dali na NULL, sedaj spre.
+ t++; // da ne začnemo z vprašajem ampak z prvim znakom
+ parsed->params = parse_html_keyvalue(t);
+ return parsed;
+}
+
+static void *doit(void *a) {
+ intptr_t rc, i, thread_id = (intptr_t)a;
+ pid_t pid = getpid();
+ FCGX_Request request;
+ char *server_name;
+ char * uri_to_parse;
+ struct request_uri_s * parseduri;
+
+ FCGX_InitRequest(&request, 0, 0);
+
+ for (;;) {
+ static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_mutex_t counts_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+ /* Some platforms require accept() serialization, some don't.. */
+ pthread_mutex_lock(&accept_mutex);
+ rc = FCGX_Accept_r(&request);
+ pthread_mutex_unlock(&accept_mutex);
+
+ if (rc < 0)
+ break;
+
+ server_name = FCGX_GetParam("SERVER_NAME", request.envp);
+ uri_to_parse = FCGX_GetParam("REQUEST_URI", request.envp);
+ parseduri = parse_request_uri(uri_to_parse);
+ if (strchr(parseduri->path, 'S') != NULL) {
+ exit(0);
+ }
+ if (parseduri == NULL) {
+ FCGX_FPrintF(request.out, "Status: 500 Zaledna napaka\r\n"
+ "Content-Type: text/plain; charset=utf-8\r\n\r\n"
+ "zgodila se je napaka na strežniku med procesiranjem URIja.\r\n");
+ free_request_uri_s(parseduri);
+ goto doit_finish;
+ }
+ FCGX_FPrintF(request.out,
+ "Status: 200 V redu\r\n"
+ "Content-type: text/html; charset=utf-8\r\n"
+ "\r\n"
+ "<title>FastCGI Pozdravljen svet! (večnitenje v C, knjižnica fcgiapp)</title>"
+ "<h1>FastCGI Pozdravljen svet! (večnitenje v C, knjižnica fcgiapp)</h1>"
+ "Nit %d, Proces %ld<p>"
+ "Števci zahtev za %d niti na strežniku <i>%s</i><p><code>",
+ thread_id, pid,
+ THREAD_COUNT, server_name ? server_name : "?");
+ free_request_uri_s(parseduri);
+ pthread_mutex_lock(&counts_mutex);
+ ++counts[thread_id];
+ for (i = 0; i < THREAD_COUNT; i++)
+ FCGX_FPrintF(request.out, "%5d " , counts[i]);
+ pthread_mutex_unlock(&counts_mutex);
+
+doit_finish:
+ FCGX_Finish_r(&request);
+ }
+
+ return NULL;
+}
+
+int main(void) {
+ intptr_t i;
+ pthread_t id[THREAD_COUNT];
+
+ FCGX_Init();
+
+ for (i = 1; i < THREAD_COUNT; i++)
+ pthread_create(&id[i], NULL, doit, (void*)i);
+
+ doit(0); // trenutno nit uporabimo tudi kot handler, zakaj pa ne (:
+
+ return 0;
+}