Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/tcp_conn.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2001-2003 FhG Fokus
3
 *
4
 * This file is part of Kamailio, a free SIP server.
5
 *
6
 * Kamailio is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version
10
 *
11
 * Kamailio is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 *
20
 */
21
22
#ifndef _tcp_conn_h
23
#define _tcp_conn_h
24
25
#include <sys/time.h>
26
27
#include "tcp_init.h"
28
#include "tcp_options.h"
29
30
#include "ip_addr.h"
31
#include "locking.h"
32
#include "atomic_ops.h"
33
#include "timer_ticks.h"
34
#include "timer.h"
35
36
/* maximum number of port aliases x search wildcard possibilities */
37
#define TCP_CON_MAX_ALIASES (4 * 3)
38
39
#define TCP_CHILD_TIMEOUT \
40
  5                /* after 5 seconds, the child "returns"
41
               * the connection to the tcp maing process */
42
0
#define TCP_MAIN_SELECT_TIMEOUT 5  /* how often "tcp main" checks for timeout*/
43
0
#define TCP_CHILD_SELECT_TIMEOUT 2 /* the same as above but for children */
44
45
#define TCPCONN_MATCH_DEFAULT 0
46
0
#define TCPCONN_MATCH_STRICT 1
47
48
/* tcp connection flags */
49
0
#define F_CONN_READ_W 2      /* watched for READ ev. in main */
50
0
#define F_CONN_WRITE_W 4    /* watched for WRITE (main) */
51
0
#define F_CONN_READER 8      /* handled by a tcp reader */
52
0
#define F_CONN_HASHED 16    /* in tcp_main hash */
53
0
#define F_CONN_FD_CLOSED 32    /* fd was already closed */
54
0
#define F_CONN_PENDING 64    /* pending connect  (fd not known yet in main) */
55
0
#define F_CONN_MAIN_TIMER 128 /* timer active in the tcp_main process */
56
0
#define F_CONN_EOF_SEEN 256    /* FIN or RST have been received */
57
0
#define F_CONN_FORCE_EOF 512  /* act as if an EOF was received */
58
0
#define F_CONN_OOB_DATA 1024  /* out of band data on the connection */
59
0
#define F_CONN_WR_ERROR 2048  /* write error on the fd */
60
0
#define F_CONN_WANTS_RD 4096  /* conn. should be watched for READ */
61
0
#define F_CONN_WANTS_WR 8192  /* conn. should be watched for WRITE */
62
0
#define F_CONN_PASSIVE 16384  /* conn. created via accept() and not connect()*/
63
#define F_CONN_CLOSE_EV 32768 /* explicitely call tcpops ev route when closed */
64
0
#define F_CONN_NOSEND 65536    /* do not send data on this connection */
65
66
#ifndef NO_READ_HTTP11
67
#define READ_HTTP11
68
#endif
69
70
#ifndef NO_READ_MSRP
71
#define READ_MSRP
72
#endif
73
74
#ifndef NO_READ_WS
75
#define READ_WS
76
#endif
77
78
typedef enum tcp_req_errors
79
{
80
  TCP_REQ_INIT,
81
  TCP_REQ_OK,
82
  TCP_READ_ERROR,
83
  TCP_REQ_OVERRUN,
84
  TCP_REQ_BAD_LEN
85
} tcp_req_errors_t;
86
typedef enum tcp_req_states
87
{
88
  H_SKIP_EMPTY,
89
  H_SKIP_EMPTY_CR_FOUND,
90
  H_SKIP_EMPTY_CRLF_FOUND,
91
  H_SKIP_EMPTY_CRLFCR_FOUND,
92
  H_SKIP,
93
  H_LF,
94
  H_LFCR,
95
  H_BODY,
96
  H_STARTWS,
97
  H_CONT_LEN1,
98
  H_CONT_LEN2,
99
  H_CONT_LEN3,
100
  H_CONT_LEN4,
101
  H_CONT_LEN5,
102
  H_CONT_LEN6,
103
  H_CONT_LEN7,
104
  H_CONT_LEN8,
105
  H_CONT_LEN9,
106
  H_CONT_LEN10,
107
  H_CONT_LEN11,
108
  H_CONT_LEN12,
109
  H_CONT_LEN13,
110
  H_L_COLON,
111
  H_CONT_LEN_BODY,
112
  H_CONT_LEN_BODY_PARSE,
113
  H_STUN_MSG,
114
  H_STUN_READ_BODY,
115
  H_STUN_FP,
116
  H_STUN_END,
117
  H_PING_CRLF
118
#ifdef READ_HTTP11
119
  ,
120
  H_HTTP11_CHUNK_START,
121
  H_HTTP11_CHUNK_SIZE,
122
  H_HTTP11_CHUNK_BODY,
123
  H_HTTP11_CHUNK_END,
124
  H_HTTP11_CHUNK_FINISH
125
#endif
126
#ifdef READ_MSRP
127
  ,
128
  H_MSRP_BODY,
129
  H_MSRP_BODY_LF,
130
  H_MSRP_BODY_END,
131
  H_MSRP_FINISH
132
#endif
133
} tcp_req_states_t;
134
135
typedef enum tcp_conn_states
136
{
137
  S_CONN_ERROR = -2,
138
  S_CONN_BAD = -1,
139
  S_CONN_OK = 0, /* established (write or read) */
140
  S_CONN_INIT,   /* initial state (invalid) */
141
  S_CONN_EOF,
142
  S_CONN_ACCEPT,
143
  S_CONN_CONNECT
144
} tcp_conn_states_t;
145
146
147
/* fd communication commands */
148
typedef enum conn_cmds
149
{
150
  CONN_DESTROY = -3 /* destroy connection & auto-dec. refcnt */,
151
  CONN_ERROR = -2 /* error on connection & auto-dec. refcnt */,
152
  CONN_EOF = -1 /* eof received or conn. closed & auto-dec refcnt */,
153
  CONN_NOP = 0 /* do-nothing (invalid for tcp_main) */,
154
  CONN_RELEASE /* release a connection from tcp_read back into tcp_main
155
           * & auto-dec refcnt */
156
  ,
157
  CONN_GET_FD /* request a fd from tcp_main */,
158
  CONN_NEW /* update/set a fd int a new tcp connection; refcnts are
159
           * not touched */
160
  ,
161
  CONN_QUEUED_WRITE /* new write queue: start watching the fd for write &
162
            * auto-dec refcnt */
163
  ,
164
  CONN_NEW_PENDING_WRITE /* like CONN_NEW+CONN_QUEUED_WRITE: set fd and
165
              * start watching it for write (write queue
166
              * non-empty); refcnts are not touced */
167
  ,
168
  CONN_NEW_COMPLETE /* like CONN_NEW_PENDING_WRITE, but there is no
169
            * pending write (the write queue might be empty) */
170
} conn_cmds_t;
171
/* CONN_RELEASE, EOF, ERROR, DESTROY can be used by "reader" processes
172
 * CONN_GET_FD, CONN_NEW*, CONN_QUEUED_WRITE only by writers */
