147 lines
3.5 KiB

package main
import (
// Client holds the state for a chat client
type Client struct {
conn net.Conn
serverAddr string
username string
// NewClient creates a new Client
func NewClient(serverAddr, username string) *Client {
return &Client{
serverAddr: serverAddr,
username: username,
// Connect to the server
func (c *Client) Connect() error {
conn, err := net.Dial("tcp", c.serverAddr)
if err != nil {
return err
c.conn = conn
return nil
// EncryptWithPublicKey encrypts plaintext with the public key
func (c *Client) EncryptWithPublicKey(plaintext []byte, pub *rsa.PublicKey) []byte {
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, pub, plaintext, nil)
if err != nil {
log.Fatalf("Error encrypting message: %s", err)
return ciphertext
// DecryptWithPrivateKey decrypts ciphertext with the private key
func (c *Client) DecryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) []byte {
plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, priv, ciphertext, nil)
if err != nil {
log.Fatalf("Error decrypting message: %s", err)
return plaintext
// JoinChannel allows the client to join a channel
func (c *Client) JoinChannel(channel string) error {
// Create a join channel request payload
joinRequest := map[string]string{
"action": "join",
"channel": channel,
// Serialize the join channel request to JSON
joinRequestJSON, err := json.Marshal(joinRequest)
if err != nil {
return fmt.Errorf("failed to serialize join request: %v", err)
// Send the join channel request to the server
_, err = c.conn.Write(joinRequestJSON)
if err != nil {
return fmt.Errorf("failed to send join request to server: %v", err)
// Optionally, we can wait for an acknowledgment from the server
// to confirm that the join request was successful.
return nil
// SendMessage sends a message to a channel
func (c *Client) SendMessage(channel string, message string) error {
// Create a Message object
msg := common.Message{
Username: c.username,
Content: message,
// Serialize the Message object to JSON
msgJSON, err := json.Marshal(msg)
if err != nil {
return fmt.Errorf("failed to serialize message: %v", err)
// Create a send message request payload
sendRequest := map[string]interface{}{
"action": "send",
"channel": channel,
"message": msgJSON,
// Serialize the send message request to JSON
sendRequestJSON, err := json.Marshal(sendRequest)
if err != nil {
return fmt.Errorf("failed to serialize send request: %v", err)
// Send the serialized send message request to the server
_, err = c.conn.Write(sendRequestJSON)
if err != nil {
return fmt.Errorf("failed to send message to server: %v", err)
return nil
// ListenForMessages listens for incoming messages from the server
func (c *Client) ListenForMessages() {
buffer := make([]byte, 4096)
for {
// Read incoming data from the server
n, err := c.conn.Read(buffer)
if err != nil {
fmt.Printf("Error reading from server: %v\n", err)
// Deserialize the received JSON into a Message object
var msg common.Message
err = json.Unmarshal(buffer[:n], &msg)
if err != nil {
fmt.Printf("Error deserializing message: %v\n", err)
// Handle the received message
// For now, we'll just print it to the console
fmt.Printf("%s: %s\n", msg.Username, msg.Content)
// TODO: Update the GUI with the received message