Browse Source

initial commit

tags/v0.1.0
Jeremy Latt 12 years ago
commit
a427e2bb47
6 changed files with 175 additions and 0 deletions
  1. 3
    0
      .gitignore
  2. 11
    0
      goircd.go
  3. 28
    0
      src/irc/client.go
  4. 46
    0
      src/irc/net.go
  5. 43
    0
      src/irc/protocol.go
  6. 44
    0
      src/irc/server.go

+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
1
+pkg
2
+bin
3
+goircd

+ 11
- 0
goircd.go View File

@@ -0,0 +1,11 @@
1
+package main
2
+// http://tools.ietf.org/html/rfc1459
3
+
4
+import (
5
+	"irc"
6
+)
7
+
8
+func main() {
9
+	server := irc.NewServer()
10
+	server.Listen(":6697")
11
+}

+ 28
- 0
src/irc/client.go View File

@@ -0,0 +1,28 @@
1
+package irc
2
+
3
+import (
4
+	"net"
5
+)
6
+
7
+
8
+type Client struct {
9
+	conn net.Conn
10
+	ch chan Message
11
+}
12
+
13
+func NewClient(conn net.Conn) *Client {
14
+	return &Client{conn, NewMessageChan(NewStringChan(conn))}
15
+}
16
+
17
+// Write messages from the client to the server.
18
+func (c *Client) Communicate(server chan Message) {
19
+	for message := range c.ch {
20
+		message.client = c
21
+		server <- message
22
+	}
23
+	c.Close()
24
+}
25
+
26
+func (c *Client) Close() {
27
+	c.conn.Close()
28
+}

+ 46
- 0
src/irc/net.go View File

@@ -0,0 +1,46 @@
1
+package irc
2
+
3
+import (
4
+	"bufio"
5
+	"log"
6
+	"net"
7
+)
8
+
9
+// Adapt `net.Conn` to a `chan string`.
10
+func NewStringChan(conn net.Conn) chan string {
11
+	ch := make(chan string)
12
+	rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
13
+
14
+	done := make(chan bool)
15
+	go func() {
16
+		<- done
17
+		close(ch)
18
+	}()
19
+
20
+	// conn -> ch
21
+	go func() {
22
+		for {
23
+			line, err := rw.ReadString('\n')
24
+			if err != nil {
25
+				log.Print("StringChan[read]: %v", err)
26
+				break
27
+			}
28
+			ch <- line
29
+		}
30
+		done <- true
31
+	}()
32
+
33
+	// ch -> conn
34
+	go func() {
35
+		for str := range ch {
36
+			if _, err := rw.WriteString(str + "\r\n"); err != nil {
37
+				log.Print("StringChan[write]: %v", err)
38
+				break
39
+			}
40
+			rw.Flush()
41
+		}
42
+		done <- true
43
+	}()
44
+
45
+	return ch
46
+}

+ 43
- 0
src/irc/protocol.go View File

@@ -0,0 +1,43 @@
1
+package irc
2
+
3
+import (
4
+)
5
+
6
+type Message struct {
7
+	line string
8
+	client *Client
9
+}
10
+
11
+func (m *Message) Encode() string {
12
+	return m.line
13
+}
14
+
15
+
16
+// Adapt `chan string` to a `chan Message`.
17
+func NewMessageChan(strch chan string) chan Message {
18
+	msgch := make(chan Message)
19
+
20
+	done := make(chan bool)
21
+	go func() {
22
+		<- done
23
+		close(msgch)
24
+	}()
25
+
26
+	// str -> msg
27
+	go func() {
28
+		for str := range strch {
29
+			msgch <- Message{str, nil}
30
+		}
31
+		done <- true
32
+	}()
33
+
34
+	// msg -> str
35
+	go func() {
36
+		for message := range msgch {
37
+			strch <- message.Encode()
38
+		}
39
+		done <- true
40
+	}()
41
+
42
+	return msgch
43
+}

+ 44
- 0
src/irc/server.go View File

@@ -0,0 +1,44 @@
1
+package irc
2
+
3
+import (
4
+	"log"
5
+	"net"
6
+)
7
+
8
+type Server struct {
9
+	ch chan Message
10
+}
11
+
12
+func NewServer() *Server {
13
+	server := Server{make(chan Message)}
14
+	go server.Receive()
15
+	return &server
16
+}
17
+
18
+func (s *Server) Listen(addr string) {
19
+	listener, err := net.Listen("tcp", addr)
20
+	if err != nil {
21
+		log.Fatal("Server.Listen: %v", err)
22
+	}
23
+
24
+	for {
25
+		conn, err := listener.Accept()
26
+		if err != nil {
27
+			log.Print("Server.Listen: %v", err)
28
+			continue
29
+		}
30
+		client := NewClient(conn)
31
+		go client.Communicate(s.ch)
32
+	}
33
+}
34
+
35
+func (s *Server) Receive() {
36
+	for message := range s.ch {
37
+		log.Print("Server.Receive: %v", message.line)
38
+		message.client.ch <- Message{"pong: " + message.line, nil}
39
+	}
40
+}
41
+
42
+func (s *Server) Close() {
43
+	close(s.ch)
44
+}

Loading…
Cancel
Save