//
// CRAM: CREATE Real-time Applications Manager
// See the copyright and acknowledgment of authors in the file COPYRIGHT
//
//// Server.cpp -- the CRAM service interface class ////
//
// This is pretty simple; subclasses extend it.
//

#include "Server.h"

using namespace cram;

// Server constructor

Server :: Server(char * name, unsigned short lport, unsigned short eport) 
				: Program(name, lport, eport) { /* nothing special */ };

// Initialize may be overridden in subclasses

void Server :: initialize(void) { 
	mAppStatus = CRAM_INIT;
};

// Actually shut the service down

void Server :: stop(void) {
	shut_down();	// kill the 2 listener threads
}

// Private command decoder
// The return value is # of bytes to write back as response

int Server :: handle_packet(in_addr_t sender, CRAMPacketHeader * pkt) {
	int cmd = pkt->magic & 0x000000ff;	
	int ret_val = CRAM_HEADER_SIZE;		// normal return value
	
	switch (cmd) {
	
	case CRAM_START:					// start-service command
		mLog.log_msg("[Starting service]");
		if (pkt->size != CRAM_HEADER_SIZE) {
			pkt->value = CRAM_ARGUMENT_ERROR;
			printf("Error in start: bad packet size %d\n", pkt->size);
		} else {
			start();					// start service
			pkt->value = CRAM_AOK;
		}
		break;
	case CRAM_STOP:						// stop/exit-service command
		mLog.log_msg("[Stopping service]");
		if (pkt->size != CRAM_HEADER_SIZE) {
			pkt->size = CRAM_ARGUMENT_ERROR;
		} else {
			stop();						// stop service
			pkt->value = CRAM_AOK;
		}
		break;
	case CRAM_SUSPEND:					// suspend-service command
		mLog.log_msg("[Suspending service]");
		if (pkt->size != CRAM_HEADER_SIZE) {
			pkt->size = CRAM_ARGUMENT_ERROR;
		} else {
			suspend();					// suspend service
			pkt->value = CRAM_AOK;
		}
		break;
	case CRAM_RESUME:					// resume-service command
		mLog.log_msg("[Resuming service]");
		if (pkt->size != CRAM_HEADER_SIZE) {
			pkt->size = CRAM_ARGUMENT_ERROR;
		} else {
			resume();					// resume service
			pkt->value = CRAM_AOK;
		}
		break;
	case CRAM_INITIALIZE:
		mLog.log_msg("[Initializing service]");
		if (pkt->size != CRAM_HEADER_SIZE) {
			pkt->size = CRAM_ARGUMENT_ERROR;
		} else {
			initialize();				// initialize service (use a separate thread for this?)
			pkt->value = CRAM_AOK;
		}
		break;
		
	default:							// pass it up to the superclass' version
		return (Program :: handle_packet(sender, pkt));	
	}
	return ret_val;
}

// ServiceRecord constructor

ServiceRecord :: ServiceRecord(char * name, unsigned short lport, unsigned short eport, int pid) 
							: Server(name, lport, eport),
							 mHeartrate(0), mLastbeat(0), mNextbeat(0) { 
	mPid = pid;
};

