예제 #1
0
    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
예제 #2
0
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