Example #1
0
func getObjectsHandler(w http.ResponseWriter, req *http.Request) {
	if req.Method != "CONNECT" {
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		w.WriteHeader(http.StatusMethodNotAllowed)
		io.WriteString(w, "405 must CONNECT\n")
		return
	}
	conn, bufrw, err := w.(http.Hijacker).Hijack()
	if err != nil {
		logger.Println("rpc hijacking ", req.RemoteAddr, ": ", err.Error())
		return
	}
	defer conn.Close()
	defer bufrw.Flush()
	io.WriteString(conn, "HTTP/1.0 200 Connected to GetObjects RPC\n\n")
	var request objectserver.GetObjectsRequest
	var response objectserver.GetObjectsResponse
	if request.Exclusive {
		exclusive.Lock()
		defer exclusive.Unlock()
	} else {
		exclusive.RLock()
		defer exclusive.RUnlock()
		getSemaphore <- true
		defer releaseSemaphore(getSemaphore)
	}
	decoder := gob.NewDecoder(bufrw)
	encoder := gob.NewEncoder(bufrw)
	err = decoder.Decode(&request)
	if err != nil {
		response.ResponseString = err.Error()
		encoder.Encode(response)
		return
	}
	response.ObjectSizes, err = objectServer.CheckObjects(request.Hashes)
	if err != nil {
		response.ResponseString = err.Error()
		encoder.Encode(response)
		return
	}
	// First a quick check for existence. If any objects missing, fail request.
	for index, hash := range request.Hashes {
		if response.ObjectSizes[index] < 1 {
			response.ResponseString = fmt.Sprintf("unknown object: %x", hash)
			encoder.Encode(response)
			return
		}
	}
	objectsReader, err := objectServer.GetObjects(request.Hashes)
	if err != nil {
		response.ResponseString = err.Error()
		encoder.Encode(response)
		return
	}
	encoder.Encode(response)
	bufrw.Flush()
	for range request.Hashes {
		_, reader, err := objectsReader.NextObject()
		if err != nil {
			logger.Println(err)
			return
		}
		_, err = io.Copy(conn, reader)
		reader.Close()
		if err != nil {
			logger.Printf("Error copying:\t%s\n", err)
			return
		}
	}
}
Example #2
0
func (objSrv *srpcType) GetObjects(conn *srpc.Conn) error {
	defer conn.Flush()
	var request objectserver.GetObjectsRequest
	var response objectserver.GetObjectsResponse
	if request.Exclusive {
		exclusive.Lock()
		defer exclusive.Unlock()
	} else {
		exclusive.RLock()
		defer exclusive.RUnlock()
		objSrv.getSemaphore <- true
		defer releaseSemaphore(objSrv.getSemaphore)
	}
	decoder := gob.NewDecoder(conn)
	encoder := gob.NewEncoder(conn)
	var err error
	if err = decoder.Decode(&request); err != nil {
		response.ResponseString = err.Error()
		return encoder.Encode(response)
	}
	response.ObjectSizes, err = objSrv.objectServer.CheckObjects(request.Hashes)
	if err != nil {
		response.ResponseString = err.Error()
		return encoder.Encode(response)
	}
	// First a quick check for existence. If any objects missing, fail request.
	for index, hash := range request.Hashes {
		if response.ObjectSizes[index] < 1 {
			response.ResponseString = fmt.Sprintf("unknown object: %x", hash)
			return encoder.Encode(response)
		}
	}
	objectsReader, err := objSrv.objectServer.GetObjects(request.Hashes)
	if err != nil {
		response.ResponseString = err.Error()
		return encoder.Encode(response)
	}
	defer objectsReader.Close()
	if err := encoder.Encode(response); err != nil {
		return err
	}
	conn.Flush()
	for _, hash := range request.Hashes {
		length, reader, err := objectsReader.NextObject()
		if err != nil {
			objSrv.logger.Println(err)
			return err
		}
		nCopied, err := io.Copy(conn.Writer, reader)
		reader.Close()
		if err != nil {
			objSrv.logger.Printf("Error copying:\t%s\n", err)
			return err
		}
		if nCopied != int64(length) {
			txt := fmt.Sprintf("Expected length: %d, got: %d for: %x",
				length, nCopied, hash)
			objSrv.logger.Printf(txt)
			return errors.New(txt)
		}
	}
	objSrv.logger.Printf("GetObjects() sent: %d objects\n", len(request.Hashes))
	return nil
}