func main() { var ( rset, wset, eset syscall.FdSet still_running, curl_timeout int = 0, 0 err error ) ch1 := curl.EasyInit() ch2 := curl.EasyInit() ch1.Setopt(curl.OPT_URL, "http://www.163.com") ch1.Setopt(curl.OPT_HEADER, 0) ch1.Setopt(curl.OPT_VERBOSE, true) ch2.Setopt(curl.OPT_URL, "http://www.baidu.com") ch2.Setopt(curl.OPT_HEADER, 0) ch2.Setopt(curl.OPT_VERBOSE, true) mh := curl.MultiInit() mh.AddHandle(ch1) mh.AddHandle(ch2) for { FD_ZERO(&rset) FD_ZERO(&wset) FD_ZERO(&eset) timeout := syscall.Timeval{Sec: 1, Usec: 0} curl_timeout, err = mh.Timeout() if err != nil { fmt.Printf("Error multi_timeout: %s\n", err) } if curl_timeout >= 0 { timeout.Sec = int64(curl_timeout / 1000) if timeout.Sec > 1 { timeout.Sec = 1 } else { timeout.Usec = int64((curl_timeout % 1000)) * 1000 } } max_fd, err := mh.Fdset(&rset, &wset, &eset) if err != nil { fmt.Printf("Error FDSET: %s\n", err) } _, err = syscall.Select(int(max_fd+1), &rset, &wset, &eset, &timeout) if err != nil { fmt.Printf("Error select: %s\n", err) } else { still_running, err = mh.Perform() if still_running > 0 { fmt.Printf("Still running: %d\n", still_running) } else { break } } } }
func (w *Worker) createRawSocket() (fd int) { socket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_TCP) if err != nil { fmt.Fprintf(os.Stderr, "fail to Socket :%s\n", err.Error()) os.Exit(1) } err = syscall.SetsockoptString(socket, syscall.IPPROTO_IP, syscall.IP_HDRINCL, "1") if err != nil { fmt.Fprintf(os.Stderr, "SetsockoptString error :%s\ns", err.Error()) os.Exit(1) } timeVal := new(syscall.Timeval) timeVal.Sec = 6 err = syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, timeVal) if err != nil { fmt.Fprintf(os.Stderr, "SetsockoptTimeval error :%s", err.Error()) os.Exit(1) } return socket }
// timeToTimeval - Convert time.Time to syscall.Timeval // // Note: This does not use syscall.NsecToTimespec because // that does not work properly for times before 1970, // see https://github.com/golang/go/issues/12777 func timeToTimeval(t *time.Time) syscall.Timeval { var tv syscall.Timeval tv.Usec = int32(t.Nanosecond() / 1000) tv.Sec = t.Unix() return tv }
// Returns errors (if any) triggered by the inotify subsystem or when reading // the file. Errors when writing to the writer are ignored. func streamFile(writer io.Writer, path string, maxIdleTime uint32) error { handle, err := os.Open(path) if err != nil { return err } _, err = handle.Seek(0, os.SEEK_END) if err != nil { handle.Close() return err } reader := bufio.NewReader(handle) readBuffer := make([]byte, 4096) inotifyFd, err := syscall.InotifyInit() if err != nil { handle.Close() return err } watchDesc, err := syscall.InotifyAddWatch(inotifyFd, path, syscall.IN_MODIFY) if err != nil { syscall.Close(inotifyFd) handle.Close() return err } eventsBuffer := make([]byte, syscall.SizeofInotifyEvent*4096) selectMaxIdleTime := syscall.Timeval{} selectMaxIdleTime.Sec = int64(maxIdleTime) inotifyFdSet := syscall.FdSet{} lastWriteTime := time.Now() canScan := true for canScan && !timeout(lastWriteTime, maxIdleTime) { clearAll(&inotifyFdSet) set(&inotifyFdSet, inotifyFd) _, err := syscall.Select(inotifyFd+1, &inotifyFdSet, nil, nil, &selectMaxIdleTime) if err != nil { break } if !isSet(&inotifyFdSet, inotifyFd) { continue } numEventsBytes, err := syscall.Read(inotifyFd, eventsBuffer[0:]) if numEventsBytes < syscall.SizeofInotifyEvent { if numEventsBytes < 0 { err = errors.New("inotify: read failed.") } else { err = errors.New("inotify: short read.") } break } var offset uint32 = 0 for offset <= uint32(numEventsBytes-syscall.SizeofInotifyEvent) { event := (*syscall.InotifyEvent)(unsafe. Pointer(&eventsBuffer[offset])) n, err := reader.Read(readBuffer) if err != nil { // Ignore the EOF error and continue polling // the file until timeout. if err == io.EOF { err = nil } break } buffer := make([]byte, n) for index := 0; index < n; index++ { buffer[index] = readBuffer[index] } _, err = writer.Write(buffer) if err != nil { // Stop scanning for updates to the file. canScan = false // Ignore the write error. err = nil break } lastWriteTime = time.Now() // Move to the next event. offset += syscall.SizeofInotifyEvent + event.Len } } // The inotify watch gets automatically removed by the inotify system // when the file is removed. If the above loop times out, but the file // is removed only just before the if block below is executed, then the // removal of the watch below will throw an error as the watch // descriptor is obsolete. We ignore this error because it is harmless. syscall.InotifyRmWatch(inotifyFd, uint32(watchDesc)) // Though we return the first error that occured, we still need to // attempt to close all the file descriptors. inotifyCloseErr := syscall.Close(inotifyFd) handleCloseErr := handle.Close() if err != nil { return err } else if inotifyCloseErr != nil { return inotifyCloseErr } return handleCloseErr }
func (s *SyncReceiver) HandleConnection(conn net.Conn) { var err error defer func() { log.Println("Receiver: client disconnect with:", err) if err != nil { conn.Write([]byte{VerifyResultError}) } conn.Close() }() log.Println("New Connection Com") br := bufio.NewReader(conn) headerLen := syncHeaderLen() headerBuf := make([]byte, headerLen) _, err = br.Read(headerBuf) if err != nil { return } syncHeader := NewSyncHeaderFromBytes(headerBuf) log.Println("Read Header Succ", syncHeader.FileLength) buf_filename, err := br.ReadBytes('\n') //log.Println(len(buf_filename), buf_filename) if len(buf_filename) <= 1 { return } filename := string(buf_filename[0 : len(buf_filename)-1]) log.Println("filename:", filename) filename = path.Join(s.cfg.SyncRootFolder, filename) var fi os.FileInfo fi, err = os.Stat(filename) if os.IsNotExist(err) || fi.IsDir() { log.Printf("no such file: %s\n", filename) conn.Write([]byte{VerifyResultTransferToMe}) //NOW Read&Write Entire File rbuf := make([]byte, 512) //readbuf //create temp file tempfilename := filename + ".syncing" tempFile, err := os.Create(tempfilename) if err != nil { log.Println("Create temp file error", err) return } endTransfer := false readedBytes := int64(0) for !endTransfer { n, err := br.Read(rbuf) if err != nil { log.Println("Transfering File Err:", err) return } if n > 0 { if nw, err := tempFile.Write(rbuf[0:n]); err != nil || nw != n { log.Println("Write tempfile error") return } } readedBytes += int64(n) if readedBytes > syncHeader.FileLength { log.Println("Transfer more than syncheader:", readedBytes, syncHeader.FileLength) return } else if readedBytes == syncHeader.FileLength { endTransfer = true } log.Println("recv:", n) } if err := tempFile.Close(); err != nil { log.Println("Sync&Close temp file failed!") return } // log.Println("file recv over") //rename file & give a new mod time os.Rename(tempfilename, filename) fi, _ = os.Stat(filename) accessTimeval := new(syscall.Timeval) accessTimeval.Sec = fi.ModTime().Unix() modTimeval := new(syscall.Timeval) modTimeval.Sec = syncHeader.FileModTime.Unix() err = syscall.Utimes(filename, []syscall.Timeval{*accessTimeval, *modTimeval}) if err != nil { log.Println("utime error:", err) return } err = nil conn.Write([]byte{VerifyResultDoNext}) log.Println("sync over!!!") } else { if syncHeader.FileLength == fi.Size() && syncHeader.FileModTime.Equal(fi.ModTime()) { log.Println("Timestamp & Size Equal. This file is synced") conn.Write([]byte{VerifyResultDoNext}) //TBD continue the loop } else { log.Println("Modtime not equal. So need file compare") //Send need compare flag conn.Write([]byte{VerifyResultNeedCompare}) //Compute & Send chunkchecksum // syncHeader.FileLength f, err := os.Open(filename) if err != nil { log.Println("open file err:", err) return } checkSum := NewRollingCheckSum(f, syncHeader.ChunkSize) hashes, err := checkSum.SumEveryChunk() if err != nil { log.Println("error when generate checksum", err) return } checksumBytes := CheckSumPackArrayToBytes(hashes) conn.Write(checksumBytes) //adler+md5 //Recv TransferData Packages } } /* version := br.ReadByte() packageType := br.ReadByte() if !(version == 0x01 && packageType == PackageTypeSyncRequest) { return } return temp2 := make([]byte, 2) br.Read(temp) //little endian packageLen := uint16(temp2[0])|(uint16(temp2[1])<<8) io.WriteString(conn, "Hi") */ }