File: gatling.h

package info (click to toggle)
gatling 0.13-6
  • links: PTS
  • area: main
  • in suites: sid, stretch
  • size: 1,196 kB
  • ctags: 1,115
  • sloc: ansic: 23,805; makefile: 143; sh: 71; perl: 30
file content (444 lines) | stat: -rw-r--r-- 11,744 bytes parent folder | download
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
#ifndef _GATLING_H
#define _GATLING_H

#define _FILE_OFFSET_BITS 64

#include "gatling_features.h"
#include "iob.h"
#include "array.h"
#include "buffer.h"
#include "uint16.h"
#include "uint32.h"
#include "uint64.h"

#include <sys/stat.h>
#include <regex.h>
#include <sys/un.h>

#include <time.h>

#ifdef STATE_DEBUG
#include <stdio.h>
#endif

#ifdef SUPPORT_FTP
enum ftpstate {
  GREETING,
  WAITINGFORUSER,
  LOGGEDIN,
  WAITCONNECT,
  DOWNLOADING,
  UPLOADING,
};

extern int askforpassword;
#endif

#ifdef SUPPORT_PROXY
enum proxyprotocol {
  HTTP,
  FASTCGI,
  SCGI,
};
#endif

enum encoding {
  NORMAL=0,
  GZIP=1,
#ifdef SUPPORT_BZIP2
  BZIP2=2,
#endif
};

enum conntype {
  UNUSED,

  HTTPSERVER6,	/* call socket_accept6() */
  HTTPSERVER4,	/* call socket_accept4() */
  HTTPREQUEST,	/* read and handle http request */

#ifdef SUPPORT_FTP
  FTPSERVER6,	/* call socket_accept6() */
  FTPSERVER4,	/* call socket_accept4() */
  FTPCONTROL6,	/* read and handle ftp commands */
  FTPCONTROL4,	/* read and handle ftp commands */
  FTPPASSIVE,	/* accept a slave connection */
  FTPACTIVE,	/* still need to connect slave connection */
  FTPSLAVE,	/* send/receive files */
#endif

#ifdef SUPPORT_SMB
  SMBSERVER6,	/* call socket_accept6() */
  SMBSERVER4,	/* call socket_accept4() */
  SMBREQUEST,	/* read and handle SMB request */
#endif

#ifdef SUPPORT_PROXY
  PROXYSLAVE,	/* write-to-proxy connection. */
		/* write HTTP header; switch type to PROXYPOST */
  PROXYPOST,	/* while still_to_copy>0: write POST data; relay answer */
  HTTPPOST,	/* type of HTTP request with POST data
		   read post data and write them to proxy (ctx->buddy) */
#endif

#ifdef SUPPORT_HTTPS
  HTTPSSERVER4,	/* call socket_accept6() */
  HTTPSSERVER6,	/* call socket_accept4() */
  HTTPSACCEPT,	/* call SSL_accept() */
  HTTPSACCEPT_CHECK,	/* check whether input looks like SSL, then call SSL_accept() */
  HTTPSREQUEST,	/* read and handle https request */
  HTTPSRESPONSE,	/* write response to https request */
  HTTPSPOST,	/* like HTTPPOST but using SSL */
#endif

  PUNISHMENT,	/* if we detected a DoS and tarpit someone */

  LAST_UNUNSED
};

#ifdef SUPPORT_HTTPS

#ifdef USE_MBEDTLS
#undef USE_OPENSSL
#else
#define USE_OPENSSL
#endif

#ifdef USE_OPENSSL
/* in ssl.c */
#include <openssl/ssl.h>
#include <openssl/err.h>
extern int init_serverside_tls(SSL** ssl,int sock);
#endif

#ifdef USE_MBEDTLS
/* in pssl.c */
#include <mbedtls/ssl.h>
#include <mbedtls/net.h>
extern int init_serverside_tls(mbedtls_ssl_context* ssl, int sock);
#endif

#endif

/* the tree id is always 1 (we export exactly one tree in TreeConnectAndX)
 * the user id is always 1, too (we hand it out in SessionSetupAndX)
 * we need to hand out file handles relative the the PID though */
struct handle {
  uint32_t pid,handle;
  int fd;
  off_t size,cur;
  unsigned short* filename;
};

struct handles {
  size_t u,a;	/* used, allocated */
  struct handle* h;
};

