forked from darkk/redsocks
-
Notifications
You must be signed in to change notification settings - Fork 0
/
redsocks.h
164 lines (140 loc) · 6.13 KB
/
redsocks.h
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
#ifndef REDSOCKS_H_WED_JAN_24_22_17_11_2007
#define REDSOCKS_H_WED_JAN_24_22_17_11_2007
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <assert.h>
#include <event.h>
#include "list.h"
#include "parser.h"
struct redsocks_client_t;
struct redsocks_instance_t;
typedef struct relay_subsys_t {
char *name;
size_t payload_len; // size of relay-specific data in client section
size_t instance_payload_len; // size of relay-specify data in instance section
evbuffercb readcb;
evbuffercb writecb;
void (*init)(struct redsocks_client_t *client);
void (*fini)(struct redsocks_client_t *client);
void (*instance_init)(struct redsocks_instance_t *instance);
void (*instance_fini)(struct redsocks_instance_t *instance);
// connect_relay (if any) is called instead of redsocks_connect_relay after client connection acceptance
void (*connect_relay)(struct redsocks_client_t *client);
} relay_subsys;
typedef struct redsocks_config_t {
struct sockaddr_in bindaddr;
struct sockaddr_in relayaddr;
char *type;
char *login;
char *password;
bool parse_sni_host;
bool parse_http_host;
uint16_t listenq;
bool use_splice;
enum disclose_src_e disclose_src;
enum on_proxy_fail_e on_proxy_fail;
} redsocks_config;
typedef struct redsocks_instance_t {
list_head list;
redsocks_config config;
struct event listener;
list_head clients;
relay_subsys *relay_ss;
} redsocks_instance;
typedef unsigned short evshut_t; // EV_READ | EV_WRITE
typedef struct redsocks_client_t {
list_head list;
redsocks_instance *instance;
struct bufferevent *client;
struct bufferevent *relay;
struct sockaddr_in clientaddr;
struct sockaddr_in destaddr;
char *hostname;
int state; // it's used by bottom layer
evshut_t client_evshut;
evshut_t relay_evshut;
struct timeval first_event;
struct timeval last_event;
} redsocks_client;
typedef struct splice_pipe_t {
int read;
int write;
size_t size;
} splice_pipe;
typedef struct redsocks_pump_t {
/* Quick-n-dirty test show, that some Linux 4.4.0 build uses ~1.5 kb of
* slab_unreclaimable RAM per every pipe pair. Most of connections are
* usually idle and it's possble to save some measurable amount of RAM
* using shared pipe pool. */
redsocks_client c;
splice_pipe request;
splice_pipe reply;
struct event client_read;
struct event client_write;
struct event relay_read;
struct event relay_write;
} redsocks_pump;
static inline size_t sizeof_client(redsocks_instance *i)
{
return ((i->config.use_splice) ? sizeof(redsocks_pump) : sizeof(redsocks_client)) + i->relay_ss->payload_len;
}
static inline void* red_payload(redsocks_client *c)
{
return (c->instance->config.use_splice) ? (void*)(((redsocks_pump*)c) + 1) : (void*)(c + 1);
}
static inline redsocks_pump* red_pump(redsocks_client *c)
{
assert(c->instance->config.use_splice);
return (redsocks_pump*)c;
}
void redsocks_shutdown(redsocks_client *client, struct bufferevent *buffev, int how);
void redsocks_drop_client(redsocks_client *client);
void redsocks_touch_client(redsocks_client *client);
void redsocks_connect_relay(redsocks_client *client);
void redsocks_start_relay(redsocks_client *client);
bool redsocks_has_splice_instance();
typedef int (*size_comparator)(size_t a, size_t b);
int sizes_equal(size_t a, size_t b);
int sizes_greater_equal(size_t a, size_t b);
/** helper for functions when we expect ONLY reply of some size and anything else is error
*/
int redsocks_read_expected(redsocks_client *client, struct evbuffer *input, void *data, size_comparator comparator, size_t expected);
typedef struct evbuffer* (*redsocks_message_maker)(redsocks_client *client);
typedef struct evbuffer* (*redsocks_message_maker_plain)(void *p);
struct evbuffer *mkevbuffer(void *data, size_t len);
/* Yahoo! This code is ex-plain! :-D */
int redsocks_write_helper_ex_plain(
struct bufferevent *buffev, redsocks_client *client,
redsocks_message_maker_plain mkmessage, void *p, int state, size_t wm_low, size_t wm_high);
int redsocks_write_helper_ex(
struct bufferevent *buffev, redsocks_client *client,
redsocks_message_maker mkmessage, int state, size_t wm_low, size_t wm_high);
int redsocks_write_helper(
struct bufferevent *buffev, redsocks_client *client,
redsocks_message_maker mkmessage, int state, size_t wm_only);
#define redsocks_close(fd) redsocks_close_internal((fd), __FILE__, __LINE__, __func__)
void redsocks_close_internal(int fd, const char* file, int line, const char *func);
#define redsocks_event_add(client, ev) redsocks_event_add_internal((client), (ev), __FILE__, __LINE__, __func__)
void redsocks_event_add_internal(redsocks_client *client, struct event *ev, const char *file, int line, const char *func);
#define redsocks_event_del(client, ev) redsocks_event_del_internal((client), (ev), __FILE__, __LINE__, __func__)
void redsocks_event_del_internal(redsocks_client *client, struct event *ev, const char *file, int line, const char *func);
#define redsocks_bufferevent_dropfd(client, ev) redsocks_bufferevent_dropfd_internal((client), (ev), __FILE__, __LINE__, __func__)
void redsocks_bufferevent_dropfd_internal(redsocks_client *client, struct bufferevent *ev, const char *file, int line, const char *func);
// I have to account descriptiors for accept-backoff, that's why BEV_OPT_CLOSE_ON_FREE is not used.
void redsocks_bufferevent_free(struct bufferevent *buffev);
#define redsocks_log_error(client, prio, msg...) \
redsocks_log_write_plain(__FILE__, __LINE__, __func__, 0, &(client)->clientaddr, &(client)->destaddr, prio, ## msg)
#define redsocks_log_errno(client, prio, msg...) \
redsocks_log_write_plain(__FILE__, __LINE__, __func__, 1, &(client)->clientaddr, &(client)->destaddr, prio, ## msg)
void redsocks_log_write_plain(
const char *file, int line, const char *func, int do_errno,
const struct sockaddr_in *clientaddr, const struct sockaddr_in *destaddr,
int priority, const char *fmt, ...)
#if defined(__GNUC__)
__attribute__ (( format (printf, 8, 9) ))
#endif
;
/* vim:set tabstop=4 softtabstop=4 shiftwidth=4: */
/* vim:set foldmethod=marker foldlevel=32 foldmarker={,}: */
#endif /* REDSOCKS_H_WED_JAN_24_22_17_11_2007 */