Server

Communication Protocol Guide

Build CookieFarm protocol plugins to submit flags to the Flag Checker service, parse JSON responses, and handle errors reliably.

File Location and Starter Template

Create your protocol file in:

pkg/protocols

Use this starter:

protocol.go
//go:build ignore

package main

import (
	"protocols"
)

// Submit sends flags to the Flag Checker service and returns parsed results.
func Submit(host string, teamToken string, flags []string) ([]models.ResponseProtocol, error) {
 // Your implementation here
 return nil, nil
}

Note: The return type should be []models.ResponseProtocol.


Response Model

The checker response should map to:

type ResponseProtocol struct {
 Msg    string `json:"msg"`    // Human-readable message (often includes the flag)
 Flag   string `json:"flag"`   // Submitted flag
 Status string `json:"status"` // ACCEPTED | DENIED | RESUBMIT | ERROR
}

Expected JSON Response

The Flag Checker returns a JSON array, one object per submitted flag:

[
  {
    "msg": "[<flag>] <message>",
    "flag": "<flag>",
    "status": "ACCEPTED"
  }
]

status values

  • ACCEPTED — valid flag accepted
  • DENIED — invalid/duplicate/not accepted
  • RESUBMIT — temporary issue, retry later
  • ERROR — internal/generic processing error

Submit Function Contract

func Submit(host string, token string, flags []string) ([]models.ResponseProtocol, error)

Parameters

  • host: Flag Checker address (example: localhost:5000)
  • token: team authentication token
  • flags: list of flags to submit

Returns

  • []models.ResponseProtocol: parsed checker result per flag
  • error: request/response/parsing error

Example Implementations

cc_http.go
//go:build ignore

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"models"
	"net/http"
	"strings"

	"protocols"
)

func Submit(url string, teamToken string, flags []string) ([]protocols.ResponseProtocol, error) {
	jsonData, err := json.Marshal(flags)
	if err != nil {
		return nil, fmt.Errorf("error during marshalling: %w", err)
	}

	req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, fmt.Errorf("error during request creation: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Team-Token", teamToken)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("error during request submission: %w", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("error during response reading: %w", err)
	}

	var responses []struct {
		Status string `json:"status"` // Status of the response (e.g., "0", "1", "2" ,"3") see enum in pkg/models/models.go
		Flag   string `json:"flag"`   // Flag string received from the flag checker service
		Msg    string `json:"msg"`
	}
	// logger.Debug("Raw body %s", string(body))
	if err := json.Unmarshal(body, &responses); err != nil {
		return nil, fmt.Errorf("error during response parsing: %w", err)
	}

	var responsesParsed []protocols.ResponseProtocol = make([]protocols.ResponseProtocol, len(responses))
	for i := range responses {
		responsesParsed[i].Flag = responses[i].Flag
		responsesParsed[i].Msg = strings.Split(responses[i].Msg, "]")[1]

		switch responses[i].Status {
		case "ACCEPTED":
			responsesParsed[i].Status = models.StatusAccepted
		case "DENIED":
			responsesParsed[i].Status = models.StatusDenied
		case "Error":
			responsesParsed[i].Status = models.StatusError
		default:
			responsesParsed[i].Status = models.StatusNotValid
		}
	}

	return responsesParsed, nil
}

Build as a Go Plugin

Compile your protocol into a .so plugin:

go build -buildmode=plugin -o <name>.so <name>.go
  • -buildmode=plugin: builds a runtime-loadable plugin
  • <name>.so: output plugin
  • <name>.go: source file

Error Handling Checklist

Your implementation should handle:

  • network failures (checker unreachable/timeouts)
  • invalid or malformed response bodies
  • JSON unmarshal errors

On failure, return:

  • nil response
  • non-nil error

Final Notes

  • Ensure the Flag Checker is reachable at the configured host.
  • Always send a valid team token.
  • Keep response parsing strict to avoid silent failures.
  • Prefer clear wrapped errors (fmt.Errorf("...: %w", err)) for easier debugging.

How is this guide?

On this page