/** * Copyright 2013-2015 Seagate Technology LLC. * * This Source Code Form is subject to the terms of the Mozilla * Public License, v. 2.0. If a copy of the MPL was not * distributed with this file, You can obtain one at * https://mozilla.org/MP:/2.0/. * * This program is distributed in the hope that it will be useful, * but is provided AS-IS, WITHOUT ANY WARRANTY; including without * the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or * FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public * License for more details. * * See www.openkinetic.org for more project information */ package com.seagate.kinetic.simulator.internal; import java.security.Key; import java.util.logging.Level; import java.util.logging.Logger; import com.google.protobuf.ByteString; import com.seagate.kinetic.common.lib.Hmac; import com.seagate.kinetic.common.lib.KineticMessage; import com.seagate.kinetic.proto.Kinetic.Command; import com.seagate.kinetic.proto.Kinetic.Command.MessageType; import com.seagate.kinetic.proto.Kinetic.Command.PinOperation.PinOpType; import com.seagate.kinetic.proto.Kinetic.Command.Status.StatusCode; import com.seagate.kinetic.proto.Kinetic.Message; import com.seagate.kinetic.proto.Kinetic.Message.AuthType; import com.seagate.kinetic.simulator.internal.handler.ServiceException; import com.seagate.kinetic.simulator.lib.HeaderOp; /** * Request context is a container that encapsulate each request information to * process the request command. * * @author chiaming * */ public class RequestContext { private final static Logger logger = Logger.getLogger(RequestContext.class .getName()); // simulator engine private SimulatorEngine engine = null; // response message private KineticMessage request = null; // create response message private KineticMessage response = null;; // response command builder private Command.Builder commandBuilder = null;; // response message builder private Message.Builder messageBuilder = null; // user identity for this message private long userId = -1; // get user key private Key key = null;; private MessageType mtype = null;; /** * The constructor. * * @param engine * simulator engine. * * @param request * request message */ public RequestContext(SimulatorEngine engine, KineticMessage request) { this.engine = engine; this.request = request; this.init(); } /** * Get request message for this context. * * @return request message for this context */ public KineticMessage getRequestMessage() { return this.request; } /** * Get response message for this context. * * @return response message for this context. */ public KineticMessage getResponseMessage() { return this.response; } /** * Get message type for this request. * * @return message type for this request */ public MessageType getMessageType() { return this.mtype; } /** * Get user Id for this request message. * * @return user Id for this request. */ public long getUserId() { return this.userId; } /** * Get user key for this request message. * * @return user key for this request message. */ public Key getUserKey() { return this.key; } /** * Get response command builder for this context. * * @return response command builder for this context. */ public Command.Builder getCommandBuilder() { return this.commandBuilder; } /** * Get response message builder for this context. * * @return response message builder for this context. */ public Message.Builder getMessgeBuilder() { return this.messageBuilder; } /** * initialize context for this request message. * */ private void init() { // create response message response = createKineticMessageWithBuilder(); // get response command builder commandBuilder = (Command.Builder) response.getCommand(); // get response message builder messageBuilder = (Message.Builder) response.getMessage(); // get user id for this request userId = request.getMessage().getHmacAuth().getIdentity(); // get key for this request key = this.engine.getHmacKeyMap().get(Long.valueOf(userId)); // get message type for this request mtype = request.getCommand().getHeader().getMessageType(); if (request.getIsBatchMessage()) { response.setIsBatchMessage(true); } } /** * Create an internal message with empty builder message. * * @return an internal message with empty builder message */ public static KineticMessage createKineticMessageWithBuilder() { // new instance of internal message KineticMessage kineticMessage = new KineticMessage(); // new builder message Message.Builder message = Message.newBuilder(); // set to im kineticMessage.setMessage(message); // set hmac auth type message.setAuthType(AuthType.HMACAUTH); // create command builder Command.Builder commandBuilder = Command.newBuilder(); // set command kineticMessage.setCommand(commandBuilder); return kineticMessage; } /** * Pre process the request message. * * @throws Exception * if any internal error occurred. */ public void preProcessRequest() throws Exception { HeaderOp.checkHeader(this.request, this.response, key, this.engine); checkDeviceLocked(); } /** * check if the device is locked. * * @param kmreq * @param kmresp * @throws DeviceLockedException */ private void checkDeviceLocked() throws DeviceLockedException { if (this.engine.getDeviceLocked() == false) { return; } PinOpType pinOpType = request.getCommand().getBody().getPinOp() .getPinOpType(); if (pinOpType != PinOpType.UNLOCK_PINOP && pinOpType != PinOpType.LOCK_PINOP) { // set device locked status code commandBuilder.getStatusBuilder().setCode(StatusCode.DEVICE_LOCKED); // set status message commandBuilder.getStatusBuilder().setStatusMessage( "Device is locked"); throw new DeviceLockedException(); } } /** * Process the request message within the current context. * * @throws ServiceException * if any internal error occurred. */ public void processRequest() throws ServiceException { // dispatch to handler to process the request this.engine.getCommandManager().getHandler(this.mtype) .processRequest(request, response); } /** * Post process the request message. */ public void postProcessRequest() { this.finalizeResponseMessage(); } /** * Finalize the response message. * */ private void finalizeResponseMessage() { try { // get command byte stirng ByteString commandByteString = commandBuilder.build() .toByteString(); // get command byte[] byte[] commandByte = commandByteString.toByteArray(); // require Hmac calculation ? if (request.getMessage().getAuthType() == AuthType.HMACAUTH) { // calculate hmac ByteString hmac = Hmac.calc(commandByte, key); // set identity messageBuilder.getHmacAuthBuilder().setIdentity(userId); // set hmac messageBuilder.getHmacAuthBuilder().setHmac(hmac); } // set command bytes messageBuilder.setCommandBytes(commandByteString); } catch (Exception e) { logger.log(Level.WARNING, e.getMessage(), e); } } }