def activate_profile(self, name: str) -> RetVal: ''' Activates the specified profile. Returns: "error" : string "wid" : string "host" : string "port" : integer ''' if self.active_index >= 0: self.profiles[self.active_index].deactivate() self.active_index = -1 if not name: return RetVal(BadParameterValue, "BUG: name may not be empty") name_squashed = name.casefold() active_index = self.__index_for_profile(name_squashed) if active_index < 0: return RetVal(ResourceNotFound, "%s doesn't exist" % name_squashed) self.profile_id = name_squashed self.active_index = active_index self.profiles[self.active_index].activate() out = RetVal() out.set_values({ 'wid': self.profiles[active_index].wid, 'host': self.profiles[active_index].domain, 'port': self.profiles[active_index].port }) return out
def register(conn: ServerConnection, uid: str, pwhash: str, devicekey: CryptoString) -> RetVal: '''Creates an account on the server.''' if uid and len(re.findall(r'[\/" \s]',uid)) > 0: return RetVal(BadParameterValue, 'user id contains illegal characters') # This construct is a little strange, but it is to work around the minute possibility that # there is a WID collision, i.e. the WID generated by the client already exists on the server. # In such an event, it should try again. However, in the ridiculously small chance that the # client keeps generating collisions, it should wait 3 seconds after 10 collisions to reduce # server load. out = RetVal() devid = str(uuid.uuid4()) wid = '' response = dict() tries = 1 while not wid: if not tries % 10: time.sleep(3.0) # Technically, the active profile already has a WID, but it is not attached to a domain and # doesn't matter as a result. Rather than adding complexity, we just generate a new UUID # and always return the replacement value wid = str(uuid.uuid4()) request = { 'Action' : 'REGISTER', 'Data' : { 'Workspace-ID' : wid, 'Password-Hash' : pwhash, 'Device-ID' : devid, 'Device-Key' : devicekey.as_string() } } if uid: request['Data']['User-ID'] = uid status = conn.send_message(request) if status.error(): return status response = conn.read_response(server_response) if response.error(): return response if response['Code'] in [ 101, 201]: # Pending, Success out.set_values({ 'devid' : devid, 'wid' : wid, 'domain' : response['Data']['Domain'], 'uid' : uid }) break if response['Code'] == 408: # WID or UID exists if 'Field' not in response['Data']: return RetVal(ServerError, 'server sent 408 without telling what existed') if response['Data']['Field'] not in ['User-ID', 'Workspace-ID']: return RetVal(ServerError, 'server sent bad 408 response').set_value( \ 'Field', response['Data']['Field']) if response['Data']['Field'] == 'User-ID': return RetVal(ResourceExists, 'user id') tries = tries + 1 wid = '' else: # Something we didn't expect -- reg closed, payment req'd, etc. return wrap_server_error(response) return out