basic functionality
This commit is contained in:
parent
6f558fd5a2
commit
5c363132fa
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue