use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class MailingNewImpl method transport5_postEnd.
/*
* postEnd
* = procedure 9
*/
private static void transport5_postEnd(PostEndParams params, PostEndResults results) {
// log ingoing data
if (logParamsAndResults) {
StringBuilder sb = new StringBuilder();
params.append(sb, " ", "params");
logf("##\n## procedure MailingNewImpl.transport5_postEnd() -- params\n%s\n##\n", sb.toString());
}
// get the transaction, raising a generic courier exception as we do not know the real protocol...
PostMailTransaction mt = getMailTransaction(params.mailTransaction.get());
if (mt == null) {
throw new IllegalStateException("invalid mail-transaction");
}
// collect recipients
NameList allRecipients = NameList.make();
ChsDatabase chs = mailService.getChsDatabase();
for (ThreePartName rcpt : mt.recipients) {
String rcptFqn = chs.resolveName(rcpt);
List<Name> dlMemberNames;
if (rcptFqn != null && mailService.hasMailbox(rcptFqn)) {
Name rcptName = Name.make();
rcptName.from(rcptFqn);
allRecipients.addDistinct(rcptName);
} else if (rcptFqn != null && (dlMemberNames = MailingOldImpl.getUserGroupMembersLcFqns(rcptFqn)) != null) {
for (Name dlMember : dlMemberNames) {
allRecipients.addDistinct(dlMember);
}
}
}
if (allRecipients.size() == 0) {
if (logParamsAndResults) {
StringBuilder sb = new StringBuilder();
results.append(sb, " ", "results");
logf("##\n## procedure MailingNewImpl.transport5_postEnd() -- results (NO valid RECIPIENTS)\n%s\n##\n", sb.toString());
}
// leave messageId as all-zeroes => (hopefully) NullID => (hopefully) message not sent
return;
}
// create the items for the mail service
SerializedFile mailContentFile = mt.attachment;
if (mailContentFile == null) {
// no attached serialized item => produce one with the attributes used by Star..VP2.x
// force version = 2
mailContentFile = new SerializedFile(null, true);
// leave the content proper empty
mailContentFile.file.content.lastByteSignificant.set(true);
SEQUENCE<Attribute> attrs = mailContentFile.file.attributes.value;
attrs.add().set(FilingCommon.atAccessList, FilingCommon.AccessList::make4, v -> v.defaulted.set(true));
attrs.add().setAsTime(FilingCommon.atBackedUpOn, mt.mailPostTime.get());
attrs.add().setAsCardinal(FilingCommon.atChecksum, 0xFFFF);
attrs.add().setAsChsName(FilingCommon.atCreatedBy, mt.senderName);
attrs.add().setAsTime(FilingCommon.atCreatedOn, mt.mailPostTime.get());
attrs.add().setAsBoolean(FilingCommon.atIsDirectory, false);
attrs.add().set(MailingCommon.subject, STRING::make, v -> v.set(mt.subject));
attrs.add().setAsLongCardinal(MailingCommon.bodySize, 0);
attrs.add().setAsLongCardinal(FilingCommon.atStoredSize, 0);
attrs.add().setAsLongCardinal(FilingCommon.atSubtreeSize, 0);
attrs.add().setAsLongCardinal(MailingCommon.bodyType, FilingCommon.tVPMailNote);
attrs.add().setAsCardinal(4402, 0);
attrs.add().setAsCardinal(4401, 1);
attrs.add().setAsCardinal(4348, 11);
attrs.add().setAsCardinal(4403, 0x005C009E);
attrs.add().setAsBoolean(MailingCommon.coversheetOn, true);
attrs.add().set(MailingCommon.from, NameList::make, v -> v.add().from(mt.senderName));
attrs.add().set(MailingCommon.to, NameList::make, v -> copyNames(mt.toNames, v));
attrs.add().set(MailingCommon.comments, STRING::make, v -> v.set(mt.mailText));
attrs.add().set(MailingCommon.cc, NameList::make, v -> copyNames(mt.ccNames, v));
} else {
// check if all required Star..VP2.x attributes are present, adding the missing ones if necessary
boolean hasMailFrom = false;
boolean hasMailTo = false;
boolean hasMailCc = false;
boolean hasCoversheetOn = false;
SEQUENCE<Attribute> attrs = mailContentFile.file.attributes.value;
for (int i = 0; i < attrs.size(); i++) {
int attributeType = (int) (attrs.get(i).type.get() & 0xFFFF_FFFFL);
hasMailFrom |= (attributeType == MailingCommon.from);
hasMailTo |= (attributeType == MailingCommon.to);
hasMailCc |= (attributeType == MailingCommon.cc);
hasCoversheetOn |= (attributeType == MailingCommon.coversheetOn);
}
if (!hasCoversheetOn) {
attrs.add().setAsBoolean(MailingCommon.coversheetOn, true);
}
if (!hasMailFrom) {
attrs.add().set(MailingCommon.from, NameList::make, v -> v.add().from(mt.senderName));
}
if (!hasMailTo) {
attrs.add().set(MailingCommon.to, NameList::make, v -> copyNames(mt.toNames, v));
}
if (!hasMailCc) {
attrs.add().set(MailingCommon.cc, NameList::make, v -> copyNames(mt.ccNames, v));
}
}
// create the mail
iContentSource source = new MailService.ValueContentSource(mailContentFile);
int[] mailId = mailService.postMail(mt.senderName, allRecipients, MailingCommon.ctSerializedFile, source);
// set return values
for (int i = 0; i < mailId.length; i++) {
results.messageId.get(i).set(mailId[i]);
}
// we're done with this mail, so forget the mail transaction
dropMailTransaction(mt);
// log outgoing data
if (logParamsAndResults) {
StringBuilder sb = new StringBuilder();
results.append(sb, " ", "results");
logf("##\n## procedure MailingNewImpl.transport5_postEnd() -- results\n%s\n##\n", sb.toString());
}
}
use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class MailingOldImpl method init.
/**
* Initialize the filing volume holding the mail files and create
* the mail service instance used by the Courier procedures.
*
* @param network the network number serviced by the XNS services
* @param machine the network number of the machine hosting the mail service
* @param chsDatabase the Clearinghouse database to be used by the mail service
* @param mailboxesVolumePath the OS file system path of the filing volume where
* the mail files will be stored.
* @return {@code true} if the initialization was successful
*/
public static boolean init(long network, long machine, ChsDatabase chsDatabase, String mailboxesVolumePath) {
if (mailService != null) {
log("MS,Error: mail service already started\n");
return false;
}
networkId = network;
machineId = machine;
// the name of the "one" XNS mail service in a Dodo network
String svcName = chsDatabase.getMailServiceFqn();
// content of the minimal root folders file for the mail Filing volume
// (as this volume is reserved for mailing, we take the liberty to force things here)
String initRootFolders = "Mailboxes\t" + svcName + "\n" + "Mailfiles\t" + svcName + "\n";
log("Starting mail service '%s' (mailboxes volume directory: %s)", svcName, mailboxesVolumePath);
try {
// check the filing volume root path and ensure that the toplevel folders are present (or created)
File mailboxesDir = new File(mailboxesVolumePath);
if (!mailboxesDir.exists()) {
if (!mailboxesDir.mkdirs()) {
log("MS,Error: unable to create mailBoxes directory '%s', aborting startup\n", mailboxesVolumePath);
return false;
}
}
File rootFoldersLst = new File(mailboxesDir, "root-folder.lst");
try (FileOutputStream fos = new FileOutputStream(rootFoldersLst)) {
fos.write(initRootFolders.getBytes());
}
// open the filing volume for the mail files
Volume volume = Volume.openVolume(mailboxesVolumePath, new ErrorRaiser());
// create the mailservice instance
mailService = new MailService(networkId, machineId, svcName, chsDatabase, volume);
} catch (Exception e) {
log("Error: unable to open mailboxes volume, cause: %s", e.getMessage());
return false;
}
log("Mail service '%s' started", svcName);
return (mailService != null);
}
use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class FilingImpl method addVolume.
public static boolean addVolume(ThreePartName serviceName, String volumeBasedirName) {
if (chsDatabase == null || networkId < 0 || machineId < 0) {
throw new IllegalStateException("Not initialized (chsDatabase == null || networkId < 0 || machineId < 0)");
}
synchronized (services) {
String svcName = serviceName.getLcFqn();
if (services.containsKey(svcName)) {
log("Error: attempt to re-open service %s (volume directory: %s)", svcName, volumeBasedirName);
return false;
}
log("Starting file service '%s' (volume directory: %s)", svcName, volumeBasedirName);
try {
Volume volume = Volume.openVolume(volumeBasedirName, new ErrorRaiser());
Service svc = new Service(chsDatabase, machineId, serviceName, volume);
services.put(svcName, svc);
if (defaultService == null) {
defaultService = svc;
}
} catch (Exception e) {
log("Error: unable to open volume, cause: %s", e.getMessage());
return false;
}
log("File service '%s' started", svcName);
return true;
}
}
use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class Clearinghouse3Impl method init.
/**
* Set values to use for responses.
*
* @param network networkId for the local network
* @param machine hostId of the local machine
* @param chsDb clearinghouse database to use for courier requests
* @param hostIds explicit list of network addresses to respond BfS requests with
* (if the local machine is to be part of the BfS responses, the host
* {@code network}/{@code machine} must be explicitely added to {@code hostIds})
*/
public static void init(long network, long machine, ChsDatabase chsDb, List<NetworkAddress> hostIds) {
networkId = network;
machineId = machine;
chsDatabase = chsDb;
bfsHosts.clear();
if (hostIds == null || hostIds.isEmpty()) {
// add the only known server to the address list: ourself
NetworkAddress addr = NetworkAddress.make();
addr.network.set((int) networkId);
addr.host.set(machineId);
addr.socket.set(0);
bfsHosts.add(addr);
} else {
bfsHosts.addAll(hostIds);
}
}
use of dev.hawala.xns.level4.common.ChsDatabase in project dodo by devhawala.
the class Service method checkCredentials.
private ThreePartName checkCredentials(Credentials credentials, Verifier verifier, int[] decodedConversationKey, StrongVerifier decodedVerifier) {
ThreePartName username = null;
try {
if (credentials.type.get() == CredentialsType.simple) {
if (credentials.value.size() == 0) {
// anonymous access resp. secondary credentials currently not supported
new AuthenticationErrorRecord(Problem.credentialsInvalid).raise();
}
username = AuthChsCommon.simpleCheckPasswordForSimpleCredentials(chsDatabase, credentials, verifier);
} else {
username = AuthChsCommon.checkStrongCredentials(chsDatabase, credentials, verifier, // chsDatabase.getChsQueryName(),
this.serviceName, machineId, decodedConversationKey, decodedVerifier);
}
} catch (IllegalArgumentException iac) {
AuthenticationErrorRecord err = new AuthenticationErrorRecord(Problem.credentialsInvalid);
Log.C.printf("FS", "checkCredentials() IllegalArgumentException (name not existing) -> rejecting with AuthenticationError[credentialsInvalid]\n");
err.raise();
} catch (EndOfMessageException e) {
AuthenticationErrorRecord err = new AuthenticationErrorRecord(Problem.inappropriateCredentials);
Log.C.printf("FS", "checkCredentials() EndOfMessageException when deserializing credsObject -> rejecting with AuthenticationError[inappropriateCredentials]\n");
err.raise();
} catch (Exception e) {
AuthenticationErrorRecord err = new AuthenticationErrorRecord(Problem.otherProblem);
Log.C.printf("FS", "checkCredentials() Exception when checking credentials -> rejecting with AuthenticationError[otherProblem]: %s\n", e.getMessage());
err.raise();
}
if (username == null) {
AuthenticationErrorRecord err = new AuthenticationErrorRecord(Problem.credentialsInvalid);
Log.C.printf("FS", "checkCredentials() -> rejecting with AuthenticationError[credentialsInvalid]\n");
err.raise();
}
return username;
}
Aggregations