func cmdJsonFromBencoding(args []string) { if len(args) != 0 { logger.Fatalf("Usage: %v from-bencoding < FOO.torrent > FOO.bittorrent.json", os.Args[0]) return } data, err := ioutil.ReadAll(os.Stdin) if err != nil { logger.Fatalf("Error reading stdin: %v", err) return } decoded, err := bencoding.Decode(data) if err != nil { logger.Fatalf("Error bdecoding stdin: %v", err) return } jsonable, err := decoded.ToJsonable() if err != nil { logger.Fatalf("Error converting bencoded value to jsonable: %v", err) } jsoned, err := json.Marshal(jsonable) if err != nil { logger.Fatalf("Error json-encoding data: %v", err) return } os.Stdout.Write(jsoned) os.Stdout.Sync() }
func (s *swarm) SetInfo(info []byte) (err error) { hashData := sha1.Sum(info) hash := string(hashData[:]) if s.InfoHash() == BTID(hash) { info, _ := bencoding.Decode(info) s.info = info.(bencoding.Dict) logger.Info("Validated full info for torrent! %v", s) return nil } else { logger.Error("Infohash invalid: %v expected != %v actual", s.InfoHash(), BTID(hash)) return errors.New("info hash was invalid") } }
func (local *localNode) rpcListenLoop(terminate <-chan bool) { response := new([1024]byte) for { logger.Info("Waiting for next incoming UDP message.") n, remoteAddr, err := local.Connection.ReadFromUDP(response[:]) _ = remoteAddr if err != nil { logger.Info("Ignoring UDP read err: %v", err) continue } result, err := bencoding.Decode(response[:n]) if err != nil { logger.Info("Ignoring un-bedecodable message: %v", err) continue } resultD, ok := result.(bencoding.Dict) if !ok { logger.Info("Ignoring bedecoded non-dict message: %v", err) continue } transactionId := string(resultD["t"].(bencoding.String)) query, ok := local.OutstandingQueries[transactionId] if !ok { logger.Info("Ignoring query response with unexpected token.") continue } query.Remote.LastResponseFrom = time.Now() resultBody, ok := resultD["r"].(bencoding.Dict) if !ok { logger.Info("Ignoring response with non-dict contents.") continue } query.Result <- &resultBody delete(local.OutstandingQueries, transactionId) } }
func (p *swarmPeer) onExtensionMessage(body string) { if len(body) == 0 { logger.Warning("got extension message with 0-length body -- what?!") return } extensionId := body[0] // TODO: A more sensible generic way of handling extensions and extension mesages if extensionId == 0 { // Handshake! logger.Info("Got an extension handshake message") bencoded := body[1:] data, err := bencoding.Decode([]byte(bencoded)) if err != nil { logger.Error("Error decoding message: %v", err) return } // Check if the peer supports metadata exchange if dataM, hasM := data.(bencoding.Dict)["m"]; hasM { if mdxIdP, hasMdx := dataM.(bencoding.Dict)["ut_metadata"]; hasMdx { mdxId := uint8(mdxIdP.(bencoding.Int)) if mdxId != 0 { logger.Info("Peer %v supports metadata exchange, using extension ID %v.", p, mdxId) p.extensions.bep9MetadataExchange.supported = true p.extensions.bep9MetadataExchange.id = mdxId go p.requestNextMetadataPiece() } else { logger.Info("Peer %v does not support metadata exchange!", p) return } } else { logger.Info("Peer %v does not support metadata exchange!", p) return } } else { logger.Info("Peer %v does not support metadata exchange!", p) return } } else if p.extensions.bep9MetadataExchange.supported && extensionId == ourUtMetadataId { p.onMdxMessage(body[1:]) } else { logger.Warning("got extension message for unrecognied extension id %v from %v: %v", extensionId, p, body[1:]) } }
/* OpenClient instantiates a client whose state will be persisted at the specified path. Existing state will be loaded if it exists, otherwise a new client will be generated using a node a randomly-selected ID and port. A filesystem lock will be used to ensure that only one Client may be open with a given path at a time. The blocking parameter determines whether we block or return an error when another Client is using the path. */ func OpenClient(path string, blocking bool) (c Client, err error) { var ( openDataFile *os.File nodeData []byte nodeDict bencoding.Bencodable nodeDictAsDict bencoding.Dict ok bool lc *localNodeClient ) lc = new(localNodeClient) openDataFile, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644) if err != nil { return } lc.openDataFile = openDataFile flockMode := syscall.LOCK_EX if !blocking { flockMode |= syscall.LOCK_NB } err = syscall.Flock(int(openDataFile.Fd()), flockMode) if err != nil { return } nodeData, err = ioutil.ReadAll(lc.openDataFile) if err != nil { logger.Info("Unable to read existing DHT node file (%v). Creating a new one.", err) lc.localNode = newLocalNode() } else if len(nodeData) == 0 { logger.Info("Existing DHT node file was empty. Creating a new one.") lc.localNode = newLocalNode() } else { nodeDict, err = bencoding.Decode(nodeData) if err != nil { openDataFile.Close() return } nodeDictAsDict, ok = nodeDict.(bencoding.Dict) if !ok { err = errors.New("Node data wasn't a dict.") logger.Info("%v", err) openDataFile.Close() return } lc.localNode = localNodeFromBencodingDict(nodeDictAsDict) logger.Info("Loaded local node info from %v.", path) } terminateLocalNode := make(chan bool) lc.terminateLocalNode = terminateLocalNode c = Client(lc) err = lc.Run(terminateLocalNode) if err != nil { return } go func() { for lc.localNode != nil { c.Save() time.Sleep(15 * time.Second) } }() return }