Skip to content

Commit

Permalink
Added peer discovery client
Browse files Browse the repository at this point in the history
Signed-off-by: leonard.kosta <[email protected]>
  • Loading branch information
kostaleonard committed Jan 1, 2025
1 parent 7ad9a59 commit ba9d617
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_library(mining_thread src/mining_thread.c)
target_link_libraries(mining_thread hash)
target_link_libraries(mining_thread pthread)
target_link_libraries(miner mining_thread)
add_library(sleep src/sleep.c)
# Peer discovery bootstrap server
add_executable(peer_discovery_bootstrap_server src/peer_discovery_bootstrap_server.c)
target_link_libraries(peer_discovery_bootstrap_server linked_list)
Expand Down Expand Up @@ -70,6 +71,7 @@ add_library(test_endian tests/test_endian.c)
target_link_libraries(test_endian endian)
target_link_libraries(tests test_endian)
add_library(test_mining_thread tests/test_mining_thread.c)
target_link_libraries(test_mining_thread sleep)
target_link_libraries(test_mining_thread mining_thread)
target_link_libraries(tests test_mining_thread)
add_library(test_peer_discovery tests/test_peer_discovery.c)
Expand Down
40 changes: 40 additions & 0 deletions include/peer_discovery_thread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* @brief Contains functions for the peer discovery thread.
*/

#ifndef INCLUDE_PEER_DISCOVERY_THREAD_H_
#define INCLUDE_PEER_DISCOVERY_THREAD_H_

#include <pthread.h>
#include <stdatomic.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include "include/return_codes.h"
#include "include/linked_list.h"

// TODO docstring. Look at mining_thread.h, because the synchronization stuff is the same
typedef struct discover_peers_args_t {
struct sockaddr_in6 peer_discovery_bootstrap_server_addr;
uint64_t communication_interval_seconds;
linked_list_t *peer_info_list; // TODO shared between threads. Initially empty.
pthread_mutex_t peer_info_list_mutex;
bool print_progress;
atomic_bool *should_stop;
bool *exit_ready;
pthread_cond_t exit_ready_cond;
pthread_mutex_t exit_ready_mutex;
} discover_peers_args_t;

// TODO docstrings
return_code_t *discover_peers(discover_peers_args_t *args);

#endif // INCLUDE_PEER_DISCOVERY_THREAD_H_
1 change: 1 addition & 0 deletions include/return_codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ typedef enum return_code_t {
FAILURE_INVALID_COMMAND_PREFIX,
FAILURE_INVALID_COMMAND,
FAILURE_INVALID_COMMAND_LEN,
FAILURE_SLEEP,
} return_code_t;

#endif // INCLUDE_RETURN_CODES_H_
18 changes: 18 additions & 0 deletions include/sleep.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @brief Contains functions for cross-platform sleep (pause the program).
*/

#ifndef INCLUDE_SLEEP_H_
#define INCLUDE_SLEEP_H_

#include <stdint.h>
#include "include/return_codes.h"

/**
* @brief Pauses the program for the given number of microseconds.
*
* @return return_code_t A return code indicating success or failure.
*/
return_code_t sleep_microseconds(uint64_t microseconds);

