Add telnet file with support to send and receive text from Merc MUD
[midgaard_bot.git] / telnet.go
1 /*
2 midgaard_bot, a Telegram bot which sets a bridge to Midgaard Merc MUD
3 Copyright (C) 2017 by Javier Sancho Fernandez <jsf at jsancho dot org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package main
20
21 import (
22         "bytes"
23         "time"
24
25         "github.com/reiver/go-oi"
26         "github.com/reiver/go-telnet"
27 )
28
29 type TelnetCaller struct {
30         Input chan string
31         Output chan string
32 }
33
34 func (caller TelnetCaller) CallTELNET(ctx telnet.Context, writer telnet.Writer, reader telnet.Reader) {
35
36         // Send text to MUD
37         go func() {
38                 var buffer bytes.Buffer
39                 var p []byte
40
41                 crlfBuffer := [2]byte{'\r', '\n'}
42                 crlf := crlfBuffer[:]
43
44                 for {
45                         message := <-caller.Input
46                         buffer.Write([]byte(message))
47                         buffer.Write(crlf)
48
49                         p = buffer.Bytes()
50                         oi.LongWrite(writer, p)
51                         buffer.Reset()
52                 }
53         }()
54
55         // Receive text from MUD
56         chunks := make(chan string)
57         chunk := ""
58         
59         go func() {
60                 var buffer [1]byte
61                 p := buffer[:]
62
63                 for {
64                         n, err := reader.Read(p)
65                         if n <= 0 && err == nil {
66                                 continue
67                         } else if n <= 0 && err != nil {
68                                 break
69                         }
70
71                         chunks <- string(p)
72                 }
73         }()
74
75         for {
76                 select {
77                 case input := <-chunks:
78                         chunk = input
79                         for chunk != "" {
80                                 select {
81                                 case input := <-chunks:
82                                         chunk = chunk + input
83                                 case <-time.After(time.Millisecond * 500):
84                                         caller.Output <- chunk
85                                         chunk = ""
86                                 }
87                         }
88                 }
89         }
90 }