/* * @(#)Server.h * * This file is part of webCDwriter - Network CD/DVD Writing. * * Copyright (C) 1999-2006 Jörg P. M. Haeger * * webCDwriter is free software. See CDWserver.cpp for details. */ #ifndef SERVER_H #define SERVER_H #include #include "CDstate.h" #include "Options.h" #include "Session.h" #include "Socket.h" #include "Thread.h" #include "Writer.h" /* * Implementation of a server process. * * @version 20060214 * @author Jörg P. M. Haeger */ class Server { public: static const char errorInCommand[], hint[], hintPercentDone[], info[], unknown[]; private: static pthread_mutex_t activateConfigMutex; private: static bool activateConfigPending; private: static int activeServersNum; protected: static String features, license, serialNo, validity; protected: static int maxServers, maxUsers; static pthread_mutex_t licenseMutex; static int nextServerNo; static class WriterQueues *writerQueue; static Writer *writers; int serverNo, readerNo; time_t connectionT0, sessionT0, sessionT1; Socket &socket; class InputStream &inStream; char errorStr[1024], lineStr[1024]; int logFilesNum; // states unsigned int bytesReceived; int openCommands, isOffline, lineStrPending; String clientIP, clientLocale, clientSoftware; const char *clientSystemName, *clientSystemVersion, *clientUserID, *clientUserName, *userID, *userPassword; bool ejectBeforeVerify; int copiesReady, copiesToDo; // modes int modeShowCdrecord, modeShowMkisofs; struct Options options; class Session *session; const char *tmpSessionID; FILE *project; int quit; public: Server(Socket &socket); virtual ~Server(); static void activateConfig(); static int getActiveServersNum() { return activeServersNum; } int getNo() { return serverNo; } static int getWriterFifoPercent(int writerNo) { return writers[writerNo].fifoPercent; } static String &getWriterOwnerIP(int writerNo) { return writers[writerNo].ownerIP; } static String &getWriterOwnerUser(int writerNo) { return writers[writerNo].ownerUser; } static int getWriterPercent(int writerNo) { return writers[writerNo].percent; } static int getWriterReservedUntil(int writerNo) { return writers[writerNo].reservedUntil; } static String &getWriterStateMedium(int writerNo) { return writers[writerNo].CDState.mediaType; } static enum writerStates getWriterStatus(int writerNo) { return writers[writerNo].state; } static int hextoint(const char *str, int length); static void initStatic(); void run(); static void terminate(); int waitForService(class Queue *queue, int toRank); int waitForService(class Queue *queue, int toRank, int ID); private: void addArgs(Process &p, const char *args); protected: virtual String *addKey(String &preparerID) { return new String(preparerID); } void blank(char *cmdStr); void burnCopy(); void burnSession(); void burnSession2(int threadID); void burnSession3(); void burnSession4(); protected: const char *CD() { return "CD"; } protected: struct CDstate &CDState() { return writer().CDState; } protected: virtual void checkDVDSize() {} void checkFileName(const char *fileName); void checkLoggedIn(); protected: virtual void checkMediumSupport(const char *medium) { throw new Exception(S.e + "This version of CDWserver has no " + medium + " support!"); } void checkOpenSession(); static String *dateToShortString(); void eject() { try { eject2(); } catch (Exception *e) { delete e; } } private: void eject2(); protected: void ejectReader(); void errorToClient(const char *format, ...); void errorToClient(String &str); void executeCmd(); public: static String *getFeatures() { pthread_mutex_lock(&licenseMutex); String *str = new String(features); pthread_mutex_unlock(&licenseMutex); return str; } public: static String *getLicense() { pthread_mutex_lock(&licenseMutex); String *str = new String(license); pthread_mutex_unlock(&licenseMutex); return str; } public: static int getMaxServers() { return maxServers; } public: static int getMaxUsers() { return maxUsers; } public: static String *getSerialNo() { pthread_mutex_lock(&licenseMutex); String *str = new String(serialNo); pthread_mutex_unlock(&licenseMutex); return str; } public: static String *getValidity() { pthread_mutex_lock(&licenseMutex); String *str = new String(validity); pthread_mutex_unlock(&licenseMutex); return str; } protected: String *getNewLogFileName(); protected: bool hasWriter() { try { writerNo(); return true; } catch (Exception *e) { delete e; return false; } } protected: virtual bool isMediumOK(); void load(); void logConnection() { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); try { logConnection2(); } catch (Exception *e) { pthread_mutex_unlock(&mutex); throw e; } pthread_mutex_unlock(&mutex); } void logConnection2(); void logSession(const char *typeStr, const char *result) { String result2 = result; logSession(typeStr, result2); } void logSession(const char *typeStr, String &result) { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); try { logSession2(typeStr, result); } catch (Exception *e) { pthread_mutex_unlock(&mutex); throw e; } pthread_mutex_unlock(&mutex); } void logSession2(const char *typeStr, String &result); void nextCmd(); int noDisc(int trayOpenIfNoDisc = 0) { try { return noDisc2(trayOpenIfNoDisc); } catch (Exception *e) { delete e; } return 1; } private: int noDisc2(int trayOpenIfNoDisc); protected: virtual void putFileContinue( InputStream &inStream, int length) { session->putFileContinue(inStream, length); successToClient("file continued"); } protected: virtual void putFileEnd(int mode, int time) { session->putFileEnd(mode, time); } protected: virtual void putFileStart( const char *arg1, const char *arg2) { session->putFileStart(arg1); } void readATIP(); void readMultiSessionInfo(); protected: virtual void readTOC(); char *removeEscChars(char *str); void reserveDevice(int ID); void resetImageFile(); static void resetStatic(); protected: void resetWriter(); void run_cdrdaoCopy(); void run_cdrecord(); void run_cdrecord2(); protected: virtual void run_cdrecordBlank(const char *modeStr); void run_cdrecordCopy(); protected: virtual void run_growisofs() { } void run_mkisofs(); void run_readcd(); void saveLineStr(); protected: virtual void showFeatures(); void showInsertDiscMsg(); static const char *spaceToEsc(const char *str); protected: void start(); void start_mkisofs(Process &p); protected: virtual void statusToClient() { } void successToClient(const char *format, ...); static String *timeToDigits(time_t t = 0); public: static String *timeToShortString(); public: static String *timeToString(time_t t = 0); protected: void toClient(int code, String &text, int logLevel = 10); void toClient(const char *type, const char *format, ...); void toClient(const char *type, String &str); private: void toClientInternal(String &line, int logLevel = 10); private: void toClientWriteLine(String &line); protected: void verify(); int waitForDisc(); bool wasCancelled(int timeout = 0); void writeImageToRawDevice(); int writerNo() { const Thread *thread = Thread::currentThread(); for (int i = 0; i < maxNumOfWriters; i++) if (writers[i].state != idle && writers[i].thread == thread) return i; throw new Exception(S.e + "Internal error: Has no writer"); } Writer &writer() { return writers[writerNo()]; } }; #endif