173
174
/* tcp_req flags */
175
typedef enum tcp_req_flags
176
{
177
  F_TCP_REQ_HAS_CLEN = (1 << 0),
178
  F_TCP_REQ_COMPLETE = (1 << 1),
179
#ifdef READ_HTTP11
180
  F_TCP_REQ_BCHUNKED = (1 << 2),
181
#endif
182
#ifdef READ_MSRP
183
  F_TCP_REQ_MSRP_NO = (1 << 3),
184
  F_TCP_REQ_MSRP_FRAME = (1 << 4),
185
  F_TCP_REQ_MSRP_BODY = (1 << 5),
186
#endif
187
  F_TCP_REQ_HEP3 = (1 << 6),
188
} tcp_req_flags_t;
189
190
0
#define TCP_REQ_HAS_CLEN(tr) ((tr)->flags & F_TCP_REQ_HAS_CLEN)
191
#define TCP_REQ_COMPLETE(tr) ((tr)->flags & F_TCP_REQ_COMPLETE)
192
#ifdef READ_HTTP11
193
0
#define TCP_REQ_BCHUNKED(tr) ((tr)->flags & F_TCP_REQ_BCHUNKED)
194
#endif
195
196
0
#define KSR_TCP_REQSTATE_DATARECV (1 << 0)
197
198
typedef struct tcp_req
199
{
200
  struct tcp_req *next;
201
  /* sockaddr ? */
202
  char *buf;    /* bytes read so far (+0-terminator)*/
203
  char *start;  /* where the message starts, after all the empty lines are
204
          skipped*/
205
  char *pos;    /* current position in buf */
206
  char *parsed; /* last parsed position */
207
  char *body;   /* body position */
208
  unsigned int b_size; /* buffer size-1 (extra space for 0-term)*/
209
  int content_len;
210
#ifdef READ_HTTP11
211
  int chunk_size;
212
#endif
213
  enum tcp_req_flags flags; /* F_TCP_REQ_HAS_CLEN | F_TCP_REQ_COMPLETE */
214
  int bytes_to_go; /* how many bytes we have still to read from the body*/
215
  enum tcp_req_errors error;
216
  enum tcp_req_states state;
217
  unsigned int dxstate;
218
  struct timeval tvrstart;
219
} tcp_req_t;
220
221
struct tcp_connection;
222
223
/* tcp port alias structure */
224
typedef struct tcp_conn_alias
225
{
226
  struct tcp_connection *parent;
227
  struct tcp_conn_alias *next;
228
  struct tcp_conn_alias *prev;
229
  unsigned short port; /* alias port */
230
  unsigned short hash; /* hash index in the address hash */
231
} tcp_conn_alias_t;
232
233
234
#ifdef TCP_ASYNC
235
typedef struct tcp_wbuffer
236
{
237
  struct tcp_wbuffer *next;
238
  unsigned int b_size;
239
  char buf[1];
240
} tcp_wbuffer_t;
241
242
typedef struct tcp_wbuffer_queue
243
{
244
  struct tcp_wbuffer *first;
245
  struct tcp_wbuffer *last;
246
  ticks_t wr_timeout;   /* write timeout*/
247
  unsigned int queued;  /* total size */
248
  unsigned int offset;  /* offset in the first wbuffer were data
249
                starts */
250
  unsigned int last_used; /* how much of the last buffer is used */
251
} tcp_wbuffer_queue_t;
252
#endif
253
254
255
enum tcp_closed_reason
256
{
257
  TCP_CLOSED_EOF = 0,
258
  TCP_CLOSED_TIMEOUT,
259
  TCP_CLOSED_RESET,
260
261
  _TCP_CLOSED_REASON_MAX /* /!\ keep this one always at the end */
262
};
263
264
265
typedef struct tcp_connection
266
{
267
  int s;  /*socket, used by "tcp main" */
268
  int fd; /* used only by "children", don't modify it! private data! */
269
  gen_lock_t write_lock;
270
  int id; /* id (unique!) used to retrieve a specific connection when
271
       * reply-ing */
272
  enum tcp_closed_reason event; /* connection close reason */
273
  int reader_pid;         /* pid of the active reader process */
274
  struct receive_info rcv;    /* src & dst ip, ports, proto a.s.o*/
275
  ksr_coninfo_t cinfo;      /* connection info (e.g., for haproxy ) */
276
  struct tcp_req req;       /* request data */
277
  atomic_t refcnt;
278
  enum sip_protos type;   /* PROTO_TCP or a protocol over it, e.g. TLS */
279
  unsigned int flags;     /* connection related flags */
280
  snd_flags_t send_flags;   /* special send flags */
281
  enum tcp_conn_states state; /* connection state */
282
  enum tcp_conn_states initstate; /* initial connection state */
283
  void *extra_data; /* extra data associated to the connection, 0 for tcp*/
284
  struct timer_ln timer;
285
  time_t timestamp; /* connection creation timestamp */
286
  ticks_t timeout;  /* connection timeout, after this it will be removed*/
287
  ticks_t lifetime; /* connection lifetime */
288
  unsigned id_hash; /* hash index in the id_hash */
289
  struct tcp_connection *id_next; /* next, prev in id hash table */
290
  struct tcp_connection *id_prev;
291
  struct tcp_connection *c_next; /* child next prev (use locally) */
292
  struct tcp_connection *c_prev;
293
  struct tcp_conn_alias con_aliases[TCP_CON_MAX_ALIASES];
294
  int aliases; /* aliases number, at least 1 */
295
#ifdef TCP_ASYNC
296
  struct tcp_wbuffer_queue wbuf_q;
297
#endif
298
} tcp_connection_t;
299
300
301
/* helper macros */
302
303
#define tcpconn_set_send_flags(c, snd_flags) \
304
0
  SND_FLAGS_OR(&(c)->send_flags, &(c)->send_flags, &(snd_flags))
