/**
 * @param addr_type
 *   UCAST - my unicast address attached to this device
 *   BCAST - my broadcast addres attached to this device
 *   MCAST - multicast address
 * @param ifname
 *   Interface name
 * @param mcast
 *   Multicast address (only used if type MCAST)
 * @param port
 *   Port to bind address to
 */
int makeSocket(addr_type_t addr_type,
	       net_if_t *net_if,
	       struct sockaddr_in *tmpl,
	       int port) {
    int ret, s;
    struct sockaddr_in myaddr;
    in_addr_t ip=0;

#ifdef WINDOWS
    static int lastSocket=-1;
    /* Very ugly hack, but hey!, this is for Windows */

    if(addr_type == ADDR_TYPE_MCAST) {
	mcastListen(lastSocket, net_if, tmpl);
	return -1;
    } else if(addr_type != ADDR_TYPE_UCAST)
	return -1;
#endif

    s = socket(PF_INET, SOCK_DGRAM, 0);
    if (s < 0) {
	perror("make socket");
	exit(1);
    }

    if(addr_type == ADDR_TYPE_MCAST && tmpl != NULL) {
	ip = tmpl->sin_addr.s_addr;
    }

    ret = initSockAddress(addr_type, net_if, ip, port, &myaddr);
    if(ret < 0)
	udpc_fatal(1, "Could not get socket address fot %d/%s",
		   addr_type, net_if->name);
    if(addr_type == ADDR_TYPE_BCAST && myaddr.sin_addr.s_addr == 0) {
      /* Attempting to bind to broadcast address on not-broadcast media ... */
      closesocket(s);
      return -1;
    }
    ret = bind(s, (struct sockaddr *) &myaddr, sizeof(myaddr));
    if (ret < 0) {
	char buffer[16];
	udpc_fatal(1, "bind socket to %s:%d (%s)\n",
		   udpc_getIpString(&myaddr, buffer),
		   udpc_getPort(&myaddr),
		   strerror(errno));
    }

    if(addr_type == ADDR_TYPE_MCAST)
	mcastListen(s, net_if, &myaddr);
#ifdef WINDOWS
    lastSocket=s;
#endif
    return s;
}
static int initSockAddress(addr_type_t addr_type,
			   net_if_t *net_if,
			   in_addr_t ip,
			   unsigned short port,
			   struct sockaddr_in *addr) {
    memset ((char *) addr, 0, sizeof(struct sockaddr_in));
    addr->sin_family = AF_INET;
    addr->sin_port = htons(port);

    if(!net_if && addr_type != ADDR_TYPE_MCAST)
	udpc_fatal(1, "initSockAddr without ifname\n");

    switch(addr_type) {
    case ADDR_TYPE_UCAST:
	addr->sin_addr = net_if->addr;
	break;
    case ADDR_TYPE_BCAST:
	addr->sin_addr = net_if->bcast;
	break;
    case ADDR_TYPE_MCAST:
	addr->sin_addr.s_addr = ip;
	break;
    }
    return 0;
}
static int openOutFile(struct disk_config *disk_config)
{
    int outFile=1;
    if(disk_config->fileName != NULL) {
	int oflags = O_CREAT | O_WRONLY | O_TRUNC;
	if((disk_config->flags & FLAG_SYNC)) {
	    oflags |= O_SYNC;
	} else if( !(disk_config->flags & FLAG_NOSYNC)) {
	    struct stat buf;
	    if(stat(disk_config->fileName, &buf) == 0) {
		/* If target is device, open it synchronously */
		if(S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode))
			oflags |= O_SYNC;
	    }
	}
	outFile = open(disk_config->fileName, oflags | O_BINARY, 0644);
	if(outFile < 0) {
#ifdef NO_BB
#ifndef errno
	    extern int errno;
#endif
#endif
	    udpc_fatal(1, "open outfile %s: %s\n",
		       disk_config->fileName, strerror(errno));
	}
    } else {
#ifdef __MINGW32__
	_setmode(1, O_BINARY);
#endif
    }
    return outFile;
}
Beispiel #4
0
static int sendRawData(int sock,
		       struct net_config *config, 
		       char *header, int headerSize, 
		       unsigned char *data, int dataSize)
{
    struct iovec iov[2];
    struct msghdr hdr;
    int packetSize;
    int ret;
    
    iov[0].iov_base = header;
    iov[0].iov_len = headerSize;

    iov[1].iov_base = data;
    iov[1].iov_len = dataSize;

    hdr.msg_name = &config->dataMcastAddr;
    hdr.msg_namelen = sizeof(struct sockaddr_in);
    hdr.msg_iov = iov;
    hdr.msg_iovlen  = 2;
    initMsgHdr(&hdr);

    packetSize = dataSize + headerSize;
    rgWaitAll(config, sock, config->dataMcastAddr.sin_addr.s_addr, packetSize);
    ret = sendmsg(sock, &hdr, 0);
    if (ret < 0) {
	char ipBuffer[16];
	udpc_fatal(1, "Could not broadcast data packet to %s:%d (%s)\n",
		   getIpString(&config->dataMcastAddr, ipBuffer),
		   getPort(&config->dataMcastAddr),
		   strerror(errno));
    }

    return 0;
}
unsigned long parseSize(char *sizeString) {
    char *eptr;
    unsigned long size = strtoul(sizeString, &eptr, 10);
    if(eptr && *eptr) {
	switch(*eptr) {
	    case 'm':
	    case 'M':
		size *= 1024 * 1024;
		break;
	    case 'k':
	    case 'K':
		size *= 1024;
		break;
	    case '\0':
		break;
	    default:
		udpc_fatal(1, "Unit %c unsupported\n", *eptr);
	}
    }
    return size;
}
Beispiel #6
0
static int sendRawData(int sock,
                       struct net_config *config, 
                       char *header, int headerSize, 
                       unsigned char *data, int dataSize)
{
    struct iovec iov[2];
    struct msghdr hdr;
    int packetSize;
    int ret;
    
    iov[0].iov_base = header;
    iov[0].iov_len = headerSize;

    iov[1].iov_base = data;
    iov[1].iov_len = dataSize;

    hdr.msg_name = &config->dataMcastAddr;
    hdr.msg_namelen = sizeof(struct sockaddr_in);
    hdr.msg_iov = iov;
    hdr.msg_iovlen  = 2;
    initMsgHdr(&hdr);

    packetSize = dataSize + headerSize;
    doRateLimit(config->rateLimit, packetSize);
#ifdef FLAG_AUTORATE
    if(config->flags & FLAG_AUTORATE)
        doAutoRateLimit(sock, config->dir, config->sendbuf, packetSize);
#endif
    ret = sendmsg(sock, &hdr, 0);
    if (ret < 0) {
        char ipBuffer[16];
        udpc_fatal(1, "Could not broadcast data packet to %s:%d (%s)\n",
                   getIpString(&config->dataMcastAddr, ipBuffer),
                   getPort(&config->dataMcastAddr),
                   strerror(errno));
    }

    return 0;
}
/* makes a socket address */
int makeSockAddr(char *hostname, short port, struct sockaddr_in *addr)
{
    struct hostent *host;

    memset ((char *) addr, 0, sizeof(struct sockaddr_in));
    if (hostname && *hostname) {
	char *inaddr;
	int len;

	host = gethostbyname(hostname);
	if (host == NULL) {
	    udpc_fatal(1, "Unknown host %s\n", hostname);
	}

	inaddr = host->h_addr_list[0];
	len = host->h_length;
	memcpy((void *)&((struct sockaddr_in *)addr)->sin_addr, inaddr, len);
    }

    ((struct sockaddr_in *)addr)->sin_family = AF_INET;
    ((struct sockaddr_in *)addr)->sin_port = htons(port);
    return 0;
}
Beispiel #8
0
static void intHandler(int nr) {
    signalNumber=nr;
    udpc_fatal(1, "Signal %d: Cancelled by user\n", nr);
}
/**
 * Canonize interface name. If attempt is not NULL, pick the interface
 * which has that address.
 * If attempt is NULL, pick interfaces in the following order of preference
 * 1. eth0
 * 2. Anything starting with eth0:
 * 3. Anything starting with eth
 * 4. Anything else
 * 5. localhost
 * 6. zero address
 */
