github.com/status-im/status-go@v1.1.0/server/pairing/handlers.go (about) 1 package pairing 2 3 import ( 4 "io" 5 "net/http" 6 7 "go.uber.org/zap" 8 9 "github.com/status-im/status-go/signal" 10 ) 11 12 const ( 13 // Handler routes for pairing 14 pairingBase = "/pairing" 15 pairingChallenge = pairingBase + "/challenge" 16 pairingSendAccount = pairingBase + "/sendAccount" 17 pairingReceiveAccount = pairingBase + "/receiveAccount" 18 pairingSendSyncDevice = pairingBase + "/sendSyncDevice" 19 pairingReceiveSyncDevice = pairingBase + "/receiveSyncDevice" 20 pairingSendInstallation = pairingBase + "/sendInstallation" 21 pairingReceiveInstallation = pairingBase + "/receiveInstallation" 22 ) 23 24 // Account handling 25 26 func handleReceiveAccount(logger *zap.Logger, pr PayloadReceiver) http.HandlerFunc { 27 return func(w http.ResponseWriter, r *http.Request) { 28 signal.SendLocalPairingEvent(Event{Type: EventConnectionSuccess, Action: ActionPairingAccount}) 29 payload, err := io.ReadAll(r.Body) 30 if err != nil { 31 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionPairingAccount}) 32 logger.Error("handleReceiveAccount io.ReadAll(r.Body)", zap.Error(err)) 33 http.Error(w, "error", http.StatusInternalServerError) 34 return 35 } 36 signal.SendLocalPairingEvent(Event{Type: EventTransferSuccess, Action: ActionPairingAccount}) 37 38 err = pr.Receive(payload) 39 if err != nil { 40 signal.SendLocalPairingEvent(Event{Type: EventProcessError, Error: err.Error(), Action: ActionPairingAccount}) 41 logger.Error("handleReceiveAccount pr.Receive(payload)", zap.Error(err), zap.Binary("payload", payload)) 42 http.Error(w, "error", http.StatusInternalServerError) 43 return 44 } 45 signal.SendLocalPairingEvent(Event{Type: EventProcessSuccess, Action: ActionPairingAccount}) 46 } 47 } 48 49 func handleSendAccount(logger *zap.Logger, pm PayloadMounter, beforeSending func()) http.HandlerFunc { 50 return func(w http.ResponseWriter, r *http.Request) { 51 signal.SendLocalPairingEvent(Event{Type: EventConnectionSuccess, Action: ActionPairingAccount}) 52 w.Header().Set("Content-Type", "application/octet-stream") 53 err := pm.Mount() 54 if err != nil { 55 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionPairingAccount}) 56 logger.Error("handleSendAccount pm.Mount()", zap.Error(err)) 57 http.Error(w, "error", http.StatusInternalServerError) 58 return 59 } 60 61 beforeSending() 62 _, err = w.Write(pm.ToSend()) 63 if err != nil { 64 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionPairingAccount}) 65 logger.Error("handleSendAccount w.Write(pm.ToSend())", zap.Error(err)) 66 http.Error(w, "error", http.StatusInternalServerError) 67 return 68 } 69 signal.SendLocalPairingEvent(Event{Type: EventTransferSuccess, Action: ActionPairingAccount}) 70 71 pm.LockPayload() 72 } 73 } 74 75 // Device sync handling 76 77 func handleParingSyncDeviceReceive(logger *zap.Logger, pr PayloadReceiver) http.HandlerFunc { 78 return func(w http.ResponseWriter, r *http.Request) { 79 signal.SendLocalPairingEvent(Event{Type: EventConnectionSuccess, Action: ActionSyncDevice}) 80 payload, err := io.ReadAll(r.Body) 81 if err != nil { 82 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionSyncDevice}) 83 logger.Error("handleParingSyncDeviceReceive io.ReadAll(r.Body)", zap.Error(err)) 84 http.Error(w, "error", http.StatusInternalServerError) 85 return 86 } 87 signal.SendLocalPairingEvent(Event{Type: EventTransferSuccess, Action: ActionSyncDevice}) 88 89 err = pr.Receive(payload) 90 if err != nil { 91 signal.SendLocalPairingEvent(Event{Type: EventProcessError, Error: err.Error(), Action: ActionSyncDevice}) 92 logger.Error("handleParingSyncDeviceReceive pr.Receive(payload)", zap.Error(err), zap.Binary("payload", payload)) 93 http.Error(w, "error", http.StatusInternalServerError) 94 return 95 } 96 signal.SendLocalPairingEvent(Event{Type: EventProcessSuccess, Action: ActionSyncDevice}) 97 } 98 } 99 100 func handlePairingSyncDeviceSend(logger *zap.Logger, pm PayloadMounter, beforeSending func()) http.HandlerFunc { 101 return func(w http.ResponseWriter, r *http.Request) { 102 signal.SendLocalPairingEvent(Event{Type: EventConnectionSuccess, Action: ActionSyncDevice}) 103 w.Header().Set("Content-Type", "application/octet-stream") 104 105 err := pm.Mount() 106 if err != nil { 107 // maybe better to use a new event type here instead of EventTransferError? 108 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionSyncDevice}) 109 logger.Error("handlePairingSyncDeviceSend pm.Mount()", zap.Error(err)) 110 http.Error(w, "error", http.StatusInternalServerError) 111 return 112 } 113 114 beforeSending() 115 _, err = w.Write(pm.ToSend()) 116 if err != nil { 117 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionSyncDevice}) 118 logger.Error("handlePairingSyncDeviceSend w.Write(pm.ToSend())", zap.Error(err)) 119 http.Error(w, "error", http.StatusInternalServerError) 120 return 121 } 122 signal.SendLocalPairingEvent(Event{Type: EventTransferSuccess, Action: ActionSyncDevice}) 123 124 pm.LockPayload() 125 } 126 } 127 128 // Installation data handling 129 130 func handleReceiveInstallation(logger *zap.Logger, pmr PayloadMounterReceiver) http.HandlerFunc { 131 return func(w http.ResponseWriter, r *http.Request) { 132 signal.SendLocalPairingEvent(Event{Type: EventConnectionSuccess, Action: ActionPairingInstallation}) 133 payload, err := io.ReadAll(r.Body) 134 if err != nil { 135 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionPairingInstallation}) 136 logger.Error("handleReceiveInstallation io.ReadAll(r.Body)", zap.Error(err)) 137 http.Error(w, "error", http.StatusInternalServerError) 138 return 139 } 140 signal.SendLocalPairingEvent(Event{Type: EventTransferSuccess, Action: ActionPairingInstallation}) 141 142 err = pmr.Receive(payload) 143 if err != nil { 144 signal.SendLocalPairingEvent(Event{Type: EventProcessError, Error: err.Error(), Action: ActionPairingInstallation}) 145 logger.Error("handleReceiveInstallation pmr.Receive(payload)", zap.Error(err), zap.Binary("payload", payload)) 146 http.Error(w, "error", http.StatusInternalServerError) 147 return 148 } 149 signal.SendLocalPairingEvent(Event{Type: EventProcessSuccess, Action: ActionPairingInstallation}) 150 } 151 } 152 153 func handleSendInstallation(logger *zap.Logger, pmr PayloadMounterReceiver, beforeSending func()) http.HandlerFunc { 154 return func(w http.ResponseWriter, r *http.Request) { 155 signal.SendLocalPairingEvent(Event{Type: EventConnectionSuccess, Action: ActionPairingInstallation}) 156 w.Header().Set("Content-Type", "application/octet-stream") 157 err := pmr.Mount() 158 if err != nil { 159 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionPairingInstallation}) 160 logger.Error("handleSendInstallation pmr.Mount()", zap.Error(err)) 161 http.Error(w, "error", http.StatusInternalServerError) 162 return 163 } 164 165 beforeSending() 166 _, err = w.Write(pmr.ToSend()) 167 if err != nil { 168 signal.SendLocalPairingEvent(Event{Type: EventTransferError, Error: err.Error(), Action: ActionPairingInstallation}) 169 logger.Error("handleSendInstallation w.Write(pmr.ToSend())", zap.Error(err)) 170 http.Error(w, "error", http.StatusInternalServerError) 171 return 172 } 173 signal.SendLocalPairingEvent(Event{Type: EventTransferSuccess, Action: ActionPairingInstallation}) 174 175 pmr.LockPayload() 176 } 177 } 178 179 // Challenge middleware and handling 180 181 func middlewareChallenge(cg *ChallengeGiver, next http.Handler) http.HandlerFunc { 182 return func(w http.ResponseWriter, r *http.Request) { 183 err := cg.checkChallengeResponse(w, r) 184 if err != nil { 185 if cErr, ok := err.(*ChallengeError); ok { 186 http.Error(w, cErr.Text, cErr.HTTPCode) 187 return 188 } 189 cg.logger.Error("failed to checkChallengeResponse in middlewareChallenge", zap.Error(err)) 190 http.Error(w, "error", http.StatusInternalServerError) 191 return 192 } 193 194 next.ServeHTTP(w, r) 195 } 196 } 197 198 func handlePairingChallenge(cg *ChallengeGiver) http.HandlerFunc { 199 return func(w http.ResponseWriter, r *http.Request) { 200 challenge, err := cg.getChallenge(w, r) 201 if err != nil { 202 if cErr, ok := err.(*ChallengeError); ok { 203 http.Error(w, cErr.Text, cErr.HTTPCode) 204 return 205 } 206 cg.logger.Error("failed to getChallenge in handlePairingChallenge", zap.Error(err)) 207 http.Error(w, "error", http.StatusInternalServerError) 208 return 209 } 210 211 w.Header().Set("Content-Type", "application/octet-stream") 212 _, err = w.Write(challenge) 213 if err != nil { 214 cg.logger.Error("failed to Write(challenge) in handlePairingChallenge", zap.Error(err)) 215 http.Error(w, "error", http.StatusInternalServerError) 216 return 217 } 218 } 219 }