#!/usr/bin/python3 -BEsStt
"""This client connects to a sync service and sends requests from
stdin and prints the responses. This can be used for testing of
StreamRequestResponseMultiplexer from guerillabackup.Transfer.
See source of StreamRequestResponseMultiplexer for description
of protocol structure."""

import sys
sys.path = sys.path[1:] + ['/usr/lib/guerillabackup/lib', '/etc/guerillabackup/lib-enabled']

import errno
import fcntl
import os
import socket
import struct

if len(sys.argv) != 2:
  print('Usage %s [target]' % sys.argv[0], file=sys.stderr)
  sys.exit(1)

connectAddress = sys.argv[1]

clientSocket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
clientSocket.connect(connectAddress)
print('Connected to %s' % repr(connectAddress), file=sys.stderr)

flags = fcntl.fcntl(clientSocket.fileno(), fcntl.F_GETFL)
fcntl.fcntl(clientSocket.fileno(), fcntl.F_SETFL, flags|os.O_NONBLOCK)

remoteData = b''
while True:
  readData = None
  try:
    readData = clientSocket.recv(1<<20)
  except socket.error as receiveError:
    if receiveError.errno == errno.EAGAIN:
      readData = b''
    else:
      raise

  if len(readData) != 0:
    print('Received %d bytes of remote data' % len(readData), file=sys.stderr)
    remoteData += readData
  if len(remoteData) >= 5:
    if remoteData[0] not in b'APRS':
      print('Invalid remote data package type %s, purging data %s' % (
          repr(remoteData[0]), repr(remoteData)), file=sys.stderr)
      remoteData = b''
    else:
      remoteDataLength = struct.unpack('<I', remoteData[1:5])[0]
      print('Packet length is %d' % remoteDataLength, file=sys.stderr)
      if (remoteDataLength < 0) or (remoteDataLength > (1<<20)):
        print('Invalid remote data length %d, purging data %s' % (
            remoteDataLength, repr(remoteData)), file=sys.stderr)
        remoteData = b''
      elif remoteDataLength+5 <= len(remoteData):
        print('Received valid packet %s' % repr(remoteData[0:1]+remoteData[5:5+remoteDataLength]),
              file=sys.stderr)
        remoteData = remoteData[5+remoteDataLength:]
# Try again to read more data
        continue

# No remote data to dump, try to read a command
  commandLine = sys.stdin.readline()
  if commandLine == '':
# End of input.
    break

  commandLine = commandLine[:-1]
  if commandLine == '':
    continue

  commandLength = commandLine.find(' ')
  if commandLength < 0:
    commandLength = len(commandLine)
  command = commandLine[:commandLength]

  if command == 'send':
    sendData = bytes(commandLine[commandLength+1:], sys.getdefaultencoding())
    if (len(sendData) == 0) or (sendData[0] not in b'APRS'):
      print('Send data has to start with type letter, optionally ' \
          'followed by data %s' % repr(sendData), file=sys.stderr)
      continue

    sendData = sendData[0:1]+struct.pack('<I', len(sendData)-1)+sendData[1:]
    sendPos = 0
    while sendPos < len(sendData):
      sendLength = clientSocket.send(sendData[sendPos:])
      sendPos += sendLength
    continue

  print('Unknown command %s' % repr(command), file=sys.stderr)