#endif // INCLUDE_SLEEP_H_
6 changes: 3 additions & 3 deletions src/mining_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,16 @@ return_code_t *mine_blocks(mine_blocks_args_t *args) {
if (FAILURE_COULD_NOT_FIND_VALID_PROOF_OF_WORK == return_code) {
if (args->print_progress) {
printf("\nCouldn't find valid proof of work for block; "
"generating new block\n");
"generating new block.\n");
}
} else if (FAILURE_LONGER_BLOCKCHAIN_DETECTED == return_code) {
if (args->print_progress) {
printf("Longer chain detected; switching to new chain\n");
printf("Longer chain detected; switching to new chain.\n");
}
return_code = SUCCESS;
} else if (FAILURE_STOPPED_EARLY == return_code) {
if (args->print_progress) {
printf("Stopping miner\n");
printf("Stopping miner.\n");
}
return_code = SUCCESS;
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/peer_discovery_bootstrap_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ int main(int argc, char **argv) {
command_register_peer_t command_register_peer = {0};
// TODO use error command to send info back to client
//command_error_t command_error = {0};
// TODO don't need this because we know we're expecting a peer list command and it includes header deserialization.
return_code = command_header_deserialize(
&command_header, (unsigned char *)recv_buf, bytes_received);
if (SUCCESS != return_code) {
Expand Down Expand Up @@ -180,6 +181,7 @@ int main(int argc, char **argv) {
}
// TODO filter peer list for last_connected > 60 seconds old
command_send_peer_list_t command_send_peer_list = {0};
// TODO can use the header initializer
memcpy(command_send_peer_list.header.command_prefix, COMMAND_PREFIX, COMMAND_PREFIX_LEN);
command_send_peer_list.header.command = COMMAND_SEND_PEER_LIST;
return_code = peer_info_list_serialize(peer_list, &command_send_peer_list.peer_list_data, &command_send_peer_list.peer_list_data_len);
Expand Down
16 changes: 16 additions & 0 deletions src/peer_discovery_client.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @brief Runs the peer discovery client.
*/

#include "include/peer_discovery_thread.h"
#include "include/return_codes.h"

int main(int argc, char **argv) {
return_code_t return_code = SUCCESS;
discover_peers_args_t args = {0};
// TODO read bootstrap server address from argv
// TODO read communication interval from argv
// TODO launch thread
end:
return return_code;
}
35 changes: 35 additions & 0 deletions src/peer_discovery_thread.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// TODO registers with peer discovery server and maintains peer list.

#include "include/peer_discovery_thread.h"
#include "include/sleep.h"

return_code_t *discover_peers(discover_peers_args_t *args) {
return_code_t return_code = SUCCESS;
bool should_stop = *args->should_stop;
while (!should_stop) {
if (args->print_progress) {
printf("Attempting to connect to peer discovery server.\n");
}
// TODO connect to peer discovery server

// TODO register self as peer
// TODO request peer list

sleep_microseconds(args->communication_interval_seconds * 1000000);
should_stop = *args->should_stop;
}
if (should_stop) {
return_code = FAILURE_STOPPED_EARLY;
if (args->print_progress) {
printf("Stopping peer discovery.\n");
}
}
pthread_mutex_lock(&args->exit_ready_mutex);
*args->exit_ready = true;
pthread_cond_signal(&args->exit_ready_cond);
pthread_mutex_unlock(&args->exit_ready_mutex);
end:
return_code_t *return_code_ptr = malloc(sizeof(return_code_t));
*return_code_ptr = return_code;
return return_code_ptr;
}
17 changes: 17 additions & 0 deletions src/sleep.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <time.h>
#include "include/sleep.h"

// TODO test this function
return_code_t sleep_microseconds(uint64_t microseconds) {
return_code_t return_code = SUCCESS;
struct timespec ts;
ts.tv_sec = microseconds / 1000000;
ts.tv_nsec = (microseconds % 1000000) * 1000;
int result = nanosleep(&ts, NULL);
if (0 != result) {
return_code = FAILURE_SLEEP;
goto end;
}
end:
return return_code;
}
9 changes: 1 addition & 8 deletions tests/test_mining_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "include/base64.h"
#include "include/blockchain.h"
#include "include/mining_thread.h"
#include "include/sleep.h"
#include "tests/test_cryptography.h"
#include "tests/test_mining_thread.h"

#define NUM_LEADING_ZERO_BYTES_IN_BLOCK_HASH 2

void sleep_microseconds(uint64_t microseconds) {
struct timespec ts;
ts.tv_sec = microseconds / 1000000;
ts.tv_nsec = (microseconds % 1000000) * 1000;
nanosleep(&ts, NULL);
}

void test_mine_blocks_exits_when_should_stop_is_set() {
blockchain_t *blockchain = NULL;
return_code_t return_code = blockchain_create(
Expand Down

0 comments on commit ba9d617

Please sign in to comment.