]> sjero.net Git - linphone/blob - p2pproxy/src/org/linphone/p2pproxy/core/stun/StunServer.java
remove mediastreamer2 and add it as a submodule instead.
[linphone] / p2pproxy / src / org / linphone / p2pproxy / core / stun / StunServer.java
1 /*
2 p2pproxy Copyright (C) 2007  Jehan Monnier ()
3
4 StunServer.java - .
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 */
20 package org.linphone.p2pproxy.core.stun;
21
22
23 import java.net.DatagramPacket;
24 import java.net.DatagramSocket;
25 import java.net.SocketException;
26 import org.apache.log4j.Logger;
27 import org.linphone.p2pproxy.api.P2pProxyException;
28 import org.linphone.p2pproxy.core.GenericUdpSession;
29 import org.linphone.p2pproxy.core.ServiceProvider;
30
31 import de.javawi.jstun.attribute.ChangeRequest;
32 import de.javawi.jstun.attribute.ErrorCode;
33 import de.javawi.jstun.attribute.MappedAddress;
34 import de.javawi.jstun.attribute.MessageAttributeException;
35 import de.javawi.jstun.attribute.ResponseAddress;
36 import de.javawi.jstun.attribute.SourceAddress;
37 import de.javawi.jstun.attribute.UnknownAttribute;
38 import de.javawi.jstun.attribute.UnknownMessageAttributeException;
39 import de.javawi.jstun.attribute.MessageAttributeInterface.MessageAttributeType;
40 import de.javawi.jstun.header.MessageHeader;
41 import de.javawi.jstun.header.MessageHeaderParsingException;
42 import de.javawi.jstun.header.MessageHeaderInterface.MessageHeaderType;
43 import de.javawi.jstun.util.Address;
44
45
46 /*
47  * This class implements a STUN server as described in RFC 3489.
48  * neither change port nor change address are implemented 
49  */
50 public class StunServer implements GenericUdpSession.MessageHandler {
51         private static Logger mLog = Logger.getLogger(StunServer.class);
52         private final DatagramSocket mSocket;
53         
54         public StunServer(DatagramSocket mListeningSocket) throws SocketException {
55                 mSocket = mListeningSocket;
56         }
57
58         public void onMessage(DatagramPacket lMessage) {
59                 // derivated from JSTUN (Thomas King) 
60                 MessageHeader receiveMH = null;
61                 try {
62                         receiveMH = MessageHeader.parseHeader(lMessage.getData());
63                 } catch (MessageHeaderParsingException e1) {
64                         if (mLog.isInfoEnabled()) mLog.info("not a stun message");
65                         return;
66                 }
67
68                 try {
69                         receiveMH.parseAttributes(lMessage.getData());
70                         if (receiveMH.getType() == MessageHeaderType.BindingRequest) {
71                                 ChangeRequest cr = (ChangeRequest) receiveMH.getMessageAttribute(MessageAttributeType.ChangeRequest);
72                                 if (cr == null) throw new MessageAttributeException("Message attribute change request is not set.");
73                                 ResponseAddress ra = (ResponseAddress) receiveMH.getMessageAttribute(MessageAttributeType.ResponseAddress);
74
75                                 MessageHeader sendMH = new MessageHeader(MessageHeaderType.BindingResponse);
76                                 sendMH.setTransactionID(receiveMH.getTransactionID());
77
78                                 // Mapped address attribute
79                                 MappedAddress ma = new MappedAddress();
80                                 ma.setAddress(new Address(lMessage.getAddress().getAddress()));
81                                 ma.setPort(lMessage.getPort());
82                                 sendMH.addMessageAttribute(ma);
83                                 if ((!cr.isChangePort()) && (!cr.isChangeIP())) {
84                                         if (mLog.isInfoEnabled()) mLog.info("Nothing received in Change Request attribute");
85                                         // Source address attribute
86                                         SourceAddress sa = new SourceAddress();
87                                         sa.setAddress(new Address(mSocket.getLocalAddress().getAddress()));
88                                         sa.setPort(mSocket.getLocalPort());
89                                         sendMH.addMessageAttribute(sa);
90                                         byte[] data = sendMH.getBytes();
91                                         DatagramPacket send = new DatagramPacket(data, data.length);
92                                         if (ra != null) {
93                                                 send.setPort(ra.getPort());
94                                                 send.setAddress(ra.getAddress().getInetAddress());
95                                         } else {
96                                                 send.setPort(lMessage.getPort());
97                                                 send.setAddress(lMessage.getAddress());
98                                         }
99                                         mSocket.send(send);
100                                         if (mLog.isInfoEnabled()) mLog.info(mSocket.getLocalAddress().getHostAddress() + ":" + mSocket.getLocalPort() + " send Binding Response to " + send.getAddress().getHostAddress() + ":" + send.getPort());
101                                 } else {
102 //                                      Generate Binding error response
103                                         sendMH = new MessageHeader(MessageHeaderType.BindingErrorResponse);
104                                         sendMH.setTransactionID(receiveMH.getTransactionID());
105                                         ErrorCode lErrorCode = new ErrorCode();
106                                         lErrorCode.setResponseCode(400); //bad request
107                                         sendMH.addMessageAttribute(lErrorCode);
108                                         byte[] data = sendMH.getBytes();
109                                         DatagramPacket send = new DatagramPacket(data, data.length);
110                                         send.setPort(lMessage.getPort());
111                                         send.setAddress(lMessage.getAddress());
112                                         mSocket.send(send);
113                                         if (mLog.isInfoEnabled()) mLog.info("cannot handle cr ["+cr+"] attibute");
114                                 }
115                         }
116                 } catch ( Exception e) {
117
118                         try {
119                                 // Generate Binding error response
120
121                                 MessageHeader sendMH = new MessageHeader(MessageHeaderType.BindingErrorResponse);
122                                 sendMH.setTransactionID(receiveMH.getTransactionID());
123
124                                 if (e instanceof UnknownMessageAttributeException) {
125                                         // Unknown attributes
126                                         UnknownAttribute ua = new UnknownAttribute();
127                                         ua.addAttribute(((UnknownMessageAttributeException) e).getType());
128                                         sendMH.addMessageAttribute(ua);
129                                 } else {
130                                         ErrorCode lErrorCode = new ErrorCode();
131                                         lErrorCode.setResponseCode(500);
132                                         sendMH.addMessageAttribute(lErrorCode); 
133                                 }
134                                 byte[] data = sendMH.getBytes();
135                                 DatagramPacket send = new DatagramPacket(data, data.length);
136                                 send.setPort(lMessage.getPort());
137                                 send.setAddress(lMessage.getAddress());
138                                 mSocket.send(send);
139                                 mLog.error(" send Binding Error Response to " + send.getAddress().getHostAddress() + ":" + send.getPort(),e);
140                         } catch(Exception e1) {
141                                 mLog.error("cannot handle error", e1);
142                         }
143                 }       
144
145         }
146
147
148 }