net_if_t *getNetIf(const char *wanted) {
#ifndef __MINGW32__
	struct ifreq *ifrp, *ifend, *chosen;
	struct ifconf ifc;
	int s;
#else /* __MINGW32__ */
	int i;

	int etherNo=-1;
	int wantedEtherNo=-2; /* Wanted ethernet interface */

	MIB_IPADDRTABLE *iptab=NULL;
	MIB_IFTABLE *iftab=NULL;

	MIB_IPADDRROW *iprow, *chosen=NULL;
	MIB_IFROW *chosenIf=NULL;
	WORD wVersionRequested; /* Version of Winsock to load */
	WSADATA wsaData; /* Winsock implementation details */
	ULONG a;

	int r;
#endif /* __MINGW32__ */

	int lastGoodness=0;
	struct in_addr wantedAddress;
	int isAddress=0;
	int wantedLen=0;
	net_if_t *net_if;

	if(wanted == NULL) {
	    wanted = getenv("IFNAME");
	}

	if(wanted && INET_ATON(wanted, &wantedAddress))
	    isAddress=1;
	else
	    wantedAddress.s_addr=0;

	if(wanted)
	    wantedLen=strlen(wanted);

	net_if = MALLOC(net_if_t);
	if(net_if == NULL)
	    udpc_fatal(1, "Out of memory error");

#ifndef __MINGW32__

	s = socket(PF_INET, SOCK_DGRAM, 0);
	if (s < 0) {
	    perror("make socket");
	    exit(1);
	}

	ifc.ifc_len = sizeof(struct ifreq) * 10;
	while(1) {
	    size_t len = ifc.ifc_len;
	    ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
	    if(ifc.ifc_buf == NULL) {
		udpc_fatal(1, "Out of memory error");
	    }

	    if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0 ||
		ifc.ifc_len < (signed int)sizeof(struct ifreq)) {
		perror("udpcast: SIOCGIFCONF: ");
		exit(1);
	    }

	    if(len == ifc.ifc_len) {
		ifc.ifc_len += sizeof(struct ifreq) * 10;
		free(ifc.ifc_buf);
	    } else
		break;
	}

	ifend = (struct ifreq *)((char *)ifc.ifc_buf + ifc.ifc_len);
	chosen=NULL;

	for (ifrp = (struct ifreq *) ifc.ifc_buf ; ifrp < ifend;
#ifdef IFREQ_SIZE
	     ifrp = IFREQ_SIZE(*ifrp) + (char *)ifrp
#else
	     ifrp++
#endif
	     ) {
	    unsigned long iaddr = getSinAddr(&ifrp->ifr_addr).s_addr;
	    int goodness;

	    if(ifrp->ifr_addr.sa_family != PF_INET)
		continue;

	    if(wanted) {
		if(isAddress && iaddr == wantedAddress.s_addr) {
		    goodness=8;
		} else if(strcmp(wanted, ifrp->ifr_name) ==0) {
		    /* perfect match on interface name */
		    goodness=12;
		} else if(wanted != NULL &&
			  strncmp(wanted, ifrp->ifr_name, wantedLen) ==0) {
		    /* prefix match on interface name */
		    goodness=7;
		} else {
		    /* no match, try next */
		    continue;
		}
	    } else {
		if(iaddr == 0) {
		    /* disregard interfaces whose address is zero */
		    goodness = 1;
		} else if(iaddr == htonl(0x7f000001)) {
		    /* disregard localhost type devices */
		    goodness = 2;
		} else if(strcmp("eth0", ifrp->ifr_name) == 0 ||
			  strcmp("en0",  ifrp->ifr_name) == 0) {
		    /* prefer first ethernet interface */
		    goodness = 6;
		} else if(strncmp("eth0:", ifrp->ifr_name, 5) == 0) {
		    /* second choice: any secondary addresses of first ethernet */
		    goodness = 5;
		} else if(strncmp("eth", ifrp->ifr_name, 3) == 0 ||
			  strncmp("en",  ifrp->ifr_name, 2) == 0) {
		    /* and, if not available, any other ethernet device */
		    goodness = 4;
		} else {
		    goodness = 3;
		}
	    }

	    if(hasLink(s, ifrp->ifr_name))
	      /* Good or unknown link status privileged over known
	       * disconnected */
	      goodness += 3;

	    /* If all else is the same, prefer interfaces that
	     * have broadcast */
	    goodness = goodness * 2;
	    if(goodness >= lastGoodness) {
		/* Privilege broadcast-enabled interfaces */
		if(ioctl(s,  SIOCGIFBRDADDR, ifrp) < 0)
		    udpc_fatal(-1, "Error getting broadcast address for %s: %s",
			       ifrp->ifr_name, strerror(errno));
		if(getSinAddr(&ifrp->ifr_ifru.ifru_broadaddr).s_addr)
		    goodness++;
	    }

	    if(goodness > lastGoodness) {
		chosen = ifrp;
		lastGoodness = goodness;
		net_if->addr.s_addr = iaddr;
	    }
	}


	if(!chosen) {
	    fprintf(stderr, "No suitable network interface found\n");
	    fprintf(stderr, "The following interfaces are available:\n");

	    for (ifrp = (struct ifreq *) ifc.ifc_buf ; ifrp < ifend;
#ifdef IFREQ_SIZE
		 ifrp = IFREQ_SIZE(*ifrp) + (char *)ifrp
#else
		 ifrp++
#endif
		 ) {
		char buffer[16];

		if(ifrp->ifr_addr.sa_family != PF_INET)
		    continue;

		fprintf(stderr, "\t%s\t%s\n",
			ifrp->ifr_name,
			udpc_getIpString((struct sockaddr_in *)&ifrp->ifr_addr, buffer));
	    }
	    exit(1);
	}

	net_if->name = strdup(chosen->ifr_name);

