protected HttpResponseMessage ResponseToClient(HttpStatusCode code, Exception e = null) { HttpResponseMessage res = new HttpResponseMessage(code); res.Headers.TryAddWithoutValidation("Content-Type", "x-www-form-urlencoded"); res.Headers.TryAddWithoutValidation("Connection", "keep-alive"); res.Headers.TryAddWithoutValidation("PoGoEmulator", ".NET 4.6.2 MVC API"); res.Headers.TryAddWithoutValidation("Date", $"{string.Format(new CultureInfo("en-GB"), "{0:ddd, dd MMM yyyy hh:mm:ss}", DateTime.UtcNow)} GMT"); if (code == HttpStatusCode.OK) { Database.SaveChanges(); Log.LogInformation($"succesfully responding[{Request.Host.Host}]:"); } else { ProtoResponse = new ResponseEnvelope() { RequestId = ProtoRequest.RequestId, Error = e.Message, StatusCode = 1, }; Log.LogError($"{DateTime.Now.ToString()} responding error[{Request.Host.Host}]: {e.Message}"); } res.Content = new ByteArrayContent(ProtoResponse.ToByteArray()); return(res); }
/** * <summary> * Wraps protocol message into a results bean.</summary> * * <param name="data">Protocol message that need to be wrapped.</param> * <returns>Wrapped message.</returns> */ private static GridClientResponse WrapResponse(ProtoResponse data) { GridClientResponse bean = new GridClientResponse(); //bean.RequestId = data.RequestId; //bean.ClientId = WrapGuid(data.ClientId); bean.Status = GridClientResponse.FindByCode(data.Status); if (data.HasErrorMessage) { bean.ErrorMessage = data.ErrorMessage; } if (data.HasResultBean) { bean.Result = WrapObject(data.ResultBean); } if (data.HasSessionToken) { bean.SessionToken = data.SessionToken.ToByteArray(); } return(bean); }
public StaticFileContext(ProtoContext context, StaticFileOptions options, PathString matchUrl, ILogger logger, IFileProvider fileProvider, IContentTypeProvider contentTypeProvider) { _context = context; _options = options; _matchUrl = matchUrl; _request = context.Request; _response = context.Response; _logger = logger; _requestHeaders = _request.GetTypedHeaders(); _responseHeaders = _response.GetTypedHeaders(); _fileProvider = fileProvider; _contentTypeProvider = contentTypeProvider; _method = null; _isGet = false; _isHead = false; _subPath = PathString.Empty; _contentType = null; _fileInfo = null; _length = 0; _lastModified = new DateTimeOffset(); _etag = null; _ifMatchState = PreconditionState.Unspecified; _ifNoneMatchState = PreconditionState.Unspecified; _ifModifiedSinceState = PreconditionState.Unspecified; _ifUnmodifiedSinceState = PreconditionState.Unspecified; _range = null; _isRangeRequest = false; }
/** * <summary> * Wraps results bean into a protocol message.</summary> * * <param name="bean">Results bean that need to be wrapped.</param> * <returns>Wrapped message.</returns> */ private static ProtoResponse WrapResultBean(GridClientResponse bean) { ProtoResponse.Builder builder = ProtoResponse.CreateBuilder() //.SetRequestId(bean.RequestId) //.SetClientId(WrapGuid(bean.ClientId)) .SetStatus((int)bean.Status); if (bean.ErrorMessage != null) { builder.SetErrorMessage(bean.ErrorMessage); } if (bean.Result != null) { builder.SetResultBean(WrapObject(bean.Result)); } if (bean.SessionToken != null) { builder.SetSessionToken(ByteString.CopyFrom(bean.SessionToken)); } return(builder.Build()); }
// Handle MAD data /* * [ * HttpPost("/raw"), * Produces("application/json"), * ] * public async Task<ProtoResponse> PostAsync(List<ProtoData> payloads) * { * Response.Headers["Accept"] = "application/json"; * Response.Headers["Content-Type"] = "application/json"; * var response await HandleProtoRequest(new ProtoPayload * { * Username = "******", * Uuid = Request.Headers["Origin"], * Contents = payloads, * }); * return response; * } */ #endregion #region Handlers private async Task <ProtoResponse> HandleProtoRequest(ProtoPayload payload) { if (payload == null) { _logger.LogError("Invalid proto payload received"); return(null); } var stopwatch = new Stopwatch(); stopwatch.Start(); var device = await _deviceRepository.GetByIdAsync(payload.Uuid).ConfigureAwait(false); if (device != null) { device.LastLatitude = payload.LatitudeTarget; device.LastLongitude = payload.LongitudeTarget; device.LastSeen = DateTime.UtcNow.ToTotalSeconds(); await _deviceRepository.UpdateAsync(device).ConfigureAwait(false); } if (!string.IsNullOrEmpty(payload.Username) && payload.Level > 0) { if (!_levelCache.ContainsKey(payload.Username)) { _levelCache.Add(payload.Username, payload.Level); } else { var oldLevel = _levelCache[payload.Username]; if (oldLevel != payload.Level) { var account = await _accountRepository.GetByIdAsync(payload.Username).ConfigureAwait(false); if (account != null) { account.Level = payload.Level; await _accountRepository.UpdateAsync(account).ConfigureAwait(false); } _levelCache[payload.Username] = payload.Level; } } } if (payload.Contents?.Count == 0) { _logger.LogWarning($"[Proto] [{payload.Uuid}] Invalid GMO"); return(null); } var wildPokemon = 0; var nearbyPokemon = 0; var clientWeather = 0; var forts = 0; var fortDetails = new List <FortDetailsOutProto>(); var quests = 0; var fortSearch = 0; var encounters = 0; var cells = new List <ulong>(); var inventory = new List <InventoryDeltaProto>(); var playerData = 0; //var spawnpoints = new List<Spawnpoint>(); var isEmptyGmo = true; var isInvalidGmo = true; var containsGmo = false; if (payload.Contents == null) { _logger.LogWarning($"[Proto] [{payload.Uuid}] Empty data"); return(null); } Coordinate targetCoord = null; var inArea = false; if (payload.LatitudeTarget != 0 && payload.LongitudeTarget != 0) { targetCoord = new Coordinate(payload.LatitudeTarget, payload.LongitudeTarget); } var targetKnown = false; S2CellId targetCellId = default; if (targetCoord != null) { // Check target is within cell id instead of checking geofences targetKnown = true; targetCellId = S2CellId.FromLatLng(S2LatLng.FromDegrees(targetCoord.Latitude, targetCoord.Longitude)); //_logger.LogDebug($"[Proto] [{payload.Uuid}] Data received within target area {targetCoord} and target distance {payload.TargetMaxDistance}"); } //_logger.LogWarning($"[{device.Uuid}] InArea={inArea}"); foreach (var rawData in payload.Contents) { if (string.IsNullOrEmpty(rawData.Data)) { _logger.LogWarning($"[Proto] [{payload.Uuid}] Unhandled proto {rawData.Method}: {rawData.Data}"); continue; } var data = rawData.Data; var method = (Method)rawData.Method; switch (method) { case Method.GetPlayer: try { var gpr = GetPlayerOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (gpr?.Success == true) { await PushData(RedisChannels.ProtoAccount, new { gpr, username = payload.Username, }); playerData++; } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed GetPlayerOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode GetPlayerOutProto: {ex}"); } break; case Method.GetHoloholoInventory: try { var ghi = GetHoloholoInventoryOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (ghi?.Success == true) { if (ghi.InventoryDelta.InventoryItem?.Count > 0) { // TODO: Publish with redis inventory.Add(ghi.InventoryDelta); } } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed GetHoloholoInventoryOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode GetHoloholoInventoryOutProto: {ex}"); } break; case Method.FortSearch: try { var fsr = FortSearchOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (fsr != null) { if (fsr.ChallengeQuest?.Quest != null) { await PushData(RedisChannels.ProtoQuest, new { raw = data, }); quests++; } //fortSearch.Add(fsr); fortSearch++; } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed FortSearchOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode FortSearchOutProto: {ex}"); } break; case Method.Encounter: isEmptyGmo = false; isInvalidGmo = false; try { if (payload.Level >= 30) { var er = EncounterOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (er?.Status == EncounterOutProto.Types.Status.EncounterSuccess) { await PushData(RedisChannels.ProtoEncounter, new { data = er, username = payload.Username, }); encounters++; } else if (er == null) { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed EncounterOutProto"); } } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode EncounterOutProto: {ex}"); } break; case Method.FortDetails: try { var fdr = FortDetailsOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (fdr != null) { fortDetails.Add(fdr); //fortDetails++; // TODO: Publish with redis //await PublishData(RedisChannels.Fort, fdr); } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed FortDetailsOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode FortDetailsOutProto: {ex}"); } break; case Method.GetMapObjects: containsGmo = true; try { var gmo = GetMapObjectsOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (gmo != null) { isInvalidGmo = false; var mapCellsNew = gmo.MapCell; if (mapCellsNew.Count == 0) { //_logger.LogDebug($"[Proto] [{payload.Uuid}] Map cells are empty"); //return null; } // Check if we're within the same cell, if so then we are within the target distance if (!inArea && targetKnown && mapCellsNew.Select(x => x.S2CellId).Contains(targetCellId.Id)) { inArea = true; } foreach (var mapCell in mapCellsNew) { cells.Add(mapCell.S2CellId); await PushData(RedisChannels.ProtoCell, mapCell.S2CellId); var tsMs = mapCell.AsOfTimeMs; foreach (var wild in mapCell.WildPokemon) { await PushData(RedisChannels.ProtoWildPokemon, new { cell = mapCell.S2CellId, data = wild, timestamp_ms = tsMs, username = payload.Username, }); wildPokemon++; } foreach (var nearby in mapCell.NearbyPokemon) { await PushData(RedisChannels.ProtoNearbyPokemon, new { cell = mapCell.S2CellId, data = nearby, timestamp_ms = tsMs, username = payload.Username, }); nearbyPokemon++; } foreach (var fort in mapCell.Fort) { await PushData(RedisChannels.ProtoFort, new { cell = mapCell.S2CellId, data = fort, }); forts++; } } foreach (var weather in gmo.ClientWeather) { await PushData(RedisChannels.ProtoWeather, new Weather(weather)); clientWeather++; } if (wildPokemon == 0 && nearbyPokemon == 0 && forts == 0 && quests == 0) { foreach (var cellId in cells) { if (!_emptyCells.ContainsKey(cellId)) { _emptyCells.Add(cellId, 1); } else { _emptyCells[cellId]++; } if (_emptyCells[cellId] == 3) { _logger.LogWarning($"[Proto] [{payload.Uuid}] Cell {cellId} was empty 3 times in a row, assuming empty..."); await PushData(RedisChannels.ProtoCell, cellId); } } _logger.LogDebug($"[Proto] [{payload.Uuid}] GMO is empty"); isEmptyGmo = true; } else { cells.ForEach(cellId => _emptyCells[cellId] = 0); isEmptyGmo = false; } } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed GetMapObjectsOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode GetMapObjectsOutProto: {ex}"); } break; case Method.GymGetInfo: try { var ggi = GymGetInfoOutProto.Parser.ParseFrom(Convert.FromBase64String(data)); if (ggi != null) { if (ggi.GymStatusAndDefenders == null) { ConsoleExt.WriteWarn($"[DataConsumer] Invalid GymStatusAndDefenders provided, skipping...\n: {ggi}"); continue; } var fortId = ggi.GymStatusAndDefenders.PokemonFortProto.FortId; var gymDefenders = ggi.GymStatusAndDefenders.GymDefender; if (gymDefenders == null) { continue; } foreach (var gymDefender in gymDefenders) { if (gymDefender.TrainerPublicProfile != null) { await PushData(RedisChannels.ProtoGymTrainer, new Trainer(gymDefender)); } if (gymDefender.MotivatedPokemon != null) { await PushData(RedisChannels.ProtoGymDefender, new GymDefender(fortId, gymDefender)); } } } else { _logger.LogError($"[Proto] [{payload.Uuid}] Malformed GymGetInfoOutProto"); } } catch (Exception ex) { _logger.LogError($"[Proto] [{payload.Uuid}] Unable to decode GymGetInfoOutProto: {ex}"); } break; //case Method.Unset: default: _logger.LogDebug($"[Proto] [{payload.Uuid}] Invalid method or data provided. {method}:{data}"); break; } } Coordinate pokemonCoords = null; /* * if (targetCoord != null) * { * foreach (var fort in forts) * { * if (!inArea) * { * var coord = new Coordinate(fort.data.Latitude, fort.data.Longitude); * if (coord.DistanceTo(targetCoord) <= payload.TargetMaxDistance) * { * inArea = true; * } * } * } * } * if (targetCoord != null || payload.PokemonEncounterId != null) * { * foreach (var pokemon in wildPokemons) * { * WildPokemonProto wild = (WildPokemonProto)pokemon.data; * if (targetCoord != null) * { * if (pokemonCoords != null && inArea) * { * break; * } * * if (!inArea) * { * var coord = new Coordinate(wild.Latitude, wild.Longitude); * if (coord.DistanceTo(targetCoord) <= payload.TargetMaxDistance) * { * inArea = true; * } * } * } * if (!string.IsNullOrEmpty(payload.PokemonEncounterId)) * { * if (pokemonCoords != null && inArea) * { * break; * } * * if (pokemonCoords == null) * { * if (string.Compare(wild.EncounterId.ToString(), payload.PokemonEncounterId, true) == 0) * { * pokemonCoords = new Coordinate(wild.Latitude, wild.Longitude); * } * } * } * } * } * if (targetCoord != null && !inArea) * { * foreach (var cell in cells) * { * if (inArea) * { * break; * } * * var s2cell = new S2Cell(new S2CellId(cell)); * var latlng = new S2LatLng(s2cell.Center); * var coord = new Coordinate(latlng.LatDegrees, latlng.LngDegrees); * if (coord.DistanceTo(targetCoord) <= Math.Max(payload.TargetMaxDistance ?? 250, 100)) * { * inArea = true; * } * } * } */ stopwatch.Stop(); var response = new ProtoResponse { Status = "ok", Data = new ProtoDataDetails { Nearby = nearbyPokemon, Wild = wildPokemon, Forts = forts, Quests = quests, FortSearch = fortSearch, Encounters = encounters, Level = payload.Level, OnlyEmptyGmos = containsGmo && isEmptyGmo, OnlyInvalidGmos = containsGmo && isInvalidGmo, ContainsGmos = containsGmo, InArea = inArea, LatitudeTarget = targetCoord?.Latitude, LongitudeTarget = targetCoord?.Longitude, PokemonLatitude = pokemonCoords?.Latitude, PokemonLongitude = pokemonCoords?.Longitude, PokemonEncounterId = payload.PokemonEncounterId, }, }; _logger.LogInformation($"[{payload.Uuid}] {response.ToJson()} parsed in {stopwatch.Elapsed.TotalSeconds}s"); return(response); }
/** * <summary> * Converts protocol object into object.</summary> * * <param name="val">Protocol message object to convert into value.</param> * <returns>Recovered object.</returns> */ public static Object WrapObject(ObjectWrapper val) { byte[] bin = val.Binary.ToByteArray(); // Primitives. switch (val.Type) { case ObjectWrapperType.NONE: return(null); case ObjectWrapperType.BOOL: Dbg.Assert(bin.Length == 1, "bin.Length == 1"); return(bin[0] != 0); case ObjectWrapperType.BYTE: Dbg.Assert(bin.Length == 1, "bin.Length == 1"); return(bin[0]); case ObjectWrapperType.SHORT: Dbg.Assert(bin.Length == 2, "bin.Length == 2"); return(U.BytesToInt16(bin, 0)); case ObjectWrapperType.INT32: Dbg.Assert(bin.Length == 4, "bin.Length == 4"); return(U.BytesToInt32(bin, 0)); case ObjectWrapperType.INT64: Dbg.Assert(bin.Length == 8, "bin.Length == 8"); return(U.BytesToInt64(bin, 0)); case ObjectWrapperType.FLOAT: Dbg.Assert(bin.Length == 4, "bin.Length == 4"); return(U.BytesToSingle(bin, 0)); case ObjectWrapperType.DOUBLE: Dbg.Assert(bin.Length == 8, "bin.Length == 8"); return(U.BytesToDouble(bin, 0)); case ObjectWrapperType.BYTES: return(bin); case ObjectWrapperType.UUID: return(WrapGuid(val.Binary)); case ObjectWrapperType.STRING: return(val.Binary.ToStringUtf8()); case ObjectWrapperType.COLLECTION: return(WrapCollection(Collection.ParseFrom(bin))); case ObjectWrapperType.MAP: return(WrapMap(Map.ParseFrom(bin))); case ObjectWrapperType.AUTH_REQUEST: return(WrapAuthRequest(ProtoRequest.ParseFrom(bin))); case ObjectWrapperType.CACHE_REQUEST: return(WrapCacheRequest(ProtoRequest.ParseFrom(bin))); case ObjectWrapperType.TASK_REQUEST: return(WrapTaskRequest(ProtoRequest.ParseFrom(bin))); case ObjectWrapperType.LOG_REQUEST: return(WrapLogRequest(ProtoRequest.ParseFrom(bin))); case ObjectWrapperType.TOPOLOGY_REQUEST: return(WrapTopologyRequest(ProtoRequest.ParseFrom(bin))); case ObjectWrapperType.RESPONSE: return(WrapResponse(ProtoResponse.ParseFrom(bin))); case ObjectWrapperType.NODE_BEAN: return(WrapNode(ProtoNodeBean.ParseFrom(bin))); case ObjectWrapperType.TASK_BEAN: return(WrapTaskResult(ProtoTaskBean.ParseFrom(bin))); default: throw new ArgumentException("Failed to deserialize object (object deserialization" + " of given type is not supported): " + val.Type); } }