Commit graph

2785 commits

Author SHA1 Message Date
Daniel Calviño Sánchez
af514b142a Reorder code that handles nick changed events
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-28 11:47:55 +01:00
Daniel Calviño Sánchez
81f353f7f0 Return empty display name rather than default nick from web socket
If the display name is not known whether "Guest" or something else needs
to be shown is not a responsibility of the web socket, so now an empty
string is returned instead.

In practice this should not make any difference, though, as the display
name of users is always known as soon as the user joined, and if the
nick of a guest is not known the UI will set it to "Guest".

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-28 11:47:55 +01:00
Daniel Calviño Sánchez
0dcdd6161f Move nick handling out of PeerConnectionWrapper
PeerConnectionWrappers should not be concerned with the nick of
participants. Moreover, the nick is included in offers and answers due
to legacy reasons and only when the internal signaling server is used.
Due to that the nick was moved out of PeerConnectionWrapper; although
the handling is now different the end result should be the same (there
might be some differences in very specific sequences of events, but in
any case all this is just a temporary step and any leftover issue should
be addressed once call participants and peer connections are split).

As the PeerConnectionWrapper does not keep track of the nick now the
nick changed event is always emitted when a nick changed data channel
message is received, even if the nick did not actually change.
Nevertheless, before it was anyway always emitted if it was for a user
and only when it was for a guest it was emitted only on real changes. In
any case this is not expected to cause any issue (other than some
unneeded view updates, but that will be addressed at a later point by
updating the views only when the model actually changed).

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-28 11:47:55 +01:00
Daniel Calviño Sánchez
2eac8c2cba Move default nick out of PeerConnectionWrapper
If the nick is not known whether "Guest" or something else needs to be
shown is a responsability of the UI, so now the PeerConnectionWrapper
just returns an empty string and the UI shows the default guest nick if
needed.

Moreover, the nick stored in the PeerConnectionWrapper was not always
correct, as if no nick was received it was returned as "Guest" even
if the connection belonged to a user. Now "Guest" is used only for
actual guests.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-28 11:47:55 +01:00
Daniel Calviño Sánchez
68cf4ee028 Use generic data channel message instead of nick specific one
The generic data channel message works fine for receiving, but it could
not be used for sending, because the serialization of the payload failed
(the generated JsonMapper did not call 'writeFieldName("payload")',
apparently because the payload was defined as "Any", so there was no
field name set when serializing the payload contents).

It is very likely that the nick data channel message, which has an
explicit payload type and was used only for sending but not for
receiving, was added back in the day just to work around that
limitation. However, due to how the JsonMappers are generated if several
properties with the same name are defined only the first one will be
parsed, and only those with a value will be serialized. This makes
possible to define first a generic payload property and then a payload
property with an explicit type to have a single data channel message
class that can be used both for sending and receiving.

As the nick data channel message is now no longer needed it was removed.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-28 11:47:55 +01:00
Daniel Calviño Sánchez
faf25f8071 Replace concrete implementation with interface
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-28 11:47:55 +01:00
Daniel Calviño Sánchez
65ff4efcb9
Send signaling messages directly from PeerConnectionWrapper
Note that the thread used to send the message does not change; the
EventBus subscriber mode was "BACKGROUND", but as the messages were
posted from a WebSocket handler (when requesting offers to the HPB) and
peer connection observers (when sending offers/answers and candidates,
both with and without HPB), which run in worker threads rather than in
the main thread, the subscriber was executed in the same thread as
the poster.

