Merge "Changed tests to leverage a dynamic port for testing COPS message marshalling...
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / prpdp / COPSPdpMsgSender.java
1 /*
2  * Copyright (c) 2004 University of Murcia.  All rights reserved.
3  * --------------------------------------------------------------
4  * For more information, please see <http://www.umu.euro6ix.org/>.
5  */
6
7 package org.umu.cops.prpdp;
8
9 import org.umu.cops.stack.*;
10 import org.umu.cops.stack.COPSContext.RType;
11 import org.umu.cops.stack.COPSDecision.Command;
12 import org.umu.cops.stack.COPSDecision.DecisionFlag;
13 import org.umu.cops.stack.COPSObjHeader.CType;
14
15 import java.io.IOException;
16 import java.net.Socket;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.Map;
20 import java.util.Set;
21
22 /**
23  * COPS message transceiver class for provisioning connections at the PDP side.
24  *
25  * TODO - Need to continue refactoring by removing all instances of Hashtable (change to Map<>)
26  */
27 public class COPSPdpMsgSender {
28
29     /**
30      * Socket connected to PEP
31      */
32     protected final Socket _sock;
33
34     /**
35      * COPS client-type that identifies the policy client
36      */
37     protected final short _clientType;
38
39     /**
40      * COPS client handle used to uniquely identify a particular
41      * PEP's request for a client-type
42      */
43     protected final COPSHandle _handle;
44
45     /**
46      * Creates a COPSPepMsgSender
47      *
48      * @param clientType        COPS client-type
49      * @param clientHandle      Client handle
50      * @param sock              Socket to the PEP
51      */
52     public COPSPdpMsgSender (final short clientType, final COPSHandle clientHandle, final Socket sock) {
53         // COPS Handle
54         _handle = clientHandle;
55         _clientType = clientType;
56
57         _sock = sock;
58     }
59
60     /**
61      * Gets the client handle
62      * @return   Client's <tt>COPSHandle</tt>
63      */
64     public COPSHandle getClientHandle() {
65         return _handle;
66     }
67
68     /**
69      * Gets the client-type
70      * @return   Client-type value
71      */
72     public short getClientType() {
73         return _clientType;
74     }
75
76     /**
77      * Sends a decision message
78      * @param removeDecs    Decisions to be removed
79      * @param installDecs   Decisions to be installed
80      * @throws COPSPdpException
81      */
82     public void sendDecision(final Map<String, String> removeDecs, Map<String, String> installDecs)
83             throws COPSPdpException {
84         /* <Decision Message> ::= <Common Header: Flag SOLICITED>
85          *                          <Client Handle>
86          *                          *(<Decision>) | <Error>
87          *                          [<Integrity>]
88          * <Decision> ::= <Context>
89          *                  <Decision: Flags>
90          *                  [<Named Decision Data: Provisioning>]
91          * <Decision: Flags> ::= <Command-Code> NULLFlag
92          * <Command-Code> ::= NULLDecision | Install | Remove
93          * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>
94          * <Install Decision> ::= *(<PRID> <EPD>)
95          * <Remove Decision> ::= *(<PRID> | <PPRID>)
96          *
97          * Very important, this is actually being treated like this:
98          * <Install Decision> ::= <PRID> | <EPD>
99          * <Remove Decision> ::= <PRID> | <PPRID>
100          *
101         */
102
103         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
104
105         // Decisions (no flags supplied)
106         //  <Context>
107         final COPSContext cntxt = new COPSContext(RType.CONFIG, (short)0);
108
109         // Remove Decisions
110         //  <Decision: Flags>
111         final COPSDecision rdec1 = new COPSDecision(Command.REMOVE);
112
113         final Set<COPSDecision> decisionSet = new HashSet<>();
114         decisionSet.add(rdec1);
115         decisionMap.put(cntxt, decisionSet);
116
117         for (final Map.Entry<String, String> entry : removeDecs.entrySet()) {
118             //  <Named Decision Data: Provisioning> (PRID)
119             final COPSPrID prid = new COPSPrID();
120             prid.setData(new COPSData(entry.getKey()));
121             final COPSDecision decisionPrid = new COPSDecision(CType.NAMED,
122                     new COPSData(prid.getDataRep(), 0, prid.getDataLength()));
123
124             decisionMap.get(cntxt).add(decisionPrid);
125
126             final COPSPrEPD epd = new COPSPrEPD();
127             final COPSDecision decisionPrepd = new COPSDecision(CType.NAMED,
128                     new COPSData(epd.getDataRep(), 0, epd.getDataLength()));
129
130             decisionMap.get(cntxt).add(decisionPrepd);
131         }
132
133         // Install Decisions
134         //  <Decision: Flags>
135         final COPSDecision idec1 = new COPSDecision(Command.INSTALL);
136         decisionMap.get(cntxt).add(idec1);
137
138         for (final Map.Entry<String, String> entry : installDecs.entrySet()) {
139             //  <Named Decision Data: Provisioning> (PRID)
140             final COPSPrID prid = new COPSPrID();
141             prid.setData(new COPSData(entry.getKey()));
142             final COPSDecision decisionPrid2 = new COPSDecision(CType.NAMED,
143                     new COPSData(prid.getDataRep(), 0, prid.getDataLength()));
144
145             decisionMap.get(cntxt).add(decisionPrid2);
146         }
147
148         // Common Header with the same ClientType as the request
149         // Client Handle with the same clientHandle as the request
150         final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
151                 decisionMap, null);
152
153         //** Send the decision
154         //**
155         try {
156             decisionMsg.writeData(_sock);
157         } catch (IOException e) {
158             throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());
159         }
160     }
161
162     /**
163      * Sends a decision message which was not requested by the PEP
164      * @param removeDecs    Decisions to be removed
165      * @param installDecs   Decisions to be installed
166      * @throws COPSPdpException
167      */
168     public void sendUnsolicitedDecision(final Map<String, String> removeDecs, final Map<String, String> installDecs)
169             throws COPSPdpException {
170         //** Example of an UNSOLICITED decision
171         //**
172
173         /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
174          *                          <Client Handle>
175          *                          *(<Decision>) | <Error>
176          *                          [<Integrity>]
177          * <Decision> ::= <Context>
178          *                  <Decision: Flags>
179          *                  [<Named Decision Data: Provisioning>]
180          * <Decision: Flags> ::= <Command-Code> NULLFlag
181          * <Command-Code> ::= NULLDecision | Install | Remove
182          * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>
183          * <Install Decision> ::= *(<PRID> <EPD>)
184          * <Remove Decision> ::= *(<PRID> | <PPRID>)
185          *
186          * Very important, this is actually being treated like this:
187          * <Install Decision> ::= <PRID> | <EPD>
188          * <Remove Decision> ::= <PRID> | <PPRID>
189          *
190         */
191
192         // Common Header with the same ClientType as the request
193         // Client Handle with the same clientHandle as the request
194         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
195         // Decisions (no flags supplied)
196         //  <Context>
197         final COPSContext cntxt = new COPSContext(RType.CONFIG, (short)0);
198
199         // Remove Decisions
200         //  <Decision: Flags>
201         final Set<COPSDecision> decisionSet = new HashSet<>();
202         decisionSet.add(new COPSDecision(Command.REMOVE));
203         decisionMap.put(cntxt, decisionSet);
204
205         for (final Map.Entry<String, String> entry : removeDecs.entrySet()) {
206             //  <Named Decision Data: Provisioning> (PRID)
207             final COPSPrID prid = new COPSPrID();
208             prid.setData(new COPSData(entry.getKey()));
209             decisionMap.get(cntxt).add(new COPSDecision(CType.NAMED,
210                     new COPSData(prid.getDataRep(), 0, prid.getDataLength())));
211
212             //  <Named Decision Data: Provisioning> (EPD)
213             final COPSPrEPD epd = new COPSPrEPD();
214             epd.setData(new COPSData(entry.getValue()));
215             decisionMap.get(cntxt).add(
216                     new COPSDecision(CType.NAMED, new COPSData(epd.getDataRep(), 0, epd.getDataLength())));
217         }
218
219         // Install Decisions
220         //  <Decision: Flags>
221         decisionMap.get(cntxt).add(new COPSDecision(Command.INSTALL));
222
223         for (final Map.Entry<String, String> entry : installDecs.entrySet()) {
224             //  <Named Decision Data: Provisioning> (PRID)
225             final COPSPrID prid = new COPSPrID();
226             prid.setData(new COPSData(entry.getKey()));
227             decisionMap.get(cntxt).add(new COPSDecision(CType.NAMED,
228                     new COPSData(prid.getDataRep(), 0, prid.getDataLength())));
229
230             final COPSPrEPD epd = new COPSPrEPD();
231             epd.setData(new COPSData(entry.getValue()));
232             decisionMap.get(cntxt).add(
233                     new COPSDecision(CType.NAMED, new COPSData(epd.getDataRep(), 0, epd.getDataLength())));
234         }
235
236         /**
237         COPSIntegrity intr = new COPSIntegrity();
238         intr.setKeyId(19);
239         intr.setSeqNum(9);
240         intr.setKeyDigest(new COPSData("KEY DIGEST"));
241         decisionMsg.add(intr);
242         /**/
243
244         final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
245                 decisionMap, null);
246
247         //** Send the decision
248         //**
249         try {
250             decisionMsg.writeData(_sock);
251         } catch (IOException e) {
252             throw new COPSPdpException("Failed to send the decision, reason: " + e.getMessage());
253         }
254     }
255
256     /**
257      * Sends a message asking that the request state be deleted
258      * @throws   COPSPdpException
259      */
260     public void sendDeleteRequestState() throws COPSPdpException {
261         /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
262          *                          <Client Handle>
263          *                          *(<Decision>)
264          *                          [<Integrity>]
265          * <Decision> ::= <Context>
266          *                  <Decision: Flags>
267          * <Decision: Flags> ::= Remove Request-State
268          *
269         */
270
271         // Decisions
272         //  <Context>
273         //  <Decision: Flags>
274         final COPSDecision dec = new COPSDecision(Command.REMOVE, DecisionFlag.REQSTATE);
275         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
276         final Set<COPSDecision> decisionSet = new HashSet<>();
277         decisionSet.add(dec);
278         decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
279
280         final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
281                 decisionMap, null);
282         try {
283             decisionMsg.writeData(_sock);
284         } catch (IOException e) {
285             throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());
286         }
287     }
288
289     /**
290      * Sends a request asking that a new request state be created
291      * @throws   COPSPdpException
292      */
293     public void sendOpenNewRequestState()
294     throws COPSPdpException {
295         /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
296          *                          <Client Handle>
297          *                          *(<Decision>)
298          *                          [<Integrity>]
299          * <Decision> ::= <Context>
300          *                  <Decision: Flags>
301          * <Decision: Flags> ::= Install Request-State
302          *
303         */
304
305         //  <Decision: Flags>
306         final COPSDecision dec = new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE);
307         final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
308         final Set<COPSDecision> decisionSet = new HashSet<>();
309         decisionSet.add(dec);
310         decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
311
312         final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(_handle.getId()),
313                 decisionMap, null);
314
315         try {
316             decisionMsg.writeData(_sock);
317         } catch (IOException e) {
318             throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());
319         }
320     }
321
322     /**
323      * Sends a message asking for a COPS sync operation
324      * @throws COPSPdpException
325      */
326     public void sendSyncRequestState()
327     throws COPSPdpException {
328         /* <Synchronize State Request>  ::= <Common Header>
329          *                                  [<Client Handle>]
330          *                                  [<Integrity>]
331          */
332
333         final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, new COPSHandle(_handle.getId()), null);
334         try {
335             msg.writeData(_sock);
336         } catch (IOException e) {
337             throw new COPSPdpException("Failed to send the sync state request, reason: " + e.getMessage());
338         }
339     }
340 }