static int
cnt_error(struct sess *sp)
{
    struct worker *w;
    struct http *h;
    char date[40];

    CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);

    w = sp->wrk;
    if (sp->obj == NULL) {
        HSH_Prealloc(sp);
        sp->obj = HSH_NewObject(sp, 1);
        sp->obj->xid = sp->xid;
        sp->obj->entered = sp->t_req;
    } else {
        /* XXX: Null the headers ? */
    }
    CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
    h = sp->obj->http;

    http_PutProtocol(w, sp->fd, h, "HTTP/1.1");
    http_PutStatus(w, sp->fd, h, sp->err_code);
    TIM_format(TIM_real(), date);
    http_PrintfHeader(w, sp->fd, h, "Date: %s", date);
    http_PrintfHeader(w, sp->fd, h, "Server: Varnish");
    http_PrintfHeader(w, sp->fd, h, "Retry-After: %d", params->err_ttl);

    if (sp->err_reason != NULL)
        http_PutResponse(w, sp->fd, h, sp->err_reason);
    else
        http_PutResponse(w, sp->fd, h,
                         http_StatusMessage(sp->err_code));
    VCL_error_method(sp);

    if (sp->handling == VCL_RET_RESTART) {
        HSH_Drop(sp);
        sp->director = NULL;
        sp->restarts++;
        sp->step = STP_RECV;
        return (0);
    }

    /* We always close when we take this path */
    sp->doclose = "error";
    sp->wantbody = 1;

    assert(sp->handling == VCL_RET_DELIVER);
    sp->err_code = 0;
    sp->err_reason = NULL;
    sp->wrk->bereq = NULL;
    sp->step = STP_DELIVER;
    return (0);
}
static int
cnt_error(struct sess *sp)
{
    struct http *h;
    char date[40];
    struct worker *wrk;

    CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
    wrk = sp->wrk;
    CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);

    if (wrk->obj == NULL) {
        HSH_Prealloc(sp);
        AZ(wrk->busyobj);
        wrk->busyobj = VBO_GetBusyObj(wrk);
        wrk->obj = STV_NewObject(wrk, NULL, cache_param->http_resp_size,
                                 (uint16_t)cache_param->http_max_hdr);
        if (wrk->obj == NULL)
            wrk->obj = STV_NewObject(wrk, TRANSIENT_STORAGE,
                                     cache_param->http_resp_size,
                                     (uint16_t)cache_param->http_max_hdr);
        if (wrk->obj == NULL) {
            sp->doclose = "Out of objects";
            sp->director = NULL;
            http_Setup(wrk->busyobj->beresp, NULL);
            http_Setup(wrk->busyobj->bereq, NULL);
            sp->step = STP_DONE;
            return(0);
        }
        AN(wrk->obj);
        wrk->obj->xid = sp->xid;
        wrk->obj->exp.entered = sp->t_req;
    } else {
        CHECK_OBJ_NOTNULL(wrk->busyobj, BUSYOBJ_MAGIC);
        /* XXX: Null the headers ? */
    }
    CHECK_OBJ_NOTNULL(wrk->obj, OBJECT_MAGIC);
    h = wrk->obj->http;

    if (sp->err_code < 100 || sp->err_code > 999)
        sp->err_code = 501;

    http_PutProtocol(wrk, sp->vsl_id, h, "HTTP/1.1");
    http_PutStatus(h, sp->err_code);
    VTIM_format(W_TIM_real(wrk), date);
    http_PrintfHeader(wrk, sp->vsl_id, h, "Date: %s", date);
    http_SetHeader(wrk, sp->vsl_id, h, "Server: Varnish");

    if (sp->err_reason != NULL)
        http_PutResponse(wrk, sp->vsl_id, h, sp->err_reason);
    else
        http_PutResponse(wrk, sp->vsl_id, h,
                         http_StatusMessage(sp->err_code));
    VCL_error_method(sp);

    if (sp->handling == VCL_RET_RESTART &&
            sp->restarts <  cache_param->max_restarts) {
        HSH_Drop(wrk);
        VBO_DerefBusyObj(wrk, &wrk->busyobj);
        sp->director = NULL;
        sp->restarts++;
        sp->step = STP_RECV;
        return (0);
    } else if (sp->handling == VCL_RET_RESTART)
        sp->handling = VCL_RET_DELIVER;


    /* We always close when we take this path */
    sp->doclose = "error";
    sp->wantbody = 1;

    assert(sp->handling == VCL_RET_DELIVER);
    sp->err_code = 0;
    sp->err_reason = NULL;
    http_Setup(wrk->busyobj->bereq, NULL);
    VBO_DerefBusyObj(wrk, &wrk->busyobj);
    sp->step = STP_PREPRESP;
    return (0);
}