$socket->send("file\n");
$socket->send("$fileName\n");
$socket->send("$fileHash\n");
- sleep 2;
- $socket->recv(my $port, 128);
- ($port) = $port =~ m/(\d+)/;
+ $socket->recv(my $ignored, 128);
+ my $port = undef;
+ my $r;
+ my $sleeptime = 2;
+ my $attemptcount = 0;
+ while (! defined $port) {
+ sleep $sleeptime;
+ $sleeptime *= 2;
+ $sleeptime = 10 if ($sleeptime > 10);
+ $socket->recv($r, 128);
+ ($port) = $r =~ m/(\d+)/;
+ $attemptcount += 1;
+ if ($attemptcount >= 5) {
+ print_log "File: upload failure ($file)";
+ exit;
+ }
+ }
# Send file once
print_log "File: upload port is $port ($file)";
FILENAME="${FILENAME}_${SUFFIX}"
fi
+ # Grab an open port and listen for file. Use netcat since sh can't
+ # handle binary data well
+ ATTEMPTCOUNT=0
+ SLEEPTIME=0
+ while true; do
+ sleep $(( RANDOM % (SLEEPTIME + 5) + 1 ))
+ PORT=$(( (RANDOM * 2 + RANDOM % 2) % 64511 + 1024 ))
+ nc -w 7 -l -p "$PORT" > "$FILENAME" 2>/dev/null &
+ NC_PID=$!
+ # Wait for nc to fail. There seems to be a bug with busybox sh where
+ # using the builtin sleep when following the backgrounded nc
+ # doesn't sleep, so calling the binary again
+ ../../../busybox sleep 1
+ if ps -o pid | grep -q -e $NC_PID ; then
+ break
+ fi
+ ATTEMPTCOUNT=$(( ATTEMPTCOUNT + 1 ))
+ SLEEPTIME=$(( SLEEPTIME + 2 ))
+ if [ $ATTEMPTCOUNT -gt 5 ]; then
+ echo "$CLIENTNAME: ($FILENAME) Failed to bind open port for file transfer, giving up" >&2
+ echo "[${FILERECVTIME}] File transfer failed: ${FILENAME}" >> _files.log
+ exit
+ fi
+ done
+ echo "$PORT"
+ wait $NC_PID
+
FILERECVTIME="$(date '+%Y-%m-%d %H:%M:%S')"
echo "[${FILERECVTIME}] File received: ${FILENAME}" >> _files.log
- # Client should send with `cat file | nc ip port`
- PORT=$(( (RANDOM * 2 + RANDOM % 2) % 64511 + 1024 ))
- echo "$PORT"
- nc -w 5 -l -p "$PORT" > "$FILENAME"
-
HASH=$(md5sum "$FILENAME" | cut -d' ' -f1)
if [ "$HASH" != "$TMPHASH" ]; then
echo "Checksum error"