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  }