func receiveProtobuf(conn *transport.Conn, inBuf []byte, t *testing.T) *proto.ServerToClient { response := new(proto.ServerToClient) conn.SetDeadline(time.Now().Add(time.Second)) num, err := conn.ReadFrame(inBuf) handleError(err, t) unpadMsg := proto.Unpad(inBuf[:num]) if err := response.Unmarshal(unpadMsg); err != nil { t.Error(err) } if response.Status == nil { t.Error("Server returned nil status.") } if *response.Status == proto.ServerToClient_PARSE_ERROR { t.Error("Server threw a parse error.") } return response }
func ReceiveProtobuf(conn *transport.Conn, inBuf []byte) (*proto.ServerToClient, error) { response := new(proto.ServerToClient) conn.SetDeadline(time.Now().Add(time.Hour)) num, err := conn.ReadFrame(inBuf) if err != nil { return nil, err } unpadMsg := proto.Unpad(inBuf[:num]) if err := response.Unmarshal(unpadMsg); err != nil { return nil, err } if response.Status == nil { return nil, errors.New("Server returned nil status.") } if *response.Status != proto.ServerToClient_OK { return nil, errors.New("Server did not return OK") } return response, 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() } }