package com.rayo.server; import java.net.URI; import java.util.Map; import org.apache.log4j.MDC; import com.rayo.core.CallRef; import com.rayo.core.DialCommand; import com.rayo.core.JoinCommand; import com.rayo.server.admin.AdminService; import com.voxeo.logging.Loggerf; import com.voxeo.moho.ApplicationContext; import com.voxeo.moho.Call; import com.voxeo.moho.CallableEndpoint; import com.voxeo.moho.Endpoint; import com.voxeo.moho.IncomingCall; import com.voxeo.moho.event.AcceptableEvent.Reason; public class CallManager extends ReflectiveActor { private static final Loggerf log = Loggerf.getLogger(CallManager.class); private CallRegistry callRegistry; private CallActorFactory callActorFactory; private ApplicationContext applicationContext; private CdrManager cdrManager; private AdminService adminService; private CallStatistics callStatistics; private boolean removeUserPhoneParameter; // Calls // ================================================================================ @Message public CallRef onDial(DialCommand command) throws Exception { log.info("Dialing [%s]", command.getTo()); CallableEndpoint toEndpoint = (CallableEndpoint) applicationContext.createEndpoint(command.getTo().toString()); URI from = command.getFrom(); Endpoint fromEndpoint = null; if(from != null) { fromEndpoint = applicationContext.createEndpoint(from.toString()); } log.debug("Creating call to [%s] from [%s]", toEndpoint, fromEndpoint); final Call mohoCall = toEndpoint.createCall(fromEndpoint, command.getHeaders()); MDC.put("CallID", mohoCall.getId()); log.debug("Call to [%s] from [%s] created successfully", toEndpoint, fromEndpoint); if (command.getJoin() != null) { log.debug("Nested join operation detected. Setting join parameters [%s]", command.getJoin()); if (command.getJoin().getMedia() != null) { mohoCall.setAttribute(JoinCommand.MEDIA_TYPE, command.getJoin().getMedia()); } if (command.getJoin().getDirection() != null) { mohoCall.setAttribute(JoinCommand.DIRECTION, command.getJoin().getDirection()); } if (command.getJoin().getTo() != null) { mohoCall.setAttribute(JoinCommand.TO, command.getJoin().getTo()); mohoCall.setAttribute(JoinCommand.TYPE, command.getJoin().getType()); } if (command.getJoin().getForce() != null) { mohoCall.setAttribute(JoinCommand.FORCE, command.getJoin().getForce()); } else { mohoCall.setAttribute(JoinCommand.FORCE, Boolean.FALSE); } } CallActor<?> callActor = createCallActor(mohoCall); callActor.publish(mohoCall); log.debug("Call actor started for call [%s]", mohoCall.getId()); return new CallRef(mohoCall.getId()); } @Message public void onIncomingCall(IncomingCall mohoCall) { log.info("Incoming Call [%s]", mohoCall); if (adminService.isQuiesceMode()) { log.warn("Quiesce Mode ON. Dropping incoming call: %s", mohoCall.getId()); callStatistics.callRejected(); callStatistics.callBusy(); mohoCall.reject(Reason.BUSY); return; } CallActor<?> callActor = createCallActor(mohoCall); callActor.publish(mohoCall); } public CallActor<?> createCallActor(URI to, URI from, Map<String, String> headers, Call source) { log.info("Creating call to [%s] from [%s]", to, from); String destination = to.toString(); if (removeUserPhoneParameter && destination.contains(";user=phone")) { log.debug("Removing user=phone from to's URI"); destination = destination.replaceAll(";user=phone", ""); } CallableEndpoint toEndpoint = (CallableEndpoint) applicationContext.createEndpoint(destination); Endpoint fromEndpoint = null; if(from != null) { fromEndpoint = applicationContext.createEndpoint(from.toString()); } log.debug("Creating moho call to [%s] from [%s]", toEndpoint, fromEndpoint); final Call mohoCall = toEndpoint.createCall(fromEndpoint, headers, source); MDC.put("CallID", mohoCall.getId()); return createCallActor(mohoCall); } public CallActor<?> createCallActor(final Call mohoCall) { // Store the CDR cdrManager.create(mohoCall); if(getEventHandlers().isEmpty()) { log.warn("If an INVITE arrives and noone's there to handle it; does it make a sound? [call=%s]", mohoCall); mohoCall.disconnect(); } // Construct Actor CallActor<?> callActor = callActorFactory.create(mohoCall); callActor.start(); // Wire up default call handlers for (EventHandler handler : getEventHandlers()) { callActor.addEventHandler(handler); } // Register Call callRegistry.add(callActor); // Link to actor callActor.link(new ActorLink() { @Override public void postStop() { log.info("Call cleanup [call=%s]", mohoCall); callRegistry.remove(mohoCall.getId()); } }); return callActor; } // Properties // ================================================================================ public ApplicationContext getApplicationContext() { return applicationContext; } public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public CallRegistry getCallRegistry() { return callRegistry; } public void setCallRegistry(CallRegistry registry) { this.callRegistry = registry; } public void setCallActorFactory(CallActorFactory callActorFactory) { this.callActorFactory = callActorFactory; } public CallActorFactory getCallActorFactory() { return callActorFactory; } public void setCdrManager(CdrManager cdrManager) { this.cdrManager = cdrManager; } public void setAdminService(AdminService adminService) { this.adminService = adminService; } public void setCallStatistics(CallStatistics callStatistics) { this.callStatistics = callStatistics; } public void setRemoveUserPhoneParameter(boolean removeUserPhoneParameter) { this.removeUserPhoneParameter = removeUserPhoneParameter; } }