305
306
#define tcpconn_close_after_send(c) ((c)->send_flags.f & SND_F_CON_CLOSE)
307
308
#define TCP_RCV_INFO(c) (&(c)->rcv)
309
310
#define TCP_RCV_LADDR(r) (&((r).dst_ip))
311
#define TCP_RCV_LPORT(r) ((r).dst_port)
312
#define TCP_RCV_PADDR(r) (&((r).src_ip))
313
#define TCP_RCV_PPORT(r) ((r).src_port)
314
#define TCP_RCV_PSU(r) (&(r).src_su)
315
#define TCP_RCV_SOCK_INFO(r) ((r).bind_address)
316
#define TCP_RCV_PROTO(r) ((r).proto)
317
#ifdef USE_COMP
318
#define TCP_RCV_COMP(r) ((r).comp)
319
#else
320
#define TCP_RCV_COMP(r) 0
321
#endif /* USE_COMP */
322
323
#define TCP_LADDR(c) TCP_RCV_LADDR(c->rcv)
324
#define TCP_LPORT(c) TCP_RCV_LPORT(c->rcv)
325
#define TCP_PADDR(c) TCP_RCV_PADDR(c->rcv)
326
#define TCP_PPORT(c) TCP_RCV_PPORT(c->rcv)
327
#define TCP_PSU(c) TCP_RCV_PSU(c->rcv)
328
#define TCP_SOCK_INFO(c) TCP_RCV_SOCK_INFO(c->rcv)
329
#define TCP_PROTO(c) TCP_RCV_PROTO(c->rcv)
330
#define TCP_COMP(c) TCP_RCV_COMP(c->rcv)
331
332
333
0
#define tcpconn_ref(c) atomic_inc(&((c)->refcnt))
334
0
#define tcpconn_put(c) atomic_dec_and_test(&((c)->refcnt))
335
336
337
#define init_tcp_req(r, rd_buf, rd_buf_size)                   \
338
0
  do {                                                       \
339
0
    memset((r), 0, sizeof(struct tcp_req));                \
340
0
    (r)->buf = (rd_buf);                                   \
341
0
    (r)->b_size = (rd_buf_size)-1; /* space for 0 term. */ \
342
0
    (r)->parsed = (r)->pos = (r)->start = (r)->buf;        \
343
0
    (r)->error = TCP_REQ_OK;                               \
344
0
    (r)->state = H_SKIP_EMPTY;                             \
345
0
  } while(0)
