aboutsummaryrefslogtreecommitdiff
path: root/src/cadet
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2015-01-09 18:04:40 +0000
committerBart Polot <bart@net.in.tum.de>2015-01-09 18:04:40 +0000
commit98c41d7079e10e0b0e46599d5db01fabba2212b7 (patch)
tree6c469746dd815ddf65572e96368cab943e0dc19e /src/cadet
parentb82ec529ff7bac309665c605ba0c83f15f670941 (diff)
downloadgnunet-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.c90
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 */
786static uint32_t
787get_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 */
800static int
801is_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)