⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snppserver.c++

📁 fax相关的东西
💻 C++
📖 第 1 页 / 共 3 页
字号:
    time_t now = Sys::now();    if (when > now) {	defJob.tts = when;	const struct tm* tm = cvtTime(defJob.tts);	reply(250, "Message will be processed at %02d%02d%02d%02d%02d."	    , tm->tm_year	    , tm->tm_mon+1	    , tm->tm_mday	    , tm->tm_hour	    , tm->tm_min	);    } else	reply(550, "Invalid delivery date/time; time in the past.");}/* * Login as the specified user. */voidSNPPServer::loginCmd(const char* loginID, const char* pass){    if (IS(LOGGEDIN))        end_login();    the_user = loginID;    state &= ~S_PRIVILEGED;    adminwd = "*";			// make sure no admin privileges    passwd = "*";			// just in case...    if (checkUser(loginID)) {	if (passwd != "") {	    if (pass[0] == '\0' || !(streq(crypt(pass, passwd), passwd) || pamCheck(the_user, pass))) {		if (++loginAttempts >= maxLoginAttempts) {		    reply(421, "Login incorrect (closing connection).");		    logNotice("Repeated SNPP login failures for user %s from %s [%s]"			, (const char*) the_user			, (const char*) remotehost			, (const char*) remoteaddr		    );		    dologout(0);		}		reply(550, "Login incorrect.");		logInfo("SNPP login failed from %s [%s], %s"		    , (const char*) remotehost		    , (const char*) remoteaddr		    , (const char*) the_user		);		return;	    }	}	login(250);    } else {	if (++loginAttempts >= maxLoginAttempts) {	    reply(421, "Login incorrect (closing connection).");	    logNotice("Repeated SNPP login failures for user %s from %s [%s]"		, (const char*) the_user		, (const char*) remotehost		, (const char*) remoteaddr	    );	    dologout(0);	} else {	    reply(421, "User %s access denied.", (const char*) the_user);	    logNotice("SNPP LOGIN REFUSED (%s) FROM %s [%s], %s"		, "user denied"		, (const char*) remotehost		, (const char*) remoteaddr		, (const char*) the_user	    );	}    }}/* * Specify a one-line message text. */voidSNPPServer::messageCmd(const char* msg){    if (!haveText) {	u_int len = strlen(msg);	if (len > maxMsgLength) {	    reply(550,		"Error, message too long; no more than %u characters accepted.",		maxMsgLength);	    return;	}	fxStr emsg;	u_int seqnum = getDocumentNumber(emsg);	if (seqnum == (u_int) -1) {	    reply(554, "%s", (const char*)emsg);	    return;	}	msgFile = fxStr::format("/%s/doc%u.page", FAX_TMPDIR, seqnum);	FILE* fout = Sys::fopen(msgFile, "w");	if (fout != NULL) {	    setFileOwner(msgFile);	    FileCache::chmod(msgFile, 0660);		// sync cache	    tempFiles.append(msgFile);	    (void) fwrite(msg, len, 1, fout);	    if (fclose(fout)) {		perror_reply(554, msgFile, errno);		Sys::unlink(msgFile);	    } else {		haveText = true;		reply(250, "Message text OK.");	    }	} else	    perror_reply(554, msgFile, errno);    } else	reply(503, "Error, message already entered.");}/* * Process a PAGE command.  Map the client-specified pager * identification string to a service provider phone number * and destination PIN and create a new job for this request. */voidSNPPServer::pagerCmd(const char* pagerID, const char* pin){    /*     * Lookup pager ID and map to a service provider     * and, optionally, PIN.     */    fxStr provider;    fxStr PIN;    fxStr emsg;    if (!mapPagerID(pagerID, provider, PIN, emsg)) {	reply(550, "%s.", (const char*) emsg);	return;    }    /*     * RFC 1861 says we should lock the Level, Coverage,     * Holdtime, and Alert values for the request at this point.     * To do this we create a job (inheriting the current state     * from the default job) and fill in any other information.     * However we do not submit it until later (when a SEND     * request is made).     */    curJob = &defJob;				// inherit from default job    // XXX merge items to same provider (maybe?)    if (newJob(emsg) && updateJobOnDisk(*curJob, emsg)) {	fxStr file("/" | curJob->qfile);	setFileOwner(file);			// force ownership	FileCache::chmod(file, 0660);		// sync cache	curJob->lastmod = Sys::now();		// noone else should update	curJob->number = provider;		// destination phone number	if (!pin)				// use mapped value	    pin = PIN;	curJob->items.append(FaxItem(FaxRequest::send_page, 0, "", pin));	curJob->items.append(	    FaxItem(FaxRequest::send_page_saved, 0, "", pin));	reply(250, "Pager ID accepted; provider: %s pin: %s jobid: %s."	    , (const char*) provider	    , pin	    , (const char*) curJob->jobid	);	msgs.append(curJob->jobid);    } else	reply(554, "%s.", (const char*) emsg);    initSNPPJob();				// reset job-related state}/* * Validate a client-specified pager ID string. * This is only sort of like the intended usage * but is the only thing that makes sense in * our environment (where the provider is not * directly accessible). */voidSNPPServer::pingCmd(const char* pagerID){    /*     * Lookup pager ID and map to a service provider     * and, optionally, PIN.     */    fxStr provider;    fxStr PIN;    fxStr emsg;    if (mapPagerID(pagerID, provider, PIN, emsg))	reply(821, "Valid pager ID, no location information available.");    else	reply(550, "%s.", (const char*) emsg);}static boolnotPresent(FaxItemArray& a, const char* name){    for (u_int i = 0, n = a.length(); i < n; i++)	if (a[i].op == FaxRequest::send_data && a[i].item == name)	    return (false);    return (true);}/* * Send (submit) a pager request.  We complete the * formulation of the job and submit it to the * scheduler.  If this job is marked for no queueing * then we also wait around for the job to complete. */voidSNPPServer::sendCmd(void){    if (msgs.length() == 0) {	reply(503, "Error, no pager ID specified with PAGE.");	return;    }    /*     * If we need to wait for jobs to complete, construct     * and register a trigger now before we submit the jobs.     */    fxStr emsg;    u_int i, n = msgs.length();    bool waitForJobs = false;    for (i = 0; i < n; i++) {	Job* job = findJob(msgs[i], emsg);	if (!job)	    msgs.remove(i), n--;	else if (!job->queued)	    waitForJobs = true;    }    if (waitForJobs) {	state &= ~S_LOGTRIG;		// just process events	if (!newTrigger(emsg, "J%04x", 1<<Trigger::JOB_DEAD)) {	    reply(550,		"Cannot register trigger to wait for job completion: %s.",		(const char*) emsg);	    return;	}    }    const char* docname = msgFile;    const char* cp = strrchr(docname, '/');    if (!cp)				// relative name, e.g. doc123	cp = docname;    for (i = 0; i < n; i++) {	Job* job = findJob(msgs[i], emsg);	if (!job) {	    msgs.remove(i), n--;	    continue;	}	if (*cp != '\0') {	    /*	     * Add a reference to the message text for	     * the current job, if not already present.	     */	    fxStr document =		fxStr::format("/" FAX_DOCDIR "%s.", cp) | job->jobid;	    if (notPresent(job->items, &document[1])) {		if (Sys::link(docname, document) < 0) {		    reply(554, "Unable to link document %s to %s: %s.",			docname, (const char*) document, strerror(errno));		    return;		}		job->items.append(		    FaxItem(FaxRequest::send_data, 0, "", &document[1]));	    }	}	/*	 * Submit the job for scheduling.	 */	if (job->mailaddr == "")	    replyBadJob(*job, T_NOTIFYADDR);	else if (job->sender == "")	    replyBadJob(*job, T_FROM_USER);	else if (job->modem == "")	    replyBadJob(*job, T_MODEM);	else if (job->client == "")	    replyBadJob(*job, T_CLIENT);	else {	    if (job->external == "")		job->external = job->number;	    if (job->tts == 0)		job->tts = Sys::now();	    job->killtime += job->tts;	// adjust based on any hold time	    if (updateJobOnDisk(*job, emsg)) {		const char* jobid = job->jobid;		/*		 * NB: we don't mark the lastmod time for the		 * job since the scheduler should re-write the		 * queue file to reflect what it did with it		 * (e.g. what state it placed the job in).		 */		if (sendQueuerACK(emsg, "S%s", jobid))		    continue;		reply(554, "Failed to submit message %s: %s.",		    jobid, (const char*) emsg);	    } else		reply(554, "%s.", (const char*) emsg);	}	if (waitForJobs) {		// cleanup trigger on error	    cancelTrigger(emsg);	    /*	     * Not sure what to do here.  If some jobs got	     * submitted then we want to remove them so the	     * client can just reissue SEND if the error was	     * transient (e.g. faxq was temporarily stopped).	     * However we don't track which jobs got started	     * and which did not so for now we'll just leave	     * everything so the client can resubmit things	     * with a subsequent SEND.  Unfortunately this	     * can result in duplicate pages being sent.	     */	}	return;				// failure    }    if (waitForJobs) {			// no queueing, wait for submitted jobs	if (setjmp(urgcatch) == 0) {	    Dispatcher& disp = Dispatcher::instance();	    state |= S_WAITTRIG|S_SENDWAIT;	    bool jobsPending;	    do {		disp.dispatch();		/*		 * The trigger event handlers update our notion		 * of the job state asynchronously so we can just		 * monitor the job state(s) after each event we		 * receive.		 */		jobsPending = false;		for (i = 0; i < n; i++) {		    Job* job = findJob(msgs[i], emsg);		    if (!job)			msgs.remove(i), n--;		    else if (!job->queued && 		      job->state != FaxRequest::state_done &&		      job->state != FaxRequest::state_failed)			jobsPending = true;		}	    } while (IS(WAITTRIG) && jobsPending);	    reply(250, "Message processing completed.");	}	state &= ~(S_WAITTRIG|S_SENDWAIT);	(void) cancelTrigger(emsg);    } else				// jobs queued, just acknowledge	reply(250, "Message%s succesfully queued.",	    msgs.length() > 1 ? "s" : "");    resetState();			// reset SEND-related state}/* * Set the message service level.  We currently use * this just to select a scheduling priority and * job expiration time. */voidSNPPServer::serviceLevel(u_int level){    if (level <= 11) {	defJob.usrpri = priMap[level];	defJob.killtime = 60*killMap[level];	defJob.retrytime = retryMap[level];	reply(250, "OK, service level %u accepted.", level);    } else	reply(550, "Invalid service level %u; we only handle 0-11.", level);}/* * Return server status. */voidSNPPServer::statusCmd(void){    reply(214, "%s SNPP server status:", (const char*) hostname);    reply(214, "    %s", version);    if (!isdigit(remotehost[0]))	reply(214, "    Connected to %s (%s).",	    (const char*) remotehost, (const char*) remoteaddr);    else	reply(214, "    Connected to %s.", (const char*) remotehost);    if (IS(LOGGEDIN)) {	reply(214, "    Logged in as user %s (uid %u)."	    , (const char*) the_user	    , uid	);    } else	reply(214, "    Waiting for login.");    reply(214, "    Idle timeout set to %d seconds.", idleTimeout);    if (discTime > 0)	reply(214, "    Server scheduled to be unavailable at %.24s.",	    asctime(cvtTime(discTime)));    else	reply(214, "    No server down time currently scheduled.");    reply(214, "    HylaFAX scheduler reached at %s (%sconnected)."	, (const char*) faxqFIFOName	, faxqFd == -1 ? "not " : ""    );    if (clientFd != -1)	reply(214, "    Server FIFO is /%s (%sopen)."	    , (const char*) clientFIFOName	    , clientFd == -1 ? "not " : ""	);    if (IS(WAITFIFO))	reply(214, "    Waiting for response from HylaFAX scheduler.");    if (msgs.length() > 0) {	reply(214, "    %u message%s prepared for transmission.",	    msgs.length(), msgs.length() > 1 ? "s" : "");	// XXX dump status of msgs    } else	reply(214, "    No messages prepared for transmission.");    reply(214, "    %s message text.", haveText ? "Received" : "No received");    reply(250, "End of status");}/* * Set the subject for outgoing messages. * For now we just use it to tag the jobs. */voidSNPPServer::subjectCmd(const char* subj){    defJob.jobtag = subj;			// XXX    reply(250, "Message subject OK.");}/* * Configuration support. */voidSNPPServer::resetConfig(){    InetFaxServer::resetConfig();    setupConfig();}voidSNPPServer::setupConfig(){    setConfigItem("maxmsglength",  "128");    setConfigItem("pageridmapfile","/etc/pagermap");    setConfigItem("prioritymap",	"63 127 127 127 127 127 127  127  127  127  127  127");    setConfigItem("killtimemap",	" 5   5   5  15  60 240 720 1440 1440 1440 1440 1440");    setConfigItem("retrytimemap",	"30  60  60 180   0   0   0    0    0    0    0    0");}static voidsetShortMap(u_short map[12], const char* value){    char* cp;    for (int i = 0; i < 12; i++) {	map[i] = (u_short) strtoul(value, &cp, 0);	if (!cp && *cp == '\0')	    break;	value = cp;    }}static voidsetTimeMap(time_t map[12], const char* value){    char* cp;    for (int i = 0; i < 12; i++) {	map[i] = (time_t) strtoul(value, &cp, 0);	if (!cp && *cp == '\0')	    break;	value = cp;    }}boolSNPPServer::setConfigItem(const char* tag, const char* value){    if (streq(tag, "maxmsglength")) {	maxMsgLength = getNumber(value);    } else if (streq(tag, "pageridmapfile")) {	pagerIDMapFile = value;    } else if (streq(tag, "prioritymap")) {	setShortMap(priMap, value);    } else if (streq(tag, "killtimemap")) {	setTimeMap(killMap, value);    } else if (streq(tag, "retrytimemap")) {	setTimeMap(retryMap, value);    } else if (!InetFaxServer::setConfigItem(tag, value))	return (false);    return (true);}#endif /* SNPP_SUPPORT */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -