diff options
author | Lars Müller | 2008-03-01 19:30:38 +0100 |
---|---|---|
committer | Lars Müller | 2008-03-01 19:30:38 +0100 |
commit | 93b9103f7383d400616d222606c294e07b16e1aa (patch) | |
tree | 611a39f7bc1d1dd5a4335157ef95c101d64dddc8 /test-app | |
download | dnbd2-93b9103f7383d400616d222606c294e07b16e1aa.tar.gz dnbd2-93b9103f7383d400616d222606c294e07b16e1aa.tar.xz dnbd2-93b9103f7383d400616d222606c294e07b16e1aa.zip |
Import dnbd* from the former openslx-contrib repo as of revision 92.
openslx-contrib is currently read only and will get removed in some
days.
git-svn-id: http://svn.openslx.org/svn/openslx/contrib/dnbd2/trunk@1592 95ad53e4-c205-0410-b2fa-d234c58c8868
Diffstat (limited to 'test-app')
-rw-r--r-- | test-app/Makefile | 17 | ||||
-rw-r--r-- | test-app/data-client.c | 281 |
2 files changed, 298 insertions, 0 deletions
diff --git a/test-app/Makefile b/test-app/Makefile new file mode 100644 index 0000000..248a285 --- /dev/null +++ b/test-app/Makefile @@ -0,0 +1,17 @@ +# +# test-apps/Makefile +# + +CPPFLAGS = -I../include +CFLAGS = -Wall -O2 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 +VPATH = ../include +APP = data-client + +all: $(APP) + +install: + cp $(APP) /usr/local/bin + +.PHONY: +clean: + $(RM) *.o *~ $(APP) diff --git a/test-app/data-client.c b/test-app/data-client.c new file mode 100644 index 0000000..da85b89 --- /dev/null +++ b/test-app/data-client.c @@ -0,0 +1,281 @@ +/* + * test-apps/data-client.c + */ + +#include <sys/socket.h> +#include <netinet/in.h> +#include <byteswap.h> +#include <arpa/inet.h> +#include <strings.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include "dnbd2.h" + + +void print_usage(void); +ssize_t writen(int fd, const void *msg, size_t n); +ssize_t readn(int fd, void *msg, size_t n); +int dnbd2_data_request(dnbd2_server_t server, + dnbd2_data_request_t request, + dnbd2_data_reply_t *reply); + + +int main(int argc, char **argv) +{ + if (argc != 6) { + print_usage(); + return 0; + } + + dnbd2_data_request_t request; + dnbd2_data_reply_t reply; + + /* The time field is always echoed by the server. + This is an arbitrary value. */ + request.time = 28481; + + /* Read IP and Port */ + dnbd2_server_t server; + if (!inet_aton(argv[1], (struct in_addr *) &(server.ip))) { + fprintf(stderr, "Invalid IP\n"); + return -1; + } + if (sscanf(argv[2], "%hu", &(server.port)) != 1) { + fprintf(stderr, "Invalid Port\n"); + return -1; + } + server.port = htons(server.port); + + /* Read Volume-ID and Release-ID */ + if (sscanf(argv[3], "%hu", &(request.vid)) != 1) { + fprintf(stderr, "Invalid Volume-ID\n"); + return -1; + } + if (sscanf(argv[4], "%hu", &(request.rid)) != 1) { + fprintf(stderr, "Invalid Release-ID\n"); + return -1; + } + + /* Read command */ + char str[16]; + int cmd = 0; + if (sscanf(argv[5], "%s", str) == 1) { + if (!strcmp("getdata", str)) + cmd = 1; + + if (!strcmp("getsize", str)) + cmd = 2; + + if (!strcmp("getservers", str)) + cmd = 3; + } + if (!cmd) { + fprintf(stderr, "Invalid CMD\n"); + return -1; + } + + /* Complete and issue request(s) */ + int ret, i, rest; + off_t size, blocks; + switch (cmd) { + case 1: + /* Get Dataset size */ + request.cmd = CMD_GET_SIZE; + ret = dnbd2_data_request(server, request, &reply); + if (ret == -1) + goto out_nosize; + size = reply.num; + + /* size = blocks * DNBD2_BLOCK_SIZE + rest */ + blocks = size / DNBD2_BLOCK_SIZE; + rest = size % DNBD2_BLOCK_SIZE; + + /* Fetch "blocks * DNBD2_BLOCK_SIZE" bytes */ + request.cmd = CMD_GET_BLOCK; + for (i=0 ; i<blocks ; i++) { + request.num = i * DNBD2_BLOCK_SIZE; + ret = dnbd2_data_request(server, request, &reply); + if (ret == -1) + goto out_nodata; + write(STDOUT_FILENO, reply.payload.data, + DNBD2_BLOCK_SIZE); + } + + /* Fetch "rest" bytes */ + if (rest != 0) { + request.num = i*DNBD2_BLOCK_SIZE; + ret = dnbd2_data_request(server, request, &reply); + if (ret == -1) + goto out_nodata; + write(STDOUT_FILENO, reply.payload.data, rest); + } + break; + + case 2: + /* Get Dataset size */ + request.cmd = CMD_GET_SIZE; + ret = dnbd2_data_request(server, request, &reply); + if (ret == -1) + goto out_nosize; + printf("Dataset Size = %lld\n", reply.num); + break; + + case 3: + /* Get list of alternative servers */ + request.cmd = CMD_GET_SERVERS; + ret = dnbd2_data_request(server, request, &reply); + if (ret == -1) + goto out_noservers; + if (reply.num == 0) + printf("No alternative servers.\n"); + + for (i=0 ; i<reply.num ; i++) { + dnbd2_server_t server; + struct in_addr addr; + memcpy(&server, + &reply.payload.server[i], + sizeof(dnbd2_server_t)); + memcpy(&addr, + &server.ip, + sizeof(uint32_t)); + printf("%s:%hu\n", inet_ntoa(addr), ntohs(server.port)); + } + break; + } + + + return 0; + + out_nodata: + fprintf(stderr, "Could not get data.\n"); + return -1; + + out_nosize: + fprintf(stderr, "Could not get Dataset size.\n"); + return -1; + + out_noservers: + fprintf(stderr, "Could not get list of alternative servers.\n"); + return -1; +} + + +int dnbd2_data_request(dnbd2_server_t server, + dnbd2_data_request_t request, + dnbd2_data_reply_t *reply) +{ + struct sockaddr_in server_addr; + bzero(&server_addr, sizeof(server_addr)); + server_addr.sin_addr.s_addr = server.ip; + server_addr.sin_port = server.port; + server_addr.sin_family = AF_INET; + + int sockfd = socket(PF_INET, SOCK_DGRAM, 0); + if (sockfd == -1) { + fprintf(stderr, "Could not create socket.\n"); + return -1; + } + if (connect(sockfd, (struct sockaddr *) &server_addr, + sizeof(server_addr)) == -1) { + fprintf(stderr,"Could not connect UDP socket."); + return -1; + } + + request.cmd = htons(request.cmd); + request.time = htons(request.time); + request.vid = htons(request.vid); + request.rid = htons(request.rid); + request.num = htonll(request.num); + + /* Send request. */ + ssize_t n = writen(sockfd, &request, sizeof(request)); + if (n == -1) { + fprintf(stderr, "Error sending request.\n"); + return -1; + } + if (n != sizeof(request)) { + fprintf(stderr, "Sent wrong request size.\n"); + return -1; + } + + /* Receive reply. */ + n = readn(sockfd, reply, sizeof(*reply)); + if (n == -1) { + fprintf(stderr, "Error receiving reply.\n"); + return -1; + } + if (n != sizeof(*reply)) { + fprintf(stderr, "Got wrong reply size.\n"); + return -1; + } + close(sockfd); + + reply->cmd = ntohs(reply->cmd); + reply->time = ntohs(reply->time); + reply->vid = ntohs(reply->vid); + reply->rid = ntohs(reply->rid); + reply->num = ntohll(reply->num); + + return 0; +} + + +ssize_t writen(int fd, const void *msg, size_t n) { + + size_t nleft; + ssize_t nwritten; + const char *ptr; + + ptr = msg; + nleft = n; + + while (nleft > 0) { + if ((nwritten = write(fd, ptr, nleft)) <= 0) { + if (errno == EINTR) + nwritten = 0; + else + return -1; + } + nleft -= nwritten; + ptr += nwritten; + } + + return (n); +} + + +ssize_t readn(int fd, void *msg, size_t n) { + + size_t nleft; + ssize_t nread; + char *ptr; + + ptr = msg; + nleft = n; + + while (nleft > 0) { + if ((nread = read(fd, ptr, nleft)) < 0) { + if (errno == EINTR) + nread = 0; + else + return -1; + } else if (nread == 0) { + break; + } + nleft -= nread; + ptr += nread; + } + + return n - nleft; +} + + +void print_usage(void) { + printf("usage: dnbd2-data IP Port Volume-ID Release-ID " + "(getsize|getdata|getservers)\n"); + printf(" getsize: Print the Dataset's size.\n"); + printf(" getdata: Write the Dataset's contents to stdout.\n"); + printf(" getsize: Print the list of alternative Servers.\n"); +} |