Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}
45 changes: 31 additions & 14 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"encoding/json"
"fmt"
"time"
)

Expand All @@ -10,18 +11,25 @@ type ChatMessage struct {
User string `json:"user"`
}

var lastTimestamp int
var lastTimestamp = map[string]int{}
var initalizedChannels = map[string]bool{}

func runClientSender(msg string) {
msgJson := ChatMessage{Message: msg, User: *user}
chanNum := 0
fmt.Sscanf(activeChannel,"channel %d",&chanNum)//parce activeChannel number to chanNum
pass := channelPass(chanNum)
msgJson := ChatMessage{Message: msg, User: currentUser}
jsonBytes, _ := json.Marshal(msgJson)
hash := passHash(*pass)
sendBytes(append(hash, encryptToBytes(jsonBytes, []byte(*pass))...), *ip)
hash := passHash(pass)
sendBytes(append(hash, encryptToBytes(jsonBytes, []byte(currentPass))...), *ip)
}

func runClientListener() {
func runClientListener(chanNum int) {
channel := currentChannel(chanNum)
name := currentChannel(chanNum)
pass := channelPass(chanNum)
for {
passwordHashBytes := passHash(*pass)
passwordHashBytes := passHash(pass)
responseBytes := sendBytes(passwordHashBytes, *ip)
responseStr := decryptFromBytes(responseBytes, passwordHashBytes)
var response MsgRecord
Expand All @@ -31,22 +39,31 @@ func runClientListener() {
continue
}
var incomingMsgJson ChatMessage
msgTextStr := decryptUsingPass(response.LastMsgEncrypted, *pass)
msgTextStr := decryptUsingPass(response.LastMsgEncrypted, pass)
json.Unmarshal([]byte(msgTextStr), &incomingMsgJson)
if response.LastMsgTimestamp != lastTimestamp {
if incomingMsgJson.Message == "" && incomingMsgJson.User == "" {
tuiPrint("Chat begins here")
if response.LastMsgTimestamp != lastTimestamp[name] {
if incomingMsgJson.Message == "" && incomingMsgJson.User == "" && !initalizedChannels[channel]{
tuiPrint(channel,name,"Chat begins here")
initalizedChannels[channel] = true
} else {
tuiPrint(incomingMsgJson.User + ": " + incomingMsgJson.Message)
tuiPrint(channel,name,incomingMsgJson.User + ": " + incomingMsgJson.Message)
}
if response.LastMsgTimestamp != lastTimestamp[name]{//make match global
lastTimestamp[name] = response.LastMsgTimestamp
}
lastTimestamp = response.LastMsgTimestamp
}
time.Sleep(1 * time.Second)
time.Sleep(300 * time.Millisecond)
}
}

func listenClient(){//listens on all channels
for i := 0; i < listNum; i++{
go runClientListener(i)
}
}

func runClient() {
initTUI(runClientSender)
go runClientListener()
//go runClientListener()
runTUI()
}
2 changes: 1 addition & 1 deletion encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"crypto/rand"
"crypto/sha256"

"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/chacha20poly1305"//if throwing errors, use "go get golang.com/..."
"golang.org/x/crypto/scrypt"
)

Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func main() {
enableKernelReplies(true)
} else if *server {
enableKernelReplies(false)
runServer()
listenForPackets()
} else {
runClient()
}
Expand Down
6 changes: 3 additions & 3 deletions networking.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func makeChecksum(b []byte) uint16 {
func enableKernelReplies(val bool) {
option := "0"
if !val {
option = "1"
option = "1" //1 makes system ignore incoming pings
}
err := os.WriteFile("/proc/sys/net/ipv4/icmp_echo_ignore_all", []byte(option), 0644)
processErr(err)
Expand All @@ -42,10 +42,10 @@ func sendBytes(data []byte, dest string) []byte {
defer c.Close()

dst, _ := net.ResolveIPAddr("ip4", dest)
c.WriteTo(buf, dst)
c.WriteTo(buf, dst)//Send packets

recv := make([]byte, 1500)
c.SetReadDeadline(time.Now().Add(3 * time.Second))
c.SetReadDeadline(time.Now().Add(1 * time.Second))
for {
n, addr, err := c.ReadFrom(recv)
if err != nil {
Expand Down
4 changes: 0 additions & 4 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,3 @@ func sendReply(ip string, incomingPayload []byte) []byte {
recordJson, _ := json.Marshal(record)
return encryptToBytes(recordJson, key)
}

func runServer() {
listenForPackets()
}
113 changes: 95 additions & 18 deletions tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,91 @@ package main

import (
"fmt"

"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)

var (
app *tview.Application
msgView *tview.TextView
msgView map[string]*tview.TextView
listNum int = 5
activeChannel string = "channel 0"
currentUser string//both of these are assigned in sign in window
currentPass string//passed tp client.go
)

func initTUI(onSend func(string)) {
app = tview.NewApplication()
pages := tview.NewPages()
msgView = make(map[string]*tview.TextView)
chanPages := tview.NewPages()
var firstInput *tview.InputField

for i := 0; i < listNum; i++ {//initalize pages on per-channel basis
name := fmt.Sprintf("channel %d", i)
view, prim, input:= channel(name, onSend,)//channel returns TextView and Primitive
msgView[name] = view
if i == 0{
firstInput = input//
}
chanPages.AddPage(name,prim,true,i == 0)
}

list := tview.NewList()//initalize list
for i := 0; i < listNum; i++ {
name := fmt.Sprintf("channel %d", i)
list.AddItem(name,"",0, func(){
activeChannel = name
chanPages.SwitchToPage(name)//switches chan pages, not page
})
}


chat := tview.NewFlex().SetDirection(tview.FlexRow).//adds everything to flex, to be refrenced later
AddItem(chanPages,0,1, true)
mainView := tview.NewFlex().
AddItem(list,20,0,false).
AddItem(chat,0,1,true)

signIn := tview.NewForm()//input form, ran on launch
signIn.AddInputField("username", "", 20, nil, nil)
signIn.AddInputField("password", "", 20, nil, nil)
signIn.AddDropDown("username color",[]string{"red","blue","green"},0,nil)
signIn.AddButton("enter", func() {
currentUser = signIn.GetFormItemByLabel("username").(*tview.InputField).GetText()
currentPass = signIn.GetFormItemByLabel("password").(*tview.InputField).GetText()
_, color := signIn.GetFormItemByLabel("username color").(*tview.DropDown).GetCurrentOption()
_ = color //negate unused var
//fmt.Println(currentUser,currentPass,color)
go listenClient()
//go runClientListener()
pages.SwitchToPage("main")//switch to other pages
app.SetFocus(firstInput)//focus to whatever is selected
})
signIn.SetBorder(true).SetTitle("enter details").SetTitleAlign(tview.AlignLeft)

pages.AddPage("signIn",signIn,true,true)
pages.AddPage("main",mainView,true,false)//unable to be reached unless with sign in form

app.SetRoot(pages,true).SetFocus(signIn) //puts the user in sign in to start
}

msgView = tview.NewTextView().
func channel(name string, onSend func(string)) (*tview.TextView, tview.Primitive, *tview.InputField){
textView := tview.NewTextView().
SetScrollable(true).
SetDynamicColors(true).
ScrollToEnd()
msgView.SetBackgroundColor(tcell.ColorDefault)
msgView.SetBorderPadding(0, 0, 1, 1)
msgView.SetBorder(true)
msgView.SetTitle(" PingChat v2 ")

inputBox := tview.NewInputField()
SetDynamicColors(true)
textView.ScrollToEnd()
textView.SetBackgroundColor(tcell.ColorDefault)
textView.SetBorderPadding(0, 0, 1, 1)
textView.SetBorder(true)
textView.SetTitle(" PingChat v2 ")

inputBox := tview.NewInputField()
inputBox.SetBorder(true)
inputBox.SetBackgroundColor(tcell.ColorDefault)
inputBox.SetFieldBackgroundColor(tcell.ColorDefault)

inputBox.SetDoneFunc(func(key tcell.Key) {
inputBox.SetDoneFunc(func(key tcell.Key) {//take input from inputBox, sends off
if key != tcell.KeyEnter {
return
}
Expand All @@ -41,20 +98,40 @@ func initTUI(onSend func(string)) {
go onSend(text)
})

flex := tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(msgView, 0, 1, false).
flex := tview.NewFlex().SetDirection(tview.FlexRow).//puts text view and input into respective positions
AddItem(textView, 0, 1, false).
AddItem(inputBox, 3, 1, true)
app.SetRoot(flex, true).SetFocus(inputBox)

return textView, flex, inputBox
}

func tuiPrint(line string) {
func currentChannel(chanNum int)(chanName string){
return fmt.Sprintf("channel %d",chanNum)
}

func channelPass(channelNum int)(chanPas string){
return fmt.Sprintf("%s%d",currentPass,channelNum)
}

func tuiPrint(channel string, name string, line string) {
view := msgView[channel]//updates with new messages
//if view == nil {
// return
//}
app.QueueUpdateDraw(func() {
fmt.Fprintf(msgView, "%s\n", line)
fmt.Fprintf(view, "%s\n",name,line)
})
}

func runTUI() {
func runTUI() {//throwing errors
if err := app.Run(); err != nil {
panic(err)
}
}

func ScrollToMessage(){
textView := msgView[activeChannel]
app.QueueUpdateDraw(func(){
textView.ScrollToEnd()
})
}