#!/usr/bin/env python
import socket
import select
from cStringIO import StringIO
import os
clients = [] # (socket, buffer)
fqdn = socket.getfqdn()
unix_user = os.environ["USER"]
nick = unix_user # TODO: make overridable
server = "irc.freenode.net"
server_port = 6667
port_path = server
# TODO remove neccessity for that.
try:
os.unlink(port_path)
except:
pass
port_1 = socket.socket(socket.AF_UNIX)
port_1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port_1.bind(port_path)
port_1.listen(5) # TODO setting
# use IRClib? probably overkill
socket_1 = socket.socket()
socket_1.connect((server, server_port))
foo = "Gate"
socket_1.send("NICK %s\r\n" % nick)
#line NOTICE AUTH :*** No identd (auth) response
#line :sterling.freenode.net 433 * dannym :Nickname is already in use.
#line ERROR :Closing Link: 127.0.0.1 (Connection Timed Out)
# FIXME "bla" ?
socket_1.send("USER %s %s bla :%s\r\n" % (unix_user, fqdn, foo))
#read_set, write_set, except_set = select.select(set([socket_1]), set(), set(), 120)
# buffer: temp buffer (to write to)
# socket_1: socket to read from
def buffered_lined_read(buffer, socket_1):
#if socket_1 in read_set:
block = socket_1.recv(1024)
if block == "": # EOF?
return
buffer.write(block)
buffer.seek(0)
while True:
line = buffer.readline()
if not line.endswith("\n"):
break
# here, <line> is one complete line, with line terminator
# remove line terminator
line = line[:-1]
# remove "\r" which "ought" to be here
if len(line) > 0 and line[-1] == "\r":
line = line[:-1]
# here, <line> is one complete line, without line terminators
yield line
buffer.seek(0)
buffer.truncate()
buffer.write(line)
buffer = StringIO()
while True:
read_set, write_set, except_set = select.select(set(\
[socket_1, port_1] +
[client_socket for client_socket, client_buffer in clients]),
set(), set(), 120)
if read_set == set() and except_set == set():
#print "zzZZZ"
continue
if port_1 in read_set:
print "helloooo"
if len(clients) < 100: # TODO configurable
client, dummy = port_1.accept()
clients.append((client, StringIO()))
print "client", client
else:
pass # TODO reject
dead_clients = set([])
for client_socket, client_buffer in clients:
if client_socket in read_set:
print "got stuff"
for line in buffered_lined_read(client_buffer, client_socket):
# send stuff to IRC server
socket_1.send(line + "\r\n")
if client_socket in except_set:
client_socket.close() # shutdown(1)
dead_clients.append(client_socket)
# remove dead clients
clients = [(client_socket, client_buffer)
for client_socket, client_buffer in clients
if client_socket not in dead_clients]
if socket_1 in read_set:
# read as many complete lines from IRC as possible, storing excess in buffer
for line in buffered_lined_read(buffer, socket_1):
print "line", line
# traverse all clients in order
for client_socket, client_buffer in clients:
# send line(s) to that client
client_socket.send(line + "\r\n")
parts = line.split(" ", 1)
# line PING :sterling.freenode.net
if len(parts) > 1:
command = parts[0]
argument_string = parts[1]
else:
command = parts[0]
argument_string = ""
if command == "PING":
#print "ping..."
response = "PONG %s\r\n" % argument_string
#print "response", response
socket_1.send(response)