|
21 | 21 | #include "config.h"
|
22 | 22 |
|
23 | 23 | #include "output/udpcli.h"
|
| 24 | +#include "core/object/dns.h" |
24 | 25 | #include "core/object/udp.h"
|
| 26 | +#include "core/object/tcp.h" |
25 | 27 |
|
26 | 28 | #include <sys/types.h>
|
27 | 29 | #include <sys/socket.h>
|
|
30 | 32 | #include <fcntl.h>
|
31 | 33 | #include <string.h>
|
32 | 34 | #include <netinet/in.h>
|
| 35 | +#include <errno.h> |
33 | 36 |
|
34 | 37 | static core_log_t _log = LOG_T_INIT("output.udpcli");
|
35 | 38 | static output_udpcli_t _defaults = {
|
@@ -110,23 +113,61 @@ int output_udpcli_destroy(output_udpcli_t* self)
|
110 | 113 |
|
111 | 114 | static int _receive(void* ctx, const core_object_t* obj)
|
112 | 115 | {
|
113 |
| - output_udpcli_t* self = (output_udpcli_t*)ctx; |
114 |
| - core_object_udp_t* udp = (core_object_udp_t*)obj; |
| 116 | + output_udpcli_t* self = (output_udpcli_t*)ctx; |
| 117 | + const uint8_t* payload; |
| 118 | + size_t len, sent; |
115 | 119 |
|
116 |
| - if (!self || !obj || obj->obj_type != CORE_OBJECT_UDP) { |
| 120 | + if (!self) { |
117 | 121 | return 1;
|
118 | 122 | }
|
119 | 123 |
|
120 |
| - if (udp->len < 3 || udp->payload[2] & 0x80) { |
121 |
| - return 0; |
122 |
| - } |
123 |
| - |
124 |
| - self->pkts++; |
125 |
| - if (sendto(self->fd, udp->payload, udp->len, 0, (struct sockaddr*)self->addr, self->addr_len) < 0) { |
126 |
| - self->errs++; |
| 124 | + for (; obj;) { |
| 125 | + switch (obj->obj_type) { |
| 126 | + case CORE_OBJECT_DNS: |
| 127 | + obj = obj->obj_prev; |
| 128 | + continue; |
| 129 | + case CORE_OBJECT_UDP: |
| 130 | + payload = ((core_object_udp_t*)obj)->payload; |
| 131 | + len = ((core_object_udp_t*)obj)->len; |
| 132 | + break; |
| 133 | + case CORE_OBJECT_TCP: |
| 134 | + payload = ((core_object_tcp_t*)obj)->payload; |
| 135 | + len = ((core_object_tcp_t*)obj)->len; |
| 136 | + break; |
| 137 | + default: |
| 138 | + return 1; |
| 139 | + } |
| 140 | + |
| 141 | + if (len < 3 || payload[2] & 0x80) { |
| 142 | + return 0; |
| 143 | + } |
| 144 | + |
| 145 | + sent = 0; |
| 146 | + self->pkts++; |
| 147 | + for (;;) { |
| 148 | + ssize_t ret = sendto(self->fd, payload + sent, len - sent, 0, (struct sockaddr*)self->addr, self->addr_len); |
| 149 | + if (ret > -1) { |
| 150 | + sent += ret; |
| 151 | + if (sent < len) |
| 152 | + continue; |
| 153 | + return 0; |
| 154 | + } |
| 155 | + switch (errno) { |
| 156 | + case EAGAIN: |
| 157 | +#if EAGAIN != EWOULDBLOCK |
| 158 | + case EWOULDBLOCK: |
| 159 | +#endif |
| 160 | + continue; |
| 161 | + default: |
| 162 | + break; |
| 163 | + } |
| 164 | + self->errs++; |
| 165 | + break; |
| 166 | + } |
| 167 | + break; |
127 | 168 | }
|
128 | 169 |
|
129 |
| - return 0; |
| 170 | + return 1; |
130 | 171 | }
|
131 | 172 |
|
132 | 173 | core_receiver_t output_udpcli_receiver()
|
|
0 commit comments