Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fixed some bugs. Apple-Response function rewritten with ByteOutputStr…
…eam (idea from JAirport). Moved libraries in repo.
  • Loading branch information
bencall committed May 3, 2011
1 parent ed7beb7 commit 2a47f62
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 46 deletions.
Binary file modified .DS_Store
Binary file not shown.
8 changes: 0 additions & 8 deletions .classpath

This file was deleted.

3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -8,4 +8,5 @@
/bin/Rplay.class
/bin/UDPDelegate.class
/bin/com/beatofthedrum/alacdecoder/License.txt
/bin/License.txt
/bin/License.txt
/.classpath
File renamed without changes.
Binary file added libs/bcprov-jdk16-146.jar
Binary file not shown.
Binary file added libs/commons-codec-1.5.jar
Binary file not shown.
Binary file added libs/jmdns.jar
Binary file not shown.
14 changes: 10 additions & 4 deletions src/AudioServer.java
Expand Up @@ -22,6 +22,7 @@ public class AudioServer implements UDPDelegate{

// Sockets
private DatagramSocket sock, csock;
UDPListener l1, l2;

// client address
private InetAddress rtpClient;
Expand Down Expand Up @@ -52,6 +53,13 @@ public AudioServer(AudioSession session){
player.start();
}

public void close(){
player.interrupt();
l1.interrupt();
l2.interrupt();
sock.close();
csock.close();
}

public void setVolume(double vol){
player.setVolume(vol);
Expand Down Expand Up @@ -81,10 +89,8 @@ private void initRTP(){
break;
}

@SuppressWarnings("unused")
UDPListener l1 = new UDPListener(sock, this);
@SuppressWarnings("unused")
UDPListener l2 = new UDPListener(csock, this);
l1 = new UDPListener(sock, this);
l2 = new UDPListener(csock, this);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/BonjourEmitter.java
Expand Up @@ -30,7 +30,7 @@ public BonjourEmitter(String name, String identifier, int port) throws DNSSDExce
txtRecord.set("et", "0,1");
txtRecord.set("cn", "0,1");
txtRecord.set("vn", "3");

// Il faut un serial bidon pour se connecter
if (identifier == null){
identifier = "";
Expand Down
66 changes: 43 additions & 23 deletions src/RTSPResponder.java
@@ -1,15 +1,18 @@
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.security.KeyPair;
import java.security.Security;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.net.InetSocketAddress;

import javax.crypto.Cipher;

Expand All @@ -30,7 +33,8 @@ public class RTSPResponder{
private int[] fmtp;
private byte[] aesiv, aeskey; // ANNOUNCE request infos
private AudioServer serv; // Audio listener

byte[] hwAddr;

private String key =
"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIIEpQIBAAKCAQEA59dE8qLieItsH1WgjrcFRKj6eUWqi+bGLOX1HL3U3GhC/j0Qg90u3sG/1CUt\n"
Expand Down Expand Up @@ -61,7 +65,9 @@ public class RTSPResponder{
* @param port Will try to use the defined port. If not possible, check getPort() to know which port was taken.
* @throws IOException
*/
public RTSPResponder(int port) throws IOException{
public RTSPResponder(int port, byte[] hwAddr) throws IOException{
this.hwAddr = hwAddr;

// Try to take the given port. If not possible, take another. If not possible: ERROR
try {
sock = new ServerSocket(5000);
Expand All @@ -70,6 +76,13 @@ public RTSPResponder(int port) throws IOException{
}
}


public void stop() throws IOException{
serv.close();
sock.close();
}


/**
* @return port number
*/
Expand All @@ -78,6 +91,7 @@ public int getPort(){
}

public void handlePacket(RTSPPacket packet){
System.out.println(packet.getRawPacket());

// We init the response holder
StringBuilder response = new StringBuilder("RTSP/1.0 200 OK\r\n");
Expand All @@ -91,33 +105,39 @@ public void handlePacket(RTSPPacket packet){
byte[] decoded = Base64.decodeBase64(challenge);

// IP byte array
byte[] ip = socket.getLocalAddress().getAddress();

// Identifier byte array
byte[] identifier = {(byte)(0xF1 & 0xFF), (byte)(0xF1 & 0xFF), (byte)(0xF1 & 0xFF), (byte)(0xF1 & 0xFF), (byte)(0xF1 & 0xFF), (byte)(0xF1 & 0xFF)};

// New byte array of total size
byte[] result = new byte[decoded.length + ip.length + identifier.length];
//byte[] ip = socket.getLocalAddress().getAddress();
SocketAddress localAddress = socket.getLocalSocketAddress(); //.getRemoteSocketAddress();

byte[] ip = ((InetSocketAddress) localAddress).getAddress().getAddress();

// Copy everything
for(int i=0; i<decoded.length; i++){
result[i] = decoded[i];
}
for(int i=0; i<ip.length; i++){
result[i+decoded.length] = ip[i];
}
for(int i=0; i<identifier.length; i++){
result[i+decoded.length+ip.length] = identifier[i];
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
// Challenge
try {
out.write(decoded);
// IP-Address
out.write(ip);
// HW-Addr
out.write(hwAddr);

// Pad to 32 Bytes
int padLen = 32 - out.size();
for(int i = 0; i < padLen; ++i) {
out.write(0x00);
}

} catch (IOException e) {
e.printStackTrace();
}


// RSA
byte[] crypted = this.encryptRSA(result);
byte[] crypted = this.encryptRSA(out.toByteArray());

// Encode64
String ret = Base64.encodeBase64String(crypted);

// On retire les ==
ret = ret.substring(0,ret.length()-2)+ret.substring(ret.length());
ret = ret.replace("=", "").replace("\r", "").replace("\n", "");

// Write
response.append("Apple-Response: " + ret + "\r\n");
Expand Down Expand Up @@ -200,9 +220,7 @@ public void handlePacket(RTSPPacket packet){
// Timing port
Pattern p = Pattern.compile("volume: (.+)");
Matcher m = p.matcher(packet.getContent());
System.out.println(packet.getContent());
if(m.find()){
System.out.println("VOLUME: " + Double.parseDouble(m.group(1)));
double volume = (double) Math.pow(10.0,0.05*Double.parseDouble(m.group(1)));
serv.setVolume(65536.0 * volume);
}
Expand All @@ -215,6 +233,8 @@ public void handlePacket(RTSPPacket packet){
// We close the response
response.append("\r\n");

System.out.println(response);

// Write the packet to the wire
BufferedWriter oStream;
try {
Expand Down
85 changes: 76 additions & 9 deletions src/Rplay.java
@@ -1,6 +1,14 @@
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;

import com.apple.dnssd.DNSSDException;
import javax.swing.JButton;
import javax.swing.JFrame;

/**
* Main class
Expand All @@ -9,28 +17,87 @@
*/

//
public class Rplay {

public class Rplay extends Thread implements ActionListener{
private boolean on = false;
private JButton bouton;
RTSPResponder repondeur;

/**
* @param args
*/
public static void main(String[] args) {
new Rplay();
}

public Rplay(){
super();

JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(200, 65);
window.setTitle("RPlay");

java.awt.Container contenu = window.getContentPane();
contenu.setLayout(new FlowLayout());

bouton = new JButton("Start Airport Express");
bouton.addActionListener(this);
contenu.add(bouton);

window.setVisible(true);
}


public void run(){
int port = 5000;
byte[] hwAddr = null;;

InetAddress local;
try {
local = InetAddress.getLocalHost();
NetworkInterface ni = NetworkInterface.getByInetAddress(local);
if (ni != null) {
hwAddr = ni.getHardwareAddress();
}
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
StringBuilder sb = new StringBuilder();
for (byte b : hwAddr) {
sb.append(String.format("%02x", b));
}

try {
// DNS Emitter (Bonjour)
RTSPResponder repondeur = new RTSPResponder(port);
repondeur = new RTSPResponder(port, hwAddr);
@SuppressWarnings("unused")
BonjourEmitter emetteur = new BonjourEmitter("Benj", "F1F1F1F1F1F1", repondeur.getPort());
BonjourEmitter emetteur = new BonjourEmitter("Benj", sb.toString(), repondeur.getPort());
repondeur.listen();


} catch (DNSSDException e) {
} catch (Exception e) {
// Bonjour error
e.printStackTrace();
} catch (IOException e) {
// No socket
e.printStackTrace();
}
}

@Override
public void actionPerformed(ActionEvent arg0) {
if(!on){
this.start();
bouton.setText("Stop Airport Express");
} else {
try {
repondeur.stop();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bouton.setText("Start Airport Express");
}
}

Expand Down

0 comments on commit 2a47f62

Please sign in to comment.