2016-11-02 1 views
0

J'ai un objet struct. Et une méthode, dont l'entrée est la charge utile. Maintenant, je crée un mutableData nommé packet, et ses octets mutables font référence à la structure ICMPHeader.Les octets de NSMutableData à UnsafeMutableRawPointer ne mettant pas à jour la valeur de mutableData

struct ICMPHeader { 
    var type:UInt8 
    var code:UInt8 
    var checksum:UInt16 
    var identifier:UInt16 
    var sequenceNumber:UInt16 
}; 


func createPacket(payload:NSData) -> NSData(){ 
    var packet:NSMutableData? 
    var icmpPtr:ICMPHeader = ICMPHeader(type: 0, code: 0, checksum: 0, identifier: 0, sequenceNumber: 0) 
    packet = NSMutableData(length: Int(MemoryLayout<ICMPHeader>.size + payload.length)) 

    if packet != nil { 

     icmpPtr = packet!.mutableBytes.assumingMemoryBound(to: ICMPHeader.self).pointee 

     icmpPtr.type = type 
     icmpPtr.code = 0 
     icmpPtr.checksum = 0 
     icmpPtr.identifier = CFSwapInt16BigToHost(identifier) 
     icmpPtr.sequenceNumber = CFSwapInt16HostToBig(identifier) 
     memcpy(&icmpPtr + 1, payload.bytes, payload.length) 

     if (requiresChecksum) { 
      icmpPtr.checksum = in_cksum(packet!.bytes, bufferLen: packet!.length); 
     } 

    } 
    return packet 
} 

octets Mutable sont obtenir avec succès binded struct, et les valeurs sont mises à jour en se struct ICMPHeader.

Le problème est de changer les valeurs dans struct ne change pas la valeur des données mutables packet.

Et si, j'essaye de recréer le paquet après avoir créé la structure, alors il plante.

package = NSMutableData(bytes: unsafeBitCast(icmpPtr, to: UnsafeMutableRawPointer.self), length: Int(MemoryLayout<ICMPHeader>.size + payload.length)) 

Répondre

0

J'ai trouvé la réponse dans les notes de version de XCode 8.1 Swift.

Après avoir apporté les modifications dans l'objet struct icmpPtr, je l'ai redéfini sur le pointeur de la mémoire tampon. Donc, au lieu de créer le nouvel objet de données, j'ai remplacé les octets et cela a fonctionné comme un charme.

Selon la documentation:

XCode 8.1 Release Notes: https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html Section Swift:

Un nouveau withUnsafeBytes (de :) fonction expose en mémoire représentation d'une valeur en tant UnsafeRawBufferPointer. Cet exemple copie un struct hétérogène dans une matrice homogène d'octets:

struct Header { 
var x: Int 
var y: Float 
} 

var header = Header(x: 0, y: 0.0) 
var byteBuffer = [UInt8]() 

withUnsafeBytes(of: &header) { 
    (bytes: UnsafeRawBufferPointer) in byteBuffer += bytes 
} 

Une nouvelle méthode de Array.withUnsafeBytes expose tampon sous-jacent d'un tableau comme UnsafeRawBufferPointer. Cet exemple copie un tableau de entiers dans un tableau d'octets:

let intArray = [1, 2, 3] 
var byteBuffer = [UInt8]() 

intArray.withUnsafeBytes { 
    (bytes: UnsafeRawBufferPointer) in byteBuffer += bytes 
} 

donc la mise en œuvre finale est

struct ICMPHeader { 
    var type:UInt8 
    var code:UInt8 
    var checksum:UInt16 
    var identifier:UInt16 
    var sequenceNumber:UInt16 
}; 


func createPacket(payload:NSData) -> NSData(){ 
    var packet:NSMutableData? 
    var icmpPtr:ICMPHeader = ICMPHeader(type: 0, code: 0, checksum: 0, identifier: 0, sequenceNumber: 0) 
    packet = NSMutableData(length: Int(MemoryLayout<ICMPHeader>.size + payload.length)) 

    if packet != nil { 

     icmpPtr = packet!.mutableBytes.assumingMemoryBound(to: ICMPHeader.self).pointee 

     icmpPtr.type = type 
     icmpPtr.code = 0 
     icmpPtr.checksum = 0 
     icmpPtr.identifier = CFSwapInt16BigToHost(identifier) 
     icmpPtr.sequenceNumber = CFSwapInt16HostToBig(identifier) 
     memcpy(&icmpPtr + 1, payload.bytes, payload.length) 

     if (requiresChecksum) { 
      icmpPtr.checksum = in_cksum(packet!.bytes, bufferLen: packet!.length); 
     } 

     var byteBuffer = [UInt8]() 
     withUnsafeBytes(of: &icmpPtr) { 
     (bytes: UnsafeRawBufferPointer) in byteBuffer += bytes 
     } 
     packet.replaceBytes(in: NSMakeRange(0, byteBuffer.count), withBytes: byteBuffer) 

    } 
    return packet 
}