#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
	/* Index for multicast subscriptions */
	if(ioctl(s,  SIOCGIFINDEX, chosen) < 0)
	    udpc_fatal(-1, "Error getting index for %s: %s", net_if->name,
		       strerror(errno));
	net_if->index = chosen->ifr_ifindex;
#endif

	/* Broadcast */
	if(ioctl(s,  SIOCGIFBRDADDR, chosen) < 0)
	    udpc_fatal(-1, "Error getting broadcast address for %s: %s",
		       net_if->name, strerror(errno));
	net_if->bcast = getSinAddr(&chosen->ifr_ifru.ifru_broadaddr);

	close(s);
	free(ifc.ifc_buf);

#else /* __MINGW32__ */

	/* WINSOCK initialization */
	wVersionRequested = MAKEWORD(2, 0); /* Request Winsock v2.0 */
	if (WSAStartup(wVersionRequested, &wsaData) != 0) /* Load Winsock DLL */ {
	    fprintf(stderr,"WSAStartup() failed");
	    exit(1);
	}
	/* End WINSOCK initialization */


	a=0;
	r=GetIpAddrTable(iptab, &a, TRUE);
	iptab=malloc(a);
	r=GetIpAddrTable(iptab, &a, TRUE);

	a=0;
	r=GetIfTable(iftab, &a, TRUE);
	iftab=malloc(a);
	r=GetIfTable(iftab, &a, TRUE);

	if(wanted && !strncmp(wanted, "eth", 3) && wanted[3]) {
	    char *ptr;
	    int n = strtoul(wanted+3, &ptr, 10);
	    if(!*ptr)
		wantedEtherNo=n;
	}

	for(i=0; i<iptab->dwNumEntries; i++) {
	    int goodness=-1;
	    unsigned long iaddr;
	    int isEther=0;
	    MIB_IFROW *ifrow;

	    iprow = &iptab->table[i];
	    iaddr = iprow->dwAddr;

	    ifrow = getIfRow(iftab, iprow->dwIndex);

	    if(ifrow && ifrow->dwPhysAddrLen == 6 && iprow->dwBCastAddr) {
		isEther=1;
		etherNo++;
	    }

	    if(wanted) {
		if(isAddress && iaddr == wantedAddress.s_addr) {
		    goodness=8;
		} else if(isEther && wantedEtherNo == etherNo) {
			goodness=9;
		} else if(ifrow->dwPhysAddrLen) {
		    int j;
		    const char *ptr=wanted;
		    for(j=0; *ptr && j<ifrow->dwPhysAddrLen; j++) {
			int digit = strtoul(ptr, (char**)&ptr, 16);
			if(digit != ifrow->bPhysAddr[j])
			    break; /* Digit mismatch */
			if(*ptr == '-' || *ptr == ':') {
			    ptr++;
			}
		    }
		    if(!*ptr && j == ifrow->dwPhysAddrLen) {
			goodness=9;
		    }
		}
	    } else {
		if(iaddr == 0) {
		    /* disregard interfaces whose address is zero */
		    goodness = 1;
		} else if(iaddr == htonl(0x7f000001)) {
		    /* disregard localhost type devices */
		    goodness = 2;
		} else if(isEther) {
		    /* prefer ethernet */
		    goodness = 6;
		} else if(ifrow->dwPhysAddrLen) {
		    /* then prefer interfaces which have a physical address */
		    goodness = 4;
		} else {
		    goodness = 3;
		}
	    }

	    goodness = goodness * 2;
	    /* If all else is the same, prefer interfaces that
	     * have broadcast */
	    if(goodness >= lastGoodness) {
		/* Privilege broadcast-enabled interfaces */
		if(iprow->dwBCastAddr)
		    goodness++;
	    }

	    if(goodness > lastGoodness) {
		chosen = iprow;
		chosenIf = ifrow;
		lastGoodness = goodness;
	    }
	}

	if(!chosen) {
	    fprintf(stderr, "No suitable network interface found%s%s\n",
		    wanted ? " for " : "", wanted ? wanted : "");
	    fprintf(stderr, "The following interfaces are available:\n");

	    for(i=0; i<iptab->dwNumEntries; i++) {
		char buffer[16];
		struct sockaddr_in addr;
		MIB_IFROW *ifrow;
		char *name=NULL;
		iprow = &iptab->table[i];
		addr.sin_addr.s_addr = iprow->dwAddr;
		ifrow = getIfRow(iftab, iprow->dwIndex);
		name = fmtName(ifrow);
		fprintf(stderr, " %15s  %s\n",
			udpc_getIpString(&addr, buffer),
			name ? name : "");
		if(name)
		    free(name);
	    }
	    exit(1);
	}

	net_if->bcast.s_addr = net_if->addr.s_addr = chosen->dwAddr;
	if(chosen->dwBCastAddr)
	    net_if->bcast.s_addr |= ~chosen->dwMask;
	if(chosenIf) {
	    net_if->name = fmtName(chosenIf);
	} else {
	    net_if->name = "*";
	}
	free(iftab);
	free(iptab);