For legacy reasons, when the internal signaling server is used the
offers and answers are expected to also provide the nick of the local
participant. When the external signaling server is used the field can be
included, but it is just ignored and not sent to the other clients. As
the local participant nick is a value unrelated to the peer connection
and is only needed with one type of signaling server the messages are
adjusted as needed before being sent rather than handling this inside
the PeerConnectionWrapper.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:57 +01:00
Daniel Calviño Sánchez
58e371c98c
Do not apply "toLowerCase()" on already lower case canonical form
The canonical form is already in lower case (see
https://webrtc.googlesource.com/src/+/79d8df02/sdk/android/api/org/webrtc/SessionDescription.java#29),
so there is no need to apply "toLowerCase()".

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:57 +01:00
Daniel Calviño Sánchez
473b8b238d
Extract interface to send signaling messages
Like done with SignalingMessageReceiver, an implementation specific to
each signaling server type (internal or external) is added.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:57 +01:00
Daniel Calviño Sánchez
6b032fc55a
Replace constant String of length 1 with character
Fixes UCPM_USE_CHARACTER_PARAMETERIZED_METHOD issue from SpotBugs.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:57 +01:00
Daniel Calviño Sánchez
4086499a32
Remove special method to request offers
As the "requestoffer" message is just a signaling message the generic
method can be used instead.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:57 +01:00
Daniel Calviño Sánchez
37db855170
Use generic message rather than specific one for requesting offers
"requestoffer" messages are compatible with the generic messages, so for
simplicity the generic message is used now instead of having specific
classes just for it.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:56 +01:00
Daniel Calviño Sánchez
95007882f4
Remove no longer used JSON model
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:56 +01:00
Daniel Calviño Sánchez
48a64fde7e
Fix message wrapper type in documentation
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:56 +01:00
Daniel Calviño Sánchez
b4d4cdf219
Remove unused wrapper in the internal signaling server
Messages sent to the internal signaling server need to be serialized
twice, first the signaling message and then the wrapper as a whole. Due
to this the NCMessageWrapper was not actually used.

For simplicity the manual serialization was kept rather than adding
something like "NCMessageWrapperToSend" where a serialized signaling
message could be set before serializing it.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:56 +01:00
Daniel Calviño Sánchez
e1eca7764f
Replace wrapper with actual message in external signaling server
NCMessageWrapper is used only for messages sent and received by the
internal signaling server. However, it is unused by the external
signaling server, except for getting the NCSignalingMessage, which is
the common message for both signaling servers.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-27 14:28:55 +01:00
Daniel Calviño Sánchez
c4c64df5a6 Remove no longer needed code after removing EventBus message
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:44:41 +01:00
Daniel Calviño Sánchez
5e224c5a24 Use listener for participant list messages
Note that the thread used to handle the participant list messages from
the external signaling server does not change; the EventBus subscriber
mode was "BACKGROUND", but as the message was posted from a WebSocket
handler, which runs in a worker thread rather than in the main thread,
the subscriber was executed in the same thread as the poster.

Also note that the removed "userId" remark was not fully accurate;
although some external signaling messages do actually use "userid" those
currently handled to process the users do not, they always use "userId"
(as documented in the SignalingMessageReceiver).

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:44:41 +01:00
Daniel Calviño Sánchez
e0c676bb35 Add listener for participant list messages
For now only the same participant list messages that were already
handled are taken into account, but at a later point further messages,
like participants joining or leaving the conversation, could be added
too.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:44:41 +01:00
Daniel Calviño Sánchez
c8e77c3d3b Split message receiver for internal and external signaling servers
Note that the thread used to handle and notify messages from the
external signaling server does not change; the EventBus subscriber mode
was "BACKGROUND", but as the message was posted from a WebSocket
handler, which runs in a worker thread rather than in the main thread,
the subscriber was executed in the same thread as the poster.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:44:41 +01:00
Daniel Calviño Sánchez
9df56dccda Process signaling message directly in the SignalingMessageReceiver
This will no longer log an error if the room type of the received
message is neither "video" nor "screen". However, that should never
happen, and it would be useful only while debugging, so it is fine to
lose that.

Note that the check is not added to SignalingMessageReceiver itself to
keep it as generic as possible (and due to the low value of adding it as
explained above). Nevertheless, if needed in the future it would be
possible to add a special listener that receives raw messages in order
to validate them and log the errors, if any.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:44:20 +01:00
Daniel Calviño Sánchez
bda7d2719b Add listener for call participant messages
Although "unshareScreen" is technically bound to a specific peer
connection it is instead treated as a general message on the call
participant.

Nevertheless, call participant messages will make possible (at a later
point) to listen to events like "raise hand" or "mute" (which, again,
could be technically bound to a specific peer connection, but at least
for now are treated as a general message on the call participant).

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:41:34 +01:00
Daniel Calviño Sánchez
d42fe61e89 Add listener for offer messages
Unlike the WebRtcMessageListener, which is bound to a specific peer
connection, an OfferMessageListener listens to all offer messages, no
matter which peer connection they are bound to. This can be used, for
example, to create a new peer connection when a remote offer for which
there is no previous connection is received.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:40:01 +01:00
Daniel Calviño Sánchez
476fb59a08 Use temporary SignalingMessageReceiver implementation in CallActivity
Eventually all signaling related code should be moved to a Signaling
class that abstracts the differences between the internal and external
signaling servers, including how messages are sent and listened to. In
the meantime a temporary SignalingMessageReceiver implementation is
added to CallActivity to be able to start using it.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:40:01 +01:00
Daniel Calviño Sánchez
45787caf0a Add SignalingMessageReceiver class to listen to signaling messages
For now only WebRTC messages can be listened to, although it will be
extended with other kinds later.

This commit only introduces the base class, although it is not used yet
anywhere; a concrete implementation will be added in a following commit.

The test class is named "SignalingMessageReceiverWebRtcTest" rather than
just "SignalingMessageReceiverTest" to have smaller, more manageable
test classes for each listener kind rather than one large test class for
all of them.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:40:01 +01:00
Daniel Calviño Sánchez
0e36002036 Hide and delete no longer needed public methods
Although the rest of the methods are no longer needed since the handling
of WebRTC messages was moved to PeerConnectionWrapper "setSessionId()"
was not needed even before that.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:40:01 +01:00
Daniel Calviño Sánchez
4dffd29ceb Move handling of WebRTC messages to PeerConnectionWrapper
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:40:01 +01:00
Daniel Calviño Sánchez
f3e04b8e18 Simplify condition
"peerConnectionWrapper" needs to be defined to enter the if and execute
the switch, so just return before the switch if "peerConnectionWrapper"
is null.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:40:01 +01:00
Daniel Calviño Sánchez
075ba20cf9 Split handling of "unshareScreen" and WebRTC messages
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:40:01 +01:00
Daniel Calviño Sánchez
7b1bfb2c17 Simplify getting the message type
The message type is set for all signaling messages. On the other hand,
the payload type is only set for offers and answers (and, if the message
was sent by the Android app, also for candidates). However, in all those
cases the payload type just duplicates the message type, so the message
type can be assigned directly rather than falling back to it if there is
no payload type.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 20:39:49 +01:00
Daniel Calviño Sánchez
331bf49f73 Fix processing of participant list on reconnections
When the HPB is used the signaling messages can be received even when
the local participant is not currently in the call (for example, when
starting the call timed out without other participant joining, or when
reconnecting due to the publisher connection failing). Therefore if the
local participant is not in the call it should not try to establish a
connection with the other participants and disconnect them instead.

Moreover, if the connection is tried to be established when not
in the call the HPB will prevent that, and the PeerConnectionWrapper
will stay in a limbo state waiting for an offer to be sent. If the local
participant then joins the call the PeerConnectionWrapper will already
exist for the other participants, so no new connections will be created,
but those previous connections will never be finally established.

Additionally, as the signaling messages can be received before the join
call response the participant list could be received while the call
state is "RECONNECTING" or "PUBLISHER_FAILED". In those cases, as long
as the local participant is already in the call, the participant list
should be processed as if the call state was already "JOINED" (otherwise
the connections were not established either).

For simplicity the participant list is now ignored only when the call
state is "LEAVING"; this means that the participant list would be also
processed in the "CONNECTION_TIMEOUT" state, but the signaling message
should not be received anyway in that case.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 11:00:05 +00:00
Daniel Calviño Sánchez
8cdcc63687 Return without further processing if the call is remotely ended
If the call is hung up with a view shutdown (which finishes the
activity) there is no need to do any further processing on the
participant list.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 11:00:05 +00:00
Daniel Calviño Sánchez
379ec8eae8 Fix call state when join call response is received after signaling
When a call is joined the call flags of the local participant change, so
this causes a signaling message to be sent by the server. When the HPB
is used the signaling message is sent through a WebSocket, which is
already connected before joining the call. Therefore, in some cases the
signaling message can be received through the WebSocket even before the
response to the HTTP "joinCall" request.

If there are other participants in the call the call state is changed to
"IN_CONVERSATION" when the signaling message is processed. However, in
the case described above the call state was then set to "JOINED", which
automatically traverses to "CONNECTION_TIMEOUT" if no other call state
was set in 45 seconds. Due to all this the call was joined and the
connections with the other participants were established, but they were
not visible in the UI (although they could be heard) and after 45
seconds the call was left.

To prevent that now the call state is changed to "JOINED" if it was not
already changed to "IN_CONVERSATION" in the meantime.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2022-12-23 11:00:05 +00:00
Marcel Hibbe
d9280d3d98
avoid NPE in processAutocompleteUserList
did not test why this can happen.   autocompleteUser.id must have been null..

Exception java.lang.NullPointerException:
  at com.nextcloud.talk.controllers.ContactsController.processAutocompleteUserList (ContactsController.kt:498)
  at com.nextcloud.talk.controllers.ContactsController.processAutocompleteUserList (ContactsController.kt:482)
  at com.nextcloud.talk.controllers.ContactsController.access$processAutocompleteUserList (ContactsController.kt:90)
  at com.nextcloud.talk.controllers.ContactsController$fetchData$1.onNext (ContactsController.kt:438)
  at com.nextcloud.talk.controllers.ContactsController$fetchData$1.onNext (ContactsController.kt:432)
  at io.reactivex.internal.operators.observable.ObservableRetryPredicate$RepeatObserver.onNext (ObservableRetryPredicate.java:69)
  at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal (ObservableObserveOn.java:201)
  at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run (ObservableObserveOn.java:255)
  at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run (HandlerScheduler.java:124)
  at android.os.Handler.handleCallback (Handler.java:883)
  at android.os.Handler.dispatchMessage (Handler.java:100)
  at android.os.Looper.loop (Looper.java:237)
  at android.app.ActivityThread.main (ActivityThread.java:7948)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1075)

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-23 11:16:53 +01:00
Álvaro Brey
8bc5735751
RepositoryModule: fix wrong injection for dateUtils
The module class is not supposed to have things injected into it. @Provides-annotated methods
will have their parameters injected, instead.

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
2022-12-19 17:35:19 +01:00
Andy Scherzinger
54b1427471
Implement closing for file input/output streams
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
2022-12-19 09:37:06 +01:00
Andy Scherzinger
ae6b7156c0
Implement hasCode based on equals() elements to fullfil hasCode/equals contract
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
2022-12-19 09:37:01 +01:00
Andy Scherzinger
20ad889206
remove unneeded class cast
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
2022-12-15 13:23:06 +01:00
Andy Scherzinger
d858169668
prevent NPE
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
2022-12-15 13:22:47 +01:00
Marcel Hibbe
eff4b912bd
fix Spot Bugs warning
Possible null pointer dereference in com.nextcloud.talk.utils.PushUtils.updatePushStateForUser(Map, User) due to return value of called method

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-15 13:11:42 +01:00
Marcel Hibbe
da8148a134
fix spotbug warning "PRMC: Possibly Redundant Method Calls"
PRMC: In class com.nextcloud.talk.utils.ssl.MagicKeyManager
In class com.nextcloud.talk.utils.ssl.MagicKeyManager
In method com.nextcloud.talk.utils.ssl.MagicKeyManager.chooseClientAlias(String[], Principal[], Socket)
At MagicKeyManager.java:[line 68]
Value getCurrentUser()Lio/reactivex/Maybe;
Method com.nextcloud.talk.utils.ssl.MagicKeyManager.chooseClientAlias(String[], Principal[], Socket) appears to call the same method on the same object redundantly

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-15 13:11:41 +01:00
Marcel Hibbe
e238c4c9e5
ensure that there is always a current user
this should also fix the app to start after it always crashed on startup because of https://github.com/nextcloud/talk-android/issues/2531

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-15 13:11:41 +01:00
Marcel Hibbe
dd155db6ab
rename method to update PushState for a user
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-15 13:11:41 +01:00
Álvaro Brey
a37f947eb9
PushUtils: update only pushState when updating users
This is to work around a race condition where this class would asynchronously overwrite other user attributes
with old values after a user switch.