struct http_data {
  enum conntype t;
#ifdef SUPPORT_FTP
  enum ftpstate f;
#endif
  array r;
  io_batch iob;
  char myip[16];	/* this is needed for virtual hosting */
  uint32 myscope_id;	/* in the absence of a Host header */
  uint16 myport,peerport;
  uint16 destport;	/* port on remote system, used for active FTP */
  char* hdrbuf,* bodybuf;
  const char *mimetype;
  int hlen,blen;	/* hlen == length of hdrbuf, blen == length of bodybuf */
  int keepalive;	/* 1 if we want the TCP connection to stay connected */
			/* this is always 1 for FTP except after the client said QUIT */
  int filefd;		/* -1 or the descriptor of the file we are sending out */
  int buddy;		/* descriptor for the other connection, used for FTP and proxy/CGI */
  char peerip[16];	/* needed for active FTP */
  unsigned long long received,sent;
  enum encoding encoding;
#if defined(SUPPORT_FTP) || defined(SUPPORT_SMB)
  char* ftppath;	/* for FTP we store the path here, for SMB the last FIRST_FIRST2 glob expression */
#endif
#ifdef SUPPORT_FTP
  uint64 ftp_rest;	/* offset to start transfer at */
#endif
  uint64 sent_until,prefetched_until;
#ifdef SUPPORT_PROXY
  enum proxyprotocol proxyproto;
  unsigned long long still_to_copy;	/* for POST/PUT requests */
  int havefirst;	/* first read contains cgi header */
  char* oldheader;	/* old, unmodified request */
#endif
#ifdef SUPPORT_HTTPS
#ifdef USE_MBEDTLS
  mbedtls_ssl_context ssl;
#endif
#ifdef USE_OPENSSL
  SSL* ssl;
#endif
#if 0
  int writefail;
#endif
#endif
#ifdef SUPPORT_SMB
  struct handles h;
#endif
#ifdef SUPPORT_THREADED_OPEN
  int try_encoding;
  int cwd;
  char* name_of_file_to_open;
  struct stat ss;
#endif
#ifdef STATE_DEBUG
  int myfd;
#endif
};

#ifdef STATE_DEBUG
extern const char* state2string(enum conntype t);
#endif

static inline void changestate(struct http_data* x,enum conntype t) {
#ifdef STATE_DEBUG
  if (x->t==UNUSED)
    printf("STATE: new fd %d: state %s\n",x->myfd,state2string(t));
  else
    printf("STATE: fd %d: state change from %s to %s\n",x->myfd,state2string(x->t),state2string(t));
#endif
  x->t=t;
}

#ifdef SUPPORT_HTTPS
extern char* sshd;
#endif

extern size_t max_handles;

extern struct handle* alloc_handle(struct handles* h);
extern struct handle* deref_handle(struct handles* h,uint32_t handle);
extern void close_handle(struct handle* h);
extern void close_all_handles(struct handles* h);

extern int virtual_hosts;
extern int transproxy;
extern int directory_index;
extern int logging;
extern int nouploads;
extern int chmoduploads;
extern const char months[];
#ifdef __MINGW32__
extern char origdir[PATH_MAX];
#else
extern int64 origdir;
#endif

typedef struct de {
  long name;	/* offset within b */
  struct stat ss;
  int todir;
} de;
extern char* base;

extern int sort_name_a(de* x,de* y);
extern int sort_name_d(de* x,de* y);
extern int sort_mtime_a(de* x,de* y);
extern int sort_mtime_d(de* x,de* y);
extern int sort_size_a(de* x,de* y);
extern int sort_size_d(de* x,de* y);

extern unsigned long connections;
extern unsigned long http_connections, https_connections, ftp_connections, smb_connections;
extern unsigned long cps,cps1;	/* connections per second */
extern unsigned long rps,rps1;	/* requests per second */
extern unsigned long eps,eps1;	/* events per second */
extern unsigned long long tin,tin1;	/* traffic inbound */
extern unsigned long long tout,tout1;	/* traffic outbound */

extern int open_for_reading(int64* fd,const char* name,struct stat* SS);
extern unsigned int fmt_2digits(char* dest,int i);
extern int canonpath(char* s);
extern int open_for_writing(int64* fd,const char* name);

#ifdef SUPPORT_FTP
extern void ftpresponse(struct http_data* h,int64 s);
extern void handle_read_ftppassive(int64 i,struct http_data* H);
extern void handle_write_ftpactive(int64 i,struct http_data* h);
#endif

#if defined(SUPPORT_PROXY) || defined(SUPPORT_CGI)
/* You configure a list of regular expressions, and if a request matches
 * one of them, the request is forwarded to some other IP:port.  You can
 * run another httpd there that can handle CGI, PHP, JSP and whatnot. */
struct cgi_proxy {
  regex_t r;
  int file_executable;
  char ip[16];
  uint32 port,scope_id;
  struct sockaddr_un uds;
  struct cgi_proxy* next;
#ifdef SUPPORT_PROXY
  enum proxyprotocol proxyproto;
#endif
};
extern struct cgi_proxy* last,* cgis;
extern char** _envp;
#endif

#ifdef SUPPORT_CGI
extern int forksock[2];
#endif

extern void httpresponse(struct http_data* h,int64 s,long headerlen);
extern char* http_header(struct http_data* r,char* h);

extern int ip_vhost(struct http_data* h);

#ifdef SUPPORT_FALLBACK_REDIR
extern const char* redir;
#endif

extern tai6464 now,next;
extern unsigned long timeout_secs;
extern const char* mimetypesfilename;
extern const char* mimetype(const char* filename,int fd);

