first poc client

This commit is contained in:
1e99 2025-01-06 12:03:58 +01:00
parent 0c3842b90c
commit 9d47fc3282
5 changed files with 181 additions and 2 deletions

View file

@ -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
View 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
View file

@ -1,3 +1,3 @@
module git.1e99.eu/1e99/chitchat module git.1e99.eu/1e99/chitchat
go 1.23.4 go 1.23.3

View file

@ -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:

View file

@ -1,6 +1,8 @@
package storage package storage
import "sync" import (
"sync"
)
func NewMemStore() Store { func NewMemStore() Store {
s := &memStore{ s := &memStore{