From fbb8c27761964f3ee87f859bfbb57db75849cd1a Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Fri, 17 Jun 2016 11:31:16 +0200 Subject: Initial import : make-boot-image.sh operationnal. Dumb mcastseed. --- mcastseed/src/mcastleech.c | 227 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 mcastseed/src/mcastleech.c (limited to 'mcastseed/src/mcastleech.c') 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 . + */ + +#ifndef __MINGW32__ +#include +#endif +#include +#include +#include +#include +#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; +} + -- cgit v1.2.3