1 | package com.bowman.cardserv.session;
|
---|
2 |
|
---|
3 | import com.bowman.cardserv.*;
|
---|
4 | import com.bowman.cardserv.cws.CwsConnectorManager;
|
---|
5 | import com.bowman.cardserv.tv.TvService;
|
---|
6 | import com.bowman.cardserv.interfaces.*;
|
---|
7 |
|
---|
8 | import java.net.Socket;
|
---|
9 | import java.util.*;
|
---|
10 | import java.io.IOException;
|
---|
11 |
|
---|
12 | /**
|
---|
13 | * Created by IntelliJ IDEA.
|
---|
14 | * User: bowman
|
---|
15 | * Date: Jan 12, 2010
|
---|
16 | * Time: 4:22:37 PM
|
---|
17 | */
|
---|
18 | public class ExtNewcamdSession extends NewcamdSession implements CwsListener {
|
---|
19 |
|
---|
20 | private Set allowedClients = new HashSet(); // todo
|
---|
21 | private Map sentData = new HashMap();
|
---|
22 |
|
---|
23 | private CardData mainCard;
|
---|
24 | private int mainCaId, mainNetworkId;
|
---|
25 | private Integer[] mergedProviders;
|
---|
26 |
|
---|
27 | public ExtNewcamdSession(Socket conn, ListenPort listenPort, CamdMessageListener listener) {
|
---|
28 | super(conn, listenPort, listener);
|
---|
29 |
|
---|
30 | String mainCaId = listenPort.getStringProperty("main-ca-id");
|
---|
31 | if(mainCaId != null) {
|
---|
32 | this.mainCaId = Integer.parseInt(mainCaId, 16);
|
---|
33 | this.mergedProviders = getProvidersForCaId(this.mainCaId);
|
---|
34 | }
|
---|
35 | initSession();
|
---|
36 | }
|
---|
37 |
|
---|
38 | protected void initSession() {
|
---|
39 | String clients = listenPort.getStringProperty("clients");
|
---|
40 | if(clients != null) allowedClients.addAll(Arrays.asList(clients.split(" ")));
|
---|
41 | String excludeProfiles = listenPort.getStringProperty("exclude-profiles");
|
---|
42 | ProxyConfig config = ProxyConfig.getInstance();
|
---|
43 | mappedProfiles = config.getRealProfiles();
|
---|
44 | if(excludeProfiles != null) {
|
---|
45 | Set excluded = new HashSet(Arrays.asList(excludeProfiles.split(" "))); CaProfile profile;
|
---|
46 | for(Iterator iter = mappedProfiles.iterator(); iter.hasNext(); ) {
|
---|
47 | profile = (CaProfile)iter.next();
|
---|
48 | if(excluded.contains(profile.getName())) iter.remove();
|
---|
49 | }
|
---|
50 | }
|
---|
51 | if(user != null) setupLimits(ProxyConfig.getInstance().getUserManager());
|
---|
52 | }
|
---|
53 |
|
---|
54 | protected Integer[] getProvidersForCaId(int caId) {
|
---|
55 | CaProfile profile; Set providers = new HashSet();
|
---|
56 | for(Iterator iter = mappedProfiles.iterator(); iter.hasNext(); ) {
|
---|
57 | profile = (CaProfile)iter.next();
|
---|
58 | if(profile.getCaId() == caId) providers.addAll(profile.getProviderSet());
|
---|
59 | }
|
---|
60 | return (Integer[])providers.toArray(new Integer[providers.size()]);
|
---|
61 | }
|
---|
62 |
|
---|
63 | protected CamdNetMessage getLoginOkMsg() {
|
---|
64 | CamdNetMessage msg = super.getLoginOkMsg();
|
---|
65 | msg.setServiceId(0x6E73);
|
---|
66 | msg.getFixedData()[9] = 0x14; // newcs protocol version?
|
---|
67 | return msg;
|
---|
68 | }
|
---|
69 |
|
---|
70 | protected boolean handleMessage(CamdNetMessage msg) {
|
---|
71 | switch(msg.getCommandTag()) {
|
---|
72 | case EXT_GET_VERSION:
|
---|
73 | CamdNetMessage versionMsg = new CamdNetMessage(EXT_GET_VERSION);
|
---|
74 | versionMsg.setCustomData("1.67".getBytes());
|
---|
75 | sendMessageNative(versionMsg, msg.getSequenceNr(), true);
|
---|
76 | fireCamdMessage(versionMsg, true);
|
---|
77 | break;
|
---|
78 |
|
---|
79 | case MSG_CARD_DATA_REQ:
|
---|
80 | // if main-ca-id is configured: attempt to merge provider idents for that id as a cccam workaround
|
---|
81 | // if a single au-card can be identified for this user, use that instead of main-ca-id
|
---|
82 | CwsConnector auConn = findAuConnector();
|
---|
83 | CardData card = getAuCardData(auConn);
|
---|
84 | boolean au = true;
|
---|
85 | if(card == null) {
|
---|
86 | card = CardData.createEmptyData(mainCaId);
|
---|
87 | au = false;
|
---|
88 | }
|
---|
89 | if(card.getCaId() == mainCaId && mergedProviders != null) card = CardData.createMergedData(card, mergedProviders);
|
---|
90 |
|
---|
91 | if(au) {
|
---|
92 | mainCard = card;
|
---|
93 | mainNetworkId = auConn.getProfile().getNetworkId();
|
---|
94 | } else mainCard = new CardData(card.getData(true));
|
---|
95 |
|
---|
96 | CamdNetMessage cardDataMsg = new CamdNetMessage(MSG_CARD_DATA);
|
---|
97 | cardDataMsg.setCustomData(card.getData(!au));
|
---|
98 | sendMessageNative(cardDataMsg, msg.getSequenceNr(), true);
|
---|
99 | fireCamdMessage(cardDataMsg, true);
|
---|
100 | logger.fine("Sent card-data: " + card);
|
---|
101 |
|
---|
102 | sentData.clear();
|
---|
103 | Map map = getProfileMap(); CaidProviderPair pair;
|
---|
104 | for(Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
|
---|
105 | pair = (CaidProviderPair)iter.next();
|
---|
106 | sendAddCardData(msg.getSequenceNr(), pair, (CaProfile)map.get(pair));
|
---|
107 | }
|
---|
108 | ProxyConfig.getInstance().getConnManager().addCwsListener(this);
|
---|
109 |
|
---|
110 | logger.fine("Sent extended state: " + sentData);
|
---|
111 | if(sentData.isEmpty()) logger.warning("No extended data available for user '" + user + "' (no provider-idents currently associated with any active and allowed profiles).");
|
---|
112 | break;
|
---|
113 |
|
---|
114 | default:
|
---|
115 | return handleNewcamd(msg);
|
---|
116 | }
|
---|
117 | return true;
|
---|
118 | }
|
---|
119 |
|
---|
120 | void endSession() {
|
---|
121 | ProxyConfig.getInstance().getConnManager().removeCwsListener(this);
|
---|
122 | super.endSession();
|
---|
123 | }
|
---|
124 |
|
---|
125 | private CwsConnector findAuConnector() {
|
---|
126 | ProxyConfig config = ProxyConfig.getInstance();
|
---|
127 | CwsConnectorManager cm = config.getConnManager(); List connectors = new ArrayList(); CwsConnector cws;
|
---|
128 | for(Iterator iter = config.getRealProfiles().iterator(); iter.hasNext(); ) {
|
---|
129 | cws = cm.getConnectorForAU(((CaProfile)iter.next()).getName(), user);
|
---|
130 | if(cws != null) connectors.add(cws);
|
---|
131 | }
|
---|
132 | if(connectors.size() > 1) {
|
---|
133 | logger.warning("AU-user '" + user + "' assigned for multiple active connectors: " + connectors + " (only " +
|
---|
134 | connectors.get(0) + " is likely to receive the correct updates)");
|
---|
135 | } else if(connectors.isEmpty()) return null;
|
---|
136 |
|
---|
137 | return (CwsConnector)connectors.get(0);
|
---|
138 | }
|
---|
139 |
|
---|
140 | protected void sendAddCardData(int seqNr, CaidProviderPair pair, CaProfile profile) {
|
---|
141 | CamdNetMessage addMsg = new CamdNetMessage(EXT_ADD_CARD);
|
---|
142 | addMsg.setServiceId(listenPort.getPort()); // sid field used for portnumber
|
---|
143 | addMsg.setCaIdInHdr(pair.caId);
|
---|
144 | addMsg.setProviderInHdr(pair.providerIdent);
|
---|
145 | sendMessageNative(addMsg, seqNr, true);
|
---|
146 | sentData.put(pair, profile);
|
---|
147 | fireCamdMessage(addMsg, true);
|
---|
148 | }
|
---|
149 |
|
---|
150 | protected void sendRemoveCardData(int seqNr, CaidProviderPair pair) {
|
---|
151 | CamdNetMessage delMsg = new CamdNetMessage(EXT_REMOVE_CARD);
|
---|
152 | delMsg.setServiceId(listenPort.getPort()); // sid field used for portnumber
|
---|
153 | delMsg.setCaIdInHdr(pair.caId);
|
---|
154 | delMsg.setProviderInHdr(pair.providerIdent);
|
---|
155 | sendMessageNative(delMsg, seqNr, true);
|
---|
156 | sentData.remove(pair);
|
---|
157 | fireCamdMessage(delMsg, true);
|
---|
158 | }
|
---|
159 |
|
---|
160 | protected boolean profileAllowed(CaProfile profile) {
|
---|
161 | Set allowed = ProxyConfig.getInstance().getUserManager().getAllowedProfiles(user);
|
---|
162 | return allowed == null || allowed.isEmpty() || allowed.contains(profile.getName());
|
---|
163 | }
|
---|
164 |
|
---|
165 | CamdNetMessage readMessage() throws IOException {
|
---|
166 | // add extended info to msg and identify network id
|
---|
167 | CamdNetMessage msg = super.readMessage();
|
---|
168 | if(msg != null) {
|
---|
169 | if(msg.isEcm()) {
|
---|
170 | msg.setProviderIdent(msg.getProviderFromHdr());
|
---|
171 | msg.setCaId(msg.getCaIdFromHdr());
|
---|
172 | msg.setNetworkId(-1);
|
---|
173 |
|
---|
174 | CaidProviderPair pair = new CaidProviderPair(msg.getCaId(), msg.getProviderIdent());
|
---|
175 | if(!sentData.containsKey(pair))
|
---|
176 | logger.warning("User '" + user + "' sent request for ca-id/provider-ident not previously communicated: " + pair);
|
---|
177 | else msg.setNetworkId(((CaProfile)sentData.get(pair)).getNetworkId());
|
---|
178 | } else if(msg.isEmm()) {
|
---|
179 | if(mainCard != null) {
|
---|
180 | msg.setCaId(mainCard.getCaId());
|
---|
181 | msg.setProviderIdent(msg.getProviderFromHdr());
|
---|
182 |
|
---|
183 | CaidProviderPair pair = new CaidProviderPair(mainCard.getCaId(), msg.getProviderIdent());
|
---|
184 | if(!sentData.containsKey(pair)) {
|
---|
185 | // not able to determine profile target for emm based on caid and ident in header (probably normal, no ident associated with emms?)
|
---|
186 | // obtain profile from the card data context instead
|
---|
187 | msg.setNetworkId(mainNetworkId);
|
---|
188 | } else msg.setNetworkId(((CaProfile)sentData.get(pair)).getNetworkId());
|
---|
189 | }
|
---|
190 | }
|
---|
191 | }
|
---|
192 | return msg;
|
---|
193 | }
|
---|
194 |
|
---|
195 | private Map getProfileMap() {
|
---|
196 | Map map = new HashMap();
|
---|
197 |
|
---|
198 | CaProfile profile; CaidProviderPair record;
|
---|
199 | for(Iterator iter = mappedProfiles.iterator(); iter.hasNext(); ) {
|
---|
200 | profile = (CaProfile)iter.next();
|
---|
201 | if(profile.getNetworkId() > 0 && profile.getCaId() > 0) { // only present those profiles that have onid/caid set - todo
|
---|
202 | if(profileAllowed(profile)) { // and only if the user has access to them
|
---|
203 | Integer[] pi = profile.getProviderIdents();
|
---|
204 | for(int i = 0; i < pi.length; i++) {
|
---|
205 | record = new CaidProviderPair(profile.getCaId(), pi[i].intValue());
|
---|
206 | if(!map.containsKey(record)) {
|
---|
207 | map.put(record, profile);
|
---|
208 | } else {
|
---|
209 | logger.warning("Ambigious situation - [" + record + "] (profile: " + profile.getName() +
|
---|
210 | ") clashes with profile: " + ((CaProfile)map.get(record)).getName() +
|
---|
211 | " (both profiles can't be assigned to the same extended-newcamd port)");
|
---|
212 | }
|
---|
213 | }
|
---|
214 |
|
---|
215 | }
|
---|
216 | }
|
---|
217 | }
|
---|
218 | return map;
|
---|
219 | }
|
---|
220 |
|
---|
221 | private void updateSentState(Map map) {
|
---|
222 | CaidProviderPair key;
|
---|
223 | for(Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
|
---|
224 | key = (CaidProviderPair)iter.next();
|
---|
225 | if(!sentData.containsKey(key)) {
|
---|
226 | sendAddCardData(-1, key, (CaProfile)map.get(key)); // no previous mapping
|
---|
227 | logger.fine("New mapping: " + key + " -> " + map.get(key));
|
---|
228 | } else {
|
---|
229 | if(sentData.get(key) != map.get(key)) {
|
---|
230 | logger.fine("Mapping change: " + key + " -> " + map.get(key) + " (was: " + sentData.get(key) + ")");
|
---|
231 | sentData.put(key, map.get(key)); // change previous mapping, no need to send anything
|
---|
232 | }
|
---|
233 | // else no change
|
---|
234 | }
|
---|
235 | }
|
---|
236 | for(Iterator iter = new ArrayList(sentData.keySet()).iterator(); iter.hasNext(); ) {
|
---|
237 | key = (CaidProviderPair)iter.next();
|
---|
238 | if(!map.containsKey(key)) {
|
---|
239 | logger.fine("Mapping removed: " + key + " -> " + sentData.get(key));
|
---|
240 | sendRemoveCardData(-1, key); // mapping disappeared
|
---|
241 | }
|
---|
242 | }
|
---|
243 | }
|
---|
244 |
|
---|
245 | public String getProtocol() {
|
---|
246 | return "ExtNewcamd";
|
---|
247 | }
|
---|
248 |
|
---|
249 | public String getLastContext() {
|
---|
250 | if(mainCard == null) return "?";
|
---|
251 | else return mainCard.toString();
|
---|
252 | }
|
---|
253 |
|
---|
254 | public void cwsConnected(CwsConnector cws) {
|
---|
255 | updateSentState(getProfileMap());
|
---|
256 | }
|
---|
257 |
|
---|
258 | public void cwsDisconnected(CwsConnector cws) {
|
---|
259 | updateSentState(getProfileMap());
|
---|
260 | }
|
---|
261 |
|
---|
262 | public void cwsConnectionFailed(CwsConnector cws, String message) {}
|
---|
263 | public void cwsEcmTimeout(CwsConnector cws, String message, int failureCount) {}
|
---|
264 | public void cwsLostService(CwsConnector cws, TvService service, boolean show) {}
|
---|
265 | public void cwsFoundService(CwsConnector cws, TvService service, boolean show) {}
|
---|
266 | public void cwsInvalidCard(CwsConnector cws, String message) {}
|
---|
267 |
|
---|
268 | public void cwsProfileChanged(CaProfile profile, boolean added) {
|
---|
269 | initSession();
|
---|
270 | updateSentState(getProfileMap());
|
---|
271 | }
|
---|
272 | }
|
---|