summaryrefslogtreecommitdiff
path: root/mcastseed/src/mcastleech.c
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2016-06-17 11:31:16 +0200
committerLudovic Pouzenc <ludovic@pouzenc.fr>2016-06-17 11:31:16 +0200
commitfbb8c27761964f3ee87f859bfbb57db75849cd1a (patch)
tree6ec5ed2a72e5e2205614ec96678c62aee3c869c4 /mcastseed/src/mcastleech.c
downloadeficast-fbb8c27761964f3ee87f859bfbb57db75849cd1a.tar.gz
eficast-fbb8c27761964f3ee87f859bfbb57db75849cd1a.tar.bz2
eficast-fbb8c27761964f3ee87f859bfbb57db75849cd1a.zip
Initial import : make-boot-image.sh operationnal. Dumb mcastseed.
Diffstat (limited to 'mcastseed/src/mcastleech.c')
-rw-r--r--mcastseed/src/mcastleech.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/mcastseed/src/mcastleech.c b/mcastseed/src/mcastleech.c
new file mode 100644
index 0000000..d19bff9
--- /dev/null
+++ b/mcastseed/src/mcastleech.c
@@ -0,0 +1,227 @@
+/* client.c
+ * Greatly inspired from examples written by tmouse, July 2005
+ * http://cboard.cprogramming.com/showthread.php?t=67469
+ * Modified to run multi-platform by Christian Beier <dontmind@freeshell.org>.
+ */
+
+#ifndef __MINGW32__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "msock.h"
+
+#define MULTICAST_RECV_BUF 10240
+#define MULTICAST_SO_RCVBUF 425984
+#define DEFAULT_MCAST_IP_STR "ff02::114"
+#define DEFAULT_PORT_STR "9000"
+
+/* Cmdline Arguments */
+char *prog_name = NULL;
+char *mcast_ip = NULL;
+char *port = NULL;
+
+/* Sockets as global, used everywhere, even in die() */
+SOCKET mcast_sock = (SOCKET) -1; /* Multicast socket for receiving data */
+SOCKET ucast_sock = (SOCKET) -1; /* Unicast socket for give feedback to server */
+
+/* Buffer used for earch recvfrom() */
+char recvbuf[MULTICAST_RECV_BUF];
+
+/* Strings to print out representation of various states of the program */
+const char * const state_str[] = {
+ "exiting",
+ "wait_hello_and_connect_back",
+ "wait_start_and_start_job",
+ "receive_data",
+ "finalize_job",
+ "is_there_more_job"
+};
+
+/* Some boring funcs you didn't want to read now */
+void die(char* msg);
+void usage(char *msg);
+void arg_parse(int argc, char* argv[]);
+
+/* Parts of the "protocol", definitions are after main() */
+int wait_hello_and_connect_back();
+int wait_start_and_start_job();
+int receive_data();
+int finalize_job();
+int is_there_more_job();
+
+
+int main(int argc, char* argv[]) {
+ int state = 1; /* state of the "protocol" state machine */
+ int res;
+
+ arg_parse(argc, argv);
+
+ /* Finite state machine */
+ while ( state > 0 ) {
+ fprintf(stderr, "Now in %s state\n", state_str[state]);
+ switch ( state ) {
+ case 1: state = (wait_hello_and_connect_back() == 0)?2:1; break;
+ case 2: state = (wait_start_and_start_job() == 0)?2:3; break;
+ case 3: res = receive_data();
+ if (res==0) state = 4;
+ else if (res==1) state=3;
+ else state = -1;
+ break;
+ case 4: state = (finalize_job() == 0)?5:-2; break;
+ case 5: state = (is_there_more_job() == 0)?2:0; break;
+ }
+ }
+
+ if ( mcast_sock > 0 ) {
+ close(mcast_sock);
+ }
+
+ if ( state < 0 )
+ return -state;
+
+ return EXIT_SUCCESS;
+}
+
+
+int wait_hello_and_connect_back() {
+ /* Buffers for host and service strings after resolve */
+ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+ /* Server address, filled by system after first recvfrom */
+ struct sockaddr_storage peer_addr;
+ socklen_t peer_addr_len;
+ /* Various needed variables */
+ ssize_t nread;
+ int res;
+
+ /* Setup mcast_sock */
+ if ( mcast_sock > 0 ) {
+ close(mcast_sock);
+ mcast_sock = 0;
+ }
+ mcast_sock = mcast_recv_socket(mcast_ip, port, MULTICAST_SO_RCVBUF);
+ if(mcast_sock < 0)
+ usage("Could not setup multicast socket. Wrong args given ?");
+
+ /* Wait for a single datagram from the server (for sync, no check on contain) */
+ peer_addr_len = sizeof(struct sockaddr_storage);
+ nread = recvfrom(mcast_sock, recvbuf, MULTICAST_RECV_BUF, 0, (struct sockaddr *) &peer_addr, &peer_addr_len);
+ if (nread < 0 ) {
+ perror("recvfrom() failed");
+ return -1;
+ }
+ /* Get peer informations as strings from peer_addr */
+ res = getnameinfo((struct sockaddr *) &peer_addr, peer_addr_len,
+ hbuf, NI_MAXHOST, sbuf, NI_MAXSERV, NI_NUMERICSERV);
+ if ( res != 0 ) {
+ fprintf(stderr, "getnameinfo: %s\n", gai_strerror(res));
+ return -2;
+ }
+ /* Connect back to the server, with reliable unicast */
+ if ( ucast_sock > 0 ) {
+ close(ucast_sock);
+ }
+ ucast_sock = ucast_client_socket(hbuf,port);
+ if(ucast_sock < 0) {
+ fprintf(stderr, "Could not setup unicast socket or connect to %s:%s\n", hbuf, port);
+ return -3;
+ }
+
+ return 0;
+}
+
+int wait_start_and_start_job() {
+ ssize_t nread, nwrite;
+
+ /* Wait for a "start" datagram from the server */
+ nread = recvfrom(mcast_sock, recvbuf, MULTICAST_RECV_BUF, 0, NULL, 0);
+ if (nread < 0 ) {
+ perror("recvfrom() failed");
+ return -1;
+ }
+ if ( nread >= 5 && strncmp("start", recvbuf, 5) == 0 ) {
+
+ nwrite = write(ucast_sock, "ready", 5);
+ if ( nwrite < 0 ) {
+ fprintf(stderr, "write() failed\n");
+ return -2;
+ }
+ if (nwrite != 5) {
+ fprintf(stderr, "write() short\n");
+ return -3;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int receive_data() {
+ ssize_t nread;
+ uint32_t seq;
+ uint16_t datalen;
+
+ /* Wait for a "dataN" datagram from the server */
+ nread = recvfrom(mcast_sock, recvbuf, MULTICAST_RECV_BUF, 0, NULL, 0);
+ if (nread < 0 ) {
+ perror("recvfrom() failed");
+ return -1;
+ }
+ if ( nread >= 10 && strncmp("data", recvbuf, 4) == 0 ) {
+ seq = ntohl( *( (uint32_t *) recvbuf+1 ) );
+ datalen = ntohs( *( (uint16_t *) recvbuf+4 ) );
+ //fprintf(stderr, "debug seq==%i, datalen==%hi\n", seq, datalen);
+ if ( nread != (10 + datalen) ) {
+ fprintf(stderr, "debug nread==%zi, (10 + datalen)==%i\n", nread, (10 + datalen));
+ //TODO nack ?
+ return -2;
+ }
+ fprintf(stdout, "data #%i, ", seq);
+ fwrite(recvbuf+10, datalen, 1, stdout);
+ fflush(stdout);
+ //TODO buffer zero copy, ack
+ return 1;
+ }
+
+ return 0;
+}
+
+int finalize_job() {
+ return 0;
+}
+int is_there_more_job() {
+ return 1;
+}
+
+
+
+
+void die(char* msg) {
+ fprintf(stderr, "%s\n", msg);
+ if (mcast_sock > 0)
+ close(mcast_sock);
+ if (ucast_sock > 0)
+ close(ucast_sock);
+ exit(EXIT_FAILURE);
+}
+
+void usage(char *msg) {
+ char ubuf[256];
+ if ( msg != NULL )
+ fprintf(stderr, "%s\n", msg);
+ ubuf[0] = '\0';
+ snprintf(ubuf, 255, "Usage: %s [port] [mcast_ip]\n", prog_name);
+ die(ubuf);
+}
+
+void arg_parse(int argc, char* argv[]) {
+ prog_name = argv[0];
+ if ( argc > 3 )
+ usage("Too many arguments");
+ port = (argc >= 2)?argv[1]:DEFAULT_PORT_STR;
+ mcast_ip = (argc >= 3)?argv[2]:DEFAULT_MCAST_IP_STR;
+}
+