DomainServiceObjectDispatchTable.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. using Ryujinx.Horizon.Common;
  2. using System;
  3. using System.Runtime.CompilerServices;
  4. using System.Runtime.InteropServices;
  5. namespace Ryujinx.Horizon.Sdk.Sf.Cmif
  6. {
  7. class DomainServiceObjectDispatchTable : ServiceDispatchTableBase
  8. {
  9. public override Result ProcessMessage(ref ServiceDispatchContext context, ReadOnlySpan<byte> inRawData)
  10. {
  11. return ProcessMessageImpl(ref context, ((DomainServiceObject)context.ServiceObject).GetServerDomain(), inRawData);
  12. }
  13. private Result ProcessMessageImpl(ref ServiceDispatchContext context, ServerDomainBase domain, ReadOnlySpan<byte> inRawData)
  14. {
  15. if (inRawData.Length < Unsafe.SizeOf<CmifDomainInHeader>())
  16. {
  17. return SfResult.InvalidHeaderSize;
  18. }
  19. var inHeader = MemoryMarshal.Cast<byte, CmifDomainInHeader>(inRawData)[0];
  20. ReadOnlySpan<byte> inDomainRawData = inRawData[Unsafe.SizeOf<CmifDomainInHeader>()..];
  21. int targetObjectId = inHeader.ObjectId;
  22. switch (inHeader.Type)
  23. {
  24. case CmifDomainRequestType.SendMessage:
  25. var targetObject = domain.GetObject(targetObjectId);
  26. if (targetObject == null)
  27. {
  28. return SfResult.TargetNotFound;
  29. }
  30. if (inHeader.DataSize + inHeader.ObjectsCount * sizeof(int) > inDomainRawData.Length)
  31. {
  32. return SfResult.InvalidHeaderSize;
  33. }
  34. ReadOnlySpan<byte> inMessageRawData = inDomainRawData[..inHeader.DataSize];
  35. if (inHeader.ObjectsCount > DomainServiceObjectProcessor.MaximumObjects)
  36. {
  37. return SfResult.InvalidInObjectsCount;
  38. }
  39. int[] inObjectIds = new int[inHeader.ObjectsCount];
  40. var domainProcessor = new DomainServiceObjectProcessor(domain, inObjectIds);
  41. if (context.Processor == null)
  42. {
  43. context.Processor = domainProcessor;
  44. }
  45. else
  46. {
  47. context.Processor.SetImplementationProcessor(domainProcessor);
  48. }
  49. context.ServiceObject = targetObject.ServiceObject;
  50. return targetObject.ProcessMessage(ref context, inMessageRawData);
  51. case CmifDomainRequestType.Close:
  52. domain.UnregisterObject(targetObjectId);
  53. return Result.Success;
  54. default:
  55. return SfResult.InvalidInHeader;
  56. }
  57. }
  58. }
  59. }