diff options
author | Bart Polot <bart@net.in.tum.de> | 2015-01-09 18:04:40 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2015-01-09 18:04:40 +0000 |
commit | 98c41d7079e10e0b0e46599d5db01fabba2212b7 (patch) | |
tree | 6c469746dd815ddf65572e96368cab943e0dc19e /src/cadet | |
parent | b82ec529ff7bac309665c605ba0c83f15f670941 (diff) | |
download | gnunet-98c41d7079e10e0b0e46599d5db01fabba2212b7.tar.gz gnunet-98c41d7079e10e0b0e46599d5db01fabba2212b7.zip |
Accept Out-of-Order connection messages
Diffstat (limited to 'src/cadet')
-rw-r--r-- | src/cadet/gnunet-service-cadet_connection.c | 90 |
1 files changed, 71 insertions, 19 deletions
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c index 7a9ae37d2..4c4e50585 100644 --- a/src/cadet/gnunet-service-cadet_connection.c +++ b/src/cadet/gnunet-service-cadet_connection.c | |||
@@ -83,6 +83,13 @@ struct CadetFlowControl | |||
83 | uint32_t last_pid_recv; | 83 | uint32_t last_pid_recv; |
84 | 84 | ||
85 | /** | 85 | /** |
86 | * Bitmap of past 32 messages received: | ||
87 | * - LSB being @c last_pid_recv. | ||
88 | * - MSB being @c last_pid_recv - 31 (mod UINTMAX). | ||
89 | */ | ||
90 | uint32_t recv_bitmap; | ||
91 | |||
92 | /** | ||
86 | * Last ACK sent to the peer (peer can't send more than this PID). | 93 | * Last ACK sent to the peer (peer can't send more than this PID). |
87 | */ | 94 | */ |
88 | uint32_t last_ack_sent; | 95 | uint32_t last_ack_sent; |
@@ -757,7 +764,7 @@ get_next_hop (const struct CadetConnection *c) | |||
757 | * Get the hop in a connection. | 764 | * Get the hop in a connection. |
758 | * | 765 | * |
759 | * @param c Connection. | 766 | * @param c Connection. |
760 | * @param fwd Next hop? | 767 | * @param fwd Next in the FWD direction? |
761 | * | 768 | * |
762 | * @return Next peer in the connection. | 769 | * @return Next peer in the connection. |
763 | */ | 770 | */ |
@@ -771,6 +778,42 @@ get_hop (struct CadetConnection *c, int fwd) | |||
771 | 778 | ||
772 | 779 | ||
773 | /** | 780 | /** |
781 | * Get a bit mask for a message received out-of-order. | ||
782 | * | ||
783 | * @param last_pid_recv Last PID we received prior to the out-of-order. | ||
784 | * @param ooo_pid PID of the out-of-order message. | ||
785 | */ | ||
786 | static uint32_t | ||
787 | get_recv_bitmask (uint32_t last_pid_recv, uint32_t ooo_pid) | ||
788 | { | ||
789 | return 1 << (last_pid_recv - ooo_pid); | ||
790 | } | ||
791 | |||
792 | |||
793 | /** | ||
794 | * Check is an out-of-order message is ok: | ||
795 | * - at most 31 messages behind. | ||
796 | * - not duplicate. | ||
797 | * | ||
798 | * @param last_pid_recv Last in-order PID received. | ||
799 | */ | ||
800 | static int | ||
801 | is_ooo_ok (uint32_t last_pid_recv, uint32_t ooo_pid, uint32_t ooo_bitmap) | ||
802 | { | ||
803 | uint32_t mask; | ||
804 | |||
805 | if (GC_is_pid_bigger (last_pid_recv - 31, ooo_pid)) | ||
806 | return GNUNET_NO; | ||
807 | |||
808 | mask = get_recv_bitmask (last_pid_recv, ooo_pid); | ||
809 | if (0 != (ooo_bitmap & mask)) | ||
810 | return GNUNET_NO; | ||
811 | |||
812 | return GNUNET_YES; | ||
813 | } | ||
814 | |||
815 | |||
816 | /** | ||
774 | * Is traffic coming from this sender 'FWD' traffic? | 817 | * Is traffic coming from this sender 'FWD' traffic? |
775 | * | 818 | * |
776 | * @param c Connection to check. | 819 | * @param c Connection to check. |
@@ -2054,6 +2097,7 @@ GCC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2054 | return GNUNET_OK; | 2097 | return GNUNET_OK; |
2055 | } | 2098 | } |
2056 | 2099 | ||
2100 | |||
2057 | /** | 2101 | /** |
2058 | * Generic handler for cadet network encrypted traffic. | 2102 | * Generic handler for cadet network encrypted traffic. |
2059 | * | 2103 | * |
@@ -2126,29 +2170,41 @@ handle_cadet_encrypted (const struct GNUNET_PeerIdentity *peer, | |||
2126 | /* Check PID */ | 2170 | /* Check PID */ |
2127 | fc = fwd ? &c->bck_fc : &c->fwd_fc; | 2171 | fc = fwd ? &c->bck_fc : &c->fwd_fc; |
2128 | pid = ntohl (msg->pid); | 2172 | pid = ntohl (msg->pid); |
2129 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u+)\n", | 2173 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u - %u)\n", |
2130 | pid, fc->last_pid_recv + 1); | 2174 | pid, fc->last_pid_recv + 1, fc->last_ack_sent); |
2131 | if (GC_is_pid_bigger (pid, fc->last_ack_sent)) | 2175 | if (GC_is_pid_bigger (pid, fc->last_ack_sent)) |
2132 | { | 2176 | { |
2133 | GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO); | 2177 | GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO); |
2134 | GNUNET_break_op (0); | 2178 | GNUNET_break_op (0); |
2135 | LOG (GNUNET_ERROR_TYPE_WARNING, | 2179 | LOG (GNUNET_ERROR_TYPE_WARNING, "Received PID %u, (prev %u), ACK %u\n", |
2136 | "Received PID %u, (prev %u), ACK %u\n", | ||
2137 | pid, fc->last_pid_recv, fc->last_ack_sent); | 2180 | pid, fc->last_pid_recv, fc->last_ack_sent); |
2138 | return GNUNET_OK; | 2181 | return GNUNET_OK; |
2139 | } | 2182 | } |
2140 | if (GNUNET_NO == GC_is_pid_bigger (pid, fc->last_pid_recv)) | 2183 | if (GC_is_pid_bigger (pid, fc->last_pid_recv)) |
2141 | { | 2184 | { |
2142 | GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO); | 2185 | unsigned int delta; |
2143 | LOG (GNUNET_ERROR_TYPE_WARNING, | 2186 | |
2144 | " PID %u not expected (%u+), dropping!\n", | 2187 | delta = pid - fc->last_pid_recv; |
2145 | pid, fc->last_pid_recv + 1); | 2188 | fc->last_pid_recv = pid; |
2146 | return GNUNET_OK; | 2189 | fc->recv_bitmap <<= delta; |
2190 | fc->recv_bitmap |= 1; | ||
2191 | LOG (GNUNET_ERROR_TYPE_WARNING, " OK bitmap %X\n", fc->recv_bitmap); | ||
2192 | } | ||
2193 | else | ||
2194 | { | ||
2195 | GNUNET_STATISTICS_update (stats, "# out of order PID", 1, GNUNET_NO); | ||
2196 | if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv, pid, fc->recv_bitmap)) | ||
2197 | { | ||
2198 | LOG (GNUNET_ERROR_TYPE_WARNING, "PID %u not expected (%u+), dropping!\n", | ||
2199 | pid, fc->last_pid_recv - 31); | ||
2200 | return GNUNET_OK; | ||
2201 | } | ||
2202 | fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv, pid); | ||
2203 | LOG (GNUNET_ERROR_TYPE_WARNING, " KO bitmap %X\n", fc->recv_bitmap); | ||
2147 | } | 2204 | } |
2148 | if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state) | 2205 | if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state) |
2149 | connection_change_state (c, CADET_CONNECTION_READY); | 2206 | connection_change_state (c, CADET_CONNECTION_READY); |
2150 | connection_reset_timeout (c, fwd); | 2207 | connection_reset_timeout (c, fwd); |
2151 | fc->last_pid_recv = pid; | ||
2152 | 2208 | ||
2153 | /* Is this message for us? */ | 2209 | /* Is this message for us? */ |
2154 | if (GCC_is_terminal (c, fwd)) | 2210 | if (GCC_is_terminal (c, fwd)) |
@@ -2161,7 +2217,6 @@ handle_cadet_encrypted (const struct GNUNET_PeerIdentity *peer, | |||
2161 | GNUNET_break (GNUNET_NO != c->destroy); | 2217 | GNUNET_break (GNUNET_NO != c->destroy); |
2162 | return GNUNET_OK; | 2218 | return GNUNET_OK; |
2163 | } | 2219 | } |
2164 | fc->last_pid_recv = pid; | ||
2165 | GCT_handle_encrypted (c->t, msg); | 2220 | GCT_handle_encrypted (c->t, msg); |
2166 | GCC_send_ack (c, fwd, GNUNET_NO); | 2221 | GCC_send_ack (c, fwd, GNUNET_NO); |
2167 | return GNUNET_OK; | 2222 | return GNUNET_OK; |
@@ -2361,13 +2416,11 @@ GCC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2361 | id = GNUNET_PEER_search (peer); | 2416 | id = GNUNET_PEER_search (peer); |
2362 | if (GCP_get_short_id (get_next_hop (c)) == id) | 2417 | if (GCP_get_short_id (get_next_hop (c)) == id) |
2363 | { | 2418 | { |
2364 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); | ||
2365 | fc = &c->fwd_fc; | 2419 | fc = &c->fwd_fc; |
2366 | fwd = GNUNET_YES; | 2420 | fwd = GNUNET_YES; |
2367 | } | 2421 | } |
2368 | else if (GCP_get_short_id (get_prev_hop (c)) == id) | 2422 | else if (GCP_get_short_id (get_prev_hop (c)) == id) |
2369 | { | 2423 | { |
2370 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); | ||
2371 | fc = &c->bck_fc; | 2424 | fc = &c->bck_fc; |
2372 | fwd = GNUNET_NO; | 2425 | fwd = GNUNET_NO; |
2373 | } | 2426 | } |
@@ -2378,8 +2431,8 @@ GCC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2378 | } | 2431 | } |
2379 | 2432 | ||
2380 | ack = ntohl (msg->ack); | 2433 | ack = ntohl (msg->ack); |
2381 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n", | 2434 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n", |
2382 | ack, fc->last_ack_recv); | 2435 | GC_f2s (fwd), ack, fc->last_ack_recv); |
2383 | if (GC_is_pid_bigger (ack, fc->last_ack_recv)) | 2436 | if (GC_is_pid_bigger (ack, fc->last_ack_recv)) |
2384 | fc->last_ack_recv = ack; | 2437 | fc->last_ack_recv = ack; |
2385 | 2438 | ||
@@ -2478,8 +2531,7 @@ GCC_send_ack (struct CadetConnection *c, int fwd, int force) | |||
2478 | { | 2531 | { |
2479 | unsigned int buffer; | 2532 | unsigned int buffer; |
2480 | 2533 | ||
2481 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2534 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMC send %s ACK on %s\n", |
2482 | "GMC send %s ACK on %s\n", | ||
2483 | GC_f2s (fwd), GCC_2s (c)); | 2535 | GC_f2s (fwd), GCC_2s (c)); |
2484 | 2536 | ||
2485 | if (NULL == c) | 2537 | if (NULL == c) |