346
347
348
/* add a tcpconn to a list*/
349
/* list head, new element, next member, prev member */
350
#define tcpconn_listadd(head, c, next, prev)     \
351
0
  do {                                         \
352
0
    /* add it at the beginning of the list*/ \
353
0
    (c)->next = (head);                      \
354
0
    (c)->prev = 0;                           \
355
0
    if((head))                               \
356
0
      (head)->prev = (c);                  \
357
0
    (head) = (c);                            \
358
0
  } while(0)
359
360
361
/* remove a tcpconn from a list*/
362
#define tcpconn_listrm(head, c, next, prev) \
363
0
  do {                                    \
364
0
    if((head) == (c))                   \
365
0
      (head) = (c)->next;             \
366
0
    if((c)->next)                       \
367
0
      (c)->next->prev = (c)->prev;    \
368
0
    if((c)->prev)                       \
369
0
      (c)->prev->next = (c)->next;    \
370
0
  } while(0)
371
372
373
0
#define TCPCONN_LOCK lock_get(tcpconn_lock);
374
0
#define TCPCONN_UNLOCK lock_release(tcpconn_lock);
375
376
0
#define TCP_ALIAS_HASH_SIZE 4096
377
0
#define TCP_ID_HASH_SIZE 1024
378
379
/* hash (dst_ip, dst_port, local_ip, local_port) */
380
static inline unsigned tcp_addr_hash(struct ip_addr *ip, unsigned short port,
381
    struct ip_addr *l_ip, unsigned short l_port)