extern int add_proxy(const char* c);
extern void handle_read_proxypost(int64 i,struct http_data* H);
extern void handle_read_httppost(int64 i,struct http_data* H);
extern void handle_write_proxypost(int64 i,struct http_data* h);
extern void handle_write_httppost(int64 i,struct http_data* h);
extern void handle_write_proxyslave(int64 i,struct http_data* h);

extern void cleanup(int64 sock);
extern size_t header_complete(struct http_data* r,int64 sock);

extern void httperror_realm(struct http_data* r,const char* title,const char* message,const char* realm,int nobody);
extern void httperror(struct http_data* r,const char* title,const char* message,int nobody);

extern int buffer_putlogstr(buffer* b,const char* s);

extern char fsbuf[8192];
extern void forkslave(int fd,buffer* in,int savedir);

#ifdef USE_ZLIB
#include <zlib.h>
#endif

#ifdef SUPPORT_SMB
extern int smbresponse(struct http_data* h,int64 s);

extern char workgroup[20];
extern int wglen;
extern char workgroup_utf16[100];
extern int wglen16;
#endif

extern int64 origdir;

#include "version.h"
#define RELEASE "Gatling/" VERSION

extern unsigned int max_requests_per_minute;

/* call this function when a request comes in, with the peer's IP
 * address as argument */
int new_request_from_ip(const char ip[16],time_t now);
/* returns 0 if the request was added and should be serviced.
 * returns 1 if a denial of service attack from this IP was detected and
 *           the request should not be serviced
 * returns -1 if we ran out of memory trying to add the request */

#ifdef SUPPORT_HTTPS
extern int64 https_write_callback(int64 sock,const void* buf,uint64 n);
extern int handle_ssl_error_code(int sock,int code,int reading);
#endif

extern char* magicelfvalue;
extern char serverroot[];
extern char* defaultindex;

#ifdef DEBUG_EVENTS
#include "fmt.h"

static void new_io_wantwrite(int64 s,const char* file,unsigned int line) {
  char a[FMT_ULONG];
  char b[FMT_ULONG];
  char c[100];
#ifdef STATE_DEBUG
  struct http_data* h=io_getcookie(s);
  if (h)
    c[fmt_strm(c," [state ",state2string(h->t),"]")]=0;
  else
    strcpy(c," [cookie is NULL]");
#else
  c[0]=0;
#endif
  a[fmt_ulong(a,s)]=0;
  b[fmt_ulong(b,line)]=0;
  buffer_putmflush(buffer_2,"DEBUG: ",file,":",b,": io_wantwrite(",a,")",c,"\n");
  io_wantwrite(s);
}

static void new_io_dontwantwrite(int64 s,const char* file,unsigned int line) {
  char a[FMT_ULONG];
  char b[FMT_ULONG];
  char c[100];
#ifdef STATE_DEBUG
  struct http_data* h=io_getcookie(s);
  if (h)
    c[fmt_strm(c," [state ",state2string(h->t),"]")]=0;
  else
    strcpy(c," [cookie is NULL]");
#else
  c[0]=0;
#endif
  a[fmt_ulong(a,s)]=0;
  b[fmt_ulong(b,line)]=0;
  buffer_putmflush(buffer_2,"DEBUG: ",file,":",b,": io_dontwantwrite(",a,")",c,"\n");
  io_dontwantwrite(s);
}

static void new_io_wantread(int64 s,const char* file,unsigned int line) {
  char a[FMT_ULONG];
  char b[FMT_ULONG];
  char c[100];
#ifdef STATE_DEBUG
  struct http_data* h=io_getcookie(s);
  if (h)
    c[fmt_strm(c," [state ",state2string(h->t),"]")]=0;
  else
    strcpy(c," [cookie is NULL]");
#else
  c[0]=0;
#endif
  a[fmt_ulong(a,s)]=0;
  b[fmt_ulong(b,line)]=0;
  buffer_putmflush(buffer_2,"DEBUG: ",file,":",b,": io_wantread(",a,")",c,"\n");
  io_wantread(s);
}

static void new_io_dontwantread(int64 s,const char* file,unsigned int line) {
  char a[FMT_ULONG];
  char b[FMT_ULONG];
  struct http_data* h=io_getcookie(s);
  char c[100];
  c[0]=0;
#ifdef STATE_DEBUG
  if (h)
    c[fmt_strm(c," [state ",state2string(h->t),"]")]=0;
  else
    strcpy(c," [cookie is NULL]");
#endif
  a[fmt_ulong(a,s)]=0;
  b[fmt_ulong(b,line)]=0;
  buffer_putmflush(buffer_2,"DEBUG: ",file,":",b,": io_dontwantread(",a,")",c,"\n");
  io_dontwantread(s);
}

#define io_wantwrite(s) new_io_wantwrite(s,__FILE__,__LINE__)
#define io_wantread(s) new_io_wantread(s,__FILE__,__LINE__)
#define io_dontwantwrite(s) new_io_dontwantwrite(s,__FILE__,__LINE__)
#define io_dontwantread(s) new_io_dontwantread(s,__FILE__,__LINE__)
#endif

#endif