/* Distributed Checksum Clearinghouse
 *
 * convert a DCC opcode to a string
 *
 * Copyright (c) 2005 by Rhyolite Software
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE
 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Rhyolite Software DCC 1.2.74-1.20 $Revision$
 */

#include "dcc_defs.h"

/* This is not thread safe */

static struct {
    char buf[30];
} unk[4];
static int unk_index;

const char *
dcc_op2str(DCC_OPS op, DCC_AOPS aop, u_int32_t val1)
{
	char *p;

	switch (op) {
	case DCC_OP_INVALID:	return "INVALID";
	case DCC_OP_NOP:	return "NOP";
	case DCC_OP_REPORT:	return "REPORT";
	case DCC_OP_QUERY:	return "QUERY";
	case DCC_OP_QUERY_RESP:	return "QUERY-RESP";
	case DCC_OP_ADMN:
		switch (aop) {
		case DCC_AOP_OK:	    return "ADMN";
		case DCC_AOP_STOP:	    return "ADMN STOP";
		case DCC_AOP_NEW_IDS:	    return "ADMN NEW_IDS";
		case DCC_AOP_FLOD:
			switch ((DCC_AOP_FLODS)(val1 % 256)) {
#			define FS "ADMN FLOD"
			case DCC_AOP_FLOD_CHECK:    return FS" CHECK";
			case DCC_AOP_FLOD_SHUTDOWN: return FS" SHUTDOWN";
			case DCC_AOP_FLOD_HALT:	    return FS" HALT";
			case DCC_AOP_FLOD_RESUME:   return FS" RESUME";
			case DCC_AOP_FLOD_REWIND:   return FS" REWIND";
			case DCC_AOP_FLOD_LIST:	    return FS" LIST";
			case DCC_AOP_FLOD_STATS:    return FS" STATS";
			case DCC_AOP_FLOD_STATS_CLEAR:return FS" STATS CLEAR";
			case DCC_AOP_FLOD_FFWD_IN:  return FS" FFWD IN";
			case DCC_AOP_FLOD_FFWD_OUT: return FS" FFWD OUT";
#			undef FS
			}
			break;
		case DCC_AOP_DB_UNLOCK:	    return "ADMN DB unlock";
		case DCC_AOP_DB_NEW:	    return "ADMN DB new";
		case DCC_AOP_STATS:	    return "ADMN stats";
		case DCC_AOP_STATS_CLEAR:   return "ADMN stats clear";
		case DCC_AOP_TRACE_ON:	    return "ADMN trace on";
		case DCC_AOP_TRACE_OFF:	    return "ADMN trace off";
		case DCC_AOP_unused:	    break;
		case DCC_AOP_CLIENTS:	    return "ADMN clients";
		case DCC_AOP_CLIENTS_ID:    return "ADMN clients by ID";
		case DCC_AOP_ANON_DELAY:    return "ADMN anon delay";
		}
		snprintf(p = unk[unk_index].buf,
			 sizeof(unk[unk_index].buf),
			 "ADMN unknown #%d #%#x", aop, val1);
		unk_index = (unk_index+1) % DIM(unk);
		return p;
	case DCC_OP_OK:		return "OK";
	case DCC_OP_ERROR:	return "ERROR";
	case DCC_OP_DELETE:	return "DELETE";
	case DCC_OP_GREY_REPORT:return "GREYLIST REPORT";
	case DCC_OP_GREY_QUERY:	return "GREYLIST QUERY";
	case DCC_OP_GREY_SPAM:	return "GREYLIST SPAM";
	case DCC_OP_GREY_WHITE:	return "GREYLIST WHITELIST";
	}

	snprintf(p = unk[unk_index].buf,
		 sizeof(unk[unk_index].buf),
		 "unknown op #%d", op);
	unk_index = (unk_index+1) % DIM(unk);
	return p;
}



const char *
dcc_req_op2str(const DCC_ADMN_REQ *req)
{
	return dcc_op2str(req->hdr.op, req->aop, ntohl(req->val1));
}



const char *
dcc_hdr_op2str(const DCC_HDR *hdr)
{
	return dcc_op2str(hdr->op, DCC_AOP_OK, 0);
}
