package com.jcumulus.server.rtmfp;
/**
* jCumulus is a Java port of Cumulus OpenRTMP
*
* Copyright 2011 OpenRTMFP
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License received along this program for more
* details (or else see http://www.gnu.org/licenses/).
*
*
* This file is a part of jCumulus.
*/
import com.jcumulus.server.rtmfp.client.*;
import com.jcumulus.server.rtmfp.packet.*;
import com.jcumulus.server.rtmfp.pipe.C;
import com.jcumulus.server.rtmfp.publisher.E;
import com.jcumulus.server.rtmfp.publisher.F;
import com.jcumulus.server.rtmfp.stream.B;
import com.google.common.base.Strings;
import java.net.SocketAddress;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.jboss.netty.channel.Channel;
public class ServerSession implements ISession
{
private static final Logger J = Logger.getLogger(ServerSession.class);
int O;
int D;
protected Peer M;
boolean I;
boolean F;
byte H;
K S;
K K;
protected final B N;
Channel Q;
com.jcumulus.server.rtmfp.pipe.B G;
short A;
boolean U;
int B;
int E;
Map L;
com.jcumulus.server.rtmfp.publisher.FlowWriter R;
int P;
Map C;
Map T;
public ServerSession(int i, int j, byte abyte0[], byte abyte1[])
{
this(i, j, abyte0, abyte1, new Peer());
}
public ServerSession(int i, int j, byte abyte0[], byte abyte1[], Peer p)
{
N = new B();
G = new com.jcumulus.server.rtmfp.pipe.B();
A = 0;
U = false;
L = new HashMap();
P = 1;
C = new HashMap();
T = new HashMap();
H = 0;
F = false;
I = false;
O = i;
D = j;
M = p;
M.A(new ClientHandler());
S = new K(abyte0, com.jcumulus.server.rtmfp.K.Encryption.DECRYPT);
K = new K(abyte1, com.jcumulus.server.rtmfp.K.Encryption.ENCRYPT);
N.E(11);
N.C(com.jcumulus.server.rtmfp.N.G);
}
public I A(byte abyte0[])
{
I i = (I)T.get(abyte0);
if(i == null)
{
i = new I();
T.put(abyte0, i);
}
return i;
}
public void A(Channel channel, SocketAddress socketaddress)
{
Q = channel;
M.A(socketaddress);
}
public void A(AudioPacket a)
{
if(!com.jcumulus.server.rtmfp.N.A(S, a))
{
J.error((new StringBuilder()).append("Decrypt error on session ").append(O).toString());
return;
} else
{
B(a);
return;
}
}
protected void A(B b)
{
if(Q == null)
{
J.error((new StringBuilder()).append("Impossible to send on a null socket for session ").append(O).toString());
return;
}
B b1 = com.jcumulus.server.rtmfp.N.A(K, b);
if(b1 != null)
{
com.jcumulus.server.rtmfp.N.A(b1, D);
Q.write(b1.E(), M.L());
}
}
public boolean A(com.jcumulus.server.rtmfp.publisher.FlowWriter h)
{
return R == h;
}
public void B(com.jcumulus.server.rtmfp.publisher.FlowWriter h)
{
while(++P == 0 || C.get(Integer.valueOf(P)) != null) ;
h.B(P);
if(L.size() > 0)
h.C(((E[])L.values().toArray(new E[L.size()]))[0].D());
C.put(Integer.valueOf(P), h);
}
public com.jcumulus.server.rtmfp.stream.B A(byte paramByte, int paramInt, com.jcumulus.server.rtmfp.publisher.FlowWriter paramH)
{
if (this.U)
synchronized (this.N)
{
this.N.B(11);
this.N.C(this.N.C());
return this.N;
}
this.R = paramH;
int i = paramInt + 3;
if (i > this.N.D())
{
A(false);
if (i > this.N.D())
{
J.error("Message truncated because exceeds maximum UDP packet size on session " + this.O);
i = this.N.D();
}
this.R = null;
}
synchronized (this.N)
{
this.N.C(this.N.C() + i);
this.N.B(paramByte);
this.N.A((short)paramInt);
return this.N;
}
}
private void D()
{
if(F)
return;
B++;
synchronized(N)
{
N.B((byte)12);
N.A((short)0);
}
A(false);
if(B == 10 || G.A(0x15752a00L))
C();
}
private void A(String s)
{
if(U)
return;
synchronized(N)
{
N.B(11);
}
Integer integer;
for(Iterator iterator = C.keySet().iterator(); iterator.hasNext(); ((com.jcumulus.server.rtmfp.publisher.FlowWriter)C.get(integer)).I())
integer = (Integer)iterator.next();
this.M.A((com.jcumulus.server.rtmfp.publisher.FlowWriter)null);
this.M.J();
this.U = true;
if(!Strings.isNullOrEmpty(s))
{
J.warn((new StringBuilder()).append("Session failed id : ").append(s).toString());
M.E(s);
D();
}
}
public void C()
{
if(F)
return;
M.O();
M.C();
U = true;
M.A((com.jcumulus.server.rtmfp.publisher.FlowWriter)null);
M.J();
E e;
for(Iterator iterator = L.values().iterator(); iterator.hasNext(); e.C())
e = (E)iterator.next();
L.clear();
com.jcumulus.server.rtmfp.publisher.FlowWriter h;
for(Iterator iterator1 = C.values().iterator(); iterator1.hasNext(); h.F())
h = (com.jcumulus.server.rtmfp.publisher.FlowWriter)iterator1.next();
C.clear();
F = true;
J.info((new StringBuilder()).append("Session ").append(O).append(" died").toString());
}
protected void B(AudioPacket a)
{
if(F)
return;
if(!U && M.K())
A("");
if(M.N().size() == 0)
{
J.error((new StringBuilder()).append("Session ").append(O).append(" has no any addresses!").toString());
M.N().add(M.L().toString());
}
G.A();
byte byte0 = (byte)(a.L() | 0xfffffff0);
A = a.E();
if(byte0 == -3)
{
short word0 = com.jcumulus.server.rtmfp.N.A(G.getTime());
short word1 = a.E();
M.A((short)(word1 <= word0 ? word0 - word1 : 0));
} else
if(byte0 != -7)
J.warn("Packet marker unknown : marker");
byte byte1 = 0;
E e = null;
int i = 0;
int j = 0;
byte byte2 = a.I() <= 0 ? -1 : a.L();
boolean flag = false;
do
{
if(byte2 == -1)
break;
short word2 = a.E();
AudioPacket a1 = new AudioPacket(a.G(), word2);
switch(byte2)
{
case 112: // 'p'
break;
case 12: // '\f'
A("failed on client side");
break;
case 76: // 'L'
C();
return;
case 1: // '\001'
if(!M.M())
A("Timeout connection client");
else
A((byte)65, 0, null);
// fall through
case 65: // 'A'
E = 0;
break;
case 94: // '^'
int k = a1.J();
com.jcumulus.server.rtmfp.publisher.FlowWriter h = (com.jcumulus.server.rtmfp.publisher.FlowWriter)C.get(Integer.valueOf(k));
if(h != null)
h.D((new StringBuilder()).append("FlowWriter rejected on session ").append(O).toString());
else
J.warn((new StringBuilder()).append("FlowWriter ").append(k).append(" unfound for failed signal on session ").append(O).toString());
break;
case 24: // '\030'
A("ack negative from server");
break;
case 81: // 'Q'
int l = a1.J();
com.jcumulus.server.rtmfp.publisher.FlowWriter h1 = (com.jcumulus.server.rtmfp.publisher.FlowWriter)C.get(Integer.valueOf(l));
if(h1 != null)
h1.A(a1);
else
J.warn((new StringBuilder()).append("FlowWriter ").append(l).append(" unfound for acknowledgment on session").append(O).toString());
break;
case 16: // '\020'
byte1 = a1.L();
int i1 = a1.J();
i = a1.J() - 1;
j = a1.J() - 1;
if(U)
break;
e = (E)L.get(Integer.valueOf(i1));
if((byte1 & com.jcumulus.server.rtmfp.publisher.E.N.intValue()) != 0)
{
byte abyte0[] = a1.F(a1.L() & 0xff);
if(e == null)
e = A(i1, abyte0);
if(a1.L() > 0)
{
if(a1.L() != 10)
J.warn((new StringBuilder()).append("Unknown fullduplex header part for the flow '").append(i1).append("'").toString());
else
a1.J();
byte byte3;
for(byte3 = a1.L(); byte3 > 0 && a1.I() > 0; byte3 = a1.L())
{
J.warn((new StringBuilder()).append("Unknown message part on flow '").append(i1).append("'").toString());
a1.D(byte3);
}
if(byte3 > 0)
J.error("Bad header message part, finished before scheduled");
}
}
if(e == null)
J.warn((new StringBuilder()).append("Flow ").append(i1).append(" unfound").toString());
// fall through
case 17: // '\021'
i++;
j++;
if(byte2 == 17)
byte1 = a1.L();
if(e == null)
break;
e.A(i, j, a1, byte1);
if(!Strings.isNullOrEmpty(e.G()) || M.K())
{
A(e.G());
e = null;
}
break;
default:
J.error((new StringBuilder()).append("Message type '").append(byte2).append("' unknown").toString());
break;
}
a.D(word2);
byte2 = a.I() <= 0 ? -1 : a.L();
if(e != null && byte2 != 17)
{
e.F();
if(e.B())
L.remove(Integer.valueOf(e.D()));
e = null;
}
} while(true);
A((byte)74, true);
}
private E A(int i, byte abyte0[])
{
if(F)
{
J.error((new StringBuilder()).append("Session ").append(i).append(" is died, no more Flow creation possible").toString());
return null;
}
Object obj = (E)L.get(Integer.valueOf(i));
if(obj != null)
{
J.warn((new StringBuilder()).append("Flow ").append(i).append(" has already been created").toString());
return ((E) (obj));
}
if(com.jcumulus.server.rtmfp.pipe.C.B(abyte0, com.jcumulus.server.rtmfp.publisher.F.S))
obj = new F(i, M, this);
else
if(com.jcumulus.server.rtmfp.pipe.C.B(abyte0, com.jcumulus.server.rtmfp.publisher.C.Q))
obj = new com.jcumulus.server.rtmfp.publisher.C(i, M, this);
else
if(com.jcumulus.server.rtmfp.pipe.C.A(com.jcumulus.server.rtmfp.publisher.A.Z, abyte0))
obj = new com.jcumulus.server.rtmfp.publisher.A(i, abyte0, M, this);
else
J.error((new StringBuilder()).append("New unknown flow '").append(Arrays.toString(abyte0)).append("' on session ").append(O).toString());
if(obj != null)
{
J.debug((new StringBuilder()).append("New flow ").append(i).append(" on session ").append(O).toString());
L.put(Integer.valueOf(i), obj);
}
return ((E) (obj));
}
public void A(boolean flag)
{
A((byte)74, flag);
}
protected void A(byte byte0, boolean flag)
{
R = null;
if(F)
return;
if(N.A() >= com.jcumulus.server.rtmfp.N.C)
{
if(G.A(0x1c9c380L))
flag = false;
byte byte1 = 0;
if(flag)
byte0 += 4;
else
byte1 = 2;
B b1;
synchronized(N)
{
b1 = N.F();
N.B(11);
N.C(com.jcumulus.server.rtmfp.N.G);
}
if(b1 != null)
{
b1.C(0);
b1.G(byte1);
b1.F(6);
b1.B(byte0);
b1.A(com.jcumulus.server.rtmfp.N.A());
if(flag)
b1.A((short)(A + com.jcumulus.server.rtmfp.N.A(G.B())));
A(b1);
}
}
}
public boolean A()
{
return U;
}
public B B()
{
N.C(com.jcumulus.server.rtmfp.N.G);
return N;
}
}