Co-authored-by: Marcel Hibbe <dev@mhibbe.de>
Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
2022-12-15 13:11:40 +01:00
Álvaro Brey
2e2d4a9ca3
CurrentUserProviderImpl: ensure only one observer is set up for all threads
Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
2022-12-15 13:11:40 +01:00
Álvaro Brey
25dd46f95a
UsersDao: fix wrong attribute used in setUserAsActive
Co-authored-by: Marcel Hibbe <dev@mhibbe.de>
Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
2022-12-15 13:11:40 +01:00
Marcel Hibbe
962b1d4e3a
WIP. replace loop to set current state of users by single UPDATE query
i was able to see that the loop was somehow interrupted during debugging which caused two users to have current =true

this should avoid the problem with the loop.

anyway, this doesn't seem to solve the issue completely as i was able to reproduce it again with the new solution. so maybe there are still more methods/scenarios which can cause this.

additionally, i managed to have all users to have current =false with this new query (while switching accounts very fast and often in ChooseAccountDialogFragment..)

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-15 13:11:39 +01:00
Marcel Hibbe
f73d1c14fc
add logging and toasts if current user was null
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-15 13:11:39 +01:00
Marcel Hibbe
e9dbcc554a
set user.current by value from userAttributes
this should have no effect but it should ensure "current" is not falsely set to true if the method storeProfile will be used for more scenarios in the future.

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-15 13:11:39 +01:00
Marcel Hibbe
d4e545e67d
use setUserAsActive instead of userManager.disableAllUsersWithoutId
just refactoring for now. this doesn't solve the bug!

Problem that needs to be solved:
When adding a new Account (User), it is marked as "current", while for the other logged in users "current" must be unset (-> disabled).

The problem is, that for the old active user, "current" is not unset so there were multiple accounts marked as "current".

In the ChooseAccountDialogFragment, only one of the current accounts is shown at the top. Below the set status field, all accounts are listed that are not marked with "current". So as a result, there can be accounts hidden that were marked as "current".

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
2022-12-15 13:11:35 +01:00