#!/usr/bin/python
#
# fishpoll - client for fishpolld server
#
# Copyright (C) 2008  Owen Taylor
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, If not, see
# http://www.gnu.org/licenses/.

from optparse import OptionParser
import re
import select
import sys
import socket
from StringIO import StringIO
import time

FISHPOLL_PORT = 27527

def read_all(s, max_bytes, timeout):
    start = time.time()
    bytes_read = 0
    buf = StringIO()
    while True:
        now = time.time()
        to_wait = start + timeout - now
        if to_wait <= 0:
            raise RuntimeError("Timed out")

        if bytes_read >= max_bytes:
            raise RuntimeError("Too much data")

        read_ready, _, _, = select.select([s.fileno()], [], [], to_wait)
        if read_ready:
            bytes = s.recv(max_bytes - bytes_read)
            if (bytes == ""):
                break
            bytes_read += len(bytes)
            buf.write(bytes)

    return buf.getvalue()

def main():
    global options

    usage = "usage: %prog HOST[:PORT] TOPIC [SUBJECT...]"
    parser = OptionParser(usage=usage)
    options, args = parser.parse_args()
    if len(args) < 2:
        parser.print_usage()
        sys.exit(1)

    host = args[0]
    topic = args[1]
    subjects = args[2:]

    m = re.match(r"^(.*?)(?::(\d+))?$", host)
    host = m.group(1)
    if m.group(2) != None:
        port = int(m.group(2))
    else:
        port = FISHPOLL_PORT

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        sock.connect((host, port))
    except socket.error, e:
        print >>sys.stderr, "Can't connect to server: %s" % e.args[1]
        sys.exit(1)

    message = topic + " " + " ".join(subjects) + "\n"

    try:
        sock.sendall(message)
    except socket.error, e:
        print >>sys.stderr, "Can't send message: %s" % e.args[1]
        sys.exit(1)

    response = read_all(sock, max_bytes=512, timeout=300)
    if response.strip() != "OK":
        sys.stderr.write(response)
        sys.exit(1)

    sock.close()

if __name__ == '__main__':
    main()
