basic functionality

This commit is contained in:
Andreas Neue 2016-09-02 07:27:25 +02:00
parent 6f558fd5a2
commit 5c363132fa
2 changed files with 195 additions and 0 deletions

84
ircconn.go Normal file
View File

@ -0,0 +1,84 @@
// vim:ts=4:sts=4:sw=4:noet:tw=72
package main
import (
"bufio"
"net"
"strings"
"time"
)
type IRCConn struct {
conn net.Conn
read chan string
write chan string
done chan bool
closed bool
}
func NewIRCConn(conn net.Conn, done chan bool) *IRCConn {
read := make(chan string, 1024)
write := make(chan string, 1024)
c := &IRCConn{conn: conn, read: read, write: write, done: done, closed: false}
go c.reader()
go c.writer()
return c
}
func (c *IRCConn) Read() string {
select {
case s := <-c.read:
return s
default:
return ""
}
}
func (c *IRCConn) Write(s string) {
c.write <- s
}
func (c *IRCConn) Close() {
c.conn.Close()
c.closed = true
}
func (c *IRCConn) reader() {
input := bufio.NewReader(c.conn)
for {
s, err := input.ReadString('\n')
if err != nil {
c.done <- true
return
}
s = strings.Trim(s, "\r\n")
c.read <- s
}
}
func (c *IRCConn) writer() {
for {
select {
case line := <-c.write:
written := 0
bytes := []byte(line + "\r\n")
for written < len(line) {
n, err := c.conn.Write(bytes[written:])
if err != nil {
c.done <- true
return
}
written += n
}
default:
if c.closed {
return
}
time.Sleep(1 * time.Millisecond)
}
}
}

111
main.go Normal file
View File

@ -0,0 +1,111 @@
// vim:ts=4:sts=4:sw=4:noet:tw=72
package main
import (
"flag"
"fmt"
"log"
"net"
"strings"
"time"
"code.dnix.de/an/irc"
"code.dnix.de/an/xlog"
)
var saddr = flag.String("server", "irc.example.com:6667", "Server address")
var laddr = flag.String("listen", "0.0.0.0:6667", "Listen address")
func init() {
flag.Parse()
}
func main() {
listen, err := net.Listen("tcp", *laddr)
if err != nil {
xlog.Fatal(err.Error())
return
}
for {
cconn, err := listen.Accept()
if err != nil {
log.Println(err)
continue
}
go bounce(cconn, saddr)
}
}
func bounce(cconn net.Conn, saddr *string) {
done := make(chan bool, 5)
client := NewIRCConn(cconn, done)
defer func() {
client.Close()
}()
sconn, err := net.Dial("tcp", *saddr)
if err != nil {
log.Println(err)
return
}
server := NewIRCConn(sconn, done)
defer func() {
server.Close()
}()
if !login(server, client) {
return
}
go relay(server, client)
go relay(client, server)
<-done
}
func login(server, client *IRCConn) bool {
nick := ""
user := ""
pass := ""
for {
s := client.Read()
msg := irc.Parse(s)
msg.Cmd = strings.ToUpper(msg.Cmd)
switch msg.Cmd {
case "PASS":
pass = msg.Args[0]
case "USER":
user = msg.Args[0]
case "NICK":
nick = msg.Args[0]
}
if nick != "" && user != "" {
if authenticate(nick, pass) {
server.Write(fmt.Sprintf("NICK %s", nick))
server.Write(fmt.Sprintf("USER %s %s %s :%s", user, user, user, user))
return true
} else {
return false
}
}
}
}
func authenticate(name, password string) bool {
return true
}
func relay(conn1 *IRCConn, conn2 *IRCConn) {
for {
if conn1.closed || conn2.closed {
return
}
s := conn1.Read()
if s != "" {
conn2.Write(s)
}
time.Sleep(1 * time.Millisecond)
}
}