/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*/
package org.thingml.externalthingplugins.c.posix.dnssd;
import java.util.ArrayList;
import java.util.Map;
import org.sintef.thingml.*;
import org.sintef.thingml.constraints.ThingMLHelpers;
import org.sintef.thingml.helpers.CompositeStateHelper;
import org.sintef.thingml.helpers.ThingMLElementHelper;
import org.thingml.compilers.DebugProfile;
import org.thingml.compilers.c.CCompilerContext;
import org.thingml.compilers.c.CThingImplCompiler;
import org.thingml.externalthingplugins.c.posix.PosixDNSSDExternalThingPlugin;
import org.thingml.externalthingplugins.c.posix.dnssd.utils.DNSSDUtils;
/**
* Created by vassik on 01.11.16.
*/
public class PosixDNSSDThingImplCompiler extends CThingImplCompiler {
private PosixDNSSDExternalThingPlugin plugin;
public PosixDNSSDThingImplCompiler(PosixDNSSDExternalThingPlugin _plugin) {
plugin = _plugin;
}
protected void generateCFunctions(Thing thing, StringBuilder builder, CCompilerContext ctx, DebugProfile debugProfile) {
super.generateCFunctions(thing, builder, ctx, debugProfile);
builder.append("// Implementation of the declared prototypes to integrate with DNSSD. " +
"Generated by " + this.getClass().getSimpleName() + "\n");
Port port = DNSSDUtils.getDNSSDPort(thing);
Map<String, Property> propertyMap = DNSSDUtils.getDNSSDProperties(thing);
if(port == null || propertyMap == null)
return;
Message message_failure = DNSSDUtils.getDNSSDSrvPublishFailure(port.getSends());
Message message_publish = DNSSDUtils.getDNSSDSrvPublishSuccess(port.getSends());
Message message_unpublish = DNSSDUtils.getDNSSDSrvUnpublishSuccess(port.getSends());
Map<String, String> success_callback = DNSSDUtils.generateDNSSDClientRunningCallback(thing, ctx);
Map<String, String> failure_callback = DNSSDUtils.generateDNSSDClientFailureCallback(thing, port, message_failure, ctx);
Map<String, String> publish_success_callback = DNSSDUtils.generateDNSSDSrvPublishCallback(thing, port, message_publish, ctx);
Map<String, String> unpublish_success_callback = DNSSDUtils.generateDNSSDSrvUnpublishCallback(thing, port, message_unpublish, ctx);
Map<String, String> publish_failure_callback = DNSSDUtils.generateDNSSDSrvFailureCallback(thing, port, message_failure, ctx);
builder.append("// DNSSD callbacks. " +
"Generated by " + this.getClass().getSimpleName() + "\n\n");
builder.append(success_callback.values().iterator().next());
builder.append("\n");
builder.append(failure_callback.values().iterator().next());
builder.append("\n");
builder.append(publish_success_callback.values().iterator().next());
builder.append("\n");
builder.append(unpublish_success_callback.values().iterator().next());
builder.append("\n");
builder.append(publish_failure_callback.values().iterator().next());
builder.append("\n");
builder.append("void ");
builder.append(thing.getName() + "_setup");
ctx.appendFormalParametersEmptyHandler(thing, builder);
builder.append("{\n");
builder.append(ctx.getInstanceVarName() + "->avahi_client = " +
plugin.getProtocolName() + "_constructDNSSDThreadedAhvaiClient();\n");
builder.append(ctx.getInstanceVarName() + "->avahi_client->thing_instance = " +
"" + ctx.getInstanceVarName() + ";\n");
builder.append(ctx.getInstanceVarName() + "->avahi_client->fn_client_running_callback = " +
"" + success_callback.keySet().iterator().next() + ";\n");
builder.append(ctx.getInstanceVarName() + "->avahi_client->fn_client_failure_callback = " +
"" + failure_callback.keySet().iterator().next() + ";\n");
builder.append("}\n\n");
builder.append("void ");
builder.append(thing.getName() + "_startup");
ctx.appendFormalParametersEmptyHandler(thing, builder);
builder.append("{\n");
builder.append(plugin.getProtocolName() + "_start_avahi_client" +
"(" + ctx.getInstanceVarName() + "->avahi_client);\n");
builder.append("}\n\n");
builder.append("void ");
builder.append(thing.getName() + "_shutdown");
ctx.appendFormalParametersEmptyHandler(thing, builder);
builder.append("{\n");
builder.append(plugin.getProtocolName() + "_remove_dnssd_service" +
"(" + ctx.getInstanceVarName() + "->service_data);\n");
builder.append(plugin.getProtocolName() + "_distructDNSSDAvahiService" +
"(&" + ctx.getInstanceVarName() + "->service_data);\n");
builder.append(plugin.getProtocolName() + "_distructDNSSDThreadedAhvaiClient" +
"(&" + ctx.getInstanceVarName() + "->avahi_client);\n");
builder.append("}\n\n");
builder.append("void ");
builder.append(thing.getName() + "_add_dnssd_service");
ctx.appendFormalParametersEmptyHandler(thing, builder);
builder.append("{\n");
builder.append(ctx.getInstanceVarName() + "->service_data = " +
plugin.getProtocolName() + "_constructDNSSDAvahiService();\n");
builder.append(ctx.getInstanceVarName() + "->service_data->fn_srv_publish_success_callback = " +
publish_success_callback.keySet().iterator().next() + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->fn_srv_unpublish_success_callback = " +
unpublish_success_callback.keySet().iterator().next() + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->fn_srv_failure_callback = " +
publish_failure_callback.keySet().iterator().next() + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->name = " +
ctx.getInstanceVarName() + "->" +ctx.getCVarName(propertyMap.get(DNSSDUtils.srv_name)) + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->type = " +
ctx.getInstanceVarName() + "->" +ctx.getCVarName(propertyMap.get(DNSSDUtils.srv_type)) + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->port = " +
ctx.getInstanceVarName() + "->" +ctx.getCVarName(propertyMap.get(DNSSDUtils.srv_port)) + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->txt = " +
ctx.getInstanceVarName() + "->" +ctx.getCVarName(propertyMap.get(DNSSDUtils.srv_txt)) + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->host = " +
ctx.getInstanceVarName() + "->" +ctx.getCVarName(propertyMap.get(DNSSDUtils.srv_host)) + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->domain = " +
ctx.getInstanceVarName() + "->" + ctx.getCVarName(propertyMap.get(DNSSDUtils.srv_domain)) + ";\n");
builder.append(ctx.getInstanceVarName() + "->service_data->avahi_client = " +
ctx.getInstanceVarName() + "->avahi_client;\n");
builder.append(plugin.getProtocolName() + "_add_dnssd_service" +
"(" + ctx.getInstanceVarName() + "->service_data);\n");
builder.append("}\n\n");
builder.append("void ");
builder.append(thing.getName() + "_remove_dnssd_service");
ctx.appendFormalParametersEmptyHandler(thing, builder);
builder.append("{\n");
builder.append(plugin.getProtocolName() + "_remove_dnssd_service" +
"(" + ctx.getInstanceVarName() + "->service_data);\n");
builder.append(plugin.getProtocolName() + "_distructDNSSDAvahiService" +
"(&" + ctx.getInstanceVarName() + "->service_data);\n");
builder.append("}\n\n");
}
@Override
protected void generateEntryActions(Thing thing, StringBuilder builder, CCompilerContext ctx, DebugProfile debugProfile) {
builder.append("// Custom behavior for the DNSSD thing. " +
"Generated by " + this.getClass().getSimpleName() + "\n");
if (ThingMLHelpers.allStateMachines(thing).isEmpty()) return;
StateMachine sm = ThingMLHelpers.allStateMachines(thing).get(0);
builder.append("void " + getCppNameScope() + ThingMLElementHelper.qname(sm, "_") + "_OnEntry(int state, ");
builder.append("struct " + ctx.getInstanceStructName(thing) + " *" + ctx.getInstanceVarName() + ") {\n");
builder.append("switch(state) {\n");
//there must be one empty state
CompositeState cs = CompositeStateHelper.allContainedCompositeStatesIncludingSessions(sm).get(0);
builder.append("case " + ctx.getStateID(cs) + ":{\n");
if (debugProfile.isDebugBehavior()) {
builder.append(thing.getName() + "_print_debug(" + ctx.getInstanceVarName() + ", \""
+ ctx.traceOnEntry(thing, sm) + "\\n\");\n");
}
ArrayList<Region> regions = new ArrayList<Region>();
regions.add(cs);
regions.addAll(cs.getRegion());
// Init state
for (Region r : regions) {
if (!r.isHistory()) {
builder.append(ctx.getInstanceVarName() + "->" + ctx.getStateVarName(r) + " = " + ctx.getStateID(r.getInitial()) + ";\n");
}
}
// Execute Entry actions
builder.append(thing.getName() + "_setup");
builder.append("("+ ctx.getInstanceVarName() +");\n");
// Recurse on contained states
for (Region r : regions) {
builder.append(ThingMLElementHelper.qname(sm, "_") + "_OnEntry(" + ctx.getInstanceVarName() + "->" + ctx.getStateVarName(r) + ", " + ctx.getInstanceVarName() + ");\n");
}
State s = CompositeStateHelper.allContainedSimpleStatesIncludingSessions(sm).get(0);
builder.append("break;\n}\n");
builder.append("case " + ctx.getStateID(s) + ":{\n");
if (debugProfile.isDebugBehavior()) {
builder.append(thing.getName() + "_print_debug(" + ctx.getInstanceVarName() + ", \""
+ ctx.traceOnEntry(thing, sm, s) + "\\n\");\n");
}
// Execute Entry actions
builder.append(thing.getName() + "_startup");
builder.append("("+ ctx.getInstanceVarName() +");\n");
builder.append("break;\n}\n");
builder.append("case " + DNSSDUtils.getTerminateStateName(thing) + ":{\n");
if (debugProfile.isDebugBehavior()) {
builder.append(thing.getName() + "_print_debug(" + ctx.getInstanceVarName() + ", \"" +
"Enters custom terminate state of DNSSD"
+ "\\n\");\n");
}
// Execute Entry actions
builder.append(thing.getName() + "_shutdown");
builder.append("("+ ctx.getInstanceVarName() +");\n");
builder.append("break;\n}\n");
builder.append("default: break;\n");
builder.append("}\n");
builder.append("}\n");
}
@Override
protected void generateStateMachineOnExitCPrototypes(Thing thing, StringBuilder builder, CCompilerContext ctx) {
builder.append("// No on exit action for DNSSD. " +
"Generated by " + this.getClass().getSimpleName() + "\n");
}
@Override
protected void generateExitActions(Thing thing, StringBuilder builder, CCompilerContext ctx, DebugProfile debugProfile) {
builder.append("// No on exit action for DNSSD. " +
"Generated by " + this.getClass().getSimpleName() + "\n");
}
}