github.com/racerxdl/gonx@v0.0.0-20210103083128-c5afc43bcbd2/services/sm/sm.go (about) 1 package sm 2 3 import ( 4 "fmt" 5 "github.com/racerxdl/gonx/nx/nxerrors" 6 "github.com/racerxdl/gonx/nx/nxtypes" 7 "github.com/racerxdl/gonx/services/ipc" 8 "github.com/racerxdl/gonx/svc" 9 ) 10 11 var smInitializations = 0 12 var smObject ipc.Object 13 14 const ( 15 smServiceName = "sm:\x00" 16 debugSm = false 17 ) 18 19 // str2u64 converts a string to uint64 representation 20 // used on SM service name 21 func str2u64(str string) uint64 { 22 var b [8]byte 23 24 for i := 0; i < 8; i++ { 25 if len(str) <= i { 26 break 27 } 28 b[i] = str[i] 29 } 30 31 return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | 32 uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 33 } 34 35 // Init initializes the SM Service if needed 36 func Init() error { 37 if debugSm { 38 println("SM::Init") 39 } 40 if smInitializations > 0 { 41 smInitializations++ // Already initialized, increment ref count 42 return nil 43 } 44 45 smInitializations++ 46 47 smObject.ObjectID = -1 48 handle := nxtypes.Handle(0) 49 smName := []byte(smServiceName) 50 r := svc.ConnectToNamedPort(&handle, &smName[0]) 51 if r != nxtypes.ResultOK { 52 smInitializations-- 53 return nxerrors.IPCError{ 54 Message: "error initializing sm", 55 Result: r, 56 } 57 } 58 59 smObject.SetSession(handle) 60 61 // sm:#0 Initialize 62 rq := ipc.MakeDefaultRequest(0) 63 rq.SendPID = true 64 rq.SetRawDataFromUint64(uint64(0)) 65 66 rs := ipc.ResponseFmt{} 67 68 err := ipc.Send(smObject, &rq, &rs) 69 if err != nil { 70 if debugSm { 71 fmt.Printf("error initializing sm: %s", err) 72 } 73 _ = ipc.Close(&smObject) 74 smInitializations-- 75 return err 76 } 77 78 return nil 79 } 80 81 // Finalize closes the a initialized SM Service 82 func Finalize() { 83 smInitializations-- 84 if smInitializations == 0 { 85 smForceFinalize() 86 } 87 } 88 89 func smForceFinalize() { 90 _ = ipc.Close(&smObject) 91 smInitializations = 0 92 } 93 94 func GetService(outObject *ipc.Object, name string) error { 95 if debugSm { 96 fmt.Printf("SM::GetService(%p, %s)\n", outObject, name) 97 } 98 if smObject.GetSession() == 0 { 99 return nxerrors.SmNotInitialized 100 } 101 102 if len(name) > 8 { 103 return nxerrors.SmServiceNameTooLong 104 } 105 106 serviceName := str2u64(name) 107 outObject.ObjectID = -1 108 outObject.IsBorrowed = false 109 110 rq := ipc.MakeDefaultRequest(1) 111 rq.SetRawDataFromUint64(serviceName) 112 113 rs := ipc.ResponseFmt{} 114 rs.MoveHandles = make([]nxtypes.Handle, 1) 115 116 err := ipc.Send(smObject, &rq, &rs) 117 if err != nil { 118 return err 119 } 120 121 outObject.SetSession(rs.MoveHandles[0]) 122 123 return nil 124 }