#endif /* __MINGW32__ */

	return net_if;
}
static int safe_inet_aton(const char *address, struct in_addr *ip) {
    if(!INET_ATON(address, ip))
	udpc_fatal(-1, "Bad address %s", address);
    return 0;
}
int startReceiver(int doWarn,
		  struct disk_config *disk_config,
		  struct net_config *net_config,
		  struct stat_config *stat_config,
		  const char *ifName)
{
    char ipBuffer[16];
    union serverControlMsg Msg;
    int connectReqSent=0;
    struct client_config client_config;
    int outFile=1;
    int pipedOutFile;
    struct sockaddr_in myIp;
    int pipePid = 0;
    int origOutFile;
    int haveServerAddress;

    client_config.sender_is_newgen = 0;

    net_config->net_if = getNetIf(ifName);
    zeroSockArray(client_config.socks, NR_CLIENT_SOCKS);

    client_config.S_UCAST = makeSocket(ADDR_TYPE_UCAST,
				       net_config->net_if,
				       0, RECEIVER_PORT(net_config->portBase));
    client_config.S_BCAST = makeSocket(ADDR_TYPE_BCAST,
				       net_config->net_if,
				       0, RECEIVER_PORT(net_config->portBase));

    if(net_config->ttl == 1 && net_config->mcastRdv == NULL) {
	getBroadCastAddress(net_config->net_if,
			    &net_config->controlMcastAddr,
			    SENDER_PORT(net_config->portBase));
	setSocketToBroadcast(client_config.S_UCAST);
    } else {
	getMcastAllAddress(&net_config->controlMcastAddr,
			   net_config->mcastRdv,
			   SENDER_PORT(net_config->portBase));
	if(isMcastAddress(&net_config->controlMcastAddr)) {
	    setMcastDestination(client_config.S_UCAST, net_config->net_if,
				&net_config->controlMcastAddr);
	    setTtl(client_config.S_UCAST, net_config->ttl);
	    
	    client_config.S_MCAST_CTRL =
		makeSocket(ADDR_TYPE_MCAST,
			   net_config->net_if,
			   &net_config->controlMcastAddr,
			   RECEIVER_PORT(net_config->portBase));
	    // TODO: subscribe address as receiver to!
	}
    }
    clearIp(&net_config->dataMcastAddr);
    udpc_flprintf("%sUDP receiver for %s at ", 
		  disk_config->pipeName == NULL ? "" :  "Compressed ",
		  disk_config->fileName == NULL ? "(stdout)":disk_config->fileName);
    printMyIp(net_config->net_if);
    udpc_flprintf(" on %s\n", net_config->net_if->name);

    connectReqSent = 0;
    haveServerAddress = 0;

    client_config.clientNumber= 0; /*default number for asynchronous transfer*/
    while(1) {
	// int len;
	int msglen;
	int sock;

	if (!connectReqSent) {
	    if (sendConnectReq(&client_config, net_config,
			       haveServerAddress) < 0) {
		perror("sendto to locate server");
	    }
	    connectReqSent = 1;
	}

	haveServerAddress=0;

	sock = udpc_selectSock(client_config.socks, NR_CLIENT_SOCKS,
			       net_config->startTimeout);
	if(sock < 0) {
		return -1;
	}

	// len = sizeof(server);
	msglen=RECV(sock, 
		    Msg, client_config.serverAddr, net_config->portBase);
	if (msglen < 0) {
	    perror("recvfrom to locate server");
	    exit(1);
	}
	
	if(getPort(&client_config.serverAddr) != 
	   SENDER_PORT(net_config->portBase))
	    /* not from the right port */
	    continue;

	switch(ntohs(Msg.opCode)) {
	    case CMD_CONNECT_REPLY:
		client_config.clientNumber = ntohl(Msg.connectReply.clNr);
		net_config->blockSize = ntohl(Msg.connectReply.blockSize);

		udpc_flprintf("received message, cap=%08lx\n",
			      (long) ntohl(Msg.connectReply.capabilities));
		if(ntohl(Msg.connectReply.capabilities) & CAP_NEW_GEN) {
		    client_config.sender_is_newgen = 1;
		    copyFromMessage(&net_config->dataMcastAddr,
				    Msg.connectReply.mcastAddr);
		}
		if (client_config.clientNumber == -1) {
		    udpc_fatal(1, "Too many clients already connected\n");
		}
		goto break_loop;

	    case CMD_HELLO_STREAMING:
	    case CMD_HELLO_NEW:
	    case CMD_HELLO:
		connectReqSent = 0;
		if(ntohs(Msg.opCode) == CMD_HELLO_STREAMING)
			net_config->flags |= FLAG_STREAMING;
		if(ntohl(Msg.hello.capabilities) & CAP_NEW_GEN) {
		    client_config.sender_is_newgen = 1;
		    copyFromMessage(&net_config->dataMcastAddr,
				    Msg.hello.mcastAddr);
		    net_config->blockSize = ntohs(Msg.hello.blockSize);
		    if(ntohl(Msg.hello.capabilities) & CAP_ASYNC)
			net_config->flags |= FLAG_PASSIVE;
		    if(net_config->flags & FLAG_PASSIVE)
			goto break_loop;
		}
		haveServerAddress=1;
		continue;
	    case CMD_CONNECT_REQ:
	    case CMD_DATA:
	    case CMD_FEC:
		continue;
	    default:
		break;
	}


	udpc_fatal(1, 
		   "Bad server reply %04x. Other transfer in progress?\n",
		   (unsigned short) ntohs(Msg.opCode));
    }

 break_loop:
    udpc_flprintf("Connected as #%d to %s\n", 
		  client_config.clientNumber, 
		  getIpString(&client_config.serverAddr, ipBuffer));

    getMyAddress(net_config->net_if, &myIp);

    if(!ipIsZero(&net_config->dataMcastAddr)  &&
       !ipIsEqual(&net_config->dataMcastAddr, &myIp) &&
       (ipIsZero(&net_config->controlMcastAddr) ||
       !ipIsEqual(&net_config->dataMcastAddr, &net_config->controlMcastAddr)
	)) {
	udpc_flprintf("Listening to multicast on %s\n",
		      getIpString(&net_config->dataMcastAddr, ipBuffer));
	client_config.S_MCAST_DATA = 
	  makeSocket(ADDR_TYPE_MCAST, net_config->net_if, 
		     &net_config->dataMcastAddr, 
		     RECEIVER_PORT(net_config->portBase));
    }


    if(net_config->requestedBufSize) {
      int i;
      for(i=0; i<NR_CLIENT_SOCKS; i++)
	if(client_config.socks[i] != -1)
	  setRcvBuf(client_config.socks[i],net_config->requestedBufSize);
    }

    outFile=openOutFile(disk_config);
    origOutFile = outFile;
    pipedOutFile = openPipe(outFile, disk_config, &pipePid);

    global_client_config= &client_config;
    atexit(sendDisconnectWrapper);
    {
	struct fifo fifo;
	int printUncompressedPos =
	    udpc_shouldPrintUncompressedPos(stat_config->printUncompressedPos,
					    origOutFile, pipedOutFile);

	receiver_stats_t stats = allocReadStats(origOutFile,
						stat_config->statPeriod,
						printUncompressedPos);
	
	udpc_initFifo(&fifo, net_config->blockSize);

	fifo.data = pc_makeProduconsum(fifo.dataBufSize, "receive");

	client_config.isStarted = 0;

	if((net_config->flags & (FLAG_PASSIVE|FLAG_NOKBD))) {
	  /* No console used */
	  client_config.console = NULL;
	} else {
	  if(doWarn)
	    udpc_flprintf("WARNING: This will overwrite the hard disk of this machine\n");
	  client_config.console = prepareConsole(0);
	  atexit(fixConsole);
	}

	spawnNetReceiver(&fifo,&client_config, net_config, stats);
	writer(&fifo, pipedOutFile);
	if(pipePid) {
	    close(pipedOutFile);
	}
	pthread_join(client_config.thread, NULL);

	/* if we have a pipe, now wait for that too */
	if(pipePid) {
	    udpc_waitForProcess(pipePid, "Pipe");
	}
#ifndef __MINGW32__
	fsync(origOutFile);
#endif /* __MINGW32__ */
	displayReceiverStats(stats, 1);

    }
    fixConsole();
    sendDisconnectWrapper();
    global_client_config= NULL;
    return 0;
}