github.com/Ryan-Johnson-1315/socketlogger@v0.0.2/client.go (about) 1 package socketlogger 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "net" 8 "time" 9 ) 10 11 type Client interface { 12 Connect(client, server Connection) error 13 Disconnect() 14 15 start() 16 buildSocket(local, remote Connection) (string, net.Conn, error) 17 writeOverSocket(chan SocketMessage) 18 setMsgChannel(chan SocketMessage) 19 init(i interface{}) 20 } 21 22 type client struct { 23 comms 24 msgsToSend chan SocketMessage 25 remoteAddr net.Addr 26 this interface{} 27 disconnected chan bool 28 } 29 30 func (c *client) Connect(client, server Connection) error { 31 var err error = nil 32 inst, ok := c.this.(Client) 33 if !ok { 34 err = fmt.Errorf(`type is not interface type "Server". Type %t`, c.this) 35 } else { 36 c.connectionProtocol, c.sock, err = inst.buildSocket(client, server) 37 c.msgsToSend <- newLogMessage(MessageLevelSuccess, "Built %s at %s", c.connectionProtocol, c.sock.LocalAddr()) 38 c.disconnected = make(chan bool) 39 } 40 c.start() 41 return err 42 } 43 44 func (c *client) Disconnect() { 45 close(c.msgsToSend) 46 <-c.disconnected 47 } 48 49 func (c *client) start() { 50 c.this.(Client).setMsgChannel(c.msgsToSend) 51 go c.this.(Client).writeOverSocket(c.msgsToSend) 52 } 53 54 func (c *client) init(i interface{}) { 55 if inst, ok := i.(Client); !ok { 56 panic(fmt.Errorf("instance is not of type Client! Type: %T", inst)) 57 } else { 58 c.this = i 59 c.msgsToSend = make(chan SocketMessage, 100) 60 } 61 } 62 63 type udpClient struct { 64 client 65 } 66 67 func (u *udpClient) buildSocket(local Connection, remote Connection) (string, net.Conn, error) { 68 sock, err := net.ListenUDP(udpProtocol, &net.UDPAddr{ 69 IP: net.ParseIP(local.Addr), 70 Port: local.Port, 71 }) 72 73 u.remoteAddr = &net.UDPAddr{ 74 IP: net.ParseIP(remote.Addr), 75 Port: remote.Port, 76 } 77 return "UDP Client", sock, err 78 } 79 80 func (u *udpClient) writeOverSocket(msgsToSend chan SocketMessage) { 81 sock, goodSock := u.sock.(*net.UDPConn) 82 addr, goodAddr := u.remoteAddr.(*net.UDPAddr) 83 84 if !goodSock || !goodAddr { 85 panic(fmt.Errorf("udp client socket/server addr is not *net.UDPConn/*net.UDPAddr. Type: %T/%T", sock, addr)) 86 } else { 87 for msg := range msgsToSend { 88 bytes, _ := json.Marshal(msg) 89 sock.WriteToUDP(bytes, addr) 90 } 91 sock.Close() 92 u.disconnected <- true // Notify that we have finished writing 93 } 94 } 95 96 type tcpClient struct { 97 client 98 connected bool 99 } 100 101 func (t *tcpClient) buildSocket(local Connection, remote Connection) (string, net.Conn, error) { 102 tcpAddr, err := net.ResolveTCPAddr(tcpProtocol, fmt.Sprintf("%s:%d", remote.Addr, remote.Port)) 103 if err != nil { 104 log.Fatal(err) 105 } 106 107 sock, err := net.DialTCP(tcpProtocol, nil, tcpAddr) 108 if err != nil { 109 log.Fatal(err) 110 } else { 111 time.Sleep(50 * time.Millisecond) 112 } 113 114 t.connected = (err == nil) 115 return "TCP Client", sock, err 116 } 117 118 func (t *tcpClient) writeOverSocket(msgsToSend chan SocketMessage) { 119 if t.connected { 120 sock, ok := t.sock.(*net.TCPConn) 121 if !ok { 122 log.Fatal(fmt.Errorf("socket is not *net.TCPConn type. Type: %T", t.sock)) 123 } else { 124 for msg := range msgsToSend { 125 bytes, _ := json.Marshal(msg) 126 sock.Write(bytes) 127 } 128 sock.Close() 129 t.disconnected <- true // Notify that we have finished sending over socket 130 } 131 } 132 }