diff options
author | Supriti Singh <supritisingh08@gmail.com> | 2014-08-22 15:07:41 +0000 |
---|---|---|
committer | Supriti Singh <supritisingh08@gmail.com> | 2014-08-22 15:07:41 +0000 |
commit | 58a5314f452ed35b7a71988efca8c9419e6ca5ba (patch) | |
tree | 7126f130dc17356b9cea6ece88c9092949e1b5e7 /src | |
parent | 68e27c68530fcdcba06b6e44ab411aad62eda0ac (diff) | |
download | gnunet-58a5314f452ed35b7a71988efca8c9419e6ca5ba.tar.gz gnunet-58a5314f452ed35b7a71988efca8c9419e6ca5ba.zip |
Adding a new message type, GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION
Diffstat (limited to 'src')
-rw-r--r-- | src/dht/gnunet-service-xdht_neighbours.c | 189 | ||||
-rw-r--r-- | src/include/gnunet_protocols.h | 7 |
2 files changed, 188 insertions, 8 deletions
diff --git a/src/dht/gnunet-service-xdht_neighbours.c b/src/dht/gnunet-service-xdht_neighbours.c index bf2324ad7..dd6dc93fc 100644 --- a/src/dht/gnunet-service-xdht_neighbours.c +++ b/src/dht/gnunet-service-xdht_neighbours.c | |||
@@ -95,6 +95,12 @@ | |||
95 | #define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) | 95 | #define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) |
96 | 96 | ||
97 | /** | 97 | /** |
98 | * In case we don't hear back from the current successor, then we can start | ||
99 | * verify successor. | ||
100 | */ | ||
101 | #define WAIT_NOTIFY_CONFIRMATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200) | ||
102 | |||
103 | /** | ||
98 | * Maximum number of trails allowed to go through a friend. | 104 | * Maximum number of trails allowed to go through a friend. |
99 | */ | 105 | */ |
100 | #define TRAILS_THROUGH_FRIEND_THRESHOLD 64 | 106 | #define TRAILS_THROUGH_FRIEND_THRESHOLD 64 |
@@ -498,6 +504,27 @@ struct PeerNotifyNewSuccessorMessage | |||
498 | */ | 504 | */ |
499 | }; | 505 | }; |
500 | 506 | ||
507 | /** | ||
508 | * P2P Notify Successor Confirmation message. | ||
509 | */ | ||
510 | struct PeerNotifyConfirmationMessage | ||
511 | { | ||
512 | /** | ||
513 | * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN | ||
514 | */ | ||
515 | struct GNUNET_MessageHeader header; | ||
516 | |||
517 | /** | ||
518 | * Unique identifier of the trail. | ||
519 | */ | ||
520 | struct GNUNET_HashCode trail_id; | ||
521 | |||
522 | /** | ||
523 | * Direction of trail. | ||
524 | */ | ||
525 | uint32_t trail_direction; | ||
526 | }; | ||
527 | |||
501 | 528 | ||
502 | /** | 529 | /** |
503 | * P2P Trail Tear Down message. | 530 | * P2P Trail Tear Down message. |
@@ -742,6 +769,12 @@ struct FingerInfo | |||
742 | struct GNUNET_PeerIdentity finger_identity; | 769 | struct GNUNET_PeerIdentity finger_identity; |
743 | 770 | ||
744 | /** | 771 | /** |
772 | * In case not 0, this amount is time to wait for notify successor message. | ||
773 | * Used ONLY for successor. NOT for any other finger. | ||
774 | */ | ||
775 | struct GNUNET_TIME_Absolute wait_notify_confirmation; | ||
776 | |||
777 | /** | ||
745 | * Is any finger stored at this finger index. | 778 | * Is any finger stored at this finger index. |
746 | */ | 779 | */ |
747 | unsigned int is_present; | 780 | unsigned int is_present; |
@@ -863,6 +896,12 @@ static struct GNUNET_TIME_Relative find_finger_trail_task_next_send_time; | |||
863 | */ | 896 | */ |
864 | static struct GNUNET_TIME_Relative verify_successor_next_send_time; | 897 | static struct GNUNET_TIME_Relative verify_successor_next_send_time; |
865 | 898 | ||
899 | /** | ||
900 | * Are we waiting for confirmation from our new successor that it got the | ||
901 | * message | ||
902 | */ | ||
903 | static unsigned int waiting_for_notify_confirmation; | ||
904 | |||
866 | /* Below variables are used only for testing, and statistics collection. */ | 905 | /* Below variables are used only for testing, and statistics collection. */ |
867 | /** | 906 | /** |
868 | * Should we store our topology predecessor and successor IDs into statistics? | 907 | * Should we store our topology predecessor and successor IDs into statistics? |
@@ -1134,6 +1173,50 @@ GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer | |||
1134 | process_friend_queue (target_friend); | 1173 | process_friend_queue (target_friend); |
1135 | } | 1174 | } |
1136 | 1175 | ||
1176 | /** | ||
1177 | * Send notify successor confirmation message. | ||
1178 | * @param trail_id Unique Identifier of the trail. | ||
1179 | * @param trail_direction Destination to Source. | ||
1180 | * @param target_friend Friend to get this message next. | ||
1181 | */ | ||
1182 | void | ||
1183 | GDS_NEIGHBOURS_send_notify_succcessor_confirmation (struct GNUNET_HashCode trail_id, | ||
1184 | unsigned int trail_direction, | ||
1185 | struct FriendInfo *target_friend) | ||
1186 | { | ||
1187 | struct PeerNotifyConfirmationMessage *ncm; | ||
1188 | struct P2PPendingMessage *pending; | ||
1189 | size_t msize; | ||
1190 | |||
1191 | msize = sizeof (struct PeerNotifyConfirmationMessage); | ||
1192 | if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) | ||
1193 | { | ||
1194 | GNUNET_break (0); | ||
1195 | return; | ||
1196 | } | ||
1197 | |||
1198 | if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) | ||
1199 | { | ||
1200 | GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), | ||
1201 | 1, GNUNET_NO); | ||
1202 | } | ||
1203 | |||
1204 | pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); | ||
1205 | pending->importance = 0; /* FIXME */ | ||
1206 | pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT); | ||
1207 | ncm = (struct PeerNotifyConfirmationMessage *) &pending[1]; | ||
1208 | pending->msg = &ncm->header; | ||
1209 | ncm->header.size = htons (msize); | ||
1210 | ncm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION); | ||
1211 | ncm->trail_id = trail_id; | ||
1212 | ncm->trail_direction = htonl (trail_direction); | ||
1213 | |||
1214 | /* Send the message to chosen friend. */ | ||
1215 | GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); | ||
1216 | target_friend->pending_count++; | ||
1217 | process_friend_queue (target_friend); | ||
1218 | } | ||
1219 | |||
1137 | 1220 | ||
1138 | /** | 1221 | /** |
1139 | * Send trail rejection message to target friend | 1222 | * Send trail rejection message to target friend |
@@ -2885,7 +2968,6 @@ send_trail_teardown (struct FingerInfo *finger, | |||
2885 | __LINE__,GNUNET_h2s(&trail->trail_id), GNUNET_i2s(&my_identity),trail->trail_length); | 2968 | __LINE__,GNUNET_h2s(&trail->trail_id), GNUNET_i2s(&my_identity),trail->trail_length); |
2886 | return; | 2969 | return; |
2887 | } | 2970 | } |
2888 | FPRINTF (stderr,_("\nSUPU %s, %s, %d, REMOVE trail id = %s"),__FILE__, __func__,__LINE__,GNUNET_h2s(&trail->trail_id)); | ||
2889 | GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id)); | 2971 | GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id)); |
2890 | friend->trails_count--; | 2972 | friend->trails_count--; |
2891 | GDS_NEIGHBOURS_send_trail_teardown (trail->trail_id, | 2973 | GDS_NEIGHBOURS_send_trail_teardown (trail->trail_id, |
@@ -3077,6 +3159,13 @@ send_verify_successor_message (void *cls, | |||
3077 | &send_verify_successor_message, | 3159 | &send_verify_successor_message, |
3078 | NULL); | 3160 | NULL); |
3079 | successor = &finger_table[0]; | 3161 | successor = &finger_table[0]; |
3162 | /* We are waiting for a confirmation from the notify message and we have not | ||
3163 | * crossed the wait time, then return. */ | ||
3164 | if ((1 == waiting_for_notify_confirmation) | ||
3165 | && (0 != GNUNET_TIME_absolute_get_remaining(successor->wait_notify_confirmation).rel_value_us)) | ||
3166 | { | ||
3167 | return; | ||
3168 | } | ||
3080 | /* Among all the trails to reach to successor, select first one which is present.*/ | 3169 | /* Among all the trails to reach to successor, select first one which is present.*/ |
3081 | for (i = 0; i < successor->trails_count; i++) | 3170 | for (i = 0; i < successor->trails_count; i++) |
3082 | { | 3171 | { |
@@ -3379,6 +3468,13 @@ finger_table_add (struct GNUNET_PeerIdentity finger_identity, | |||
3379 | remove_existing_finger (existing_finger, finger_table_index); | 3468 | remove_existing_finger (existing_finger, finger_table_index); |
3380 | add_new_finger (finger_identity, finger_trail, finger_trail_length, | 3469 | add_new_finger (finger_identity, finger_trail, finger_trail_length, |
3381 | finger_trail_id, finger_table_index); | 3470 | finger_trail_id, finger_table_index); |
3471 | if ((0 == finger_table_index) && (1 == waiting_for_notify_confirmation)) | ||
3472 | { | ||
3473 | /* SUPUS: We have removed our successor, but we are still waiting for a | ||
3474 | * confirmation. As we have removed successor, then it does not make | ||
3475 | sense to wait for the new successor. */ | ||
3476 | waiting_for_notify_confirmation = 0; | ||
3477 | } | ||
3382 | } | 3478 | } |
3383 | else | 3479 | else |
3384 | { | 3480 | { |
@@ -4689,7 +4785,6 @@ handle_dht_p2p_verify_successor(void *cls, | |||
4689 | { | 4785 | { |
4690 | //SUPUs anyways you are passing the trail, just do the lookup | 4786 | //SUPUs anyways you are passing the trail, just do the lookup |
4691 | // and pass the message forward. | 4787 | // and pass the message forward. |
4692 | FPRINTF (stderr,_("\nSUPU %s, %s, %d, Trail not found trail id = %s"),__FILE__, __func__,__LINE__,GNUNET_h2s(&trail_id)); | ||
4693 | // int my_index = search_my_index (trail, trail_length); | 4788 | // int my_index = search_my_index (trail, trail_length); |
4694 | // if(-1 == my_index) | 4789 | // if(-1 == my_index) |
4695 | // { | 4790 | // { |
@@ -4936,7 +5031,13 @@ compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ, | |||
4936 | 5031 | ||
4937 | add_new_finger (probable_successor, trail_me_to_probable_succ, | 5032 | add_new_finger (probable_successor, trail_me_to_probable_succ, |
4938 | trail_me_to_probable_succ_len, trail_id, 0); | 5033 | trail_me_to_probable_succ_len, trail_id, 0); |
4939 | 5034 | /* SUPUS We are sending notify message, but before sending the next request | |
5035 | we should wait for confirmation. */ | ||
5036 | waiting_for_notify_confirmation = 1; | ||
5037 | current_successor = &finger_table[0]; | ||
5038 | current_successor->wait_notify_confirmation = | ||
5039 | GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), | ||
5040 | WAIT_NOTIFY_CONFIRMATION); | ||
4940 | GDS_NEIGHBOURS_send_notify_new_successor (my_identity, probable_successor, | 5041 | GDS_NEIGHBOURS_send_notify_new_successor (my_identity, probable_successor, |
4941 | trail_me_to_probable_succ, | 5042 | trail_me_to_probable_succ, |
4942 | trail_me_to_probable_succ_len, | 5043 | trail_me_to_probable_succ_len, |
@@ -5094,6 +5195,10 @@ handle_dht_p2p_notify_new_successor(void *cls, | |||
5094 | GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity(&source, peer)); | 5195 | GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity(&source, peer)); |
5095 | 5196 | ||
5096 | compare_and_update_predecessor (source, trail, trail_length); | 5197 | compare_and_update_predecessor (source, trail, trail_length); |
5198 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer); | ||
5199 | GDS_NEIGHBOURS_send_notify_succcessor_confirmation (trail_id, | ||
5200 | GDS_ROUTING_DEST_TO_SRC, | ||
5201 | target_friend); | ||
5097 | return GNUNET_OK; | 5202 | return GNUNET_OK; |
5098 | } | 5203 | } |
5099 | 5204 | ||
@@ -5138,6 +5243,78 @@ handle_dht_p2p_notify_new_successor(void *cls, | |||
5138 | 5243 | ||
5139 | 5244 | ||
5140 | /** | 5245 | /** |
5246 | * Core handler for P2P notify successor message | ||
5247 | * @param cls closure | ||
5248 | * @param message message | ||
5249 | * @param peer peer identity this notification is about | ||
5250 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
5251 | */ | ||
5252 | static int | ||
5253 | handle_dht_p2p_notify_succ_confirmation (void *cls, | ||
5254 | const struct GNUNET_PeerIdentity *peer, | ||
5255 | const struct GNUNET_MessageHeader *message) | ||
5256 | { | ||
5257 | const struct PeerNotifyConfirmationMessage *notify_confirmation; | ||
5258 | enum GDS_ROUTING_trail_direction trail_direction; | ||
5259 | struct GNUNET_HashCode trail_id; | ||
5260 | struct FriendInfo *target_friend; | ||
5261 | struct GNUNET_PeerIdentity *next_hop; | ||
5262 | size_t msize; | ||
5263 | |||
5264 | msize = ntohs (message->size); | ||
5265 | |||
5266 | if (msize != sizeof (struct PeerNotifyConfirmationMessage)) | ||
5267 | { | ||
5268 | GNUNET_break_op (0); | ||
5269 | return GNUNET_OK; | ||
5270 | } | ||
5271 | GNUNET_STATISTICS_update (GDS_stats, | ||
5272 | gettext_noop | ||
5273 | ("# Bytes received from other peers"), msize, | ||
5274 | GNUNET_NO); | ||
5275 | |||
5276 | notify_confirmation = (const struct PeerNotifyConfirmationMessage *) message; | ||
5277 | trail_direction = ntohl (notify_confirmation->trail_direction); | ||
5278 | trail_id = notify_confirmation->trail_id; | ||
5279 | |||
5280 | next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction); | ||
5281 | if (NULL == next_hop) | ||
5282 | { | ||
5283 | /* The source of notify new successor, might have found even a better | ||
5284 | successor. In that case it send a trail teardown message, and hence, | ||
5285 | the next hop is NULL. */ | ||
5286 | //Fixme: Add some print to confirm the above theory. | ||
5287 | return GNUNET_OK; | ||
5288 | } | ||
5289 | |||
5290 | /* I peer which sent the notify successor message to the successor. */ | ||
5291 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)) | ||
5292 | { | ||
5293 | /* | ||
5294 | * Schedule another round of verify sucessor with your current successor | ||
5295 | * which may or may not be source of this message. This message is used | ||
5296 | * only to ensure that we have a path setup to reach to our successor. | ||
5297 | */ | ||
5298 | waiting_for_notify_confirmation = 0; | ||
5299 | //FIXME: Should we reset the time out to 0? | ||
5300 | } | ||
5301 | else | ||
5302 | { | ||
5303 | target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); | ||
5304 | if (NULL == target_friend) | ||
5305 | { | ||
5306 | DEBUG ("\n friend not found, line number = %d",__LINE__); | ||
5307 | return GNUNET_SYSERR; | ||
5308 | } | ||
5309 | GDS_NEIGHBOURS_send_notify_succcessor_confirmation (trail_id, | ||
5310 | GDS_ROUTING_DEST_TO_SRC, | ||
5311 | target_friend); | ||
5312 | } | ||
5313 | return GNUNET_OK; | ||
5314 | } | ||
5315 | |||
5316 | |||
5317 | /** | ||
5141 | * Core handler for P2P trail rejection message | 5318 | * Core handler for P2P trail rejection message |
5142 | * @param cls closure | 5319 | * @param cls closure |
5143 | * @param message message | 5320 | * @param message message |
@@ -5353,7 +5530,6 @@ handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer | |||
5353 | /* I am the next hop, which means I am the final destination. */ | 5530 | /* I am the next hop, which means I am the final destination. */ |
5354 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)) | 5531 | if (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity)) |
5355 | { | 5532 | { |
5356 | FPRINTF (stderr,_("\nSUPU %s, %s, %d, REMOVE trail id = %s"),__FILE__, __func__,__LINE__,GNUNET_h2s(&trail_id)); | ||
5357 | GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id)); | 5533 | GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id)); |
5358 | return GNUNET_OK; | 5534 | return GNUNET_OK; |
5359 | } | 5535 | } |
@@ -5361,7 +5537,6 @@ handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer | |||
5361 | { | 5537 | { |
5362 | /* If not final destination, then send a trail teardown message to next hop.*/ | 5538 | /* If not final destination, then send a trail teardown message to next hop.*/ |
5363 | GNUNET_assert (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)); | 5539 | GNUNET_assert (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)); |
5364 | FPRINTF (stderr,_("\nSUPU %s, %s, %d, REMOVE trail id = %s"),__FILE__, __func__,__LINE__,GNUNET_h2s(&trail_id)); | ||
5365 | GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id)); | 5540 | GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id)); |
5366 | GDS_NEIGHBOURS_send_trail_teardown (trail_id, trail_direction, *next_hop); | 5541 | GDS_NEIGHBOURS_send_trail_teardown (trail_id, trail_direction, *next_hop); |
5367 | } | 5542 | } |
@@ -5512,7 +5687,6 @@ remove_matching_trails (const struct GNUNET_PeerIdentity *disconnected_friend, | |||
5512 | { | 5687 | { |
5513 | GNUNET_assert (0 == (GNUNET_CRYPTO_cmp_peer_identity (disconnected_friend, | 5688 | GNUNET_assert (0 == (GNUNET_CRYPTO_cmp_peer_identity (disconnected_friend, |
5514 | next_hop))); | 5689 | next_hop))); |
5515 | FPRINTF (stderr,_("\nSUPU %s, %s, %d, REMOVE trail id = %s"),__FILE__, __func__,__LINE__,GNUNET_h2s(¤t_trail->trail_id)); | ||
5516 | GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (current_trail->trail_id)); | 5690 | GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (current_trail->trail_id)); |
5517 | } | 5691 | } |
5518 | matching_trails_count++; | 5692 | matching_trails_count++; |
@@ -5607,7 +5781,6 @@ handle_core_disconnect (void *cls, | |||
5607 | } | 5781 | } |
5608 | 5782 | ||
5609 | remove_matching_fingers (peer); | 5783 | remove_matching_fingers (peer); |
5610 | FPRINTF (stderr,_("\nSUPU %s, %s, %d, REMOVE trail id of peer %s"),__FILE__, __func__,__LINE__,GNUNET_i2s(peer)); | ||
5611 | GNUNET_assert (GNUNET_SYSERR != GDS_ROUTING_remove_trail_by_peer (peer)); | 5784 | GNUNET_assert (GNUNET_SYSERR != GDS_ROUTING_remove_trail_by_peer (peer)); |
5612 | GNUNET_assert (GNUNET_YES == | 5785 | GNUNET_assert (GNUNET_YES == |
5613 | GNUNET_CONTAINER_multipeermap_remove (friend_peermap, | 5786 | GNUNET_CONTAINER_multipeermap_remove (friend_peermap, |
@@ -5735,6 +5908,8 @@ GDS_NEIGHBOURS_init (void) | |||
5735 | {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN, | 5908 | {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN, |
5736 | sizeof (struct PeerTrailTearDownMessage)}, | 5909 | sizeof (struct PeerTrailTearDownMessage)}, |
5737 | {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL, 0}, | 5910 | {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL, 0}, |
5911 | {&handle_dht_p2p_notify_succ_confirmation, GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION, | ||
5912 | sizeof (struct PeerNotifyConfirmationMessage)}, | ||
5738 | {NULL, 0, 0} | 5913 | {NULL, 0, 0} |
5739 | }; | 5914 | }; |
5740 | 5915 | ||
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index e03b7072a..ec6d64d9c 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -2600,10 +2600,15 @@ extern "C" | |||
2600 | #define GNUNET_MESSAGE_TYPE_DHT_ACT_MALICIOUS 892 | 2600 | #define GNUNET_MESSAGE_TYPE_DHT_ACT_MALICIOUS 892 |
2601 | #endif | 2601 | #endif |
2602 | 2602 | ||
2603 | /** | ||
2604 | * Send back peer that considers you are its successor, a confirmation | ||
2605 | * that you got the notify successor message. | ||
2606 | */ | ||
2607 | #define GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION 893 | ||
2603 | /*******************************************************************************/ | 2608 | /*******************************************************************************/ |
2604 | 2609 | ||
2605 | /** | 2610 | /** |
2606 | * Next available: 902 | 2611 | * Next available: 903 |
2607 | */ | 2612 | */ |
2608 | 2613 | ||
2609 | /** | 2614 | /** |