-
Notifications
You must be signed in to change notification settings - Fork 438
/
TcpServer.h
251 lines (202 loc) · 9.12 KB
/
TcpServer.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
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
// Copyright Matt Wells Nov 2000
// . TODO: don't keep alloc'ing TcpSockets, re-use "empty" TcpSockets from
// an array of them (grow array if needed) (do same for UdpServer)
// . used as client AND server
// . used to do non-blocking sends/receives of messages using TCP/IP
// . re-uses sockets (keep alive) in server AND client directions
// . uses custom dns client (Dns.h) for non-blocking domain name lookups
// . a callback can be specified for each TcpSocket
// . a pointer to custom callback data can also be specified for each socket
// . that callback is called on connect/read/write/dnsLookup TIMEOUT or ERROR
// . callback is also called on reception of REPLY
// . receptions of REQUESTS are received thru TcpSocket*TcpServer::read(int sd)
// . if a msg being received is too big we make call(s) to putMsgPiece() to
// empty the receive buffer when it gets full (m_maxReadBufSize)
#ifndef _TCPSERVER_H_
#define _TCPSERVER_H_
#include <sys/time.h> // time()
#include <sys/types.h> // setsockopt()
#include <sys/socket.h> // setsockopt()
#include <netinet/tcp.h> // TCP_CORK and SOL_TCP (linux only!)
#include <openssl/ssl.h> // for ssl stuff
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "Mem.h" // for mem routines
#include "MsgC.h" // for udp-only, non-blocking dns lookups
#include "TcpSocket.h"
#include "Loop.h" // g_loop.registerRead/WriteCallback()
// raised from 5k to 15k in case we are a spider compression proxy
#define MAX_TCP_SOCKS 15000
extern bool g_isYippy;
class TcpServer {
friend class HttpServer;
public:
// free all TcpSockets and their bufs
void reset();
// . constructor
TcpServer() { m_port = -1; m_sock = -1; m_useSSL = false; m_ctx = NULL; };
// . creates a tcp socket which listens on port "port"
// . will close unused sockets to ensure we stay under "maxSockets"
// . receiving msgs bigger then "16k" will result in a call to
// TcpSocket::putMsgPiece(), if not NULL
// . we call "requestHandler" when an incoming request arrives
// . IMPORTANT: requestHandler MUST call sendMsg(s,...) eventually
// . getMsgSize is called to get the total size of an incoming msg
// . it returns -1 if it doesn't yet know
bool init ( void (* requestHandler)(TcpSocket *s) ,
int32_t (* getMsgSize )(char *msg , int32_t msgBytesRead,
TcpSocket *s ),
int32_t (* getMsgPiece )(TcpSocket *s ),
int16_t port ,
int32_t *maxSocketsPtr = NULL , //MAX_TCP_SOCS def
bool useSSL = false );
//int32_t maxReadBufSize = 128*1024 ,
//int32_t maxSendBufSize = 128*1024 );
bool testBind ( uint16_t port , bool printMsg ) ;
// . returns false if blocked, true otherwise
// . sets errno on error
// . uses g_dns to find the ip then calls sendRequest() below
// . callback is called on completion of TRANSACTION
// . that is, when both m_sendBuf and m_readBuf have been filled
// . callback is also called on error
// . default timeout of 60 secs of no read OR no write
bool sendMsg ( char *hostname ,
int32_t hostnameLen ,
int16_t port ,
char *sendBuf ,
int32_t sendBufSize ,
int32_t sendBufUsed ,
int32_t msgTotalSize ,
void *state ,
void (* callback )( void *state, TcpSocket *s ) ,
int32_t timeout , // 60*1000
int32_t maxTextDocLen , // -1 for no max
int32_t maxOtherDocLen );
bool sendMsg ( char *url ,
char *sendBuf ,
int32_t sendBufSize ,
int32_t sendBufUsed ,
int32_t msgTotalSize ,
void *state ,
void (* callback )( void *state, TcpSocket *s ) ,
int32_t timeout , // 60*1000
int32_t maxTextDocLen , // -1 for no max
int32_t maxOtherDocLen );
bool sendChunk ( class TcpSocket *s ,
class SafeBuf *sb ,
void *state ,
// call this function when done sending this chunk
// so that it can read another chunk and call
// sendChunk() again.
void (* doneSendingWrapper)(void *state,TcpSocket *));
// . returns false if blocked, true otherwise
// . sets errno on error
// . use this for sending a msg to another host
// . if a reply is expected then you should specify the "done" callback
// which will be called on complete reception of the reply
// . after completion/done this will call reseTcpSocket()
// . upon successful transmission of "msg" we shift socket into readMode
// . default timeout of 60 secs of no read OR no write
bool sendMsg ( int32_t ip ,
int16_t port ,
char *sendBuf ,
int32_t sendBufSize ,
int32_t sendBufUsed ,
int32_t msgTotalSize ,
void *state ,
void (* callback )( void *state , TcpSocket *s ) ,
int32_t timeout , // 60*1000
int32_t maxTextDocLen , // -1 for no max
int32_t maxOtherDocLen ,
bool useHttpTunnel = false );
// . send request over an available (pre-connected) TcpSocket
// . destroys the socket on error
// . calls callback on completion of transaction
// . default timeout of 60 secs of no read OR no write
bool sendMsg ( TcpSocket *s ,
char *sendBuf ,
int32_t sendBufSize ,
int32_t sendBufUsed ,
int32_t msgTotalSize ,
void *state ,
void (* callback )( void *state , TcpSocket *s ),
int32_t timeout = 60*1000 ,
int32_t maxTextDocLen = -1 , // -1 for no max
int32_t maxOtherDocLen = -1 );
// . the following public funcs are public so C wrappers can call them
// . you should not call them
// . we use this as a callback called by DnsServer
// . gotta keep this public cuz getIpWrapper() calls it
// . returns true if didn't block when sending msg (using sendRequest)
bool gotTcpServerIp ( class TcpState *tst , int32_t ip );
// get a TcpSocket from a socket descriptor
TcpSocket *getSocket ( int sd ) ;
int32_t readSocket ( TcpSocket *s );
int32_t writeSocket ( TcpSocket *s );
void readTimeoutPoll ( ) ;
TcpSocket *acceptSocket ( ) ;
bool sslAccept ( class TcpSocket *s ) ;
// keep public so PageResults can call if had error getting query results
void destroySocket ( TcpSocket *s ) ;
// calls s->m_callback ( s->m_state , s )
void makeCallback ( TcpSocket * s ) ;
void recycleSocket ( TcpSocket *s ) ;
// only wrappers should call this
int32_t connectSocket ( TcpSocket *s ) ;
// set from init() to handle incoming requests
void (* m_requestHandler)(TcpSocket *s) ;
// cancel the transaction that had this state
void cancel ( void *state );
// void (*callback)(void *state, TcpSocket *s) ) ;
// private:
TcpSocket *getAvailableSocket ( int32_t ip, int16_t port ) ;
TcpSocket *getNewSocket ( ) ;
TcpSocket *wrapSocket ( int sd , int32_t niceness, bool incoming);
bool closeLeastUsed ( int32_t maxIdleTime = -1 ) ;
bool setTotalToRead ( TcpSocket *s ) ;
int sslHandshake ( TcpSocket *s ) ;
// . we call this to try to figure out the size of the WHOLE msg
// being read so that we might pre-allocate memory for it
// . overridden for different protocols
// . this is called upon reception of every packet
// of the msg being read until a non-negative msg size is returned.
// this is used to avoid doing excessive reallocs and extract the
// reply size from things like "Content-Length: xxx" so we can do
// one alloc() and forget about having to do more...
// . up to 128 bytes of the reply can be stored in a static buffer
// contained in TcpSocket, until we need to alloc...
// virtual int32_t getMsgSize ( char *buf , int32_t bufSize ) ;
int m_sock ; // for listening for connections
int16_t m_port ; // for listening for connections
// handlers set in the init() routine
// ptrs to our TcpSockets 1-1 w/ real sockets
TcpSocket *m_tcpSockets [ MAX_TCP_SOCKS ];
int32_t m_lastFilled;
int32_t m_numUsed;
// # used for incoming connections
int32_t m_numIncomingUsed;
// let's have them all pre-allocated, it's only ~1.1MB...
TcpSocket m_actualSockets [ MAX_TCP_SOCKS ];
// . how many socket descriptors can we use simultaneously?
// . just applies to incoming sockets
int32_t m_dummy;
int32_t *m_maxSocketsPtr;
bool m_doReadRateTimeouts;
//MsgC m_msgc;
// . we don't wanna use too much memory reading/sending a big msg
// so we have a limit on our buffer sizes (set with set())
//int32_t m_maxReadBufSize;
//int32_t m_maxSendBufSize;
// these callbacks should be set in init()
int32_t (* m_getMsgSize )(char *msg , int32_t msgBytesRead, TcpSocket *s);
int32_t (* m_getMsgPiece )(TcpSocket *s );
// flag to specify SSL or not
bool m_useSSL;
// SSL members
SSL_CTX *m_ctx;
// ready to go or not
bool m_ready;
int32_t m_numOpen;
int32_t m_numClosed;
};
#endif