// Caller MUST call Put or PutClose after this func (cc *ConnectionCache) DialServer(cacheKey, addr string, port int, serverPK, pk, sk *[32]byte) (conn *transport.Conn, err error) { cc.Lock() ch, ok := cc.connections[cacheKey] if !ok { ch = make(chan *transport.Conn, 1) cc.connections[cacheKey] = ch } cc.Unlock() if ok { conn := <-ch if conn != nil { return conn, nil } } // ch is empty now plainconn, err := cc.dialer.Dial("tcp", net.JoinHostPort(addr, strconv.Itoa(port))) if err != nil { cc.PutClose(cacheKey) return nil, err } conn, _, err = transport.Handshake(plainconn, pk, sk, serverPK, proto.SERVER_MESSAGE_SIZE) if err != nil { conn.Close() cc.PutClose(cacheKey) return nil, err } return conn, nil }
func CreateTestHomeServerConn(dename string, denameClient *client.Client, secretConfig *proto.LocalAccountConfig, t testing.TB) *transport.Conn { profile, err := denameClient.Lookup(dename) if err != nil { t.Fatal(err) } chatProfileBytes, err := client.GetProfileField(profile, PROFILE_FIELD_ID) if err != nil { t.Fatal(err) } chatProfile := new(proto.Profile) if err := chatProfile.Unmarshal(chatProfileBytes); err != nil { t.Fatal(err) } addr := chatProfile.ServerAddressTCP port := chatProfile.ServerPortTCP pkTransport := ([32]byte)(chatProfile.ServerTransportPK) pkp := (*[32]byte)(&chatProfile.UserIDAtServer) oldConn, err := net.Dial("tcp", net.JoinHostPort(addr, fmt.Sprint(port))) if err != nil { t.Fatal(err) } skp := (*[32]byte)(&secretConfig.TransportSecretKeyForServer) conn, _, err := transport.Handshake(oldConn, pkp, skp, &pkTransport, proto.SERVER_MESSAGE_SIZE) if err != nil { t.Fatal(err) } return conn }
//Test message listing func TestMessageListing(t *testing.T) { server, pks, _, teardown := CreateTestServer(t) oldConn, err := net.Dial("tcp", server.listener.Addr().String()) if err != nil { t.Fatal(err) } defer oldConn.Close() pkp, skp, err := box.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } conn, _, err := transport.Handshake(oldConn, pkp, skp, pks, proto.SERVER_MESSAGE_SIZE) if err != nil { t.Fatal(err) } inBuf := make([]byte, proto.SERVER_MESSAGE_SIZE) outBuf := make([]byte, proto.SERVER_MESSAGE_SIZE) envelope1 := []byte("Envelope1") envelope2 := []byte("Envelope2") createAccount(conn, inBuf, outBuf, t) uploadMessageToUser(conn, inBuf, outBuf, t, pkp, envelope1) uploadMessageToUser(conn, inBuf, outBuf, t, pkp, envelope2) messageList := listUserMessages(conn, inBuf, outBuf, t) expected := make([][32]byte, 0, 64) envelope1Hash := sha256.Sum256(envelope1) envelope2Hash := sha256.Sum256(envelope2) expected = append(expected, envelope1Hash) expected = append(expected, envelope2Hash) outer: for _, hash := range expected { for _, msgid := range messageList { if bytes.Equal(msgid[8:], hash[:24]) { continue outer } } t.Error("Wrong message list returned") } teardown() }
func dropMessage(t *testing.T, server *Server, uid *[32]byte, message []byte) { oldConn, err := net.Dial("tcp", server.listener.Addr().String()) if err != nil { t.Fatal(err) } defer oldConn.Close() pkp, skp, err := box.GenerateKey(rand.Reader) handleError(err, t) conn, _, err := transport.Handshake(oldConn, pkp, skp, nil, proto.SERVER_MESSAGE_SIZE) handleError(err, t) inBuf := make([]byte, proto.SERVER_MESSAGE_SIZE) outBuf := make([]byte, proto.SERVER_MESSAGE_SIZE) uploadMessageToUser(conn, inBuf, outBuf, t, uid, message) }
func setUpServerTest(db *leveldb.DB, t *testing.T) (*Server, *transport.Conn, []byte, []byte, *[32]byte) { shutdown := make(chan struct{}) pks, sks, err := box.GenerateKey(rand.Reader) handleError(err, t) server, err := StartServer(db, shutdown, pks, sks, ":0") handleError(err, t) oldConn, err := net.Dial("tcp", server.listener.Addr().String()) handleError(err, t) pkp, skp, err := box.GenerateKey(rand.Reader) handleError(err, t) conn, _, err := transport.Handshake(oldConn, pkp, skp, nil, proto.SERVER_MESSAGE_SIZE) handleError(err, t) inBuf := make([]byte, proto.SERVER_MESSAGE_SIZE) outBuf := make([]byte, proto.SERVER_MESSAGE_SIZE) return server, conn, inBuf, outBuf, pkp }
//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() } }