Coverage Report

Created: 2026-01-10 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensips/net/net_tcp_report.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2017 OpenSIPS Solutions
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips 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
 * opensips 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
#include "../dprint.h"
22
#include "../ipc.h"
23
#include "trans.h"
24
#include "net_tcp.h"
25
#include "net_tcp_report.h"
26
27
/* is the process TCP MAIN ? */
28
extern int is_tcp_main;
29
30
typedef struct _tcp_report_job {
31
  /* TCP connection ID */
32
  unsigned long long conn_id;
33
  /* TCP connection flags */
34
  unsigned long long conn_flags;
35
  /* reporting type */
36
  int type;
37
  /* the protocol ID */
38
  int proto;
39
  /* extra data */
40
  void *extra;
41
} tcp_report_job;
42
43
44
static void tcp_report_ipc_handler(int sender, void *param)
45
0
{
46
0
  tcp_report_job *job = (tcp_report_job*)param;
47
48
  /* run the report callback  */
49
0
  protos[job->proto].net.report( job->type, job->conn_id, job->conn_flags,
50
0
    job->extra);
51
  /* and free the job memory */
52
0
  shm_free(job);
53
0
}
54
55
56
/* Pushes a TCP event as a repot to the PROTO layer. Depending on the type of
57
 * of the reported event, the function will construct and push forward a
58
 * per-type string holding the description of the reported event - the TCP
59
 * connection itself does not propgate further to the proto layer.
60
 * As the TCP MAIN process has a special status when comes to what it is able
61
 * to do (handling, communication,etc) and to avoid any problems within the
62
 * PROTO layer (when handling the report), the function will take care NOT to
63
 * run the "report" handler in the TCP MAIN - it will push the execution to
64
 * a TCP WORKER process via IPC.
65
 * Parameters:
66
 *   - conn - the tcp connection; be carefull what you do with it as there is
67
 *            0 guarantee on what happens with the conn after the triggering;
68
 *            it may be destoied, so do not keep references to it;
69
 *   - type - the reported event, CLOSE, STATS, others
70
 *   - extra - data specific to the event; to be sure you do not end-up with
71
 *            any dangling pointers, either use static/global data, either
72
 *            malloced/freeed when passing it here.
73
 */
74
void tcp_trigger_report(struct tcp_connection *conn, int type, void *extra)
75
0
{
76
0
  tcp_report_job *job;
77
78
  /* any reporting function registered by the PROTO layer ? */
79
0
  if (protos[conn->type].net.report==NULL)
80
0
    return;
81
82
  /* convert the extra data, from what we get from the TRANSport layer
83
   * to what we pass to the reporting callback ;
84
   * Basically aggregate info from "conn" and "extra" to generate a more
85
   * complex "extra" to be passed further */
86
0
  if (type == TCP_REPORT_CLOSE) {
87
    /* the extra is the "reason" string for having the TCP connection
88
     * closed; it is a static string, so no handling/conversion is
89
     * needed for it */
90
0
  } else {
91
0
    LM_ERR("not understanding report type %d, discarding\n", type);
92
0
    return;
93
0
  }
94
95
  /* now, trigger the "report" callback from the PROTO layer */
96
0
  if (is_tcp_main) {
97
98
    /* we are in TCP MAIN, use IPC to push the report */
99
100
    /* build and send the job */
101
0
    job = shm_malloc(sizeof(tcp_report_job));
102
0
    if (job==NULL) {
103
0
      LM_ERR("failed to allocated SHM mem, discarding report\n");
104
0
      return;
105
0
    }
106
0
    job->type = type;
107
0
    job->conn_id = conn->cid;
108
0
    job->conn_flags = conn->flags;
109
0
    job->proto = conn->type;
110
0
    job->extra = extra;
111
    /* ...sending it any worker via RPC dispatching */
112
0
    if (ipc_dispatch_rpc( tcp_report_ipc_handler, job)<0) {
113
0
      LM_ERR("failed to send IPC job, discarding report\n");
114
0
      shm_free(job);
115
0
      return;
116
0
    }
117
    /* done here */
118
119
0
  } else {
120
121
    /* do the reporting inline */
122
123
    /* run the report callback  */
124
0
    protos[conn->type].net.report( type, conn->cid, conn->flags, extra);
125
126
0
  }
127
128
0
  return;
129
0
}
130