public
Description: New and ultra-turbo-crazy-fast backend for Thin
Homepage: http://code.macournoyer.com/thin/
Clone URL: git://github.com/macournoyer/thin-turbo.git
macournoyer (author)
Wed Apr 30 20:53:03 -0700 2008
commit  edab8a1dbcfcd9c70ab912423a69a5f5767dece6
tree    6da3857a454eeb9d7e6463d51d9c6e3234196609
parent  c1e069fc34f4a5964770375db8b938f4126aa435
thin-turbo / ext / thin_backend / thin.h
100644 143 lines (113 sloc) 3.579 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#ifndef _THIN_H_
#define _THIN_H_
 
#include <ruby.h>
#include <ev.h>
 
/* TODO ifdef some of this? */
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
 
#include "ext_help.h"
#include "buffer.h"
#include "palloc.h"
#include "parser.h"
#include "queue.h"
#include "status.h"
 
#ifdef __FreeBSD__
#define LISTEN_BACKLOG -1 /* FreeBSD set to max when negative */
#else
#define LISTEN_BACKLOG 511 /* that's what most web server use, ie: Apache & Nginx */
#endif
 
/* initialize number of connections in the pool, will grow */
#define CONNECTIONS_SIZE 100
 
/* when write buffer reach this size, it is sent right away, it controls the speed
 * at which a response is streamed. */
#define STREAM_SIZE 1024
 
#define MAX_HEADER 1024 * (80 + 32)
#define RACK_VERSION INT2FIX(3), INT2FIX(0)
 
 
#define HEADER_SEP ": "
#define RESP_HTTP_VERSION "HTTP/1.1 "
#define CRLF "\x0d\x0a"
 
typedef struct backend_s backend_t;
typedef struct connection_s connection_t;
 
struct connection_s {
  /* socket */
  int fd;
  char *remote_addr;
  
  /* request */
  buffer_t read_buffer;
  http_parser parser;
  VALUE env;
  VALUE input;
  size_t content_length;
  
  /* response */
  buffer_t write_buffer;
  unsigned finished : 1;
  
  /* backend */
  backend_t *backend;
  
  /* libev */
  struct ev_loop *loop;
  ev_io read_watcher;
  ev_io write_watcher;
  ev_timer timeout_watcher;
};
 
struct backend_s {
  /* socket */
  char *address;
  unsigned port;
  int fd;
  unsigned open;
  struct sockaddr_in local_addr;
  
  /* ruby */
  VALUE obj; /* Ruby Backend object */
  VALUE app; /* Rack app */
  
  /* connections */
  queue_t connections;
  size_t thread_count;
  
  /* libev */
  ev_tstamp timeout;
  struct ev_loop *loop;
  ev_io accept_watcher;
  ev_idle idle_watcher;
  ev_prepare prepare_watcher;
};
 
/* libev helpers */
#define get_ev_data(type, w, event) \
  (type##_t *) w->data; \
  assert(&((type##_t *)w->data)->event##_watcher == w);
 
/* log helpers */
#define log_error(b, msg) \
  rb_funcall(b->obj, rb_intern("log_error"), 4, \
             rb_str_new2(msg), rb_str_new2(__FILE__), \
             rb_str_new2(__FUNCTION__), INT2FIX(__LINE__))
 
#define log_errno(b) log_error(b, strerror(errno))
 
extern VALUE cStringIO;
extern VALUE sInternedCall;
extern VALUE sInternedKeys;
extern VALUE sRackInput;
 
/* backend */
void backend_define(void);
 
/* connection */
void connection_start(backend_t *backend, int fd, struct sockaddr_in remote_addr);
void connection_error(connection_t *c, const char *msg);
void connection_errno(connection_t *c);
void connection_close(connection_t *connection);
 
void request_parse(connection_t *connection, char *buf, int len);
VALUE response_process(connection_t *connection);
 
/* connections */
void connections_init(backend_t *backend);
void connections_push(backend_t *backend);
void connections_free(backend_t *backend);
 
/* parser */
void parser_callbacks_define();
void parser_callbacks_setup(connection_t *connection);
 
#endif /* _THIN_H_ */