first poc client
This commit is contained in:
parent
0c3842b90c
commit
9d47fc3282
5 changed files with 181 additions and 2 deletions
148
client/main.go
148
client/main.go
|
@ -1,11 +1,159 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math/rand/v2"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Connect:
|
||||||
|
1. Client A: Create URL with public key and ID to reach on
|
||||||
|
2. Client B: Parses URL, generate AES key, upload key to storage
|
||||||
|
3. Client A: Polls for storage on server
|
||||||
|
*/
|
||||||
|
|
||||||
|
func get(id string) ([]byte, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("http://localhost:3000/store/%s", id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("failed to get")
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func put(id string, data []byte) error {
|
||||||
|
req, err := http.NewRequest(
|
||||||
|
http.MethodPut,
|
||||||
|
fmt.Sprintf("http://localhost:3000/store/%s", id),
|
||||||
|
bytes.NewReader(data),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != http.StatusNoContent {
|
||||||
|
return fmt.Errorf("failed to get")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomId() string {
|
||||||
|
var charset = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||||
|
|
||||||
|
runes := make([]rune, 512)
|
||||||
|
for i := range runes {
|
||||||
|
runes[i] = charset[rand.IntN(len(charset))]
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(runes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func connect() (string, string) {
|
||||||
|
// link: chitchat:<temporary-id>
|
||||||
|
var selfId, partnerId string
|
||||||
|
selfId = randomId()
|
||||||
|
|
||||||
|
fmt.Printf("Your ID: %s\n", selfId)
|
||||||
|
fmt.Printf("Partner ID: ")
|
||||||
|
fmt.Scanln(&partnerId)
|
||||||
|
|
||||||
|
partnerId = strings.TrimSpace(partnerId)
|
||||||
|
return selfId, partnerId
|
||||||
|
}
|
||||||
|
|
||||||
|
func pollPartner(partnerId string) {
|
||||||
|
var message string
|
||||||
|
|
||||||
|
for {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
data, err := get(partnerId)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to poll: %s\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
partnerId, message, _ = strings.Cut(string(data), ":")
|
||||||
|
fmt.Printf("%s\n", message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pollInput(selfId string) {
|
||||||
|
var message string
|
||||||
|
|
||||||
|
for {
|
||||||
|
fmt.Scanln(&message)
|
||||||
|
nextId := randomId()
|
||||||
|
data := fmt.Sprintf("%s:%s", nextId, message)
|
||||||
|
|
||||||
|
err := put(selfId, []byte(data))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to put: %s\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
selfId = nextId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func run() error {
|
func run() error {
|
||||||
|
selfId, partnerId := connect()
|
||||||
|
if partnerId == "" {
|
||||||
|
fmt.Printf("Waiting for partner to connect to you...\n")
|
||||||
|
|
||||||
|
for {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
data, err := get(selfId)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Partner hasn't connected: %s\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
partnerId = string(data)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := put(partnerId, []byte(selfId))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to put next id: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Your ID: %s\n", selfId)
|
||||||
|
fmt.Printf("Partner ID: %s\n", partnerId)
|
||||||
|
|
||||||
|
fmt.Printf("Chat away!\n")
|
||||||
|
|
||||||
|
go pollInput(partnerId)
|
||||||
|
go pollPartner(selfId)
|
||||||
|
for {
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
client/server.go
Normal file
27
client/server.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if the storage has an element with the id.
|
||||||
|
// Returns [ErrNotExists] if the element doesn't exist.
|
||||||
|
func (s *Server) Has(id string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retreive an element from the storage.
|
||||||
|
// Returns [ErrNotExists] if the element doesn't exist.
|
||||||
|
func (s *Server) Get(id string) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store an element in the storage.
|
||||||
|
func (s *Server) Put(id string, element []byte) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete an element from the storage.
|
||||||
|
// Returns [ErrNotExists] if the elment doesn't exist.
|
||||||
|
func (s *Server) Delete(id string) error {
|
||||||
|
return nil
|
||||||
|
}
|
2
go.mod
2
go.mod
|
@ -1,3 +1,3 @@
|
||||||
module git.1e99.eu/1e99/chitchat
|
module git.1e99.eu/1e99/chitchat
|
||||||
|
|
||||||
go 1.23.4
|
go 1.23.3
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -56,6 +57,7 @@ func StoreHandler(store storage.Store, idRegex *regexp.Regexp, maxSize int) http
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Put %s = %s\n", id, string(data))
|
||||||
err = store.Put(id, data)
|
err = store.Put(id, data)
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
func NewMemStore() Store {
|
func NewMemStore() Store {
|
||||||
s := &memStore{
|
s := &memStore{
|
||||||
|
|
Loading…
Reference in a new issue