382
0
{
383
0
  unsigned h;
384
385
0
  if(ip->len == 4)
386
0
    h = (ip->u.addr32[0] ^ port) ^ (l_ip->u.addr32[0] ^ l_port);
387
0
  else if(ip->len == 16)
388
0
    h = (ip->u.addr32[0] ^ ip->u.addr32[1] ^ ip->u.addr32[2]
389
0
          ^ ip->u.addr32[3] ^ port)
390
0
      ^ (l_ip->u.addr32[0] ^ l_ip->u.addr32[1] ^ l_ip->u.addr32[2]
391
0
          ^ l_ip->u.addr32[3] ^ l_port);
392
0
  else {
393
0
    LM_CRIT("bad len %d for an ip address\n", ip->len);
394
0
    return 0;
395
0
  }
396
  /* make sure the first bits are influenced by all 32
397
   * (the first log2(TCP_ALIAS_HASH_SIZE) bits should be a mix of all
398
   *  32)*/
399
0
  h ^= h >> 17;
400
0
  h ^= h >> 7;
401
0
  return h & (TCP_ALIAS_HASH_SIZE - 1);
402
0
}
Unexecuted instantiation: receive.c:tcp_addr_hash
Unexecuted instantiation: route.c:tcp_addr_hash
Unexecuted instantiation: select_core.c:tcp_addr_hash
Unexecuted instantiation: tcp_main.c:tcp_addr_hash
Unexecuted instantiation: tcp_read.c:tcp_addr_hash
Unexecuted instantiation: tls_hooks.c:tcp_addr_hash
Unexecuted instantiation: action.c:tcp_addr_hash
Unexecuted instantiation: core_cmd.c:tcp_addr_hash
Unexecuted instantiation: forward.c:tcp_addr_hash
Unexecuted instantiation: kemi.c:tcp_addr_hash
Unexecuted instantiation: local_timer.c:tcp_addr_hash
Unexecuted instantiation: msg_translator.c:tcp_addr_hash
403
404
0
#define tcp_id_hash(id) (id & (TCP_ID_HASH_SIZE - 1))
405
406
struct tcp_connection *tcpconn_get(int id, struct ip_addr *ip, int port,
407
    union sockaddr_union *local_addr, ticks_t timeout);
408
409
struct tcp_connection *tcpconn_lookup(int id, struct ip_addr *ip, int port,
410
    union sockaddr_union *local_addr, int try_local_port, ticks_t timeout);
411
412
typedef struct tcp_event_info
413
{
414
  int type;
415
  char *buf;
416
  unsigned int len;
417
  struct receive_info *rcv;
418
  struct tcp_connection *con;
419
} tcp_event_info_t;
420
421
typedef struct tcp_closed_event_info
422
{
423
  enum tcp_closed_reason reason;
424
  struct tcp_connection *con;
425
} tcp_closed_event_info_t;
426
427
typedef struct ws_event_info
428
{
429
  int type;
430
  char *buf;
431
  unsigned int len;
432
  int id;
433
} ws_event_info_t;
434
435
#endif