handleFetcherKeys handles cases where a fetcher can satisfy the remaining requests.
( ctx context.Context, _ gomatrixserverlib.Timestamp, fetcher gomatrixserverlib.KeyFetcher, requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp, results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, )
| 179 | // handleFetcherKeys handles cases where a fetcher can satisfy |
| 180 | // the remaining requests. |
| 181 | func (s *FederationInternalAPI) handleFetcherKeys( |
| 182 | ctx context.Context, |
| 183 | _ gomatrixserverlib.Timestamp, |
| 184 | fetcher gomatrixserverlib.KeyFetcher, |
| 185 | requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp, |
| 186 | results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, |
| 187 | ) error { |
| 188 | logrus.WithFields(logrus.Fields{ |
| 189 | "fetcher_name": fetcher.FetcherName(), |
| 190 | }).Infof("Fetching %d key(s)", len(requests)) |
| 191 | |
| 192 | // Create a context that limits our requests to 30 seconds. |
| 193 | fetcherCtx, fetcherCancel := context.WithTimeout(ctx, time.Second*30) |
| 194 | defer fetcherCancel() |
| 195 | |
| 196 | // Try to fetch the keys. |
| 197 | fetcherResults, err := fetcher.FetchKeys(fetcherCtx, requests) |
| 198 | if err != nil { |
| 199 | return fmt.Errorf("fetcher.FetchKeys: %w", err) |
| 200 | } |
| 201 | |
| 202 | // Build a map of the results that we want to commit to the |
| 203 | // database. We do this in a separate map because otherwise we |
| 204 | // might end up trying to rewrite database entries. |
| 205 | storeResults := map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult{} |
| 206 | |
| 207 | // Now let's look at the results that we got from this fetcher. |
| 208 | for req, res := range fetcherResults { |
| 209 | if prev, ok := results[req]; ok { |
| 210 | // We've already got a previous entry for this request |
| 211 | // so let's see if the newly retrieved one contains a more |
| 212 | // up-to-date validity period. |
| 213 | if res.ValidUntilTS > prev.ValidUntilTS { |
| 214 | // This key is newer than the one we had so let's store |
| 215 | // it in the database. |
| 216 | storeResults[req] = res |
| 217 | } |
| 218 | } else { |
| 219 | // We didn't already have a previous entry for this request |
| 220 | // so store it in the database anyway for now. |
| 221 | storeResults[req] = res |
| 222 | } |
| 223 | |
| 224 | // Update the results map with this new result. If nothing |
| 225 | // else, we can try verifying against this key. |
| 226 | results[req] = res |
| 227 | |
| 228 | // Remove it from the request list so we won't re-fetch it. |
| 229 | delete(requests, req) |
| 230 | } |
| 231 | |
| 232 | // Store the keys from our store map. |
| 233 | if err = s.keyRing.KeyDatabase.StoreKeys(context.Background(), storeResults); err != nil { |
| 234 | logrus.WithError(err).WithFields(logrus.Fields{ |
| 235 | "fetcher_name": fetcher.FetcherName(), |
| 236 | "database_name": s.keyRing.KeyDatabase.FetcherName(), |
| 237 | }).Errorf("Failed to store keys in the database") |
| 238 | return fmt.Errorf("server key API failed to store retrieved keys: %w", err) |
no test coverage detected