Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
DigitalMarc committed Jul 11, 2016
0 parents commit df0c739
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 0 deletions.
Binary file added client/client
Binary file not shown.
Binary file added client/client.exe
Binary file not shown.
149 changes: 149 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package main

import (
"bufio"
"fmt"
"net"
"os"
"strconv"
"strings"
"time"

"github.com/digitalmarc/go/udp-chat/common"
"github.com/nu7hatch/gouuid"
)

type Client struct {
connection *net.UDPConn
alive bool
userID uuid.UUID
userName string
sendingMessageQueue chan string
receiveMessages chan string
}

var scanError error

func (c *Client) packMessage(msg string, messageType common.MessageType) string {
return strings.Join([]string{c.userID.String(), strconv.Itoa(int(messageType)), c.userName, msg, time.Now().Format("15:04:05")}, "\x01")
}

func (c *Client) funcSendMessage(msg string) {
message := c.packMessage(msg, common.FUNC)
_, err := c.connection.Write([]byte(message))
checkError(err, "func_sendMessage")
}

func (c *Client) sendMessage() {
for c.alive {

msg := <-c.sendingMessageQueue
message := c.packMessage(msg, common.CLASSIQUE)
_, err := c.connection.Write([]byte(message))
checkError(err, "sendMessage")
}

}

func (c *Client) receiveMessage() {
var buf [512]byte
//var userID *uuid.UUID
for c.alive {
n, err := c.connection.Read(buf[0:])
checkError(err, "receiveMessage")
//msg := string(buf[0:n])
//stringArray := strings.Split(msg, "\x01")

//userID, err = uuid.ParseHex(stringArray[0])
//checkError(err, "receiveMessage")
//if *userID != c.userID {
c.receiveMessages <- string(buf[0:n])
fmt.Println("")
//}
}
}

func (c *Client) readInput() {
var msg string
for c.alive {
fmt.Println("msg: ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
msg = scanner.Text()
if msg == ":quit" || msg == ":q" {
c.alive = false
}
c.sendingMessageQueue <- msg
}
//_,scanError := fmt.Scanln(&msg)
//checkError(scanError, "readInput")

}
}

func (c *Client) printMessage() {
for c.alive {
msg := <-c.receiveMessages
stringArray := strings.Split(msg, "\x01")
var userName = stringArray[2]
var content = stringArray[3]
var time = stringArray[4]
fmt.Printf("%s %s: %s", time, userName, content)
fmt.Println("")
// pf("MESSAGE RECEIVED: %s \n", msg)
// pf("USER NAME: %s \n", stringArray [2])
// pf("CONTENT: %s \n", stringArray [3])
if strings.HasPrefix(msg, ":q") || strings.HasPrefix(msg, ":quit") {
fmt.Printf("%s is leaving", userName)
}
}
}

func nowTime() string {
return time.Now().String()
}
func checkError(err error, funcName string) {
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error:%s-----in func:%s", err.Error(), funcName)
os.Exit(1)
}
}
func main() {
// if len(os.Args) != 2 {
// fmt.Fprintf(os.Stderr, "Usage:%s host:port", os.Args[0])
// os.Exit(1)
// }
// service := os.Args[1]
// udpAddr, err := net.ResolveUDPAddr("udp4", service)
udpAddr, err := net.ResolveUDPAddr("udp4", "78.242.118.156:1200")
checkError(err, "main")

var c Client
c.alive = true
c.sendingMessageQueue = make(chan string)
c.receiveMessages = make(chan string)
u, err := uuid.NewV4()

c.userID = *u

fmt.Println("input name: ")
_, err = fmt.Scanln(&c.userName)
checkError(err, "main")

c.connection, err = net.DialUDP("udp", nil, udpAddr)
checkError(err, "main")
defer c.connection.Close()

c.funcSendMessage("joined")

go c.printMessage()
go c.receiveMessage()

go c.sendMessage()
c.readInput()

c.funcSendMessage("left")

os.Exit(0)
}
18 changes: 18 additions & 0 deletions common/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package common

// MessageType designate the type of a message send from a client
type MessageType int
const (
// FUNC for functionnal messages ie technical messages from the client to the server
FUNC MessageType = iota
// CLASSIQUE message for messages sent by the end user
CLASSIQUE
)


// ConnectionStatus is self explained
type ConnectionStatus int
const (
JOINING ConnectionStatus = iota
LEAVING
)
7 changes: 7 additions & 0 deletions cross-compile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
https://golang.org/doc/install/source#environment

$env:GOOS = "linux"
$env:GOARCH="amd64"

$env:GOOS = "windows"
$env:GOARCH="amd64"
Binary file added server/server.exe
Binary file not shown.
130 changes: 130 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package main

import (
"fmt"
"net"
"os"
"strconv"
"strings"
"github.com/digitalmarc/go/udp-chat/common"
"github.com/nu7hatch/gouuid"
)

const (
port string = ":1200"
)

var p = fmt.Println
var pf = fmt.Printf

type Server struct {
conn *net.UDPConn
messages chan string
clients map[*uuid.UUID]Client
}

type Client struct {
userID uuid.UUID
userName string
userAddr *net.UDPAddr
}

type Message struct {
messageType common.MessageType
userID *uuid.UUID
userName string
content string
connectionStatus common.ConnectionStatus
time string
}

func (server *Server) handleMessage() {
var buf [512]byte

n, addr, err := server.conn.ReadFromUDP(buf[0:])
if err != nil {
return
}

msg := string(buf[0:n])
m := server.parseMessage(msg)

if m.connectionStatus == common.LEAVING {
delete(server.clients, m.userID)
server.messages <- msg
pf("%s left", m.userName)
} else {
switch m.messageType {
case common.FUNC:
var c Client
c.userAddr = addr
c.userID = *m.userID
c.userName = m.userName
server.clients[m.userID] = c
server.messages <- msg
pf("%s joining", m.userName)
case common.CLASSIQUE:

pf("%s %s: %s", m.time, m.userName, m.content)
server.messages <- msg
}
}
}

func (s *Server) parseMessage(msg string) (m Message) {
stringArray := strings.Split(msg, "\x01")

fmt.Println("")
m.userID, _ = uuid.ParseHex(stringArray[0])
messageTypeStr, _ := strconv.Atoi(stringArray[1])
m.messageType = common.MessageType(messageTypeStr)
m.userName = stringArray[2]
m.content = stringArray[3]
m.time = stringArray[4]
// pf("MESSAGE RECEIVED: %s \n", msg)
// pf("USER NAME: %s \n", stringArray [2])
// pf("CONTENT: %s \n", stringArray [3])
if strings.HasPrefix(msg, ":q") || strings.HasPrefix(msg, ":quit") {
pf("%s is leaving", m.userName)
m.connectionStatus = common.LEAVING
}
return
}

func (s *Server) sendMessage() {
for {
msg := <-s.messages
//p(00, sendstr)
for _, c := range s.clients {
_, err := s.conn.WriteToUDP([]byte(msg), c.userAddr)
//pf("Bytes read %d, error: %v", n, err)
checkError(err)
}
}

}

func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error:%s", err.Error())
os.Exit(1)
}
}

func main() {
udpAddress, err := net.ResolveUDPAddr("udp4", port)
checkError(err)

var s Server
s.messages = make(chan string, 20)
s.clients = make(map[*uuid.UUID]Client, 0)

s.conn, err = net.ListenUDP("udp", udpAddress)
checkError(err)

go s.sendMessage()

for {
s.handleMessage()
}
}

0 comments on commit df0c739

Please sign in to comment.