func listUserMessages(conn *transport.Conn, inBuf []byte, outBuf []byte, t *testing.T) []*[32]byte { listMessages := &proto.ClientToServer{ ListMessages: protobuf.Bool(true), } writeProtobuf(conn, outBuf, listMessages, t) response := receiveProtobuf(conn, inBuf, t) return proto.To32ByteList(response.MessageList) }
func ListUserMessages(connToServer *ConnectionToServer) ([]*[32]byte, error) { listMessages := &proto.ClientToServer{ ListMessages: protobuf.Bool(true), } if err := WriteProtobuf(connToServer.Conn, listMessages); err != nil { return nil, err } response, err := ReceiveReply(connToServer) if err != nil { return nil, err } return proto.To32ByteList(response.MessageList), nil }
//for each client, listen for commands func (server *Server) handleClient(connection net.Conn) error { defer server.wg.Done() newConnection, uid, err := transport.Handshake(connection, server.pk, server.sk, nil, proto.SERVER_MESSAGE_SIZE) //TODO: Decide on this bound if err != nil { return err } commands := make(chan *proto.ClientToServer) disconnected := make(chan error) server.wg.Add(2) go server.readClientCommands(newConnection, commands, disconnected) go server.handleClientShutdown(newConnection) var notificationsUnbuffered, notifications chan *MessageWithId var notifyEnabled bool defer func() { if notifyEnabled { server.notifier.StopWaitingSync(uid, notificationsUnbuffered) } }() outBuf := make([]byte, proto.SERVER_MESSAGE_SIZE) response := new(proto.ServerToClient) for { select { case err := <-disconnected: return err case cmd := <-commands: if cmd.CreateAccount != nil && *cmd.CreateAccount { err = server.newUser(uid) } else if cmd.DeliverEnvelope != nil { msg_id, err := server.newMessage((*[32]byte)(cmd.DeliverEnvelope.User), cmd.DeliverEnvelope.Envelope) if err != nil { return err } response.MessageId = (*proto.Byte32)(msg_id) } else if cmd.ListMessages != nil && *cmd.ListMessages { var messageList []*[32]byte messageList, err = server.getMessageList(uid) response.MessageList = proto.ToProtoByte32List(messageList) } else if cmd.DownloadEnvelope != nil { response.Envelope, err = server.getEnvelope(uid, (*[32]byte)(cmd.DownloadEnvelope)) response.MessageId = cmd.DownloadEnvelope } else if cmd.DeleteMessages != nil { messageList := cmd.DeleteMessages err = server.deleteMessages(uid, proto.To32ByteList(messageList)) } else if cmd.UploadSignedKeys != nil { err = server.newKeys(uid, cmd.UploadSignedKeys) } else if cmd.GetSignedKey != nil { response.SignedKey, err = server.getKey((*[32]byte)(cmd.GetSignedKey)) } else if cmd.GetNumKeys != nil { response.NumKeys, err = server.getNumKeys(uid) } else if cmd.ReceiveEnvelopes != nil { if *cmd.ReceiveEnvelopes && !notifyEnabled { notifyEnabled = true notificationsUnbuffered = server.notifier.StartWaiting(uid) notifications = make(chan *MessageWithId) server.wg.Add(1) go server.readClientNotifications(notificationsUnbuffered, notifications) } else if !*cmd.ReceiveEnvelopes && notifyEnabled { server.notifier.StopWaitingSync(uid, notificationsUnbuffered) notifyEnabled = false } } if err != nil { fmt.Printf("Server error: %v\n", err) response.Status = proto.ServerToClient_PARSE_ERROR.Enum() } else { response.Status = proto.ServerToClient_OK.Enum() } if err = server.writeProtobuf(newConnection, outBuf, response); err != nil { return err } commands <- cmd case notification, ok := <-notifications: if !notifyEnabled { continue } if !ok { notifyEnabled = false go server.notifier.StopWaitingSync(uid, notificationsUnbuffered) continue } response.Envelope = notification.Envelope response.MessageId = (*proto.Byte32)(notification.Id) response.Status = proto.ServerToClient_OK.Enum() if err = server.writeProtobuf(newConnection, outBuf, response); err != nil { return err } } response.Reset() } }