| … | … | @@ -104,22 +104,29 @@ int main(int argc, char **argv) { |
| 104 | 104 | printf("joined topic, opened %s\n", proto); |
| 105 | 105 | fflush(stdout); |
| 106 | 106 | |
| 107 | // ⛔ DO NOT SEND ON A TIMER. The first version fired once, eight seconds in, |
| 108 | // whether or not a peer existed — and a send onto a channel the remote has |
| 109 | // not opened yet is discarded by protomux. It worked on a local testnet, |
| 110 | // where the mesh forms in under a second, and would have been a coin toss on |
| 111 | // the public DHT. The daemon now answers `accepted` truthfully, so the right |
| 112 | // trigger is that answer: keep offering the frame until it is taken. |
| 107 | 113 | const time_t deadline = time(nullptr) + seconds; |
| 108 | | bool sent = false; |
| 114 | const uint64_t FIRST_SEND_ID = 4; |
| 115 | uint64_t next_send_id = FIRST_SEND_ID; |
| 116 | bool send_accepted = false; |
| 117 | time_t last_attempt = 0; |
| 109 | 118 | std::vector<uint8_t> in; |
| 110 | 119 | while (time(nullptr) < deadline) { |
| 111 | | if (send_text && !sent && time(nullptr) > deadline - seconds + 8) { |
| 120 | if (send_text && !send_accepted && time(nullptr) != last_attempt) { |
| 121 | last_attempt = time(nullptr); |
| 112 | 122 | swarmd_send_request_t sr; |
| 113 | 123 | memset(&sr, 0, sizeof(sr)); |
| 114 | 124 | sr.channel = 1; sr.slot = 0; sr.target = 0; |
| 115 | 125 | sr.bytes = (uint8_t *)send_text; |
| 116 | 126 | sr.bytes_len = strlen(send_text); |
| 117 | | if (swarmd_encode_send(4, &sr, &buf, &len) >= 0) { |
| 127 | if (swarmd_encode_send(next_send_id++, &sr, &buf, &len) >= 0) { |
| 118 | 128 | send_frame(fd, buf, len); |
| 119 | | printf("sent: %s\n", send_text); |
| 120 | | fflush(stdout); |
| 121 | 129 | } |
| 122 | | sent = true; |
| 123 | 130 | } |
| 124 | 131 | |
| 125 | 132 | uint8_t tmp[65536]; |
| … | … | @@ -138,12 +145,22 @@ int main(int argc, char **argv) { |
| 138 | 145 | compact_state_t st = { 0, n, in.data() + 4 }; |
| 139 | 146 | rpc_message_t msg; |
| 140 | 147 | if (rpc_decode_message(&st, &msg) >= 0) { |
| 141 | | swarmd_message_t m; |
| 142 | | hrpc_error_t err; |
| 143 | | memset(&m, 0, sizeof(m)); |
| 144 | | // An event carries no reply; decoding it as on-message tells us |
| 145 | | // whether that is what arrived. |
| 146 | | if (msg.type == rpc_request && m.bytes_len == 0) { |
| 148 | if (msg.type == rpc_response && msg.id >= FIRST_SEND_ID) { |
| 149 | // The answer to one of our send attempts. `accepted` is the |
| 150 | // daemon saying it had an open channel to put the frame on. |
| 151 | swarmd_send_result_t res; |
| 152 | memset(&res, 0, sizeof(res)); |
| 153 | compact_state_t body = { 0, msg.len, msg.data }; |
| 154 | if (swarmd_send_result_decode(&body, &res) >= 0 && res.accepted && |
| 155 | !send_accepted) { |
| 156 | send_accepted = true; |
| 157 | printf("sent (accepted after %d attempt%s): %s\n", |
| 158 | (int)(msg.id - FIRST_SEND_ID + 1), |
| 159 | msg.id == FIRST_SEND_ID ? "" : "s", send_text); |
| 160 | fflush(stdout); |
| 161 | } |
| 162 | } else if (msg.type == rpc_request) { |
| 163 | // An event: no reply, and dispatching it tells us which one. |
| 147 | 164 | swarmd_hrpc_handlers_t h; |
| 148 | 165 | memset(&h, 0, sizeof(h)); |
| 149 | 166 | static std::string got; |
| … | … | @@ -161,12 +178,19 @@ int main(int argc, char **argv) { |
| 161 | 178 | return 0; |
| 162 | 179 | } |
| 163 | 180 | } |
| 164 | | (void)err; |
| 165 | 181 | } |
| 166 | 182 | in.erase(in.begin(), in.begin() + 4 + n); |
| 167 | 183 | } |
| 168 | 184 | } |
| 169 | 185 | |
| 186 | // A pure sender has nothing to receive, so say what it actually knows. |
| 187 | if (send_text) { |
| 188 | printf(send_accepted ? "sent, never answered\n" |
| 189 | : "the daemon never accepted the frame — no channel was " |
| 190 | "open on any peer\n"); |
| 191 | close(fd); |
| 192 | return send_accepted ? 0 : 1; |
| 193 | } |
| 170 | 194 | printf("no message received\n"); |
| 171 | 195 | close(fd); |
| 172 | 196 | return 1; |