19. public class PushDaemon {
private final Queue<String> queue;
private final HttpClient httpclient;
private final DatagramSocket socket;
public PushDaemon() throws SocketException {
queue = new LinkedBlockingQueue<>();
httpClient = HttpClients.createDefault();
socket = new DatagramSocket(6889);
}
}
20. public void start() {
Runnable client = new Runnable() {
@Override
public void run() {
while (true) {
String json = queue.poll();
if (json == null || json.length() <= 0) {
try {
sleep(1000);
continue;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
HttpPost post = new HttpPost("https://android.googleapis.com/gcm/send");
post.setHeader("Authorization", "key=AIzaSyCABSTd47XeIH");
post.setHeader("Content-Type", "application/json");
System.out.println("posting " + json);
try {
HttpEntity entity = new StringEntity(json);
post.setEntity(entity);
httpclient.execute(post);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
Thread t = new Thread(client);
t.start();
while (true) {
try {
byte[] buf = new byte[4096];
DatagramPacket received = new DatagramPacket(buf, buf.length);
socket.receive(received);
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
byte[] sendData = "PONG".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, received.getAddress(), received.getPort());
socket.send(sendPacket);
} else if ("SEND".equals(command)) {
String message = data.replace(command, "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) + "", "data" : { "alert" : "" + matcher.group(2) + ""}}";
System.out.println(json);
queue.add(json);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
24. private void spawnWorkers() {
Runnable client = new Runnable() {
@Override
public void run()
while (true) {
String json = queue.poll();
if (json == null || json.length() <= 0) {
try {
sleep(1000);
continue;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
HttpPost post = new HttpPost("https://android.googleapis.com/gcm/send");
post.setHeader("Authorization", "key=AIzaSyCABSTd47XeIH");
post.setHeader("Content-Type", "application/json");
try {
HttpEntity entity = new StringEntity(json);
post.setEntity(entity);
httpclient.execute(post);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
Thread t = new Thread(client);
t.start();
}
}
25. private void processRequests() {
try {
byte[] buf = new byte[4096];
DatagramPacket received = new DatagramPacket(buf, buf.length);
socket.receive(received);
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
byte[] sendData = "PONG".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
received.getAddress(), received.getPort());
socket.send(sendPacket);
} else if ("SEND".equals(command)) {
String message = data.replace(command, "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) + "", "data
{ "alert" : "" + matcher.group(2) + ""}}";
queue.add(json);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
26. public class PushDaemon {
private final Queue<String> queue;
private final HttpClient httpclient;
private final DatagramSocket socket;
public PushDaemon() throws SocketException {
queue = new LinkedBlockingQueue<>();
httpclient = HttpClients.createDefault();
socket = new DatagramSocket(6889);
}
public void start() {
spawnWorkers();
while(true){processRequests();}
}
private void processRequests() {
//…
}
private void spawnWorkers() {
//…
}
}
27. Update authorization key
Increase thread pool size
Swap HTTP client
Use a different transport protocol
Modify wire protocol format
Add commands
Add a different push notification service
Move UDP port
Use x-www-urlencoded instead of JSON
Lower maximum payload size
Bind a specific interface address
Update push service URL
30. private void spawnWorkers() {
Runnable client = new Runnable() {
@Override
public void run()
while (true) {
String json = queue.poll();
if (json == null || json.length() <= 0) {
try {
sleep(1000);
continue;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
HttpPost post = new HttpPost("https://android.googleapis.com/gcm/send");
post.setHeader("Authorization", "key=AIzaSyCABSTd47XeIH");
post.setHeader("Content-Type", "application/json");
try {
HttpEntity entity = new StringEntity(json);
post.setEntity(entity);
httpclient.execute(post);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
Thread t = new Thread(client);
t.start();
}
}
31. public class Worker {
private final Queue<String> queue;
private final HttpClient httpclient;
public Worker() {
queue = new LinkedBlockingQueue<>();
httpclient = HttpClients.createDefault();
}
public void add(String json) {
this.queue.add(json);
}
}
32. public class PushDaemon {
public PushDaemon() throws SocketException {
queue = new LinkedBlockingQueue<>();
httpclient = HttpClients.createDefault();
socket = new DatagramSocket(6889);
}
}
33. public class PushDaemon {
public PushDaemon() throws SocketException {
worker = new Worker();
socket = new DatagramSocket(6889);
}
}
34. private void processRequests() {
try {
byte[] buf = new byte[4096];
DatagramPacket received = new DatagramPacket(buf, buf.length);
socket.receive(received);
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
byte[] sendData = "PONG".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
received.getAddress(), received.getPort());
socket.send(sendPacket);
} else if ("SEND".equals(command)) {
String message = data.replace(command, "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) + "", "data
{ "alert" : "" + matcher.group(2) + ""}}";
queue.add(json);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
35. private void processRequests() {
try {
byte[] buf = new byte[4096];
DatagramPacket received = new DatagramPacket(buf, buf.length);
socket.receive(received);
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
byte[] sendData = "PONG".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
received.getAddress(), received.getPort());
socket.send(sendPacket);
} else if ("SEND".equals(command)) {
String message = data.replace(command, "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) + "", "data
{ "alert" : "" + matcher.group(2) + ""}}";
worker.add(json);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
36. public class PushDaemon {
public void start() {
spawnWorkers();
while(true){processRequests();}
}
}
37. public class PushDaemon {
public void start() {
worker.spawn();
while(true){processRequests();}
}
}
38. public class PushDaemon {
public PushDaemon() throws SocketException {
worker = new Worker();
socket = new DatagramSocket(6889);
}
}
39. private void processRequests() {
while (true) {
try {
byte[] buf = new byte[4096];
DatagramPacket received = new DatagramPacket(buf, buf.length);
socket.receive(received);
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
byte[] sendData = "PONG".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
received.getAddress(), received.getPort());
socket.send(sendPacket);
} else if ("SEND".equals(command)) {
String message = data.replace(command, "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) + "", "data
{ "alert" : "" + matcher.group(2) + ""}}";
worker.add(json);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
40. public class UDPServer {
private final DatagramSocket socket;
public UDPServer() throws SocketException {
socket = new DatagramSocket(6889);
}
}
41. private void processRequests() {
while (true) {
try {
byte[] buf = new byte[4096];
DatagramPacket received = new DatagramPacket(buf, buf.length);
socket.receive(received);
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
byte[] sendData = "PONG".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
received.getAddress(), received.getPort());
socket.send(sendPacket);
} else if ("SEND".equals(command)) {
String message = data.replace(command, "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) + "", "data
{ "alert" : "" + matcher.group(2) + ""}}";
worker.add(json);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
receive
send
42. public class UDPServer {
private final DatagramSocket socket;
public UDPServer() throws SocketException {
socket = new DatagramSocket(6889);
}
public DatagramPacket receive() throws IOException {
byte[] buf = new byte[4096];
DatagramPacket received = new DatagramPacket(buf, buf.length);
socket.receive(received);
return received;
}
public void send(String message, InetAddress address, int port) throws
IOException {
byte[] sendData = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
address, port);
socket.send(sendPacket);
}
}
43. private void processRequests() {
try {
byte[] buf = new byte[4096];
DatagramPacket received = new DatagramPacket(buf, buf.length);
socket.receive(received);
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
byte[] sendData = "PONG".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
received.getAddress(), received.getPort());
socket.send(sendPacket);
} else if ("SEND".equals(command)) {
String message = data.replace(command, "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) + "", "data
{ "alert" : "" + matcher.group(2) + ""}}";
worker.add(json);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
44. public class PushDaemon {
private final Worker worker;
private final UDPServer server;
public PushDaemon() throws SocketException {
worker = new Worker();
server = new UDPServer();
}
public void start() {
worker.spawn();
while(true){processRequests();}
}
private void processRequests() {
//…
}
}
49. public class PushDaemon {
private final Worker worker;
private final UDPServer server;
public PushDaemon() throws SocketException {
worker = new Worker();
server = new UDPServer();
}
public void start() {
worker.spawn();
processRequests();
}
private void processRequests() {
//…
}
}
50. public class PushDaemon {
private final Worker worker;
private final UDPServer server;
public PushDaemon() throws SocketException {
worker = new Worker();
server = new UDPServer(this);
}
public void start() {
worker.spawn();
processRequests();
}
private void processRequests() {
//…
}
}
51. public class PushDaemon {
private final Worker worker;
private final UDPServer server;
public PushDaemon() throws SocketException {
worker = new Worker();
server = new UDPServer(this);
}
public void start() {
worker.spawn();
while(true){processRequests();}
}
private void processRequests() {
//…
}
}
52. public class PushDaemon {
private final Worker worker;
private final UDPServer server;
public PushDaemon() throws SocketException {
worker = new Worker();
server = new UDPServer(this);
}
public void start() {
worker.spawn();
server.listen(6889);
}
private void processRequests() {
//…
}
}
61. public class Ping {
private UDPServer server;
private DatagramPacket received;
public Ping(UDPServer server, DatagramPacket received) {
this.server = server;
this.received = received;
}
public void run() throws IOException {
server.send("PONG", received.getAddress(), received.getPort());
}
}
62. public void call(DatagramPacket received) {
try {
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
new Jobs(server, received).run();
} else if ("SEND".equals(command)) {
String message = data.replace(command, "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) +
"", "data" : { "alert" : "" + matcher.group(2) + ""}}";
worker.add(json);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
63. public class Send {
private DatagramPacket received;
public Send(DatagramPacket received) {
this.received = received;
}
public String run() {
String data = new String(received.getData());
String message = data.replace("SEND", "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
return "{"registration_ids" : "" + matcher.group(1) + "", "data" :
{ "alert" : "" + matcher.group(2) + ""}}";
}
return null;
}
}
64. public void call(DatagramPacket received) {
try {
String data = new String(received.getData());
String command = data.split("s")[0];
if ("PING".equals(command)) {
new Ping(server, received).run();
} else if ("SEND".equals(command)) {
String json = new Send(received).run();
worker.add(json);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
65. public class Worker {
private final Queue<String> queue;
private final HttpClient httpclient;
public Worker() {
queue = new LinkedBlockingQueue<>();
httpclient = HttpClients.createDefault();
}
public void add(String json) {
this.queue.add(json);
}
void spawn() {
Runnable client = new Runnable() {
@Override
public void run() {
while (true) {
String json = queue.poll();
if (json == null || json.length() <= 0) {
try {
sleep(1000);
continue;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
HttpPost post = new HttpPost("https://android.googleapis.com/gcm/send");
post.setHeader("Authorization", "key=AIzaSyCABSTd47XeIH");
post.setHeader("Content-Type", "application/json");
System.out.println("posting " + json);
try {
HttpEntity entity = new StringEntity(json);
post.setEntity(entity);
httpclient.execute(post);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
Thread t = new Thread(client);
t.start();
}
}
66. public class Send {
private DatagramPacket received;
private final HttpClient httpclient;
public Send(DatagramPacket received) {
this.received = received;
this.httpclient = HttpClients.createDefault();
}
public void run() throws IOException {
String data = new String(received.getData());
String message = data.replace("SEND", "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) + "",
"data" : { "alert" : "" + matcher.group(2) + ""}}";
HttpPost post = new HttpPost("https://android.googleapis.com/gcm/
send");
post.setHeader("Authorization", "key=AIzaSyCABSTd47XeIH");
post.setHeader("Content-Type", "application/json");
HttpEntity entity = new StringEntity(json);
post.setEntity(entity);
httpclient.execute(post);
}
}
}
67. public class Worker {
public Worker() {
queue = new LinkedBlockingQueue<>();
}
public void accept(Job job) {
this.queue.add(job);
}
void spawn() {
Runnable client = new Runnable() {
@Override
public void run() {
while (true) {
Job job = queue.poll();
if (job != null) {
try {
job.run();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
Thread t = new Thread(client);
t.start();
}
}
68. public interface Job {
void run() throws IOException;
}
public class Ping implements Job {
//…
}
public class Send implements Job {
//…
}
69. public class PushDaemon {
private final Worker worker;
private final UDPServer server;
public PushDaemon() throws SocketException {
worker = new Worker();
server = new UDPServer(this);
}
public void start() throws IOException {
worker.spawn();
server.listen(6889);
}
public void call(DatagramPacket received) {
String data = new String(received.getData());
String command = data.split("s")[0];
Job job = null;
if ("PING".equals(command)) {
job = new Ping(server, received);
} else if ("SEND".equals(command)) {
job = new Send(received);
}
if(job != null) {
worker.accept(job);
}
}
}
71. public interface Job {
public static Job create(DatagramPacket received, UDPServer server) {
String data = new String(received.getData());
String command = data.split("s")[0];
Job job = null;
if ("PING".equals(command)) {
job = new Ping(server, received);
} else if ("SEND".equals(command)) {
job = new Send(received);
}
return job;
}
}
72. public class PushDaemon {
private final Worker worker;
private final UDPServer server;
public PushDaemon() throws SocketException {
worker = new Worker();
server = new UDPServer(this);
}
public void start() throws IOException {
worker.spawn();
server.listen(6889);
}
public void call(DatagramPacket received) {
Job job = Job.create(received, server);
if (job != null) {
worker.accept(job);
}
}
}
73. public class Ping implements Job {
public void run() throws IOException {
server.send("PONG", received.getAddress(), received.getPort());
}
}
public class Send implements Job {
public void run() throws IOException {
String data = new String(received.getData());
String message = data.replace("SEND", "").trim();
Pattern p = Pattern.compile("([a-zA-Z0-9_-]*) "([^"]*)"");
Matcher matcher = p.matcher(message);
if (matcher.matches()) {
String json = "{"registration_ids" : "" + matcher.group(1) +
"", "data" : { "alert" : "" + matcher.group(2) + ""}}";
HttpPost post = new HttpPost("https://android.googleapis.com/gcm/
send");
post.setHeader("Authorization", "key=AIzaSyCABSTd47XeIH");
post.setHeader("Content-Type", "application/json");
HttpEntity entity = new StringEntity(json);
post.setEntity(entity);
httpclient.execute(post);
}
}
}
74. public class Client {
private final InetSocketAddress socketAddress;
public Client(InetSocketAddress socketAddress) {
this.socketAddress = socketAddress;
}
public int port() {
return socketAddress.getPort();
}
public InetAddress address() {
return socketAddress.getAddress();
}
}
75. public class UDPServer {
public UDPServer(PushDaemon app) {
this.app = app;
}
public void listen(int port) throws IOException {
socket = new DatagramSocket(port);
while (true) { app.call(receive()); }
}
}
76. public class UDPServer {
public void listen(int port) throws IOException {
socket = new DatagramSocket(port);
while (true) {
DatagramPacket received = receive();
String message = messageOf(received);
Client client = clientOf(received);
app.call(message, client);
}
}
private String messageOf(DatagramPacket received) {
return new String(received.getData());
}
private Client clientOf(DatagramPacket received) {
return new Client((InetSocketAddress) received.getSocketAddress());
}
}
77. public interface Job {
public static Job create(DatagramPacket received, UDPServer server) {
String data = new String(received.getData());
String command = data.split("s")[0];
Job job = null;
if ("PING".equals(command)) {
job = new Ping(server, received);
} else if ("SEND".equals(command)) {
job = new Send(received);
}
return job;
}
}
78. public interface Job {
public static Job create(Client client, String message, UDPServer server) {
//…
}
}
79. public class Ping implements Job {
private final Client client;
private final String message;
private UDPServer server;
public Ping(Client client, String message, UDPServer server) {
this.client = client;
this.message = message;
this.server = server;
}
public void run() throws IOException {
server.send("PONG", client.address(), client.port());
}
}