summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsr2013-07-15 20:46:42 +0200
committersr2013-07-15 20:46:42 +0200
commit2c9731d63810c839c8040d9d7131326ad48d515b (patch)
tree5350a04a8f39b07e2c70bb54af99aebbaf0c8b94 /src
parentRewriiiiiiiiite (diff)
downloaddnbd3-2c9731d63810c839c8040d9d7131326ad48d515b.tar.gz
dnbd3-2c9731d63810c839c8040d9d7131326ad48d515b.tar.xz
dnbd3-2c9731d63810c839c8040d9d7131326ad48d515b.zip
"It's compiling!"
Diffstat (limited to 'src')
-rw-r--r--src/server/globals.h72
-rw-r--r--src/server/image.c51
-rw-r--r--src/server/image.h29
-rw-r--r--src/server/net.c15
-rw-r--r--src/server/server.c99
-rw-r--r--src/server/server.h41
-rw-r--r--src/server/sockhelper.h1
-rw-r--r--src/server/uplink.c18
-rw-r--r--src/server/uplink.h3
-rw-r--r--src/types.h1
10 files changed, 204 insertions, 126 deletions
diff --git a/src/server/globals.h b/src/server/globals.h
index ccdaa01..e8203ea 100644
--- a/src/server/globals.h
+++ b/src/server/globals.h
@@ -1,6 +1,78 @@
#ifndef _GLOBALS_H_
#define _GLOBALS_H_
+#include "../types.h"
+#include <stdint.h>
+#include <time.h>
+#include <pthread.h>
+#include <glib/gslist.h>
+
+// ######### All structs/types used by the server ########
+
+typedef struct
+{
+ int fd;
+} dnbd3_connection_t;
+
+typedef struct
+{
+ uint16_t len;
+ uint8_t data[65535];
+} dnbd3_binstring_t;
+// Do not always allocate as much memory as required to hold the entire binstring struct,
+// but only as much as is required to hold the actual data
+#define NEW_BINSTRING(_name, _len) \
+ dnbd3_binstring_t *_name = malloc(sizeof(uint16_t) + _len); \
+ _name->len = _len
+
+typedef struct
+{
+ char comment[COMMENT_LENGTH];
+ time_t last_told;
+ dnbd3_host_t host;
+} dnbd3_alt_server_t;
+
+typedef struct
+{
+ char comment[COMMENT_LENGTH];
+ dnbd3_host_t host;
+ dnbd3_host_t mask;
+} dnbd3_acess_rules_t;
+
+/**
+ * Image struct. An image path could be something like
+ * /mnt/images/rz/zfs/Windows7 ZfS.vmdk.1
+ * and the lower_name would then be
+ * rz/zfs/windows7 zfs.vmdk
+ */
+typedef struct
+{
+ char *path; // absolute path of the image
+ char *lower_name; // relative path, all lowercase, minus revision ID
+ uint8_t *cache_map; // cache map telling which parts are locally cached, NULL if complete
+ uint32_t *crc32; // list of crc32 checksums for each 16MiB block in image
+ dnbd3_connection_t *uplink; // pointer to a server connection
+ uint64_t filesize; // size of image
+ int rid; // revision of image
+ int users; // clients currently using this image
+ time_t atime; // last access time
+ char working; // TRUE if image exists and completeness is == 100% or a working upstream proxy is connected
+ pthread_spinlock_t lock;
+} dnbd3_image_t;
+
+typedef struct
+{
+ int sock;
+ dnbd3_host_t host;
+ uint8_t is_server; // TRUE if a server in proxy mode, FALSE if real client
+ pthread_t thread;
+ dnbd3_image_t *image;
+ pthread_spinlock_t lock;
+ GSList *sendqueue; // list of dnbd3_binstring_t*
+} dnbd3_client_t;
+
+// #######################################################
+
/**
* Base directory where all images are stored in. Will always have a trailing slash
*/
diff --git a/src/server/image.c b/src/server/image.c
index 4e69eb2..78b528a 100644
--- a/src/server/image.c
+++ b/src/server/image.c
@@ -1,11 +1,14 @@
#include "image.h"
#include "helper.h"
+#include "memlog.h"
+#include "uplink.h"
#include <glib/gmacros.h>
#include <assert.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
+#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
@@ -19,10 +22,10 @@ pthread_spinlock_t _images_lock;
// ##########################################
-static void image_load_all(char *base, char *path);
+static int image_load_all_internal(char *base, char *path);
static int image_try_load(char *base, char *path);
static int image_check_blocks_crc32(int fd, uint32_t *crc32list, int *blocks);
-static void image_free(dnbd3_image_t *image);
+static dnbd3_image_t* image_free(dnbd3_image_t *image);
// ##########################################
@@ -180,20 +183,28 @@ void image_remove(dnbd3_image_t *image)
_images[i] = NULL;
if ( i + 1 == _num_images ) _num_images--;
}
- if ( image->users == 0 ) image_free( image );
pthread_spin_unlock( &image->lock );
+ if ( image->users <= 0 ) image = image_free( image );
pthread_spin_unlock( &_images_lock );
}
-void image_load_all()
+/**
+ * Load all images in given path recursively.
+ * Pass NULL to use path from config.
+ */
+int image_load_all(char *path)
{
- image_load_all( _basePath, _basePath );
+ if ( path == NULL ) {
+ return image_load_all_internal( _basePath, _basePath );
+ }
+ return image_load_all_internal( path, path );
}
/**
- * Load all images in the given path
+ * Load all images in the given path recursively,
+ * consider bash the base path that is to be cut off
*/
-static int image_load_all(char *base, char *path)
+static int image_load_all_internal(char *base, char *path)
{
#define SUBDIR_LEN 120
assert( path != NULL );
@@ -223,7 +234,7 @@ static int image_load_all(char *base, char *path)
continue;
}
if ( S_ISDIR( st.st_mode )) {
- image_load_all( base, subpath ); // Recurse
+ image_load_all_internal( base, subpath ); // Recurse
} else {
image_try_load( base, subpath ); // Load image if possible
}
@@ -278,6 +289,8 @@ static int image_try_load(char *base, char *path)
}
*dst = '\0';
}
+ char mapFile[strlen( path ) + 10 + 1];
+ char hashFile[strlen( path ) + 10 + 1];
if ( revision <= 0 ) {
memlogf( "[WARNING] Image '%s' has invalid revision ID %d", path, revision );
goto load_error;
@@ -300,8 +313,6 @@ static int image_try_load(char *base, char *path)
memlogf( "[WARNING] Empty image file '%s'", path );
goto load_error;
}
- char mapFile[strlen( path ) + 10 + 1];
- char hashFile[strlen( path ) + 10 + 1];
// 1. Allocate memory for the cache map if the image is incomplete
sprintf( mapFile, "%s.map", path );
int fdMap = open( path, O_RDONLY );
@@ -314,7 +325,7 @@ static int image_try_load(char *base, char *path)
}
close( fdMap );
}
- // TODO: Maybe try sha-256 or 512 first if you're paranoid
+ // TODO: Maybe try sha-256 or 512 first if you're paranoid (to be implemented)
const int hashBlocks = IMGSIZE_TO_HASHBLOCKS( fileSize );
// Currently this should only prevent accidental corruption (esp. regarding transparent proxy mode)
// but maybe later on you want better security
@@ -330,7 +341,7 @@ static int image_try_load(char *base, char *path)
memlogf( "[WARNING] Could not seek back to beginning of '%s'", hashFile );
} else {
uint32_t crcCrc;
- if ( read( fdHash, &crc32, sizeof(crc32) ) != 4 ) {
+ if ( read( fdHash, &crcCrc, sizeof(crcCrc) ) != 4 ) {
memlogf( "[WARNING] Error reading first crc32 of '%s'", path );
} else {
crc32list = calloc( hashBlocks, sizeof(uint32_t) );
@@ -340,7 +351,7 @@ static int image_try_load(char *base, char *path)
memlogf( "[WARNING] Could not read crc32 list of '%s'", path );
} else {
uint32_t lists_crc = crc32( 0L, Z_NULL, 0 );
- lists_crc = crc32( lists_crc, crc32list, hashBlocks * sizeof(uint32_t) );
+ lists_crc = crc32( lists_crc, (Bytef*)crc32list, hashBlocks * sizeof(uint32_t) );
if ( lists_crc != crcCrc ) {
free( crc32list );
crc32list = NULL;
@@ -386,13 +397,13 @@ static int image_try_load(char *base, char *path)
image->filesize = fileSize;
image->rid = revision;
image->users = 0;
- if ( stat( image, &st ) == 0 ) {
+ if ( stat( path, &st ) == 0 ) {
image->atime = st.st_mtime;
} else {
image->atime = time( NULL );
}
image->working = (image->cache_map == NULL );
- pthread_spin_init( &image->lock );
+ pthread_spin_init( &image->lock, PTHREAD_PROCESS_PRIVATE );
// Get rid of cache map if image is complete
if ( image->cache_map != NULL && image_is_complete( image ) ) {
remove( mapFile );
@@ -414,7 +425,7 @@ static int image_try_load(char *base, char *path)
if ( _num_images >= SERVER_MAX_IMAGES ) {
memlogf( "[ERROR] Cannot load image '%s': maximum number of images reached.", path );
pthread_spin_unlock( &_images_lock );
- image_free( image );
+ image = image_free( image );
goto load_error;
}
_images[_num_images++] = image;
@@ -451,7 +462,7 @@ static int image_check_blocks_crc32(int fd, uint32_t *crc32list, int *blocks)
memlogf( "Read error" );
return FALSE;
}
- crc = crc32( crc, buffer, r );
+ crc = crc32( crc, (Bytef*)buffer, r );
bytes += r;
}
if ( crc != crc32list[*blocks] ) return FALSE;
@@ -460,16 +471,20 @@ static int image_check_blocks_crc32(int fd, uint32_t *crc32list, int *blocks)
return TRUE;
}
-static void image_free(dnbd3_image_t *image)
+static dnbd3_image_t* image_free(dnbd3_image_t *image)
{
assert( image != NULL );
+ //
free( image->cache_map );
free( image->crc32 );
free( image->path );
free( image->lower_name );
uplink_shutdown( image->uplink );
+ pthread_spin_destroy( &image->lock );
+ //
memset( image, 0, sizeof(dnbd3_image_t) );
free( image );
+ return NULL ;
}
/*
diff --git a/src/server/image.h b/src/server/image.h
index 1a64b60..c776361 100644
--- a/src/server/image.h
+++ b/src/server/image.h
@@ -2,32 +2,7 @@
#define _IMAGE_H_
#include "../config.h"
-
-typedef struct
-{
- int fd;
-} dnbd3_connection_t;
-
-/**
- * Image struct. An image path could be something like
- * /mnt/images/rz/zfs/Windows7 ZfS.vmdk.1
- * and the lower_name would then be
- * rz/zfs/windows7 zfs.vmdk
- */
-typedef struct
-{
- char *path; // absolute path of the image
- char *lower_name; // relative path, all lowercase, minus revision ID
- uint8_t *cache_map; // cache map telling which parts are locally cached, NULL if complete
- uint32_t *crc32; // list of crc32 checksums for each 16MiB block in image
- dnbd3_connection_t *uplink; // pointer to a server connection
- uint64_t filesize; // size of image
- int rid; // revision of image
- int users; // clients currently using this image
- time_t atime; // last access time
- char working; // TRUE if image exists and completeness is == 100% or a working upstream proxy is connected
- pthread_spinlock_t lock;
-} dnbd3_image_t;
+#include "globals.h"
extern dnbd3_image_t *_images[SERVER_MAX_IMAGES];
extern int _num_images;
@@ -41,7 +16,7 @@ dnbd3_image_t* image_get(char *name, uint16_t revision);
void image_release(dnbd3_image_t *image);
-void image_load_all();
+int image_load_all(char *path);
diff --git a/src/server/net.c b/src/server/net.c
index 5a75a9b..6aa5d5b 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -115,24 +115,24 @@ void *net_client_handler(void *dnbd3_client)
dnbd3_image_t *image = NULL;
int image_file = -1;
- int i, num;
+ int num;
int bOk = FALSE;
- uint64_t map_y;
- char map_x, bit_mask;
serialized_buffer_t payload;
char *image_name;
uint16_t rid, client_version;
+ /*
+ char map_x, bit_mask;
+ uint64_t map_y;
uint64_t todo_size = 0;
uint64_t todo_offset = 0;
uint64_t cur_offset = 0;
uint64_t last_offset = 0;
+ */
dnbd3_server_entry_t server_list[NUMBER_SERVERS];
- int dirty = 0;
-
reply.magic = dnbd3_packet_magic;
// Receive first packet. This must be CMD_SELECT_IMAGE by protocol specification
@@ -153,7 +153,6 @@ void *net_client_handler(void *dnbd3_client)
}
} else {
image = image_get( image_name, rid );
- const time_t now = time( NULL );
if ( image == NULL ) {
printf( "[DEBUG] Client requested non-existent image '%s' (rid:%d), rejected\n", image_name, (int)rid );
} else if ( !image->working ) {
@@ -357,8 +356,6 @@ void *net_client_handler(void *dnbd3_client)
}
exit_client_cleanup: if ( client->sock != -1 ) close( client->sock );
if ( image_file != -1 ) close( image_file );
- image_release( image );
- client->image = image = NULL;
- dnbd3_free_client( client );
+ dnbd3_remove_client( client );
pthread_exit( (void *)0 );
}
diff --git a/src/server/server.c b/src/server/server.c
index 7c24358..97bf00a 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -27,6 +27,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdint.h>
+#include <unistd.h>
#include "../types.h"
#include "../version.h"
@@ -52,9 +53,15 @@ char *_config_file_name = DEFAULT_SERVER_CONFIG_FILE;
char *_rpc_password = NULL;
char *_cache_dir = NULL;
+static int dnbd3_add_client(dnbd3_client_t *client);
+static dnbd3_client_t* dnbd3_free_client(dnbd3_client_t *client);
+static void dnbd3_load_config();
static void dnbd3_handle_sigpipe(int signum);
static void dnbd3_handle_sigterm(int signum);
+/**
+ * Print help text for usage instructions
+ */
void dnbd3_print_help(char *argv_0)
{
printf( "Usage: %s [OPTIONS]...\n", argv_0 );
@@ -72,15 +79,21 @@ void dnbd3_print_help(char *argv_0)
exit( 0 );
}
+/**
+ * Print version information
+ */
void dnbd3_print_version()
{
printf( "Version: %s\n", VERSION_STRING );
exit( 0 );
}
+/**
+ * Clean up structs, connections, write out data, then exit
+ */
void dnbd3_cleanup()
{
- int fd, i;
+ int i;
memlogf( "INFO: Cleanup...\n" );
@@ -113,7 +126,7 @@ void dnbd3_cleanup()
// save cache maps to files
image_save_cache_map( image );
// free uplink connection
- uplink_free( image->uplink );
+ uplink_shutdown( image->uplink );
// free other stuff
free( image->cache_map );
free( image->path );
@@ -128,12 +141,14 @@ void dnbd3_cleanup()
exit( EXIT_SUCCESS );
}
+/**
+ * Program entry point
+ */
int main(int argc, char *argv[])
{
int demonize = 1;
int opt = 0;
int longIndex = 0;
- int i;
static const char *optString = "f:d:nrsiHV?";
static const struct option longOpts[] = { { "file", required_argument, NULL, 'f' }, { "delay", required_argument, NULL, 'd' }, {
"nodaemon", no_argument, NULL, 'n' }, { "reload", no_argument, NULL, 'r' }, { "stop", no_argument, NULL, 's' }, { "info",
@@ -200,7 +215,10 @@ int main(int argc, char *argv[])
signal( SIGINT, dnbd3_handle_sigterm );
// Load all images in base path
- images_load_all();
+ if (!image_load_all(NULL)) {
+ printf("[ERROR] Could not load images.\n");
+ return EXIT_FAILURE;
+ }
// setup network
sockets[socket_count] = sock_listen_any( PF_INET, PORT );
@@ -262,6 +280,10 @@ int main(int argc, char *argv[])
dnbd3_cleanup();
}
+/**
+ * Initialize and populate the client struct - called when an incoming
+ * connection is accepted
+ */
dnbd3_client_t* dnbd3_init_client(struct sockaddr_storage *client, int fd)
{
dnbd3_client_t *dnbd3_client = calloc( 1, sizeof(dnbd3_client_t) );
@@ -270,18 +292,18 @@ dnbd3_client_t* dnbd3_init_client(struct sockaddr_storage *client, int fd)
return NULL ;
}
- if ( client.ss_family == AF_INET ) {
- struct sockaddr_in *v4 = (struct sockaddr_in *)&client;
+ if ( client->ss_family == AF_INET ) {
+ struct sockaddr_in *v4 = (struct sockaddr_in *)client;
dnbd3_client->host.type = AF_INET;
memcpy( dnbd3_client->host.addr, &(v4->sin_addr), 4 );
dnbd3_client->host.port = v4->sin_port;
- } else if ( client.ss_family == AF_INET6 ) {
- struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)&client;
+ } else if ( client->ss_family == AF_INET6 ) {
+ struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)client;
dnbd3_client->host.type = AF_INET6;
memcpy( dnbd3_client->host.addr, &(v6->sin6_addr), 16 );
dnbd3_client->host.port = v6->sin6_port;
} else {
- memlogf( "[ERROR] New client has unknown address family %d, disconnecting...", (int)client.ss_family );
+ memlogf( "[ERROR] New client has unknown address family %d, disconnecting...", (int)client->ss_family );
free( dnbd3_client );
return NULL ;
}
@@ -291,21 +313,28 @@ dnbd3_client_t* dnbd3_init_client(struct sockaddr_storage *client, int fd)
}
/**
- * Free the client struct recursively.
- * Doesn't lock, so call this function after removing the client from _dnbd3_clients
+ * Remove a client from the clients array
+ * Locks on: _clients_lock
*/
-void dnbd3_free_client(dnbd3_client_t *client)
+void dnbd3_remove_client(dnbd3_client_t *client)
{
- GSList *it;
- for (it = client->sendqueue; it; it = it->next) {
- free( it->data );
+ int i;
+ pthread_spin_lock( &_clients_lock );
+ for (i = _num_clients - 1; i >= 0; --i) {
+ if ( _clients[i] != client ) continue;
+ _clients[i] = NULL;
+ if ( i + 1 == _num_clients ) --_num_clients;
}
- g_slist_free( client->sendqueue );
- if ( client->sock >= 0 ) close( client->sock );
- g_free( client );
+ pthread_spin_unlock( &_clients_lock );
}
-int dnbd3_add_client(dnbd3_client_t *client)
+//###//
+
+/**
+ * Add client to the clients array.
+ * Locks on: _clients_lock
+ */
+static int dnbd3_add_client(dnbd3_client_t *client)
{
int i;
pthread_spin_lock( &_clients_lock );
@@ -325,16 +354,32 @@ int dnbd3_add_client(dnbd3_client_t *client)
return TRUE;
}
-void dnbd3_remove_client(dnbd3_client_t *client)
+/**
+ * Free the client struct recursively.
+ * !! Make sure to call this function after removing the client from _dnbd3_clients !!
+ * Locks on: _clients[].lock
+ */
+static dnbd3_client_t* dnbd3_free_client(dnbd3_client_t *client)
{
- int i;
- pthread_spin_lock( &_clients_lock );
- for (i = _num_clients - 1; i >= 0; --i) {
- if ( _clients[i] != client ) continue;
- _clients[i] = NULL;
- if ( i + 1 == _num_clients ) --_num_clients;
+ GSList *it;
+ pthread_spin_lock(&client->lock);
+ for (it = client->sendqueue; it; it = it->next) {
+ free( it->data );
}
- pthread_spin_unlock( &_clients_lock );
+ g_slist_free( client->sendqueue );
+ if ( client->sock >= 0 ) close( client->sock );
+ client->sock = -1;
+ if ( client->image != NULL ) image_release( client->image );
+ client->image = NULL;
+ pthread_spin_unlock(&client->lock);
+ pthread_spin_destroy(&client->lock);
+ free( client );
+ return NULL;
+}
+
+static void dnbd3_load_config()
+{
+ // Load configuration
}
static void dnbd3_handle_sigpipe(int signum)
diff --git a/src/server/server.h b/src/server/server.h
index 46cd86f..413b2d4 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -27,44 +27,9 @@
#include "../config.h"
#include "../types.h"
+#include "globals.h"
-struct dnbd3_image_t;
-
-typedef struct
-{
- uint16_t len;
- uint8_t data[65535];
-} dnbd3_binstring_t;
-// Do not always allocate as much memory as required to hold the entire binstring struct,
-// but only as much as is required to hold the actual data
-#define NEW_BINSTRING(_name, _len) \
- dnbd3_binstring_t *_name = malloc(sizeof(uint16_t) + _len); \
- _name->len = _len
-
-typedef struct
-{
- int sock;
- dnbd3_host_t host;
- uint8_t is_server; // TRUE if a server in proxy mode, FALSE if real client
- pthread_t thread;
- dnbd3_image_t *image;
- pthread_spinlock_t lock;
- GSList *sendqueue; // list of dnbd3_binstring_t*
-} dnbd3_client_t;
-
-typedef struct
-{
- time_t last_told;
- dnbd3_host_t host;
- char comment[COMMENT_LENGTH];
-} dnbd3_alt_server_t;
-
-typedef struct
-{
- char comment[COMMENT_LENGTH];
- dnbd3_host_t host;
- dnbd3_host_t mask;
-} dnbd3_acess_rules_t;
+struct sockaddr_storage;
extern dnbd3_client_t *_clients[SERVER_MAX_CLIENTS];
extern int _num_clients;
@@ -77,10 +42,8 @@ extern int _fake_delay;
#endif
void dnbd3_cleanup();
-void dnbd3_add_client(dnbd3_client_t *client);
void dnbd3_remove_client(dnbd3_client_t *client);
dnbd3_client_t* dnbd3_init_client(struct sockaddr_storage *client, int fd);
-void dnbd3_free_client(dnbd3_client_t *client);
#if !defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
#error Please set _FILE_OFFSET_BITS to 64 in your makefile/configuration
diff --git a/src/server/sockhelper.h b/src/server/sockhelper.h
index 421b8b5..c20cf8f 100644
--- a/src/server/sockhelper.h
+++ b/src/server/sockhelper.h
@@ -6,6 +6,7 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <string.h>
int sock_connect4(struct sockaddr_in *addr, const int connect_ms, const int rw_ms);
diff --git a/src/server/uplink.c b/src/server/uplink.c
index 27e92b3..7675a76 100644
--- a/src/server/uplink.c
+++ b/src/server/uplink.c
@@ -1,6 +1,7 @@
#include "uplink.h"
#include <pthread.h>
-#include <bits/socket.h>
+#include <sys/socket.h>
+#include <string.h>
dnbd3_alt_server_t *_alt_servers[SERVER_MAX_ALTS];
int _num_alts = 0;
@@ -21,9 +22,9 @@ int uplink_get_matching_alt_servers(dnbd3_host_t *host, dnbd3_server_entry_t *ou
if ( host->type != _alt_servers[i]->host.type ) continue; // Wrong address family
if ( count == 0 ) {
// Trivial - this is the first entry
- memcpy( &output[0]->host, &_alt_servers[i]->host, sizeof(dnbd3_host_t) );
- output[0]->failures = 0;
- distance[0] = uplink_net_closeness( host, &output[0]->host );
+ memcpy( &output[0].host, &_alt_servers[i]->host, sizeof(dnbd3_host_t) );
+ output[0].failures = 0;
+ distance[0] = uplink_net_closeness( host, &output[0].host );
count++;
} else {
// Other entries already exist, insert in proper position
@@ -40,8 +41,8 @@ int uplink_get_matching_alt_servers(dnbd3_host_t *host, dnbd3_server_entry_t *ou
} else {
count++;
}
- memcpy( &output[j]->host, &_alt_servers[i]->host, sizeof(dnbd3_host_t) );
- output[j]->failures = 0;
+ memcpy( &output[j].host, &_alt_servers[i]->host, sizeof(dnbd3_host_t) );
+ output[j].failures = 0;
distance[j] = dist;
break;
}
@@ -69,3 +70,8 @@ int uplink_net_closeness(dnbd3_host_t *host1, dnbd3_host_t *host2)
}
return retval;
}
+
+void uplink_shutdown( dnbd3_connection_t *uplink)
+{
+ return;
+}
diff --git a/src/server/uplink.h b/src/server/uplink.h
index 77a6ca5..2a876ec 100644
--- a/src/server/uplink.h
+++ b/src/server/uplink.h
@@ -2,6 +2,7 @@
#define _UPLINK_H_
#include "../types.h"
+#include "globals.h"
extern dnbd3_alt_server_t *_alt_servers[SERVER_MAX_ALTS];
extern int _num_alts;
@@ -11,4 +12,6 @@ int uplink_get_matching_alt_servers(dnbd3_host_t *host, dnbd3_server_entry_t *ou
int uplink_net_closeness(dnbd3_host_t *host1, dnbd3_host_t *host2);
+void uplink_shutdown( dnbd3_connection_t *uplink);
+
#endif /* UPLINK_H_ */
diff --git a/src/types.h b/src/types.h
index f6eb5f4..6b074b7 100644
--- a/src/types.h
+++ b/src/types.h
@@ -22,6 +22,7 @@
#define TYPES_H_
#include "config.h"
+#include <stdint.h>
// ioctl
#define DNBD3_MAGIC 'd'