diff --git a/apis/swagger.yml b/apis/swagger.yml index af35f6b3f..50d78075a 100644 --- a/apis/swagger.yml +++ b/apis/swagger.yml @@ -44,6 +44,156 @@ paths: 500: $ref: "#/responses/500ErrorResponse" + /peer/registry: + post: + summary: "registry a task" + description: | + Create a peer-to-peer downloading task in supernode. + parameters: + - name: "body" + in: "body" + description: "request body which contains task creation information" + schema: + $ref: "#/definitions/TaskRegisterRequest" + responses: + 200: + description: "no error" + schema: + $ref: "#/definitions/ResultInfo" + 400: + description: "bad parameter" + schema: + $ref: '#/definitions/Error' + 500: + $ref: "#/responses/500ErrorResponse" + + /peer/task: + get: + summary: "Get pieces in task" + description: | + When dfget starts to download pieces of a task, it should get fixed + number of pieces in a task and the use pieces information to download + the pirces. The request piece number is set in query. + produces: + - "application/json" + parameters: + - name: taskId + in: query + required: true + description: "ID of task" + type: string + - name: srcCid + in: query + type: "string" + required: true + description: + When dfget needs to get pieces of specific task, it must mark which peer it plays role of. + - name: dstCid + in: query + type: "string" + description: | + the uploader cid + - name: status + type: "string" + in: query + description: | + dfgetTaskStatus indicates whether the dfgetTask is running. + enum: ["STARTED", "RUNNING", "FINISHED"] + - name: result + in: query + type: "string" + description: | + pieceResult It indicates whether the dfgetTask successfully download the piece. + It's only useful when `status` is `RUNNING`. + enum: ["FAILED", "SUCCESS", "INVALID", "SEMISUC"] + - name: range + type: "string" + in: query + description: | + the range of specific piece in the task, example "0-45565". + responses: + 200: + description: "no error" + schema: + $ref: "#/definitions/ResultInfo" + 404: + description: "no such task" + schema: + $ref: "#/responses/404ErrorResponse" + 500: + $ref: "#/responses/500ErrorResponse" + + /peer/piece/suc: + get: + summary: "report a piece has been success" + description: | + Update some information of piece. When peer A finishes to download + piece B, A must send request to supernode to update piece B's info + to mark that peer A has the complete piece B. Then when other peers + request to download this piece B, supernode could schedule peer A + to those peers. + produces: + - "application/json" + parameters: + - name: taskId + in: query + required: true + description: "ID of task" + type: string + - name: pieceRange + in: query + required: true + description: | + the range of specific piece in the task, example "0-45565". + type: string + - name: cid + in: query + type: string + required: true + description: | + the downloader clientID + - name: dstCid + in: query + type: string + description: | + the uploader peerID + responses: + 200: + description: "no error" + schema: + $ref: "#/definitions/ResultInfo" + 404: + $ref: "#/responses/404ErrorResponse" + 500: + $ref: "#/responses/500ErrorResponse" + + /peer/service/down: + get: + summary: "report a peer service will offline" + produces: + - "application/json" + parameters: + - name: taskId + in: query + required: true + description: "ID of task" + type: string + - name: cid + in: query + type: string + required: true + description: | + the downloader clientID + responses: + 200: + description: "no error" + schema: + $ref: "#/definitions/ResultInfo" + 404: + $ref: "#/responses/404ErrorResponse" + 500: + $ref: "#/responses/500ErrorResponse" + /peers: post: summary: "register dfget in Supernode as a peer node" @@ -417,6 +567,105 @@ definitions: message: type: string + ResultInfo: + type: "object" + description: | + The returned information from supernode. + properties: + code: + type: "integer" + format: "int32" + description: "the result code" + msg: + type: "string" + description: "the result msg" + data: + type: "object" + description: "the result data" + + TaskRegisterRequest: + type: "object" + description: "" + properties: + IP: + type: "string" + description: "IP address which peer client carries" + format: "ipv4" + superNodeIp: + type: "string" + description: "IP address of supernode that the client can connect to" + format: "ipv4" + hostName: + type: "string" + description: "host name of peer client node, as a valid RFC 1123 hostname." + format: "hostname" + minLength: 1 + port: + type: "integer" + description: | + when registering, dfget will setup one uploader process. + This one acts as a server for peer pulling tasks. + This port is which this server listens on. + format: "int32" + minimum: 15000 + maximum: 65000 + version: + type: "string" + description: "version number of dfget binary." + cID: + type: "string" + description: | + CID means the client ID. It maps to the specific dfget process. + When user wishes to download an image/file, user would start a dfget process to do this. + This dfget is treated a client and carries a client ID. + Thus, multiple dfget processes on the same peer have different CIDs. + rawURL: + type: "string" + description: | + The is the resource's URL which user uses dfget to download. The location of URL can be anywhere, LAN or WAN. + For image distribution, this is image layer's URL in image registry. + The resource url is provided by command line parameter. + taskURL: + type: "string" + description: | + taskURL is generated from rawURL. rawURL may contains some queries or parameter, dfget will filter some queries via + --filter parameter of dfget. The usage of it is that different rawURL may generate the same taskID. + md5: + type: "string" + description: | + md5 checksum for the resource to distribute. dfget catches this parameter from dfget's CLI + and passes it to supernode. When supernode finishes downloading file/image from the source location, + it will validate the source file with this md5 value to check whether this is a valid file. + identifier: + type: "string" + description: | + special attribute of remote source file. This field is used with taskURL to generate new taskID to + identify different downloading task of remote source file. For example, if user A and user B uses + the same taskURL and taskID to download file, A and B will share the same peer network to distribute files. + If user A additionally adds an identifier with taskURL, while user B still carries only taskURL, then A's + generated taskID is different from B, and the result is that two users use different peer networks. + path: + type: "string" + description: | + path is used in one peer A for uploading functionality. When peer B hopes + to get piece C from peer A, B must provide a URL for piece C. + Then when creating a task in supernode, peer A must provide this URL in request. + headers: + type: "object" + description: | + extra HTTP headers sent to the rawURL. + This field is carried with the request to supernode. + Supernode will extract these HTTP headers, and set them in HTTP downloading requests + from source server as user's wish. + additionalProperties: + type: "string" + dfdaemon: + type: "boolean" + description: | + tells whether it is a call from dfdaemon. dfdaemon is a long running + process which works for container engines. It translates the image + pulling request into raw requests into those dfget recognizes. + PeerCreateRequest: type: "object" description: | @@ -493,6 +742,7 @@ definitions: type : "string" format : "date-time" description: "the time to join the P2P network" + TaskCreateRequest: type: "object" description: "" @@ -510,6 +760,11 @@ definitions: The is the resource's URL which user uses dfget to download. The location of URL can be anywhere, LAN or WAN. For image distribution, this is image layer's URL in image registry. The resource url is provided by command line parameter. + taskURL: + type: "string" + description: | + taskURL is generated from rawURL. rawURL may contains some queries or parameter, dfget will filter some queries via + --filter parameter of dfget. The usage of it is that different rawURL may generate the same taskID. md5: type: "string" description: | diff --git a/apis/types/result_info.go b/apis/types/result_info.go new file mode 100644 index 000000000..660f62c08 --- /dev/null +++ b/apis/types/result_info.go @@ -0,0 +1,49 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package types + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + strfmt "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// ResultInfo The returned information from supernode. +// +// swagger:model ResultInfo +type ResultInfo struct { + + // the result code + Code int32 `json:"code,omitempty"` + + // the result data + Data interface{} `json:"data,omitempty"` + + // the result msg + Msg string `json:"msg,omitempty"` +} + +// Validate validates this result info +func (m *ResultInfo) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *ResultInfo) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ResultInfo) UnmarshalBinary(b []byte) error { + var res ResultInfo + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/apis/types/task_create_request.go b/apis/types/task_create_request.go index 23fef3fc7..c537e0561 100644 --- a/apis/types/task_create_request.go +++ b/apis/types/task_create_request.go @@ -81,6 +81,11 @@ type TaskCreateRequest struct { // The resource url is provided by command line parameter. // RawURL string `json:"rawURL,omitempty"` + + // taskURL is generated from rawURL. rawURL may contains some queries or parameter, dfget will filter some queries via + // --filter parameter of dfget. The usage of it is that different rawURL may generate the same taskID. + // + TaskURL string `json:"taskURL,omitempty"` } // Validate validates this task create request diff --git a/apis/types/task_register_request.go b/apis/types/task_register_request.go new file mode 100644 index 000000000..04e6fe852 --- /dev/null +++ b/apis/types/task_register_request.go @@ -0,0 +1,197 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package types + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/errors" + strfmt "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// TaskRegisterRequest task register request +// swagger:model TaskRegisterRequest +type TaskRegisterRequest struct { + + // IP address which peer client carries + // Format: ipv4 + IP strfmt.IPv4 `json:"IP,omitempty"` + + // CID means the client ID. It maps to the specific dfget process. + // When user wishes to download an image/file, user would start a dfget process to do this. + // This dfget is treated a client and carries a client ID. + // Thus, multiple dfget processes on the same peer have different CIDs. + // + CID string `json:"cID,omitempty"` + + // tells whether it is a call from dfdaemon. dfdaemon is a long running + // process which works for container engines. It translates the image + // pulling request into raw requests into those dfget recognizes. + // + Dfdaemon bool `json:"dfdaemon,omitempty"` + + // extra HTTP headers sent to the rawURL. + // This field is carried with the request to supernode. + // Supernode will extract these HTTP headers, and set them in HTTP downloading requests + // from source server as user's wish. + // + Headers map[string]string `json:"headers,omitempty"` + + // host name of peer client node, as a valid RFC 1123 hostname. + // Min Length: 1 + // Format: hostname + HostName strfmt.Hostname `json:"hostName,omitempty"` + + // special attribute of remote source file. This field is used with taskURL to generate new taskID to + // identify different downloading task of remote source file. For example, if user A and user B uses + // the same taskURL and taskID to download file, A and B will share the same peer network to distribute files. + // If user A additionally adds an identifier with taskURL, while user B still carries only taskURL, then A's + // generated taskID is different from B, and the result is that two users use different peer networks. + // + Identifier string `json:"identifier,omitempty"` + + // md5 checksum for the resource to distribute. dfget catches this parameter from dfget's CLI + // and passes it to supernode. When supernode finishes downloading file/image from the source location, + // it will validate the source file with this md5 value to check whether this is a valid file. + // + Md5 string `json:"md5,omitempty"` + + // path is used in one peer A for uploading functionality. When peer B hopes + // to get piece C from peer A, B must provide a URL for piece C. + // Then when creating a task in supernode, peer A must provide this URL in request. + // + Path string `json:"path,omitempty"` + + // when registering, dfget will setup one uploader process. + // This one acts as a server for peer pulling tasks. + // This port is which this server listens on. + // + // Maximum: 65000 + // Minimum: 15000 + Port int32 `json:"port,omitempty"` + + // The is the resource's URL which user uses dfget to download. The location of URL can be anywhere, LAN or WAN. + // For image distribution, this is image layer's URL in image registry. + // The resource url is provided by command line parameter. + // + RawURL string `json:"rawURL,omitempty"` + + // IP address of supernode that the client can connect to + // Format: ipv4 + SuperNodeIP strfmt.IPv4 `json:"superNodeIp,omitempty"` + + // taskURL is generated from rawURL. rawURL may contains some queries or parameter, dfget will filter some queries via + // --filter parameter of dfget. The usage of it is that different rawURL may generate the same taskID. + // + TaskURL string `json:"taskURL,omitempty"` + + // version number of dfget binary. + Version string `json:"version,omitempty"` +} + +// Validate validates this task register request +func (m *TaskRegisterRequest) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateIP(formats); err != nil { + res = append(res, err) + } + + if err := m.validateHostName(formats); err != nil { + res = append(res, err) + } + + if err := m.validatePort(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSuperNodeIP(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *TaskRegisterRequest) validateIP(formats strfmt.Registry) error { + + if swag.IsZero(m.IP) { // not required + return nil + } + + if err := validate.FormatOf("IP", "body", "ipv4", m.IP.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *TaskRegisterRequest) validateHostName(formats strfmt.Registry) error { + + if swag.IsZero(m.HostName) { // not required + return nil + } + + if err := validate.MinLength("hostName", "body", string(m.HostName), 1); err != nil { + return err + } + + if err := validate.FormatOf("hostName", "body", "hostname", m.HostName.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *TaskRegisterRequest) validatePort(formats strfmt.Registry) error { + + if swag.IsZero(m.Port) { // not required + return nil + } + + if err := validate.MinimumInt("port", "body", int64(m.Port), 15000, false); err != nil { + return err + } + + if err := validate.MaximumInt("port", "body", int64(m.Port), 65000, false); err != nil { + return err + } + + return nil +} + +func (m *TaskRegisterRequest) validateSuperNodeIP(formats strfmt.Registry) error { + + if swag.IsZero(m.SuperNodeIP) { // not required + return nil + } + + if err := validate.FormatOf("superNodeIp", "body", "ipv4", m.SuperNodeIP.String(), formats); err != nil { + return err + } + + return nil +} + +// MarshalBinary interface implementation +func (m *TaskRegisterRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *TaskRegisterRequest) UnmarshalBinary(b []byte) error { + var res TaskRegisterRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/supernode/daemon/mgr/progress/progress_manager.go b/supernode/daemon/mgr/progress/progress_manager.go index 3b86e0275..d161cdefc 100644 --- a/supernode/daemon/mgr/progress/progress_manager.go +++ b/supernode/daemon/mgr/progress/progress_manager.go @@ -242,6 +242,11 @@ func (pm *Manager) GetPeerStateByPeerID(ctx context.Context, peerID string) (*mg // DeletePeerStateByPeerID deletes the peerState by PeerID. func (pm *Manager) DeletePeerStateByPeerID(ctx context.Context, peerID string) error { + // delete client blackinfo + // TODO: delete the blackinfo that refer to peerID + pm.clientBlackInfo.Delete(peerID) + + // delete peer progress return pm.peerProgress.remove(peerID) } diff --git a/supernode/daemon/mgr/task/manager_util.go b/supernode/daemon/mgr/task/manager_util.go index 4a44132a7..40b661b33 100644 --- a/supernode/daemon/mgr/task/manager_util.go +++ b/supernode/daemon/mgr/task/manager_util.go @@ -18,7 +18,10 @@ import ( // addOrUpdateTask adds a new task or update the exist task to taskStore. func (tm *Manager) addOrUpdateTask(ctx context.Context, req *types.TaskCreateRequest) (*types.TaskInfo, error) { - taskURL := cutil.FilterURLParam(req.RawURL, req.Filter) + taskURL := req.TaskURL + if cutil.IsEmptyStr(req.TaskURL) { + taskURL = cutil.FilterURLParam(req.RawURL, req.Filter) + } taskID := generateTaskID(taskURL, req.Md5, req.Identifier) // using the existing task if it already exists corresponding to taskID diff --git a/supernode/server/0.3_bridge.go b/supernode/server/0.3_bridge.go new file mode 100644 index 000000000..61cdc755f --- /dev/null +++ b/supernode/server/0.3_bridge.go @@ -0,0 +1,232 @@ +package server + +import ( + "context" + "encoding/json" + "net/http" + + "github.com/dragonflyoss/Dragonfly/apis/types" + "github.com/dragonflyoss/Dragonfly/common/constants" + errTypes "github.com/dragonflyoss/Dragonfly/common/errors" + cutil "github.com/dragonflyoss/Dragonfly/common/util" + sutil "github.com/dragonflyoss/Dragonfly/supernode/util" + + "github.com/go-openapi/strfmt" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +// RegisterResponseData is the data when registering supernode successfully. +type RegisterResponseData struct { + TaskID string `json:"taskId"` + FileLength int64 `json:"fileLength"` + PieceSize int32 `json:"pieceSize"` +} + +// PullPieceTaskResponseContinueData is the data when successfully pulling piece task +// and the task is continuing. +type PullPieceTaskResponseContinueData struct { + Range string `json:"range"` + PieceNum int `json:"pieceNum"` + PieceSize int32 `json:"pieceSize"` + PieceMd5 string `json:"pieceMd5"` + Cid string `json:"cid"` + PeerIP string `json:"peerIp"` + PeerPort int `json:"peerPort"` + Path string `json:"path"` + DownLink int `json:"downLink"` +} + +var statusMap = map[string]string{ + "700": types.PiecePullRequestDfgetTaskStatusSTARTED, + "701": types.PiecePullRequestDfgetTaskStatusRUNNING, + "702": types.PiecePullRequestDfgetTaskStatusFINISHED, +} + +var resultMap = map[string]string{ + "500": types.PiecePullRequestPieceResultFAILED, + "501": types.PiecePullRequestPieceResultSUCCESS, + "502": types.PiecePullRequestPieceResultINVALID, + "503": types.PiecePullRequestPieceResultSEMISUC, +} + +func (s *Server) registry(ctx context.Context, rw http.ResponseWriter, req *http.Request) (err error) { + reader := req.Body + request := &types.TaskRegisterRequest{} + if err := json.NewDecoder(reader).Decode(request); err != nil { + return errors.Wrap(errTypes.ErrInvalidValue, err.Error()) + } + + if err := request.Validate(strfmt.NewFormats()); err != nil { + return errors.Wrap(errTypes.ErrInvalidValue, err.Error()) + } + + peerCreateRequest := &types.PeerCreateRequest{ + IP: request.IP, + HostName: request.HostName, + Port: request.Port, + Version: request.Version, + } + peerCreateResponse, err := s.PeerMgr.Register(ctx, peerCreateRequest) + if err != nil { + logrus.Errorf("failed to register peer %+v: %v", peerCreateRequest, err) + return errors.Wrapf(errTypes.ErrSystemError, "failed to register peer: %v", err) + } + logrus.Infof("success to register peer %+v", peerCreateRequest) + + peerID := peerCreateResponse.ID + taskCreateRequest := &types.TaskCreateRequest{ + CID: request.CID, + Dfdaemon: request.Dfdaemon, + Headers: request.Headers, + Identifier: request.Identifier, + Md5: request.Md5, + Path: request.Path, + PeerID: peerID, + RawURL: request.RawURL, + TaskURL: request.TaskURL, + } + resp, err := s.TaskMgr.Register(ctx, taskCreateRequest) + if err != nil { + logrus.Errorf("failed to register task %+v: %v", taskCreateRequest, err) + return err + } + logrus.Infof("success to register task %+v", taskCreateRequest) + return EncodeResponse(rw, http.StatusOK, &types.ResultInfo{ + Code: constants.Success, + Msg: constants.GetMsgByCode(constants.Success), + Data: &RegisterResponseData{ + TaskID: resp.ID, + FileLength: resp.FileLength, + PieceSize: resp.PieceSize, + }, + }) +} + +func (s *Server) pullPieceTask(ctx context.Context, rw http.ResponseWriter, req *http.Request) (err error) { + params := req.URL.Query() + taskID := params.Get("taskId") + srcCID := params.Get("srcCid") + + request := &types.PiecePullRequest{ + DfgetTaskStatus: statusMap[params.Get("status")], + PieceRange: params.Get("range"), + PieceResult: resultMap[params.Get("result")], + } + + // try to get dstPID + dstCID := params.Get("dstCid") + if !cutil.IsEmptyStr(dstCID) { + dstDfgetTask, err := s.DfgetTaskMgr.Get(ctx, dstCID, taskID) + if err != nil { + return err + } + request.DstPID = dstDfgetTask.PeerID + } + + isFinished, data, err := s.TaskMgr.GetPieces(ctx, taskID, srcCID, request) + logrus.Infof("get pieces data:%+v", data) + if err != nil { + logrus.Errorf("failed to get pieces %+v: %v", request, err) + resultInfo := NewResultInfoWithError(err) + return EncodeResponse(rw, http.StatusOK, &types.ResultInfo{ + Code: int32(resultInfo.code), + Msg: resultInfo.msg, + Data: data, + }) + } + + if isFinished { + return EncodeResponse(rw, http.StatusOK, &types.ResultInfo{ + Code: constants.CodePeerFinish, + Data: data, + }) + } + + var datas []*PullPieceTaskResponseContinueData + pieceInfos, ok := data.([]*types.PieceInfo) + if !ok { + return EncodeResponse(rw, http.StatusOK, &types.ResultInfo{ + Code: constants.CodeSystemError, + Msg: "failed to parse PullPieceTaskResponseContinueData", + }) + } + + for _, v := range pieceInfos { + cid, err := s.DfgetTaskMgr.GetCIDByPeerIDAndTaskID(ctx, v.PID, taskID) + if err != nil { + continue + } + datas = append(datas, &PullPieceTaskResponseContinueData{ + Range: v.PieceRange, + PieceNum: sutil.CalculatePieceNum(v.PieceRange), + PieceSize: v.PieceSize, + PieceMd5: v.PieceMD5, + Cid: cid, + PeerIP: v.PeerIP, + PeerPort: int(v.PeerPort), + Path: v.Path, + }) + } + return EncodeResponse(rw, http.StatusOK, &types.ResultInfo{ + Code: constants.CodePeerContinue, + Data: datas, + }) +} + +func (s *Server) reportPiece(ctx context.Context, rw http.ResponseWriter, req *http.Request) (err error) { + params := req.URL.Query() + taskID := params.Get("taskId") + srcCID := params.Get("cid") + dstCID := params.Get("dstCid") + pieceRange := params.Get("pieceRange") + + dstDfgetTask, err := s.DfgetTaskMgr.Get(ctx, dstCID, taskID) + if err != nil { + return err + } + + request := &types.PieceUpdateRequest{ + ClientID: srcCID, + DstPID: dstDfgetTask.PeerID, + PieceStatus: types.PieceUpdateRequestPieceStatusSUCCESS, + } + + if err := s.TaskMgr.UpdatePieceStatus(ctx, taskID, pieceRange, request); err != nil { + logrus.Errorf("failed to update pieces status %+v: %v", request, err) + return err + } + + rw.WriteHeader(http.StatusOK) + return nil +} + +func (s *Server) reportServiceDown(ctx context.Context, rw http.ResponseWriter, req *http.Request) (err error) { + params := req.URL.Query() + taskID := params.Get("taskId") + cID := params.Get("cid") + + dfgetTask, err := s.DfgetTaskMgr.Get(ctx, cID, taskID) + if err != nil { + return err + } + + if err := s.ProgressMgr.DeletePieceProgressByCID(ctx, taskID, cID); err != nil { + return err + } + + if err := s.ProgressMgr.DeletePeerStateByPeerID(ctx, dfgetTask.PeerID); err != nil { + return err + } + + if err := s.PeerMgr.DeRegister(ctx, dfgetTask.PeerID); err != nil { + return err + } + + if err := s.DfgetTaskMgr.Delete(ctx, cID, taskID); err != nil { + return err + } + + rw.WriteHeader(http.StatusOK) + return nil +} diff --git a/supernode/server/router.go b/supernode/server/router.go index fd924f3a1..77979cd91 100644 --- a/supernode/server/router.go +++ b/supernode/server/router.go @@ -21,6 +21,13 @@ func initRoute(s *Server) *mux.Router { // system {Method: http.MethodGet, Path: "/_ping", HandlerFunc: s.ping}, + // v0.3 + {Method: http.MethodPost, Path: "/peer/registry", HandlerFunc: s.registry}, + {Method: http.MethodGet, Path: "/peer/task", HandlerFunc: s.pullPieceTask}, + {Method: http.MethodGet, Path: "/peer/piece/suc", HandlerFunc: s.reportPiece}, + {Method: http.MethodGet, Path: "/peer/service/down", HandlerFunc: s.reportServiceDown}, + + // v1 // peer {Method: http.MethodPost, Path: "/peers", HandlerFunc: s.registerPeer}, {Method: http.MethodDelete, Path: "/peers/{id}", HandlerFunc: s.deRegisterPeer}, diff --git a/supernode/server/server.go b/supernode/server/server.go index 84ed6b338..93be4ccd4 100644 --- a/supernode/server/server.go +++ b/supernode/server/server.go @@ -25,6 +25,7 @@ type Server struct { PeerMgr mgr.PeerMgr TaskMgr mgr.TaskMgr DfgetTaskMgr mgr.DfgetTaskMgr + ProgressMgr mgr.ProgressMgr } // New creates a brand new server instance. @@ -73,6 +74,7 @@ func New(cfg *config.Config) (*Server, error) { PeerMgr: peerMgr, TaskMgr: taskMgr, DfgetTaskMgr: dfgetTaskMgr, + ProgressMgr: progressMgr, }, nil }