| 153 | } |
| 154 | |
| 155 | int send_stream_proxy_protocol_v1(struct tcp_connection *c, int fd, |
| 156 | int write_timeout, int lock, const struct receive_info *ri, |
| 157 | const char *proto_name) |
| 158 | { |
| 159 | char pp_hdr[PROXY_PROTOCOL_BUF_MAX]; |
| 160 | int pp_len, rc, dbg_len; |
| 161 | const char *action; |
| 162 | |
| 163 | if (!should_send_stream_proxy_protocol(c)) |
| 164 | return 0; |
| 165 | |
| 166 | if (fd < 0 && ((c->flags & F_CONN_INIT) == 0 || c->fd < 0)) |
| 167 | return 0; |
| 168 | |
| 169 | pp_len = build_outbound_proxy_protocol_v1_hdr(ri, |
| 170 | &c->rcv.dst_ip, c->rcv.dst_port, |
| 171 | &c->rcv.src_ip, c->rcv.src_port, |
| 172 | pp_hdr, sizeof(pp_hdr)); |
| 173 | if (pp_len < 0) { |
| 174 | LM_ERR("failed to build outbound PROXY header\n"); |
| 175 | return -1; |
| 176 | } |
| 177 | |
| 178 | dbg_len = pp_len; |
| 179 | if (dbg_len >= 2 && pp_hdr[dbg_len - 2] == '\r' && |
| 180 | pp_hdr[dbg_len - 1] == '\n') |
| 181 | dbg_len -= 2; |
| 182 | |
| 183 | action = (fd < 0) ? "queueing" : "sending"; |
| 184 | LM_DBG("%s outbound PROXY header on %s conn %u: %.*s\n", |
| 185 | action, proto_name ? proto_name : "stream", c->id, |
| 186 | dbg_len, pp_hdr); |
| 187 | |
| 188 | if (fd < 0) { |
| 189 | rc = tcp_async_add_chunk(c, pp_hdr, pp_len, lock); |
| 190 | } else { |
| 191 | if (lock) |
| 192 | lock_get(&c->write_lock); |
| 193 | rc = tsend_stream(fd, pp_hdr, pp_len, write_timeout); |
| 194 | if (lock) |
| 195 | lock_release(&c->write_lock); |
| 196 | if (rc != pp_len) { |
| 197 | LM_ERR("failed to send outbound PROXY header on %s\n", |
| 198 | proto_name ? proto_name : "stream"); |
| 199 | return -1; |
| 200 | } |
| 201 | tcp_conn_reset_lifetime(c); |
| 202 | rc = 0; |
| 203 | } |
| 204 | |
| 205 | if (rc < 0) { |
| 206 | LM_ERR("failed to send outbound PROXY header on %s\n", |
| 207 | proto_name ? proto_name : "stream"); |
| 208 | return -1; |
| 209 | } |
| 210 | |
| 211 | c->flags |= F_CONN_PROXY_OUT_SENT; |
| 212 | return 0; |
no test coverage detected