package net.floodlightcontroller.qos; import java.io.IOException; import java.util.Iterator; import java.util.List; import net.floodlightcontroller.qos.IQoSService; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonToken; import org.codehaus.jackson.map.MappingJsonFactory; import org.restlet.resource.Delete; import org.restlet.resource.Post; import org.restlet.resource.Get; import org.restlet.resource.ServerResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Copyright 2012 Marist College, New York * Author Ryan Wallner (ryan.wallner1@marist.edu) * * 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. * * Implementation adopted from Firewall */ public class QoSTypeOfServiceResource extends ServerResource { public static Logger logger = LoggerFactory.getLogger(QoSTypeOfServiceResource.class); /** * Get list of services * @return */ @Get("json") public Object handleRequest(){ IQoSService qos = (IQoSService)getContext().getAttributes(). get(IQoSService.class.getCanonicalName()); String status = null; if(qos.isEnabled()){ // gets the list of policies currently being implemented return qos.getServices(); } else{ status = "Please enable Quality of Service"; return ("{\"status\" : \"" + status + "\"}"); } } /** * * @param tosJson The qos policy entry in JSON format. * @return A string status message */ @Post public String store(String tosJson) { IQoSService qos = (IQoSService)getContext().getAttributes(). get(IQoSService.class.getCanonicalName()); //dummy service QoSTypeOfService service; try{ service = jsonToService(tosJson); } catch(IOException e){ logger.debug("Error Parsing QoS Service to JSON: {}, Error: {}", tosJson, e); e.printStackTrace(); return "{\"status\" : \"Error! Could not parse Service, see log for details.\"}"; } String status = null; if(checkIfServiceExists(service,qos.getServices())){ status = "Error!, This service already exists!"; logger.error(status); } else{ //Only add if enabled ?needed? if(qos.isEnabled()){ status = "Adding Type Of Service: " + service.name + " " + service.tos; qos.addService(service); } else{ status = "Please enable Quality of Service"; } } return ("{\"status\" : \"" + status + "\"}"); } /** * * @param tosJson * @return */ @Delete public String delete(String tosJson) { IQoSService qos = (IQoSService)getContext().getAttributes(). get(IQoSService.class.getCanonicalName()); //dummy service QoSTypeOfService service; //Accepts just "name": "<Service-Name>" //or the full service object try{ service = jsonToService(tosJson); } catch(IOException e){ logger.debug("Error Parsing QoS Service to JSON: {}, Error: {}", tosJson, e); e.printStackTrace(); return "{\"status\" : \"Error! Could not parse Service, see log for details.\"}"; } String status = null; if(qos.isEnabled()){ boolean found = false; Iterator<QoSTypeOfService> sIter = qos.getServices().iterator(); while(sIter.hasNext()){ QoSTypeOfService s = sIter.next(); if(s.sid == service.sid){ found = true; break; } } if(!found){ status = "Error! Cannot delete a rule with this ID or NAME, does not exist."; logger.error(status); } else{ qos.deleteService(service.sid); status = "Type Of Service Service-ID: "+service.sid+" Deleted"; } } else{ status = "Please enable QoS"; } return ("{\"status\" : \"" + status + "\"}"); } /** * Take in a json POST and turns it into a QoS Service * @param tosJson * @return * @throws IOException */ public static QoSTypeOfService jsonToService(String tosJson) throws IOException { QoSTypeOfService service = new QoSTypeOfService(); MappingJsonFactory jf = new MappingJsonFactory(); JsonParser jp; try{ jp = jf.createJsonParser(tosJson); }catch(JsonParseException e){ throw new IOException(e); } //debug for dev logger.info("JSON Object POSTED is " +jp.toString()); //see if the the current token is '{' to start processing json objects JsonToken tkn = jp.getCurrentToken(); if(tkn != JsonToken.START_OBJECT){ jp.nextToken(); if(jp.getCurrentToken() != JsonToken.START_OBJECT){ throw new IOException("Did not recieve START_OBJECT"); } } while(jp.nextToken() != JsonToken.END_OBJECT){ if (jp.getCurrentToken() != JsonToken.FIELD_NAME){ throw new IOException("Needed a FIELD_NAME token"); } try{ String s = jp.getCurrentName(); jp.nextToken(); //System.out.println("Current text is "+ jp.getText()); //debug for dev if(jp.getText().equals("")){ continue; } //user only needs to specify with remove //when it becomes stored it will get a different id //Reference QoS.java:381 if(s == "sid"){ service.sid = Integer.parseInt(jp.getText()); } else if(s == "name"){ service.name = jp.getText(); } // do not need to check the Byte length 0-64 here, this will be caught // by the addService QoS.java:371 else if(s == "tos"){ //This is so you can enter a binary number or a integer number. //It will be stored as a Byte try{ //Try to get binary number first Integer tmpInt = Integer.parseInt(jp.getText(),2); service.tos = tmpInt.byteValue(); }catch(NumberFormatException e){ logger.debug("Number entered was not binary, processing as int..."); //Must be entered as 0-64 Integer tmpInt = Integer.parseInt(jp.getText()); service.tos = tmpInt.byteValue(); } } }catch(JsonParseException e){ logger.debug("Error getting current FIELD_NAME {}", e); }catch(IOException e){ logger.debug("Error procession Json {}", e); } } return service; } /** * Check * @param service * @param services * @return */ public static boolean checkIfServiceExists(QoSTypeOfService service, List<QoSTypeOfService> services){ Iterator<QoSTypeOfService> iter = services.iterator(); while(iter.hasNext()){ QoSTypeOfService s = iter.next(); //catch if entire service is same or name or bits if(service.isSameAs(s) || service.name.equals(s.name) || service.equals(s.tos) ){ return true; } } return false; } }