XYOracleNetwork/sdk-core-swift

View on GitHub
Sources/sdk-core-swift/persist/repositories/XyoStorageTcpPeerRepository.swift

Summary

Maintainability
D
1 day
Test Coverage
//
//  XyoStorageTcpPeerRepository.swift
//  sdk-core-swift
//
//  Created by Carter Harrison on 2/25/19.
//  Copyright © 2019 XYO Network. All rights reserved.
//

import Foundation

public class XyoStorageTcpPeerRepository : XyoTcpPeerRepository {
    
    private static let PEER_ARRAY_INDEX_KEY = Array("PEER_ARRAY_INDEX_KEY".utf8)
    
    private var peerCache = [XyoTcpPeer]()
    private let storage : XyoStorageProvider
    
    public init (storage : XyoStorageProvider) {
        self.storage = storage
    }
    
    public func getRandomPeer() -> XyoTcpPeer? {
        let allPeers = getPeers()
        
        if (allPeers.count > 0) {
            return nil
        }
        
        return allPeers[Int(arc4random_uniform(UInt32(allPeers.count)))]
    }
    
    public func getPeers() -> [XyoTcpPeer] {
        return peerCache
    }
    
    public func addPeer(peer: XyoTcpPeer) {
        peerCache = getPeers()
        peerCache.append(peer)
        savePeerList(peers: peerCache)
    }
    
    public func removePeer(peer: XyoTcpPeer) {
        removePeerFromCache(peer: peer)
        savePeerList(peers: peerCache)
    }
    
    private func restorePeers () {
        var peers = [XyoTcpPeer]()
        let stringPeers = getPeerIndex()
        
        for i in 0...stringPeers.count {
            let peer = stringPeerToTcpPeer(string: stringPeers[i])
            
            if (peer != nil) {
                peers.append(peer!)
            }
        }
        
        peerCache = peers
    }
    
    private func savePeerList (peers : [XyoTcpPeer]) {
        var structures = [XyoObjectStructure]()
        
        for peer in peers {
            let content = XyoBuffer(data: Array(tcpPeerToStringPeer(peer: peer).utf8))
            let structure = XyoObjectStructure.newInstance(schema: XyoSchemas.BLOB, bytes: content)
            structures.append(structure)
        }
        
        let encodedIndex = XyoIterableStructure.createUntypedIterableObject(schema: XyoSchemas.ARRAY_TYPED, values: structures).getBuffer().toByteArray()
        
        do {
            try storage.write(key: XyoStorageTcpPeerRepository.PEER_ARRAY_INDEX_KEY, value: encodedIndex)
        } catch  {
            // todo handle this error
        }
    }
    
    private func stringPeerToTcpPeer (string : String) -> XyoTcpPeer? {
        let sections = string.split(separator: ":")
        
        if (sections.count != 2) {
            return nil
        }
        
        let ip = String(sections[0])
        guard let port = UInt32(sections[1]) else {
            return nil
        }
        
        return XyoTcpPeer(ip: ip, port: port)
    }
    
    private func tcpPeerToStringPeer (peer : XyoTcpPeer) -> String {
        return "\(peer.ip):\(peer.port)"
    }
    
    private func getPeerIndex () -> [String] {
        do {
            var peers = [String]()
            
            guard let encodedPeersArray = try storage.read(key: XyoStorageTcpPeerRepository.PEER_ARRAY_INDEX_KEY) else {
                return []
            }
            
            let peersArrayIt = try XyoIterableStructure(value: XyoBuffer(data: encodedPeersArray)).getNewIterator()
            
            while try peersArrayIt.hasNext() {
                let peer = String(bytes: try peersArrayIt.next().getValueCopy().toByteArray(), encoding: String.Encoding.utf8)
                
                if (peer != nil) {
                    peers.append(peer!)
                }
            }
            
            return peers
        } catch {
            return []
        }
    }
    
    private func removePeerFromCache (peer: XyoTcpPeer) {
        guard let indexOfPeer = (peerCache.firstIndex { (cachedPeer) -> Bool in
            let ipSame = peer.ip == cachedPeer.ip
            
            if (ipSame) {
                return peer.port == cachedPeer.port
            }
            
            return false
        }) else { return }
        
        peerCache.remove(at: indexOfPeer)
    }
}