Initial review. Haven't tested yet. I'd like to review again.
Nitpicking, but the error message Unknown directory is not a LongName as the spec indicates.
Hm, if (hs_dir_node) {. Is !hs_dir_node possible in that code? If yes, it should have an else clause to initialize hs_dir to a helpful string (it's currently printed as NULL in control_event_hs_descriptor_requested()). If no, then maybe it should be an assert?
Unittests would be awesome!
Other than that, code looks sane. Will need to test it to see it in action though.
I am still not sure how to handle the unknown directory, should I change the spec to indicate it might return "Unknown directory"? Or should I return something else here? If so, generally what should I return for an unknown LongName?
Yep, I think calling assert on hs_dir_node makes more sense. I need to look more into it though ;p
As for tests, no problem, I will look into that as well.
One problem regarding tests, it seems like a non trivial task to write tests for control event, is mocking a dir_connection_t for connection_dir_client_reached_eof function the right thing to do here?
Generally, I would try doing controller tests by mocking the funtions that write to the controller connection (e.g, "send_control_event_string()"), and by invoking the controller code rather than the directory code. connection_dir_client_reached_eof is very badly factored; trying to test that one without breaking it down into smaller functions first seems like an iffy choice to me.
Can you add some brief docs to specify what the test is supposed to do?
The received_msg global variable is a bit confusing -- especially if we expect to add more unit tests to test_hs.c. Can you at least document that the variable is a helper for a specific test? Same goes for the STR_HS_ADDR constants, which I would personally only define within the body of test_hs_desc_event().
Check out test_streq() instead of test_assert(!strncmp(...)).
Also, you merged master on top of your branch. Ideally, your commits should be on top and you should rebase your branch to use master as its base.
If you don't have time to do the above tasks, just tell us and we can do them before merging.
You might also want to add a changes file that describes the feature that you added (example commits: 71e0ca02b57f7945d922a8708a2c97815a9350ad907711d790a391c12a398d3cc402c37a68576381). Feel free to also add your name in there if you want.
control_event_hs_descriptor_receive_end worries me a bit. It takes a fmt argument as a char*, and bypasses the GCC printf argument checking. Instead, why not give it an extra const char * argument to receive either "FAILED" or "RECEIVED"?
In test_hs.c, I'd suggest adding TT_FORK to the flags field, so that the tests are run in a subprocess.
Okay, another round of reviews. (Sorry about the delays):
We should prefer tor_malloc to malloc(); we should prefer tor_malloc_zero() to malloc()+bzero(). We should use tor_free(), not free().
This won't build with all our gcc warnings enabled. (It uses C99 constructs by declaring variables in the middle of blocks.)
node_describe(rs) is a better choice than routerstatus_describe(node->rs) for describing nodes.
The tor_assert(hs_dir_node) thing makes me worry about race conditions where the node goes away after the circuit is launched. Perhaps we can send events with node_describe(hs_dir_node) when hs_dir_node is non-null, and with the base 16 encoding if the ID when node_get_by_id() returns NULL? That would be a fine thing to wrap into a "node_describe_by_id()" function.
Most of these new functions lack documentation. See doc/HACKING for a documentation style.
Anybody on the cc list want to offer to help dave2008 out with these changes? We've left him hanging for a while, they're fairly simple changes, and it would be cool to pick up some of our slack.
I will start cleaning my patch tomorrow, all the suggestions looks fine to me, except I am not exactly sure on how to get the tor_assert one done. I will look more into it tomorrow as well.
Agree. I am wondering where which file I should put the testcase in.
Since node_describe_by_id is a generic router specific function, it obviously does not belong to test_hs.c. Is there any test module that is specifically for router related functions?
Agree. I am wondering where which file I should put the testcase in.
Since node_describe_by_id is a generic router specific function, it obviously does not belong to test_hs.c. Is there any test module that is specifically for router related functions?
Hm, there is no test_router.c indeed. And there doesn't seem to be a place with lots of router.c unittests either (test_dir.c contains a few).
I would suggest making your own test_router.c. We will need to unit test the rest of the funcs at router.c at some point anyway... If you think that's a poor idea, maybe you can put the test in test.c or test_hs.c but it doesn't look very suiting...
Should we really be using numeric values 0, 1, 2 to indicate authorization types? We usually use human-readable strings in the rest of the controller protocol.
I noticed that all the functions in control.c either uses node_get_verbose_nickname or implement their own version of it to get the LongName. If the concept of LongName is specific to the control submodule. Maybe it's better to have one generic get_longname function and use it instead of duplicating the code again and again.