Skip to content

Commit

Permalink
Merge pull request #11683 from nextcloud/bugfix/11272/federation-hand…
Browse files Browse the repository at this point in the history
…ling

fix(federation): Handle federation errors
  • Loading branch information
nickvergessen authored Feb 29, 2024
2 parents cd4dea3 + 7901e80 commit ea3e2ff
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 43 deletions.
2 changes: 1 addition & 1 deletion lib/BackgroundJob/RetryJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function execute(IJobList $jobList, ?ILogger $logger = null): void {

protected function run($argument): void {
$remote = $argument['remote'];
$data = json_decode($argument['data'], true);
$data = json_decode($argument['data'], true, flags: JSON_THROW_ON_ERROR);
$try = (int)$argument['try'] + 1;

$this->backendNotifier->sendUpdateDataToRemote($remote, $data, $try);
Expand Down
94 changes: 69 additions & 25 deletions lib/Federation/BackendNotifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCP\App\IAppManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Services\IAppConfig;
use OCP\BackgroundJob\IJobList;
use OCP\DB\Exception;
Expand All @@ -43,6 +44,7 @@
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\OCM\Exceptions\OCMProviderException;
use OCP\Server;
use Psr\Log\LoggerInterface;
use SensitiveParameter;
Expand Down Expand Up @@ -146,13 +148,22 @@ public function sendRemoteShare(
$protocol['name'] = FederationManager::TALK_PROTOCOL_NAME;
$share->setProtocol($protocol);

$response = $this->federationProviderManager->sendShare($share);
if (is_array($response)) {
return true;
}
$this->logger->info("Failed sharing $roomToken with $shareWith");
try {
$response = $this->federationProviderManager->sendCloudShare($share);
if ($response->getStatusCode() === Http::STATUS_CREATED) {
return true;
}

$this->logger->warning("Failed sharing $roomToken with $shareWith, received status code {code}\n{body}", [
'code' => $response->getStatusCode(),
'body' => (string) $response->getBody(),
]);

return false;
return false;
} catch (OCMProviderException $e) {
$this->logger->error("Failed sharing $roomToken with $shareWith, received OCMProviderException", ['exception' => $e]);
return false;
}
}

/**
Expand All @@ -178,13 +189,25 @@ public function sendShareAccepted(
'remoteServerUrl' => $this->getServerRemoteUrl(),
'sharedSecret' => $accessToken,
'message' => 'Recipient accepted the share',
]
);

try {
$response = $this->federationProviderManager->sendCloudNotification($remote, $notification);
if ($response->getStatusCode() === Http::STATUS_CREATED) {
return true;
}

$this->logger->warning("Failed to send share accepted notification for share from $remote, received status code {code}\n{body}", [
'code' => $response->getStatusCode(),
'body' => (string) $response->getBody(),
]);
$response = $this->federationProviderManager->sendNotification($remote, $notification);
if (!is_array($response)) {
$this->logger->info("Failed to send share accepted notification for share from $remote");

return false;
} catch (OCMProviderException $e) {
$this->logger->error("Failed to send share accepted notification for share from $remote, received OCMProviderException", ['exception' => $e]);
return false;
}
return true;
}

/**
Expand All @@ -210,12 +233,23 @@ public function sendShareDeclined(
'message' => 'Recipient declined the share',
]
);
$response = $this->federationProviderManager->sendNotification($remote, $notification);
if (!is_array($response)) {
$this->logger->info("Failed to send share declined notification for share from $remote");

try {
$response = $this->federationProviderManager->sendCloudNotification($remote, $notification);
if ($response->getStatusCode() === Http::STATUS_CREATED) {
return true;
}

$this->logger->warning("Failed to send share declined notification for share from $remote, received status code {code}\n{body}", [
'code' => $response->getStatusCode(),
'body' => (string) $response->getBody(),
]);

return false;
} catch (OCMProviderException $e) {
$this->logger->error("Failed to send share declined notification for share from $remote, received OCMProviderException", ['exception' => $e]);
return false;
}
return true;
}

public function sendRemoteUnShare(
Expand Down Expand Up @@ -328,18 +362,28 @@ public function sendUpdateDataToRemote(string $remote, array $data, int $try): v
}

protected function sendUpdateToRemote(string $remote, ICloudFederationNotification $notification, int $try = 0): void {
\OC::$server->getLogger()->error('sendUpdateToRemote');
\OC::$server->getLogger()->error(json_encode($notification->getMessage()));
$response = $this->federationProviderManager->sendNotification($remote, $notification);
if (!is_array($response)) {
$this->jobList->add(RetryJob::class,
[
'remote' => $remote,
'data' => json_encode($notification->getMessage()),
'try' => $try,
]
);
try {
$response = $this->federationProviderManager->sendCloudNotification($remote, $notification);
if ($response->getStatusCode() === Http::STATUS_CREATED) {
return;
}

$this->logger->warning("Failed to send notification for share from $remote, received status code {code}\n{body}", [
'code' => $response->getStatusCode(),
'body' => (string) $response->getBody(),
]);
} catch (OCMProviderException $e) {
$this->logger->error("Failed to send notification for share from $remote, received OCMProviderException", ['exception' => $e]);
}

$this->jobList->add(
RetryJob::class,
[
'remote' => $remote,
'data' => json_encode($notification->getMessage(), JSON_THROW_ON_ERROR),
'try' => $try,
]
);
}

protected function prepareRemoteUrl(string $remote): string {
Expand Down
15 changes: 11 additions & 4 deletions lib/Federation/CloudFederationProviderTalk.php
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,14 @@ private function shareUnshared(int $remoteAttendeeId, array $notification): arra
}

$this->invitationMapper->delete($invite);
$participant = $this->participantService->getParticipantByActor($room, Attendee::ACTOR_USERS, $invite->getUserId());
$this->participantService->removeAttendee($room, $participant, AAttendeeRemovedEvent::REASON_REMOVED);

try {
$participant = $this->participantService->getParticipantByActor($room, Attendee::ACTOR_USERS, $invite->getUserId());
$this->participantService->removeAttendee($room, $participant, AAttendeeRemovedEvent::REASON_REMOVED);
} catch (ParticipantNotFoundException) {
// Never accepted the invite
}

return [];
}

Expand Down Expand Up @@ -364,7 +370,7 @@ private function messagePosted(int $remoteAttendeeId, array $notification): arra
// DBException::REASON_UNIQUE_CONSTRAINT_VIOLATION happens when
// multiple users are in the same conversation. We are therefore
// informed multiple times about the same remote message.
if ($e->getCode() !== DBException::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
if ($e->getReason() !== DBException::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
$this->logger->error('Error saving proxy cache message failed: ' . $e->getMessage(), ['exception' => $e]);
throw $e;
}
Expand All @@ -373,7 +379,8 @@ private function messagePosted(int $remoteAttendeeId, array $notification): arra
try {
$participant = $this->participantService->getParticipant($room, $invite->getUserId(), false);
} catch (ParticipantNotFoundException) {
throw new ShareNotFound();
// Not accepted the invite yet
return [];
}

$this->participantService->updateUnreadInfoForProxyParticipant(
Expand Down
18 changes: 17 additions & 1 deletion src/types/openapi/openapi-backend-sipbridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export type components = {
lastActivity: number;
/** Format: int64 */
lastCommonReadMessage: number;
lastMessage: components["schemas"]["ChatMessage"] | unknown[];
lastMessage: components["schemas"]["RoomLastMessage"] | unknown[];
/** Format: int64 */
lastPing: number;
/** Format: int64 */
Expand Down Expand Up @@ -213,6 +213,22 @@ export type components = {
/** Format: int64 */
unreadMessages: number;
};
RoomLastMessage: components["schemas"]["ChatMessage"] | components["schemas"]["RoomProxyMessage"];
RoomProxyMessage: {
actorDisplayName: string;
actorId: string;
actorType: string;
/** Format: int64 */
expirationTimestamp: number;
message: string;
messageParameters: {
[key: string]: {
[key: string]: Record<string, never>;
};
};
messageType: string;
systemMessage: string;
};
};
responses: never;
parameters: never;
Expand Down
18 changes: 17 additions & 1 deletion src/types/openapi/openapi-federation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export type components = {
lastActivity: number;
/** Format: int64 */
lastCommonReadMessage: number;
lastMessage: components["schemas"]["ChatMessage"] | unknown[];
lastMessage: components["schemas"]["RoomLastMessage"] | unknown[];
/** Format: int64 */
lastPing: number;
/** Format: int64 */
Expand Down Expand Up @@ -226,6 +226,22 @@ export type components = {
/** Format: int64 */
unreadMessages: number;
};
RoomLastMessage: components["schemas"]["ChatMessage"] | components["schemas"]["RoomProxyMessage"];
RoomProxyMessage: {
actorDisplayName: string;
actorId: string;
actorType: string;
/** Format: int64 */
expirationTimestamp: number;
message: string;
messageParameters: {
[key: string]: {
[key: string]: Record<string, never>;
};
};
messageType: string;
systemMessage: string;
};
};
responses: never;
parameters: never;
Expand Down
22 changes: 19 additions & 3 deletions src/types/openapi/openapi-full.ts
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ export type components = {
lastActivity: number;
/** Format: int64 */
lastCommonReadMessage: number;
lastMessage: components["schemas"]["ChatMessage"] | unknown[];
lastMessage: components["schemas"]["RoomLastMessage"] | unknown[];
/** Format: int64 */
lastPing: number;
/** Format: int64 */
Expand Down Expand Up @@ -830,6 +830,22 @@ export type components = {
/** Format: int64 */
unreadMessages: number;
};
RoomLastMessage: components["schemas"]["ChatMessage"] | components["schemas"]["RoomProxyMessage"];
RoomProxyMessage: {
actorDisplayName: string;
actorId: string;
actorType: string;
/** Format: int64 */
expirationTimestamp: number;
message: string;
messageParameters: {
[key: string]: {
[key: string]: Record<string, never>;
};
};
messageType: string;
systemMessage: string;
};
SignalingSession: {
/** Format: int64 */
inCall: number;
Expand Down Expand Up @@ -2434,7 +2450,7 @@ export type operations = {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: unknown;
data: components["schemas"]["Room"];
};
};
};
Expand Down Expand Up @@ -2463,7 +2479,7 @@ export type operations = {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: unknown;
data: components["schemas"]["Room"];
};
};
};
Expand Down
22 changes: 19 additions & 3 deletions src/types/openapi/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ export type components = {
lastActivity: number;
/** Format: int64 */
lastCommonReadMessage: number;
lastMessage: components["schemas"]["ChatMessage"] | unknown[];
lastMessage: components["schemas"]["RoomLastMessage"] | unknown[];
/** Format: int64 */
lastPing: number;
/** Format: int64 */
Expand Down Expand Up @@ -671,6 +671,22 @@ export type components = {
/** Format: int64 */
unreadMessages: number;
};
RoomLastMessage: components["schemas"]["ChatMessage"] | components["schemas"]["RoomProxyMessage"];
RoomProxyMessage: {
actorDisplayName: string;
actorId: string;
actorType: string;
/** Format: int64 */
expirationTimestamp: number;
message: string;
messageParameters: {
[key: string]: {
[key: string]: Record<string, never>;
};
};
messageType: string;
systemMessage: string;
};
SignalingSession: {
/** Format: int64 */
inCall: number;
Expand Down Expand Up @@ -2275,7 +2291,7 @@ export type operations = {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: unknown;
data: components["schemas"]["Room"];
};
};
};
Expand Down Expand Up @@ -2304,7 +2320,7 @@ export type operations = {
"application/json": {
ocs: {
meta: components["schemas"]["OCSMeta"];
data: unknown;
data: components["schemas"]["Room"];
};
};
};
Expand Down
Loading

0 comments on commit ea3e2ff

Please sign in to comment.